Skip to content

Commit

Permalink
core/{.,state,vm},miner,ethr/tracers: implement 7709
Browse files Browse the repository at this point in the history
Co-authored-by: Ignacio Hagopian <[email protected]>

Signed-off-by: Guillaume Ballet <[email protected]>
  • Loading branch information
gballet committed Jan 10, 2025
1 parent 033de2a commit 0081ab6
Show file tree
Hide file tree
Showing 8 changed files with 39 additions and 18 deletions.
4 changes: 2 additions & 2 deletions core/chain_makers.go
Original file line number Diff line number Diff line change
Expand Up @@ -384,7 +384,7 @@ func GenerateChain(config *params.ChainConfig, parent *types.Block, engine conse
blockContext := NewEVMBlockContext(b.header, cm, &b.header.Coinbase)
blockContext.Random = &common.Hash{} // enable post-merge instruction set
evm := vm.NewEVM(blockContext, statedb, cm.config, vm.Config{})
ProcessParentBlockHash(b.header.ParentHash, evm)
ProcessParentBlockHash(b.header.ParentHash, evm, false)
}

// Execute any user modifications to the block
Expand Down Expand Up @@ -492,7 +492,7 @@ func GenerateVerkleChain(config *params.ChainConfig, parent *types.Block, engine
// EIP-2935
blockContext := NewEVMBlockContext(b.header, cm, &b.header.Coinbase)
evm := vm.NewEVM(blockContext, statedb, cm.config, vm.Config{})
ProcessParentBlockHash(b.header.ParentHash, evm)
ProcessParentBlockHash(b.header.ParentHash, evm, false)
}

// Execute any user modifications to the block.
Expand Down
4 changes: 4 additions & 0 deletions core/state/statedb_hooked.go
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,10 @@ func (s *hookedStateDB) Witness() *stateless.Witness {
return s.inner.Witness()
}

func (s *hookedStateDB) AccessEvents() *AccessEvents {
return s.inner.AccessEvents()
}

func (s *hookedStateDB) SubBalance(addr common.Address, amount *uint256.Int, reason tracing.BalanceChangeReason) uint256.Int {
prev := s.inner.SubBalance(addr, amount, reason)
if s.hooks.OnBalanceChange != nil && !amount.IsZero() {
Expand Down
17 changes: 14 additions & 3 deletions core/state_processor.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
package core

import (
"encoding/binary"
"fmt"
"math/big"

Expand Down Expand Up @@ -86,7 +87,7 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg
ProcessBeaconBlockRoot(*beaconRoot, evm)
}
if p.config.IsPrague(block.Number(), block.Time()) {
ProcessParentBlockHash(block.ParentHash(), evm)
ProcessParentBlockHash(block.ParentHash(), evm, p.config.IsVerkle(block.Number(), block.Time()))
}

// Iterate over and process the individual transactions
Expand Down Expand Up @@ -234,14 +235,24 @@ func ProcessBeaconBlockRoot(beaconRoot common.Hash, evm *vm.EVM) {
}

// ProcessParentBlockHash stores the parent block hash in the history storage contract
// as per EIP-2935.
func ProcessParentBlockHash(prevHash common.Hash, evm *vm.EVM) {
// as per EIP-2935/7709.
func ProcessParentBlockHash(prevHash common.Hash, evm *vm.EVM, is7709 bool) {
if tracer := evm.Config.Tracer; tracer != nil {
onSystemCallStart(tracer, evm.GetVMContext())
if tracer.OnSystemCallEnd != nil {
defer tracer.OnSystemCallEnd()
}
}
if is7709 {
// currently 8192 for kautinen7, to be changed to 8 (and made a constant) for kaustinen8
ringIndex := (evm.Context.BlockNumber.Uint64() - 1) % 8192
var key common.Hash
binary.BigEndian.PutUint64(key[24:], ringIndex)
evm.StateDB.SetState(params.SystemAddress, key, prevHash)
evm.StateDB.AccessEvents().SlotGas(params.SystemAddress, key, true)
evm.StateDB.Finalise(false)
return
}
msg := &Message{
From: params.SystemAddress,
GasLimit: 30_000_000,
Expand Down
17 changes: 10 additions & 7 deletions core/verkle_witness_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,7 @@ func TestProcessParentBlockHash(t *testing.T) {
// block 1 parent hash is 0x0100....
// block 2 parent hash is 0x0200....
// etc
checkBlockHashes := func(statedb *state.StateDB) {
checkBlockHashes := func(statedb *state.StateDB, isVerkle bool) {
statedb.SetNonce(params.HistoryStorageAddress, 1)
statedb.SetCode(params.HistoryStorageAddress, params.HistoryStorageCode)
// Process n blocks, from 1 .. num
Expand All @@ -226,35 +226,38 @@ func TestProcessParentBlockHash(t *testing.T) {
header := &types.Header{ParentHash: common.Hash{byte(i)}, Number: big.NewInt(int64(i)), Difficulty: new(big.Int)}
vmContext := NewEVMBlockContext(header, nil, new(common.Address))
evm := vm.NewEVM(vmContext, statedb, params.MergedTestChainConfig, vm.Config{})
ProcessParentBlockHash(header.ParentHash, evm)
ProcessParentBlockHash(header.ParentHash, evm, isVerkle)
}
// Read block hashes for block 0 .. num-1
for i := 0; i < num; i++ {
have, want := getContractStoredBlockHash(statedb, uint64(i)), common.Hash{byte(i + 1)}
have, want := getContractStoredBlockHash(statedb, uint64(i), isVerkle), common.Hash{byte(i + 1)}
if have != want {
t.Errorf("block %d, have parent hash %v, want %v", i, have, want)
t.Errorf("block %d, verkle=%v, have parent hash %v, want %v", i, isVerkle, have, want)
}
}
}
t.Run("MPT", func(t *testing.T) {
statedb, _ := state.New(types.EmptyRootHash, state.NewDatabaseForTesting())
checkBlockHashes(statedb)
checkBlockHashes(statedb, false)
})
t.Run("Verkle", func(t *testing.T) {
db := rawdb.NewMemoryDatabase()
cacheConfig := DefaultCacheConfigWithScheme(rawdb.PathScheme)
cacheConfig.SnapshotLimit = 0
triedb := triedb.NewDatabase(db, cacheConfig.triedbConfig(true))
statedb, _ := state.New(types.EmptyVerkleHash, state.NewDatabase(triedb, nil))
checkBlockHashes(statedb)
checkBlockHashes(statedb, true)
})
}

// getContractStoredBlockHash is a utility method which reads the stored parent blockhash for block 'number'
func getContractStoredBlockHash(statedb *state.StateDB, number uint64) common.Hash {
func getContractStoredBlockHash(statedb *state.StateDB, number uint64, isVerkle bool) common.Hash {
ringIndex := number % params.HistoryServeWindow
var key common.Hash
binary.BigEndian.PutUint64(key[24:], ringIndex)
if isVerkle {
return statedb.GetState(params.SystemAddress, key)
}
return statedb.GetState(params.HistoryStorageAddress, key)
}

Expand Down
3 changes: 3 additions & 0 deletions core/vm/interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (
"math/big"

"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/stateless"
"github.com/ethereum/go-ethereum/core/tracing"
"github.com/ethereum/go-ethereum/core/types"
Expand Down Expand Up @@ -98,6 +99,8 @@ type StateDB interface {

Witness() *stateless.Witness

AccessEvents() *state.AccessEvents

// Finalise must be invoked at the end of a transaction
Finalise(bool)
}
Expand Down
2 changes: 1 addition & 1 deletion eth/state_accessor.go
Original file line number Diff line number Diff line change
Expand Up @@ -242,7 +242,7 @@ func (eth *Ethereum) stateAtTransaction(ctx context.Context, block *types.Block,
}
// If prague hardfork, insert parent block hash in the state as per EIP-2935.
if eth.blockchain.Config().IsPrague(block.Number(), block.Time()) {
core.ProcessParentBlockHash(block.ParentHash(), evm)
core.ProcessParentBlockHash(block.ParentHash(), evm, eth.blockchain.Config().IsVerkle(block.Number(), block.Time()))
}
if txIndex == 0 && len(block.Transactions()) == 0 {
return nil, vm.BlockContext{}, statedb, release, nil
Expand Down
8 changes: 4 additions & 4 deletions eth/tracers/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -386,7 +386,7 @@ func (api *API) traceChain(start, end *types.Block, config *TraceConfig, closed
}
// Insert parent hash in history contract.
if api.backend.ChainConfig().IsPrague(next.Number(), next.Time()) {
core.ProcessParentBlockHash(next.ParentHash(), evm)
core.ProcessParentBlockHash(next.ParentHash(), evm, api.backend.ChainConfig().IsVerkle(next.Number(), next.Time()))
}
// Clean out any pending release functions of trace state. Note this
// step must be done after constructing tracing state, because the
Expand Down Expand Up @@ -541,7 +541,7 @@ func (api *API) IntermediateRoots(ctx context.Context, hash common.Hash, config
core.ProcessBeaconBlockRoot(*beaconRoot, evm)
}
if chainConfig.IsPrague(block.Number(), block.Time()) {
core.ProcessParentBlockHash(block.ParentHash(), evm)
core.ProcessParentBlockHash(block.ParentHash(), evm, api.backend.ChainConfig().IsVerkle(block.Number(), block.Time()))
}
for i, tx := range block.Transactions() {
if err := ctx.Err(); err != nil {
Expand Down Expand Up @@ -605,7 +605,7 @@ func (api *API) traceBlock(ctx context.Context, block *types.Block, config *Trac
core.ProcessBeaconBlockRoot(*beaconRoot, evm)
}
if api.backend.ChainConfig().IsPrague(block.Number(), block.Time()) {
core.ProcessParentBlockHash(block.ParentHash(), evm)
core.ProcessParentBlockHash(block.ParentHash(), evm, api.backend.ChainConfig().IsVerkle(block.Number(), block.Time()))
}

// JS tracers have high overhead. In this case run a parallel
Expand Down Expand Up @@ -782,7 +782,7 @@ func (api *API) standardTraceBlockToFile(ctx context.Context, block *types.Block
core.ProcessBeaconBlockRoot(*beaconRoot, evm)
}
if chainConfig.IsPrague(block.Number(), block.Time()) {
core.ProcessParentBlockHash(block.ParentHash(), evm)
core.ProcessParentBlockHash(block.ParentHash(), evm, api.backend.ChainConfig().IsVerkle(block.Number(), block.Time()))
}
for i, tx := range block.Transactions() {
// Prepare the transaction for un-traced execution
Expand Down
2 changes: 1 addition & 1 deletion miner/worker.go
Original file line number Diff line number Diff line change
Expand Up @@ -231,7 +231,7 @@ func (miner *Miner) prepareWork(genParams *generateParams, witness bool) (*envir
core.ProcessBeaconBlockRoot(*header.ParentBeaconRoot, env.evm)
}
if miner.chainConfig.IsPrague(header.Number, header.Time) {
core.ProcessParentBlockHash(header.ParentHash, env.evm)
core.ProcessParentBlockHash(header.ParentHash, env.evm, false)
}
return env, nil
}
Expand Down

0 comments on commit 0081ab6

Please sign in to comment.