github.com/tacshi/go-ethereum@v0.0.0-20230616113857-84a434e20921/core/state_transition.go (about) 1 // Copyright 2014 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 core 18 19 import ( 20 "fmt" 21 "math" 22 "math/big" 23 24 "github.com/tacshi/go-ethereum/common" 25 cmath "github.com/tacshi/go-ethereum/common/math" 26 "github.com/tacshi/go-ethereum/core/types" 27 "github.com/tacshi/go-ethereum/core/vm" 28 "github.com/tacshi/go-ethereum/params" 29 ) 30 31 // ExecutionResult includes all output after executing given evm 32 // message no matter the execution itself is successful or not. 33 type ExecutionResult struct { 34 UsedGas uint64 // Total used gas but include the refunded gas 35 Err error // Any error encountered during the execution(listed in core/vm/errors.go) 36 ReturnData []byte // Returned data from evm(function result or data supplied with revert opcode) 37 38 // Arbitrum: a tx may yield others that need to run afterward (see retryables) 39 ScheduledTxes types.Transactions 40 // Arbitrum: the contract deployed from the top-level transaction, or nil if not a contract creation tx 41 TopLevelDeployed *common.Address 42 } 43 44 // Unwrap returns the internal evm error which allows us for further 45 // analysis outside. 46 func (result *ExecutionResult) Unwrap() error { 47 return result.Err 48 } 49 50 // Failed returns the indicator whether the execution is successful or not 51 func (result *ExecutionResult) Failed() bool { return result.Err != nil } 52 53 // Return is a helper function to help caller distinguish between revert reason 54 // and function return. Return returns the data after execution if no error occurs. 55 func (result *ExecutionResult) Return() []byte { 56 if result.Err != nil { 57 return nil 58 } 59 return common.CopyBytes(result.ReturnData) 60 } 61 62 // Revert returns the concrete revert reason if the execution is aborted by `REVERT` 63 // opcode. Note the reason can be nil if no data supplied with revert opcode. 64 func (result *ExecutionResult) Revert() []byte { 65 if result.Err != vm.ErrExecutionReverted { 66 return nil 67 } 68 return common.CopyBytes(result.ReturnData) 69 } 70 71 // IntrinsicGas computes the 'intrinsic gas' for a message with the given data. 72 func IntrinsicGas(data []byte, accessList types.AccessList, isContractCreation bool, isHomestead, isEIP2028 bool, isEIP3860 bool) (uint64, error) { 73 // Set the starting gas for the raw transaction 74 var gas uint64 75 if isContractCreation && isHomestead { 76 gas = params.TxGasContractCreation 77 } else { 78 gas = params.TxGas 79 } 80 dataLen := uint64(len(data)) 81 // Bump the required gas by the amount of transactional data 82 if dataLen > 0 { 83 // Zero and non-zero bytes are priced differently 84 var nz uint64 85 for _, byt := range data { 86 if byt != 0 { 87 nz++ 88 } 89 } 90 // Make sure we don't exceed uint64 for all data combinations 91 nonZeroGas := params.TxDataNonZeroGasFrontier 92 if isEIP2028 { 93 nonZeroGas = params.TxDataNonZeroGasEIP2028 94 } 95 if (math.MaxUint64-gas)/nonZeroGas < nz { 96 return 0, ErrGasUintOverflow 97 } 98 gas += nz * nonZeroGas 99 100 z := dataLen - nz 101 if (math.MaxUint64-gas)/params.TxDataZeroGas < z { 102 return 0, ErrGasUintOverflow 103 } 104 gas += z * params.TxDataZeroGas 105 106 if isContractCreation && isEIP3860 { 107 lenWords := toWordSize(dataLen) 108 if (math.MaxUint64-gas)/params.InitCodeWordGas < lenWords { 109 return 0, ErrGasUintOverflow 110 } 111 gas += lenWords * params.InitCodeWordGas 112 } 113 } 114 if accessList != nil { 115 gas += uint64(len(accessList)) * params.TxAccessListAddressGas 116 gas += uint64(accessList.StorageKeys()) * params.TxAccessListStorageKeyGas 117 } 118 return gas, nil 119 } 120 121 // toWordSize returns the ceiled word size required for init code payment calculation. 122 func toWordSize(size uint64) uint64 { 123 if size > math.MaxUint64-31 { 124 return math.MaxUint64/32 + 1 125 } 126 127 return (size + 31) / 32 128 } 129 130 // A Message contains the data derived from a single transaction that is relevant to state 131 // processing. 132 type Message struct { 133 // Arbitrum-specific 134 TxRunMode MessageRunMode 135 Tx *types.Transaction 136 137 To *common.Address 138 From common.Address 139 Nonce uint64 140 Value *big.Int 141 GasLimit uint64 142 GasPrice *big.Int 143 GasFeeCap *big.Int 144 GasTipCap *big.Int 145 Data []byte 146 AccessList types.AccessList 147 148 // When SkipAccountCheckss is true, the message nonce is not checked against the 149 // account nonce in state. It also disables checking that the sender is an EOA. 150 // This field will be set to true for operations like RPC eth_call. 151 SkipAccountChecks bool 152 } 153 154 type MessageRunMode uint8 155 156 const ( 157 MessageCommitMode MessageRunMode = iota 158 MessageGasEstimationMode 159 MessageEthcallMode 160 ) 161 162 // TransactionToMessage converts a transaction into a Message. 163 func TransactionToMessage(tx *types.Transaction, s types.Signer, baseFee *big.Int) (*Message, error) { 164 msg := &Message{ 165 Tx: tx, 166 167 Nonce: tx.Nonce(), 168 GasLimit: tx.Gas(), 169 GasPrice: new(big.Int).Set(tx.GasPrice()), 170 GasFeeCap: new(big.Int).Set(tx.GasFeeCap()), 171 GasTipCap: new(big.Int).Set(tx.GasTipCap()), 172 To: tx.To(), 173 Value: tx.Value(), 174 Data: tx.Data(), 175 AccessList: tx.AccessList(), 176 SkipAccountChecks: tx.SkipAccountChecks(), 177 } 178 // If baseFee provided, set gasPrice to effectiveGasPrice. 179 if baseFee != nil { 180 msg.GasPrice = cmath.BigMin(msg.GasPrice.Add(msg.GasTipCap, baseFee), msg.GasFeeCap) 181 } 182 var err error 183 msg.From, err = types.Sender(s, tx) 184 return msg, err 185 } 186 187 // ApplyMessage computes the new state by applying the given message 188 // against the old state within the environment. 189 // 190 // ApplyMessage returns the bytes returned by any EVM execution (if it took place), 191 // the gas used (which includes gas refunds) and an error if it failed. An error always 192 // indicates a core error meaning that the message would always fail for that particular 193 // state and would never be accepted within a block. 194 func ApplyMessage(evm *vm.EVM, msg *Message, gp *GasPool) (*ExecutionResult, error) { 195 return NewStateTransition(evm, msg, gp).TransitionDb() 196 } 197 198 // StateTransition represents a state transition. 199 // 200 // == The State Transitioning Model 201 // 202 // A state transition is a change made when a transaction is applied to the current world 203 // state. The state transitioning model does all the necessary work to work out a valid new 204 // state root. 205 // 206 // 1. Nonce handling 207 // 2. Pre pay gas 208 // 3. Create a new state object if the recipient is nil 209 // 4. Value transfer 210 // 211 // == If contract creation == 212 // 213 // 4a. Attempt to run transaction data 214 // 4b. If valid, use result as code for the new state object 215 // 216 // == end == 217 // 218 // 5. Run Script section 219 // 6. Derive new state root 220 type StateTransition struct { 221 gp *GasPool 222 msg *Message 223 gasRemaining uint64 224 initialGas uint64 225 state vm.StateDB 226 evm *vm.EVM 227 } 228 229 // NewStateTransition initialises and returns a new state transition object. 230 func NewStateTransition(evm *vm.EVM, msg *Message, gp *GasPool) *StateTransition { 231 if ReadyEVMForL2 != nil { 232 ReadyEVMForL2(evm, msg) 233 } 234 235 return &StateTransition{ 236 gp: gp, 237 evm: evm, 238 msg: msg, 239 state: evm.StateDB, 240 } 241 } 242 243 // to returns the recipient of the message. 244 func (st *StateTransition) to() common.Address { 245 if st.msg == nil || st.msg.To == nil /* contract creation */ { 246 return common.Address{} 247 } 248 return *st.msg.To 249 } 250 251 func (st *StateTransition) buyGas() error { 252 mgval := new(big.Int).SetUint64(st.msg.GasLimit) 253 mgval = mgval.Mul(mgval, st.msg.GasPrice) 254 balanceCheck := mgval 255 if st.msg.GasFeeCap != nil { 256 balanceCheck = new(big.Int).SetUint64(st.msg.GasLimit) 257 balanceCheck = balanceCheck.Mul(balanceCheck, st.msg.GasFeeCap) 258 balanceCheck.Add(balanceCheck, st.msg.Value) 259 } 260 if have, want := st.state.GetBalance(st.msg.From), balanceCheck; have.Cmp(want) < 0 { 261 return fmt.Errorf("%w: address %v have %v want %v", ErrInsufficientFunds, st.msg.From.Hex(), have, want) 262 } 263 if err := st.gp.SubGas(st.msg.GasLimit); err != nil { 264 return err 265 } 266 st.gasRemaining += st.msg.GasLimit 267 268 st.initialGas = st.msg.GasLimit 269 st.state.SubBalance(st.msg.From, mgval) 270 271 // Arbitrum: record fee payment 272 if st.evm.Config.Debug { 273 st.evm.Config.Tracer.CaptureArbitrumTransfer(st.evm, &st.msg.From, nil, mgval, true, "feePayment") 274 } 275 276 return nil 277 } 278 279 func (st *StateTransition) preCheck() error { 280 // Only check transactions that are not fake 281 msg := st.msg 282 if !msg.SkipAccountChecks { 283 // Make sure this transaction's nonce is correct. 284 stNonce := st.state.GetNonce(msg.From) 285 if msgNonce := msg.Nonce; stNonce < msgNonce { 286 return fmt.Errorf("%w: address %v, tx: %d state: %d", ErrNonceTooHigh, 287 msg.From.Hex(), msgNonce, stNonce) 288 } else if stNonce > msgNonce { 289 return fmt.Errorf("%w: address %v, tx: %d state: %d", ErrNonceTooLow, 290 msg.From.Hex(), msgNonce, stNonce) 291 } else if stNonce+1 < stNonce { 292 return fmt.Errorf("%w: address %v, nonce: %d", ErrNonceMax, 293 msg.From.Hex(), stNonce) 294 } 295 // Make sure the sender is an EOA 296 codeHash := st.state.GetCodeHash(msg.From) 297 if codeHash != (common.Hash{}) && codeHash != types.EmptyCodeHash { 298 return fmt.Errorf("%w: address %v, codehash: %s", ErrSenderNoEOA, 299 msg.From.Hex(), codeHash) 300 } 301 } 302 303 // Make sure that transaction gasFeeCap is greater than the baseFee (post london) 304 if st.evm.ChainConfig().IsLondon(st.evm.Context.BlockNumber) { 305 // Skip the checks if gas fields are zero and baseFee was explicitly disabled (eth_call) 306 if !st.evm.Config.NoBaseFee || msg.GasFeeCap.BitLen() > 0 || msg.GasTipCap.BitLen() > 0 { 307 if l := msg.GasFeeCap.BitLen(); l > 256 { 308 return fmt.Errorf("%w: address %v, maxFeePerGas bit length: %d", ErrFeeCapVeryHigh, 309 msg.From.Hex(), l) 310 } 311 if l := msg.GasTipCap.BitLen(); l > 256 { 312 return fmt.Errorf("%w: address %v, maxPriorityFeePerGas bit length: %d", ErrTipVeryHigh, 313 msg.From.Hex(), l) 314 } 315 if msg.GasFeeCap.Cmp(msg.GasTipCap) < 0 { 316 return fmt.Errorf("%w: address %v, maxPriorityFeePerGas: %s, maxFeePerGas: %s", ErrTipAboveFeeCap, 317 msg.From.Hex(), msg.GasTipCap, msg.GasFeeCap) 318 } 319 // This will panic if baseFee is nil, but basefee presence is verified 320 // as part of header validation. 321 if msg.GasFeeCap.Cmp(st.evm.Context.BaseFee) < 0 { 322 return fmt.Errorf("%w: address %v, maxFeePerGas: %s baseFee: %s", ErrFeeCapTooLow, 323 msg.From.Hex(), msg.GasFeeCap, st.evm.Context.BaseFee) 324 } 325 } 326 } 327 return st.buyGas() 328 } 329 330 // TransitionDb will transition the state by applying the current message and 331 // returning the evm execution result with following fields. 332 // 333 // - used gas: total gas used (including gas being refunded) 334 // - returndata: the returned data from evm 335 // - concrete execution error: various EVM errors which abort the execution, e.g. 336 // ErrOutOfGas, ErrExecutionReverted 337 // 338 // However if any consensus issue encountered, return the error directly with 339 // nil evm execution result. 340 func (st *StateTransition) TransitionDb() (*ExecutionResult, error) { 341 endTxNow, startHookUsedGas, err, returnData := st.evm.ProcessingHook.StartTxHook() 342 if endTxNow { 343 return &ExecutionResult{ 344 UsedGas: startHookUsedGas, 345 Err: err, 346 ReturnData: returnData, 347 ScheduledTxes: st.evm.ProcessingHook.ScheduledTxes(), 348 }, nil 349 } 350 351 // First check this message satisfies all consensus rules before 352 // applying the message. The rules include these clauses 353 // 354 // 1. the nonce of the message caller is correct 355 // 2. caller has enough balance to cover transaction fee(gaslimit * gasprice) 356 // 3. the amount of gas required is available in the block 357 // 4. the purchased gas is enough to cover intrinsic usage 358 // 5. there is no overflow when calculating intrinsic gas 359 // 6. caller has enough balance to cover asset transfer for **topmost** call 360 361 // Arbitrum: drop tip for delayed (and old) messages 362 if st.evm.ProcessingHook.DropTip() && st.msg.GasPrice.Cmp(st.evm.Context.BaseFee) > 0 { 363 st.msg.GasPrice = st.evm.Context.BaseFee 364 st.msg.GasTipCap = common.Big0 365 } 366 367 // Check clauses 1-3, buy gas if everything is correct 368 if err := st.preCheck(); err != nil { 369 return nil, err 370 } 371 372 if st.evm.Config.Debug { 373 st.evm.Config.Tracer.CaptureTxStart(st.initialGas) 374 defer func() { 375 st.evm.Config.Tracer.CaptureTxEnd(st.gasRemaining) 376 }() 377 } 378 379 var ( 380 msg = st.msg 381 sender = vm.AccountRef(msg.From) 382 rules = st.evm.ChainConfig().Rules(st.evm.Context.BlockNumber, st.evm.Context.Random != nil, st.evm.Context.Time, st.evm.Context.ArbOSVersion) 383 contractCreation = msg.To == nil 384 ) 385 386 // Check clauses 4-5, subtract intrinsic gas if everything is correct 387 gas, err := IntrinsicGas(msg.Data, msg.AccessList, contractCreation, rules.IsHomestead, rules.IsIstanbul, rules.IsShanghai) 388 if err != nil { 389 return nil, err 390 } 391 if st.gasRemaining < gas { 392 return nil, fmt.Errorf("%w: have %d, want %d", ErrIntrinsicGas, st.gasRemaining, gas) 393 } 394 st.gasRemaining -= gas 395 396 tipAmount := big.NewInt(0) 397 tipReceipient, err := st.evm.ProcessingHook.GasChargingHook(&st.gasRemaining) 398 if err != nil { 399 return nil, err 400 } 401 402 // Check clause 6 403 if msg.Value.Sign() > 0 && !st.evm.Context.CanTransfer(st.state, msg.From, msg.Value) { 404 return nil, fmt.Errorf("%w: address %v", ErrInsufficientFundsForTransfer, msg.From.Hex()) 405 } 406 407 // Check whether the init code size has been exceeded. 408 if rules.IsShanghai && contractCreation && len(msg.Data) > params.MaxInitCodeSize { 409 return nil, fmt.Errorf("%w: code size %v limit %v", ErrMaxInitCodeSizeExceeded, len(msg.Data), params.MaxInitCodeSize) 410 } 411 412 // Execute the preparatory steps for state transition which includes: 413 // - prepare accessList(post-berlin) 414 // - reset transient storage(eip 1153) 415 st.state.Prepare(rules, msg.From, st.evm.Context.Coinbase, msg.To, vm.ActivePrecompiles(rules), msg.AccessList) 416 417 var deployedContract *common.Address 418 419 var ( 420 ret []byte 421 vmerr error // vm errors do not effect consensus and are therefore not assigned to err 422 ) 423 if contractCreation { 424 deployedContract = &common.Address{} 425 ret, *deployedContract, st.gasRemaining, vmerr = st.evm.Create(sender, msg.Data, st.gasRemaining, msg.Value) 426 } else { 427 // Increment the nonce for the next transaction 428 st.state.SetNonce(msg.From, st.state.GetNonce(sender.Address())+1) 429 ret, st.gasRemaining, vmerr = st.evm.Call(sender, st.to(), msg.Data, st.gasRemaining, msg.Value) 430 } 431 432 if !rules.IsLondon { 433 // Before EIP-3529: refunds were capped to gasUsed / 2 434 st.refundGas(params.RefundQuotient) 435 } else { 436 // After EIP-3529: refunds are capped to gasUsed / 5 437 st.refundGas(params.RefundQuotientEIP3529) 438 } 439 effectiveTip := msg.GasPrice 440 if rules.IsLondon { 441 effectiveTip = cmath.BigMin(msg.GasTipCap, new(big.Int).Sub(msg.GasFeeCap, st.evm.Context.BaseFee)) 442 } 443 444 if st.evm.Config.NoBaseFee && msg.GasFeeCap.Sign() == 0 && msg.GasTipCap.Sign() == 0 { 445 // Skip fee payment when NoBaseFee is set and the fee fields 446 // are 0. This avoids a negative effectiveTip being applied to 447 // the coinbase when simulating calls. 448 } else { 449 fee := new(big.Int).SetUint64(st.gasUsed()) 450 fee.Mul(fee, effectiveTip) 451 st.state.AddBalance(tipReceipient, fee) 452 tipAmount = fee 453 } 454 455 // Arbitrum: record the tip 456 if st.evm.Config.Debug && !st.evm.ProcessingHook.DropTip() { 457 st.evm.Config.Tracer.CaptureArbitrumTransfer(st.evm, nil, &tipReceipient, tipAmount, false, "tip") 458 } 459 460 st.evm.ProcessingHook.EndTxHook(st.gasRemaining, vmerr == nil) 461 462 // Arbitrum: record self destructs 463 if st.evm.Config.Debug { 464 suicides := st.evm.StateDB.GetSuicides() 465 for i, address := range suicides { 466 balance := st.evm.StateDB.GetBalance(address) 467 st.evm.Config.Tracer.CaptureArbitrumTransfer(st.evm, &suicides[i], nil, balance, false, "selfDestruct") 468 } 469 } 470 471 return &ExecutionResult{ 472 UsedGas: st.gasUsed(), 473 Err: vmerr, 474 ReturnData: ret, 475 ScheduledTxes: st.evm.ProcessingHook.ScheduledTxes(), 476 TopLevelDeployed: deployedContract, 477 }, nil 478 } 479 480 func (st *StateTransition) refundGas(refundQuotient uint64) { 481 st.gasRemaining += st.evm.ProcessingHook.ForceRefundGas() 482 483 nonrefundable := st.evm.ProcessingHook.NonrefundableGas() 484 if nonrefundable < st.gasUsed() { 485 // Apply refund counter, capped to a refund quotient 486 refund := (st.gasUsed() - nonrefundable) / refundQuotient 487 if refund > st.state.GetRefund() { 488 refund = st.state.GetRefund() 489 } 490 st.gasRemaining += refund 491 } 492 493 // Return ETH for remaining gas, exchanged at the original rate. 494 remaining := new(big.Int).Mul(new(big.Int).SetUint64(st.gasRemaining), st.msg.GasPrice) 495 st.state.AddBalance(st.msg.From, remaining) 496 497 // Arbitrum: record the gas refund 498 if st.evm.Config.Debug { 499 st.evm.Config.Tracer.CaptureArbitrumTransfer(st.evm, nil, &st.msg.From, remaining, false, "gasRefund") 500 } 501 502 // Also return remaining gas to the block gas counter so it is 503 // available for the next transaction. 504 st.gp.AddGas(st.gasRemaining) 505 } 506 507 // gasUsed returns the amount of gas used up by the state transition. 508 func (st *StateTransition) gasUsed() uint64 { 509 return st.initialGas - st.gasRemaining 510 }