Skip to content
This repository has been archived by the owner on Nov 30, 2021. It is now read-only.

app: fix export genesis #619

Merged
merged 8 commits into from
Nov 27, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,13 @@ Ref: https://keepachangelog.com/en/1.0.0/

## Unreleased

### Bug Fixes

* (evm) [\#621](https://github.com/cosmos/ethermint/issues/621) EVM `GenesisAccount` fields now share the same format as the auth module `Account`.
* (app) [\#617](https://github.com/cosmos/ethermint/issues/617) Fix genesis export functionality.

## [v0.3.1] - 2020-11-24

### Improvements

* (deps) [\#615](https://github.com/cosmos/ethermint/pull/615) Bump Cosmos SDK version to [v0.39.2](https://github.com/cosmos/cosmos-sdk/tag/v0.39.2)
Expand Down
10 changes: 6 additions & 4 deletions cmd/ethermintd/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -111,14 +111,16 @@ func newApp(logger log.Logger, db dbm.DB, traceStore io.Writer) abci.Application
func exportAppStateAndTMValidators(
logger log.Logger, db dbm.DB, traceStore io.Writer, height int64, forZeroHeight bool, jailWhiteList []string,
) (json.RawMessage, []tmtypes.GenesisValidator, error) {

ethermintApp := app.NewEthermintApp(logger, db, traceStore, true, map[int64]bool{}, 0)
var ethermintApp *app.EthermintApp

if height != -1 {
err := ethermintApp.LoadHeight(height)
if err != nil {
ethermintApp = app.NewEthermintApp(logger, db, traceStore, false, map[int64]bool{}, 0)

if err := ethermintApp.LoadHeight(height); err != nil {
return nil, nil, err
}
} else {
ethermintApp = app.NewEthermintApp(logger, db, traceStore, true, map[int64]bool{}, 0)
}

return ethermintApp.ExportAppStateAndValidators(forZeroHeight, jailWhiteList)
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/cosmos/ethermint/types"
ethcmn "github.com/ethereum/go-ethereum/common"

ethermint "github.com/cosmos/ethermint/types"
"github.com/cosmos/ethermint/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.NewIntFromBigInt(balanceInt)

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.NewIntFromBigInt(balanceInt)

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.Int `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
Loading