diff --git a/ethchain/closure.go b/ethchain/closure.go index e9cb2c8bc1..d1fac0f43b 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 f68dcf3677..113d067a43 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 95e46e41d5..7a2a762b29 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 b4b2177bfb..a6a02dc9f6 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 85ec4c6935..745005b099 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(),