eth: release state on error in stateAtTransaction

Call the state release function on ApplyMessage failure and when the
requested transaction index is out of range, avoiding leaked state
snapshots on error paths.
This commit is contained in:
Weixie Cui 2026-07-09 20:00:00 +08:00
parent 896a4ab7c6
commit 89d231e4d1

View file

@ -267,11 +267,13 @@ func (eth *Ethereum) stateAtTransaction(ctx context.Context, block *types.Block,
// Not yet the searched for transaction, execute on top of the current state // Not yet the searched for transaction, execute on top of the current state
statedb.SetTxContext(tx.Hash(), idx, uint32(idx+1)) statedb.SetTxContext(tx.Hash(), idx, uint32(idx+1))
if _, err := core.ApplyMessage(evm, msg, nil); err != nil { if _, err := core.ApplyMessage(evm, msg, nil); err != nil {
release()
return nil, vm.BlockContext{}, nil, nil, fmt.Errorf("transaction %#x failed: %v", tx.Hash(), err) return nil, vm.BlockContext{}, nil, nil, fmt.Errorf("transaction %#x failed: %v", tx.Hash(), err)
} }
// Ensure any modifications are committed to the state // Ensure any modifications are committed to the state
// Only delete empty objects if EIP158/161 (a.k.a Spurious Dragon) is in effect // Only delete empty objects if EIP158/161 (a.k.a Spurious Dragon) is in effect
statedb.Finalise(evm.ChainConfig().IsEIP158(block.Number())) statedb.Finalise(evm.ChainConfig().IsEIP158(block.Number()))
} }
release()
return nil, vm.BlockContext{}, nil, nil, fmt.Errorf("transaction index %d out of range for block %#x", txIndex, block.Hash()) return nil, vm.BlockContext{}, nil, nil, fmt.Errorf("transaction index %d out of range for block %#x", txIndex, block.Hash())
} }