mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-17 17:33:47 +00:00
core/{.,state,vm},miner,ethr/tracers: implement 7709
Co-authored-by: Ignacio Hagopian <jsign.uy@gmail.com> Signed-off-by: Guillaume Ballet <3272758+gballet@users.noreply.github.com>
This commit is contained in:
parent
033de2a05b
commit
dd5ff823bd
8 changed files with 39 additions and 18 deletions
|
|
@ -384,7 +384,7 @@ func GenerateChain(config *params.ChainConfig, parent *types.Block, engine conse
|
||||||
blockContext := NewEVMBlockContext(b.header, cm, &b.header.Coinbase)
|
blockContext := NewEVMBlockContext(b.header, cm, &b.header.Coinbase)
|
||||||
blockContext.Random = &common.Hash{} // enable post-merge instruction set
|
blockContext.Random = &common.Hash{} // enable post-merge instruction set
|
||||||
evm := vm.NewEVM(blockContext, statedb, cm.config, vm.Config{})
|
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
|
// Execute any user modifications to the block
|
||||||
|
|
@ -492,7 +492,7 @@ func GenerateVerkleChain(config *params.ChainConfig, parent *types.Block, engine
|
||||||
// EIP-2935
|
// EIP-2935
|
||||||
blockContext := NewEVMBlockContext(b.header, cm, &b.header.Coinbase)
|
blockContext := NewEVMBlockContext(b.header, cm, &b.header.Coinbase)
|
||||||
evm := vm.NewEVM(blockContext, statedb, cm.config, vm.Config{})
|
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.
|
// Execute any user modifications to the block.
|
||||||
|
|
|
||||||
|
|
@ -157,6 +157,10 @@ func (s *hookedStateDB) Witness() *stateless.Witness {
|
||||||
return s.inner.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 {
|
func (s *hookedStateDB) SubBalance(addr common.Address, amount *uint256.Int, reason tracing.BalanceChangeReason) uint256.Int {
|
||||||
prev := s.inner.SubBalance(addr, amount, reason)
|
prev := s.inner.SubBalance(addr, amount, reason)
|
||||||
if s.hooks.OnBalanceChange != nil && !amount.IsZero() {
|
if s.hooks.OnBalanceChange != nil && !amount.IsZero() {
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@
|
||||||
package core
|
package core
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/binary"
|
||||||
"fmt"
|
"fmt"
|
||||||
"math/big"
|
"math/big"
|
||||||
|
|
||||||
|
|
@ -86,7 +87,7 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg
|
||||||
ProcessBeaconBlockRoot(*beaconRoot, evm)
|
ProcessBeaconBlockRoot(*beaconRoot, evm)
|
||||||
}
|
}
|
||||||
if p.config.IsPrague(block.Number(), block.Time()) {
|
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
|
// Iterate over and process the individual transactions
|
||||||
|
|
@ -234,14 +235,24 @@ func ProcessBeaconBlockRoot(beaconRoot common.Hash, evm *vm.EVM) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// ProcessParentBlockHash stores the parent block hash in the history storage contract
|
// ProcessParentBlockHash stores the parent block hash in the history storage contract
|
||||||
// as per EIP-2935.
|
// as per EIP-2935/7709.
|
||||||
func ProcessParentBlockHash(prevHash common.Hash, evm *vm.EVM) {
|
func ProcessParentBlockHash(prevHash common.Hash, evm *vm.EVM, is7709 bool) {
|
||||||
if tracer := evm.Config.Tracer; tracer != nil {
|
if tracer := evm.Config.Tracer; tracer != nil {
|
||||||
onSystemCallStart(tracer, evm.GetVMContext())
|
onSystemCallStart(tracer, evm.GetVMContext())
|
||||||
if tracer.OnSystemCallEnd != nil {
|
if tracer.OnSystemCallEnd != nil {
|
||||||
defer tracer.OnSystemCallEnd()
|
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) % params.HistoryServeWindow
|
||||||
|
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{
|
msg := &Message{
|
||||||
From: params.SystemAddress,
|
From: params.SystemAddress,
|
||||||
GasLimit: 30_000_000,
|
GasLimit: 30_000_000,
|
||||||
|
|
|
||||||
|
|
@ -217,7 +217,7 @@ func TestProcessParentBlockHash(t *testing.T) {
|
||||||
// block 1 parent hash is 0x0100....
|
// block 1 parent hash is 0x0100....
|
||||||
// block 2 parent hash is 0x0200....
|
// block 2 parent hash is 0x0200....
|
||||||
// etc
|
// etc
|
||||||
checkBlockHashes := func(statedb *state.StateDB) {
|
checkBlockHashes := func(statedb *state.StateDB, isVerkle bool) {
|
||||||
statedb.SetNonce(params.HistoryStorageAddress, 1)
|
statedb.SetNonce(params.HistoryStorageAddress, 1)
|
||||||
statedb.SetCode(params.HistoryStorageAddress, params.HistoryStorageCode)
|
statedb.SetCode(params.HistoryStorageAddress, params.HistoryStorageCode)
|
||||||
// Process n blocks, from 1 .. num
|
// Process n blocks, from 1 .. num
|
||||||
|
|
@ -226,19 +226,19 @@ func TestProcessParentBlockHash(t *testing.T) {
|
||||||
header := &types.Header{ParentHash: common.Hash{byte(i)}, Number: big.NewInt(int64(i)), Difficulty: new(big.Int)}
|
header := &types.Header{ParentHash: common.Hash{byte(i)}, Number: big.NewInt(int64(i)), Difficulty: new(big.Int)}
|
||||||
vmContext := NewEVMBlockContext(header, nil, new(common.Address))
|
vmContext := NewEVMBlockContext(header, nil, new(common.Address))
|
||||||
evm := vm.NewEVM(vmContext, statedb, params.MergedTestChainConfig, vm.Config{})
|
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
|
// Read block hashes for block 0 .. num-1
|
||||||
for i := 0; i < num; i++ {
|
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 {
|
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) {
|
t.Run("MPT", func(t *testing.T) {
|
||||||
statedb, _ := state.New(types.EmptyRootHash, state.NewDatabaseForTesting())
|
statedb, _ := state.New(types.EmptyRootHash, state.NewDatabaseForTesting())
|
||||||
checkBlockHashes(statedb)
|
checkBlockHashes(statedb, false)
|
||||||
})
|
})
|
||||||
t.Run("Verkle", func(t *testing.T) {
|
t.Run("Verkle", func(t *testing.T) {
|
||||||
db := rawdb.NewMemoryDatabase()
|
db := rawdb.NewMemoryDatabase()
|
||||||
|
|
@ -246,15 +246,18 @@ func TestProcessParentBlockHash(t *testing.T) {
|
||||||
cacheConfig.SnapshotLimit = 0
|
cacheConfig.SnapshotLimit = 0
|
||||||
triedb := triedb.NewDatabase(db, cacheConfig.triedbConfig(true))
|
triedb := triedb.NewDatabase(db, cacheConfig.triedbConfig(true))
|
||||||
statedb, _ := state.New(types.EmptyVerkleHash, state.NewDatabase(triedb, nil))
|
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'
|
// 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
|
ringIndex := number % params.HistoryServeWindow
|
||||||
var key common.Hash
|
var key common.Hash
|
||||||
binary.BigEndian.PutUint64(key[24:], ringIndex)
|
binary.BigEndian.PutUint64(key[24:], ringIndex)
|
||||||
|
if isVerkle {
|
||||||
|
return statedb.GetState(params.SystemAddress, key)
|
||||||
|
}
|
||||||
return statedb.GetState(params.HistoryStorageAddress, key)
|
return statedb.GetState(params.HistoryStorageAddress, key)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,7 @@ import (
|
||||||
"math/big"
|
"math/big"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"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/stateless"
|
||||||
"github.com/ethereum/go-ethereum/core/tracing"
|
"github.com/ethereum/go-ethereum/core/tracing"
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
|
|
@ -98,6 +99,8 @@ type StateDB interface {
|
||||||
|
|
||||||
Witness() *stateless.Witness
|
Witness() *stateless.Witness
|
||||||
|
|
||||||
|
AccessEvents() *state.AccessEvents
|
||||||
|
|
||||||
// Finalise must be invoked at the end of a transaction
|
// Finalise must be invoked at the end of a transaction
|
||||||
Finalise(bool)
|
Finalise(bool)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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 prague hardfork, insert parent block hash in the state as per EIP-2935.
|
||||||
if eth.blockchain.Config().IsPrague(block.Number(), block.Time()) {
|
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 {
|
if txIndex == 0 && len(block.Transactions()) == 0 {
|
||||||
return nil, vm.BlockContext{}, statedb, release, nil
|
return nil, vm.BlockContext{}, statedb, release, nil
|
||||||
|
|
|
||||||
|
|
@ -386,7 +386,7 @@ func (api *API) traceChain(start, end *types.Block, config *TraceConfig, closed
|
||||||
}
|
}
|
||||||
// Insert parent hash in history contract.
|
// Insert parent hash in history contract.
|
||||||
if api.backend.ChainConfig().IsPrague(next.Number(), next.Time()) {
|
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
|
// Clean out any pending release functions of trace state. Note this
|
||||||
// step must be done after constructing tracing state, because the
|
// step must be done after constructing tracing state, because the
|
||||||
|
|
@ -541,7 +541,7 @@ func (api *API) IntermediateRoots(ctx context.Context, hash common.Hash, config
|
||||||
core.ProcessBeaconBlockRoot(*beaconRoot, evm)
|
core.ProcessBeaconBlockRoot(*beaconRoot, evm)
|
||||||
}
|
}
|
||||||
if chainConfig.IsPrague(block.Number(), block.Time()) {
|
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() {
|
for i, tx := range block.Transactions() {
|
||||||
if err := ctx.Err(); err != nil {
|
if err := ctx.Err(); err != nil {
|
||||||
|
|
@ -605,7 +605,7 @@ func (api *API) traceBlock(ctx context.Context, block *types.Block, config *Trac
|
||||||
core.ProcessBeaconBlockRoot(*beaconRoot, evm)
|
core.ProcessBeaconBlockRoot(*beaconRoot, evm)
|
||||||
}
|
}
|
||||||
if api.backend.ChainConfig().IsPrague(block.Number(), block.Time()) {
|
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
|
// JS tracers have high overhead. In this case run a parallel
|
||||||
|
|
@ -782,7 +782,7 @@ func (api *API) standardTraceBlockToFile(ctx context.Context, block *types.Block
|
||||||
core.ProcessBeaconBlockRoot(*beaconRoot, evm)
|
core.ProcessBeaconBlockRoot(*beaconRoot, evm)
|
||||||
}
|
}
|
||||||
if chainConfig.IsPrague(block.Number(), block.Time()) {
|
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() {
|
for i, tx := range block.Transactions() {
|
||||||
// Prepare the transaction for un-traced execution
|
// Prepare the transaction for un-traced execution
|
||||||
|
|
|
||||||
|
|
@ -231,7 +231,7 @@ func (miner *Miner) prepareWork(genParams *generateParams, witness bool) (*envir
|
||||||
core.ProcessBeaconBlockRoot(*header.ParentBeaconRoot, env.evm)
|
core.ProcessBeaconBlockRoot(*header.ParentBeaconRoot, env.evm)
|
||||||
}
|
}
|
||||||
if miner.chainConfig.IsPrague(header.Number, header.Time) {
|
if miner.chainConfig.IsPrague(header.Number, header.Time) {
|
||||||
core.ProcessParentBlockHash(header.ParentHash, env.evm)
|
core.ProcessParentBlockHash(header.ParentHash, env.evm, false)
|
||||||
}
|
}
|
||||||
return env, nil
|
return env, nil
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue