From ee00f1841288a2185770c3ae9d602b444a79cbfe Mon Sep 17 00:00:00 2001 From: Marius van der Wijden Date: Thu, 24 Jun 2021 11:40:46 +0200 Subject: [PATCH 1/5] all: removed blockhash from statedb --- cmd/evm/internal/t8ntool/execution.go | 3 +-- core/chain_makers.go | 2 +- core/state/statedb.go | 17 +++++------------ core/state_prefetcher.go | 2 +- core/state_processor.go | 4 ++-- eth/catalyst/api.go | 2 +- eth/state_accessor.go | 2 +- eth/tracers/api.go | 6 +++--- les/state_accessor.go | 2 +- miner/worker.go | 2 +- 10 files changed, 17 insertions(+), 25 deletions(-) diff --git a/cmd/evm/internal/t8ntool/execution.go b/cmd/evm/internal/t8ntool/execution.go index ccc90618b499..d71515863b70 100644 --- a/cmd/evm/internal/t8ntool/execution.go +++ b/cmd/evm/internal/t8ntool/execution.go @@ -109,7 +109,6 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig, statedb = MakePreState(rawdb.NewMemoryDatabase(), pre.Pre) signer = types.MakeSigner(chainConfig, new(big.Int).SetUint64(pre.Env.Number)) gaspool = new(core.GasPool) - blockHash = common.Hash{0x13, 0x37} rejectedTxs []*rejectedTx includedTxs types.Transactions gasUsed = uint64(0) @@ -152,7 +151,7 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig, } vmConfig.Tracer = tracer vmConfig.Debug = (tracer != nil) - statedb.Prepare(tx.Hash(), blockHash, txIndex) + statedb.Prepare(tx.Hash(), txIndex) txContext := core.NewEVMTxContext(msg) snapshot := statedb.Snapshot() evm := vm.NewEVM(vmContext, txContext, statedb, chainConfig, vmConfig) diff --git a/core/chain_makers.go b/core/chain_makers.go index dc207f202e06..929a2aa3a43a 100644 --- a/core/chain_makers.go +++ b/core/chain_makers.go @@ -102,7 +102,7 @@ func (b *BlockGen) AddTxWithChain(bc *BlockChain, tx *types.Transaction) { if b.gasPool == nil { b.SetCoinbase(common.Address{}) } - b.statedb.Prepare(tx.Hash(), common.Hash{}, len(b.txs)) + b.statedb.Prepare(tx.Hash(), len(b.txs)) receipt, err := ApplyTransaction(b.config, bc, &b.header.Coinbase, b.gasPool, b.statedb, b.header, tx, &b.header.GasUsed, vm.Config{}) if err != nil { panic(err) diff --git a/core/state/statedb.go b/core/state/statedb.go index 203556c6b76a..97c83ecae3eb 100644 --- a/core/state/statedb.go +++ b/core/state/statedb.go @@ -89,10 +89,10 @@ type StateDB struct { // The refund counter, also used by state transitioning. refund uint64 - thash, bhash common.Hash - txIndex int - logs map[common.Hash][]*types.Log - logSize uint + thash common.Hash + txIndex int + logs map[common.Hash][]*types.Log + logSize uint preimages map[common.Hash][]byte @@ -186,7 +186,6 @@ func (s *StateDB) AddLog(log *types.Log) { s.journal.append(addLogChange{txhash: s.thash}) log.TxHash = s.thash - log.BlockHash = s.bhash log.TxIndex = uint(s.txIndex) log.Index = s.logSize s.logs[s.thash] = append(s.logs[s.thash], log) @@ -272,11 +271,6 @@ func (s *StateDB) TxIndex() int { return s.txIndex } -// BlockHash returns the current block hash set by Prepare. -func (s *StateDB) BlockHash() common.Hash { - return s.bhash -} - func (s *StateDB) GetCode(addr common.Address) []byte { stateObject := s.getStateObject(addr) if stateObject != nil { @@ -894,9 +888,8 @@ func (s *StateDB) IntermediateRoot(deleteEmptyObjects bool) common.Hash { // Prepare sets the current transaction hash and index and block hash which is // used when the EVM emits new state logs. -func (s *StateDB) Prepare(thash, bhash common.Hash, ti int) { +func (s *StateDB) Prepare(thash common.Hash, ti int) { s.thash = thash - s.bhash = bhash s.txIndex = ti s.accessList = newAccessList() } diff --git a/core/state_prefetcher.go b/core/state_prefetcher.go index ecdfa67f00dd..10a1722940b0 100644 --- a/core/state_prefetcher.go +++ b/core/state_prefetcher.go @@ -67,7 +67,7 @@ func (p *statePrefetcher) Prefetch(block *types.Block, statedb *state.StateDB, c if err != nil { return // Also invalid block, bail out } - statedb.Prepare(tx.Hash(), block.Hash(), i) + statedb.Prepare(tx.Hash(), i) if err := precacheTransaction(msg, p.config, gaspool, statedb, header, evm); err != nil { return // Ugh, something went horribly wrong, bail out } diff --git a/core/state_processor.go b/core/state_processor.go index 6f6bc1879b8d..0cfac2975cf2 100644 --- a/core/state_processor.go +++ b/core/state_processor.go @@ -75,7 +75,7 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg if err != nil { return nil, nil, 0, fmt.Errorf("could not apply tx %d [%v]: %w", i, tx.Hash().Hex(), err) } - statedb.Prepare(tx.Hash(), block.Hash(), i) + statedb.Prepare(tx.Hash(), i) receipt, err := applyTransaction(msg, p.config, p.bc, nil, gp, statedb, header, tx, usedGas, vmenv) if err != nil { return nil, nil, 0, fmt.Errorf("could not apply tx %d [%v]: %w", i, tx.Hash().Hex(), err) @@ -128,7 +128,7 @@ func applyTransaction(msg types.Message, config *params.ChainConfig, bc ChainCon // Set the receipt logs and create the bloom filter. receipt.Logs = statedb.GetLogs(tx.Hash()) receipt.Bloom = types.CreateBloom(types.Receipts{receipt}) - receipt.BlockHash = statedb.BlockHash() + receipt.BlockHash = header.Hash() receipt.BlockNumber = header.Number receipt.TransactionIndex = uint(statedb.TxIndex()) return receipt, err diff --git a/eth/catalyst/api.go b/eth/catalyst/api.go index c074ac5af093..2622c4a148f6 100644 --- a/eth/catalyst/api.go +++ b/eth/catalyst/api.go @@ -178,7 +178,7 @@ func (api *consensusAPI) AssembleBlock(params assembleBlockParams) (*executableD from, _ := types.Sender(signer, tx) // Execute the transaction - env.state.Prepare(tx.Hash(), common.Hash{}, env.tcount) + env.state.Prepare(tx.Hash(), env.tcount) err = env.commitTransaction(tx, coinbase) switch err { case core.ErrGasLimitReached: diff --git a/eth/state_accessor.go b/eth/state_accessor.go index 8d53739721fb..eb178311f30b 100644 --- a/eth/state_accessor.go +++ b/eth/state_accessor.go @@ -170,7 +170,7 @@ func (eth *Ethereum) stateAtTransaction(block *types.Block, txIndex int, reexec } // Not yet the searched for transaction, execute on top of the current state vmenv := vm.NewEVM(context, txContext, statedb, eth.blockchain.Config(), vm.Config{}) - statedb.Prepare(tx.Hash(), block.Hash(), idx) + statedb.Prepare(tx.Hash(), idx) if _, err := core.ApplyMessage(vmenv, msg, new(core.GasPool).AddGas(tx.Gas())); err != nil { return nil, vm.BlockContext{}, nil, fmt.Errorf("transaction %#x failed: %v", tx.Hash(), err) } diff --git a/eth/tracers/api.go b/eth/tracers/api.go index c6cd64688116..68265932854c 100644 --- a/eth/tracers/api.go +++ b/eth/tracers/api.go @@ -539,7 +539,7 @@ func (api *API) traceBlock(ctx context.Context, block *types.Block, config *Trac // Generate the next state snapshot fast without tracing msg, _ := tx.AsMessage(signer, block.BaseFee()) - statedb.Prepare(tx.Hash(), block.Hash(), i) + statedb.Prepare(tx.Hash(), i) vmenv := vm.NewEVM(blockCtx, core.NewEVMTxContext(msg), statedb, api.backend.ChainConfig(), vm.Config{}) if _, err := core.ApplyMessage(vmenv, msg, new(core.GasPool).AddGas(msg.Gas())); err != nil { failed = err @@ -653,7 +653,7 @@ func (api *API) standardTraceBlockToFile(ctx context.Context, block *types.Block } // Execute the transaction and flush any traces to disk vmenv := vm.NewEVM(vmctx, txContext, statedb, chainConfig, vmConf) - statedb.Prepare(tx.Hash(), block.Hash(), i) + statedb.Prepare(tx.Hash(), i) _, err = core.ApplyMessage(vmenv, msg, new(core.GasPool).AddGas(msg.Gas())) if writer != nil { writer.Flush() @@ -816,7 +816,7 @@ func (api *API) traceTx(ctx context.Context, message core.Message, txctx *Contex vmenv := vm.NewEVM(vmctx, txContext, statedb, api.backend.ChainConfig(), vm.Config{Debug: true, Tracer: tracer, NoBaseFee: true}) // Call Prepare to clear out the statedb access list - statedb.Prepare(txctx.TxHash, txctx.BlockHash, txctx.TxIndex) + statedb.Prepare(txctx.TxHash, txctx.TxIndex) result, err := core.ApplyMessage(vmenv, message, new(core.GasPool).AddGas(message.Gas())) if err != nil { diff --git a/les/state_accessor.go b/les/state_accessor.go index e276b06dc748..112e6fd44d12 100644 --- a/les/state_accessor.go +++ b/les/state_accessor.go @@ -58,7 +58,7 @@ func (leth *LightEthereum) stateAtTransaction(ctx context.Context, block *types. msg, _ := tx.AsMessage(signer, block.BaseFee()) txContext := core.NewEVMTxContext(msg) context := core.NewEVMBlockContext(block.Header(), leth.blockchain, nil) - statedb.Prepare(tx.Hash(), block.Hash(), idx) + statedb.Prepare(tx.Hash(), idx) if idx == txIndex { return msg, context, statedb, nil } diff --git a/miner/worker.go b/miner/worker.go index b0b676ad020e..0c3ff11d9436 100644 --- a/miner/worker.go +++ b/miner/worker.go @@ -805,7 +805,7 @@ func (w *worker) commitTransactions(txs *types.TransactionsByPriceAndNonce, coin continue } // Start executing the transaction - w.current.state.Prepare(tx.Hash(), common.Hash{}, w.current.tcount) + w.current.state.Prepare(tx.Hash(), w.current.tcount) logs, err := w.commitTransaction(tx, coinbase) switch { From e54eea86811c4f3b3b78aa775354973628e18ecf Mon Sep 17 00:00:00 2001 From: Marius van der Wijden Date: Thu, 24 Jun 2021 14:50:44 +0200 Subject: [PATCH 2/5] core: set blockhash in receipt logs --- core/state_processor.go | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/core/state_processor.go b/core/state_processor.go index 0cfac2975cf2..835e6740a519 100644 --- a/core/state_processor.go +++ b/core/state_processor.go @@ -126,9 +126,14 @@ func applyTransaction(msg types.Message, config *params.ChainConfig, bc ChainCon } // Set the receipt logs and create the bloom filter. - receipt.Logs = statedb.GetLogs(tx.Hash()) + blockhash := header.Hash() + logs := statedb.GetLogs(tx.Hash()) + for _, l := range logs { + l.BlockHash = blockhash + } + receipt.Logs = logs receipt.Bloom = types.CreateBloom(types.Receipts{receipt}) - receipt.BlockHash = header.Hash() + receipt.BlockHash = blockhash receipt.BlockNumber = header.Number receipt.TransactionIndex = uint(statedb.TxIndex()) return receipt, err From d3f4fcf93cb7453fbb54e26811d7495d90458454 Mon Sep 17 00:00:00 2001 From: Marius van der Wijden Date: Thu, 24 Jun 2021 15:29:47 +0200 Subject: [PATCH 3/5] core: set blockhash in GetLogs --- cmd/evm/internal/t8ntool/execution.go | 3 ++- core/state/statedb.go | 8 ++++++-- core/state/statedb_test.go | 4 ++-- core/state_processor.go | 9 ++------- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/cmd/evm/internal/t8ntool/execution.go b/cmd/evm/internal/t8ntool/execution.go index d71515863b70..1ab2f001e267 100644 --- a/cmd/evm/internal/t8ntool/execution.go +++ b/cmd/evm/internal/t8ntool/execution.go @@ -109,6 +109,7 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig, statedb = MakePreState(rawdb.NewMemoryDatabase(), pre.Pre) signer = types.MakeSigner(chainConfig, new(big.Int).SetUint64(pre.Env.Number)) gaspool = new(core.GasPool) + blockHash = common.Hash{0x13, 0x37} rejectedTxs []*rejectedTx includedTxs types.Transactions gasUsed = uint64(0) @@ -196,7 +197,7 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig, } // Set the receipt logs and create the bloom filter. - receipt.Logs = statedb.GetLogs(tx.Hash()) + receipt.Logs = statedb.GetLogs(tx.Hash(), blockHash) receipt.Bloom = types.CreateBloom(types.Receipts{receipt}) // These three are non-consensus fields: //receipt.BlockHash diff --git a/core/state/statedb.go b/core/state/statedb.go index 97c83ecae3eb..45776efed339 100644 --- a/core/state/statedb.go +++ b/core/state/statedb.go @@ -192,8 +192,12 @@ func (s *StateDB) AddLog(log *types.Log) { s.logSize++ } -func (s *StateDB) GetLogs(hash common.Hash) []*types.Log { - return s.logs[hash] +func (s *StateDB) GetLogs(hash common.Hash, blockHash common.Hash) []*types.Log { + logs := s.logs[hash] + for _, l := range logs { + l.BlockHash = blockHash + } + return logs } func (s *StateDB) Logs() []*types.Log { diff --git a/core/state/statedb_test.go b/core/state/statedb_test.go index f8145531240b..e9576d4dc44d 100644 --- a/core/state/statedb_test.go +++ b/core/state/statedb_test.go @@ -463,9 +463,9 @@ func (test *snapshotTest) checkEqual(state, checkstate *StateDB) error { return fmt.Errorf("got GetRefund() == %d, want GetRefund() == %d", state.GetRefund(), checkstate.GetRefund()) } - if !reflect.DeepEqual(state.GetLogs(common.Hash{}), checkstate.GetLogs(common.Hash{})) { + if !reflect.DeepEqual(state.GetLogs(common.Hash{}, common.Hash{}), checkstate.GetLogs(common.Hash{}, common.Hash{})) { return fmt.Errorf("got GetLogs(common.Hash{}) == %v, want GetLogs(common.Hash{}) == %v", - state.GetLogs(common.Hash{}), checkstate.GetLogs(common.Hash{})) + state.GetLogs(common.Hash{}, common.Hash{}), checkstate.GetLogs(common.Hash{}, common.Hash{})) } return nil } diff --git a/core/state_processor.go b/core/state_processor.go index 835e6740a519..6c13a3f01010 100644 --- a/core/state_processor.go +++ b/core/state_processor.go @@ -126,14 +126,9 @@ func applyTransaction(msg types.Message, config *params.ChainConfig, bc ChainCon } // Set the receipt logs and create the bloom filter. - blockhash := header.Hash() - logs := statedb.GetLogs(tx.Hash()) - for _, l := range logs { - l.BlockHash = blockhash - } - receipt.Logs = logs + receipt.Logs = statedb.GetLogs(tx.Hash(), header.Hash()) receipt.Bloom = types.CreateBloom(types.Receipts{receipt}) - receipt.BlockHash = blockhash + receipt.BlockHash = header.Hash() receipt.BlockNumber = header.Number receipt.TransactionIndex = uint(statedb.TxIndex()) return receipt, err From 5fcab357627e535a82ae23fcfb12807fcf0a5d19 Mon Sep 17 00:00:00 2001 From: Marius van der Wijden Date: Thu, 24 Jun 2021 16:21:42 +0200 Subject: [PATCH 4/5] core: cache blockhash --- core/state_processor.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/core/state_processor.go b/core/state_processor.go index 6c13a3f01010..0040b8849c90 100644 --- a/core/state_processor.go +++ b/core/state_processor.go @@ -126,9 +126,10 @@ func applyTransaction(msg types.Message, config *params.ChainConfig, bc ChainCon } // Set the receipt logs and create the bloom filter. - receipt.Logs = statedb.GetLogs(tx.Hash(), header.Hash()) + blockhash := header.Hash() + receipt.Logs = statedb.GetLogs(tx.Hash(), blockhash) receipt.Bloom = types.CreateBloom(types.Receipts{receipt}) - receipt.BlockHash = header.Hash() + receipt.BlockHash = blockhash receipt.BlockNumber = header.Number receipt.TransactionIndex = uint(statedb.TxIndex()) return receipt, err From b5e579c4872dc604379689ce26c1312a8a1c877b Mon Sep 17 00:00:00 2001 From: Marius van der Wijden Date: Mon, 28 Jun 2021 14:27:45 +0200 Subject: [PATCH 5/5] core: use cached blockhash instead of header hash --- core/state_processor.go | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/core/state_processor.go b/core/state_processor.go index 0040b8849c90..d4c77ae41042 100644 --- a/core/state_processor.go +++ b/core/state_processor.go @@ -18,6 +18,7 @@ package core import ( "fmt" + "math/big" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/consensus" @@ -57,11 +58,13 @@ func NewStateProcessor(config *params.ChainConfig, bc *BlockChain, engine consen // transactions failed to execute due to insufficient gas it will return an error. func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg vm.Config) (types.Receipts, []*types.Log, uint64, error) { var ( - receipts types.Receipts - usedGas = new(uint64) - header = block.Header() - allLogs []*types.Log - gp = new(GasPool).AddGas(block.GasLimit()) + receipts types.Receipts + usedGas = new(uint64) + header = block.Header() + blockHash = block.Hash() + blockNumber = block.Number() + allLogs []*types.Log + gp = new(GasPool).AddGas(block.GasLimit()) ) // Mutate the block and state according to any hard-fork specs if p.config.DAOForkSupport && p.config.DAOForkBlock != nil && p.config.DAOForkBlock.Cmp(block.Number()) == 0 { @@ -76,7 +79,7 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg return nil, nil, 0, fmt.Errorf("could not apply tx %d [%v]: %w", i, tx.Hash().Hex(), err) } statedb.Prepare(tx.Hash(), i) - receipt, err := applyTransaction(msg, p.config, p.bc, nil, gp, statedb, header, tx, usedGas, vmenv) + receipt, err := applyTransaction(msg, p.config, p.bc, nil, gp, statedb, blockNumber, blockHash, tx, usedGas, vmenv) if err != nil { return nil, nil, 0, fmt.Errorf("could not apply tx %d [%v]: %w", i, tx.Hash().Hex(), err) } @@ -89,7 +92,7 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg return receipts, allLogs, *usedGas, nil } -func applyTransaction(msg types.Message, config *params.ChainConfig, bc ChainContext, author *common.Address, gp *GasPool, statedb *state.StateDB, header *types.Header, tx *types.Transaction, usedGas *uint64, evm *vm.EVM) (*types.Receipt, error) { +func applyTransaction(msg types.Message, config *params.ChainConfig, bc ChainContext, author *common.Address, gp *GasPool, statedb *state.StateDB, blockNumber *big.Int, blockHash common.Hash, tx *types.Transaction, usedGas *uint64, evm *vm.EVM) (*types.Receipt, error) { // Create a new context to be used in the EVM environment. txContext := NewEVMTxContext(msg) evm.Reset(txContext, statedb) @@ -102,10 +105,10 @@ func applyTransaction(msg types.Message, config *params.ChainConfig, bc ChainCon // Update the state with pending changes. var root []byte - if config.IsByzantium(header.Number) { + if config.IsByzantium(blockNumber) { statedb.Finalise(true) } else { - root = statedb.IntermediateRoot(config.IsEIP158(header.Number)).Bytes() + root = statedb.IntermediateRoot(config.IsEIP158(blockNumber)).Bytes() } *usedGas += result.UsedGas @@ -126,11 +129,10 @@ func applyTransaction(msg types.Message, config *params.ChainConfig, bc ChainCon } // Set the receipt logs and create the bloom filter. - blockhash := header.Hash() - receipt.Logs = statedb.GetLogs(tx.Hash(), blockhash) + receipt.Logs = statedb.GetLogs(tx.Hash(), blockHash) receipt.Bloom = types.CreateBloom(types.Receipts{receipt}) - receipt.BlockHash = blockhash - receipt.BlockNumber = header.Number + receipt.BlockHash = blockHash + receipt.BlockNumber = blockNumber receipt.TransactionIndex = uint(statedb.TxIndex()) return receipt, err } @@ -147,5 +149,5 @@ func ApplyTransaction(config *params.ChainConfig, bc ChainContext, author *commo // Create a new context to be used in the EVM environment blockContext := NewEVMBlockContext(header, bc, author) vmenv := vm.NewEVM(blockContext, vm.TxContext{}, statedb, config, cfg) - return applyTransaction(msg, config, bc, author, gp, statedb, header, tx, usedGas, vmenv) + return applyTransaction(msg, config, bc, author, gp, statedb, header.Number, header.Hash(), tx, usedGas, vmenv) }