Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: used the same keystore instance to fetch pKey everytime #1200

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 14 additions & 44 deletions accounts/accountUtils.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,56 +2,26 @@
package accounts

import (
"crypto/ecdsa"
"github.com/ethereum/go-ethereum/accounts"
"github.com/ethereum/go-ethereum/accounts/keystore"
"github.com/ethereum/go-ethereum/crypto"
"os"
"razor/core/types"
)

//go:generate mockery --name AccountInterface --output ./mocks/ --case=underscore

var AccountUtilsInterface AccountInterface

type AccountInterface interface {
CreateAccount(path string, password string) accounts.Account
GetPrivateKeyFromKeystore(keystorePath string, password string) (*ecdsa.PrivateKey, error)
GetPrivateKey(address string, password string, keystorePath string) (*ecdsa.PrivateKey, error)
SignData(hash []byte, account types.Account, defaultPath string) ([]byte, error)
Accounts(path string) []accounts.Account
NewAccount(path string, passphrase string) (accounts.Account, error)
DecryptKey(jsonBytes []byte, password string) (*keystore.Key, error)
Sign(digestHash []byte, prv *ecdsa.PrivateKey) ([]byte, error)
ReadFile(filename string) ([]byte, error)
}

type AccountUtils struct{}

//This function returns all the accounts in form of array
func (accountUtils AccountUtils) Accounts(path string) []accounts.Account {
ks := keystore.NewKeyStore(path, keystore.StandardScryptN, keystore.StandardScryptP)
return ks.Accounts()
}

//This function takes path and pass phrase as input and returns the new account
func (accountUtils AccountUtils) NewAccount(path string, passphrase string) (accounts.Account, error) {
ks := keystore.NewKeyStore(path, keystore.StandardScryptN, keystore.StandardScryptP)
accounts.NewManager(&accounts.Config{InsecureUnlockAllowed: false}, ks)
return ks.NewAccount(passphrase)
}

//This function takes json bytes array and password as input and returns the decrypted key
func (accountUtils AccountUtils) DecryptKey(jsonBytes []byte, password string) (*keystore.Key, error) {
return keystore.DecryptKey(jsonBytes, password)
type AccountManager struct {
Keystore *keystore.KeyStore
}

//This function takes hash in form of byte array and private key as input and returns signature as byte array
func (accountUtils AccountUtils) Sign(digestHash []byte, prv *ecdsa.PrivateKey) (sig []byte, err error) {
return crypto.Sign(digestHash, prv)
func NewAccountManager(keystorePath string) *AccountManager {
ks := keystore.NewKeyStore(keystorePath, keystore.StandardScryptN, keystore.StandardScryptP)
return &AccountManager{
Keystore: ks,
}
}

//This function takes name of the file as input and returns the file data as byte array
func (accountUtils AccountUtils) ReadFile(filename string) ([]byte, error) {
return os.ReadFile(filename)
// InitAccountStruct initializes an Account struct with provided details.
func InitAccountStruct(address, password string, accountManager types.AccountManagerInterface) types.Account {
return types.Account{
Address: address,
Password: password,
AccountManager: accountManager,
}
}
49 changes: 29 additions & 20 deletions accounts/accounts.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@ import (
"crypto/ecdsa"
"errors"
"github.com/ethereum/go-ethereum/accounts"
"razor/core/types"
"github.com/ethereum/go-ethereum/accounts/keystore"
"github.com/ethereum/go-ethereum/crypto"
"os"
"razor/logger"
"razor/path"
"strings"
Expand All @@ -14,51 +16,58 @@ import (
var log = logger.NewLogger()

//This function takes path and password as input and returns new account
func (AccountUtils) CreateAccount(keystorePath string, password string) accounts.Account {
func (am *AccountManager) CreateAccount(keystorePath string, password string) accounts.Account {
if _, err := path.OSUtilsInterface.Stat(keystorePath); path.OSUtilsInterface.IsNotExist(err) {
mkdirErr := path.OSUtilsInterface.Mkdir(keystorePath, 0700)
if mkdirErr != nil {
log.Fatal("Error in creating directory: ", mkdirErr)
}
}
newAcc, err := AccountUtilsInterface.NewAccount(keystorePath, password)
newAcc, err := am.NewAccount(password)
if err != nil {
log.Fatal("Error in creating account: ", err)
}
return newAcc
}

//This function takes path and pass phrase as input and returns the new account
func (am *AccountManager) NewAccount(passphrase string) (accounts.Account, error) {
ks := am.Keystore
accounts.NewManager(&accounts.Config{InsecureUnlockAllowed: false}, ks)
return ks.NewAccount(passphrase)
}

//This function takes address of account, password and keystore path as input and returns private key of account
func (am *AccountManager) GetPrivateKey(address string, password string) (*ecdsa.PrivateKey, error) {
allAccounts := am.Keystore.Accounts()
for _, account := range allAccounts {
if strings.EqualFold(account.Address.Hex(), address) {
return getPrivateKeyFromKeystore(account.URL.Path, password)
}
}
return nil, errors.New("no keystore file found")
}

//This function takes and path of keystore and password as input and returns private key of account
func (AccountUtils) GetPrivateKeyFromKeystore(keystorePath string, password string) (*ecdsa.PrivateKey, error) {
jsonBytes, err := AccountUtilsInterface.ReadFile(keystorePath)
func getPrivateKeyFromKeystore(keystoreFilePath string, password string) (*ecdsa.PrivateKey, error) {
jsonBytes, err := os.ReadFile(keystoreFilePath)
if err != nil {
log.Error("Error in reading keystore: ", err)
return nil, err
}
key, err := AccountUtilsInterface.DecryptKey(jsonBytes, password)
key, err := keystore.DecryptKey(jsonBytes, password)
if err != nil {
log.Error("Error in fetching private key: ", err)
return nil, err
}
return key.PrivateKey, nil
}

//This function takes address of account, password and keystore path as input and returns private key of account
func (AccountUtils) GetPrivateKey(address string, password string, keystorePath string) (*ecdsa.PrivateKey, error) {
allAccounts := AccountUtilsInterface.Accounts(keystorePath)
for _, account := range allAccounts {
if strings.EqualFold(account.Address.Hex(), address) {
return AccountUtilsInterface.GetPrivateKeyFromKeystore(account.URL.Path, password)
}
}
return nil, errors.New("no keystore file found")
}

//This function takes hash, account and path as input and returns the signed data as array of byte
func (AccountUtils) SignData(hash []byte, account types.Account, defaultPath string) ([]byte, error) {
privateKey, err := AccountUtilsInterface.GetPrivateKey(account.Address, account.Password, defaultPath)
func (am *AccountManager) SignData(hash []byte, address string, password string) ([]byte, error) {
privateKey, err := am.GetPrivateKey(address, password)
if err != nil {
return nil, err
}
return AccountUtilsInterface.Sign(hash, privateKey)
return crypto.Sign(hash, privateKey)
}
Loading
Loading