From c0a030ef0a3ce8342fda2a53cdafd50a271b4837 Mon Sep 17 00:00:00 2001 From: obscuren Date: Wed, 9 Apr 2014 14:08:18 +0200 Subject: Added new insruction methods --- ethchain/closure.go | 5 +++++ ethchain/contract.go | 9 +++++++++ ethchain/vm.go | 26 +++++++++++++++++++++++++- 3 files changed, 39 insertions(+), 1 deletion(-) 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())) -- cgit From 4f2e9c2640eaa962d085db329221bfd6f1a1799e Mon Sep 17 00:00:00 2001 From: obscuren Date: Wed, 9 Apr 2014 12:27:25 -0400 Subject: Check for nil --- ethutil/rlp.go | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/ethutil/rlp.go b/ethutil/rlp.go index e6c75696e..d95ace425 100644 --- a/ethutil/rlp.go +++ b/ethutil/rlp.go @@ -186,7 +186,12 @@ func Encode(object interface{}) []byte { case byte: buff.Write(Encode(big.NewInt(int64(t)))) case *big.Int: - buff.Write(Encode(t.Bytes())) + // Not sure how this is possible while we check for + if t == nil { + buff.WriteByte(0xc0) + } else { + buff.Write(Encode(t.Bytes())) + } case []byte: if len(t) == 1 && t[0] <= 0x7f { buff.Write(t) -- cgit From e09f0a5f2c1e1b46226656dbac9a4ae10e0dcd14 Mon Sep 17 00:00:00 2001 From: obscuren Date: Wed, 9 Apr 2014 12:27:54 -0400 Subject: Split code for contracts --- ethchain/closure.go | 22 ++++++++++++++-------- ethchain/contract.go | 22 ++++++++++++++-------- ethchain/state_manager.go | 2 +- ethchain/vm.go | 4 ++-- ethchain/vm_test.go | 3 ++- 5 files changed, 33 insertions(+), 20 deletions(-) diff --git a/ethchain/closure.go b/ethchain/closure.go index e9cb2c8bc..d1fac0f43 100644 --- a/ethchain/closure.go +++ b/ethchain/closure.go @@ -12,18 +12,18 @@ type Callee interface { Address() []byte } -type ClosureBody interface { +type Reference interface { Callee 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 type Closure struct { callee Callee - object ClosureBody + object Reference + Script []byte State *State Gas *big.Int @@ -33,8 +33,8 @@ type Closure struct { } // Create a new closure for the given data items -func NewClosure(callee Callee, object ClosureBody, state *State, gas, val *big.Int) *Closure { - return &Closure{callee, object, state, gas, val, nil} +func NewClosure(callee Callee, object Reference, script []byte, state *State, gas, val *big.Int) *Closure { + return &Closure{callee, object, script, state, gas, val, nil} } // Retuns the x element in data slice @@ -47,8 +47,14 @@ 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) Get(x *big.Int) *ethutil.Value { + return c.Gets(x, big.NewInt(1)) +} + +func (c *Closure) Gets(x, y *big.Int) *ethutil.Value { + partial := c.Script[x.Int64() : x.Int64()+y.Int64()] + + return ethutil.NewValue(partial) } func (c *Closure) SetMem(x *big.Int, val *ethutil.Value) { @@ -86,7 +92,7 @@ func (c *Closure) ReturnGas(gas *big.Int, state *State) { c.Gas.Add(c.Gas, gas) } -func (c *Closure) Object() ClosureBody { +func (c *Closure) Object() Reference { return c.object } diff --git a/ethchain/contract.go b/ethchain/contract.go index f68dcf367..113d067a4 100644 --- a/ethchain/contract.go +++ b/ethchain/contract.go @@ -9,9 +9,10 @@ type Contract struct { Amount *big.Int Nonce uint64 //state *ethutil.Trie - state *State - address []byte - script []byte + state *State + address []byte + script []byte + initScript []byte } func NewContract(address []byte, Amount *big.Int, root []byte) *Contract { @@ -88,12 +89,17 @@ func MakeContract(tx *Transaction, state *State) *Contract { value := tx.Value contract := NewContract(addr, value, []byte("")) state.trie.Update(string(addr), string(contract.RlpEncode())) - for i, val := range tx.Data { - if len(val) > 0 { - bytNum := ethutil.BigToBytes(big.NewInt(int64(i)), 256) - contract.state.trie.Update(string(bytNum), string(ethutil.Encode(val))) + contract.script = tx.Data + contract.initScript = tx.Init + + /* + for i, val := range tx.Data { + if len(val) > 0 { + bytNum := ethutil.BigToBytes(big.NewInt(int64(i)), 256) + contract.state.trie.Update(string(bytNum), string(ethutil.Encode(val))) + } } - } + */ state.trie.Update(string(addr), string(contract.RlpEncode())) return contract diff --git a/ethchain/state_manager.go b/ethchain/state_manager.go index 95e46e41d..7a2a762b2 100644 --- a/ethchain/state_manager.go +++ b/ethchain/state_manager.go @@ -311,7 +311,7 @@ func (sm *StateManager) ProcessContract(contract *Contract, tx *Transaction, blo }() caller := sm.procState.GetAccount(tx.Sender()) - closure := NewClosure(caller, contract, sm.procState, tx.Gas, tx.Value) + closure := NewClosure(caller, contract, contract.script, sm.procState, tx.Gas, tx.Value) vm := NewVm(sm.procState, RuntimeVars{ origin: caller.Address(), blockNumber: block.BlockInfo().Number, diff --git a/ethchain/vm.go b/ethchain/vm.go index b4b2177bf..a6a02dc9f 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.GetInstr(pc) + val := closure.Get(pc) // Get the opcode (it must be an opcode!) op := OpCode(val.Uint()) if ethutil.Config.Debug { @@ -357,7 +357,7 @@ func (vm *Vm) RunClosure(closure *Closure) []byte { // Fetch the contract which will serve as the closure body contract := vm.state.GetContract(addr.Bytes()) // Create a new callable closure - closure := NewClosure(closure, contract, vm.state, gas, value) + closure := NewClosure(closure, contract, contract.script, vm.state, gas, value) // Executer the closure and get the return value (if any) ret := closure.Call(vm, args) diff --git a/ethchain/vm_test.go b/ethchain/vm_test.go index 85ec4c693..745005b09 100644 --- a/ethchain/vm_test.go +++ b/ethchain/vm_test.go @@ -112,7 +112,8 @@ func TestRun4(t *testing.T) { // Contract addr as test address account := NewAccount(ContractAddr, big.NewInt(10000000)) - callerClosure := NewClosure(account, MakeContract(callerTx, state), state, big.NewInt(1000000000), new(big.Int)) + c := MakeContract(callerTx, state) + callerClosure := NewClosure(account, c, c.script, state, big.NewInt(1000000000), new(big.Int)) vm := NewVm(state, RuntimeVars{ origin: account.Address(), -- cgit From 720521ed4a28c8a1b74bedd03e82bf4f887c9cb5 Mon Sep 17 00:00:00 2001 From: obscuren Date: Wed, 9 Apr 2014 12:28:16 -0400 Subject: Changed how txs define their data & added init field --- ethchain/transaction.go | 66 +++++++++++++++++--------------------------- ethchain/transaction_test.go | 53 ----------------------------------- 2 files changed, 25 insertions(+), 94 deletions(-) diff --git a/ethchain/transaction.go b/ethchain/transaction.go index 506e3c159..b359c9151 100644 --- a/ethchain/transaction.go +++ b/ethchain/transaction.go @@ -14,7 +14,8 @@ type Transaction struct { Value *big.Int Gas *big.Int Gasprice *big.Int - Data []string + Data []byte + Init []byte v byte r, s []byte @@ -22,11 +23,11 @@ type Transaction struct { contractCreation bool } -func NewContractCreationTx(value, gasprice *big.Int, data []string) *Transaction { +func NewContractCreationTx(value, gasprice *big.Int, data []byte) *Transaction { return &Transaction{Value: value, Gasprice: gasprice, Data: data, contractCreation: true} } -func NewTransactionMessage(to []byte, value, gasprice, gas *big.Int, data []string) *Transaction { +func NewTransactionMessage(to []byte, value, gasprice, gas *big.Int, data []byte) *Transaction { return &Transaction{Recipient: to, Value: value, Gasprice: gasprice, Gas: gas, Data: data} } @@ -45,19 +46,12 @@ func NewTransactionFromValue(val *ethutil.Value) *Transaction { } func (tx *Transaction) Hash() []byte { - data := make([]interface{}, len(tx.Data)) - for i, val := range tx.Data { - data[i] = val + data := []interface{}{tx.Nonce, tx.Value, tx.Gasprice, tx.Gas, tx.Recipient, string(tx.Data)} + if tx.contractCreation { + data = append(data, string(tx.Init)) } - preEnc := []interface{}{ - tx.Nonce, - tx.Recipient, - tx.Value, - data, - } - - return ethutil.Sha3Bin(ethutil.Encode(preEnc)) + return ethutil.Sha3Bin(ethutil.NewValue(data).Encode()) } func (tx *Transaction) IsContract() bool { @@ -110,15 +104,17 @@ func (tx *Transaction) Sign(privk []byte) error { return nil } +// [ NONCE, VALUE, GASPRICE, GAS, TO, DATA, V, R, S ] +// [ NONCE, VALUE, GASPRICE, GAS, 0, CODE, INIT, V, R, S ] func (tx *Transaction) RlpData() interface{} { - data := []interface{}{tx.Nonce, tx.Value, tx.Gasprice} + data := []interface{}{tx.Nonce, tx.Value, tx.Gasprice, tx.Gas, tx.Recipient, tx.Data} - if !tx.contractCreation { - data = append(data, tx.Recipient, tx.Gas) + if tx.contractCreation { + data = append(data, tx.Init) } - d := ethutil.NewSliceValue(tx.Data).Slice() + //d := ethutil.NewSliceValue(tx.Data).Slice() - return append(data, d, tx.v, tx.r, tx.s) + return append(data, tx.v, tx.r, tx.s) } func (tx *Transaction) RlpValue() *ethutil.Value { @@ -137,31 +133,19 @@ func (tx *Transaction) RlpValueDecode(decoder *ethutil.Value) { tx.Nonce = decoder.Get(0).Uint() tx.Value = decoder.Get(1).BigInt() tx.Gasprice = decoder.Get(2).BigInt() + tx.Gas = decoder.Get(3).BigInt() + tx.Recipient = decoder.Get(4).Bytes() + tx.Data = decoder.Get(5).Bytes() - // If the 4th item is a list(slice) this tx - // is a contract creation tx - if decoder.Get(3).IsList() { - d := decoder.Get(3) - tx.Data = make([]string, d.Len()) - for i := 0; i < d.Len(); i++ { - tx.Data[i] = d.Get(i).Str() - } - - tx.v = byte(decoder.Get(4).Uint()) - tx.r = decoder.Get(5).Bytes() - tx.s = decoder.Get(6).Bytes() - + // If the list is of length 10 it's a contract creation tx + if decoder.Len() == 10 { tx.contractCreation = true - } else { - tx.Recipient = decoder.Get(3).Bytes() - tx.Gas = decoder.Get(4).BigInt() - - d := decoder.Get(5) - tx.Data = make([]string, d.Len()) - for i := 0; i < d.Len(); i++ { - tx.Data[i] = d.Get(i).Str() - } + tx.Init = decoder.Get(6).Bytes() + tx.v = byte(decoder.Get(7).Uint()) + tx.r = decoder.Get(8).Bytes() + tx.s = decoder.Get(9).Bytes() + } else { tx.v = byte(decoder.Get(6).Uint()) tx.r = decoder.Get(7).Bytes() tx.s = decoder.Get(8).Bytes() diff --git a/ethchain/transaction_test.go b/ethchain/transaction_test.go index a49768aea..3603fd8a7 100644 --- a/ethchain/transaction_test.go +++ b/ethchain/transaction_test.go @@ -1,54 +1 @@ package ethchain - -import ( - "encoding/hex" - "math/big" - "testing" -) - -func TestAddressRetrieval(t *testing.T) { - // TODO - // 88f9b82462f6c4bf4a0fb15e5c3971559a316e7f - key, _ := hex.DecodeString("3ecb44df2159c26e0f995712d4f39b6f6e499b40749b1cf1246c37f9516cb6a4") - - tx := &Transaction{ - Nonce: 0, - Recipient: ZeroHash160, - Value: big.NewInt(0), - Data: nil, - } - //fmt.Printf("rlp %x\n", tx.RlpEncode()) - //fmt.Printf("sha rlp %x\n", tx.Hash()) - - tx.Sign(key) - - //fmt.Printf("hex tx key %x\n", tx.PublicKey()) - //fmt.Printf("seder %x\n", tx.Sender()) -} - -func TestAddressRetrieval2(t *testing.T) { - // TODO - // 88f9b82462f6c4bf4a0fb15e5c3971559a316e7f - key, _ := hex.DecodeString("3ecb44df2159c26e0f995712d4f39b6f6e499b40749b1cf1246c37f9516cb6a4") - addr, _ := hex.DecodeString("944400f4b88ac9589a0f17ed4671da26bddb668b") - tx := &Transaction{ - Nonce: 0, - Recipient: addr, - Value: big.NewInt(1000), - Data: nil, - } - tx.Sign(key) - //data, _ := hex.DecodeString("f85d8094944400f4b88ac9589a0f17ed4671da26bddb668b8203e8c01ca0363b2a410de00bc89be40f468d16e70e543b72191fbd8a684a7c5bef51dc451fa02d8ecf40b68f9c64ed623f6ee24c9c878943b812e1e76bd73ccb2bfef65579e7") - //tx := NewTransactionFromData(data) - /* - fmt.Println(tx.RlpValue()) - - fmt.Printf("rlp %x\n", tx.RlpEncode()) - fmt.Printf("sha rlp %x\n", tx.Hash()) - - //tx.Sign(key) - - fmt.Printf("hex tx key %x\n", tx.PublicKey()) - fmt.Printf("seder %x\n", tx.Sender()) - */ -} -- cgit From 0fccbeabcc3b8c110ce3712e5488ad99245f92ee Mon Sep 17 00:00:00 2001 From: obscuren Date: Wed, 9 Apr 2014 12:28:34 -0400 Subject: No longer return a list, but raw bytes --- ethutil/parsing.go | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/ethutil/parsing.go b/ethutil/parsing.go index 16ed2d06d..a9d50e425 100644 --- a/ethutil/parsing.go +++ b/ethutil/parsing.go @@ -131,13 +131,14 @@ func Instr(instr string) (int, []string, error) { // Script compilation functions // Compiles strings to machine code -func Assemble(instructions ...interface{}) (script []string) { - script = make([]string, len(instructions)) +func Assemble(instructions ...interface{}) (script []byte) { + //script = make([]string, len(instructions)) - for i, val := range instructions { + for _, val := range instructions { instr, _ := CompileInstr(val) - script[i] = string(instr) + //script[i] = string(instr) + script = append(script, instr...) } return -- cgit From 6a530ea3717e592407737c6cd2ebeba0200c9cd8 Mon Sep 17 00:00:00 2001 From: obscuren Date: Thu, 10 Apr 2014 14:40:12 -0400 Subject: 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 d1fac0f43..8e57a0d03 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 113d067a4..e99e413f7 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 a6a02dc9f..f94425d2d 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 745005b09..65113ff57 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 a9d50e425..0de396654 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) { -- cgit From 969e748dce5562fc543990b6911d53ab699e393e Mon Sep 17 00:00:00 2001 From: obscuren Date: Thu, 10 Apr 2014 15:30:14 -0400 Subject: Call fixed --- ethchain/vm_test.go | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/ethchain/vm_test.go b/ethchain/vm_test.go index 65113ff57..dc74422cc 100644 --- a/ethchain/vm_test.go +++ b/ethchain/vm_test.go @@ -119,7 +119,7 @@ func TestRun4(t *testing.T) { if err != nil { fmt.Println(err) } - //asm = append(asm, "LOG") + asm = append(asm, "LOG") fmt.Println(asm) callerScript := ethutil.Assemble(asm...) @@ -128,8 +128,6 @@ 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{ -- cgit From 891f7259091cba0fe5e8c9370e7b0b1055b56683 Mon Sep 17 00:00:00 2001 From: obscuren Date: Thu, 10 Apr 2014 18:14:19 -0400 Subject: Added better address format --- ethchain/stack.go | 1 + ethchain/vm.go | 11 ++++++++++- ethchain/vm_test.go | 5 +++-- ethutil/parsing.go | 5 ++++- 4 files changed, 18 insertions(+), 4 deletions(-) diff --git a/ethchain/stack.go b/ethchain/stack.go index e3fc4b684..0dadd15e5 100644 --- a/ethchain/stack.go +++ b/ethchain/stack.go @@ -55,6 +55,7 @@ const ( // 0x50 range - 'storage' and execution oPUSH = 0x50 + oPUSH20 = 0x80 oPOP = 0x51 oDUP = 0x52 oSWAP = 0x53 diff --git a/ethchain/vm.go b/ethchain/vm.go index f94425d2d..dd99ee790 100644 --- a/ethchain/vm.go +++ b/ethchain/vm.go @@ -301,7 +301,6 @@ 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()) @@ -309,6 +308,16 @@ func (vm *Vm) RunClosure(closure *Closure) []byte { stack.Push(val) pc.Add(pc, big.NewInt(31)) + case oPUSH20: + pc.Add(pc, ethutil.Big1) + data := closure.Gets(pc, big.NewInt(20)) + val := ethutil.BigD(data.Bytes()) + + // Push value to stack + stack.Push(val) + + pc.Add(pc, big.NewInt(19)) + case oPOP: stack.Pop() case oDUP: diff --git a/ethchain/vm_test.go b/ethchain/vm_test.go index dc74422cc..923d3526c 100644 --- a/ethchain/vm_test.go +++ b/ethchain/vm_test.go @@ -114,12 +114,13 @@ func TestRun4(t *testing.T) { int8 ret = 0 int8 arg = 10 - call(938726394128221156290138488023434115948430767407, 0, 100000000, arg, ret) + addr address = "a46df28529eb8aa8b8c025b0b413c5f4b688352f" + call(address, 0, 100000000, arg, ret) `), false) if err != nil { fmt.Println(err) } - asm = append(asm, "LOG") + //asm = append(asm, "LOG") fmt.Println(asm) callerScript := ethutil.Assemble(asm...) diff --git a/ethutil/parsing.go b/ethutil/parsing.go index 0de396654..278414982 100644 --- a/ethutil/parsing.go +++ b/ethutil/parsing.go @@ -51,7 +51,10 @@ var OpCodes = map[string]byte{ "GASLIMIT": 0x45, // 0x50 range - 'storage' and execution - "PUSH": 0x50, + "PUSH": 0x50, + + "PUSH20": 0x80, + "POP": 0x51, "DUP": 0x52, "SWAP": 0x53, -- cgit From afc92fb7d799a4085d2256a7106ee9f7b9ea2f9e Mon Sep 17 00:00:00 2001 From: obscuren Date: Thu, 10 Apr 2014 18:32:54 -0400 Subject: Added better address format --- ethchain/vm_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ethchain/vm_test.go b/ethchain/vm_test.go index 923d3526c..55fb71dbe 100644 --- a/ethchain/vm_test.go +++ b/ethchain/vm_test.go @@ -120,7 +120,7 @@ func TestRun4(t *testing.T) { if err != nil { fmt.Println(err) } - //asm = append(asm, "LOG") + asm = append(asm, "LOG") fmt.Println(asm) callerScript := ethutil.Assemble(asm...) -- cgit From 25dd46061fc3b732056ea87fe4a9696e160179cc Mon Sep 17 00:00:00 2001 From: obscuren Date: Thu, 10 Apr 2014 21:03:14 -0400 Subject: Added push20 --- ethchain/stack.go | 2 +- ethchain/vm_test.go | 24 +++++++++++------------- 2 files changed, 12 insertions(+), 14 deletions(-) diff --git a/ethchain/stack.go b/ethchain/stack.go index 0dadd15e5..d475f2f8e 100644 --- a/ethchain/stack.go +++ b/ethchain/stack.go @@ -251,7 +251,7 @@ func (m *Memory) Print() { if len(m.store) > 0 { addr := 0 for i := 0; i+32 <= len(m.store); i += 32 { - fmt.Printf("%03d %v\n", addr, m.store[i:i+32]) + fmt.Printf("%03d: % x\n", addr, m.store[i:i+32]) addr++ } } else { diff --git a/ethchain/vm_test.go b/ethchain/vm_test.go index 55fb71dbe..4075dfbc6 100644 --- a/ethchain/vm_test.go +++ b/ethchain/vm_test.go @@ -98,24 +98,22 @@ func TestRun4(t *testing.T) { fmt.Printf("%x\n", addr) asm, err = mutan.Compile(strings.NewReader(` - int32 a = 10 - int32 b = 10 - if a == b { - int32 c = 10 - if c == 10 { - int32 d = 1000 - int32 e = 10 - } + // Check if there's any cash in the initial store + if store[1000] == 0 { + store[1000] = 10^20 } - store[0] = 20 - store[a] = 20 - store[b] = this.caller() + store[1001] = this.value() * 20 + store[this.origin()] = store[this.origin()] + 1000 + + if store[1001] > 20 { + store[1001] = 10^50 + } int8 ret = 0 int8 arg = 10 - addr address = "a46df28529eb8aa8b8c025b0b413c5f4b688352f" - call(address, 0, 100000000, arg, ret) + store[1002] = "a46df28529eb8aa8b8c025b0b413c5f4b688352f" + call(store[1002], 0, 100000000, arg, ret) `), false) if err != nil { fmt.Println(err) -- cgit