diff --git a/ethchain/state_manager.go b/ethchain/state_manager.go index 4f009b6d34..2d2a32e2fe 100644 --- a/ethchain/state_manager.go +++ b/ethchain/state_manager.go @@ -120,16 +120,27 @@ func (sm *StateManager) ApplyTransactions(state *State, block *Block, txs []*Tra } func (sm *StateManager) ApplyTransaction(state *State, block *Block, tx *Transaction) (*big.Int, error) { - // If there's no recipient, it's a contract - // Check if this is a contract creation traction and if so - // create a contract of this tx. - // TODO COMMENT THIS SECTION + /* + Applies transactions to the given state and creates new + state objects where needed. + + If said objects needs to be created + run the initialization script provided by the transaction and + assume there's a return value. The return value will be set to + the script section of the state object. + */ totalGasUsed := big.NewInt(0) - if tx.IsContract() { - err := sm.Ethereum.TxPool().ProcessTransaction(tx, state, false) + // Apply the transaction to the current state + err := sm.Ethereum.TxPool().ProcessTransaction(tx, state, false) + if tx.CreatesContract() { if err == nil { + // Create a new state object and the transaction + // as it's data provider. contract := sm.MakeStateObject(state, tx) if contract != nil { + // Evaluate the initialization script + // and use the return value as the + // script section for the state object. script, err := sm.EvalScript(state, contract.Init(), contract, tx, block) if err != nil { return nil, fmt.Errorf("[STATE] Error during init script run %v", err) @@ -143,10 +154,11 @@ func (sm *StateManager) ApplyTransaction(state *State, block *Block, tx *Transac return nil, fmt.Errorf("[STATE] contract creation tx:", err) } } else { - err := sm.Ethereum.TxPool().ProcessTransaction(tx, state, false) - contract := state.GetStateObject(tx.Recipient) - if err == nil && contract != nil && len(contract.Script()) > 0 { - sm.EvalScript(state, contract.Script(), contract, tx, block) + // Find the state object at the "recipient" address. If + // there's an object attempt to run the script. + stateObject := state.GetStateObject(tx.Recipient) + if err == nil && stateObject != nil && len(stateObject.Script()) > 0 { + sm.EvalScript(state, stateObject.Script(), stateObject, tx, block) } else if err != nil { return nil, fmt.Errorf("[STATE] process:", err) } diff --git a/ethchain/transaction.go b/ethchain/transaction.go index 25d63879bd..2c5615f991 100644 --- a/ethchain/transaction.go +++ b/ethchain/transaction.go @@ -57,10 +57,15 @@ func (tx *Transaction) Hash() []byte { return ethutil.Sha3Bin(ethutil.NewValue(data).Encode()) } -func (tx *Transaction) IsContract() bool { +func (tx *Transaction) CreatesContract() bool { return tx.contractCreation } +/* Depricated */ +func (tx *Transaction) IsContract() bool { + return tx.CreatesContract() +} + func (tx *Transaction) CreationAddress() []byte { return ethutil.Sha3Bin(ethutil.NewValue([]interface{}{tx.Sender(), tx.Nonce}).Encode())[12:] } @@ -139,6 +144,9 @@ func (tx *Transaction) RlpValueDecode(decoder *ethutil.Value) { tx.v = byte(decoder.Get(6).Uint()) tx.r = decoder.Get(7).Bytes() tx.s = decoder.Get(8).Bytes() + if len(tx.Recipient) == 0 { + tx.contractCreation = true + } /* // If the list is of length 10 it's a contract creation tx @@ -173,7 +181,7 @@ func (tx *Transaction) String() string { S: 0x%x `, tx.Hash(), - len(tx.Recipient) == 1, + len(tx.Recipient) == 0, tx.Sender(), tx.Recipient, tx.Nonce, diff --git a/ethchain/vm_test.go b/ethchain/vm_test.go index 2ec70536aa..520f9a2ed7 100644 --- a/ethchain/vm_test.go +++ b/ethchain/vm_test.go @@ -1,6 +1,5 @@ package ethchain -/* import ( _ "bytes" "fmt" @@ -13,60 +12,33 @@ import ( ) func TestRun4(t *testing.T) { - ethutil.ReadConfig("", ethutil.LogStd) + ethutil.ReadConfig("", ethutil.LogStd, "") db, _ := ethdb.NewMemDatabase() state := NewState(ethutil.NewTrie(db, "")) - script, err := mutan.Compile(strings.NewReader(` - int32 a = 10 - int32 b = 20 - if a > b { - int32 c = this.caller() - } - exit() - `), false) - tx := NewContractCreationTx(ethutil.Big("0"), ethutil.Big("1000"), ethutil.Big("100"), script, nil) - tx.Sign(ContractAddr) - addr := tx.CreationAddress() - contract := MakeContract(tx, state) - state.UpdateStateObject(contract) - fmt.Printf("%x\n", addr) - callerScript, err := mutan.Compile(strings.NewReader(` - // Check if there's any cash in the initial store - if this.store[1000] == 0 { - this.store[1000] = 10**20 - } - - - this.store[1001] = this.value() * 20 - this.store[this.origin()] = this.store[this.origin()] + 1000 - - if this.store[1001] > 20 { - this.store[1001] = 10^50 - } - - int8 ret = 0 - int8 arg = 10 - call(0xe6a12555fad1fb6eaaaed69001a87313d1fd7b54, 0, 100, arg, ret) - - big t - for int8 i = 0; i < 10; i++ { - t = i - } - - if 10 > 20 { - int8 shouldnt = 2 - } else { - int8 should = 1 + this.store[this.origin()] = 10**20 + hello := "world" + + return lambda { + big to = this.data[0] + big from = this.origin() + big value = this.data[1] + + if this.store[from] >= value { + this.store[from] = this.store[from] - value + this.store[to] = this.store[to] + value } + } `), false) if err != nil { fmt.Println(err) } + fmt.Println(Disassemble(callerScript)) - callerTx := NewContractCreationTx(ethutil.Big("0"), ethutil.Big("1000"), ethutil.Big("100"), callerScript, nil) + callerTx := NewContractCreationTx(ethutil.Big("0"), ethutil.Big("1000"), ethutil.Big("100"), callerScript) + callerTx.Sign([]byte("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")) // Contract addr as test address gas := big.NewInt(1000) @@ -79,7 +51,7 @@ func TestRun4(t *testing.T) { fmt.Println(err) } fmt.Println("account.Amount =", account.Amount) - callerClosure := NewClosure(account, c, c.script, state, gas, gasPrice) + callerClosure := NewClosure(account, c, callerScript, state, gas, gasPrice) vm := NewVm(state, nil, RuntimeVars{ Origin: account.Address(), @@ -89,10 +61,10 @@ func TestRun4(t *testing.T) { Time: 1, Diff: big.NewInt(256), }) - _, e = callerClosure.Call(vm, nil, nil) + var ret []byte + ret, e = callerClosure.Call(vm, nil, nil) if e != nil { fmt.Println("error", e) } - fmt.Println("account.Amount =", account.Amount) + fmt.Println(ret) } -*/ diff --git a/ethpub/pub.go b/ethpub/pub.go index e726c66f36..b75d3abc85 100644 --- a/ethpub/pub.go +++ b/ethpub/pub.go @@ -87,14 +87,14 @@ func (lib *PEthereum) SecretToAddress(key string) string { } func (lib *PEthereum) Transact(key, recipient, valueStr, gasStr, gasPriceStr, dataStr string) (*PReceipt, error) { - return lib.createTx(key, recipient, valueStr, gasStr, gasPriceStr, dataStr, "") + return lib.createTx(key, recipient, valueStr, gasStr, gasPriceStr, dataStr) } -func (lib *PEthereum) Create(key, valueStr, gasStr, gasPriceStr, initStr, bodyStr string) (*PReceipt, error) { - return lib.createTx(key, "", valueStr, gasStr, gasPriceStr, initStr, bodyStr) +func (lib *PEthereum) Create(key, valueStr, gasStr, gasPriceStr, script string) (*PReceipt, error) { + return lib.createTx(key, "", valueStr, gasStr, gasPriceStr, script) } -func (lib *PEthereum) createTx(key, recipient, valueStr, gasStr, gasPriceStr, initStr, scriptStr string) (*PReceipt, error) { +func (lib *PEthereum) createTx(key, recipient, valueStr, gasStr, gasPriceStr, scriptStr string) (*PReceipt, error) { var hash []byte var contractCreation bool if len(recipient) == 0 { @@ -121,35 +121,47 @@ func (lib *PEthereum) createTx(key, recipient, valueStr, gasStr, gasPriceStr, in var tx *ethchain.Transaction // Compile and assemble the given data if contractCreation { - var initScript, mainScript []byte + /* + var initScript, mainScript []byte + var err error + if ethutil.IsHex(initStr) { + initScript = ethutil.FromHex(initStr[2:]) + } else { + initScript, err = ethutil.Compile(initStr) + if err != nil { + return nil, err + } + } + + if ethutil.IsHex(scriptStr) { + mainScript = ethutil.FromHex(scriptStr[2:]) + } else { + mainScript, err = ethutil.Compile(scriptStr) + if err != nil { + return nil, err + } + } + + script := ethchain.AppendScript(initScript, mainScript) + */ + var script []byte var err error - if ethutil.IsHex(initStr) { - initScript = ethutil.FromHex(initStr[2:]) - } else { - initScript, err = ethutil.Compile(initStr) - if err != nil { - return nil, err - } - } - if ethutil.IsHex(scriptStr) { - mainScript = ethutil.FromHex(scriptStr[2:]) + script = ethutil.FromHex(scriptStr) } else { - mainScript, err = ethutil.Compile(scriptStr) + script, err = ethutil.Compile(scriptStr) if err != nil { return nil, err } } - script := ethchain.AppendScript(initScript, mainScript) - tx = ethchain.NewContractCreationTx(value, gas, gasPrice, script) } else { // Just in case it was submitted as a 0x prefixed string - if len(initStr) > 0 && initStr[0:2] == "0x" { - initStr = initStr[2:len(initStr)] + if len(scriptStr) > 0 && scriptStr[0:2] == "0x" { + scriptStr = scriptStr[2:len(scriptStr)] } - tx = ethchain.NewTransactionMessage(hash, value, gas, gasPrice, ethutil.FromHex(initStr)) + tx = ethchain.NewTransactionMessage(hash, value, gas, gasPrice, ethutil.FromHex(scriptStr)) } acc := lib.stateManager.TransState().GetStateObject(keyPair.Address()) diff --git a/ethrpc/packages.go b/ethrpc/packages.go index 87cfc99b2d..1c4fb99f6f 100644 --- a/ethrpc/packages.go +++ b/ethrpc/packages.go @@ -137,7 +137,7 @@ func (p *EthereumApi) Create(args *NewTxArgs, reply *string) error { if err != nil { return err } - result, _ := p.ethp.Create(p.ethp.GetKey().PrivateKey, args.Value, args.Gas, args.GasPrice, args.Init, args.Body) + result, _ := p.ethp.Create(p.ethp.GetKey().PrivateKey, args.Value, args.Gas, args.GasPrice, args.Body) *reply = NewSuccessRes(result) return nil }