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

stargate: migrate types #670

Merged
merged 16 commits into from
Jan 6, 2021
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,12 @@ Ref: https://keepachangelog.com/en/1.0.0/

### API Breaking

* (evm) [\#670](https://github.com/cosmos/ethermint/pull/670) Migrate types to the ones defined by the protobuf messages, which are required for the stargate release.

## [v0.4.0] - 2020-12-15

### API Breaking

* (evm) [\#661](https://github.com/cosmos/ethermint/pull/661) `Balance` field has been removed from the evm module's `GenesisState`.

### Features
Expand Down
2 changes: 1 addition & 1 deletion app/ante/eth.go
Original file line number Diff line number Diff line change
Expand Up @@ -330,7 +330,7 @@ func (egcd EthGasConsumeDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simula
// Charge sender for gas up to limit
if gasLimit != 0 {
// Cost calculates the fees paid to validators based on gas limit and price
cost := new(big.Int).Mul(msgEthTx.Data.Price, new(big.Int).SetUint64(gasLimit))
cost := new(big.Int).Mul(msgEthTx.Data.Price.BigInt(), new(big.Int).SetUint64(gasLimit))

evmDenom := egcd.evmKeeper.GetParams(ctx).EvmDenom

Expand Down
10 changes: 5 additions & 5 deletions rpc/types/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,15 +48,15 @@ func NewTransaction(tx *evmtypes.MsgEthereumTx, txHash, blockHash common.Hash, b
rpcTx := &Transaction{
From: from,
Gas: hexutil.Uint64(tx.Data.GasLimit),
GasPrice: (*hexutil.Big)(tx.Data.Price),
GasPrice: (*hexutil.Big)(tx.Data.Price.BigInt()),
Hash: txHash,
Input: hexutil.Bytes(tx.Data.Payload),
Nonce: hexutil.Uint64(tx.Data.AccountNonce),
To: tx.To(),
Value: (*hexutil.Big)(tx.Data.Amount),
V: (*hexutil.Big)(tx.Data.V),
R: (*hexutil.Big)(tx.Data.R),
S: (*hexutil.Big)(tx.Data.S),
Value: (*hexutil.Big)(tx.Data.Amount.BigInt()),
V: (*hexutil.Big)(new(big.Int).SetBytes(tx.Data.V)),
R: (*hexutil.Big)(new(big.Int).SetBytes(tx.Data.R)),
S: (*hexutil.Big)(new(big.Int).SetBytes(tx.Data.S)),
fedekunze marked this conversation as resolved.
Show resolved Hide resolved
}

if blockHash != (common.Hash{}) {
Expand Down
23 changes: 0 additions & 23 deletions types/types.proto

This file was deleted.

17 changes: 17 additions & 0 deletions types/validation.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package types

import (
"bytes"

ethcmn "github.com/ethereum/go-ethereum/common"
)

// IsEmptyHash returns true if the hash corresponds to an empty ethereum hex hash.
func IsEmptyHash(hash string) bool {
return bytes.Equal(ethcmn.HexToHash(hash).Bytes(), ethcmn.Hash{}.Bytes())
}

// IsZeroAddress returns true if the address corresponds to an empty ethereum hex address.
func IsZeroAddress(address string) bool {
return bytes.Equal(ethcmn.HexToAddress(address).Bytes(), ethcmn.Address{}.Bytes())
}
55 changes: 55 additions & 0 deletions types/validation_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package types

import (
"testing"

"github.com/stretchr/testify/require"

ethcmn "github.com/ethereum/go-ethereum/common"
)

func TestIsEmptyHash(t *testing.T) {
testCases := []struct {
name string
hash string
expEmpty bool
}{
{
"empty string", "", true,
},
{
"zero hash", ethcmn.Hash{}.String(), true,
},

{
"non-empty hash", ethcmn.BytesToHash([]byte{1, 2, 3, 4}).String(), false,
},
}

for _, tc := range testCases {
require.Equal(t, tc.expEmpty, IsEmptyHash(tc.hash), tc.name)
}
}

func TestIsZeroAddress(t *testing.T) {
testCases := []struct {
name string
address string
expEmpty bool
}{
{
"empty string", "", true,
},
{
"zero address", ethcmn.Address{}.String(), true,
},

{
"non-empty address", ethcmn.BytesToAddress([]byte{1, 2, 3, 4}).String(), false,
},
}

for _, tc := range testCases {
require.Equal(t, tc.expEmpty, IsZeroAddress(tc.address), tc.name)
}
}
18 changes: 12 additions & 6 deletions x/evm/genesis.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,18 @@ import (

ethermint "github.com/cosmos/ethermint/types"
"github.com/cosmos/ethermint/x/evm/types"
"github.com/cosmos/ethermint/x/evm/keeper"

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

// InitGenesis initializes genesis state based on exported genesis
func InitGenesis(ctx sdk.Context, k Keeper, accountKeeper types.AccountKeeper, data GenesisState) []abci.ValidatorUpdate { // nolint: interfacer
func InitGenesis(
ctx sdk.Context,
k keeper.Keeper,
fedekunze marked this conversation as resolved.
Show resolved Hide resolved
accountKeeper types.AccountKeeper,
data GenesisState,
) []abci.ValidatorUpdate { // nolint: interfacer
evmDenom := data.Params.EvmDenom

for _, account := range data.Accounts {
Expand All @@ -40,16 +46,16 @@ func InitGenesis(ctx sdk.Context, k Keeper, accountKeeper types.AccountKeeper, d

k.SetNonce(ctx, address, acc.GetSequence())
k.SetBalance(ctx, address, evmBalance.BigInt())
k.SetCode(ctx, address, account.Code)
k.SetCode(ctx, address, ethcmn.Hex2Bytes(account.Code))

for _, storage := range account.Storage {
k.SetState(ctx, address, storage.Key, storage.Value)
k.SetState(ctx, address, ethcmn.HexToHash(storage.Key), ethcmn.HexToHash(storage.Value))
}
}

var err error
for _, txLog := range data.TxsLogs {
if err = k.SetLogs(ctx, txLog.Hash, txLog.Logs); err != nil {
if err = k.SetLogs(ctx, ethcmn.HexToHash(txLog.Hash), txLog.Logs); err != nil {
panic(err)
}
}
Expand All @@ -74,7 +80,7 @@ func InitGenesis(ctx sdk.Context, k Keeper, accountKeeper types.AccountKeeper, d
}

// ExportGenesis exports genesis state of the EVM module
func ExportGenesis(ctx sdk.Context, k Keeper, ak types.AccountKeeper) GenesisState {
func ExportGenesis(ctx sdk.Context, k keeper.Keeper, ak types.AccountKeeper) GenesisState {
// nolint: prealloc
var ethGenAccounts []types.GenesisAccount
ak.IterateAccounts(ctx, func(account authexported.Account) bool {
Expand All @@ -93,7 +99,7 @@ func ExportGenesis(ctx sdk.Context, k Keeper, ak types.AccountKeeper) GenesisSta

genAccount := types.GenesisAccount{
Address: addr.String(),
Code: k.GetCode(ctx, addr),
Code: ethcmn.Bytes2Hex(k.GetCode(ctx, addr)),
Storage: storage,
}

Expand Down
2 changes: 1 addition & 1 deletion x/evm/genesis_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ func (suite *EvmTestSuite) TestInitGenesis() {
{
Address: address.String(),
Storage: types.Storage{
{Key: common.BytesToHash([]byte("key")), Value: common.BytesToHash([]byte("value"))},
{Key: common.BytesToHash([]byte("key")).String(), Value: common.BytesToHash([]byte("value")).String()},
},
},
},
Expand Down
87 changes: 5 additions & 82 deletions x/evm/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,93 +29,16 @@ func NewHandler(k Keeper) sdk.Handler {

// handleMsgEthereumTx handles an Ethereum specific tx
func handleMsgEthereumTx(ctx sdk.Context, k Keeper, msg types.MsgEthereumTx) (*sdk.Result, error) {
// parse the chainID from a string to a base-10 integer
chainIDEpoch, err := ethermint.ParseChainID(ctx.ChainID())
if err != nil {
return nil, err
}

// Verify signature and retrieve sender address
sender, err := msg.VerifySig(chainIDEpoch)
// execute state transition
res, err := k.EthereumTx(ctx, msg)
if err != nil {
return nil, err
}

txHash := tmtypes.Tx(ctx.TxBytes()).Hash()
ethHash := common.BytesToHash(txHash)

st := types.StateTransition{
AccountNonce: msg.Data.AccountNonce,
Price: msg.Data.Price,
GasLimit: msg.Data.GasLimit,
Recipient: msg.Data.Recipient,
Amount: msg.Data.Amount,
Payload: msg.Data.Payload,
Csdb: k.CommitStateDB.WithContext(ctx),
ChainID: chainIDEpoch,
TxHash: &ethHash,
Sender: sender,
Simulate: ctx.IsCheckTx(),
}

// since the txCount is used by the stateDB, and a simulated tx is run only on the node it's submitted to,
// then this will cause the txCount/stateDB of the node that ran the simulated tx to be different than the
// other nodes, causing a consensus error
if !st.Simulate {
// Prepare db for logs
blockHash := types.HashFromContext(ctx)
k.CommitStateDB.Prepare(ethHash, blockHash, k.TxCount)
k.TxCount++
}

config, found := k.GetChainConfig(ctx)
if !found {
return nil, types.ErrChainConfigNotFound
}

executionResult, err := st.TransitionDb(ctx, config)
if err != nil {
return nil, err
}
// log state transition result
k.Logger(ctx).Info(res.Log)

if !st.Simulate {
// update block bloom filter
k.Bloom.Or(k.Bloom, executionResult.Bloom)

// update transaction logs in KVStore
err = k.SetLogs(ctx, common.BytesToHash(txHash), executionResult.Logs)
if err != nil {
panic(err)
}
}

// log successful execution
k.Logger(ctx).Info(executionResult.Result.Log)

ctx.EventManager().EmitEvents(sdk.Events{
sdk.NewEvent(
types.EventTypeEthereumTx,
sdk.NewAttribute(sdk.AttributeKeyAmount, msg.Data.Amount.String()),
),
sdk.NewEvent(
sdk.EventTypeMessage,
sdk.NewAttribute(sdk.AttributeKeyModule, types.AttributeValueCategory),
sdk.NewAttribute(sdk.AttributeKeySender, sender.String()),
),
})

if msg.Data.Recipient != nil {
ctx.EventManager().EmitEvent(
sdk.NewEvent(
types.EventTypeEthereumTx,
sdk.NewAttribute(types.AttributeKeyRecipient, msg.Data.Recipient.String()),
),
)
}

// set the events to the result
executionResult.Result.Events = ctx.EventManager().Events()
return executionResult.Result, nil
return res, nil
}

// handleMsgEthermint handles an sdk.StdTx for an Ethereum state transition
Expand Down
8 changes: 4 additions & 4 deletions x/evm/keeper/keeper.go
Original file line number Diff line number Diff line change
Expand Up @@ -164,9 +164,9 @@ func (k Keeper) GetAccountStorage(ctx sdk.Context, address common.Address) (type

// GetChainConfig gets block height from block consensus hash
func (k Keeper) GetChainConfig(ctx sdk.Context) (types.ChainConfig, bool) {
store := prefix.NewStore(ctx.KVStore(k.storeKey), types.KeyPrefixChainConfig)
store := ctx.KVStore(k.storeKey)
fedekunze marked this conversation as resolved.
Show resolved Hide resolved
// get from an empty key that's already prefixed by KeyPrefixChainConfig
fedekunze marked this conversation as resolved.
Show resolved Hide resolved
bz := store.Get([]byte{})
fedekunze marked this conversation as resolved.
Show resolved Hide resolved
bz := store.Get(types.KeyPrefixChainConfig)
if len(bz) == 0 {
return types.ChainConfig{}, false
}
Expand All @@ -178,8 +178,8 @@ func (k Keeper) GetChainConfig(ctx sdk.Context) (types.ChainConfig, bool) {

// SetChainConfig sets the mapping from block consensus hash to block height
func (k Keeper) SetChainConfig(ctx sdk.Context, config types.ChainConfig) {
store := prefix.NewStore(ctx.KVStore(k.storeKey), types.KeyPrefixChainConfig)
store := ctx.KVStore(k.storeKey)
bz := k.cdc.MustMarshalBinaryBare(config)
// get to an empty key that's already prefixed by KeyPrefixChainConfig
fedekunze marked this conversation as resolved.
Show resolved Hide resolved
store.Set([]byte{}, bz)
store.Set(types.KeyPrefixChainConfig, bz)
}
4 changes: 2 additions & 2 deletions x/evm/keeper/keeper_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -98,10 +98,10 @@ func (suite *KeeperTestSuite) TestTransactionLogs() {
txLogs := suite.app.EvmKeeper.GetAllTxLogs(suite.ctx)
suite.Require().Equal(2, len(txLogs))

suite.Require().Equal(ethcmn.Hash{}.String(), txLogs[0].Hash.String())
suite.Require().Equal(ethcmn.Hash{}.String(), txLogs[0].Hash)
suite.Require().Equal([]*ethtypes.Log{log2, log3}, txLogs[0].Logs)

suite.Require().Equal(ethHash.String(), txLogs[1].Hash.String())
suite.Require().Equal(ethHash.String(), txLogs[1].Hash)
suite.Require().Equal([]*ethtypes.Log{log}, txLogs[1].Logs)
}

Expand Down
Loading