mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-24 21:56:43 +00:00
Merge pull request #52 from sei-protocol/tony/adapt-traceBlock
process non-EVM txs during traceBlock
This commit is contained in:
commit
520314db05
13 changed files with 153 additions and 104 deletions
|
|
@ -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) {
|
||||||
|
|
|
||||||
|
|
@ -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"
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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()
|
||||||
|
|
|
||||||
|
|
@ -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}:
|
||||||
|
|
|
||||||
|
|
@ -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) {
|
||||||
|
|
|
||||||
|
|
@ -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")
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
11
eth/tracers/tracersutils/types.go
Normal file
11
eth/tracers/tracersutils/types.go
Normal 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)
|
||||||
|
}
|
||||||
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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")
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue