diff options
author | Felix Lange <fjl@twurst.com> | 2014-10-23 21:01:27 +0800 |
---|---|---|
committer | Felix Lange <fjl@twurst.com> | 2014-10-23 21:01:27 +0800 |
commit | 69baa465ea69ae60eed802445cf0132b9eb69934 (patch) | |
tree | b09da7582b5c4850d4db13aee808f2fef2f97de0 /vm/execution.go | |
parent | 50fd46924900869e7210217c6a07979b544991c8 (diff) | |
parent | feef194829b07570e91873ed5d1e8cc51e8fa430 (diff) | |
download | dexon-69baa465ea69ae60eed802445cf0132b9eb69934.tar dexon-69baa465ea69ae60eed802445cf0132b9eb69934.tar.gz dexon-69baa465ea69ae60eed802445cf0132b9eb69934.tar.bz2 dexon-69baa465ea69ae60eed802445cf0132b9eb69934.tar.lz dexon-69baa465ea69ae60eed802445cf0132b9eb69934.tar.xz dexon-69baa465ea69ae60eed802445cf0132b9eb69934.tar.zst dexon-69baa465ea69ae60eed802445cf0132b9eb69934.zip |
Merge eth-go repository into go-ethereum
mist, etheruem have been moved to cmd/
Diffstat (limited to 'vm/execution.go')
-rw-r--r-- | vm/execution.go | 93 |
1 files changed, 93 insertions, 0 deletions
diff --git a/vm/execution.go b/vm/execution.go new file mode 100644 index 000000000..8da0469de --- /dev/null +++ b/vm/execution.go @@ -0,0 +1,93 @@ +package vm + +import ( + "fmt" + "math/big" + + "github.com/ethereum/go-ethereum/ethstate" + "github.com/ethereum/go-ethereum/ethutil" +) + +type Execution struct { + vm VirtualMachine + address, input []byte + Gas, price, value *big.Int + object *ethstate.StateObject + SkipTransfer bool +} + +func NewExecution(vm VirtualMachine, address, input []byte, gas, gasPrice, value *big.Int) *Execution { + return &Execution{vm: vm, address: address, input: input, Gas: gas, price: gasPrice, value: value} +} + +func (self *Execution) Addr() []byte { + return self.address +} + +func (self *Execution) Exec(codeAddr []byte, caller ClosureRef) ([]byte, error) { + // Retrieve the executing code + code := self.vm.Env().State().GetCode(codeAddr) + + return self.exec(code, codeAddr, caller) +} + +func (self *Execution) exec(code, caddr []byte, caller ClosureRef) (ret []byte, err error) { + env := self.vm.Env() + + snapshot := env.State().Copy() + defer func() { + if IsDepthErr(err) || IsOOGErr(err) { + env.State().Set(snapshot) + } + }() + + msg := env.State().Manifest().AddMessage(ðstate.Message{ + To: self.address, From: caller.Address(), + Input: self.input, + Origin: env.Origin(), + Block: env.BlockHash(), Timestamp: env.Time(), Coinbase: env.Coinbase(), Number: env.BlockNumber(), + Value: self.value, + }) + + from, to := caller.Object(), env.State().GetOrNewStateObject(self.address) + // Skipping transfer is used on testing for the initial call + if !self.SkipTransfer { + err = env.Transfer(from, to, self.value) + } + + if err != nil { + caller.ReturnGas(self.Gas, self.price) + + err = fmt.Errorf("Insufficient funds to transfer value. Req %v, has %v", self.value, from.Balance) + } else { + self.object = to + // Pre-compiled contracts (address.go) 1, 2 & 3. + naddr := ethutil.BigD(caddr).Uint64() + if p := Precompiled[naddr]; p != nil { + if self.Gas.Cmp(p.Gas) >= 0 { + ret = p.Call(self.input) + self.vm.Printf("NATIVE_FUNC(%x) => %x", naddr, ret) + } + } else { + // Create a new callable closure + c := NewClosure(msg, caller, to, code, self.Gas, self.price) + c.exe = self + + if self.vm.Depth() == MaxCallDepth { + c.UseGas(self.Gas) + + return c.Return(nil), DepthError{} + } + + // Executer the closure and get the return value (if any) + ret, _, err = c.Call(self.vm, self.input) + msg.Output = ret + } + } + + return +} + +func (self *Execution) Create(caller ClosureRef) (ret []byte, err error) { + return self.exec(self.input, nil, caller) +} |