From 3f32f9ba8a1f2573e12ee3213db2028fec319ab9 Mon Sep 17 00:00:00 2001 From: Marko Date: Fri, 2 Aug 2019 15:53:14 +0200 Subject: [PATCH 01/14] Merge PR #513: Add chainsafe to readme --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index ebc269eaf..b2f70f3d7 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,9 @@ # Ethermint -__**WARNING:**__ Ethermint is under VERY ACTIVE DEVELOPMENT and should be treated as pre-alpha software. This means it is not meant to be run in production, its APIs are subject to change without warning and should not be relied upon, and it should not be used to hold any value. We will remove this warning when we have a release that is stable, secure, and properly tested. +### Ethermint is currently being worked on by [Chainsafe](https://chainsafe.io/), you can follow the progress [here](https://github.com/ChainSafe/ethermint) + +\***\*WARNING:\*\*** Ethermint is under VERY ACTIVE DEVELOPMENT and should be treated as pre-alpha software. This means it is not meant to be run in production, its APIs are subject to change without warning and should not be relied upon, and it should not be used to hold any value. We will remove this warning when we have a release that is stable, secure, and properly tested. ## What is it? From 3ad28f82db0cec437434784ff8399f9c04170732 Mon Sep 17 00:00:00 2001 From: Federico Kunze Date: Tue, 29 Sep 2020 15:48:46 +0200 Subject: [PATCH 02/14] rpc: implement personal_importRawKey --- CHANGELOG.md | 6 ++++++ crypto/algorithm.go | 4 +++- rpc/personal_api.go | 43 +++++++++++++++++++++++++++++++------------ 3 files changed, 40 insertions(+), 13 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1cfefed04..666c76334 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -35,6 +35,12 @@ Ref: https://keepachangelog.com/en/1.0.0/ # Changelog +## Unreleased + +### Features + +* (rpc) Implement Eth Personal namespace `personal_importRawKey`. + ## [v0.2.0] - 2020-09-24 ### State Machine Breaking diff --git a/crypto/algorithm.go b/crypto/algorithm.go index 20a0febba..3422d0b69 100644 --- a/crypto/algorithm.go +++ b/crypto/algorithm.go @@ -18,8 +18,10 @@ import ( ) const ( + // EthSecp256k1Type string constant for the EthSecp256k1 algorithm + EthSecp256k1Type = "eth_secp256k1" // EthSecp256k1 defines the ECDSA secp256k1 used on Ethereum - EthSecp256k1 = keys.SigningAlgo("eth_secp256k1") + EthSecp256k1 = keys.SigningAlgo(EthSecp256k1Type) ) // SupportedAlgorithms defines the list of signing algorithms used on Ethermint: diff --git a/rpc/personal_api.go b/rpc/personal_api.go index 2b783dd15..050e12c95 100644 --- a/rpc/personal_api.go +++ b/rpc/personal_api.go @@ -8,19 +8,23 @@ import ( "sync" "time" + "github.com/spf13/viper" + + "github.com/tendermint/tendermint/libs/log" + sdkcontext "github.com/cosmos/cosmos-sdk/client/context" "github.com/cosmos/cosmos-sdk/client/flags" "github.com/cosmos/cosmos-sdk/crypto/keys" + "github.com/cosmos/cosmos-sdk/crypto/keys/mintkey" sdk "github.com/cosmos/cosmos-sdk/types" - emintcrypto "github.com/cosmos/ethermint/crypto" - params "github.com/cosmos/ethermint/rpc/args" - "github.com/spf13/viper" - "github.com/tendermint/tendermint/libs/log" "github.com/ethereum/go-ethereum/accounts" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/crypto" + + emintcrypto "github.com/cosmos/ethermint/crypto" + params "github.com/cosmos/ethermint/rpc/args" ) // PersonalEthAPI is the eth_ prefixed set of APIs in the Web3 JSON-RPC spec. @@ -75,16 +79,31 @@ func (e *PersonalEthAPI) getKeybaseInfo() ([]keys.Info, error) { return e.cliCtx.Keybase.List() } -// ImportRawKey stores the given hex encoded ECDSA key into the key directory, -// encrypting it with the passphrase. -// Currently, this is not implemented since the feature is not supported by the keys. +// ImportRawKey armors and encrypts a given raw hex encoded ECDSA key and stores it into the key directory. +// The name of the key will have the format "personal_", where is the total number of +// keys stored on the keyring. +// NOTE: The key will be both armored and encrypted using the same passphrase. func (e *PersonalEthAPI) ImportRawKey(privkey, password string) (common.Address, error) { - e.logger.Debug("personal_importRawKey", "error", "not implemented") - _, err := crypto.HexToECDSA(privkey) + e.logger.Debug("personal_importRawKey") + priv, err := crypto.HexToECDSA(privkey) if err != nil { return common.Address{}, err } + privKey := emintcrypto.PrivKeySecp256k1(crypto.FromECDSA(priv)) + + armor := mintkey.EncryptArmorPrivKey(privKey, password, emintcrypto.EthSecp256k1Type) + + // ignore error as we only care about the length of the list + list, _ := e.cliCtx.Keybase.List() + privKeyName := fmt.Sprintf("personal_%d", len(list)) + + if err := e.cliCtx.Keybase.ImportPrivKey(privKeyName, armor, password); err != nil { + return common.Address{}, err + } + + e.logger.Info("key successfully imported", "name", privKeyName) + return common.Address{}, nil } @@ -128,6 +147,8 @@ func (e *PersonalEthAPI) LockAccount(address common.Address) bool { return true } + e.logger.Debug("account unlocked", "address", address) + return false } @@ -158,7 +179,6 @@ func (e *PersonalEthAPI) NewAccount(password string) (common.Address, error) { return common.Address{}, fmt.Errorf("invalid private key type: %T", privKey) } e.ethAPI.keys = append(e.ethAPI.keys, emintKey) - e.logger.Debug("personal_newAccount", "address", fmt.Sprintf("0x%x", emintKey.PubKey().Address().Bytes())) addr := common.BytesToAddress(info.GetPubKey().Address().Bytes()) e.logger.Info("Your new key was generated", "address", addr) @@ -200,8 +220,7 @@ func (e *PersonalEthAPI) UnlockAccount(ctx context.Context, addr common.Address, e.keys = append(e.keys, emintKey) e.ethAPI.keys = append(e.ethAPI.keys, emintKey) - e.logger.Debug("personal_unlockAccount", "address", fmt.Sprintf("0x%x", emintKey.PubKey().Address().Bytes())) - + e.logger.Debug("account unlocked", "address", addr) return true, nil } From a9379cb679e658b598e82daf1693b0ab7454bc60 Mon Sep 17 00:00:00 2001 From: Federico Kunze Date: Tue, 29 Sep 2020 15:51:13 +0200 Subject: [PATCH 03/14] changelog --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 666c76334..1acb3c24e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -39,7 +39,7 @@ Ref: https://keepachangelog.com/en/1.0.0/ ### Features -* (rpc) Implement Eth Personal namespace `personal_importRawKey`. +* (rpc) [\#552](https://github.com/ChainSafe/ethermint/pull/552) Implement Eth Personal namespace `personal_importRawKey`. ## [v0.2.0] - 2020-09-24 From d95aaf616a5e9c73862093993055cfba510e2309 Mon Sep 17 00:00:00 2001 From: Federico Kunze Date: Tue, 29 Sep 2020 16:16:19 +0200 Subject: [PATCH 04/14] rpc tests --- rpc/personal_api.go | 5 +++-- tests/personal_test.go | 19 +++++++++++++++++++ 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/rpc/personal_api.go b/rpc/personal_api.go index 050e12c95..8eff74ea1 100644 --- a/rpc/personal_api.go +++ b/rpc/personal_api.go @@ -102,9 +102,10 @@ func (e *PersonalEthAPI) ImportRawKey(privkey, password string) (common.Address, return common.Address{}, err } - e.logger.Info("key successfully imported", "name", privKeyName) + addr := common.BytesToAddress(privKey.PubKey().Address().Bytes()) + e.logger.Info("key successfully imported", "name", privKeyName, "address", addr.String()) - return common.Address{}, nil + return addr, nil } // ListAccounts will return a list of addresses for accounts this node manages. diff --git a/tests/personal_test.go b/tests/personal_test.go index 914183e2e..3491edbeb 100644 --- a/tests/personal_test.go +++ b/tests/personal_test.go @@ -6,6 +6,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" + ethcrypto "github.com/ethereum/go-ethereum/crypto" "github.com/stretchr/testify/require" ) @@ -42,6 +43,24 @@ func TestPersonal_Sign(t *testing.T) { // TODO: check that signature is same as with geth, requires importing a key } +func TestPersonal_ImportRawKey(t *testing.T) { + privkey, err := ethcrypto.GenerateKey() + require.NoError(t, err) + + // parse priv key to hex + hexPriv := common.Bytes2Hex(ethcrypto.FromECDSA(privkey)) + rpcRes := call(t, "personal_importRawKey", []string{hexPriv, "password"}) + + var res hexutil.Bytes + err = json.Unmarshal(rpcRes.Result, &res) + require.NoError(t, err) + + addr := ethcrypto.PubkeyToAddress(privkey.PublicKey) + resAddr := common.BytesToAddress(res) + + require.Equal(t, addr.String(), resAddr.String()) +} + func TestPersonal_EcRecover(t *testing.T) { data := hexutil.Bytes{0x88} rpcRes := call(t, "personal_sign", []interface{}{data, hexutil.Bytes(from), ""}) From d7e7b2c810f6f46a47ba14c0da1e21f07a1db0e2 Mon Sep 17 00:00:00 2001 From: Federico Kunze Date: Tue, 29 Sep 2020 16:38:39 +0200 Subject: [PATCH 05/14] add key to infos --- rpc/personal_api.go | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/rpc/personal_api.go b/rpc/personal_api.go index 8eff74ea1..0fd9b79bf 100644 --- a/rpc/personal_api.go +++ b/rpc/personal_api.go @@ -103,6 +103,16 @@ func (e *PersonalEthAPI) ImportRawKey(privkey, password string) (common.Address, } addr := common.BytesToAddress(privKey.PubKey().Address().Bytes()) + + info, err := e.cliCtx.Keybase.Get(privKeyName) + if err != nil { + return common.Address{}, err + } + + // append key and info to be able to lock and list the account + e.keys = append(e.ethAPI.keys, privKey) + e.keyInfos = append(e.keyInfos, info) + e.logger.Info("key successfully imported", "name", privKeyName, "address", addr.String()) return addr, nil From b08412880f1800540dad0b31f772eb6b338efbf5 Mon Sep 17 00:00:00 2001 From: Federico Kunze Date: Tue, 29 Sep 2020 16:40:54 +0200 Subject: [PATCH 06/14] update comments --- rpc/personal_api.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/rpc/personal_api.go b/rpc/personal_api.go index 0fd9b79bf..930d64be0 100644 --- a/rpc/personal_api.go +++ b/rpc/personal_api.go @@ -27,7 +27,7 @@ import ( params "github.com/cosmos/ethermint/rpc/args" ) -// PersonalEthAPI is the eth_ prefixed set of APIs in the Web3 JSON-RPC spec. +// PersonalEthAPI is the personal_ prefixed set of APIs in the Web3 JSON-RPC spec. type PersonalEthAPI struct { logger log.Logger cliCtx sdkcontext.CLIContext @@ -38,7 +38,7 @@ type PersonalEthAPI struct { keybaseLock sync.Mutex } -// NewPersonalEthAPI creates an instance of the public ETH Web3 API. +// NewPersonalEthAPI creates an instance of the public Personal Eth API. func NewPersonalEthAPI(cliCtx sdkcontext.CLIContext, ethAPI *PublicEthAPI, nonceLock *AddrLocker, keys []emintcrypto.PrivKeySecp256k1) *PersonalEthAPI { api := &PersonalEthAPI{ logger: log.NewTMLogger(log.NewSyncWriter(os.Stdout)).With("module", "json-rpc"), From ec6beb68f3cc50f7b02b4938614c56cfece22df7 Mon Sep 17 00:00:00 2001 From: Federico Kunze Date: Tue, 29 Sep 2020 16:41:43 +0200 Subject: [PATCH 07/14] update comments --- rpc/personal_api.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rpc/personal_api.go b/rpc/personal_api.go index 930d64be0..fcca84197 100644 --- a/rpc/personal_api.go +++ b/rpc/personal_api.go @@ -110,7 +110,7 @@ func (e *PersonalEthAPI) ImportRawKey(privkey, password string) (common.Address, } // append key and info to be able to lock and list the account - e.keys = append(e.ethAPI.keys, privKey) + e.keys = append(e.keys, privKey) e.keyInfos = append(e.keyInfos, info) e.logger.Info("key successfully imported", "name", privKeyName, "address", addr.String()) From 55aae1720ae10c3dc267d4a04feea7d377c7d583 Mon Sep 17 00:00:00 2001 From: Federico Kunze Date: Tue, 29 Sep 2020 17:36:36 +0200 Subject: [PATCH 08/14] remove e.keys --- rpc/personal_api.go | 37 ++++++++++++------------------------- 1 file changed, 12 insertions(+), 25 deletions(-) diff --git a/rpc/personal_api.go b/rpc/personal_api.go index fcca84197..c5eed5898 100644 --- a/rpc/personal_api.go +++ b/rpc/personal_api.go @@ -33,7 +33,6 @@ type PersonalEthAPI struct { cliCtx sdkcontext.CLIContext ethAPI *PublicEthAPI nonceLock *AddrLocker - keys []emintcrypto.PrivKeySecp256k1 keyInfos []keys.Info keybaseLock sync.Mutex } @@ -45,7 +44,6 @@ func NewPersonalEthAPI(cliCtx sdkcontext.CLIContext, ethAPI *PublicEthAPI, nonce cliCtx: cliCtx, ethAPI: ethAPI, nonceLock: nonceLock, - keys: keys, } infos, err := api.getKeybaseInfo() @@ -53,6 +51,7 @@ func NewPersonalEthAPI(cliCtx sdkcontext.CLIContext, ethAPI *PublicEthAPI, nonce return api } + api.ethAPI.keys = append(api.ethAPI.keys, keys...) api.keyInfos = infos return api } @@ -110,7 +109,7 @@ func (e *PersonalEthAPI) ImportRawKey(privkey, password string) (common.Address, } // append key and info to be able to lock and list the account - e.keys = append(e.keys, privKey) + e.ethAPI.keys = append(e.ethAPI.keys, privKey) e.keyInfos = append(e.keyInfos, info) e.logger.Info("key successfully imported", "name", privKeyName, "address", addr.String()) @@ -133,18 +132,7 @@ func (e *PersonalEthAPI) ListAccounts() ([]common.Address, error) { // LockAccount will lock the account associated with the given address when it's unlocked. // It removes the key corresponding to the given address from the API's local keys. func (e *PersonalEthAPI) LockAccount(address common.Address) bool { - e.logger.Debug("personal_lockAccount", "address", address) - for i, key := range e.keys { - if !bytes.Equal(key.PubKey().Address().Bytes(), address.Bytes()) { - continue - } - - tmp := make([]emintcrypto.PrivKeySecp256k1, len(e.keys)-1) - copy(tmp[:i], e.keys[:i]) - copy(tmp[i:], e.keys[i+1:]) - e.keys = tmp - return true - } + e.logger.Debug("personal_lockAccount", "address", address.String()) for i, key := range e.ethAPI.keys { if !bytes.Equal(key.PubKey().Address().Bytes(), address.Bytes()) { @@ -158,7 +146,7 @@ func (e *PersonalEthAPI) LockAccount(address common.Address) bool { return true } - e.logger.Debug("account unlocked", "address", address) + e.logger.Debug("account unlocked", "address", address.String()) return false } @@ -177,8 +165,6 @@ func (e *PersonalEthAPI) NewAccount(password string) (common.Address, error) { return common.Address{}, err } - e.keyInfos = append(e.keyInfos, info) - // update ethAPI privKey, err := e.cliCtx.Keybase.ExportPrivateKeyObject(name, password) if err != nil { @@ -189,10 +175,12 @@ func (e *PersonalEthAPI) NewAccount(password string) (common.Address, error) { if !ok { return common.Address{}, fmt.Errorf("invalid private key type: %T", privKey) } + + e.keyInfos = append(e.keyInfos, info) e.ethAPI.keys = append(e.ethAPI.keys, emintKey) addr := common.BytesToAddress(info.GetPubKey().Address().Bytes()) - e.logger.Info("Your new key was generated", "address", addr) + e.logger.Info("Your new key was generated", "address", addr.String()) e.logger.Info("Please backup your key file!", "path", os.Getenv("HOME")+"/.ethermintcli/"+name) e.logger.Info("Please remember your password!") return addr, nil @@ -203,7 +191,7 @@ func (e *PersonalEthAPI) NewAccount(password string) (common.Address, error) { // default of 300 seconds. It returns an indication if the account was unlocked. // It exports the private key corresponding to the given address from the keyring and stores it in the API's local keys. func (e *PersonalEthAPI) UnlockAccount(ctx context.Context, addr common.Address, password string, _ *uint64) (bool, error) { - e.logger.Debug("personal_unlockAccount", "address", addr) + e.logger.Debug("personal_unlockAccount", "address", addr.String()) // TODO: use duration name := "" @@ -215,7 +203,7 @@ func (e *PersonalEthAPI) UnlockAccount(ctx context.Context, addr common.Address, } if name == "" { - return false, fmt.Errorf("cannot find key with given address") + return false, fmt.Errorf("cannot find key with given address %s", addr.String()) } // TODO: this only works on local keys @@ -229,9 +217,8 @@ func (e *PersonalEthAPI) UnlockAccount(ctx context.Context, addr common.Address, return false, fmt.Errorf("invalid private key type: %T", privKey) } - e.keys = append(e.keys, emintKey) e.ethAPI.keys = append(e.ethAPI.keys, emintKey) - e.logger.Debug("account unlocked", "address", addr) + e.logger.Debug("account unlocked", "address", addr.String()) return true, nil } @@ -252,9 +239,9 @@ func (e *PersonalEthAPI) SendTransaction(ctx context.Context, args params.SendTx // // https://github.com/ethereum/go-ethereum/wiki/Management-APIs#personal_sign func (e *PersonalEthAPI) Sign(ctx context.Context, data hexutil.Bytes, addr common.Address, passwd string) (hexutil.Bytes, error) { - e.logger.Debug("personal_sign", "data", data, "address", addr) + e.logger.Debug("personal_sign", "data", data, "address", addr.String()) - key, ok := checkKeyInKeyring(e.keys, addr) + key, ok := checkKeyInKeyring(e.ethAPI.keys, addr) if !ok { return nil, fmt.Errorf("cannot find key with given address") } From 27f2e60e00e4e3c6d2cd34f31f78df5e0d89dcb8 Mon Sep 17 00:00:00 2001 From: Federico Kunze Date: Tue, 29 Sep 2020 17:47:01 +0200 Subject: [PATCH 09/14] lint --- rpc/personal_api.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rpc/personal_api.go b/rpc/personal_api.go index c5eed5898..daf970ab1 100644 --- a/rpc/personal_api.go +++ b/rpc/personal_api.go @@ -190,7 +190,7 @@ func (e *PersonalEthAPI) NewAccount(password string) (common.Address, error) { // the given password for duration seconds. If duration is nil it will use a // default of 300 seconds. It returns an indication if the account was unlocked. // It exports the private key corresponding to the given address from the keyring and stores it in the API's local keys. -func (e *PersonalEthAPI) UnlockAccount(ctx context.Context, addr common.Address, password string, _ *uint64) (bool, error) { +func (e *PersonalEthAPI) UnlockAccount(ctx context.Context, addr common.Address, password string, _ *uint64) (bool, error) { // nolint: interfacer e.logger.Debug("personal_unlockAccount", "address", addr.String()) // TODO: use duration From 1fbc385092f6e70759c982382b3da2ddfe321dbf Mon Sep 17 00:00:00 2001 From: Federico Kunze Date: Tue, 29 Sep 2020 19:25:46 +0200 Subject: [PATCH 10/14] consolidate client context --- rpc/apis.go | 2 +- rpc/personal_api.go | 25 +++++++++++-------------- 2 files changed, 12 insertions(+), 15 deletions(-) diff --git a/rpc/apis.go b/rpc/apis.go index 0dfb4ae0c..c970ba594 100644 --- a/rpc/apis.go +++ b/rpc/apis.go @@ -40,7 +40,7 @@ func GetRPCAPIs(cliCtx context.CLIContext, keys []emintcrypto.PrivKeySecp256k1) { Namespace: PersonalNamespace, Version: apiVersion, - Service: NewPersonalEthAPI(cliCtx, ethAPI, nonceLock, keys), + Service: NewPersonalEthAPI(ethAPI, nonceLock, keys), Public: false, }, { diff --git a/rpc/personal_api.go b/rpc/personal_api.go index daf970ab1..273e49e14 100644 --- a/rpc/personal_api.go +++ b/rpc/personal_api.go @@ -12,7 +12,6 @@ import ( "github.com/tendermint/tendermint/libs/log" - sdkcontext "github.com/cosmos/cosmos-sdk/client/context" "github.com/cosmos/cosmos-sdk/client/flags" "github.com/cosmos/cosmos-sdk/crypto/keys" "github.com/cosmos/cosmos-sdk/crypto/keys/mintkey" @@ -30,7 +29,6 @@ import ( // PersonalEthAPI is the personal_ prefixed set of APIs in the Web3 JSON-RPC spec. type PersonalEthAPI struct { logger log.Logger - cliCtx sdkcontext.CLIContext ethAPI *PublicEthAPI nonceLock *AddrLocker keyInfos []keys.Info @@ -38,10 +36,9 @@ type PersonalEthAPI struct { } // NewPersonalEthAPI creates an instance of the public Personal Eth API. -func NewPersonalEthAPI(cliCtx sdkcontext.CLIContext, ethAPI *PublicEthAPI, nonceLock *AddrLocker, keys []emintcrypto.PrivKeySecp256k1) *PersonalEthAPI { +func NewPersonalEthAPI(ethAPI *PublicEthAPI, nonceLock *AddrLocker, keys []emintcrypto.PrivKeySecp256k1) *PersonalEthAPI { api := &PersonalEthAPI{ logger: log.NewTMLogger(log.NewSyncWriter(os.Stdout)).With("module", "json-rpc"), - cliCtx: cliCtx, ethAPI: ethAPI, nonceLock: nonceLock, } @@ -60,22 +57,22 @@ func (e *PersonalEthAPI) getKeybaseInfo() ([]keys.Info, error) { e.keybaseLock.Lock() defer e.keybaseLock.Unlock() - if e.cliCtx.Keybase == nil { + if e.ethAPI.cliCtx.Keybase == nil { keybase, err := keys.NewKeyring( sdk.KeyringServiceName(), viper.GetString(flags.FlagKeyringBackend), viper.GetString(flags.FlagHome), - e.cliCtx.Input, + e.ethAPI.cliCtx.Input, emintcrypto.EthSecp256k1Options()..., ) if err != nil { return nil, err } - e.cliCtx.Keybase = keybase + e.ethAPI.cliCtx.Keybase = keybase } - return e.cliCtx.Keybase.List() + return e.ethAPI.cliCtx.Keybase.List() } // ImportRawKey armors and encrypts a given raw hex encoded ECDSA key and stores it into the key directory. @@ -94,16 +91,16 @@ func (e *PersonalEthAPI) ImportRawKey(privkey, password string) (common.Address, armor := mintkey.EncryptArmorPrivKey(privKey, password, emintcrypto.EthSecp256k1Type) // ignore error as we only care about the length of the list - list, _ := e.cliCtx.Keybase.List() + list, _ := e.ethAPI.cliCtx.Keybase.List() privKeyName := fmt.Sprintf("personal_%d", len(list)) - if err := e.cliCtx.Keybase.ImportPrivKey(privKeyName, armor, password); err != nil { + if err := e.ethAPI.cliCtx.Keybase.ImportPrivKey(privKeyName, armor, password); err != nil { return common.Address{}, err } addr := common.BytesToAddress(privKey.PubKey().Address().Bytes()) - info, err := e.cliCtx.Keybase.Get(privKeyName) + info, err := e.ethAPI.cliCtx.Keybase.Get(privKeyName) if err != nil { return common.Address{}, err } @@ -160,13 +157,13 @@ func (e *PersonalEthAPI) NewAccount(password string) (common.Address, error) { } name := "key_" + time.Now().UTC().Format(time.RFC3339) - info, _, err := e.cliCtx.Keybase.CreateMnemonic(name, keys.English, password, emintcrypto.EthSecp256k1) + info, _, err := e.ethAPI.cliCtx.Keybase.CreateMnemonic(name, keys.English, password, emintcrypto.EthSecp256k1) if err != nil { return common.Address{}, err } // update ethAPI - privKey, err := e.cliCtx.Keybase.ExportPrivateKeyObject(name, password) + privKey, err := e.ethAPI.cliCtx.Keybase.ExportPrivateKeyObject(name, password) if err != nil { return common.Address{}, err } @@ -207,7 +204,7 @@ func (e *PersonalEthAPI) UnlockAccount(ctx context.Context, addr common.Address, } // TODO: this only works on local keys - privKey, err := e.cliCtx.Keybase.ExportPrivateKeyObject(name, password) + privKey, err := e.ethAPI.cliCtx.Keybase.ExportPrivateKeyObject(name, password) if err != nil { return false, err } From 2f3726d26b4a8f2b49e5ad4e8262b57a07473e23 Mon Sep 17 00:00:00 2001 From: Federico Kunze Date: Tue, 29 Sep 2020 19:27:07 +0200 Subject: [PATCH 11/14] update log --- rpc/personal_api.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/rpc/personal_api.go b/rpc/personal_api.go index 273e49e14..2be96a1d8 100644 --- a/rpc/personal_api.go +++ b/rpc/personal_api.go @@ -140,11 +140,11 @@ func (e *PersonalEthAPI) LockAccount(address common.Address) bool { copy(tmp[:i], e.ethAPI.keys[:i]) copy(tmp[i:], e.ethAPI.keys[i+1:]) e.ethAPI.keys = tmp + + e.logger.Debug("account unlocked", "address", address.String()) return true } - e.logger.Debug("account unlocked", "address", address.String()) - return false } From d4034193ffb02fd56700f4173bedddd6f82610a1 Mon Sep 17 00:00:00 2001 From: Federico Kunze Date: Tue, 29 Sep 2020 21:56:30 +0200 Subject: [PATCH 12/14] remove dup fields --- rpc/apis.go | 2 +- rpc/personal_api.go | 59 +++++++++++++++++++-------------------------- 2 files changed, 26 insertions(+), 35 deletions(-) diff --git a/rpc/apis.go b/rpc/apis.go index c970ba594..eeeaf0d45 100644 --- a/rpc/apis.go +++ b/rpc/apis.go @@ -40,7 +40,7 @@ func GetRPCAPIs(cliCtx context.CLIContext, keys []emintcrypto.PrivKeySecp256k1) { Namespace: PersonalNamespace, Version: apiVersion, - Service: NewPersonalEthAPI(ethAPI, nonceLock, keys), + Service: NewPersonalEthAPI(ethAPI), Public: false, }, { diff --git a/rpc/personal_api.go b/rpc/personal_api.go index 2be96a1d8..9c47d772d 100644 --- a/rpc/personal_api.go +++ b/rpc/personal_api.go @@ -5,13 +5,10 @@ import ( "context" "fmt" "os" - "sync" "time" "github.com/spf13/viper" - "github.com/tendermint/tendermint/libs/log" - "github.com/cosmos/cosmos-sdk/client/flags" "github.com/cosmos/cosmos-sdk/crypto/keys" "github.com/cosmos/cosmos-sdk/crypto/keys/mintkey" @@ -28,19 +25,14 @@ import ( // PersonalEthAPI is the personal_ prefixed set of APIs in the Web3 JSON-RPC spec. type PersonalEthAPI struct { - logger log.Logger - ethAPI *PublicEthAPI - nonceLock *AddrLocker - keyInfos []keys.Info - keybaseLock sync.Mutex + *PublicEthAPI + keyInfos []keys.Info } // NewPersonalEthAPI creates an instance of the public Personal Eth API. -func NewPersonalEthAPI(ethAPI *PublicEthAPI, nonceLock *AddrLocker, keys []emintcrypto.PrivKeySecp256k1) *PersonalEthAPI { +func NewPersonalEthAPI(ethAPI *PublicEthAPI) *PersonalEthAPI { api := &PersonalEthAPI{ - logger: log.NewTMLogger(log.NewSyncWriter(os.Stdout)).With("module", "json-rpc"), - ethAPI: ethAPI, - nonceLock: nonceLock, + PublicEthAPI: ethAPI, } infos, err := api.getKeybaseInfo() @@ -48,7 +40,6 @@ func NewPersonalEthAPI(ethAPI *PublicEthAPI, nonceLock *AddrLocker, keys []emint return api } - api.ethAPI.keys = append(api.ethAPI.keys, keys...) api.keyInfos = infos return api } @@ -57,22 +48,22 @@ func (e *PersonalEthAPI) getKeybaseInfo() ([]keys.Info, error) { e.keybaseLock.Lock() defer e.keybaseLock.Unlock() - if e.ethAPI.cliCtx.Keybase == nil { + if e.cliCtx.Keybase == nil { keybase, err := keys.NewKeyring( sdk.KeyringServiceName(), viper.GetString(flags.FlagKeyringBackend), viper.GetString(flags.FlagHome), - e.ethAPI.cliCtx.Input, + e.cliCtx.Input, emintcrypto.EthSecp256k1Options()..., ) if err != nil { return nil, err } - e.ethAPI.cliCtx.Keybase = keybase + e.cliCtx.Keybase = keybase } - return e.ethAPI.cliCtx.Keybase.List() + return e.cliCtx.Keybase.List() } // ImportRawKey armors and encrypts a given raw hex encoded ECDSA key and stores it into the key directory. @@ -91,22 +82,22 @@ func (e *PersonalEthAPI) ImportRawKey(privkey, password string) (common.Address, armor := mintkey.EncryptArmorPrivKey(privKey, password, emintcrypto.EthSecp256k1Type) // ignore error as we only care about the length of the list - list, _ := e.ethAPI.cliCtx.Keybase.List() + list, _ := e.cliCtx.Keybase.List() privKeyName := fmt.Sprintf("personal_%d", len(list)) - if err := e.ethAPI.cliCtx.Keybase.ImportPrivKey(privKeyName, armor, password); err != nil { + if err := e.cliCtx.Keybase.ImportPrivKey(privKeyName, armor, password); err != nil { return common.Address{}, err } addr := common.BytesToAddress(privKey.PubKey().Address().Bytes()) - info, err := e.ethAPI.cliCtx.Keybase.Get(privKeyName) + info, err := e.cliCtx.Keybase.Get(privKeyName) if err != nil { return common.Address{}, err } // append key and info to be able to lock and list the account - e.ethAPI.keys = append(e.ethAPI.keys, privKey) + e.keys = append(e.keys, privKey) e.keyInfos = append(e.keyInfos, info) e.logger.Info("key successfully imported", "name", privKeyName, "address", addr.String()) @@ -131,15 +122,15 @@ func (e *PersonalEthAPI) ListAccounts() ([]common.Address, error) { func (e *PersonalEthAPI) LockAccount(address common.Address) bool { e.logger.Debug("personal_lockAccount", "address", address.String()) - for i, key := range e.ethAPI.keys { + for i, key := range e.keys { if !bytes.Equal(key.PubKey().Address().Bytes(), address.Bytes()) { continue } - tmp := make([]emintcrypto.PrivKeySecp256k1, len(e.ethAPI.keys)-1) - copy(tmp[:i], e.ethAPI.keys[:i]) - copy(tmp[i:], e.ethAPI.keys[i+1:]) - e.ethAPI.keys = tmp + tmp := make([]emintcrypto.PrivKeySecp256k1, len(e.keys)-1) + copy(tmp[:i], e.keys[:i]) + copy(tmp[i:], e.keys[i+1:]) + e.keys = tmp e.logger.Debug("account unlocked", "address", address.String()) return true @@ -157,13 +148,13 @@ func (e *PersonalEthAPI) NewAccount(password string) (common.Address, error) { } name := "key_" + time.Now().UTC().Format(time.RFC3339) - info, _, err := e.ethAPI.cliCtx.Keybase.CreateMnemonic(name, keys.English, password, emintcrypto.EthSecp256k1) + info, _, err := e.cliCtx.Keybase.CreateMnemonic(name, keys.English, password, emintcrypto.EthSecp256k1) if err != nil { return common.Address{}, err } // update ethAPI - privKey, err := e.ethAPI.cliCtx.Keybase.ExportPrivateKeyObject(name, password) + privKey, err := e.cliCtx.Keybase.ExportPrivateKeyObject(name, password) if err != nil { return common.Address{}, err } @@ -174,7 +165,7 @@ func (e *PersonalEthAPI) NewAccount(password string) (common.Address, error) { } e.keyInfos = append(e.keyInfos, info) - e.ethAPI.keys = append(e.ethAPI.keys, emintKey) + e.keys = append(e.keys, emintKey) addr := common.BytesToAddress(info.GetPubKey().Address().Bytes()) e.logger.Info("Your new key was generated", "address", addr.String()) @@ -204,7 +195,7 @@ func (e *PersonalEthAPI) UnlockAccount(ctx context.Context, addr common.Address, } // TODO: this only works on local keys - privKey, err := e.ethAPI.cliCtx.Keybase.ExportPrivateKeyObject(name, password) + privKey, err := e.cliCtx.Keybase.ExportPrivateKeyObject(name, password) if err != nil { return false, err } @@ -214,7 +205,7 @@ func (e *PersonalEthAPI) UnlockAccount(ctx context.Context, addr common.Address, return false, fmt.Errorf("invalid private key type: %T", privKey) } - e.ethAPI.keys = append(e.ethAPI.keys, emintKey) + e.keys = append(e.keys, emintKey) e.logger.Debug("account unlocked", "address", addr.String()) return true, nil } @@ -222,8 +213,8 @@ func (e *PersonalEthAPI) UnlockAccount(ctx context.Context, addr common.Address, // SendTransaction will create a transaction from the given arguments and // tries to sign it with the key associated with args.To. If the given password isn't // able to decrypt the key it fails. -func (e *PersonalEthAPI) SendTransaction(ctx context.Context, args params.SendTxArgs, passwd string) (common.Hash, error) { - return e.ethAPI.SendTransaction(args) +func (e *PersonalEthAPI) SendTransaction(_ context.Context, args params.SendTxArgs, _ string) (common.Hash, error) { + return e.PublicEthAPI.SendTransaction(args) } // Sign calculates an Ethereum ECDSA signature for: @@ -238,7 +229,7 @@ func (e *PersonalEthAPI) SendTransaction(ctx context.Context, args params.SendTx func (e *PersonalEthAPI) Sign(ctx context.Context, data hexutil.Bytes, addr common.Address, passwd string) (hexutil.Bytes, error) { e.logger.Debug("personal_sign", "data", data, "address", addr.String()) - key, ok := checkKeyInKeyring(e.ethAPI.keys, addr) + key, ok := checkKeyInKeyring(e.keys, addr) if !ok { return nil, fmt.Errorf("cannot find key with given address") } From c5620a639dce46c781c6ecbc1cb0f6a2506838d2 Mon Sep 17 00:00:00 2001 From: Federico Kunze Date: Tue, 29 Sep 2020 23:26:58 +0200 Subject: [PATCH 13/14] minor updates --- rpc/personal_api.go | 28 +++++++++++++++++----------- tests/personal_test.go | 4 ++-- 2 files changed, 19 insertions(+), 13 deletions(-) diff --git a/rpc/personal_api.go b/rpc/personal_api.go index 9c47d772d..0f9062e93 100644 --- a/rpc/personal_api.go +++ b/rpc/personal_api.go @@ -178,24 +178,30 @@ func (e *PersonalEthAPI) NewAccount(password string) (common.Address, error) { // the given password for duration seconds. If duration is nil it will use a // default of 300 seconds. It returns an indication if the account was unlocked. // It exports the private key corresponding to the given address from the keyring and stores it in the API's local keys. -func (e *PersonalEthAPI) UnlockAccount(ctx context.Context, addr common.Address, password string, _ *uint64) (bool, error) { // nolint: interfacer +func (e *PersonalEthAPI) UnlockAccount(_ context.Context, addr common.Address, password string, _ *uint64) (bool, error) { // nolint: interfacer e.logger.Debug("personal_unlockAccount", "address", addr.String()) // TODO: use duration - name := "" + var keyInfo keys.Info + for _, info := range e.keyInfos { addressBytes := info.GetPubKey().Address().Bytes() if bytes.Equal(addressBytes, addr[:]) { - name = info.GetName() + keyInfo = info + break } } - if name == "" { + if keyInfo == nil { return false, fmt.Errorf("cannot find key with given address %s", addr.String()) } - // TODO: this only works on local keys - privKey, err := e.cliCtx.Keybase.ExportPrivateKeyObject(name, password) + // exporting private key only works on local keys + if keyInfo.GetType() != keys.TypeLocal { + return false, fmt.Errorf("key type must be %s, got %s", keys.TypeLedger.String(), keyInfo.GetType().String()) + } + + privKey, err := e.cliCtx.Keybase.ExportPrivateKeyObject(keyInfo.GetName(), password) if err != nil { return false, err } @@ -226,12 +232,12 @@ func (e *PersonalEthAPI) SendTransaction(_ context.Context, args params.SendTxAr // The key used to calculate the signature is decrypted with the given password. // // https://github.com/ethereum/go-ethereum/wiki/Management-APIs#personal_sign -func (e *PersonalEthAPI) Sign(ctx context.Context, data hexutil.Bytes, addr common.Address, passwd string) (hexutil.Bytes, error) { +func (e *PersonalEthAPI) Sign(_ context.Context, data hexutil.Bytes, addr common.Address, _ string) (hexutil.Bytes, error) { e.logger.Debug("personal_sign", "data", data, "address", addr.String()) key, ok := checkKeyInKeyring(e.keys, addr) if !ok { - return nil, fmt.Errorf("cannot find key with given address") + return nil, fmt.Errorf("cannot find key with address %s", addr.String()) } sig, err := crypto.Sign(accounts.TextHash(data), key.ToECDSA()) @@ -253,7 +259,7 @@ func (e *PersonalEthAPI) Sign(ctx context.Context, data hexutil.Bytes, addr comm // the V value must be 27 or 28 for legacy reasons. // // https://github.com/ethereum/go-ethereum/wiki/Management-APIs#personal_ecRecove -func (e *PersonalEthAPI) EcRecover(ctx context.Context, data, sig hexutil.Bytes) (common.Address, error) { +func (e *PersonalEthAPI) EcRecover(_ context.Context, data, sig hexutil.Bytes) (common.Address, error) { e.logger.Debug("personal_ecRecover", "data", data, "sig", sig) if len(sig) != crypto.SignatureLength { @@ -264,9 +270,9 @@ func (e *PersonalEthAPI) EcRecover(ctx context.Context, data, sig hexutil.Bytes) } sig[crypto.RecoveryIDOffset] -= 27 // Transform yellow paper V from 27/28 to 0/1 - rpk, err := crypto.SigToPub(accounts.TextHash(data), sig) + pubkey, err := crypto.SigToPub(accounts.TextHash(data), sig) if err != nil { return common.Address{}, err } - return crypto.PubkeyToAddress(*rpk), nil + return crypto.PubkeyToAddress(*pubkey), nil } diff --git a/tests/personal_test.go b/tests/personal_test.go index 3491edbeb..94a881ebc 100644 --- a/tests/personal_test.go +++ b/tests/personal_test.go @@ -86,7 +86,7 @@ func TestPersonal_UnlockAccount(t *testing.T) { // try to sign, should be locked _, err = callWithError("personal_sign", []interface{}{hexutil.Bytes{0x88}, addr, ""}) - require.NotNil(t, err) + require.Error(t, err) rpcRes = call(t, "personal_unlockAccount", []interface{}{addr, ""}) var unlocked bool @@ -123,5 +123,5 @@ func TestPersonal_LockAccount(t *testing.T) { // try to sign, should be locked _, err = callWithError("personal_sign", []interface{}{hexutil.Bytes{0x88}, addr, ""}) - require.NotNil(t, err) + require.Error(t, err) } From 0297bfcc84ed79526338248a40602fa3a6637964 Mon Sep 17 00:00:00 2001 From: noot Date: Tue, 29 Sep 2020 20:21:42 -0400 Subject: [PATCH 14/14] update locked vs unlocked account logic --- rpc/eth_api.go | 2 +- rpc/personal_api.go | 85 +++++++++++++++++++-------------------------- 2 files changed, 37 insertions(+), 50 deletions(-) diff --git a/rpc/eth_api.go b/rpc/eth_api.go index a360fcfbb..059dfa846 100644 --- a/rpc/eth_api.go +++ b/rpc/eth_api.go @@ -46,7 +46,7 @@ type PublicEthAPI struct { chainIDEpoch *big.Int logger log.Logger backend Backend - keys []crypto.PrivKeySecp256k1 + keys []crypto.PrivKeySecp256k1 // unlocked keys nonceLock *AddrLocker keybaseLock sync.Mutex } diff --git a/rpc/personal_api.go b/rpc/personal_api.go index 0f9062e93..439d17039 100644 --- a/rpc/personal_api.go +++ b/rpc/personal_api.go @@ -25,14 +25,14 @@ import ( // PersonalEthAPI is the personal_ prefixed set of APIs in the Web3 JSON-RPC spec. type PersonalEthAPI struct { - *PublicEthAPI - keyInfos []keys.Info + ethAPI *PublicEthAPI + keyInfos []keys.Info // all keys, both locked and unlocked. unlocked keys are stored in ethAPI.keys } // NewPersonalEthAPI creates an instance of the public Personal Eth API. func NewPersonalEthAPI(ethAPI *PublicEthAPI) *PersonalEthAPI { api := &PersonalEthAPI{ - PublicEthAPI: ethAPI, + ethAPI: ethAPI, } infos, err := api.getKeybaseInfo() @@ -45,25 +45,25 @@ func NewPersonalEthAPI(ethAPI *PublicEthAPI) *PersonalEthAPI { } func (e *PersonalEthAPI) getKeybaseInfo() ([]keys.Info, error) { - e.keybaseLock.Lock() - defer e.keybaseLock.Unlock() + e.ethAPI.keybaseLock.Lock() + defer e.ethAPI.keybaseLock.Unlock() - if e.cliCtx.Keybase == nil { + if e.ethAPI.cliCtx.Keybase == nil { keybase, err := keys.NewKeyring( sdk.KeyringServiceName(), viper.GetString(flags.FlagKeyringBackend), viper.GetString(flags.FlagHome), - e.cliCtx.Input, + e.ethAPI.cliCtx.Input, emintcrypto.EthSecp256k1Options()..., ) if err != nil { return nil, err } - e.cliCtx.Keybase = keybase + e.ethAPI.cliCtx.Keybase = keybase } - return e.cliCtx.Keybase.List() + return e.ethAPI.cliCtx.Keybase.List() } // ImportRawKey armors and encrypts a given raw hex encoded ECDSA key and stores it into the key directory. @@ -71,7 +71,7 @@ func (e *PersonalEthAPI) getKeybaseInfo() ([]keys.Info, error) { // keys stored on the keyring. // NOTE: The key will be both armored and encrypted using the same passphrase. func (e *PersonalEthAPI) ImportRawKey(privkey, password string) (common.Address, error) { - e.logger.Debug("personal_importRawKey") + e.ethAPI.logger.Debug("personal_importRawKey") priv, err := crypto.HexToECDSA(privkey) if err != nil { return common.Address{}, err @@ -82,32 +82,31 @@ func (e *PersonalEthAPI) ImportRawKey(privkey, password string) (common.Address, armor := mintkey.EncryptArmorPrivKey(privKey, password, emintcrypto.EthSecp256k1Type) // ignore error as we only care about the length of the list - list, _ := e.cliCtx.Keybase.List() + list, _ := e.ethAPI.cliCtx.Keybase.List() privKeyName := fmt.Sprintf("personal_%d", len(list)) - if err := e.cliCtx.Keybase.ImportPrivKey(privKeyName, armor, password); err != nil { + if err := e.ethAPI.cliCtx.Keybase.ImportPrivKey(privKeyName, armor, password); err != nil { return common.Address{}, err } addr := common.BytesToAddress(privKey.PubKey().Address().Bytes()) - info, err := e.cliCtx.Keybase.Get(privKeyName) + info, err := e.ethAPI.cliCtx.Keybase.Get(privKeyName) if err != nil { return common.Address{}, err } // append key and info to be able to lock and list the account - e.keys = append(e.keys, privKey) + //e.ethAPI.keys = append(e.ethAPI.keys, privKey) e.keyInfos = append(e.keyInfos, info) - - e.logger.Info("key successfully imported", "name", privKeyName, "address", addr.String()) + e.ethAPI.logger.Info("key successfully imported", "name", privKeyName, "address", addr.String()) return addr, nil } // ListAccounts will return a list of addresses for accounts this node manages. func (e *PersonalEthAPI) ListAccounts() ([]common.Address, error) { - e.logger.Debug("personal_listAccounts") + e.ethAPI.logger.Debug("personal_listAccounts") addrs := []common.Address{} for _, info := range e.keyInfos { addressBytes := info.GetPubKey().Address().Bytes() @@ -120,19 +119,19 @@ func (e *PersonalEthAPI) ListAccounts() ([]common.Address, error) { // LockAccount will lock the account associated with the given address when it's unlocked. // It removes the key corresponding to the given address from the API's local keys. func (e *PersonalEthAPI) LockAccount(address common.Address) bool { - e.logger.Debug("personal_lockAccount", "address", address.String()) + e.ethAPI.logger.Debug("personal_lockAccount", "address", address.String()) - for i, key := range e.keys { + for i, key := range e.ethAPI.keys { if !bytes.Equal(key.PubKey().Address().Bytes(), address.Bytes()) { continue } - tmp := make([]emintcrypto.PrivKeySecp256k1, len(e.keys)-1) - copy(tmp[:i], e.keys[:i]) - copy(tmp[i:], e.keys[i+1:]) - e.keys = tmp + tmp := make([]emintcrypto.PrivKeySecp256k1, len(e.ethAPI.keys)-1) + copy(tmp[:i], e.ethAPI.keys[:i]) + copy(tmp[i:], e.ethAPI.keys[i+1:]) + e.ethAPI.keys = tmp - e.logger.Debug("account unlocked", "address", address.String()) + e.ethAPI.logger.Debug("account unlocked", "address", address.String()) return true } @@ -141,36 +140,24 @@ func (e *PersonalEthAPI) LockAccount(address common.Address) bool { // NewAccount will create a new account and returns the address for the new account. func (e *PersonalEthAPI) NewAccount(password string) (common.Address, error) { - e.logger.Debug("personal_newAccount") + e.ethAPI.logger.Debug("personal_newAccount") _, err := e.getKeybaseInfo() if err != nil { return common.Address{}, err } name := "key_" + time.Now().UTC().Format(time.RFC3339) - info, _, err := e.cliCtx.Keybase.CreateMnemonic(name, keys.English, password, emintcrypto.EthSecp256k1) - if err != nil { - return common.Address{}, err - } - - // update ethAPI - privKey, err := e.cliCtx.Keybase.ExportPrivateKeyObject(name, password) + info, _, err := e.ethAPI.cliCtx.Keybase.CreateMnemonic(name, keys.English, password, emintcrypto.EthSecp256k1) if err != nil { return common.Address{}, err } - emintKey, ok := privKey.(emintcrypto.PrivKeySecp256k1) - if !ok { - return common.Address{}, fmt.Errorf("invalid private key type: %T", privKey) - } - e.keyInfos = append(e.keyInfos, info) - e.keys = append(e.keys, emintKey) addr := common.BytesToAddress(info.GetPubKey().Address().Bytes()) - e.logger.Info("Your new key was generated", "address", addr.String()) - e.logger.Info("Please backup your key file!", "path", os.Getenv("HOME")+"/.ethermintcli/"+name) - e.logger.Info("Please remember your password!") + e.ethAPI.logger.Info("Your new key was generated", "address", addr.String()) + e.ethAPI.logger.Info("Please backup your key file!", "path", os.Getenv("HOME")+"/.ethermintcli/"+name) + e.ethAPI.logger.Info("Please remember your password!") return addr, nil } @@ -179,7 +166,7 @@ func (e *PersonalEthAPI) NewAccount(password string) (common.Address, error) { // default of 300 seconds. It returns an indication if the account was unlocked. // It exports the private key corresponding to the given address from the keyring and stores it in the API's local keys. func (e *PersonalEthAPI) UnlockAccount(_ context.Context, addr common.Address, password string, _ *uint64) (bool, error) { // nolint: interfacer - e.logger.Debug("personal_unlockAccount", "address", addr.String()) + e.ethAPI.logger.Debug("personal_unlockAccount", "address", addr.String()) // TODO: use duration var keyInfo keys.Info @@ -201,7 +188,7 @@ func (e *PersonalEthAPI) UnlockAccount(_ context.Context, addr common.Address, p return false, fmt.Errorf("key type must be %s, got %s", keys.TypeLedger.String(), keyInfo.GetType().String()) } - privKey, err := e.cliCtx.Keybase.ExportPrivateKeyObject(keyInfo.GetName(), password) + privKey, err := e.ethAPI.cliCtx.Keybase.ExportPrivateKeyObject(keyInfo.GetName(), password) if err != nil { return false, err } @@ -211,8 +198,8 @@ func (e *PersonalEthAPI) UnlockAccount(_ context.Context, addr common.Address, p return false, fmt.Errorf("invalid private key type: %T", privKey) } - e.keys = append(e.keys, emintKey) - e.logger.Debug("account unlocked", "address", addr.String()) + e.ethAPI.keys = append(e.ethAPI.keys, emintKey) + e.ethAPI.logger.Debug("account unlocked", "address", addr.String()) return true, nil } @@ -220,7 +207,7 @@ func (e *PersonalEthAPI) UnlockAccount(_ context.Context, addr common.Address, p // tries to sign it with the key associated with args.To. If the given password isn't // able to decrypt the key it fails. func (e *PersonalEthAPI) SendTransaction(_ context.Context, args params.SendTxArgs, _ string) (common.Hash, error) { - return e.PublicEthAPI.SendTransaction(args) + return e.ethAPI.SendTransaction(args) } // Sign calculates an Ethereum ECDSA signature for: @@ -233,9 +220,9 @@ func (e *PersonalEthAPI) SendTransaction(_ context.Context, args params.SendTxAr // // https://github.com/ethereum/go-ethereum/wiki/Management-APIs#personal_sign func (e *PersonalEthAPI) Sign(_ context.Context, data hexutil.Bytes, addr common.Address, _ string) (hexutil.Bytes, error) { - e.logger.Debug("personal_sign", "data", data, "address", addr.String()) + e.ethAPI.logger.Debug("personal_sign", "data", data, "address", addr.String()) - key, ok := checkKeyInKeyring(e.keys, addr) + key, ok := checkKeyInKeyring(e.ethAPI.keys, addr) if !ok { return nil, fmt.Errorf("cannot find key with address %s", addr.String()) } @@ -260,7 +247,7 @@ func (e *PersonalEthAPI) Sign(_ context.Context, data hexutil.Bytes, addr common // // https://github.com/ethereum/go-ethereum/wiki/Management-APIs#personal_ecRecove func (e *PersonalEthAPI) EcRecover(_ context.Context, data, sig hexutil.Bytes) (common.Address, error) { - e.logger.Debug("personal_ecRecover", "data", data, "sig", sig) + e.ethAPI.logger.Debug("personal_ecRecover", "data", data, "sig", sig) if len(sig) != crypto.SignatureLength { return common.Address{}, fmt.Errorf("signature must be %d bytes long", crypto.SignatureLength)