From bf6693122de2e9940987fa2efcc862514f5d655f Mon Sep 17 00:00:00 2001 From: romanman Date: Sat, 7 Jun 2014 19:08:50 +0100 Subject: [PATCH] Contract Creation: + main sequence - no edge cases testeds --- .../org/ethereum/manager/WorldManager.java | 73 ++++++++++++++----- .../main/java/org/ethereum/vm/Program.java | 16 +++- .../java/org/ethereum/vm/ProgramResult.java | 13 ++++ .../src/main/java/org/ethereum/vm/VM.java | 10 ++- .../src/test/java/org/ethereum/vm/VMTest.java | 8 +- 5 files changed, 89 insertions(+), 31 deletions(-) diff --git a/ethereumj-core/src/main/java/org/ethereum/manager/WorldManager.java b/ethereumj-core/src/main/java/org/ethereum/manager/WorldManager.java index b4cf6666..8d2122bc 100644 --- a/ethereumj-core/src/main/java/org/ethereum/manager/WorldManager.java +++ b/ethereumj-core/src/main/java/org/ethereum/manager/WorldManager.java @@ -1,11 +1,14 @@ package org.ethereum.manager; +import io.netty.channel.AddressedEnvelope; import org.ethereum.core.AccountState; import org.ethereum.core.Block; import org.ethereum.core.Transaction; +import org.ethereum.crypto.HashUtil; import org.ethereum.db.Database; import org.ethereum.trie.Trie; import org.ethereum.vm.Program; +import org.ethereum.vm.ProgramResult; import org.ethereum.vm.VM; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -64,19 +67,23 @@ public class WorldManager { return; } + // 2. THE SIMPLE BALANCE CHANGE SHOULD HAPPEN ANYWAY + AccountState recieverState = null; - // 2. FIND OUT WHAT IS THE TRANSACTION TYPE + // Check if the receive is a new contract if (tx.isContractCreation()){ - // todo 0. run the init method + byte[] contractAddress= tx.getContractAddress(); + AccountState contractAccount = new AccountState(BigInteger.ZERO, BigInteger.valueOf(0)); + allAccountsState.update(contractAddress, contractAccount.getEncoded()); + recieverState = contractAccount; + stateLogger.info("New contract created address={}", + Hex.toHexString(contractAddress)); + } - VM vm = new VM(); - Program program = new Program(null, null); - - - } else{ - - AccountState recieverState; + // if reciver was not set by + // creation of contract + if (recieverState == null) { byte[] accountData = this.allAccountsState.get(tx.getReceiveAddress()); if (accountData.length == 0){ @@ -90,22 +97,48 @@ public class WorldManager { stateLogger.info("Account updated address={}", Hex.toHexString(tx.getReceiveAddress())); } + } - // APPLY THE BALANCE VALUE - recieverState.addToBalance(new BigInteger(1, tx.getValue())); - senderState.addToBalance(new BigInteger(1, tx.getValue()).negate()); + recieverState.addToBalance(new BigInteger(1, tx.getValue())); + senderState.addToBalance(new BigInteger(1, tx.getValue()).negate()); + + if (senderState.getBalance().compareTo(BigInteger.ZERO) == 1){ + + senderState.incrementNonce(); + allAccountsState.update(tx.getSender(), senderState.getEncoded()); + allAccountsState.update(tx.getReceiveAddress(), recieverState.getEncoded()); + } + + + + // 3. FIND OUT WHAT IS THE TRANSACTION TYPE + if (tx.isContractCreation()){ + + byte[] initCode = tx.getData(); + + VM vm = new VM(); + Program program = new Program(initCode, null); + vm.play(program); + + ProgramResult result = program.getResult(); + byte[] bodyCode = result.gethReturn().array(); + // todo: what if the body code is null , still submit ? + + // TODO: (!!!!!) ALL THE CHECKS FOR THE PROGRAM RESULT + + byte[] key = HashUtil.sha3(bodyCode); + chainDB.put(key, bodyCode); + + if (stateLogger.isInfoEnabled()) + stateLogger.info("saving code of the contract to the db: sha3(code)={} code={}", + Hex.toHexString(key), + Hex.toHexString(bodyCode)); + + } else{ // todo 2. check if the address is a contract, if it is perform contract call - - if (senderState.getBalance().compareTo(BigInteger.ZERO) == 1){ - - senderState.incrementNonce(); - allAccountsState.update(tx.getSender(), senderState.getEncoded()); - allAccountsState.update(tx.getReceiveAddress(), recieverState.getEncoded()); - } - } pendingTransactions.put(Hex.toHexString(tx.getHash()), tx); diff --git a/ethereumj-core/src/main/java/org/ethereum/vm/Program.java b/ethereumj-core/src/main/java/org/ethereum/vm/Program.java index 6ef5057e..c5f9275f 100644 --- a/ethereumj-core/src/main/java/org/ethereum/vm/Program.java +++ b/ethereumj-core/src/main/java/org/ethereum/vm/Program.java @@ -24,7 +24,7 @@ public class Program { Map storage = new HashMap(); ByteBuffer memory = null; - ByteBuffer hReturn = null; + ProgramResult result = new ProgramResult(); byte[] ops; int pc = 0; @@ -84,7 +84,7 @@ public class Program { } public void setHReturn(ByteBuffer buff){ - hReturn = buff; + result.setHReturn(buff.array()); } public void step(){ @@ -267,6 +267,14 @@ public class Program { } + public ProgramResult getResult() { + return result; + } + + public void setRuntimeFailure(RuntimeException e){ + result.setException(e); + } + public void fullTrace(){ // todo: add gas to full trace calc @@ -336,8 +344,8 @@ public class Program { global.append(" -- MEMORY -- ").append(memoryData).append("\n"); global.append(" -- STORAGE -- ").append(storageData).append("\n"); - if (hReturn != null){ - global.append("\n HReturn: ").append(Hex.toHexString(hReturn.array())); + if (result.gethReturn() != null){ + global.append("\n HReturn: ").append(Hex.toHexString(result.gethReturn().array())); } if (listener != null){ diff --git a/ethereumj-core/src/main/java/org/ethereum/vm/ProgramResult.java b/ethereumj-core/src/main/java/org/ethereum/vm/ProgramResult.java index 26be9660..0d85b8f1 100644 --- a/ethereumj-core/src/main/java/org/ethereum/vm/ProgramResult.java +++ b/ethereumj-core/src/main/java/org/ethereum/vm/ProgramResult.java @@ -12,6 +12,7 @@ public class ProgramResult { private int gasUsed = 0; private ByteBuffer hReturn = null; + private RuntimeException exception; public void spendGas(int gas){ gasUsed += gas; @@ -23,5 +24,17 @@ public class ProgramResult { this.hReturn.put(hReturn); } + public ByteBuffer gethReturn() { + return hReturn; + } + + public RuntimeException getException() { + return exception; + } + + public void setException(RuntimeException exception) { + this.exception = exception; + } + } diff --git a/ethereumj-core/src/main/java/org/ethereum/vm/VM.java b/ethereumj-core/src/main/java/org/ethereum/vm/VM.java index 93e3d04b..b515ffbe 100644 --- a/ethereumj-core/src/main/java/org/ethereum/vm/VM.java +++ b/ethereumj-core/src/main/java/org/ethereum/vm/VM.java @@ -556,7 +556,7 @@ public class VM { DataWord size = program.stackPop(); ByteBuffer hReturn = program.memoryChunk(offset, size); - program.hReturn = hReturn; + program.setHReturn(hReturn); program.step(); program.stop(); @@ -585,8 +585,12 @@ public class VM { public void play(Program program){ - while(!program.isStopped()) - this.step(program); + try { + while(!program.isStopped()) + this.step(program); + } catch (RuntimeException e) { + program.setRuntimeFailure(e); + } } diff --git a/ethereumj-core/src/test/java/org/ethereum/vm/VMTest.java b/ethereumj-core/src/test/java/org/ethereum/vm/VMTest.java index df78b95f..acc7f1d5 100644 --- a/ethereumj-core/src/test/java/org/ethereum/vm/VMTest.java +++ b/ethereumj-core/src/test/java/org/ethereum/vm/VMTest.java @@ -2141,7 +2141,7 @@ public class VMTest { vm.step(program); vm.step(program); - assertEquals(s_expected_1, Hex.toHexString(program.hReturn.array()).toUpperCase()); + assertEquals(s_expected_1, Hex.toHexString(program.getResult().gethReturn().array()).toUpperCase()); assertTrue(program.stopped); } @@ -2160,7 +2160,7 @@ public class VMTest { vm.step(program); vm.step(program); - assertEquals(s_expected_1, Hex.toHexString(program.hReturn.array()).toUpperCase()); + assertEquals(s_expected_1, Hex.toHexString(program.getResult().gethReturn().array()).toUpperCase()); assertTrue(program.stopped); } @@ -2180,7 +2180,7 @@ public class VMTest { vm.step(program); vm.step(program); - assertEquals(s_expected_1, Hex.toHexString(program.hReturn.array()).toUpperCase()); + assertEquals(s_expected_1, Hex.toHexString(program.getResult().gethReturn().array()).toUpperCase()); assertTrue(program.stopped); } @@ -2201,7 +2201,7 @@ public class VMTest { vm.step(program); vm.step(program); - assertEquals(s_expected_1, Hex.toHexString(program.hReturn.array()).toUpperCase()); + assertEquals(s_expected_1, Hex.toHexString(program.getResult().gethReturn().array()).toUpperCase()); assertTrue(program.stopped); }