From 32d125131f602d63f66ee7eb09439074f0b94a91 Mon Sep 17 00:00:00 2001 From: obscuren Date: Thu, 24 Jul 2014 12:04:15 +0200 Subject: Refactored to new state and vm --- ethchain/state_transition.go | 95 +++++++++++++++++++++++++++++--------------- 1 file changed, 63 insertions(+), 32 deletions(-) (limited to 'ethchain/state_transition.go') diff --git a/ethchain/state_transition.go b/ethchain/state_transition.go index 8ed528c9f..a03a3a94a 100644 --- a/ethchain/state_transition.go +++ b/ethchain/state_transition.go @@ -2,6 +2,10 @@ package ethchain import ( "fmt" + "github.com/ethereum/eth-go/ethstate" + "github.com/ethereum/eth-go/ethtrie" + "github.com/ethereum/eth-go/ethutil" + "github.com/ethereum/eth-go/ethvm" "math/big" ) @@ -27,17 +31,17 @@ type StateTransition struct { gas, gasPrice *big.Int value *big.Int data []byte - state *State + state *ethstate.State block *Block - cb, rec, sen *StateObject + cb, rec, sen *ethstate.StateObject } -func NewStateTransition(coinbase *StateObject, tx *Transaction, state *State, block *Block) *StateTransition { +func NewStateTransition(coinbase *ethstate.StateObject, tx *Transaction, state *ethstate.State, block *Block) *StateTransition { return &StateTransition{coinbase.Address(), tx.Recipient, tx, new(big.Int), new(big.Int).Set(tx.GasPrice), tx.Value, tx.Data, state, block, coinbase, nil, nil} } -func (self *StateTransition) Coinbase() *StateObject { +func (self *StateTransition) Coinbase() *ethstate.StateObject { if self.cb != nil { return self.cb } @@ -45,7 +49,7 @@ func (self *StateTransition) Coinbase() *StateObject { self.cb = self.state.GetOrNewStateObject(self.coinbase) return self.cb } -func (self *StateTransition) Sender() *StateObject { +func (self *StateTransition) Sender() *ethstate.StateObject { if self.sen != nil { return self.sen } @@ -54,7 +58,7 @@ func (self *StateTransition) Sender() *StateObject { return self.sen } -func (self *StateTransition) Receiver() *StateObject { +func (self *StateTransition) Receiver() *ethstate.StateObject { if self.tx != nil && self.tx.CreatesContract() { return nil } @@ -67,7 +71,7 @@ func (self *StateTransition) Receiver() *StateObject { return self.rec } -func (self *StateTransition) MakeStateObject(state *State, tx *Transaction) *StateObject { +func (self *StateTransition) MakeStateObject(state *ethstate.State, tx *Transaction) *ethstate.StateObject { contract := MakeContract(tx, state) return contract @@ -154,7 +158,7 @@ func (self *StateTransition) TransitionState() (err error) { var ( tx = self.tx sender = self.Sender() - receiver *StateObject + receiver *ethstate.StateObject ) defer self.RefundGas() @@ -163,13 +167,13 @@ func (self *StateTransition) TransitionState() (err error) { sender.Nonce += 1 // Transaction gas - if err = self.UseGas(GasTx); err != nil { + if err = self.UseGas(ethvm.GasTx); err != nil { return } // Pay data gas dataPrice := big.NewInt(int64(len(self.data))) - dataPrice.Mul(dataPrice, GasData) + dataPrice.Mul(dataPrice, ethvm.GasData) if err = self.UseGas(dataPrice); err != nil { return } @@ -178,7 +182,7 @@ func (self *StateTransition) TransitionState() (err error) { return fmt.Errorf("Insufficient funds to transfer value. Req %v, has %v", self.value, sender.Amount) } - var snapshot *State + var snapshot *ethstate.State // If the receiver is nil it's a contract (\0*32). if tx.CreatesContract() { // Subtract the (irreversible) amount from the senders account @@ -220,10 +224,10 @@ func (self *StateTransition) TransitionState() (err error) { return fmt.Errorf("Error during init execution %v", err) } - receiver.script = code + receiver.Code = code } else { - if len(receiver.Script()) > 0 { - _, err = self.Eval(receiver.Script(), receiver, "code") + if len(receiver.Code) > 0 { + _, err = self.Eval(receiver.Code, receiver, "code") if err != nil { self.state.Set(snapshot) @@ -235,7 +239,7 @@ func (self *StateTransition) TransitionState() (err error) { return } -func (self *StateTransition) transferValue(sender, receiver *StateObject) error { +func (self *StateTransition) transferValue(sender, receiver *ethstate.StateObject) error { if sender.Amount.Cmp(self.value) < 0 { return fmt.Errorf("Insufficient funds to transfer value. Req %v, has %v", self.value, sender.Amount) } @@ -248,34 +252,61 @@ func (self *StateTransition) transferValue(sender, receiver *StateObject) error return nil } -func (self *StateTransition) Eval(script []byte, context *StateObject, typ string) (ret []byte, err error) { +func (self *StateTransition) Eval(script []byte, context *ethstate.StateObject, typ string) (ret []byte, err error) { var ( - block = self.block - initiator = self.Sender() - state = self.state + transactor = self.Sender() + state = self.state + env = NewEnv(state, self.tx, self.block) + callerClosure = ethvm.NewClosure(transactor, context, script, self.gas, self.gasPrice) ) - closure := NewClosure(initiator, context, script, state, self.gas, self.gasPrice) - vm := NewVm(state, nil, RuntimeVars{ - Origin: initiator.Address(), - Block: block, - BlockNumber: block.Number, - PrevHash: block.PrevHash, - Coinbase: block.Coinbase, - Time: block.Time, - Diff: block.Difficulty, - Value: self.value, - }) + vm := ethvm.New(env) vm.Verbose = true vm.Fn = typ - ret, err = Call(vm, closure, self.data) + ret, _, err = callerClosure.Call(vm, self.tx.Data) + + /* + closure := NewClosure(initiator, context, script, state, self.gas, self.gasPrice) + vm := NewVm(state, nil, RuntimeVars{ + Origin: initiator.Address(), + Block: block, + BlockNumber: block.Number, + PrevHash: block.PrevHash, + Coinbase: block.Coinbase, + Time: block.Time, + Diff: block.Difficulty, + Value: self.value, + }) + vm.Verbose = true + vm.Fn = typ + + ret, err = Call(vm, closure, self.data) + */ return } -func Call(vm *Vm, closure *Closure, data []byte) (ret []byte, err error) { +/* +func Call(vm *eth.Vm, closure *Closure, data []byte) (ret []byte, err error) { ret, _, err = closure.Call(vm, data) return } +*/ + +// Converts an transaction in to a state object +func MakeContract(tx *Transaction, state *ethstate.State) *ethstate.StateObject { + // Create contract if there's no recipient + if tx.IsContract() { + addr := tx.CreationAddress() + + contract := state.NewStateObject(addr) + contract.InitCode = tx.Data + contract.State = ethstate.NewState(ethtrie.NewTrie(ethutil.Config.Db, "")) + + return contract + } + + return nil +} -- cgit v1.2.3