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