From de8d5aaa92ff843e6960eb9b7bd7ec1c1ebc6608 Mon Sep 17 00:00:00 2001 From: Felix Lange Date: Wed, 2 Sep 2015 12:55:11 +0200 Subject: core, core/state: move gas tracking out of core/state The amount of gas available for tx execution was tracked in the StateObject representing the coinbase account. This commit makes the gas counter a separate type in package core, which avoids unintended consequences of intertwining the counter with state logic. --- core/state_transition.go | 50 ++++++++++++++++++++++++++---------------------- 1 file changed, 27 insertions(+), 23 deletions(-) (limited to 'core/state_transition.go') diff --git a/core/state_transition.go b/core/state_transition.go index e83019229..7ecc01d4c 100644 --- a/core/state_transition.go +++ b/core/state_transition.go @@ -21,7 +21,6 @@ import ( "math/big" "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/logger" "github.com/ethereum/go-ethereum/logger/glog" @@ -29,23 +28,24 @@ import ( ) /* - * 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 / buy gas of the coinbase (miner) - * 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 - */ +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 +*/ type StateTransition struct { - gp GasPool + gp *GasPool msg Message gas, gasPrice *big.Int initialGas *big.Int @@ -94,7 +94,7 @@ func IntrinsicGas(data []byte) *big.Int { return igas } -func ApplyMessage(env vm.Environment, msg Message, gp GasPool) ([]byte, *big.Int, error) { +func ApplyMessage(env vm.Environment, msg Message, gp *GasPool) ([]byte, *big.Int, error) { var st = StateTransition{ gp: gp, env: env, @@ -158,7 +158,7 @@ func (self *StateTransition) buyGas() error { 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()) } - if err = self.gp.SubGas(mgas, self.gasPrice); err != nil { + if err = self.gp.SubGas(mgas); err != nil { return err } self.addGas(mgas) @@ -180,9 +180,9 @@ func (self *StateTransition) preCheck() (err error) { return NonceError(msg.Nonce(), n) } - // Pre-pay gas / Buy gas of the coinbase account + // Pre-pay gas if err = self.buyGas(); err != nil { - if state.IsGasLimitErr(err) { + if IsGasLimitErr(err) { return err } return InvalidTxError(err) @@ -246,17 +246,21 @@ func (self *StateTransition) transitionDb() (ret []byte, usedGas *big.Int, err e } func (self *StateTransition) refundGas() { + // Return eth for remaining gas to the sender account, + // exchanged at the original rate. sender, _ := self.from() // err already checked - // Return remaining gas remaining := new(big.Int).Mul(self.gas, self.gasPrice) sender.AddBalance(remaining) + // Apply refund counter, capped to half of the used gas. uhalf := remaining.Div(self.gasUsed(), common.Big2) refund := common.BigMin(uhalf, self.state.GetRefund()) self.gas.Add(self.gas, refund) self.state.AddBalance(sender.Address(), refund.Mul(refund, self.gasPrice)) - self.gp.AddGas(self.gas, self.gasPrice) + // Also return remaining gas to the block gas counter so it is + // available for the next transaction. + self.gp.AddGas(self.gas) } func (self *StateTransition) gasUsed() *big.Int { -- cgit v1.2.3