From fe6bce3769dd8e1e430e84132beea61d7df5e080 Mon Sep 17 00:00:00 2001 From: Jared Wasinger Date: Wed, 1 Oct 2025 12:37:51 +0800 Subject: [PATCH] fix a lot of tests --- core/block_access_list_creation.go | 14 +--- core/blockchain.go | 7 +- core/chain_makers.go | 4 +- core/parallel_state_processor.go | 108 ++++++++++++++--------------- core/state/statedb.go | 7 -- core/state_processor.go | 39 +++++------ core/types/bal/bal.go | 28 +++++++- 7 files changed, 101 insertions(+), 106 deletions(-) diff --git a/core/block_access_list_creation.go b/core/block_access_list_creation.go index e6f5bac856..e6179422b7 100644 --- a/core/block_access_list_creation.go +++ b/core/block_access_list_creation.go @@ -1,7 +1,6 @@ package core import ( - "fmt" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/tracing" "github.com/ethereum/go-ethereum/core/types" @@ -27,10 +26,10 @@ type BlockAccessListTracer struct { } // NewBlockAccessListTracer returns an BlockAccessListTracer and a set of hooks -func NewBlockAccessListTracer() (*BlockAccessListTracer, *tracing.Hooks) { +func NewBlockAccessListTracer(startIdx int) (*BlockAccessListTracer, *tracing.Hooks) { balTracer := &BlockAccessListTracer{ callAccessLists: []*bal.ConstructionBlockAccessList{bal.NewConstructionBlockAccessList()}, - txIdx: 0, + txIdx: uint16(startIdx), } hooks := &tracing.Hooks{ OnTxEnd: balTracer.TxEndHook, @@ -52,11 +51,6 @@ func (a *BlockAccessListTracer) AccessList() *bal.ConstructionBlockAccessList { 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) { a.txIdx++ } @@ -80,11 +74,8 @@ func (a *BlockAccessListTracer) OnExit(depth int, output []byte, gasUsed uint64, parentAccessList := a.callAccessLists[len(a.callAccessLists)-2] scopeAccessList := a.callAccessLists[len(a.callAccessLists)-1] if reverted { - fmt.Println("exit reverted") parentAccessList.MergeReads(scopeAccessList) } else { - fmt.Println("exit normal") - fmt.Printf("scope access list is\n%s\n", scopeAccessList.ToEncodingObj().String()) parentAccessList.Merge(scopeAccessList) } @@ -112,7 +103,6 @@ func (a *BlockAccessListTracer) OnColdStorageRead(addr common.Address, key commo } func (a *BlockAccessListTracer) OnColdAccountRead(addr common.Address) { - fmt.Printf("cold account read %x\n", addr) a.callAccessLists[len(a.callAccessLists)-1].AccountRead(addr) } diff --git a/core/blockchain.go b/core/blockchain.go index 898be9f6cc..40e6b3cff7 100644 --- a/core/blockchain.go +++ b/core/blockchain.go @@ -2062,11 +2062,6 @@ func (bc *BlockChain) ProcessBlock(parentRoot common.Hash, block *types.Block, s }(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 // while processing transactions. Before Byzantium the prefetcher is mostly // 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 // Process block using the parent state as reference point if constructBALForTesting { - balTracer, bc.cfg.VmConfig.Tracer = NewBlockAccessListTracer() + balTracer, bc.cfg.VmConfig.Tracer = NewBlockAccessListTracer(0) } // Process block using the parent state as reference point pstart := time.Now() diff --git a/core/chain_makers.go b/core/chain_makers.go index 32c444dee7..af55716cca 100644 --- a/core/chain_makers.go +++ b/core/chain_makers.go @@ -328,11 +328,11 @@ func (b *BlockGen) collectRequests(readonly bool) (requests [][]byte) { blockContext := NewEVMBlockContext(b.header, b.cm, &b.header.Coinbase) evm := vm.NewEVM(blockContext, statedb, b.cm.config, vm.Config{}) // 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)) } // 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)) } } diff --git a/core/parallel_state_processor.go b/core/parallel_state_processor.go index e39d708bdb..7da5a0752a 100644 --- a/core/parallel_state_processor.go +++ b/core/parallel_state_processor.go @@ -58,13 +58,20 @@ func (p *ParallelStateProcessor) prepareExecResult(block *types.Block, allStateR tPostprocessStart := time.Now() header := block.Header() - postTxState.SetAccessListIndex(len(block.Transactions()) + 1) - var tracingStateDB = vm.StateDB(postTxState) - if hooks := p.vmCfg.Tracer; hooks != nil { - tracingStateDB = state.NewHookedState(postTxState, hooks) - } + balTracer, hooks := NewBlockAccessListTracer(len(block.Transactions()) + 1) + tracingStateDB := state.NewHookedState(postTxState, hooks) 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 // 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...) } - computedDiff := &bal.StateDiff{make(map[common.Address]*bal.AccountState)} - computedAccesses := make(bal.StateAccesses) - // Read requests if Prague is enabled. if p.config.IsPrague(block.Number(), block.Time()) { requests = [][]byte{} @@ -99,38 +103,35 @@ func (p *ParallelStateProcessor) prepareExecResult(block *types.Block, allStateR } // EIP-7002 - diff, accesses, err := ProcessWithdrawalQueue(&requests, evm) + err := ProcessWithdrawalQueue(&requests, evm) if err != nil { return &ProcessResultWithMetrics{ ProcessResult: &ProcessResult{Error: err}, } } - computedDiff = diff - computedAccesses = *accesses // EIP-7251 - diff, accesses, err = ProcessConsolidationQueue(&requests, evm) + err = ProcessConsolidationQueue(&requests, evm) if err != nil { return &ProcessResultWithMetrics{ ProcessResult: &ProcessResult{Error: err}, } } - computedDiff.Merge(diff) - computedAccesses.Merge(*accesses) } // Finalize the block, applying any consensus engine specific extras (e.g. block rewards) p.chain.engine.Finalize(p.chain, header, tracingStateDB, block.Body()) // invoke Finalise so that withdrawals are accounted for in the state diff 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{ ProcessResult: &ProcessResult{Error: err}, } } - allStateReads.Merge(computedAccesses) if err := postTxState.BlockAccessList().ValidateStateReads(*allStateReads); err != nil { return &ProcessResultWithMetrics{ ProcessResult: &ProcessResult{Error: err}, @@ -156,13 +157,12 @@ type txExecResult struct { receipt *types.Receipt err error // non-EVM error which would render the block invalid - mutations *bal.StateDiff - stateReads *bal.StateAccesses + accessList *bal.ConstructionBlockAccessList } // resultHandler polls until all transactions have finished executing and the // 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 // 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 @@ -172,7 +172,7 @@ func (p *ParallelStateProcessor) resultHandler(block *types.Block, preTxStateRea var numTxComplete int allReads := make(bal.StateAccesses) - allReads.Merge(*preTxStateReads) + allReads.Merge(preTxStateReads) if len(block.Transactions()) > 0 { loop: for { @@ -186,7 +186,7 @@ func (p *ParallelStateProcessor) resultHandler(block *types.Block, preTxStateRea execErr = err } else { 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 -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() - balTracer, hooks := NewBlockAccessListTracer() + balTracer, hooks := NewBlockAccessListTracer(txIdx + 1) tracingStateDB := state.NewHookedState(db, hooks) 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) 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} } - sender, _ := types.Sender(signer, tx) - db.SetTxSender(sender) - db.SetTxContext(tx.Hash(), idx) - db.SetAccessListIndex(idx + 1) - - evm.StateDB = db gp := new(GasPool) gp.SetGas(block.GasLimit()) 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 { - 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} } - 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{ - idx: idx, + idx: txIdx, receipt: receipt, - mutations: mutatedState, - stateReads: accessedState, + accessList: balTracer.AccessList(), } } // Process performs EVM execution and state root computation for a block which is known // to contain an access list. func (p *ParallelStateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg vm.Config) (*ProcessResultWithMetrics, error) { - fmt.Println("start ParallelProcess") var ( header = block.Header() resCh = make(chan *ProcessResultWithMetrics) @@ -310,30 +312,22 @@ func (p *ParallelStateProcessor) Process(block *types.Block, statedb *state.Stat alReader := state.NewBALReader(block, statedb) statedb.SetBlockAccessList(alReader) - // Apply pre-execution system calls. - var tracingStateDB = vm.StateDB(statedb) - if hooks := cfg.Tracer; hooks != nil { - tracingStateDB = state.NewHookedState(statedb, hooks) - } + balTracer, hooks := NewBlockAccessListTracer(0) + tracingStateDB := state.NewHookedState(statedb, hooks) + // TODO: figure out exactly why we need to set the hooks on the TracingStateDB and the vm.Config + cfg.Tracer = hooks + context = NewEVMBlockContext(header, p.chain, nil) 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 { - diff, reads := ProcessBeaconBlockRoot(*beaconRoot, evm) - computedPreTxDiff.Merge(diff) - preTxStateReads.Merge(*reads) + ProcessBeaconBlockRoot(*beaconRoot, evm) } if p.config.IsPrague(block.Number(), block.Time()) || p.config.IsVerkle(block.Number(), block.Time()) { - diff, reads := ProcessParentBlockHash(block.ParentHash(), evm) - computedPreTxDiff.Merge(diff) - preTxStateReads.Merge(*reads) + ProcessParentBlockHash(block.ParentHash(), evm) } - if err := statedb.BlockAccessList().ValidateStateDiff(0, computedPreTxDiff); err != nil { + if err := statedb.BlockAccessList().ValidateStateDiff(0, balTracer.AccessList().DiffAt(0)); err != nil { 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 + // 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() - 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 startingState := statedb.Copy() for i, tx := range block.Transactions() { diff --git a/core/state/statedb.go b/core/state/statedb.go index 90d9e343e2..df4217891e 100644 --- a/core/state/statedb.go +++ b/core/state/statedb.go @@ -1085,13 +1085,6 @@ func (s *StateDB) SetTxContext(thash common.Hash, ti int) { 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. func (s *StateDB) SetTxSender(sender common.Address) { s.sender = sender diff --git a/core/state_processor.go b/core/state_processor.go index 7f7352222a..9783fa2c7f 100644 --- a/core/state_processor.go +++ b/core/state_processor.go @@ -18,7 +18,6 @@ package core import ( "fmt" - "github.com/ethereum/go-ethereum/core/types/bal" "math/big" "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) - _, _, 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 { 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) } // EIP-7002 - if _, _, err := ProcessWithdrawalQueue(&requests, evm); err != nil { + if err := ProcessWithdrawalQueue(&requests, evm); err != nil { return nil, err } // EIP-7251 - if _, _, err := ProcessConsolidationQueue(&requests, evm); err != nil { + if err := ProcessConsolidationQueue(&requests, evm); err != nil { 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 // and uses the input parameters for its environment similar to ApplyTransaction. However, // 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.OnTxStart != nil { 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). result, err := ApplyMessage(evm, msg, gp) if err != nil { - return nil, nil, nil, err + return nil, err } // Update the state with pending changes. var root []byte if evm.ChainConfig().IsByzantium(blockNumber) { - mutatedState, accessedState = evm.StateDB.Finalise(true) + evm.StateDB.Finalise(true) } else { 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() { 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. @@ -212,13 +211,13 @@ func ApplyTransaction(evm *vm.EVM, gp *GasPool, statedb *state.StateDB, header * return nil, err } // 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 } // ProcessBeaconBlockRoot applies the EIP-4788 system call to the beacon block root // 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 { onSystemCallStart(tracer, evm.GetVMContext()) if tracer.OnSystemCallEnd != nil { @@ -237,12 +236,12 @@ func ProcessBeaconBlockRoot(beaconRoot common.Hash, evm *vm.EVM) (*bal.StateDiff evm.SetTxContext(NewEVMTxContext(msg)) evm.StateDB.AddAddressToAccessList(params.BeaconRootsAddress) _, _, _ = 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 // 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 { onSystemCallStart(tracer, evm.GetVMContext()) if tracer.OnSystemCallEnd != nil { @@ -267,22 +266,22 @@ func ProcessParentBlockHash(prevHash common.Hash, evm *vm.EVM) (*bal.StateDiff, if evm.StateDB.AccessEvents() != nil { evm.StateDB.AccessEvents().Merge(evm.AccessEvents) } - return evm.StateDB.Finalise(true) + evm.StateDB.Finalise(true) } // ProcessWithdrawalQueue calls the EIP-7002 withdrawal queue 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) } // ProcessConsolidationQueue calls the EIP-7251 consolidation queue 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) } -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 { onSystemCallStart(tracer, evm.GetVMContext()) if tracer.OnSystemCallEnd != nil { @@ -300,19 +299,19 @@ func processRequestsSystemCall(requests *[][]byte, evm *vm.EVM, requestType byte evm.SetTxContext(NewEVMTxContext(msg)) evm.StateDB.AddAddressToAccessList(addr) 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 { - 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 { - return diff, accesses, nil // skip empty output + return nil // skip empty output } // Append prefixed requestsData to the requests list. requestsData := make([]byte, len(ret)+1) requestsData[0] = requestType copy(requestsData[1:], ret) *requests = append(*requests, requestsData) - return diff, accesses, nil + return nil } var depositTopic = common.HexToHash("0x649bbc62d0e31342afea4e5cd82d4049e7e1ee912fc0889aa790803be39038c5") diff --git a/core/types/bal/bal.go b/core/types/bal/bal.go index 29139f2164..d0546cd9c3 100644 --- a/core/types/bal/bal.go +++ b/core/types/bal/bal.go @@ -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)} + idx := uint16(i) + for addr, account := range c.Accounts { accountState := &AccountState{} if balance, ok := account.BalanceChanges[idx]; ok { @@ -127,10 +129,26 @@ func (c *ConstructionBlockAccessList) DiffAt(idx uint16) *StateDiff { } } if len(storageWrites) > 0 { - accountState.StorageWrites = make(map[common.Hash]common.Hash) + accountState.StorageWrites = storageWrites } - res.Mutations[addr] = accountState + if !accountState.Empty() { + 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 } @@ -317,6 +335,10 @@ type AccountState struct { 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 { var res bytes.Buffer enc := json.NewEncoder(&res)