aboutsummaryrefslogtreecommitdiffstats
path: root/core/state_transition.go
diff options
context:
space:
mode:
Diffstat (limited to 'core/state_transition.go')
-rw-r--r--core/state_transition.go35
1 files changed, 26 insertions, 9 deletions
diff --git a/core/state_transition.go b/core/state_transition.go
index cc357aaca..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) {
@@ -124,7 +138,7 @@ func (self *StateTransition) from() (vm.Account, error) {
f common.Address
err error
)
- if params.IsHomestead(self.env.BlockNumber()) {
+ if self.env.RuleSet().IsHomestead(self.env.BlockNumber()) {
f, err = self.msg.From()
} else {
f, err = self.msg.FromFrontier()
@@ -209,18 +223,19 @@ 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
}
msg := self.msg
sender, _ := self.from() // err checked in preCheck
- homestead := params.IsHomestead(self.env.BlockNumber())
+ homestead := self.env.RuleSet().IsHomestead(self.env.BlockNumber())
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() {