Skip to content

Commit 7fe6eb0

Browse files
feat(eth/tracers): Allow header overwrites (#295)
## Why this should be merged The `types.Header` must be altered in SAE to return the appropriate state root and base fee, so that the API can accurately find the these values for execution. However, this will modify the block hash (since this is found runtime in the header), so this provides the option to overwrite the block hash via an optional interface. Instead of getting the block hash from the header, an implementer can retrieve the block again, and use the original hash instead. ## How this works Use optional interface for every call of `block.Hash()` ## How this was tested New UT --------- Signed-off-by: Tsvetan Dimitrov (tsvetan.dimitrov@avalabs.org) Co-authored-by: Tsvetan Dimitrov <tsvetan.dimitrov23@gmail.com>
1 parent 90e9e9d commit 7fe6eb0

3 files changed

Lines changed: 411 additions & 6 deletions

File tree

eth/tracers/api.go

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,7 @@ func (api *API) blockByNumberAndHash(ctx context.Context, number rpc.BlockNumber
141141
if err != nil {
142142
return nil, err
143143
}
144-
if block.Hash() == hash {
144+
if api.blockHash(block) == hash {
145145
return block, nil
146146
}
147147
return api.blockByHash(ctx, hash)
@@ -272,7 +272,7 @@ func (api *API) traceChain(start, end *types.Block, config *TraceConfig, closed
272272
for i, tx := range task.block.Transactions() {
273273
msg, _ := core.TransactionToMessage(tx, signer, task.block.BaseFee())
274274
txctx := &Context{
275-
BlockHash: task.block.Hash(),
275+
BlockHash: api.blockHash(task.block),
276276
BlockNumber: task.block.Number(),
277277
TxIndex: i,
278278
TxHash: tx.Hash(),
@@ -407,7 +407,7 @@ func (api *API) traceChain(start, end *types.Block, config *TraceConfig, closed
407407
// Queue up next received result
408408
result := &blockTraceResult{
409409
Block: hexutil.Uint64(res.block.NumberU64()),
410-
Hash: res.block.Hash(),
410+
Hash: api.blockHash(res.block),
411411
Traces: res.results,
412412
}
413413
done[uint64(result.Block)] = result
@@ -597,7 +597,7 @@ func (api *API) traceBlock(ctx context.Context, block *types.Block, config *Trac
597597
// Native tracers have low overhead
598598
var (
599599
txs = block.Transactions()
600-
blockHash = block.Hash()
600+
blockHash = api.blockHash(block)
601601
is158 = api.backend.ChainConfig().IsEIP158(block.Number())
602602
blockCtx = core.NewEVMBlockContext(block.Header(), api.chainContext(ctx), nil)
603603
signer = types.MakeSigner(api.backend.ChainConfig(), block.Number(), block.Time())
@@ -631,7 +631,7 @@ func (api *API) traceBlockParallel(ctx context.Context, block *types.Block, stat
631631
// Execute all the transaction contained within the block concurrently
632632
var (
633633
txs = block.Transactions()
634-
blockHash = block.Hash()
634+
blockHash = api.blockHash(block)
635635
blockCtx = core.NewEVMBlockContext(block.Header(), api.chainContext(ctx), nil)
636636
signer = types.MakeSigner(api.backend.ChainConfig(), block.Number(), block.Time())
637637
results = make([]*txTraceResult, len(txs))
@@ -769,7 +769,7 @@ func (api *API) standardTraceBlockToFile(ctx context.Context, block *types.Block
769769
// If the transaction needs tracing, swap out the configs
770770
if tx.Hash() == txHash || txHash == (common.Hash{}) {
771771
// Generate a unique temporary file to dump it into
772-
prefix := fmt.Sprintf("block_%#x-%d-%#x-", block.Hash().Bytes()[:4], i, tx.Hash().Bytes()[:4])
772+
prefix := fmt.Sprintf("block_%#x-%d-%#x-", api.blockHash(block).Bytes()[:4], i, tx.Hash().Bytes()[:4])
773773
if !canon {
774774
prefix = fmt.Sprintf("%valt-", prefix)
775775
}

eth/tracers/api.libevm.go

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
// Copyright 2026 the libevm authors.
2+
//
3+
// The libevm additions to go-ethereum are free software: you can redistribute
4+
// them and/or modify them under the terms of the GNU Lesser General Public License
5+
// as published by the Free Software Foundation, either version 3 of the License,
6+
// or (at your option) any later version.
7+
//
8+
// The libevm additions are distributed in the hope that they will be useful,
9+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
10+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
11+
// General Public License for more details.
12+
//
13+
// You should have received a copy of the GNU Lesser General Public License
14+
// along with the go-ethereum library. If not, see
15+
// <http://www.gnu.org/licenses/>.
16+
17+
package tracers
18+
19+
import (
20+
"github.com/ava-labs/libevm/common"
21+
"github.com/ava-labs/libevm/core/types"
22+
)
23+
24+
// BlockHashOverrider is an optional extension to [Backend], allowing an
25+
// arbitrary block hash to be returned for a block. If not implemented,
26+
// [types.Block.Hash] is used instead.
27+
//
28+
// This would be used in the case that the [types.Header] is manipulated in the
29+
// [Backend] for tracer-specific behavior. However, all hashes directly
30+
// returned by the [Backend] are expected to be correct.
31+
type BlockHashOverrider interface {
32+
// BlockHash returns the hash of the provided block.
33+
BlockHash(*types.Block) common.Hash
34+
}
35+
36+
func (a *API) blockHash(block *types.Block) common.Hash {
37+
overrider, ok := a.backend.(BlockHashOverrider)
38+
if !ok {
39+
return block.Hash()
40+
}
41+
return overrider.BlockHash(block)
42+
}

0 commit comments

Comments
 (0)