aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJeffrey Wilcke <geffobscura@gmail.com>2016-04-01 06:30:21 +0800
committerJeffrey Wilcke <geffobscura@gmail.com>2016-04-01 07:01:10 +0800
commit1f3596c25af077a3303c554ee6b49404b20f7117 (patch)
tree33d4c6a96eed3bf1ce9f69bbef3cbc1561f2b114
parent9055c16efad80d0c69992e7992083f967733aa9c (diff)
downloadgo-tangerine-1f3596c25af077a3303c554ee6b49404b20f7117.tar.gz
go-tangerine-1f3596c25af077a3303c554ee6b49404b20f7117.tar.zst
go-tangerine-1f3596c25af077a3303c554ee6b49404b20f7117.zip
core: transition db now also returns the required gas amount
Exposes some core methods to transition and compute new state information and adds an additional return value to the transition db method to fetch required gas for that particular message (excluding gas refunds from any SSTORE[X] = 0 and SUICIDE. Fixes #2395
-rw-r--r--core/state_transition.go31
-rw-r--r--eth/api.go6
2 files changed, 27 insertions, 10 deletions
diff --git a/core/state_transition.go b/core/state_transition.go
index 60ac7d8cb..c8160424b 100644
--- a/core/state_transition.go
+++ b/core/state_transition.go
@@ -104,8 +104,9 @@ func IntrinsicGas(data []byte, contractCreation, homestead bool) *big.Int {
return igas
}
-func ApplyMessage(env vm.Environment, msg Message, gp *GasPool) ([]byte, *big.Int, error) {
- var st = StateTransition{
+// NewStateTransition initialises and returns a new state transition object.
+func NewStateTransition(env vm.Environment, msg Message, gp *GasPool) *StateTransition {
+ return &StateTransition{
gp: gp,
env: env,
msg: msg,
@@ -116,7 +117,20 @@ func ApplyMessage(env vm.Environment, msg Message, gp *GasPool) ([]byte, *big.In
data: msg.Data(),
state: env.Db(),
}
- return st.transitionDb()
+}
+
+// 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.
+func ApplyMessage(env vm.Environment, msg Message, gp *GasPool) ([]byte, *big.Int, error) {
+ st := NewStateTransition(env, msg, gp)
+
+ ret, _, gasUsed, err := st.TransitionDb()
+ return ret, gasUsed, err
}
func (self *StateTransition) from() (vm.Account, error) {
@@ -209,7 +223,8 @@ func (self *StateTransition) preCheck() (err error) {
return nil
}
-func (self *StateTransition) transitionDb() (ret []byte, usedGas *big.Int, err error) {
+// TransitionDb will move the state by applying the message against the given environment.
+func (self *StateTransition) TransitionDb() (ret []byte, requiredGas, usedGas *big.Int, err error) {
if err = self.preCheck(); err != nil {
return
}
@@ -220,7 +235,7 @@ func (self *StateTransition) transitionDb() (ret []byte, usedGas *big.Int, err e
contractCreation := MessageCreatesContract(msg)
// Pay intrinsic gas
if err = self.useGas(IntrinsicGas(self.data, contractCreation, homestead)); err != nil {
- return nil, nil, InvalidTxError(err)
+ return nil, nil, nil, InvalidTxError(err)
}
vmenv := self.env
@@ -245,7 +260,7 @@ func (self *StateTransition) transitionDb() (ret []byte, usedGas *big.Int, err e
}
if err != nil && IsValueTransferErr(err) {
- return nil, nil, InvalidTxError(err)
+ return nil, nil, nil, InvalidTxError(err)
}
// We aren't interested in errors here. Errors returned by the VM are non-consensus errors and therefor shouldn't bubble up
@@ -253,10 +268,12 @@ func (self *StateTransition) transitionDb() (ret []byte, usedGas *big.Int, err e
err = nil
}
+ requiredGas = new(big.Int).Set(self.gasUsed())
+
self.refundGas()
self.state.AddBalance(self.env.Coinbase(), new(big.Int).Mul(self.gasUsed(), self.gasPrice))
- return ret, self.gasUsed(), err
+ return ret, requiredGas, self.gasUsed(), err
}
func (self *StateTransition) refundGas() {
diff --git a/eth/api.go b/eth/api.go
index 06c10daa9..af03c096d 100644
--- a/eth/api.go
+++ b/eth/api.go
@@ -674,11 +674,11 @@ func (s *PublicBlockChainAPI) doCall(args CallArgs, blockNr rpc.BlockNumber) (st
vmenv := core.NewEnv(stateDb, s.config, s.bc, msg, block.Header(), s.config.VmConfig)
gp := new(core.GasPool).AddGas(common.MaxBig)
- res, gas, err := core.ApplyMessage(vmenv, msg, gp)
+ res, requiredGas, _, err := core.NewStateTransition(vmenv, msg, gp).TransitionDb()
if len(res) == 0 { // backwards compatibility
- return "0x", gas, err
+ return "0x", requiredGas, err
}
- return common.ToHex(res), gas, err
+ return common.ToHex(res), requiredGas, err
}
// Call executes the given transaction on the state for the given block number.