aboutsummaryrefslogtreecommitdiffstats
path: root/chain/state_transition.go
diff options
context:
space:
mode:
authorobscuren <geffobscura@gmail.com>2014-12-04 00:06:54 +0800
committerobscuren <geffobscura@gmail.com>2014-12-04 00:06:54 +0800
commit99853ac3ce57807deb4822dd324186e1d2ee0821 (patch)
tree4c7dc0c8fa1f83d1081f429fa3175b03c9011101 /chain/state_transition.go
parent82405501872385b240012070bad2f0eda643d423 (diff)
downloaddexon-99853ac3ce57807deb4822dd324186e1d2ee0821.tar
dexon-99853ac3ce57807deb4822dd324186e1d2ee0821.tar.gz
dexon-99853ac3ce57807deb4822dd324186e1d2ee0821.tar.bz2
dexon-99853ac3ce57807deb4822dd324186e1d2ee0821.tar.lz
dexon-99853ac3ce57807deb4822dd324186e1d2ee0821.tar.xz
dexon-99853ac3ce57807deb4822dd324186e1d2ee0821.tar.zst
dexon-99853ac3ce57807deb4822dd324186e1d2ee0821.zip
Moved execution from vm to chain.
This moves call and create to the specified environments. Vms are no longer re-used. Vm uses environment's Call(Code) and Create in order to execute new contracts or transfer value between accounts. State transition now uses the same mechanism described above.
Diffstat (limited to 'chain/state_transition.go')
-rw-r--r--chain/state_transition.go117
1 files changed, 9 insertions, 108 deletions
diff --git a/chain/state_transition.go b/chain/state_transition.go
index 8f7b55cd4..b2ba4f22a 100644
--- a/chain/state_transition.go
+++ b/chain/state_transition.go
@@ -169,120 +169,21 @@ func (self *StateTransition) TransitionState() (err error) {
return
}
- if sender.Balance().Cmp(self.value) < 0 {
- return fmt.Errorf("Insufficient funds to transfer value. Req %v, has %v", self.value, sender.Balance)
- }
-
- var snapshot *state.State
- // If the receiver is nil it's a contract (\0*32).
+ var ret []byte
+ vmenv := NewEnv(self.state, self.tx, self.block)
+ var ref vm.ClosureRef
if tx.CreatesContract() {
- // Subtract the (irreversible) amount from the senders account
- sender.SubAmount(self.value)
+ self.rec = MakeContract(tx, self.state)
- snapshot = self.state.Copy()
-
- // Create a new state object for the contract
- receiver = MakeContract(tx, self.state)
- self.rec = receiver
- if receiver == nil {
- return fmt.Errorf("Unable to create contract")
- }
-
- // Add the amount to receivers account which should conclude this transaction
- receiver.AddAmount(self.value)
+ ret, err, ref = vmenv.Create(sender, receiver.Address(), self.tx.Data, self.gas, self.gasPrice, self.value)
+ ref.SetCode(ret)
} else {
- receiver = self.Receiver()
-
- // Subtract the amount from the senders account
- sender.SubAmount(self.value)
- // Add the amount to receivers account which should conclude this transaction
- receiver.AddAmount(self.value)
-
- snapshot = self.state.Copy()
+ ret, err = vmenv.Call(self.Sender(), self.Receiver().Address(), self.tx.Data, self.gas, self.gasPrice, self.value)
}
-
- msg := self.state.Manifest().AddMessage(&state.Message{
- To: receiver.Address(), From: sender.Address(),
- Input: self.tx.Data,
- Origin: sender.Address(),
- Block: self.block.Hash(), Timestamp: self.block.Time, Coinbase: self.block.Coinbase, Number: self.block.Number,
- Value: self.value,
- })
-
- // Process the init code and create 'valid' contract
- if types.IsContractAddr(self.receiver) {
- // Evaluate the initialization script
- // and use the return value as the
- // script section for the state object.
- self.data = nil
-
- code, evmerr := self.Eval(msg, receiver.Init(), receiver)
- if evmerr != nil {
- self.state.Set(snapshot)
-
- statelogger.Debugf("Error during init execution %v", evmerr)
- }
-
- receiver.Code = code
- msg.Output = code
- } else {
- if len(receiver.Code) > 0 {
- ret, evmerr := self.Eval(msg, receiver.Code, receiver)
- if evmerr != nil {
- self.state.Set(snapshot)
-
- statelogger.Debugf("Error during code execution %v", evmerr)
- }
-
- msg.Output = ret
- }
+ if err != nil {
+ statelogger.Debugln(err)
}
- /*
- * XXX The following _should_ replace the above transaction
- * execution (also for regular calls. Will replace / test next
- * phase
- */
- /*
- // Execute transaction
- if tx.CreatesContract() {
- self.rec = MakeContract(tx, self.state)
- }
-
- address := self.Receiver().Address()
- evm := vm.New(NewEnv(state, self.tx, self.block), vm.DebugVmTy)
- exe := NewExecution(evm, address, self.tx.Data, self.gas, self.gas.Price, self.tx.Value)
- ret, err := msg.Exec(address, self.Sender())
- if err != nil {
- statelogger.Debugln(err)
- } else {
- if tx.CreatesContract() {
- self.Receiver().Code = ret
- }
- msg.Output = ret
- }
- */
-
- // Add default LOG. Default = big(sender.addr) + 1
- //addr := ethutil.BigD(receiver.Address())
- //self.state.AddLog(&state.Log{ethutil.U256(addr.Add(addr, ethutil.Big1)).Bytes(), [][]byte{sender.Address()}, nil})
-
- return
-}
-
-func (self *StateTransition) Eval(msg *state.Message, script []byte, context *state.StateObject) (ret []byte, err error) {
- var (
- transactor = self.Sender()
- state = self.state
- env = NewEnv(state, self.tx, self.block)
- callerClosure = vm.NewClosure(msg, transactor, context, script, self.gas, self.gasPrice)
- )
-
- evm := vm.New(env, vm.DebugVmTy)
- // TMP this will change in the refactor
- callerClosure.SetExecution(vm.NewExecution(evm, nil, nil, nil, nil, self.tx.Value))
- ret, _, err = callerClosure.Call(evm, self.tx.Data)
-
return
}