github.com/palisadeinc/bor@v0.0.0-20230615125219-ab7196213d15/eth/tracers/tracers_test.go (about)

     1  // Copyright 2017 The go-ethereum Authors
     2  // This file is part of the go-ethereum library.
     3  //
     4  // The go-ethereum library is free software: you can redistribute it and/or modify
     5  // it under the terms of the GNU Lesser General Public License as published by
     6  // the Free Software Foundation, either version 3 of the License, or
     7  // (at your option) any later version.
     8  //
     9  // The go-ethereum library is distributed in the hope that it will be useful,
    10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    12  // GNU Lesser General Public License for more details.
    13  //
    14  // You should have received a copy of the GNU Lesser General Public License
    15  // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  package tracers
    18  
    19  import (
    20  	"context"
    21  	"math/big"
    22  	"testing"
    23  
    24  	"github.com/ethereum/go-ethereum/common"
    25  	"github.com/ethereum/go-ethereum/common/hexutil"
    26  	"github.com/ethereum/go-ethereum/core"
    27  	"github.com/ethereum/go-ethereum/core/rawdb"
    28  	"github.com/ethereum/go-ethereum/core/types"
    29  	"github.com/ethereum/go-ethereum/core/vm"
    30  	"github.com/ethereum/go-ethereum/crypto"
    31  	"github.com/ethereum/go-ethereum/eth/tracers/logger"
    32  	"github.com/ethereum/go-ethereum/params"
    33  	"github.com/ethereum/go-ethereum/tests"
    34  )
    35  
    36  // callTrace is the result of a callTracer run.
    37  type callTrace struct {
    38  	Type    string          `json:"type"`
    39  	From    common.Address  `json:"from"`
    40  	To      common.Address  `json:"to"`
    41  	Input   hexutil.Bytes   `json:"input"`
    42  	Output  hexutil.Bytes   `json:"output"`
    43  	Gas     *hexutil.Uint64 `json:"gas,omitempty"`
    44  	GasUsed *hexutil.Uint64 `json:"gasUsed,omitempty"`
    45  	Value   *hexutil.Big    `json:"value,omitempty"`
    46  	Error   string          `json:"error,omitempty"`
    47  	Calls   []callTrace     `json:"calls,omitempty"`
    48  }
    49  
    50  func BenchmarkTransactionTrace(b *testing.B) {
    51  	key, _ := crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
    52  	from := crypto.PubkeyToAddress(key.PublicKey)
    53  	gas := uint64(1000000) // 1M gas
    54  	to := common.HexToAddress("0x00000000000000000000000000000000deadbeef")
    55  	signer := types.LatestSignerForChainID(big.NewInt(1337))
    56  	tx, err := types.SignNewTx(key, signer,
    57  		&types.LegacyTx{
    58  			Nonce:    1,
    59  			GasPrice: big.NewInt(500),
    60  			Gas:      gas,
    61  			To:       &to,
    62  		})
    63  	if err != nil {
    64  		b.Fatal(err)
    65  	}
    66  	txContext := vm.TxContext{
    67  		Origin:   from,
    68  		GasPrice: tx.GasPrice(),
    69  	}
    70  	blockContext := vm.BlockContext{
    71  		CanTransfer: core.CanTransfer,
    72  		Transfer:    core.Transfer,
    73  		Coinbase:    common.Address{},
    74  		BlockNumber: new(big.Int).SetUint64(uint64(5)),
    75  		Time:        new(big.Int).SetUint64(uint64(5)),
    76  		Difficulty:  big.NewInt(0xffffffff),
    77  		GasLimit:    gas,
    78  		BaseFee:     big.NewInt(8),
    79  	}
    80  	alloc := core.GenesisAlloc{}
    81  	// The code pushes 'deadbeef' into memory, then the other params, and calls CREATE2, then returns
    82  	// the address
    83  	loop := []byte{
    84  		byte(vm.JUMPDEST), //  [ count ]
    85  		byte(vm.PUSH1), 0, // jumpdestination
    86  		byte(vm.JUMP),
    87  	}
    88  	alloc[common.HexToAddress("0x00000000000000000000000000000000deadbeef")] = core.GenesisAccount{
    89  		Nonce:   1,
    90  		Code:    loop,
    91  		Balance: big.NewInt(1),
    92  	}
    93  	alloc[from] = core.GenesisAccount{
    94  		Nonce:   1,
    95  		Code:    []byte{},
    96  		Balance: big.NewInt(500000000000000),
    97  	}
    98  	_, statedb := tests.MakePreState(rawdb.NewMemoryDatabase(), alloc, false)
    99  	// Create the tracer, the EVM environment and run it
   100  	tracer := logger.NewStructLogger(&logger.Config{
   101  		Debug: false,
   102  		//DisableStorage: true,
   103  		//EnableMemory: false,
   104  		//EnableReturnData: false,
   105  	})
   106  	evm := vm.NewEVM(blockContext, txContext, statedb, params.AllEthashProtocolChanges, vm.Config{Debug: true, Tracer: tracer})
   107  	msg, err := tx.AsMessage(signer, nil)
   108  	if err != nil {
   109  		b.Fatalf("failed to prepare transaction for tracing: %v", err)
   110  	}
   111  	b.ResetTimer()
   112  	b.ReportAllocs()
   113  
   114  	for i := 0; i < b.N; i++ {
   115  		snap := statedb.Snapshot()
   116  		st := core.NewStateTransition(evm, msg, new(core.GasPool).AddGas(tx.Gas()))
   117  		_, err = st.TransitionDb(context.Background())
   118  		if err != nil {
   119  			b.Fatal(err)
   120  		}
   121  		statedb.RevertToSnapshot(snap)
   122  		if have, want := len(tracer.StructLogs()), 244752; have != want {
   123  			b.Fatalf("trace wrong, want %d steps, have %d", want, have)
   124  		}
   125  		tracer.Reset()
   126  	}
   127  }