From 6a530ea3717e592407737c6cd2ebeba0200c9cd8 Mon Sep 17 00:00:00 2001 From: obscuren Date: Thu, 10 Apr 2014 14:40:12 -0400 Subject: [PATCH] Call fixed --- ethchain/closure.go | 4 ++++ ethchain/contract.go | 4 +++- ethchain/vm.go | 26 ++++++++++++++++---------- ethchain/vm_test.go | 23 ++++++++++++++++++++--- ethutil/parsing.go | 28 +++++++--------------------- 5 files changed, 50 insertions(+), 35 deletions(-) diff --git a/ethchain/closure.go b/ethchain/closure.go index d1fac0f43b..8e57a0d03f 100644 --- a/ethchain/closure.go +++ b/ethchain/closure.go @@ -52,6 +52,10 @@ func (c *Closure) Get(x *big.Int) *ethutil.Value { } func (c *Closure) Gets(x, y *big.Int) *ethutil.Value { + if x.Int64() > int64(len(c.Script)) || y.Int64() > int64(len(c.Script)) { + return ethutil.NewValue(0) + } + partial := c.Script[x.Int64() : x.Int64()+y.Int64()] return ethutil.NewValue(partial) diff --git a/ethchain/contract.go b/ethchain/contract.go index 113d067a43..e99e413f7a 100644 --- a/ethchain/contract.go +++ b/ethchain/contract.go @@ -70,7 +70,7 @@ func (c *Contract) Address() []byte { } func (c *Contract) RlpEncode() []byte { - return ethutil.Encode([]interface{}{c.Amount, c.Nonce, c.state.trie.Root}) + return ethutil.Encode([]interface{}{c.Amount, c.Nonce, c.state.trie.Root, c.script, c.initScript}) } func (c *Contract) RlpDecode(data []byte) { @@ -79,6 +79,8 @@ func (c *Contract) RlpDecode(data []byte) { c.Amount = decoder.Get(0).BigInt() c.Nonce = decoder.Get(1).Uint() c.state = NewState(ethutil.NewTrie(ethutil.Config.Db, decoder.Get(2).Interface())) + c.script = decoder.Get(3).Bytes() + c.initScript = decoder.Get(4).Bytes() } func MakeContract(tx *Transaction, state *State) *Contract { diff --git a/ethchain/vm.go b/ethchain/vm.go index a6a02dc9f6..f94425d2d1 100644 --- a/ethchain/vm.go +++ b/ethchain/vm.go @@ -2,7 +2,7 @@ package ethchain import ( _ "bytes" - "fmt" + _ "fmt" "github.com/ethereum/eth-go/ethutil" _ "github.com/obscuren/secp256k1-go" _ "math" @@ -301,9 +301,14 @@ func (vm *Vm) RunClosure(closure *Closure) []byte { // 0x50 range case oPUSH: // Push PC+1 on to the stack pc.Add(pc, ethutil.Big1) + //val := closure.GetMem(pc).BigInt() + data := closure.Gets(pc, big.NewInt(32)) + val := ethutil.BigD(data.Bytes()) - val := closure.GetMem(pc).BigInt() + // Push value to stack stack.Push(val) + + pc.Add(pc, big.NewInt(31)) case oPOP: stack.Pop() case oDUP: @@ -343,17 +348,16 @@ func (vm *Vm) RunClosure(closure *Closure) []byte { stack.Push(big.NewInt(int64(mem.Len()))) // 0x60 range case oCALL: - // Pop return size and offset - retSize, retOffset := stack.Popn() + // Closure addr + addr := stack.Pop() + // Pop gas and value of the stack. + gas, value := stack.Popn() // Pop input size and offset inSize, inOffset := stack.Popn() - fmt.Println(inSize, inOffset) + // Pop return size and offset + retSize, retOffset := stack.Popn() // Get the arguments from the memory args := mem.Get(inOffset.Int64(), inSize.Int64()) - // Pop gas and value of the stack. - gas, value := stack.Popn() - // Closure addr - addr := stack.Pop() // Fetch the contract which will serve as the closure body contract := vm.state.GetContract(addr.Bytes()) // Create a new callable closure @@ -385,7 +389,9 @@ func (vm *Vm) RunClosure(closure *Closure) []byte { break out */ default: - ethutil.Config.Log.Debugln("Invalid opcode", op) + ethutil.Config.Log.Debugf("Invalid opcode %x\n", op) + + return closure.Return(nil) } pc.Add(pc, ethutil.Big1) diff --git a/ethchain/vm_test.go b/ethchain/vm_test.go index 745005b099..65113ff573 100644 --- a/ethchain/vm_test.go +++ b/ethchain/vm_test.go @@ -83,6 +83,21 @@ func TestRun4(t *testing.T) { state := NewState(ethutil.NewTrie(db, "")) asm, err := mutan.Compile(strings.NewReader(` + int32 a = 10 + int32 b = 20 + if a > b { + int32 c = this.caller() + } + exit() + `), false) + script := ethutil.Assemble(asm...) + tx := NewContractCreationTx(ethutil.Big("0"), ethutil.Big("1000"), script) + addr := tx.Hash()[12:] + contract := MakeContract(tx, state) + state.UpdateContract(contract) + fmt.Printf("%x\n", addr) + + asm, err = mutan.Compile(strings.NewReader(` int32 a = 10 int32 b = 10 if a == b { @@ -97,9 +112,9 @@ func TestRun4(t *testing.T) { store[a] = 20 store[b] = this.caller() - int8[10] ret - int8[10] arg - call(1234, 0, 100000000, arg, ret) + int8 ret = 0 + int8 arg = 10 + call(938726394128221156290138488023434115948430767407, 0, 100000000, arg, ret) `), false) if err != nil { fmt.Println(err) @@ -113,6 +128,8 @@ func TestRun4(t *testing.T) { // Contract addr as test address account := NewAccount(ContractAddr, big.NewInt(10000000)) c := MakeContract(callerTx, state) + //fmt.Println(c.script[230:240]) + //fmt.Println(c.script) callerClosure := NewClosure(account, c, c.script, state, big.NewInt(1000000000), new(big.Int)) vm := NewVm(state, RuntimeVars{ diff --git a/ethutil/parsing.go b/ethutil/parsing.go index a9d50e4252..0de3966548 100644 --- a/ethutil/parsing.go +++ b/ethutil/parsing.go @@ -1,8 +1,8 @@ package ethutil import ( + _ "fmt" "math/big" - "strconv" ) // Op codes @@ -98,11 +98,16 @@ func CompileInstr(s interface{}) ([]byte, error) { // Assume regular bytes during compilation if !success { num.SetBytes([]byte(str)) + } else { + // tmp fix for 32 bytes + n := BigToBytes(num, 256) + return n, nil } return num.Bytes(), nil case int: - return big.NewInt(int64(s.(int))).Bytes(), nil + num := BigToBytes(big.NewInt(int64(s.(int))), 256) + return num, nil case []byte: return BigD(s.([]byte)).Bytes(), nil } @@ -110,25 +115,6 @@ func CompileInstr(s interface{}) ([]byte, error) { return nil, nil } -func Instr(instr string) (int, []string, error) { - - base := new(big.Int) - base.SetString(instr, 0) - - args := make([]string, 7) - for i := 0; i < 7; i++ { - // int(int(val) / int(math.Pow(256,float64(i)))) % 256 - exp := BigPow(256, i) - num := new(big.Int) - num.Div(base, exp) - - args[i] = num.Mod(num, big.NewInt(256)).String() - } - op, _ := strconv.Atoi(args[0]) - - return op, args[1:7], nil -} - // Script compilation functions // Compiles strings to machine code func Assemble(instructions ...interface{}) (script []byte) {