diff --git a/README.md b/README.md index 2ecb6eb8c..a4180b3b0 100644 --- a/README.md +++ b/README.md @@ -124,7 +124,7 @@ docker exec -it razor-go razor setConfig --provider --alternatePr Example: ``` -$ ./razor setConfig --provider https://mainnet.skalenodes.com/v1/turbulent-unique-scheat --alternateProvider https://ce2m-skale.chainode.tech:10200/ --gasmultiplier 1 --buffer 20 --wait 30 --gasprice 0 --logLevel debug --gasLimit 2 --rpcTimeout 10 --httpTimeout 10 --logFileMaxSize 200 --logFileMaxBackups 52 --logFileMaxAge 365 +$ ./razor setConfig --provider https://mainnet.skalenodes.com/v1/turbulent-unique-scheat --alternateProvider https://ce2m-skale.chainode.tech:10200/ --gasmultiplier 1 --buffer 20 --wait 30 --gasprice 0 --logLevel debug --gasLimit 2 --rpcTimeout 10 --httpTimeout 10 --logFileMaxSize 200 --logFileMaxBackups 10 --logFileMaxAge 60 ``` Besides, setting these parameters in the config, you can use different values for these parameters in various commands. Just add the same flag to any command you want to use and the new config changes will appear for that command. diff --git a/accounts/accountUtils.go b/accounts/accountUtils.go index 11f8a5f10..e0d7e87df 100644 --- a/accounts/accountUtils.go +++ b/accounts/accountUtils.go @@ -2,56 +2,26 @@ package accounts import ( - "crypto/ecdsa" - "github.com/ethereum/go-ethereum/accounts" "github.com/ethereum/go-ethereum/accounts/keystore" - "github.com/ethereum/go-ethereum/crypto" - "os" "razor/core/types" ) -//go:generate mockery --name AccountInterface --output ./mocks/ --case=underscore - -var AccountUtilsInterface AccountInterface - -type AccountInterface interface { - CreateAccount(path string, password string) accounts.Account - GetPrivateKeyFromKeystore(keystorePath string, password string) (*ecdsa.PrivateKey, error) - GetPrivateKey(address string, password string, keystorePath string) (*ecdsa.PrivateKey, error) - SignData(hash []byte, account types.Account, defaultPath string) ([]byte, error) - Accounts(path string) []accounts.Account - NewAccount(path string, passphrase string) (accounts.Account, error) - DecryptKey(jsonBytes []byte, password string) (*keystore.Key, error) - Sign(digestHash []byte, prv *ecdsa.PrivateKey) ([]byte, error) - ReadFile(filename string) ([]byte, error) -} - -type AccountUtils struct{} - -//This function returns all the accounts in form of array -func (accountUtils AccountUtils) Accounts(path string) []accounts.Account { - ks := keystore.NewKeyStore(path, keystore.StandardScryptN, keystore.StandardScryptP) - return ks.Accounts() -} - -//This function takes path and pass phrase as input and returns the new account -func (accountUtils AccountUtils) NewAccount(path string, passphrase string) (accounts.Account, error) { - ks := keystore.NewKeyStore(path, keystore.StandardScryptN, keystore.StandardScryptP) - accounts.NewManager(&accounts.Config{InsecureUnlockAllowed: false}, ks) - return ks.NewAccount(passphrase) -} - -//This function takes json bytes array and password as input and returns the decrypted key -func (accountUtils AccountUtils) DecryptKey(jsonBytes []byte, password string) (*keystore.Key, error) { - return keystore.DecryptKey(jsonBytes, password) +type AccountManager struct { + Keystore *keystore.KeyStore } -//This function takes hash in form of byte array and private key as input and returns signature as byte array -func (accountUtils AccountUtils) Sign(digestHash []byte, prv *ecdsa.PrivateKey) (sig []byte, err error) { - return crypto.Sign(digestHash, prv) +func NewAccountManager(keystorePath string) *AccountManager { + ks := keystore.NewKeyStore(keystorePath, keystore.StandardScryptN, keystore.StandardScryptP) + return &AccountManager{ + Keystore: ks, + } } -//This function takes name of the file as input and returns the file data as byte array -func (accountUtils AccountUtils) ReadFile(filename string) ([]byte, error) { - return os.ReadFile(filename) +// InitAccountStruct initializes an Account struct with provided details. +func InitAccountStruct(address, password string, accountManager types.AccountManagerInterface) types.Account { + return types.Account{ + Address: address, + Password: password, + AccountManager: accountManager, + } } diff --git a/accounts/accounts.go b/accounts/accounts.go index b907dfef9..4284ed6a3 100644 --- a/accounts/accounts.go +++ b/accounts/accounts.go @@ -5,7 +5,9 @@ import ( "crypto/ecdsa" "errors" "github.com/ethereum/go-ethereum/accounts" - "razor/core/types" + "github.com/ethereum/go-ethereum/accounts/keystore" + "github.com/ethereum/go-ethereum/crypto" + "os" "razor/logger" "razor/path" "strings" @@ -14,28 +16,46 @@ import ( var log = logger.NewLogger() //This function takes path and password as input and returns new account -func (AccountUtils) CreateAccount(keystorePath string, password string) accounts.Account { +func (am *AccountManager) CreateAccount(keystorePath string, password string) accounts.Account { if _, err := path.OSUtilsInterface.Stat(keystorePath); path.OSUtilsInterface.IsNotExist(err) { mkdirErr := path.OSUtilsInterface.Mkdir(keystorePath, 0700) if mkdirErr != nil { log.Fatal("Error in creating directory: ", mkdirErr) } } - newAcc, err := AccountUtilsInterface.NewAccount(keystorePath, password) + newAcc, err := am.NewAccount(password) if err != nil { log.Fatal("Error in creating account: ", err) } return newAcc } +//This function takes path and pass phrase as input and returns the new account +func (am *AccountManager) NewAccount(passphrase string) (accounts.Account, error) { + ks := am.Keystore + accounts.NewManager(&accounts.Config{InsecureUnlockAllowed: false}, ks) + return ks.NewAccount(passphrase) +} + +//This function takes address of account, password and keystore path as input and returns private key of account +func (am *AccountManager) GetPrivateKey(address string, password string) (*ecdsa.PrivateKey, error) { + allAccounts := am.Keystore.Accounts() + for _, account := range allAccounts { + if strings.EqualFold(account.Address.Hex(), address) { + return getPrivateKeyFromKeystore(account.URL.Path, password) + } + } + return nil, errors.New("no keystore file found") +} + //This function takes and path of keystore and password as input and returns private key of account -func (AccountUtils) GetPrivateKeyFromKeystore(keystorePath string, password string) (*ecdsa.PrivateKey, error) { - jsonBytes, err := AccountUtilsInterface.ReadFile(keystorePath) +func getPrivateKeyFromKeystore(keystoreFilePath string, password string) (*ecdsa.PrivateKey, error) { + jsonBytes, err := os.ReadFile(keystoreFilePath) if err != nil { log.Error("Error in reading keystore: ", err) return nil, err } - key, err := AccountUtilsInterface.DecryptKey(jsonBytes, password) + key, err := keystore.DecryptKey(jsonBytes, password) if err != nil { log.Error("Error in fetching private key: ", err) return nil, err @@ -43,22 +63,11 @@ func (AccountUtils) GetPrivateKeyFromKeystore(keystorePath string, password stri return key.PrivateKey, nil } -//This function takes address of account, password and keystore path as input and returns private key of account -func (AccountUtils) GetPrivateKey(address string, password string, keystorePath string) (*ecdsa.PrivateKey, error) { - allAccounts := AccountUtilsInterface.Accounts(keystorePath) - for _, account := range allAccounts { - if strings.EqualFold(account.Address.Hex(), address) { - return AccountUtilsInterface.GetPrivateKeyFromKeystore(account.URL.Path, password) - } - } - return nil, errors.New("no keystore file found") -} - //This function takes hash, account and path as input and returns the signed data as array of byte -func (AccountUtils) SignData(hash []byte, account types.Account, defaultPath string) ([]byte, error) { - privateKey, err := AccountUtilsInterface.GetPrivateKey(account.Address, account.Password, defaultPath) +func (am *AccountManager) SignData(hash []byte, address string, password string) ([]byte, error) { + privateKey, err := am.GetPrivateKey(address, password) if err != nil { return nil, err } - return AccountUtilsInterface.Sign(hash, privateKey) + return crypto.Sign(hash, privateKey) } diff --git a/accounts/accounts_test.go b/accounts/accounts_test.go index aa964bf47..986a78c5c 100644 --- a/accounts/accounts_test.go +++ b/accounts/accounts_test.go @@ -2,314 +2,193 @@ package accounts import ( "crypto/ecdsa" - "errors" - "github.com/ethereum/go-ethereum/accounts" - "github.com/ethereum/go-ethereum/accounts/keystore" - "github.com/ethereum/go-ethereum/common" - "github.com/magiconair/properties/assert" - "github.com/stretchr/testify/mock" - "io/fs" - "razor/accounts/mocks" - "razor/core/types" - "razor/path" - mocks1 "razor/path/mocks" + "encoding/hex" "reflect" "testing" ) -func TestCreateAccount(t *testing.T) { - var keystorePath string - var password string - var fileInfo fs.FileInfo - - type args struct { - account accounts.Account - accountErr error - statErr error - isNotExist bool - mkdirErr error - } - tests := []struct { - name string - args args - want accounts.Account - expectedFatal bool - }{ - { - name: "Test 1: When NewAccounts executes successfully", - args: args{ - account: accounts.Account{Address: common.HexToAddress("0x000000000000000000000000000000000000dea1"), - URL: accounts.URL{Scheme: "TestKeyScheme", Path: "test/key/path"}, - }, - }, - want: accounts.Account{Address: common.HexToAddress("0x000000000000000000000000000000000000dea1"), - URL: accounts.URL{Scheme: "TestKeyScheme", Path: "test/key/path"}, - }, - expectedFatal: false, - }, - { - name: "Test 2: When there is an error in getting new account", - args: args{ - accountErr: errors.New("account error"), - }, - want: accounts.Account{Address: common.HexToAddress("0x00")}, - expectedFatal: true, - }, - { - name: "Test 3: When keystore directory does not exists and mkdir creates it", - args: args{ - account: accounts.Account{Address: common.HexToAddress("0x000000000000000000000000000000000000dea1"), - URL: accounts.URL{Scheme: "TestKeyScheme", Path: "test/key/path"}, - }, - statErr: errors.New("not exists"), - isNotExist: true, - }, - want: accounts.Account{Address: common.HexToAddress("0x000000000000000000000000000000000000dea1"), - URL: accounts.URL{Scheme: "TestKeyScheme", Path: "test/key/path"}, - }, - expectedFatal: false, - }, - { - name: "Test 4: When keystore directory does not exists and there an error creating new one", - args: args{ - account: accounts.Account{Address: common.HexToAddress("0x000000000000000000000000000000000000dea1"), - URL: accounts.URL{Scheme: "TestKeyScheme", Path: "test/key/path"}, - }, - statErr: errors.New("not exists"), - isNotExist: true, - mkdirErr: errors.New("mkdir error"), - }, - want: accounts.Account{Address: common.HexToAddress("0x000000000000000000000000000000000000dea1"), - URL: accounts.URL{Scheme: "TestKeyScheme", Path: "test/key/path"}, - }, - expectedFatal: true, - }, - } - - defer func() { log.ExitFunc = nil }() - var fatal bool - log.ExitFunc = func(int) { fatal = true } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - accountsMock := new(mocks.AccountInterface) - osMock := new(mocks1.OSInterface) - - path.OSUtilsInterface = osMock - AccountUtilsInterface = accountsMock - - accountsMock.On("NewAccount", mock.AnythingOfType("string"), mock.AnythingOfType("string")).Return(tt.args.account, tt.args.accountErr) - osMock.On("Stat", mock.AnythingOfType("string")).Return(fileInfo, tt.args.statErr) - osMock.On("IsNotExist", mock.Anything).Return(tt.args.isNotExist) - osMock.On("Mkdir", mock.Anything, mock.Anything).Return(tt.args.mkdirErr) - - accountUtils := AccountUtils{} - fatal = false - got := accountUtils.CreateAccount(keystorePath, password) - if tt.expectedFatal { - assert.Equal(t, tt.expectedFatal, fatal) - } - if got.Address != tt.want.Address { - t.Errorf("New address created, got = %v, want %v", got, tt.want.Address) - } - }) - } +func privateKeyToHex(privateKey *ecdsa.PrivateKey) string { + return hex.EncodeToString(privateKey.D.Bytes()) } -func TestGetPrivateKeyFromKeystore(t *testing.T) { - var password string - var keystorePath string - var privateKey *ecdsa.PrivateKey - var jsonBytes []byte +func Test_getPrivateKeyFromKeystore(t *testing.T) { + password := "Razor@123" type args struct { - jsonBytes []byte - jsonBytesErr error - key *keystore.Key - keyErr error + keystoreFilePath string + password string } tests := []struct { name string args args - want *ecdsa.PrivateKey + want string wantErr bool }{ { - name: "Test 1: When GetPrivateKey function executes successfully", + name: "Test 1: When keystore file is present and getPrivateKeyFromKeystore function executes successfully", args: args{ - jsonBytes: jsonBytes, - key: &keystore.Key{ - PrivateKey: privateKey, - }, + keystoreFilePath: "test_accounts/UTC--2024-03-20T07-03-56.358521000Z--911654feb423363fb771e04e18d1e7325ae10a91", + password: password, }, - want: privateKey, + want: "b110b1f06b7b64323a6fb768ceab966abe9f65f4e6ab3c39382bd446122f7b01", wantErr: false, }, { - name: "Test 2: When there is an error in reading data from file", + name: "Test 2: When there is no keystore file present at the desired path", args: args{ - jsonBytesErr: errors.New("error in reading data"), - key: &keystore.Key{ - PrivateKey: nil, - }, + keystoreFilePath: "test_accounts/UTC--2024-03-20T07-03-56.358521000Z--211654feb423363fb771e04e18d1e7325ae10a91", + password: password, }, - want: nil, + want: "", wantErr: true, }, { - name: "Test 3: When there is an error in fetching private key", + name: "Test 3: When password is incorrect for the desired keystore file", args: args{ - jsonBytes: jsonBytes, - key: &keystore.Key{ - PrivateKey: nil, - }, - keyErr: errors.New("private key error"), + keystoreFilePath: "test_accounts/UTC--2024-03-20T07-03-56.358521000Z--911654feb423363fb771e04e18d1e7325ae10a91", + password: "Razor@456", }, - want: privateKey, + want: "", wantErr: true, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - accountsMock := new(mocks.AccountInterface) - AccountUtilsInterface = accountsMock - - accountsMock.On("ReadFile", mock.AnythingOfType("string")).Return(tt.args.jsonBytes, tt.args.jsonBytesErr) - accountsMock.On("DecryptKey", mock.Anything, mock.AnythingOfType("string")).Return(tt.args.key, tt.args.keyErr) - - accountUtils := &AccountUtils{} - got, err := accountUtils.GetPrivateKeyFromKeystore(keystorePath, password) - if got != tt.want { - t.Errorf("Private key from GetPrivateKey, got = %v, want %v", got, tt.want) - } + gotPrivateKey, err := getPrivateKeyFromKeystore(tt.args.keystoreFilePath, tt.args.password) if (err != nil) != tt.wantErr { t.Errorf("GetPrivateKeyFromKeystore() error = %v, wantErr %v", err, tt.wantErr) return } + + // If there's no error and a private key is expected, compare the keys + if !tt.wantErr && tt.want != "" { + gotPrivateKeyHex := privateKeyToHex(gotPrivateKey) + if gotPrivateKeyHex != tt.want { + t.Errorf("GetPrivateKey() got private key = %v, want %v", gotPrivateKeyHex, tt.want) + } + } }) } } func TestGetPrivateKey(t *testing.T) { - var password string - var keystorePath string - var privateKey *ecdsa.PrivateKey - - accountsList := []accounts.Account{ - {Address: common.HexToAddress("0x000000000000000000000000000000000000dea1"), - URL: accounts.URL{Scheme: "TestKeyScheme", Path: "test/key/path"}, - }, - {Address: common.HexToAddress("0x000000000000000000000000000000000000dea2"), - URL: accounts.URL{Scheme: "TestKeyScheme", Path: "test/key/path"}, - }, - } + password := "Razor@123" + keystoreDirPath := "test_accounts" type args struct { - address string - accounts []accounts.Account - privateKey *ecdsa.PrivateKey + address string + password string } tests := []struct { name string args args - want *ecdsa.PrivateKey + want string wantErr bool }{ { - name: "Test 1: When input address is present in accountsList", + name: "Test 1: When input address with correct password is present in keystore directory", + args: args{ + address: "0x911654feb423363fb771e04e18d1e7325ae10a91", + password: password, + }, + want: "b110b1f06b7b64323a6fb768ceab966abe9f65f4e6ab3c39382bd446122f7b01", + wantErr: false, + }, + { + name: "Test 2: When input upper case address with correct password is present in keystore directory", args: args{ - address: "0x000000000000000000000000000000000000dea1", - accounts: accountsList, - privateKey: privateKey, + address: "0x2F5F59615689B706B6AD13FD03343DCA28784989", + password: password, }, - want: privateKey, + want: "726223b8b95628edef6cf2774ddde39fb3ea482949c8847fabf74cd994219b50", wantErr: false, }, { - name: "Test 2: When input address is not present in accountsList", + name: "Test 3: When provided address is not present in keystore directory", args: args{ - address: "0x000000000000000000000000000000000000dea3", - accounts: accountsList, - privateKey: privateKey, + address: "0x911654feb423363fb771e04e18d1e7325ae10a91_not_present", }, - want: nil, + want: "", + wantErr: true, + }, + { + name: "Test 4: When input address with incorrect password is present in keystore directory", + args: args{ + address: "0x911654feb423363fb771e04e18d1e7325ae10a91", + password: "incorrect password", + }, + want: "", wantErr: true, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - accountsMock := new(mocks.AccountInterface) - AccountUtilsInterface = accountsMock - - accountsMock.On("Accounts", mock.AnythingOfType("string")).Return(tt.args.accounts) - accountsMock.On("GetPrivateKeyFromKeystore", mock.AnythingOfType("string"), mock.AnythingOfType("string")).Return(tt.args.privateKey, nil) - - accountUtils := &AccountUtils{} - got, err := accountUtils.GetPrivateKey(tt.args.address, password, keystorePath) - if !reflect.DeepEqual(got, tt.want) { - t.Errorf("GetPrivateKey() got = %v, want %v", got, tt.want) - } + am := NewAccountManager(keystoreDirPath) + gotPrivateKey, err := am.GetPrivateKey(tt.args.address, tt.args.password) if (err != nil) != tt.wantErr { t.Errorf("GetPrivateKey() error = %v, wantErr %v", err, tt.wantErr) return } + + // If there's no error and a private key is expected, compare the keys + if !tt.wantErr && tt.want != "" { + gotPrivateKeyHex := privateKeyToHex(gotPrivateKey) + if gotPrivateKeyHex != tt.want { + t.Errorf("GetPrivateKey() got private key = %v, want %v", gotPrivateKeyHex, tt.want) + } + } }) } } func TestSignData(t *testing.T) { - var hash []byte - var account types.Account - var defaultPath string - var privateKey *ecdsa.PrivateKey - var signature []byte + password := "Razor@123" + + hexHash := "a3b8d42c7015c1e9354f8b9c2161d9b2e1ad89e6b6c7a9610e029fd7afec27ae" + hashBytes, err := hex.DecodeString(hexHash) + if err != nil { + log.Fatal("Failed to decode hex string") + } type args struct { - privateKey *ecdsa.PrivateKey - privateKeyErr error - signature []byte - signatureErr error + address string + password string + hash []byte } tests := []struct { name string args args - want []byte + want string wantErr bool }{ { name: "Test 1: When Sign function returns no error", args: args{ - privateKey: privateKey, - signature: signature, - signatureErr: nil, + address: "0x911654feb423363fb771e04e18d1e7325ae10a91", + password: password, + hash: hashBytes, }, - want: signature, + want: "f14cf1b8c9486777e4280b4da6cb7c314d5c19b7e30d32a46f83767a1946e35a39f6941df71375d7ffceaddac81e2454e9a129896803d02f633eb78ab7883ff200", wantErr: false, }, { name: "Test 2: When there is an error in getting private key", args: args{ - privateKeyErr: errors.New("privateKey"), + address: "0x_invalid_address", + password: password, + hash: hashBytes, }, - want: nil, + want: hex.EncodeToString(nil), wantErr: true, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - accountsMock := new(mocks.AccountInterface) - AccountUtilsInterface = accountsMock - - accountsMock.On("GetPrivateKey", mock.AnythingOfType("string"), mock.AnythingOfType("string"), mock.AnythingOfType("string")).Return(tt.args.privateKey, tt.args.privateKeyErr) - accountsMock.On("Sign", mock.Anything, mock.Anything).Return(tt.args.signature, tt.args.signatureErr) - - accountUtils := &AccountUtils{} - - got, err := accountUtils.SignData(hash, account, defaultPath) - - if !reflect.DeepEqual(got, tt.want) { - t.Errorf("Sign() got = %v, want %v", got, tt.want) + am := NewAccountManager("test_accounts") + got, err := am.SignData(tt.args.hash, tt.args.address, tt.args.password) + if !reflect.DeepEqual(hex.EncodeToString(got), tt.want) { + t.Errorf("Sign() got = %v, want %v", hex.EncodeToString(got), tt.want) } if (err != nil) != tt.wantErr { diff --git a/accounts/mocks/account_interface.go b/accounts/mocks/account_interface.go deleted file mode 100644 index e8e006441..000000000 --- a/accounts/mocks/account_interface.go +++ /dev/null @@ -1,224 +0,0 @@ -// Code generated by mockery v2.14.0. DO NOT EDIT. - -package mocks - -import ( - ecdsa "crypto/ecdsa" - - accounts "github.com/ethereum/go-ethereum/accounts" - - keystore "github.com/ethereum/go-ethereum/accounts/keystore" - - mock "github.com/stretchr/testify/mock" - - types "razor/core/types" -) - -// AccountInterface is an autogenerated mock type for the AccountInterface type -type AccountInterface struct { - mock.Mock -} - -// Accounts provides a mock function with given fields: path -func (_m *AccountInterface) Accounts(path string) []accounts.Account { - ret := _m.Called(path) - - var r0 []accounts.Account - if rf, ok := ret.Get(0).(func(string) []accounts.Account); ok { - r0 = rf(path) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).([]accounts.Account) - } - } - - return r0 -} - -// CreateAccount provides a mock function with given fields: path, password -func (_m *AccountInterface) CreateAccount(path string, password string) accounts.Account { - ret := _m.Called(path, password) - - var r0 accounts.Account - if rf, ok := ret.Get(0).(func(string, string) accounts.Account); ok { - r0 = rf(path, password) - } else { - r0 = ret.Get(0).(accounts.Account) - } - - return r0 -} - -// DecryptKey provides a mock function with given fields: jsonBytes, password -func (_m *AccountInterface) DecryptKey(jsonBytes []byte, password string) (*keystore.Key, error) { - ret := _m.Called(jsonBytes, password) - - var r0 *keystore.Key - if rf, ok := ret.Get(0).(func([]byte, string) *keystore.Key); ok { - r0 = rf(jsonBytes, password) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*keystore.Key) - } - } - - var r1 error - if rf, ok := ret.Get(1).(func([]byte, string) error); ok { - r1 = rf(jsonBytes, password) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// GetPrivateKey provides a mock function with given fields: address, password, keystorePath -func (_m *AccountInterface) GetPrivateKey(address string, password string, keystorePath string) (*ecdsa.PrivateKey, error) { - ret := _m.Called(address, password, keystorePath) - - var r0 *ecdsa.PrivateKey - if rf, ok := ret.Get(0).(func(string, string, string) *ecdsa.PrivateKey); ok { - r0 = rf(address, password, keystorePath) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*ecdsa.PrivateKey) - } - } - - var r1 error - if rf, ok := ret.Get(1).(func(string, string, string) error); ok { - r1 = rf(address, password, keystorePath) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// GetPrivateKeyFromKeystore provides a mock function with given fields: keystorePath, password -func (_m *AccountInterface) GetPrivateKeyFromKeystore(keystorePath string, password string) (*ecdsa.PrivateKey, error) { - ret := _m.Called(keystorePath, password) - - var r0 *ecdsa.PrivateKey - if rf, ok := ret.Get(0).(func(string, string) *ecdsa.PrivateKey); ok { - r0 = rf(keystorePath, password) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*ecdsa.PrivateKey) - } - } - - var r1 error - if rf, ok := ret.Get(1).(func(string, string) error); ok { - r1 = rf(keystorePath, password) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// NewAccount provides a mock function with given fields: path, passphrase -func (_m *AccountInterface) NewAccount(path string, passphrase string) (accounts.Account, error) { - ret := _m.Called(path, passphrase) - - var r0 accounts.Account - if rf, ok := ret.Get(0).(func(string, string) accounts.Account); ok { - r0 = rf(path, passphrase) - } else { - r0 = ret.Get(0).(accounts.Account) - } - - var r1 error - if rf, ok := ret.Get(1).(func(string, string) error); ok { - r1 = rf(path, passphrase) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// ReadFile provides a mock function with given fields: filename -func (_m *AccountInterface) ReadFile(filename string) ([]byte, error) { - ret := _m.Called(filename) - - var r0 []byte - if rf, ok := ret.Get(0).(func(string) []byte); ok { - r0 = rf(filename) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).([]byte) - } - } - - var r1 error - if rf, ok := ret.Get(1).(func(string) error); ok { - r1 = rf(filename) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// Sign provides a mock function with given fields: digestHash, prv -func (_m *AccountInterface) Sign(digestHash []byte, prv *ecdsa.PrivateKey) ([]byte, error) { - ret := _m.Called(digestHash, prv) - - var r0 []byte - if rf, ok := ret.Get(0).(func([]byte, *ecdsa.PrivateKey) []byte); ok { - r0 = rf(digestHash, prv) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).([]byte) - } - } - - var r1 error - if rf, ok := ret.Get(1).(func([]byte, *ecdsa.PrivateKey) error); ok { - r1 = rf(digestHash, prv) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// SignData provides a mock function with given fields: hash, account, defaultPath -func (_m *AccountInterface) SignData(hash []byte, account types.Account, defaultPath string) ([]byte, error) { - ret := _m.Called(hash, account, defaultPath) - - var r0 []byte - if rf, ok := ret.Get(0).(func([]byte, types.Account, string) []byte); ok { - r0 = rf(hash, account, defaultPath) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).([]byte) - } - } - - var r1 error - if rf, ok := ret.Get(1).(func([]byte, types.Account, string) error); ok { - r1 = rf(hash, account, defaultPath) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -type mockConstructorTestingTNewAccountInterface interface { - mock.TestingT - Cleanup(func()) -} - -// NewAccountInterface creates a new instance of AccountInterface. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. -func NewAccountInterface(t mockConstructorTestingTNewAccountInterface) *AccountInterface { - mock := &AccountInterface{} - mock.Mock.Test(t) - - t.Cleanup(func() { mock.AssertExpectations(t) }) - - return mock -} diff --git a/accounts/mocks/account_manager_interface.go b/accounts/mocks/account_manager_interface.go new file mode 100644 index 000000000..0bc33fab1 --- /dev/null +++ b/accounts/mocks/account_manager_interface.go @@ -0,0 +1,120 @@ +// Code generated by mockery v2.30.1. DO NOT EDIT. + +package mocks + +import ( + ecdsa "crypto/ecdsa" + + accounts "github.com/ethereum/go-ethereum/accounts" + + mock "github.com/stretchr/testify/mock" +) + +// AccountManagerInterface is an autogenerated mock type for the AccountManagerInterface type +type AccountManagerInterface struct { + mock.Mock +} + +// CreateAccount provides a mock function with given fields: keystorePath, password +func (_m *AccountManagerInterface) CreateAccount(keystorePath string, password string) accounts.Account { + ret := _m.Called(keystorePath, password) + + var r0 accounts.Account + if rf, ok := ret.Get(0).(func(string, string) accounts.Account); ok { + r0 = rf(keystorePath, password) + } else { + r0 = ret.Get(0).(accounts.Account) + } + + return r0 +} + +// GetPrivateKey provides a mock function with given fields: address, password +func (_m *AccountManagerInterface) GetPrivateKey(address string, password string) (*ecdsa.PrivateKey, error) { + ret := _m.Called(address, password) + + var r0 *ecdsa.PrivateKey + var r1 error + if rf, ok := ret.Get(0).(func(string, string) (*ecdsa.PrivateKey, error)); ok { + return rf(address, password) + } + if rf, ok := ret.Get(0).(func(string, string) *ecdsa.PrivateKey); ok { + r0 = rf(address, password) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*ecdsa.PrivateKey) + } + } + + if rf, ok := ret.Get(1).(func(string, string) error); ok { + r1 = rf(address, password) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// NewAccount provides a mock function with given fields: passphrase +func (_m *AccountManagerInterface) NewAccount(passphrase string) (accounts.Account, error) { + ret := _m.Called(passphrase) + + var r0 accounts.Account + var r1 error + if rf, ok := ret.Get(0).(func(string) (accounts.Account, error)); ok { + return rf(passphrase) + } + if rf, ok := ret.Get(0).(func(string) accounts.Account); ok { + r0 = rf(passphrase) + } else { + r0 = ret.Get(0).(accounts.Account) + } + + if rf, ok := ret.Get(1).(func(string) error); ok { + r1 = rf(passphrase) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// SignData provides a mock function with given fields: hash, address, password +func (_m *AccountManagerInterface) SignData(hash []byte, address string, password string) ([]byte, error) { + ret := _m.Called(hash, address, password) + + var r0 []byte + var r1 error + if rf, ok := ret.Get(0).(func([]byte, string, string) ([]byte, error)); ok { + return rf(hash, address, password) + } + if rf, ok := ret.Get(0).(func([]byte, string, string) []byte); ok { + r0 = rf(hash, address, password) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]byte) + } + } + + if rf, ok := ret.Get(1).(func([]byte, string, string) error); ok { + r1 = rf(hash, address, password) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// NewAccountManagerInterface creates a new instance of AccountManagerInterface. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func NewAccountManagerInterface(t interface { + mock.TestingT + Cleanup(func()) +}) *AccountManagerInterface { + mock := &AccountManagerInterface{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/accounts/test_accounts/UTC--2024-03-20T07-03-56.358521000Z--911654feb423363fb771e04e18d1e7325ae10a91 b/accounts/test_accounts/UTC--2024-03-20T07-03-56.358521000Z--911654feb423363fb771e04e18d1e7325ae10a91 new file mode 100644 index 000000000..bc50d72f6 --- /dev/null +++ b/accounts/test_accounts/UTC--2024-03-20T07-03-56.358521000Z--911654feb423363fb771e04e18d1e7325ae10a91 @@ -0,0 +1 @@ +{"address":"911654feb423363fb771e04e18d1e7325ae10a91","crypto":{"cipher":"aes-128-ctr","ciphertext":"032e882238c605aa6ede0c54658b1f26a8800e4b41c67349159236e7ffa76955","cipherparams":{"iv":"12cae1b8475b00f92e2eac08e08a6a39"},"kdf":"scrypt","kdfparams":{"dklen":32,"n":262144,"p":1,"r":8,"salt":"bacdad2b595bda0ed52706842b9a1d20ce64210eeadcf7302e6ba9e2ddc22706"},"mac":"722ea7fc4cee367e92bc403a5371aab1e78e66e3876d00d3a40830130c443101"},"id":"e0b6a612-8877-4400-813a-ef8a627d33d8","version":3} \ No newline at end of file diff --git a/accounts/test_accounts/UTC--2024-03-20T07-04-11.601622000Z--2f5f59615689b706b6ad13fd03343dca28784989 b/accounts/test_accounts/UTC--2024-03-20T07-04-11.601622000Z--2f5f59615689b706b6ad13fd03343dca28784989 new file mode 100644 index 000000000..c773f086e --- /dev/null +++ b/accounts/test_accounts/UTC--2024-03-20T07-04-11.601622000Z--2f5f59615689b706b6ad13fd03343dca28784989 @@ -0,0 +1 @@ +{"address":"2f5f59615689b706b6ad13fd03343dca28784989","crypto":{"cipher":"aes-128-ctr","ciphertext":"e46770162aa3d74c00f1b7dff2a6e255743e61483d3f6a4c266c2697ac05aed3","cipherparams":{"iv":"8941588ce2540c7bef63f0df4a67e6cb"},"kdf":"scrypt","kdfparams":{"dklen":32,"n":262144,"p":1,"r":8,"salt":"e106a7ef7916893083977dbe18cd5edf57491ba21a13adc2db7b79c7c8b85ded"},"mac":"d30b6bf80ea2ddbaca14f7635596e56ac150bda4416e9dc915117b8574cda2ba"},"id":"0accaaa4-2e5c-451b-b813-6551f9c01511","version":3} \ No newline at end of file diff --git a/addresses.json b/addresses.json deleted file mode 100644 index 5226f0726..000000000 --- a/addresses.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "Governance": "0xD2A74B7A962FFc85827da0124A4278e731D15464", - "BlockManager": "0x096e44B0d8b68376C8Efe40F28C3857951f03069", - "CollectionManager": "0x3b76eB8c0282dAf531D7C507E4f3143A9A9c38b1", - "StakeManager": "0x9f55a2C6C1F1Be8B01562cEae2df2F22931C7a46", - "RewardManager": "0x07875369943951b1Af9c37f4ea137dcED9d9181d", - "VoteManager": "0x11995b74D6d07a6Edc05653a71F3e8B3354caBF0", - "Delegator": "0xe295863DF95AaAeC66E7de11D3aD0C35698d0fE9", - "RAZOR": "0x4500E10fEb89e46E9fb642D0c62b1a761278155D", - "StakedTokenFactory": "0xe20e11687F269fE9e356da92C4B15aBF98BbC9ff", - "RandomNoManager": "0x31463bC4D5E67Bca623fFc6152D253Ea17216fA9" -} \ No newline at end of file diff --git a/addresses/mainnet.json b/addresses/mainnet.json index 84568c78b..81462089a 100644 --- a/addresses/mainnet.json +++ b/addresses/mainnet.json @@ -9,4 +9,4 @@ "RAZOR": "0xcbf70914Fae03B3acB91E953De60CfDAaCA8145f", "StakedTokenFactory": "0xEffA78888Dc1b6033286E5dF9b170bc5223178AB", "RandomNoManager": "0xC6eF45F5Add040800D30FE6dEe01b4EBC4BfC467" - } \ No newline at end of file +} \ No newline at end of file diff --git a/addresses/testnet.json b/addresses/testnet.json index 263d97f53..a70785723 100644 --- a/addresses/testnet.json +++ b/addresses/testnet.json @@ -1,12 +1,13 @@ { - "Governance": "0x6aC4BbACE4E38B085BA82bDA5477cc85222C2B40", - "BlockManager": "0x39D4B78bb09DEEC54fA2df729808b19962Cb9aae", - "CollectionManager": "0x7B8BF9a0B648Dd9f75D5E9e8a3054D18E8C4Cc5e", - "StakeManager": "0x432bDa6F3E5148898929be9d3555Ca5AA82b214b", - "RewardManager": "0x09FF6AB6F720F9866fe7b782566448E853c1F306", - "VoteManager": "0x86886e048fd0f253E6E75c13a3f924598799e06A", - "Delegator": "0x5755d776F77bF88d226EEEe0bA7f337F49Ac7FaE", - "RAZOR": "0xbF3BCf61f64C9825C7Af3f3D79817c9Cf44afBa7", - "StakedTokenFactory": "0x5008862c54ff6fae663Acd36E52D4614DcaF4329", - "RandomNoManager": "0x1495Ab19E7937e4259e3C292D906bB2e6302802f" + "Governance": "0x0b9CC11E7f7D3D4f9bBc0cCaB85b73B96C322c78", + "BlockManager": "0x076df1c2d81C40D30DF115Ab68A13251fBD3FFA4", + "CollectionManager": "0x83f4D7ad6dD366c3F04Af45a1437c77636b03388", + "StakeManager": "0xf99a873a6afdF1b24388ac02ea0f1CFE3c70A80b", + "RewardManager": "0x522d2A51639332388dA4788DF59fB4E598278fAd", + "VoteManager": "0x2399D4d92b4D8762971605d0bC9597F780852CC4", + "Delegator": "0x81c72fB60d19Bfc3A0adDfE394501150d290cd66", + "RAZOR": "0x504C6635af1e7E6fdc586c8A89973783b9281A77", + "StakedTokenFactory": "0xf271bd91104946Cb8e43BC0e83423ed073ab136e", + "RandomNoManager": "0x2dc9E4663675c933f78D97cDD44463ee9C43144c", + "DelegatorV2": "0x4e9E5AE58Fb6d7Ca5b79A196b8d0FCF7CA15C100" } \ No newline at end of file diff --git a/block/block.go b/block/block.go index bd12e70d2..ea896d420 100644 --- a/block/block.go +++ b/block/block.go @@ -32,9 +32,9 @@ func CalculateLatestBlock(client *ethclient.Client) { latestHeader, err := client.HeaderByNumber(context.Background(), nil) if err != nil { logrus.Error("CalculateBlockNumber: Error in fetching block: ", err) - continue + } else { + SetLatestBlock(latestHeader) } - SetLatestBlock(latestHeader) } time.Sleep(time.Second * time.Duration(core.BlockNumberInterval)) } diff --git a/cache/collectionsCache.go b/cache/collectionsCache.go new file mode 100644 index 000000000..c27064b64 --- /dev/null +++ b/cache/collectionsCache.go @@ -0,0 +1,35 @@ +package cache + +import ( + "razor/pkg/bindings" + "sync" +) + +// CollectionsCache struct to hold collection cache and associated mutex +type CollectionsCache struct { + Collections map[uint16]bindings.StructsCollection + Mu sync.RWMutex +} + +// NewCollectionsCache creates a new instance of CollectionsCache +func NewCollectionsCache() *CollectionsCache { + return &CollectionsCache{ + Collections: make(map[uint16]bindings.StructsCollection), + Mu: sync.RWMutex{}, + } +} + +func (c *CollectionsCache) GetCollection(collectionId uint16) (bindings.StructsCollection, bool) { + c.Mu.RLock() + defer c.Mu.RUnlock() + + collection, exists := c.Collections[collectionId] + return collection, exists +} + +func (c *CollectionsCache) UpdateCollection(collectionId uint16, updatedCollection bindings.StructsCollection) { + c.Mu.Lock() + defer c.Mu.Unlock() + + c.Collections[collectionId] = updatedCollection +} diff --git a/cache/jobsCache.go b/cache/jobsCache.go new file mode 100644 index 000000000..a13f1e0cd --- /dev/null +++ b/cache/jobsCache.go @@ -0,0 +1,35 @@ +package cache + +import ( + "razor/pkg/bindings" + "sync" +) + +// JobsCache struct to hold job cache and associated mutex +type JobsCache struct { + Jobs map[uint16]bindings.StructsJob + Mu sync.RWMutex +} + +// NewJobsCache creates a new instance of JobsCache +func NewJobsCache() *JobsCache { + return &JobsCache{ + Jobs: make(map[uint16]bindings.StructsJob), + Mu: sync.RWMutex{}, + } +} + +func (j *JobsCache) GetJob(jobId uint16) (bindings.StructsJob, bool) { + j.Mu.RLock() + defer j.Mu.RUnlock() + + job, exists := j.Jobs[jobId] + return job, exists +} + +func (j *JobsCache) UpdateJob(jobId uint16, updatedJob bindings.StructsJob) { + j.Mu.Lock() + defer j.Mu.Unlock() + + j.Jobs[jobId] = updatedJob +} diff --git a/cmd/addStake.go b/cmd/addStake.go index 9ae55fcd2..b8765442d 100644 --- a/cmd/addStake.go +++ b/cmd/addStake.go @@ -2,6 +2,7 @@ package cmd import ( + "razor/accounts" "razor/core" "razor/core/types" "razor/logger" @@ -49,7 +50,12 @@ func (*UtilsStruct) ExecuteStake(flagSet *pflag.FlagSet) { log.Debug("Getting password...") password := razorUtils.AssignPassword(flagSet) - err = razorUtils.CheckPassword(address, password) + accountManager, err := razorUtils.AccountManagerForKeystore() + utils.CheckError("Error in getting accounts manager for keystore: ", err) + + account := accounts.InitAccountStruct(address, password, accountManager) + + err = razorUtils.CheckPassword(account) utils.CheckError("Error in fetching private key from given password: ", err) balance, err := razorUtils.FetchBalance(client, address) @@ -87,12 +93,11 @@ func (*UtilsStruct) ExecuteStake(flagSet *pflag.FlagSet) { } txnArgs := types.TransactionOptions{ - Client: client, - AccountAddress: address, - Password: password, - Amount: valueInWei, - ChainId: core.ChainId, - Config: config, + Client: client, + Amount: valueInWei, + ChainId: core.ChainId, + Config: config, + Account: account, } log.Debug("ExecuteStake: Calling Approve() for amount: ", txnArgs.Amount) diff --git a/cmd/addStake_test.go b/cmd/addStake_test.go index 51ed697a0..df21fd316 100644 --- a/cmd/addStake_test.go +++ b/cmd/addStake_test.go @@ -3,6 +3,7 @@ package cmd import ( "errors" "math/big" + "razor/accounts" "razor/core" "razor/core/types" "razor/pkg/bindings" @@ -318,7 +319,8 @@ func TestExecuteStake(t *testing.T) { fileUtilsMock.On("AssignLogFile", mock.AnythingOfType("*pflag.FlagSet"), mock.Anything) cmdUtilsMock.On("GetConfigData").Return(tt.args.config, tt.args.configErr) utilsMock.On("AssignPassword", mock.AnythingOfType("*pflag.FlagSet")).Return(tt.args.password) - utilsMock.On("CheckPassword", mock.Anything, mock.Anything).Return(nil) + utilsMock.On("CheckPassword", mock.Anything).Return(nil) + utilsMock.On("AccountManagerForKeystore").Return(&accounts.AccountManager{}, nil) flagSetMock.On("GetStringAddress", mock.AnythingOfType("*pflag.FlagSet")).Return(tt.args.address, tt.args.addressErr) utilsMock.On("ConnectToClient", mock.AnythingOfType("string")).Return(client) utilsMock.On("WaitForBlockCompletion", mock.AnythingOfType("*ethclient.Client"), mock.AnythingOfType("string")).Return(nil) diff --git a/cmd/approve.go b/cmd/approve.go index 1a8cf1b8a..76f5e991f 100644 --- a/cmd/approve.go +++ b/cmd/approve.go @@ -11,7 +11,7 @@ import ( //This function approves the transaction if the user has sufficient balance otherwise it fails the transaction func (*UtilsStruct) Approve(txnArgs types.TransactionOptions) (common.Hash, error) { opts := razorUtils.GetOptions() - allowance, err := tokenManagerUtils.Allowance(txnArgs.Client, &opts, common.HexToAddress(txnArgs.AccountAddress), common.HexToAddress(core.StakeManagerAddress)) + allowance, err := tokenManagerUtils.Allowance(txnArgs.Client, &opts, common.HexToAddress(txnArgs.Account.Address), common.HexToAddress(core.StakeManagerAddress)) if err != nil { return core.NilHash, err } diff --git a/cmd/claimBounty.go b/cmd/claimBounty.go index e4513cd68..0e91572bd 100644 --- a/cmd/claimBounty.go +++ b/cmd/claimBounty.go @@ -5,6 +5,7 @@ import ( "errors" "math/big" "os" + "razor/accounts" "razor/core" "razor/core/types" "razor/logger" @@ -53,7 +54,12 @@ func (*UtilsStruct) ExecuteClaimBounty(flagSet *pflag.FlagSet) { log.Debug("Getting password...") password := razorUtils.AssignPassword(flagSet) - err = razorUtils.CheckPassword(address, password) + accountManager, err := razorUtils.AccountManagerForKeystore() + utils.CheckError("Error in getting accounts manager for keystore: ", err) + + account := accounts.InitAccountStruct(address, password, accountManager) + + err = razorUtils.CheckPassword(account) utils.CheckError("Error in fetching private key from given password: ", err) if razorUtils.IsFlagPassed("bountyId") { @@ -62,12 +68,10 @@ func (*UtilsStruct) ExecuteClaimBounty(flagSet *pflag.FlagSet) { log.Debug("ExecuteClaimBounty: BountyId: ", bountyId) redeemBountyInput := types.RedeemBountyInput{ - Address: address, - Password: password, BountyId: bountyId, + Account: account, } - log.Debugf("ExecuteClaimBounty: Calling ClaimBounty() with arguments redeem bounty input: %+v", redeemBountyInput) txn, err := cmdUtils.ClaimBounty(config, client, redeemBountyInput) utils.CheckError("ClaimBounty error: ", err) @@ -77,10 +81,7 @@ func (*UtilsStruct) ExecuteClaimBounty(flagSet *pflag.FlagSet) { } } else { log.Debug("ExecuteClaimBounty: Calling HandleClaimBounty()") - err := cmdUtils.HandleClaimBounty(client, config, types.Account{ - Address: address, - Password: password, - }) + err := cmdUtils.HandleClaimBounty(client, config, account) utils.CheckError("HandleClaimBounty error: ", err) } @@ -114,8 +115,7 @@ func (*UtilsStruct) HandleClaimBounty(client *ethclient.Client, config types.Con log.Info("Claiming bounty for bountyId ", disputeData.BountyIdQueue[length-1]) redeemBountyInput := types.RedeemBountyInput{ BountyId: disputeData.BountyIdQueue[length-1], - Address: account.Address, - Password: account.Password, + Account: account, } log.Debugf("HandleClaimBounty: Calling ClaimBounty() with arguments redeemBountyInput: %+v", redeemBountyInput) claimBountyTxn, err := cmdUtils.ClaimBounty(config, client, redeemBountyInput) @@ -147,8 +147,7 @@ func (*UtilsStruct) HandleClaimBounty(client *ethclient.Client, config types.Con func (*UtilsStruct) ClaimBounty(config types.Configurations, client *ethclient.Client, redeemBountyInput types.RedeemBountyInput) (common.Hash, error) { txnArgs := types.TransactionOptions{ Client: client, - AccountAddress: redeemBountyInput.Address, - Password: redeemBountyInput.Password, + Account: redeemBountyInput.Account, ChainId: core.ChainId, Config: config, ContractAddress: core.StakeManagerAddress, diff --git a/cmd/claimBounty_test.go b/cmd/claimBounty_test.go index 552d93fd1..848540833 100644 --- a/cmd/claimBounty_test.go +++ b/cmd/claimBounty_test.go @@ -4,6 +4,7 @@ import ( "errors" "io/fs" "math/big" + "razor/accounts" "razor/cmd/mocks" "razor/core" "razor/core/types" @@ -123,7 +124,8 @@ func TestExecuteClaimBounty(t *testing.T) { fileUtilsMock.On("AssignLogFile", mock.AnythingOfType("*pflag.FlagSet"), mock.Anything) cmdUtilsMock.On("GetConfigData").Return(tt.args.config, tt.args.configErr) utilsMock.On("AssignPassword", mock.AnythingOfType("*pflag.FlagSet")).Return(tt.args.password) - utilsMock.On("CheckPassword", mock.Anything, mock.Anything).Return(nil) + utilsMock.On("CheckPassword", mock.Anything).Return(nil) + utilsMock.On("AccountManagerForKeystore").Return(&accounts.AccountManager{}, nil) flagSetMock.On("GetStringAddress", mock.AnythingOfType("*pflag.FlagSet")).Return(tt.args.address, tt.args.addressErr) flagSetMock.On("GetUint32BountyId", mock.AnythingOfType("*pflag.FlagSet")).Return(tt.args.bountyId, tt.args.bountyIdErr) utilsMock.On("ConnectToClient", mock.AnythingOfType("string")).Return(client) diff --git a/cmd/claimCommission.go b/cmd/claimCommission.go index e79b71db7..6de6853df 100644 --- a/cmd/claimCommission.go +++ b/cmd/claimCommission.go @@ -3,6 +3,7 @@ package cmd import ( "math/big" + "razor/accounts" "razor/core" "razor/core/types" "razor/logger" @@ -45,7 +46,12 @@ func (*UtilsStruct) ClaimCommission(flagSet *pflag.FlagSet) { log.Debug("Getting password...") password := razorUtils.AssignPassword(flagSet) - err = razorUtils.CheckPassword(address, password) + accountManager, err := razorUtils.AccountManagerForKeystore() + utils.CheckError("Error in getting accounts manager for keystore: ", err) + + account := accounts.InitAccountStruct(address, password, accountManager) + + err = razorUtils.CheckPassword(account) utils.CheckError("Error in fetching private key from given password: ", err) stakerId, err := razorUtils.GetStakerId(client, address) @@ -60,14 +66,13 @@ func (*UtilsStruct) ClaimCommission(flagSet *pflag.FlagSet) { if stakerInfo.StakerReward.Cmp(big.NewInt(0)) > 0 { txnOpts := razorUtils.GetTxnOpts(types.TransactionOptions{ Client: client, - AccountAddress: address, - Password: password, ChainId: core.ChainId, Config: config, ContractAddress: core.StakeManagerAddress, MethodName: "claimStakerReward", Parameters: []interface{}{}, ABI: bindings.StakeManagerMetaData.ABI, + Account: account, }) log.Info("Claiming commission...") diff --git a/cmd/claimCommission_test.go b/cmd/claimCommission_test.go index aa2b7ba4a..50a252130 100644 --- a/cmd/claimCommission_test.go +++ b/cmd/claimCommission_test.go @@ -3,6 +3,7 @@ package cmd import ( "errors" "math/big" + "razor/accounts" "razor/core/types" "testing" @@ -201,7 +202,8 @@ func TestClaimCommission(t *testing.T) { utilsMock.On("GetStakerId", mock.AnythingOfType("*ethclient.Client"), mock.AnythingOfType("string")).Return(tt.args.stakerId, tt.args.stakerIdErr) utilsMock.On("GetOptions").Return(callOpts) utilsMock.On("AssignPassword", mock.AnythingOfType("*pflag.FlagSet")).Return(tt.args.password) - utilsMock.On("CheckPassword", mock.Anything, mock.Anything).Return(nil) + utilsMock.On("CheckPassword", mock.Anything).Return(nil) + utilsMock.On("AccountManagerForKeystore").Return(&accounts.AccountManager{}, nil) utilsMock.On("ConnectToClient", mock.AnythingOfType("string")).Return(client) utilsMock.On("GetTxnOpts", mock.AnythingOfType("types.TransactionOptions")).Return(TxnOpts) utilsMock.On("WaitForBlockCompletion", mock.AnythingOfType("*ethclient.Client"), mock.Anything).Return(nil) diff --git a/cmd/cmd-utils.go b/cmd/cmd-utils.go index 30a84e1cd..2583c3586 100644 --- a/cmd/cmd-utils.go +++ b/cmd/cmd-utils.go @@ -23,7 +23,12 @@ func (*UtilsStruct) GetEpochAndState(client *ethclient.Client) (uint32, int64, e if err != nil { return 0, 0, err } - state, err := razorUtils.GetBufferedState(client, bufferPercent) + latestHeader, err := clientUtils.GetLatestBlockWithRetry(client) + if err != nil { + log.Error("Error in fetching block: ", err) + return 0, 0, err + } + state, err := razorUtils.GetBufferedState(client, latestHeader, bufferPercent) if err != nil { return 0, 0, err } diff --git a/cmd/cmd-utils_test.go b/cmd/cmd-utils_test.go index 63f543611..0da68b1e5 100644 --- a/cmd/cmd-utils_test.go +++ b/cmd/cmd-utils_test.go @@ -2,6 +2,7 @@ package cmd import ( "errors" + Types "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/ethclient" "github.com/spf13/pflag" "github.com/stretchr/testify/mock" @@ -15,6 +16,8 @@ func TestGetEpochAndState(t *testing.T) { type args struct { epoch uint32 epochErr error + latestHeader *Types.Header + latestHeaderErr error bufferPercent int32 bufferPercentErr error state int64 @@ -32,6 +35,7 @@ func TestGetEpochAndState(t *testing.T) { name: "Test 1: When GetEpochAndState function executes successfully", args: args{ epoch: 4, + latestHeader: &Types.Header{}, bufferPercent: 20, state: 0, stateName: "commit", @@ -44,6 +48,7 @@ func TestGetEpochAndState(t *testing.T) { name: "Test 2: When there is an error in getting epoch", args: args{ epochErr: errors.New("epoch error"), + latestHeader: &Types.Header{}, bufferPercent: 20, state: 0, stateName: "commit", @@ -56,6 +61,7 @@ func TestGetEpochAndState(t *testing.T) { name: "Test 3: When there is an error in getting bufferPercent", args: args{ epoch: 4, + latestHeader: &Types.Header{}, bufferPercentErr: errors.New("bufferPercent error"), state: 0, stateName: "commit", @@ -68,6 +74,7 @@ func TestGetEpochAndState(t *testing.T) { name: "Test 4: When there is an error in getting state", args: args{ epoch: 4, + latestHeader: &Types.Header{}, bufferPercent: 20, stateErr: errors.New("state error"), }, @@ -75,6 +82,19 @@ func TestGetEpochAndState(t *testing.T) { wantState: 0, wantErr: errors.New("state error"), }, + { + name: "Test 5: When there is an error in getting latest header", + args: args{ + epoch: 4, + latestHeaderErr: errors.New("header error"), + bufferPercent: 20, + state: 0, + stateName: "commit", + }, + wantEpoch: 0, + wantState: 0, + wantErr: errors.New("header error"), + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { @@ -82,7 +102,8 @@ func TestGetEpochAndState(t *testing.T) { utilsMock.On("GetEpoch", mock.AnythingOfType("*ethclient.Client")).Return(tt.args.epoch, tt.args.epochErr) cmdUtilsMock.On("GetBufferPercent").Return(tt.args.bufferPercent, tt.args.bufferPercentErr) - utilsMock.On("GetBufferedState", mock.AnythingOfType("*ethclient.Client"), mock.AnythingOfType("int32")).Return(tt.args.state, tt.args.stateErr) + clientUtilsMock.On("GetLatestBlockWithRetry", mock.Anything).Return(tt.args.latestHeader, tt.args.latestHeaderErr) + utilsMock.On("GetBufferedState", mock.Anything, mock.Anything, mock.Anything).Return(tt.args.state, tt.args.stateErr) utils := &UtilsStruct{} gotEpoch, gotState, err := utils.GetEpochAndState(client) diff --git a/cmd/commit.go b/cmd/commit.go index e7148975c..df340bf5d 100644 --- a/cmd/commit.go +++ b/cmd/commit.go @@ -13,6 +13,8 @@ import ( "sync" "time" + Types "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/ethclient" solsha3 "github.com/miguelmota/go-solidity-sha3" @@ -56,7 +58,7 @@ func (*UtilsStruct) GetSalt(client *ethclient.Client, epoch uint32) ([32]byte, e HandleCommitState fetches the collections assigned to the staker and creates the leaves required for the merkle tree generation. Values for only the collections assigned to the staker is fetched for others, 0 is added to the leaves of tree. */ -func (*UtilsStruct) HandleCommitState(client *ethclient.Client, epoch uint32, seed []byte, rogueData types.Rogue) (types.CommitData, error) { +func (*UtilsStruct) HandleCommitState(client *ethclient.Client, epoch uint32, seed []byte, commitParams *types.CommitParams, rogueData types.Rogue) (types.CommitData, error) { numActiveCollections, err := razorUtils.GetNumActiveCollections(client) if err != nil { return types.CommitData{}, err @@ -78,7 +80,7 @@ func (*UtilsStruct) HandleCommitState(client *ethclient.Client, epoch uint32, se var wg sync.WaitGroup log.Debug("Creating a local cache which will store API result and expire at the end of commit state") - localCache := cache.NewLocalCache(time.Second * time.Duration(core.StateLength)) + commitParams.LocalCache = cache.NewLocalCache(time.Second * time.Duration(core.StateLength)) log.Debug("Iterating over all the collections...") for i := 0; i < int(numActiveCollections); i++ { @@ -95,7 +97,7 @@ func (*UtilsStruct) HandleCommitState(client *ethclient.Client, epoch uint32, se errChan <- err return } - collectionData, err := razorUtils.GetAggregatedDataOfCollection(client, collectionId, epoch, localCache) + collectionData, err := razorUtils.GetAggregatedDataOfCollection(client, collectionId, epoch, commitParams) if err != nil { log.Error("Error in getting aggregated data of collection: ", err) errChan <- err @@ -127,7 +129,7 @@ func (*UtilsStruct) HandleCommitState(client *ethclient.Client, epoch uint32, se if err != nil { // Returning the first error from the error channel log.Error("Error in getting collection data: ", err) - localCache.StopCleanup() + commitParams.LocalCache.StopCleanup() return types.CommitData{}, err } } @@ -137,7 +139,7 @@ func (*UtilsStruct) HandleCommitState(client *ethclient.Client, epoch uint32, se log.Debug("HandleCommitState: SeqAllottedCollections: ", seqAllottedCollections) log.Debug("HandleCommitState: Leaves: ", leavesOfTree) - localCache.StopCleanup() + commitParams.LocalCache.StopCleanup() return types.CommitData{ AssignedCollections: assignedCollections, @@ -149,8 +151,8 @@ func (*UtilsStruct) HandleCommitState(client *ethclient.Client, epoch uint32, se /* Commit finally commits the data to the smart contract. It calculates the commitment to send using the merkle tree root and the seed. */ -func (*UtilsStruct) Commit(client *ethclient.Client, config types.Configurations, account types.Account, epoch uint32, seed []byte, values []*big.Int) (common.Hash, error) { - if state, err := razorUtils.GetBufferedState(client, config.BufferPercent); err != nil || state != 0 { +func (*UtilsStruct) Commit(client *ethclient.Client, config types.Configurations, account types.Account, epoch uint32, latestHeader *Types.Header, seed []byte, values []*big.Int) (common.Hash, error) { + if state, err := razorUtils.GetBufferedState(client, latestHeader, config.BufferPercent); err != nil || state != 0 { log.Error("Not commit state") return core.NilHash, err } @@ -163,14 +165,13 @@ func (*UtilsStruct) Commit(client *ethclient.Client, config types.Configurations txnOpts := razorUtils.GetTxnOpts(types.TransactionOptions{ Client: client, - Password: account.Password, - AccountAddress: account.Address, ChainId: core.ChainId, Config: config, ContractAddress: core.VoteManagerAddress, ABI: bindings.VoteManagerMetaData.ABI, MethodName: "commit", Parameters: []interface{}{epoch, commitmentToSend}, + Account: account, }) log.Info("Commitment sent...") diff --git a/cmd/commit_test.go b/cmd/commit_test.go index bbcaa80cb..bba1409a7 100644 --- a/cmd/commit_test.go +++ b/cmd/commit_test.go @@ -9,21 +9,24 @@ import ( "github.com/ethereum/go-ethereum/ethclient" "github.com/stretchr/testify/mock" "math/big" + "razor/cache" "razor/core" "razor/core/types" "razor/pkg/bindings" "razor/utils" "reflect" "testing" + "time" ) func TestCommit(t *testing.T) { var ( - client *ethclient.Client - account types.Account - config types.Configurations - seed []byte - epoch uint32 + client *ethclient.Client + account types.Account + config types.Configurations + latestHeader *Types.Header + seed []byte + epoch uint32 ) type args struct { @@ -94,13 +97,13 @@ func TestCommit(t *testing.T) { utils.MerkleInterface = &utils.MerkleTreeStruct{} merkleUtils = utils.MerkleInterface - utilsMock.On("GetBufferedState", mock.AnythingOfType("*ethclient.Client"), mock.AnythingOfType("int32")).Return(tt.args.state, tt.args.stateErr) + utilsMock.On("GetBufferedState", mock.AnythingOfType("*ethclient.Client"), mock.Anything, mock.Anything).Return(tt.args.state, tt.args.stateErr) utilsMock.On("GetTxnOpts", mock.AnythingOfType("types.TransactionOptions")).Return(TxnOpts) voteManagerMock.On("Commit", mock.AnythingOfType("*ethclient.Client"), mock.AnythingOfType("*bind.TransactOpts"), mock.AnythingOfType("uint32"), mock.Anything).Return(tt.args.commitTxn, tt.args.commitErr) transactionMock.On("Hash", mock.AnythingOfType("*types.Transaction")).Return(tt.args.hash) utils := &UtilsStruct{} - got, err := utils.Commit(client, config, account, epoch, seed, tt.args.values) + got, err := utils.Commit(client, config, account, epoch, latestHeader, seed, tt.args.values) if got != tt.want { t.Errorf("Txn hash for Commit function, got = %v, want = %v", got, tt.want) } @@ -223,16 +226,21 @@ func TestHandleCommitState(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { + localCache := cache.NewLocalCache(time.Second * 10) + commitParams := &types.CommitParams{ + LocalCache: localCache, + } + SetUpMockInterfaces() utilsMock.On("GetNumActiveCollections", mock.AnythingOfType("*ethclient.Client")).Return(tt.args.numActiveCollections, tt.args.numActiveCollectionsErr) utilsMock.On("GetAssignedCollections", mock.AnythingOfType("*ethclient.Client"), mock.Anything, mock.Anything).Return(tt.args.assignedCollections, tt.args.seqAllottedCollections, tt.args.assignedCollectionsErr) utilsMock.On("GetCollectionIdFromIndex", mock.AnythingOfType("*ethclient.Client"), mock.Anything).Return(tt.args.collectionId, tt.args.collectionIdErr) - utilsMock.On("GetAggregatedDataOfCollection", mock.AnythingOfType("*ethclient.Client"), mock.Anything, mock.Anything, mock.Anything).Return(tt.args.collectionData, tt.args.collectionDataErr) + utilsMock.On("GetAggregatedDataOfCollection", mock.AnythingOfType("*ethclient.Client"), mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(tt.args.collectionData, tt.args.collectionDataErr) utilsMock.On("GetRogueRandomValue", mock.Anything).Return(rogueValue) utils := &UtilsStruct{} - got, err := utils.HandleCommitState(client, epoch, seed, tt.args.rogueData) + got, err := utils.HandleCommitState(client, epoch, seed, commitParams, tt.args.rogueData) if !reflect.DeepEqual(got, tt.want) { t.Errorf("Data from HandleCommitState function, got = %v, want = %v", got, tt.want) } @@ -388,16 +396,21 @@ func BenchmarkHandleCommitState(b *testing.B) { for _, v := range table { b.Run(fmt.Sprintf("Number_Of_Active_Collections%d", v.numActiveCollections), func(b *testing.B) { for i := 0; i < b.N; i++ { + localCache := cache.NewLocalCache(time.Second * 10) + commitParams := &types.CommitParams{ + LocalCache: localCache, + } + SetUpMockInterfaces() utilsMock.On("GetNumActiveCollections", mock.AnythingOfType("*ethclient.Client")).Return(v.numActiveCollections, nil) utilsMock.On("GetAssignedCollections", mock.AnythingOfType("*ethclient.Client"), mock.Anything, mock.Anything).Return(v.assignedCollections, nil, nil) utilsMock.On("GetCollectionIdFromIndex", mock.AnythingOfType("*ethclient.Client"), mock.Anything).Return(uint16(1), nil) - utilsMock.On("GetAggregatedDataOfCollection", mock.AnythingOfType("*ethclient.Client"), mock.Anything, mock.Anything, mock.Anything).Return(big.NewInt(1000), nil) + utilsMock.On("GetAggregatedDataOfCollection", mock.AnythingOfType("*ethclient.Client"), mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(big.NewInt(1000), nil) utilsMock.On("GetRogueRandomValue", mock.Anything).Return(rogueValue) ut := &UtilsStruct{} - _, err := ut.HandleCommitState(client, epoch, seed, types.Rogue{IsRogue: false}) + _, err := ut.HandleCommitState(client, epoch, seed, commitParams, types.Rogue{IsRogue: false}) if err != nil { log.Fatal(err) } diff --git a/cmd/config-utils.go b/cmd/config-utils.go index 6fde89832..a5e5839a1 100644 --- a/cmd/config-utils.go +++ b/cmd/config-utils.go @@ -99,7 +99,6 @@ func (*UtilsStruct) GetConfigData() (types.Configurations, error) { config.RPCTimeout = rpcTimeout utils.RPCTimeout = rpcTimeout config.HTTPTimeout = httpTimeout - utils.HTTPTimeout = httpTimeout config.LogFileMaxSize = logFileMaxSize config.LogFileMaxBackups = logFileMaxBackups config.LogFileMaxAge = logFileMaxAge @@ -210,7 +209,7 @@ func (*UtilsStruct) GetMultiplier() (float32, error) { func (*UtilsStruct) GetBufferPercent() (int32, error) { const ( MinBufferPercent = 0 - MaxBufferPercent = 5 + MaxBufferPercent = 30 ) bufferPercent, err := getConfigValue("buffer", "int32", core.DefaultBufferPercent, "buffer") @@ -238,8 +237,8 @@ func (*UtilsStruct) GetBufferPercent() (int32, error) { //This function returns the wait time func (*UtilsStruct) GetWaitTime() (int32, error) { const ( - MinWaitTime = 1 // Minimum wait time in seconds - MaxWaitTime = 5 // Maximum wait time in seconds + MinWaitTime = 1 // Minimum wait time in seconds + MaxWaitTime = 30 // Maximum wait time in seconds ) waitTime, err := getConfigValue("wait", "int32", core.DefaultWaitTime, "wait") @@ -335,7 +334,7 @@ func (*UtilsStruct) GetGasLimitOverride() (uint64, error) { func (*UtilsStruct) GetRPCTimeout() (int64, error) { const ( MinRPCTimeout = 10 // Minimum RPC timeout in seconds - MaxRPCTimeout = 20 // Maximum RPC timeout in seconds + MaxRPCTimeout = 60 // Maximum RPC timeout in seconds ) rpcTimeout, err := getConfigValue("rpcTimeout", "int64", core.DefaultRPCTimeout, "rpcTimeout") @@ -357,7 +356,7 @@ func (*UtilsStruct) GetRPCTimeout() (int64, error) { func (*UtilsStruct) GetHTTPTimeout() (int64, error) { const ( MinHTTPTimeout = 10 // Minimum HTTP timeout in seconds - MaxHTTPTimeout = 20 // Maximum HTTP timeout in seconds + MaxHTTPTimeout = 60 // Maximum HTTP timeout in seconds ) httpTimeout, err := getConfigValue("httpTimeout", "int64", core.DefaultHTTPTimeout, "httpTimeout") diff --git a/cmd/confirm.go b/cmd/confirm.go index 000cc3616..e9d308b04 100644 --- a/cmd/confirm.go +++ b/cmd/confirm.go @@ -29,7 +29,7 @@ func (*UtilsStruct) ClaimBlockReward(options types.TransactionOptions) (common.H return core.NilHash, nil } - stakerID, err := razorUtils.GetStakerId(options.Client, options.AccountAddress) + stakerID, err := razorUtils.GetStakerId(options.Client, options.Account.Address) if err != nil { log.Error("Error in getting stakerId: ", err) return core.NilHash, err diff --git a/cmd/create.go b/cmd/create.go index 639318672..71ca08a98 100644 --- a/cmd/create.go +++ b/cmd/create.go @@ -49,8 +49,14 @@ func (*UtilsStruct) Create(password string) (accounts.Account, error) { return accounts.Account{Address: common.Address{0x00}}, err } log.Debug("Create: .razor directory path: ", razorPath) + accountManager, err := razorUtils.AccountManagerForKeystore() + if err != nil { + log.Error("Error in getting accounts manager for keystore: ", err) + return accounts.Account{Address: common.Address{0x00}}, err + } + keystorePath := filepath.Join(razorPath, "keystore_files") - account := accountUtils.CreateAccount(keystorePath, password) + account := accountManager.CreateAccount(keystorePath, password) return account, nil } diff --git a/cmd/createCollection.go b/cmd/createCollection.go index be61d6509..d6c44cd93 100644 --- a/cmd/createCollection.go +++ b/cmd/createCollection.go @@ -2,6 +2,7 @@ package cmd import ( + "razor/accounts" "razor/core" "razor/core/types" "razor/logger" @@ -51,7 +52,12 @@ func (*UtilsStruct) ExecuteCreateCollection(flagSet *pflag.FlagSet) { log.Debug("Getting password...") password := razorUtils.AssignPassword(flagSet) - err = razorUtils.CheckPassword(address, password) + accountManager, err := razorUtils.AccountManagerForKeystore() + utils.CheckError("Error in getting accounts manager for keystore: ", err) + + account := accounts.InitAccountStruct(address, password, accountManager) + + err = razorUtils.CheckPassword(account) utils.CheckError("Error in fetching private key from given password: ", err) name, err := flagSetUtils.GetStringName(flagSet) @@ -70,16 +76,14 @@ func (*UtilsStruct) ExecuteCreateCollection(flagSet *pflag.FlagSet) { utils.CheckError("Error in getting tolerance: ", err) collectionInput := types.CreateCollectionInput{ - Address: address, - Password: password, Power: power, Name: name, Aggregation: aggregation, JobIds: jobIdInUint, Tolerance: tolerance, + Account: account, } - log.Debugf("Calling CreateCollection() with argument collectionInput: %+v", collectionInput) txn, err := cmdUtils.CreateCollection(client, config, collectionInput) utils.CheckError("CreateCollection error: ", err) err = razorUtils.WaitForBlockCompletion(client, txn.Hex()) @@ -97,14 +101,13 @@ func (*UtilsStruct) CreateCollection(client *ethclient.Client, config types.Conf } txnOpts := razorUtils.GetTxnOpts(types.TransactionOptions{ Client: client, - Password: collectionInput.Password, - AccountAddress: collectionInput.Address, ChainId: core.ChainId, Config: config, ContractAddress: core.CollectionManagerAddress, MethodName: "createCollection", Parameters: []interface{}{collectionInput.Tolerance, collectionInput.Power, collectionInput.Aggregation, jobIds, collectionInput.Name}, ABI: bindings.CollectionManagerMetaData.ABI, + Account: collectionInput.Account, }) log.Debugf("Executing CreateCollection transaction with tolerance: %d, power = %d , aggregation = %d, jobIds = %v, name = %s", collectionInput.Tolerance, collectionInput.Power, collectionInput.Aggregation, jobIds, collectionInput.Name) txn, err := assetManagerUtils.CreateCollection(client, txnOpts, collectionInput.Tolerance, collectionInput.Power, collectionInput.Aggregation, jobIds, collectionInput.Name) diff --git a/cmd/createCollection_test.go b/cmd/createCollection_test.go index 9c03dd3a9..cb8cfcc08 100644 --- a/cmd/createCollection_test.go +++ b/cmd/createCollection_test.go @@ -3,6 +3,7 @@ package cmd import ( "errors" "math/big" + "razor/accounts" "razor/core" "razor/core/types" "testing" @@ -275,7 +276,8 @@ func TestExecuteCreateCollection(t *testing.T) { fileUtilsMock.On("AssignLogFile", mock.AnythingOfType("*pflag.FlagSet"), mock.Anything) cmdUtilsMock.On("GetConfigData").Return(tt.args.config, tt.args.configErr) utilsMock.On("AssignPassword", flagSet).Return(tt.args.password) - utilsMock.On("CheckPassword", mock.Anything, mock.Anything).Return(nil) + utilsMock.On("CheckPassword", mock.Anything).Return(nil) + utilsMock.On("AccountManagerForKeystore").Return(&accounts.AccountManager{}, nil) flagSetMock.On("GetStringAddress", flagSet).Return(tt.args.address, tt.args.addressErr) flagSetMock.On("GetStringName", flagSet).Return(tt.args.name, tt.args.nameErr) flagSetMock.On("GetUintSliceJobIds", flagSet).Return(tt.args.jobId, tt.args.jobIdErr) diff --git a/cmd/createJob.go b/cmd/createJob.go index 30a399fda..df93330cf 100644 --- a/cmd/createJob.go +++ b/cmd/createJob.go @@ -2,6 +2,7 @@ package cmd import ( + "razor/accounts" "razor/core" "razor/core/types" "razor/logger" @@ -52,7 +53,12 @@ func (*UtilsStruct) ExecuteCreateJob(flagSet *pflag.FlagSet) { log.Debug("Getting password...") password := razorUtils.AssignPassword(flagSet) - err = razorUtils.CheckPassword(address, password) + accountManager, err := razorUtils.AccountManagerForKeystore() + utils.CheckError("Error in getting accounts manager for keystore: ", err) + + account := accounts.InitAccountStruct(address, password, accountManager) + + err = razorUtils.CheckPassword(account) utils.CheckError("Error in fetching private key from given password: ", err) name, err := flagSetUtils.GetStringName(flagSet) @@ -74,16 +80,15 @@ func (*UtilsStruct) ExecuteCreateJob(flagSet *pflag.FlagSet) { utils.CheckError("Error in getting selectorType: ", err) jobInput := types.CreateJobInput{ - Address: address, - Password: password, Url: url, Name: name, Selector: selector, SelectorType: selectorType, Weight: weight, Power: power, + Account: account, } - log.Debugf("ExecuteCreateJob: Calling CreateJob() with argument jobInput: %+v", jobInput) + txn, err := cmdUtils.CreateJob(client, config, jobInput) utils.CheckError("CreateJob error: ", err) err = razorUtils.WaitForBlockCompletion(client, txn.Hex()) @@ -94,14 +99,13 @@ func (*UtilsStruct) ExecuteCreateJob(flagSet *pflag.FlagSet) { func (*UtilsStruct) CreateJob(client *ethclient.Client, config types.Configurations, jobInput types.CreateJobInput) (common.Hash, error) { txnArgs := types.TransactionOptions{ Client: client, - Password: jobInput.Password, - AccountAddress: jobInput.Address, ChainId: core.ChainId, Config: config, ContractAddress: core.CollectionManagerAddress, MethodName: "createJob", Parameters: []interface{}{jobInput.Weight, jobInput.Power, jobInput.SelectorType, jobInput.Name, jobInput.Selector, jobInput.Url}, ABI: bindings.CollectionManagerMetaData.ABI, + Account: jobInput.Account, } txnOpts := razorUtils.GetTxnOpts(txnArgs) diff --git a/cmd/createJob_test.go b/cmd/createJob_test.go index be5d088ae..81bb56119 100644 --- a/cmd/createJob_test.go +++ b/cmd/createJob_test.go @@ -3,6 +3,7 @@ package cmd import ( "errors" "math/big" + "razor/accounts" "razor/core" "razor/core/types" "testing" @@ -297,7 +298,8 @@ func TestExecuteCreateJob(t *testing.T) { fileUtilsMock.On("AssignLogFile", mock.AnythingOfType("*pflag.FlagSet"), mock.Anything) cmdUtilsMock.On("GetConfigData").Return(tt.args.config, tt.args.configErr) utilsMock.On("AssignPassword", flagSet).Return(tt.args.password) - utilsMock.On("CheckPassword", mock.Anything, mock.Anything).Return(nil) + utilsMock.On("CheckPassword", mock.Anything).Return(nil) + utilsMock.On("AccountManagerForKeystore").Return(&accounts.AccountManager{}, nil) flagSetMock.On("GetStringAddress", flagSet).Return(tt.args.address, tt.args.addressErr) flagSetMock.On("GetStringName", flagSet).Return(tt.args.name, tt.args.nameErr) flagSetMock.On("GetStringUrl", flagSet).Return(tt.args.url, tt.args.urlErr) diff --git a/cmd/create_test.go b/cmd/create_test.go index 2ddd5a02d..cb7bf36e9 100644 --- a/cmd/create_test.go +++ b/cmd/create_test.go @@ -2,7 +2,10 @@ package cmd import ( "errors" + accountsPkgMocks "razor/accounts/mocks" "razor/core/types" + pathPkgMocks "razor/path/mocks" + utilsPkgMocks "razor/utils/mocks" "testing" "github.com/ethereum/go-ethereum/accounts" @@ -14,10 +17,15 @@ import ( func TestCreate(t *testing.T) { var password string + nilAccount := accounts.Account{Address: common.Address{0x00}, + URL: accounts.URL{Scheme: "TestKeyScheme", Path: "test/key/path"}, + } + type args struct { - path string - pathErr error - account accounts.Account + path string + pathErr error + accountManagerErr error + account accounts.Account } tests := []struct { name string @@ -48,21 +56,40 @@ func TestCreate(t *testing.T) { URL: accounts.URL{Scheme: "TestKeyScheme", Path: "test/key/path"}, }, }, - want: accounts.Account{Address: common.Address{0x00}, - URL: accounts.URL{Scheme: "TestKeyScheme", Path: "test/key/path"}, - }, + want: nilAccount, wantErr: errors.New("path error"), }, + { + name: "Test 3: When there is an error in getting account manager", + args: args{ + path: "/home/local", + pathErr: nil, + accountManagerErr: errors.New("account manager error"), + account: accounts.Account{Address: common.HexToAddress("0x000000000000000000000000000000000000dea1"), + URL: accounts.URL{Scheme: "TestKeyScheme", Path: "test/key/path"}, + }, + }, + want: nilAccount, + wantErr: errors.New("account manager error"), + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - SetUpMockInterfaces() + accountsMock := new(accountsPkgMocks.AccountManagerInterface) + + var pathMock *pathPkgMocks.PathInterface + var utilsMock *utilsPkgMocks.Utils + + pathMock = new(pathPkgMocks.PathInterface) + pathUtils = pathMock + + utilsMock = new(utilsPkgMocks.Utils) + razorUtils = utilsMock pathMock.On("GetDefaultPath").Return(tt.args.path, tt.args.pathErr) - accountsMock.On("CreateAccount", mock.AnythingOfType("string"), mock.AnythingOfType("string")).Return(accounts.Account{ - Address: tt.args.account.Address, - URL: accounts.URL{Scheme: "TestKeyScheme", Path: "test/key/path"}, - }) + utilsMock.On("AccountManagerForKeystore").Return(accountsMock, tt.args.accountManagerErr) + + accountsMock.On("CreateAccount", mock.Anything, mock.Anything).Return(tt.args.account) utils := &UtilsStruct{} got, err := utils.Create(password) @@ -131,7 +158,7 @@ func TestExecuteCreate(t *testing.T) { fileUtilsMock.On("AssignLogFile", mock.AnythingOfType("*pflag.FlagSet"), mock.Anything) utilsMock.On("AssignPassword", mock.AnythingOfType("*pflag.FlagSet")).Return(tt.args.password) - utilsMock.On("CheckPassword", mock.Anything, mock.Anything).Return(nil) + utilsMock.On("CheckPassword", mock.Anything).Return(nil) cmdUtilsMock.On("Create", mock.AnythingOfType("string")).Return(tt.args.account, tt.args.accountErr) cmdUtilsMock.On("GetConfigData").Return(types.Configurations{}, nil) diff --git a/cmd/delegate.go b/cmd/delegate.go index 9645906ff..f14ac0b6d 100644 --- a/cmd/delegate.go +++ b/cmd/delegate.go @@ -2,6 +2,7 @@ package cmd import ( + "razor/accounts" "razor/core" "razor/core/types" "razor/logger" @@ -49,7 +50,12 @@ func (*UtilsStruct) ExecuteDelegate(flagSet *pflag.FlagSet) { log.Debug("Getting password...") password := razorUtils.AssignPassword(flagSet) - err = razorUtils.CheckPassword(address, password) + accountManager, err := razorUtils.AccountManagerForKeystore() + utils.CheckError("Error in getting accounts manager for keystore: ", err) + + account := accounts.InitAccountStruct(address, password, accountManager) + + err = razorUtils.CheckPassword(account) utils.CheckError("Error in fetching private key from given password: ", err) stakerId, err := flagSetUtils.GetUint32StakerId(flagSet) @@ -70,15 +76,13 @@ func (*UtilsStruct) ExecuteDelegate(flagSet *pflag.FlagSet) { razorUtils.CheckEthBalanceIsZero(client, address) txnArgs := types.TransactionOptions{ - Client: client, - Password: password, - Amount: valueInWei, - AccountAddress: address, - ChainId: core.ChainId, - Config: config, + Client: client, + Amount: valueInWei, + ChainId: core.ChainId, + Config: config, + Account: account, } - log.Debugf("ExecuteDelegate: Calling Approve() with transaction arguments: %+v", txnArgs) approveTxnHash, err := cmdUtils.Approve(txnArgs) utils.CheckError("Approve error: ", err) diff --git a/cmd/delegate_test.go b/cmd/delegate_test.go index be9b81e02..fe6ac8811 100644 --- a/cmd/delegate_test.go +++ b/cmd/delegate_test.go @@ -3,6 +3,7 @@ package cmd import ( "errors" "math/big" + "razor/accounts" "razor/core" "razor/core/types" "testing" @@ -239,7 +240,8 @@ func TestExecuteDelegate(t *testing.T) { fileUtilsMock.On("AssignLogFile", mock.AnythingOfType("*pflag.FlagSet"), mock.Anything) cmdUtilsMock.On("GetConfigData").Return(tt.args.config, tt.args.configErr) utilsMock.On("AssignPassword", flagSet).Return(tt.args.password) - utilsMock.On("CheckPassword", mock.Anything, mock.Anything).Return(nil) + utilsMock.On("CheckPassword", mock.Anything).Return(nil) + utilsMock.On("AccountManagerForKeystore").Return(&accounts.AccountManager{}, nil) flagSetMock.On("GetStringAddress", mock.AnythingOfType("*pflag.FlagSet")).Return(tt.args.address, tt.args.addressErr) flagSetMock.On("GetUint32StakerId", flagSet).Return(tt.args.stakerId, tt.args.stakerIdErr) utilsMock.On("ConnectToClient", mock.AnythingOfType("string")).Return(client) diff --git a/cmd/dispute.go b/cmd/dispute.go index ae662c917..516cef698 100644 --- a/cmd/dispute.go +++ b/cmd/dispute.go @@ -36,7 +36,7 @@ func (*UtilsStruct) HandleDispute(client *ethclient.Client, config types.Configu } log.Debug("HandleDispute: SortedProposedBlockIds: ", sortedProposedBlockIds) - biggestStake, biggestStakerId, err := cmdUtils.GetBiggestStakeAndId(client, account.Address, epoch) + biggestStake, biggestStakerId, err := cmdUtils.GetBiggestStakeAndId(client, epoch) if err != nil { return err } @@ -57,11 +57,10 @@ func (*UtilsStruct) HandleDispute(client *ethclient.Client, config types.Configu randomSortedProposedBlockIds := utils.Shuffle(sortedProposedBlockIds) //shuffles the sortedProposedBlockIds array transactionOptions := types.TransactionOptions{ - Client: client, - Password: account.Password, - AccountAddress: account.Address, - ChainId: core.ChainId, - Config: config, + Client: client, + ChainId: core.ChainId, + Config: config, + Account: account, } log.Debug("HandleDispute: Shuffled sorted proposed blocks: ", randomSortedProposedBlockIds) @@ -88,11 +87,10 @@ func (*UtilsStruct) HandleDispute(client *ethclient.Client, config types.Configu log.Warn("PROPOSED BIGGEST STAKE DOES NOT MATCH WITH ACTUAL BIGGEST STAKE") log.Info("Disputing BiggestStakeProposed...") txnOpts := razorUtils.GetTxnOpts(types.TransactionOptions{ - Client: client, - Password: account.Password, - AccountAddress: account.Address, - ChainId: core.ChainId, - Config: config, + Client: client, + ChainId: core.ChainId, + Config: config, + Account: account, }) log.Debugf("Executing DisputeBiggestStakeProposed transaction with arguments epoch = %d, blockIndex = %d, biggest staker Id = %d", epoch, blockIndex, biggestStakerId) disputeBiggestStakeProposedTxn, err := blockManagerUtils.DisputeBiggestStakeProposed(client, txnOpts, epoch, uint8(blockIndex), biggestStakerId) @@ -324,11 +322,10 @@ func (*UtilsStruct) Dispute(client *ethclient.Client, config types.Configuration blockManager := razorUtils.GetBlockManager(client) txnArgs := types.TransactionOptions{ - Client: client, - Password: account.Password, - AccountAddress: account.Address, - ChainId: core.ChainId, - Config: config, + Client: client, + ChainId: core.ChainId, + Config: config, + Account: account, } if !utils.Contains(giveSortedLeafIds, leafId) { @@ -429,7 +426,7 @@ func GiveSorted(client *ethclient.Client, blockManager *bindings.BlockManager, t } callOpts := razorUtils.GetOptions() txnOpts := razorUtils.GetTxnOpts(txnArgs) - disputesMapping, err := blockManagerUtils.Disputes(client, &callOpts, epoch, common.HexToAddress(txnArgs.AccountAddress)) + disputesMapping, err := blockManagerUtils.Disputes(client, &callOpts, epoch, common.HexToAddress(txnArgs.Account.Address)) if err != nil { log.Error("Error in getting disputes mapping: ", disputesMapping) return err diff --git a/cmd/dispute_test.go b/cmd/dispute_test.go index 6723f7e32..2a473f238 100644 --- a/cmd/dispute_test.go +++ b/cmd/dispute_test.go @@ -525,7 +525,7 @@ func TestHandleDispute(t *testing.T) { SetUpMockInterfaces() utilsMock.On("GetSortedProposedBlockIds", mock.AnythingOfType("*ethclient.Client"), mock.AnythingOfType("uint32")).Return(tt.args.sortedProposedBlockIds, tt.args.sortedProposedBlockIdsErr) - cmdUtilsMock.On("GetBiggestStakeAndId", mock.AnythingOfType("*ethclient.Client"), mock.AnythingOfType("string"), mock.AnythingOfType("uint32")).Return(tt.args.biggestStake, tt.args.biggestStakeId, tt.args.biggestStakeErr) + cmdUtilsMock.On("GetBiggestStakeAndId", mock.AnythingOfType("*ethclient.Client"), mock.AnythingOfType("uint32")).Return(tt.args.biggestStake, tt.args.biggestStakeId, tt.args.biggestStakeErr) cmdUtilsMock.On("GetLocalMediansData", mock.AnythingOfType("*ethclient.Client"), mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(types.ProposeFileData{ MediansData: tt.args.medians, RevealedCollectionIds: tt.args.revealedCollectionIds, @@ -1203,7 +1203,7 @@ func BenchmarkHandleDispute(b *testing.B) { BiggestStake: big.NewInt(1).Mul(big.NewInt(5356), big.NewInt(1e18))} utilsMock.On("GetSortedProposedBlockIds", mock.AnythingOfType("*ethclient.Client"), mock.AnythingOfType("uint32")).Return(getUint32DummyIds(v.numOfSortedBlocks), nil) - cmdUtilsMock.On("GetBiggestStakeAndId", mock.AnythingOfType("*ethclient.Client"), mock.AnythingOfType("string"), mock.AnythingOfType("uint32")).Return(big.NewInt(1).Mul(big.NewInt(5356), big.NewInt(1e18)), uint32(2), nil) + cmdUtilsMock.On("GetBiggestStakeAndId", mock.AnythingOfType("*ethclient.Client"), mock.AnythingOfType("uint32")).Return(big.NewInt(1).Mul(big.NewInt(5356), big.NewInt(1e18)), uint32(2), nil) cmdUtilsMock.On("GetLocalMediansData", mock.AnythingOfType("*ethclient.Client"), mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(proposedData, nil) utilsMock.On("GetProposedBlock", mock.AnythingOfType("*ethclient.Client"), mock.AnythingOfType("uint32"), mock.AnythingOfType("uint32")).Return(proposedBlock, nil) utilsMock.On("GetTxnOpts", mock.AnythingOfType("types.TransactionOptions")).Return(txnOpts) diff --git a/cmd/eventListeners.go b/cmd/eventListeners.go new file mode 100644 index 000000000..7b8d876fa --- /dev/null +++ b/cmd/eventListeners.go @@ -0,0 +1,135 @@ +package cmd + +import ( + "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/common" + Types "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/ethclient" + "math/big" + "razor/cache" + "razor/core" + "razor/core/types" + "razor/pkg/bindings" + "razor/utils" + "strings" +) + +func (*UtilsStruct) InitJobAndCollectionCache(client *ethclient.Client) (*cache.JobsCache, *cache.CollectionsCache, *big.Int, error) { + initAssetCacheBlock, err := clientUtils.GetLatestBlockWithRetry(client) + if err != nil { + log.Error("Error in fetching block: ", err) + return nil, nil, nil, err + } + log.Debugf("InitJobAndCollectionCache: Latest header value when initializing jobs and collections cache: %d", initAssetCacheBlock.Number) + + log.Info("INITIALIZING JOBS AND COLLECTIONS CACHE...") + + // Create instances of cache + jobsCache := cache.NewJobsCache() + collectionsCache := cache.NewCollectionsCache() + + // Initialize caches + if err := utils.InitJobsCache(client, jobsCache); err != nil { + log.Error("Error in initializing jobs cache: ", err) + return nil, nil, nil, err + } + if err := utils.InitCollectionsCache(client, collectionsCache); err != nil { + log.Error("Error in initializing collections cache: ", err) + return nil, nil, nil, err + } + + return jobsCache, collectionsCache, initAssetCacheBlock.Number, nil +} + +// CheckForJobAndCollectionEvents checks for specific job and collections event that were emitted. +func CheckForJobAndCollectionEvents(client *ethclient.Client, commitParams *types.CommitParams) error { + collectionManagerContractABI, err := abi.JSON(strings.NewReader(bindings.CollectionManagerMetaData.ABI)) + if err != nil { + log.Errorf("Error in parsing collection manager contract ABI: %v", err) + return err + } + + eventNames := []string{core.JobUpdatedEvent, core.CollectionUpdatedEvent, core.CollectionActivityStatusEvent, core.JobCreatedEvent, core.CollectionCreatedEvent} + + log.Debug("Checking for Job/Collection update events...") + toBlock, err := clientUtils.GetLatestBlockWithRetry(client) + if err != nil { + log.Error("Error in getting latest block to start event listener: ", err) + return err + } + + // Process events and update the fromBlock for the next iteration + newFromBlock, err := processEvents(client, collectionManagerContractABI, commitParams.FromBlockToCheckForEvents, toBlock.Number, eventNames, commitParams.JobsCache, commitParams.CollectionsCache) + if err != nil { + return err + } + + // Update the commitParams with the new fromBlock + commitParams.FromBlockToCheckForEvents = new(big.Int).Add(newFromBlock, big.NewInt(1)) + + return nil +} + +// processEvents fetches and processes logs for multiple event types. +func processEvents(client *ethclient.Client, contractABI abi.ABI, fromBlock, toBlock *big.Int, eventNames []string, jobsCache *cache.JobsCache, collectionsCache *cache.CollectionsCache) (*big.Int, error) { + logs, err := getEventLogs(client, fromBlock, toBlock) + if err != nil { + log.Errorf("Failed to fetch logs: %v", err) + return nil, err + } + + for _, eventName := range eventNames { + eventID := contractABI.Events[eventName].ID.Hex() + for _, vLog := range logs { + if len(vLog.Topics) > 0 && vLog.Topics[0].Hex() == eventID { + switch eventName { + case core.JobUpdatedEvent, core.JobCreatedEvent: + jobId := utils.ConvertHashToUint16(vLog.Topics[1]) + updatedJob, err := utils.UtilsInterface.GetActiveJob(client, jobId) + if err != nil { + log.Errorf("Error in getting job with job Id %v: %v", jobId, err) + continue + } + log.Debugf("RECEIVED JOB EVENT: Updating the job with Id %v with details %+v...", jobId, updatedJob) + jobsCache.UpdateJob(jobId, updatedJob) + case core.CollectionUpdatedEvent, core.CollectionCreatedEvent, core.CollectionActivityStatusEvent: + collectionId := utils.ConvertHashToUint16(vLog.Topics[1]) + newCollection, err := utils.UtilsInterface.GetCollection(client, collectionId) + if err != nil { + log.Errorf("Error in getting collection with collection Id %v: %v", collectionId, err) + continue + } + log.Debugf("RECEIVED COLLECTION EVENT: Updating the collection with ID %v with details %+v", collectionId, newCollection) + collectionsCache.UpdateCollection(collectionId, newCollection) + } + } + } + } + + // Return the new toBlock for the next iteration + return toBlock, nil +} + +// getEventLogs is a utility function to fetch the event logs +func getEventLogs(client *ethclient.Client, fromBlock *big.Int, toBlock *big.Int) ([]Types.Log, error) { + log.Debugf("Checking for events from block %v to block %v...", fromBlock, toBlock) + + // Set up the query for filtering logs + query := ethereum.FilterQuery{ + FromBlock: fromBlock, + ToBlock: toBlock, + Addresses: []common.Address{ + common.HexToAddress(core.CollectionManagerAddress), + }, + } + + // Retrieve the logs + logs, err := clientUtils.FilterLogsWithRetry(client, query) + if err != nil { + log.Errorf("Error in filter logs: %v", err) + return []Types.Log{}, err + } + + return logs, nil +} diff --git a/cmd/initiateWithdraw.go b/cmd/initiateWithdraw.go index 8568baedf..f1393c452 100644 --- a/cmd/initiateWithdraw.go +++ b/cmd/initiateWithdraw.go @@ -4,6 +4,7 @@ package cmd import ( "errors" "math/big" + "razor/accounts" "razor/core" "razor/core/types" "razor/logger" @@ -50,7 +51,12 @@ func (*UtilsStruct) ExecuteInitiateWithdraw(flagSet *pflag.FlagSet) { log.Debug("Getting password...") password := razorUtils.AssignPassword(flagSet) - err = razorUtils.CheckPassword(address, password) + accountManager, err := razorUtils.AccountManagerForKeystore() + utils.CheckError("Error in getting accounts manager for keystore: ", err) + + account := accounts.InitAccountStruct(address, password, accountManager) + + err = razorUtils.CheckPassword(account) utils.CheckError("Error in fetching private key from given password: ", err) stakerId, err := razorUtils.AssignStakerId(flagSet, client, address) @@ -58,12 +64,9 @@ func (*UtilsStruct) ExecuteInitiateWithdraw(flagSet *pflag.FlagSet) { log.Debug("ExecuteInitiateWithdraw: Staker Id: ", stakerId) log.Debugf("ExecuteInitiateWithdraw: Calling HandleUnstakeLock() with arguments account address: %s, stakerId: %d", address, stakerId) - txn, err := cmdUtils.HandleUnstakeLock(client, types.Account{ - Address: address, - Password: password, - }, config, stakerId) - + txn, err := cmdUtils.HandleUnstakeLock(client, account, config, stakerId) utils.CheckError("InitiateWithdraw error: ", err) + if txn != core.NilHash { err := razorUtils.WaitForBlockCompletion(client, txn.Hex()) utils.CheckError("Error in WaitForBlockCompletion for initiateWithdraw: ", err) @@ -121,14 +124,13 @@ func (*UtilsStruct) HandleUnstakeLock(client *ethclient.Client, account types.Ac txnArgs := types.TransactionOptions{ Client: client, - Password: account.Password, - AccountAddress: account.Address, ChainId: core.ChainId, Config: configurations, ContractAddress: core.StakeManagerAddress, MethodName: "initiateWithdraw", ABI: bindings.StakeManagerMetaData.ABI, Parameters: []interface{}{stakerId}, + Account: account, } txnOpts := razorUtils.GetTxnOpts(txnArgs) diff --git a/cmd/initiateWithdraw_test.go b/cmd/initiateWithdraw_test.go index 937be53d2..ac827497f 100644 --- a/cmd/initiateWithdraw_test.go +++ b/cmd/initiateWithdraw_test.go @@ -6,6 +6,7 @@ import ( "errors" "github.com/ethereum/go-ethereum/crypto" "math/big" + "razor/accounts" "razor/core" "razor/core/types" "testing" @@ -363,7 +364,8 @@ func TestExecuteWithdraw(t *testing.T) { fileUtilsMock.On("AssignLogFile", mock.AnythingOfType("*pflag.FlagSet"), mock.Anything) cmdUtilsMock.On("GetConfigData").Return(tt.args.config, tt.args.configErr) utilsMock.On("AssignPassword", flagSet).Return(tt.args.password) - utilsMock.On("CheckPassword", mock.Anything, mock.Anything).Return(nil) + utilsMock.On("CheckPassword", mock.Anything).Return(nil) + utilsMock.On("AccountManagerForKeystore").Return(&accounts.AccountManager{}, nil) flagSetMock.On("GetStringAddress", flagSet).Return(tt.args.address, tt.args.addressErr) utilsMock.On("AssignStakerId", flagSet, mock.AnythingOfType("*ethclient.Client"), mock.Anything).Return(tt.args.stakerId, tt.args.stakerIdErr) utilsMock.On("ConnectToClient", mock.AnythingOfType("string")).Return(client) diff --git a/cmd/interface.go b/cmd/interface.go index 3c2392540..51a1e127d 100644 --- a/cmd/interface.go +++ b/cmd/interface.go @@ -5,7 +5,7 @@ import ( "context" "crypto/ecdsa" "math/big" - Accounts "razor/accounts" + "razor/cache" "razor/core/types" "razor/path" "razor/pkg/bindings" @@ -165,14 +165,14 @@ type UtilsCmdInterface interface { ClaimBounty(config types.Configurations, client *ethclient.Client, redeemBountyInput types.RedeemBountyInput) (common.Hash, error) ClaimBlockReward(options types.TransactionOptions) (common.Hash, error) GetSalt(client *ethclient.Client, epoch uint32) ([32]byte, error) - HandleCommitState(client *ethclient.Client, epoch uint32, seed []byte, rogueData types.Rogue) (types.CommitData, error) - Commit(client *ethclient.Client, config types.Configurations, account types.Account, epoch uint32, seed []byte, values []*big.Int) (common.Hash, error) + HandleCommitState(client *ethclient.Client, epoch uint32, seed []byte, commitParams *types.CommitParams, rogueData types.Rogue) (types.CommitData, error) + Commit(client *ethclient.Client, config types.Configurations, account types.Account, epoch uint32, latestHeader *Types.Header, seed []byte, values []*big.Int) (common.Hash, error) ListAccounts() ([]accounts.Account, error) AssignAmountInWei(flagSet *pflag.FlagSet) (*big.Int, error) ExecuteTransfer(flagSet *pflag.FlagSet) Transfer(client *ethclient.Client, config types.Configurations, transferInput types.TransferInput) (common.Hash, error) CheckForLastCommitted(client *ethclient.Client, staker bindings.StructsStaker, epoch uint32) error - Reveal(client *ethclient.Client, config types.Configurations, account types.Account, epoch uint32, commitData types.CommitData, signature []byte) (common.Hash, error) + Reveal(client *ethclient.Client, config types.Configurations, account types.Account, epoch uint32, latestHeader *Types.Header, commitData types.CommitData, signature []byte) (common.Hash, error) GenerateTreeRevealData(merkleTree [][][]byte, commitData types.CommitData) bindings.StructsMerkleTree IndexRevealEventsOfCurrentEpoch(client *ethclient.Client, blockNumber *big.Int, epoch uint32) ([]types.RevealedStruct, error) ExecuteCreateJob(flagSet *pflag.FlagSet) @@ -207,7 +207,7 @@ type UtilsCmdInterface interface { IsElectedProposer(proposer types.ElectedProposer, currentStakerStake *big.Int) bool GetSortedRevealedValues(client *ethclient.Client, blockNumber *big.Int, epoch uint32) (*types.RevealedDataMaps, error) GetIteration(client *ethclient.Client, proposer types.ElectedProposer, bufferPercent int32) int - Propose(client *ethclient.Client, config types.Configurations, account types.Account, staker bindings.StructsStaker, epoch uint32, blockNumber *big.Int, rogueData types.Rogue) error + Propose(client *ethclient.Client, config types.Configurations, account types.Account, staker bindings.StructsStaker, epoch uint32, latestHeader *Types.Header, rogueData types.Rogue) error GiveSorted(client *ethclient.Client, blockManager *bindings.BlockManager, txnArgs types.TransactionOptions, epoch uint32, assetId uint16, sortedStakers []*big.Int) error GetLocalMediansData(client *ethclient.Client, account types.Account, epoch uint32, blockNumber *big.Int, rogueData types.Rogue) (types.ProposeFileData, error) CheckDisputeForIds(client *ethclient.Client, transactionOpts types.TransactionOptions, epoch uint32, blockIndex uint8, idsInProposedBlock []uint16, revealedCollectionIds []uint16) (*Types.Transaction, error) @@ -228,20 +228,20 @@ type UtilsCmdInterface interface { ImportAccount() (accounts.Account, error) ExecuteUpdateCommission(flagSet *pflag.FlagSet) UpdateCommission(config types.Configurations, client *ethclient.Client, updateCommissionInput types.UpdateCommissionInput) error - GetBiggestStakeAndId(client *ethclient.Client, address string, epoch uint32) (*big.Int, uint32, error) + GetBiggestStakeAndId(client *ethclient.Client, epoch uint32) (*big.Int, uint32, error) GetSmallestStakeAndId(client *ethclient.Client, epoch uint32) (*big.Int, uint32, error) StakeCoins(txnArgs types.TransactionOptions) (common.Hash, error) CalculateSecret(account types.Account, epoch uint32, keystorePath string, chainId *big.Int) ([]byte, []byte, error) - HandleBlock(client *ethclient.Client, account types.Account, blockNumber *big.Int, config types.Configurations, rogueData types.Rogue, backupNodeActionsToIgnore []string) + HandleBlock(client *ethclient.Client, account types.Account, stakerId uint32, header *Types.Header, config types.Configurations, commitParams *types.CommitParams, rogueData types.Rogue, backupNodeActionsToIgnore []string) ExecuteVote(flagSet *pflag.FlagSet) - Vote(ctx context.Context, config types.Configurations, client *ethclient.Client, rogueData types.Rogue, account types.Account, backupNodeActionsToIgnore []string) error + Vote(ctx context.Context, config types.Configurations, client *ethclient.Client, account types.Account, stakerId uint32, commitParams *types.CommitParams, rogueData types.Rogue, backupNodeActionsToIgnore []string) error HandleExit() ExecuteListAccounts(flagSet *pflag.FlagSet) ClaimCommission(flagSet *pflag.FlagSet) ExecuteStake(flagSet *pflag.FlagSet) - InitiateCommit(client *ethclient.Client, config types.Configurations, account types.Account, epoch uint32, stakerId uint32, rogueData types.Rogue) error - InitiateReveal(client *ethclient.Client, config types.Configurations, account types.Account, epoch uint32, staker bindings.StructsStaker, rogueData types.Rogue) error - InitiatePropose(client *ethclient.Client, config types.Configurations, account types.Account, epoch uint32, staker bindings.StructsStaker, blockNumber *big.Int, rogueData types.Rogue) error + InitiateCommit(client *ethclient.Client, config types.Configurations, account types.Account, epoch uint32, stakerId uint32, latestHeader *Types.Header, commitParams *types.CommitParams, rogueData types.Rogue) error + InitiateReveal(client *ethclient.Client, config types.Configurations, account types.Account, epoch uint32, staker bindings.StructsStaker, latestHeader *Types.Header, rogueData types.Rogue) error + InitiatePropose(client *ethclient.Client, config types.Configurations, account types.Account, epoch uint32, staker bindings.StructsStaker, latestHeader *Types.Header, rogueData types.Rogue) error GetBountyIdFromEvents(client *ethclient.Client, blockNumber *big.Int, bountyHunter string) (uint32, error) HandleClaimBounty(client *ethclient.Client, config types.Configurations, account types.Account) error ExecuteContractAddresses(flagSet *pflag.FlagSet) @@ -249,6 +249,8 @@ type UtilsCmdInterface interface { ResetDispute(client *ethclient.Client, blockManager *bindings.BlockManager, txnOpts *bind.TransactOpts, epoch uint32) StoreBountyId(client *ethclient.Client, account types.Account) error CheckToDoResetDispute(client *ethclient.Client, blockManager *bindings.BlockManager, txnOpts *bind.TransactOpts, epoch uint32, sortedValues []*big.Int) + InitJobAndCollectionCache(client *ethclient.Client) (*cache.JobsCache, *cache.CollectionsCache, *big.Int, error) + BatchGetStakeSnapshotCalls(client *ethclient.Client, epoch uint32, numberOfStakers uint32) ([]*big.Int, error) } type TransactionInterface interface { @@ -313,7 +315,6 @@ func InitializeInterfaces() { abiUtils = AbiUtils{} osUtils = OSUtils{} - Accounts.AccountUtilsInterface = Accounts.AccountUtils{} path.PathUtilsInterface = path.PathUtils{} path.OSUtilsInterface = path.OSUtils{} InitializeUtils() diff --git a/cmd/mocks/utils_cmd_interface.go b/cmd/mocks/utils_cmd_interface.go index 9b8b794a0..b957be0e5 100644 --- a/cmd/mocks/utils_cmd_interface.go +++ b/cmd/mocks/utils_cmd_interface.go @@ -11,6 +11,8 @@ import ( bindings "razor/pkg/bindings" + cache "razor/cache" + common "github.com/ethereum/go-ethereum/common" context "context" @@ -109,6 +111,32 @@ func (_m *UtilsCmdInterface) AssignAmountInWei(flagSet *pflag.FlagSet) (*big.Int return r0, r1 } +// BatchGetStakeSnapshotCalls provides a mock function with given fields: client, epoch, numberOfStakers +func (_m *UtilsCmdInterface) BatchGetStakeSnapshotCalls(client *ethclient.Client, epoch uint32, numberOfStakers uint32) ([]*big.Int, error) { + ret := _m.Called(client, epoch, numberOfStakers) + + var r0 []*big.Int + var r1 error + if rf, ok := ret.Get(0).(func(*ethclient.Client, uint32, uint32) ([]*big.Int, error)); ok { + return rf(client, epoch, numberOfStakers) + } + if rf, ok := ret.Get(0).(func(*ethclient.Client, uint32, uint32) []*big.Int); ok { + r0 = rf(client, epoch, numberOfStakers) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]*big.Int) + } + } + + if rf, ok := ret.Get(1).(func(*ethclient.Client, uint32, uint32) error); ok { + r1 = rf(client, epoch, numberOfStakers) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + // CalculateSecret provides a mock function with given fields: account, epoch, keystorePath, chainId func (_m *UtilsCmdInterface) CalculateSecret(account types.Account, epoch uint32, keystorePath string, chainId *big.Int) ([]byte, []byte, error) { ret := _m.Called(account, epoch, keystorePath, chainId) @@ -270,25 +298,25 @@ func (_m *UtilsCmdInterface) ClaimCommission(flagSet *pflag.FlagSet) { _m.Called(flagSet) } -// Commit provides a mock function with given fields: client, config, account, epoch, seed, values -func (_m *UtilsCmdInterface) Commit(client *ethclient.Client, config types.Configurations, account types.Account, epoch uint32, seed []byte, values []*big.Int) (common.Hash, error) { - ret := _m.Called(client, config, account, epoch, seed, values) +// Commit provides a mock function with given fields: client, config, account, epoch, latestHeader, seed, values +func (_m *UtilsCmdInterface) Commit(client *ethclient.Client, config types.Configurations, account types.Account, epoch uint32, latestHeader *coretypes.Header, seed []byte, values []*big.Int) (common.Hash, error) { + ret := _m.Called(client, config, account, epoch, latestHeader, seed, values) var r0 common.Hash var r1 error - if rf, ok := ret.Get(0).(func(*ethclient.Client, types.Configurations, types.Account, uint32, []byte, []*big.Int) (common.Hash, error)); ok { - return rf(client, config, account, epoch, seed, values) + if rf, ok := ret.Get(0).(func(*ethclient.Client, types.Configurations, types.Account, uint32, *coretypes.Header, []byte, []*big.Int) (common.Hash, error)); ok { + return rf(client, config, account, epoch, latestHeader, seed, values) } - if rf, ok := ret.Get(0).(func(*ethclient.Client, types.Configurations, types.Account, uint32, []byte, []*big.Int) common.Hash); ok { - r0 = rf(client, config, account, epoch, seed, values) + if rf, ok := ret.Get(0).(func(*ethclient.Client, types.Configurations, types.Account, uint32, *coretypes.Header, []byte, []*big.Int) common.Hash); ok { + r0 = rf(client, config, account, epoch, latestHeader, seed, values) } else { if ret.Get(0) != nil { r0 = ret.Get(0).(common.Hash) } } - if rf, ok := ret.Get(1).(func(*ethclient.Client, types.Configurations, types.Account, uint32, []byte, []*big.Int) error); ok { - r1 = rf(client, config, account, epoch, seed, values) + if rf, ok := ret.Get(1).(func(*ethclient.Client, types.Configurations, types.Account, uint32, *coretypes.Header, []byte, []*big.Int) error); ok { + r1 = rf(client, config, account, epoch, latestHeader, seed, values) } else { r1 = ret.Error(1) } @@ -570,32 +598,32 @@ func (_m *UtilsCmdInterface) GetAlternateProvider() (string, error) { return r0, r1 } -// GetBiggestStakeAndId provides a mock function with given fields: client, address, epoch -func (_m *UtilsCmdInterface) GetBiggestStakeAndId(client *ethclient.Client, address string, epoch uint32) (*big.Int, uint32, error) { - ret := _m.Called(client, address, epoch) +// GetBiggestStakeAndId provides a mock function with given fields: client, epoch +func (_m *UtilsCmdInterface) GetBiggestStakeAndId(client *ethclient.Client, epoch uint32) (*big.Int, uint32, error) { + ret := _m.Called(client, epoch) var r0 *big.Int var r1 uint32 var r2 error - if rf, ok := ret.Get(0).(func(*ethclient.Client, string, uint32) (*big.Int, uint32, error)); ok { - return rf(client, address, epoch) + if rf, ok := ret.Get(0).(func(*ethclient.Client, uint32) (*big.Int, uint32, error)); ok { + return rf(client, epoch) } - if rf, ok := ret.Get(0).(func(*ethclient.Client, string, uint32) *big.Int); ok { - r0 = rf(client, address, epoch) + if rf, ok := ret.Get(0).(func(*ethclient.Client, uint32) *big.Int); ok { + r0 = rf(client, epoch) } else { if ret.Get(0) != nil { r0 = ret.Get(0).(*big.Int) } } - if rf, ok := ret.Get(1).(func(*ethclient.Client, string, uint32) uint32); ok { - r1 = rf(client, address, epoch) + if rf, ok := ret.Get(1).(func(*ethclient.Client, uint32) uint32); ok { + r1 = rf(client, epoch) } else { r1 = ret.Get(1).(uint32) } - if rf, ok := ret.Get(2).(func(*ethclient.Client, string, uint32) error); ok { - r2 = rf(client, address, epoch) + if rf, ok := ret.Get(2).(func(*ethclient.Client, uint32) error); ok { + r2 = rf(client, epoch) } else { r2 = ret.Error(2) } @@ -1189,9 +1217,9 @@ func (_m *UtilsCmdInterface) GiveSorted(client *ethclient.Client, blockManager * return r0 } -// HandleBlock provides a mock function with given fields: client, account, blockNumber, config, rogueData, backupNodeActionsToIgnore -func (_m *UtilsCmdInterface) HandleBlock(client *ethclient.Client, account types.Account, blockNumber *big.Int, config types.Configurations, rogueData types.Rogue, backupNodeActionsToIgnore []string) { - _m.Called(client, account, blockNumber, config, rogueData, backupNodeActionsToIgnore) +// HandleBlock provides a mock function with given fields: client, account, stakerId, header, config, commitParams, rogueData, backupNodeActionsToIgnore +func (_m *UtilsCmdInterface) HandleBlock(client *ethclient.Client, account types.Account, stakerId uint32, header *coretypes.Header, config types.Configurations, commitParams *types.CommitParams, rogueData types.Rogue, backupNodeActionsToIgnore []string) { + _m.Called(client, account, stakerId, header, config, commitParams, rogueData, backupNodeActionsToIgnore) } // HandleClaimBounty provides a mock function with given fields: client, config, account @@ -1208,23 +1236,23 @@ func (_m *UtilsCmdInterface) HandleClaimBounty(client *ethclient.Client, config return r0 } -// HandleCommitState provides a mock function with given fields: client, epoch, seed, rogueData -func (_m *UtilsCmdInterface) HandleCommitState(client *ethclient.Client, epoch uint32, seed []byte, rogueData types.Rogue) (types.CommitData, error) { - ret := _m.Called(client, epoch, seed, rogueData) +// HandleCommitState provides a mock function with given fields: client, epoch, seed, commitParams, rogueData +func (_m *UtilsCmdInterface) HandleCommitState(client *ethclient.Client, epoch uint32, seed []byte, commitParams *types.CommitParams, rogueData types.Rogue) (types.CommitData, error) { + ret := _m.Called(client, epoch, seed, commitParams, rogueData) var r0 types.CommitData var r1 error - if rf, ok := ret.Get(0).(func(*ethclient.Client, uint32, []byte, types.Rogue) (types.CommitData, error)); ok { - return rf(client, epoch, seed, rogueData) + if rf, ok := ret.Get(0).(func(*ethclient.Client, uint32, []byte, *types.CommitParams, types.Rogue) (types.CommitData, error)); ok { + return rf(client, epoch, seed, commitParams, rogueData) } - if rf, ok := ret.Get(0).(func(*ethclient.Client, uint32, []byte, types.Rogue) types.CommitData); ok { - r0 = rf(client, epoch, seed, rogueData) + if rf, ok := ret.Get(0).(func(*ethclient.Client, uint32, []byte, *types.CommitParams, types.Rogue) types.CommitData); ok { + r0 = rf(client, epoch, seed, commitParams, rogueData) } else { r0 = ret.Get(0).(types.CommitData) } - if rf, ok := ret.Get(1).(func(*ethclient.Client, uint32, []byte, types.Rogue) error); ok { - r1 = rf(client, epoch, seed, rogueData) + if rf, ok := ret.Get(1).(func(*ethclient.Client, uint32, []byte, *types.CommitParams, types.Rogue) error); ok { + r1 = rf(client, epoch, seed, commitParams, rogueData) } else { r1 = ret.Error(1) } @@ -1353,13 +1381,57 @@ func (_m *UtilsCmdInterface) IndexRevealEventsOfCurrentEpoch(client *ethclient.C return r0, r1 } -// InitiateCommit provides a mock function with given fields: client, config, account, epoch, stakerId, rogueData -func (_m *UtilsCmdInterface) InitiateCommit(client *ethclient.Client, config types.Configurations, account types.Account, epoch uint32, stakerId uint32, rogueData types.Rogue) error { - ret := _m.Called(client, config, account, epoch, stakerId, rogueData) +// InitJobAndCollectionCache provides a mock function with given fields: client +func (_m *UtilsCmdInterface) InitJobAndCollectionCache(client *ethclient.Client) (*cache.JobsCache, *cache.CollectionsCache, *big.Int, error) { + ret := _m.Called(client) + + var r0 *cache.JobsCache + var r1 *cache.CollectionsCache + var r2 *big.Int + var r3 error + if rf, ok := ret.Get(0).(func(*ethclient.Client) (*cache.JobsCache, *cache.CollectionsCache, *big.Int, error)); ok { + return rf(client) + } + if rf, ok := ret.Get(0).(func(*ethclient.Client) *cache.JobsCache); ok { + r0 = rf(client) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*cache.JobsCache) + } + } + + if rf, ok := ret.Get(1).(func(*ethclient.Client) *cache.CollectionsCache); ok { + r1 = rf(client) + } else { + if ret.Get(1) != nil { + r1 = ret.Get(1).(*cache.CollectionsCache) + } + } + + if rf, ok := ret.Get(2).(func(*ethclient.Client) *big.Int); ok { + r2 = rf(client) + } else { + if ret.Get(2) != nil { + r2 = ret.Get(2).(*big.Int) + } + } + + if rf, ok := ret.Get(3).(func(*ethclient.Client) error); ok { + r3 = rf(client) + } else { + r3 = ret.Error(3) + } + + return r0, r1, r2, r3 +} + +// InitiateCommit provides a mock function with given fields: client, config, account, epoch, stakerId, latestHeader, commitParams, rogueData +func (_m *UtilsCmdInterface) InitiateCommit(client *ethclient.Client, config types.Configurations, account types.Account, epoch uint32, stakerId uint32, latestHeader *coretypes.Header, commitParams *types.CommitParams, rogueData types.Rogue) error { + ret := _m.Called(client, config, account, epoch, stakerId, latestHeader, commitParams, rogueData) var r0 error - if rf, ok := ret.Get(0).(func(*ethclient.Client, types.Configurations, types.Account, uint32, uint32, types.Rogue) error); ok { - r0 = rf(client, config, account, epoch, stakerId, rogueData) + if rf, ok := ret.Get(0).(func(*ethclient.Client, types.Configurations, types.Account, uint32, uint32, *coretypes.Header, *types.CommitParams, types.Rogue) error); ok { + r0 = rf(client, config, account, epoch, stakerId, latestHeader, commitParams, rogueData) } else { r0 = ret.Error(0) } @@ -1367,13 +1439,13 @@ func (_m *UtilsCmdInterface) InitiateCommit(client *ethclient.Client, config typ return r0 } -// InitiatePropose provides a mock function with given fields: client, config, account, epoch, staker, blockNumber, rogueData -func (_m *UtilsCmdInterface) InitiatePropose(client *ethclient.Client, config types.Configurations, account types.Account, epoch uint32, staker bindings.StructsStaker, blockNumber *big.Int, rogueData types.Rogue) error { - ret := _m.Called(client, config, account, epoch, staker, blockNumber, rogueData) +// InitiatePropose provides a mock function with given fields: client, config, account, epoch, staker, latestHeader, rogueData +func (_m *UtilsCmdInterface) InitiatePropose(client *ethclient.Client, config types.Configurations, account types.Account, epoch uint32, staker bindings.StructsStaker, latestHeader *coretypes.Header, rogueData types.Rogue) error { + ret := _m.Called(client, config, account, epoch, staker, latestHeader, rogueData) var r0 error - if rf, ok := ret.Get(0).(func(*ethclient.Client, types.Configurations, types.Account, uint32, bindings.StructsStaker, *big.Int, types.Rogue) error); ok { - r0 = rf(client, config, account, epoch, staker, blockNumber, rogueData) + if rf, ok := ret.Get(0).(func(*ethclient.Client, types.Configurations, types.Account, uint32, bindings.StructsStaker, *coretypes.Header, types.Rogue) error); ok { + r0 = rf(client, config, account, epoch, staker, latestHeader, rogueData) } else { r0 = ret.Error(0) } @@ -1381,13 +1453,13 @@ func (_m *UtilsCmdInterface) InitiatePropose(client *ethclient.Client, config ty return r0 } -// InitiateReveal provides a mock function with given fields: client, config, account, epoch, staker, rogueData -func (_m *UtilsCmdInterface) InitiateReveal(client *ethclient.Client, config types.Configurations, account types.Account, epoch uint32, staker bindings.StructsStaker, rogueData types.Rogue) error { - ret := _m.Called(client, config, account, epoch, staker, rogueData) +// InitiateReveal provides a mock function with given fields: client, config, account, epoch, staker, latestHeader, rogueData +func (_m *UtilsCmdInterface) InitiateReveal(client *ethclient.Client, config types.Configurations, account types.Account, epoch uint32, staker bindings.StructsStaker, latestHeader *coretypes.Header, rogueData types.Rogue) error { + ret := _m.Called(client, config, account, epoch, staker, latestHeader, rogueData) var r0 error - if rf, ok := ret.Get(0).(func(*ethclient.Client, types.Configurations, types.Account, uint32, bindings.StructsStaker, types.Rogue) error); ok { - r0 = rf(client, config, account, epoch, staker, rogueData) + if rf, ok := ret.Get(0).(func(*ethclient.Client, types.Configurations, types.Account, uint32, bindings.StructsStaker, *coretypes.Header, types.Rogue) error); ok { + r0 = rf(client, config, account, epoch, staker, latestHeader, rogueData) } else { r0 = ret.Error(0) } @@ -1531,13 +1603,13 @@ func (_m *UtilsCmdInterface) ModifyCollectionStatus(client *ethclient.Client, co return r0, r1 } -// Propose provides a mock function with given fields: client, config, account, staker, epoch, blockNumber, rogueData -func (_m *UtilsCmdInterface) Propose(client *ethclient.Client, config types.Configurations, account types.Account, staker bindings.StructsStaker, epoch uint32, blockNumber *big.Int, rogueData types.Rogue) error { - ret := _m.Called(client, config, account, staker, epoch, blockNumber, rogueData) +// Propose provides a mock function with given fields: client, config, account, staker, epoch, latestHeader, rogueData +func (_m *UtilsCmdInterface) Propose(client *ethclient.Client, config types.Configurations, account types.Account, staker bindings.StructsStaker, epoch uint32, latestHeader *coretypes.Header, rogueData types.Rogue) error { + ret := _m.Called(client, config, account, staker, epoch, latestHeader, rogueData) var r0 error - if rf, ok := ret.Get(0).(func(*ethclient.Client, types.Configurations, types.Account, bindings.StructsStaker, uint32, *big.Int, types.Rogue) error); ok { - r0 = rf(client, config, account, staker, epoch, blockNumber, rogueData) + if rf, ok := ret.Get(0).(func(*ethclient.Client, types.Configurations, types.Account, bindings.StructsStaker, uint32, *coretypes.Header, types.Rogue) error); ok { + r0 = rf(client, config, account, staker, epoch, latestHeader, rogueData) } else { r0 = ret.Error(0) } @@ -1576,25 +1648,25 @@ func (_m *UtilsCmdInterface) ResetUnstakeLock(client *ethclient.Client, config t return r0, r1 } -// Reveal provides a mock function with given fields: client, config, account, epoch, commitData, signature -func (_m *UtilsCmdInterface) Reveal(client *ethclient.Client, config types.Configurations, account types.Account, epoch uint32, commitData types.CommitData, signature []byte) (common.Hash, error) { - ret := _m.Called(client, config, account, epoch, commitData, signature) +// Reveal provides a mock function with given fields: client, config, account, epoch, latestHeader, commitData, signature +func (_m *UtilsCmdInterface) Reveal(client *ethclient.Client, config types.Configurations, account types.Account, epoch uint32, latestHeader *coretypes.Header, commitData types.CommitData, signature []byte) (common.Hash, error) { + ret := _m.Called(client, config, account, epoch, latestHeader, commitData, signature) var r0 common.Hash var r1 error - if rf, ok := ret.Get(0).(func(*ethclient.Client, types.Configurations, types.Account, uint32, types.CommitData, []byte) (common.Hash, error)); ok { - return rf(client, config, account, epoch, commitData, signature) + if rf, ok := ret.Get(0).(func(*ethclient.Client, types.Configurations, types.Account, uint32, *coretypes.Header, types.CommitData, []byte) (common.Hash, error)); ok { + return rf(client, config, account, epoch, latestHeader, commitData, signature) } - if rf, ok := ret.Get(0).(func(*ethclient.Client, types.Configurations, types.Account, uint32, types.CommitData, []byte) common.Hash); ok { - r0 = rf(client, config, account, epoch, commitData, signature) + if rf, ok := ret.Get(0).(func(*ethclient.Client, types.Configurations, types.Account, uint32, *coretypes.Header, types.CommitData, []byte) common.Hash); ok { + r0 = rf(client, config, account, epoch, latestHeader, commitData, signature) } else { if ret.Get(0) != nil { r0 = ret.Get(0).(common.Hash) } } - if rf, ok := ret.Get(1).(func(*ethclient.Client, types.Configurations, types.Account, uint32, types.CommitData, []byte) error); ok { - r1 = rf(client, config, account, epoch, commitData, signature) + if rf, ok := ret.Get(1).(func(*ethclient.Client, types.Configurations, types.Account, uint32, *coretypes.Header, types.CommitData, []byte) error); ok { + r1 = rf(client, config, account, epoch, latestHeader, commitData, signature) } else { r1 = ret.Error(1) } @@ -1826,13 +1898,13 @@ func (_m *UtilsCmdInterface) UpdateJob(client *ethclient.Client, config types.Co return r0, r1 } -// Vote provides a mock function with given fields: ctx, config, client, rogueData, account, backupNodeActionsToIgnore -func (_m *UtilsCmdInterface) Vote(ctx context.Context, config types.Configurations, client *ethclient.Client, rogueData types.Rogue, account types.Account, backupNodeActionsToIgnore []string) error { - ret := _m.Called(ctx, config, client, rogueData, account, backupNodeActionsToIgnore) +// Vote provides a mock function with given fields: ctx, config, client, account, stakerId, commitParams, rogueData, backupNodeActionsToIgnore +func (_m *UtilsCmdInterface) Vote(ctx context.Context, config types.Configurations, client *ethclient.Client, account types.Account, stakerId uint32, commitParams *types.CommitParams, rogueData types.Rogue, backupNodeActionsToIgnore []string) error { + ret := _m.Called(ctx, config, client, account, stakerId, commitParams, rogueData, backupNodeActionsToIgnore) var r0 error - if rf, ok := ret.Get(0).(func(context.Context, types.Configurations, *ethclient.Client, types.Rogue, types.Account, []string) error); ok { - r0 = rf(ctx, config, client, rogueData, account, backupNodeActionsToIgnore) + if rf, ok := ret.Get(0).(func(context.Context, types.Configurations, *ethclient.Client, types.Account, uint32, *types.CommitParams, types.Rogue, []string) error); ok { + r0 = rf(ctx, config, client, account, stakerId, commitParams, rogueData, backupNodeActionsToIgnore) } else { r0 = ret.Error(0) } diff --git a/cmd/modifyCollectionStatus.go b/cmd/modifyCollectionStatus.go index 6e968d2cd..7f16efad6 100644 --- a/cmd/modifyCollectionStatus.go +++ b/cmd/modifyCollectionStatus.go @@ -2,6 +2,7 @@ package cmd import ( + "razor/accounts" "razor/core" "razor/core/types" "razor/logger" @@ -48,7 +49,12 @@ func (*UtilsStruct) ExecuteModifyCollectionStatus(flagSet *pflag.FlagSet) { log.Debug("Getting password...") password := razorUtils.AssignPassword(flagSet) - err = razorUtils.CheckPassword(address, password) + accountManager, err := razorUtils.AccountManagerForKeystore() + utils.CheckError("Error in getting accounts manager for keystore: ", err) + + account := accounts.InitAccountStruct(address, password, accountManager) + + err = razorUtils.CheckPassword(account) utils.CheckError("Error in fetching private key from given password: ", err) collectionId, err := flagSetUtils.GetUint16CollectionId(flagSet) @@ -61,13 +67,11 @@ func (*UtilsStruct) ExecuteModifyCollectionStatus(flagSet *pflag.FlagSet) { utils.CheckError("Error in parsing status: ", err) modifyCollectionInput := types.ModifyCollectionInput{ - Address: address, - Password: password, Status: status, CollectionId: collectionId, + Account: account, } - log.Debugf("Calling ModifyCollectionStatus() with arguments modifyCollectionInput = %+v", modifyCollectionInput) txn, err := cmdUtils.ModifyCollectionStatus(client, config, modifyCollectionInput) utils.CheckError("Error in changing collection active status: ", err) if txn != core.NilHash { @@ -101,14 +105,13 @@ func (*UtilsStruct) ModifyCollectionStatus(client *ethclient.Client, config type txnArgs := types.TransactionOptions{ Client: client, - Password: modifyCollectionInput.Password, - AccountAddress: modifyCollectionInput.Address, ChainId: core.ChainId, Config: config, ContractAddress: core.CollectionManagerAddress, MethodName: "setCollectionStatus", Parameters: []interface{}{modifyCollectionInput.Status, modifyCollectionInput.CollectionId}, ABI: bindings.CollectionManagerMetaData.ABI, + Account: modifyCollectionInput.Account, } txnOpts := razorUtils.GetTxnOpts(txnArgs) diff --git a/cmd/modifyCollectionStatus_test.go b/cmd/modifyCollectionStatus_test.go index 30bc82ac3..f6fb0d750 100644 --- a/cmd/modifyCollectionStatus_test.go +++ b/cmd/modifyCollectionStatus_test.go @@ -3,6 +3,7 @@ package cmd import ( "errors" "math/big" + "razor/accounts" "razor/core" "razor/core/types" "testing" @@ -321,7 +322,8 @@ func TestExecuteModifyAssetStatus(t *testing.T) { flagSetMock.On("GetUint16CollectionId", flagSet).Return(tt.args.collectionId, tt.args.collectionIdErr) flagSetMock.On("GetStringStatus", flagSet).Return(tt.args.status, tt.args.statusErr) utilsMock.On("AssignPassword", flagSet).Return(tt.args.password) - utilsMock.On("CheckPassword", mock.Anything, mock.Anything).Return(nil) + utilsMock.On("CheckPassword", mock.Anything).Return(nil) + utilsMock.On("AccountManagerForKeystore").Return(&accounts.AccountManager{}, nil) stringMock.On("ParseBool", mock.AnythingOfType("string")).Return(tt.args.parseStatus, tt.args.parseStatusErr) utilsMock.On("ConnectToClient", mock.AnythingOfType("string")).Return(client) cmdUtilsMock.On("ModifyCollectionStatus", mock.Anything, mock.Anything, mock.Anything).Return(tt.args.ModifyCollectionStatusHash, tt.args.ModifyCollectionStatusErr) diff --git a/cmd/propose.go b/cmd/propose.go index f4278e4f2..b0d5b576c 100644 --- a/cmd/propose.go +++ b/cmd/propose.go @@ -11,9 +11,11 @@ import ( "razor/pkg/bindings" "razor/utils" "sort" + "strings" "sync" "time" + Types "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/ethclient" solsha3 "github.com/miguelmota/go-solidity-sha3" ) @@ -29,8 +31,8 @@ var globalProposedDataStruct types.ProposeFileData // Find iteration using salt as seed //This functions handles the propose state -func (*UtilsStruct) Propose(client *ethclient.Client, config types.Configurations, account types.Account, staker bindings.StructsStaker, epoch uint32, blockNumber *big.Int, rogueData types.Rogue) error { - if state, err := razorUtils.GetBufferedState(client, config.BufferPercent); err != nil || state != 2 { +func (*UtilsStruct) Propose(client *ethclient.Client, config types.Configurations, account types.Account, staker bindings.StructsStaker, epoch uint32, latestHeader *Types.Header, rogueData types.Rogue) error { + if state, err := razorUtils.GetBufferedState(client, latestHeader, config.BufferPercent); err != nil || state != 2 { log.Error("Not propose state") return err } @@ -60,7 +62,7 @@ func (*UtilsStruct) Propose(client *ethclient.Client, config types.Configuration biggestStakerId = smallestStakerId log.Debugf("Propose: In rogue mode, Biggest Stake: %s, Biggest Staker Id: %d", biggestStake, biggestStakerId) } else { - biggestStake, biggestStakerId, biggestStakerErr = cmdUtils.GetBiggestStakeAndId(client, account.Address, epoch) + biggestStake, biggestStakerId, biggestStakerErr = cmdUtils.GetBiggestStakeAndId(client, epoch) if biggestStakerErr != nil { log.Error("Error in calculating biggest staker: ", biggestStakerErr) return biggestStakerErr @@ -132,8 +134,8 @@ func (*UtilsStruct) Propose(client *ethclient.Client, config types.Configuration } log.Info("Current iteration is less than iteration of last proposed block, can propose") } - log.Debugf("Propose: Calling MakeBlock() with arguments blockNumber = %s, epoch = %d, rogueData = %+v", blockNumber, epoch, rogueData) - medians, ids, revealedDataMaps, err := cmdUtils.MakeBlock(client, blockNumber, epoch, rogueData) + log.Debugf("Propose: Calling MakeBlock() with arguments blockNumber = %s, epoch = %d, rogueData = %+v", latestHeader.Number, epoch, rogueData) + medians, ids, revealedDataMaps, err := cmdUtils.MakeBlock(client, latestHeader.Number, epoch, rogueData) if err != nil { log.Error(err) return err @@ -145,14 +147,13 @@ func (*UtilsStruct) Propose(client *ethclient.Client, config types.Configuration txnOpts := razorUtils.GetTxnOpts(types.TransactionOptions{ Client: client, - Password: account.Password, - AccountAddress: account.Address, ChainId: core.ChainId, Config: config, ContractAddress: core.BlockManagerAddress, ABI: bindings.BlockManagerMetaData.ABI, MethodName: "propose", Parameters: []interface{}{epoch, ids, medians, big.NewInt(int64(iteration)), biggestStakerId}, + Account: account, }) log.Debugf("Executing Propose transaction with epoch = %d, Ids = %v, medians = %s, iteration = %s, biggestStakerId = %d", epoch, ids, medians, big.NewInt(int64(iteration)), biggestStakerId) @@ -199,7 +200,7 @@ func (*UtilsStruct) Propose(client *ethclient.Client, config types.Configuration } //This function returns the biggest stake and Id of it -func (*UtilsStruct) GetBiggestStakeAndId(client *ethclient.Client, address string, epoch uint32) (*big.Int, uint32, error) { +func (*UtilsStruct) GetBiggestStakeAndId(client *ethclient.Client, epoch uint32) (*big.Int, uint32, error) { numberOfStakers, err := razorUtils.GetNumberOfStakers(client) if err != nil { return nil, 0, err @@ -211,38 +212,20 @@ func (*UtilsStruct) GetBiggestStakeAndId(client *ethclient.Client, address strin var biggestStakerId uint32 biggestStake := big.NewInt(0) - bufferPercent, err := cmdUtils.GetBufferPercent() + stakeSnapshotArray, err := cmdUtils.BatchGetStakeSnapshotCalls(client, epoch, numberOfStakers) if err != nil { return nil, 0, err } - log.Debug("GetBiggestStakeAndId: Buffer Percent: ", bufferPercent) - - stateRemainingTime, err := razorUtils.GetRemainingTimeOfCurrentState(client, bufferPercent) - if err != nil { - return nil, 0, err - } - log.Debug("GetBiggestStakeAndId: State remaining time: ", stateRemainingTime) - stateTimeout := time.NewTimer(time.Second * time.Duration(stateRemainingTime)) + log.Debugf("Stake Snapshot Array: %+v", stakeSnapshotArray) log.Debug("Iterating over all the stakers...") -loop: - for i := 1; i <= int(numberOfStakers); i++ { - select { - case <-stateTimeout.C: - log.Error("State timeout!") - err = errors.New("state timeout error") - break loop - default: - log.Debug("Propose: Staker Id: ", i) - stake, err := razorUtils.GetStakeSnapshot(client, uint32(i), epoch) - if err != nil { - return nil, 0, err - } - log.Debugf("Stake Snapshot of staker having stakerId %d is %s", i, stake) - if stake.Cmp(biggestStake) > 0 { - biggestStake = stake - biggestStakerId = uint32(i) - } + for i := 0; i < len(stakeSnapshotArray); i++ { + log.Debug("Propose: Staker Id: ", i) + stake := stakeSnapshotArray[i] + log.Debugf("Stake Snapshot of staker having stakerId %d is %s", i+1, stake) + if stake.Cmp(biggestStake) > 0 { + biggestStake = stake + biggestStakerId = uint32(i + 1) } } if err != nil { @@ -494,6 +477,32 @@ func (*UtilsStruct) GetSmallestStakeAndId(client *ethclient.Client, epoch uint32 return smallestStake, smallestStakerId, nil } +func (*UtilsStruct) BatchGetStakeSnapshotCalls(client *ethclient.Client, epoch uint32, numberOfStakers uint32) ([]*big.Int, error) { + voteManagerABI, err := utils.ABIInterface.Parse(strings.NewReader(bindings.VoteManagerMetaData.ABI)) + if err != nil { + log.Errorf("Error in parsed voteManager ABI: %v", err) + return nil, err + } + + args := make([][]interface{}, numberOfStakers) + for i := uint32(1); i <= numberOfStakers; i++ { + args[i-1] = []interface{}{epoch, i} + } + + results, err := clientUtils.BatchCall(client, &voteManagerABI, core.VoteManagerAddress, core.GetStakeSnapshotMethod, args) + if err != nil { + log.Error("Error in performing getStakeSnapshot batch calls: ", err) + return nil, err + } + + var stakeArray []*big.Int + for _, result := range results { + stakeArray = append(stakeArray, result[0].(*big.Int)) + } + + return stakeArray, nil +} + func updateGlobalProposedDataStruct(proposedData types.ProposeFileData) types.ProposeFileData { globalProposedDataStruct.MediansData = proposedData.MediansData globalProposedDataStruct.RevealedDataMaps = proposedData.RevealedDataMaps diff --git a/cmd/propose_test.go b/cmd/propose_test.go index f98b20af6..c18379085 100644 --- a/cmd/propose_test.go +++ b/cmd/propose_test.go @@ -3,11 +3,14 @@ package cmd import ( "errors" "fmt" + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/stretchr/testify/assert" "math/big" "razor/core/types" "razor/pkg/bindings" utilsPkgMocks "razor/utils/mocks" "reflect" + "strings" "testing" "github.com/stretchr/testify/mock" @@ -20,18 +23,20 @@ import ( func TestPropose(t *testing.T) { var ( - client *ethclient.Client - account types.Account - config types.Configurations - staker bindings.StructsStaker - epoch uint32 - blockNumber *big.Int + client *ethclient.Client + account types.Account + config types.Configurations + staker bindings.StructsStaker + epoch uint32 ) salt := []byte{142, 170, 157, 83, 109, 43, 34, 152, 21, 154, 159, 12, 195, 119, 50, 186, 218, 57, 39, 173, 228, 135, 20, 100, 149, 27, 169, 158, 34, 113, 66, 64} saltBytes32 := [32]byte{} copy(saltBytes32[:], salt) + latestHeader := &Types.Header{ + Number: big.NewInt(1001), + } type args struct { rogueData types.Rogue state int64 @@ -514,9 +519,9 @@ func TestPropose(t *testing.T) { for _, tt := range tests { SetUpMockInterfaces() - utilsMock.On("GetBufferedState", mock.AnythingOfType("*ethclient.Client"), mock.AnythingOfType("int32")).Return(tt.args.state, tt.args.stateErr) + utilsMock.On("GetBufferedState", mock.Anything, mock.Anything, mock.Anything).Return(tt.args.state, tt.args.stateErr) utilsMock.On("GetNumberOfStakers", mock.AnythingOfType("*ethclient.Client"), mock.AnythingOfType("string")).Return(tt.args.numStakers, tt.args.numStakerErr) - cmdUtilsMock.On("GetBiggestStakeAndId", mock.AnythingOfType("*ethclient.Client"), mock.AnythingOfType("string"), mock.AnythingOfType("uint32")).Return(tt.args.biggestStake, tt.args.biggestStakerId, tt.args.biggestStakerIdErr) + cmdUtilsMock.On("GetBiggestStakeAndId", mock.AnythingOfType("*ethclient.Client"), mock.AnythingOfType("uint32")).Return(tt.args.biggestStake, tt.args.biggestStakerId, tt.args.biggestStakerIdErr) cmdUtilsMock.On("GetSmallestStakeAndId", mock.Anything, mock.Anything).Return(tt.args.smallestStake, tt.args.smallestStakerId, tt.args.smallestStakerIdErr) utilsMock.On("GetRandaoHash", mock.AnythingOfType("*ethclient.Client")).Return(tt.args.randaoHash, tt.args.randaoHashErr) cmdUtilsMock.On("GetIteration", mock.Anything, mock.Anything, mock.Anything).Return(tt.args.iteration) @@ -539,7 +544,7 @@ func TestPropose(t *testing.T) { utils := &UtilsStruct{} t.Run(tt.name, func(t *testing.T) { - err := utils.Propose(client, config, account, staker, epoch, blockNumber, tt.args.rogueData) + err := utils.Propose(client, config, account, staker, epoch, latestHeader, tt.args.rogueData) if err == nil || tt.wantErr == nil { if err != tt.wantErr { t.Errorf("Error for Propose function, got = %v, want %v", err, tt.wantErr) @@ -555,18 +560,13 @@ func TestPropose(t *testing.T) { func TestGetBiggestStakeAndId(t *testing.T) { var client *ethclient.Client - var address string var epoch uint32 type args struct { - numOfStakers uint32 - numOfStakersErr error - bufferPercent int32 - bufferPercentErr error - remainingTime int64 - remainingTimeErr error - stake *big.Int - stakeErr error + numOfStakers uint32 + numOfStakersErr error + stakeArray []*big.Int + stakeErr error } tests := []struct { name string @@ -578,12 +578,11 @@ func TestGetBiggestStakeAndId(t *testing.T) { { name: "Test 1: When GetBiggestStakeAndId function executes successfully", args: args{ - numOfStakers: 2, - remainingTime: 10, - stake: big.NewInt(1).Mul(big.NewInt(5326), big.NewInt(1e18)), + numOfStakers: 7, + stakeArray: []*big.Int{big.NewInt(89999), big.NewInt(70000), big.NewInt(72000), big.NewInt(99999), big.NewInt(200030), big.NewInt(67777), big.NewInt(100011)}, }, - wantStake: big.NewInt(1).Mul(big.NewInt(5326), big.NewInt(1e18)), - wantId: 1, + wantStake: big.NewInt(200030), + wantId: 5, wantErr: nil, }, { @@ -599,55 +598,30 @@ func TestGetBiggestStakeAndId(t *testing.T) { name: "Test 3: When there is an error in getting numOfStakers", args: args{ numOfStakersErr: errors.New("numOfStakers error"), - remainingTime: 10, }, wantStake: nil, wantId: 0, wantErr: errors.New("numOfStakers error"), }, { - name: "Test 4: When there is an error in getting stake", - args: args{ - numOfStakers: 5, - remainingTime: 10, - stakeErr: errors.New("stake error"), - }, - wantStake: nil, - wantId: 0, - wantErr: errors.New("stake error"), - }, - { - name: "Test 5: When there is an error in getting remaining time", + name: "Test 4: When there is an error in getting stakeArray from batch calls", args: args{ - numOfStakers: 2, - remainingTime: 10, - remainingTimeErr: errors.New("time error"), - }, - wantStake: nil, - wantId: 0, - wantErr: errors.New("time error"), - }, - { - name: "Test 6: When there is a timeout case", - args: args{ - numOfStakers: 100000, - bufferPercent: 10, - remainingTime: 0, - stake: big.NewInt(1).Mul(big.NewInt(5326), big.NewInt(1e18)), + numOfStakers: 5, + stakeErr: errors.New("batch calls error"), }, wantStake: nil, wantId: 0, - wantErr: errors.New("state timeout error"), + wantErr: errors.New("batch calls error"), }, { - name: "Test 7: When there is an error in getting buffer percent", + name: "Test 5: When there are large number of stakers", args: args{ - numOfStakers: 2, - bufferPercentErr: errors.New("buffer error"), + numOfStakers: 999, + stakeArray: GenerateDummyStakeSnapshotArray(999), }, - wantStake: nil, - wantId: 0, - wantErr: errors.New("buffer error"), + wantStake: big.NewInt(999000), + wantId: 999, + wantErr: nil, }, } for _, tt := range tests { @@ -655,19 +629,11 @@ func TestGetBiggestStakeAndId(t *testing.T) { SetUpMockInterfaces() utilsMock.On("GetNumberOfStakers", mock.AnythingOfType("*ethclient.Client"), mock.AnythingOfType("string")).Return(tt.args.numOfStakers, tt.args.numOfStakersErr) - utilsMock.On("GetStakeSnapshot", mock.AnythingOfType("*ethclient.Client"), mock.AnythingOfType("uint32"), mock.AnythingOfType("uint32")).Return(tt.args.stake, tt.args.stakeErr) - utilsMock.On("GetRemainingTimeOfCurrentState", mock.Anything, mock.Anything).Return(tt.args.remainingTime, tt.args.remainingTimeErr) - cmdUtilsMock.On("GetBufferPercent").Return(tt.args.bufferPercent, tt.args.bufferPercentErr) + cmdUtilsMock.On("BatchGetStakeSnapshotCalls", mock.AnythingOfType("*ethclient.Client"), mock.AnythingOfType("uint32"), mock.AnythingOfType("uint32")).Return(tt.args.stakeArray, tt.args.stakeErr) utils := &UtilsStruct{} - gotStake, gotId, err := utils.GetBiggestStakeAndId(client, address, epoch) - if gotStake.Cmp(tt.wantStake) != 0 { - t.Errorf("Biggest Stake from GetBiggestStakeAndId function, got = %v, want %v", gotStake, tt.wantStake) - } - if gotId != tt.wantId { - t.Errorf("Staker Id of staker having biggest Influence from GetBiggestStakeAndId function, got = %v, want %v", gotId, tt.wantId) - } + gotStake, gotId, err := utils.GetBiggestStakeAndId(client, epoch) if err == nil || tt.wantErr == nil { if err != tt.wantErr { t.Errorf("Error for GetBiggestStakeAndId function, got = %v, want %v", err, tt.wantErr) @@ -677,6 +643,12 @@ func TestGetBiggestStakeAndId(t *testing.T) { t.Errorf("Error for GetBiggestStakeAndId function, got = %v, want %v", err, tt.wantErr) } } + if gotStake.Cmp(tt.wantStake) != 0 { + t.Errorf("Biggest Stake from GetBiggestStakeAndId function, got = %v, want %v", gotStake, tt.wantStake) + } + if gotId != tt.wantId { + t.Errorf("Staker Id of staker having biggest Influence from GetBiggestStakeAndId function, got = %v, want %v", gotId, tt.wantId) + } }) } @@ -1350,6 +1322,72 @@ func TestGetSmallestStakeAndId(t *testing.T) { } } +func TestBatchGetStakeCalls(t *testing.T) { + var client *ethclient.Client + var epoch uint32 + + voteManagerABI, _ := abi.JSON(strings.NewReader(bindings.VoteManagerMetaData.ABI)) + + type args struct { + ABI abi.ABI + numberOfStakers uint32 + parseErr error + batchCallResults [][]interface{} + batchCallError error + } + tests := []struct { + name string + args args + wantStakes []*big.Int + wantErr error + }{ + { + name: "Test 1: When BatchGetStakeCalls executes successfully", + args: args{ + ABI: voteManagerABI, + numberOfStakers: 3, + batchCallResults: [][]interface{}{ + {big.NewInt(10)}, + {big.NewInt(11)}, + {big.NewInt(12)}, + }, + }, + wantStakes: []*big.Int{ + big.NewInt(10), + big.NewInt(11), + big.NewInt(12), + }, + wantErr: nil, + }, + { + name: "Test 2: When there is an error in parsing voteManager ABI", + args: args{ + parseErr: errors.New("parse error"), + }, + wantErr: errors.New("parse error"), + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + SetUpMockInterfaces() + + abiUtilsMock.On("Parse", mock.Anything).Return(tt.args.ABI, tt.args.parseErr) + clientUtilsMock.On("BatchCall", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(tt.args.batchCallResults, tt.args.batchCallError) + + ut := &UtilsStruct{} + gotStakes, err := ut.BatchGetStakeSnapshotCalls(client, epoch, tt.args.numberOfStakers) + + if err == nil || tt.wantErr == nil { + assert.Equal(t, tt.wantErr, err) + } else { + assert.EqualError(t, err, tt.wantErr.Error()) + } + + assert.Equal(t, tt.wantStakes, gotStakes) + }) + } +} + func BenchmarkGetIteration(b *testing.B) { var client *ethclient.Client var bufferPercent int32 @@ -1393,7 +1431,6 @@ func BenchmarkGetIteration(b *testing.B) { func BenchmarkGetBiggestStakeAndId(b *testing.B) { var client *ethclient.Client - var address string var epoch uint32 var table = []struct { @@ -1411,12 +1448,10 @@ func BenchmarkGetBiggestStakeAndId(b *testing.B) { SetUpMockInterfaces() utilsMock.On("GetNumberOfStakers", mock.AnythingOfType("*ethclient.Client"), mock.AnythingOfType("string")).Return(v.numOfStakers, nil) - utilsMock.On("GetStakeSnapshot", mock.AnythingOfType("*ethclient.Client"), mock.AnythingOfType("uint32"), mock.AnythingOfType("uint32")).Return(big.NewInt(10000), nil) - utilsMock.On("GetRemainingTimeOfCurrentState", mock.Anything, mock.Anything).Return(int64(150), nil) - cmdUtilsMock.On("GetBufferPercent").Return(int32(60), nil) + cmdUtilsMock.On("BatchGetStakeSnapshotCalls", mock.Anything, mock.Anything, mock.Anything).Return(GenerateDummyStakeSnapshotArray(v.numOfStakers), nil) ut := &UtilsStruct{} - _, _, err := ut.GetBiggestStakeAndId(client, address, epoch) + _, _, err := ut.GetBiggestStakeAndId(client, epoch) if err != nil { log.Fatal(err) } @@ -1497,6 +1532,15 @@ func BenchmarkMakeBlock(b *testing.B) { } } +func GenerateDummyStakeSnapshotArray(numOfStakers uint32) []*big.Int { + stakeSnapshotArray := make([]*big.Int, numOfStakers) + for i := 0; i < int(numOfStakers); i++ { + // For testing purposes, we will assign a stake value of (i + 1) * 1000 + stakeSnapshotArray[i] = big.NewInt(int64(i+1) * 1000) + } + return stakeSnapshotArray +} + func GetDummyVotes(numOfVotes int) []*big.Int { var result []*big.Int for i := 0; i < numOfVotes; i++ { diff --git a/cmd/resetUnstakeLock.go b/cmd/resetUnstakeLock.go index 477e86d7b..3f4d5d474 100644 --- a/cmd/resetUnstakeLock.go +++ b/cmd/resetUnstakeLock.go @@ -2,6 +2,7 @@ package cmd import ( + "razor/accounts" "razor/core" "razor/core/types" "razor/logger" @@ -50,18 +51,22 @@ func (*UtilsStruct) ExecuteExtendLock(flagSet *pflag.FlagSet) { log.Debug("Getting password...") password := razorUtils.AssignPassword(flagSet) - err = razorUtils.CheckPassword(address, password) + accountManager, err := razorUtils.AccountManagerForKeystore() + utils.CheckError("Error in getting accounts manager for keystore: ", err) + + account := accounts.InitAccountStruct(address, password, accountManager) + + err = razorUtils.CheckPassword(account) utils.CheckError("Error in fetching private key from given password: ", err) stakerId, err := razorUtils.AssignStakerId(flagSet, client, address) utils.CheckError("Error in getting stakerId: ", err) extendLockInput := types.ExtendLockInput{ - Address: address, - Password: password, StakerId: stakerId, + Account: account, } - log.Debugf("ExecuteExtendLock: Calling ResetUnstakeLock with arguments extendLockInput = %+v", extendLockInput) + txn, err := cmdUtils.ResetUnstakeLock(client, config, extendLockInput) utils.CheckError("Error in extending lock: ", err) err = razorUtils.WaitForBlockCompletion(client, txn.Hex()) @@ -72,14 +77,13 @@ func (*UtilsStruct) ExecuteExtendLock(flagSet *pflag.FlagSet) { func (*UtilsStruct) ResetUnstakeLock(client *ethclient.Client, config types.Configurations, extendLockInput types.ExtendLockInput) (common.Hash, error) { txnOpts := razorUtils.GetTxnOpts(types.TransactionOptions{ Client: client, - Password: extendLockInput.Password, - AccountAddress: extendLockInput.Address, ChainId: core.ChainId, Config: config, ContractAddress: core.StakeManagerAddress, MethodName: "resetUnstakeLock", Parameters: []interface{}{extendLockInput.StakerId}, ABI: bindings.StakeManagerMetaData.ABI, + Account: extendLockInput.Account, }) log.Info("Extending lock...") diff --git a/cmd/resetUnstakeLock_test.go b/cmd/resetUnstakeLock_test.go index f769bb27a..1d598abdc 100644 --- a/cmd/resetUnstakeLock_test.go +++ b/cmd/resetUnstakeLock_test.go @@ -3,6 +3,7 @@ package cmd import ( "errors" "math/big" + "razor/accounts" "razor/core" "razor/core/types" "testing" @@ -172,7 +173,8 @@ func TestExecuteExtendLock(t *testing.T) { fileUtilsMock.On("AssignLogFile", mock.AnythingOfType("*pflag.FlagSet"), mock.Anything) cmdUtilsMock.On("GetConfigData").Return(tt.args.config, tt.args.configErr) utilsMock.On("AssignPassword", flagSet).Return(tt.args.password) - utilsMock.On("CheckPassword", mock.Anything, mock.Anything).Return(nil) + utilsMock.On("CheckPassword", mock.Anything).Return(nil) + utilsMock.On("AccountManagerForKeystore").Return(&accounts.AccountManager{}, nil) flagSetMock.On("GetStringAddress", mock.AnythingOfType("*pflag.FlagSet")).Return(tt.args.address, tt.args.addressErr) utilsMock.On("AssignStakerId", flagSet, mock.AnythingOfType("*ethclient.Client"), mock.Anything).Return(tt.args.stakerId, tt.args.stakerIdErr) utilsMock.On("ConnectToClient", mock.AnythingOfType("string")).Return(client) diff --git a/cmd/reveal.go b/cmd/reveal.go index c0d1be8a0..0667c6666 100644 --- a/cmd/reveal.go +++ b/cmd/reveal.go @@ -12,6 +12,7 @@ import ( "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/common" + Types "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/ethclient" ) @@ -29,8 +30,8 @@ func (*UtilsStruct) CheckForLastCommitted(client *ethclient.Client, staker bindi } //This function checks if the state is reveal or not and then reveals the votes -func (*UtilsStruct) Reveal(client *ethclient.Client, config types.Configurations, account types.Account, epoch uint32, commitData types.CommitData, signature []byte) (common.Hash, error) { - if state, err := razorUtils.GetBufferedState(client, config.BufferPercent); err != nil || state != 1 { +func (*UtilsStruct) Reveal(client *ethclient.Client, config types.Configurations, account types.Account, epoch uint32, latestHeader *Types.Header, commitData types.CommitData, signature []byte) (common.Hash, error) { + if state, err := razorUtils.GetBufferedState(client, latestHeader, config.BufferPercent); err != nil || state != 1 { log.Error("Not reveal state") return core.NilHash, err } @@ -56,14 +57,13 @@ func (*UtilsStruct) Reveal(client *ethclient.Client, config types.Configurations txnOpts := razorUtils.GetTxnOpts(types.TransactionOptions{ Client: client, - Password: account.Password, - AccountAddress: account.Address, ChainId: core.ChainId, Config: config, ContractAddress: core.VoteManagerAddress, ABI: bindings.VoteManagerMetaData.ABI, MethodName: "reveal", Parameters: []interface{}{epoch, treeRevealData, signature}, + Account: account, }) log.Debugf("Executing Reveal transaction wih epoch = %d, treeRevealData = %v, signature = %v", epoch, treeRevealData, signature) txn, err := voteManagerUtils.Reveal(client, txnOpts, epoch, treeRevealData, signature) diff --git a/cmd/reveal_test.go b/cmd/reveal_test.go index a1333696a..c276ade07 100644 --- a/cmd/reveal_test.go +++ b/cmd/reveal_test.go @@ -85,12 +85,15 @@ func TestCheckForLastCommitted(t *testing.T) { } func TestReveal(t *testing.T) { - var client *ethclient.Client - var commitData types.CommitData - var signature []byte - var account types.Account - var config types.Configurations - var epoch uint32 + var ( + client *ethclient.Client + commitData types.CommitData + signature []byte + account types.Account + config types.Configurations + epoch uint32 + latestHeader *Types.Header + ) type args struct { state int64 @@ -157,7 +160,7 @@ func TestReveal(t *testing.T) { t.Run(tt.name, func(t *testing.T) { SetUpMockInterfaces() - utilsMock.On("GetBufferedState", mock.AnythingOfType("*ethclient.Client"), mock.AnythingOfType("int32")).Return(tt.args.state, tt.args.stateErr) + utilsMock.On("GetBufferedState", mock.Anything, mock.Anything, mock.Anything).Return(tt.args.state, tt.args.stateErr) merkleUtilsMock.On("CreateMerkle", mock.Anything).Return(tt.args.merkleTree, tt.args.merkleTreeErr) cmdUtilsMock.On("GenerateTreeRevealData", mock.Anything, mock.Anything).Return(tt.args.treeRevealData) utilsMock.On("GetTxnOpts", mock.AnythingOfType("types.TransactionOptions")).Return(TxnOpts) @@ -166,7 +169,7 @@ func TestReveal(t *testing.T) { utils := &UtilsStruct{} - got, err := utils.Reveal(client, config, account, epoch, commitData, signature) + got, err := utils.Reveal(client, config, account, epoch, latestHeader, commitData, signature) if got != tt.want { t.Errorf("Txn hash for Reveal function, got = %v, want = %v", got, tt.want) } diff --git a/cmd/setDelegation.go b/cmd/setDelegation.go index 30b41fe43..f28ca97d3 100644 --- a/cmd/setDelegation.go +++ b/cmd/setDelegation.go @@ -2,6 +2,7 @@ package cmd import ( + "razor/accounts" "razor/core" "razor/core/types" "razor/logger" @@ -50,7 +51,12 @@ func (*UtilsStruct) ExecuteSetDelegation(flagSet *pflag.FlagSet) { log.Debug("Getting password...") password := razorUtils.AssignPassword(flagSet) - err = razorUtils.CheckPassword(address, password) + accountManager, err := razorUtils.AccountManagerForKeystore() + utils.CheckError("Error in getting accounts manager for keystore: ", err) + + account := accounts.InitAccountStruct(address, password, accountManager) + + err = razorUtils.CheckPassword(account) utils.CheckError("Error in fetching private key from given password: ", err) statusString, err := flagSetUtils.GetStringStatus(flagSet) @@ -66,15 +72,13 @@ func (*UtilsStruct) ExecuteSetDelegation(flagSet *pflag.FlagSet) { utils.CheckError("Error in fetching commission: ", err) delegationInput := types.SetDelegationInput{ - Address: address, - Password: password, Status: status, StatusString: statusString, StakerId: stakerId, Commission: commission, + Account: account, } - log.Debugf("ExecuteSetDelegation: Calling SetDelegation() with argument delegationInput = %+v", delegationInput) txn, err := cmdUtils.SetDelegation(client, config, delegationInput) utils.CheckError("SetDelegation error: ", err) if txn != core.NilHash { @@ -93,11 +97,9 @@ func (*UtilsStruct) SetDelegation(client *ethclient.Client, config types.Configu if delegationInput.Commission != 0 { updateCommissionInput := types.UpdateCommissionInput{ StakerId: delegationInput.StakerId, - Address: delegationInput.Address, - Password: delegationInput.Password, Commission: delegationInput.Commission, + Account: delegationInput.Account, } - log.Debugf("Calling UpdateCommission() with argument updateCommissionInput = %+v", updateCommissionInput) err = cmdUtils.UpdateCommission(config, client, updateCommissionInput) if err != nil { return core.NilHash, err @@ -106,14 +108,13 @@ func (*UtilsStruct) SetDelegation(client *ethclient.Client, config types.Configu txnOpts := types.TransactionOptions{ Client: client, - Password: delegationInput.Password, - AccountAddress: delegationInput.Address, ChainId: core.ChainId, Config: config, ContractAddress: core.StakeManagerAddress, ABI: bindings.StakeManagerMetaData.ABI, MethodName: "setDelegationAcceptance", Parameters: []interface{}{delegationInput.Status}, + Account: delegationInput.Account, } if stakerInfo.AcceptDelegation == delegationInput.Status { diff --git a/cmd/setDelegation_test.go b/cmd/setDelegation_test.go index 9e15804ae..e9cc4b2b1 100644 --- a/cmd/setDelegation_test.go +++ b/cmd/setDelegation_test.go @@ -3,6 +3,7 @@ package cmd import ( "errors" "math/big" + "razor/accounts" "razor/cmd/mocks" "razor/core" "razor/core/types" @@ -404,7 +405,8 @@ func TestExecuteSetDelegation(t *testing.T) { fileUtilsMock.On("AssignLogFile", mock.AnythingOfType("*pflag.FlagSet"), mock.Anything) cmdUtilsMock.On("GetConfigData").Return(tt.args.config, tt.args.configErr) utilsMock.On("AssignPassword", flagSet).Return(tt.args.password) - utilsMock.On("CheckPassword", mock.Anything, mock.Anything).Return(nil) + utilsMock.On("CheckPassword", mock.Anything).Return(nil) + utilsMock.On("AccountManagerForKeystore").Return(&accounts.AccountManager{}, nil) flagSetUtilsMock.On("GetStringAddress", flagSet).Return(tt.args.address, tt.args.addressErr) flagSetUtilsMock.On("GetStringStatus", flagSet).Return(tt.args.status, tt.args.statusErr) flagSetUtilsMock.On("GetUint8Commission", flagSet).Return(tt.args.commission, tt.args.commissionErr) diff --git a/cmd/struct-utils.go b/cmd/struct-utils.go index f9f9ac333..eebc2712f 100644 --- a/cmd/struct-utils.go +++ b/cmd/struct-utils.go @@ -6,7 +6,6 @@ import ( "errors" "math/big" "os" - "razor/accounts" "razor/core" "razor/core/types" "razor/path" @@ -29,13 +28,12 @@ import ( ) var ( - razorUtils = utils.UtilsInterface - pathUtils = path.PathUtilsInterface - clientUtils = utils.ClientInterface - fileUtils = utils.FileInterface - gasUtils = utils.GasInterface - merkleUtils = utils.MerkleInterface - accountUtils = accounts.AccountUtilsInterface + razorUtils = utils.UtilsInterface + pathUtils = path.PathUtilsInterface + clientUtils = utils.ClientInterface + fileUtils = utils.FileInterface + gasUtils = utils.GasInterface + merkleUtils = utils.MerkleInterface ) //This function initializes the utils @@ -52,7 +50,6 @@ func InitializeUtils() { utils.ABIInterface = &utils.ABIStruct{} utils.PathInterface = &utils.PathStruct{} utils.BindInterface = &utils.BindStruct{} - utils.AccountsInterface = &utils.AccountsStruct{} utils.BlockManagerInterface = &utils.BlockManagerStruct{} utils.StakeManagerInterface = &utils.StakeManagerStruct{} utils.AssetManagerInterface = &utils.AssetManagerStruct{} @@ -71,8 +68,6 @@ func InitializeUtils() { utils.GasInterface = &utils.GasStruct{} merkleUtils = &utils.MerkleTreeStruct{} utils.MerkleInterface = &utils.MerkleTreeStruct{} - accountUtils = &accounts.AccountUtils{} - accounts.AccountUtilsInterface = &accounts.AccountUtils{} } func ExecuteTransaction(interfaceName interface{}, methodName string, args ...interface{}) (*Types.Transaction, error) { diff --git a/cmd/test_utils_test.go b/cmd/test_utils_test.go index d2c44ef82..f410e24a3 100644 --- a/cmd/test_utils_test.go +++ b/cmd/test_utils_test.go @@ -6,7 +6,6 @@ import ( "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/crypto" "math/big" - accountsPkgMocks "razor/accounts/mocks" "razor/cmd/mocks" "razor/path" pathPkgMocks "razor/path/mocks" @@ -24,7 +23,6 @@ var ( ioUtilsMock *utilsPkgMocks.IOUtils abiUtilsMock *utilsPkgMocks.ABIUtils bindUtilsMock *utilsPkgMocks.BindUtils - accountUtilsMock *utilsPkgMocks.AccountsUtils blockManagerUtilsMock *utilsPkgMocks.BlockManagerUtils stakeManagerUtilsMock *utilsPkgMocks.StakeManagerUtils assetManagerUtilsMock *utilsPkgMocks.AssetManagerUtils @@ -52,7 +50,6 @@ var ( osMock *mocks.OSInterface pathMock *pathPkgMocks.PathInterface osPathMock *pathPkgMocks.OSInterface - accountsMock *accountsPkgMocks.AccountInterface ) func SetUpMockInterfaces() { @@ -89,9 +86,6 @@ func SetUpMockInterfaces() { bindUtilsMock = new(utilsPkgMocks.BindUtils) utils.BindingsInterface = bindingUtilsMock - accountUtilsMock = new(utilsPkgMocks.AccountsUtils) - utils.AccountsInterface = accountUtilsMock - blockManagerUtilsMock = new(utilsPkgMocks.BlockManagerUtils) utils.BlockManagerInterface = blockManagerUtilsMock @@ -169,9 +163,6 @@ func SetUpMockInterfaces() { osPathMock = new(pathPkgMocks.OSInterface) path.OSUtilsInterface = osPathMock - - accountsMock = new(accountsPkgMocks.AccountInterface) - accountUtils = accountsMock } var privateKey, _ = ecdsa.GenerateKey(crypto.S256(), rand.Reader) diff --git a/cmd/transfer.go b/cmd/transfer.go index b467ee422..bbb7517b1 100644 --- a/cmd/transfer.go +++ b/cmd/transfer.go @@ -2,6 +2,7 @@ package cmd import ( + "razor/accounts" "razor/core" "razor/core/types" "razor/logger" @@ -50,7 +51,12 @@ func (*UtilsStruct) ExecuteTransfer(flagSet *pflag.FlagSet) { log.Debug("Getting password...") password := razorUtils.AssignPassword(flagSet) - err = razorUtils.CheckPassword(fromAddress, password) + accountManager, err := razorUtils.AccountManagerForKeystore() + utils.CheckError("Error in getting accounts manager for keystore: ", err) + + account := accounts.InitAccountStruct(fromAddress, password, accountManager) + + err = razorUtils.CheckPassword(account) utils.CheckError("Error in fetching private key from given password: ", err) toAddress, err := flagSetUtils.GetStringTo(flagSet) @@ -64,14 +70,12 @@ func (*UtilsStruct) ExecuteTransfer(flagSet *pflag.FlagSet) { utils.CheckError("Error in getting amount: ", err) transferInput := types.TransferInput{ - FromAddress: fromAddress, - ToAddress: toAddress, - Password: password, - ValueInWei: valueInWei, - Balance: balance, + ToAddress: toAddress, + ValueInWei: valueInWei, + Balance: balance, + Account: account, } - log.Debugf("Calling Transfer() with arguments transferInput = %+v", transferInput) txn, err := cmdUtils.Transfer(client, config, transferInput) utils.CheckError("Transfer error: ", err) @@ -86,16 +90,15 @@ func (*UtilsStruct) Transfer(client *ethclient.Client, config types.Configuratio txnOpts := razorUtils.GetTxnOpts(types.TransactionOptions{ Client: client, - Password: transferInput.Password, - AccountAddress: transferInput.FromAddress, ChainId: core.ChainId, Config: config, ContractAddress: core.RAZORAddress, MethodName: "transfer", Parameters: []interface{}{common.HexToAddress(transferInput.ToAddress), transferInput.ValueInWei}, ABI: bindings.RAZORMetaData.ABI, + Account: transferInput.Account, }) - log.Infof("Transferring %g tokens from %s to %s", utils.GetAmountInDecimal(transferInput.ValueInWei), transferInput.FromAddress, transferInput.ToAddress) + log.Infof("Transferring %g tokens from %s to %s", utils.GetAmountInDecimal(transferInput.ValueInWei), transferInput.Account.Address, transferInput.ToAddress) log.Debugf("Executing Transfer transaction with toAddress: %s, amount: %s", transferInput.ToAddress, transferInput.ValueInWei) txn, err := tokenManagerUtils.Transfer(client, txnOpts, common.HexToAddress(transferInput.ToAddress), transferInput.ValueInWei) diff --git a/cmd/transfer_test.go b/cmd/transfer_test.go index 5e46350b5..d0e04e651 100644 --- a/cmd/transfer_test.go +++ b/cmd/transfer_test.go @@ -3,6 +3,7 @@ package cmd import ( "errors" "math/big" + "razor/accounts" "razor/core" "razor/core/types" "testing" @@ -245,7 +246,8 @@ func TestExecuteTransfer(t *testing.T) { fileUtilsMock.On("AssignLogFile", mock.AnythingOfType("*pflag.FlagSet"), mock.Anything) cmdUtilsMock.On("GetConfigData").Return(tt.args.config, tt.args.configErr) utilsMock.On("AssignPassword", flagSet).Return(tt.args.password) - utilsMock.On("CheckPassword", mock.Anything, mock.Anything).Return(nil) + utilsMock.On("CheckPassword", mock.Anything).Return(nil) + utilsMock.On("AccountManagerForKeystore").Return(&accounts.AccountManager{}, nil) flagSetMock.On("GetStringFrom", flagSet).Return(tt.args.from, tt.args.fromErr) flagSetMock.On("GetStringTo", flagSet).Return(tt.args.to, tt.args.toErr) cmdUtilsMock.On("AssignAmountInWei", flagSet).Return(tt.args.amount, tt.args.amountErr) diff --git a/cmd/unlockWithdraw.go b/cmd/unlockWithdraw.go index 7657beb24..5edd33c91 100644 --- a/cmd/unlockWithdraw.go +++ b/cmd/unlockWithdraw.go @@ -4,6 +4,7 @@ package cmd import ( "errors" "math/big" + "razor/accounts" "razor/core" "razor/core/types" "razor/logger" @@ -50,20 +51,21 @@ func (*UtilsStruct) ExecuteUnlockWithdraw(flagSet *pflag.FlagSet) { log.Debug("Getting password...") password := razorUtils.AssignPassword(flagSet) - err = razorUtils.CheckPassword(address, password) + accountManager, err := razorUtils.AccountManagerForKeystore() + utils.CheckError("Error in getting accounts manager for keystore: ", err) + + account := accounts.InitAccountStruct(address, password, accountManager) + + err = razorUtils.CheckPassword(account) utils.CheckError("Error in fetching private key from given password: ", err) stakerId, err := razorUtils.AssignStakerId(flagSet, client, address) utils.CheckError("Error in fetching stakerId: ", err) log.Debug("ExecuteUnlockWithdraw: StakerId: ", stakerId) - log.Debugf("ExecuteUnlockWithdraw: Calling HandleWithdrawLock with arguments account address = %s, stakerId = %d", address, stakerId) - txn, err := cmdUtils.HandleWithdrawLock(client, types.Account{ - Address: address, - Password: password, - }, config, stakerId) + txn, err := cmdUtils.HandleWithdrawLock(client, account, config, stakerId) + utils.CheckError("HandleWithdrawLock error: ", err) - utils.CheckError("UnlockWithdraw error: ", err) if txn != core.NilHash { err = razorUtils.WaitForBlockCompletion(client, txn.Hex()) utils.CheckError("Error in WaitForBlockCompletion for unlockWithdraw: ", err) @@ -100,14 +102,13 @@ func (*UtilsStruct) HandleWithdrawLock(client *ethclient.Client, account types.A if big.NewInt(int64(epoch)).Cmp(withdrawLock.UnlockAfter) >= 0 { txnArgs := types.TransactionOptions{ Client: client, - Password: account.Password, - AccountAddress: account.Address, ChainId: core.ChainId, Config: configurations, ContractAddress: core.StakeManagerAddress, MethodName: "unlockWithdraw", ABI: bindings.StakeManagerMetaData.ABI, Parameters: []interface{}{stakerId}, + Account: account, } txnOpts := razorUtils.GetTxnOpts(txnArgs) log.Debug("HandleWithdrawLock: Calling UnlockWithdraw() with arguments stakerId = ", stakerId) diff --git a/cmd/unlockWithdraw_test.go b/cmd/unlockWithdraw_test.go index 173c4e89a..210613e20 100644 --- a/cmd/unlockWithdraw_test.go +++ b/cmd/unlockWithdraw_test.go @@ -3,6 +3,7 @@ package cmd import ( "errors" "math/big" + "razor/accounts" "razor/core" "razor/core/types" "reflect" @@ -97,7 +98,8 @@ func TestExecuteUnlockWithdraw(t *testing.T) { flagSetMock.On("GetStringAddress", mock.AnythingOfType("*pflag.FlagSet")).Return(tt.args.address, tt.args.addressErr) cmdUtilsMock.On("GetConfigData").Return(tt.args.config, tt.args.configErr) utilsMock.On("AssignPassword", flagSet).Return(tt.args.password) - utilsMock.On("CheckPassword", mock.Anything, mock.Anything).Return(nil) + utilsMock.On("CheckPassword", mock.Anything).Return(nil) + utilsMock.On("AccountManagerForKeystore").Return(&accounts.AccountManager{}, nil) utilsMock.On("ConnectToClient", mock.AnythingOfType("string")).Return(client) utilsMock.On("AssignStakerId", mock.Anything, mock.Anything, mock.Anything).Return(tt.args.stakerId, tt.args.stakerIdErr) cmdUtilsMock.On("HandleWithdrawLock", mock.AnythingOfType("*ethclient.Client"), mock.Anything, mock.Anything, mock.Anything).Return(tt.args.txn, tt.args.err) diff --git a/cmd/unstake.go b/cmd/unstake.go index 40c6abbe0..af79f2591 100644 --- a/cmd/unstake.go +++ b/cmd/unstake.go @@ -4,6 +4,7 @@ package cmd import ( "errors" "math/big" + "razor/accounts" "razor/core" "razor/core/types" "razor/logger" @@ -53,7 +54,12 @@ func (*UtilsStruct) ExecuteUnstake(flagSet *pflag.FlagSet) { log.Debug("Getting password...") password := razorUtils.AssignPassword(flagSet) - err = razorUtils.CheckPassword(address, password) + accountManager, err := razorUtils.AccountManagerForKeystore() + utils.CheckError("Error in getting accounts manager for keystore: ", err) + + account := accounts.InitAccountStruct(address, password, accountManager) + + err = razorUtils.CheckPassword(account) utils.CheckError("Error in fetching private key from given password: ", err) log.Debug("Getting amount in wei...") @@ -64,13 +70,11 @@ func (*UtilsStruct) ExecuteUnstake(flagSet *pflag.FlagSet) { utils.CheckError("StakerId error: ", err) unstakeInput := types.UnstakeInput{ - Address: address, - Password: password, ValueInWei: valueInWei, StakerId: stakerId, + Account: account, } - log.Debugf("ExecuteUnstake: Calling Unstake() with arguments unstakeInput: %+v", unstakeInput) txnHash, err := cmdUtils.Unstake(config, client, unstakeInput) utils.CheckError("Unstake Error: ", err) if txnHash != core.NilHash { @@ -82,12 +86,11 @@ func (*UtilsStruct) ExecuteUnstake(flagSet *pflag.FlagSet) { //This function allows user to unstake their sRZRs in the razor network func (*UtilsStruct) Unstake(config types.Configurations, client *ethclient.Client, input types.UnstakeInput) (common.Hash, error) { txnArgs := types.TransactionOptions{ - Client: client, - Password: input.Password, - AccountAddress: input.Address, - Amount: input.ValueInWei, - ChainId: core.ChainId, - Config: config, + Client: client, + Amount: input.ValueInWei, + ChainId: core.ChainId, + Config: config, + Account: input.Account, } stakerId := input.StakerId staker, err := razorUtils.GetStaker(client, stakerId) @@ -116,7 +119,7 @@ func (*UtilsStruct) Unstake(config types.Configurations, client *ethclient.Clien txnArgs.MethodName = "unstake" txnArgs.ABI = bindings.StakeManagerMetaData.ABI - unstakeLock, err := razorUtils.GetLock(txnArgs.Client, txnArgs.AccountAddress, stakerId, 0) + unstakeLock, err := razorUtils.GetLock(txnArgs.Client, txnArgs.Account.Address, stakerId, 0) if err != nil { log.Error("Error in getting unstakeLock: ", err) return core.NilHash, err diff --git a/cmd/unstake_test.go b/cmd/unstake_test.go index 883ecffb4..3f8008dfe 100644 --- a/cmd/unstake_test.go +++ b/cmd/unstake_test.go @@ -6,6 +6,7 @@ import ( "errors" "github.com/ethereum/go-ethereum/crypto" "math/big" + "razor/accounts" "razor/core" "razor/core/types" "razor/pkg/bindings" @@ -23,8 +24,7 @@ import ( func TestUnstake(t *testing.T) { var config types.Configurations var client *ethclient.Client - var address string - var password string + var account types.Account var stakerId uint32 type args struct { @@ -134,8 +134,7 @@ func TestUnstake(t *testing.T) { utils := &UtilsStruct{} _, gotErr := utils.Unstake(config, client, types.UnstakeInput{ - Address: address, - Password: password, + Account: account, StakerId: stakerId, ValueInWei: tt.args.amount, }) @@ -294,7 +293,8 @@ func TestExecuteUnstake(t *testing.T) { fileUtilsMock.On("AssignLogFile", mock.AnythingOfType("*pflag.FlagSet"), mock.Anything) cmdUtilsMock.On("GetConfigData").Return(tt.args.config, tt.args.configErr) utilsMock.On("AssignPassword", flagSet).Return(tt.args.password) - utilsMock.On("CheckPassword", mock.Anything, mock.Anything).Return(nil) + utilsMock.On("CheckPassword", mock.Anything).Return(nil) + utilsMock.On("AccountManagerForKeystore").Return(&accounts.AccountManager{}, nil) flagSetMock.On("GetStringAddress", flagSet).Return(tt.args.address, tt.args.addressErr) utilsMock.On("ConnectToClient", mock.AnythingOfType("string")).Return(client) cmdUtilsMock.On("AssignAmountInWei", flagSet).Return(tt.args.value, tt.args.valueErr) diff --git a/cmd/updateCollection.go b/cmd/updateCollection.go index a73c92c08..10b249064 100644 --- a/cmd/updateCollection.go +++ b/cmd/updateCollection.go @@ -2,6 +2,7 @@ package cmd import ( + "razor/accounts" "razor/core" "razor/core/types" "razor/logger" @@ -52,7 +53,12 @@ func (*UtilsStruct) ExecuteUpdateCollection(flagSet *pflag.FlagSet) { log.Debug("Getting password...") password := razorUtils.AssignPassword(flagSet) - err = razorUtils.CheckPassword(address, password) + accountManager, err := razorUtils.AccountManagerForKeystore() + utils.CheckError("Error in getting accounts manager for keystore: ", err) + + account := accounts.InitAccountStruct(address, password, accountManager) + + err = razorUtils.CheckPassword(account) utils.CheckError("Error in fetching private key from given password: ", err) collectionId, err := flagSetUtils.GetUint16CollectionId(flagSet) @@ -71,14 +77,12 @@ func (*UtilsStruct) ExecuteUpdateCollection(flagSet *pflag.FlagSet) { utils.CheckError("Error in getting tolerance: ", err) collectionInput := types.CreateCollectionInput{ - Address: address, - Password: password, Aggregation: aggregation, Power: power, JobIds: jobIdInUint, Tolerance: tolerance, + Account: account, } - log.Debugf("ExecuteUpdateCollection: Calling UpdateCollection() with arguments collectionInput: %+v, collectionId: %d", collectionInput, collectionId) txn, err := cmdUtils.UpdateCollection(client, config, collectionInput, collectionId) utils.CheckError("Update Collection error: ", err) err = razorUtils.WaitForBlockCompletion(client, txn.Hex()) @@ -96,14 +100,13 @@ func (*UtilsStruct) UpdateCollection(client *ethclient.Client, config types.Conf } txnOpts := razorUtils.GetTxnOpts(types.TransactionOptions{ Client: client, - Password: collectionInput.Password, - AccountAddress: collectionInput.Address, ChainId: core.ChainId, Config: config, ContractAddress: core.CollectionManagerAddress, MethodName: "updateCollection", Parameters: []interface{}{collectionId, collectionInput.Tolerance, collectionInput.Aggregation, collectionInput.Power, jobIds}, ABI: bindings.CollectionManagerMetaData.ABI, + Account: collectionInput.Account, }) log.Info("Updating collection...") log.Debugf("Executing UpdateCollection transaction with collectionId = %d, tolerance = %d, aggregation method = %d, power = %d, jobIds = %v", collectionId, collectionInput.Tolerance, collectionInput.Aggregation, collectionInput.Power, jobIds) diff --git a/cmd/updateCollection_test.go b/cmd/updateCollection_test.go index 477d89328..f473a212d 100644 --- a/cmd/updateCollection_test.go +++ b/cmd/updateCollection_test.go @@ -3,6 +3,7 @@ package cmd import ( "errors" "math/big" + "razor/accounts" "razor/core" "razor/core/types" "testing" @@ -276,7 +277,8 @@ func TestExecuteUpdateCollection(t *testing.T) { fileUtilsMock.On("AssignLogFile", mock.AnythingOfType("*pflag.FlagSet"), mock.Anything) cmdUtilsMock.On("GetConfigData").Return(tt.args.config, tt.args.configErr) utilsMock.On("AssignPassword", flagSet).Return(tt.args.password) - utilsMock.On("CheckPassword", mock.Anything, mock.Anything).Return(nil) + utilsMock.On("CheckPassword", mock.Anything).Return(nil) + utilsMock.On("AccountManagerForKeystore").Return(&accounts.AccountManager{}, nil) flagSetMock.On("GetStringAddress", flagSet).Return(tt.args.address, tt.args.addressErr) flagSetMock.On("GetUint16CollectionId", flagSet).Return(tt.args.collectionId, tt.args.collectionIdErr) flagSetMock.On("GetUintSliceJobIds", flagSet).Return(tt.args.jobId, tt.args.jobIdErr) diff --git a/cmd/updateCommission.go b/cmd/updateCommission.go index b5fa8e3d9..5c59f15ab 100644 --- a/cmd/updateCommission.go +++ b/cmd/updateCommission.go @@ -3,6 +3,7 @@ package cmd import ( "errors" + "razor/accounts" "razor/core" "razor/core/types" "razor/logger" @@ -49,7 +50,12 @@ func (*UtilsStruct) ExecuteUpdateCommission(flagSet *pflag.FlagSet) { log.Debug("Getting password...") password := razorUtils.AssignPassword(flagSet) - err = razorUtils.CheckPassword(address, password) + accountManager, err := razorUtils.AccountManagerForKeystore() + utils.CheckError("Error in getting accounts manager for keystore: ", err) + + account := accounts.InitAccountStruct(address, password, accountManager) + + err = razorUtils.CheckPassword(account) utils.CheckError("Error in fetching private key from given password: ", err) commission, err := flagSetUtils.GetUint8Commission(flagSet) @@ -60,14 +66,12 @@ func (*UtilsStruct) ExecuteUpdateCommission(flagSet *pflag.FlagSet) { updateCommissionInput := types.UpdateCommissionInput{ Commission: commission, - Address: address, - Password: password, StakerId: stakerId, + Account: account, } - log.Debugf("ExecuteUpdateCommission: calling UpdateCommission() with argument UpdateCommissionInput: %+v", updateCommissionInput) err = cmdUtils.UpdateCommission(config, client, updateCommissionInput) - utils.CheckError("SetDelegation error: ", err) + utils.CheckError("UpdateCommission error: ", err) } //This function allows a staker to add/update the commission value @@ -114,14 +118,13 @@ func (*UtilsStruct) UpdateCommission(config types.Configurations, client *ethcli } txnOpts := types.TransactionOptions{ Client: client, - Password: updateCommissionInput.Password, - AccountAddress: updateCommissionInput.Address, ChainId: core.ChainId, Config: config, ContractAddress: core.StakeManagerAddress, ABI: bindings.StakeManagerMetaData.ABI, MethodName: "updateCommission", Parameters: []interface{}{updateCommissionInput.Commission}, + Account: updateCommissionInput.Account, } updateCommissionTxnOpts := razorUtils.GetTxnOpts(txnOpts) log.Infof("Setting the commission value of Staker %d to %d%%", updateCommissionInput.StakerId, updateCommissionInput.Commission) diff --git a/cmd/updateCommission_test.go b/cmd/updateCommission_test.go index d69415221..79dbeecd7 100644 --- a/cmd/updateCommission_test.go +++ b/cmd/updateCommission_test.go @@ -2,6 +2,7 @@ package cmd import ( "errors" + "razor/accounts" "razor/core/types" "razor/pkg/bindings" "testing" @@ -334,7 +335,8 @@ func TestExecuteUpdateCommission(t *testing.T) { cmdUtilsMock.On("GetConfigData").Return(tt.args.config, tt.args.configErr) flagSetMock.On("GetStringAddress", flagSet).Return(tt.args.address, tt.args.addressErr) utilsMock.On("AssignPassword", flagSet).Return(tt.args.password) - utilsMock.On("CheckPassword", mock.Anything, mock.Anything).Return(nil) + utilsMock.On("CheckPassword", mock.Anything).Return(nil) + utilsMock.On("AccountManagerForKeystore").Return(&accounts.AccountManager{}, nil) flagSetMock.On("GetUint8Commission", flagSet).Return(tt.args.commission, tt.args.commissionErr) utilsMock.On("GetStakerId", mock.AnythingOfType("*ethclient.Client"), mock.AnythingOfType("string")).Return(tt.args.stakerId, tt.args.stakerIdErr) utilsMock.On("ConnectToClient", mock.AnythingOfType("string")).Return(client) diff --git a/cmd/updateJob.go b/cmd/updateJob.go index e75e421f2..a1cbe352d 100644 --- a/cmd/updateJob.go +++ b/cmd/updateJob.go @@ -2,6 +2,7 @@ package cmd import ( + "razor/accounts" "razor/core" "razor/core/types" "razor/logger" @@ -52,7 +53,12 @@ func (*UtilsStruct) ExecuteUpdateJob(flagSet *pflag.FlagSet) { log.Debug("Getting password...") password := razorUtils.AssignPassword(flagSet) - err = razorUtils.CheckPassword(address, password) + accountManager, err := razorUtils.AccountManagerForKeystore() + utils.CheckError("Error in getting accounts manager for keystore: ", err) + + account := accounts.InitAccountStruct(address, password, accountManager) + + err = razorUtils.CheckPassword(account) utils.CheckError("Error in fetching private key from given password: ", err) jobId, err := flagSetUtils.GetUint16JobId(flagSet) @@ -74,16 +80,14 @@ func (*UtilsStruct) ExecuteUpdateJob(flagSet *pflag.FlagSet) { utils.CheckError("Error in getting selector type: ", err) jobInput := types.CreateJobInput{ - Address: address, - Password: password, Power: power, Selector: selector, Url: url, Weight: weight, SelectorType: selectorType, + Account: account, } - log.Debugf("ExecuteUpdateJob: Calling UpdateJob() with arguments jobInput = %+v, jobId = %d", jobInput, jobId) txn, err := cmdUtils.UpdateJob(client, config, jobInput, jobId) utils.CheckError("UpdateJob error: ", err) err = razorUtils.WaitForBlockCompletion(client, txn.Hex()) @@ -99,14 +103,13 @@ func (*UtilsStruct) UpdateJob(client *ethclient.Client, config types.Configurati } txnArgs := razorUtils.GetTxnOpts(types.TransactionOptions{ Client: client, - Password: jobInput.Password, - AccountAddress: jobInput.Address, ChainId: core.ChainId, Config: config, ContractAddress: core.CollectionManagerAddress, MethodName: "updateJob", Parameters: []interface{}{jobId, jobInput.Weight, jobInput.Power, jobInput.SelectorType, jobInput.Selector, jobInput.Url}, ABI: bindings.CollectionManagerMetaData.ABI, + Account: jobInput.Account, }) log.Info("Updating Job...") log.Debugf("Executing UpdateJob transaction with arguments jobId = %d, weight = %d, power = %d, selector type = %d, selector = %s, URL = %s", jobId, jobInput.Weight, jobInput.Power, jobInput.SelectorType, jobInput.Selector, jobInput.Url) diff --git a/cmd/updateJob_test.go b/cmd/updateJob_test.go index a847bc8df..0d2da59a7 100644 --- a/cmd/updateJob_test.go +++ b/cmd/updateJob_test.go @@ -3,6 +3,7 @@ package cmd import ( "errors" "math/big" + "razor/accounts" "razor/core" "razor/core/types" "testing" @@ -323,7 +324,8 @@ func TestExecuteUpdateJob(t *testing.T) { fileUtilsMock.On("AssignLogFile", mock.AnythingOfType("*pflag.FlagSet"), mock.Anything) cmdUtilsMock.On("GetConfigData").Return(tt.args.config, tt.args.configErr) utilsMock.On("AssignPassword", flagSet).Return(tt.args.password) - utilsMock.On("CheckPassword", mock.Anything, mock.Anything).Return(nil) + utilsMock.On("CheckPassword", mock.Anything).Return(nil) + utilsMock.On("AccountManagerForKeystore").Return(&accounts.AccountManager{}, nil) flagSetMock.On("GetStringAddress", flagSet).Return(tt.args.address, tt.args.addressErr) flagSetMock.On("GetStringUrl", flagSet).Return(tt.args.url, tt.args.urlErr) flagSetMock.On("GetStringSelector", flagSet).Return(tt.args.selector, tt.args.selectorErr) diff --git a/cmd/vote.go b/cmd/vote.go index 2e3739718..4aa85cdaa 100644 --- a/cmd/vote.go +++ b/cmd/vote.go @@ -6,6 +6,7 @@ import ( "errors" "fmt" "math/big" + "net/http" "os" "os/signal" "path/filepath" @@ -17,6 +18,8 @@ import ( "razor/utils" "time" + Types "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/crypto" "github.com/spf13/pflag" @@ -62,7 +65,12 @@ func (*UtilsStruct) ExecuteVote(flagSet *pflag.FlagSet) { log.Debug("Getting password...") password := razorUtils.AssignPassword(flagSet) - err = razorUtils.CheckPassword(address, password) + accountManager, err := razorUtils.AccountManagerForKeystore() + utils.CheckError("Error in getting accounts manager for keystore: ", err) + + account := accounts.InitAccountStruct(address, password, accountManager) + + err = razorUtils.CheckPassword(account) utils.CheckError("Error in fetching private key from given password: ", err) isRogue, err := flagSetUtils.GetBoolRogue(flagSet) @@ -86,11 +94,35 @@ func (*UtilsStruct) ExecuteVote(flagSet *pflag.FlagSet) { log.Warn("YOU ARE RUNNING VOTE IN ROGUE MODE, THIS CAN INCUR PENALTIES!") } - account := types.Account{Address: address, Password: password} + httpClient := &http.Client{ + Timeout: time.Duration(config.HTTPTimeout) * time.Second, + Transport: &http.Transport{ + MaxIdleConns: core.HTTPClientMaxIdleConns, + MaxIdleConnsPerHost: core.HTTPClientMaxIdleConnsPerHost, + }, + } + + stakerId, err := razorUtils.GetStakerId(client, address) + utils.CheckError("Error in getting staker id: ", err) + + if stakerId == 0 { + log.Fatal("Staker doesn't exist") + } cmdUtils.HandleExit() + + jobsCache, collectionsCache, initCacheBlockNumber, err := cmdUtils.InitJobAndCollectionCache(client) + utils.CheckError("Error in initializing asset cache: ", err) + + commitParams := &types.CommitParams{ + JobsCache: jobsCache, + CollectionsCache: collectionsCache, + HttpClient: httpClient, + FromBlockToCheckForEvents: initCacheBlockNumber, + } + log.Debugf("Calling Vote() with arguments rogueData = %+v, account address = %s, backup node actions to ignore = %s", rogueData, account.Address, backupNodeActionsToIgnore) - if err := cmdUtils.Vote(context.Background(), config, client, rogueData, account, backupNodeActionsToIgnore); err != nil { + if err := cmdUtils.Vote(context.Background(), config, client, account, stakerId, commitParams, rogueData, backupNodeActionsToIgnore); err != nil { log.Errorf("%v\n", err) osUtils.Exit(1) } @@ -121,7 +153,7 @@ func (*UtilsStruct) HandleExit() { } //This function handles all the states of voting -func (*UtilsStruct) Vote(ctx context.Context, config types.Configurations, client *ethclient.Client, rogueData types.Rogue, account types.Account, backupNodeActionsToIgnore []string) error { +func (*UtilsStruct) Vote(ctx context.Context, config types.Configurations, client *ethclient.Client, account types.Account, stakerId uint32, commitParams *types.CommitParams, rogueData types.Rogue, backupNodeActionsToIgnore []string) error { header, err := clientUtils.GetLatestBlockWithRetry(client) utils.CheckError("Error in getting block: ", err) for { @@ -138,7 +170,7 @@ func (*UtilsStruct) Vote(ctx context.Context, config types.Configurations, clien log.Debugf("Vote: Latest header value: %d", latestHeader.Number) if latestHeader.Number.Cmp(header.Number) != 0 { header = latestHeader - cmdUtils.HandleBlock(client, account, latestHeader.Number, config, rogueData, backupNodeActionsToIgnore) + cmdUtils.HandleBlock(client, account, stakerId, latestHeader, config, commitParams, rogueData, backupNodeActionsToIgnore) } time.Sleep(time.Second * time.Duration(core.BlockNumberInterval)) } @@ -153,8 +185,8 @@ var ( ) //This function handles the block -func (*UtilsStruct) HandleBlock(client *ethclient.Client, account types.Account, blockNumber *big.Int, config types.Configurations, rogueData types.Rogue, backupNodeActionsToIgnore []string) { - state, err := razorUtils.GetBufferedState(client, config.BufferPercent) +func (*UtilsStruct) HandleBlock(client *ethclient.Client, account types.Account, stakerId uint32, latestHeader *Types.Header, config types.Configurations, commitParams *types.CommitParams, rogueData types.Rogue, backupNodeActionsToIgnore []string) { + state, err := razorUtils.GetBufferedState(client, latestHeader, config.BufferPercent) if err != nil { log.Error("Error in getting state: ", err) return @@ -165,15 +197,6 @@ func (*UtilsStruct) HandleBlock(client *ethclient.Client, account types.Account, return } - stakerId, err := razorUtils.GetStakerId(client, account.Address) - if err != nil { - log.Error("Error in getting staker id: ", err) - return - } - if stakerId == 0 { - log.Error("Staker doesn't exist") - return - } staker, err := razorUtils.GetStaker(client, stakerId) if err != nil { log.Error(err) @@ -230,21 +253,21 @@ func (*UtilsStruct) HandleBlock(client *ethclient.Client, account types.Account, switch state { case 0: log.Debugf("Starting commit...") - err := cmdUtils.InitiateCommit(client, config, account, epoch, stakerId, rogueData) + err := cmdUtils.InitiateCommit(client, config, account, epoch, stakerId, latestHeader, commitParams, rogueData) if err != nil { log.Error(err) break } case 1: log.Debugf("Starting reveal...") - err := cmdUtils.InitiateReveal(client, config, account, epoch, staker, rogueData) + err := cmdUtils.InitiateReveal(client, config, account, epoch, staker, latestHeader, rogueData) if err != nil { log.Error(err) break } case 2: log.Debugf("Starting propose...") - err := cmdUtils.InitiatePropose(client, config, account, epoch, staker, blockNumber, rogueData) + err := cmdUtils.InitiatePropose(client, config, account, epoch, staker, latestHeader, rogueData) if err != nil { log.Error(err) break @@ -257,7 +280,7 @@ func (*UtilsStruct) HandleBlock(client *ethclient.Client, account types.Account, break } - err := cmdUtils.HandleDispute(client, config, account, epoch, blockNumber, rogueData, backupNodeActionsToIgnore) + err := cmdUtils.HandleDispute(client, config, account, epoch, latestHeader.Number, rogueData, backupNodeActionsToIgnore) if err != nil { log.Error(err) break @@ -280,13 +303,12 @@ func (*UtilsStruct) HandleBlock(client *ethclient.Client, account types.Account, if lastVerification == epoch && blockConfirmed < epoch { txn, err := cmdUtils.ClaimBlockReward(types.TransactionOptions{ Client: client, - Password: account.Password, - AccountAddress: account.Address, ChainId: core.ChainId, Config: config, ContractAddress: core.BlockManagerAddress, MethodName: "claimBlockReward", ABI: bindings.BlockManagerMetaData.ABI, + Account: account, }) if err != nil { @@ -313,7 +335,24 @@ func (*UtilsStruct) HandleBlock(client *ethclient.Client, account types.Account, } //This function initiates the commit -func (*UtilsStruct) InitiateCommit(client *ethclient.Client, config types.Configurations, account types.Account, epoch uint32, stakerId uint32, rogueData types.Rogue) error { +func (*UtilsStruct) InitiateCommit(client *ethclient.Client, config types.Configurations, account types.Account, epoch uint32, stakerId uint32, latestHeader *Types.Header, commitParams *types.CommitParams, rogueData types.Rogue) error { + lastCommit, err := razorUtils.GetEpochLastCommitted(client, stakerId) + if err != nil { + return errors.New("Error in fetching last commit: " + err.Error()) + } + log.Debug("InitiateCommit: Epoch last committed: ", lastCommit) + + if lastCommit >= epoch { + log.Debugf("Cannot commit in epoch %d because last committed epoch is %d", epoch, lastCommit) + return nil + } + + err = CheckForJobAndCollectionEvents(client, commitParams) + if err != nil { + log.Error("Error in checking for asset events: ", err) + return err + } + staker, err := razorUtils.GetStaker(client, stakerId) if err != nil { log.Error(err) @@ -331,17 +370,6 @@ func (*UtilsStruct) InitiateCommit(client *ethclient.Client, config types.Config log.Error("Stake is below minimum required. Kindly add stake to continue voting.") return nil } - - lastCommit, err := razorUtils.GetEpochLastCommitted(client, stakerId) - if err != nil { - return errors.New("Error in fetching last commit: " + err.Error()) - } - log.Debug("InitiateCommit: Epoch last committed: ", lastCommit) - - if lastCommit >= epoch { - log.Debugf("Cannot commit in epoch %d because last committed epoch is %d", epoch, lastCommit) - return nil - } razorPath, err := pathUtils.GetDefaultPath() if err != nil { return err @@ -356,13 +384,13 @@ func (*UtilsStruct) InitiateCommit(client *ethclient.Client, config types.Config } log.Debugf("InitiateCommit: Calling HandleCommitState with arguments epoch = %d, seed = %v, rogueData = %+v", epoch, seed, rogueData) - commitData, err := cmdUtils.HandleCommitState(client, epoch, seed, rogueData) + commitData, err := cmdUtils.HandleCommitState(client, epoch, seed, commitParams, rogueData) if err != nil { return errors.New("Error in getting active assets: " + err.Error()) } log.Debug("InitiateCommit: Commit Data: ", commitData) - commitTxn, err := cmdUtils.Commit(client, config, account, epoch, seed, commitData.Leaves) + commitTxn, err := cmdUtils.Commit(client, config, account, epoch, latestHeader, seed, commitData.Leaves) if err != nil { return errors.New("Error in committing data: " + err.Error()) } @@ -395,7 +423,7 @@ func (*UtilsStruct) InitiateCommit(client *ethclient.Client, config types.Config } //This function initiates the reveal -func (*UtilsStruct) InitiateReveal(client *ethclient.Client, config types.Configurations, account types.Account, epoch uint32, staker bindings.StructsStaker, rogueData types.Rogue) error { +func (*UtilsStruct) InitiateReveal(client *ethclient.Client, config types.Configurations, account types.Account, epoch uint32, staker bindings.StructsStaker, latestHeader *Types.Header, rogueData types.Rogue) error { stakedAmount := staker.Stake log.Debug("InitiateReveal: Staked Amount: ", stakedAmount) minStakeAmount, err := razorUtils.GetMinStakeAmount(client) @@ -506,7 +534,7 @@ func (*UtilsStruct) InitiateReveal(client *ethclient.Client, config types.Config SeqAllottedCollections: globalCommitDataStruct.SeqAllottedCollections, } log.Debugf("InitiateReveal: Calling Reveal() with arguments epoch = %d, commitDataToSend = %+v, signature = %v", epoch, commitDataToSend, signature) - revealTxn, err := cmdUtils.Reveal(client, config, account, epoch, commitDataToSend, signature) + revealTxn, err := cmdUtils.Reveal(client, config, account, epoch, latestHeader, commitDataToSend, signature) if err != nil { return errors.New("Reveal error: " + err.Error()) } @@ -525,7 +553,7 @@ func (*UtilsStruct) InitiateReveal(client *ethclient.Client, config types.Config } //This function initiates the propose -func (*UtilsStruct) InitiatePropose(client *ethclient.Client, config types.Configurations, account types.Account, epoch uint32, staker bindings.StructsStaker, blockNumber *big.Int, rogueData types.Rogue) error { +func (*UtilsStruct) InitiatePropose(client *ethclient.Client, config types.Configurations, account types.Account, epoch uint32, staker bindings.StructsStaker, latestHeader *Types.Header, rogueData types.Rogue) error { stakedAmount := staker.Stake log.Debug("InitiatePropose: Staked Amount: ", stakedAmount) minStakeAmount, err := razorUtils.GetMinStakeAmount(client) @@ -557,8 +585,8 @@ func (*UtilsStruct) InitiatePropose(client *ethclient.Client, config types.Confi return nil } - log.Debugf("InitiatePropose: Calling Propose() with arguments staker = %+v, epoch = %d, blockNumber = %s, rogueData = %+v", staker, epoch, blockNumber, rogueData) - err = cmdUtils.Propose(client, config, account, staker, epoch, blockNumber, rogueData) + log.Debugf("InitiatePropose: Calling Propose() with arguments staker = %+v, epoch = %d, blockNumber = %s, rogueData = %+v", staker, epoch, latestHeader.Number, rogueData) + err = cmdUtils.Propose(client, config, account, staker, epoch, latestHeader, rogueData) if err != nil { return errors.New("Propose error: " + err.Error()) } @@ -575,7 +603,7 @@ func (*UtilsStruct) CalculateSecret(account types.Account, epoch uint32, keystor ethHash := utils.SignHash(hash) log.Debug("Hash generated for secret") log.Debug("CalculateSecret: Ethereum signed hash: ", ethHash) - signedData, err := accounts.AccountUtilsInterface.SignData(ethHash, account, keystorePath) + signedData, err := account.AccountManager.SignData(ethHash, account.Address, account.Password) if err != nil { return nil, nil, errors.New("Error in signing the data: " + err.Error()) } diff --git a/cmd/vote_test.go b/cmd/vote_test.go index 4dadc4683..26e8d2186 100644 --- a/cmd/vote_test.go +++ b/cmd/vote_test.go @@ -1,17 +1,23 @@ package cmd import ( + "context" "encoding/hex" "errors" "math/big" "os" "path" "path/filepath" + "razor/accounts" + "razor/cache" "razor/core/types" "razor/pkg/bindings" "razor/utils" "reflect" "testing" + "time" + + Types "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/ethclient" @@ -34,6 +40,8 @@ func TestExecuteVote(t *testing.T) { rogueModeErr error address string addressErr error + stakerId uint32 + stakerIdErr error voteErr error } tests := []struct { @@ -47,6 +55,7 @@ func TestExecuteVote(t *testing.T) { config: config, password: "test", address: "0x000000000000000000000000000000000000dea1", + stakerId: 1, rogueStatus: true, rogueMode: []string{"propose", "commit"}, voteErr: nil, @@ -109,12 +118,37 @@ func TestExecuteVote(t *testing.T) { config: config, password: "test", address: "0x000000000000000000000000000000000000dea1", + stakerId: 1, rogueStatus: true, rogueMode: []string{"propose", "commit"}, voteErr: errors.New("vote error"), }, expectedFatal: false, }, + { + name: "Test 7: When there is an error in getting stakerId", + args: args{ + config: config, + password: "test", + address: "0x000000000000000000000000000000000000dea1", + stakerIdErr: errors.New("stakerId error"), + rogueStatus: true, + rogueMode: []string{"propose", "commit"}, + }, + expectedFatal: true, + }, + { + name: "Test 8: When stakerId is 0", + args: args{ + config: config, + password: "test", + address: "0x000000000000000000000000000000000000dea1", + stakerId: 0, + rogueStatus: true, + rogueMode: []string{"propose", "commit"}, + }, + expectedFatal: true, + }, } defer func() { log.ExitFunc = nil }() @@ -128,14 +162,17 @@ func TestExecuteVote(t *testing.T) { fileUtilsMock.On("AssignLogFile", mock.AnythingOfType("*pflag.FlagSet"), mock.Anything) cmdUtilsMock.On("GetConfigData").Return(tt.args.config, tt.args.configErr) utilsMock.On("AssignPassword", flagSet).Return(tt.args.password) - utilsMock.On("CheckPassword", mock.Anything, mock.Anything).Return(nil) + utilsMock.On("CheckPassword", mock.Anything).Return(nil) + utilsMock.On("AccountManagerForKeystore").Return(&accounts.AccountManager{}, nil) flagSetMock.On("GetStringAddress", mock.AnythingOfType("*pflag.FlagSet")).Return(tt.args.address, tt.args.addressErr) flagSetMock.On("GetStringSliceBackupNode", mock.Anything).Return([]string{}, nil) utilsMock.On("ConnectToClient", mock.AnythingOfType("string")).Return(client) flagSetMock.On("GetBoolRogue", mock.AnythingOfType("*pflag.FlagSet")).Return(tt.args.rogueStatus, tt.args.rogueErr) + utilsMock.On("GetStakerId", mock.AnythingOfType("*ethclient.Client"), mock.AnythingOfType("string")).Return(tt.args.stakerId, tt.args.stakerIdErr) flagSetMock.On("GetStringSliceRogueMode", mock.AnythingOfType("*pflag.FlagSet")).Return(tt.args.rogueMode, tt.args.rogueModeErr) + cmdUtilsMock.On("InitJobAndCollectionCache", mock.Anything).Return(&cache.JobsCache{}, &cache.CollectionsCache{}, big.NewInt(100), nil) cmdUtilsMock.On("HandleExit").Return() - cmdUtilsMock.On("Vote", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(tt.args.voteErr) + cmdUtilsMock.On("Vote", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(tt.args.voteErr) osMock.On("Exit", mock.AnythingOfType("int")).Return() utils := &UtilsStruct{} @@ -275,33 +312,43 @@ func TestCalculateSecret(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { InitializeInterfaces() - gotSignature, gotSecret, err := cmdUtils.CalculateSecret(types.Account{Address: tt.args.address, - Password: tt.args.password}, tt.args.epoch, testKeystorePath, tt.args.chainId) + accountManager := accounts.NewAccountManager(testKeystorePath) + account := accounts.InitAccountStruct(tt.args.address, tt.args.password, accountManager) + gotSignature, gotSecret, err := cmdUtils.CalculateSecret(account, tt.args.epoch, testKeystorePath, tt.args.chainId) + if (err != nil) != tt.wantErr { + t.Errorf("CalculateSecret() error = %v, wantErr %v", err, tt.wantErr) + return + } gotSignatureInHash := hex.EncodeToString(gotSignature) gotSecretInHash := hex.EncodeToString(gotSecret) + if !reflect.DeepEqual(gotSignatureInHash, tt.wantSignature) { t.Errorf("CalculateSecret() Signature = %v, want %v", gotSignatureInHash, tt.wantSignature) } if !reflect.DeepEqual(gotSecretInHash, tt.wantSecret) { t.Errorf("CalculateSecret() Secret = %v, want %v", gotSecretInHash, tt.wantSecret) } - if (err != nil) != tt.wantErr { - t.Errorf("CalculateSecret() error = %v, wantErr %v", err, tt.wantErr) - return - } }) } } func TestInitiateCommit(t *testing.T) { var ( - client *ethclient.Client - config types.Configurations - account types.Account - stakerId uint32 - rogueData types.Rogue + client *ethclient.Client + config types.Configurations + latestHeader *Types.Header + account types.Account + stakerId uint32 + rogueData types.Rogue ) + + commitParams := &types.CommitParams{ + JobsCache: cache.NewJobsCache(), + CollectionsCache: cache.NewCollectionsCache(), + FromBlockToCheckForEvents: big.NewInt(1), + } + type args struct { staker bindings.StructsStaker stakerErr error @@ -354,13 +401,17 @@ func TestInitiateCommit(t *testing.T) { { name: "Test 2: When there is an error in getting staker", args: args{ - stakerErr: errors.New("error in getting staker"), + epoch: 5, + lastCommit: 2, + stakerErr: errors.New("error in getting staker"), }, wantErr: true, }, { name: "Test 3: When there is an error in getting minStakeAmount", args: args{ + epoch: 5, + lastCommit: 2, staker: bindings.StructsStaker{Id: 1, Stake: big.NewInt(10000)}, minStakeAmountErr: errors.New("error in getting minStakeAmount"), }, @@ -501,14 +552,16 @@ func TestInitiateCommit(t *testing.T) { utilsMock.On("GetEpochLastCommitted", mock.AnythingOfType("*ethclient.Client"), mock.AnythingOfType("uint32")).Return(tt.args.lastCommit, tt.args.lastCommitErr) cmdUtilsMock.On("CalculateSecret", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(tt.args.signature, tt.args.secret, tt.args.secretErr) cmdUtilsMock.On("GetSalt", mock.AnythingOfType("*ethclient.Client"), mock.Anything).Return(tt.args.salt, tt.args.saltErr) - cmdUtilsMock.On("HandleCommitState", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(tt.args.commitData, tt.args.commitDataErr) + cmdUtilsMock.On("HandleCommitState", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(tt.args.commitData, tt.args.commitDataErr) pathMock.On("GetDefaultPath").Return(tt.args.path, tt.args.pathErr) - cmdUtilsMock.On("Commit", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(tt.args.commitTxn, tt.args.commitTxnErr) + cmdUtilsMock.On("Commit", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(tt.args.commitTxn, tt.args.commitTxnErr) utilsMock.On("WaitForBlockCompletion", mock.AnythingOfType("*ethclient.Client"), mock.AnythingOfType("string")).Return(tt.args.waitForBlockCompletionErr) pathMock.On("GetCommitDataFileName", mock.AnythingOfType("string")).Return(tt.args.fileName, tt.args.fileNameErr) fileUtilsMock.On("SaveDataToCommitJsonFile", mock.Anything, mock.Anything, mock.Anything).Return(tt.args.saveErr) + clientUtilsMock.On("GetLatestBlockWithRetry", mock.Anything).Return(&Types.Header{Number: big.NewInt(100)}, nil) + clientUtilsMock.On("FilterLogsWithRetry", mock.Anything, mock.Anything).Return([]Types.Log{}, nil) ut := &UtilsStruct{} - if err := ut.InitiateCommit(client, config, account, tt.args.epoch, stakerId, rogueData); (err != nil) != tt.wantErr { + if err := ut.InitiateCommit(client, config, account, tt.args.epoch, stakerId, latestHeader, commitParams, rogueData); (err != nil) != tt.wantErr { t.Errorf("InitiateCommit() error = %v, wantErr %v", err, tt.wantErr) } }) @@ -517,9 +570,10 @@ func TestInitiateCommit(t *testing.T) { func TestInitiateReveal(t *testing.T) { var ( - client *ethclient.Client - config types.Configurations - account types.Account + client *ethclient.Client + config types.Configurations + account types.Account + latestHeader *Types.Header ) randomNum := big.NewInt(1111) @@ -725,10 +779,10 @@ func TestInitiateReveal(t *testing.T) { cmdUtilsMock.On("CalculateSecret", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(tt.args.signature, tt.args.secret, tt.args.secretErr) cmdUtilsMock.On("GetSalt", mock.Anything, mock.Anything).Return([32]byte{}, nil) utilsMock.On("GetCommitment", mock.Anything, mock.Anything).Return(types.Commitment{}, nil) - cmdUtilsMock.On("Reveal", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(tt.args.revealTxn, tt.args.revealTxnErr) + cmdUtilsMock.On("Reveal", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(tt.args.revealTxn, tt.args.revealTxnErr) utilsMock.On("WaitForBlockCompletion", mock.AnythingOfType("*ethclient.Client"), mock.AnythingOfType("string")).Return(nil) ut := &UtilsStruct{} - if err := ut.InitiateReveal(client, config, account, tt.args.epoch, tt.args.staker, tt.args.rogueData); (err != nil) != tt.wantErr { + if err := ut.InitiateReveal(client, config, account, tt.args.epoch, tt.args.staker, latestHeader, tt.args.rogueData); (err != nil) != tt.wantErr { t.Errorf("InitiateReveal() error = %v, wantErr %v", err, tt.wantErr) } }) @@ -737,11 +791,10 @@ func TestInitiateReveal(t *testing.T) { func TestInitiatePropose(t *testing.T) { var ( - client *ethclient.Client - config types.Configurations - account types.Account - blockNumber *big.Int - rogueData types.Rogue + client *ethclient.Client + config types.Configurations + account types.Account + rogueData types.Rogue ) type args struct { staker bindings.StructsStaker @@ -754,6 +807,10 @@ func TestInitiatePropose(t *testing.T) { lastRevealErr error proposeTxnErr error } + + latestHeader := &Types.Header{ + Number: big.NewInt(1), + } tests := []struct { name string args args @@ -841,10 +898,10 @@ func TestInitiatePropose(t *testing.T) { utilsMock.On("GetMinStakeAmount", mock.AnythingOfType("*ethclient.Client")).Return(tt.args.minStakeAmount, tt.args.minStakeAmountErr) utilsMock.On("GetEpochLastProposed", mock.AnythingOfType("*ethclient.Client"), mock.AnythingOfType("uint32")).Return(tt.args.lastProposal, tt.args.lastProposalErr) utilsMock.On("GetEpochLastRevealed", mock.AnythingOfType("*ethclient.Client"), mock.AnythingOfType("uint32")).Return(tt.args.lastReveal, tt.args.lastRevealErr) - cmdUtilsMock.On("Propose", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(tt.args.proposeTxnErr) + cmdUtilsMock.On("Propose", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(tt.args.proposeTxnErr) utilsMock.On("WaitForBlockCompletion", mock.AnythingOfType("*ethclient.Client"), mock.AnythingOfType("string")).Return(nil) ut := &UtilsStruct{} - if err := ut.InitiatePropose(client, config, account, tt.args.epoch, tt.args.staker, blockNumber, rogueData); (err != nil) != tt.wantErr { + if err := ut.InitiatePropose(client, config, account, tt.args.epoch, tt.args.staker, latestHeader, rogueData); (err != nil) != tt.wantErr { t.Errorf("InitiatePropose() error = %v, wantErr %v", err, tt.wantErr) } }) @@ -855,11 +912,15 @@ func TestHandleBlock(t *testing.T) { var ( client *ethclient.Client account types.Account - blockNumber *big.Int + stakerId uint32 + commitParams *types.CommitParams rogueData types.Rogue backupNodeActionsToIgnore []string ) + latestHeader := &Types.Header{ + Number: big.NewInt(1001), + } type args struct { config types.Configurations state int64 @@ -867,8 +928,6 @@ func TestHandleBlock(t *testing.T) { epoch uint32 epochErr error stateName string - stakerId uint32 - stakerIdErr error staker bindings.StructsStaker stakerErr error ethBalance *big.Int @@ -899,7 +958,6 @@ func TestHandleBlock(t *testing.T) { state: 0, epoch: 1, stateName: "commit", - stakerId: 1, staker: bindings.StructsStaker{Id: 1, Stake: big.NewInt(10000)}, ethBalance: big.NewInt(1000), actualStake: big.NewFloat(10000), @@ -921,30 +979,12 @@ func TestHandleBlock(t *testing.T) { epochErr: errors.New("error in getting epoch"), }, }, - { - name: "Test 4: When there is an error in getting stakerId", - args: args{ - state: 0, - epoch: 1, - stakerIdErr: errors.New("error in getting stakerId"), - }, - }, - { - name: "Test 5: When stakerId is 0", - args: args{ - state: 0, - epoch: 1, - stateName: "commit", - stakerId: 0, - }, - }, { name: "Test 6: When there is an error in getting staker", args: args{ state: 0, epoch: 1, stateName: "commit", - stakerId: 1, stakerErr: errors.New("error in getting staker"), }, }, @@ -954,7 +994,6 @@ func TestHandleBlock(t *testing.T) { state: 0, epoch: 1, stateName: "commit", - stakerId: 1, staker: bindings.StructsStaker{Id: 1, Stake: big.NewInt(10000)}, ethBalanceErr: errors.New("error in getting ethBalance"), }, @@ -965,7 +1004,6 @@ func TestHandleBlock(t *testing.T) { state: 0, epoch: 1, stateName: "commit", - stakerId: 1, sRZRBalance: big.NewInt(1000), staker: bindings.StructsStaker{Id: 1, Stake: big.NewInt(10000)}, ethBalance: big.NewInt(1000), @@ -979,7 +1017,6 @@ func TestHandleBlock(t *testing.T) { state: 0, epoch: 1, stateName: "commit", - stakerId: 1, staker: bindings.StructsStaker{Id: 1, Stake: big.NewInt(10000)}, ethBalance: big.NewInt(1000), actualStake: big.NewFloat(10000), @@ -993,7 +1030,6 @@ func TestHandleBlock(t *testing.T) { state: 0, epoch: 1, stateName: "commit", - stakerId: 1, staker: bindings.StructsStaker{Id: 1, Stake: big.NewInt(100)}, ethBalance: big.NewInt(1000), actualStake: big.NewFloat(100), @@ -1008,7 +1044,6 @@ func TestHandleBlock(t *testing.T) { state: 0, epoch: 1, stateName: "commit", - stakerId: 1, staker: bindings.StructsStaker{Id: 1, Stake: big.NewInt(0)}, ethBalance: big.NewInt(1000), actualStake: big.NewFloat(0), @@ -1023,7 +1058,6 @@ func TestHandleBlock(t *testing.T) { state: 0, epoch: 1, stateName: "commit", - stakerId: 1, staker: bindings.StructsStaker{Id: 1, Stake: big.NewInt(10000), IsSlashed: true}, ethBalance: big.NewInt(1000), actualStake: big.NewFloat(10000), @@ -1038,7 +1072,6 @@ func TestHandleBlock(t *testing.T) { state: 0, epoch: 1, stateName: "commit", - stakerId: 1, staker: bindings.StructsStaker{Id: 1, Stake: big.NewInt(10000)}, ethBalance: big.NewInt(1000), actualStake: big.NewFloat(10000), @@ -1054,7 +1087,6 @@ func TestHandleBlock(t *testing.T) { state: 1, epoch: 1, stateName: "reveal", - stakerId: 1, staker: bindings.StructsStaker{Id: 1, Stake: big.NewInt(10000)}, ethBalance: big.NewInt(1000), actualStake: big.NewFloat(10000), @@ -1070,7 +1102,6 @@ func TestHandleBlock(t *testing.T) { state: 2, epoch: 1, stateName: "propose", - stakerId: 1, staker: bindings.StructsStaker{Id: 1, Stake: big.NewInt(10000)}, ethBalance: big.NewInt(1000), actualStake: big.NewFloat(10000), @@ -1086,7 +1117,6 @@ func TestHandleBlock(t *testing.T) { state: 3, epoch: 1, stateName: "dispute", - stakerId: 1, staker: bindings.StructsStaker{Id: 1, Stake: big.NewInt(10000)}, ethBalance: big.NewInt(1000), actualStake: big.NewFloat(10000), @@ -1102,7 +1132,6 @@ func TestHandleBlock(t *testing.T) { state: 3, epoch: 1, stateName: "dispute", - stakerId: 1, staker: bindings.StructsStaker{Id: 1, Stake: big.NewInt(10000)}, ethBalance: big.NewInt(1000), actualStake: big.NewFloat(10000), @@ -1118,7 +1147,6 @@ func TestHandleBlock(t *testing.T) { state: 3, epoch: 1, stateName: "dispute", - stakerId: 1, staker: bindings.StructsStaker{Id: 1, Stake: big.NewInt(10000)}, ethBalance: big.NewInt(1000), actualStake: big.NewFloat(10000), @@ -1136,7 +1164,6 @@ func TestHandleBlock(t *testing.T) { epoch: 1, stateName: "confirm", lastVerification: 1, - stakerId: 1, staker: bindings.StructsStaker{Id: 1, Stake: big.NewInt(10000)}, ethBalance: big.NewInt(1000), actualStake: big.NewFloat(10000), @@ -1153,7 +1180,6 @@ func TestHandleBlock(t *testing.T) { epoch: 2, stateName: "confirm", lastVerification: 1, - stakerId: 2, staker: bindings.StructsStaker{Id: 2, Stake: big.NewInt(10000)}, ethBalance: big.NewInt(1000), actualStake: big.NewFloat(10000), @@ -1170,7 +1196,6 @@ func TestHandleBlock(t *testing.T) { epoch: 1, lastVerification: 4, stateName: "dispute", - stakerId: 1, staker: bindings.StructsStaker{Id: 1, Stake: big.NewInt(10000)}, ethBalance: big.NewInt(1000), actualStake: big.NewFloat(10000), @@ -1186,7 +1211,6 @@ func TestHandleBlock(t *testing.T) { epoch: 1, lastVerification: 4, stateName: "", - stakerId: 1, staker: bindings.StructsStaker{Id: 1, Stake: big.NewInt(10000)}, ethBalance: big.NewInt(1000), actualStake: big.NewFloat(10000), @@ -1201,16 +1225,15 @@ func TestHandleBlock(t *testing.T) { t.Run(tt.name, func(t *testing.T) { SetUpMockInterfaces() - utilsMock.On("GetBufferedState", mock.AnythingOfType("*ethclient.Client"), mock.AnythingOfType("int32")).Return(tt.args.state, tt.args.stateErr) + utilsMock.On("GetBufferedState", mock.Anything, mock.Anything, mock.Anything).Return(tt.args.state, tt.args.stateErr) utilsMock.On("GetEpoch", mock.AnythingOfType("*ethclient.Client")).Return(tt.args.epoch, tt.args.epochErr) - utilsMock.On("GetStakerId", mock.AnythingOfType("*ethclient.Client"), mock.AnythingOfType("string")).Return(tt.args.stakerId, tt.args.stakerIdErr) utilsMock.On("GetStaker", mock.AnythingOfType("*ethclient.Client"), mock.AnythingOfType("uint32")).Return(tt.args.staker, tt.args.stakerErr) clientUtilsMock.On("BalanceAtWithRetry", mock.AnythingOfType("*ethclient.Client"), mock.Anything).Return(tt.args.ethBalance, tt.args.ethBalanceErr) utilsMock.On("GetStakerSRZRBalance", mock.Anything, mock.Anything).Return(tt.args.sRZRBalance, tt.args.sRZRBalanceErr) osMock.On("Exit", mock.AnythingOfType("int")).Return() - cmdUtilsMock.On("InitiateCommit", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(tt.args.initiateCommitErr) - cmdUtilsMock.On("InitiateReveal", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(tt.args.initiateRevealErr) - cmdUtilsMock.On("InitiatePropose", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(tt.args.initiateProposeErr) + cmdUtilsMock.On("InitiateCommit", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(tt.args.initiateCommitErr) + cmdUtilsMock.On("InitiateReveal", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(tt.args.initiateRevealErr) + cmdUtilsMock.On("InitiatePropose", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(tt.args.initiateProposeErr) cmdUtilsMock.On("HandleDispute", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(tt.args.handleDisputeErr) utilsMock.On("IsFlagPassed", mock.AnythingOfType("string")).Return(tt.args.isFlagPassed) cmdUtilsMock.On("HandleClaimBounty", mock.Anything, mock.Anything, mock.Anything).Return(tt.args.handleClaimBountyErr) @@ -1220,7 +1243,67 @@ func TestHandleBlock(t *testing.T) { utilsMock.On("WaitTillNextNSecs", mock.AnythingOfType("int32")).Return() lastVerification = tt.args.lastVerification ut := &UtilsStruct{} - ut.HandleBlock(client, account, blockNumber, tt.args.config, rogueData, backupNodeActionsToIgnore) + ut.HandleBlock(client, account, stakerId, latestHeader, tt.args.config, commitParams, rogueData, backupNodeActionsToIgnore) + }) + } +} + +func TestVote(t *testing.T) { + var ( + config types.Configurations + client *ethclient.Client + rogueData types.Rogue + account types.Account + stakerId uint32 + commitParams *types.CommitParams + backupNodeActionsToIgnore []string + ) + type args struct { + header *Types.Header + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "Test when context is cancelled", + args: args{ + header: &Types.Header{ + Number: big.NewInt(101), + }, + }, + wantErr: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + SetUpMockInterfaces() + + clientUtilsMock.On("GetLatestBlockWithRetry", mock.Anything).Return(tt.args.header, nil) + cmdUtilsMock.On("HandleBlock", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil) + + ut := &UtilsStruct{} + errChan := make(chan error) + // Run Vote function in a goroutine + go func() { + errChan <- ut.Vote(ctx, config, client, account, stakerId, commitParams, rogueData, backupNodeActionsToIgnore) + }() + + // Wait for some time to allow Vote function to execute + time.Sleep(time.Second * 2) + + // Cancel the context to simulate its done + cancel() + + // Check the error returned from the function + err := <-errChan + if (err != nil) != tt.wantErr { + t.Errorf("Vote() error = %v, wantErr %v", err, tt.wantErr) + } }) } } diff --git a/config.sh b/config.sh index 4d8c884fb..210fcd1f1 100644 --- a/config.sh +++ b/config.sh @@ -19,15 +19,15 @@ then GAS_MULTIPLIER=1.0 fi -read -rp "Buffer Percent: (0) " BUFFER +read -rp "Buffer Percent: (20) " BUFFER if [ -z "$BUFFER" ]; then - BUFFER=0 + BUFFER=20 fi -read -rp "Wait Time: (1) " WAIT_TIME +read -rp "Wait Time: (5) " WAIT_TIME if [ -z "$WAIT_TIME" ]; then - WAIT_TIME=1 + WAIT_TIME=5 fi read -rp "Gas Price: (0) " GAS_PRICE @@ -45,14 +45,14 @@ if [ -z "$MAX_SIZE" ]; then MAX_SIZE=200 fi -read -rp "Log Files Max Backups: (52) " MAX_BACKUPS +read -rp "Log Files Max Backups: (10) " MAX_BACKUPS if [ -z "$MAX_BACKUPS" ]; then - MAX_BACKUPS=52 + MAX_BACKUPS=10 fi -read -rp "Log Files Max Age: (365) " MAX_AGE +read -rp "Log Files Max Age: (60) " MAX_AGE if [ -z "$MAX_AGE" ]; then - MAX_AGE=365 + MAX_AGE=60 fi ALT_PROVIDER_OPTION="" diff --git a/core/constants.go b/core/constants.go index c8952f864..2aad5ba69 100644 --- a/core/constants.go +++ b/core/constants.go @@ -3,81 +3,111 @@ package core import ( - "github.com/ethereum/go-ethereum/common" "math/big" + + "github.com/ethereum/go-ethereum/common" ) -var EpochLength uint64 = 300 -var NumberOfStates uint64 = 5 -var StateLength = EpochLength / NumberOfStates +const ( + EpochLength uint64 = 1200 + NumberOfStates uint64 = 5 + StateLength = EpochLength / NumberOfStates +) // ChainId corresponds to the SKALE chain -var ChainId = big.NewInt(0x561bf78b) +var ChainId = big.NewInt(0x109B4597) + +const MaxRetries uint = 8 -var MaxRetries uint = 8 var NilHash = common.Hash{0x00} -var BlockCompletionTimeout = 30 -//Following are the default config values for all the config parameters +const BlockCompletionTimeout = 30 -var DefaultGasMultiplier float32 = 1.0 -var DefaultBufferPercent int32 = 0 -var DefaultGasPrice int32 = 0 -var DefaultWaitTime int32 = 1 -var DefaultGasLimit float32 = 2 -var DefaultGasLimitOverride uint64 = 30000000 -var DefaultRPCTimeout int64 = 10 -var DefaultHTTPTimeout int64 = 10 -var DefaultLogLevel = "" +//Following are the default config values for all the config parameters +const ( + DefaultGasMultiplier float32 = 1.0 + DefaultBufferPercent int32 = 20 + DefaultGasPrice int32 = 0 + DefaultWaitTime int32 = 5 + DefaultGasLimit float32 = 2 + DefaultGasLimitOverride uint64 = 30000000 + DefaultRPCTimeout int64 = 10 + DefaultHTTPTimeout int64 = 10 + DefaultLogLevel = "" +) //BufferStateSleepTime is the sleeping time whenever buffer state hits -var BufferStateSleepTime int32 = 2 +const BufferStateSleepTime int32 = 2 //Following are the default logFile parameters in config - -var DefaultLogFileMaxSize = 200 -var DefaultLogFileMaxBackups = 52 -var DefaultLogFileMaxAge = 365 +const ( + DefaultLogFileMaxSize = 200 + DefaultLogFileMaxBackups = 10 + DefaultLogFileMaxAge = 60 +) //DisputeGasMultiplier is a constant gasLimitMultiplier to increase gas Limit for function `disputeCollectionIdShouldBeAbsent` and `disputeCollectionIdShouldBePresent` -var DisputeGasMultiplier float32 = 5.5 +const DisputeGasMultiplier float32 = 5.5 // Following are the constants which will be used to derive different file paths -var DataFileDirectory = "data_files" -var CommitDataFile = "_commitData.json" -var ProposeDataFile = "_proposeData.json" -var DisputeDataFile = "_disputeData.json" -var AssetsDataFile = "assets.json" -var ConfigFile = "razor.yaml" -var LogFileDirectory = "logs" -var DefaultPathName = ".razor" +const ( + DataFileDirectory = "data_files" + CommitDataFile = "_commitData.json" + ProposeDataFile = "_proposeData.json" + DisputeDataFile = "_disputeData.json" + AssetsDataFile = "assets.json" + ConfigFile = "razor.yaml" + LogFileDirectory = "logs" + DefaultPathName = ".razor" +) //BlockNumberInterval is the interval in seconds after which blockNumber needs to be calculated again -var BlockNumberInterval = 5 +const BlockNumberInterval = 5 //APIKeyRegex will be used as a regular expression to be matched in job Urls -var APIKeyRegex = `\$\{(.+?)\}` +const APIKeyRegex = `\$\{(.+?)\}` // Following are the constants which defines retry attempts and retry delay if there is an error in processing request - -var ProcessRequestRetryAttempts uint = 2 -var ProcessRequestRetryDelay = 2 +const ( + ProcessRequestRetryAttempts uint = 2 + ProcessRequestRetryDelay int64 = 2 +) //SwitchClientDuration is the time after which alternate client from secondary RPC will be switched back to client from primary RPC -var SwitchClientDuration = 5 * EpochLength +const SwitchClientDuration = 5 * EpochLength -// HexReturnType is the ReturnType for a job if that job returns a hex value -var HexReturnType = "hex" +const ( + // HexReturnType is the ReturnType for a job if that job returns a hex value + HexReturnType = "hex" -// HexArrayReturnType is the ReturnType for a job if that job returns a hex array value -var HexArrayReturnType = "^hexArray\\[\\d+\\]$" + // HexArrayReturnType is the ReturnType for a job if that job returns a hex array value + HexArrayReturnType = "^hexArray\\[\\d+\\]$" -// HexArrayExtractIndexRegex will be used as a regular expression to extract index from hexArray return type -var HexArrayExtractIndexRegex = `^hexArray\[(\d+)\]$` + // HexArrayExtractIndexRegex will be used as a regular expression to extract index from hexArray return type + HexArrayExtractIndexRegex = `^hexArray\[(\d+)\]$` +) // Following are the constants which helps in calculating iteration for a staker +const ( + BatchSize = 1000 + NumRoutines = 10 + MaxIterations = 10000000 +) -var BatchSize = 1000 -var NumRoutines = 10 -var MaxIterations = 10000000 +// Following are the constants used in custom http.Transport configuration for the common HTTP client that we use for all the requests +const ( + HTTPClientMaxIdleConns = 15 + HTTPClientMaxIdleConnsPerHost = 5 +) + +const GetStakeSnapshotMethod = "getStakeSnapshot" + +// Following are the event names that nodes will listen to in order to update the jobs/collections in the cache +const ( + JobCreatedEvent = "JobCreated" + CollectionCreatedEvent = "CollectionCreated" + JobUpdatedEvent = "JobUpdated" + CollectionUpdatedEvent = "CollectionUpdated" + CollectionActivityStatusEvent = "CollectionActivityStatus" +) diff --git a/core/contracts.go b/core/contracts.go index 957204ed7..6079b6e4c 100644 --- a/core/contracts.go +++ b/core/contracts.go @@ -1,7 +1,7 @@ package core -var StakeManagerAddress = "0x432bDa6F3E5148898929be9d3555Ca5AA82b214b" -var RAZORAddress = "0xbF3BCf61f64C9825C7Af3f3D79817c9Cf44afBa7" -var CollectionManagerAddress = "0x7B8BF9a0B648Dd9f75D5E9e8a3054D18E8C4Cc5e" -var VoteManagerAddress = "0x86886e048fd0f253E6E75c13a3f924598799e06A" -var BlockManagerAddress = "0x39D4B78bb09DEEC54fA2df729808b19962Cb9aae" +var StakeManagerAddress = "0xe0bC695203d9C9f379bcdE9260B9F71B64B85298" +var RAZORAddress = "0xcbf70914Fae03B3acB91E953De60CfDAaCA8145f" +var CollectionManagerAddress = "0x367962d1462C568A0dDd0e2448311469451bF5a3" +var VoteManagerAddress = "0x641BAD0641eB5B94B19568C0a22a55AEbDAF1870" +var BlockManagerAddress = "0x11aB70d78f1Dd2c3F967180d8A64858Db03A0aBa" diff --git a/core/types/account.go b/core/types/account.go index 5d230f53d..da16d30d8 100644 --- a/core/types/account.go +++ b/core/types/account.go @@ -1,6 +1,21 @@ package types +import ( + "crypto/ecdsa" + "github.com/ethereum/go-ethereum/accounts" +) + +//go:generate mockery --name=AccountManagerInterface --output=../../accounts/mocks --case=underscore + type Account struct { - Address string - Password string + Address string + Password string + AccountManager AccountManagerInterface +} + +type AccountManagerInterface interface { + CreateAccount(keystorePath, password string) accounts.Account + GetPrivateKey(address, password string) (*ecdsa.PrivateKey, error) + SignData(hash []byte, address string, password string) ([]byte, error) + NewAccount(passphrase string) (accounts.Account, error) } diff --git a/core/types/inputs.go b/core/types/inputs.go index 63893e579..89a95d18d 100644 --- a/core/types/inputs.go +++ b/core/types/inputs.go @@ -3,29 +3,25 @@ package types import "math/big" type UnstakeInput struct { - Address string - Password string + Account Account ValueInWei *big.Int StakerId uint32 } type RedeemBountyInput struct { - Address string - Password string + Account Account BountyId uint32 } type TransferInput struct { - FromAddress string - ToAddress string - Password string - ValueInWei *big.Int - Balance *big.Int + Account Account + ToAddress string + ValueInWei *big.Int + Balance *big.Int } type CreateJobInput struct { - Address string - Password string + Account Account Name string Url string Selector string @@ -35,9 +31,8 @@ type CreateJobInput struct { } type CreateCollectionInput struct { - Address string + Account Account Name string - Password string Aggregation uint32 Power int8 JobIds []uint @@ -45,21 +40,18 @@ type CreateCollectionInput struct { } type ExtendLockInput struct { - Address string - Password string + Account Account StakerId uint32 } type ModifyCollectionInput struct { - Address string - Password string + Account Account CollectionId uint16 Status bool } type SetDelegationInput struct { - Address string - Password string + Account Account Status bool StatusString string StakerId uint32 @@ -67,8 +59,7 @@ type SetDelegationInput struct { } type UpdateCommissionInput struct { - Address string - Password string + Account Account Commission uint8 StakerId uint32 } diff --git a/core/types/transaction.go b/core/types/transaction.go index 11c46cadd..75819cacf 100644 --- a/core/types/transaction.go +++ b/core/types/transaction.go @@ -7,14 +7,13 @@ import ( type TransactionOptions struct { Client *ethclient.Client - Password string EtherValue *big.Int Amount *big.Int - AccountAddress string ChainId *big.Int Config Configurations ContractAddress string MethodName string Parameters []interface{} ABI string + Account Account } diff --git a/core/types/vote.go b/core/types/vote.go index 445afb5ae..f1fb7b743 100644 --- a/core/types/vote.go +++ b/core/types/vote.go @@ -1,6 +1,10 @@ package types -import "math/big" +import ( + "math/big" + "net/http" + "razor/cache" +) type ElectedProposer struct { Iteration int @@ -62,3 +66,11 @@ type ProposeFileData struct { RevealedCollectionIds []uint16 RevealedDataMaps *RevealedDataMaps } + +type CommitParams struct { + JobsCache *cache.JobsCache + CollectionsCache *cache.CollectionsCache + LocalCache *cache.LocalCache + HttpClient *http.Client + FromBlockToCheckForEvents *big.Int +} diff --git a/core/version.go b/core/version.go index e05fa25c3..b31b42ff3 100644 --- a/core/version.go +++ b/core/version.go @@ -4,8 +4,8 @@ import "fmt" const ( VersionMajor = 1 // Major version component of the current release - VersionMinor = 1 // Minor version component of the current release - VersionPatch = 1 // Patch version component of the current release + VersionMinor = 2 // Minor version component of the current release + VersionPatch = 0 // Patch version component of the current release VersionMeta = "" // Version metadata to append to the version string ) diff --git a/package.json b/package.json index a14ebf922..2fd2ffcc2 100644 --- a/package.json +++ b/package.json @@ -7,6 +7,7 @@ "setup": "make setup", "build": "make build", "build-all": "make all", + "build-all-testnet": "make all-testnet", "build-noargs": "make build-noargs", "build-noargs-testnet": "make build-noargs-testnet", "test": "go test ./... -v" diff --git a/utils/api.go b/utils/api.go index 39378a65f..a64eb1a41 100644 --- a/utils/api.go +++ b/utils/api.go @@ -7,7 +7,6 @@ import ( "fmt" "io" "net/http" - "razor/cache" "razor/core" "regexp" "time" @@ -19,34 +18,30 @@ import ( "github.com/gocolly/colly" ) -func GetDataFromAPI(dataSourceURLStruct types.DataSourceURL, localCache *cache.LocalCache) ([]byte, error) { - client := http.Client{ - Timeout: time.Duration(HTTPTimeout) * time.Second, - } - +func GetDataFromAPI(commitParams *types.CommitParams, dataSourceURLStruct types.DataSourceURL) ([]byte, error) { cacheKey, err := generateCacheKey(dataSourceURLStruct.URL, dataSourceURLStruct.Body) if err != nil { log.Errorf("Error in generating cache key for API %s: %v", dataSourceURLStruct.URL, err) return nil, err } - cachedData, found := localCache.Read(cacheKey) + cachedData, found := commitParams.LocalCache.Read(cacheKey) if found { log.Debugf("Getting Data for URL %s from local cache...", dataSourceURLStruct.URL) return cachedData, nil } - response, err := makeAPIRequest(client, dataSourceURLStruct) + response, err := makeAPIRequest(commitParams.HttpClient, dataSourceURLStruct) if err != nil { return nil, err } // Storing the data into cache - localCache.Update(response, cacheKey, time.Now().Add(time.Second*time.Duration(core.StateLength)).Unix()) + commitParams.LocalCache.Update(response, cacheKey, time.Now().Add(time.Second*time.Duration(core.StateLength)).Unix()) return response, nil } -func makeAPIRequest(client http.Client, dataSourceURLStruct types.DataSourceURL) ([]byte, error) { +func makeAPIRequest(httpClient *http.Client, dataSourceURLStruct types.DataSourceURL) ([]byte, error) { var requestBody io.Reader // Using the broader io.Reader interface here switch dataSourceURLStruct.Type { @@ -68,7 +63,7 @@ func makeAPIRequest(client http.Client, dataSourceURLStruct types.DataSourceURL) var response []byte err := retry.Do( func() error { - responseBody, err := ProcessRequest(client, dataSourceURLStruct, requestBody) + responseBody, err := ProcessRequest(httpClient, dataSourceURLStruct, requestBody) if err != nil { log.Errorf("Error in processing %s request: %v", dataSourceURLStruct.Type, err) return err @@ -146,13 +141,13 @@ func addHeaderToRequest(request *http.Request, headerMap map[string]string) *htt return request } -func ProcessRequest(client http.Client, dataSourceURLStruct types.DataSourceURL, requestBody io.Reader) ([]byte, error) { +func ProcessRequest(httpClient *http.Client, dataSourceURLStruct types.DataSourceURL, requestBody io.Reader) ([]byte, error) { request, err := http.NewRequest(dataSourceURLStruct.Type, dataSourceURLStruct.URL, requestBody) if err != nil { return nil, err } requestWithHeader := addHeaderToRequest(request, dataSourceURLStruct.Header) - response, err := client.Do(requestWithHeader) + response, err := httpClient.Do(requestWithHeader) if err != nil { log.Errorf("Error sending %s request URL %s: %v", dataSourceURLStruct.Type, dataSourceURLStruct.URL, err) return nil, err diff --git a/utils/api_test.go b/utils/api_test.go index 34bdce5f1..0d5355237 100644 --- a/utils/api_test.go +++ b/utils/api_test.go @@ -3,12 +3,14 @@ package utils import ( "encoding/hex" "encoding/json" - "github.com/stretchr/testify/assert" + "net/http" "razor/cache" "razor/core/types" "reflect" "testing" "time" + + "github.com/stretchr/testify/assert" ) func getAPIByteArray(index int) []byte { @@ -34,6 +36,14 @@ func TestGetDataFromAPI(t *testing.T) { //postRequestInput := `{"type": "POST","url": "https://rpc.ankr.com/polygon_mumbai","body": {"jsonrpc": "2.0","method": "eth_chainId","params": [],"id": 0},"header": {"content-type": "application/json"}}` sampleChainId, _ := hex.DecodeString("7b226a736f6e727063223a22322e30222c22726573756c74223a223078616133376463222c226964223a307d0a") + httpClient := &http.Client{ + Timeout: 10 * time.Second, + Transport: &http.Transport{ + MaxIdleConns: 2, + MaxIdleConnsPerHost: 1, + }, + } + type args struct { urlStruct types.DataSourceURL } @@ -169,7 +179,11 @@ func TestGetDataFromAPI(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { localCache := cache.NewLocalCache(time.Second * 10) - got, err := GetDataFromAPI(tt.args.urlStruct, localCache) + commitParams := &types.CommitParams{ + LocalCache: localCache, + HttpClient: httpClient, + } + got, err := GetDataFromAPI(commitParams, tt.args.urlStruct) if (err != nil) != tt.wantErr { t.Errorf("GetDataFromAPI() error = %v, wantErr %v", err, tt.wantErr) return diff --git a/utils/asset.go b/utils/asset.go index 5051cc39d..7f3602a41 100644 --- a/utils/asset.go +++ b/utils/asset.go @@ -141,21 +141,21 @@ func (*UtilsStruct) GetActiveCollectionIds(client *ethclient.Client) ([]uint16, return activeCollectionIds, nil } -func (*UtilsStruct) GetAggregatedDataOfCollection(client *ethclient.Client, collectionId uint16, epoch uint32, localCache *cache.LocalCache) (*big.Int, error) { - activeCollection, err := UtilsInterface.GetActiveCollection(client, collectionId) +func (*UtilsStruct) GetAggregatedDataOfCollection(client *ethclient.Client, collectionId uint16, epoch uint32, commitParams *types.CommitParams) (*big.Int, error) { + activeCollection, err := UtilsInterface.GetActiveCollection(commitParams.CollectionsCache, collectionId) if err != nil { log.Error(err) return nil, err } //Supply previous epoch to Aggregate in case if last reported value is required. - collectionData, aggregationError := UtilsInterface.Aggregate(client, epoch-1, activeCollection, localCache) + collectionData, aggregationError := UtilsInterface.Aggregate(client, epoch-1, activeCollection, commitParams) if aggregationError != nil { return nil, aggregationError } return collectionData, nil } -func (*UtilsStruct) Aggregate(client *ethclient.Client, previousEpoch uint32, collection bindings.StructsCollection, localCache *cache.LocalCache) (*big.Int, error) { +func (*UtilsStruct) Aggregate(client *ethclient.Client, previousEpoch uint32, collection bindings.StructsCollection, commitParams *types.CommitParams) (*big.Int, error) { var jobs []bindings.StructsJob var overriddenJobIds []uint16 @@ -184,7 +184,7 @@ func (*UtilsStruct) Aggregate(client *ethclient.Client, previousEpoch uint32, co } // Overriding the jobs from contracts with official jobs present in asset.go - overrideJobs, overriddenJobIdsFromJSONfile := UtilsInterface.HandleOfficialJobsFromJSONFile(client, collection, dataString) + overrideJobs, overriddenJobIdsFromJSONfile := UtilsInterface.HandleOfficialJobsFromJSONFile(client, collection, dataString, commitParams) jobs = append(jobs, overrideJobs...) overriddenJobIds = append(overriddenJobIds, overriddenJobIdsFromJSONfile...) @@ -199,9 +199,9 @@ func (*UtilsStruct) Aggregate(client *ethclient.Client, previousEpoch uint32, co for _, id := range collection.JobIDs { // Ignoring the Jobs which are already overriden and added to jobs array if !Contains(overriddenJobIds, id) { - job, err := UtilsInterface.GetActiveJob(client, id) - if err != nil { - log.Errorf("Error in fetching job %d: %v", id, err) + job, isPresent := commitParams.JobsCache.GetJob(id) + if !isPresent { + log.Errorf("Job with id %v is not present in cache", id) continue } jobs = append(jobs, job) @@ -211,7 +211,7 @@ func (*UtilsStruct) Aggregate(client *ethclient.Client, previousEpoch uint32, co if len(jobs) == 0 { return nil, errors.New("no jobs present in the collection") } - dataToCommit, weight := UtilsInterface.GetDataToCommitFromJobs(jobs, localCache) + dataToCommit, weight := UtilsInterface.GetDataToCommitFromJobs(jobs, commitParams) if len(dataToCommit) == 0 { prevCommitmentData, err := UtilsInterface.FetchPreviousValue(client, previousEpoch, collection.Id) if err != nil { @@ -242,10 +242,10 @@ func (*UtilsStruct) GetActiveJob(client *ethclient.Client, jobId uint16) (bindin return job, nil } -func (*UtilsStruct) GetActiveCollection(client *ethclient.Client, collectionId uint16) (bindings.StructsCollection, error) { - collection, err := UtilsInterface.GetCollection(client, collectionId) - if err != nil { - return bindings.StructsCollection{}, err +func (*UtilsStruct) GetActiveCollection(collectionsCache *cache.CollectionsCache, collectionId uint16) (bindings.StructsCollection, error) { + collection, isPresent := collectionsCache.GetCollection(collectionId) + if !isPresent { + return bindings.StructsCollection{}, errors.New("collection not present in cache") } if !collection.Active { return bindings.StructsCollection{}, errors.New("collection inactive") @@ -253,7 +253,7 @@ func (*UtilsStruct) GetActiveCollection(client *ethclient.Client, collectionId u return collection, nil } -func (*UtilsStruct) GetDataToCommitFromJobs(jobs []bindings.StructsJob, localCache *cache.LocalCache) ([]*big.Int, []uint8) { +func (*UtilsStruct) GetDataToCommitFromJobs(jobs []bindings.StructsJob, commitParams *types.CommitParams) ([]*big.Int, []uint8) { var ( wg sync.WaitGroup mu sync.Mutex @@ -263,7 +263,7 @@ func (*UtilsStruct) GetDataToCommitFromJobs(jobs []bindings.StructsJob, localCac for _, job := range jobs { wg.Add(1) - go processJobConcurrently(&wg, &mu, &data, &weight, job, localCache) + go processJobConcurrently(&wg, &mu, &data, &weight, job, commitParams) } wg.Wait() @@ -271,10 +271,10 @@ func (*UtilsStruct) GetDataToCommitFromJobs(jobs []bindings.StructsJob, localCac return data, weight } -func processJobConcurrently(wg *sync.WaitGroup, mu *sync.Mutex, data *[]*big.Int, weight *[]uint8, job bindings.StructsJob, localCache *cache.LocalCache) { +func processJobConcurrently(wg *sync.WaitGroup, mu *sync.Mutex, data *[]*big.Int, weight *[]uint8, job bindings.StructsJob, commitParams *types.CommitParams) { defer wg.Done() - dataToAppend, err := UtilsInterface.GetDataToCommitFromJob(job, localCache) + dataToAppend, err := UtilsInterface.GetDataToCommitFromJob(job, commitParams) if err != nil { return } @@ -286,9 +286,12 @@ func processJobConcurrently(wg *sync.WaitGroup, mu *sync.Mutex, data *[]*big.Int *weight = append(*weight, job.Weight) } -func (*UtilsStruct) GetDataToCommitFromJob(job bindings.StructsJob, localCache *cache.LocalCache) (*big.Int, error) { - var dataSourceURLStruct types.DataSourceURL - +func (*UtilsStruct) GetDataToCommitFromJob(job bindings.StructsJob, commitParams *types.CommitParams) (*big.Int, error) { + var ( + response []byte + apiErr error + dataSourceURLStruct types.DataSourceURL + ) log.Debugf("Job ID: %d, Getting the data to commit for job %s", job.Id, job.Name) if isJSONCompatible(job.Url) { log.Debugf("Job ID: %d, Job URL passed is a struct containing URL along with type of request data", job.Id) @@ -318,7 +321,7 @@ func (*UtilsStruct) GetDataToCommitFromJob(job bindings.StructsJob, localCache * var parsedData interface{} if job.SelectorType == 0 { start := time.Now() - response, apiErr := GetDataFromAPI(dataSourceURLStruct, localCache) + response, apiErr = GetDataFromAPI(commitParams, dataSourceURLStruct) if apiErr != nil { log.Errorf("Job ID: %d, Error in fetching data from API %s: %v", job.Id, job.Url, apiErr) return nil, apiErr @@ -483,7 +486,7 @@ func ConvertCustomJobToStructJob(customJob types.CustomJob) bindings.StructsJob } } -func (*UtilsStruct) HandleOfficialJobsFromJSONFile(client *ethclient.Client, collection bindings.StructsCollection, dataString string) ([]bindings.StructsJob, []uint16) { +func (*UtilsStruct) HandleOfficialJobsFromJSONFile(client *ethclient.Client, collection bindings.StructsCollection, dataString string, commitParams *types.CommitParams) ([]bindings.StructsJob, []uint16) { var overrideJobs []bindings.StructsJob var overriddenJobIds []uint16 @@ -496,8 +499,9 @@ func (*UtilsStruct) HandleOfficialJobsFromJSONFile(client *ethclient.Client, col if officialJobsJSONResult.Exists() { officialJobs := officialJobsJSONResult.String() if officialJobs != "" { - job, err := UtilsInterface.GetActiveJob(client, jobIds[i]) - if err != nil { + job, isPresent := commitParams.JobsCache.GetJob(jobIds[i]) + if !isPresent { + log.Errorf("Job with id %v is not present in cache", jobIds[i]) continue } log.Debugf("Overriding job %s having jobId %d from official job present in assets.json file...", job.Url, job.Id) @@ -528,6 +532,54 @@ func (*UtilsStruct) HandleOfficialJobsFromJSONFile(client *ethclient.Client, col return overrideJobs, overriddenJobIds } +// InitJobsCache initializes the jobs cache with data fetched from the blockchain +func InitJobsCache(client *ethclient.Client, jobsCache *cache.JobsCache) error { + jobsCache.Mu.Lock() + defer jobsCache.Mu.Unlock() + + // Flush the jobsCache before initialization + for k := range jobsCache.Jobs { + delete(jobsCache.Jobs, k) + } + + numJobs, err := AssetManagerInterface.GetNumJobs(client) + if err != nil { + return err + } + for i := 1; i <= int(numJobs); i++ { + job, err := UtilsInterface.GetActiveJob(client, uint16(i)) + if err != nil { + return err + } + jobsCache.Jobs[job.Id] = job + } + return nil +} + +// InitCollectionsCache initializes the collections cache with data fetched from the blockchain +func InitCollectionsCache(client *ethclient.Client, collectionsCache *cache.CollectionsCache) error { + collectionsCache.Mu.Lock() + defer collectionsCache.Mu.Unlock() + + // Flush the collectionsCache before initialization + for k := range collectionsCache.Collections { + delete(collectionsCache.Collections, k) + } + + numCollections, err := AssetManagerInterface.GetNumCollections(client) + if err != nil { + return err + } + for i := 1; i <= int(numCollections); i++ { + collection, err := AssetManagerInterface.GetCollection(client, uint16(i)) + if err != nil { + return err + } + collectionsCache.Collections[collection.Id] = collection + } + return nil +} + func ReplaceValueWithDataFromENVFile(re *regexp.Regexp, value string) string { // substrings denotes all the occurrences of substring which satisfies APIKeyRegex substrings := re.FindAllString(value, -1) diff --git a/utils/asset_test.go b/utils/asset_test.go index 7651bd8c8..e45bf8314 100644 --- a/utils/asset_test.go +++ b/utils/asset_test.go @@ -5,6 +5,7 @@ import ( "fmt" "io/fs" "math/big" + "net/http" "os" "razor/cache" "razor/core" @@ -25,11 +26,18 @@ import ( ) func TestAggregate(t *testing.T) { - var client *ethclient.Client - var previousEpoch uint32 - var fileInfo fs.FileInfo + var ( + client *ethclient.Client + previousEpoch uint32 + fileInfo fs.FileInfo + ) - job := bindings.StructsJob{Id: 1, SelectorType: 1, Weight: 100, + job1 := bindings.StructsJob{Id: 1, SelectorType: 1, Weight: 100, + Power: 2, Name: "ethusd_gemini", Selector: "last", + Url: "https://api.gemini.com/v1/pubticker/ethusd", + } + + job2 := bindings.StructsJob{Id: 2, SelectorType: 1, Weight: 100, Power: 2, Name: "ethusd_gemini", Selector: "last", Url: "https://api.gemini.com/v1/pubticker/ethusd", } @@ -39,14 +47,13 @@ func TestAggregate(t *testing.T) { Id: 4, Power: 2, AggregationMethod: 2, - JobIDs: []uint16{1, 2, 3}, + JobIDs: []uint16{1, 2}, Name: "ethCollectionMean", } type args struct { collection bindings.StructsCollection - activeJob bindings.StructsJob - activeJobErr error + jobCacheError bool dataToCommit []*big.Int dataToCommitErr error weight []uint8 @@ -72,21 +79,20 @@ func TestAggregate(t *testing.T) { name: "Test 1: When Aggregate() executes successfully", args: args{ collection: collection, - activeJob: job, - dataToCommit: []*big.Int{big.NewInt(3827200), big.NewInt(3828474), big.NewInt(3826440), big.NewInt(3824616), big.NewInt(3823852)}, - weight: []uint8{1, 1, 1, 1, 1}, + dataToCommit: []*big.Int{big.NewInt(3827200), big.NewInt(3828474)}, + weight: []uint8{1, 1}, prevCommitmentData: big.NewInt(1), assetFilePath: "", statErr: nil, }, - want: big.NewInt(3826116), + want: big.NewInt(3827837), wantErr: false, }, { - name: "Test 2: When there is an error in getting activeJob", + name: "Test 2: When the job is not present in cache", args: args{ collection: collection, - activeJobErr: errors.New("activeJob error"), + jobCacheError: true, dataToCommit: []*big.Int{big.NewInt(2)}, weight: []uint8{100}, prevCommitmentData: big.NewInt(1), @@ -100,7 +106,6 @@ func TestAggregate(t *testing.T) { name: "Test 3: When there is an error in getting dataToCommit", args: args{ collection: collection, - activeJob: job, dataToCommitErr: errors.New("dataToCommit error"), weight: []uint8{100}, prevCommitmentData: big.NewInt(1), @@ -112,7 +117,6 @@ func TestAggregate(t *testing.T) { name: "Test 4: When there is an error in getting prevCommitmentData", args: args{ collection: collection, - activeJob: job, dataToCommit: []*big.Int{big.NewInt(2)}, weight: []uint8{100}, prevCommitmentDataErr: errors.New("prevCommitmentData error"), @@ -124,7 +128,6 @@ func TestAggregate(t *testing.T) { name: "Test 5: When there is an error in getting prevCommitmentData", args: args{ collection: collection, - activeJob: job, dataToCommitErr: errors.New("dataToCommit error"), weight: []uint8{100}, prevCommitmentDataErr: errors.New("prevCommitmentData error"), @@ -172,6 +175,16 @@ func TestAggregate(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { + commitParams := &types.CommitParams{ + JobsCache: cache.NewJobsCache(), + CollectionsCache: cache.NewCollectionsCache(), + } + if !tt.args.jobCacheError { + commitParams.JobsCache.Jobs[job1.Id] = job1 + commitParams.JobsCache.Jobs[job2.Id] = job2 + commitParams.CollectionsCache.Collections[collection.Id] = collection + } + utilsMock := new(mocks.Utils) pathUtilsMock := new(pathMocks.PathInterface) osUtilsMock := new(pathMocks.OSInterface) @@ -185,16 +198,16 @@ func TestAggregate(t *testing.T) { path.OSUtilsInterface = osUtilsMock utils := StartRazor(optionsPackageStruct) - utilsMock.On("GetActiveJob", mock.AnythingOfType("*ethclient.Client"), mock.AnythingOfType("uint16")).Return(tt.args.activeJob, tt.args.activeJobErr) - utilsMock.On("GetDataToCommitFromJobs", mock.Anything, mock.Anything).Return(tt.args.dataToCommit, tt.args.weight, tt.args.dataToCommitErr) + utilsMock.On("GetDataToCommitFromJobs", mock.Anything, mock.Anything, mock.Anything).Return(tt.args.dataToCommit, tt.args.weight, tt.args.dataToCommitErr) utilsMock.On("FetchPreviousValue", mock.AnythingOfType("*ethclient.Client"), mock.AnythingOfType("uint32"), mock.AnythingOfType("uint16")).Return(tt.args.prevCommitmentData, tt.args.prevCommitmentDataErr) pathUtilsMock.On("GetJobFilePath").Return(tt.args.assetFilePath, tt.args.assetFilePathErr) osUtilsMock.On("Stat", mock.Anything).Return(fileInfo, tt.args.statErr) osUtilsMock.On("Open", mock.Anything).Return(tt.args.jsonFile, tt.args.jsonFileErr) ioMock.On("ReadAll", mock.Anything).Return(tt.args.fileData, tt.args.fileDataErr) - utilsMock.On("HandleOfficialJobsFromJSONFile", mock.Anything, mock.Anything, mock.Anything).Return(tt.args.overrrideJobs, tt.args.overrideJobIds) + utilsMock.On("HandleOfficialJobsFromJSONFile", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(tt.args.overrrideJobs, tt.args.overrideJobIds) + + got, err := utils.Aggregate(client, previousEpoch, tt.args.collection, commitParams) - got, err := utils.Aggregate(client, previousEpoch, tt.args.collection, &cache.LocalCache{}) if (err != nil) != tt.wantErr { t.Errorf("Aggregate() error = %v, wantErr %v", err, tt.wantErr) return @@ -267,24 +280,21 @@ func TestGetActiveCollectionIds(t *testing.T) { } func TestGetActiveCollection(t *testing.T) { - var client *ethclient.Client - var collectionId uint16 - - collectionEth := bindings.StructsCollection{Active: true, - Id: 2, - Power: 2, - AggregationMethod: 2, - JobIDs: []uint16{1, 2}, - Name: "ethCollectionMean", + collectionEth := bindings.StructsCollection{ + Active: true, Id: 1, Power: 2, + AggregationMethod: 2, JobIDs: []uint16{1, 2}, + Name: "ethCollectionMean", } - collectionEthInactive := bindings.StructsCollection{Active: false, Id: 2, Power: 2, - AggregationMethod: 2, JobIDs: []uint16{1, 2}, Name: "ethCollectionMean", + collectionEthInactive := bindings.StructsCollection{ + Active: false, Id: 2, Power: 2, + AggregationMethod: 2, JobIDs: []uint16{1, 2}, + Name: "ethCollectionMean", } type args struct { - collection bindings.StructsCollection - collectionErr error + collectionId uint16 + collectionCacheErr bool } tests := []struct { name string @@ -295,15 +305,15 @@ func TestGetActiveCollection(t *testing.T) { { name: "Test 1: When GetActiveCollection() executes successfully", args: args{ - collection: collectionEth, + collectionId: 1, }, want: collectionEth, wantErr: false, }, { - name: "Test 2: When there is an error in getting collection", + name: "Test 2: When the collection is not present in cache", args: args{ - collectionErr: errors.New("collection error"), + collectionCacheErr: true, }, want: bindings.StructsCollection{}, wantErr: true, @@ -311,7 +321,7 @@ func TestGetActiveCollection(t *testing.T) { { name: "Test 3: When there is an inactive collection", args: args{ - collection: collectionEthInactive, + collectionId: 2, }, want: bindings.StructsCollection{}, wantErr: true, @@ -319,16 +329,12 @@ func TestGetActiveCollection(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - utilsMock := new(mocks.Utils) + collectionCache := cache.NewCollectionsCache() + collectionCache.Collections[collectionEth.Id] = collectionEth + collectionCache.Collections[collectionEthInactive.Id] = collectionEthInactive - optionsPackageStruct := OptionsPackageStruct{ - UtilsInterface: utilsMock, - } - utils := StartRazor(optionsPackageStruct) - - utilsMock.On("GetCollection", mock.AnythingOfType("*ethclient.Client"), mock.AnythingOfType("uint16")).Return(tt.args.collection, tt.args.collectionErr) - - got, err := utils.GetActiveCollection(client, collectionId) + utils := UtilsStruct{} + got, err := utils.GetActiveCollection(collectionCache, tt.args.collectionId) if (err != nil) != tt.wantErr { t.Errorf("GetActiveCollection() error = %v, wantErr %v", err, tt.wantErr) return @@ -553,6 +559,14 @@ func TestGetAllCollections(t *testing.T) { } func TestGetDataToCommitFromJobs(t *testing.T) { + httpClient := &http.Client{ + Timeout: 10 * time.Second, + Transport: &http.Transport{ + MaxIdleConns: 2, + MaxIdleConnsPerHost: 1, + }, + } + jobsArray := []bindings.StructsJob{ {Id: 1, SelectorType: 0, Weight: 10, Power: 2, Name: "ethusd_gemini", Selector: "last", @@ -629,9 +643,12 @@ func TestGetDataToCommitFromJobs(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { UtilsInterface = &UtilsStruct{} - lc := cache.NewLocalCache(time.Second * 10) + commitParams := &types.CommitParams{ + LocalCache: cache.NewLocalCache(time.Second * 10), + HttpClient: httpClient, + } - gotDataArray, gotWeightArray := UtilsInterface.GetDataToCommitFromJobs(tt.args.jobs, lc) + gotDataArray, gotWeightArray := UtilsInterface.GetDataToCommitFromJobs(tt.args.jobs, commitParams) if len(gotDataArray) != tt.wantArrayLength || len(gotWeightArray) != tt.wantArrayLength { t.Errorf("GetDataToCommitFromJobs() got = %v, want %v", gotDataArray, tt.wantArrayLength) } @@ -642,6 +659,14 @@ func TestGetDataToCommitFromJobs(t *testing.T) { } func TestGetDataToCommitFromJob(t *testing.T) { + httpClient := &http.Client{ + Timeout: 10 * time.Second, + Transport: &http.Transport{ + MaxIdleConns: 2, + MaxIdleConnsPerHost: 1, + }, + } + job := bindings.StructsJob{Id: 1, SelectorType: 0, Weight: 100, Power: 2, Name: "ethusd_kraken", Selector: "result.XETHZUSD.c[0]", Url: `{"type": "GET","url": "https://api.kraken.com/0/public/Ticker?pair=ETHUSD","body": {},"header": {}}`, @@ -761,8 +786,12 @@ func TestGetDataToCommitFromJob(t *testing.T) { } utils := StartRazor(optionsPackageStruct) - lc := cache.NewLocalCache(time.Second * 10) - data, err := utils.GetDataToCommitFromJob(tt.args.job, lc) + commitParams := &types.CommitParams{ + LocalCache: cache.NewLocalCache(time.Second * 10), + HttpClient: httpClient, + } + + data, err := utils.GetDataToCommitFromJob(tt.args.job, commitParams) fmt.Println("JOB returns data: ", data) if (err != nil) != tt.wantErr { t.Errorf("GetDataToCommitFromJob() error = %v, wantErr %v", err, tt.wantErr) @@ -1093,14 +1122,23 @@ func TestHandleOfficialJobsFromJSONFile(t *testing.T) { ethCollection1 := bindings.StructsCollection{ Active: true, Id: 7, Power: 2, - AggregationMethod: 2, JobIDs: []uint16{1, 2, 3}, Name: "ethCollection", + AggregationMethod: 2, JobIDs: []uint16{1, 2}, Name: "ethCollection", + } + + job1 := bindings.StructsJob{Id: 1, SelectorType: 0, Weight: 0, + Power: 2, Name: "ethusd_kucoin", Selector: "last", + Url: "http://kucoin.com/eth", + } + + job2 := bindings.StructsJob{Id: 2, SelectorType: 0, Weight: 2, + Power: 3, Name: "ethusd_coinbase", Selector: "eth2", + Url: "http://api.coinbase.com/eth", } type args struct { - collection bindings.StructsCollection - dataString string - job bindings.StructsJob - jobErr error + collection bindings.StructsCollection + dataString string + addJobToCache bool } tests := []struct { name string @@ -1111,19 +1149,19 @@ func TestHandleOfficialJobsFromJSONFile(t *testing.T) { { name: "Test 1: When officialJobs for collection is present in assets.json", args: args{ - collection: ethCollection, - dataString: jsonDataString, - job: bindings.StructsJob{ - Id: 1, - }, + collection: ethCollection, + dataString: jsonDataString, + addJobToCache: true, }, want: []bindings.StructsJob{ { - Id: 1, - Url: "http://kucoin.com/eth1", - Selector: "eth1", - Power: 2, - Weight: 2, + Id: 1, + SelectorType: 0, + Name: "ethusd_kucoin", + Url: "http://kucoin.com/eth1", + Selector: "eth1", + Power: 2, + Weight: 2, }, }, wantOverrideJobIds: []uint16{1}, @@ -1133,9 +1171,6 @@ func TestHandleOfficialJobsFromJSONFile(t *testing.T) { args: args{ collection: ethCollection, dataString: "", - job: bindings.StructsJob{ - Id: 1, - }, }, want: nil, wantOverrideJobIds: nil, @@ -1143,9 +1178,9 @@ func TestHandleOfficialJobsFromJSONFile(t *testing.T) { { name: "Test 3: When there is an error from GetActiveJob()", args: args{ - collection: ethCollection, - dataString: jsonDataString, - jobErr: errors.New("job error"), + collection: ethCollection, + dataString: jsonDataString, + addJobToCache: false, }, want: nil, wantOverrideJobIds: nil, @@ -1153,26 +1188,22 @@ func TestHandleOfficialJobsFromJSONFile(t *testing.T) { { name: "Test 4: When multiple jobIds are needed to be overridden from official jobs", args: args{ - collection: ethCollection1, - dataString: jsonDataString, - job: bindings.StructsJob{ - Id: 1, - Url: "http://kraken.com/eth1", - Selector: "data.ETH", - Power: 3, - Weight: 1, - }, + collection: ethCollection1, + dataString: jsonDataString, + addJobToCache: true, }, want: []bindings.StructsJob{ { Id: 1, + Name: "ethusd_kucoin", Url: "http://kucoin.com/eth1", Selector: "eth1", Power: 2, Weight: 2, }, { - Id: 1, + Id: 2, + Name: "ethusd_coinbase", Url: "http://api.coinbase.com/eth2", Selector: "eth2", Power: 3, @@ -1184,15 +1215,17 @@ func TestHandleOfficialJobsFromJSONFile(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - utilsMock := new(mocks.Utils) - utilsMock.On("GetActiveJob", mock.AnythingOfType("*ethclient.Client"), mock.AnythingOfType("uint16")).Return(tt.args.job, tt.args.jobErr) - - optionsPackageStruct := OptionsPackageStruct{ - UtilsInterface: utilsMock, + commitParams := &types.CommitParams{ + JobsCache: cache.NewJobsCache(), } - utils := StartRazor(optionsPackageStruct) + if tt.args.addJobToCache { + commitParams.JobsCache.Jobs[job1.Id] = job1 + commitParams.JobsCache.Jobs[job2.Id] = job2 + } + + utils := &UtilsStruct{} - gotJobs, gotOverrideJobIds := utils.HandleOfficialJobsFromJSONFile(client, tt.args.collection, tt.args.dataString) + gotJobs, gotOverrideJobIds := utils.HandleOfficialJobsFromJSONFile(client, tt.args.collection, tt.args.dataString, commitParams) if !reflect.DeepEqual(gotJobs, tt.want) { t.Errorf("HandleOfficialJobsFromJSONFile() gotJobs = %v, want %v", gotJobs, tt.want) } @@ -1295,9 +1328,9 @@ func TestGetAggregatedDataOfCollection(t *testing.T) { utils := StartRazor(optionsPackageStruct) utilsMock.On("GetActiveCollection", mock.Anything, mock.Anything).Return(tt.args.activeCollection, tt.args.activeCollectionErr) - utilsMock.On("Aggregate", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(tt.args.collectionData, tt.args.aggregationErr) + utilsMock.On("Aggregate", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(tt.args.collectionData, tt.args.aggregationErr) - got, err := utils.GetAggregatedDataOfCollection(client, collectionId, epoch, &cache.LocalCache{}) + got, err := utils.GetAggregatedDataOfCollection(client, collectionId, epoch, &types.CommitParams{HttpClient: &http.Client{}}) if (err != nil) != tt.wantErr { t.Errorf("GetAggregatedDataOfCollection() error = %v, wantErr %v", err, tt.wantErr) return diff --git a/utils/batch.go b/utils/batch.go new file mode 100644 index 000000000..a7a5bfdbc --- /dev/null +++ b/utils/batch.go @@ -0,0 +1,132 @@ +package utils + +import ( + "context" + "errors" + "fmt" + "github.com/avast/retry-go" + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/ethclient" + "github.com/ethereum/go-ethereum/rpc" + "razor/core" +) + +//Each batch call may require multiple arguments therefore defining args as [][]interface{} + +// BatchCall performs a batch call to the Ethereum client, using the provided contract ABI, address, method name, and arguments. +func (c ClientStruct) BatchCall(client *ethclient.Client, contractABI *abi.ABI, contractAddress, methodName string, args [][]interface{}) ([][]interface{}, error) { + calls, err := ClientInterface.CreateBatchCalls(contractABI, contractAddress, methodName, args) + if err != nil { + log.Errorf("Error in creating batch calls: %v", err) + return nil, err + } + + err = performBatchCallWithRetry(client, calls) + if err != nil { + log.Errorf("Error in performing batch call: %v", err) + return nil, err + } + + results, err := processBatchResults(contractABI, methodName, calls) + if err != nil { + log.Errorf("Error in processing batch call result: %v", err) + return nil, err + } + + return results, nil +} + +// CreateBatchCalls creates a slice of rpc.BatchElem, each representing an Ethereum call, using the provided ABI, contract address, method name, and arguments. +func (c ClientStruct) CreateBatchCalls(contractABI *abi.ABI, contractAddress, methodName string, args [][]interface{}) ([]rpc.BatchElem, error) { + var calls []rpc.BatchElem + + for _, arg := range args { + data, err := contractABI.Pack(methodName, arg...) + if err != nil { + log.Errorf("Failed to pack data for method %s: %v", methodName, err) + return nil, err + } + + calls = append(calls, rpc.BatchElem{ + Method: "eth_call", + Args: []interface{}{ + map[string]interface{}{ + "to": contractAddress, + "data": fmt.Sprintf("0x%x", data), + }, + "latest", + }, + Result: new(string), + }) + } + return calls, nil +} + +func (c ClientStruct) PerformBatchCall(client *ethclient.Client, calls []rpc.BatchElem) error { + err := client.Client().BatchCallContext(context.Background(), calls) + if err != nil { + return err + } + return nil +} + +// performBatchCallWithRetry performs the batch call to the Ethereum client with retry logic. +func performBatchCallWithRetry(client *ethclient.Client, calls []rpc.BatchElem) error { + err := retry.Do(func() error { + err := ClientInterface.PerformBatchCall(client, calls) + if err != nil { + log.Errorf("Error in performing batch call, retrying: %v", err) + return err + } + for _, call := range calls { + if call.Error != nil { + log.Errorf("Error in call result: %v", call.Error) + return call.Error + } + } + return nil + }, retry.Attempts(core.MaxRetries)) + + if err != nil { + log.Errorf("All attempts failed to perform batch call: %v", err) + return err + } + + return nil +} + +// processBatchResults processes the results of the batch call, unpacking the data using the provided ABI and method name. +func processBatchResults(contractABI *abi.ABI, methodName string, calls []rpc.BatchElem) ([][]interface{}, error) { + var results [][]interface{} + + for _, call := range calls { + if call.Error != nil { + log.Errorf("Error in call result: %v", call.Error) + return nil, call.Error + } + + result, ok := call.Result.(*string) + if !ok { + log.Error("Failed to type assert call result to *string") + return nil, errors.New("type asserting of batch call result error") + } + + if result == nil || *result == "" { + return nil, errors.New("empty batch call result") + } + + data := common.FromHex(*result) + if len(data) == 0 { + return nil, errors.New("empty hex data") + } + + unpackedData, err := contractABI.Unpack(methodName, data) + if err != nil { + return nil, errors.New("unpacking data error") + } + + results = append(results, unpackedData) + } + return results, nil +} diff --git a/utils/batch_test.go b/utils/batch_test.go new file mode 100644 index 000000000..00cdbc40b --- /dev/null +++ b/utils/batch_test.go @@ -0,0 +1,202 @@ +package utils + +import ( + "errors" + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/ethclient" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/mock" + "math/big" + "razor/core" + "razor/pkg/bindings" + "razor/utils/mocks" + "strings" + "testing" +) + +func TestBatchCall(t *testing.T) { + //Testing Batch call scenario for getting StakeSnapshot + var client *ethclient.Client + + voteManagerABI, _ := abi.JSON(strings.NewReader(bindings.VoteManagerMetaData.ABI)) + stakeManagerABI, _ := abi.JSON(strings.NewReader(bindings.StakeManagerMetaData.ABI)) + numberOfArguments := 3 + + type args struct { + contractABI *abi.ABI + contractAddress string + methodName string + createBatchCallsErr error + performBatchCallErr error + results []interface{} + callErrors []error + } + tests := []struct { + name string + args args + want [][]interface{} + wantErr bool + }{ + { + name: "Test 1: When batch call executes successfully", + args: args{ + contractABI: &voteManagerABI, + contractAddress: core.VoteManagerAddress, + methodName: core.GetStakeSnapshotMethod, + results: []interface{}{ + ptrString("0x000000000000000000000000000000000000000000000000000000000000000a"), + ptrString("0x000000000000000000000000000000000000000000000000000000000000000b"), + ptrString("0x000000000000000000000000000000000000000000000000000000000000000c"), + }, + callErrors: []error{nil, nil, nil}, + }, + want: [][]interface{}{ + {big.NewInt(10)}, + {big.NewInt(11)}, + {big.NewInt(12)}, + }, + wantErr: false, + }, + { + name: "Test 2: When one of batch calls throw an error", + args: args{ + contractABI: &voteManagerABI, + contractAddress: core.VoteManagerAddress, + methodName: core.GetStakeSnapshotMethod, + results: []interface{}{ + nil, + ptrString("0x000000000000000000000000000000000000000000000000000000000000000b"), + ptrString("0x000000000000000000000000000000000000000000000000000000000000000c"), + }, + callErrors: []error{errors.New("batch call error"), nil, nil}, + }, + want: nil, + wantErr: true, + }, + { + name: "Test 3: When BatchCalls receives an result of invalid type which cannot be type asserted to *string", + args: args{ + contractABI: &voteManagerABI, + contractAddress: core.VoteManagerAddress, + methodName: core.GetStakeSnapshotMethod, + results: []interface{}{ + 42, // intentionally incorrect data type, + ptrString("0x000000000000000000000000000000000000000000000000000000000000000b"), + ptrString("0x000000000000000000000000000000000000000000000000000000000000000c"), + }, + callErrors: []error{nil, nil, nil}, + }, + want: nil, + wantErr: true, + }, + { + name: "Test 4: When BatchCalls receives a nil result (empty batch call result error)", + args: args{ + contractABI: &voteManagerABI, + contractAddress: core.VoteManagerAddress, + methodName: core.GetStakeSnapshotMethod, + results: []interface{}{ + nil, + nil, + ptrString("0x000000000000000000000000000000000000000000000000000000000000000b"), + }, + callErrors: []error{nil, nil, nil}, + }, + want: nil, + wantErr: true, + }, + { + name: "Test 5: When BatchCalls receives an empty result (empty hex data error)", + args: args{ + contractABI: &voteManagerABI, + contractAddress: core.VoteManagerAddress, + methodName: core.GetStakeSnapshotMethod, + results: []interface{}{ + ptrString("0x"), + ptrString("0x000000000000000000000000000000000000000000000000000000000000000b"), + ptrString("0x000000000000000000000000000000000000000000000000000000000000000c"), + }, + callErrors: []error{nil, nil, nil}, + }, + want: nil, + wantErr: true, + }, + { + name: "Test 6: When incorrect ABI is provided for unpacking", + args: args{ + contractABI: &stakeManagerABI, + contractAddress: core.VoteManagerAddress, + methodName: core.GetStakeSnapshotMethod, + results: []interface{}{ + ptrString("0x000000000000000000000000000000000000000000000000000000000000000a"), + ptrString("0x000000000000000000000000000000000000000000000000000000000000000b"), + ptrString("0x000000000000000000000000000000000000000000000000000000000000000c"), + }, + callErrors: []error{nil, nil, nil}, + }, + want: nil, + wantErr: true, + }, + { + name: "Test 7: When there is an error in creating batch calls", + args: args{ + contractABI: &voteManagerABI, + contractAddress: core.VoteManagerAddress, + methodName: core.GetStakeSnapshotMethod, + createBatchCallsErr: errors.New("create batch calls error"), + }, + want: nil, + wantErr: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + var stakerIds []uint32 + for i := 1; i <= numberOfArguments; i++ { + stakerIds = append(stakerIds, uint32(i)) + } + + arguments := make([][]interface{}, len(stakerIds)) + for i, stakerId := range stakerIds { + arguments[i] = []interface{}{uint32(100), stakerId} + } + + ClientInterface = &ClientStruct{} + calls, err := ClientInterface.CreateBatchCalls(tt.args.contractABI, tt.args.contractAddress, tt.args.methodName, arguments) + if err != nil { + log.Error("Error in creating batch calls: ", err) + return + } + // Mock batch call responses + for i, result := range tt.args.results { + if result != nil { + calls[i].Result = result + } + calls[i].Error = tt.args.callErrors[i] + } + clientMock := new(mocks.ClientUtils) + optionsPackageStruct := OptionsPackageStruct{ + ClientInterface: clientMock, + } + + StartRazor(optionsPackageStruct) + + clientMock.On("CreateBatchCalls", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(calls, tt.args.createBatchCallsErr) + clientMock.On("PerformBatchCall", mock.Anything, mock.Anything).Return(tt.args.performBatchCallErr) + + c := ClientStruct{} + gotResults, err := c.BatchCall(client, tt.args.contractABI, tt.args.contractAddress, tt.args.methodName, arguments) + if (err != nil) != tt.wantErr { + t.Errorf("BatchCall() error = %v, but wantErr bool is %v", err, tt.wantErr) + return + } + if !assert.Equal(t, gotResults, tt.want) { + t.Errorf("BatchCall() got = %v, want %v", gotResults, tt.want) + } + }) + } +} + +func ptrString(s string) *string { + return &s +} diff --git a/utils/common.go b/utils/common.go index 164c3a74a..3167e77ce 100644 --- a/utils/common.go +++ b/utils/common.go @@ -3,9 +3,11 @@ package utils import ( "context" "errors" + Types "github.com/ethereum/go-ethereum/core/types" "math/big" "os" "path/filepath" + "razor/accounts" "razor/core" "razor/core/types" "razor/logger" @@ -51,21 +53,17 @@ func (*UtilsStruct) FetchBalance(client *ethclient.Client, accountAddress string return balance, nil } -func (*UtilsStruct) GetBufferedState(client *ethclient.Client, buffer int32) (int64, error) { - block, err := ClientInterface.GetLatestBlockWithRetry(client) - if err != nil { - return -1, err - } +func (*UtilsStruct) GetBufferedState(client *ethclient.Client, header *Types.Header, buffer int32) (int64, error) { stateBuffer, err := UtilsInterface.GetStateBuffer(client) if err != nil { return -1, err } lowerLimit := (core.StateLength * uint64(buffer)) / 100 upperLimit := core.StateLength - (core.StateLength*uint64(buffer))/100 - if block.Time%(core.StateLength) > upperLimit-stateBuffer || block.Time%(core.StateLength) < lowerLimit+stateBuffer { + if header.Time%(core.StateLength) > upperLimit-stateBuffer || header.Time%(core.StateLength) < lowerLimit+stateBuffer { return -1, nil } - state := block.Time / core.StateLength + state := header.Time / core.StateLength return int64(state % core.NumberOfStates), nil } @@ -379,14 +377,8 @@ func (*FileStruct) ReadFromDisputeJsonFile(filePath string) (types.DisputeFileDa return disputeData, nil } -func (*UtilsStruct) CheckPassword(address string, password string) error { - razorPath, err := PathInterface.GetDefaultPath() - if err != nil { - log.Error("CheckPassword: Error in getting .razor path: ", err) - return err - } - keystorePath := filepath.Join(razorPath, "keystore_files") - _, err = AccountsInterface.GetPrivateKey(address, password, keystorePath) +func (*UtilsStruct) CheckPassword(account types.Account) error { + _, err := account.AccountManager.GetPrivateKey(account.Address, account.Password) if err != nil { log.Info("Kindly check your password!") log.Error("CheckPassword: Error in getting private key: ", err) @@ -394,3 +386,15 @@ func (*UtilsStruct) CheckPassword(address string, password string) error { } return nil } + +func (*UtilsStruct) AccountManagerForKeystore() (types.AccountManagerInterface, error) { + razorPath, err := PathInterface.GetDefaultPath() + if err != nil { + log.Error("GetKeystorePath: Error in getting .razor path: ", err) + return nil, err + } + keystorePath := filepath.Join(razorPath, "keystore_files") + + accountManager := accounts.NewAccountManager(keystorePath) + return accountManager, nil +} diff --git a/utils/common_test.go b/utils/common_test.go index f2cb12a59..4ab53a83b 100644 --- a/utils/common_test.go +++ b/utils/common_test.go @@ -4,6 +4,7 @@ import ( "errors" "math/big" "os" + "razor/accounts" Types "razor/core/types" "razor/pkg/bindings" "razor/utils/mocks" @@ -365,7 +366,6 @@ func TestGetBufferedState(t *testing.T) { type args struct { block *types.Header - blockErr error buffer int32 stateBuffer uint64 stateBufferErr error @@ -386,22 +386,11 @@ func TestGetBufferedState(t *testing.T) { stateBuffer: 5, }, - want: 1, + want: 0, wantErr: false, }, { - name: "Test 2: When there is an error in getting block", - args: args{ - block: &types.Header{ - Number: big.NewInt(100), - }, - blockErr: errors.New("block error"), - }, - want: -1, - wantErr: true, - }, - { - name: "Test 3: When blockNumber%(core.StateLength) is greater than lowerLimit", + name: "Test 2: When blockNumber%(core.StateLength) is greater than lowerLimit", args: args{ block: &types.Header{ Time: 1080, @@ -409,11 +398,11 @@ func TestGetBufferedState(t *testing.T) { buffer: 2, stateBuffer: 5, }, - want: -1, + want: 4, wantErr: false, }, { - name: "Test 4: When GetBufferedState() executes successfully and state we get is other than 0", + name: "Test 3: When GetBufferedState() executes successfully and state we get is other than 0", args: args{ block: &types.Header{ Time: 900, @@ -422,11 +411,11 @@ func TestGetBufferedState(t *testing.T) { stateBuffer: 5, }, - want: -1, + want: 3, wantErr: false, }, { - name: "Test 5: When there is an error in getting stateBuffer", + name: "Test 4: When there is an error in getting stateBuffer", args: args{ block: &types.Header{ Time: 100, @@ -453,9 +442,8 @@ func TestGetBufferedState(t *testing.T) { utils := StartRazor(optionsPackageStruct) utilsMock.On("GetStateBuffer", mock.AnythingOfType("*ethclient.Client")).Return(tt.args.stateBuffer, tt.args.stateBufferErr) - clientUtilsMock.On("GetLatestBlockWithRetry", mock.AnythingOfType("*ethclient.Client")).Return(tt.args.block, tt.args.blockErr) - got, err := utils.GetBufferedState(client, tt.args.buffer) + got, err := utils.GetBufferedState(client, tt.args.block, tt.args.buffer) if (err != nil) != tt.wantErr { t.Errorf("GetBufferedState() error = %v, wantErr %v", err, tt.wantErr) return @@ -971,7 +959,7 @@ func TestGetRemainingTimeOfCurrentState(t *testing.T) { block: &types.Header{}, stateBuffer: 5, }, - want: 55, + want: 235, wantErr: false, }, { @@ -1098,7 +1086,7 @@ func TestEstimateBlockNumberAtEpochBeginning(t *testing.T) { block: &types.Header{Time: 1, Number: big.NewInt(1)}, previousBlock: &types.Header{Time: 20, Number: big.NewInt(1)}, }, - want: big.NewInt(-59), + want: big.NewInt(-239), wantErr: false, }, { @@ -1559,3 +1547,101 @@ func TestReadFromDisputeJsonFile(t *testing.T) { }) } } + +func TestUtilsStruct_CheckPassword(t *testing.T) { + type args struct { + account Types.Account + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "Test 1: When password is correct", + args: args{ + account: Types.Account{ + Address: "0x57Baf83BAD5bee0F7F44d84669A50C35c57E3576", + Password: "Test@123", + AccountManager: accounts.NewAccountManager("test_accounts"), + }, + }, + wantErr: false, + }, + { + name: "Test 2: When password is incorrect", + args: args{ + account: Types.Account{ + Address: "0x57Baf83BAD5bee0F7F44d84669A50C35c57E3576", + Password: "Test@456", + AccountManager: accounts.NewAccountManager("test_accounts"), + }, + }, + wantErr: true, + }, + { + name: "Test 3: When address or keystore path provided is not present", + args: args{ + account: Types.Account{ + Address: "0x57Baf83BAD5bee0F7F44d84669A50C35c57E3576", + Password: "Test@123", + AccountManager: accounts.NewAccountManager("test_accounts_1"), + }, + }, + wantErr: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + ut := &UtilsStruct{} + if err := ut.CheckPassword(tt.args.account); (err != nil) != tt.wantErr { + t.Errorf("CheckPassword() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} + +func TestUtilsStruct_AccountManagerForKeystore(t *testing.T) { + type args struct { + path string + pathErr error + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "Test 1: When account manager for keystore is returned successfully", + args: args{ + path: "test_accounts", + }, + wantErr: false, + }, + { + name: "Test 2: When there is an error in getting path", + args: args{ + pathErr: errors.New("path error"), + }, + wantErr: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + pathMock := new(mocks.PathUtils) + optionsPackageStruct := OptionsPackageStruct{ + PathInterface: pathMock, + } + + utils := StartRazor(optionsPackageStruct) + + pathMock.On("GetDefaultPath").Return(tt.args.path, tt.args.pathErr) + + _, err := utils.AccountManagerForKeystore() + if (err != nil) != tt.wantErr { + t.Errorf("AccountManagerForKeystore() error = %v, wantErr %v", err, tt.wantErr) + return + } + }) + } +} diff --git a/utils/interface.go b/utils/interface.go index 77304e2d8..cc7ee2274 100644 --- a/utils/interface.go +++ b/utils/interface.go @@ -3,6 +3,7 @@ package utils import ( "context" "crypto/ecdsa" + "github.com/ethereum/go-ethereum/rpc" "io" "io/fs" "math/big" @@ -32,7 +33,6 @@ import ( //go:generate mockery --name ABIUtils --output ./mocks --case=underscore //go:generate mockery --name PathUtils --output ./mocks --case=underscore //go:generate mockery --name BindUtils --output ./mocks --case=underscore -//go:generate mockery --name AccountsUtils --output ./mocks --case=underscore //go:generate mockery --name BlockManagerUtils --output ./mocks --case=underscore //go:generate mockery --name AssetManagerUtils --output ./mocks --case=underscore //go:generate mockery --name VoteManagerUtils --output ./mocks --case=underscore @@ -56,7 +56,6 @@ var IOInterface IOUtils var ABIInterface ABIUtils var PathInterface PathUtils var BindInterface BindUtils -var AccountsInterface AccountsUtils var BlockManagerInterface BlockManagerUtils var StakeManagerInterface StakeManagerUtils var AssetManagerInterface AssetManagerUtils @@ -111,23 +110,23 @@ type Utils interface { GetNumCollections(client *ethclient.Client) (uint16, error) GetActiveJob(client *ethclient.Client, jobId uint16) (bindings.StructsJob, error) GetCollection(client *ethclient.Client, collectionId uint16) (bindings.StructsCollection, error) - GetActiveCollection(client *ethclient.Client, collectionId uint16) (bindings.StructsCollection, error) - Aggregate(client *ethclient.Client, previousEpoch uint32, collection bindings.StructsCollection, localCache *cache.LocalCache) (*big.Int, error) - GetDataToCommitFromJobs(jobs []bindings.StructsJob, localCache *cache.LocalCache) ([]*big.Int, []uint8) - GetDataToCommitFromJob(job bindings.StructsJob, localCache *cache.LocalCache) (*big.Int, error) + GetActiveCollection(collectionsCache *cache.CollectionsCache, collectionId uint16) (bindings.StructsCollection, error) + Aggregate(client *ethclient.Client, previousEpoch uint32, collection bindings.StructsCollection, commitParams *types.CommitParams) (*big.Int, error) + GetDataToCommitFromJobs(jobs []bindings.StructsJob, commitParams *types.CommitParams) ([]*big.Int, []uint8) + GetDataToCommitFromJob(job bindings.StructsJob, commitParams *types.CommitParams) (*big.Int, error) GetAssignedCollections(client *ethclient.Client, numActiveCollections uint16, seed []byte) (map[int]bool, []*big.Int, error) GetLeafIdOfACollection(client *ethclient.Client, collectionId uint16) (uint16, error) GetCollectionIdFromIndex(client *ethclient.Client, medianIndex uint16) (uint16, error) GetCollectionIdFromLeafId(client *ethclient.Client, leafId uint16) (uint16, error) GetNumActiveCollections(client *ethclient.Client) (uint16, error) - GetAggregatedDataOfCollection(client *ethclient.Client, collectionId uint16, epoch uint32, localCache *cache.LocalCache) (*big.Int, error) + GetAggregatedDataOfCollection(client *ethclient.Client, collectionId uint16, epoch uint32, commitParams *types.CommitParams) (*big.Int, error) GetJobs(client *ethclient.Client) ([]bindings.StructsJob, error) GetAllCollections(client *ethclient.Client) ([]bindings.StructsCollection, error) GetActiveCollectionIds(client *ethclient.Client) ([]uint16, error) - HandleOfficialJobsFromJSONFile(client *ethclient.Client, collection bindings.StructsCollection, dataString string) ([]bindings.StructsJob, []uint16) + HandleOfficialJobsFromJSONFile(client *ethclient.Client, collection bindings.StructsCollection, dataString string, commitParams *types.CommitParams) ([]bindings.StructsJob, []uint16) ConnectToClient(provider string) *ethclient.Client FetchBalance(client *ethclient.Client, accountAddress string) (*big.Int, error) - GetBufferedState(client *ethclient.Client, buffer int32) (int64, error) + GetBufferedState(client *ethclient.Client, header *Types.Header, buffer int32) (int64, error) WaitForBlockCompletion(client *ethclient.Client, hashToRead string) error CheckEthBalanceIsZero(client *ethclient.Client, address string) AssignStakerId(flagSet *pflag.FlagSet, client *ethclient.Client, address string) (uint32, error) @@ -157,7 +156,8 @@ type Utils interface { GetRogueRandomValue(value int) *big.Int GetStakedTokenManagerWithOpts(client *ethclient.Client, tokenAddress common.Address) (*bindings.StakedToken, bind.CallOpts) GetStakerSRZRBalance(client *ethclient.Client, staker bindings.StructsStaker) (*big.Int, error) - CheckPassword(address string, password string) error + CheckPassword(account types.Account) error + AccountManagerForKeystore() (types.AccountManagerInterface, error) } type EthClientUtils interface { @@ -178,6 +178,9 @@ type ClientUtils interface { FilterLogsWithRetry(client *ethclient.Client, query ethereum.FilterQuery) ([]Types.Log, error) BalanceAtWithRetry(client *ethclient.Client, account common.Address) (*big.Int, error) GetNonceAtWithRetry(client *ethclient.Client, accountAddress common.Address) (uint64, error) + PerformBatchCall(client *ethclient.Client, calls []rpc.BatchElem) error + CreateBatchCalls(contractABI *abi.ABI, contractAddress, methodName string, args [][]interface{}) ([]rpc.BatchElem, error) + BatchCall(client *ethclient.Client, contractABI *abi.ABI, contractAddress, methodName string, args [][]interface{}) ([][]interface{}, error) } type TimeUtils interface { @@ -218,10 +221,6 @@ type BindUtils interface { NewKeyedTransactorWithChainID(key *ecdsa.PrivateKey, chainID *big.Int) (*bind.TransactOpts, error) } -type AccountsUtils interface { - GetPrivateKey(address string, password string, keystorePath string) (*ecdsa.PrivateKey, error) -} - type BlockManagerUtils interface { GetNumProposedBlocks(client *ethclient.Client, epoch uint32) (uint8, error) GetProposedBlock(client *ethclient.Client, epoch uint32, proposedBlock uint32) (bindings.StructsBlock, error) @@ -322,7 +321,6 @@ type IOStruct struct{} type ABIStruct struct{} type PathStruct struct{} type BindStruct struct{} -type AccountsStruct struct{} type BlockManagerStruct struct{} type StakeManagerStruct struct{} type AssetManagerStruct struct{} @@ -347,7 +345,6 @@ type OptionsPackageStruct struct { ABIInterface ABIUtils PathInterface PathUtils BindInterface BindUtils - AccountsInterface AccountsUtils BlockManagerInterface BlockManagerUtils StakeManagerInterface StakeManagerUtils AssetManagerInterface AssetManagerUtils diff --git a/utils/math.go b/utils/math.go index 976ec9202..5312b64a6 100644 --- a/utils/math.go +++ b/utils/math.go @@ -3,6 +3,7 @@ package utils import ( "crypto/rand" "errors" + "github.com/ethereum/go-ethereum/common" "math" "math/big" mathRand "math/rand" @@ -294,3 +295,11 @@ func isHexArrayPattern(s string) bool { re := regexp.MustCompile(pattern) return re.MatchString(s) } + +func ConvertHashToUint16(hash common.Hash) uint16 { + // Convert the hash to a big integer to handle the numeric value + bigIntValue := hash.Big() + + // Convert the big integer to uint64 first (safe for down casting to uint16) and then downcast to uint16 + return uint16(bigIntValue.Uint64()) +} diff --git a/utils/math_test.go b/utils/math_test.go index 9106c9fd7..0772dad53 100644 --- a/utils/math_test.go +++ b/utils/math_test.go @@ -1,6 +1,7 @@ package utils import ( + "github.com/ethereum/go-ethereum/common" "math/big" "razor/utils/mocks" "reflect" @@ -1297,3 +1298,46 @@ func Test_isHexArrayPattern(t *testing.T) { }) } } + +func TestConvertHashToUint16(t *testing.T) { + tests := []struct { + name string + hash common.Hash + expected uint16 + }{ + { + name: "ZeroHash", + hash: common.Hash{}, + expected: 0, + }, + { + name: "SmallNumber", + hash: common.BigToHash(big.NewInt(42)), + expected: 42, + }, + { + name: "MaxUint16", + hash: common.BigToHash(big.NewInt(65535)), + expected: 65535, + }, + { + name: "OverflowUint16", + hash: common.BigToHash(big.NewInt(65536)), + expected: 0, // 65536 % 65536 == 0 + }, + { + name: "LargeNumber", + hash: common.BigToHash(big.NewInt(123456789)), + expected: 52501, // 123456789 % 65536 + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + result := ConvertHashToUint16(tt.hash) + if result != tt.expected { + t.Errorf("ConvertHashToUint16(%v) = %v, expected %v", tt.hash, result, tt.expected) + } + }) + } +} diff --git a/utils/mocks/client_utils.go b/utils/mocks/client_utils.go index 703c4b5e2..73cdfe6ac 100644 --- a/utils/mocks/client_utils.go +++ b/utils/mocks/client_utils.go @@ -1,19 +1,24 @@ -// Code generated by mockery v2.14.0. DO NOT EDIT. +// Code generated by mockery v2.30.1. DO NOT EDIT. package mocks import ( - context "context" big "math/big" + abi "github.com/ethereum/go-ethereum/accounts/abi" + common "github.com/ethereum/go-ethereum/common" + context "context" + ethclient "github.com/ethereum/go-ethereum/ethclient" ethereum "github.com/ethereum/go-ethereum" mock "github.com/stretchr/testify/mock" + rpc "github.com/ethereum/go-ethereum/rpc" + types "github.com/ethereum/go-ethereum/core/types" ) @@ -27,6 +32,10 @@ func (_m *ClientUtils) BalanceAt(client *ethclient.Client, ctx context.Context, ret := _m.Called(client, ctx, account, blockNumber) var r0 *big.Int + var r1 error + if rf, ok := ret.Get(0).(func(*ethclient.Client, context.Context, common.Address, *big.Int) (*big.Int, error)); ok { + return rf(client, ctx, account, blockNumber) + } if rf, ok := ret.Get(0).(func(*ethclient.Client, context.Context, common.Address, *big.Int) *big.Int); ok { r0 = rf(client, ctx, account, blockNumber) } else { @@ -35,7 +44,6 @@ func (_m *ClientUtils) BalanceAt(client *ethclient.Client, ctx context.Context, } } - var r1 error if rf, ok := ret.Get(1).(func(*ethclient.Client, context.Context, common.Address, *big.Int) error); ok { r1 = rf(client, ctx, account, blockNumber) } else { @@ -50,6 +58,10 @@ func (_m *ClientUtils) BalanceAtWithRetry(client *ethclient.Client, account comm ret := _m.Called(client, account) var r0 *big.Int + var r1 error + if rf, ok := ret.Get(0).(func(*ethclient.Client, common.Address) (*big.Int, error)); ok { + return rf(client, account) + } if rf, ok := ret.Get(0).(func(*ethclient.Client, common.Address) *big.Int); ok { r0 = rf(client, account) } else { @@ -58,7 +70,6 @@ func (_m *ClientUtils) BalanceAtWithRetry(client *ethclient.Client, account comm } } - var r1 error if rf, ok := ret.Get(1).(func(*ethclient.Client, common.Address) error); ok { r1 = rf(client, account) } else { @@ -68,18 +79,73 @@ func (_m *ClientUtils) BalanceAtWithRetry(client *ethclient.Client, account comm return r0, r1 } +// BatchCall provides a mock function with given fields: client, contractABI, contractAddress, methodName, args +func (_m *ClientUtils) BatchCall(client *ethclient.Client, contractABI *abi.ABI, contractAddress string, methodName string, args [][]interface{}) ([][]interface{}, error) { + ret := _m.Called(client, contractABI, contractAddress, methodName, args) + + var r0 [][]interface{} + var r1 error + if rf, ok := ret.Get(0).(func(*ethclient.Client, *abi.ABI, string, string, [][]interface{}) ([][]interface{}, error)); ok { + return rf(client, contractABI, contractAddress, methodName, args) + } + if rf, ok := ret.Get(0).(func(*ethclient.Client, *abi.ABI, string, string, [][]interface{}) [][]interface{}); ok { + r0 = rf(client, contractABI, contractAddress, methodName, args) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([][]interface{}) + } + } + + if rf, ok := ret.Get(1).(func(*ethclient.Client, *abi.ABI, string, string, [][]interface{}) error); ok { + r1 = rf(client, contractABI, contractAddress, methodName, args) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// CreateBatchCalls provides a mock function with given fields: contractABI, contractAddress, methodName, args +func (_m *ClientUtils) CreateBatchCalls(contractABI *abi.ABI, contractAddress string, methodName string, args [][]interface{}) ([]rpc.BatchElem, error) { + ret := _m.Called(contractABI, contractAddress, methodName, args) + + var r0 []rpc.BatchElem + var r1 error + if rf, ok := ret.Get(0).(func(*abi.ABI, string, string, [][]interface{}) ([]rpc.BatchElem, error)); ok { + return rf(contractABI, contractAddress, methodName, args) + } + if rf, ok := ret.Get(0).(func(*abi.ABI, string, string, [][]interface{}) []rpc.BatchElem); ok { + r0 = rf(contractABI, contractAddress, methodName, args) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]rpc.BatchElem) + } + } + + if rf, ok := ret.Get(1).(func(*abi.ABI, string, string, [][]interface{}) error); ok { + r1 = rf(contractABI, contractAddress, methodName, args) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + // EstimateGas provides a mock function with given fields: client, ctx, msg func (_m *ClientUtils) EstimateGas(client *ethclient.Client, ctx context.Context, msg ethereum.CallMsg) (uint64, error) { ret := _m.Called(client, ctx, msg) var r0 uint64 + var r1 error + if rf, ok := ret.Get(0).(func(*ethclient.Client, context.Context, ethereum.CallMsg) (uint64, error)); ok { + return rf(client, ctx, msg) + } if rf, ok := ret.Get(0).(func(*ethclient.Client, context.Context, ethereum.CallMsg) uint64); ok { r0 = rf(client, ctx, msg) } else { r0 = ret.Get(0).(uint64) } - var r1 error if rf, ok := ret.Get(1).(func(*ethclient.Client, context.Context, ethereum.CallMsg) error); ok { r1 = rf(client, ctx, msg) } else { @@ -94,13 +160,16 @@ func (_m *ClientUtils) EstimateGasWithRetry(client *ethclient.Client, message et ret := _m.Called(client, message) var r0 uint64 + var r1 error + if rf, ok := ret.Get(0).(func(*ethclient.Client, ethereum.CallMsg) (uint64, error)); ok { + return rf(client, message) + } if rf, ok := ret.Get(0).(func(*ethclient.Client, ethereum.CallMsg) uint64); ok { r0 = rf(client, message) } else { r0 = ret.Get(0).(uint64) } - var r1 error if rf, ok := ret.Get(1).(func(*ethclient.Client, ethereum.CallMsg) error); ok { r1 = rf(client, message) } else { @@ -115,6 +184,10 @@ func (_m *ClientUtils) FilterLogs(client *ethclient.Client, ctx context.Context, ret := _m.Called(client, ctx, q) var r0 []types.Log + var r1 error + if rf, ok := ret.Get(0).(func(*ethclient.Client, context.Context, ethereum.FilterQuery) ([]types.Log, error)); ok { + return rf(client, ctx, q) + } if rf, ok := ret.Get(0).(func(*ethclient.Client, context.Context, ethereum.FilterQuery) []types.Log); ok { r0 = rf(client, ctx, q) } else { @@ -123,7 +196,6 @@ func (_m *ClientUtils) FilterLogs(client *ethclient.Client, ctx context.Context, } } - var r1 error if rf, ok := ret.Get(1).(func(*ethclient.Client, context.Context, ethereum.FilterQuery) error); ok { r1 = rf(client, ctx, q) } else { @@ -138,6 +210,10 @@ func (_m *ClientUtils) FilterLogsWithRetry(client *ethclient.Client, query ether ret := _m.Called(client, query) var r0 []types.Log + var r1 error + if rf, ok := ret.Get(0).(func(*ethclient.Client, ethereum.FilterQuery) ([]types.Log, error)); ok { + return rf(client, query) + } if rf, ok := ret.Get(0).(func(*ethclient.Client, ethereum.FilterQuery) []types.Log); ok { r0 = rf(client, query) } else { @@ -146,7 +222,6 @@ func (_m *ClientUtils) FilterLogsWithRetry(client *ethclient.Client, query ether } } - var r1 error if rf, ok := ret.Get(1).(func(*ethclient.Client, ethereum.FilterQuery) error); ok { r1 = rf(client, query) } else { @@ -161,6 +236,10 @@ func (_m *ClientUtils) GetLatestBlockWithRetry(client *ethclient.Client) (*types ret := _m.Called(client) var r0 *types.Header + var r1 error + if rf, ok := ret.Get(0).(func(*ethclient.Client) (*types.Header, error)); ok { + return rf(client) + } if rf, ok := ret.Get(0).(func(*ethclient.Client) *types.Header); ok { r0 = rf(client) } else { @@ -169,7 +248,6 @@ func (_m *ClientUtils) GetLatestBlockWithRetry(client *ethclient.Client) (*types } } - var r1 error if rf, ok := ret.Get(1).(func(*ethclient.Client) error); ok { r1 = rf(client) } else { @@ -184,13 +262,16 @@ func (_m *ClientUtils) GetNonceAtWithRetry(client *ethclient.Client, accountAddr ret := _m.Called(client, accountAddress) var r0 uint64 + var r1 error + if rf, ok := ret.Get(0).(func(*ethclient.Client, common.Address) (uint64, error)); ok { + return rf(client, accountAddress) + } if rf, ok := ret.Get(0).(func(*ethclient.Client, common.Address) uint64); ok { r0 = rf(client, accountAddress) } else { r0 = ret.Get(0).(uint64) } - var r1 error if rf, ok := ret.Get(1).(func(*ethclient.Client, common.Address) error); ok { r1 = rf(client, accountAddress) } else { @@ -205,6 +286,10 @@ func (_m *ClientUtils) HeaderByNumber(client *ethclient.Client, ctx context.Cont ret := _m.Called(client, ctx, number) var r0 *types.Header + var r1 error + if rf, ok := ret.Get(0).(func(*ethclient.Client, context.Context, *big.Int) (*types.Header, error)); ok { + return rf(client, ctx, number) + } if rf, ok := ret.Get(0).(func(*ethclient.Client, context.Context, *big.Int) *types.Header); ok { r0 = rf(client, ctx, number) } else { @@ -213,7 +298,6 @@ func (_m *ClientUtils) HeaderByNumber(client *ethclient.Client, ctx context.Cont } } - var r1 error if rf, ok := ret.Get(1).(func(*ethclient.Client, context.Context, *big.Int) error); ok { r1 = rf(client, ctx, number) } else { @@ -228,13 +312,16 @@ func (_m *ClientUtils) NonceAt(client *ethclient.Client, ctx context.Context, ac ret := _m.Called(client, ctx, account) var r0 uint64 + var r1 error + if rf, ok := ret.Get(0).(func(*ethclient.Client, context.Context, common.Address) (uint64, error)); ok { + return rf(client, ctx, account) + } if rf, ok := ret.Get(0).(func(*ethclient.Client, context.Context, common.Address) uint64); ok { r0 = rf(client, ctx, account) } else { r0 = ret.Get(0).(uint64) } - var r1 error if rf, ok := ret.Get(1).(func(*ethclient.Client, context.Context, common.Address) error); ok { r1 = rf(client, ctx, account) } else { @@ -244,11 +331,29 @@ func (_m *ClientUtils) NonceAt(client *ethclient.Client, ctx context.Context, ac return r0, r1 } +// PerformBatchCall provides a mock function with given fields: client, calls +func (_m *ClientUtils) PerformBatchCall(client *ethclient.Client, calls []rpc.BatchElem) error { + ret := _m.Called(client, calls) + + var r0 error + if rf, ok := ret.Get(0).(func(*ethclient.Client, []rpc.BatchElem) error); ok { + r0 = rf(client, calls) + } else { + r0 = ret.Error(0) + } + + return r0 +} + // SuggestGasPrice provides a mock function with given fields: client, ctx func (_m *ClientUtils) SuggestGasPrice(client *ethclient.Client, ctx context.Context) (*big.Int, error) { ret := _m.Called(client, ctx) var r0 *big.Int + var r1 error + if rf, ok := ret.Get(0).(func(*ethclient.Client, context.Context) (*big.Int, error)); ok { + return rf(client, ctx) + } if rf, ok := ret.Get(0).(func(*ethclient.Client, context.Context) *big.Int); ok { r0 = rf(client, ctx) } else { @@ -257,7 +362,6 @@ func (_m *ClientUtils) SuggestGasPrice(client *ethclient.Client, ctx context.Con } } - var r1 error if rf, ok := ret.Get(1).(func(*ethclient.Client, context.Context) error); ok { r1 = rf(client, ctx) } else { @@ -272,6 +376,10 @@ func (_m *ClientUtils) SuggestGasPriceWithRetry(client *ethclient.Client) (*big. ret := _m.Called(client) var r0 *big.Int + var r1 error + if rf, ok := ret.Get(0).(func(*ethclient.Client) (*big.Int, error)); ok { + return rf(client) + } if rf, ok := ret.Get(0).(func(*ethclient.Client) *big.Int); ok { r0 = rf(client) } else { @@ -280,7 +388,6 @@ func (_m *ClientUtils) SuggestGasPriceWithRetry(client *ethclient.Client) (*big. } } - var r1 error if rf, ok := ret.Get(1).(func(*ethclient.Client) error); ok { r1 = rf(client) } else { @@ -295,6 +402,10 @@ func (_m *ClientUtils) TransactionReceipt(client *ethclient.Client, ctx context. ret := _m.Called(client, ctx, txHash) var r0 *types.Receipt + var r1 error + if rf, ok := ret.Get(0).(func(*ethclient.Client, context.Context, common.Hash) (*types.Receipt, error)); ok { + return rf(client, ctx, txHash) + } if rf, ok := ret.Get(0).(func(*ethclient.Client, context.Context, common.Hash) *types.Receipt); ok { r0 = rf(client, ctx, txHash) } else { @@ -303,7 +414,6 @@ func (_m *ClientUtils) TransactionReceipt(client *ethclient.Client, ctx context. } } - var r1 error if rf, ok := ret.Get(1).(func(*ethclient.Client, context.Context, common.Hash) error); ok { r1 = rf(client, ctx, txHash) } else { @@ -313,13 +423,12 @@ func (_m *ClientUtils) TransactionReceipt(client *ethclient.Client, ctx context. return r0, r1 } -type mockConstructorTestingTNewClientUtils interface { +// NewClientUtils creates a new instance of ClientUtils. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func NewClientUtils(t interface { mock.TestingT Cleanup(func()) -} - -// NewClientUtils creates a new instance of ClientUtils. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. -func NewClientUtils(t mockConstructorTestingTNewClientUtils) *ClientUtils { +}) *ClientUtils { mock := &ClientUtils{} mock.Mock.Test(t) diff --git a/utils/mocks/utils.go b/utils/mocks/utils.go index a30978eaf..869a2fbcb 100644 --- a/utils/mocks/utils.go +++ b/utils/mocks/utils.go @@ -12,6 +12,8 @@ import ( common "github.com/ethereum/go-ethereum/common" + coretypes "github.com/ethereum/go-ethereum/core/types" + ethclient "github.com/ethereum/go-ethereum/ethclient" mock "github.com/stretchr/testify/mock" @@ -26,6 +28,32 @@ type Utils struct { mock.Mock } +// AccountManagerForKeystore provides a mock function with given fields: +func (_m *Utils) AccountManagerForKeystore() (types.AccountManagerInterface, error) { + ret := _m.Called() + + var r0 types.AccountManagerInterface + var r1 error + if rf, ok := ret.Get(0).(func() (types.AccountManagerInterface, error)); ok { + return rf() + } + if rf, ok := ret.Get(0).(func() types.AccountManagerInterface); ok { + r0 = rf() + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(types.AccountManagerInterface) + } + } + + if rf, ok := ret.Get(1).(func() error); ok { + r1 = rf() + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + // AddJobToJSON provides a mock function with given fields: fileName, job func (_m *Utils) AddJobToJSON(fileName string, job *types.StructsJob) error { ret := _m.Called(fileName, job) @@ -40,25 +68,25 @@ func (_m *Utils) AddJobToJSON(fileName string, job *types.StructsJob) error { return r0 } -// Aggregate provides a mock function with given fields: client, previousEpoch, collection, localCache -func (_m *Utils) Aggregate(client *ethclient.Client, previousEpoch uint32, collection bindings.StructsCollection, localCache *cache.LocalCache) (*big.Int, error) { - ret := _m.Called(client, previousEpoch, collection, localCache) +// Aggregate provides a mock function with given fields: client, previousEpoch, collection, commitParams +func (_m *Utils) Aggregate(client *ethclient.Client, previousEpoch uint32, collection bindings.StructsCollection, commitParams *types.CommitParams) (*big.Int, error) { + ret := _m.Called(client, previousEpoch, collection, commitParams) var r0 *big.Int var r1 error - if rf, ok := ret.Get(0).(func(*ethclient.Client, uint32, bindings.StructsCollection, *cache.LocalCache) (*big.Int, error)); ok { - return rf(client, previousEpoch, collection, localCache) + if rf, ok := ret.Get(0).(func(*ethclient.Client, uint32, bindings.StructsCollection, *types.CommitParams) (*big.Int, error)); ok { + return rf(client, previousEpoch, collection, commitParams) } - if rf, ok := ret.Get(0).(func(*ethclient.Client, uint32, bindings.StructsCollection, *cache.LocalCache) *big.Int); ok { - r0 = rf(client, previousEpoch, collection, localCache) + if rf, ok := ret.Get(0).(func(*ethclient.Client, uint32, bindings.StructsCollection, *types.CommitParams) *big.Int); ok { + r0 = rf(client, previousEpoch, collection, commitParams) } else { if ret.Get(0) != nil { r0 = ret.Get(0).(*big.Int) } } - if rf, ok := ret.Get(1).(func(*ethclient.Client, uint32, bindings.StructsCollection, *cache.LocalCache) error); ok { - r1 = rf(client, previousEpoch, collection, localCache) + if rf, ok := ret.Get(1).(func(*ethclient.Client, uint32, bindings.StructsCollection, *types.CommitParams) error); ok { + r1 = rf(client, previousEpoch, collection, commitParams) } else { r1 = ret.Error(1) } @@ -155,13 +183,13 @@ func (_m *Utils) CheckEthBalanceIsZero(client *ethclient.Client, address string) _m.Called(client, address) } -// CheckPassword provides a mock function with given fields: address, password -func (_m *Utils) CheckPassword(address string, password string) error { - ret := _m.Called(address, password) +// CheckPassword provides a mock function with given fields: account +func (_m *Utils) CheckPassword(account types.Account) error { + ret := _m.Called(account) var r0 error - if rf, ok := ret.Get(0).(func(string, string) error); ok { - r0 = rf(address, password) + if rf, ok := ret.Get(0).(func(types.Account) error); ok { + r0 = rf(account) } else { r0 = ret.Error(0) } @@ -291,23 +319,23 @@ func (_m *Utils) FetchPreviousValue(client *ethclient.Client, epoch uint32, asse return r0, r1 } -// GetActiveCollection provides a mock function with given fields: client, collectionId -func (_m *Utils) GetActiveCollection(client *ethclient.Client, collectionId uint16) (bindings.StructsCollection, error) { - ret := _m.Called(client, collectionId) +// GetActiveCollection provides a mock function with given fields: collectionsCache, collectionId +func (_m *Utils) GetActiveCollection(collectionsCache *cache.CollectionsCache, collectionId uint16) (bindings.StructsCollection, error) { + ret := _m.Called(collectionsCache, collectionId) var r0 bindings.StructsCollection var r1 error - if rf, ok := ret.Get(0).(func(*ethclient.Client, uint16) (bindings.StructsCollection, error)); ok { - return rf(client, collectionId) + if rf, ok := ret.Get(0).(func(*cache.CollectionsCache, uint16) (bindings.StructsCollection, error)); ok { + return rf(collectionsCache, collectionId) } - if rf, ok := ret.Get(0).(func(*ethclient.Client, uint16) bindings.StructsCollection); ok { - r0 = rf(client, collectionId) + if rf, ok := ret.Get(0).(func(*cache.CollectionsCache, uint16) bindings.StructsCollection); ok { + r0 = rf(collectionsCache, collectionId) } else { r0 = ret.Get(0).(bindings.StructsCollection) } - if rf, ok := ret.Get(1).(func(*ethclient.Client, uint16) error); ok { - r1 = rf(client, collectionId) + if rf, ok := ret.Get(1).(func(*cache.CollectionsCache, uint16) error); ok { + r1 = rf(collectionsCache, collectionId) } else { r1 = ret.Error(1) } @@ -365,25 +393,25 @@ func (_m *Utils) GetActiveJob(client *ethclient.Client, jobId uint16) (bindings. return r0, r1 } -// GetAggregatedDataOfCollection provides a mock function with given fields: client, collectionId, epoch, localCache -func (_m *Utils) GetAggregatedDataOfCollection(client *ethclient.Client, collectionId uint16, epoch uint32, localCache *cache.LocalCache) (*big.Int, error) { - ret := _m.Called(client, collectionId, epoch, localCache) +// GetAggregatedDataOfCollection provides a mock function with given fields: client, collectionId, epoch, commitParams +func (_m *Utils) GetAggregatedDataOfCollection(client *ethclient.Client, collectionId uint16, epoch uint32, commitParams *types.CommitParams) (*big.Int, error) { + ret := _m.Called(client, collectionId, epoch, commitParams) var r0 *big.Int var r1 error - if rf, ok := ret.Get(0).(func(*ethclient.Client, uint16, uint32, *cache.LocalCache) (*big.Int, error)); ok { - return rf(client, collectionId, epoch, localCache) + if rf, ok := ret.Get(0).(func(*ethclient.Client, uint16, uint32, *types.CommitParams) (*big.Int, error)); ok { + return rf(client, collectionId, epoch, commitParams) } - if rf, ok := ret.Get(0).(func(*ethclient.Client, uint16, uint32, *cache.LocalCache) *big.Int); ok { - r0 = rf(client, collectionId, epoch, localCache) + if rf, ok := ret.Get(0).(func(*ethclient.Client, uint16, uint32, *types.CommitParams) *big.Int); ok { + r0 = rf(client, collectionId, epoch, commitParams) } else { if ret.Get(0) != nil { r0 = ret.Get(0).(*big.Int) } } - if rf, ok := ret.Get(1).(func(*ethclient.Client, uint16, uint32, *cache.LocalCache) error); ok { - r1 = rf(client, collectionId, epoch, localCache) + if rf, ok := ret.Get(1).(func(*ethclient.Client, uint16, uint32, *types.CommitParams) error); ok { + r1 = rf(client, collectionId, epoch, commitParams) } else { r1 = ret.Error(1) } @@ -542,23 +570,23 @@ func (_m *Utils) GetBlockManagerWithOpts(client *ethclient.Client) (*bindings.Bl return r0, r1 } -// GetBufferedState provides a mock function with given fields: client, buffer -func (_m *Utils) GetBufferedState(client *ethclient.Client, buffer int32) (int64, error) { - ret := _m.Called(client, buffer) +// GetBufferedState provides a mock function with given fields: client, header, buffer +func (_m *Utils) GetBufferedState(client *ethclient.Client, header *coretypes.Header, buffer int32) (int64, error) { + ret := _m.Called(client, header, buffer) var r0 int64 var r1 error - if rf, ok := ret.Get(0).(func(*ethclient.Client, int32) (int64, error)); ok { - return rf(client, buffer) + if rf, ok := ret.Get(0).(func(*ethclient.Client, *coretypes.Header, int32) (int64, error)); ok { + return rf(client, header, buffer) } - if rf, ok := ret.Get(0).(func(*ethclient.Client, int32) int64); ok { - r0 = rf(client, buffer) + if rf, ok := ret.Get(0).(func(*ethclient.Client, *coretypes.Header, int32) int64); ok { + r0 = rf(client, header, buffer) } else { r0 = ret.Get(0).(int64) } - if rf, ok := ret.Get(1).(func(*ethclient.Client, int32) error); ok { - r1 = rf(client, buffer) + if rf, ok := ret.Get(1).(func(*ethclient.Client, *coretypes.Header, int32) error); ok { + r1 = rf(client, header, buffer) } else { r1 = ret.Error(1) } @@ -704,25 +732,25 @@ func (_m *Utils) GetCommitment(client *ethclient.Client, address string) (types. return r0, r1 } -// GetDataToCommitFromJob provides a mock function with given fields: job, localCache -func (_m *Utils) GetDataToCommitFromJob(job bindings.StructsJob, localCache *cache.LocalCache) (*big.Int, error) { - ret := _m.Called(job, localCache) +// GetDataToCommitFromJob provides a mock function with given fields: job, commitParams +func (_m *Utils) GetDataToCommitFromJob(job bindings.StructsJob, commitParams *types.CommitParams) (*big.Int, error) { + ret := _m.Called(job, commitParams) var r0 *big.Int var r1 error - if rf, ok := ret.Get(0).(func(bindings.StructsJob, *cache.LocalCache) (*big.Int, error)); ok { - return rf(job, localCache) + if rf, ok := ret.Get(0).(func(bindings.StructsJob, *types.CommitParams) (*big.Int, error)); ok { + return rf(job, commitParams) } - if rf, ok := ret.Get(0).(func(bindings.StructsJob, *cache.LocalCache) *big.Int); ok { - r0 = rf(job, localCache) + if rf, ok := ret.Get(0).(func(bindings.StructsJob, *types.CommitParams) *big.Int); ok { + r0 = rf(job, commitParams) } else { if ret.Get(0) != nil { r0 = ret.Get(0).(*big.Int) } } - if rf, ok := ret.Get(1).(func(bindings.StructsJob, *cache.LocalCache) error); ok { - r1 = rf(job, localCache) + if rf, ok := ret.Get(1).(func(bindings.StructsJob, *types.CommitParams) error); ok { + r1 = rf(job, commitParams) } else { r1 = ret.Error(1) } @@ -730,25 +758,25 @@ func (_m *Utils) GetDataToCommitFromJob(job bindings.StructsJob, localCache *cac return r0, r1 } -// GetDataToCommitFromJobs provides a mock function with given fields: jobs, localCache -func (_m *Utils) GetDataToCommitFromJobs(jobs []bindings.StructsJob, localCache *cache.LocalCache) ([]*big.Int, []uint8) { - ret := _m.Called(jobs, localCache) +// GetDataToCommitFromJobs provides a mock function with given fields: jobs, commitParams +func (_m *Utils) GetDataToCommitFromJobs(jobs []bindings.StructsJob, commitParams *types.CommitParams) ([]*big.Int, []uint8) { + ret := _m.Called(jobs, commitParams) var r0 []*big.Int var r1 []uint8 - if rf, ok := ret.Get(0).(func([]bindings.StructsJob, *cache.LocalCache) ([]*big.Int, []uint8)); ok { - return rf(jobs, localCache) + if rf, ok := ret.Get(0).(func([]bindings.StructsJob, *types.CommitParams) ([]*big.Int, []uint8)); ok { + return rf(jobs, commitParams) } - if rf, ok := ret.Get(0).(func([]bindings.StructsJob, *cache.LocalCache) []*big.Int); ok { - r0 = rf(jobs, localCache) + if rf, ok := ret.Get(0).(func([]bindings.StructsJob, *types.CommitParams) []*big.Int); ok { + r0 = rf(jobs, commitParams) } else { if ret.Get(0) != nil { r0 = ret.Get(0).([]*big.Int) } } - if rf, ok := ret.Get(1).(func([]bindings.StructsJob, *cache.LocalCache) []uint8); ok { - r1 = rf(jobs, localCache) + if rf, ok := ret.Get(1).(func([]bindings.StructsJob, *types.CommitParams) []uint8); ok { + r1 = rf(jobs, commitParams) } else { if ret.Get(1) != nil { r1 = ret.Get(1).([]uint8) @@ -1710,25 +1738,25 @@ func (_m *Utils) GetWithdrawInitiationPeriod(client *ethclient.Client) (uint16, return r0, r1 } -// HandleOfficialJobsFromJSONFile provides a mock function with given fields: client, collection, dataString -func (_m *Utils) HandleOfficialJobsFromJSONFile(client *ethclient.Client, collection bindings.StructsCollection, dataString string) ([]bindings.StructsJob, []uint16) { - ret := _m.Called(client, collection, dataString) +// HandleOfficialJobsFromJSONFile provides a mock function with given fields: client, collection, dataString, commitParams +func (_m *Utils) HandleOfficialJobsFromJSONFile(client *ethclient.Client, collection bindings.StructsCollection, dataString string, commitParams *types.CommitParams) ([]bindings.StructsJob, []uint16) { + ret := _m.Called(client, collection, dataString, commitParams) var r0 []bindings.StructsJob var r1 []uint16 - if rf, ok := ret.Get(0).(func(*ethclient.Client, bindings.StructsCollection, string) ([]bindings.StructsJob, []uint16)); ok { - return rf(client, collection, dataString) + if rf, ok := ret.Get(0).(func(*ethclient.Client, bindings.StructsCollection, string, *types.CommitParams) ([]bindings.StructsJob, []uint16)); ok { + return rf(client, collection, dataString, commitParams) } - if rf, ok := ret.Get(0).(func(*ethclient.Client, bindings.StructsCollection, string) []bindings.StructsJob); ok { - r0 = rf(client, collection, dataString) + if rf, ok := ret.Get(0).(func(*ethclient.Client, bindings.StructsCollection, string, *types.CommitParams) []bindings.StructsJob); ok { + r0 = rf(client, collection, dataString, commitParams) } else { if ret.Get(0) != nil { r0 = ret.Get(0).([]bindings.StructsJob) } } - if rf, ok := ret.Get(1).(func(*ethclient.Client, bindings.StructsCollection, string) []uint16); ok { - r1 = rf(client, collection, dataString) + if rf, ok := ret.Get(1).(func(*ethclient.Client, bindings.StructsCollection, string, *types.CommitParams) []uint16); ok { + r1 = rf(client, collection, dataString, commitParams) } else { if ret.Get(1) != nil { r1 = ret.Get(1).([]uint16) diff --git a/utils/options.go b/utils/options.go index b64821544..21062e0cd 100644 --- a/utils/options.go +++ b/utils/options.go @@ -3,7 +3,6 @@ package utils import ( "context" "errors" - "path/filepath" "razor/core/types" "strings" @@ -28,14 +27,14 @@ func (*UtilsStruct) GetOptions() bind.CallOpts { func (*UtilsStruct) GetTxnOpts(transactionData types.TransactionOptions) *bind.TransactOpts { log.Debug("Getting transaction options...") - defaultPath, err := PathInterface.GetDefaultPath() - CheckError("Error in fetching default path: ", err) - keystorePath := filepath.Join(defaultPath, "keystore_files") - privateKey, err := AccountsInterface.GetPrivateKey(transactionData.AccountAddress, transactionData.Password, keystorePath) - if privateKey == nil || err != nil { - CheckError("Error in fetching private key: ", errors.New(transactionData.AccountAddress+" not present in razor-go")) + account := transactionData.Account + if account.AccountManager == nil { + log.Fatal("Account Manager in transaction data is not initialised") } - nonce, err := ClientInterface.GetNonceAtWithRetry(transactionData.Client, common.HexToAddress(transactionData.AccountAddress)) + privateKey, err := account.AccountManager.GetPrivateKey(account.Address, account.Password) + CheckError("Error in fetching private key: ", err) + + nonce, err := ClientInterface.GetNonceAtWithRetry(transactionData.Client, common.HexToAddress(account.Address)) CheckError("Error in fetching nonce: ", err) gasPrice := GasInterface.GetGasPrice(transactionData.Client, transactionData.Config) @@ -103,7 +102,7 @@ func (*GasStruct) GetGasLimit(transactionData types.TransactionOptions, txnOpts } contractAddress := common.HexToAddress(transactionData.ContractAddress) msg := ethereum.CallMsg{ - From: common.HexToAddress(transactionData.AccountAddress), + From: common.HexToAddress(transactionData.Account.Address), To: &contractAddress, GasPrice: txnOpts.GasPrice, Value: txnOpts.Value, diff --git a/utils/options_test.go b/utils/options_test.go index c7ecdfe71..54d7f9071 100644 --- a/utils/options_test.go +++ b/utils/options_test.go @@ -7,6 +7,7 @@ import ( "errors" "github.com/ethereum/go-ethereum/crypto" "math/big" + "razor/accounts" "razor/core/types" "razor/utils/mocks" "reflect" @@ -17,7 +18,6 @@ import ( "github.com/ethereum/go-ethereum/accounts/abi/bind" Types "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/ethclient" - "github.com/magiconair/properties/assert" "github.com/stretchr/testify/mock" ) @@ -134,16 +134,13 @@ func Test_getGasPrice(t *testing.T) { } func Test_utils_GetTxnOpts(t *testing.T) { - var transactionData types.TransactionOptions var gasPrice *big.Int privateKey, _ := ecdsa.GenerateKey(crypto.S256(), rand.Reader) txnOpts, _ := bind.NewKeyedTransactorWithChainID(privateKey, big.NewInt(1)) type args struct { - path string - pathErr error - privateKey *ecdsa.PrivateKey + address string nonce uint64 nonceErr error txnOpts *bind.TransactOpts @@ -162,36 +159,32 @@ func Test_utils_GetTxnOpts(t *testing.T) { { name: "Test 1: When GetTxnOptions execute successfully", args: args{ - path: "/home/local", - privateKey: privateKey, - nonce: 2, - txnOpts: txnOpts, - gasLimit: 1, + address: "0x57Baf83BAD5bee0F7F44d84669A50C35c57E3576", + nonce: 2, + txnOpts: txnOpts, + gasLimit: 1, }, want: txnOpts, expectedFatal: false, }, { - name: "Test 2: When there is an error in getting path", + name: "Test 2: When there is an error in getting private key as address is not present in keystore", args: args{ - path: "/home/local", - pathErr: errors.New("path error"), - privateKey: privateKey, - nonce: 2, - txnOpts: txnOpts, - gasLimit: 1, + address: "0x77Baf83BAD5bee0F7F44d84669A50C35c57E3576", + nonce: 2, + txnOpts: txnOpts, + gasLimit: 1, }, want: txnOpts, expectedFatal: true, }, { - name: "Test 3: When the privateKey is nil", + name: "Test 3: When the accountManager is nil", args: args{ - path: "/home/local", - privateKey: nil, - nonce: 2, - txnOpts: txnOpts, - gasLimit: 1, + address: "", + nonce: 2, + txnOpts: txnOpts, + gasLimit: 1, }, want: txnOpts, expectedFatal: true, @@ -199,12 +192,11 @@ func Test_utils_GetTxnOpts(t *testing.T) { { name: "Test 4: When there is an error in getting nonce", args: args{ - path: "/home/local", - privateKey: privateKey, - nonce: 2, - nonceErr: errors.New("nonce error"), - txnOpts: txnOpts, - gasLimit: 1, + address: "0x57Baf83BAD5bee0F7F44d84669A50C35c57E3576", + nonce: 2, + nonceErr: errors.New("nonce error"), + txnOpts: txnOpts, + gasLimit: 1, }, want: txnOpts, expectedFatal: true, @@ -212,8 +204,7 @@ func Test_utils_GetTxnOpts(t *testing.T) { { name: "Test 5: When there is an error in getting transactor", args: args{ - path: "/home/local", - privateKey: privateKey, + address: "0x57Baf83BAD5bee0F7F44d84669A50C35c57E3576", nonce: 2, txnOpts: txnOpts, txnOptsErr: errors.New("transactor error"), @@ -225,8 +216,7 @@ func Test_utils_GetTxnOpts(t *testing.T) { { name: "Test 6: When there is an error in getting gasLimit", args: args{ - path: "/home/local", - privateKey: privateKey, + address: "0x57Baf83BAD5bee0F7F44d84669A50C35c57E3576", nonce: 2, txnOpts: txnOpts, gasLimitErr: errors.New("gasLimit error"), @@ -235,10 +225,9 @@ func Test_utils_GetTxnOpts(t *testing.T) { expectedFatal: false, }, { - name: "Test 6: When there is an rpc error in getting gasLimit", + name: "Test 7: When there is an rpc error in getting gasLimit", args: args{ - path: "/home/local", - privateKey: privateKey, + address: "0x57Baf83BAD5bee0F7F44d84669A50C35c57E3576", nonce: 2, txnOpts: txnOpts, gasLimitErr: errors.New("504 gateway error"), @@ -250,10 +239,9 @@ func Test_utils_GetTxnOpts(t *testing.T) { expectedFatal: false, }, { - name: "Test 7: When there is an rpc error in getting gasLimit and than error in getting latest header", + name: "Test 8: When there is an rpc error in getting gasLimit and than error in getting latest header", args: args{ - path: "/home/local", - privateKey: privateKey, + address: "0x57Baf83BAD5bee0F7F44d84669A50C35c57E3576", nonce: 2, txnOpts: txnOpts, gasLimitErr: errors.New("504 gateway error"), @@ -267,32 +255,42 @@ func Test_utils_GetTxnOpts(t *testing.T) { }, } - defer func() { log.ExitFunc = nil }() - var fatal bool - log.ExitFunc = func(int) { fatal = true } + originalExitFunc := log.ExitFunc // Preserve the original ExitFunc + defer func() { log.ExitFunc = originalExitFunc }() // Ensure it's reset after tests for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { + fatalOccurred := false + + // Override log.ExitFunc to induce a panic for testing the fatal scenario + log.ExitFunc = func(int) { panic("log.Fatal called") } + + var account types.Account + accountManager := accounts.NewAccountManager("test_accounts") + if tt.args.address != "" { + account = accounts.InitAccountStruct(tt.args.address, "Test@123", accountManager) + } else { + account = types.Account{} + } + transactionData := types.TransactionOptions{ + Account: account, + } utilsMock := new(mocks.Utils) pathMock := new(mocks.PathUtils) bindMock := new(mocks.BindUtils) - accountsMock := new(mocks.AccountsUtils) clientMock := new(mocks.ClientUtils) gasMock := new(mocks.GasUtils) optionsPackageStruct := OptionsPackageStruct{ - UtilsInterface: utilsMock, - PathInterface: pathMock, - BindInterface: bindMock, - AccountsInterface: accountsMock, - ClientInterface: clientMock, - GasInterface: gasMock, + UtilsInterface: utilsMock, + PathInterface: pathMock, + BindInterface: bindMock, + ClientInterface: clientMock, + GasInterface: gasMock, } utils := StartRazor(optionsPackageStruct) - pathMock.On("GetDefaultPath").Return(tt.args.path, tt.args.pathErr) - accountsMock.On("GetPrivateKey", mock.AnythingOfType("string"), mock.AnythingOfType("string"), mock.AnythingOfType("string")).Return(tt.args.privateKey, nil) clientMock.On("GetNonceAtWithRetry", mock.AnythingOfType("*ethclient.Client"), mock.AnythingOfType("common.Address")).Return(tt.args.nonce, tt.args.nonceErr) gasMock.On("GetGasPrice", mock.AnythingOfType("*ethclient.Client"), mock.AnythingOfType("types.Configurations")).Return(gasPrice) bindMock.On("NewKeyedTransactorWithChainID", mock.AnythingOfType("*ecdsa.PrivateKey"), mock.AnythingOfType("*big.Int")).Return(tt.args.txnOpts, tt.args.txnOptsErr) @@ -301,10 +299,29 @@ func Test_utils_GetTxnOpts(t *testing.T) { utilsMock.On("MultiplyFloatAndBigInt", mock.AnythingOfType("*big.Int"), mock.AnythingOfType("float64")).Return(big.NewInt(1)) clientMock.On("GetLatestBlockWithRetry", mock.AnythingOfType("*ethclient.Client")).Return(tt.args.latestHeader, tt.args.latestHeaderErr) - fatal = false + // Defer a function to recover from the panic and check if it matches the expectedFatal condition + defer func() { + if r := recover(); r != nil { + // A panic occurred, check if it was expected + if tt.expectedFatal { + // Panic (fatal) was expected and occurred, so this is correct + fatalOccurred = true + } else { + // Panic occurred but was not expected, fail the test + t.Errorf("Unexpected log.Fatal call") + } + } else { + // No panic occurred, check if it was expected + if tt.expectedFatal { + // Expected a fatal condition but it didn't occur, fail the test + t.Errorf("Expected log.Fatal call did not occur") + } + } + }() + got := utils.GetTxnOpts(transactionData) - if tt.expectedFatal { - assert.Equal(t, tt.expectedFatal, fatal) + if !tt.expectedFatal && fatalOccurred { + t.Fatalf("Test exited due to an unexpected fatal condition") } if got != tt.want { t.Errorf("GetTxnOpts() function, got = %v, want = %v", got, tt.want) diff --git a/utils/struct-utils.go b/utils/struct-utils.go index 4eb404a85..d22ac17d3 100644 --- a/utils/struct-utils.go +++ b/utils/struct-utils.go @@ -9,7 +9,6 @@ import ( "io/fs" "math/big" "os" - "razor/accounts" "razor/client" "razor/core" coretypes "razor/core/types" @@ -29,7 +28,6 @@ import ( ) var RPCTimeout int64 -var HTTPTimeout int64 func StartRazor(optionsPackageStruct OptionsPackageStruct) Utils { UtilsInterface = optionsPackageStruct.UtilsInterface @@ -42,7 +40,6 @@ func StartRazor(optionsPackageStruct OptionsPackageStruct) Utils { ABIInterface = optionsPackageStruct.ABIInterface PathInterface = optionsPackageStruct.PathInterface BindInterface = optionsPackageStruct.BindInterface - AccountsInterface = optionsPackageStruct.AccountsInterface BlockManagerInterface = optionsPackageStruct.BlockManagerInterface StakeManagerInterface = optionsPackageStruct.StakeManagerInterface AssetManagerInterface = optionsPackageStruct.AssetManagerInterface @@ -249,10 +246,6 @@ func (v VoteManagerStruct) GetSaltFromBlockchain(client *ethclient.Client) ([32] return returnedValues[0].Interface().([32]byte), nil } -func (a AccountsStruct) GetPrivateKey(address string, password string, keystorePath string) (*ecdsa.PrivateKey, error) { - return accounts.AccountUtilsInterface.GetPrivateKey(address, password, keystorePath) -} - func (b BlockManagerStruct) GetNumProposedBlocks(client *ethclient.Client, epoch uint32) (uint8, error) { blockManager, opts := UtilsInterface.GetBlockManagerWithOpts(client) returnedValues := InvokeFunctionWithTimeout(blockManager, "GetNumProposedBlocks", &opts, epoch)