aboutsummaryrefslogtreecommitdiffstats
path: root/core/state_transition.go
diff options
context:
space:
mode:
authorFelix Lange <fjl@twurst.com>2015-09-02 18:55:11 +0800
committerFelix Lange <fjl@twurst.com>2015-10-17 16:24:34 +0800
commitde8d5aaa92ff843e6960eb9b7bd7ec1c1ebc6608 (patch)
tree59930f3d627940e1b73030ee2c5685104a04ee34 /core/state_transition.go
parent10ed107ba2001d1aabba3d319ba88c5ce6e8fdc0 (diff)
downloaddexon-de8d5aaa92ff843e6960eb9b7bd7ec1c1ebc6608.tar
dexon-de8d5aaa92ff843e6960eb9b7bd7ec1c1ebc6608.tar.gz
dexon-de8d5aaa92ff843e6960eb9b7bd7ec1c1ebc6608.tar.bz2
dexon-de8d5aaa92ff843e6960eb9b7bd7ec1c1ebc6608.tar.lz
dexon-de8d5aaa92ff843e6960eb9b7bd7ec1c1ebc6608.tar.xz
dexon-de8d5aaa92ff843e6960eb9b7bd7ec1c1ebc6608.tar.zst
dexon-de8d5aaa92ff843e6960eb9b7bd7ec1c1ebc6608.zip
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.
Diffstat (limited to 'core/state_transition.go')
-rw-r--r--core/state_transition.go50
1 files changed, 27 insertions, 23 deletions
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 {