Skip to content

Commit

Permalink
Merge PR: export genesis (#455)
Browse files Browse the repository at this point in the history
* merge cosmos/ethermint#619

* use NewDecFromBigIntWithPrec

* fix ut

* update go.mod
  • Loading branch information
zhongqiuwood authored Nov 29, 2020
1 parent f11ddd8 commit 5e0bab6
Show file tree
Hide file tree
Showing 8 changed files with 207 additions and 130 deletions.
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ require (
github.com/btcsuite/btcd v0.21.0-beta
github.com/btcsuite/btcutil v1.0.2
github.com/cespare/cp v1.1.1 // indirect
github.com/cosmos/cosmos-sdk v0.39.1
github.com/cosmos/cosmos-sdk v0.39.2
github.com/deckarep/golang-set v1.7.1 // indirect
github.com/ethereum/go-ethereum v1.9.24
github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5 // indirect
Expand Down
58 changes: 46 additions & 12 deletions x/evm/genesis.go
Original file line number Diff line number Diff line change
@@ -1,29 +1,61 @@
package evm

import (
"fmt"

sdk "github.com/cosmos/cosmos-sdk/types"

emint "github.com/okex/okexchain/app/types"
ethcmn "github.com/ethereum/go-ethereum/common"

ethermint "github.com/okex/okexchain/app/types"
"github.com/okex/okexchain/x/evm/types"

abci "github.com/tendermint/tendermint/abci/types"
)

// InitGenesis initializes genesis state based on exported genesis
func InitGenesis(ctx sdk.Context, k Keeper, data GenesisState) []abci.ValidatorUpdate {
func InitGenesis(ctx sdk.Context, k Keeper, accountKeeper types.AccountKeeper, data GenesisState) []abci.ValidatorUpdate { // nolint: interfacer
evmDenom := data.Params.EvmDenom

for _, account := range data.Accounts {
// FIXME: this will override bank InitGenesis balance!
k.SetBalance(ctx, account.Address, account.Balance)
k.SetCode(ctx, account.Address, account.Code)
address := ethcmn.HexToAddress(account.Address)
accAddress := sdk.AccAddress(address.Bytes())

// check that the EVM balance the matches the account balance
acc := accountKeeper.GetAccount(ctx, accAddress)
if acc == nil {
panic(fmt.Errorf("account not found for address %s", account.Address))
}

_, ok := acc.(*ethermint.EthAccount)
if !ok {
panic(
fmt.Errorf("account %s must be an %T type, got %T",
account.Address, &ethermint.EthAccount{}, acc,
),
)
}

evmBalance := acc.GetCoins().AmountOf(evmDenom)
if !evmBalance.Equal(account.Balance) {
panic(
fmt.Errorf(
"balance mismatch for account %s, expected %s%s, got %s%s",
account.Address, evmBalance, evmDenom, account.Balance, evmDenom,
),
)
}

k.SetBalance(ctx, address, account.Balance.BigInt())
k.SetCode(ctx, address, account.Code)
for _, storage := range account.Storage {
k.SetState(ctx, account.Address, storage.Key, storage.Value)
k.SetState(ctx, address, storage.Key, storage.Value)
}
}

var err error
for _, txLog := range data.TxsLogs {
err = k.SetLogs(ctx, txLog.Hash, txLog.Logs)
if err != nil {
if err = k.SetLogs(ctx, txLog.Hash, txLog.Logs); err != nil {
panic(err)
}
}
Expand Down Expand Up @@ -54,8 +86,7 @@ func ExportGenesis(ctx sdk.Context, k Keeper, ak types.AccountKeeper) GenesisSta
accounts := ak.GetAllAccounts(ctx)

for _, account := range accounts {

ethAccount, ok := account.(*emint.EthAccount)
ethAccount, ok := account.(*ethermint.EthAccount)
if !ok {
continue
}
Expand All @@ -67,9 +98,12 @@ func ExportGenesis(ctx sdk.Context, k Keeper, ak types.AccountKeeper) GenesisSta
panic(err)
}

balanceInt := k.GetBalance(ctx, addr)
balance := sdk.NewDecFromBigIntWithPrec(balanceInt, sdk.Precision)

genAccount := types.GenesisAccount{
Address: addr,
Balance: k.GetBalance(ctx, addr),
Address: addr.String(),
Balance: balance,
Code: k.GetCode(ctx, addr),
Storage: storage,
}
Expand Down
151 changes: 112 additions & 39 deletions x/evm/genesis_test.go

Large diffs are not rendered by default.

10 changes: 7 additions & 3 deletions x/evm/keeper/querier.go
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,8 @@ func queryAccount(ctx sdk.Context, path []string, keeper Keeper) ([]byte, error)
}

func queryExportAccount(ctx sdk.Context, path []string, keeper Keeper) ([]byte, error) {
addr := ethcmn.HexToAddress(path[1])
hexAddress := path[1]
addr := ethcmn.HexToAddress(hexAddress)

var storage types.Storage
err := keeper.ForEachStorage(ctx, addr, func(key, value ethcmn.Hash) bool {
Expand All @@ -211,9 +212,12 @@ func queryExportAccount(ctx sdk.Context, path []string, keeper Keeper) ([]byte,
return nil, err
}

balanceInt := keeper.GetBalance(ctx, addr)
balance := sdk.NewDecFromBigIntWithPrec(balanceInt, sdk.Precision)

res := types.GenesisAccount{
Address: addr,
Balance: keeper.GetBalance(ctx, addr),
Address: hexAddress,
Balance: balance,
Code: keeper.GetCode(ctx, addr),
Storage: storage,
}
Expand Down
2 changes: 1 addition & 1 deletion x/evm/module.go
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ func (am AppModule) EndBlock(ctx sdk.Context, req abci.RequestEndBlock) []abci.V
func (am AppModule) InitGenesis(ctx sdk.Context, data json.RawMessage) []abci.ValidatorUpdate {
var genesisState types.GenesisState
types.ModuleCdc.MustUnmarshalJSON(data, &genesisState)
return InitGenesis(ctx, am.keeper, genesisState)
return InitGenesis(ctx, am.keeper, am.ak, genesisState)
}

// ExportGenesis exports the genesis state to be used by daemon
Expand Down
38 changes: 0 additions & 38 deletions x/evm/module_test.go

This file was deleted.

29 changes: 15 additions & 14 deletions x/evm/types/genesis.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
package types

import (
"bytes"
"errors"
"fmt"
"math/big"

sdk "github.com/cosmos/cosmos-sdk/types"

ethcmn "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
Expand All @@ -23,22 +23,22 @@ type (
// Its main difference between with Geth's GenesisAccount is that it uses a custom
// storage type and that it doesn't contain the private key field.
GenesisAccount struct {
Address ethcmn.Address `json:"address"`
Balance *big.Int `json:"balance"`
Code hexutil.Bytes `json:"code,omitempty"`
Storage Storage `json:"storage,omitempty"`
Address string `json:"address"`
Balance sdk.Dec `json:"balance"`
Code hexutil.Bytes `json:"code,omitempty"`
Storage Storage `json:"storage,omitempty"`
}
)

// Validate performs a basic validation of a GenesisAccount fields.
func (ga GenesisAccount) Validate() error {
if bytes.Equal(ga.Address.Bytes(), ethcmn.Address{}.Bytes()) {
return fmt.Errorf("address cannot be the zero address %s", ga.Address.String())
if ga.Address == (ethcmn.Address{}.String()) {
return fmt.Errorf("address cannot be the zero address %s", ga.Address)
}
if ga.Balance == nil {
if ga.Balance.IsNil() {
return errors.New("balance cannot be nil")
}
if ga.Balance.Sign() == -1 {
if ga.Balance.IsNegative() {
return errors.New("balance cannot be negative")
}
if ga.Code != nil && len(ga.Code) == 0 {
Expand All @@ -65,14 +65,15 @@ func (gs GenesisState) Validate() error {
seenAccounts := make(map[string]bool)
seenTxs := make(map[string]bool)
for _, acc := range gs.Accounts {
if seenAccounts[acc.Address.String()] {
return fmt.Errorf("duplicated genesis account %s", acc.Address.String())
if seenAccounts[acc.Address] {
return fmt.Errorf("duplicated genesis account %s", acc.Address)
}
if err := acc.Validate(); err != nil {
return fmt.Errorf("invalid genesis account %s: %w", acc.Address.String(), err)
return fmt.Errorf("invalid genesis account %s: %w", acc.Address, err)
}
seenAccounts[acc.Address.String()] = true
seenAccounts[acc.Address] = true
}

for _, tx := range gs.TxsLogs {
if seenTxs[tx.Hash.String()] {
return fmt.Errorf("duplicated logs from transaction %s", tx.Hash.String())
Expand Down
47 changes: 25 additions & 22 deletions x/evm/types/genesis_test.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package types

import (
"math/big"
"testing"

"github.com/stretchr/testify/require"
Expand All @@ -10,9 +9,13 @@ import (
ethtypes "github.com/ethereum/go-ethereum/core/types"
ethcrypto "github.com/ethereum/go-ethereum/crypto"

sdk "github.com/cosmos/cosmos-sdk/types"

"github.com/okex/okexchain/app/crypto/ethsecp256k1"
)

var address = ethcmn.BytesToAddress([]byte{1, 2, 3, 4, 5})

func TestValidateGenesisAccount(t *testing.T) {
testCases := []struct {
name string
Expand All @@ -22,8 +25,8 @@ func TestValidateGenesisAccount(t *testing.T) {
{
"valid genesis account",
GenesisAccount{
Address: ethcmn.BytesToAddress([]byte{1, 2, 3, 4, 5}),
Balance: big.NewInt(1),
Address: address.String(),
Balance: sdk.NewDec(1),
Code: []byte{1, 2, 3},
Storage: Storage{
NewState(ethcmn.BytesToHash([]byte{1, 2, 3}), ethcmn.BytesToHash([]byte{1, 2, 3})),
Expand All @@ -34,32 +37,32 @@ func TestValidateGenesisAccount(t *testing.T) {
{
"empty account address bytes",
GenesisAccount{
Address: ethcmn.Address{},
Balance: big.NewInt(1),
Address: ethcmn.Address{}.String(),
Balance: sdk.NewDec(1),
},
false,
},
{
"nil account balance",
GenesisAccount{
Address: ethcmn.BytesToAddress([]byte{1, 2, 3, 4, 5}),
Balance: nil,
Address: address.String(),
Balance: sdk.Dec{},
},
false,
},
{
"nil account balance",
GenesisAccount{
Address: ethcmn.BytesToAddress([]byte{1, 2, 3, 4, 5}),
Balance: big.NewInt(-1),
Address: address.String(),
Balance: sdk.NewDec(-1),
},
false,
},
{
"empty code bytes",
GenesisAccount{
Address: ethcmn.BytesToAddress([]byte{1, 2, 3, 4, 5}),
Balance: big.NewInt(1),
Address: address.String(),
Balance: sdk.NewDec(1),
Code: []byte{},
},
false,
Expand Down Expand Up @@ -97,8 +100,8 @@ func TestValidateGenesis(t *testing.T) {
genState: GenesisState{
Accounts: []GenesisAccount{
{
Address: ethcmn.BytesToAddress([]byte{1, 2, 3, 4, 5}),
Balance: big.NewInt(1),
Address: address.String(),
Balance: sdk.NewDec(1),
Code: []byte{1, 2, 3},
Storage: Storage{
{Key: ethcmn.BytesToHash([]byte{1, 2, 3})},
Expand Down Expand Up @@ -138,7 +141,7 @@ func TestValidateGenesis(t *testing.T) {
genState: GenesisState{
Accounts: []GenesisAccount{
{
Address: ethcmn.Address{},
Address: ethcmn.Address{}.String(),
},
},
},
Expand All @@ -149,16 +152,16 @@ func TestValidateGenesis(t *testing.T) {
genState: GenesisState{
Accounts: []GenesisAccount{
{
Address: ethcmn.BytesToAddress([]byte{1, 2, 3, 4, 5}),
Balance: big.NewInt(1),
Address: address.String(),
Balance: sdk.NewDec(1),
Code: []byte{1, 2, 3},
Storage: Storage{
NewState(ethcmn.BytesToHash([]byte{1, 2, 3}), ethcmn.BytesToHash([]byte{1, 2, 3})),
},
},
{
Address: ethcmn.BytesToAddress([]byte{1, 2, 3, 4, 5}),
Balance: big.NewInt(1),
Address: address.String(),
Balance: sdk.NewDec(1),
Code: []byte{1, 2, 3},
Storage: Storage{
NewState(ethcmn.BytesToHash([]byte{1, 2, 3}), ethcmn.BytesToHash([]byte{1, 2, 3})),
Expand All @@ -173,8 +176,8 @@ func TestValidateGenesis(t *testing.T) {
genState: GenesisState{
Accounts: []GenesisAccount{
{
Address: ethcmn.BytesToAddress([]byte{1, 2, 3, 4, 5}),
Balance: big.NewInt(1),
Address: address.String(),
Balance: sdk.NewDec(1),
Code: []byte{1, 2, 3},
Storage: Storage{
{Key: ethcmn.BytesToHash([]byte{1, 2, 3})},
Expand Down Expand Up @@ -223,8 +226,8 @@ func TestValidateGenesis(t *testing.T) {
genState: GenesisState{
Accounts: []GenesisAccount{
{
Address: ethcmn.BytesToAddress([]byte{1, 2, 3, 4, 5}),
Balance: big.NewInt(1),
Address: address.String(),
Balance: sdk.NewDec(1),
Code: []byte{1, 2, 3},
Storage: Storage{
{Key: ethcmn.BytesToHash([]byte{1, 2, 3})},
Expand Down

0 comments on commit 5e0bab6

Please sign in to comment.