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

fix incorrect blockHash in evm #780

Merged
merged 8 commits into from
Mar 19, 2021
Merged
Show file tree
Hide file tree
Changes from 3 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
3 changes: 2 additions & 1 deletion importer/importer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -254,7 +254,8 @@ func TestImportBlocks(t *testing.T) {
}

for i, tx := range block.Transactions() {
evmKeeper.Prepare(ctx, tx.Hash(), block.Hash(), i)
evmKeeper.Prepare(ctx, tx.Hash(), i)
evmKeeper.CommitStateDB.SetBlockHash(block.Hash())

receipt, gas, err := applyTransaction(
chainConfig, chainContext, nil, gp, evmKeeper, header, tx, usedGas, vmConfig,
Expand Down
3 changes: 1 addition & 2 deletions x/evm/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -106,8 +106,7 @@ func handleMsgEthermint(ctx sdk.Context, k *Keeper, msg types.MsgEthermint) (*sd

if !st.Simulate {
// Prepare db for logs
blockHash := types.HashFromContext(ctx)
k.CommitStateDB.Prepare(ethHash, blockHash, k.TxCount)
k.CommitStateDB.Prepare(ethHash, k.TxCount)
k.TxCount++
}

Expand Down
8 changes: 5 additions & 3 deletions x/evm/keeper/abci.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,13 @@ func (k *Keeper) BeginBlock(ctx sdk.Context, req abci.RequestBeginBlock) {
ctx = ctx.WithGasMeter(sdk.NewInfiniteGasMeter())

// Set the hash -> height and height -> hash mapping.
hash := req.Header.LastBlockId.GetHash()
currentHash := req.Hash
lastHash := req.Header.LastBlockId.GetHash()
height := req.Header.GetHeight() - 1
araskachoi marked this conversation as resolved.
Show resolved Hide resolved

k.SetHeightHash(ctx, uint64(height), common.BytesToHash(hash))
k.SetBlockHash(ctx, hash, height)
k.SetHeightHash(ctx, uint64(height), common.BytesToHash(lastHash))
k.SetBlockHash(ctx, lastHash, height)
k.CommitStateDB.SetBlockHash(common.BytesToHash(currentHash))

// reset counters that are used on CommitStateDB.Prepare
k.Bloom = big.NewInt(0)
Expand Down
3 changes: 1 addition & 2 deletions x/evm/keeper/msg_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,7 @@ func (k Keeper) EthereumTx(ctx sdk.Context, msg types.MsgEthereumTx) (*sdk.Resul
// 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.CommitStateDB.Prepare(ethHash, k.TxCount)
k.TxCount++
}

Expand Down
4 changes: 2 additions & 2 deletions x/evm/keeper/statedb.go
Original file line number Diff line number Diff line change
Expand Up @@ -225,8 +225,8 @@ func (k *Keeper) Reset(ctx sdk.Context, root ethcmn.Hash) error {
}

// Prepare calls CommitStateDB.Prepare using the passed in context
func (k *Keeper) Prepare(ctx sdk.Context, thash, bhash ethcmn.Hash, txi int) {
k.CommitStateDB.WithContext(ctx).Prepare(thash, bhash, txi)
func (k *Keeper) Prepare(ctx sdk.Context, thash ethcmn.Hash, txi int) {
k.CommitStateDB.WithContext(ctx).Prepare(thash, txi)
}

// CreateAccount calls CommitStateDB.CreateAccount using the passed in context
Expand Down
5 changes: 3 additions & 2 deletions x/evm/keeper/statedb_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import (
func (suite *KeeperTestSuite) TestBloomFilter() {
// Prepare db for logs
tHash := ethcmn.BytesToHash([]byte{0x1})
suite.app.EvmKeeper.Prepare(suite.ctx, tHash, ethcmn.Hash{}, 0)
suite.app.EvmKeeper.Prepare(suite.ctx, tHash, 0)
contractAddress := ethcmn.BigToAddress(big.NewInt(1))
log := ethtypes.Log{Address: contractAddress}

Expand Down Expand Up @@ -359,7 +359,8 @@ func (suite *KeeperTestSuite) TestSuiteDB_Prepare() {
bhash := ethcmn.BytesToHash([]byte("bhash"))
txi := 1

suite.app.EvmKeeper.Prepare(suite.ctx, thash, bhash, txi)
suite.app.EvmKeeper.Prepare(suite.ctx, thash, txi)
suite.app.EvmKeeper.CommitStateDB.SetBlockHash(bhash)

suite.Require().Equal(txi, suite.app.EvmKeeper.TxIndex(suite.ctx))
suite.Require().Equal(bhash, suite.app.EvmKeeper.BlockHash(suite.ctx))
Expand Down
22 changes: 2 additions & 20 deletions x/evm/types/state_transition.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ type ExecutionResult struct {
}

// GetHashFn implements vm.GetHashFunc for Ethermint. It handles 3 cases:
// 1. The requested height matches the current height from context (and thus same epoch number)
// 1. The requested height matches the current height (and thus same epoch number)
// 2. The requested height is from an previous height from the same chain epoch
// 3. The requested height is from a height greater than the latest one
func GetHashFn(ctx sdk.Context, csdb *CommitStateDB) vm.GetHashFunc {
Expand All @@ -57,7 +57,7 @@ func GetHashFn(ctx sdk.Context, csdb *CommitStateDB) vm.GetHashFunc {
case ctx.BlockHeight() == int64(height):
// Case 1: The requested height matches the one from the context so we can retrieve the header
// hash directly from the context.
return HashFromContext(ctx)
return csdb.bhash
summerpro marked this conversation as resolved.
Show resolved Hide resolved

case ctx.BlockHeight() > int64(height):
// Case 2: if the chain is not the current height we need to retrieve the hash from the store for the
Expand Down Expand Up @@ -268,21 +268,3 @@ func (st StateTransition) TransitionDb(ctx sdk.Context, config ChainConfig) (*Ex

return executionResult, nil
}

// HashFromContext returns the Ethereum Header hash from the context's Tendermint
// block header.
func HashFromContext(ctx sdk.Context) common.Hash {
// cast the ABCI header to tendermint Header type
tmHeader := AbciHeaderToTendermint(ctx.BlockHeader())

// get the Tendermint block hash from the current header
tmBlockHash := tmHeader.Hash()

// NOTE: if the validator set hash is missing the hash will be returned as nil,
// so we need to check for this case to prevent a panic when calling Bytes()
if tmBlockHash == nil {
return common.Hash{}
}

return common.BytesToHash(tmBlockHash.Bytes())
}
araskachoi marked this conversation as resolved.
Show resolved Hide resolved
4 changes: 3 additions & 1 deletion x/evm/types/state_transition_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ func (suite *StateDBTestSuite) TestGetHashFn() {
ValidatorsHash: []byte("val_hash"),
},
)
hash := ethcmn.BytesToHash([]byte("test hash"))
suite.stateDB.SetBlockHash(hash)
},
false,
},
Expand All @@ -54,7 +56,7 @@ func (suite *StateDBTestSuite) TestGetHashFn() {
ValidatorsHash: []byte("val_hash"),
},
)
hash := types.HashFromContext(suite.ctx)
hash := ethcmn.BytesToHash([]byte("test hash"))
suite.stateDB.WithContext(suite.ctx).SetHeightHash(1, hash)
},
false,
Expand Down
7 changes: 5 additions & 2 deletions x/evm/types/statedb.go
Original file line number Diff line number Diff line change
Expand Up @@ -342,6 +342,10 @@ func (csdb *CommitStateDB) BlockHash() ethcmn.Hash {
return csdb.bhash
}

func (csdb *CommitStateDB) SetBlockHash(hash ethcmn.Hash) {
csdb.bhash = hash
}

// GetCode returns the code for a given account.
func (csdb *CommitStateDB) GetCode(addr ethcmn.Address) []byte {
so := csdb.getStateObject(addr)
Expand Down Expand Up @@ -733,9 +737,8 @@ func (csdb *CommitStateDB) clearJournalAndRefund() {

// Prepare sets the current transaction hash and index and block hash which is
// used when the EVM emits new state logs.
func (csdb *CommitStateDB) Prepare(thash, bhash ethcmn.Hash, txi int) {
func (csdb *CommitStateDB) Prepare(thash ethcmn.Hash, txi int) {
csdb.thash = thash
csdb.bhash = bhash
csdb.txIndex = txi
}

Expand Down
5 changes: 3 additions & 2 deletions x/evm/types/statedb_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ func (suite *StateDBTestSuite) TestGetHeightHash() {
func (suite *StateDBTestSuite) TestBloomFilter() {
// Prepare db for logs
tHash := ethcmn.BytesToHash([]byte{0x1})
suite.stateDB.Prepare(tHash, ethcmn.Hash{}, 0)
suite.stateDB.Prepare(tHash, 0)
contractAddress := ethcmn.BigToAddress(big.NewInt(1))
log := ethtypes.Log{Address: contractAddress}

Expand Down Expand Up @@ -419,7 +419,8 @@ func (suite *StateDBTestSuite) TestSuiteDB_Prepare() {
bhash := ethcmn.BytesToHash([]byte("bhash"))
txi := 1

suite.stateDB.Prepare(thash, bhash, txi)
suite.stateDB.Prepare(thash, txi)
suite.stateDB.SetBlockHash(bhash)

suite.Require().Equal(txi, suite.stateDB.TxIndex())
suite.Require().Equal(bhash, suite.stateDB.BlockHash())
Expand Down
37 changes: 0 additions & 37 deletions x/evm/types/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,6 @@ import (
"github.com/pkg/errors"
"golang.org/x/crypto/sha3"

abci "github.com/tendermint/tendermint/abci/types"
tmtypes "github.com/tendermint/tendermint/types"
"github.com/tendermint/tendermint/version"

"github.com/cosmos/cosmos-sdk/codec"
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
Expand Down Expand Up @@ -162,36 +158,3 @@ func recoverEthSig(R, S, Vb *big.Int, sigHash ethcmn.Hash) (ethcmn.Address, erro

return addr, nil
}

// AbciHeaderToTendermint is a util function to parse a tendermint ABCI Header to
// tendermint types Header.
func AbciHeaderToTendermint(header abci.Header) tmtypes.Header {
return tmtypes.Header{
Version: version.Consensus{
Block: version.Protocol(header.Version.Block),
App: version.Protocol(header.Version.App),
},
ChainID: header.ChainID,
Height: header.Height,
Time: header.Time,

LastBlockID: tmtypes.BlockID{
Hash: header.LastBlockId.Hash,
PartsHeader: tmtypes.PartSetHeader{
Total: int(header.LastBlockId.PartsHeader.Total),
Hash: header.LastBlockId.PartsHeader.Hash,
},
},
LastCommitHash: header.LastCommitHash,
DataHash: header.DataHash,

ValidatorsHash: header.ValidatorsHash,
NextValidatorsHash: header.NextValidatorsHash,
ConsensusHash: header.ConsensusHash,
AppHash: header.AppHash,
LastResultsHash: header.LastResultsHash,

EvidenceHash: header.EvidenceHash,
ProposerAddress: header.ProposerAddress,
}
}