types: unmarshal account from hex address (#504)

* types: unmarshal account from hex address:

* changelog
This commit is contained in:
Federico Kunze 2020-09-08 17:58:19 +02:00 committed by GitHub
parent 1505ba89a1
commit d6783707dc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 78 additions and 4 deletions

View File

@ -43,6 +43,7 @@ Ref: https://keepachangelog.com/en/1.0.0/
### Improvements
* (types) [\#504](https://github.com/ChainSafe/ethermint/pull/504) Unmarshal a JSON `EthAccount` using an Ethereum hex address in addition to Bech32.
* (types) [\#503](https://github.com/ChainSafe/ethermint/pull/503) Add `--coin-denom` flag to testnet command that sets the given coin denomination to SDK and Ethermint parameters.
* (types) [\#502](https://github.com/ChainSafe/ethermint/pull/502) `EthAccount` now also exposes the Ethereum hex address in `string` format to clients.
* (types) [\#494](https://github.com/ChainSafe/ethermint/pull/494) Update `EthAccount` public key JSON type to `string`.

View File

@ -1,12 +1,14 @@
package types
import (
"bytes"
"encoding/json"
"fmt"
"gopkg.in/yaml.v2"
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
"github.com/cosmos/cosmos-sdk/x/auth"
"github.com/cosmos/cosmos-sdk/x/auth/exported"
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
@ -114,9 +116,15 @@ func (acc EthAccount) MarshalYAML() (interface{}, error) {
// MarshalJSON returns the JSON representation of an EthAccount.
func (acc EthAccount) MarshalJSON() ([]byte, error) {
var ethAddress = ""
if acc.BaseAccount != nil && acc.Address != nil {
ethAddress = acc.EthAddress().String()
}
alias := ethermintAccountPretty{
Address: acc.Address,
EthAddress: acc.EthAddress().String(),
EthAddress: ethAddress,
Coins: acc.Coins,
AccountNumber: acc.AccountNumber,
Sequence: acc.Sequence,
@ -146,6 +154,37 @@ func (acc *EthAccount) UnmarshalJSON(bz []byte) error {
return err
}
switch {
case !alias.Address.Empty() && alias.EthAddress != "":
// Both addresses provided. Verify correctness
ethAddress := ethcmn.HexToAddress(alias.EthAddress)
ethAddressFromAccAddress := ethcmn.BytesToAddress(alias.Address.Bytes())
if !bytes.Equal(ethAddress.Bytes(), alias.Address.Bytes()) {
err = sdkerrors.Wrapf(
sdkerrors.ErrInvalidAddress,
"expected %s, got %s",
ethAddressFromAccAddress.String(), ethAddress.String(),
)
}
case !alias.Address.Empty() && alias.EthAddress == "":
// unmarshal sdk.AccAddress only. Do nothing here
case alias.Address.Empty() && alias.EthAddress != "":
// retrieve sdk.AccAddress from ethereum address
ethAddress := ethcmn.HexToAddress(alias.EthAddress)
alias.Address = sdk.AccAddress(ethAddress.Bytes())
case alias.Address.Empty() && alias.EthAddress == "":
err = sdkerrors.Wrapf(
sdkerrors.ErrInvalidAddress,
"account must contain address in Ethereum Hex or Cosmos Bech32 format",
)
}
if err != nil {
return err
}
acc.BaseAccount = &authtypes.BaseAccount{
Coins: alias.Coins,
Address: alias.Address,

View File

@ -7,12 +7,12 @@ import (
"github.com/stretchr/testify/require"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/auth"
tmamino "github.com/tendermint/tendermint/crypto/encoding/amino"
"github.com/tendermint/tendermint/crypto/secp256k1"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/auth"
emintcrypto "github.com/cosmos/ethermint/crypto"
)
@ -106,9 +106,43 @@ func TestEthermintAccount_MarshalJSON(t *testing.T) {
bz, err := ethAcc.MarshalJSON()
require.NoError(t, err)
require.Contains(t, string(bz), ethAcc.EthAddress().String())
res := new(EthAccount)
err = res.UnmarshalJSON(bz)
require.NoError(t, err)
require.Equal(t, ethAcc, res)
bech32pubkey, err := sdk.Bech32ifyPubKey(sdk.Bech32PubKeyTypeAccPub, pubkey)
require.NoError(t, err)
// test that the sdk.AccAddress is populated from the hex address
jsonAcc := fmt.Sprintf(
`{"address":"","eth_address":"%s","coins":[{"denom":"aphoton","amount":"1"}],"public_key":"%s","account_number":10,"sequence":50,"code_hash":"0102"}`,
ethAcc.EthAddress().String(), bech32pubkey,
)
res = new(EthAccount)
err = res.UnmarshalJSON([]byte(jsonAcc))
require.NoError(t, err)
require.Equal(t, addr.String(), res.Address.String())
jsonAcc = fmt.Sprintf(
`{"address":"","eth_address":"","coins":[{"denom":"aphoton","amount":"1"}],"public_key":"%s","account_number":10,"sequence":50,"code_hash":"0102"}`,
bech32pubkey,
)
res = new(EthAccount)
err = res.UnmarshalJSON([]byte(jsonAcc))
require.Error(t, err, "should fail if both address are empty")
// test that the sdk.AccAddress is populated from the hex address
jsonAcc = fmt.Sprintf(
`{"address": "%s","eth_address":"0x0000000000000000000000000000000000000000","coins":[{"denom":"aphoton","amount":"1"}],"public_key":"%s","account_number":10,"sequence":50,"code_hash":"0102"}`,
ethAcc.Address.String(), bech32pubkey,
)
res = new(EthAccount)
err = res.UnmarshalJSON([]byte(jsonAcc))
require.Error(t, err, "should fail if addresses mismatch")
}