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