diff --git a/ethchain/closure.go b/ethchain/closure.go index f8e692f61..2e809aa9d 100644 --- a/ethchain/closure.go +++ b/ethchain/closure.go @@ -15,7 +15,8 @@ type Callee interface { type ClosureBody interface { Callee ethutil.RlpEncodable - GetMem(int64) *ethutil.Value + GetMem(*big.Int) *ethutil.Value + SetMem(*big.Int, *ethutil.Value) } // Basic inline closure object which implement the 'closure' interface @@ -36,7 +37,7 @@ func NewClosure(callee Callee, object ClosureBody, state *State, gas, val *big.I } // Retuns the x element in data slice -func (c *Closure) GetMem(x int64) *ethutil.Value { +func (c *Closure) GetMem(x *big.Int) *ethutil.Value { m := c.object.GetMem(x) if m == nil { return ethutil.EmptyValue() @@ -45,6 +46,10 @@ func (c *Closure) GetMem(x int64) *ethutil.Value { return m } +func (c *Closure) SetMem(x *big.Int, val *ethutil.Value) { + c.object.SetMem(x, val) +} + func (c *Closure) Address() []byte { return c.object.Address() } diff --git a/ethchain/contract.go b/ethchain/contract.go index 93d2b68ba..f7ae01753 100644 --- a/ethchain/contract.go +++ b/ethchain/contract.go @@ -39,12 +39,17 @@ func (c *Contract) State() *State { return c.state } -func (c *Contract) GetMem(num int64) *ethutil.Value { - nb := ethutil.BigToBytes(big.NewInt(num), 256) +func (c *Contract) GetMem(num *big.Int) *ethutil.Value { + nb := ethutil.BigToBytes(num, 256) return c.Addr(nb) } +func (c *Contract) SetMem(num *big.Int, val *ethutil.Value) { + addr := ethutil.BigToBytes(num, 256) + c.state.trie.Update(string(addr), string(val.Encode())) +} + // Return the gas back to the origin. Used by the Virtual machine or Closures func (c *Contract) ReturnGas(val *big.Int, state *State) { c.Amount.Add(c.Amount, val) diff --git a/ethchain/stack.go b/ethchain/stack.go index b64b759fd..3c2899e62 100644 --- a/ethchain/stack.go +++ b/ethchain/stack.go @@ -237,6 +237,10 @@ func (m *Memory) Get(offset, size int64) []byte { return m.store[offset : offset+size] } +func (m *Memory) Len() int { + return len(m.store) +} + func (m *Memory) Print() { fmt.Println("### MEM ###") if len(m.store) > 0 { diff --git a/ethchain/vm.go b/ethchain/vm.go index 8b5bb93c0..bc3a9edaf 100644 --- a/ethchain/vm.go +++ b/ethchain/vm.go @@ -49,7 +49,7 @@ func (vm *Vm) RunClosure(closure *Closure) []byte { // New stack (should this be shared?) stack := NewStack() // Instruction pointer - pc := int64(0) + pc := big.NewInt(0) // Current step count step := 0 // The base for all big integer arithmetic @@ -226,7 +226,8 @@ func (vm *Vm) RunClosure(closure *Closure) []byte { // 0x50 range case oPUSH: // Push PC+1 on to the stack - pc++ + pc.Add(pc, ethutil.Big1) + val := closure.GetMem(pc).BigInt() stack.Push(val) case oPOP: @@ -250,14 +251,22 @@ func (vm *Vm) RunClosure(closure *Closure) []byte { mem.Set(mStart.Int64(), 32, ethutil.BigToBytes(base, 256)) case oSLOAD: loc := stack.Pop() - val := closure.GetMem(loc.Int64()) + val := closure.GetMem(loc) stack.Push(val.BigInt()) case oSSTORE: + val, loc := stack.Popn() + closure.SetMem(loc, ethutil.NewValue(val)) case oJUMP: + pc = stack.Pop() case oJUMPI: + pos, cond := stack.Popn() + if cond.Cmp(big.NewInt(0)) > 0 { + pc = pos + } case oPC: + stack.Push(pc) case oMSIZE: - + stack.Push(big.NewInt(int64(mem.Len()))) // 0x60 range case oCALL: // Pop return size and offset @@ -304,7 +313,7 @@ func (vm *Vm) RunClosure(closure *Closure) []byte { ethutil.Config.Log.Debugln("Invalid opcode", op) } - pc++ + pc.Add(pc, ethutil.Big1) } } @@ -682,7 +691,7 @@ func makeInlineTx(addr []byte, value, from, length *big.Int, contract *Contract, j := int64(0) dataItems := make([]string, int(length.Uint64())) for i := from.Int64(); i < length.Int64(); i++ { - dataItems[j] = contract.GetMem(j).Str() + dataItems[j] = contract.GetMem(big.NewInt(j)).Str() j++ } diff --git a/ethutil/common.go b/ethutil/common.go index 07df6bb13..f15b10e6d 100644 --- a/ethutil/common.go +++ b/ethutil/common.go @@ -33,3 +33,9 @@ func CurrencyToString(num *big.Int) string { return fmt.Sprintf("%v Wei", num) } + +var ( + Big1 = big.NewInt(1) + Big0 = big.NewInt(0) + Big256 = big.NewInt(0xff) +)