| 
									
										
										
										
											2015-07-07 02:54:22 +02:00
										 |  |  | // Copyright 2014 The go-ethereum Authors | 
					
						
							| 
									
										
										
										
											2015-07-22 18:48:40 +02:00
										 |  |  | // This file is part of the go-ethereum library. | 
					
						
							| 
									
										
										
										
											2015-07-07 02:54:22 +02:00
										 |  |  | // | 
					
						
							| 
									
										
										
										
											2015-07-23 18:35:11 +02:00
										 |  |  | // The go-ethereum library is free software: you can redistribute it and/or modify | 
					
						
							| 
									
										
										
										
											2015-07-07 02:54:22 +02:00
										 |  |  | // it under the terms of the GNU Lesser General Public License as published by | 
					
						
							|  |  |  | // the Free Software Foundation, either version 3 of the License, or | 
					
						
							|  |  |  | // (at your option) any later version. | 
					
						
							|  |  |  | // | 
					
						
							| 
									
										
										
										
											2015-07-22 18:48:40 +02:00
										 |  |  | // The go-ethereum library is distributed in the hope that it will be useful, | 
					
						
							| 
									
										
										
										
											2015-07-07 02:54:22 +02:00
										 |  |  | // but WITHOUT ANY WARRANTY; without even the implied warranty of | 
					
						
							| 
									
										
										
										
											2015-07-22 18:48:40 +02:00
										 |  |  | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 
					
						
							| 
									
										
										
										
											2015-07-07 02:54:22 +02:00
										 |  |  | // GNU Lesser General Public License for more details. | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | // You should have received a copy of the GNU Lesser General Public License | 
					
						
							| 
									
										
										
										
											2015-07-22 18:48:40 +02:00
										 |  |  | // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. | 
					
						
							| 
									
										
										
										
											2015-07-07 02:54:22 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-12-04 10:28:02 +01:00
										 |  |  | package core | 
					
						
							| 
									
										
										
										
											2014-06-13 12:58:01 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							| 
									
										
										
										
											2017-02-22 23:29:59 +01:00
										 |  |  | 	"errors" | 
					
						
							| 
									
										
										
										
											2017-11-13 13:47:27 +02:00
										 |  |  | 	"math" | 
					
						
							| 
									
										
										
										
											2014-07-30 00:31:15 +02:00
										 |  |  | 	"math/big" | 
					
						
							| 
									
										
										
										
											2015-03-09 18:05:56 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-16 11:27:38 +01:00
										 |  |  | 	"github.com/ethereum/go-ethereum/common" | 
					
						
							| 
									
										
										
										
											2015-03-23 16:59:09 +01:00
										 |  |  | 	"github.com/ethereum/go-ethereum/core/vm" | 
					
						
							| 
									
										
										
										
											2017-02-22 14:10:07 +02:00
										 |  |  | 	"github.com/ethereum/go-ethereum/log" | 
					
						
							| 
									
										
										
										
											2015-04-02 05:17:15 +02:00
										 |  |  | 	"github.com/ethereum/go-ethereum/params" | 
					
						
							| 
									
										
										
										
											2014-06-13 12:58:01 +02:00
										 |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-27 15:40:29 +01:00
										 |  |  | var ( | 
					
						
							| 
									
										
										
										
											2017-02-22 23:29:59 +01:00
										 |  |  | 	errInsufficientBalanceForGas = errors.New("insufficient balance to pay for gas") | 
					
						
							| 
									
										
										
										
											2015-11-27 15:40:29 +01:00
										 |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-06-13 13:06:27 +02:00
										 |  |  | /* | 
					
						
							| 
									
										
										
										
											2015-09-02 12:55:11 +02:00
										 |  |  | The State Transitioning Model | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | A state transition is a change made when a transaction is applied to the current world state | 
					
						
							|  |  |  | The state transitioning model does all all the necessary work to work out a valid new state root. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 1) Nonce handling | 
					
						
							|  |  |  | 2) Pre pay gas | 
					
						
							|  |  |  | 3) Create a new state object if the recipient is \0*32 | 
					
						
							|  |  |  | 4) Value transfer | 
					
						
							|  |  |  | == If contract creation == | 
					
						
							|  |  |  |   4a) Attempt to run transaction data | 
					
						
							|  |  |  |   4b) If valid, use result as code for the new state object | 
					
						
							|  |  |  | == end == | 
					
						
							|  |  |  | 5) Run Script section | 
					
						
							|  |  |  | 6) Derive new state root | 
					
						
							|  |  |  | */ | 
					
						
							| 
									
										
										
										
											2014-06-13 12:58:01 +02:00
										 |  |  | type StateTransition struct { | 
					
						
							| 
									
										
										
										
											2017-01-04 20:17:24 +01:00
										 |  |  | 	gp         *GasPool | 
					
						
							|  |  |  | 	msg        Message | 
					
						
							|  |  |  | 	gas        uint64 | 
					
						
							|  |  |  | 	gasPrice   *big.Int | 
					
						
							| 
									
										
										
										
											2017-11-13 13:47:27 +02:00
										 |  |  | 	initialGas uint64 | 
					
						
							| 
									
										
										
										
											2017-01-04 20:17:24 +01:00
										 |  |  | 	value      *big.Int | 
					
						
							|  |  |  | 	data       []byte | 
					
						
							|  |  |  | 	state      vm.StateDB | 
					
						
							| 
									
										
										
										
											2017-08-21 08:47:15 +08:00
										 |  |  | 	evm        *vm.EVM | 
					
						
							| 
									
										
										
										
											2014-12-18 15:18:13 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-17 12:00:29 +01:00
										 |  |  | // Message represents a message sent to a contract. | 
					
						
							| 
									
										
										
										
											2014-12-18 15:18:13 +01:00
										 |  |  | type Message interface { | 
					
						
							| 
									
										
										
										
											2016-11-02 13:44:13 +01:00
										 |  |  | 	From() common.Address | 
					
						
							|  |  |  | 	//FromFrontier() (common.Address, error) | 
					
						
							| 
									
										
										
										
											2015-03-17 12:00:29 +01:00
										 |  |  | 	To() *common.Address | 
					
						
							| 
									
										
										
										
											2014-12-18 15:18:13 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	GasPrice() *big.Int | 
					
						
							| 
									
										
										
										
											2017-11-13 13:47:27 +02:00
										 |  |  | 	Gas() uint64 | 
					
						
							| 
									
										
										
										
											2014-12-18 15:18:13 +01:00
										 |  |  | 	Value() *big.Int | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	Nonce() uint64 | 
					
						
							| 
									
										
										
										
											2016-07-11 11:58:10 +02:00
										 |  |  | 	CheckNonce() bool | 
					
						
							| 
									
										
										
										
											2014-12-18 15:18:13 +01:00
										 |  |  | 	Data() []byte | 
					
						
							| 
									
										
										
										
											2014-06-13 12:58:01 +02:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2015-03-18 13:00:01 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-13 13:47:27 +02:00
										 |  |  | // IntrinsicGas computes the 'intrinsic gas' for a message with the given data. | 
					
						
							|  |  |  | func IntrinsicGas(data []byte, contractCreation, homestead bool) (uint64, error) { | 
					
						
							|  |  |  | 	// Set the starting gas for the raw transaction | 
					
						
							|  |  |  | 	var gas uint64 | 
					
						
							| 
									
										
										
										
											2015-11-27 15:40:29 +01:00
										 |  |  | 	if contractCreation && homestead { | 
					
						
							| 
									
										
										
										
											2017-11-13 13:47:27 +02:00
										 |  |  | 		gas = params.TxGasContractCreation | 
					
						
							| 
									
										
										
										
											2015-11-27 15:40:29 +01:00
										 |  |  | 	} else { | 
					
						
							| 
									
										
										
										
											2017-11-13 13:47:27 +02:00
										 |  |  | 		gas = params.TxGas | 
					
						
							| 
									
										
										
										
											2015-11-27 15:40:29 +01:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-11-13 13:47:27 +02:00
										 |  |  | 	// Bump the required gas by the amount of transactional data | 
					
						
							| 
									
										
										
										
											2015-06-25 14:46:44 +02:00
										 |  |  | 	if len(data) > 0 { | 
					
						
							| 
									
										
										
										
											2017-11-13 13:47:27 +02:00
										 |  |  | 		// Zero and non-zero bytes are priced differently | 
					
						
							|  |  |  | 		var nz uint64 | 
					
						
							| 
									
										
										
										
											2015-06-25 14:46:44 +02:00
										 |  |  | 		for _, byt := range data { | 
					
						
							|  |  |  | 			if byt != 0 { | 
					
						
							|  |  |  | 				nz++ | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2015-04-08 20:47:32 +02:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2017-11-13 13:47:27 +02:00
										 |  |  | 		// Make sure we don't exceed uint64 for all data combinations | 
					
						
							|  |  |  | 		if (math.MaxUint64-gas)/params.TxDataNonZeroGas < nz { | 
					
						
							|  |  |  | 			return 0, vm.ErrOutOfGas | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		gas += nz * params.TxDataNonZeroGas | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		z := uint64(len(data)) - nz | 
					
						
							|  |  |  | 		if (math.MaxUint64-gas)/params.TxDataZeroGas < z { | 
					
						
							|  |  |  | 			return 0, vm.ErrOutOfGas | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		gas += z * params.TxDataZeroGas | 
					
						
							| 
									
										
										
										
											2015-04-08 20:47:32 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-11-13 13:47:27 +02:00
										 |  |  | 	return gas, nil | 
					
						
							| 
									
										
										
										
											2015-04-08 20:47:32 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-01 00:30:21 +02:00
										 |  |  | // NewStateTransition initialises and returns a new state transition object. | 
					
						
							| 
									
										
										
										
											2017-01-04 20:17:24 +01:00
										 |  |  | func NewStateTransition(evm *vm.EVM, msg Message, gp *GasPool) *StateTransition { | 
					
						
							| 
									
										
										
										
											2016-04-01 00:30:21 +02:00
										 |  |  | 	return &StateTransition{ | 
					
						
							| 
									
										
										
										
											2017-11-13 13:47:27 +02:00
										 |  |  | 		gp:       gp, | 
					
						
							|  |  |  | 		evm:      evm, | 
					
						
							|  |  |  | 		msg:      msg, | 
					
						
							|  |  |  | 		gasPrice: msg.GasPrice(), | 
					
						
							|  |  |  | 		value:    msg.Value(), | 
					
						
							|  |  |  | 		data:     msg.Data(), | 
					
						
							|  |  |  | 		state:    evm.StateDB, | 
					
						
							| 
									
										
										
										
											2014-12-18 15:18:13 +01:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2016-04-01 00:30:21 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // ApplyMessage computes the new state by applying the given message | 
					
						
							|  |  |  | // against the old state within the environment. | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | // ApplyMessage returns the bytes returned by any EVM execution (if it took place), | 
					
						
							|  |  |  | // the gas used (which includes gas refunds) and an error if it failed. An error always | 
					
						
							|  |  |  | // indicates a core error meaning that the message would always fail for that particular | 
					
						
							|  |  |  | // state and would never be accepted within a block. | 
					
						
							| 
									
										
										
										
											2017-11-13 13:47:27 +02:00
										 |  |  | func ApplyMessage(evm *vm.EVM, msg Message, gp *GasPool) ([]byte, uint64, bool, error) { | 
					
						
							|  |  |  | 	return NewStateTransition(evm, msg, gp).TransitionDb() | 
					
						
							| 
									
										
										
										
											2014-06-13 12:58:01 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-10 15:33:25 +02:00
										 |  |  | // to returns the recipient of the message. | 
					
						
							|  |  |  | func (st *StateTransition) to() common.Address { | 
					
						
							|  |  |  | 	if st.msg == nil || st.msg.To() == nil /* contract creation */ { | 
					
						
							|  |  |  | 		return common.Address{} | 
					
						
							| 
									
										
										
										
											2015-08-30 10:19:10 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2018-04-10 15:33:25 +02:00
										 |  |  | 	return *st.msg.To() | 
					
						
							| 
									
										
										
										
											2014-06-13 12:58:01 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-11 09:55:48 +08:00
										 |  |  | func (st *StateTransition) useGas(amount uint64) error { | 
					
						
							|  |  |  | 	if st.gas < amount { | 
					
						
							| 
									
										
										
										
											2017-01-05 11:52:10 +01:00
										 |  |  | 		return vm.ErrOutOfGas | 
					
						
							| 
									
										
										
										
											2014-06-13 12:58:01 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-05-11 09:55:48 +08:00
										 |  |  | 	st.gas -= amount | 
					
						
							| 
									
										
										
										
											2014-06-13 12:58:01 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-11 09:55:48 +08:00
										 |  |  | func (st *StateTransition) buyGas() error { | 
					
						
							| 
									
										
										
										
											2017-11-13 13:47:27 +02:00
										 |  |  | 	mgval := new(big.Int).Mul(new(big.Int).SetUint64(st.msg.Gas()), st.gasPrice) | 
					
						
							| 
									
										
										
										
											2018-04-10 15:33:25 +02:00
										 |  |  | 	if st.state.GetBalance(st.msg.From()).Cmp(mgval) < 0 { | 
					
						
							| 
									
										
										
										
											2017-02-22 23:29:59 +01:00
										 |  |  | 		return errInsufficientBalanceForGas | 
					
						
							| 
									
										
										
										
											2014-06-13 12:58:01 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-11-13 13:47:27 +02:00
										 |  |  | 	if err := st.gp.SubGas(st.msg.Gas()); err != nil { | 
					
						
							| 
									
										
										
										
											2014-06-13 12:58:01 +02:00
										 |  |  | 		return err | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-11-13 13:47:27 +02:00
										 |  |  | 	st.gas += st.msg.Gas() | 
					
						
							| 
									
										
										
										
											2017-01-04 20:17:24 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-13 13:47:27 +02:00
										 |  |  | 	st.initialGas = st.msg.Gas() | 
					
						
							| 
									
										
										
										
											2018-04-10 15:33:25 +02:00
										 |  |  | 	st.state.SubBalance(st.msg.From(), mgval) | 
					
						
							| 
									
										
										
										
											2014-06-13 12:58:01 +02:00
										 |  |  | 	return nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-11 09:55:48 +08:00
										 |  |  | func (st *StateTransition) preCheck() error { | 
					
						
							| 
									
										
										
										
											2018-04-10 15:33:25 +02:00
										 |  |  | 	// Make sure this transaction's nonce is correct. | 
					
						
							|  |  |  | 	if st.msg.CheckNonce() { | 
					
						
							|  |  |  | 		nonce := st.state.GetNonce(st.msg.From()) | 
					
						
							|  |  |  | 		if nonce < st.msg.Nonce() { | 
					
						
							| 
									
										
										
										
											2017-09-04 22:35:00 +03:00
										 |  |  | 			return ErrNonceTooHigh | 
					
						
							| 
									
										
										
										
											2018-04-10 15:33:25 +02:00
										 |  |  | 		} else if nonce > st.msg.Nonce() { | 
					
						
							| 
									
										
										
										
											2017-09-04 22:35:00 +03:00
										 |  |  | 			return ErrNonceTooLow | 
					
						
							| 
									
										
										
										
											2016-07-11 11:58:10 +02:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2014-06-19 13:41:17 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-05-11 09:55:48 +08:00
										 |  |  | 	return st.buyGas() | 
					
						
							| 
									
										
										
										
											2014-06-19 13:41:17 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-13 13:47:27 +02:00
										 |  |  | // TransitionDb will transition the state by applying the current message and | 
					
						
							|  |  |  | // returning the result including the the used gas. It returns an error if it | 
					
						
							| 
									
										
										
										
											2017-01-04 20:17:24 +01:00
										 |  |  | // failed. An error indicates a consensus issue. | 
					
						
							| 
									
										
										
										
											2017-11-13 13:47:27 +02:00
										 |  |  | func (st *StateTransition) TransitionDb() (ret []byte, usedGas uint64, failed bool, err error) { | 
					
						
							| 
									
										
										
										
											2017-05-11 09:55:48 +08:00
										 |  |  | 	if err = st.preCheck(); err != nil { | 
					
						
							| 
									
										
										
										
											2014-06-19 13:41:17 +02:00
										 |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-05-11 09:55:48 +08:00
										 |  |  | 	msg := st.msg | 
					
						
							| 
									
										
										
										
											2018-04-10 15:33:25 +02:00
										 |  |  | 	sender := vm.AccountRef(msg.From()) | 
					
						
							| 
									
										
										
										
											2017-05-11 09:55:48 +08:00
										 |  |  | 	homestead := st.evm.ChainConfig().IsHomestead(st.evm.BlockNumber) | 
					
						
							| 
									
										
										
										
											2017-05-08 12:09:35 +03:00
										 |  |  | 	contractCreation := msg.To() == nil | 
					
						
							| 
									
										
										
										
											2017-05-11 09:55:48 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-08 20:47:32 +02:00
										 |  |  | 	// Pay intrinsic gas | 
					
						
							| 
									
										
										
										
											2017-11-13 13:47:27 +02:00
										 |  |  | 	gas, err := IntrinsicGas(st.data, contractCreation, homestead) | 
					
						
							| 
									
										
										
										
											2018-02-14 21:02:51 +01:00
										 |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return nil, 0, false, err | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-11-13 13:47:27 +02:00
										 |  |  | 	if err = st.useGas(gas); err != nil { | 
					
						
							|  |  |  | 		return nil, 0, false, err | 
					
						
							| 
									
										
										
										
											2014-06-13 12:58:01 +02:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-06 02:16:03 +01:00
										 |  |  | 	var ( | 
					
						
							| 
									
										
										
										
											2017-05-11 09:55:48 +08:00
										 |  |  | 		evm = st.evm | 
					
						
							| 
									
										
										
										
											2016-12-06 02:16:03 +01:00
										 |  |  | 		// vm errors do not effect consensus and are therefor | 
					
						
							|  |  |  | 		// not assigned to err, except for insufficient balance | 
					
						
							|  |  |  | 		// error. | 
					
						
							|  |  |  | 		vmerr error | 
					
						
							|  |  |  | 	) | 
					
						
							| 
									
										
										
										
											2015-11-27 15:40:29 +01:00
										 |  |  | 	if contractCreation { | 
					
						
							| 
									
										
										
										
											2017-05-11 09:55:48 +08:00
										 |  |  | 		ret, _, st.gas, vmerr = evm.Create(sender, st.data, st.gas, st.value) | 
					
						
							| 
									
										
										
										
											2014-07-07 13:59:09 +02:00
										 |  |  | 	} else { | 
					
						
							| 
									
										
										
										
											2015-03-24 15:23:16 +01:00
										 |  |  | 		// Increment the nonce for the next transaction | 
					
						
							| 
									
										
										
										
											2018-04-10 15:33:25 +02:00
										 |  |  | 		st.state.SetNonce(msg.From(), st.state.GetNonce(sender.Address())+1) | 
					
						
							|  |  |  | 		ret, st.gas, vmerr = evm.Call(sender, st.to(), st.data, st.gas, st.value) | 
					
						
							| 
									
										
										
										
											2014-06-13 12:58:01 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2016-12-06 02:16:03 +01:00
										 |  |  | 	if vmerr != nil { | 
					
						
							| 
									
										
										
										
											2017-06-04 12:30:02 +01:00
										 |  |  | 		log.Debug("VM returned with error", "err", vmerr) | 
					
						
							| 
									
										
										
										
											2016-12-06 02:16:03 +01:00
										 |  |  | 		// The only possible consensus-error would be if there wasn't | 
					
						
							|  |  |  | 		// sufficient balance to make the transfer happen. The first | 
					
						
							|  |  |  | 		// balance transfer may never fail. | 
					
						
							|  |  |  | 		if vmerr == vm.ErrInsufficientBalance { | 
					
						
							| 
									
										
										
										
											2017-11-13 13:47:27 +02:00
										 |  |  | 			return nil, 0, false, vmerr | 
					
						
							| 
									
										
										
										
											2016-12-06 02:16:03 +01:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2015-07-06 11:54:11 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-05-11 09:55:48 +08:00
										 |  |  | 	st.refundGas() | 
					
						
							| 
									
										
										
										
											2017-11-13 13:47:27 +02:00
										 |  |  | 	st.state.AddBalance(st.evm.Coinbase, new(big.Int).Mul(new(big.Int).SetUint64(st.gasUsed()), st.gasPrice)) | 
					
						
							| 
									
										
										
										
											2014-07-24 12:04:15 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-13 13:47:27 +02:00
										 |  |  | 	return ret, st.gasUsed(), vmerr != nil, err | 
					
						
							| 
									
										
										
										
											2014-07-24 12:04:15 +02:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2014-12-18 21:58:26 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-11 09:55:48 +08:00
										 |  |  | func (st *StateTransition) refundGas() { | 
					
						
							| 
									
										
										
										
											2015-09-02 12:55:11 +02:00
										 |  |  | 	// Apply refund counter, capped to half of the used gas. | 
					
						
							| 
									
										
										
										
											2017-11-13 13:47:27 +02:00
										 |  |  | 	refund := st.gasUsed() / 2 | 
					
						
							|  |  |  | 	if refund > st.state.GetRefund() { | 
					
						
							|  |  |  | 		refund = st.state.GetRefund() | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	st.gas += refund | 
					
						
							| 
									
										
										
										
											2017-01-04 20:17:24 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-13 13:47:27 +02:00
										 |  |  | 	// Return ETH for remaining gas, exchanged at the original rate. | 
					
						
							|  |  |  | 	remaining := new(big.Int).Mul(new(big.Int).SetUint64(st.gas), st.gasPrice) | 
					
						
							| 
									
										
										
										
											2018-04-10 15:33:25 +02:00
										 |  |  | 	st.state.AddBalance(st.msg.From(), remaining) | 
					
						
							| 
									
										
										
										
											2014-12-18 21:58:26 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-02 12:55:11 +02:00
										 |  |  | 	// Also return remaining gas to the block gas counter so it is | 
					
						
							|  |  |  | 	// available for the next transaction. | 
					
						
							| 
									
										
										
										
											2017-11-13 13:47:27 +02:00
										 |  |  | 	st.gp.AddGas(st.gas) | 
					
						
							| 
									
										
										
										
											2014-12-18 21:58:26 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-13 13:47:27 +02:00
										 |  |  | // gasUsed returns the amount of gas used up by the state transition. | 
					
						
							|  |  |  | func (st *StateTransition) gasUsed() uint64 { | 
					
						
							|  |  |  | 	return st.initialGas - st.gas | 
					
						
							| 
									
										
										
										
											2014-12-18 21:58:26 +01:00
										 |  |  | } |