github.com/ethereum/go-ethereum@v1.14.4-0.20240516095835-473ee8fc07a3/core/tracing/hooks.go (about) 1 // Copyright 2024 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 tracing 18 19 import ( 20 "math/big" 21 22 "github.com/ethereum/go-ethereum/common" 23 "github.com/ethereum/go-ethereum/core/types" 24 "github.com/ethereum/go-ethereum/params" 25 "github.com/holiman/uint256" 26 ) 27 28 // OpContext provides the context at which the opcode is being 29 // executed in, including the memory, stack and various contract-level information. 30 type OpContext interface { 31 MemoryData() []byte 32 StackData() []uint256.Int 33 Caller() common.Address 34 Address() common.Address 35 CallValue() *uint256.Int 36 CallInput() []byte 37 } 38 39 // StateDB gives tracers access to the whole state. 40 type StateDB interface { 41 GetBalance(common.Address) *uint256.Int 42 GetNonce(common.Address) uint64 43 GetCode(common.Address) []byte 44 GetState(common.Address, common.Hash) common.Hash 45 Exist(common.Address) bool 46 GetRefund() uint64 47 } 48 49 // VMContext provides the context for the EVM execution. 50 type VMContext struct { 51 Coinbase common.Address 52 BlockNumber *big.Int 53 Time uint64 54 Random *common.Hash 55 // Effective tx gas price 56 GasPrice *big.Int 57 ChainConfig *params.ChainConfig 58 StateDB StateDB 59 } 60 61 // BlockEvent is emitted upon tracing an incoming block. 62 // It contains the block as well as consensus related information. 63 type BlockEvent struct { 64 Block *types.Block 65 TD *big.Int 66 Finalized *types.Header 67 Safe *types.Header 68 } 69 70 type ( 71 /* 72 - VM events - 73 */ 74 75 // TxStartHook is called before the execution of a transaction starts. 76 // Call simulations don't come with a valid signature. `from` field 77 // to be used for address of the caller. 78 TxStartHook = func(vm *VMContext, tx *types.Transaction, from common.Address) 79 80 // TxEndHook is called after the execution of a transaction ends. 81 TxEndHook = func(receipt *types.Receipt, err error) 82 83 // EnterHook is invoked when the processing of a message starts. 84 // 85 // Take note that EnterHook, when in the context of a live tracer, can be invoked 86 // outside of the `OnTxStart` and `OnTxEnd` hooks when dealing with system calls, 87 // see [OnSystemCallStartHook] and [OnSystemCallEndHook] for more information. 88 EnterHook = func(depth int, typ byte, from common.Address, to common.Address, input []byte, gas uint64, value *big.Int) 89 90 // ExitHook is invoked when the processing of a message ends. 91 // `revert` is true when there was an error during the execution. 92 // Exceptionally, before the homestead hardfork a contract creation that 93 // ran out of gas when attempting to persist the code to database did not 94 // count as a call failure and did not cause a revert of the call. This will 95 // be indicated by `reverted == false` and `err == ErrCodeStoreOutOfGas`. 96 // 97 // Take note that ExitHook, when in the context of a live tracer, can be invoked 98 // outside of the `OnTxStart` and `OnTxEnd` hooks when dealing with system calls, 99 // see [OnSystemCallStartHook] and [OnSystemCallEndHook] for more information. 100 ExitHook = func(depth int, output []byte, gasUsed uint64, err error, reverted bool) 101 102 // OpcodeHook is invoked just prior to the execution of an opcode. 103 OpcodeHook = func(pc uint64, op byte, gas, cost uint64, scope OpContext, rData []byte, depth int, err error) 104 105 // FaultHook is invoked when an error occurs during the execution of an opcode. 106 FaultHook = func(pc uint64, op byte, gas, cost uint64, scope OpContext, depth int, err error) 107 108 // GasChangeHook is invoked when the gas changes. 109 GasChangeHook = func(old, new uint64, reason GasChangeReason) 110 111 /* 112 - Chain events - 113 */ 114 115 // BlockchainInitHook is called when the blockchain is initialized. 116 BlockchainInitHook = func(chainConfig *params.ChainConfig) 117 118 // CloseHook is called when the blockchain closes. 119 CloseHook = func() 120 121 // BlockStartHook is called before executing `block`. 122 // `td` is the total difficulty prior to `block`. 123 BlockStartHook = func(event BlockEvent) 124 125 // BlockEndHook is called after executing a block. 126 BlockEndHook = func(err error) 127 128 // SkippedBlockHook indicates a block was skipped during processing 129 // due to it being known previously. This can happen e.g. when recovering 130 // from a crash. 131 SkippedBlockHook = func(event BlockEvent) 132 133 // GenesisBlockHook is called when the genesis block is being processed. 134 GenesisBlockHook = func(genesis *types.Block, alloc types.GenesisAlloc) 135 136 // OnSystemCallStartHook is called when a system call is about to be executed. Today, 137 // this hook is invoked when the EIP-4788 system call is about to be executed to set the 138 // beacon block root. 139 // 140 // After this hook, the EVM call tracing will happened as usual so you will receive a `OnEnter/OnExit` 141 // as well as state hooks between this hook and the `OnSystemCallEndHook`. 142 // 143 // Note that system call happens outside normal transaction execution, so the `OnTxStart/OnTxEnd` hooks 144 // will not be invoked. 145 OnSystemCallStartHook = func() 146 147 // OnSystemCallEndHook is called when a system call has finished executing. Today, 148 // this hook is invoked when the EIP-4788 system call is about to be executed to set the 149 // beacon block root. 150 OnSystemCallEndHook = func() 151 152 /* 153 - State events - 154 */ 155 156 // BalanceChangeHook is called when the balance of an account changes. 157 BalanceChangeHook = func(addr common.Address, prev, new *big.Int, reason BalanceChangeReason) 158 159 // NonceChangeHook is called when the nonce of an account changes. 160 NonceChangeHook = func(addr common.Address, prev, new uint64) 161 162 // CodeChangeHook is called when the code of an account changes. 163 CodeChangeHook = func(addr common.Address, prevCodeHash common.Hash, prevCode []byte, codeHash common.Hash, code []byte) 164 165 // StorageChangeHook is called when the storage of an account changes. 166 StorageChangeHook = func(addr common.Address, slot common.Hash, prev, new common.Hash) 167 168 // LogHook is called when a log is emitted. 169 LogHook = func(log *types.Log) 170 ) 171 172 type Hooks struct { 173 // VM events 174 OnTxStart TxStartHook 175 OnTxEnd TxEndHook 176 OnEnter EnterHook 177 OnExit ExitHook 178 OnOpcode OpcodeHook 179 OnFault FaultHook 180 OnGasChange GasChangeHook 181 // Chain events 182 OnBlockchainInit BlockchainInitHook 183 OnClose CloseHook 184 OnBlockStart BlockStartHook 185 OnBlockEnd BlockEndHook 186 OnSkippedBlock SkippedBlockHook 187 OnGenesisBlock GenesisBlockHook 188 OnSystemCallStart OnSystemCallStartHook 189 OnSystemCallEnd OnSystemCallEndHook 190 // State events 191 OnBalanceChange BalanceChangeHook 192 OnNonceChange NonceChangeHook 193 OnCodeChange CodeChangeHook 194 OnStorageChange StorageChangeHook 195 OnLog LogHook 196 } 197 198 // BalanceChangeReason is used to indicate the reason for a balance change, useful 199 // for tracing and reporting. 200 type BalanceChangeReason byte 201 202 const ( 203 BalanceChangeUnspecified BalanceChangeReason = 0 204 205 // Issuance 206 // BalanceIncreaseRewardMineUncle is a reward for mining an uncle block. 207 BalanceIncreaseRewardMineUncle BalanceChangeReason = 1 208 // BalanceIncreaseRewardMineBlock is a reward for mining a block. 209 BalanceIncreaseRewardMineBlock BalanceChangeReason = 2 210 // BalanceIncreaseWithdrawal is ether withdrawn from the beacon chain. 211 BalanceIncreaseWithdrawal BalanceChangeReason = 3 212 // BalanceIncreaseGenesisBalance is ether allocated at the genesis block. 213 BalanceIncreaseGenesisBalance BalanceChangeReason = 4 214 215 // Transaction fees 216 // BalanceIncreaseRewardTransactionFee is the transaction tip increasing block builder's balance. 217 BalanceIncreaseRewardTransactionFee BalanceChangeReason = 5 218 // BalanceDecreaseGasBuy is spent to purchase gas for execution a transaction. 219 // Part of this gas will be burnt as per EIP-1559 rules. 220 BalanceDecreaseGasBuy BalanceChangeReason = 6 221 // BalanceIncreaseGasReturn is ether returned for unused gas at the end of execution. 222 BalanceIncreaseGasReturn BalanceChangeReason = 7 223 224 // DAO fork 225 // BalanceIncreaseDaoContract is ether sent to the DAO refund contract. 226 BalanceIncreaseDaoContract BalanceChangeReason = 8 227 // BalanceDecreaseDaoAccount is ether taken from a DAO account to be moved to the refund contract. 228 BalanceDecreaseDaoAccount BalanceChangeReason = 9 229 230 // BalanceChangeTransfer is ether transferred via a call. 231 // it is a decrease for the sender and an increase for the recipient. 232 BalanceChangeTransfer BalanceChangeReason = 10 233 // BalanceChangeTouchAccount is a transfer of zero value. It is only there to 234 // touch-create an account. 235 BalanceChangeTouchAccount BalanceChangeReason = 11 236 237 // BalanceIncreaseSelfdestruct is added to the recipient as indicated by a selfdestructing account. 238 BalanceIncreaseSelfdestruct BalanceChangeReason = 12 239 // BalanceDecreaseSelfdestruct is deducted from a contract due to self-destruct. 240 BalanceDecreaseSelfdestruct BalanceChangeReason = 13 241 // BalanceDecreaseSelfdestructBurn is ether that is sent to an already self-destructed 242 // account within the same tx (captured at end of tx). 243 // Note it doesn't account for a self-destruct which appoints itself as recipient. 244 BalanceDecreaseSelfdestructBurn BalanceChangeReason = 14 245 ) 246 247 // GasChangeReason is used to indicate the reason for a gas change, useful 248 // for tracing and reporting. 249 // 250 // There is essentially two types of gas changes, those that can be emitted once per transaction 251 // and those that can be emitted on a call basis, so possibly multiple times per transaction. 252 // 253 // They can be recognized easily by their name, those that start with `GasChangeTx` are emitted 254 // once per transaction, while those that start with `GasChangeCall` are emitted on a call basis. 255 type GasChangeReason byte 256 257 const ( 258 GasChangeUnspecified GasChangeReason = 0 259 260 // GasChangeTxInitialBalance is the initial balance for the call which will be equal to the gasLimit of the call. There is only 261 // one such gas change per transaction. 262 GasChangeTxInitialBalance GasChangeReason = 1 263 // GasChangeTxIntrinsicGas is the amount of gas that will be charged for the intrinsic cost of the transaction, there is 264 // always exactly one of those per transaction. 265 GasChangeTxIntrinsicGas GasChangeReason = 2 266 // GasChangeTxRefunds is the sum of all refunds which happened during the tx execution (e.g. storage slot being cleared) 267 // this generates an increase in gas. There is at most one of such gas change per transaction. 268 GasChangeTxRefunds GasChangeReason = 3 269 // GasChangeTxLeftOverReturned is the amount of gas left over at the end of transaction's execution that will be returned 270 // to the chain. This change will always be a negative change as we "drain" left over gas towards 0. If there was no gas 271 // left at the end of execution, no such even will be emitted. The returned gas's value in Wei is returned to caller. 272 // There is at most one of such gas change per transaction. 273 GasChangeTxLeftOverReturned GasChangeReason = 4 274 275 // GasChangeCallInitialBalance is the initial balance for the call which will be equal to the gasLimit of the call. There is only 276 // one such gas change per call. 277 GasChangeCallInitialBalance GasChangeReason = 5 278 // GasChangeCallLeftOverReturned is the amount of gas left over that will be returned to the caller, this change will always 279 // be a negative change as we "drain" left over gas towards 0. If there was no gas left at the end of execution, no such even 280 // will be emitted. 281 GasChangeCallLeftOverReturned GasChangeReason = 6 282 // GasChangeCallLeftOverRefunded is the amount of gas that will be refunded to the call after the child call execution it 283 // executed completed. This value is always positive as we are giving gas back to the you, the left over gas of the child. 284 // If there was no gas left to be refunded, no such even will be emitted. 285 GasChangeCallLeftOverRefunded GasChangeReason = 7 286 // GasChangeCallContractCreation is the amount of gas that will be burned for a CREATE. 287 GasChangeCallContractCreation GasChangeReason = 8 288 // GasChangeContractCreation is the amount of gas that will be burned for a CREATE2. 289 GasChangeCallContractCreation2 GasChangeReason = 9 290 // GasChangeCallCodeStorage is the amount of gas that will be charged for code storage. 291 GasChangeCallCodeStorage GasChangeReason = 10 292 // GasChangeCallOpCode is the amount of gas that will be charged for an opcode executed by the EVM, exact opcode that was 293 // performed can be check by `OnOpcode` handling. 294 GasChangeCallOpCode GasChangeReason = 11 295 // GasChangeCallPrecompiledContract is the amount of gas that will be charged for a precompiled contract execution. 296 GasChangeCallPrecompiledContract GasChangeReason = 12 297 // GasChangeCallStorageColdAccess is the amount of gas that will be charged for a cold storage access as controlled by EIP2929 rules. 298 GasChangeCallStorageColdAccess GasChangeReason = 13 299 // GasChangeCallFailedExecution is the burning of the remaining gas when the execution failed without a revert. 300 GasChangeCallFailedExecution GasChangeReason = 14 301 // GasChangeWitnessContractInit is the amount charged for adding to the witness during the contract creation initialization step 302 GasChangeWitnessContractInit GasChangeReason = 15 303 // GasChangeWitnessContractCreation is the amount charged for adding to the witness during the contract creation finalization step 304 GasChangeWitnessContractCreation GasChangeReason = 16 305 // GasChangeWitnessCodeChunk is the amount charged for touching one or more contract code chunks 306 GasChangeWitnessCodeChunk GasChangeReason = 17 307 308 // GasChangeIgnored is a special value that can be used to indicate that the gas change should be ignored as 309 // it will be "manually" tracked by a direct emit of the gas change event. 310 GasChangeIgnored GasChangeReason = 0xFF 311 )