github.com/cryptotooltop/go-ethereum@v0.0.0-20231103184714-151d1922f3e5/core/vm/logger_trace.go (about)

     1  package vm
     2  
     3  import (
     4  	"github.com/scroll-tech/go-ethereum/common"
     5  	"github.com/scroll-tech/go-ethereum/common/hexutil"
     6  	"github.com/scroll-tech/go-ethereum/core/types"
     7  )
     8  
     9  type traceFunc func(l *StructLogger, scope *ScopeContext, extraData *types.ExtraData) error
    10  
    11  var (
    12  	// OpcodeExecs the map to load opcodes' trace funcs.
    13  	OpcodeExecs = map[OpCode][]traceFunc{
    14  		CALL:         {traceToAddressCode, traceLastNAddressCode(1), traceContractAccount, traceLastNAddressAccount(1)}, // contract account is the caller, stack.nth_last(1) is the callee's address
    15  		CALLCODE:     {traceToAddressCode, traceLastNAddressCode(1), traceContractAccount, traceLastNAddressAccount(1)}, // contract account is the caller, stack.nth_last(1) is the callee's address
    16  		DELEGATECALL: {traceToAddressCode, traceLastNAddressCode(1)},
    17  		STATICCALL:   {traceToAddressCode, traceLastNAddressCode(1), traceLastNAddressAccount(1)},
    18  		CREATE:       {}, // caller is already recorded in ExtraData.Caller, callee is recorded in CaptureEnter&CaptureExit
    19  		CREATE2:      {}, // caller is already recorded in ExtraData.Caller, callee is recorded in CaptureEnter&CaptureExit
    20  		SLOAD:        {}, // trace storage in `captureState` instead of here, to handle `l.cfg.DisableStorage` flag
    21  		SSTORE:       {}, // trace storage in `captureState` instead of here, to handle `l.cfg.DisableStorage` flag
    22  		SELFDESTRUCT: {traceContractAccount, traceLastNAddressAccount(0)},
    23  		SELFBALANCE:  {traceContractAccount},
    24  		BALANCE:      {traceLastNAddressAccount(0)},
    25  		EXTCODEHASH:  {traceLastNAddressAccount(0)},
    26  		CODESIZE:     {traceContractCode},
    27  		CODECOPY:     {traceContractCode},
    28  		EXTCODESIZE:  {traceLastNAddressCode(0)},
    29  		EXTCODECOPY:  {traceLastNAddressCode(0)},
    30  	}
    31  )
    32  
    33  // traceToAddressCode gets tx.to address’s code
    34  func traceToAddressCode(l *StructLogger, scope *ScopeContext, extraData *types.ExtraData) error {
    35  	if l.env.To == nil {
    36  		return nil
    37  	}
    38  	code := l.env.StateDB.GetCode(*l.env.To)
    39  	extraData.CodeList = append(extraData.CodeList, hexutil.Encode(code))
    40  	return nil
    41  }
    42  
    43  // traceLastNAddressCode
    44  func traceLastNAddressCode(n int) traceFunc {
    45  	return func(l *StructLogger, scope *ScopeContext, extraData *types.ExtraData) error {
    46  		stack := scope.Stack
    47  		if stack.len() <= n {
    48  			return nil
    49  		}
    50  		address := common.Address(stack.data[stack.len()-1-n].Bytes20())
    51  		code := l.env.StateDB.GetCode(address)
    52  		extraData.CodeList = append(extraData.CodeList, hexutil.Encode(code))
    53  		l.statesAffected[address] = struct{}{}
    54  		return nil
    55  	}
    56  }
    57  
    58  // traceContractCode gets the contract's code
    59  func traceContractCode(l *StructLogger, scope *ScopeContext, extraData *types.ExtraData) error {
    60  	code := l.env.StateDB.GetCode(scope.Contract.Address())
    61  	extraData.CodeList = append(extraData.CodeList, hexutil.Encode(code))
    62  	return nil
    63  }
    64  
    65  // traceStorage get contract's storage at storage_address
    66  func traceStorage(l *StructLogger, scope *ScopeContext, extraData *types.ExtraData) error {
    67  	if scope.Stack.len() == 0 {
    68  		return nil
    69  	}
    70  	key := common.Hash(scope.Stack.peek().Bytes32())
    71  	storage := getWrappedAccountForStorage(l, scope.Contract.Address(), key)
    72  	extraData.StateList = append(extraData.StateList, storage)
    73  
    74  	return nil
    75  }
    76  
    77  // traceContractAccount gets the contract's account
    78  func traceContractAccount(l *StructLogger, scope *ScopeContext, extraData *types.ExtraData) error {
    79  	// Get account state.
    80  	state := getWrappedAccountForAddr(l, scope.Contract.Address())
    81  	extraData.StateList = append(extraData.StateList, state)
    82  	l.statesAffected[scope.Contract.Address()] = struct{}{}
    83  
    84  	return nil
    85  }
    86  
    87  // traceLastNAddressAccount returns func about the last N's address account.
    88  func traceLastNAddressAccount(n int) traceFunc {
    89  	return func(l *StructLogger, scope *ScopeContext, extraData *types.ExtraData) error {
    90  		stack := scope.Stack
    91  		if stack.len() <= n {
    92  			return nil
    93  		}
    94  
    95  		address := common.Address(stack.data[stack.len()-1-n].Bytes20())
    96  		state := getWrappedAccountForAddr(l, address)
    97  		extraData.StateList = append(extraData.StateList, state)
    98  		l.statesAffected[address] = struct{}{}
    99  
   100  		return nil
   101  	}
   102  }
   103  
   104  // StorageWrapper will be empty
   105  func getWrappedAccountForAddr(l *StructLogger, address common.Address) *types.AccountWrapper {
   106  	return &types.AccountWrapper{
   107  		Address:          address,
   108  		Nonce:            l.env.StateDB.GetNonce(address),
   109  		Balance:          (*hexutil.Big)(l.env.StateDB.GetBalance(address)),
   110  		KeccakCodeHash:   l.env.StateDB.GetKeccakCodeHash(address),
   111  		PoseidonCodeHash: l.env.StateDB.GetPoseidonCodeHash(address),
   112  		CodeSize:         l.env.StateDB.GetCodeSize(address),
   113  	}
   114  }
   115  
   116  func getWrappedAccountForStorage(l *StructLogger, address common.Address, key common.Hash) *types.AccountWrapper {
   117  	return &types.AccountWrapper{
   118  		Address:          address,
   119  		Nonce:            l.env.StateDB.GetNonce(address),
   120  		Balance:          (*hexutil.Big)(l.env.StateDB.GetBalance(address)),
   121  		KeccakCodeHash:   l.env.StateDB.GetKeccakCodeHash(address),
   122  		PoseidonCodeHash: l.env.StateDB.GetPoseidonCodeHash(address),
   123  		CodeSize:         l.env.StateDB.GetCodeSize(address),
   124  		Storage: &types.StorageWrapper{
   125  			Key:   key.String(),
   126  			Value: l.env.StateDB.GetState(address, key).String(),
   127  		},
   128  	}
   129  }
   130  
   131  func getCodeForAddr(l *StructLogger, address common.Address) []byte {
   132  	return l.env.StateDB.GetCode(address)
   133  }