Merge pull request #52 from sei-protocol/tony/adapt-traceBlock

process non-EVM txs during traceBlock
This commit is contained in:
codchen 2025-05-23 21:41:11 +08:00 committed by GitHub
commit 520314db05
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
13 changed files with 153 additions and 104 deletions

View file

@ -21,6 +21,7 @@ package main
import ( import (
"bufio" "bufio"
"bytes" "bytes"
"encoding/json"
"fmt" "fmt"
"io" "io"
"math/rand" "math/rand"
@ -28,9 +29,8 @@ import (
"os/exec" "os/exec"
"strings" "strings"
"testing" "testing"
"encoding/json"
"github.com/ethereum/go-ethereum/internal/reexec" "github.com/ethereum/go-ethereum/lib/reexec"
) )
func runSelf(args ...string) ([]byte, error) { func runSelf(args ...string) ([]byte, error) {

View file

@ -26,7 +26,7 @@ import (
"time" "time"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/internal/debug" "github.com/ethereum/go-ethereum/lib/debug"
"github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/log"
"github.com/holiman/uint256" "github.com/holiman/uint256"
"github.com/urfave/cli/v2" "github.com/urfave/cli/v2"

View file

@ -34,6 +34,7 @@ import (
"github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/eth/gasprice" "github.com/ethereum/go-ethereum/eth/gasprice"
"github.com/ethereum/go-ethereum/eth/tracers" "github.com/ethereum/go-ethereum/eth/tracers"
"github.com/ethereum/go-ethereum/eth/tracers/tracersutils"
"github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/event" "github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/lib/ethapi" "github.com/ethereum/go-ethereum/lib/ethapi"
@ -115,39 +116,39 @@ func (b *EthAPIBackend) HeaderByHash(ctx context.Context, hash common.Hash) (*ty
return b.eth.blockchain.GetHeaderByHash(hash), nil return b.eth.blockchain.GetHeaderByHash(hash), nil
} }
func (b *EthAPIBackend) BlockByNumber(ctx context.Context, number rpc.BlockNumber) (*types.Block, error) { func (b *EthAPIBackend) BlockByNumber(ctx context.Context, number rpc.BlockNumber) (*types.Block, []tracersutils.TraceBlockMetadata, error) {
// Pending block is only known by the miner // Pending block is only known by the miner
if number == rpc.PendingBlockNumber { if number == rpc.PendingBlockNumber {
block := b.eth.miner.PendingBlock() block := b.eth.miner.PendingBlock()
if block == nil { if block == nil {
return nil, errors.New("pending block is not available") return nil, nil, errors.New("pending block is not available")
} }
return block, nil return block, nil, nil
} }
// Otherwise resolve and return the block // Otherwise resolve and return the block
if number == rpc.LatestBlockNumber { if number == rpc.LatestBlockNumber {
header := b.eth.blockchain.CurrentBlock() header := b.eth.blockchain.CurrentBlock()
return b.eth.blockchain.GetBlock(header.Hash(), header.Number.Uint64()), nil return b.eth.blockchain.GetBlock(header.Hash(), header.Number.Uint64()), nil, nil
} }
if number == rpc.FinalizedBlockNumber { if number == rpc.FinalizedBlockNumber {
header := b.eth.blockchain.CurrentFinalBlock() header := b.eth.blockchain.CurrentFinalBlock()
if header == nil { if header == nil {
return nil, errors.New("finalized block not found") return nil, nil, errors.New("finalized block not found")
} }
return b.eth.blockchain.GetBlock(header.Hash(), header.Number.Uint64()), nil return b.eth.blockchain.GetBlock(header.Hash(), header.Number.Uint64()), nil, nil
} }
if number == rpc.SafeBlockNumber { if number == rpc.SafeBlockNumber {
header := b.eth.blockchain.CurrentSafeBlock() header := b.eth.blockchain.CurrentSafeBlock()
if header == nil { if header == nil {
return nil, errors.New("safe block not found") return nil, nil, errors.New("safe block not found")
} }
return b.eth.blockchain.GetBlock(header.Hash(), header.Number.Uint64()), nil return b.eth.blockchain.GetBlock(header.Hash(), header.Number.Uint64()), nil, nil
} }
return b.eth.blockchain.GetBlockByNumber(uint64(number)), nil return b.eth.blockchain.GetBlockByNumber(uint64(number)), nil, nil
} }
func (b *EthAPIBackend) BlockByHash(ctx context.Context, hash common.Hash) (*types.Block, error) { func (b *EthAPIBackend) BlockByHash(ctx context.Context, hash common.Hash) (*types.Block, []tracersutils.TraceBlockMetadata, error) {
return b.eth.blockchain.GetBlockByHash(hash), nil return b.eth.blockchain.GetBlockByHash(hash), nil, nil
} }
// GetBody returns body of a block. It does not resolve special block numbers. // GetBody returns body of a block. It does not resolve special block numbers.
@ -163,7 +164,8 @@ func (b *EthAPIBackend) GetBody(ctx context.Context, hash common.Hash, number rp
func (b *EthAPIBackend) BlockByNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (*types.Block, error) { func (b *EthAPIBackend) BlockByNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (*types.Block, error) {
if blockNr, ok := blockNrOrHash.Number(); ok { if blockNr, ok := blockNrOrHash.Number(); ok {
return b.BlockByNumber(ctx, blockNr) b, _, err := b.BlockByNumber(ctx, blockNr)
return b, err
} }
if hash, ok := blockNrOrHash.Hash(); ok { if hash, ok := blockNrOrHash.Hash(); ok {
header := b.eth.blockchain.GetHeaderByHash(hash) header := b.eth.blockchain.GetHeaderByHash(hash)

View file

@ -273,7 +273,7 @@ func (oracle *Oracle) FeeHistory(ctx context.Context, blocks uint64, unresolvedL
results <- fees results <- fees
} else { } else {
if len(rewardPercentiles) != 0 { if len(rewardPercentiles) != 0 {
fees.block, fees.err = oracle.backend.BlockByNumber(ctx, rpc.BlockNumber(blockNumber)) fees.block, _, fees.err = oracle.backend.BlockByNumber(ctx, rpc.BlockNumber(blockNumber))
if fees.block != nil && fees.err == nil { if fees.block != nil && fees.err == nil {
fees.receipts, fees.err = oracle.backend.GetReceipts(ctx, fees.block.Hash()) fees.receipts, fees.err = oracle.backend.GetReceipts(ctx, fees.block.Hash())
fees.header = fees.block.Header() fees.header = fees.block.Header()

View file

@ -25,6 +25,7 @@ import (
"github.com/ethereum/go-ethereum/common/lru" "github.com/ethereum/go-ethereum/common/lru"
"github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/eth/tracers/tracersutils"
"github.com/ethereum/go-ethereum/event" "github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/params"
@ -52,7 +53,7 @@ type Config struct {
// OracleBackend includes all necessary background APIs for oracle. // OracleBackend includes all necessary background APIs for oracle.
type OracleBackend interface { type OracleBackend interface {
HeaderByNumber(ctx context.Context, number rpc.BlockNumber) (*types.Header, error) HeaderByNumber(ctx context.Context, number rpc.BlockNumber) (*types.Header, error)
BlockByNumber(ctx context.Context, number rpc.BlockNumber) (*types.Block, error) BlockByNumber(ctx context.Context, number rpc.BlockNumber) (*types.Block, []tracersutils.TraceBlockMetadata, error)
GetReceipts(ctx context.Context, hash common.Hash) (types.Receipts, error) GetReceipts(ctx context.Context, hash common.Hash) (types.Receipts, error)
PendingBlockAndReceipts() (*types.Block, types.Receipts) PendingBlockAndReceipts() (*types.Block, types.Receipts)
ChainConfig() *params.ChainConfig ChainConfig() *params.ChainConfig
@ -232,7 +233,7 @@ type results struct {
// are sent by the miner itself(it doesn't make any sense to include this kind of // are sent by the miner itself(it doesn't make any sense to include this kind of
// transaction prices for sampling), nil gasprice is returned. // transaction prices for sampling), nil gasprice is returned.
func (oracle *Oracle) getBlockValues(ctx context.Context, blockNum uint64, limit int, ignoreUnder *big.Int, result chan results, quit chan struct{}) { func (oracle *Oracle) getBlockValues(ctx context.Context, blockNum uint64, limit int, ignoreUnder *big.Int, result chan results, quit chan struct{}) {
block, err := oracle.backend.BlockByNumber(ctx, rpc.BlockNumber(blockNum)) block, _, err := oracle.backend.BlockByNumber(ctx, rpc.BlockNumber(blockNum))
if block == nil { if block == nil {
select { select {
case result <- results{nil, err}: case result <- results{nil, err}:

View file

@ -29,6 +29,7 @@ import (
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/eth/tracers/tracersutils"
"github.com/ethereum/go-ethereum/event" "github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rpc" "github.com/ethereum/go-ethereum/rpc"
@ -67,9 +68,9 @@ func (b *testBackend) HeaderByNumber(ctx context.Context, number rpc.BlockNumber
return b.chain.GetHeaderByNumber(uint64(number)), nil return b.chain.GetHeaderByNumber(uint64(number)), nil
} }
func (b *testBackend) BlockByNumber(ctx context.Context, number rpc.BlockNumber) (*types.Block, error) { func (b *testBackend) BlockByNumber(ctx context.Context, number rpc.BlockNumber) (*types.Block, []tracersutils.TraceBlockMetadata, error) {
if number > testHead { if number > testHead {
return nil, nil return nil, nil, nil
} }
if number == rpc.EarliestBlockNumber { if number == rpc.EarliestBlockNumber {
number = 0 number = 0
@ -87,10 +88,10 @@ func (b *testBackend) BlockByNumber(ctx context.Context, number rpc.BlockNumber)
if b.pending { if b.pending {
number = testHead + 1 number = testHead + 1
} else { } else {
return nil, nil return nil, nil, nil
} }
} }
return b.chain.GetBlockByNumber(uint64(number)), nil return b.chain.GetBlockByNumber(uint64(number)), nil, nil
} }
func (b *testBackend) GetReceipts(ctx context.Context, hash common.Hash) (types.Receipts, error) { func (b *testBackend) GetReceipts(ctx context.Context, hash common.Hash) (types.Receipts, error) {

View file

@ -38,6 +38,7 @@ import (
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/eth/tracers/logger" "github.com/ethereum/go-ethereum/eth/tracers/logger"
"github.com/ethereum/go-ethereum/eth/tracers/tracersutils"
"github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/lib/ethapi" "github.com/ethereum/go-ethereum/lib/ethapi"
"github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/log"
@ -80,8 +81,8 @@ type StateReleaseFunc func()
type Backend interface { type Backend interface {
HeaderByHash(ctx context.Context, hash common.Hash) (*types.Header, error) HeaderByHash(ctx context.Context, hash common.Hash) (*types.Header, error)
HeaderByNumber(ctx context.Context, number rpc.BlockNumber) (*types.Header, error) HeaderByNumber(ctx context.Context, number rpc.BlockNumber) (*types.Header, error)
BlockByHash(ctx context.Context, hash common.Hash) (*types.Block, error) BlockByHash(ctx context.Context, hash common.Hash) (*types.Block, []tracersutils.TraceBlockMetadata, error)
BlockByNumber(ctx context.Context, number rpc.BlockNumber) (*types.Block, error) BlockByNumber(ctx context.Context, number rpc.BlockNumber) (*types.Block, []tracersutils.TraceBlockMetadata, error)
GetTransaction(ctx context.Context, txHash common.Hash) (*types.Transaction, common.Hash, uint64, uint64, error) GetTransaction(ctx context.Context, txHash common.Hash) (*types.Transaction, common.Hash, uint64, uint64, error)
RPCGasCap() uint64 RPCGasCap() uint64
ChainConfig() *params.ChainConfig ChainConfig() *params.ChainConfig
@ -112,28 +113,28 @@ func (api *API) chainContext(ctx context.Context) core.ChainContext {
// blockByNumber is the wrapper of the chain access function offered by the backend. // blockByNumber is the wrapper of the chain access function offered by the backend.
// It will return an error if the block is not found. // It will return an error if the block is not found.
func (api *API) blockByNumber(ctx context.Context, number rpc.BlockNumber) (*types.Block, error) { func (api *API) blockByNumber(ctx context.Context, number rpc.BlockNumber) (*types.Block, []tracersutils.TraceBlockMetadata, error) {
block, err := api.backend.BlockByNumber(ctx, number) block, metadata, err := api.backend.BlockByNumber(ctx, number)
if err != nil { if err != nil {
return nil, err return nil, nil, err
} }
if block == nil { if block == nil {
return nil, fmt.Errorf("block #%d not found", number) return nil, nil, fmt.Errorf("block #%d not found", number)
} }
return block, nil return block, metadata, nil
} }
// blockByHash is the wrapper of the chain access function offered by the backend. // blockByHash is the wrapper of the chain access function offered by the backend.
// It will return an error if the block is not found. // It will return an error if the block is not found.
func (api *API) blockByHash(ctx context.Context, hash common.Hash) (*types.Block, error) { func (api *API) blockByHash(ctx context.Context, hash common.Hash) (*types.Block, []tracersutils.TraceBlockMetadata, error) {
block, err := api.backend.BlockByHash(ctx, hash) block, metadata, err := api.backend.BlockByHash(ctx, hash)
if err != nil { if err != nil {
return nil, err return nil, nil, err
} }
if block == nil { if block == nil {
return nil, fmt.Errorf("block %s not found", hash.Hex()) return nil, nil, fmt.Errorf("block %s not found", hash.Hex())
} }
return block, nil return block, metadata, nil
} }
// blockByNumberAndHash is the wrapper of the chain access function offered by // blockByNumberAndHash is the wrapper of the chain access function offered by
@ -141,13 +142,13 @@ func (api *API) blockByHash(ctx context.Context, hash common.Hash) (*types.Block
// //
// Note this function is friendly for the light client which can only retrieve the // Note this function is friendly for the light client which can only retrieve the
// historical(before the CHT) header/block by number. // historical(before the CHT) header/block by number.
func (api *API) blockByNumberAndHash(ctx context.Context, number rpc.BlockNumber, hash common.Hash) (*types.Block, error) { func (api *API) blockByNumberAndHash(ctx context.Context, number rpc.BlockNumber, hash common.Hash) (*types.Block, []tracersutils.TraceBlockMetadata, error) {
block, err := api.blockByNumber(ctx, number) block, metadata, err := api.blockByNumber(ctx, number)
if err != nil { if err != nil {
return nil, err return nil, nil, err
} }
if block.Hash() == hash { if block.Hash() == hash {
return block, nil return block, metadata, nil
} }
return api.blockByHash(ctx, hash) return api.blockByHash(ctx, hash)
} }
@ -213,11 +214,11 @@ type txTraceTask struct {
// TraceChain returns the structured logs created during the execution of EVM // TraceChain returns the structured logs created during the execution of EVM
// between two blocks (excluding start) and returns them as a JSON object. // between two blocks (excluding start) and returns them as a JSON object.
func (api *API) TraceChain(ctx context.Context, start, end rpc.BlockNumber, config *TraceConfig) (*rpc.Subscription, error) { // Fetch the block interval that we want to trace func (api *API) TraceChain(ctx context.Context, start, end rpc.BlockNumber, config *TraceConfig) (*rpc.Subscription, error) { // Fetch the block interval that we want to trace
from, err := api.blockByNumber(ctx, start) from, _, err := api.blockByNumber(ctx, start)
if err != nil { if err != nil {
return nil, err return nil, err
} }
to, err := api.blockByNumber(ctx, end) to, _, err := api.blockByNumber(ctx, end)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -348,12 +349,12 @@ func (api *API) traceChain(start, end *types.Block, config *TraceConfig, closed
log.Info("Tracing chain segment", "start", start.NumberU64(), "end", end.NumberU64(), "current", number, "transactions", traced, "elapsed", time.Since(begin)) log.Info("Tracing chain segment", "start", start.NumberU64(), "end", end.NumberU64(), "current", number, "transactions", traced, "elapsed", time.Since(begin))
} }
// Retrieve the parent block and target block for tracing. // Retrieve the parent block and target block for tracing.
block, err := api.blockByNumber(ctx, rpc.BlockNumber(number)) block, _, err := api.blockByNumber(ctx, rpc.BlockNumber(number))
if err != nil { if err != nil {
failed = err failed = err
break break
} }
next, err := api.blockByNumber(ctx, rpc.BlockNumber(number+1)) next, _, err := api.blockByNumber(ctx, rpc.BlockNumber(number+1))
if err != nil { if err != nil {
failed = err failed = err
break break
@ -435,21 +436,21 @@ func (api *API) traceChain(start, end *types.Block, config *TraceConfig, closed
// TraceBlockByNumber returns the structured logs created during the execution of // TraceBlockByNumber returns the structured logs created during the execution of
// EVM and returns them as a JSON object. // EVM and returns them as a JSON object.
func (api *API) TraceBlockByNumber(ctx context.Context, number rpc.BlockNumber, config *TraceConfig) ([]*TxTraceResult, error) { func (api *API) TraceBlockByNumber(ctx context.Context, number rpc.BlockNumber, config *TraceConfig) ([]*TxTraceResult, error) {
block, err := api.blockByNumber(ctx, number) block, metadata, err := api.blockByNumber(ctx, number)
if err != nil { if err != nil {
return nil, err return nil, err
} }
return api.traceBlock(ctx, block, config) return api.traceBlock(ctx, block, metadata, config)
} }
// TraceBlockByHash returns the structured logs created during the execution of // TraceBlockByHash returns the structured logs created during the execution of
// EVM and returns them as a JSON object. // EVM and returns them as a JSON object.
func (api *API) TraceBlockByHash(ctx context.Context, hash common.Hash, config *TraceConfig) ([]*TxTraceResult, error) { func (api *API) TraceBlockByHash(ctx context.Context, hash common.Hash, config *TraceConfig) ([]*TxTraceResult, error) {
block, err := api.blockByHash(ctx, hash) block, metadata, err := api.blockByHash(ctx, hash)
if err != nil { if err != nil {
return nil, err return nil, err
} }
return api.traceBlock(ctx, block, config) return api.traceBlock(ctx, block, metadata, config)
} }
// TraceBlock returns the structured logs created during the execution of EVM // TraceBlock returns the structured logs created during the execution of EVM
@ -459,7 +460,7 @@ func (api *API) TraceBlock(ctx context.Context, blob hexutil.Bytes, config *Trac
if err := rlp.DecodeBytes(blob, block); err != nil { if err := rlp.DecodeBytes(blob, block); err != nil {
return nil, fmt.Errorf("could not decode block: %v", err) return nil, fmt.Errorf("could not decode block: %v", err)
} }
return api.traceBlock(ctx, block, config) return api.traceBlock(ctx, block, nil, config)
} }
// TraceBlockFromFile returns the structured logs created during the execution of // TraceBlockFromFile returns the structured logs created during the execution of
@ -480,14 +481,14 @@ func (api *API) TraceBadBlock(ctx context.Context, hash common.Hash, config *Tra
if block == nil { if block == nil {
return nil, fmt.Errorf("bad block %#x not found", hash) return nil, fmt.Errorf("bad block %#x not found", hash)
} }
return api.traceBlock(ctx, block, config) return api.traceBlock(ctx, block, nil, config)
} }
// StandardTraceBlockToFile dumps the structured logs created during the // StandardTraceBlockToFile dumps the structured logs created during the
// execution of EVM to the local file system and returns a list of files // execution of EVM to the local file system and returns a list of files
// to the caller. // to the caller.
func (api *API) StandardTraceBlockToFile(ctx context.Context, hash common.Hash, config *StdTraceConfig) ([]string, error) { func (api *API) StandardTraceBlockToFile(ctx context.Context, hash common.Hash, config *StdTraceConfig) ([]string, error) {
block, err := api.blockByHash(ctx, hash) block, _, err := api.blockByHash(ctx, hash)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -497,7 +498,7 @@ func (api *API) StandardTraceBlockToFile(ctx context.Context, hash common.Hash,
// IntermediateRoots executes a block (bad- or canon- or side-), and returns a list // IntermediateRoots executes a block (bad- or canon- or side-), and returns a list
// of intermediate roots: the stateroot after each transaction. // of intermediate roots: the stateroot after each transaction.
func (api *API) IntermediateRoots(ctx context.Context, hash common.Hash, config *TraceConfig) ([]common.Hash, error) { func (api *API) IntermediateRoots(ctx context.Context, hash common.Hash, config *TraceConfig) ([]common.Hash, error) {
block, _ := api.blockByHash(ctx, hash) block, _, _ := api.blockByHash(ctx, hash)
if block == nil { if block == nil {
// Check in the bad blocks // Check in the bad blocks
block = rawdb.ReadBadBlock(api.backend.ChainDb(), hash) block = rawdb.ReadBadBlock(api.backend.ChainDb(), hash)
@ -508,7 +509,7 @@ func (api *API) IntermediateRoots(ctx context.Context, hash common.Hash, config
if block.NumberU64() == 0 { if block.NumberU64() == 0 {
return nil, errors.New("genesis is not traceable") return nil, errors.New("genesis is not traceable")
} }
parent, err := api.blockByNumberAndHash(ctx, rpc.BlockNumber(block.NumberU64()-1), block.ParentHash()) parent, _, err := api.blockByNumberAndHash(ctx, rpc.BlockNumber(block.NumberU64()-1), block.ParentHash())
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -570,12 +571,12 @@ func (api *API) StandardTraceBadBlockToFile(ctx context.Context, hash common.Has
// traceBlock configures a new tracer according to the provided configuration, and // traceBlock configures a new tracer according to the provided configuration, and
// executes all the transactions contained within. The return value will be one item // executes all the transactions contained within. The return value will be one item
// per transaction, dependent on the requested tracer. // per transaction, dependent on the requested tracer.
func (api *API) traceBlock(ctx context.Context, block *types.Block, config *TraceConfig) ([]*TxTraceResult, error) { func (api *API) traceBlock(ctx context.Context, block *types.Block, metadata []tracersutils.TraceBlockMetadata, config *TraceConfig) ([]*TxTraceResult, error) {
if block.NumberU64() == 0 { if block.NumberU64() == 0 {
return nil, errors.New("genesis is not traceable") return nil, errors.New("genesis is not traceable")
} }
// Prepare base state // Prepare base state
parent, err := api.blockByNumberAndHash(ctx, rpc.BlockNumber(block.NumberU64()-1), block.ParentHash()) parent, _, err := api.blockByNumberAndHash(ctx, rpc.BlockNumber(block.NumberU64()-1), block.ParentHash())
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -608,20 +609,47 @@ func (api *API) traceBlock(ctx context.Context, block *types.Block, config *Trac
signer = types.MakeSigner(api.backend.ChainConfig(), block.Number(), block.Time()) signer = types.MakeSigner(api.backend.ChainConfig(), block.Number(), block.Time())
results = make([]*TxTraceResult, len(txs)) results = make([]*TxTraceResult, len(txs))
) )
for i, tx := range txs { if len(metadata) == 0 {
// Generate the next state snapshot fast without tracing for i, tx := range txs {
msg, _ := core.TransactionToMessage(tx, signer, block.BaseFee()) // Generate the next state snapshot fast without tracing
txctx := &Context{ msg, _ := core.TransactionToMessage(tx, signer, block.BaseFee())
BlockHash: blockHash, txctx := &Context{
BlockNumber: block.Number(), BlockHash: blockHash,
TxIndex: i, BlockNumber: block.Number(),
TxHash: tx.Hash(), TxIndex: i,
TxHash: tx.Hash(),
}
res, err := api.traceTx(ctx, tx, msg, txctx, blockCtx, statedb, config)
if err != nil {
results[i] = &TxTraceResult{TxHash: tx.Hash(), Error: err.Error()}
} else {
results[i] = &TxTraceResult{TxHash: tx.Hash(), Result: res}
}
} }
res, err := api.traceTx(ctx, tx, msg, txctx, blockCtx, statedb, config) return results, nil
if err != nil { }
results[i] = &TxTraceResult{TxHash: tx.Hash(), Error: err.Error()} for _, md := range metadata {
if md.ShouldIncludeInTraceResult {
i := md.IdxInEthBlock
tx := txs[i]
// Generate the next state snapshot fast without tracing
msg, _ := core.TransactionToMessage(tx, signer, block.BaseFee())
txctx := &Context{
BlockHash: blockHash,
BlockNumber: block.Number(),
TxIndex: i,
TxHash: tx.Hash(),
}
res, err := api.traceTx(ctx, tx, msg, txctx, blockCtx, statedb, config)
if err != nil {
results[i] = &TxTraceResult{TxHash: tx.Hash(), Error: err.Error()}
} else {
results[i] = &TxTraceResult{TxHash: tx.Hash(), Result: res}
}
} else { } else {
results[i] = &TxTraceResult{TxHash: tx.Hash(), Result: res} // should not be included in result but still needs to be run because
// these txs may affect cumulative state
md.TraceRunnable(statedb)
} }
} }
return results, nil return results, nil
@ -729,7 +757,7 @@ func (api *API) standardTraceBlockToFile(ctx context.Context, block *types.Block
if block.NumberU64() == 0 { if block.NumberU64() == 0 {
return nil, errors.New("genesis is not traceable") return nil, errors.New("genesis is not traceable")
} }
parent, err := api.blockByNumberAndHash(ctx, rpc.BlockNumber(block.NumberU64()-1), block.ParentHash()) parent, _, err := api.blockByNumberAndHash(ctx, rpc.BlockNumber(block.NumberU64()-1), block.ParentHash())
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -868,7 +896,7 @@ func (api *API) TraceTransaction(ctx context.Context, hash common.Hash, config *
if config != nil && config.Reexec != nil { if config != nil && config.Reexec != nil {
reexec = *config.Reexec reexec = *config.Reexec
} }
block, err := api.blockByNumberAndHash(ctx, rpc.BlockNumber(blockNumber), blockHash) block, _, err := api.blockByNumberAndHash(ctx, rpc.BlockNumber(blockNumber), blockHash)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -913,7 +941,7 @@ func (api *API) TraceCall(ctx context.Context, args ethapi.TransactionArgs, bloc
release StateReleaseFunc release StateReleaseFunc
) )
if hash, ok := blockNrOrHash.Hash(); ok { if hash, ok := blockNrOrHash.Hash(); ok {
block, err = api.blockByHash(ctx, hash) block, _, err = api.blockByHash(ctx, hash)
} else if number, ok := blockNrOrHash.Number(); ok { } else if number, ok := blockNrOrHash.Number(); ok {
if number == rpc.PendingBlockNumber { if number == rpc.PendingBlockNumber {
// We don't have access to the miner here. For tracing 'future' transactions, // We don't have access to the miner here. For tracing 'future' transactions,
@ -923,7 +951,7 @@ func (api *API) TraceCall(ctx context.Context, args ethapi.TransactionArgs, bloc
// of what the next actual block is likely to contain. // of what the next actual block is likely to contain.
return nil, errors.New("tracing on top of pending is not supported") return nil, errors.New("tracing on top of pending is not supported")
} }
block, err = api.blockByNumber(ctx, number) block, _, err = api.blockByNumber(ctx, number)
} else { } else {
return nil, errors.New("invalid arguments; neither block nor hash specified") return nil, errors.New("invalid arguments; neither block nor hash specified")
} }

View file

@ -38,6 +38,7 @@ import (
"github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/eth/tracers/logger" "github.com/ethereum/go-ethereum/eth/tracers/logger"
"github.com/ethereum/go-ethereum/eth/tracers/tracersutils"
"github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/lib/ethapi" "github.com/ethereum/go-ethereum/lib/ethapi"
"github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/params"
@ -101,15 +102,15 @@ func (b *testBackend) HeaderByNumber(ctx context.Context, number rpc.BlockNumber
return b.chain.GetHeaderByNumber(uint64(number)), nil return b.chain.GetHeaderByNumber(uint64(number)), nil
} }
func (b *testBackend) BlockByHash(ctx context.Context, hash common.Hash) (*types.Block, error) { func (b *testBackend) BlockByHash(ctx context.Context, hash common.Hash) (*types.Block, []tracersutils.TraceBlockMetadata, error) {
return b.chain.GetBlockByHash(hash), nil return b.chain.GetBlockByHash(hash), nil, nil
} }
func (b *testBackend) BlockByNumber(ctx context.Context, number rpc.BlockNumber) (*types.Block, error) { func (b *testBackend) BlockByNumber(ctx context.Context, number rpc.BlockNumber) (*types.Block, []tracersutils.TraceBlockMetadata, error) {
if number == rpc.PendingBlockNumber || number == rpc.LatestBlockNumber { if number == rpc.PendingBlockNumber || number == rpc.LatestBlockNumber {
return b.chain.GetBlockByNumber(b.chain.CurrentBlock().Number.Uint64()), nil return b.chain.GetBlockByNumber(b.chain.CurrentBlock().Number.Uint64()), nil, nil
} }
return b.chain.GetBlockByNumber(uint64(number)), nil return b.chain.GetBlockByNumber(uint64(number)), nil, nil
} }
func (b *testBackend) GetTransaction(ctx context.Context, txHash common.Hash) (*types.Transaction, common.Hash, uint64, uint64, error) { func (b *testBackend) GetTransaction(ctx context.Context, txHash common.Hash) (*types.Transaction, common.Hash, uint64, uint64, error) {
@ -1043,8 +1044,8 @@ func TestTraceChain(t *testing.T) {
ref.Store(0) ref.Store(0)
rel.Store(0) rel.Store(0)
from, _ := api.blockByNumber(context.Background(), rpc.BlockNumber(c.start)) from, _, _ := api.blockByNumber(context.Background(), rpc.BlockNumber(c.start))
to, _ := api.blockByNumber(context.Background(), rpc.BlockNumber(c.end)) to, _, _ := api.blockByNumber(context.Background(), rpc.BlockNumber(c.end))
resCh := api.traceChain(from, to, c.config, nil) resCh := api.traceChain(from, to, c.config, nil)
next := c.start + 1 next := c.start + 1

View file

@ -0,0 +1,11 @@
package tracersutils
import "github.com/ethereum/go-ethereum/core/vm"
type TraceBlockMetadata struct {
ShouldIncludeInTraceResult bool
// must be set if shouldIncludeInTraceResult
IdxInEthBlock int
// must be set if !shouldIncludeInTraceResult
TraceRunnable func(vm.StateDB)
}

View file

@ -807,7 +807,7 @@ func (s *BlockChainAPI) GetHeaderByHash(ctx context.Context, hash common.Hash) m
// - When fullTx is true all transactions in the block are returned, otherwise // - When fullTx is true all transactions in the block are returned, otherwise
// only the transaction hash is returned. // only the transaction hash is returned.
func (s *BlockChainAPI) GetBlockByNumber(ctx context.Context, number rpc.BlockNumber, fullTx bool) (map[string]interface{}, error) { func (s *BlockChainAPI) GetBlockByNumber(ctx context.Context, number rpc.BlockNumber, fullTx bool) (map[string]interface{}, error) {
block, err := s.b.BlockByNumber(ctx, number) block, _, err := s.b.BlockByNumber(ctx, number)
if block != nil && err == nil { if block != nil && err == nil {
response, err := s.rpcMarshalBlock(ctx, block, true, fullTx) response, err := s.rpcMarshalBlock(ctx, block, true, fullTx)
if err == nil && number == rpc.PendingBlockNumber { if err == nil && number == rpc.PendingBlockNumber {
@ -824,7 +824,7 @@ func (s *BlockChainAPI) GetBlockByNumber(ctx context.Context, number rpc.BlockNu
// GetBlockByHash returns the requested block. When fullTx is true all transactions in the block are returned in full // GetBlockByHash returns the requested block. When fullTx is true all transactions in the block are returned in full
// detail, otherwise only the transaction hash is returned. // detail, otherwise only the transaction hash is returned.
func (s *BlockChainAPI) GetBlockByHash(ctx context.Context, hash common.Hash, fullTx bool) (map[string]interface{}, error) { func (s *BlockChainAPI) GetBlockByHash(ctx context.Context, hash common.Hash, fullTx bool) (map[string]interface{}, error) {
block, err := s.b.BlockByHash(ctx, hash) block, _, err := s.b.BlockByHash(ctx, hash)
if block != nil { if block != nil {
return s.rpcMarshalBlock(ctx, block, true, fullTx) return s.rpcMarshalBlock(ctx, block, true, fullTx)
} }
@ -833,7 +833,7 @@ func (s *BlockChainAPI) GetBlockByHash(ctx context.Context, hash common.Hash, fu
// GetUncleByBlockNumberAndIndex returns the uncle block for the given block hash and index. // GetUncleByBlockNumberAndIndex returns the uncle block for the given block hash and index.
func (s *BlockChainAPI) GetUncleByBlockNumberAndIndex(ctx context.Context, blockNr rpc.BlockNumber, index hexutil.Uint) (map[string]interface{}, error) { func (s *BlockChainAPI) GetUncleByBlockNumberAndIndex(ctx context.Context, blockNr rpc.BlockNumber, index hexutil.Uint) (map[string]interface{}, error) {
block, err := s.b.BlockByNumber(ctx, blockNr) block, _, err := s.b.BlockByNumber(ctx, blockNr)
if block != nil { if block != nil {
uncles := block.Uncles() uncles := block.Uncles()
if index >= hexutil.Uint(len(uncles)) { if index >= hexutil.Uint(len(uncles)) {
@ -848,7 +848,7 @@ func (s *BlockChainAPI) GetUncleByBlockNumberAndIndex(ctx context.Context, block
// GetUncleByBlockHashAndIndex returns the uncle block for the given block hash and index. // GetUncleByBlockHashAndIndex returns the uncle block for the given block hash and index.
func (s *BlockChainAPI) GetUncleByBlockHashAndIndex(ctx context.Context, blockHash common.Hash, index hexutil.Uint) (map[string]interface{}, error) { func (s *BlockChainAPI) GetUncleByBlockHashAndIndex(ctx context.Context, blockHash common.Hash, index hexutil.Uint) (map[string]interface{}, error) {
block, err := s.b.BlockByHash(ctx, blockHash) block, _, err := s.b.BlockByHash(ctx, blockHash)
if block != nil { if block != nil {
uncles := block.Uncles() uncles := block.Uncles()
if index >= hexutil.Uint(len(uncles)) { if index >= hexutil.Uint(len(uncles)) {
@ -863,7 +863,7 @@ func (s *BlockChainAPI) GetUncleByBlockHashAndIndex(ctx context.Context, blockHa
// GetUncleCountByBlockNumber returns number of uncles in the block for the given block number // GetUncleCountByBlockNumber returns number of uncles in the block for the given block number
func (s *BlockChainAPI) GetUncleCountByBlockNumber(ctx context.Context, blockNr rpc.BlockNumber) *hexutil.Uint { func (s *BlockChainAPI) GetUncleCountByBlockNumber(ctx context.Context, blockNr rpc.BlockNumber) *hexutil.Uint {
if block, _ := s.b.BlockByNumber(ctx, blockNr); block != nil { if block, _, _ := s.b.BlockByNumber(ctx, blockNr); block != nil {
n := hexutil.Uint(len(block.Uncles())) n := hexutil.Uint(len(block.Uncles()))
return &n return &n
} }
@ -872,7 +872,7 @@ func (s *BlockChainAPI) GetUncleCountByBlockNumber(ctx context.Context, blockNr
// GetUncleCountByBlockHash returns number of uncles in the block for the given block hash // GetUncleCountByBlockHash returns number of uncles in the block for the given block hash
func (s *BlockChainAPI) GetUncleCountByBlockHash(ctx context.Context, blockHash common.Hash) *hexutil.Uint { func (s *BlockChainAPI) GetUncleCountByBlockHash(ctx context.Context, blockHash common.Hash) *hexutil.Uint {
if block, _ := s.b.BlockByHash(ctx, blockHash); block != nil { if block, _, _ := s.b.BlockByHash(ctx, blockHash); block != nil {
n := hexutil.Uint(len(block.Uncles())) n := hexutil.Uint(len(block.Uncles()))
return &n return &n
} }
@ -1619,7 +1619,7 @@ func NewTransactionAPI(b Backend, nonceLock *AddrLocker) *TransactionAPI {
// GetBlockTransactionCountByNumber returns the number of transactions in the block with the given block number. // GetBlockTransactionCountByNumber returns the number of transactions in the block with the given block number.
func (s *TransactionAPI) GetBlockTransactionCountByNumber(ctx context.Context, blockNr rpc.BlockNumber) *hexutil.Uint { func (s *TransactionAPI) GetBlockTransactionCountByNumber(ctx context.Context, blockNr rpc.BlockNumber) *hexutil.Uint {
if block, _ := s.b.BlockByNumber(ctx, blockNr); block != nil { if block, _, _ := s.b.BlockByNumber(ctx, blockNr); block != nil {
n := hexutil.Uint(len(block.Transactions())) n := hexutil.Uint(len(block.Transactions()))
return &n return &n
} }
@ -1628,7 +1628,7 @@ func (s *TransactionAPI) GetBlockTransactionCountByNumber(ctx context.Context, b
// GetBlockTransactionCountByHash returns the number of transactions in the block with the given hash. // GetBlockTransactionCountByHash returns the number of transactions in the block with the given hash.
func (s *TransactionAPI) GetBlockTransactionCountByHash(ctx context.Context, blockHash common.Hash) *hexutil.Uint { func (s *TransactionAPI) GetBlockTransactionCountByHash(ctx context.Context, blockHash common.Hash) *hexutil.Uint {
if block, _ := s.b.BlockByHash(ctx, blockHash); block != nil { if block, _, _ := s.b.BlockByHash(ctx, blockHash); block != nil {
n := hexutil.Uint(len(block.Transactions())) n := hexutil.Uint(len(block.Transactions()))
return &n return &n
} }
@ -1637,7 +1637,7 @@ func (s *TransactionAPI) GetBlockTransactionCountByHash(ctx context.Context, blo
// GetTransactionByBlockNumberAndIndex returns the transaction for the given block number and index. // GetTransactionByBlockNumberAndIndex returns the transaction for the given block number and index.
func (s *TransactionAPI) GetTransactionByBlockNumberAndIndex(ctx context.Context, blockNr rpc.BlockNumber, index hexutil.Uint) *RPCTransaction { func (s *TransactionAPI) GetTransactionByBlockNumberAndIndex(ctx context.Context, blockNr rpc.BlockNumber, index hexutil.Uint) *RPCTransaction {
if block, _ := s.b.BlockByNumber(ctx, blockNr); block != nil { if block, _, _ := s.b.BlockByNumber(ctx, blockNr); block != nil {
return newRPCTransactionFromBlockIndex(block, uint64(index), s.b.ChainConfig()) return newRPCTransactionFromBlockIndex(block, uint64(index), s.b.ChainConfig())
} }
return nil return nil
@ -1645,7 +1645,7 @@ func (s *TransactionAPI) GetTransactionByBlockNumberAndIndex(ctx context.Context
// GetTransactionByBlockHashAndIndex returns the transaction for the given block hash and index. // GetTransactionByBlockHashAndIndex returns the transaction for the given block hash and index.
func (s *TransactionAPI) GetTransactionByBlockHashAndIndex(ctx context.Context, blockHash common.Hash, index hexutil.Uint) *RPCTransaction { func (s *TransactionAPI) GetTransactionByBlockHashAndIndex(ctx context.Context, blockHash common.Hash, index hexutil.Uint) *RPCTransaction {
if block, _ := s.b.BlockByHash(ctx, blockHash); block != nil { if block, _, _ := s.b.BlockByHash(ctx, blockHash); block != nil {
return newRPCTransactionFromBlockIndex(block, uint64(index), s.b.ChainConfig()) return newRPCTransactionFromBlockIndex(block, uint64(index), s.b.ChainConfig())
} }
return nil return nil
@ -1653,7 +1653,7 @@ func (s *TransactionAPI) GetTransactionByBlockHashAndIndex(ctx context.Context,
// GetRawTransactionByBlockNumberAndIndex returns the bytes of the transaction for the given block number and index. // GetRawTransactionByBlockNumberAndIndex returns the bytes of the transaction for the given block number and index.
func (s *TransactionAPI) GetRawTransactionByBlockNumberAndIndex(ctx context.Context, blockNr rpc.BlockNumber, index hexutil.Uint) hexutil.Bytes { func (s *TransactionAPI) GetRawTransactionByBlockNumberAndIndex(ctx context.Context, blockNr rpc.BlockNumber, index hexutil.Uint) hexutil.Bytes {
if block, _ := s.b.BlockByNumber(ctx, blockNr); block != nil { if block, _, _ := s.b.BlockByNumber(ctx, blockNr); block != nil {
return newRPCRawTransactionFromBlockIndex(block, uint64(index)) return newRPCRawTransactionFromBlockIndex(block, uint64(index))
} }
return nil return nil
@ -1661,7 +1661,7 @@ func (s *TransactionAPI) GetRawTransactionByBlockNumberAndIndex(ctx context.Cont
// GetRawTransactionByBlockHashAndIndex returns the bytes of the transaction for the given block hash and index. // GetRawTransactionByBlockHashAndIndex returns the bytes of the transaction for the given block hash and index.
func (s *TransactionAPI) GetRawTransactionByBlockHashAndIndex(ctx context.Context, blockHash common.Hash, index hexutil.Uint) hexutil.Bytes { func (s *TransactionAPI) GetRawTransactionByBlockHashAndIndex(ctx context.Context, blockHash common.Hash, index hexutil.Uint) hexutil.Bytes {
if block, _ := s.b.BlockByHash(ctx, blockHash); block != nil { if block, _, _ := s.b.BlockByHash(ctx, blockHash); block != nil {
return newRPCRawTransactionFromBlockIndex(block, uint64(index)) return newRPCRawTransactionFromBlockIndex(block, uint64(index))
} }
return nil return nil
@ -2078,7 +2078,7 @@ func (api *DebugAPI) GetRawBlock(ctx context.Context, blockNrOrHash rpc.BlockNum
} }
hash = block.Hash() hash = block.Hash()
} }
block, _ := api.b.BlockByHash(ctx, hash) block, _, _ := api.b.BlockByHash(ctx, hash)
if block == nil { if block == nil {
return nil, fmt.Errorf("block #%d not found", hash) return nil, fmt.Errorf("block #%d not found", hash)
} }
@ -2130,7 +2130,7 @@ func (s *DebugAPI) GetRawTransaction(ctx context.Context, hash common.Hash) (hex
// PrintBlock retrieves a block and returns its pretty printed form. // PrintBlock retrieves a block and returns its pretty printed form.
func (api *DebugAPI) PrintBlock(ctx context.Context, number uint64) (string, error) { func (api *DebugAPI) PrintBlock(ctx context.Context, number uint64) (string, error) {
block, _ := api.b.BlockByNumber(ctx, rpc.BlockNumber(number)) block, _, _ := api.b.BlockByNumber(ctx, rpc.BlockNumber(number))
if block == nil { if block == nil {
return "", fmt.Errorf("block #%d not found", number) return "", fmt.Errorf("block #%d not found", number)
} }

View file

@ -42,6 +42,7 @@ import (
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/eth/tracers/tracersutils"
"github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/event" "github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/lib/blocktest" "github.com/ethereum/go-ethereum/lib/blocktest"
@ -475,25 +476,27 @@ func (b testBackend) HeaderByNumberOrHash(ctx context.Context, blockNrOrHash rpc
} }
func (b testBackend) CurrentHeader() *types.Header { return b.chain.CurrentBlock() } func (b testBackend) CurrentHeader() *types.Header { return b.chain.CurrentBlock() }
func (b testBackend) CurrentBlock() *types.Header { return b.chain.CurrentBlock() } func (b testBackend) CurrentBlock() *types.Header { return b.chain.CurrentBlock() }
func (b testBackend) BlockByNumber(ctx context.Context, number rpc.BlockNumber) (*types.Block, error) { func (b testBackend) BlockByNumber(ctx context.Context, number rpc.BlockNumber) (*types.Block, []tracersutils.TraceBlockMetadata, error) {
if number == rpc.LatestBlockNumber { if number == rpc.LatestBlockNumber {
head := b.chain.CurrentBlock() head := b.chain.CurrentBlock()
return b.chain.GetBlock(head.Hash(), head.Number.Uint64()), nil return b.chain.GetBlock(head.Hash(), head.Number.Uint64()), nil, nil
} }
if number == rpc.PendingBlockNumber { if number == rpc.PendingBlockNumber {
return b.pending, nil return b.pending, nil, nil
} }
return b.chain.GetBlockByNumber(uint64(number)), nil return b.chain.GetBlockByNumber(uint64(number)), nil, nil
} }
func (b testBackend) BlockByHash(ctx context.Context, hash common.Hash) (*types.Block, error) { func (b testBackend) BlockByHash(ctx context.Context, hash common.Hash) (*types.Block, []tracersutils.TraceBlockMetadata, error) {
return b.chain.GetBlockByHash(hash), nil return b.chain.GetBlockByHash(hash), nil, nil
} }
func (b testBackend) BlockByNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (*types.Block, error) { func (b testBackend) BlockByNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (*types.Block, error) {
if blockNr, ok := blockNrOrHash.Number(); ok { if blockNr, ok := blockNrOrHash.Number(); ok {
return b.BlockByNumber(ctx, blockNr) b, _, err := b.BlockByNumber(ctx, blockNr)
return b, err
} }
if blockHash, ok := blockNrOrHash.Hash(); ok { if blockHash, ok := blockNrOrHash.Hash(); ok {
return b.BlockByHash(ctx, blockHash) b, _, err := b.BlockByHash(ctx, blockHash)
return b, err
} }
panic("unknown type rpc.BlockNumberOrHash") panic("unknown type rpc.BlockNumberOrHash")
} }

View file

@ -30,6 +30,7 @@ import (
"github.com/ethereum/go-ethereum/core/bloombits" "github.com/ethereum/go-ethereum/core/bloombits"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/eth/tracers/tracersutils"
"github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/event" "github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/params"
@ -59,8 +60,8 @@ type Backend interface {
HeaderByNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (*types.Header, error) HeaderByNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (*types.Header, error)
CurrentHeader() *types.Header CurrentHeader() *types.Header
CurrentBlock() *types.Header CurrentBlock() *types.Header
BlockByNumber(ctx context.Context, number rpc.BlockNumber) (*types.Block, error) BlockByNumber(ctx context.Context, number rpc.BlockNumber) (*types.Block, []tracersutils.TraceBlockMetadata, error)
BlockByHash(ctx context.Context, hash common.Hash) (*types.Block, error) BlockByHash(ctx context.Context, hash common.Hash) (*types.Block, []tracersutils.TraceBlockMetadata, error)
BlockByNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (*types.Block, error) BlockByNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (*types.Block, error)
StateAndHeaderByNumber(ctx context.Context, number rpc.BlockNumber) (vm.StateDB, *types.Header, error) StateAndHeaderByNumber(ctx context.Context, number rpc.BlockNumber) (vm.StateDB, *types.Header, error)
StateAndHeaderByNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (vm.StateDB, *types.Header, error) StateAndHeaderByNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (vm.StateDB, *types.Header, error)

View file

@ -33,6 +33,7 @@ import (
"github.com/ethereum/go-ethereum/core/bloombits" "github.com/ethereum/go-ethereum/core/bloombits"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/eth/tracers/tracersutils"
"github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/event" "github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/params"
@ -278,11 +279,11 @@ func (b *backendMock) HeaderByNumberOrHash(ctx context.Context, blockNrOrHash rp
return nil, nil return nil, nil
} }
func (b *backendMock) CurrentBlock() *types.Header { return nil } func (b *backendMock) CurrentBlock() *types.Header { return nil }
func (b *backendMock) BlockByNumber(ctx context.Context, number rpc.BlockNumber) (*types.Block, error) { func (b *backendMock) BlockByNumber(ctx context.Context, number rpc.BlockNumber) (*types.Block, []tracersutils.TraceBlockMetadata, error) {
return nil, nil return nil, nil, nil
} }
func (b *backendMock) BlockByHash(ctx context.Context, hash common.Hash) (*types.Block, error) { func (b *backendMock) BlockByHash(ctx context.Context, hash common.Hash) (*types.Block, []tracersutils.TraceBlockMetadata, error) {
return nil, nil return nil, nil, nil
} }
func (b *backendMock) BlockByNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (*types.Block, error) { func (b *backendMock) BlockByNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (*types.Block, error) {
return nil, nil return nil, nil