Skip to content

Commit 2121836

Browse files
authored
Merge pull request #709 from onflow/mpeter/fix-trace-generation
Use current block data when constructing `BlockContext` for trace generation
2 parents 80d005f + 59e4f20 commit 2121836

File tree

2 files changed

+42
-47
lines changed

2 files changed

+42
-47
lines changed

api/debug.go

+20-24
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import (
55
"errors"
66
"fmt"
77
"math/big"
8-
"slices"
8+
"strings"
99

1010
"github.com/goccy/go-json"
1111
"github.com/onflow/flow-go/fvm/evm/offchain/query"
@@ -29,6 +29,8 @@ import (
2929
"github.com/onflow/flow-evm-gateway/storage/pebble"
3030
flowEVM "github.com/onflow/flow-go/fvm/evm"
3131

32+
offchain "github.com/onflow/flow-go/fvm/evm/offchain/storage"
33+
3234
// this import is needed for side-effects, because the
3335
// tracers.DefaultDirectory is relying on the init function
3436
_ "github.com/onflow/go-ethereum/eth/tracers/js"
@@ -302,15 +304,7 @@ func (d *DebugAPI) traceTransaction(
302304
return nil, err
303305
}
304306

305-
// We need to re-execute the given transaction and all the
306-
// transactions that precede it in the same block, based on
307-
// the previous block state, to generate the correct trace.
308-
previousBlock, err := d.blocks.GetByHeight(block.Height - 1)
309-
if err != nil {
310-
return nil, err
311-
}
312-
313-
blockExecutor, err := d.executorAtBlock(previousBlock)
307+
blockExecutor, err := d.executorAtBlock(block)
314308
if err != nil {
315309
return nil, err
316310
}
@@ -383,14 +377,7 @@ func (d *DebugAPI) traceBlockByNumber(
383377
return results, nil
384378
}
385379

386-
// We need to re-execute all the transactions from the given block,
387-
// on top of the previous block state, to generate the correct traces.
388-
previousBlock, err := d.blocks.GetByHeight(block.Height - 1)
389-
if err != nil {
390-
return nil, err
391-
}
392-
393-
blockExecutor, err := d.executorAtBlock(previousBlock)
380+
blockExecutor, err := d.executorAtBlock(block)
394381
if err != nil {
395382
return nil, err
396383
}
@@ -424,19 +411,28 @@ func (d *DebugAPI) traceBlockByNumber(
424411
}
425412

426413
func (d *DebugAPI) executorAtBlock(block *models.Block) (*evm.BlockExecutor, error) {
427-
snapshot, err := d.registerStore.GetSnapshotAt(block.Height)
414+
previousBlock, err := d.blocks.GetByHeight(block.Height - 1)
415+
if err != nil {
416+
return nil, err
417+
}
418+
419+
// We need to re-execute all the transactions from the given block,
420+
// on top of the previous block state, to generate the correct traces.
421+
snapshot, err := d.registerStore.GetSnapshotAt(previousBlock.Height)
428422
if err != nil {
429423
return nil, fmt.Errorf(
430424
"failed to get register snapshot at block height %d: %w",
431-
block.Height,
425+
previousBlock.Height,
432426
err,
433427
)
434428
}
435-
ledger := storage.NewRegisterDelta(snapshot)
429+
430+
// create storage
431+
state := offchain.NewEphemeralStorage(offchain.NewReadOnlyStorage(snapshot))
436432

437433
return evm.NewBlockExecutor(
438434
block,
439-
ledger,
435+
state,
440436
d.config.FlowNetworkID,
441437
d.blocks,
442438
d.receipts,
@@ -484,6 +480,6 @@ func isDefaultCallTracer(config *tracers.TraceConfig) bool {
484480
return false
485481
}
486482

487-
tracerConfig := json.RawMessage(replayer.TracerConfig)
488-
return slices.Equal(config.TracerConfig, tracerConfig)
483+
trimmedConfig := strings.ReplaceAll(string(config.TracerConfig), " ", "")
484+
return trimmedConfig == replayer.TracerConfig
489485
}

services/evm/executor.go

+22-23
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66
"github.com/onflow/atree"
77
"github.com/onflow/flow-go/fvm/evm"
88
"github.com/onflow/flow-go/fvm/evm/emulator"
9+
"github.com/onflow/flow-go/fvm/evm/offchain/blocks"
910
"github.com/onflow/flow-go/fvm/evm/precompiles"
1011
"github.com/onflow/flow-go/fvm/evm/types"
1112
flowGo "github.com/onflow/flow-go/model/flow"
@@ -98,6 +99,13 @@ func (s *BlockExecutor) Run(
9899
s.gasUsed += res.GasConsumed
99100
s.txIndex++
100101

102+
if res.GasConsumed != receipt.GasUsed {
103+
return fmt.Errorf(
104+
"used gas mismatch, expected: %d, got: %d",
105+
receipt.GasUsed,
106+
res.GasConsumed,
107+
)
108+
}
101109
l.Debug().Msg("transaction executed successfully")
102110

103111
return nil
@@ -110,25 +118,11 @@ func (s *BlockExecutor) blockContext(
110118
receipt *models.Receipt,
111119
tracer *tracers.Tracer,
112120
) (types.BlockContext, error) {
113-
ctx := types.BlockContext{
114-
ChainID: types.EVMChainIDFromFlowChainID(s.chainID),
115-
BlockNumber: s.block.Height,
116-
BlockTimestamp: s.block.Timestamp,
117-
DirectCallBaseGasUsage: types.DefaultDirectCallBaseGasUsage,
118-
DirectCallGasPrice: types.DefaultDirectCallGasPrice,
119-
GasFeeCollector: types.CoinbaseAddress,
120-
GetHashFunc: func(n uint64) common.Hash {
121-
// For block heights greater than or equal to the current,
122-
// return an empty block hash.
123-
if n >= s.block.Height {
124-
return common.Hash{}
125-
}
126-
// If the given block height, is more than 256 blocks
127-
// in the past, return an empty block hash.
128-
if s.block.Height-n > 256 {
129-
return common.Hash{}
130-
}
131-
121+
ctx, err := blocks.NewBlockContext(
122+
s.chainID,
123+
s.block.Height,
124+
s.block.Timestamp,
125+
func(n uint64) common.Hash {
132126
block, err := s.blocks.GetByHeight(n)
133127
if err != nil {
134128
return common.Hash{}
@@ -140,12 +134,17 @@ func (s *BlockExecutor) blockContext(
140134

141135
return blockHash
142136
},
143-
Random: s.block.PrevRandao,
144-
TxCountSoFar: s.txIndex,
145-
TotalGasUsedSoFar: s.gasUsed,
146-
Tracer: tracer,
137+
s.block.PrevRandao,
138+
tracer,
139+
)
140+
141+
if err != nil {
142+
return types.BlockContext{}, err
147143
}
148144

145+
ctx.TxCountSoFar = s.txIndex
146+
ctx.TotalGasUsedSoFar = s.gasUsed
147+
149148
// only add precompile cadence arch contract if we have a receipt
150149
if receipt != nil {
151150
calls, err := types.AggregatedPrecompileCallsFromEncoded(receipt.PrecompiledCalls)

0 commit comments

Comments
 (0)