aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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.