fix(eip-7778): use separate gas accumulators in parallel processor

The parallel state processor was using receipt.GasUsed (pre-refund,
MaxUsedGas for Amsterdam) for both CumulativeGasUsed and block gas.
This caused receipt root mismatches because CumulativeGasUsed must
be post-refund.

The fix:
- cumulativeGasUsed: accumulates receipt.CumulativeGasUsed (post-refund
  from execTx) for proper receipt CumulativeGasUsed
- blockGasUsed: accumulates receipt.GasUsed (pre-refund for Amsterdam)
  for block header GasUsed and gas limit validation

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
qu0b 2026-02-05 13:31:10 +00:00
parent 97d384f1bb
commit aec81c69f5

View file

@ -77,12 +77,22 @@ func (p *ParallelStateProcessor) prepareExecResult(block *types.Block, allStateR
return cmp.Compare(a.TransactionIndex, b.TransactionIndex) return cmp.Compare(a.TransactionIndex, b.TransactionIndex)
}) })
var cumulativeGasUsed uint64 var (
// cumulativeGasUsed tracks post-refund gas for receipt.CumulativeGasUsed
cumulativeGasUsed uint64
// blockGasUsed tracks pre-refund gas (receipt.GasUsed = MaxUsedGas for Amsterdam)
// for block header and gas limit validation per EIP-7778
blockGasUsed uint64
)
var allLogs []*types.Log var allLogs []*types.Log
for _, receipt := range receipts { for _, receipt := range receipts {
receipt.CumulativeGasUsed = cumulativeGasUsed + receipt.GasUsed // receipt.CumulativeGasUsed holds this tx's post-refund gas (result.UsedGas)
cumulativeGasUsed += receipt.GasUsed // since execTx called ApplyTransactionWithEVM with cumulativeGas=0
if receipt.CumulativeGasUsed > header.GasLimit { cumulativeGasUsed += receipt.CumulativeGasUsed
receipt.CumulativeGasUsed = cumulativeGasUsed
// receipt.GasUsed is pre-refund (MaxUsedGas for Amsterdam) for block accounting
blockGasUsed += receipt.GasUsed
if blockGasUsed > header.GasLimit {
return &ProcessResultWithMetrics{ return &ProcessResultWithMetrics{
ProcessResult: &ProcessResult{Error: fmt.Errorf("gas limit exceeded")}, ProcessResult: &ProcessResult{Error: fmt.Errorf("gas limit exceeded")},
} }
@ -148,7 +158,7 @@ func (p *ParallelStateProcessor) prepareExecResult(block *types.Block, allStateR
Receipts: receipts, Receipts: receipts,
Requests: requests, Requests: requests,
Logs: allLogs, Logs: allLogs,
GasUsed: cumulativeGasUsed, GasUsed: blockGasUsed,
}, },
PostProcessTime: tPostprocess, PostProcessTime: tPostprocess,
ExecTime: tExec, ExecTime: tExec,