mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-23 13:16:42 +00:00
fix a lot of tests
This commit is contained in:
parent
b2c4d19ca2
commit
fe6bce3769
7 changed files with 101 additions and 106 deletions
|
|
@ -1,7 +1,6 @@
|
||||||
package core
|
package core
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"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"
|
||||||
|
|
@ -27,10 +26,10 @@ type BlockAccessListTracer struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewBlockAccessListTracer returns an BlockAccessListTracer and a set of hooks
|
// NewBlockAccessListTracer returns an BlockAccessListTracer and a set of hooks
|
||||||
func NewBlockAccessListTracer() (*BlockAccessListTracer, *tracing.Hooks) {
|
func NewBlockAccessListTracer(startIdx int) (*BlockAccessListTracer, *tracing.Hooks) {
|
||||||
balTracer := &BlockAccessListTracer{
|
balTracer := &BlockAccessListTracer{
|
||||||
callAccessLists: []*bal.ConstructionBlockAccessList{bal.NewConstructionBlockAccessList()},
|
callAccessLists: []*bal.ConstructionBlockAccessList{bal.NewConstructionBlockAccessList()},
|
||||||
txIdx: 0,
|
txIdx: uint16(startIdx),
|
||||||
}
|
}
|
||||||
hooks := &tracing.Hooks{
|
hooks := &tracing.Hooks{
|
||||||
OnTxEnd: balTracer.TxEndHook,
|
OnTxEnd: balTracer.TxEndHook,
|
||||||
|
|
@ -52,11 +51,6 @@ func (a *BlockAccessListTracer) AccessList() *bal.ConstructionBlockAccessList {
|
||||||
return a.callAccessLists[0]
|
return a.callAccessLists[0]
|
||||||
}
|
}
|
||||||
|
|
||||||
// StateDiff returns a state diff at the current BAL index
|
|
||||||
func (a *BlockAccessListTracer) StateDiff() *bal.StateDiff {
|
|
||||||
return a.callAccessLists[0].
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a *BlockAccessListTracer) TxEndHook(receipt *types.Receipt, err error) {
|
func (a *BlockAccessListTracer) TxEndHook(receipt *types.Receipt, err error) {
|
||||||
a.txIdx++
|
a.txIdx++
|
||||||
}
|
}
|
||||||
|
|
@ -80,11 +74,8 @@ func (a *BlockAccessListTracer) OnExit(depth int, output []byte, gasUsed uint64,
|
||||||
parentAccessList := a.callAccessLists[len(a.callAccessLists)-2]
|
parentAccessList := a.callAccessLists[len(a.callAccessLists)-2]
|
||||||
scopeAccessList := a.callAccessLists[len(a.callAccessLists)-1]
|
scopeAccessList := a.callAccessLists[len(a.callAccessLists)-1]
|
||||||
if reverted {
|
if reverted {
|
||||||
fmt.Println("exit reverted")
|
|
||||||
parentAccessList.MergeReads(scopeAccessList)
|
parentAccessList.MergeReads(scopeAccessList)
|
||||||
} else {
|
} else {
|
||||||
fmt.Println("exit normal")
|
|
||||||
fmt.Printf("scope access list is\n%s\n", scopeAccessList.ToEncodingObj().String())
|
|
||||||
parentAccessList.Merge(scopeAccessList)
|
parentAccessList.Merge(scopeAccessList)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -112,7 +103,6 @@ func (a *BlockAccessListTracer) OnColdStorageRead(addr common.Address, key commo
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *BlockAccessListTracer) OnColdAccountRead(addr common.Address) {
|
func (a *BlockAccessListTracer) OnColdAccountRead(addr common.Address) {
|
||||||
fmt.Printf("cold account read %x\n", addr)
|
|
||||||
a.callAccessLists[len(a.callAccessLists)-1].AccountRead(addr)
|
a.callAccessLists[len(a.callAccessLists)-1].AccountRead(addr)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2062,11 +2062,6 @@ func (bc *BlockChain) ProcessBlock(parentRoot common.Hash, block *types.Block, s
|
||||||
}(time.Now(), throwaway, block)
|
}(time.Now(), throwaway, block)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: can remove validateBAL parameter and just look at whether the block has an access list?
|
|
||||||
if constructBALForTesting || validateBAL {
|
|
||||||
statedb.EnableStateDiffRecording()
|
|
||||||
}
|
|
||||||
|
|
||||||
// If we are past Byzantium, enable prefetching to pull in trie node paths
|
// If we are past Byzantium, enable prefetching to pull in trie node paths
|
||||||
// while processing transactions. Before Byzantium the prefetcher is mostly
|
// while processing transactions. Before Byzantium the prefetcher is mostly
|
||||||
// useless due to the intermediate root hashing after each transaction.
|
// useless due to the intermediate root hashing after each transaction.
|
||||||
|
|
@ -2150,7 +2145,7 @@ func (bc *BlockChain) ProcessBlock(parentRoot common.Hash, block *types.Block, s
|
||||||
var balTracer *BlockAccessListTracer
|
var balTracer *BlockAccessListTracer
|
||||||
// Process block using the parent state as reference point
|
// Process block using the parent state as reference point
|
||||||
if constructBALForTesting {
|
if constructBALForTesting {
|
||||||
balTracer, bc.cfg.VmConfig.Tracer = NewBlockAccessListTracer()
|
balTracer, bc.cfg.VmConfig.Tracer = NewBlockAccessListTracer(0)
|
||||||
}
|
}
|
||||||
// Process block using the parent state as reference point
|
// Process block using the parent state as reference point
|
||||||
pstart := time.Now()
|
pstart := time.Now()
|
||||||
|
|
|
||||||
|
|
@ -328,11 +328,11 @@ func (b *BlockGen) collectRequests(readonly bool) (requests [][]byte) {
|
||||||
blockContext := NewEVMBlockContext(b.header, b.cm, &b.header.Coinbase)
|
blockContext := NewEVMBlockContext(b.header, b.cm, &b.header.Coinbase)
|
||||||
evm := vm.NewEVM(blockContext, statedb, b.cm.config, vm.Config{})
|
evm := vm.NewEVM(blockContext, statedb, b.cm.config, vm.Config{})
|
||||||
// EIP-7002
|
// EIP-7002
|
||||||
if _, _, err := ProcessWithdrawalQueue(&requests, evm); err != nil {
|
if err := ProcessWithdrawalQueue(&requests, evm); err != nil {
|
||||||
panic(fmt.Sprintf("could not process withdrawal requests: %v", err))
|
panic(fmt.Sprintf("could not process withdrawal requests: %v", err))
|
||||||
}
|
}
|
||||||
// EIP-7251
|
// EIP-7251
|
||||||
if _, _, err := ProcessConsolidationQueue(&requests, evm); err != nil {
|
if err := ProcessConsolidationQueue(&requests, evm); err != nil {
|
||||||
panic(fmt.Sprintf("could not process consolidation requests: %v", err))
|
panic(fmt.Sprintf("could not process consolidation requests: %v", err))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -58,13 +58,20 @@ func (p *ParallelStateProcessor) prepareExecResult(block *types.Block, allStateR
|
||||||
tPostprocessStart := time.Now()
|
tPostprocessStart := time.Now()
|
||||||
header := block.Header()
|
header := block.Header()
|
||||||
|
|
||||||
postTxState.SetAccessListIndex(len(block.Transactions()) + 1)
|
balTracer, hooks := NewBlockAccessListTracer(len(block.Transactions()) + 1)
|
||||||
var tracingStateDB = vm.StateDB(postTxState)
|
tracingStateDB := state.NewHookedState(postTxState, hooks)
|
||||||
if hooks := p.vmCfg.Tracer; hooks != nil {
|
|
||||||
tracingStateDB = state.NewHookedState(postTxState, hooks)
|
|
||||||
}
|
|
||||||
context := NewEVMBlockContext(header, p.chain, nil)
|
context := NewEVMBlockContext(header, p.chain, nil)
|
||||||
evm := vm.NewEVM(context, tracingStateDB, p.config, *p.vmCfg)
|
|
||||||
|
cfg := vm.Config{
|
||||||
|
Tracer: hooks,
|
||||||
|
NoBaseFee: p.vmCfg.NoBaseFee,
|
||||||
|
EnablePreimageRecording: p.vmCfg.EnablePreimageRecording,
|
||||||
|
ExtraEips: slices.Clone(p.vmCfg.ExtraEips),
|
||||||
|
StatelessSelfValidation: p.vmCfg.StatelessSelfValidation,
|
||||||
|
EnableWitnessStats: p.vmCfg.EnableWitnessStats,
|
||||||
|
}
|
||||||
|
cfg.Tracer = hooks
|
||||||
|
evm := vm.NewEVM(context, tracingStateDB, p.config, cfg)
|
||||||
|
|
||||||
// 1. order the receipts by tx index
|
// 1. order the receipts by tx index
|
||||||
// 2. correctly calculate the cumulative gas used per receipt, returning bad block error if it goes over the allowed
|
// 2. correctly calculate the cumulative gas used per receipt, returning bad block error if it goes over the allowed
|
||||||
|
|
@ -85,9 +92,6 @@ func (p *ParallelStateProcessor) prepareExecResult(block *types.Block, allStateR
|
||||||
allLogs = append(allLogs, receipt.Logs...)
|
allLogs = append(allLogs, receipt.Logs...)
|
||||||
}
|
}
|
||||||
|
|
||||||
computedDiff := &bal.StateDiff{make(map[common.Address]*bal.AccountState)}
|
|
||||||
computedAccesses := make(bal.StateAccesses)
|
|
||||||
|
|
||||||
// Read requests if Prague is enabled.
|
// Read requests if Prague is enabled.
|
||||||
if p.config.IsPrague(block.Number(), block.Time()) {
|
if p.config.IsPrague(block.Number(), block.Time()) {
|
||||||
requests = [][]byte{}
|
requests = [][]byte{}
|
||||||
|
|
@ -99,38 +103,35 @@ func (p *ParallelStateProcessor) prepareExecResult(block *types.Block, allStateR
|
||||||
}
|
}
|
||||||
|
|
||||||
// EIP-7002
|
// EIP-7002
|
||||||
diff, accesses, err := ProcessWithdrawalQueue(&requests, evm)
|
err := ProcessWithdrawalQueue(&requests, evm)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return &ProcessResultWithMetrics{
|
return &ProcessResultWithMetrics{
|
||||||
ProcessResult: &ProcessResult{Error: err},
|
ProcessResult: &ProcessResult{Error: err},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
computedDiff = diff
|
|
||||||
computedAccesses = *accesses
|
|
||||||
|
|
||||||
// EIP-7251
|
// EIP-7251
|
||||||
diff, accesses, err = ProcessConsolidationQueue(&requests, evm)
|
err = ProcessConsolidationQueue(&requests, evm)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return &ProcessResultWithMetrics{
|
return &ProcessResultWithMetrics{
|
||||||
ProcessResult: &ProcessResult{Error: err},
|
ProcessResult: &ProcessResult{Error: err},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
computedDiff.Merge(diff)
|
|
||||||
computedAccesses.Merge(*accesses)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Finalize the block, applying any consensus engine specific extras (e.g. block rewards)
|
// Finalize the block, applying any consensus engine specific extras (e.g. block rewards)
|
||||||
p.chain.engine.Finalize(p.chain, header, tracingStateDB, block.Body())
|
p.chain.engine.Finalize(p.chain, header, tracingStateDB, block.Body())
|
||||||
// invoke Finalise so that withdrawals are accounted for in the state diff
|
// invoke Finalise so that withdrawals are accounted for in the state diff
|
||||||
postTxState.Finalise(true)
|
postTxState.Finalise(true)
|
||||||
|
allStateReads.Merge(balTracer.AccessList().StateAccesses())
|
||||||
|
|
||||||
if err := postTxState.BlockAccessList().ValidateStateDiff(len(block.Transactions())+1, computedDiff); err != nil {
|
balIdx := len(block.Transactions()) + 1
|
||||||
|
if err := postTxState.BlockAccessList().ValidateStateDiff(balIdx, balTracer.AccessList().DiffAt(balIdx)); err != nil {
|
||||||
return &ProcessResultWithMetrics{
|
return &ProcessResultWithMetrics{
|
||||||
ProcessResult: &ProcessResult{Error: err},
|
ProcessResult: &ProcessResult{Error: err},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
allStateReads.Merge(computedAccesses)
|
|
||||||
if err := postTxState.BlockAccessList().ValidateStateReads(*allStateReads); err != nil {
|
if err := postTxState.BlockAccessList().ValidateStateReads(*allStateReads); err != nil {
|
||||||
return &ProcessResultWithMetrics{
|
return &ProcessResultWithMetrics{
|
||||||
ProcessResult: &ProcessResult{Error: err},
|
ProcessResult: &ProcessResult{Error: err},
|
||||||
|
|
@ -156,13 +157,12 @@ type txExecResult struct {
|
||||||
receipt *types.Receipt
|
receipt *types.Receipt
|
||||||
err error // non-EVM error which would render the block invalid
|
err error // non-EVM error which would render the block invalid
|
||||||
|
|
||||||
mutations *bal.StateDiff
|
accessList *bal.ConstructionBlockAccessList
|
||||||
stateReads *bal.StateAccesses
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// resultHandler polls until all transactions have finished executing and the
|
// resultHandler polls until all transactions have finished executing and the
|
||||||
// state root calculation is complete. The result is emitted on resCh.
|
// state root calculation is complete. The result is emitted on resCh.
|
||||||
func (p *ParallelStateProcessor) resultHandler(block *types.Block, preTxStateReads *bal.StateAccesses, postTxState *state.StateDB, tExecStart time.Time, txResCh <-chan txExecResult, stateRootCalcResCh <-chan stateRootCalculationResult, resCh chan *ProcessResultWithMetrics) {
|
func (p *ParallelStateProcessor) resultHandler(block *types.Block, preTxStateReads bal.StateAccesses, postTxState *state.StateDB, tExecStart time.Time, txResCh <-chan txExecResult, stateRootCalcResCh <-chan stateRootCalculationResult, resCh chan *ProcessResultWithMetrics) {
|
||||||
// 1. if the block has transactions, receive the execution results from all of them and return an error on resCh if any txs err'd
|
// 1. if the block has transactions, receive the execution results from all of them and return an error on resCh if any txs err'd
|
||||||
// 2. once all txs are executed, compute the post-tx state transition and produce the ProcessResult sending it on resCh (or an error if the post-tx state didn't match what is reported in the BAL)
|
// 2. once all txs are executed, compute the post-tx state transition and produce the ProcessResult sending it on resCh (or an error if the post-tx state didn't match what is reported in the BAL)
|
||||||
var receipts []*types.Receipt
|
var receipts []*types.Receipt
|
||||||
|
|
@ -172,7 +172,7 @@ func (p *ParallelStateProcessor) resultHandler(block *types.Block, preTxStateRea
|
||||||
var numTxComplete int
|
var numTxComplete int
|
||||||
|
|
||||||
allReads := make(bal.StateAccesses)
|
allReads := make(bal.StateAccesses)
|
||||||
allReads.Merge(*preTxStateReads)
|
allReads.Merge(preTxStateReads)
|
||||||
if len(block.Transactions()) > 0 {
|
if len(block.Transactions()) > 0 {
|
||||||
loop:
|
loop:
|
||||||
for {
|
for {
|
||||||
|
|
@ -186,7 +186,7 @@ func (p *ParallelStateProcessor) resultHandler(block *types.Block, preTxStateRea
|
||||||
execErr = err
|
execErr = err
|
||||||
} else {
|
} else {
|
||||||
receipts = append(receipts, res.receipt)
|
receipts = append(receipts, res.receipt)
|
||||||
allReads.Merge(*res.stateReads)
|
allReads.Merge(res.accessList.StateAccesses())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -243,49 +243,51 @@ func (p *ParallelStateProcessor) calcAndVerifyRoot(preState *state.StateDB, bloc
|
||||||
}
|
}
|
||||||
|
|
||||||
// execTx executes single transaction returning a result which includes state accessed/modified
|
// execTx executes single transaction returning a result which includes state accessed/modified
|
||||||
func (p *ParallelStateProcessor) execTx(block *types.Block, tx *types.Transaction, idx int, db *state.StateDB, signer types.Signer) *txExecResult {
|
func (p *ParallelStateProcessor) execTx(block *types.Block, tx *types.Transaction, txIdx int, db *state.StateDB, signer types.Signer) *txExecResult {
|
||||||
header := block.Header()
|
header := block.Header()
|
||||||
balTracer, hooks := NewBlockAccessListTracer()
|
balTracer, hooks := NewBlockAccessListTracer(txIdx + 1)
|
||||||
tracingStateDB := state.NewHookedState(db, hooks)
|
tracingStateDB := state.NewHookedState(db, hooks)
|
||||||
context := NewEVMBlockContext(header, p.chain, nil)
|
context := NewEVMBlockContext(header, p.chain, nil)
|
||||||
evm := vm.NewEVM(context, tracingStateDB, p.config, *p.vmCfg)
|
|
||||||
|
cfg := vm.Config{
|
||||||
|
Tracer: hooks,
|
||||||
|
NoBaseFee: p.vmCfg.NoBaseFee,
|
||||||
|
EnablePreimageRecording: p.vmCfg.EnablePreimageRecording,
|
||||||
|
ExtraEips: slices.Clone(p.vmCfg.ExtraEips),
|
||||||
|
StatelessSelfValidation: p.vmCfg.StatelessSelfValidation,
|
||||||
|
EnableWitnessStats: p.vmCfg.EnableWitnessStats,
|
||||||
|
}
|
||||||
|
cfg.Tracer = hooks
|
||||||
|
evm := vm.NewEVM(context, tracingStateDB, p.config, cfg)
|
||||||
|
|
||||||
msg, err := TransactionToMessage(tx, signer, header.BaseFee)
|
msg, err := TransactionToMessage(tx, signer, header.BaseFee)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err = fmt.Errorf("could not apply tx %d [%v]: %w", idx, tx.Hash().Hex(), err)
|
err = fmt.Errorf("could not apply tx %d [%v]: %w", txIdx, tx.Hash().Hex(), err)
|
||||||
return &txExecResult{err: err}
|
return &txExecResult{err: err}
|
||||||
}
|
}
|
||||||
sender, _ := types.Sender(signer, tx)
|
|
||||||
db.SetTxSender(sender)
|
|
||||||
db.SetTxContext(tx.Hash(), idx)
|
|
||||||
db.SetAccessListIndex(idx + 1)
|
|
||||||
|
|
||||||
evm.StateDB = db
|
|
||||||
gp := new(GasPool)
|
gp := new(GasPool)
|
||||||
gp.SetGas(block.GasLimit())
|
gp.SetGas(block.GasLimit())
|
||||||
var gasUsed uint64
|
var gasUsed uint64
|
||||||
mutatedState, accessedState, receipt, err := ApplyTransactionWithEVM(msg, gp, db, block.Number(), block.Hash(), context.Time, tx, &gasUsed, evm)
|
receipt, err := ApplyTransactionWithEVM(msg, gp, db, block.Number(), block.Hash(), context.Time, tx, &gasUsed, evm)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err := fmt.Errorf("could not apply tx %d [%v]: %w", idx, tx.Hash().Hex(), err)
|
err := fmt.Errorf("could not apply tx %d [%v]: %w", txIdx, tx.Hash().Hex(), err)
|
||||||
return &txExecResult{err: err}
|
return &txExecResult{err: err}
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := db.BlockAccessList().ValidateStateDiff(idx+1, balTracer.AccessList().DiffAt(uint16(idx)+1)); err != nil {
|
if err := db.BlockAccessList().ValidateStateDiff(txIdx+1, balTracer.AccessList().DiffAt(txIdx+1)); err != nil {
|
||||||
return &txExecResult{err: err}
|
return &txExecResult{err: err}
|
||||||
}
|
}
|
||||||
|
|
||||||
return &txExecResult{
|
return &txExecResult{
|
||||||
idx: idx,
|
idx: txIdx,
|
||||||
receipt: receipt,
|
receipt: receipt,
|
||||||
mutations: mutatedState,
|
accessList: balTracer.AccessList(),
|
||||||
stateReads: accessedState,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Process performs EVM execution and state root computation for a block which is known
|
// Process performs EVM execution and state root computation for a block which is known
|
||||||
// to contain an access list.
|
// to contain an access list.
|
||||||
func (p *ParallelStateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg vm.Config) (*ProcessResultWithMetrics, error) {
|
func (p *ParallelStateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg vm.Config) (*ProcessResultWithMetrics, error) {
|
||||||
fmt.Println("start ParallelProcess")
|
|
||||||
var (
|
var (
|
||||||
header = block.Header()
|
header = block.Header()
|
||||||
resCh = make(chan *ProcessResultWithMetrics)
|
resCh = make(chan *ProcessResultWithMetrics)
|
||||||
|
|
@ -310,30 +312,22 @@ func (p *ParallelStateProcessor) Process(block *types.Block, statedb *state.Stat
|
||||||
alReader := state.NewBALReader(block, statedb)
|
alReader := state.NewBALReader(block, statedb)
|
||||||
statedb.SetBlockAccessList(alReader)
|
statedb.SetBlockAccessList(alReader)
|
||||||
|
|
||||||
// Apply pre-execution system calls.
|
balTracer, hooks := NewBlockAccessListTracer(0)
|
||||||
var tracingStateDB = vm.StateDB(statedb)
|
tracingStateDB := state.NewHookedState(statedb, hooks)
|
||||||
if hooks := cfg.Tracer; hooks != nil {
|
// TODO: figure out exactly why we need to set the hooks on the TracingStateDB and the vm.Config
|
||||||
tracingStateDB = state.NewHookedState(statedb, hooks)
|
cfg.Tracer = hooks
|
||||||
}
|
|
||||||
context = NewEVMBlockContext(header, p.chain, nil)
|
context = NewEVMBlockContext(header, p.chain, nil)
|
||||||
evm := vm.NewEVM(context, tracingStateDB, p.config, cfg)
|
evm := vm.NewEVM(context, tracingStateDB, p.config, cfg)
|
||||||
|
|
||||||
// validate the correctness of pre-transaction execution state changes
|
|
||||||
computedPreTxDiff := &bal.StateDiff{make(map[common.Address]*bal.AccountState)}
|
|
||||||
preTxStateReads := make(bal.StateAccesses)
|
|
||||||
|
|
||||||
if beaconRoot := block.BeaconRoot(); beaconRoot != nil {
|
if beaconRoot := block.BeaconRoot(); beaconRoot != nil {
|
||||||
diff, reads := ProcessBeaconBlockRoot(*beaconRoot, evm)
|
ProcessBeaconBlockRoot(*beaconRoot, evm)
|
||||||
computedPreTxDiff.Merge(diff)
|
|
||||||
preTxStateReads.Merge(*reads)
|
|
||||||
}
|
}
|
||||||
if p.config.IsPrague(block.Number(), block.Time()) || p.config.IsVerkle(block.Number(), block.Time()) {
|
if p.config.IsPrague(block.Number(), block.Time()) || p.config.IsVerkle(block.Number(), block.Time()) {
|
||||||
diff, reads := ProcessParentBlockHash(block.ParentHash(), evm)
|
ProcessParentBlockHash(block.ParentHash(), evm)
|
||||||
computedPreTxDiff.Merge(diff)
|
|
||||||
preTxStateReads.Merge(*reads)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := statedb.BlockAccessList().ValidateStateDiff(0, computedPreTxDiff); err != nil {
|
if err := statedb.BlockAccessList().ValidateStateDiff(0, balTracer.AccessList().DiffAt(0)); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -345,8 +339,10 @@ func (p *ParallelStateProcessor) Process(block *types.Block, statedb *state.Stat
|
||||||
|
|
||||||
// execute transactions and state root calculation in parallel
|
// execute transactions and state root calculation in parallel
|
||||||
|
|
||||||
|
// TODO: figure out how to funnel the state reads from the bal tracer through to the post-block-exec state/slot read
|
||||||
|
// validation
|
||||||
tExecStart = time.Now()
|
tExecStart = time.Now()
|
||||||
go p.resultHandler(block, &preTxStateReads, postTxState, tExecStart, txResCh, rootCalcResultCh, resCh)
|
go p.resultHandler(block, balTracer.AccessList().StateAccesses(), postTxState, tExecStart, txResCh, rootCalcResultCh, resCh)
|
||||||
var workers errgroup.Group
|
var workers errgroup.Group
|
||||||
startingState := statedb.Copy()
|
startingState := statedb.Copy()
|
||||||
for i, tx := range block.Transactions() {
|
for i, tx := range block.Transactions() {
|
||||||
|
|
|
||||||
|
|
@ -1085,13 +1085,6 @@ func (s *StateDB) SetTxContext(thash common.Hash, ti int) {
|
||||||
s.balIndex = ti + 1
|
s.balIndex = ti + 1
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetAccessListIndex sets the current index that state mutations will
|
|
||||||
// be reported as in the BAL. It is only relevant if this StateDB instance
|
|
||||||
// is being used in the BAL construction path.
|
|
||||||
func (s *StateDB) SetAccessListIndex(idx int) {
|
|
||||||
s.balIndex = idx
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetTxSender sets the sender of the currently-executing transaction.
|
// SetTxSender sets the sender of the currently-executing transaction.
|
||||||
func (s *StateDB) SetTxSender(sender common.Address) {
|
func (s *StateDB) SetTxSender(sender common.Address) {
|
||||||
s.sender = sender
|
s.sender = sender
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,6 @@ package core
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/ethereum/go-ethereum/core/types/bal"
|
|
||||||
"math/big"
|
"math/big"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
|
|
@ -98,7 +97,7 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg
|
||||||
}
|
}
|
||||||
statedb.SetTxContext(tx.Hash(), i)
|
statedb.SetTxContext(tx.Hash(), i)
|
||||||
|
|
||||||
_, _, receipt, err := ApplyTransactionWithEVM(msg, gp, statedb, blockNumber, blockHash, context.Time, tx, usedGas, evm)
|
receipt, err := ApplyTransactionWithEVM(msg, gp, statedb, blockNumber, blockHash, context.Time, tx, usedGas, evm)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("could not apply tx %d [%v]: %w", i, tx.Hash().Hex(), err)
|
return nil, fmt.Errorf("could not apply tx %d [%v]: %w", i, tx.Hash().Hex(), err)
|
||||||
}
|
}
|
||||||
|
|
@ -115,11 +114,11 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg
|
||||||
return nil, fmt.Errorf("failed to parse deposit logs: %w", err)
|
return nil, fmt.Errorf("failed to parse deposit logs: %w", err)
|
||||||
}
|
}
|
||||||
// EIP-7002
|
// EIP-7002
|
||||||
if _, _, err := ProcessWithdrawalQueue(&requests, evm); err != nil {
|
if err := ProcessWithdrawalQueue(&requests, evm); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
// EIP-7251
|
// EIP-7251
|
||||||
if _, _, err := ProcessConsolidationQueue(&requests, evm); err != nil {
|
if err := ProcessConsolidationQueue(&requests, evm); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -138,7 +137,7 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg
|
||||||
// ApplyTransactionWithEVM attempts to apply a transaction to the given state database
|
// ApplyTransactionWithEVM attempts to apply a transaction to the given state database
|
||||||
// and uses the input parameters for its environment similar to ApplyTransaction. However,
|
// and uses the input parameters for its environment similar to ApplyTransaction. However,
|
||||||
// this method takes an already created EVM instance as input.
|
// this method takes an already created EVM instance as input.
|
||||||
func ApplyTransactionWithEVM(msg *Message, gp *GasPool, statedb *state.StateDB, blockNumber *big.Int, blockHash common.Hash, blockTime uint64, tx *types.Transaction, usedGas *uint64, evm *vm.EVM) (mutatedState *bal.StateDiff, accessedState *bal.StateAccesses, receipt *types.Receipt, err error) {
|
func ApplyTransactionWithEVM(msg *Message, gp *GasPool, statedb *state.StateDB, blockNumber *big.Int, blockHash common.Hash, blockTime uint64, tx *types.Transaction, usedGas *uint64, evm *vm.EVM) (receipt *types.Receipt, err error) {
|
||||||
if hooks := evm.Config.Tracer; hooks != nil {
|
if hooks := evm.Config.Tracer; hooks != nil {
|
||||||
if hooks.OnTxStart != nil {
|
if hooks.OnTxStart != nil {
|
||||||
hooks.OnTxStart(evm.GetVMContext(), tx, msg.From)
|
hooks.OnTxStart(evm.GetVMContext(), tx, msg.From)
|
||||||
|
|
@ -150,13 +149,13 @@ func ApplyTransactionWithEVM(msg *Message, gp *GasPool, statedb *state.StateDB,
|
||||||
// Apply the transaction to the current state (included in the env).
|
// Apply the transaction to the current state (included in the env).
|
||||||
result, err := ApplyMessage(evm, msg, gp)
|
result, err := ApplyMessage(evm, msg, gp)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update the state with pending changes.
|
// Update the state with pending changes.
|
||||||
var root []byte
|
var root []byte
|
||||||
if evm.ChainConfig().IsByzantium(blockNumber) {
|
if evm.ChainConfig().IsByzantium(blockNumber) {
|
||||||
mutatedState, accessedState = evm.StateDB.Finalise(true)
|
evm.StateDB.Finalise(true)
|
||||||
} else {
|
} else {
|
||||||
root = statedb.IntermediateRoot(evm.ChainConfig().IsEIP158(blockNumber)).Bytes()
|
root = statedb.IntermediateRoot(evm.ChainConfig().IsEIP158(blockNumber)).Bytes()
|
||||||
}
|
}
|
||||||
|
|
@ -167,7 +166,7 @@ func ApplyTransactionWithEVM(msg *Message, gp *GasPool, statedb *state.StateDB,
|
||||||
if statedb.Database().TrieDB().IsVerkle() {
|
if statedb.Database().TrieDB().IsVerkle() {
|
||||||
statedb.AccessEvents().Merge(evm.AccessEvents)
|
statedb.AccessEvents().Merge(evm.AccessEvents)
|
||||||
}
|
}
|
||||||
return mutatedState, accessedState, MakeReceipt(evm, result, statedb, blockNumber, blockHash, blockTime, tx, *usedGas, root), nil
|
return MakeReceipt(evm, result, statedb, blockNumber, blockHash, blockTime, tx, *usedGas, root), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// MakeReceipt generates the receipt object for a transaction given its execution result.
|
// MakeReceipt generates the receipt object for a transaction given its execution result.
|
||||||
|
|
@ -212,13 +211,13 @@ func ApplyTransaction(evm *vm.EVM, gp *GasPool, statedb *state.StateDB, header *
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
// Create a new context to be used in the EVM environment
|
// Create a new context to be used in the EVM environment
|
||||||
_, _, receipts, err := ApplyTransactionWithEVM(msg, gp, statedb, header.Number, header.Hash(), header.Time, tx, usedGas, evm)
|
receipts, err := ApplyTransactionWithEVM(msg, gp, statedb, header.Number, header.Hash(), header.Time, tx, usedGas, evm)
|
||||||
return receipts, err
|
return receipts, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// ProcessBeaconBlockRoot applies the EIP-4788 system call to the beacon block root
|
// ProcessBeaconBlockRoot applies the EIP-4788 system call to the beacon block root
|
||||||
// contract. This method is exported to be used in tests.
|
// contract. This method is exported to be used in tests.
|
||||||
func ProcessBeaconBlockRoot(beaconRoot common.Hash, evm *vm.EVM) (*bal.StateDiff, *bal.StateAccesses) {
|
func ProcessBeaconBlockRoot(beaconRoot common.Hash, evm *vm.EVM) {
|
||||||
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 {
|
||||||
|
|
@ -237,12 +236,12 @@ func ProcessBeaconBlockRoot(beaconRoot common.Hash, evm *vm.EVM) (*bal.StateDiff
|
||||||
evm.SetTxContext(NewEVMTxContext(msg))
|
evm.SetTxContext(NewEVMTxContext(msg))
|
||||||
evm.StateDB.AddAddressToAccessList(params.BeaconRootsAddress)
|
evm.StateDB.AddAddressToAccessList(params.BeaconRootsAddress)
|
||||||
_, _, _ = evm.Call(msg.From, *msg.To, msg.Data, 30_000_000, common.U2560)
|
_, _, _ = evm.Call(msg.From, *msg.To, msg.Data, 30_000_000, common.U2560)
|
||||||
return evm.StateDB.Finalise(true)
|
evm.StateDB.Finalise(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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/7709.
|
// as per EIP-2935/7709.
|
||||||
func ProcessParentBlockHash(prevHash common.Hash, evm *vm.EVM) (*bal.StateDiff, *bal.StateAccesses) {
|
func ProcessParentBlockHash(prevHash common.Hash, evm *vm.EVM) {
|
||||||
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 {
|
||||||
|
|
@ -267,22 +266,22 @@ func ProcessParentBlockHash(prevHash common.Hash, evm *vm.EVM) (*bal.StateDiff,
|
||||||
if evm.StateDB.AccessEvents() != nil {
|
if evm.StateDB.AccessEvents() != nil {
|
||||||
evm.StateDB.AccessEvents().Merge(evm.AccessEvents)
|
evm.StateDB.AccessEvents().Merge(evm.AccessEvents)
|
||||||
}
|
}
|
||||||
return evm.StateDB.Finalise(true)
|
evm.StateDB.Finalise(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ProcessWithdrawalQueue calls the EIP-7002 withdrawal queue contract.
|
// ProcessWithdrawalQueue calls the EIP-7002 withdrawal queue contract.
|
||||||
// It returns the opaque request data returned by the contract.
|
// It returns the opaque request data returned by the contract.
|
||||||
func ProcessWithdrawalQueue(requests *[][]byte, evm *vm.EVM) (*bal.StateDiff, *bal.StateAccesses, error) {
|
func ProcessWithdrawalQueue(requests *[][]byte, evm *vm.EVM) error {
|
||||||
return processRequestsSystemCall(requests, evm, 0x01, params.WithdrawalQueueAddress)
|
return processRequestsSystemCall(requests, evm, 0x01, params.WithdrawalQueueAddress)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ProcessConsolidationQueue calls the EIP-7251 consolidation queue contract.
|
// ProcessConsolidationQueue calls the EIP-7251 consolidation queue contract.
|
||||||
// It returns the opaque request data returned by the contract.
|
// It returns the opaque request data returned by the contract.
|
||||||
func ProcessConsolidationQueue(requests *[][]byte, evm *vm.EVM) (*bal.StateDiff, *bal.StateAccesses, error) {
|
func ProcessConsolidationQueue(requests *[][]byte, evm *vm.EVM) error {
|
||||||
return processRequestsSystemCall(requests, evm, 0x02, params.ConsolidationQueueAddress)
|
return processRequestsSystemCall(requests, evm, 0x02, params.ConsolidationQueueAddress)
|
||||||
}
|
}
|
||||||
|
|
||||||
func processRequestsSystemCall(requests *[][]byte, evm *vm.EVM, requestType byte, addr common.Address) (*bal.StateDiff, *bal.StateAccesses, error) {
|
func processRequestsSystemCall(requests *[][]byte, evm *vm.EVM, requestType byte, addr common.Address) error {
|
||||||
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 {
|
||||||
|
|
@ -300,19 +299,19 @@ func processRequestsSystemCall(requests *[][]byte, evm *vm.EVM, requestType byte
|
||||||
evm.SetTxContext(NewEVMTxContext(msg))
|
evm.SetTxContext(NewEVMTxContext(msg))
|
||||||
evm.StateDB.AddAddressToAccessList(addr)
|
evm.StateDB.AddAddressToAccessList(addr)
|
||||||
ret, _, err := evm.Call(msg.From, *msg.To, msg.Data, 30_000_000, common.U2560)
|
ret, _, err := evm.Call(msg.From, *msg.To, msg.Data, 30_000_000, common.U2560)
|
||||||
diff, accesses := evm.StateDB.Finalise(true)
|
evm.StateDB.Finalise(true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, fmt.Errorf("system call failed to execute: %v", err)
|
return fmt.Errorf("system call failed to execute: %v", err)
|
||||||
}
|
}
|
||||||
if len(ret) == 0 {
|
if len(ret) == 0 {
|
||||||
return diff, accesses, nil // skip empty output
|
return nil // skip empty output
|
||||||
}
|
}
|
||||||
// Append prefixed requestsData to the requests list.
|
// Append prefixed requestsData to the requests list.
|
||||||
requestsData := make([]byte, len(ret)+1)
|
requestsData := make([]byte, len(ret)+1)
|
||||||
requestsData[0] = requestType
|
requestsData[0] = requestType
|
||||||
copy(requestsData[1:], ret)
|
copy(requestsData[1:], ret)
|
||||||
*requests = append(*requests, requestsData)
|
*requests = append(*requests, requestsData)
|
||||||
return diff, accesses, nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
var depositTopic = common.HexToHash("0x649bbc62d0e31342afea4e5cd82d4049e7e1ee912fc0889aa790803be39038c5")
|
var depositTopic = common.HexToHash("0x649bbc62d0e31342afea4e5cd82d4049e7e1ee912fc0889aa790803be39038c5")
|
||||||
|
|
|
||||||
|
|
@ -105,9 +105,11 @@ func NewConstructionBlockAccessList() *ConstructionBlockAccessList {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *ConstructionBlockAccessList) DiffAt(idx uint16) *StateDiff {
|
func (c *ConstructionBlockAccessList) DiffAt(i int) *StateDiff {
|
||||||
res := &StateDiff{make(map[common.Address]*AccountState)}
|
res := &StateDiff{make(map[common.Address]*AccountState)}
|
||||||
|
|
||||||
|
idx := uint16(i)
|
||||||
|
|
||||||
for addr, account := range c.Accounts {
|
for addr, account := range c.Accounts {
|
||||||
accountState := &AccountState{}
|
accountState := &AccountState{}
|
||||||
if balance, ok := account.BalanceChanges[idx]; ok {
|
if balance, ok := account.BalanceChanges[idx]; ok {
|
||||||
|
|
@ -127,11 +129,27 @@ func (c *ConstructionBlockAccessList) DiffAt(idx uint16) *StateDiff {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if len(storageWrites) > 0 {
|
if len(storageWrites) > 0 {
|
||||||
accountState.StorageWrites = make(map[common.Hash]common.Hash)
|
accountState.StorageWrites = storageWrites
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if !accountState.Empty() {
|
||||||
res.Mutations[addr] = accountState
|
res.Mutations[addr] = accountState
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *ConstructionBlockAccessList) StateAccesses() StateAccesses {
|
||||||
|
res := make(StateAccesses)
|
||||||
|
for addr, acct := range c.Accounts {
|
||||||
|
if len(acct.StorageReads) > 0 {
|
||||||
|
res[addr] = acct.StorageReads
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if len(acct.NonceChanges) == 0 && len(acct.BalanceChanges) == 0 && len(acct.StorageWrites) == 0 && len(acct.CodeChanges) == 0 {
|
||||||
|
res[addr] = make(map[common.Hash]struct{})
|
||||||
|
}
|
||||||
|
}
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -317,6 +335,10 @@ type AccountState struct {
|
||||||
StorageWrites map[common.Hash]common.Hash `json:"StorageWrites,omitempty"`
|
StorageWrites map[common.Hash]common.Hash `json:"StorageWrites,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (a *AccountState) Empty() bool {
|
||||||
|
return a.Balance == nil && a.Nonce == nil && a.Code == nil && len(a.StorageWrites) == 0
|
||||||
|
}
|
||||||
|
|
||||||
func (a *AccountState) String() string {
|
func (a *AccountState) String() string {
|
||||||
var res bytes.Buffer
|
var res bytes.Buffer
|
||||||
enc := json.NewEncoder(&res)
|
enc := json.NewEncoder(&res)
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue