From f7a264b0a8b635a459b3e67fd856e1659c723279 Mon Sep 17 00:00:00 2001 From: romanman Date: Tue, 17 Jun 2014 16:35:11 +0100 Subject: [PATCH] VMComplexTest introduced --- .../org/ethereum/gui/ContractCallDialog.java | 4 - .../main/java/org/ethereum/gui/ToolBar.java | 8 +- .../org/ethereum/manager/WorldManager.java | 2 +- .../org/ethereum/net/client/PeerData.java | 3 +- .../main/java/org/ethereum/vm/Program.java | 49 ++++---- .../java/org/ethereum/vm/ProgramInvoke.java | 2 + .../org/ethereum/vm/ProgramInvokeImpl.java | 62 ++++++++++ .../src/main/java/org/ethereum/vm/VM.java | 23 ++-- .../src/main/resources/system.properties | 23 ++-- .../ethereum/vm/ProgramInvokeMockImpl.java | 48 ++++++-- .../java/org/ethereum/vm/VMComplexTest.java | 107 ++++++++++++++++++ .../src/test/java/org/ethereum/vm/VMTest.java | 2 +- .../src/test/resources/log4j.properties | 23 ++++ .../src/test/resources/system.properties | 89 +++++++++++++++ 14 files changed, 386 insertions(+), 59 deletions(-) create mode 100644 ethereumj-core/src/test/java/org/ethereum/vm/VMComplexTest.java create mode 100644 ethereumj-core/src/test/resources/log4j.properties create mode 100644 ethereumj-core/src/test/resources/system.properties diff --git a/ethereumj-core/src/main/java/org/ethereum/gui/ContractCallDialog.java b/ethereumj-core/src/main/java/org/ethereum/gui/ContractCallDialog.java index 099bec17..a3d6b079 100644 --- a/ethereumj-core/src/main/java/org/ethereum/gui/ContractCallDialog.java +++ b/ethereumj-core/src/main/java/org/ethereum/gui/ContractCallDialog.java @@ -1,6 +1,5 @@ package org.ethereum.gui; -import com.sun.javafx.binding.StringFormatter; import org.ethereum.core.Account; import org.ethereum.core.AccountState; import org.ethereum.core.ContractDetails; @@ -19,13 +18,10 @@ import org.spongycastle.util.encoders.Hex; import javax.swing.*; import javax.swing.border.Border; import javax.swing.border.EtchedBorder; -import javax.swing.border.TitledBorder; import javax.swing.plaf.ComboBoxUI; import javax.swing.plaf.basic.BasicComboBoxUI; import javax.swing.plaf.basic.BasicComboPopup; import javax.swing.table.DefaultTableModel; -import javax.swing.table.TableModel; - import java.awt.*; import java.awt.event.*; import java.math.BigInteger; diff --git a/ethereumj-core/src/main/java/org/ethereum/gui/ToolBar.java b/ethereumj-core/src/main/java/org/ethereum/gui/ToolBar.java index c962fa19..fed3371a 100644 --- a/ethereumj-core/src/main/java/org/ethereum/gui/ToolBar.java +++ b/ethereumj-core/src/main/java/org/ethereum/gui/ToolBar.java @@ -39,10 +39,10 @@ public class ToolBar extends JFrame { public ToolBar() throws HeadlessException { introLogger.info(""); - introLogger.info("<> EthereumJ [v0.5.1] by RomanJ"); - introLogger.info("<> Code by Roman Mandeleil, (c) 2014."); - introLogger.info("<> Contribution: Nick Savers "); - introLogger.info("<> Based on a design by Vitalik Buterin."); + introLogger.info("|Ξ| EthereumJ [v0.5.1] by RomanJ"); + introLogger.info("|Ξ| Code by Roman Mandeleil, (c) 2014."); + introLogger.info("|Ξ| Contribution: Nick Savers "); + introLogger.info("|Ξ| Based on a design by Vitalik Buterin."); introLogger.info(""); introLogger.info("java.version: " + System.getProperty("java.version")); introLogger.info("java.home: " + System.getProperty("java.home")); 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 8d9fb743..d0382e25 100644 --- a/ethereumj-core/src/main/java/org/ethereum/manager/WorldManager.java +++ b/ethereumj-core/src/main/java/org/ethereum/manager/WorldManager.java @@ -76,7 +76,7 @@ public class WorldManager { public void applyTransaction(Transaction tx) { - // TODO: refactor the wallet transactions to the world manager + // TODO: refactor the wallet pending transactions to the world manager if (blockChain != null) blockChain.addWalletTransaction(tx); diff --git a/ethereumj-core/src/main/java/org/ethereum/net/client/PeerData.java b/ethereumj-core/src/main/java/org/ethereum/net/client/PeerData.java index 401386cc..fbbb20cd 100644 --- a/ethereumj-core/src/main/java/org/ethereum/net/client/PeerData.java +++ b/ethereumj-core/src/main/java/org/ethereum/net/client/PeerData.java @@ -66,7 +66,8 @@ public class PeerData { @Override public String toString() { - return "Peer: [ip=" + getInetAddress().getHostAddress() + ", port=" + getPort() + ", peerId=" + Hex.toHexString(getPeerId()) + "]"; + return "Peer: [ip=" + getInetAddress().getHostAddress() + ", port=" + getPort() + + ", peerId=" + (getPeerId() == null ? "": Hex.toHexString(getPeerId())) + "]"; } @Override 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 0e4da1ba..753bcae2 100644 --- a/ethereumj-core/src/main/java/org/ethereum/vm/Program.java +++ b/ethereumj-core/src/main/java/org/ethereum/vm/Program.java @@ -21,6 +21,7 @@ import java.util.*; public class Program { private Logger logger = LoggerFactory.getLogger("VM"); + private Logger gasLogger = null; ProgramListener listener; Stack stack = new Stack(); @@ -38,6 +39,8 @@ public class Program { public Program(byte[] ops, ProgramInvoke invokeData) { + gasLogger = LoggerFactory.getLogger("gas - " + invokeData.hashCode()); + result.setStateDb(invokeData.getStateDb()); result.setChainDb(invokeData.getChainDb()); result.setDetailDB(invokeData.getDetaildDB()); @@ -47,8 +50,14 @@ public class Program { this.invokeData = invokeData; this.ops = ops; - spendGas(GasCost.TRANSACTION); - spendGas(GasCost.TXDATA * invokeData.getDataSize().intValue()); + // In case the program invoked by wire got + // transaction, this will be the gas cost, + // otherwise the call done by other contract + // charged by CALL op + if (invokeData.byTransaction()){ + spendGas(GasCost.TRANSACTION, "TRANSACTION"); + spendGas(GasCost.TXDATA * invokeData.getDataSize().intValue(), "DATA"); + } if (invokeData.getStorage() != null){ storage = invokeData.getStorage(); @@ -220,13 +229,13 @@ public class Program { * That method implement internal calls * and code invocations * - * @param gas - * @param toAddressDW - * @param endowmentValue - * @param inDataOffs - * @param inDataSize - * @param outDataOffs - * @param outDataSize + * @param gas - gas to pay for the call, remain gas will be refunded to the caller + * @param toAddressDW - address to call + * @param endowmentValue - the value that can be transfer along with the code execution + * @param inDataOffs - start of memory to be input data to the call + * @param inDataSize - size of memory to be input data to the call + * @param outDataOffs - start of memory to be output of the call + * @param outDataSize - size of memory to be output data to the call */ public void callToAddress(DataWord gas, DataWord toAddressDW, DataWord endowmentValue, DataWord inDataOffs, DataWord inDataSize,DataWord outDataOffs, DataWord outDataSize){ @@ -252,11 +261,6 @@ public class Program { receiverState = new AccountState(accountData); } - // todo: endowment rollbacked move it from here - receiverState.addToBalance(endowmentValue.value()); - result.getStateDb().update(toAddress, receiverState.getEncoded()); - // todo: endowment rollbacked move it from here - byte[] programCode = result.getChainDb().get(receiverState.getCodeHash()); if (programCode != null && programCode.length != 0){ @@ -285,7 +289,6 @@ public class Program { return; } - // 2.2 UPDATE THE NONCE // (THIS STAGE IS NOT REVERTED BY ANY EXCEPTION) senderState.incrementNonce(); @@ -298,14 +301,17 @@ public class Program { chainDB.startTrack(); stateDB.startTrack(); - // todo: update the balance/value simple transfer + // todo: check if the endowment can really be done + receiverState.addToBalance(endowmentValue.value()); + stateDB.update(toAddress, receiverState.getEncoded()); Map storage = null; if (details != null) storage = details.getStorage(); ProgramInvoke programInvoke = - ProgramInvokeFactory.createProgramInvoke(this, toAddressDW, storage, endowmentValue, gas,receiverState.getBalance(), + ProgramInvokeFactory.createProgramInvoke(this, toAddressDW, storage, + endowmentValue, gas, receiverState.getBalance(), data.array(), detailDB, chainDB, stateDB); @@ -326,7 +332,8 @@ public class Program { } // todo: apply results: result.gethReturn() - // todo: refund for remain gas + // todo: if there is out specified place hReturn on the out + detailDB.commitTrack(); chainDB.commitTrack(); @@ -334,7 +341,7 @@ public class Program { stackPush(new DataWord(1)); // the gas spent in any internal outcome - spendGas(result.getGasUsed()); + spendGas(result.getGasUsed(), " 'Total for CALL run' "); logger.info("The usage of the gas in external call updated", result.getGasUsed()); // update the storage , it could @@ -348,7 +355,9 @@ public class Program { } - public void spendGas(int gasValue){ + public void spendGas(int gasValue, String cause){ + + gasLogger.info("Spent: for cause={} gas={}", cause, gasValue); long afterSpend = invokeData.getGas().longValue() - gasValue - result.getGasUsed(); if (afterSpend < 0) diff --git a/ethereumj-core/src/main/java/org/ethereum/vm/ProgramInvoke.java b/ethereumj-core/src/main/java/org/ethereum/vm/ProgramInvoke.java index 0ee7faad..fad8a278 100644 --- a/ethereumj-core/src/main/java/org/ethereum/vm/ProgramInvoke.java +++ b/ethereumj-core/src/main/java/org/ethereum/vm/ProgramInvoke.java @@ -38,5 +38,7 @@ public interface ProgramInvoke { public TrackDatabase getChainDb(); public TrackTrie getStateDb(); + public boolean byTransaction(); + } diff --git a/ethereumj-core/src/main/java/org/ethereum/vm/ProgramInvokeImpl.java b/ethereumj-core/src/main/java/org/ethereum/vm/ProgramInvokeImpl.java index ab09ffbe..183eaf8b 100644 --- a/ethereumj-core/src/main/java/org/ethereum/vm/ProgramInvokeImpl.java +++ b/ethereumj-core/src/main/java/org/ethereum/vm/ProgramInvokeImpl.java @@ -4,6 +4,7 @@ import org.ethereum.db.TrackDatabase; import org.ethereum.trie.TrackTrie; import org.ethereum.util.ByteUtil; +import java.util.Arrays; import java.util.Map; /** @@ -38,6 +39,7 @@ public class ProgramInvokeImpl implements ProgramInvoke { TrackDatabase detaildDB; TrackDatabase chainDb; TrackTrie stateDb; + private boolean byTransaction = true; public ProgramInvokeImpl(DataWord address, DataWord origin, DataWord caller, DataWord balance, DataWord gasPrice, DataWord gas, DataWord callValue, byte[] msgData, @@ -68,6 +70,7 @@ public class ProgramInvokeImpl implements ProgramInvoke { this.detaildDB = detaildDB; this.chainDb = chainDb; this.stateDb = stateDB; + this.byTransaction = false; } @@ -234,4 +237,63 @@ public class ProgramInvokeImpl implements ProgramInvoke { public TrackTrie getStateDb() { return stateDb; } + + @Override + public boolean byTransaction() { + return byTransaction; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + ProgramInvokeImpl that = (ProgramInvokeImpl) o; + + if (byTransaction != that.byTransaction) return false; + if (address != null ? !address.equals(that.address) : that.address != null) return false; + if (balance != null ? !balance.equals(that.balance) : that.balance != null) return false; + if (callValue != null ? !callValue.equals(that.callValue) : that.callValue != null) return false; + if (caller != null ? !caller.equals(that.caller) : that.caller != null) return false; + if (chainDb != null ? !chainDb.equals(that.chainDb) : that.chainDb != null) return false; + if (coinbase != null ? !coinbase.equals(that.coinbase) : that.coinbase != null) return false; + if (detaildDB != null ? !detaildDB.equals(that.detaildDB) : that.detaildDB != null) return false; + if (difficulty != null ? !difficulty.equals(that.difficulty) : that.difficulty != null) return false; + if (gas != null ? !gas.equals(that.gas) : that.gas != null) return false; + if (gasPrice != null ? !gasPrice.equals(that.gasPrice) : that.gasPrice != null) return false; + if (gaslimit != null ? !gaslimit.equals(that.gaslimit) : that.gaslimit != null) return false; + if (!Arrays.equals(msgData, that.msgData)) return false; + if (number != null ? !number.equals(that.number) : that.number != null) return false; + if (origin != null ? !origin.equals(that.origin) : that.origin != null) return false; + if (prevHash != null ? !prevHash.equals(that.prevHash) : that.prevHash != null) return false; + if (stateDb != null ? !stateDb.equals(that.stateDb) : that.stateDb != null) return false; + if (storage != null ? !storage.equals(that.storage) : that.storage != null) return false; + if (timestamp != null ? !timestamp.equals(that.timestamp) : that.timestamp != null) return false; + + return true; + } + + @Override + public int hashCode() { + int result = address != null ? address.hashCode() : 0; + result = 31 * result + (origin != null ? origin.hashCode() : 0); + result = 31 * result + (caller != null ? caller.hashCode() : 0); + result = 31 * result + (balance != null ? balance.hashCode() : 0); + result = 31 * result + (gas != null ? gas.hashCode() : 0); + result = 31 * result + (gasPrice != null ? gasPrice.hashCode() : 0); + result = 31 * result + (callValue != null ? callValue.hashCode() : 0); + result = 31 * result + (msgData != null ? Arrays.hashCode(msgData) : 0); + result = 31 * result + (prevHash != null ? prevHash.hashCode() : 0); + result = 31 * result + (coinbase != null ? coinbase.hashCode() : 0); + result = 31 * result + (timestamp != null ? timestamp.hashCode() : 0); + result = 31 * result + (number != null ? number.hashCode() : 0); + result = 31 * result + (difficulty != null ? difficulty.hashCode() : 0); + result = 31 * result + (gaslimit != null ? gaslimit.hashCode() : 0); + result = 31 * result + (storage != null ? storage.hashCode() : 0); + result = 31 * result + (detaildDB != null ? detaildDB.hashCode() : 0); + result = 31 * result + (chainDb != null ? chainDb.hashCode() : 0); + result = 31 * result + (stateDb != null ? stateDb.hashCode() : 0); + result = 31 * result + (byTransaction ? 1 : 0); + return result; + } } 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 c7a2a292..07f58717 100644 --- a/ethereumj-core/src/main/java/org/ethereum/vm/VM.java +++ b/ethereumj-core/src/main/java/org/ethereum/vm/VM.java @@ -65,24 +65,24 @@ public class VM { switch (OpCode.code(op)) { case SHA3: - program.spendGas(GasCost.SHA3); + program.spendGas(GasCost.SHA3, OpCode.code(op).name()); break; case SLOAD: - program.spendGas(GasCost.SLOAD); + program.spendGas(GasCost.SLOAD, OpCode.code(op).name()); break; case SSTORE: break; case BALANCE: - program.spendGas(GasCost.BALANCE); + program.spendGas(GasCost.BALANCE, OpCode.code(op).name()); break; case CREATE: - program.spendGas(GasCost.CREATE); + program.spendGas(GasCost.CREATE, OpCode.code(op).name()); break; case CALL: - program.spendGas(GasCost.CALL); + program.spendGas(GasCost.CALL, OpCode.code(op).name()); break; default: - program.spendGas(GasCost.STEP); + program.spendGas(GasCost.STEP, OpCode.code(op).name()); break; } @@ -458,11 +458,11 @@ public class VM { DataWord oldValue = program.storageLoad(addr); program.storageSave(addr, value); if (oldValue == null && !value.isZero()){ - program.spendGas(GasCost.SSTORE * 2); + program.spendGas(GasCost.SSTORE * 2, OpCode.code(op).name()); } else if (oldValue != null && value.isZero()){ - program.spendGas(GasCost.SSTORE * 0); + program.spendGas(GasCost.SSTORE * 0, OpCode.code(op).name()); } else - program.spendGas(GasCost.SSTORE); + program.spendGas(GasCost.SSTORE, OpCode.code(op).name()); program.step(); } break; case JUMP:{ @@ -554,7 +554,10 @@ public class VM { // memory gas calc int newMemSize = program.getMemSize(); - program.spendGas(GasCost.MEMORY * (newMemSize - oldMemSize) /32); + int memoryUsage = (newMemSize - oldMemSize) /32; + + if (memoryUsage > 0) + program.spendGas(GasCost.MEMORY * memoryUsage, OpCode.code(op).name()); program.fullTrace(); } catch (RuntimeException e) { diff --git a/ethereumj-core/src/main/resources/system.properties b/ethereumj-core/src/main/resources/system.properties index 431a3648..a2af0702 100644 --- a/ethereumj-core/src/main/resources/system.properties +++ b/ethereumj-core/src/main/resources/system.properties @@ -5,8 +5,9 @@ server.acceptConnections = false # one default access point to start # discover the network e.g. ip: [54.201.28.117] port: [30303] # Peer Server Zero: peer discovery -peer.discovery.ip = 54.201.28.117 +peer.discovery.ip = 54.72.69.180 peer.discovery.port = 30303 + # Peer Server One: peer discovery #peer.discovery.ip = 54.204.10.41 @@ -16,21 +17,25 @@ peer.discovery.port = 30303 # that is the peer through # we get the chain: [54.201.28.117] port: [30303] # ZeroGox -peer.active.ip = 54.204.10.41 -peer.active.port = 30303 +#peer.active.ip = 54.204.10.41 +#peer.active.port = 30303 # Some dude in Canada #peer.active.ip = 131.104.247.135 #peer.active.port = 30303 # Nick -#peer.active.ip = 82.217.72.169 +#peer.active.ip = 82.217.72.169 #peer.active.port = 30303 # RomanJ general -#peer.active.ip = 54.211.14.10 -#peer.active.port = 50505 +peer.active.ip = 54.211.14.10 +peer.active.port = 30303 + + #poc5.testnet.ethereum.org +#peer.active.ip = 54.72.69.180 +#peer.active.port = 30303 #peer.active.ip = 151.64.223.120 #peer.active.port = 30304 @@ -48,7 +53,7 @@ peer.discovery = true # number of workers that # tastes the peers for being # online [1..10] -peer.discovery.workers = 5 +peer.discovery.workers = 15 # connection timeout for trying to # connect to a peer [seconds] @@ -59,13 +64,13 @@ peer.discovery.timeout = 2 # transaction got approved when # include into a transactions msg # retrieved from the peer [seconds] -transaction.approve.timeout = 360 +transaction.approve.timeout = 15 # the parameter specifies how much # time the active peer will wait # for a message to come before kill # the channel -active.peer.channel.timeout = 360 +active.peer.channel.timeout = 15 # default directory where we keep # basic Serpent samples relative diff --git a/ethereumj-core/src/test/java/org/ethereum/vm/ProgramInvokeMockImpl.java b/ethereumj-core/src/test/java/org/ethereum/vm/ProgramInvokeMockImpl.java index 636d09cf..3e7ffebb 100644 --- a/ethereumj-core/src/test/java/org/ethereum/vm/ProgramInvokeMockImpl.java +++ b/ethereumj-core/src/test/java/org/ethereum/vm/ProgramInvokeMockImpl.java @@ -1,8 +1,10 @@ package org.ethereum.vm; +import org.ethereum.core.ContractDetails; import org.ethereum.crypto.ECKey; import org.ethereum.crypto.HashUtil; import org.ethereum.db.TrackDatabase; +import org.ethereum.manager.WorldManager; import org.ethereum.trie.TrackTrie; import org.spongycastle.util.encoders.Hex; @@ -18,6 +20,13 @@ public class ProgramInvokeMockImpl implements ProgramInvoke { byte[] msgData; + TrackTrie stateDB = null; + TrackDatabase chainDb = null; + TrackDatabase detaildDB = null; + + ContractDetails details = null; + + public ProgramInvokeMockImpl(byte[] msgDataRaw){ this.msgData = msgDataRaw; @@ -29,9 +38,7 @@ public class ProgramInvokeMockImpl implements ProgramInvoke { /* ADDRESS op */ public DataWord getOwnerAddress(){ - byte[] cowPrivKey = HashUtil.sha3("cow".getBytes()); - byte[] addr = ECKey.fromPrivate(cowPrivKey).getAddress(); - + byte[] addr = Hex.decode("77045e71a7a2c50903d88e564cd72fab11e82051"); return new DataWord(addr); } @@ -69,7 +76,7 @@ public class ProgramInvokeMockImpl implements ProgramInvoke { /* GAS op */ public DataWord getGas() { - byte[] minGasPrice = Hex.decode("03E8"); + byte[] minGasPrice = Hex.decode("0F4240"); return new DataWord(minGasPrice); } @@ -159,27 +166,50 @@ public class ProgramInvokeMockImpl implements ProgramInvoke { @Override public DataWord getGaslimit() { - long gasLimit = 968269; + long gasLimit = 1000000; return new DataWord(gasLimit); } + + public void setStateDB(TrackTrie stateDB) { + this.stateDB = stateDB; + } + + public void setChainDb(TrackDatabase chainDb) { + this.chainDb = chainDb; + } + + public void setDetaildDB(TrackDatabase detaildDB) { + this.detaildDB = detaildDB; + } + + public void setDetails(ContractDetails details) { + this.details = details; + } + @Override public Map getStorage() { - return null; + if (details == null) return null; + return details.getStorage(); } @Override public TrackDatabase getDetaildDB() { - return null; + return detaildDB; } @Override public TrackDatabase getChainDb() { - return null; + return chainDb; } @Override public TrackTrie getStateDb() { - return null; + return stateDB; + } + + @Override + public boolean byTransaction() { + return true; } } diff --git a/ethereumj-core/src/test/java/org/ethereum/vm/VMComplexTest.java b/ethereumj-core/src/test/java/org/ethereum/vm/VMComplexTest.java new file mode 100644 index 00000000..11db75a3 --- /dev/null +++ b/ethereumj-core/src/test/java/org/ethereum/vm/VMComplexTest.java @@ -0,0 +1,107 @@ +package org.ethereum.vm; + +import org.ethereum.core.AccountState; +import org.ethereum.core.ContractDetails; +import org.ethereum.crypto.HashUtil; +import org.ethereum.db.TrackDatabase; +import org.ethereum.manager.WorldManager; +import org.ethereum.trie.TrackTrie; +import org.junit.Test; +import org.spongycastle.util.encoders.Hex; + +import java.math.BigInteger; +import java.util.HashMap; + +/** + * www.ethereumJ.com + * + * @author: Roman Mandeleil + * Created on: 16/06/2014 10:37 + */ + +public class VMComplexTest { + + + @Test // contract call recursive + public void test1(){ + +/** + * #The code will run + * ------------------ + + a = contract.storage[999] + if a > 0: + contract.storage[999] = a - 1 + + # call to contract: 77045e71a7a2c50903d88e564cd72fab11e82051 + send((tx.gas / 10 * 8), 0x77045e71a7a2c50903d88e564cd72fab11e82051, 0) + else: + stop + */ + + DataWord key1 = new DataWord(999); + DataWord value1 = new DataWord(3); + + HashMap storage = new HashMap<>(); + storage.put(key1, value1); + + ContractDetails contractDetails = new ContractDetails(storage); + + + // Set contract into Database + String callerAddr = "cd2a3d9f938e13cd947ec05abc7fe734df8dd826"; + String contractAddr = "77045e71a7a2c50903d88e564cd72fab11e82051"; + String code = "6103e75660005460006000530b0f630000004b596001600053036103e757600060006000600060007377045e71a7a2c50903d88e564cd72fab11e820516008600a5c0402f1630000004c5800"; + + byte[] contractAddrB = Hex.decode(contractAddr); + byte[] callerAddrB = Hex.decode(callerAddr); + byte[] codeB = Hex.decode(code); + + byte[] codeKey = HashUtil.sha3(codeB); + AccountState accountState = new AccountState(); + accountState.setCodeHash(codeKey); + + AccountState callerAcountState = new AccountState(); + callerAcountState.addToBalance(new BigInteger("100000000000000000000")); + + WorldManager.instance.worldState.update(callerAddrB, callerAcountState.getEncoded()); + WorldManager.instance.worldState.update(contractAddrB, accountState.getEncoded()); + WorldManager.instance.chainDB.put(codeKey, codeB); + WorldManager.instance.detaildDB.put(contractAddrB, contractDetails.getEncoded()); + + TrackTrie stateDB = new TrackTrie(WorldManager.instance.worldState); + TrackDatabase chainDb = new TrackDatabase(WorldManager.instance.chainDB); + TrackDatabase detaildDB = new TrackDatabase(WorldManager.instance.detaildDB); + + ProgramInvokeMockImpl pi = new ProgramInvokeMockImpl(); + pi.setDetaildDB(detaildDB); + pi.setChainDb(chainDb); + pi.setStateDB(stateDB); + pi.setDetails(contractDetails); + + // Play the program + VM vm = new VM(); + Program program = new Program(codeB, pi); + + try { + while(!program.isStopped()) + vm.step(program); + } catch (RuntimeException e) { + program.setRuntimeFailure(e); + } + + + System.out.println("============ Results ============"); + AccountState as = + new AccountState(WorldManager.instance.worldState.get( + Hex.decode( contractAddr) )); + + System.out.println("*** Used gas: " + program.result.getGasUsed()); + System.out.println("*** Contract Balance: " + as.getBalance()); + + + + + + } +} 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 8bfd4205..75c92edf 100644 --- a/ethereumj-core/src/test/java/org/ethereum/vm/VMTest.java +++ b/ethereumj-core/src/test/java/org/ethereum/vm/VMTest.java @@ -2544,7 +2544,7 @@ public class VMTest { Program program = new Program(Hex.decode("30"), createProgramInvoke_1()); - String s_expected_1 = "000000000000000000000000CD2A3D9F938E13CD947EC05ABC7FE734DF8DD826"; + String s_expected_1 = "00000000000000000000000077045E71A7A2C50903D88E564CD72FAB11E82051"; vm.step(program); diff --git a/ethereumj-core/src/test/resources/log4j.properties b/ethereumj-core/src/test/resources/log4j.properties new file mode 100644 index 00000000..f2ac64fe --- /dev/null +++ b/ethereumj-core/src/test/resources/log4j.properties @@ -0,0 +1,23 @@ +# Root logger option +log4j.rootLogger=DEBUG, stdout + +# Direct log messages to stdout +log4j.appender.stdout=org.apache.log4j.ConsoleAppender +log4j.appender.stdout.Target=System.out +log4j.appender.stdout.layout=org.apache.log4j.PatternLayout +log4j.appender.stdout.layout.ConversionPattern= %d{HH:mm:ss} [%c{1}] %m%n + +# filter noisy classes +log4j.logger.org.ethereum.net = FATAL +log4j.logger.peerdiscovery = FATAL +log4j.logger.java.nio = FATAL +log4j.logger.io.netty = FATAL +log4j.logger.org.ethereum.core = FATAL +log4j.logger.wire = FATAL +log4j.logger.VM = FATAL +log4j.logger.main = FATAL +log4j.logger.state = FATAL +log4j.logger.blockchain = FATAL +log4j.logger.ui = FATAL +log4j.logger.gas = DEBUG + diff --git a/ethereumj-core/src/test/resources/system.properties b/ethereumj-core/src/test/resources/system.properties new file mode 100644 index 00000000..d9f01eb1 --- /dev/null +++ b/ethereumj-core/src/test/resources/system.properties @@ -0,0 +1,89 @@ +# if the system will work as a server also +# accept for incoming connections [true/false] +server.acceptConnections = false + +# one default access point to start +# discover the network e.g. ip: [54.201.28.117] port: [30303] +# Peer Server Zero: peer discovery +peer.discovery.ip = 54.201.28.117 +peer.discovery.port = 30303 + +# Peer Server One: peer discovery +#peer.discovery.ip = 54.204.10.41 +#peer.discovery.port = 30303 + +# active peer ip and port +# that is the peer through +# we get the chain: [54.201.28.117] port: [30303] +# ZeroGox +#peer.active.ip = 54.204.10.41 +#peer.active.port = 30303 + +# Some dude in Canada +#peer.active.ip = 131.104.247.135 +#peer.active.port = 30303 + +# Nick +#peer.active.ip = 82.217.72.169 +#peer.active.port = 30303 + + +# RomanJ general +peer.active.ip = 54.211.14.10 +peer.active.port = 50505 + + #poc5.testnet.ethereum.org +#peer.active.ip = 54.72.69.180 +#peer.active.port = 30303 + +#peer.active.ip = 151.64.223.120 +#peer.active.port = 30304 + +# specify if the mechanism +# to discover more and more +# peers and check the already +# discovered peers is on +# if peer discovery is off +# the peer window will show +# only what retrieved by active +# peer [true/false] +peer.discovery = true + +# number of workers that +# tastes the peers for being +# online [1..10] +peer.discovery.workers = 15 + +# connection timeout for trying to +# connect to a peer [seconds] +peer.discovery.timeout = 2 + +# the time we wait to the network +# to approve the transaction, the +# transaction got approved when +# include into a transactions msg +# retrieved from the peer [seconds] +transaction.approve.timeout = 15 + +# the parameter specifies how much +# time the active peer will wait +# for a message to come before kill +# the channel +active.peer.channel.timeout = 15 + +# default directory where we keep +# basic Serpent samples relative +# to home.dir +samples.dir = samples + +# everytime the application starts +# the existing database will be +# destroyed and all the data will be +# downloaded from peers again +database.reset = true + + +# this string is computed +# to be eventually the address +# that get the miner reward +coinbase.secret = "monkey" \ No newline at end of file