github.com/murrekatt/go-ethereum@v1.5.8-0.20170123175102-fc52f2c007fb/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/big" 22 23 "github.com/ethereum/go-ethereum/common" 24 "github.com/ethereum/go-ethereum/core/vm" 25 "github.com/ethereum/go-ethereum/logger" 26 "github.com/ethereum/go-ethereum/logger/glog" 27 "github.com/ethereum/go-ethereum/params" 28 ) 29 30 var ( 31 Big0 = big.NewInt(0) 32 ) 33 34 /* 35 The State Transitioning Model 36 37 A state transition is a change made when a transaction is applied to the current world state 38 The state transitioning model does all all the necessary work to work out a valid new state root. 39 40 1) Nonce handling 41 2) Pre pay gas 42 3) Create a new state object if the recipient is \0*32 43 4) 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 == 48 5) Run Script section 49 6) Derive new state root 50 */ 51 type StateTransition struct { 52 gp *GasPool 53 msg Message 54 gas, gasPrice *big.Int 55 initialGas *big.Int 56 value *big.Int 57 data []byte 58 state vm.StateDB 59 60 env *vm.EVM 61 } 62 63 // Message represents a message sent to a contract. 64 type Message interface { 65 From() common.Address 66 //FromFrontier() (common.Address, error) 67 To() *common.Address 68 69 GasPrice() *big.Int 70 Gas() *big.Int 71 Value() *big.Int 72 73 Nonce() uint64 74 CheckNonce() bool 75 Data() []byte 76 } 77 78 func MessageCreatesContract(msg Message) bool { 79 return msg.To() == nil 80 } 81 82 // IntrinsicGas computes the 'intrinsic gas' for a message 83 // with the given data. 84 func IntrinsicGas(data []byte, contractCreation, homestead bool) *big.Int { 85 igas := new(big.Int) 86 if contractCreation && homestead { 87 igas.Set(params.TxGasContractCreation) 88 } else { 89 igas.Set(params.TxGas) 90 } 91 if len(data) > 0 { 92 var nz int64 93 for _, byt := range data { 94 if byt != 0 { 95 nz++ 96 } 97 } 98 m := big.NewInt(nz) 99 m.Mul(m, params.TxDataNonZeroGas) 100 igas.Add(igas, m) 101 m.SetInt64(int64(len(data)) - nz) 102 m.Mul(m, params.TxDataZeroGas) 103 igas.Add(igas, m) 104 } 105 return igas 106 } 107 108 // NewStateTransition initialises and returns a new state transition object. 109 func NewStateTransition(env *vm.EVM, msg Message, gp *GasPool) *StateTransition { 110 return &StateTransition{ 111 gp: gp, 112 env: env, 113 msg: msg, 114 gas: new(big.Int), 115 gasPrice: msg.GasPrice(), 116 initialGas: new(big.Int), 117 value: msg.Value(), 118 data: msg.Data(), 119 state: env.StateDB, 120 } 121 } 122 123 // ApplyMessage computes the new state by applying the given message 124 // against the old state within the environment. 125 // 126 // ApplyMessage returns the bytes returned by any EVM execution (if it took place), 127 // the gas used (which includes gas refunds) and an error if it failed. An error always 128 // indicates a core error meaning that the message would always fail for that particular 129 // state and would never be accepted within a block. 130 func ApplyMessage(env *vm.EVM, msg Message, gp *GasPool) ([]byte, *big.Int, error) { 131 st := NewStateTransition(env, msg, gp) 132 133 ret, _, gasUsed, err := st.TransitionDb() 134 return ret, gasUsed, err 135 } 136 137 func (self *StateTransition) from() vm.Account { 138 f := self.msg.From() 139 if !self.state.Exist(f) { 140 return self.state.CreateAccount(f) 141 } 142 return self.state.GetAccount(f) 143 } 144 145 func (self *StateTransition) to() vm.Account { 146 if self.msg == nil { 147 return nil 148 } 149 to := self.msg.To() 150 if to == nil { 151 return nil // contract creation 152 } 153 154 if !self.state.Exist(*to) { 155 return self.state.CreateAccount(*to) 156 } 157 return self.state.GetAccount(*to) 158 } 159 160 func (self *StateTransition) useGas(amount *big.Int) error { 161 if self.gas.Cmp(amount) < 0 { 162 return vm.ErrOutOfGas 163 } 164 self.gas.Sub(self.gas, amount) 165 166 return nil 167 } 168 169 func (self *StateTransition) addGas(amount *big.Int) { 170 self.gas.Add(self.gas, amount) 171 } 172 173 func (self *StateTransition) buyGas() error { 174 mgas := self.msg.Gas() 175 mgval := new(big.Int).Mul(mgas, self.gasPrice) 176 177 sender := self.from() 178 if sender.Balance().Cmp(mgval) < 0 { 179 return fmt.Errorf("insufficient ETH for gas (%x). Req %v, has %v", sender.Address().Bytes()[:4], mgval, sender.Balance()) 180 } 181 if err := self.gp.SubGas(mgas); err != nil { 182 return err 183 } 184 self.addGas(mgas) 185 self.initialGas.Set(mgas) 186 sender.SubBalance(mgval) 187 return nil 188 } 189 190 func (self *StateTransition) preCheck() (err error) { 191 msg := self.msg 192 sender := self.from() 193 194 // Make sure this transaction's nonce is correct 195 if msg.CheckNonce() { 196 if n := self.state.GetNonce(sender.Address()); n != msg.Nonce() { 197 return NonceError(msg.Nonce(), n) 198 } 199 } 200 201 // Pre-pay gas 202 if err = self.buyGas(); err != nil { 203 if IsGasLimitErr(err) { 204 return err 205 } 206 return InvalidTxError(err) 207 } 208 209 return nil 210 } 211 212 // TransitionDb will move the state by applying the message against the given environment. 213 func (self *StateTransition) TransitionDb() (ret []byte, requiredGas, usedGas *big.Int, err error) { 214 if err = self.preCheck(); err != nil { 215 return 216 } 217 msg := self.msg 218 sender := self.from() // err checked in preCheck 219 220 homestead := self.env.ChainConfig().IsHomestead(self.env.BlockNumber) 221 contractCreation := MessageCreatesContract(msg) 222 // Pay intrinsic gas 223 if err = self.useGas(IntrinsicGas(self.data, contractCreation, homestead)); err != nil { 224 return nil, nil, nil, InvalidTxError(err) 225 } 226 227 var ( 228 vmenv = self.env 229 // vm errors do not effect consensus and are therefor 230 // not assigned to err, except for insufficient balance 231 // error. 232 vmerr error 233 ) 234 if contractCreation { 235 ret, _, vmerr = vmenv.Create(sender, self.data, self.gas, self.value) 236 } else { 237 // Increment the nonce for the next transaction 238 self.state.SetNonce(sender.Address(), self.state.GetNonce(sender.Address())+1) 239 ret, vmerr = vmenv.Call(sender, self.to().Address(), self.data, self.gas, self.value) 240 } 241 if vmerr != nil { 242 glog.V(logger.Core).Infoln("vm returned with error:", err) 243 // The only possible consensus-error would be if there wasn't 244 // sufficient balance to make the transfer happen. The first 245 // balance transfer may never fail. 246 if vmerr == vm.ErrInsufficientBalance { 247 return nil, nil, nil, InvalidTxError(vmerr) 248 } 249 } 250 251 requiredGas = new(big.Int).Set(self.gasUsed()) 252 253 self.refundGas() 254 self.state.AddBalance(self.env.Coinbase, new(big.Int).Mul(self.gasUsed(), self.gasPrice)) 255 256 return ret, requiredGas, self.gasUsed(), err 257 } 258 259 func (self *StateTransition) refundGas() { 260 // Return eth for remaining gas to the sender account, 261 // exchanged at the original rate. 262 sender := self.from() // err already checked 263 remaining := new(big.Int).Mul(self.gas, self.gasPrice) 264 sender.AddBalance(remaining) 265 266 // Apply refund counter, capped to half of the used gas. 267 uhalf := remaining.Div(self.gasUsed(), common.Big2) 268 refund := common.BigMin(uhalf, self.state.GetRefund()) 269 self.gas.Add(self.gas, refund) 270 self.state.AddBalance(sender.Address(), refund.Mul(refund, self.gasPrice)) 271 272 // Also return remaining gas to the block gas counter so it is 273 // available for the next transaction. 274 self.gp.AddGas(self.gas) 275 } 276 277 func (self *StateTransition) gasUsed() *big.Int { 278 return new(big.Int).Sub(self.initialGas, self.gas) 279 }