mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-27 15:16:43 +00:00
Backported a bunch more of eth/tracers
This commit is contained in:
parent
17fcdfaadf
commit
f596461a23
21 changed files with 558 additions and 88 deletions
|
|
@ -23,6 +23,8 @@ import (
|
|||
"math/big"
|
||||
"reflect"
|
||||
"strconv"
|
||||
|
||||
"github.com/holiman/uint256"
|
||||
)
|
||||
|
||||
var (
|
||||
|
|
@ -30,6 +32,7 @@ var (
|
|||
bigT = reflect.TypeOf((*Big)(nil))
|
||||
uintT = reflect.TypeOf(Uint(0))
|
||||
uint64T = reflect.TypeOf(Uint64(0))
|
||||
u256T = reflect.TypeOf((*uint256.Int)(nil))
|
||||
)
|
||||
|
||||
// Bytes marshals/unmarshals as a JSON string with 0x prefix.
|
||||
|
|
@ -91,6 +94,48 @@ func (b *Bytes) UnmarshalGraphQL(input interface{}) error {
|
|||
return err
|
||||
}
|
||||
|
||||
// U256 marshals/unmarshals as a JSON string with 0x prefix.
|
||||
// The zero value marshals as "0x0".
|
||||
type U256 uint256.Int
|
||||
|
||||
// MarshalText implements encoding.TextMarshaler
|
||||
func (b U256) MarshalText() ([]byte, error) {
|
||||
u256 := (*uint256.Int)(&b)
|
||||
return []byte(u256.Hex()), nil
|
||||
}
|
||||
|
||||
// UnmarshalJSON implements json.Unmarshaler.
|
||||
func (b *U256) UnmarshalJSON(input []byte) error {
|
||||
// The uint256.Int.UnmarshalJSON method accepts "dec", "0xhex"; we must be
|
||||
// more strict, hence we check string and invoke SetFromHex directly.
|
||||
if !isString(input) {
|
||||
return errNonString(u256T)
|
||||
}
|
||||
// The hex decoder needs to accept empty string ("") as '0', which uint256.Int
|
||||
// would reject.
|
||||
if len(input) == 2 {
|
||||
(*uint256.Int)(b).Clear()
|
||||
return nil
|
||||
}
|
||||
err := (*uint256.Int)(b).SetFromHex(string(input[1 : len(input)-1]))
|
||||
if err != nil {
|
||||
return &json.UnmarshalTypeError{Value: err.Error(), Type: u256T}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// UnmarshalText implements encoding.TextUnmarshaler
|
||||
func (b *U256) UnmarshalText(input []byte) error {
|
||||
// The uint256.Int.UnmarshalText method accepts "dec", "0xhex"; we must be
|
||||
// more strict, hence we check string and invoke SetFromHex directly.
|
||||
return (*uint256.Int)(b).SetFromHex(string(input))
|
||||
}
|
||||
|
||||
// String returns the hex encoding of b.
|
||||
func (b *U256) String() string {
|
||||
return (*uint256.Int)(b).Hex()
|
||||
}
|
||||
|
||||
// UnmarshalFixedJSON decodes the input as a string with 0x prefix. The length of out
|
||||
// determines the required input length. This function is commonly used to implement the
|
||||
// UnmarshalJSON method for fixed-size types.
|
||||
|
|
|
|||
|
|
@ -43,6 +43,12 @@ import (
|
|||
|
||||
var errGenesisNoConfig = errors.New("genesis has no chain configuration")
|
||||
|
||||
// use types.GenesisAccount instead (Deprecation not ported from latest Geth for now).
|
||||
type GenesisAccount = types.Account
|
||||
|
||||
// use types.GenesisAlloc instead (Deprecation not ported from latest Geth for now).
|
||||
type GenesisAlloc = types.GenesisAlloc
|
||||
|
||||
// Genesis specifies the header fields, state of a genesis block. It also defines hard
|
||||
// fork switch-over blocks through the chain configuration.
|
||||
type Genesis struct {
|
||||
|
|
@ -104,12 +110,6 @@ func ReadGenesis(db ethdb.Database) (*Genesis, error) {
|
|||
return &genesis, nil
|
||||
}
|
||||
|
||||
// Deprecated: use types.GenesisAccount instead.
|
||||
type GenesisAccount = types.Account
|
||||
|
||||
// Deprecated: use types.GenesisAlloc instead.
|
||||
type GenesisAlloc = types.GenesisAlloc
|
||||
|
||||
// hashAlloc computes the state root according to the genesis specification.
|
||||
func hashAlloc(ga *types.GenesisAlloc) (common.Hash, error) {
|
||||
// Create an ephemeral in-memory database for computing hash,
|
||||
|
|
|
|||
|
|
@ -56,7 +56,8 @@ type DumpAccount struct {
|
|||
Code hexutil.Bytes `json:"code,omitempty"`
|
||||
Storage map[common.Hash]string `json:"storage,omitempty"`
|
||||
Address *common.Address `json:"address,omitempty"` // Address only present in iterative (line-by-line) mode
|
||||
AddressHash hexutil.Bytes `json:"key,omitempty"` // If we don't have address, we can output the key
|
||||
SecureKey hexutil.Bytes `json:"key,omitempty"` // If we don't have address, we can output the key
|
||||
|
||||
}
|
||||
|
||||
// Dump represents the full dump in a collected format, as one large map.
|
||||
|
|
@ -110,6 +111,7 @@ func (d iterativeDump) OnAccount(addr *common.Address, account DumpAccount) {
|
|||
CodeHash: account.CodeHash,
|
||||
Code: account.Code,
|
||||
Storage: account.Storage,
|
||||
SecureKey: account.SecureKey,
|
||||
Address: addr,
|
||||
}
|
||||
d.Encode(dumpAccount)
|
||||
|
|
@ -153,6 +155,7 @@ func (s *StateDB) DumpToCollector(c DumpCollector, conf *DumpConfig) (nextKey []
|
|||
Nonce: data.Nonce,
|
||||
Root: data.Root[:],
|
||||
CodeHash: data.CodeHash,
|
||||
SecureKey: it.Key,
|
||||
}
|
||||
var (
|
||||
addrBytes = s.trie.GetKey(it.Key)
|
||||
|
|
|
|||
|
|
@ -412,6 +412,6 @@ func (b *EthAPIBackend) StateAtBlock(ctx context.Context, block *types.Block, re
|
|||
return b.eth.stateAtBlock(ctx, block, reexec, base, readOnly, preferDisk)
|
||||
}
|
||||
|
||||
func (b *EthAPIBackend) StateAtTransaction(ctx context.Context, block *types.Block, txIndex int, reexec uint64) (*core.Message, vm.BlockContext, *state.StateDB, tracers.StateReleaseFunc, error) {
|
||||
func (b *EthAPIBackend) StateAtTransaction(ctx context.Context, block *types.Block, txIndex int, reexec uint64) (*types.Transaction, vm.BlockContext, *state.StateDB, tracers.StateReleaseFunc, error) {
|
||||
return b.eth.stateAtTransaction(ctx, block, txIndex, reexec)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -216,7 +216,7 @@ func (eth *Ethereum) stateAtBlock(ctx context.Context, block *types.Block, reexe
|
|||
}
|
||||
|
||||
// stateAtTransaction returns the execution environment of a certain transaction.
|
||||
func (eth *Ethereum) stateAtTransaction(ctx context.Context, block *types.Block, txIndex int, reexec uint64) (*core.Message, vm.BlockContext, *state.StateDB, tracers.StateReleaseFunc, error) {
|
||||
func (eth *Ethereum) stateAtTransaction(ctx context.Context, block *types.Block, txIndex int, reexec uint64) (*types.Transaction, vm.BlockContext, *state.StateDB, tracers.StateReleaseFunc, error) {
|
||||
// Short circuit if it's genesis block.
|
||||
if block.NumberU64() == 0 {
|
||||
return nil, vm.BlockContext{}, nil, nil, errors.New("no transaction in genesis")
|
||||
|
|
@ -243,7 +243,7 @@ func (eth *Ethereum) stateAtTransaction(ctx context.Context, block *types.Block,
|
|||
txContext := core.NewEVMTxContext(msg)
|
||||
context := core.NewEVMBlockContext(block.Header(), eth.blockchain, nil)
|
||||
if idx == txIndex {
|
||||
return msg, context, statedb, release, nil
|
||||
return tx, context, statedb, release, nil
|
||||
}
|
||||
// Not yet the searched for transaction, execute on top of the current state
|
||||
vmenv := vm.NewEVM(context, txContext, statedb, eth.blockchain.Config(), vm.Config{})
|
||||
|
|
|
|||
|
|
@ -88,7 +88,7 @@ type Backend interface {
|
|||
Engine() consensus.Engine
|
||||
ChainDb() ethdb.Database
|
||||
StateAtBlock(ctx context.Context, block *types.Block, reexec uint64, base *state.StateDB, readOnly bool, preferDisk bool) (*state.StateDB, StateReleaseFunc, error)
|
||||
StateAtTransaction(ctx context.Context, block *types.Block, txIndex int, reexec uint64) (*core.Message, vm.BlockContext, *state.StateDB, StateReleaseFunc, error)
|
||||
StateAtTransaction(ctx context.Context, block *types.Block, txIndex int, reexec uint64) (*types.Transaction, vm.BlockContext, *state.StateDB, StateReleaseFunc, error)
|
||||
}
|
||||
|
||||
// API is the collection of tracing APIs exposed over the private debugging endpoint.
|
||||
|
|
@ -166,6 +166,7 @@ type TraceCallConfig struct {
|
|||
TraceConfig
|
||||
StateOverrides *ethapi.StateOverride
|
||||
BlockOverrides *ethapi.BlockOverrides
|
||||
TxIndex *hexutil.Uint
|
||||
}
|
||||
|
||||
// StdTraceConfig holds extra parameters to standard-json trace functions.
|
||||
|
|
@ -227,7 +228,7 @@ func (api *API) TraceChain(ctx context.Context, start, end rpc.BlockNumber, conf
|
|||
}
|
||||
sub := notifier.CreateSubscription()
|
||||
|
||||
resCh := api.traceChain(from, to, config, notifier.Closed())
|
||||
resCh := api.traceChain(from, to, config, sub.Err())
|
||||
go func() {
|
||||
for result := range resCh {
|
||||
notifier.Notify(sub.ID, result)
|
||||
|
|
@ -241,7 +242,7 @@ func (api *API) TraceChain(ctx context.Context, start, end rpc.BlockNumber, conf
|
|||
// the end block but excludes the start one. The return value will be one item per
|
||||
// transaction, dependent on the requested tracer.
|
||||
// The tracing procedure should be aborted in case the closed signal is received.
|
||||
func (api *API) traceChain(start, end *types.Block, config *TraceConfig, closed <-chan interface{}) chan *blockTraceResult {
|
||||
func (api *API) traceChain(start, end *types.Block, config *TraceConfig, closed <-chan error) chan *blockTraceResult {
|
||||
reexec := defaultTraceReexec
|
||||
if config != nil && config.Reexec != nil {
|
||||
reexec = *config.Reexec
|
||||
|
|
@ -278,7 +279,7 @@ func (api *API) traceChain(start, end *types.Block, config *TraceConfig, closed
|
|||
TxIndex: i,
|
||||
TxHash: tx.Hash(),
|
||||
}
|
||||
res, err := api.traceTx(ctx, msg, txctx, blockCtx, task.statedb, config)
|
||||
res, err := api.traceTx(ctx, tx, msg, txctx, blockCtx, task.statedb, config)
|
||||
if err != nil {
|
||||
task.results[i] = &txTraceResult{TxHash: tx.Hash(), Error: err.Error()}
|
||||
log.Warn("Tracing failed", "hash", tx.Hash(), "block", task.block.NumberU64(), "err", err)
|
||||
|
|
@ -610,7 +611,7 @@ func (api *API) traceBlock(ctx context.Context, block *types.Block, config *Trac
|
|||
TxIndex: i,
|
||||
TxHash: tx.Hash(),
|
||||
}
|
||||
res, err := api.traceTx(ctx, msg, txctx, blockCtx, statedb, config)
|
||||
res, err := api.traceTx(ctx, tx, msg, txctx, blockCtx, statedb, config)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
@ -627,7 +628,6 @@ func (api *API) traceBlockParallel(ctx context.Context, block *types.Block, stat
|
|||
var (
|
||||
txs = block.Transactions()
|
||||
blockHash = block.Hash()
|
||||
blockCtx = core.NewEVMBlockContext(block.Header(), api.chainContext(ctx), nil)
|
||||
signer = types.MakeSigner(api.backend.ChainConfig(), block.Number(), block.Time())
|
||||
results = make([]*txTraceResult, len(txs))
|
||||
pend sync.WaitGroup
|
||||
|
|
@ -650,7 +650,12 @@ func (api *API) traceBlockParallel(ctx context.Context, block *types.Block, stat
|
|||
TxIndex: task.index,
|
||||
TxHash: txs[task.index].Hash(),
|
||||
}
|
||||
res, err := api.traceTx(ctx, msg, txctx, blockCtx, task.statedb, config)
|
||||
// Reconstruct the block context for each transaction
|
||||
// as the GetHash function of BlockContext is not safe for
|
||||
// concurrent use.
|
||||
// See: https://github.com/ethereum/go-ethereum/issues/29114
|
||||
blockCtx := core.NewEVMBlockContext(block.Header(), api.chainContext(ctx), nil)
|
||||
res, err := api.traceTx(ctx, txs[task.index], msg, txctx, blockCtx, task.statedb, config)
|
||||
if err != nil {
|
||||
results[task.index] = &txTraceResult{TxHash: txs[task.index].Hash(), Error: err.Error()}
|
||||
continue
|
||||
|
|
@ -662,6 +667,7 @@ func (api *API) traceBlockParallel(ctx context.Context, block *types.Block, stat
|
|||
|
||||
// Feed the transactions into the tracers and return
|
||||
var failed error
|
||||
blockCtx := core.NewEVMBlockContext(block.Header(), api.chainContext(ctx), nil)
|
||||
txloop:
|
||||
for i, tx := range txs {
|
||||
// Send the trace task over for execution
|
||||
|
|
@ -843,11 +849,15 @@ func (api *API) TraceTransaction(ctx context.Context, hash common.Hash, config *
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
msg, vmctx, statedb, release, err := api.backend.StateAtTransaction(ctx, block, int(index), reexec)
|
||||
tx, vmctx, statedb, release, err := api.backend.StateAtTransaction(ctx, block, int(index), reexec)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer release()
|
||||
msg, err := core.TransactionToMessage(tx, types.MakeSigner(api.backend.ChainConfig(), block.Number(), block.Time()), block.BaseFee())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
txctx := &directory.Context{
|
||||
BlockHash: blockHash,
|
||||
|
|
@ -855,17 +865,23 @@ func (api *API) TraceTransaction(ctx context.Context, hash common.Hash, config *
|
|||
TxIndex: int(index),
|
||||
TxHash: hash,
|
||||
}
|
||||
return api.traceTx(ctx, msg, txctx, vmctx, statedb, config)
|
||||
return api.traceTx(ctx, tx, msg, txctx, vmctx, statedb, config)
|
||||
}
|
||||
|
||||
// TraceCall lets you trace a given eth_call. It collects the structured logs
|
||||
// created during the execution of EVM if the given transaction was added on
|
||||
// top of the provided block and returns them as a JSON object.
|
||||
// If no transaction index is specified, the trace will be conducted on the state
|
||||
// after executing the specified block. However, if a transaction index is provided,
|
||||
// the trace will be conducted on the state after executing the specified transaction
|
||||
// within the specified block.
|
||||
func (api *API) TraceCall(ctx context.Context, args ethapi.TransactionArgs, blockNrOrHash rpc.BlockNumberOrHash, config *TraceCallConfig) (interface{}, error) {
|
||||
// Try to retrieve the specified block
|
||||
var (
|
||||
err error
|
||||
block *types.Block
|
||||
statedb *state.StateDB
|
||||
release StateReleaseFunc
|
||||
)
|
||||
if hash, ok := blockNrOrHash.Hash(); ok {
|
||||
block, err = api.blockByHash(ctx, hash)
|
||||
|
|
@ -890,7 +906,12 @@ func (api *API) TraceCall(ctx context.Context, args ethapi.TransactionArgs, bloc
|
|||
if config != nil && config.Reexec != nil {
|
||||
reexec = *config.Reexec
|
||||
}
|
||||
statedb, release, err := api.backend.StateAtBlock(ctx, block, reexec, nil, true, false)
|
||||
|
||||
if config != nil && config.TxIndex != nil {
|
||||
_, _, statedb, release, err = api.backend.StateAtTransaction(ctx, block, int(*config.TxIndex), reexec)
|
||||
} else {
|
||||
statedb, release, err = api.backend.StateAtBlock(ctx, block, reexec, nil, true, false)
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
@ -905,26 +926,30 @@ func (api *API) TraceCall(ctx context.Context, args ethapi.TransactionArgs, bloc
|
|||
config.BlockOverrides.Apply(&vmctx)
|
||||
}
|
||||
// Execute the trace
|
||||
msg, err := args.ToMessage(api.backend.RPCGasCap(), block.BaseFee())
|
||||
msg, err := args.ToMessage(api.backend.RPCGasCap(), vmctx.BaseFee)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
tx, err := argsToTransaction(api.backend, &args, msg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var traceConfig *TraceConfig
|
||||
if config != nil {
|
||||
traceConfig = &config.TraceConfig
|
||||
}
|
||||
return api.traceTx(ctx, msg, new(directory.Context), vmctx, statedb, traceConfig)
|
||||
return api.traceTx(ctx, tx, msg, new(directory.Context), vmctx, statedb, traceConfig)
|
||||
}
|
||||
|
||||
// traceTx configures a new tracer according to the provided configuration, and
|
||||
// executes the given message in the provided environment. The return value will
|
||||
// be tracer dependent.
|
||||
func (api *API) traceTx(ctx context.Context, message *core.Message, txctx *directory.Context, vmctx vm.BlockContext, statedb *state.StateDB, config *TraceConfig) (interface{}, error) {
|
||||
func (api *API) traceTx(ctx context.Context, tx *types.Transaction, message *core.Message, txctx *directory.Context, vmctx vm.BlockContext, statedb *state.StateDB, config *TraceConfig) (interface{}, error) {
|
||||
var (
|
||||
tracer *directory.Tracer
|
||||
err error
|
||||
timeout = defaultTraceTimeout
|
||||
usedGas uint64
|
||||
)
|
||||
if config == nil {
|
||||
config = &TraceConfig{}
|
||||
|
|
@ -959,7 +984,8 @@ func (api *API) traceTx(ctx context.Context, message *core.Message, txctx *direc
|
|||
|
||||
// Call Prepare to clear out the statedb access list
|
||||
statedb.SetTxContext(txctx.TxHash, txctx.TxIndex)
|
||||
if _, err = core.ApplyMessage(vmenv, message, new(core.GasPool).AddGas(message.GasLimit)); err != nil {
|
||||
_, err = core.ApplyTransactionWithEVM(message, api.backend.ChainConfig(), new(core.GasPool).AddGas(message.GasLimit), statedb, vmctx.BlockNumber, txctx.BlockHash, tx, &usedGas, vmenv)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("tracing failed: %w", err)
|
||||
}
|
||||
return tracer.GetResult()
|
||||
|
|
@ -1024,3 +1050,54 @@ func overrideConfig(original *params.ChainConfig, override *params.ChainConfig)
|
|||
|
||||
return copy, canon
|
||||
}
|
||||
|
||||
// argsToTransaction produces a Transaction object given call arguments.
|
||||
// The `msg` field must be converted from the same arguments.
|
||||
func argsToTransaction(b Backend, args *ethapi.TransactionArgs, msg *core.Message) (*types.Transaction, error) {
|
||||
chainID := b.ChainConfig().ChainID
|
||||
if args.ChainID != nil {
|
||||
if have := (*big.Int)(args.ChainID); have.Cmp(chainID) != 0 {
|
||||
return nil, fmt.Errorf("chainId does not match node's (have=%v, want=%v)", have, chainID)
|
||||
}
|
||||
}
|
||||
var data types.TxData
|
||||
switch {
|
||||
case args.MaxFeePerGas != nil:
|
||||
al := types.AccessList{}
|
||||
if args.AccessList != nil {
|
||||
al = *args.AccessList
|
||||
}
|
||||
data = &types.DynamicFeeTx{
|
||||
To: args.To,
|
||||
ChainID: chainID,
|
||||
Nonce: msg.Nonce,
|
||||
Gas: msg.GasLimit,
|
||||
GasFeeCap: msg.GasFeeCap,
|
||||
GasTipCap: msg.GasTipCap,
|
||||
Value: msg.Value,
|
||||
Data: msg.Data,
|
||||
AccessList: al,
|
||||
}
|
||||
case args.AccessList != nil:
|
||||
data = &types.AccessListTx{
|
||||
To: args.To,
|
||||
ChainID: chainID,
|
||||
Nonce: msg.Nonce,
|
||||
Gas: msg.GasLimit,
|
||||
GasPrice: msg.GasPrice,
|
||||
Value: msg.Value,
|
||||
Data: msg.Data,
|
||||
AccessList: *args.AccessList,
|
||||
}
|
||||
default:
|
||||
data = &types.LegacyTx{
|
||||
To: args.To,
|
||||
Nonce: msg.Nonce,
|
||||
Gas: msg.GasLimit,
|
||||
GasPrice: msg.GasPrice,
|
||||
Value: msg.Value,
|
||||
Data: msg.Data,
|
||||
}
|
||||
}
|
||||
return types.NewTx(data), nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -155,7 +155,7 @@ func (b *testBackend) StateAtBlock(ctx context.Context, block *types.Block, reex
|
|||
return statedb, release, nil
|
||||
}
|
||||
|
||||
func (b *testBackend) StateAtTransaction(ctx context.Context, block *types.Block, txIndex int, reexec uint64) (*core.Message, vm.BlockContext, *state.StateDB, StateReleaseFunc, error) {
|
||||
func (b *testBackend) StateAtTransaction(ctx context.Context, block *types.Block, txIndex int, reexec uint64) (*types.Transaction, vm.BlockContext, *state.StateDB, StateReleaseFunc, error) {
|
||||
parent := b.chain.GetBlock(block.ParentHash(), block.NumberU64()-1)
|
||||
if parent == nil {
|
||||
return nil, vm.BlockContext{}, nil, nil, errBlockNotFound
|
||||
|
|
@ -174,7 +174,7 @@ func (b *testBackend) StateAtTransaction(ctx context.Context, block *types.Block
|
|||
txContext := core.NewEVMTxContext(msg)
|
||||
context := core.NewEVMBlockContext(block.Header(), b.chain, nil)
|
||||
if idx == txIndex {
|
||||
return msg, context, statedb, release, nil
|
||||
return tx, context, statedb, release, nil
|
||||
}
|
||||
vmenv := vm.NewEVM(context, txContext, statedb, b.chainConfig, vm.Config{})
|
||||
if _, err := core.ApplyMessage(vmenv, msg, new(core.GasPool).AddGas(tx.Gas())); err != nil {
|
||||
|
|
@ -192,7 +192,7 @@ func TestTraceCall(t *testing.T) {
|
|||
accounts := newAccounts(3)
|
||||
genesis := &core.Genesis{
|
||||
Config: params.TestChainConfig,
|
||||
Alloc: core.GenesisAlloc{
|
||||
Alloc: types.GenesisAlloc{
|
||||
accounts[0].addr: {Balance: big.NewInt(params.Ether)},
|
||||
accounts[1].addr: {Balance: big.NewInt(params.Ether)},
|
||||
accounts[2].addr: {Balance: big.NewInt(params.Ether)},
|
||||
|
|
@ -200,13 +200,51 @@ func TestTraceCall(t *testing.T) {
|
|||
}
|
||||
genBlocks := 10
|
||||
signer := types.HomesteadSigner{}
|
||||
nonce := uint64(0)
|
||||
backend := newTestBackend(t, genBlocks, genesis, func(i int, b *core.BlockGen) {
|
||||
// Transfer from account[0] to account[1]
|
||||
// value: 1000 wei
|
||||
// fee: 0 wei
|
||||
tx, _ := types.SignTx(types.NewTransaction(uint64(i), accounts[1].addr, big.NewInt(1000), params.TxGas, b.BaseFee(), nil), signer, accounts[0].key)
|
||||
tx, _ := types.SignTx(types.NewTx(&types.LegacyTx{
|
||||
Nonce: nonce,
|
||||
To: &accounts[1].addr,
|
||||
Value: big.NewInt(1000),
|
||||
Gas: params.TxGas,
|
||||
GasPrice: b.BaseFee(),
|
||||
Data: nil}),
|
||||
signer, accounts[0].key)
|
||||
b.AddTx(tx)
|
||||
nonce++
|
||||
|
||||
if i == genBlocks-2 {
|
||||
// Transfer from account[0] to account[2]
|
||||
tx, _ = types.SignTx(types.NewTx(&types.LegacyTx{
|
||||
Nonce: nonce,
|
||||
To: &accounts[2].addr,
|
||||
Value: big.NewInt(1000),
|
||||
Gas: params.TxGas,
|
||||
GasPrice: b.BaseFee(),
|
||||
Data: nil}),
|
||||
signer, accounts[0].key)
|
||||
b.AddTx(tx)
|
||||
nonce++
|
||||
|
||||
// Transfer from account[0] to account[1] again
|
||||
tx, _ = types.SignTx(types.NewTx(&types.LegacyTx{
|
||||
Nonce: nonce,
|
||||
To: &accounts[1].addr,
|
||||
Value: big.NewInt(1000),
|
||||
Gas: params.TxGas,
|
||||
GasPrice: b.BaseFee(),
|
||||
Data: nil}),
|
||||
signer, accounts[0].key)
|
||||
b.AddTx(tx)
|
||||
nonce++
|
||||
}
|
||||
})
|
||||
|
||||
uintPtr := func(i int) *hexutil.Uint { x := hexutil.Uint(i); return &x }
|
||||
|
||||
defer backend.teardown()
|
||||
api := NewAPI(backend)
|
||||
var testSuite = []struct {
|
||||
|
|
@ -240,6 +278,51 @@ func TestTraceCall(t *testing.T) {
|
|||
expectErr: nil,
|
||||
expect: `{"gas":21000,"failed":false,"returnValue":"","structLogs":[]}`,
|
||||
},
|
||||
// Upon the last state, default to the post block's state
|
||||
{
|
||||
blockNumber: rpc.BlockNumber(genBlocks - 1),
|
||||
call: ethapi.TransactionArgs{
|
||||
From: &accounts[2].addr,
|
||||
To: &accounts[0].addr,
|
||||
Value: (*hexutil.Big)(new(big.Int).Add(big.NewInt(params.Ether), big.NewInt(100))),
|
||||
},
|
||||
config: nil,
|
||||
expect: `{"gas":21000,"failed":false,"returnValue":"","structLogs":[]}`,
|
||||
},
|
||||
// Before the first transaction, should be failed
|
||||
{
|
||||
blockNumber: rpc.BlockNumber(genBlocks - 1),
|
||||
call: ethapi.TransactionArgs{
|
||||
From: &accounts[2].addr,
|
||||
To: &accounts[0].addr,
|
||||
Value: (*hexutil.Big)(new(big.Int).Add(big.NewInt(params.Ether), big.NewInt(100))),
|
||||
},
|
||||
config: &TraceCallConfig{TxIndex: uintPtr(0)},
|
||||
expectErr: fmt.Errorf("tracing failed: insufficient funds for gas * price + value: address %s have 1000000000000000000 want 1000000000000000100", accounts[2].addr),
|
||||
},
|
||||
// Before the target transaction, should be failed
|
||||
{
|
||||
blockNumber: rpc.BlockNumber(genBlocks - 1),
|
||||
call: ethapi.TransactionArgs{
|
||||
From: &accounts[2].addr,
|
||||
To: &accounts[0].addr,
|
||||
Value: (*hexutil.Big)(new(big.Int).Add(big.NewInt(params.Ether), big.NewInt(100))),
|
||||
},
|
||||
config: &TraceCallConfig{TxIndex: uintPtr(1)},
|
||||
expectErr: fmt.Errorf("tracing failed: insufficient funds for gas * price + value: address %s have 1000000000000000000 want 1000000000000000100", accounts[2].addr),
|
||||
},
|
||||
// After the target transaction, should be succeed
|
||||
{
|
||||
blockNumber: rpc.BlockNumber(genBlocks - 1),
|
||||
call: ethapi.TransactionArgs{
|
||||
From: &accounts[2].addr,
|
||||
To: &accounts[0].addr,
|
||||
Value: (*hexutil.Big)(new(big.Int).Add(big.NewInt(params.Ether), big.NewInt(100))),
|
||||
},
|
||||
config: &TraceCallConfig{TxIndex: uintPtr(2)},
|
||||
expectErr: nil,
|
||||
expect: `{"gas":21000,"failed":false,"returnValue":"","structLogs":[]}`,
|
||||
},
|
||||
// Standard JSON trace upon the non-existent block, error expects
|
||||
{
|
||||
blockNumber: rpc.BlockNumber(genBlocks + 1),
|
||||
|
|
@ -297,8 +380,8 @@ func TestTraceCall(t *testing.T) {
|
|||
t.Errorf("test %d: expect error %v, got nothing", i, testspec.expectErr)
|
||||
continue
|
||||
}
|
||||
if !reflect.DeepEqual(err, testspec.expectErr) {
|
||||
t.Errorf("test %d: error mismatch, want %v, git %v", i, testspec.expectErr, err)
|
||||
if !reflect.DeepEqual(err.Error(), testspec.expectErr.Error()) {
|
||||
t.Errorf("test %d: error mismatch, want '%v', got '%v'", i, testspec.expectErr, err)
|
||||
}
|
||||
} else {
|
||||
if err != nil {
|
||||
|
|
@ -327,7 +410,7 @@ func TestTraceTransaction(t *testing.T) {
|
|||
accounts := newAccounts(2)
|
||||
genesis := &core.Genesis{
|
||||
Config: params.TestChainConfig,
|
||||
Alloc: core.GenesisAlloc{
|
||||
Alloc: types.GenesisAlloc{
|
||||
accounts[0].addr: {Balance: big.NewInt(params.Ether)},
|
||||
accounts[1].addr: {Balance: big.NewInt(params.Ether)},
|
||||
},
|
||||
|
|
@ -338,7 +421,14 @@ func TestTraceTransaction(t *testing.T) {
|
|||
// Transfer from account[0] to account[1]
|
||||
// value: 1000 wei
|
||||
// fee: 0 wei
|
||||
tx, _ := types.SignTx(types.NewTransaction(uint64(i), accounts[1].addr, big.NewInt(1000), params.TxGas, b.BaseFee(), nil), signer, accounts[0].key)
|
||||
tx, _ := types.SignTx(types.NewTx(&types.LegacyTx{
|
||||
Nonce: uint64(i),
|
||||
To: &accounts[1].addr,
|
||||
Value: big.NewInt(1000),
|
||||
Gas: params.TxGas,
|
||||
GasPrice: b.BaseFee(),
|
||||
Data: nil}),
|
||||
signer, accounts[0].key)
|
||||
b.AddTx(tx)
|
||||
target = tx.Hash()
|
||||
})
|
||||
|
|
@ -375,7 +465,7 @@ func TestTraceBlock(t *testing.T) {
|
|||
accounts := newAccounts(3)
|
||||
genesis := &core.Genesis{
|
||||
Config: params.TestChainConfig,
|
||||
Alloc: core.GenesisAlloc{
|
||||
Alloc: types.GenesisAlloc{
|
||||
accounts[0].addr: {Balance: big.NewInt(params.Ether)},
|
||||
accounts[1].addr: {Balance: big.NewInt(params.Ether)},
|
||||
accounts[2].addr: {Balance: big.NewInt(params.Ether)},
|
||||
|
|
@ -388,7 +478,14 @@ func TestTraceBlock(t *testing.T) {
|
|||
// Transfer from account[0] to account[1]
|
||||
// value: 1000 wei
|
||||
// fee: 0 wei
|
||||
tx, _ := types.SignTx(types.NewTransaction(uint64(i), accounts[1].addr, big.NewInt(1000), params.TxGas, b.BaseFee(), nil), signer, accounts[0].key)
|
||||
tx, _ := types.SignTx(types.NewTx(&types.LegacyTx{
|
||||
Nonce: uint64(i),
|
||||
To: &accounts[1].addr,
|
||||
Value: big.NewInt(1000),
|
||||
Gas: params.TxGas,
|
||||
GasPrice: b.BaseFee(),
|
||||
Data: nil}),
|
||||
signer, accounts[0].key)
|
||||
b.AddTx(tx)
|
||||
txHash = tx.Hash()
|
||||
})
|
||||
|
|
@ -458,7 +555,7 @@ func TestTracingWithOverrides(t *testing.T) {
|
|||
storageAccount := common.Address{0x13, 37}
|
||||
genesis := &core.Genesis{
|
||||
Config: params.TestChainConfig,
|
||||
Alloc: core.GenesisAlloc{
|
||||
Alloc: types.GenesisAlloc{
|
||||
accounts[0].addr: {Balance: big.NewInt(params.Ether)},
|
||||
accounts[1].addr: {Balance: big.NewInt(params.Ether)},
|
||||
accounts[2].addr: {Balance: big.NewInt(params.Ether)},
|
||||
|
|
@ -478,7 +575,14 @@ func TestTracingWithOverrides(t *testing.T) {
|
|||
// Transfer from account[0] to account[1]
|
||||
// value: 1000 wei
|
||||
// fee: 0 wei
|
||||
tx, _ := types.SignTx(types.NewTransaction(uint64(i), accounts[1].addr, big.NewInt(1000), params.TxGas, b.BaseFee(), nil), signer, accounts[0].key)
|
||||
tx, _ := types.SignTx(types.NewTx(&types.LegacyTx{
|
||||
Nonce: uint64(i),
|
||||
To: &accounts[1].addr,
|
||||
Value: big.NewInt(1000),
|
||||
Gas: params.TxGas,
|
||||
GasPrice: b.BaseFee(),
|
||||
Data: nil}),
|
||||
signer, accounts[0].key)
|
||||
b.AddTx(tx)
|
||||
})
|
||||
defer backend.chain.Stop()
|
||||
|
|
@ -819,7 +923,7 @@ func TestTraceChain(t *testing.T) {
|
|||
accounts := newAccounts(3)
|
||||
genesis := &core.Genesis{
|
||||
Config: params.TestChainConfig,
|
||||
Alloc: core.GenesisAlloc{
|
||||
Alloc: types.GenesisAlloc{
|
||||
accounts[0].addr: {Balance: big.NewInt(params.Ether)},
|
||||
accounts[1].addr: {Balance: big.NewInt(params.Ether)},
|
||||
accounts[2].addr: {Balance: big.NewInt(params.Ether)},
|
||||
|
|
|
|||
|
|
@ -33,9 +33,9 @@ func TestMemCopying(t *testing.T) {
|
|||
{0, 100, 0, "", 0}, // No need to pad (0 size)
|
||||
{100, 50, 100, "", 100}, // Should pad 100-150
|
||||
{100, 50, 5, "", 5}, // Wanted range fully within memory
|
||||
{100, -50, 0, "offset or size must not be negative", 0}, // Errror
|
||||
{0, 1, 1024*1024 + 1, "reached limit for padding memory slice: 1048578", 0}, // Errror
|
||||
{10, 0, 1024*1024 + 100, "reached limit for padding memory slice: 1048666", 0}, // Errror
|
||||
{100, -50, 0, "offset or size must not be negative", 0}, // Error
|
||||
{0, 1, 1024*1024 + 1, "reached limit for padding memory slice: 1048578", 0}, // Error
|
||||
{10, 0, 1024*1024 + 100, "reached limit for padding memory slice: 1048666", 0}, // Error
|
||||
|
||||
} {
|
||||
mem := vm.NewMemory()
|
||||
|
|
|
|||
|
|
@ -223,10 +223,6 @@ func benchTracer(tracerName string, test *callTracerTest, b *testing.B) {
|
|||
b.Fatalf("failed to parse testcase input: %v", err)
|
||||
}
|
||||
signer := types.MakeSigner(test.Genesis.Config, new(big.Int).SetUint64(uint64(test.Context.Number)), uint64(test.Context.Time))
|
||||
msg, err := core.TransactionToMessage(tx, signer, nil)
|
||||
if err != nil {
|
||||
b.Fatalf("failed to prepare transaction for tracing: %v", err)
|
||||
}
|
||||
origin, _ := signer.Sender(tx)
|
||||
txContext := vm.TxContext{
|
||||
Origin: origin,
|
||||
|
|
@ -241,6 +237,10 @@ func benchTracer(tracerName string, test *callTracerTest, b *testing.B) {
|
|||
Difficulty: (*big.Int)(test.Context.Difficulty),
|
||||
GasLimit: uint64(test.Context.GasLimit),
|
||||
}
|
||||
msg, err := core.TransactionToMessage(tx, signer, context.BaseFee)
|
||||
if err != nil {
|
||||
b.Fatalf("failed to prepare transaction for tracing: %v", err)
|
||||
}
|
||||
triedb, _, statedb := tests.MakePreState(rawdb.NewMemoryDatabase(), test.Genesis.Alloc, false, rawdb.HashScheme)
|
||||
defer triedb.Close()
|
||||
|
||||
|
|
@ -370,11 +370,11 @@ func TestInternals(t *testing.T) {
|
|||
} {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
triedb, _, statedb := tests.MakePreState(rawdb.NewMemoryDatabase(),
|
||||
core.GenesisAlloc{
|
||||
to: core.GenesisAccount{
|
||||
types.GenesisAlloc{
|
||||
to: types.Account{
|
||||
Code: tc.code,
|
||||
},
|
||||
origin: core.GenesisAccount{
|
||||
origin: types.Account{
|
||||
Balance: big.NewInt(500000000000000),
|
||||
},
|
||||
}, false, rawdb.HashScheme)
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ import (
|
|||
"testing"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/consensus/misc/eip4844"
|
||||
"github.com/ethereum/go-ethereum/core"
|
||||
"github.com/ethereum/go-ethereum/core/rawdb"
|
||||
"github.com/ethereum/go-ethereum/core/types"
|
||||
|
|
@ -107,6 +108,11 @@ func testPrestateDiffTracer(tracerName string, dirPath string, t *testing.T) {
|
|||
)
|
||||
defer triedb.Close()
|
||||
|
||||
if test.Genesis.ExcessBlobGas != nil && test.Genesis.BlobGasUsed != nil {
|
||||
excessBlobGas := eip4844.CalcExcessBlobGas(*test.Genesis.ExcessBlobGas, *test.Genesis.BlobGasUsed)
|
||||
context.BlobBaseFee = eip4844.CalcBlobFee(excessBlobGas)
|
||||
}
|
||||
|
||||
tracer, err := directory.DefaultDirectory.New(tracerName, new(directory.Context), test.TracerConfig)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to create call tracer: %v", err)
|
||||
|
|
|
|||
63
eth/tracers/internal/tracetest/testdata/prestate_tracer/blob_tx.json
vendored
Normal file
63
eth/tracers/internal/tracetest/testdata/prestate_tracer/blob_tx.json
vendored
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
{
|
||||
"genesis": {
|
||||
"baseFeePerGas": "7",
|
||||
"blobGasUsed": "0",
|
||||
"difficulty": "0",
|
||||
"excessBlobGas": "36306944",
|
||||
"extraData": "0xd983010e00846765746888676f312e32312e308664617277696e",
|
||||
"gasLimit": "15639172",
|
||||
"hash": "0xc682259fda061bb9ce8ccb491d5b2d436cb73daf04e1025dd116d045ce4ad28c",
|
||||
"miner": "0x0000000000000000000000000000000000000000",
|
||||
"mixHash": "0xae1a5ba939a4c9ac38aabeff361169fb55a6fc2c9511457e0be6eff9514faec0",
|
||||
"nonce": "0x0000000000000000",
|
||||
"number": "315",
|
||||
"parentBeaconBlockRoot": "0x0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"stateRoot": "0x577f42ab21ccfd946511c57869ace0bdf7c217c36f02b7cd3459df0ed1cffc1a",
|
||||
"timestamp": "1709626771",
|
||||
"totalDifficulty": "1",
|
||||
"withdrawals": [],
|
||||
"withdrawalsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
|
||||
"alloc": {
|
||||
"0x0000000000000000000000000000000000000000": {
|
||||
"balance": "0x272e0528"
|
||||
},
|
||||
"0x0c2c51a0990aee1d73c1228de158688341557508": {
|
||||
"balance": "0xde0b6b3a7640000"
|
||||
}
|
||||
},
|
||||
"config": {
|
||||
"chainId": 1337,
|
||||
"homesteadBlock": 0,
|
||||
"eip150Block": 0,
|
||||
"eip155Block": 0,
|
||||
"eip158Block": 0,
|
||||
"byzantiumBlock": 0,
|
||||
"constantinopleBlock": 0,
|
||||
"petersburgBlock": 0,
|
||||
"istanbulBlock": 0,
|
||||
"muirGlacierBlock": 0,
|
||||
"berlinBlock": 0,
|
||||
"londonBlock": 0,
|
||||
"arrowGlacierBlock": 0,
|
||||
"grayGlacierBlock": 0,
|
||||
"shanghaiTime": 0,
|
||||
"cancunTime": 0,
|
||||
"terminalTotalDifficulty": 0,
|
||||
"terminalTotalDifficultyPassed": true
|
||||
}
|
||||
},
|
||||
"context": {
|
||||
"number": "316",
|
||||
"difficulty": "0",
|
||||
"timestamp": "1709626785",
|
||||
"gasLimit": "15654443",
|
||||
"miner": "0x0000000000000000000000000000000000000000"
|
||||
},
|
||||
"input": "0x03f8b1820539806485174876e800825208940c2c51a0990aee1d73c1228de1586883415575088080c083020000f842a00100c9fbdf97f747e85847b4f3fff408f89c26842f77c882858bf2c89923849aa00138e3896f3c27f2389147507f8bcec52028b0efca6ee842ed83c9158873943880a0dbac3f97a532c9b00e6239b29036245a5bfbb96940b9d848634661abee98b945a03eec8525f261c2e79798f7b45a5d6ccaefa24576d53ba5023e919b86841c0675",
|
||||
"result": {
|
||||
"0x0000000000000000000000000000000000000000": { "balance": "0x272e0528" },
|
||||
"0x0c2c51a0990aee1d73c1228de158688341557508": {
|
||||
"balance": "0xde0b6b3a7640000"
|
||||
}
|
||||
}
|
||||
}
|
||||
64
eth/tracers/internal/tracetest/testdata/prestate_tracer/create_post_eip158.json
vendored
Normal file
64
eth/tracers/internal/tracetest/testdata/prestate_tracer/create_post_eip158.json
vendored
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
{
|
||||
"genesis": {
|
||||
"baseFeePerGas": "7",
|
||||
"difficulty": "2",
|
||||
"extraData": "0xd983010d0e846765746888676f312e32312e318664617277696e0000000000001713699f05f79a59abec177c7a87b90ceda79b72ff5edc9197dd7627a447cde45b079bbc3765a236cdf680e2d4d2247135d0e6bb6fd92b50638b92504ddb274f00",
|
||||
"gasLimit": "30000000",
|
||||
"hash": "0x6ad5258175c66f4e883d238a92a08428d8ebcbeac631ab7b972634cc05effab3",
|
||||
"miner": "0x2445e8c26a2bf3d1e59f1bb9b1d442caf90768e0",
|
||||
"mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"nonce": "0x0000000000000000",
|
||||
"number": "39137",
|
||||
"stateRoot": "0x715f00df764dbadd4863247a215ac44b5420beafde3ec458b15db7aafa89be0c",
|
||||
"timestamp": "1709022192",
|
||||
"totalDifficulty": "78275",
|
||||
"alloc": {
|
||||
"0x2445e8c26a2bf3d1e59f1bb9b1d442caf90768e0": {
|
||||
"balance": "0x10f06447a8d44dba190",
|
||||
"nonce": "2"
|
||||
},
|
||||
"0x82211934c340b29561381392348d48413e15adc8": {
|
||||
"balance": "0x6abd7a808913ed2",
|
||||
"nonce": "64"
|
||||
}
|
||||
},
|
||||
"config": {
|
||||
"chainId": 12345,
|
||||
"homesteadBlock": 0,
|
||||
"eip150Block": 0,
|
||||
"eip155Block": 0,
|
||||
"eip158Block": 0,
|
||||
"byzantiumBlock": 0,
|
||||
"constantinopleBlock": 0,
|
||||
"petersburgBlock": 0,
|
||||
"istanbulBlock": 0,
|
||||
"muirGlacierBlock": 0,
|
||||
"berlinBlock": 0,
|
||||
"londonBlock": 0,
|
||||
"arrowGlacierBlock": 0,
|
||||
"grayGlacierBlock": 0,
|
||||
"clique": {
|
||||
"period": 5,
|
||||
"epoch": 30000
|
||||
}
|
||||
}
|
||||
},
|
||||
"context": {
|
||||
"number": "39138",
|
||||
"difficulty": "2",
|
||||
"timestamp": "1709022197",
|
||||
"gasLimit": "30000000",
|
||||
"miner": "0x2445e8c26a2bf3d1e59f1bb9b1d442caf90768e0"
|
||||
},
|
||||
"input": "0x02f902af823039408459682f008459682f088302b3538080b90254608060405234801561001057600080fd5b50610234806100206000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c806309ce9ccb1461003b5780633fb5c1cb14610059575b600080fd5b610043610075565b60405161005091906100e2565b60405180910390f35b610073600480360381019061006e919061012e565b61007b565b005b60005481565b80600081905550600a8111156100c6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100bd906101de565b60405180910390fd5b50565b6000819050919050565b6100dc816100c9565b82525050565b60006020820190506100f760008301846100d3565b92915050565b600080fd5b61010b816100c9565b811461011657600080fd5b50565b60008135905061012881610102565b92915050565b600060208284031215610144576101436100fd565b5b600061015284828501610119565b91505092915050565b600082825260208201905092915050565b7f4e756d6265722069732067726561746572207468616e2031302c207472616e7360008201527f616374696f6e2072657665727465642e00000000000000000000000000000000602082015250565b60006101c860308361015b565b91506101d38261016c565b604082019050919050565b600060208201905081810360008301526101f7816101bb565b905091905056fea264697066735822122069018995fecf03bda91a88b6eafe41641709dee8b4a706fe301c8a569fe8c1b364736f6c63430008130033c001a0a8cf4729b7e4664687abb3e2559853d7d489eb441519be2a17493061fb4c3a03a04b5a904ba8a6e59c6c40049c4d14a73233aeb8a45b38403199f304630dc0d453",
|
||||
"result": {
|
||||
"0x2445e8c26a2bf3d1e59f1bb9b1d442caf90768e0": {
|
||||
"balance": "0x10f06447a8d44dba190",
|
||||
"nonce": 2
|
||||
},
|
||||
"0x82211934c340b29561381392348d48413e15adc8": {
|
||||
"balance": "0x6abd7a808913ed2",
|
||||
"nonce": 64
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -83,7 +83,7 @@
|
|||
},
|
||||
"post": {
|
||||
"0x808b4da0be6c9512e948521452227efc619bea52": {
|
||||
"balance": "0x2cd72a36dd031f089",
|
||||
"balance": "0x2cd987071ba2346b6",
|
||||
"nonce": 1223933
|
||||
},
|
||||
"0x8f03f1a3f10c05e7cccf75c1fd10168e06659be7": {
|
||||
|
|
|
|||
82
eth/tracers/internal/tracetest/testdata/prestate_tracer_with_diff_mode/create_post_eip158.json
vendored
Normal file
82
eth/tracers/internal/tracetest/testdata/prestate_tracer_with_diff_mode/create_post_eip158.json
vendored
Normal file
|
|
@ -0,0 +1,82 @@
|
|||
{
|
||||
"genesis": {
|
||||
"baseFeePerGas": "7",
|
||||
"difficulty": "2",
|
||||
"extraData": "0xd983010d0e846765746888676f312e32312e318664617277696e0000000000001713699f05f79a59abec177c7a87b90ceda79b72ff5edc9197dd7627a447cde45b079bbc3765a236cdf680e2d4d2247135d0e6bb6fd92b50638b92504ddb274f00",
|
||||
"gasLimit": "30000000",
|
||||
"hash": "0x6ad5258175c66f4e883d238a92a08428d8ebcbeac631ab7b972634cc05effab3",
|
||||
"miner": "0x2445e8c26a2bf3d1e59f1bb9b1d442caf90768e0",
|
||||
"mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"nonce": "0x0000000000000000",
|
||||
"number": "39137",
|
||||
"stateRoot": "0x715f00df764dbadd4863247a215ac44b5420beafde3ec458b15db7aafa89be0c",
|
||||
"timestamp": "1709022192",
|
||||
"totalDifficulty": "78275",
|
||||
"alloc": {
|
||||
"0x2445e8c26a2bf3d1e59f1bb9b1d442caf90768e0": {
|
||||
"balance": "0x10f06447a8d44dba190",
|
||||
"nonce": "2"
|
||||
},
|
||||
"0x82211934c340b29561381392348d48413e15adc8": {
|
||||
"balance": "0x6abd7a808913ed2",
|
||||
"nonce": "64"
|
||||
}
|
||||
},
|
||||
"config": {
|
||||
"chainId": 12345,
|
||||
"homesteadBlock": 0,
|
||||
"eip150Block": 0,
|
||||
"eip155Block": 0,
|
||||
"eip158Block": 0,
|
||||
"byzantiumBlock": 0,
|
||||
"constantinopleBlock": 0,
|
||||
"petersburgBlock": 0,
|
||||
"istanbulBlock": 0,
|
||||
"muirGlacierBlock": 0,
|
||||
"berlinBlock": 0,
|
||||
"londonBlock": 0,
|
||||
"arrowGlacierBlock": 0,
|
||||
"grayGlacierBlock": 0,
|
||||
"clique": {
|
||||
"period": 5,
|
||||
"epoch": 30000
|
||||
}
|
||||
}
|
||||
},
|
||||
"context": {
|
||||
"number": "39138",
|
||||
"difficulty": "2",
|
||||
"timestamp": "1709022197",
|
||||
"gasLimit": "30000000",
|
||||
"miner": "0x2445e8c26a2bf3d1e59f1bb9b1d442caf90768e0"
|
||||
},
|
||||
"input": "0x02f902af823039408459682f008459682f088302b3538080b90254608060405234801561001057600080fd5b50610234806100206000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c806309ce9ccb1461003b5780633fb5c1cb14610059575b600080fd5b610043610075565b60405161005091906100e2565b60405180910390f35b610073600480360381019061006e919061012e565b61007b565b005b60005481565b80600081905550600a8111156100c6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100bd906101de565b60405180910390fd5b50565b6000819050919050565b6100dc816100c9565b82525050565b60006020820190506100f760008301846100d3565b92915050565b600080fd5b61010b816100c9565b811461011657600080fd5b50565b60008135905061012881610102565b92915050565b600060208284031215610144576101436100fd565b5b600061015284828501610119565b91505092915050565b600082825260208201905092915050565b7f4e756d6265722069732067726561746572207468616e2031302c207472616e7360008201527f616374696f6e2072657665727465642e00000000000000000000000000000000602082015250565b60006101c860308361015b565b91506101d38261016c565b604082019050919050565b600060208201905081810360008301526101f7816101bb565b905091905056fea264697066735822122069018995fecf03bda91a88b6eafe41641709dee8b4a706fe301c8a569fe8c1b364736f6c63430008130033c001a0a8cf4729b7e4664687abb3e2559853d7d489eb441519be2a17493061fb4c3a03a04b5a904ba8a6e59c6c40049c4d14a73233aeb8a45b38403199f304630dc0d453",
|
||||
"tracerConfig": {
|
||||
"diffMode": true
|
||||
},
|
||||
"result": {
|
||||
"post": {
|
||||
"0x1bda2f8e4735507930bd6cfe873bf0bf0f4ab1de": {
|
||||
"code": "0x608060405234801561001057600080fd5b50600436106100365760003560e01c806309ce9ccb1461003b5780633fb5c1cb14610059575b600080fd5b610043610075565b60405161005091906100e2565b60405180910390f35b610073600480360381019061006e919061012e565b61007b565b005b60005481565b80600081905550600a8111156100c6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100bd906101de565b60405180910390fd5b50565b6000819050919050565b6100dc816100c9565b82525050565b60006020820190506100f760008301846100d3565b92915050565b600080fd5b61010b816100c9565b811461011657600080fd5b50565b60008135905061012881610102565b92915050565b600060208284031215610144576101436100fd565b5b600061015284828501610119565b91505092915050565b600082825260208201905092915050565b7f4e756d6265722069732067726561746572207468616e2031302c207472616e7360008201527f616374696f6e2072657665727465642e00000000000000000000000000000000602082015250565b60006101c860308361015b565b91506101d38261016c565b604082019050919050565b600060208201905081810360008301526101f7816101bb565b905091905056fea264697066735822122069018995fecf03bda91a88b6eafe41641709dee8b4a706fe301c8a569fe8c1b364736f6c63430008130033",
|
||||
"nonce": 1
|
||||
},
|
||||
"0x2445e8c26a2bf3d1e59f1bb9b1d442caf90768e0": {
|
||||
"balance": "0x10f0645688331eb5690"
|
||||
},
|
||||
"0x82211934c340b29561381392348d48413e15adc8": {
|
||||
"balance": "0x6aae9b21b6ee855",
|
||||
"nonce": 65
|
||||
}
|
||||
},
|
||||
"pre": {
|
||||
"0x2445e8c26a2bf3d1e59f1bb9b1d442caf90768e0": {
|
||||
"balance": "0x10f06447a8d44dba190",
|
||||
"nonce": 2
|
||||
},
|
||||
"0x82211934c340b29561381392348d48413e15adc8": {
|
||||
"balance": "0x6abd7a808913ed2",
|
||||
"nonce": 64
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -144,19 +144,29 @@ func newJsTracer(code string, ctx *directory.Context, cfg json.RawMessage) (*dir
|
|||
vm: vm,
|
||||
ctx: make(map[string]goja.Value),
|
||||
}
|
||||
|
||||
t.setTypeConverters()
|
||||
t.setBuiltinFunctions()
|
||||
|
||||
if ctx == nil {
|
||||
ctx = new(directory.Context)
|
||||
}
|
||||
if ctx.BlockHash != (common.Hash{}) {
|
||||
t.ctx["blockHash"] = vm.ToValue(ctx.BlockHash.Bytes())
|
||||
blockHash, err := t.toBuf(vm, ctx.BlockHash.Bytes())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
t.ctx["blockHash"] = blockHash
|
||||
if ctx.TxHash != (common.Hash{}) {
|
||||
t.ctx["txIndex"] = vm.ToValue(ctx.TxIndex)
|
||||
t.ctx["txHash"] = vm.ToValue(ctx.TxHash.Bytes())
|
||||
txHash, err := t.toBuf(vm, ctx.TxHash.Bytes())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
t.ctx["txHash"] = txHash
|
||||
}
|
||||
}
|
||||
|
||||
t.setTypeConverters()
|
||||
t.setBuiltinFunctions()
|
||||
ret, err := vm.RunString("(" + code + ")")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
|
@ -341,6 +351,12 @@ func (t *jsTracer) onEnd(output []byte, gasUsed uint64, err error, reverted bool
|
|||
if err != nil {
|
||||
t.ctx["error"] = t.vm.ToValue(err.Error())
|
||||
}
|
||||
outputVal, err := t.toBuf(t.vm, output)
|
||||
if err != nil {
|
||||
t.err = err
|
||||
return
|
||||
}
|
||||
t.ctx["output"] = outputVal
|
||||
}
|
||||
|
||||
// OnEnter is called when EVM enters a new scope (via call, create or selfdestruct).
|
||||
|
|
@ -520,13 +536,13 @@ func (t *jsTracer) setBuiltinFunctions() {
|
|||
}
|
||||
return false
|
||||
})
|
||||
vm.Set("slice", func(slice goja.Value, start, end int) goja.Value {
|
||||
vm.Set("slice", func(slice goja.Value, start, end int64) goja.Value {
|
||||
b, err := t.fromBuf(vm, slice, false)
|
||||
if err != nil {
|
||||
vm.Interrupt(err)
|
||||
return nil
|
||||
}
|
||||
if start < 0 || start > end || end > len(b) {
|
||||
if start < 0 || start > end || end > int64(len(b)) {
|
||||
vm.Interrupt(fmt.Sprintf("Tracer accessed out of bound memory: available %d, offset %d, size %d", len(b), start, end-start))
|
||||
return nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -219,7 +219,7 @@
|
|||
return this.finalize(result);
|
||||
},
|
||||
|
||||
// finalize recreates a call object using the final desired field oder for json
|
||||
// finalize recreates a call object using the final desired field order for json
|
||||
// serialization. This is a nicety feature to pass meaningfully ordered results
|
||||
// to users who don't interpret it, just display it.
|
||||
finalize: function(call) {
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ func (s StructLog) MarshalJSON() ([]byte, error) {
|
|||
GasCost math.HexOrDecimal64 `json:"gasCost"`
|
||||
Memory hexutil.Bytes `json:"memory,omitempty"`
|
||||
MemorySize int `json:"memSize"`
|
||||
Stack []uint256.Int `json:"stack"`
|
||||
Stack []hexutil.U256 `json:"stack"`
|
||||
ReturnData hexutil.Bytes `json:"returnData,omitempty"`
|
||||
Storage map[common.Hash]common.Hash `json:"-"`
|
||||
Depth int `json:"depth"`
|
||||
|
|
@ -39,7 +39,12 @@ func (s StructLog) MarshalJSON() ([]byte, error) {
|
|||
enc.GasCost = math.HexOrDecimal64(s.GasCost)
|
||||
enc.Memory = s.Memory
|
||||
enc.MemorySize = s.MemorySize
|
||||
enc.Stack = s.Stack
|
||||
if s.Stack != nil {
|
||||
enc.Stack = make([]hexutil.U256, len(s.Stack))
|
||||
for k, v := range s.Stack {
|
||||
enc.Stack[k] = hexutil.U256(v)
|
||||
}
|
||||
}
|
||||
enc.ReturnData = s.ReturnData
|
||||
enc.Storage = s.Storage
|
||||
enc.Depth = s.Depth
|
||||
|
|
@ -59,7 +64,7 @@ func (s *StructLog) UnmarshalJSON(input []byte) error {
|
|||
GasCost *math.HexOrDecimal64 `json:"gasCost"`
|
||||
Memory *hexutil.Bytes `json:"memory,omitempty"`
|
||||
MemorySize *int `json:"memSize"`
|
||||
Stack []uint256.Int `json:"stack"`
|
||||
Stack []hexutil.U256 `json:"stack"`
|
||||
ReturnData *hexutil.Bytes `json:"returnData,omitempty"`
|
||||
Storage map[common.Hash]common.Hash `json:"-"`
|
||||
Depth *int `json:"depth"`
|
||||
|
|
@ -89,7 +94,10 @@ func (s *StructLog) UnmarshalJSON(input []byte) error {
|
|||
s.MemorySize = *dec.MemorySize
|
||||
}
|
||||
if dec.Stack != nil {
|
||||
s.Stack = dec.Stack
|
||||
s.Stack = make([]uint256.Int, len(dec.Stack))
|
||||
for k, v := range dec.Stack {
|
||||
s.Stack[k] = uint256.Int(v)
|
||||
}
|
||||
}
|
||||
if dec.ReturnData != nil {
|
||||
s.ReturnData = *dec.ReturnData
|
||||
|
|
|
|||
|
|
@ -85,6 +85,7 @@ type structLogMarshaling struct {
|
|||
GasCost math.HexOrDecimal64
|
||||
Memory hexutil.Bytes
|
||||
ReturnData hexutil.Bytes
|
||||
Stack []hexutil.U256
|
||||
OpName string `json:"opName"` // adds call to OpName() in MarshalJSON
|
||||
ErrorString string `json:"error,omitempty"` // adds call to ErrorString() in MarshalJSON
|
||||
}
|
||||
|
|
@ -418,11 +419,6 @@ func (t *mdLogger) OnFault(pc uint64, op byte, gas, cost uint64, scope tracing.O
|
|||
fmt.Fprintf(t.out, "\nError: at pc=%d, op=%v: %v\n", pc, op, err)
|
||||
}
|
||||
|
||||
func (t *mdLogger) CaptureEnd(output []byte, gasUsed uint64, err error, reverted bool) {
|
||||
fmt.Fprintf(t.out, "\nOutput: `%#x`\nConsumed gas: `%d`\nError: `%v`\n",
|
||||
output, gasUsed, err)
|
||||
}
|
||||
|
||||
// ExecutionResult groups all structured logs emitted by the EVM
|
||||
// while replaying a transaction in debug mode as well as transaction
|
||||
// execution status, the amount of gas used and the return value
|
||||
|
|
|
|||
|
|
@ -155,6 +155,9 @@ func newFlatCallTracer(ctx *directory.Context, cfg json.RawMessage) (*directory.
|
|||
func (t *flatCallTracer) OnEnter(depth int, typ byte, from common.Address, to common.Address, input []byte, gas uint64, value *big.Int) {
|
||||
t.tracer.OnEnter(depth, typ, from, to, input, gas, value)
|
||||
|
||||
if depth == 0 {
|
||||
return
|
||||
}
|
||||
// Child calls must have a value, even if it's zero.
|
||||
// Practically speaking, only STATICCALL has nil value. Set it to zero.
|
||||
if t.tracer.callstack[len(t.tracer.callstack)-1].Value == nil && value == nil {
|
||||
|
|
@ -167,6 +170,9 @@ func (t *flatCallTracer) OnEnter(depth int, typ byte, from common.Address, to co
|
|||
func (t *flatCallTracer) OnExit(depth int, output []byte, gasUsed uint64, err error, reverted bool) {
|
||||
t.tracer.OnExit(depth, output, gasUsed, err, reverted)
|
||||
|
||||
if depth == 0 {
|
||||
return
|
||||
}
|
||||
// Parity traces don't include CALL/STATICCALLs to precompiles.
|
||||
// By default we remove them from the callstack.
|
||||
if t.config.IncludePrecompiles {
|
||||
|
|
|
|||
|
|
@ -332,6 +332,6 @@ func (b *LesApiBackend) StateAtBlock(ctx context.Context, block *types.Block, re
|
|||
return b.eth.stateAtBlock(ctx, block, reexec)
|
||||
}
|
||||
|
||||
func (b *LesApiBackend) StateAtTransaction(ctx context.Context, block *types.Block, txIndex int, reexec uint64) (*core.Message, vm.BlockContext, *state.StateDB, tracers.StateReleaseFunc, error) {
|
||||
func (b *LesApiBackend) StateAtTransaction(ctx context.Context, block *types.Block, txIndex int, reexec uint64) (*types.Transaction, vm.BlockContext, *state.StateDB, tracers.StateReleaseFunc, error) {
|
||||
return b.eth.stateAtTransaction(ctx, block, txIndex, reexec)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ func (leth *LightEthereum) stateAtBlock(ctx context.Context, block *types.Block,
|
|||
}
|
||||
|
||||
// stateAtTransaction returns the execution environment of a certain transaction.
|
||||
func (leth *LightEthereum) stateAtTransaction(ctx context.Context, block *types.Block, txIndex int, reexec uint64) (*core.Message, vm.BlockContext, *state.StateDB, tracers.StateReleaseFunc, error) {
|
||||
func (leth *LightEthereum) stateAtTransaction(ctx context.Context, block *types.Block, txIndex int, reexec uint64) (*types.Transaction, vm.BlockContext, *state.StateDB, tracers.StateReleaseFunc, error) {
|
||||
// Short circuit if it's genesis block.
|
||||
if block.NumberU64() == 0 {
|
||||
return nil, vm.BlockContext{}, nil, nil, errors.New("no transaction in genesis")
|
||||
|
|
@ -65,7 +65,7 @@ func (leth *LightEthereum) stateAtTransaction(ctx context.Context, block *types.
|
|||
context := core.NewEVMBlockContext(block.Header(), leth.blockchain, nil)
|
||||
statedb.SetTxContext(tx.Hash(), idx)
|
||||
if idx == txIndex {
|
||||
return msg, context, statedb, release, nil
|
||||
return tx, context, statedb, release, nil
|
||||
}
|
||||
// Not yet the searched for transaction, execute on top of the current state
|
||||
vmenv := vm.NewEVM(context, txContext, statedb, leth.blockchain.Config(), vm.Config{})
|
||||
|
|
|
|||
Loading…
Reference in a new issue