eip2935 redesign: insert all 256 ancestors upon transition (#362)

* eip2935 redesign: only read target block hash

* review fixes

* fix: t8n tool
This commit is contained in:
Guillaume Ballet 2024-02-06 09:52:24 +01:00
parent 61ffef7961
commit 2e671ea446
5 changed files with 34 additions and 20 deletions

View file

@ -184,7 +184,10 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
misc.ApplyDAOHardFork(statedb) misc.ApplyDAOHardFork(statedb)
} }
if chainConfig.IsPrague(big.NewInt(int64(pre.Env.Number)), pre.Env.Timestamp) { if chainConfig.IsPrague(big.NewInt(int64(pre.Env.Number)), pre.Env.Timestamp) {
core.ProcessParentBlockHash(statedb, pre.Env.Number-1, *pre.Env.ParentHash) // insert all parent hashes in the contract
for i := pre.Env.Number - 1; i > 0 && i >= pre.Env.Number-257; i-- {
core.ProcessParentBlockHash(statedb, i, pre.Env.BlockHashes[math.HexOrDecimal64(i)])
}
} }
var blobGasUsed uint64 var blobGasUsed uint64
for i, tx := range txs { for i, tx := range txs {

View file

@ -386,7 +386,12 @@ func GenerateVerkleChain(config *params.ChainConfig, parent *types.Block, engine
fmt.Println("prestate", preState.GetTrie().(*trie.VerkleTrie).ToDot()) fmt.Println("prestate", preState.GetTrie().(*trie.VerkleTrie).ToDot())
if config.IsPrague(b.header.Number, b.header.Time) { 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 // Mutate the state and block according to any hard-fork specs

View file

@ -87,7 +87,12 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg
signer = types.MakeSigner(p.config, header.Number, header.Time) signer = types.MakeSigner(p.config, header.Number, header.Time)
) )
if p.config.IsPrague(block.Number(), block.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 // Iterate over and process the individual transactions
for i, tx := range block.Transactions() { for i, tx := range block.Transactions() {
@ -364,6 +369,14 @@ func (kvm *keyValueMigrator) migrateCollectedKeyValues(tree *trie.VerkleTrie) er
return nil 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()-1)
}
}
func ProcessParentBlockHash(statedb *state.StateDB, prevNumber uint64, prevHash common.Hash) { func ProcessParentBlockHash(statedb *state.StateDB, prevNumber uint64, prevHash common.Hash) {
var key common.Hash var key common.Hash
binary.BigEndian.PutUint64(key[24:], prevNumber) binary.BigEndian.PutUint64(key[24:], prevNumber)

View file

@ -515,22 +515,10 @@ func opBlockhash(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) (
} }
evm := interpreter.evm evm := interpreter.evm
bnum := evm.Context.BlockNumber.Uint64() // if Prague is active, read it from the history contract (EIP 2935).
// if Prague is active, check if we are past the 256th block so that if evm.chainRules.IsPrague {
// reading from the contract can be activated (EIP 2935). num.SetBytes(getBlockHashFromContract(num64, evm.StateDB, evm.Accesses).Bytes())
if evm.chainRules.IsPrague && bnum > 256 { return nil, nil
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.
} }
var upper, lower uint64 var upper, lower uint64

View file

@ -921,7 +921,12 @@ func (w *worker) prepareWork(genParams *generateParams) (*environment, error) {
return nil, err return nil, err
} }
if w.chainConfig.IsPrague(header.Number, header.Time) { 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 return env, nil
} }