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

View file

@ -26,7 +26,7 @@ import (
"time"
"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/holiman/uint256"
"github.com/urfave/cli/v2"

View file

@ -34,6 +34,7 @@ import (
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/eth/gasprice"
"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/event"
"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
}
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
if number == rpc.PendingBlockNumber {
block := b.eth.miner.PendingBlock()
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
if number == rpc.LatestBlockNumber {
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 {
header := b.eth.blockchain.CurrentFinalBlock()
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 {
header := b.eth.blockchain.CurrentSafeBlock()
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) {
return b.eth.blockchain.GetBlockByHash(hash), nil
func (b *EthAPIBackend) BlockByHash(ctx context.Context, hash common.Hash) (*types.Block, []tracersutils.TraceBlockMetadata, error) {
return b.eth.blockchain.GetBlockByHash(hash), nil, nil
}
// 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) {
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 {
header := b.eth.blockchain.GetHeaderByHash(hash)

View file

@ -273,7 +273,7 @@ func (oracle *Oracle) FeeHistory(ctx context.Context, blocks uint64, unresolvedL
results <- fees
} else {
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 {
fees.receipts, fees.err = oracle.backend.GetReceipts(ctx, fees.block.Hash())
fees.header = fees.block.Header()

View file

@ -25,6 +25,7 @@ import (
"github.com/ethereum/go-ethereum/common/lru"
"github.com/ethereum/go-ethereum/core"
"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/log"
"github.com/ethereum/go-ethereum/params"
@ -52,7 +53,7 @@ type Config struct {
// OracleBackend includes all necessary background APIs for oracle.
type OracleBackend interface {
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)
PendingBlockAndReceipts() (*types.Block, types.Receipts)
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
// 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{}) {
block, err := oracle.backend.BlockByNumber(ctx, rpc.BlockNumber(blockNum))
block, _, err := oracle.backend.BlockByNumber(ctx, rpc.BlockNumber(blockNum))
if block == nil {
select {
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/vm"
"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/params"
"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
}
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 {
return nil, nil
return nil, nil, nil
}
if number == rpc.EarliestBlockNumber {
number = 0
@ -87,10 +88,10 @@ func (b *testBackend) BlockByNumber(ctx context.Context, number rpc.BlockNumber)
if b.pending {
number = testHead + 1
} 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) {

View file

@ -38,6 +38,7 @@ import (
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm"
"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/lib/ethapi"
"github.com/ethereum/go-ethereum/log"
@ -80,8 +81,8 @@ type StateReleaseFunc func()
type Backend interface {
HeaderByHash(ctx context.Context, hash common.Hash) (*types.Header, error)
HeaderByNumber(ctx context.Context, number rpc.BlockNumber) (*types.Header, error)
BlockByHash(ctx context.Context, hash common.Hash) (*types.Block, error)
BlockByNumber(ctx context.Context, number rpc.BlockNumber) (*types.Block, error)
BlockByHash(ctx context.Context, hash common.Hash) (*types.Block, []tracersutils.TraceBlockMetadata, 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)
RPCGasCap() uint64
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.
// It will return an error if the block is not found.
func (api *API) blockByNumber(ctx context.Context, number rpc.BlockNumber) (*types.Block, error) {
block, err := api.backend.BlockByNumber(ctx, number)
func (api *API) blockByNumber(ctx context.Context, number rpc.BlockNumber) (*types.Block, []tracersutils.TraceBlockMetadata, error) {
block, metadata, err := api.backend.BlockByNumber(ctx, number)
if err != nil {
return nil, err
return nil, nil, err
}
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.
// It will return an error if the block is not found.
func (api *API) blockByHash(ctx context.Context, hash common.Hash) (*types.Block, error) {
block, err := api.backend.BlockByHash(ctx, hash)
func (api *API) blockByHash(ctx context.Context, hash common.Hash) (*types.Block, []tracersutils.TraceBlockMetadata, error) {
block, metadata, err := api.backend.BlockByHash(ctx, hash)
if err != nil {
return nil, err
return nil, nil, err
}
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
@ -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
// historical(before the CHT) header/block by number.
func (api *API) blockByNumberAndHash(ctx context.Context, number rpc.BlockNumber, hash common.Hash) (*types.Block, error) {
block, err := api.blockByNumber(ctx, number)
func (api *API) blockByNumberAndHash(ctx context.Context, number rpc.BlockNumber, hash common.Hash) (*types.Block, []tracersutils.TraceBlockMetadata, error) {
block, metadata, err := api.blockByNumber(ctx, number)
if err != nil {
return nil, err
return nil, nil, err
}
if block.Hash() == hash {
return block, nil
return block, metadata, nil
}
return api.blockByHash(ctx, hash)
}
@ -213,11 +214,11 @@ type txTraceTask struct {
// TraceChain returns the structured logs created during the execution of EVM
// 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
from, err := api.blockByNumber(ctx, start)
from, _, err := api.blockByNumber(ctx, start)
if err != nil {
return nil, err
}
to, err := api.blockByNumber(ctx, end)
to, _, err := api.blockByNumber(ctx, end)
if err != nil {
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))
}
// 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 {
failed = err
break
}
next, err := api.blockByNumber(ctx, rpc.BlockNumber(number+1))
next, _, err := api.blockByNumber(ctx, rpc.BlockNumber(number+1))
if err != nil {
failed = err
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
// EVM and returns them as a JSON object.
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 {
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
// EVM and returns them as a JSON object.
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 {
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
@ -459,7 +460,7 @@ func (api *API) TraceBlock(ctx context.Context, blob hexutil.Bytes, config *Trac
if err := rlp.DecodeBytes(blob, block); err != nil {
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
@ -480,14 +481,14 @@ func (api *API) TraceBadBlock(ctx context.Context, hash common.Hash, config *Tra
if block == nil {
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
// execution of EVM to the local file system and returns a list of files
// to the caller.
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 {
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
// of intermediate roots: the stateroot after each transaction.
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 {
// Check in the bad blocks
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 {
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 {
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
// executes all the transactions contained within. The return value will be one item
// 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 {
return nil, errors.New("genesis is not traceable")
}
// 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 {
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())
results = make([]*TxTraceResult, len(txs))
)
for i, tx := range txs {
// 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(),
if len(metadata) == 0 {
for i, tx := range txs {
// 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}
}
}
res, err := api.traceTx(ctx, tx, msg, txctx, blockCtx, statedb, config)
if err != nil {
results[i] = &TxTraceResult{TxHash: tx.Hash(), Error: err.Error()}
return results, nil
}
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 {
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
@ -729,7 +757,7 @@ func (api *API) standardTraceBlockToFile(ctx context.Context, block *types.Block
if block.NumberU64() == 0 {
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 {
return nil, err
}
@ -868,7 +896,7 @@ func (api *API) TraceTransaction(ctx context.Context, hash common.Hash, config *
if config != nil && config.Reexec != nil {
reexec = *config.Reexec
}
block, err := api.blockByNumberAndHash(ctx, rpc.BlockNumber(blockNumber), blockHash)
block, _, err := api.blockByNumberAndHash(ctx, rpc.BlockNumber(blockNumber), blockHash)
if err != nil {
return nil, err
}
@ -913,7 +941,7 @@ func (api *API) TraceCall(ctx context.Context, args ethapi.TransactionArgs, bloc
release StateReleaseFunc
)
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 {
if number == rpc.PendingBlockNumber {
// 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.
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 {
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/crypto"
"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/lib/ethapi"
"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
}
func (b *testBackend) BlockByHash(ctx context.Context, hash common.Hash) (*types.Block, error) {
return b.chain.GetBlockByHash(hash), nil
func (b *testBackend) BlockByHash(ctx context.Context, hash common.Hash) (*types.Block, []tracersutils.TraceBlockMetadata, error) {
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 {
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) {
@ -1043,8 +1044,8 @@ func TestTraceChain(t *testing.T) {
ref.Store(0)
rel.Store(0)
from, _ := api.blockByNumber(context.Background(), rpc.BlockNumber(c.start))
to, _ := api.blockByNumber(context.Background(), rpc.BlockNumber(c.end))
from, _, _ := api.blockByNumber(context.Background(), rpc.BlockNumber(c.start))
to, _, _ := api.blockByNumber(context.Background(), rpc.BlockNumber(c.end))
resCh := api.traceChain(from, to, c.config, nil)
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
// only the transaction hash is returned.
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 {
response, err := s.rpcMarshalBlock(ctx, block, true, fullTx)
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
// detail, otherwise only the transaction hash is returned.
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 {
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.
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 {
uncles := block.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.
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 {
uncles := block.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
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()))
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
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()))
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.
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()))
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.
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()))
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.
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 nil
@ -1645,7 +1645,7 @@ func (s *TransactionAPI) GetTransactionByBlockNumberAndIndex(ctx context.Context
// 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 {
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 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.
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 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.
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 nil
@ -2078,7 +2078,7 @@ func (api *DebugAPI) GetRawBlock(ctx context.Context, blockNrOrHash rpc.BlockNum
}
hash = block.Hash()
}
block, _ := api.b.BlockByHash(ctx, hash)
block, _, _ := api.b.BlockByHash(ctx, hash)
if block == nil {
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.
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 {
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/vm"
"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/event"
"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) 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 {
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 {
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) {
return b.chain.GetBlockByHash(hash), nil
func (b testBackend) BlockByHash(ctx context.Context, hash common.Hash) (*types.Block, []tracersutils.TraceBlockMetadata, error) {
return b.chain.GetBlockByHash(hash), nil, nil
}
func (b testBackend) BlockByNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (*types.Block, error) {
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 {
return b.BlockByHash(ctx, blockHash)
b, _, err := b.BlockByHash(ctx, blockHash)
return b, err
}
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/types"
"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/event"
"github.com/ethereum/go-ethereum/params"
@ -59,8 +60,8 @@ type Backend interface {
HeaderByNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (*types.Header, error)
CurrentHeader() *types.Header
CurrentBlock() *types.Header
BlockByNumber(ctx context.Context, number rpc.BlockNumber) (*types.Block, error)
BlockByHash(ctx context.Context, hash common.Hash) (*types.Block, error)
BlockByNumber(ctx context.Context, number rpc.BlockNumber) (*types.Block, []tracersutils.TraceBlockMetadata, error)
BlockByHash(ctx context.Context, hash common.Hash) (*types.Block, []tracersutils.TraceBlockMetadata, error)
BlockByNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (*types.Block, 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)

View file

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