| 
									
										
										
										
											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 ( | 
					
						
							|  |  |  | 	"fmt" | 
					
						
							| 
									
										
										
										
											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" | 
					
						
							| 
									
										
										
										
											2015-04-04 13:24:01 +02:00
										 |  |  | 	"github.com/ethereum/go-ethereum/logger" | 
					
						
							|  |  |  | 	"github.com/ethereum/go-ethereum/logger/glog" | 
					
						
							| 
									
										
										
										
											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 ( | 
					
						
							|  |  |  | 	Big0 = big.NewInt(0) | 
					
						
							|  |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											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 | 
					
						
							|  |  |  | 	initialGas *big.Int | 
					
						
							|  |  |  | 	value      *big.Int | 
					
						
							|  |  |  | 	data       []byte | 
					
						
							|  |  |  | 	state      vm.StateDB | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	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 | 
					
						
							|  |  |  | 	Gas() *big.Int | 
					
						
							|  |  |  | 	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
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-12-18 15:33:22 +01:00
										 |  |  | func MessageCreatesContract(msg Message) bool { | 
					
						
							| 
									
										
										
										
											2015-03-17 12:16:21 +01:00
										 |  |  | 	return msg.To() == nil | 
					
						
							| 
									
										
										
										
											2014-12-18 15:33:22 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-02-15 10:13:39 +01:00
										 |  |  | // IntrinsicGas computes the 'intrinsic gas' for a message | 
					
						
							| 
									
										
										
										
											2015-06-16 12:41:50 +02:00
										 |  |  | // with the given data. | 
					
						
							| 
									
										
										
										
											2017-01-04 20:17:24 +01:00
										 |  |  | // | 
					
						
							|  |  |  | // TODO convert to uint64 | 
					
						
							| 
									
										
										
										
											2015-11-27 15:40:29 +01:00
										 |  |  | func IntrinsicGas(data []byte, contractCreation, homestead bool) *big.Int { | 
					
						
							|  |  |  | 	igas := new(big.Int) | 
					
						
							|  |  |  | 	if contractCreation && homestead { | 
					
						
							| 
									
										
										
										
											2017-01-04 20:17:24 +01:00
										 |  |  | 		igas.SetUint64(params.TxGasContractCreation) | 
					
						
							| 
									
										
										
										
											2015-11-27 15:40:29 +01:00
										 |  |  | 	} else { | 
					
						
							| 
									
										
										
										
											2017-01-04 20:17:24 +01:00
										 |  |  | 		igas.SetUint64(params.TxGas) | 
					
						
							| 
									
										
										
										
											2015-11-27 15:40:29 +01:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2015-06-25 14:46:44 +02:00
										 |  |  | 	if len(data) > 0 { | 
					
						
							|  |  |  | 		var nz int64 | 
					
						
							|  |  |  | 		for _, byt := range data { | 
					
						
							|  |  |  | 			if byt != 0 { | 
					
						
							|  |  |  | 				nz++ | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2015-04-08 20:47:32 +02:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2015-06-25 14:46:44 +02:00
										 |  |  | 		m := big.NewInt(nz) | 
					
						
							| 
									
										
										
										
											2017-01-04 20:17:24 +01:00
										 |  |  | 		m.Mul(m, new(big.Int).SetUint64(params.TxDataNonZeroGas)) | 
					
						
							| 
									
										
										
										
											2015-06-25 14:46:44 +02:00
										 |  |  | 		igas.Add(igas, m) | 
					
						
							|  |  |  | 		m.SetInt64(int64(len(data)) - nz) | 
					
						
							| 
									
										
										
										
											2017-01-04 20:17:24 +01:00
										 |  |  | 		m.Mul(m, new(big.Int).SetUint64(params.TxDataZeroGas)) | 
					
						
							| 
									
										
										
										
											2015-06-25 14:46:44 +02:00
										 |  |  | 		igas.Add(igas, m) | 
					
						
							| 
									
										
										
										
											2015-04-08 20:47:32 +02:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	return igas | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											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{ | 
					
						
							| 
									
										
										
										
											2015-09-01 21:35:30 +02:00
										 |  |  | 		gp:         gp, | 
					
						
							| 
									
										
										
										
											2017-01-04 20:17:24 +01:00
										 |  |  | 		evm:        evm, | 
					
						
							| 
									
										
										
										
											2015-01-03 17:18:43 +01:00
										 |  |  | 		msg:        msg, | 
					
						
							| 
									
										
										
										
											2015-06-26 14:17:36 +02:00
										 |  |  | 		gasPrice:   msg.GasPrice(), | 
					
						
							| 
									
										
										
										
											2015-01-03 17:18:43 +01:00
										 |  |  | 		initialGas: new(big.Int), | 
					
						
							|  |  |  | 		value:      msg.Value(), | 
					
						
							|  |  |  | 		data:       msg.Data(), | 
					
						
							| 
									
										
										
										
											2017-01-04 20:17:24 +01:00
										 |  |  | 		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-01-04 20:17:24 +01:00
										 |  |  | func ApplyMessage(evm *vm.EVM, msg Message, gp *GasPool) ([]byte, *big.Int, error) { | 
					
						
							|  |  |  | 	st := NewStateTransition(evm, msg, gp) | 
					
						
							| 
									
										
										
										
											2016-04-01 00:30:21 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	ret, _, gasUsed, err := st.TransitionDb() | 
					
						
							|  |  |  | 	return ret, gasUsed, err | 
					
						
							| 
									
										
										
										
											2014-06-13 12:58:01 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-11-02 13:44:13 +01:00
										 |  |  | func (self *StateTransition) from() vm.Account { | 
					
						
							|  |  |  | 	f := self.msg.From() | 
					
						
							| 
									
										
										
										
											2015-08-30 10:19:10 +02:00
										 |  |  | 	if !self.state.Exist(f) { | 
					
						
							| 
									
										
										
										
											2016-11-02 13:44:13 +01:00
										 |  |  | 		return self.state.CreateAccount(f) | 
					
						
							| 
									
										
										
										
											2015-08-30 10:19:10 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2016-11-02 13:44:13 +01:00
										 |  |  | 	return self.state.GetAccount(f) | 
					
						
							| 
									
										
										
										
											2014-06-13 12:58:01 +02:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2016-02-03 23:46:27 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-08-30 10:19:10 +02:00
										 |  |  | func (self *StateTransition) to() vm.Account { | 
					
						
							| 
									
										
										
										
											2015-03-17 12:16:21 +01:00
										 |  |  | 	if self.msg == nil { | 
					
						
							| 
									
										
										
										
											2014-06-13 12:58:01 +02:00
										 |  |  | 		return nil | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2015-03-17 12:16:21 +01:00
										 |  |  | 	to := self.msg.To() | 
					
						
							|  |  |  | 	if to == nil { | 
					
						
							|  |  |  | 		return nil // contract creation | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2015-08-30 10:19:10 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if !self.state.Exist(*to) { | 
					
						
							|  |  |  | 		return self.state.CreateAccount(*to) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return self.state.GetAccount(*to) | 
					
						
							| 
									
										
										
										
											2014-06-13 12:58:01 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-04 20:17:24 +01:00
										 |  |  | func (self *StateTransition) useGas(amount uint64) error { | 
					
						
							|  |  |  | 	if self.gas < amount { | 
					
						
							| 
									
										
										
										
											2017-01-05 11:52:10 +01:00
										 |  |  | 		return vm.ErrOutOfGas | 
					
						
							| 
									
										
										
										
											2014-06-13 12:58:01 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-01-04 20:17:24 +01:00
										 |  |  | 	self.gas -= amount | 
					
						
							| 
									
										
										
										
											2014-06-13 12:58:01 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-08-30 10:19:10 +02:00
										 |  |  | func (self *StateTransition) buyGas() error { | 
					
						
							| 
									
										
										
										
											2015-06-26 14:17:36 +02:00
										 |  |  | 	mgas := self.msg.Gas() | 
					
						
							| 
									
										
										
										
											2017-01-04 20:17:24 +01:00
										 |  |  | 	if mgas.BitLen() > 64 { | 
					
						
							|  |  |  | 		return vm.ErrOutOfGas | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-06-26 14:17:36 +02:00
										 |  |  | 	mgval := new(big.Int).Mul(mgas, self.gasPrice) | 
					
						
							| 
									
										
										
										
											2014-06-13 12:58:01 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-11-02 13:44:13 +01:00
										 |  |  | 	sender := self.from() | 
					
						
							| 
									
										
										
										
											2015-06-26 14:17:36 +02:00
										 |  |  | 	if sender.Balance().Cmp(mgval) < 0 { | 
					
						
							|  |  |  | 		return fmt.Errorf("insufficient ETH for gas (%x). Req %v, has %v", sender.Address().Bytes()[:4], mgval, sender.Balance()) | 
					
						
							| 
									
										
										
										
											2014-06-13 12:58:01 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2016-11-02 13:44:13 +01:00
										 |  |  | 	if err := self.gp.SubGas(mgas); err != nil { | 
					
						
							| 
									
										
										
										
											2014-06-13 12:58:01 +02:00
										 |  |  | 		return err | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-01-04 20:17:24 +01:00
										 |  |  | 	self.gas += mgas.Uint64() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-06-26 14:17:36 +02:00
										 |  |  | 	self.initialGas.Set(mgas) | 
					
						
							|  |  |  | 	sender.SubBalance(mgval) | 
					
						
							| 
									
										
										
										
											2014-06-13 12:58:01 +02:00
										 |  |  | 	return nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-06-19 13:41:17 +02:00
										 |  |  | func (self *StateTransition) preCheck() (err error) { | 
					
						
							| 
									
										
										
										
											2015-06-01 22:00:48 +02:00
										 |  |  | 	msg := self.msg | 
					
						
							| 
									
										
										
										
											2016-11-02 13:44:13 +01:00
										 |  |  | 	sender := self.from() | 
					
						
							| 
									
										
										
										
											2014-06-19 13:41:17 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// Make sure this transaction's nonce is correct | 
					
						
							| 
									
										
										
										
											2016-07-11 11:58:10 +02:00
										 |  |  | 	if msg.CheckNonce() { | 
					
						
							|  |  |  | 		if n := self.state.GetNonce(sender.Address()); n != msg.Nonce() { | 
					
						
							|  |  |  | 			return NonceError(msg.Nonce(), n) | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2014-06-19 13:41:17 +02:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-02 12:55:11 +02:00
										 |  |  | 	// Pre-pay gas | 
					
						
							| 
									
										
										
										
											2015-08-30 10:19:10 +02:00
										 |  |  | 	if err = self.buyGas(); err != nil { | 
					
						
							| 
									
										
										
										
											2015-09-02 12:55:11 +02:00
										 |  |  | 		if IsGasLimitErr(err) { | 
					
						
							| 
									
										
										
										
											2015-03-13 17:47:11 +01:00
										 |  |  | 			return err | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2015-03-03 16:20:38 +01:00
										 |  |  | 		return InvalidTxError(err) | 
					
						
							| 
									
										
										
										
											2014-06-19 13:41:17 +02:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-04 20:17:24 +01:00
										 |  |  | // TransitionDb will transition the state by applying the current message and returning the result | 
					
						
							|  |  |  | // including the required gas for the operation as well as the used gas. It returns an error if it | 
					
						
							|  |  |  | // failed. An error indicates a consensus issue. | 
					
						
							| 
									
										
										
										
											2016-04-01 00:30:21 +02:00
										 |  |  | func (self *StateTransition) TransitionDb() (ret []byte, requiredGas, usedGas *big.Int, err error) { | 
					
						
							| 
									
										
										
										
											2014-06-19 13:41:17 +02:00
										 |  |  | 	if err = self.preCheck(); err != nil { | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2015-06-01 22:00:48 +02:00
										 |  |  | 	msg := self.msg | 
					
						
							| 
									
										
										
										
											2016-11-02 13:44:13 +01:00
										 |  |  | 	sender := self.from() // err checked in preCheck | 
					
						
							| 
									
										
										
										
											2014-06-13 12:58:01 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-04 20:17:24 +01:00
										 |  |  | 	homestead := self.evm.ChainConfig().IsHomestead(self.evm.BlockNumber) | 
					
						
							| 
									
										
										
										
											2015-11-27 15:40:29 +01:00
										 |  |  | 	contractCreation := MessageCreatesContract(msg) | 
					
						
							| 
									
										
										
										
											2015-04-08 20:47:32 +02:00
										 |  |  | 	// Pay intrinsic gas | 
					
						
							| 
									
										
										
										
											2017-01-04 20:17:24 +01:00
										 |  |  | 	// TODO convert to uint64 | 
					
						
							|  |  |  | 	intrinsicGas := IntrinsicGas(self.data, contractCreation, homestead) | 
					
						
							|  |  |  | 	if intrinsicGas.BitLen() > 64 { | 
					
						
							|  |  |  | 		return nil, nil, nil, InvalidTxError(vm.ErrOutOfGas) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if err = self.useGas(intrinsicGas.Uint64()); err != nil { | 
					
						
							| 
									
										
										
										
											2016-04-01 00:30:21 +02:00
										 |  |  | 		return nil, nil, nil, InvalidTxError(err) | 
					
						
							| 
									
										
										
										
											2014-06-13 12:58:01 +02:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-06 02:16:03 +01:00
										 |  |  | 	var ( | 
					
						
							| 
									
										
										
										
											2017-01-04 20:17:24 +01:00
										 |  |  | 		evm = self.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-01-04 20:17:24 +01:00
										 |  |  | 		ret, _, self.gas, vmerr = evm.Create(sender, self.data, self.gas, self.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 | 
					
						
							| 
									
										
										
										
											2015-08-30 10:19:10 +02:00
										 |  |  | 		self.state.SetNonce(sender.Address(), self.state.GetNonce(sender.Address())+1) | 
					
						
							| 
									
										
										
										
											2017-01-04 20:17:24 +01:00
										 |  |  | 		ret, self.gas, vmerr = evm.Call(sender, self.to().Address(), self.data, self.gas, self.value) | 
					
						
							| 
									
										
										
										
											2014-06-13 12:58:01 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2016-12-06 02:16:03 +01:00
										 |  |  | 	if vmerr != nil { | 
					
						
							| 
									
										
										
										
											2017-02-15 10:14:44 +01:00
										 |  |  | 		glog.V(logger.Debug).Infoln("vm returned with error:", err) | 
					
						
							| 
									
										
										
										
											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 { | 
					
						
							|  |  |  | 			return nil, nil, nil, InvalidTxError(vmerr) | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2015-07-06 11:54:11 +02:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-01 00:30:21 +02:00
										 |  |  | 	requiredGas = new(big.Int).Set(self.gasUsed()) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-12 22:29:10 +01:00
										 |  |  | 	self.refundGas() | 
					
						
							| 
									
										
										
										
											2017-01-04 20:17:24 +01:00
										 |  |  | 	self.state.AddBalance(self.evm.Coinbase, new(big.Int).Mul(self.gasUsed(), self.gasPrice)) | 
					
						
							| 
									
										
										
										
											2014-07-24 12:04:15 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-01 00:30:21 +02:00
										 |  |  | 	return ret, requiredGas, self.gasUsed(), err | 
					
						
							| 
									
										
										
										
											2014-07-24 12:04:15 +02:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2014-12-18 21:58:26 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-12 22:29:10 +01:00
										 |  |  | func (self *StateTransition) refundGas() { | 
					
						
							| 
									
										
										
										
											2015-09-02 12:55:11 +02:00
										 |  |  | 	// Return eth for remaining gas to the sender account, | 
					
						
							|  |  |  | 	// exchanged at the original rate. | 
					
						
							| 
									
										
										
										
											2016-11-02 13:44:13 +01:00
										 |  |  | 	sender := self.from() // err already checked | 
					
						
							| 
									
										
										
										
											2017-01-04 20:17:24 +01:00
										 |  |  | 	remaining := new(big.Int).Mul(new(big.Int).SetUint64(self.gas), self.gasPrice) | 
					
						
							| 
									
										
										
										
											2015-02-26 18:39:05 +01:00
										 |  |  | 	sender.AddBalance(remaining) | 
					
						
							| 
									
										
										
										
											2014-12-20 02:21:13 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-02 12:55:11 +02:00
										 |  |  | 	// Apply refund counter, capped to half of the used gas. | 
					
						
							| 
									
										
										
										
											2015-06-26 14:17:36 +02:00
										 |  |  | 	uhalf := remaining.Div(self.gasUsed(), common.Big2) | 
					
						
							| 
									
										
										
										
											2015-08-30 10:19:10 +02:00
										 |  |  | 	refund := common.BigMin(uhalf, self.state.GetRefund()) | 
					
						
							| 
									
										
										
										
											2017-01-04 20:17:24 +01:00
										 |  |  | 	self.gas += refund.Uint64() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-06-26 14:17:36 +02:00
										 |  |  | 	self.state.AddBalance(sender.Address(), refund.Mul(refund, self.gasPrice)) | 
					
						
							| 
									
										
										
										
											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-01-04 20:17:24 +01:00
										 |  |  | 	self.gp.AddGas(new(big.Int).SetUint64(self.gas)) | 
					
						
							| 
									
										
										
										
											2014-12-18 21:58:26 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-12 22:29:10 +01:00
										 |  |  | func (self *StateTransition) gasUsed() *big.Int { | 
					
						
							| 
									
										
										
										
											2017-01-04 20:17:24 +01:00
										 |  |  | 	return new(big.Int).Sub(self.initialGas, new(big.Int).SetUint64(self.gas)) | 
					
						
							| 
									
										
										
										
											2014-12-18 21:58:26 +01:00
										 |  |  | } |