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 }