From e0cc32a5acda16176f3292b5c2a88abbd86ba619 Mon Sep 17 00:00:00 2001 From: YashK Date: Wed, 20 Mar 2024 13:44:39 +0530 Subject: [PATCH 01/16] refactor: used regex instead of ks.Accounts to match keystore file --- accounts/accountUtils.go | 21 ----------- accounts/accounts.go | 75 ++++++++++++++++++++++++++++++++-------- 2 files changed, 61 insertions(+), 35 deletions(-) diff --git a/accounts/accountUtils.go b/accounts/accountUtils.go index 11f8a5f10..bfa234ff6 100644 --- a/accounts/accountUtils.go +++ b/accounts/accountUtils.go @@ -6,7 +6,6 @@ import ( "github.com/ethereum/go-ethereum/accounts" "github.com/ethereum/go-ethereum/accounts/keystore" "github.com/ethereum/go-ethereum/crypto" - "os" "razor/core/types" ) @@ -16,24 +15,14 @@ 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) @@ -41,17 +30,7 @@ func (accountUtils AccountUtils) NewAccount(path string, passphrase string) (acc 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) -} - //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) } - -//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) -} diff --git a/accounts/accounts.go b/accounts/accounts.go index b907dfef9..a6742c5bb 100644 --- a/accounts/accounts.go +++ b/accounts/accounts.go @@ -4,10 +4,15 @@ package accounts import ( "crypto/ecdsa" "errors" + "fmt" "github.com/ethereum/go-ethereum/accounts" + "github.com/ethereum/go-ethereum/accounts/keystore" + "os" + "path/filepath" "razor/core/types" "razor/logger" "razor/path" + "regexp" "strings" ) @@ -28,29 +33,30 @@ func (AccountUtils) CreateAccount(keystorePath string, password string) accounts return newAcc } -//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) +//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, keystoreDirPath string) (*ecdsa.PrivateKey, error) { + fileName, err := FindKeystoreFileForAddress(keystoreDirPath, address) + if err != nil { + log.Error("Error in finding keystore file for an address: ", err) + return nil, err + } + + keyJson, err := os.ReadFile(fileName) if err != nil { log.Error("Error in reading keystore: ", err) return nil, err } - key, err := AccountUtilsInterface.DecryptKey(jsonBytes, password) + key, err := keystore.DecryptKey(keyJson, password) if err != nil { - log.Error("Error in fetching private key: ", err) + log.Error("Error in decrypting private key: ", err) return nil, err } - 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) - } + // Check if the input address matches with address from keystore file in which password was matched + if key.Address.Hex() == address { + return key.PrivateKey, nil } + return nil, errors.New("no keystore file found") } @@ -62,3 +68,44 @@ func (AccountUtils) SignData(hash []byte, account types.Account, defaultPath str } return AccountUtilsInterface.Sign(hash, privateKey) } + +// FindKeystoreFileForAddress matches the keystore file for the given address. +func FindKeystoreFileForAddress(keystoreDirPath, address string) (string, error) { + normalizedAddress := strings.ToLower(address) + if strings.HasPrefix(normalizedAddress, "0x") { + normalizedAddress = normalizedAddress[2:] + } + regexPattern := fmt.Sprintf("^UTC--.*--%s$", regexp.QuoteMeta(normalizedAddress)) + re, err := regexp.Compile(regexPattern) + if err != nil { + log.Errorf("Error in compiling regex: %v", err) + return "", err + } + + var keystoreFilePath string + err = filepath.WalkDir(keystoreDirPath, func(path string, d os.DirEntry, err error) error { + if err != nil { + return err // Propagate errors encountered during traversal + } + if d.IsDir() { + return nil // Skip directories, continue walking + } + if re.MatchString(d.Name()) { // Check if file name matches the regex + keystoreFilePath = path + return filepath.SkipDir // File found, no need to continue + } + return nil + }) + + if err != nil { + log.Errorf("Error walking through keystore directory: %v", err) + return "", err + } + + if keystoreFilePath == "" { + log.Errorf("No matching keystore file found for address %s", address) + return "", errors.New("no matching keystore file found") + } + + return keystoreFilePath, nil +} From 7c7e1ff5dc505f5db246232eec614ca2d3ddea2c Mon Sep 17 00:00:00 2001 From: YashK Date: Wed, 20 Mar 2024 13:45:56 +0530 Subject: [PATCH 02/16] refactor: added more extensive realistic testing for fetching of private key --- accounts/accounts_test.go | 187 ++++++++---------- accounts/mocks/account_interface.go | 118 ++--------- ...--911654feb423363fb771e04e18d1e7325ae10a91 | 1 + ...--2f5f59615689b706b6ad13fd03343dca28784989 | 1 + ...--811654feb423363fb771e04e18d1e7325ae10a91 | 1 + ...--811654feb423363fb771e04e18d1e7325ae10a91 | 1 + 6 files changed, 111 insertions(+), 198 deletions(-) create mode 100644 accounts/test_accounts/UTC--2024-03-20T07-03-56.358521000Z--911654feb423363fb771e04e18d1e7325ae10a91 create mode 100644 accounts/test_accounts/UTC--2024-03-20T07-04-11.601622000Z--2f5f59615689b706b6ad13fd03343dca28784989 create mode 100644 accounts/test_accounts/incorrect_test_accounts/UTC--2024-03-20T07-03-56.358521000Z--811654feb423363fb771e04e18d1e7325ae10a91 create mode 100644 accounts/test_accounts/incorrect_test_accounts/UTC--2024-03-20T07-04-56.358521000Z--811654feb423363fb771e04e18d1e7325ae10a91 diff --git a/accounts/accounts_test.go b/accounts/accounts_test.go index aa964bf47..de2f4c006 100644 --- a/accounts/accounts_test.go +++ b/accounts/accounts_test.go @@ -4,11 +4,11 @@ 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" + "path/filepath" "razor/accounts/mocks" "razor/core/types" "razor/path" @@ -116,140 +116,68 @@ func TestCreateAccount(t *testing.T) { } } -func TestGetPrivateKeyFromKeystore(t *testing.T) { - var password string - var keystorePath string - var privateKey *ecdsa.PrivateKey - var jsonBytes []byte +func TestGetPrivateKey(t *testing.T) { + password := "Razor@123" + keystoreDirPath := "test_accounts" type args struct { - jsonBytes []byte - jsonBytesErr error - key *keystore.Key - keyErr error + address string + password string + keystoreDirPath string } tests := []struct { name string args args - want *ecdsa.PrivateKey wantErr bool }{ { - name: "Test 1: When GetPrivateKey function executes successfully", + name: "Test 1: When input address with correct password is present in keystore directory", args: args{ - jsonBytes: jsonBytes, - key: &keystore.Key{ - PrivateKey: privateKey, - }, + address: "0x911654feb423363fb771e04e18d1e7325ae10a91", + password: password, + keystoreDirPath: keystoreDirPath, }, - want: privateKey, wantErr: false, }, { - name: "Test 2: When there is an error in reading data from file", + name: "Test 2: When another input address with correct password is present in keystore directory", args: args{ - jsonBytesErr: errors.New("error in reading data"), - key: &keystore.Key{ - PrivateKey: nil, - }, + address: "0x2f5f59615689b706b6ad13fd03343dca28784989", + password: password, + keystoreDirPath: keystoreDirPath, }, - want: nil, - wantErr: true, + wantErr: false, }, { - name: "Test 3: When there is an error in fetching private key", + name: "Test 3: When provided address is not present in keystore directory", args: args{ - jsonBytes: jsonBytes, - key: &keystore.Key{ - PrivateKey: nil, - }, - keyErr: errors.New("private key error"), + address: "0x911654feb423363fb771e04e18d1e7325ae10a91_not_present", + keystoreDirPath: keystoreDirPath, }, - want: privateKey, 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) - } - if (err != nil) != tt.wantErr { - t.Errorf("GetPrivateKeyFromKeystore() error = %v, wantErr %v", err, tt.wantErr) - return - } - }) - } -} - -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"}, - }, - } - - type args struct { - address string - accounts []accounts.Account - privateKey *ecdsa.PrivateKey - } - tests := []struct { - name string - args args - want *ecdsa.PrivateKey - wantErr bool - }{ { - name: "Test 1: When input address is present in accountsList", + name: "Test 4: When input address with incorrect password is present in keystore directory", args: args{ - address: "0x000000000000000000000000000000000000dea1", - accounts: accountsList, - privateKey: privateKey, + address: "0x911654feb423363fb771e04e18d1e7325ae10a91", + password: "incorrect password", + keystoreDirPath: keystoreDirPath, }, - want: privateKey, - wantErr: false, + wantErr: true, }, { - name: "Test 2: When input address is not present in accountsList", + name: "Test 5: When a keystore file is renamed differently from the address to which it belonged", args: args{ - address: "0x000000000000000000000000000000000000dea3", - accounts: accountsList, - privateKey: privateKey, + address: "0x811654feb423363fb771e04e18d1e7325ae10a91", + password: password, + keystoreDirPath: "test_accounts/incorrect_test_accounts", }, - want: nil, - 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) - } + _, err := accountUtils.GetPrivateKey(tt.args.address, tt.args.password, tt.args.keystoreDirPath) if (err != nil) != tt.wantErr { t.Errorf("GetPrivateKey() error = %v, wantErr %v", err, tt.wantErr) return @@ -319,3 +247,60 @@ func TestSignData(t *testing.T) { }) } } + +func TestFindKeystoreFileForAddress(t *testing.T) { + testAccountsKeystorePath := "test_accounts" + + tests := []struct { + name string + keystoreDir string + address string + expectedFile string + expectErr bool + }{ + { + name: "Matching file exists for an address", + keystoreDir: testAccountsKeystorePath, + address: "0x911654feb423363fb771e04e18d1e7325ae10a91", + expectedFile: filepath.Join(testAccountsKeystorePath, "UTC--2024-03-20T07-03-56.358521000Z--911654feb423363fb771e04e18d1e7325ae10a91"), + expectErr: false, + }, + { + name: "Matching file exists for another address", + keystoreDir: testAccountsKeystorePath, + address: "0x2f5f59615689b706b6ad13fd03343dca28784989", + expectedFile: filepath.Join(testAccountsKeystorePath, "UTC--2024-03-20T07-04-11.601622000Z--2f5f59615689b706b6ad13fd03343dca28784989"), + expectErr: false, + }, + { + name: "No matching file", + keystoreDir: testAccountsKeystorePath, + address: "nonexistentaddress", + expectErr: true, + }, + { + name: "When keystore directory doesnt exists", + keystoreDir: "test_accounts_invalid", + address: "0x2f5f59615689b706b6ad13fd03343dca28784989", + expectErr: true, + }, + } + + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + got, err := FindKeystoreFileForAddress(tc.keystoreDir, tc.address) + if tc.expectErr { + if err == nil { + t.Errorf("Expected an error but got none") + } + } else { + if err != nil { + t.Errorf("Did not expect an error but got one: %v", err) + } + if got != tc.expectedFile { + t.Errorf("Expected file %v, got %v", tc.expectedFile, got) + } + } + }) + } +} diff --git a/accounts/mocks/account_interface.go b/accounts/mocks/account_interface.go index e8e006441..ed1e4b9f5 100644 --- a/accounts/mocks/account_interface.go +++ b/accounts/mocks/account_interface.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.14.0. DO NOT EDIT. +// Code generated by mockery v2.30.1. DO NOT EDIT. package mocks @@ -7,8 +7,6 @@ import ( 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" @@ -19,22 +17,6 @@ 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) @@ -49,34 +31,15 @@ func (_m *AccountInterface) CreateAccount(path string, password string) accounts 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 + var r1 error + if rf, ok := ret.Get(0).(func(string, string, string) (*ecdsa.PrivateKey, error)); ok { + return rf(address, password, keystorePath) + } if rf, ok := ret.Get(0).(func(string, string, string) *ecdsa.PrivateKey); ok { r0 = rf(address, password, keystorePath) } else { @@ -85,7 +48,6 @@ func (_m *AccountInterface) GetPrivateKey(address string, password string, keyst } } - var r1 error if rf, ok := ret.Get(1).(func(string, string, string) error); ok { r1 = rf(address, password, keystorePath) } else { @@ -95,41 +57,21 @@ func (_m *AccountInterface) GetPrivateKey(address string, password string, keyst 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 + var r1 error + if rf, ok := ret.Get(0).(func(string, string) (accounts.Account, error)); ok { + return rf(path, passphrase) + } 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 { @@ -139,34 +81,15 @@ func (_m *AccountInterface) NewAccount(path string, passphrase string) (accounts 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 + var r1 error + if rf, ok := ret.Get(0).(func([]byte, *ecdsa.PrivateKey) ([]byte, error)); ok { + return rf(digestHash, prv) + } if rf, ok := ret.Get(0).(func([]byte, *ecdsa.PrivateKey) []byte); ok { r0 = rf(digestHash, prv) } else { @@ -175,7 +98,6 @@ func (_m *AccountInterface) Sign(digestHash []byte, prv *ecdsa.PrivateKey) ([]by } } - var r1 error if rf, ok := ret.Get(1).(func([]byte, *ecdsa.PrivateKey) error); ok { r1 = rf(digestHash, prv) } else { @@ -190,6 +112,10 @@ func (_m *AccountInterface) SignData(hash []byte, account types.Account, default ret := _m.Called(hash, account, defaultPath) var r0 []byte + var r1 error + if rf, ok := ret.Get(0).(func([]byte, types.Account, string) ([]byte, error)); ok { + return rf(hash, account, defaultPath) + } if rf, ok := ret.Get(0).(func([]byte, types.Account, string) []byte); ok { r0 = rf(hash, account, defaultPath) } else { @@ -198,7 +124,6 @@ func (_m *AccountInterface) SignData(hash []byte, account types.Account, default } } - var r1 error if rf, ok := ret.Get(1).(func([]byte, types.Account, string) error); ok { r1 = rf(hash, account, defaultPath) } else { @@ -208,13 +133,12 @@ func (_m *AccountInterface) SignData(hash []byte, account types.Account, default return r0, r1 } -type mockConstructorTestingTNewAccountInterface interface { +// 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. +// The first argument is typically a *testing.T value. +func NewAccountInterface(t 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 { +}) *AccountInterface { mock := &AccountInterface{} mock.Mock.Test(t) 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/accounts/test_accounts/incorrect_test_accounts/UTC--2024-03-20T07-03-56.358521000Z--811654feb423363fb771e04e18d1e7325ae10a91 b/accounts/test_accounts/incorrect_test_accounts/UTC--2024-03-20T07-03-56.358521000Z--811654feb423363fb771e04e18d1e7325ae10a91 new file mode 100644 index 000000000..bc50d72f6 --- /dev/null +++ b/accounts/test_accounts/incorrect_test_accounts/UTC--2024-03-20T07-03-56.358521000Z--811654feb423363fb771e04e18d1e7325ae10a91 @@ -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/incorrect_test_accounts/UTC--2024-03-20T07-04-56.358521000Z--811654feb423363fb771e04e18d1e7325ae10a91 b/accounts/test_accounts/incorrect_test_accounts/UTC--2024-03-20T07-04-56.358521000Z--811654feb423363fb771e04e18d1e7325ae10a91 new file mode 100644 index 000000000..bc50d72f6 --- /dev/null +++ b/accounts/test_accounts/incorrect_test_accounts/UTC--2024-03-20T07-04-56.358521000Z--811654feb423363fb771e04e18d1e7325ae10a91 @@ -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 From 1c2692b29682d07372d955b15d0b388093c6be4e Mon Sep 17 00:00:00 2001 From: YashK Date: Wed, 20 Mar 2024 14:02:26 +0530 Subject: [PATCH 03/16] ci: ignore test-accounts directory in coverage --- .github/workflows/ci.yml | 2 +- .github/workflows/develop.yml | 2 +- .github/workflows/release.yml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c0e2167b2..5296ecdf5 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -60,7 +60,7 @@ jobs: - name: Execute test case run: > - go-acc ./... --ignore razor/accounts/mocks --ignore razor/cmd/mocks + go-acc ./... --ignore razor/accounts/mocks --ignore razor/accounts/test_accounts --ignore razor/cmd/mocks --ignore razor/utils/mocks --ignore pkg --ignore razor/path/mocks --output coverage.txt - name: Run benchmarks diff --git a/.github/workflows/develop.yml b/.github/workflows/develop.yml index e9f4a9baf..d58e6337d 100644 --- a/.github/workflows/develop.yml +++ b/.github/workflows/develop.yml @@ -61,7 +61,7 @@ jobs: golangci-lint run -v --timeout 5m - name: Execute test case run: | - go-acc ./... --ignore razor/accounts/mocks --ignore razor/cmd/mocks --ignore razor/cmd/eventListeners.go --ignore razor/utils/mocks --ignore pkg --ignore razor/path/mocks --output coverage.txt + go-acc ./... --ignore razor/accounts/mocks --ignore razor/accounts/test_accounts --ignore razor/cmd/mocks --ignore razor/cmd/eventListeners.go --ignore razor/utils/mocks --ignore pkg --ignore razor/path/mocks --output coverage.txt - name: Run benchmarks run: | go test ./... -bench=. -run=^# diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index d13c625f4..b4c7e9acd 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -58,7 +58,7 @@ jobs: golangci-lint run -v --timeout 5m - name: Execute test case run: | - go-acc ./... --ignore razor/accounts/mocks --ignore razor/cmd/mocks --ignore razor/utils/mocks --ignore pkg --ignore razor/path/mocks --output coverage.txt + go-acc ./... --ignore razor/accounts/mocks --ignore razor/accounts/test_accounts --ignore razor/cmd/mocks --ignore razor/utils/mocks --ignore pkg --ignore razor/path/mocks --output coverage.txt - name: Run benchmarks run: | go test ./... -bench=. -run=^# From 9be610b5ab34086247593689dce968195ea42b87 Mon Sep 17 00:00:00 2001 From: YashK Date: Wed, 20 Mar 2024 14:09:59 +0530 Subject: [PATCH 04/16] refactor: added test when multiple timestamps keystore file present for same account --- accounts/accounts_test.go | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/accounts/accounts_test.go b/accounts/accounts_test.go index de2f4c006..2a9603ea4 100644 --- a/accounts/accounts_test.go +++ b/accounts/accounts_test.go @@ -259,31 +259,38 @@ func TestFindKeystoreFileForAddress(t *testing.T) { expectErr bool }{ { - name: "Matching file exists for an address", + name: "Test 1: Matching file exists for an address", keystoreDir: testAccountsKeystorePath, address: "0x911654feb423363fb771e04e18d1e7325ae10a91", expectedFile: filepath.Join(testAccountsKeystorePath, "UTC--2024-03-20T07-03-56.358521000Z--911654feb423363fb771e04e18d1e7325ae10a91"), expectErr: false, }, { - name: "Matching file exists for another address", + name: "Test 2: Matching file exists for another address", keystoreDir: testAccountsKeystorePath, address: "0x2f5f59615689b706b6ad13fd03343dca28784989", expectedFile: filepath.Join(testAccountsKeystorePath, "UTC--2024-03-20T07-04-11.601622000Z--2f5f59615689b706b6ad13fd03343dca28784989"), expectErr: false, }, { - name: "No matching file", + name: "Test 3: No matching file", keystoreDir: testAccountsKeystorePath, address: "nonexistentaddress", expectErr: true, }, { - name: "When keystore directory doesnt exists", + name: "Test 4: When keystore directory doesnt exists", keystoreDir: "test_accounts_invalid", address: "0x2f5f59615689b706b6ad13fd03343dca28784989", expectErr: true, }, + { + name: "Test 5: When multiple files for same account is present in the keystore directory", + keystoreDir: "test_accounts/incorrect_test_accounts", + address: "0x811654feb423363fb771e04e18d1e7325ae10a91", + expectedFile: filepath.Join("test_accounts/incorrect_test_accounts", "UTC--2024-03-20T07-04-56.358521000Z--811654feb423363fb771e04e18d1e7325ae10a91"), + expectErr: true, + }, } for _, tc := range tests { From b5eeabc8a8660924a9dd5853dc651851344ca07e Mon Sep 17 00:00:00 2001 From: YashK Date: Wed, 20 Mar 2024 15:21:16 +0530 Subject: [PATCH 05/16] refactor: covered lower and upper case addresses --- accounts/accounts.go | 7 ++----- accounts/accounts_test.go | 13 +++++++------ 2 files changed, 9 insertions(+), 11 deletions(-) diff --git a/accounts/accounts.go b/accounts/accounts.go index a6742c5bb..8cb7de6b4 100644 --- a/accounts/accounts.go +++ b/accounts/accounts.go @@ -53,7 +53,7 @@ func (AccountUtils) GetPrivateKey(address string, password string, keystoreDirPa } // Check if the input address matches with address from keystore file in which password was matched - if key.Address.Hex() == address { + if strings.EqualFold(key.Address.Hex(), address) { return key.PrivateKey, nil } @@ -71,10 +71,7 @@ func (AccountUtils) SignData(hash []byte, account types.Account, defaultPath str // FindKeystoreFileForAddress matches the keystore file for the given address. func FindKeystoreFileForAddress(keystoreDirPath, address string) (string, error) { - normalizedAddress := strings.ToLower(address) - if strings.HasPrefix(normalizedAddress, "0x") { - normalizedAddress = normalizedAddress[2:] - } + normalizedAddress := strings.ToLower(strings.TrimPrefix(address, "0x")) regexPattern := fmt.Sprintf("^UTC--.*--%s$", regexp.QuoteMeta(normalizedAddress)) re, err := regexp.Compile(regexPattern) if err != nil { diff --git a/accounts/accounts_test.go b/accounts/accounts_test.go index 2a9603ea4..7e0b860ca 100644 --- a/accounts/accounts_test.go +++ b/accounts/accounts_test.go @@ -140,9 +140,9 @@ func TestGetPrivateKey(t *testing.T) { wantErr: false, }, { - name: "Test 2: When another input address with correct password is present in keystore directory", + name: "Test 2: When input upper case address with correct password is present in keystore directory", args: args{ - address: "0x2f5f59615689b706b6ad13fd03343dca28784989", + address: "0x2F5F59615689B706B6AD13FD03343DCA28784989", password: password, keystoreDirPath: keystoreDirPath, }, @@ -172,6 +172,7 @@ func TestGetPrivateKey(t *testing.T) { password: password, keystoreDirPath: "test_accounts/incorrect_test_accounts", }, + wantErr: true, }, } for _, tt := range tests { @@ -266,9 +267,9 @@ func TestFindKeystoreFileForAddress(t *testing.T) { expectErr: false, }, { - name: "Test 2: Matching file exists for another address", + name: "Test 2: Matching file exists for upper case address", keystoreDir: testAccountsKeystorePath, - address: "0x2f5f59615689b706b6ad13fd03343dca28784989", + address: "0x2F5F59615689B706B6AD13FD03343DCA28784989", expectedFile: filepath.Join(testAccountsKeystorePath, "UTC--2024-03-20T07-04-11.601622000Z--2f5f59615689b706b6ad13fd03343dca28784989"), expectErr: false, }, @@ -288,8 +289,8 @@ func TestFindKeystoreFileForAddress(t *testing.T) { name: "Test 5: When multiple files for same account is present in the keystore directory", keystoreDir: "test_accounts/incorrect_test_accounts", address: "0x811654feb423363fb771e04e18d1e7325ae10a91", - expectedFile: filepath.Join("test_accounts/incorrect_test_accounts", "UTC--2024-03-20T07-04-56.358521000Z--811654feb423363fb771e04e18d1e7325ae10a91"), - expectErr: true, + expectedFile: filepath.Join("test_accounts/incorrect_test_accounts", "UTC--2024-03-20T07-03-56.358521000Z--811654feb423363fb771e04e18d1e7325ae10a91"), + expectErr: false, }, } From c0ff52cd27da75d5b9bac70e1a69e8180f4c7efc Mon Sep 17 00:00:00 2001 From: YashK Date: Wed, 27 Mar 2024 13:26:12 +0530 Subject: [PATCH 06/16] revert: optimised fetching key from keystore dir --- .github/workflows/ci.yml | 2 +- .github/workflows/develop.yml | 2 +- .github/workflows/release.yml | 2 +- accounts/accountUtils.go | 21 ++ accounts/accounts.go | 72 ++----- accounts/accounts_test.go | 193 +++++++++--------- accounts/mocks/account_interface.go | 118 +++++++++-- ...--911654feb423363fb771e04e18d1e7325ae10a91 | 1 - ...--2f5f59615689b706b6ad13fd03343dca28784989 | 1 - ...--811654feb423363fb771e04e18d1e7325ae10a91 | 1 - ...--811654feb423363fb771e04e18d1e7325ae10a91 | 1 - 11 files changed, 235 insertions(+), 179 deletions(-) delete mode 100644 accounts/test_accounts/UTC--2024-03-20T07-03-56.358521000Z--911654feb423363fb771e04e18d1e7325ae10a91 delete mode 100644 accounts/test_accounts/UTC--2024-03-20T07-04-11.601622000Z--2f5f59615689b706b6ad13fd03343dca28784989 delete mode 100644 accounts/test_accounts/incorrect_test_accounts/UTC--2024-03-20T07-03-56.358521000Z--811654feb423363fb771e04e18d1e7325ae10a91 delete mode 100644 accounts/test_accounts/incorrect_test_accounts/UTC--2024-03-20T07-04-56.358521000Z--811654feb423363fb771e04e18d1e7325ae10a91 diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5296ecdf5..c0e2167b2 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -60,7 +60,7 @@ jobs: - name: Execute test case run: > - go-acc ./... --ignore razor/accounts/mocks --ignore razor/accounts/test_accounts --ignore razor/cmd/mocks + go-acc ./... --ignore razor/accounts/mocks --ignore razor/cmd/mocks --ignore razor/utils/mocks --ignore pkg --ignore razor/path/mocks --output coverage.txt - name: Run benchmarks diff --git a/.github/workflows/develop.yml b/.github/workflows/develop.yml index d58e6337d..e9f4a9baf 100644 --- a/.github/workflows/develop.yml +++ b/.github/workflows/develop.yml @@ -61,7 +61,7 @@ jobs: golangci-lint run -v --timeout 5m - name: Execute test case run: | - go-acc ./... --ignore razor/accounts/mocks --ignore razor/accounts/test_accounts --ignore razor/cmd/mocks --ignore razor/cmd/eventListeners.go --ignore razor/utils/mocks --ignore pkg --ignore razor/path/mocks --output coverage.txt + go-acc ./... --ignore razor/accounts/mocks --ignore razor/cmd/mocks --ignore razor/cmd/eventListeners.go --ignore razor/utils/mocks --ignore pkg --ignore razor/path/mocks --output coverage.txt - name: Run benchmarks run: | go test ./... -bench=. -run=^# diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index b4c7e9acd..d13c625f4 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -58,7 +58,7 @@ jobs: golangci-lint run -v --timeout 5m - name: Execute test case run: | - go-acc ./... --ignore razor/accounts/mocks --ignore razor/accounts/test_accounts --ignore razor/cmd/mocks --ignore razor/utils/mocks --ignore pkg --ignore razor/path/mocks --output coverage.txt + go-acc ./... --ignore razor/accounts/mocks --ignore razor/cmd/mocks --ignore razor/utils/mocks --ignore pkg --ignore razor/path/mocks --output coverage.txt - name: Run benchmarks run: | go test ./... -bench=. -run=^# diff --git a/accounts/accountUtils.go b/accounts/accountUtils.go index bfa234ff6..11f8a5f10 100644 --- a/accounts/accountUtils.go +++ b/accounts/accountUtils.go @@ -6,6 +6,7 @@ import ( "github.com/ethereum/go-ethereum/accounts" "github.com/ethereum/go-ethereum/accounts/keystore" "github.com/ethereum/go-ethereum/crypto" + "os" "razor/core/types" ) @@ -15,14 +16,24 @@ 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) @@ -30,7 +41,17 @@ func (accountUtils AccountUtils) NewAccount(path string, passphrase string) (acc 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) +} + //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) } + +//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) +} diff --git a/accounts/accounts.go b/accounts/accounts.go index 8cb7de6b4..b907dfef9 100644 --- a/accounts/accounts.go +++ b/accounts/accounts.go @@ -4,15 +4,10 @@ package accounts import ( "crypto/ecdsa" "errors" - "fmt" "github.com/ethereum/go-ethereum/accounts" - "github.com/ethereum/go-ethereum/accounts/keystore" - "os" - "path/filepath" "razor/core/types" "razor/logger" "razor/path" - "regexp" "strings" ) @@ -33,30 +28,29 @@ func (AccountUtils) CreateAccount(keystorePath string, password string) accounts return newAcc } -//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, keystoreDirPath string) (*ecdsa.PrivateKey, error) { - fileName, err := FindKeystoreFileForAddress(keystoreDirPath, address) - if err != nil { - log.Error("Error in finding keystore file for an address: ", err) - return nil, err - } - - keyJson, err := os.ReadFile(fileName) +//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) if err != nil { log.Error("Error in reading keystore: ", err) return nil, err } - key, err := keystore.DecryptKey(keyJson, password) + key, err := AccountUtilsInterface.DecryptKey(jsonBytes, password) if err != nil { - log.Error("Error in decrypting private key: ", err) + log.Error("Error in fetching private key: ", err) return nil, err } + return key.PrivateKey, nil +} - // Check if the input address matches with address from keystore file in which password was matched - if strings.EqualFold(key.Address.Hex(), address) { - 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") } @@ -68,41 +62,3 @@ func (AccountUtils) SignData(hash []byte, account types.Account, defaultPath str } return AccountUtilsInterface.Sign(hash, privateKey) } - -// FindKeystoreFileForAddress matches the keystore file for the given address. -func FindKeystoreFileForAddress(keystoreDirPath, address string) (string, error) { - normalizedAddress := strings.ToLower(strings.TrimPrefix(address, "0x")) - regexPattern := fmt.Sprintf("^UTC--.*--%s$", regexp.QuoteMeta(normalizedAddress)) - re, err := regexp.Compile(regexPattern) - if err != nil { - log.Errorf("Error in compiling regex: %v", err) - return "", err - } - - var keystoreFilePath string - err = filepath.WalkDir(keystoreDirPath, func(path string, d os.DirEntry, err error) error { - if err != nil { - return err // Propagate errors encountered during traversal - } - if d.IsDir() { - return nil // Skip directories, continue walking - } - if re.MatchString(d.Name()) { // Check if file name matches the regex - keystoreFilePath = path - return filepath.SkipDir // File found, no need to continue - } - return nil - }) - - if err != nil { - log.Errorf("Error walking through keystore directory: %v", err) - return "", err - } - - if keystoreFilePath == "" { - log.Errorf("No matching keystore file found for address %s", address) - return "", errors.New("no matching keystore file found") - } - - return keystoreFilePath, nil -} diff --git a/accounts/accounts_test.go b/accounts/accounts_test.go index 7e0b860ca..aa964bf47 100644 --- a/accounts/accounts_test.go +++ b/accounts/accounts_test.go @@ -4,11 +4,11 @@ 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" - "path/filepath" "razor/accounts/mocks" "razor/core/types" "razor/path" @@ -116,69 +116,140 @@ func TestCreateAccount(t *testing.T) { } } -func TestGetPrivateKey(t *testing.T) { - password := "Razor@123" - keystoreDirPath := "test_accounts" +func TestGetPrivateKeyFromKeystore(t *testing.T) { + var password string + var keystorePath string + var privateKey *ecdsa.PrivateKey + var jsonBytes []byte type args struct { - address string - password string - keystoreDirPath string + jsonBytes []byte + jsonBytesErr error + key *keystore.Key + keyErr error } tests := []struct { name string args args + want *ecdsa.PrivateKey wantErr bool }{ { - name: "Test 1: When input address with correct password is present in keystore directory", + name: "Test 1: When GetPrivateKey function executes successfully", args: args{ - address: "0x911654feb423363fb771e04e18d1e7325ae10a91", - password: password, - keystoreDirPath: keystoreDirPath, + jsonBytes: jsonBytes, + key: &keystore.Key{ + PrivateKey: privateKey, + }, }, + want: privateKey, wantErr: false, }, { - name: "Test 2: When input upper case address with correct password is present in keystore directory", + name: "Test 2: When there is an error in reading data from file", args: args{ - address: "0x2F5F59615689B706B6AD13FD03343DCA28784989", - password: password, - keystoreDirPath: keystoreDirPath, + jsonBytesErr: errors.New("error in reading data"), + key: &keystore.Key{ + PrivateKey: nil, + }, }, - wantErr: false, + want: nil, + wantErr: true, }, { - name: "Test 3: When provided address is not present in keystore directory", + name: "Test 3: When there is an error in fetching private key", args: args{ - address: "0x911654feb423363fb771e04e18d1e7325ae10a91_not_present", - keystoreDirPath: keystoreDirPath, + jsonBytes: jsonBytes, + key: &keystore.Key{ + PrivateKey: nil, + }, + keyErr: errors.New("private key error"), }, + want: privateKey, 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) + } + if (err != nil) != tt.wantErr { + t.Errorf("GetPrivateKeyFromKeystore() error = %v, wantErr %v", err, tt.wantErr) + return + } + }) + } +} + +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"}, + }, + } + + type args struct { + address string + accounts []accounts.Account + privateKey *ecdsa.PrivateKey + } + tests := []struct { + name string + args args + want *ecdsa.PrivateKey + wantErr bool + }{ { - name: "Test 4: When input address with incorrect password is present in keystore directory", + name: "Test 1: When input address is present in accountsList", args: args{ - address: "0x911654feb423363fb771e04e18d1e7325ae10a91", - password: "incorrect password", - keystoreDirPath: keystoreDirPath, + address: "0x000000000000000000000000000000000000dea1", + accounts: accountsList, + privateKey: privateKey, }, - wantErr: true, + want: privateKey, + wantErr: false, }, { - name: "Test 5: When a keystore file is renamed differently from the address to which it belonged", + name: "Test 2: When input address is not present in accountsList", args: args{ - address: "0x811654feb423363fb771e04e18d1e7325ae10a91", - password: password, - keystoreDirPath: "test_accounts/incorrect_test_accounts", + address: "0x000000000000000000000000000000000000dea3", + accounts: accountsList, + privateKey: privateKey, }, + want: nil, 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{} - _, err := accountUtils.GetPrivateKey(tt.args.address, tt.args.password, tt.args.keystoreDirPath) + 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) + } if (err != nil) != tt.wantErr { t.Errorf("GetPrivateKey() error = %v, wantErr %v", err, tt.wantErr) return @@ -248,67 +319,3 @@ func TestSignData(t *testing.T) { }) } } - -func TestFindKeystoreFileForAddress(t *testing.T) { - testAccountsKeystorePath := "test_accounts" - - tests := []struct { - name string - keystoreDir string - address string - expectedFile string - expectErr bool - }{ - { - name: "Test 1: Matching file exists for an address", - keystoreDir: testAccountsKeystorePath, - address: "0x911654feb423363fb771e04e18d1e7325ae10a91", - expectedFile: filepath.Join(testAccountsKeystorePath, "UTC--2024-03-20T07-03-56.358521000Z--911654feb423363fb771e04e18d1e7325ae10a91"), - expectErr: false, - }, - { - name: "Test 2: Matching file exists for upper case address", - keystoreDir: testAccountsKeystorePath, - address: "0x2F5F59615689B706B6AD13FD03343DCA28784989", - expectedFile: filepath.Join(testAccountsKeystorePath, "UTC--2024-03-20T07-04-11.601622000Z--2f5f59615689b706b6ad13fd03343dca28784989"), - expectErr: false, - }, - { - name: "Test 3: No matching file", - keystoreDir: testAccountsKeystorePath, - address: "nonexistentaddress", - expectErr: true, - }, - { - name: "Test 4: When keystore directory doesnt exists", - keystoreDir: "test_accounts_invalid", - address: "0x2f5f59615689b706b6ad13fd03343dca28784989", - expectErr: true, - }, - { - name: "Test 5: When multiple files for same account is present in the keystore directory", - keystoreDir: "test_accounts/incorrect_test_accounts", - address: "0x811654feb423363fb771e04e18d1e7325ae10a91", - expectedFile: filepath.Join("test_accounts/incorrect_test_accounts", "UTC--2024-03-20T07-03-56.358521000Z--811654feb423363fb771e04e18d1e7325ae10a91"), - expectErr: false, - }, - } - - for _, tc := range tests { - t.Run(tc.name, func(t *testing.T) { - got, err := FindKeystoreFileForAddress(tc.keystoreDir, tc.address) - if tc.expectErr { - if err == nil { - t.Errorf("Expected an error but got none") - } - } else { - if err != nil { - t.Errorf("Did not expect an error but got one: %v", err) - } - if got != tc.expectedFile { - t.Errorf("Expected file %v, got %v", tc.expectedFile, got) - } - } - }) - } -} diff --git a/accounts/mocks/account_interface.go b/accounts/mocks/account_interface.go index ed1e4b9f5..e8e006441 100644 --- a/accounts/mocks/account_interface.go +++ b/accounts/mocks/account_interface.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.30.1. DO NOT EDIT. +// Code generated by mockery v2.14.0. DO NOT EDIT. package mocks @@ -7,6 +7,8 @@ import ( 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" @@ -17,6 +19,22 @@ 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) @@ -31,15 +49,34 @@ func (_m *AccountInterface) CreateAccount(path string, password string) accounts 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 - var r1 error - if rf, ok := ret.Get(0).(func(string, string, string) (*ecdsa.PrivateKey, error)); ok { - return rf(address, password, keystorePath) - } if rf, ok := ret.Get(0).(func(string, string, string) *ecdsa.PrivateKey); ok { r0 = rf(address, password, keystorePath) } else { @@ -48,6 +85,7 @@ func (_m *AccountInterface) GetPrivateKey(address string, password string, keyst } } + var r1 error if rf, ok := ret.Get(1).(func(string, string, string) error); ok { r1 = rf(address, password, keystorePath) } else { @@ -57,21 +95,41 @@ func (_m *AccountInterface) GetPrivateKey(address string, password string, keyst 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 - var r1 error - if rf, ok := ret.Get(0).(func(string, string) (accounts.Account, error)); ok { - return rf(path, passphrase) - } 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 { @@ -81,15 +139,34 @@ func (_m *AccountInterface) NewAccount(path string, passphrase string) (accounts 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 - var r1 error - if rf, ok := ret.Get(0).(func([]byte, *ecdsa.PrivateKey) ([]byte, error)); ok { - return rf(digestHash, prv) - } if rf, ok := ret.Get(0).(func([]byte, *ecdsa.PrivateKey) []byte); ok { r0 = rf(digestHash, prv) } else { @@ -98,6 +175,7 @@ func (_m *AccountInterface) Sign(digestHash []byte, prv *ecdsa.PrivateKey) ([]by } } + var r1 error if rf, ok := ret.Get(1).(func([]byte, *ecdsa.PrivateKey) error); ok { r1 = rf(digestHash, prv) } else { @@ -112,10 +190,6 @@ func (_m *AccountInterface) SignData(hash []byte, account types.Account, default ret := _m.Called(hash, account, defaultPath) var r0 []byte - var r1 error - if rf, ok := ret.Get(0).(func([]byte, types.Account, string) ([]byte, error)); ok { - return rf(hash, account, defaultPath) - } if rf, ok := ret.Get(0).(func([]byte, types.Account, string) []byte); ok { r0 = rf(hash, account, defaultPath) } else { @@ -124,6 +198,7 @@ func (_m *AccountInterface) SignData(hash []byte, account types.Account, default } } + var r1 error if rf, ok := ret.Get(1).(func([]byte, types.Account, string) error); ok { r1 = rf(hash, account, defaultPath) } else { @@ -133,12 +208,13 @@ func (_m *AccountInterface) SignData(hash []byte, account types.Account, default return r0, r1 } -// 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. -// The first argument is typically a *testing.T value. -func NewAccountInterface(t interface { +type mockConstructorTestingTNewAccountInterface interface { mock.TestingT Cleanup(func()) -}) *AccountInterface { +} + +// 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) 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 deleted file mode 100644 index bc50d72f6..000000000 --- a/accounts/test_accounts/UTC--2024-03-20T07-03-56.358521000Z--911654feb423363fb771e04e18d1e7325ae10a91 +++ /dev/null @@ -1 +0,0 @@ -{"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 deleted file mode 100644 index c773f086e..000000000 --- a/accounts/test_accounts/UTC--2024-03-20T07-04-11.601622000Z--2f5f59615689b706b6ad13fd03343dca28784989 +++ /dev/null @@ -1 +0,0 @@ -{"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/accounts/test_accounts/incorrect_test_accounts/UTC--2024-03-20T07-03-56.358521000Z--811654feb423363fb771e04e18d1e7325ae10a91 b/accounts/test_accounts/incorrect_test_accounts/UTC--2024-03-20T07-03-56.358521000Z--811654feb423363fb771e04e18d1e7325ae10a91 deleted file mode 100644 index bc50d72f6..000000000 --- a/accounts/test_accounts/incorrect_test_accounts/UTC--2024-03-20T07-03-56.358521000Z--811654feb423363fb771e04e18d1e7325ae10a91 +++ /dev/null @@ -1 +0,0 @@ -{"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/incorrect_test_accounts/UTC--2024-03-20T07-04-56.358521000Z--811654feb423363fb771e04e18d1e7325ae10a91 b/accounts/test_accounts/incorrect_test_accounts/UTC--2024-03-20T07-04-56.358521000Z--811654feb423363fb771e04e18d1e7325ae10a91 deleted file mode 100644 index bc50d72f6..000000000 --- a/accounts/test_accounts/incorrect_test_accounts/UTC--2024-03-20T07-04-56.358521000Z--811654feb423363fb771e04e18d1e7325ae10a91 +++ /dev/null @@ -1 +0,0 @@ -{"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 From 7db8cd267ae7d61bef6015aed14056a5e0b1998d Mon Sep 17 00:00:00 2001 From: YashK Date: Wed, 27 Mar 2024 14:27:21 +0530 Subject: [PATCH 07/16] fix: reused same keystore instance for fetching pkey every time --- accounts/accountUtils.go | 14 -------------- accounts/accounts.go | 29 ++++++++++++++++++++++------- 2 files changed, 22 insertions(+), 21 deletions(-) diff --git a/accounts/accountUtils.go b/accounts/accountUtils.go index 11f8a5f10..611b98b1c 100644 --- a/accounts/accountUtils.go +++ b/accounts/accountUtils.go @@ -6,7 +6,6 @@ import ( "github.com/ethereum/go-ethereum/accounts" "github.com/ethereum/go-ethereum/accounts/keystore" "github.com/ethereum/go-ethereum/crypto" - "os" "razor/core/types" ) @@ -16,14 +15,11 @@ 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{} @@ -41,17 +37,7 @@ func (accountUtils AccountUtils) NewAccount(path string, passphrase string) (acc 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) -} - //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) } - -//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) -} diff --git a/accounts/accounts.go b/accounts/accounts.go index b907dfef9..36f9d0fe0 100644 --- a/accounts/accounts.go +++ b/accounts/accounts.go @@ -5,13 +5,24 @@ import ( "crypto/ecdsa" "errors" "github.com/ethereum/go-ethereum/accounts" + "github.com/ethereum/go-ethereum/accounts/keystore" + "os" "razor/core/types" "razor/logger" "razor/path" "strings" ) -var log = logger.NewLogger() +var ( + log = logger.NewLogger() + ksInstance *keystore.KeyStore +) + +// InitializeKeystore directly initializes the global keystore instance. +func initializeKeystore(keystorePath string) { + log.Info("Initialising keystoreInstance...") + ksInstance = keystore.NewKeyStore(keystorePath, keystore.StandardScryptN, keystore.StandardScryptP) +} //This function takes path and password as input and returns new account func (AccountUtils) CreateAccount(keystorePath string, password string) accounts.Account { @@ -29,13 +40,13 @@ func (AccountUtils) CreateAccount(keystorePath string, password string) accounts } //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 @@ -44,11 +55,15 @@ func (AccountUtils) GetPrivateKeyFromKeystore(keystorePath string, password stri } //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) +func (AccountUtils) GetPrivateKey(address string, password string, keystoreDirPath string) (*ecdsa.PrivateKey, error) { + if ksInstance == nil { + initializeKeystore(keystoreDirPath) + } + + allAccounts := ksInstance.Accounts() for _, account := range allAccounts { if strings.EqualFold(account.Address.Hex(), address) { - return AccountUtilsInterface.GetPrivateKeyFromKeystore(account.URL.Path, password) + return getPrivateKeyFromKeystore(account.URL.Path, password) } } return nil, errors.New("no keystore file found") From 2a20886029e6a438686a8c420f23af41893645db Mon Sep 17 00:00:00 2001 From: YashK Date: Wed, 27 Mar 2024 14:28:22 +0530 Subject: [PATCH 08/16] refactor: added realistic tests for fetching of pKey --- accounts/accounts_test.go | 120 +++++++----------- accounts/mocks/account_interface.go | 102 +++------------ ...--911654feb423363fb771e04e18d1e7325ae10a91 | 1 + ...--2f5f59615689b706b6ad13fd03343dca28784989 | 1 + 4 files changed, 68 insertions(+), 156 deletions(-) create mode 100644 accounts/test_accounts/UTC--2024-03-20T07-03-56.358521000Z--911654feb423363fb771e04e18d1e7325ae10a91 create mode 100644 accounts/test_accounts/UTC--2024-03-20T07-04-11.601622000Z--2f5f59615689b706b6ad13fd03343dca28784989 diff --git a/accounts/accounts_test.go b/accounts/accounts_test.go index aa964bf47..3e288ad6f 100644 --- a/accounts/accounts_test.go +++ b/accounts/accounts_test.go @@ -4,7 +4,6 @@ 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" @@ -116,17 +115,12 @@ func TestCreateAccount(t *testing.T) { } } -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 @@ -135,54 +129,35 @@ func TestGetPrivateKeyFromKeystore(t *testing.T) { 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, 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, 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, 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) - } + _, err := getPrivateKeyFromKeystore(tt.args.keystoreFilePath, tt.args.password) if (err != nil) != tt.wantErr { t.Errorf("GetPrivateKeyFromKeystore() error = %v, wantErr %v", err, tt.wantErr) return @@ -192,64 +167,59 @@ func TestGetPrivateKeyFromKeystore(t *testing.T) { } 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 + keystoreDirPath string } tests := []struct { name string args args - want *ecdsa.PrivateKey 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: "0x000000000000000000000000000000000000dea1", - accounts: accountsList, - privateKey: privateKey, + address: "0x911654feb423363fb771e04e18d1e7325ae10a91", + password: password, + keystoreDirPath: keystoreDirPath, }, - want: privateKey, wantErr: false, }, { - name: "Test 2: When input address is not present in accountsList", + name: "Test 2: When input upper case address with correct password is present in keystore directory", args: args{ - address: "0x000000000000000000000000000000000000dea3", - accounts: accountsList, - privateKey: privateKey, + address: "0x2F5F59615689B706B6AD13FD03343DCA28784989", + password: password, + keystoreDirPath: keystoreDirPath, + }, + wantErr: false, + }, + { + name: "Test 3: When provided address is not present in keystore directory", + args: args{ + address: "0x911654feb423363fb771e04e18d1e7325ae10a91_not_present", + keystoreDirPath: keystoreDirPath, + }, + wantErr: true, + }, + { + name: "Test 4: When input address with incorrect password is present in keystore directory", + args: args{ + address: "0x911654feb423363fb771e04e18d1e7325ae10a91", + password: "incorrect password", + keystoreDirPath: keystoreDirPath, }, - want: nil, 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) - } + _, err := accountUtils.GetPrivateKey(tt.args.address, tt.args.password, tt.args.keystoreDirPath) if (err != nil) != tt.wantErr { t.Errorf("GetPrivateKey() error = %v, wantErr %v", err, tt.wantErr) return diff --git a/accounts/mocks/account_interface.go b/accounts/mocks/account_interface.go index e8e006441..53570c318 100644 --- a/accounts/mocks/account_interface.go +++ b/accounts/mocks/account_interface.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.14.0. DO NOT EDIT. +// Code generated by mockery v2.30.1. DO NOT EDIT. package mocks @@ -7,8 +7,6 @@ import ( 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" @@ -49,34 +47,15 @@ func (_m *AccountInterface) CreateAccount(path string, password string) accounts 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 + var r1 error + if rf, ok := ret.Get(0).(func(string, string, string) (*ecdsa.PrivateKey, error)); ok { + return rf(address, password, keystorePath) + } if rf, ok := ret.Get(0).(func(string, string, string) *ecdsa.PrivateKey); ok { r0 = rf(address, password, keystorePath) } else { @@ -85,7 +64,6 @@ func (_m *AccountInterface) GetPrivateKey(address string, password string, keyst } } - var r1 error if rf, ok := ret.Get(1).(func(string, string, string) error); ok { r1 = rf(address, password, keystorePath) } else { @@ -95,41 +73,21 @@ func (_m *AccountInterface) GetPrivateKey(address string, password string, keyst 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 + var r1 error + if rf, ok := ret.Get(0).(func(string, string) (accounts.Account, error)); ok { + return rf(path, passphrase) + } 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 { @@ -139,34 +97,15 @@ func (_m *AccountInterface) NewAccount(path string, passphrase string) (accounts 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 + var r1 error + if rf, ok := ret.Get(0).(func([]byte, *ecdsa.PrivateKey) ([]byte, error)); ok { + return rf(digestHash, prv) + } if rf, ok := ret.Get(0).(func([]byte, *ecdsa.PrivateKey) []byte); ok { r0 = rf(digestHash, prv) } else { @@ -175,7 +114,6 @@ func (_m *AccountInterface) Sign(digestHash []byte, prv *ecdsa.PrivateKey) ([]by } } - var r1 error if rf, ok := ret.Get(1).(func([]byte, *ecdsa.PrivateKey) error); ok { r1 = rf(digestHash, prv) } else { @@ -190,6 +128,10 @@ func (_m *AccountInterface) SignData(hash []byte, account types.Account, default ret := _m.Called(hash, account, defaultPath) var r0 []byte + var r1 error + if rf, ok := ret.Get(0).(func([]byte, types.Account, string) ([]byte, error)); ok { + return rf(hash, account, defaultPath) + } if rf, ok := ret.Get(0).(func([]byte, types.Account, string) []byte); ok { r0 = rf(hash, account, defaultPath) } else { @@ -198,7 +140,6 @@ func (_m *AccountInterface) SignData(hash []byte, account types.Account, default } } - var r1 error if rf, ok := ret.Get(1).(func([]byte, types.Account, string) error); ok { r1 = rf(hash, account, defaultPath) } else { @@ -208,13 +149,12 @@ func (_m *AccountInterface) SignData(hash []byte, account types.Account, default return r0, r1 } -type mockConstructorTestingTNewAccountInterface interface { +// 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. +// The first argument is typically a *testing.T value. +func NewAccountInterface(t 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 { +}) *AccountInterface { mock := &AccountInterface{} mock.Mock.Test(t) 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 From 95d4a584d89282cb14d1b1e9b7cf0157659fff2a Mon Sep 17 00:00:00 2001 From: YashK Date: Wed, 27 Mar 2024 18:08:59 +0530 Subject: [PATCH 09/16] refactor: removed unused accounts() from interface --- accounts/accountUtils.go | 7 ------- accounts/mocks/account_interface.go | 16 ---------------- 2 files changed, 23 deletions(-) diff --git a/accounts/accountUtils.go b/accounts/accountUtils.go index 611b98b1c..bfa234ff6 100644 --- a/accounts/accountUtils.go +++ b/accounts/accountUtils.go @@ -17,19 +17,12 @@ type AccountInterface interface { CreateAccount(path string, password string) accounts.Account 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) Sign(digestHash []byte, prv *ecdsa.PrivateKey) ([]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) diff --git a/accounts/mocks/account_interface.go b/accounts/mocks/account_interface.go index 53570c318..ed1e4b9f5 100644 --- a/accounts/mocks/account_interface.go +++ b/accounts/mocks/account_interface.go @@ -17,22 +17,6 @@ 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) From 8bd27541a4b3608f72f2902ee7d4bfb0b6581ed7 Mon Sep 17 00:00:00 2001 From: YashK Date: Fri, 5 Apr 2024 10:21:52 +0530 Subject: [PATCH 10/16] refactor: used AccountManager struct with a keystore as a method caller --- accounts/accountUtils.go | 42 +++++++++++++-------------- accounts/accounts.go | 54 ++++++++++++++++------------------- cmd/addStake.go | 19 +++++++----- cmd/approve.go | 2 +- cmd/claimBounty.go | 23 +++++++-------- cmd/claimCommission.go | 11 +++++-- cmd/commit.go | 3 +- cmd/confirm.go | 2 +- cmd/create.go | 5 +++- cmd/createCollection.go | 15 ++++++---- cmd/createJob.go | 16 +++++++---- cmd/delegate.go | 20 +++++++------ cmd/dispute.go | 29 +++++++++---------- cmd/initiateWithdraw.go | 18 ++++++------ cmd/interface.go | 2 -- cmd/modifyCollectionStatus.go | 15 ++++++---- cmd/propose.go | 3 +- cmd/resetUnstakeLock.go | 16 +++++++---- cmd/reveal.go | 3 +- cmd/setDelegation.go | 19 ++++++------ cmd/struct-utils.go | 17 ++++------- cmd/test_utils_test.go | 8 +----- cmd/transfer.go | 23 ++++++++------- cmd/unlockWithdraw.go | 19 ++++++------ cmd/unstake.go | 25 +++++++++------- cmd/unstake_test.go | 6 ++-- cmd/updateCollection.go | 15 ++++++---- cmd/updateCommission.go | 17 ++++++----- cmd/updateJob.go | 15 ++++++---- cmd/vote.go | 14 +++++---- core/types/account.go | 17 +++++++++-- core/types/inputs.go | 33 ++++++++------------- core/types/transaction.go | 3 +- utils/common.go | 23 +++++++++------ utils/interface.go | 12 ++------ utils/options.go | 17 ++++++----- utils/struct-utils.go | 6 ---- 37 files changed, 304 insertions(+), 283 deletions(-) diff --git a/accounts/accountUtils.go b/accounts/accountUtils.go index bfa234ff6..cec72c5d6 100644 --- a/accounts/accountUtils.go +++ b/accounts/accountUtils.go @@ -2,35 +2,33 @@ package accounts import ( - "crypto/ecdsa" - "github.com/ethereum/go-ethereum/accounts" "github.com/ethereum/go-ethereum/accounts/keystore" - "github.com/ethereum/go-ethereum/crypto" "razor/core/types" ) -//go:generate mockery --name AccountInterface --output ./mocks/ --case=underscore +//type AccountInterface interface { +// CreateAccount(keystorePath, password string) accounts.Account +// GetPrivateKey(address, password string) (*ecdsa.PrivateKey, error) +// SignData(hash []byte, account types.Account) ([]byte, error) +// NewAccount(passphrase string) (accounts.Account, error) +//} -var AccountUtilsInterface AccountInterface - -type AccountInterface interface { - CreateAccount(path string, password string) accounts.Account - GetPrivateKey(address string, password string, keystorePath string) (*ecdsa.PrivateKey, error) - SignData(hash []byte, account types.Account, defaultPath string) ([]byte, error) - NewAccount(path string, passphrase string) (accounts.Account, error) - Sign(digestHash []byte, prv *ecdsa.PrivateKey) ([]byte, error) +type AccountManager struct { + Keystore *keystore.KeyStore } -type AccountUtils struct{} - -//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) +func NewAccountManager(keystorePath string) *AccountManager { + ks := keystore.NewKeyStore(keystorePath, keystore.StandardScryptN, keystore.StandardScryptP) + return &AccountManager{ + Keystore: ks, + } } -//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) +// 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 36f9d0fe0..97681ee5e 100644 --- a/accounts/accounts.go +++ b/accounts/accounts.go @@ -6,39 +6,50 @@ import ( "errors" "github.com/ethereum/go-ethereum/accounts" "github.com/ethereum/go-ethereum/accounts/keystore" + "github.com/ethereum/go-ethereum/crypto" "os" - "razor/core/types" "razor/logger" "razor/path" "strings" ) var ( - log = logger.NewLogger() - ksInstance *keystore.KeyStore + log = logger.NewLogger() ) -// InitializeKeystore directly initializes the global keystore instance. -func initializeKeystore(keystorePath string) { - log.Info("Initialising keystoreInstance...") - ksInstance = keystore.NewKeyStore(keystorePath, keystore.StandardScryptN, keystore.StandardScryptP) -} - //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 getPrivateKeyFromKeystore(keystoreFilePath string, password string) (*ecdsa.PrivateKey, error) { jsonBytes, err := os.ReadFile(keystoreFilePath) @@ -54,26 +65,11 @@ func getPrivateKeyFromKeystore(keystoreFilePath string, password string) (*ecdsa 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, keystoreDirPath string) (*ecdsa.PrivateKey, error) { - if ksInstance == nil { - initializeKeystore(keystoreDirPath) - } - - allAccounts := ksInstance.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 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/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/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/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/commit.go b/cmd/commit.go index e7148975c..a4ba33cc7 100644 --- a/cmd/commit.go +++ b/cmd/commit.go @@ -163,14 +163,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/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..4628b1b5d 100644 --- a/cmd/create.go +++ b/cmd/create.go @@ -49,8 +49,11 @@ 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() + utils.CheckError("Error in getting accounts manager for keystore: ", 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/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/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/dispute.go b/cmd/dispute.go index 539d9e802..c0ebf58ce 100644 --- a/cmd/dispute.go +++ b/cmd/dispute.go @@ -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) @@ -322,11 +320,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) { @@ -427,7 +424,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/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/interface.go b/cmd/interface.go index 3c2392540..9af5c3619 100644 --- a/cmd/interface.go +++ b/cmd/interface.go @@ -5,7 +5,6 @@ import ( "context" "crypto/ecdsa" "math/big" - Accounts "razor/accounts" "razor/core/types" "razor/path" "razor/pkg/bindings" @@ -313,7 +312,6 @@ func InitializeInterfaces() { abiUtils = AbiUtils{} osUtils = OSUtils{} - Accounts.AccountUtilsInterface = Accounts.AccountUtils{} path.PathUtilsInterface = path.PathUtils{} path.OSUtilsInterface = path.OSUtils{} InitializeUtils() 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/propose.go b/cmd/propose.go index 60b9cb42b..4cf8e6f0d 100644 --- a/cmd/propose.go +++ b/cmd/propose.go @@ -145,14 +145,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) 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/reveal.go b/cmd/reveal.go index 4d3ca69b3..bf9b3efb2 100644 --- a/cmd/reveal.go +++ b/cmd/reveal.go @@ -58,14 +58,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/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/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..ea157cb2e 100644 --- a/cmd/test_utils_test.go +++ b/cmd/test_utils_test.go @@ -52,7 +52,7 @@ var ( osMock *mocks.OSInterface pathMock *pathPkgMocks.PathInterface osPathMock *pathPkgMocks.OSInterface - accountsMock *accountsPkgMocks.AccountInterface + accountsMock *accountsPkgMocks.AccountManagerInterface ) func SetUpMockInterfaces() { @@ -89,9 +89,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 +166,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/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/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..24447c235 100644 --- a/cmd/unstake_test.go +++ b/cmd/unstake_test.go @@ -23,8 +23,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 +133,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, }) 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/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/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/vote.go b/cmd/vote.go index 2e3739718..10c4db843 100644 --- a/cmd/vote.go +++ b/cmd/vote.go @@ -62,7 +62,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,8 +91,6 @@ 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} - cmdUtils.HandleExit() 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 { @@ -280,13 +283,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 { @@ -575,7 +577,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/core/types/account.go b/core/types/account.go index 5d230f53d..2d2c63519 100644 --- a/core/types/account.go +++ b/core/types/account.go @@ -1,6 +1,19 @@ package types +import ( + "crypto/ecdsa" + "github.com/ethereum/go-ethereum/accounts" +) + 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/utils/common.go b/utils/common.go index 164c3a74a..155d0500b 100644 --- a/utils/common.go +++ b/utils/common.go @@ -6,6 +6,7 @@ import ( "math/big" "os" "path/filepath" + "razor/accounts" "razor/core" "razor/core/types" "razor/logger" @@ -379,14 +380,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 +389,15 @@ func (*UtilsStruct) CheckPassword(address string, password string) error { } return nil } + +func (*UtilsStruct) AccountManagerForKeystore() (*accounts.AccountManager, error) { + razorPath, err := PathInterface.GetDefaultPath() + if err != nil { + log.Error("GetKeystorePath: Error in getting .razor path: ", err) + return &accounts.AccountManager{}, err + } + keystorePath := filepath.Join(razorPath, "keystore_files") + + accountManager := accounts.NewAccountManager(keystorePath) + return accountManager, nil +} diff --git a/utils/interface.go b/utils/interface.go index 77304e2d8..0a41e4f11 100644 --- a/utils/interface.go +++ b/utils/interface.go @@ -7,6 +7,7 @@ import ( "io/fs" "math/big" "os" + "razor/accounts" "razor/cache" "razor/core/types" "razor/pkg/bindings" @@ -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 @@ -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() (*accounts.AccountManager, error) } type EthClientUtils interface { @@ -218,10 +218,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 +318,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 +342,6 @@ type OptionsPackageStruct struct { ABIInterface ABIUtils PathInterface PathUtils BindInterface BindUtils - AccountsInterface AccountsUtils BlockManagerInterface BlockManagerUtils StakeManagerInterface StakeManagerUtils AssetManagerInterface AssetManagerUtils 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/struct-utils.go b/utils/struct-utils.go index 4eb404a85..2e5aeac85 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" @@ -42,7 +41,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 +247,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) From 36b1c618a24310988e1d83d620a9489eb099baf6 Mon Sep 17 00:00:00 2001 From: YashK Date: Fri, 5 Apr 2024 13:07:45 +0530 Subject: [PATCH 11/16] refactor: fix tests --- accounts/accounts_test.go | 284 +++++++++++++--------------- accounts/mocks/account_interface.go | 148 --------------- cmd/addStake_test.go | 4 +- cmd/claimBounty_test.go | 4 +- cmd/claimCommission_test.go | 4 +- cmd/createCollection_test.go | 4 +- cmd/createJob_test.go | 4 +- cmd/create_test.go | 75 +------- cmd/delegate_test.go | 4 +- cmd/initiateWithdraw_test.go | 4 +- cmd/modifyCollectionStatus_test.go | 4 +- cmd/resetUnstakeLock_test.go | 4 +- cmd/setDelegation_test.go | 4 +- cmd/test_utils_test.go | 7 +- cmd/transfer_test.go | 4 +- cmd/unlockWithdraw_test.go | 4 +- cmd/unstake_test.go | 4 +- cmd/updateCollection_test.go | 4 +- cmd/updateCommission_test.go | 4 +- cmd/updateJob_test.go | 4 +- cmd/vote_test.go | 9 +- utils/common_test.go | 99 ++++++++++ utils/mocks/utils.go | 40 +++- utils/options_test.go | 125 ++++++------ 24 files changed, 395 insertions(+), 456 deletions(-) delete mode 100644 accounts/mocks/account_interface.go diff --git a/accounts/accounts_test.go b/accounts/accounts_test.go index 3e288ad6f..f148d1893 100644 --- a/accounts/accounts_test.go +++ b/accounts/accounts_test.go @@ -2,118 +2,108 @@ package accounts import ( "crypto/ecdsa" - "errors" - "github.com/ethereum/go-ethereum/accounts" - "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 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.AccountManagerInterface) +// osMock := new(mocks1.OSInterface) +// +// path.OSUtilsInterface = osMock +// +// 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) +// +// fatal = false +// +// got := accountsMock.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 Test_getPrivateKeyFromKeystore(t *testing.T) { password := "Razor@123" @@ -171,9 +161,8 @@ func TestGetPrivateKey(t *testing.T) { keystoreDirPath := "test_accounts" type args struct { - address string - password string - keystoreDirPath string + address string + password string } tests := []struct { name string @@ -183,43 +172,39 @@ func TestGetPrivateKey(t *testing.T) { { name: "Test 1: When input address with correct password is present in keystore directory", args: args{ - address: "0x911654feb423363fb771e04e18d1e7325ae10a91", - password: password, - keystoreDirPath: keystoreDirPath, + address: "0x911654feb423363fb771e04e18d1e7325ae10a91", + password: password, }, wantErr: false, }, { name: "Test 2: When input upper case address with correct password is present in keystore directory", args: args{ - address: "0x2F5F59615689B706B6AD13FD03343DCA28784989", - password: password, - keystoreDirPath: keystoreDirPath, + address: "0x2F5F59615689B706B6AD13FD03343DCA28784989", + password: password, }, wantErr: false, }, { name: "Test 3: When provided address is not present in keystore directory", args: args{ - address: "0x911654feb423363fb771e04e18d1e7325ae10a91_not_present", - keystoreDirPath: keystoreDirPath, + address: "0x911654feb423363fb771e04e18d1e7325ae10a91_not_present", }, wantErr: true, }, { name: "Test 4: When input address with incorrect password is present in keystore directory", args: args{ - address: "0x911654feb423363fb771e04e18d1e7325ae10a91", - password: "incorrect password", - keystoreDirPath: keystoreDirPath, + address: "0x911654feb423363fb771e04e18d1e7325ae10a91", + password: "incorrect password", }, wantErr: true, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - accountUtils := &AccountUtils{} - _, err := accountUtils.GetPrivateKey(tt.args.address, tt.args.password, tt.args.keystoreDirPath) + am := NewAccountManager(keystoreDirPath) + _, 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 @@ -229,57 +214,52 @@ func TestGetPrivateKey(t *testing.T) { } 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 ed1e4b9f5..000000000 --- a/accounts/mocks/account_interface.go +++ /dev/null @@ -1,148 +0,0 @@ -// 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" - - types "razor/core/types" -) - -// AccountInterface is an autogenerated mock type for the AccountInterface type -type AccountInterface struct { - mock.Mock -} - -// 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 -} - -// 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 - var r1 error - if rf, ok := ret.Get(0).(func(string, string, string) (*ecdsa.PrivateKey, error)); ok { - return rf(address, password, keystorePath) - } - 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) - } - } - - 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 -} - -// 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 - var r1 error - if rf, ok := ret.Get(0).(func(string, string) (accounts.Account, error)); ok { - return rf(path, passphrase) - } - if rf, ok := ret.Get(0).(func(string, string) accounts.Account); ok { - r0 = rf(path, passphrase) - } else { - r0 = ret.Get(0).(accounts.Account) - } - - if rf, ok := ret.Get(1).(func(string, string) error); ok { - r1 = rf(path, passphrase) - } 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 - var r1 error - if rf, ok := ret.Get(0).(func([]byte, *ecdsa.PrivateKey) ([]byte, error)); ok { - return rf(digestHash, prv) - } - 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) - } - } - - 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 - var r1 error - if rf, ok := ret.Get(0).(func([]byte, types.Account, string) ([]byte, error)); ok { - return rf(hash, account, defaultPath) - } - 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) - } - } - - 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 -} - -// 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. -// The first argument is typically a *testing.T value. -func NewAccountInterface(t interface { - mock.TestingT - Cleanup(func()) -}) *AccountInterface { - mock := &AccountInterface{} - mock.Mock.Test(t) - - t.Cleanup(func() { mock.AssertExpectations(t) }) - - return mock -} 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/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_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/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_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..b6ba0e167 100644 --- a/cmd/create_test.go +++ b/cmd/create_test.go @@ -11,79 +11,6 @@ import ( "github.com/stretchr/testify/mock" ) -func TestCreate(t *testing.T) { - var password string - - type args struct { - path string - pathErr error - account accounts.Account - } - tests := []struct { - name string - args args - want accounts.Account - wantErr error - }{ - { - name: "Test 1: When create function executes successfully", - args: args{ - path: "/home/local", - pathErr: nil, - 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"}, - }, - wantErr: nil, - }, - { - name: "Test 2: When create fails due to path error", - args: args{ - path: "/home/local", - pathErr: errors.New("path error"), - account: accounts.Account{Address: common.HexToAddress("0x000000000000000000000000000000000000dea1"), - 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"}, - }, - wantErr: errors.New("path error"), - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - SetUpMockInterfaces() - - 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"}, - }) - - utils := &UtilsStruct{} - got, err := utils.Create(password) - - if got.Address != tt.want.Address { - t.Errorf("New address created, got = %v, want %v", got, tt.want.Address) - } - - if err == nil || tt.wantErr == nil { - if err != tt.wantErr { - t.Errorf("Error for Create function, got = %v, want %v", got, tt.wantErr) - } - } else { - if err.Error() != tt.wantErr.Error() { - t.Errorf("Error for Create function, got = %v, want %v", got, tt.wantErr) - } - } - }) - } -} - func TestExecuteCreate(t *testing.T) { var flagSet *pflag.FlagSet @@ -131,7 +58,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_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/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/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/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/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/test_utils_test.go b/cmd/test_utils_test.go index ea157cb2e..24f9a78d2 100644 --- a/cmd/test_utils_test.go +++ b/cmd/test_utils_test.go @@ -6,7 +6,7 @@ import ( "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/crypto" "math/big" - accountsPkgMocks "razor/accounts/mocks" + //accountsPkgMocks "razor/accounts/mocks" "razor/cmd/mocks" "razor/path" pathPkgMocks "razor/path/mocks" @@ -24,7 +24,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 +51,7 @@ var ( osMock *mocks.OSInterface pathMock *pathPkgMocks.PathInterface osPathMock *pathPkgMocks.OSInterface - accountsMock *accountsPkgMocks.AccountManagerInterface + //accountsMock *accountsPkgMocks.AccountManagerInterface ) func SetUpMockInterfaces() { @@ -166,6 +165,8 @@ func SetUpMockInterfaces() { osPathMock = new(pathPkgMocks.OSInterface) path.OSUtilsInterface = osPathMock + + //accountsMock = new(accountsPkgMocks.AccountManagerInterface) } var privateKey, _ = ecdsa.GenerateKey(crypto.S256(), rand.Reader) 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_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_test.go b/cmd/unstake_test.go index 24447c235..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" @@ -292,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_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_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_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_test.go b/cmd/vote_test.go index 4dadc4683..5349b5ef8 100644 --- a/cmd/vote_test.go +++ b/cmd/vote_test.go @@ -7,6 +7,7 @@ import ( "os" "path" "path/filepath" + "razor/accounts" "razor/core/types" "razor/pkg/bindings" "razor/utils" @@ -128,7 +129,8 @@ 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) @@ -275,8 +277,9 @@ 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) gotSignatureInHash := hex.EncodeToString(gotSignature) gotSecretInHash := hex.EncodeToString(gotSecret) diff --git a/utils/common_test.go b/utils/common_test.go index f2cb12a59..bac674473 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" @@ -1559,3 +1560,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/mocks/utils.go b/utils/mocks/utils.go index a30978eaf..e71e49a09 100644 --- a/utils/mocks/utils.go +++ b/utils/mocks/utils.go @@ -4,10 +4,12 @@ package mocks import ( big "math/big" - bindings "razor/pkg/bindings" + accounts "razor/accounts" bind "github.com/ethereum/go-ethereum/accounts/abi/bind" + bindings "razor/pkg/bindings" + cache "razor/cache" common "github.com/ethereum/go-ethereum/common" @@ -26,6 +28,32 @@ type Utils struct { mock.Mock } +// AccountManagerForKeystore provides a mock function with given fields: +func (_m *Utils) AccountManagerForKeystore() (*accounts.AccountManager, error) { + ret := _m.Called() + + var r0 *accounts.AccountManager + var r1 error + if rf, ok := ret.Get(0).(func() (*accounts.AccountManager, error)); ok { + return rf() + } + if rf, ok := ret.Get(0).(func() *accounts.AccountManager); ok { + r0 = rf() + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*accounts.AccountManager) + } + } + + 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) @@ -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) } 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) From aa262c6a403d174d4899d07997846895c7b49017 Mon Sep 17 00:00:00 2001 From: YashK Date: Fri, 5 Apr 2024 14:34:17 +0530 Subject: [PATCH 12/16] refactor: removed commented test code --- accounts/accountUtils.go | 7 --- accounts/accounts_test.go | 98 --------------------------------------- 2 files changed, 105 deletions(-) diff --git a/accounts/accountUtils.go b/accounts/accountUtils.go index cec72c5d6..e0d7e87df 100644 --- a/accounts/accountUtils.go +++ b/accounts/accountUtils.go @@ -6,13 +6,6 @@ import ( "razor/core/types" ) -//type AccountInterface interface { -// CreateAccount(keystorePath, password string) accounts.Account -// GetPrivateKey(address, password string) (*ecdsa.PrivateKey, error) -// SignData(hash []byte, account types.Account) ([]byte, error) -// NewAccount(passphrase string) (accounts.Account, error) -//} - type AccountManager struct { Keystore *keystore.KeyStore } diff --git a/accounts/accounts_test.go b/accounts/accounts_test.go index f148d1893..26e6fa9d0 100644 --- a/accounts/accounts_test.go +++ b/accounts/accounts_test.go @@ -7,104 +7,6 @@ import ( "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.AccountManagerInterface) -// osMock := new(mocks1.OSInterface) -// -// path.OSUtilsInterface = osMock -// -// 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) -// -// fatal = false -// -// got := accountsMock.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 Test_getPrivateKeyFromKeystore(t *testing.T) { password := "Razor@123" From 1a93d6c1e056671d1e9644520575f91c48c3487b Mon Sep 17 00:00:00 2001 From: YashK Date: Wed, 10 Apr 2024 14:02:54 +0530 Subject: [PATCH 13/16] refactor: returned interface instead of type struct instance from AccountManagerForKeystore() --- cmd/create.go | 5 ++++- utils/common.go | 4 ++-- utils/interface.go | 3 +-- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/cmd/create.go b/cmd/create.go index 4628b1b5d..71ca08a98 100644 --- a/cmd/create.go +++ b/cmd/create.go @@ -50,7 +50,10 @@ func (*UtilsStruct) Create(password string) (accounts.Account, error) { } log.Debug("Create: .razor directory path: ", razorPath) accountManager, err := razorUtils.AccountManagerForKeystore() - utils.CheckError("Error in getting accounts manager for keystore: ", err) + 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 := accountManager.CreateAccount(keystorePath, password) diff --git a/utils/common.go b/utils/common.go index 155d0500b..9148d5cee 100644 --- a/utils/common.go +++ b/utils/common.go @@ -390,11 +390,11 @@ func (*UtilsStruct) CheckPassword(account types.Account) error { return nil } -func (*UtilsStruct) AccountManagerForKeystore() (*accounts.AccountManager, error) { +func (*UtilsStruct) AccountManagerForKeystore() (types.AccountManagerInterface, error) { razorPath, err := PathInterface.GetDefaultPath() if err != nil { log.Error("GetKeystorePath: Error in getting .razor path: ", err) - return &accounts.AccountManager{}, err + return nil, err } keystorePath := filepath.Join(razorPath, "keystore_files") diff --git a/utils/interface.go b/utils/interface.go index 0a41e4f11..ef313cb81 100644 --- a/utils/interface.go +++ b/utils/interface.go @@ -7,7 +7,6 @@ import ( "io/fs" "math/big" "os" - "razor/accounts" "razor/cache" "razor/core/types" "razor/pkg/bindings" @@ -157,7 +156,7 @@ type Utils interface { GetStakedTokenManagerWithOpts(client *ethclient.Client, tokenAddress common.Address) (*bindings.StakedToken, bind.CallOpts) GetStakerSRZRBalance(client *ethclient.Client, staker bindings.StructsStaker) (*big.Int, error) CheckPassword(account types.Account) error - AccountManagerForKeystore() (*accounts.AccountManager, error) + AccountManagerForKeystore() (types.AccountManagerInterface, error) } type EthClientUtils interface { From 95101907181dc28cb90fdd6a2ab589c6094a8801 Mon Sep 17 00:00:00 2001 From: YashK Date: Wed, 10 Apr 2024 14:03:36 +0530 Subject: [PATCH 14/16] refactor: fixed create tests --- accounts/mocks/account_manager_interface.go | 120 ++++++++++++++++++++ cmd/create_test.go | 100 ++++++++++++++++ cmd/test_utils_test.go | 4 - core/types/account.go | 2 + utils/mocks/utils.go | 14 +-- 5 files changed, 228 insertions(+), 12 deletions(-) create mode 100644 accounts/mocks/account_manager_interface.go 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/cmd/create_test.go b/cmd/create_test.go index b6ba0e167..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" @@ -11,6 +14,103 @@ import ( "github.com/stretchr/testify/mock" ) +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 + accountManagerErr error + account accounts.Account + } + tests := []struct { + name string + args args + want accounts.Account + wantErr error + }{ + { + name: "Test 1: When create function executes successfully", + args: args{ + path: "/home/local", + pathErr: nil, + 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"}, + }, + wantErr: nil, + }, + { + name: "Test 2: When create fails due to path error", + args: args{ + path: "/home/local", + pathErr: errors.New("path error"), + account: accounts.Account{Address: common.HexToAddress("0x000000000000000000000000000000000000dea1"), + 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) { + 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) + 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) + + if got.Address != tt.want.Address { + t.Errorf("New address created, got = %v, want %v", got, tt.want.Address) + } + + if err == nil || tt.wantErr == nil { + if err != tt.wantErr { + t.Errorf("Error for Create function, got = %v, want %v", got, tt.wantErr) + } + } else { + if err.Error() != tt.wantErr.Error() { + t.Errorf("Error for Create function, got = %v, want %v", got, tt.wantErr) + } + } + }) + } +} + func TestExecuteCreate(t *testing.T) { var flagSet *pflag.FlagSet diff --git a/cmd/test_utils_test.go b/cmd/test_utils_test.go index 24f9a78d2..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" @@ -51,7 +50,6 @@ var ( osMock *mocks.OSInterface pathMock *pathPkgMocks.PathInterface osPathMock *pathPkgMocks.OSInterface - //accountsMock *accountsPkgMocks.AccountManagerInterface ) func SetUpMockInterfaces() { @@ -165,8 +163,6 @@ func SetUpMockInterfaces() { osPathMock = new(pathPkgMocks.OSInterface) path.OSUtilsInterface = osPathMock - - //accountsMock = new(accountsPkgMocks.AccountManagerInterface) } var privateKey, _ = ecdsa.GenerateKey(crypto.S256(), rand.Reader) diff --git a/core/types/account.go b/core/types/account.go index 2d2c63519..da16d30d8 100644 --- a/core/types/account.go +++ b/core/types/account.go @@ -5,6 +5,8 @@ import ( "github.com/ethereum/go-ethereum/accounts" ) +//go:generate mockery --name=AccountManagerInterface --output=../../accounts/mocks --case=underscore + type Account struct { Address string Password string diff --git a/utils/mocks/utils.go b/utils/mocks/utils.go index e71e49a09..285ee4268 100644 --- a/utils/mocks/utils.go +++ b/utils/mocks/utils.go @@ -4,12 +4,10 @@ package mocks import ( big "math/big" - accounts "razor/accounts" + bindings "razor/pkg/bindings" bind "github.com/ethereum/go-ethereum/accounts/abi/bind" - bindings "razor/pkg/bindings" - cache "razor/cache" common "github.com/ethereum/go-ethereum/common" @@ -29,19 +27,19 @@ type Utils struct { } // AccountManagerForKeystore provides a mock function with given fields: -func (_m *Utils) AccountManagerForKeystore() (*accounts.AccountManager, error) { +func (_m *Utils) AccountManagerForKeystore() (types.AccountManagerInterface, error) { ret := _m.Called() - var r0 *accounts.AccountManager + var r0 types.AccountManagerInterface var r1 error - if rf, ok := ret.Get(0).(func() (*accounts.AccountManager, error)); ok { + if rf, ok := ret.Get(0).(func() (types.AccountManagerInterface, error)); ok { return rf() } - if rf, ok := ret.Get(0).(func() *accounts.AccountManager); ok { + if rf, ok := ret.Get(0).(func() types.AccountManagerInterface); ok { r0 = rf() } else { if ret.Get(0) != nil { - r0 = ret.Get(0).(*accounts.AccountManager) + r0 = ret.Get(0).(types.AccountManagerInterface) } } From 28cb8c2dbcaa618834443acf26ee7b109842b441 Mon Sep 17 00:00:00 2001 From: YashK Date: Thu, 11 Apr 2024 12:35:54 +0530 Subject: [PATCH 15/16] refactor: compared expected and returned pKey values in tests --- accounts/accounts_test.go | 35 +++++++++++++++++++++++++++++++---- 1 file changed, 31 insertions(+), 4 deletions(-) diff --git a/accounts/accounts_test.go b/accounts/accounts_test.go index 26e6fa9d0..986a78c5c 100644 --- a/accounts/accounts_test.go +++ b/accounts/accounts_test.go @@ -7,6 +7,10 @@ import ( "testing" ) +func privateKeyToHex(privateKey *ecdsa.PrivateKey) string { + return hex.EncodeToString(privateKey.D.Bytes()) +} + func Test_getPrivateKeyFromKeystore(t *testing.T) { password := "Razor@123" @@ -17,7 +21,7 @@ func Test_getPrivateKeyFromKeystore(t *testing.T) { tests := []struct { name string args args - want *ecdsa.PrivateKey + want string wantErr bool }{ { @@ -26,6 +30,7 @@ func Test_getPrivateKeyFromKeystore(t *testing.T) { keystoreFilePath: "test_accounts/UTC--2024-03-20T07-03-56.358521000Z--911654feb423363fb771e04e18d1e7325ae10a91", password: password, }, + want: "b110b1f06b7b64323a6fb768ceab966abe9f65f4e6ab3c39382bd446122f7b01", wantErr: false, }, { @@ -34,7 +39,7 @@ func Test_getPrivateKeyFromKeystore(t *testing.T) { keystoreFilePath: "test_accounts/UTC--2024-03-20T07-03-56.358521000Z--211654feb423363fb771e04e18d1e7325ae10a91", password: password, }, - want: nil, + want: "", wantErr: true, }, { @@ -43,17 +48,26 @@ func Test_getPrivateKeyFromKeystore(t *testing.T) { keystoreFilePath: "test_accounts/UTC--2024-03-20T07-03-56.358521000Z--911654feb423363fb771e04e18d1e7325ae10a91", password: "Razor@456", }, + want: "", wantErr: true, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - _, err := getPrivateKeyFromKeystore(tt.args.keystoreFilePath, tt.args.password) + 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) + } + } }) } } @@ -69,6 +83,7 @@ func TestGetPrivateKey(t *testing.T) { tests := []struct { name string args args + want string wantErr bool }{ { @@ -77,6 +92,7 @@ func TestGetPrivateKey(t *testing.T) { address: "0x911654feb423363fb771e04e18d1e7325ae10a91", password: password, }, + want: "b110b1f06b7b64323a6fb768ceab966abe9f65f4e6ab3c39382bd446122f7b01", wantErr: false, }, { @@ -85,6 +101,7 @@ func TestGetPrivateKey(t *testing.T) { address: "0x2F5F59615689B706B6AD13FD03343DCA28784989", password: password, }, + want: "726223b8b95628edef6cf2774ddde39fb3ea482949c8847fabf74cd994219b50", wantErr: false, }, { @@ -92,6 +109,7 @@ func TestGetPrivateKey(t *testing.T) { args: args{ address: "0x911654feb423363fb771e04e18d1e7325ae10a91_not_present", }, + want: "", wantErr: true, }, { @@ -100,17 +118,26 @@ func TestGetPrivateKey(t *testing.T) { address: "0x911654feb423363fb771e04e18d1e7325ae10a91", password: "incorrect password", }, + want: "", wantErr: true, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { am := NewAccountManager(keystoreDirPath) - _, err := am.GetPrivateKey(tt.args.address, tt.args.password) + 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) + } + } }) } } From 9218d2f3fe64728fd2b022f045798ceab67258e4 Mon Sep 17 00:00:00 2001 From: YashK Date: Thu, 11 Apr 2024 18:39:09 +0530 Subject: [PATCH 16/16] refactor: requested changes --- accounts/accounts.go | 4 +--- cmd/vote_test.go | 9 +++++---- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/accounts/accounts.go b/accounts/accounts.go index 97681ee5e..4284ed6a3 100644 --- a/accounts/accounts.go +++ b/accounts/accounts.go @@ -13,9 +13,7 @@ import ( "strings" ) -var ( - log = logger.NewLogger() -) +var log = logger.NewLogger() //This function takes path and password as input and returns new account func (am *AccountManager) CreateAccount(keystorePath string, password string) accounts.Account { diff --git a/cmd/vote_test.go b/cmd/vote_test.go index 5349b5ef8..72ac46e8d 100644 --- a/cmd/vote_test.go +++ b/cmd/vote_test.go @@ -280,19 +280,20 @@ func TestCalculateSecret(t *testing.T) { 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 - } }) } }