diff --git a/cmd/evm/internal/t8ntool/execution.go b/cmd/evm/internal/t8ntool/execution.go index 8c6725cb316b..5847f6f2a534 100644 --- a/cmd/evm/internal/t8ntool/execution.go +++ b/cmd/evm/internal/t8ntool/execution.go @@ -184,6 +184,7 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig, misc.ApplyDAOHardFork(statedb) } if chainConfig.IsPrague(big.NewInt(int64(pre.Env.Number)), pre.Env.Timestamp) { + // XXX figure out what to do for older hashes? core.ProcessParentBlockHash(statedb, pre.Env.Number-1, *pre.Env.ParentHash) } var blobGasUsed uint64 diff --git a/core/chain_makers.go b/core/chain_makers.go index 37a5fbf5100f..5b9dc0c6ff08 100644 --- a/core/chain_makers.go +++ b/core/chain_makers.go @@ -386,7 +386,12 @@ func GenerateVerkleChain(config *params.ChainConfig, parent *types.Block, engine fmt.Println("prestate", preState.GetTrie().(*trie.VerkleTrie).ToDot()) if config.IsPrague(b.header.Number, b.header.Time) { - ProcessParentBlockHash(statedb, b.header.Number.Uint64()-1, b.header.ParentHash) + if !config.IsPrague(b.parent.Number(), b.parent.Time()) { + // Transition case: insert all 256 ancestors + InsertBlockHashHistoryAtEip2935Fork(statedb, b.header.Number.Uint64()-1, b.header.ParentHash, chainreader) + } else { + ProcessParentBlockHash(statedb, b.header.Number.Uint64()-1, b.header.ParentHash) + } } // Mutate the state and block according to any hard-fork specs diff --git a/core/state_processor.go b/core/state_processor.go index b22c45469e6f..daf2bb729fc4 100644 --- a/core/state_processor.go +++ b/core/state_processor.go @@ -87,7 +87,12 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg signer = types.MakeSigner(p.config, header.Number, header.Time) ) if p.config.IsPrague(block.Number(), block.Time()) { - ProcessParentBlockHash(statedb, block.NumberU64()-1, block.ParentHash()) + parent := p.bc.GetBlockByHash(block.ParentHash()) + if p.config.IsPrague(parent.Number(), parent.Time()) { + InsertBlockHashHistoryAtEip2935Fork(statedb, block.NumberU64()-1, block.ParentHash(), p.bc) + } else { + ProcessParentBlockHash(statedb, block.NumberU64()-1, block.ParentHash()) + } } // Iterate over and process the individual transactions for i, tx := range block.Transactions() { @@ -364,6 +369,14 @@ func (kvm *keyValueMigrator) migrateCollectedKeyValues(tree *trie.VerkleTrie) er return nil } +func InsertBlockHashHistoryAtEip2935Fork(statedb *state.StateDB, prevNumber uint64, prevHash common.Hash, chain consensus.ChainHeaderReader) { + ancestor := chain.GetHeader(prevHash, prevNumber) + for i := prevNumber; i > 0 && i >= prevNumber-256; i-- { + ProcessParentBlockHash(statedb, i, ancestor.Hash()) + ancestor = chain.GetHeader(ancestor.ParentHash, ancestor.Number.Uint64()) + } +} + func ProcessParentBlockHash(statedb *state.StateDB, prevNumber uint64, prevHash common.Hash) { var key common.Hash binary.BigEndian.PutUint64(key[24:], prevNumber) diff --git a/core/vm/instructions.go b/core/vm/instructions.go index 00787b3d030f..29e3022fea0e 100644 --- a/core/vm/instructions.go +++ b/core/vm/instructions.go @@ -515,22 +515,10 @@ func opBlockhash(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ( } evm := interpreter.evm - bnum := evm.Context.BlockNumber.Uint64() - // if Prague is active, check if we are past the 256th block so that - // reading from the contract can be activated (EIP 2935). - if evm.chainRules.IsPrague && bnum > 256 { - if getBlockHashFromContract(bnum-256, evm.StateDB, evm.Accesses) != (common.Hash{}) { - // EIP-2935 case: get the block number from the fork, as we are 256 blocks - // after the fork activation. - - num.SetBytes(getBlockHashFromContract(num64, evm.StateDB, evm.Accesses).Bytes()) - return nil, nil - } - - // if the 256th ancestor didn't have its hash stored in the - // history contract, then we are within 256 blocks of the - // fork activation, and the former behavior should be retained. - // Fall through the legacy use case. + // if Prague is active, read it from the history contract (EIP 2935). + if evm.chainRules.IsPrague { + num.SetBytes(getBlockHashFromContract(num64, evm.StateDB, evm.Accesses).Bytes()) + return nil, nil } var upper, lower uint64 diff --git a/miner/worker.go b/miner/worker.go index ef8d6087b7cd..aae4fe8b6454 100644 --- a/miner/worker.go +++ b/miner/worker.go @@ -921,7 +921,12 @@ func (w *worker) prepareWork(genParams *generateParams) (*environment, error) { return nil, err } if w.chainConfig.IsPrague(header.Number, header.Time) { - core.ProcessParentBlockHash(env.state, header.Number.Uint64()-1, header.ParentHash) + parent := w.chain.GetHeaderByNumber(header.Number.Uint64() - 1) + if !w.chain.Config().IsPrague(parent.Number, parent.Time) { + core.InsertBlockHashHistoryAtEip2935Fork(env.state, header.Number.Uint64()-1, header.ParentHash, w.chain) + } else { + core.ProcessParentBlockHash(env.state, header.Number.Uint64()-1, header.ParentHash) + } } return env, nil }