gitee.com/liu-zhao234568/cntest@v1.0.0/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 "gitee.com/liu-zhao234568/cntest/common" 25 cmath "gitee.com/liu-zhao234568/cntest/common/math" 26 "gitee.com/liu-zhao234568/cntest/core/types" 27 "gitee.com/liu-zhao234568/cntest/core/vm" 28 "gitee.com/liu-zhao234568/cntest/params" 29 ) 30 31 /* 32 The State Transitioning Model 33 34 A state transition is a change made when a transaction is applied to the current world state 35 The state transitioning model does all the necessary work to work out a valid new state root. 36 37 1) Nonce handling 38 2) Pre pay gas 39 3) Create a new state object if the recipient is \0*32 40 4) Value transfer 41 == If contract creation == 42 4a) Attempt to run transaction data 43 4b) If valid, use result as code for the new state object 44 == end == 45 5) Run Script section 46 6) Derive new state root 47 */ 48 type StateTransition struct { 49 gp *GasPool 50 msg Message 51 gas uint64 52 gasPrice *big.Int 53 gasFeeCap *big.Int 54 gasTipCap *big.Int 55 initialGas uint64 56 value *big.Int 57 data []byte 58 state vm.StateDB 59 evm *vm.EVM 60 } 61 62 // Message represents a message sent to a contract. 63 type Message interface { 64 From() common.Address 65 To() *common.Address 66 67 GasPrice() *big.Int 68 GasFeeCap() *big.Int 69 GasTipCap() *big.Int 70 Gas() uint64 71 Value() *big.Int 72 73 Nonce() uint64 74 CheckNonce() bool 75 Data() []byte 76 AccessList() types.AccessList 77 } 78 79 // ExecutionResult includes all output after executing given evm 80 // message no matter the execution itself is successful or not. 81 type ExecutionResult struct { 82 UsedGas uint64 // Total used gas but include the refunded gas 83 Err error // Any error encountered during the execution(listed in core/vm/errors.go) 84 ReturnData []byte // Returned data from evm(function result or data supplied with revert opcode) 85 } 86 87 // Unwrap returns the internal evm error which allows us for further 88 // analysis outside. 89 func (result *ExecutionResult) Unwrap() error { 90 return result.Err 91 } 92 93 // Failed returns the indicator whether the execution is successful or not 94 func (result *ExecutionResult) Failed() bool { return result.Err != nil } 95 96 // Return is a helper function to help caller distinguish between revert reason 97 // and function return. Return returns the data after execution if no error occurs. 98 func (result *ExecutionResult) Return() []byte { 99 if result.Err != nil { 100 return nil 101 } 102 return common.CopyBytes(result.ReturnData) 103 } 104 105 // Revert returns the concrete revert reason if the execution is aborted by `REVERT` 106 // opcode. Note the reason can be nil if no data supplied with revert opcode. 107 func (result *ExecutionResult) Revert() []byte { 108 if result.Err != vm.ErrExecutionReverted { 109 return nil 110 } 111 return common.CopyBytes(result.ReturnData) 112 } 113 114 // IntrinsicGas computes the 'intrinsic gas' for a message with the given data. 115 func IntrinsicGas(data []byte, accessList types.AccessList, isContractCreation bool, isHomestead, isEIP2028 bool) (uint64, error) { 116 // Set the starting gas for the raw transaction 117 var gas uint64 118 if isContractCreation && isHomestead { 119 gas = params.TxGasContractCreation 120 } else { 121 gas = params.TxGas 122 } 123 // Bump the required gas by the amount of transactional data 124 if len(data) > 0 { 125 // Zero and non-zero bytes are priced differently 126 var nz uint64 127 for _, byt := range data { 128 if byt != 0 { 129 nz++ 130 } 131 } 132 // Make sure we don't exceed uint64 for all data combinations 133 nonZeroGas := params.TxDataNonZeroGasFrontier 134 if isEIP2028 { 135 nonZeroGas = params.TxDataNonZeroGasEIP2028 136 } 137 if (math.MaxUint64-gas)/nonZeroGas < nz { 138 return 0, ErrGasUintOverflow 139 } 140 gas += nz * nonZeroGas 141 142 z := uint64(len(data)) - nz 143 if (math.MaxUint64-gas)/params.TxDataZeroGas < z { 144 return 0, ErrGasUintOverflow 145 } 146 gas += z * params.TxDataZeroGas 147 } 148 if accessList != nil { 149 gas += uint64(len(accessList)) * params.TxAccessListAddressGas 150 gas += uint64(accessList.StorageKeys()) * params.TxAccessListStorageKeyGas 151 } 152 return gas, nil 153 } 154 155 // NewStateTransition initialises and returns a new state transition object. 156 func NewStateTransition(evm *vm.EVM, msg Message, gp *GasPool) *StateTransition { 157 return &StateTransition{ 158 gp: gp, 159 evm: evm, 160 msg: msg, 161 gasPrice: msg.GasPrice(), 162 gasFeeCap: msg.GasFeeCap(), 163 gasTipCap: msg.GasTipCap(), 164 value: msg.Value(), 165 data: msg.Data(), 166 state: evm.StateDB, 167 } 168 } 169 170 // ApplyMessage computes the new state by applying the given message 171 // against the old state within the environment. 172 // 173 // ApplyMessage returns the bytes returned by any EVM execution (if it took place), 174 // the gas used (which includes gas refunds) and an error if it failed. An error always 175 // indicates a core error meaning that the message would always fail for that particular 176 // state and would never be accepted within a block. 177 func ApplyMessage(evm *vm.EVM, msg Message, gp *GasPool) (*ExecutionResult, error) { 178 return NewStateTransition(evm, msg, gp).TransitionDb() 179 } 180 181 // to returns the recipient of the message. 182 func (st *StateTransition) to() common.Address { 183 if st.msg == nil || st.msg.To() == nil /* contract creation */ { 184 return common.Address{} 185 } 186 return *st.msg.To() 187 } 188 189 func (st *StateTransition) buyGas() error { 190 mgval := new(big.Int).SetUint64(st.msg.Gas()) 191 mgval = mgval.Mul(mgval, st.gasPrice) 192 balanceCheck := mgval 193 if st.gasFeeCap != nil { 194 balanceCheck = new(big.Int).SetUint64(st.msg.Gas()) 195 balanceCheck = balanceCheck.Mul(balanceCheck, st.gasFeeCap) 196 balanceCheck.Add(balanceCheck, st.value) 197 } 198 if have, want := st.state.GetBalance(st.msg.From()), balanceCheck; have.Cmp(want) < 0 { 199 return fmt.Errorf("%w: address %v have %v want %v", ErrInsufficientFunds, st.msg.From().Hex(), have, want) 200 } 201 if err := st.gp.SubGas(st.msg.Gas()); err != nil { 202 return err 203 } 204 st.gas += st.msg.Gas() 205 206 st.initialGas = st.msg.Gas() 207 st.state.SubBalance(st.msg.From(), mgval) 208 return nil 209 } 210 211 func (st *StateTransition) preCheck() error { 212 // Make sure this transaction's nonce is correct. 213 if st.msg.CheckNonce() { 214 stNonce := st.state.GetNonce(st.msg.From()) 215 if msgNonce := st.msg.Nonce(); stNonce < msgNonce { 216 return fmt.Errorf("%w: address %v, tx: %d state: %d", ErrNonceTooHigh, 217 st.msg.From().Hex(), msgNonce, stNonce) 218 } else if stNonce > msgNonce { 219 return fmt.Errorf("%w: address %v, tx: %d state: %d", ErrNonceTooLow, 220 st.msg.From().Hex(), msgNonce, stNonce) 221 } 222 } 223 // Make sure that transaction gasFeeCap is greater than the baseFee (post london) 224 if st.evm.ChainConfig().IsLondon(st.evm.Context.BlockNumber) { 225 // Skip the checks if gas fields are zero and baseFee was explicitly disabled (eth_call) 226 if !st.evm.Config.NoBaseFee || st.gasFeeCap.BitLen() > 0 || st.gasTipCap.BitLen() > 0 { 227 if l := st.gasFeeCap.BitLen(); l > 256 { 228 return fmt.Errorf("%w: address %v, maxFeePerGas bit length: %d", ErrFeeCapVeryHigh, 229 st.msg.From().Hex(), l) 230 } 231 if l := st.gasTipCap.BitLen(); l > 256 { 232 return fmt.Errorf("%w: address %v, maxPriorityFeePerGas bit length: %d", ErrTipVeryHigh, 233 st.msg.From().Hex(), l) 234 } 235 if st.gasFeeCap.Cmp(st.gasTipCap) < 0 { 236 return fmt.Errorf("%w: address %v, maxPriorityFeePerGas: %s, maxFeePerGas: %s", ErrTipAboveFeeCap, 237 st.msg.From().Hex(), st.gasTipCap, st.gasFeeCap) 238 } 239 // This will panic if baseFee is nil, but basefee presence is verified 240 // as part of header validation. 241 if st.gasFeeCap.Cmp(st.evm.Context.BaseFee) < 0 { 242 return fmt.Errorf("%w: address %v, maxFeePerGas: %s baseFee: %s", ErrFeeCapTooLow, 243 st.msg.From().Hex(), st.gasFeeCap, st.evm.Context.BaseFee) 244 } 245 } 246 } 247 return st.buyGas() 248 } 249 250 // TransitionDb will transition the state by applying the current message and 251 // returning the evm execution result with following fields. 252 // 253 // - used gas: 254 // total gas used (including gas being refunded) 255 // - returndata: 256 // the returned data from evm 257 // - concrete execution error: 258 // various **EVM** error which aborts the execution, 259 // e.g. ErrOutOfGas, ErrExecutionReverted 260 // 261 // However if any consensus issue encountered, return the error directly with 262 // nil evm execution result. 263 func (st *StateTransition) TransitionDb() (*ExecutionResult, error) { 264 // First check this message satisfies all consensus rules before 265 // applying the message. The rules include these clauses 266 // 267 // 1. the nonce of the message caller is correct 268 // 2. caller has enough balance to cover transaction fee(gaslimit * gasprice) 269 // 3. the amount of gas required is available in the block 270 // 4. the purchased gas is enough to cover intrinsic usage 271 // 5. there is no overflow when calculating intrinsic gas 272 // 6. caller has enough balance to cover asset transfer for **topmost** call 273 274 // Check clauses 1-3, buy gas if everything is correct 275 if err := st.preCheck(); err != nil { 276 return nil, err 277 } 278 msg := st.msg 279 sender := vm.AccountRef(msg.From()) 280 homestead := st.evm.ChainConfig().IsHomestead(st.evm.Context.BlockNumber) 281 istanbul := st.evm.ChainConfig().IsIstanbul(st.evm.Context.BlockNumber) 282 contractCreation := msg.To() == nil 283 284 // Check clauses 4-5, subtract intrinsic gas if everything is correct 285 gas, err := IntrinsicGas(st.data, st.msg.AccessList(), contractCreation, homestead, istanbul) 286 if err != nil { 287 return nil, err 288 } 289 if st.gas < gas { 290 return nil, fmt.Errorf("%w: have %d, want %d", ErrIntrinsicGas, st.gas, gas) 291 } 292 st.gas -= gas 293 294 // Check clause 6 295 if msg.Value().Sign() > 0 && !st.evm.Context.CanTransfer(st.state, msg.From(), msg.Value()) { 296 return nil, fmt.Errorf("%w: address %v", ErrInsufficientFundsForTransfer, msg.From().Hex()) 297 } 298 299 // Set up the initial access list. 300 if rules := st.evm.ChainConfig().Rules(st.evm.Context.BlockNumber); rules.IsBerlin { 301 st.state.PrepareAccessList(msg.From(), msg.To(), vm.ActivePrecompiles(rules), msg.AccessList()) 302 } 303 var ( 304 ret []byte 305 vmerr error // vm errors do not effect consensus and are therefore not assigned to err 306 ) 307 if contractCreation { 308 ret, _, st.gas, vmerr = st.evm.Create(sender, st.data, st.gas, st.value) 309 } else { 310 // Increment the nonce for the next transaction 311 st.state.SetNonce(msg.From(), st.state.GetNonce(sender.Address())+1) 312 ret, st.gas, vmerr = st.evm.Call(sender, st.to(), st.data, st.gas, st.value) 313 } 314 if !st.evm.ChainConfig().IsLondon(st.evm.Context.BlockNumber) { 315 // Before EIP-3529: refunds were capped to gasUsed / 2 316 st.refundGas(params.RefundQuotient) 317 } else { 318 // After EIP-3529: refunds are capped to gasUsed / 5 319 st.refundGas(params.RefundQuotientEIP3529) 320 } 321 effectiveTip := st.gasPrice 322 if st.evm.ChainConfig().IsLondon(st.evm.Context.BlockNumber) { 323 effectiveTip = cmath.BigMin(st.gasTipCap, new(big.Int).Sub(st.gasFeeCap, st.evm.Context.BaseFee)) 324 } 325 st.state.AddBalance(st.evm.Context.Coinbase, new(big.Int).Mul(new(big.Int).SetUint64(st.gasUsed()), effectiveTip)) 326 327 return &ExecutionResult{ 328 UsedGas: st.gasUsed(), 329 Err: vmerr, 330 ReturnData: ret, 331 }, nil 332 } 333 334 func (st *StateTransition) refundGas(refundQuotient uint64) { 335 // Apply refund counter, capped to a refund quotient 336 refund := st.gasUsed() / refundQuotient 337 if refund > st.state.GetRefund() { 338 refund = st.state.GetRefund() 339 } 340 st.gas += refund 341 342 // Return ETH for remaining gas, exchanged at the original rate. 343 remaining := new(big.Int).Mul(new(big.Int).SetUint64(st.gas), st.gasPrice) 344 st.state.AddBalance(st.msg.From(), remaining) 345 346 // Also return remaining gas to the block gas counter so it is 347 // available for the next transaction. 348 st.gp.AddGas(st.gas) 349 } 350 351 // gasUsed returns the amount of gas used up by the state transition. 352 func (st *StateTransition) gasUsed() uint64 { 353 return st.initialGas - st.gas 354 }