diff --git a/ethchain/closure.go b/ethchain/closure.go index 2e809aa9d..e9cb2c8bc 100644 --- a/ethchain/closure.go +++ b/ethchain/closure.go @@ -17,6 +17,7 @@ type ClosureBody interface { ethutil.RlpEncodable GetMem(*big.Int) *ethutil.Value SetMem(*big.Int, *ethutil.Value) + GetInstr(*big.Int) *ethutil.Value } // Basic inline closure object which implement the 'closure' interface @@ -46,6 +47,10 @@ func (c *Closure) GetMem(x *big.Int) *ethutil.Value { return m } +func (c *Closure) GetInstr(x *big.Int) *ethutil.Value { + return c.object.GetInstr(x) +} + func (c *Closure) SetMem(x *big.Int, val *ethutil.Value) { c.object.SetMem(x, val) } diff --git a/ethchain/contract.go b/ethchain/contract.go index f7ae01753..f68dcf367 100644 --- a/ethchain/contract.go +++ b/ethchain/contract.go @@ -11,6 +11,7 @@ type Contract struct { //state *ethutil.Trie state *State address []byte + script []byte } func NewContract(address []byte, Amount *big.Int, root []byte) *Contract { @@ -45,6 +46,14 @@ func (c *Contract) GetMem(num *big.Int) *ethutil.Value { return c.Addr(nb) } +func (c *Contract) GetInstr(pc *big.Int) *ethutil.Value { + if int64(len(c.script)-1) < pc.Int64() { + return ethutil.NewValue(0) + } + + return ethutil.NewValueFromBytes([]byte{c.script[pc.Int64()]}) +} + func (c *Contract) SetMem(num *big.Int, val *ethutil.Value) { addr := ethutil.BigToBytes(num, 256) c.state.trie.Update(string(addr), string(val.Encode())) diff --git a/ethchain/vm.go b/ethchain/vm.go index 98aaa603a..b4b2177bf 100644 --- a/ethchain/vm.go +++ b/ethchain/vm.go @@ -72,7 +72,7 @@ func (vm *Vm) RunClosure(closure *Closure) []byte { for { step++ // Get the memory location of pc - val := closure.GetMem(pc) + val := closure.GetInstr(pc) // Get the opcode (it must be an opcode!) op := OpCode(val.Uint()) if ethutil.Config.Debug { @@ -233,13 +233,37 @@ func (vm *Vm) RunClosure(closure *Closure) []byte { // 0x10 range case oAND: + x, y := stack.Popn() + if (x.Cmp(ethutil.BigTrue) >= 0) && (y.Cmp(ethutil.BigTrue) >= 0) { + stack.Push(ethutil.BigTrue) + } else { + stack.Push(ethutil.BigFalse) + } + case oOR: + x, y := stack.Popn() + if (x.Cmp(ethutil.BigInt0) >= 0) || (y.Cmp(ethutil.BigInt0) >= 0) { + stack.Push(ethutil.BigTrue) + } else { + stack.Push(ethutil.BigFalse) + } case oXOR: + x, y := stack.Popn() + stack.Push(base.Xor(x, y)) case oBYTE: + val, th := stack.Popn() + if th.Cmp(big.NewInt(32)) < 0 { + stack.Push(big.NewInt(int64(len(val.Bytes())-1) - th.Int64())) + } else { + stack.Push(ethutil.BigFalse) + } // 0x20 range case oSHA3: + size, offset := stack.Popn() + data := mem.Get(offset.Int64(), size.Int64()) + stack.Push(ethutil.BigD(data)) // 0x30 range case oADDRESS: stack.Push(ethutil.BigD(closure.Object().Address()))