From 878ea072d6c85f20826ec8f607a59fb925e8a8af Mon Sep 17 00:00:00 2001 From: Federico Kunze Date: Tue, 1 Sep 2020 23:30:42 +0200 Subject: [PATCH 1/7] types: update account pubkey JSON to string --- app/ethermint.go | 1 + types/account.go | 31 +++++++++++++++---------------- types/config_test.go | 2 ++ 3 files changed, 18 insertions(+), 16 deletions(-) diff --git a/app/ethermint.go b/app/ethermint.go index a219f3fb3..b8658377f 100644 --- a/app/ethermint.go +++ b/app/ethermint.go @@ -43,6 +43,7 @@ func init() { config := sdk.GetConfig() ethermint.SetBech32Prefixes(config) ethermint.SetBip44CoinType(config) + config.Seal() } const appName = "Ethermint" diff --git a/types/account.go b/types/account.go index 4f22eccdf..f7dfc9920 100644 --- a/types/account.go +++ b/types/account.go @@ -11,8 +11,6 @@ import ( "github.com/cosmos/cosmos-sdk/x/auth/exported" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" - tmamino "github.com/tendermint/tendermint/crypto/encoding/amino" - ethcmn "github.com/ethereum/go-ethereum/common" ethcrypto "github.com/ethereum/go-ethereum/crypto" ) @@ -79,7 +77,7 @@ func (acc *EthAccount) SetBalance(amt sdk.Int) { type ethermintAccountPretty struct { Address sdk.AccAddress `json:"address" yaml:"address"` Coins sdk.Coins `json:"coins" yaml:"coins"` - PubKey []byte `json:"public_key" yaml:"public_key"` + PubKey string `json:"public_key" yaml:"public_key"` AccountNumber uint64 `json:"account_number" yaml:"account_number"` Sequence uint64 `json:"sequence" yaml:"sequence"` CodeHash string `json:"code_hash" yaml:"code_hash"` @@ -95,8 +93,10 @@ func (acc EthAccount) MarshalYAML() (interface{}, error) { CodeHash: ethcmn.Bytes2Hex(acc.CodeHash), } - if acc.PubKey != nil { - alias.PubKey = acc.PubKey.Bytes() + var err error + alias.PubKey, err = sdk.Bech32ifyPubKey(sdk.Bech32PubKeyTypeAccPub, acc.PubKey) + if err != nil { + return nil, err } bz, err := yaml.Marshal(alias) @@ -117,8 +117,10 @@ func (acc EthAccount) MarshalJSON() ([]byte, error) { CodeHash: ethcmn.Bytes2Hex(acc.CodeHash), } - if acc.PubKey != nil { - alias.PubKey = acc.PubKey.Bytes() + var err error + alias.PubKey, err = sdk.Bech32ifyPubKey(sdk.Bech32PubKeyTypeAccPub, acc.PubKey) + if err != nil { + return nil, err } return json.Marshal(alias) @@ -132,17 +134,14 @@ func (acc *EthAccount) UnmarshalJSON(bz []byte) error { return err } - if alias.PubKey != nil { - pubKey, err := tmamino.PubKeyFromBytes(alias.PubKey) - if err != nil { - return err - } - - acc.BaseAccount.PubKey = pubKey - } - acc.BaseAccount.Coins = alias.Coins acc.BaseAccount.Address = alias.Address + + var err error + acc.BaseAccount.PubKey, err = sdk.GetPubKeyFromBech32(sdk.Bech32PubKeyTypeAccPub, alias.PubKey) + if err != nil { + return err + } acc.BaseAccount.AccountNumber = alias.AccountNumber acc.BaseAccount.Sequence = alias.Sequence acc.CodeHash = ethcmn.Hex2Bytes(alias.CodeHash) diff --git a/types/config_test.go b/types/config_test.go index 966b0bcfb..e72931eed 100644 --- a/types/config_test.go +++ b/types/config_test.go @@ -36,8 +36,10 @@ func TestSetBech32Prefixes(t *testing.T) { func TestSetCoinType(t *testing.T) { config := sdk.GetConfig() require.Equal(t, sdk.CoinType, int(config.GetCoinType())) + require.Equal(t, sdk.FullFundraiserPath, config.GetFullFundraiserPath()) SetBip44CoinType(config) require.Equal(t, Bip44CoinType, int(config.GetCoinType())) require.Equal(t, sdk.GetConfig().GetCoinType(), config.GetCoinType()) + require.Equal(t, sdk.GetConfig().GetFullFundraiserPath(), config.GetFullFundraiserPath()) } From acf5ade931b2c495dba6f10556109be88b5e5d93 Mon Sep 17 00:00:00 2001 From: Federico Kunze Date: Tue, 1 Sep 2020 23:33:17 +0200 Subject: [PATCH 2/7] changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 986269800..00a5a1a77 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -39,6 +39,7 @@ Ref: https://keepachangelog.com/en/1.0.0/ ### Improvements +* (types) [\#494](https://github.com/ChainSafe/ethermint/pull/494) Update `EthAccount` public key JSON type to `string`. * (app) [\#471](https://github.com/ChainSafe/ethermint/pull/471) Add `x/upgrade` module for managing software updates. ### Bug Fixes From f6a45c6b922e0625549c00011109491a0419005d Mon Sep 17 00:00:00 2001 From: Federico Kunze <31522760+fedekunze@users.noreply.github.com> Date: Wed, 2 Sep 2020 16:04:30 +0200 Subject: [PATCH 3/7] Update app/ethermint.go --- app/ethermint.go | 1 - 1 file changed, 1 deletion(-) diff --git a/app/ethermint.go b/app/ethermint.go index b8658377f..a219f3fb3 100644 --- a/app/ethermint.go +++ b/app/ethermint.go @@ -43,7 +43,6 @@ func init() { config := sdk.GetConfig() ethermint.SetBech32Prefixes(config) ethermint.SetBip44CoinType(config) - config.Seal() } const appName = "Ethermint" From 80d0b7e6e1920b4074a5a352fb66e016eb2b3a0e Mon Sep 17 00:00:00 2001 From: Federico Kunze Date: Wed, 2 Sep 2020 22:11:23 +0200 Subject: [PATCH 4/7] tests --- types/account.go | 51 ++++++++++++++++++++++++++++--------------- types/account_test.go | 39 ++++++++++++++++++++++++++++++++- types/config_test.go | 2 ++ 3 files changed, 74 insertions(+), 18 deletions(-) diff --git a/types/account.go b/types/account.go index f7dfc9920..2c66721a8 100644 --- a/types/account.go +++ b/types/account.go @@ -94,9 +94,12 @@ func (acc EthAccount) MarshalYAML() (interface{}, error) { } var err error - alias.PubKey, err = sdk.Bech32ifyPubKey(sdk.Bech32PubKeyTypeAccPub, acc.PubKey) - if err != nil { - return nil, err + + if acc.PubKey != nil { + alias.PubKey, err = sdk.Bech32ifyPubKey(sdk.Bech32PubKeyTypeAccPub, acc.PubKey) + if err != nil { + return nil, err + } } bz, err := yaml.Marshal(alias) @@ -118,9 +121,12 @@ func (acc EthAccount) MarshalJSON() ([]byte, error) { } var err error - alias.PubKey, err = sdk.Bech32ifyPubKey(sdk.Bech32PubKeyTypeAccPub, acc.PubKey) - if err != nil { - return nil, err + + if acc.PubKey != nil { + alias.PubKey, err = sdk.Bech32ifyPubKey(sdk.Bech32PubKeyTypeAccPub, acc.PubKey) + if err != nil { + return nil, err + } } return json.Marshal(alias) @@ -128,23 +134,34 @@ func (acc EthAccount) MarshalJSON() ([]byte, error) { // UnmarshalJSON unmarshals raw JSON bytes into an EthAccount. func (acc *EthAccount) UnmarshalJSON(bz []byte) error { - acc.BaseAccount = &authtypes.BaseAccount{} - var alias ethermintAccountPretty + var ( + alias ethermintAccountPretty + err error + ) + if err := json.Unmarshal(bz, &alias); err != nil { return err } - acc.BaseAccount.Coins = alias.Coins - acc.BaseAccount.Address = alias.Address - - var err error - acc.BaseAccount.PubKey, err = sdk.GetPubKeyFromBech32(sdk.Bech32PubKeyTypeAccPub, alias.PubKey) - if err != nil { - return err + acc.BaseAccount = &authtypes.BaseAccount{ + Coins: alias.Coins, + Address: alias.Address, + AccountNumber: alias.AccountNumber, + Sequence: alias.Sequence, } - acc.BaseAccount.AccountNumber = alias.AccountNumber - acc.BaseAccount.Sequence = alias.Sequence acc.CodeHash = ethcmn.Hex2Bytes(alias.CodeHash) + if alias.PubKey != "" { + acc.BaseAccount.PubKey, err = sdk.GetPubKeyFromBech32(sdk.Bech32PubKeyTypeAccPub, alias.PubKey) + if err != nil { + return err + } + } return nil } + +// String implements the fmt.Stringer interface +func (acc *EthAccount) String() string { + out, _ := yaml.Marshal(acc) + return string(out) +} diff --git a/types/account_test.go b/types/account_test.go index cb13b66e3..5f44fe755 100644 --- a/types/account_test.go +++ b/types/account_test.go @@ -2,6 +2,7 @@ package types import ( "encoding/json" + "fmt" "testing" "github.com/stretchr/testify/require" @@ -35,7 +36,7 @@ func TestEthermintAccountJSON(t *testing.T) { require.Equal(t, string(bz1), string(bz)) var a EthAccount - require.NoError(t, json.Unmarshal(bz, &a)) + require.NoError(t, a.UnmarshalJSON(bz)) require.Equal(t, ethAcc.String(), a.String()) require.Equal(t, ethAcc.PubKey, a.PubKey) } @@ -58,3 +59,39 @@ func TestSecpPubKeyJSON(t *testing.T) { require.NoError(t, err) require.Equal(t, pubk, pubkey) } + +func TestEthermintAccount_String(t *testing.T) { + pubkey := secp256k1.GenPrivKey().PubKey() + addr := sdk.AccAddress(pubkey.Address()) + balance := sdk.NewCoins(sdk.NewCoin(DenomDefault, sdk.OneInt())) + baseAcc := auth.NewBaseAccount(addr, balance, pubkey, 10, 50) + ethAcc := EthAccount{BaseAccount: baseAcc, CodeHash: []byte{1, 2}} + + config := sdk.GetConfig() + SetBech32Prefixes(config) + + bech32pubkey, err := sdk.Bech32ifyPubKey(sdk.Bech32PubKeyTypeAccPub, pubkey) + require.NoError(t, err) + + accountStr := fmt.Sprintf(`| + address: %s + coins: + - denom: aphoton + amount: "1" + public_key: %s + account_number: 10 + sequence: 50 + code_hash: "0102" +`, addr, bech32pubkey) + + require.Equal(t, accountStr, ethAcc.String()) + + i, err := ethAcc.MarshalYAML() + require.NoError(t, err) + + var ok bool + accountStr, ok = i.(string) + require.True(t, ok) + require.Contains(t, accountStr, addr.String()) + require.Contains(t, accountStr, bech32pubkey) +} diff --git a/types/config_test.go b/types/config_test.go index e72931eed..0b9850742 100644 --- a/types/config_test.go +++ b/types/config_test.go @@ -10,6 +10,8 @@ import ( func TestSetBech32Prefixes(t *testing.T) { config := sdk.GetConfig() + config = sdk.NewConfig() // reset config values + require.Equal(t, sdk.Bech32PrefixAccAddr, config.GetBech32AccountAddrPrefix()) require.Equal(t, sdk.Bech32PrefixAccPub, config.GetBech32AccountPubPrefix()) require.Equal(t, sdk.Bech32PrefixValAddr, config.GetBech32ValidatorAddrPrefix()) From 976c6ab35250058b3d1257f251b955ac3b976286 Mon Sep 17 00:00:00 2001 From: Federico Kunze Date: Wed, 2 Sep 2020 22:17:10 +0200 Subject: [PATCH 5/7] update --- types/account.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/types/account.go b/types/account.go index 2c66721a8..8020ed1bf 100644 --- a/types/account.go +++ b/types/account.go @@ -161,7 +161,7 @@ func (acc *EthAccount) UnmarshalJSON(bz []byte) error { } // String implements the fmt.Stringer interface -func (acc *EthAccount) String() string { +func (acc EthAccount) String() string { out, _ := yaml.Marshal(acc) return string(out) } From 5fc2d2d0f3d7274196b0f37c9cdb63b71c259070 Mon Sep 17 00:00:00 2001 From: noot <36753753+noot@users.noreply.github.com> Date: Mon, 7 Sep 2020 08:45:20 -0400 Subject: [PATCH 6/7] fix secp256k1 public key formatting (#501) * use Compress and Decompress pubkey for secp256k1 keys * cleanup * update estimate gas test --- crypto/secp256k1.go | 13 ++++++++++--- tests/rpc_test.go | 2 +- types/account_test.go | 16 ++++++++++++++++ 3 files changed, 27 insertions(+), 4 deletions(-) diff --git a/crypto/secp256k1.go b/crypto/secp256k1.go index c8ae6ad2c..8f6d75931 100644 --- a/crypto/secp256k1.go +++ b/crypto/secp256k1.go @@ -33,7 +33,7 @@ func GenerateKey() (PrivKeySecp256k1, error) { // PubKey returns the ECDSA private key's public key. func (privkey PrivKeySecp256k1) PubKey() tmcrypto.PubKey { ecdsaPKey := privkey.ToECDSA() - return PubKeySecp256k1(ethcrypto.FromECDSAPub(&ecdsaPKey.PublicKey)) + return PubKeySecp256k1(ethcrypto.CompressPubkey(&ecdsaPKey.PublicKey)) } // Bytes returns the raw ECDSA private key bytes. @@ -59,7 +59,10 @@ func (privkey PrivKeySecp256k1) Equals(other tmcrypto.PrivKey) bool { // ToECDSA returns the ECDSA private key as a reference to ecdsa.PrivateKey type. func (privkey PrivKeySecp256k1) ToECDSA() *ecdsa.PrivateKey { - key, _ := ethcrypto.ToECDSA(privkey) + key, err := ethcrypto.ToECDSA(privkey) + if err != nil { + panic(err) + } return key } @@ -74,7 +77,11 @@ type PubKeySecp256k1 []byte // Address returns the address of the ECDSA public key. func (key PubKeySecp256k1) Address() tmcrypto.Address { - pubk, _ := ethcrypto.UnmarshalPubkey(key) + pubk, err := ethcrypto.DecompressPubkey(key) + if err != nil { + panic(err) + } + return tmcrypto.Address(ethcrypto.PubkeyToAddress(*pubk).Bytes()) } diff --git a/tests/rpc_test.go b/tests/rpc_test.go index bf775b92d..6bfc2d584 100644 --- a/tests/rpc_test.go +++ b/tests/rpc_test.go @@ -758,7 +758,7 @@ func TestEth_EstimateGas(t *testing.T) { err := json.Unmarshal(rpcRes.Result, &gas) require.NoError(t, err, string(rpcRes.Result)) - require.Equal(t, "0x1051d", gas) + require.Equal(t, "0xfd40", gas) } func TestEth_EstimateGas_ContractDeployment(t *testing.T) { diff --git a/types/account_test.go b/types/account_test.go index 5f44fe755..98cad2bff 100644 --- a/types/account_test.go +++ b/types/account_test.go @@ -95,3 +95,19 @@ func TestEthermintAccount_String(t *testing.T) { require.Contains(t, accountStr, addr.String()) require.Contains(t, accountStr, bech32pubkey) } + +func TestEthermintAccount_MarshalJSON(t *testing.T) { + pubkey := secp256k1.GenPrivKey().PubKey() + addr := sdk.AccAddress(pubkey.Address()) + balance := sdk.NewCoins(sdk.NewCoin(DenomDefault, sdk.OneInt())) + baseAcc := auth.NewBaseAccount(addr, balance, pubkey, 10, 50) + ethAcc := &EthAccount{BaseAccount: baseAcc, CodeHash: []byte{1, 2}} + + bz, err := ethAcc.MarshalJSON() + require.NoError(t, err) + + res := new(EthAccount) + err = res.UnmarshalJSON(bz) + require.NoError(t, err) + require.Equal(t, ethAcc, res) +} From 7dce82db6e5e9919270ee7e0b28ed11611734cf6 Mon Sep 17 00:00:00 2001 From: Federico Kunze Date: Mon, 7 Sep 2020 14:54:24 +0200 Subject: [PATCH 7/7] comments --- crypto/secp256k1.go | 7 +++++-- docs/basics/accounts.md | 2 +- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/crypto/secp256k1.go b/crypto/secp256k1.go index 8f6d75931..099e9197f 100644 --- a/crypto/secp256k1.go +++ b/crypto/secp256k1.go @@ -58,6 +58,7 @@ func (privkey PrivKeySecp256k1) Equals(other tmcrypto.PrivKey) bool { } // ToECDSA returns the ECDSA private key as a reference to ecdsa.PrivateKey type. +// The function will panic if the private key is invalid. func (privkey PrivKeySecp256k1) ToECDSA() *ecdsa.PrivateKey { key, err := ethcrypto.ToECDSA(privkey) if err != nil { @@ -71,11 +72,12 @@ func (privkey PrivKeySecp256k1) ToECDSA() *ecdsa.PrivateKey { var _ tmcrypto.PubKey = (*PubKeySecp256k1)(nil) -// PubKeySecp256k1 defines a type alias for an ecdsa.PublicKey that implements -// Tendermint's PubKey interface. +// PubKeySecp256k1 defines a type alias for an ecdsa.PublicKey that implements Tendermint's PubKey +// interface. It represents the 33-byte compressed public key format. type PubKeySecp256k1 []byte // Address returns the address of the ECDSA public key. +// The function will panic if the public key is invalid. func (key PubKeySecp256k1) Address() tmcrypto.Address { pubk, err := ethcrypto.DecompressPubkey(key) if err != nil { @@ -86,6 +88,7 @@ func (key PubKeySecp256k1) Address() tmcrypto.Address { } // Bytes returns the raw bytes of the ECDSA public key. +// The function panics if the key cannot be marshaled to bytes. func (key PubKeySecp256k1) Bytes() []byte { bz, err := CryptoCodec.MarshalBinaryBare(key) if err != nil { diff --git a/docs/basics/accounts.md b/docs/basics/accounts.md index ed553ea22..ef21a7620 100644 --- a/docs/basics/accounts.md +++ b/docs/basics/accounts.md @@ -43,7 +43,7 @@ Cosmos `sdk.AccAddress`. - Address (Bech32): `eth1crwhac03z2pcgu88jfnqnwu66xlthlz2rhljah` - Address (Hex): `0xc0dd7ee1f112838470e7926609bb9ad1bebbfc4a` -- Public Key (Bech32): `ethpub1pfqnmk6pqnwwuw0h9hj58t2hyzwvqc3truhhp5tl5hfucezcfy2rs8470nkyzju2vmk645fzmw2wveaqcqek767kwa0es9rmxe9nmmjq84cpny3fvj6tpg` +- Compressed Public Key (Bech32): `ethpub1pfqnmk6pqnwwuw0h9hj58t2hyzwvqc3truhhp5tl5hfucezcfy2rs8470nkyzju2vmk645fzmw2wveaqcqek767kwa0es9rmxe9nmmjq84cpny3fvj6tpg` ## Next {hide}