From d932294c0cca1cbe33422cff0098a6d1a6d4eb30 Mon Sep 17 00:00:00 2001 From: nicksavers Date: Thu, 31 Jul 2014 22:28:00 +0200 Subject: [PATCH 1/7] Avoid putting conflicting state into the db --- .../java/org/ethereum/core/Blockchain.java | 66 +++++++++---------- .../org/ethereum/manager/WorldManager.java | 4 ++ .../java/org/ethereum/net/BlockQueue.java | 10 +-- .../src/main/java/org/ethereum/trie/Trie.java | 2 +- .../src/main/resources/system.properties | 14 ++-- .../java/org/ethereum/core/BlockTest.java | 4 +- 6 files changed, 53 insertions(+), 47 deletions(-) diff --git a/ethereumj-core/src/main/java/org/ethereum/core/Blockchain.java b/ethereumj-core/src/main/java/org/ethereum/core/Blockchain.java index a786c7e4..3afb32ae 100644 --- a/ethereumj-core/src/main/java/org/ethereum/core/Blockchain.java +++ b/ethereumj-core/src/main/java/org/ethereum/core/Blockchain.java @@ -13,7 +13,6 @@ import org.spongycastle.util.encoders.Hex; import java.io.IOException; import java.util.Arrays; import java.util.HashMap; -import java.util.List; import java.util.Map; import static org.ethereum.config.SystemProperties.CONFIG; @@ -86,14 +85,13 @@ public class Blockchain { return new Block(chainDb.get(ByteUtil.longToBytes(blockNr))); } - public void applyBlock(Block block) { + public void add(Block block) { if (block == null) return; - // if it is the first block to add - // check that the parent is the genesis + // make sure the parent is genesis if (index.isEmpty() && !Arrays.equals(Genesis.getInstance().getHash(), block.getParentHash())) { @@ -105,38 +103,24 @@ public class Blockchain { String blockParentHash = Hex.toHexString(block.getParentHash()); if (!hashLast.equals(blockParentHash)) return; } - - this.addBlock(block); + if (block.getNumber() >= CONFIG.traceStartBlock() && CONFIG.traceStartBlock() != -1) { AdvancedDeviceUtils.adjustDetailedTracing(block.getNumber()); } - /* Debug check to see if the state is still as expected */ - if(logger.isWarnEnabled()) { - String blockStateRootHash = Hex.toHexString(block.getStateRoot()); - String worldStateRootHash = Hex.toHexString(WorldManager.getInstance().getRepository().getWorldState().getRootHash()); - if(!blockStateRootHash.equals(worldStateRootHash)){ - logger.warn("WARNING: STATE CONFLICT! block: {} worldstate {} mismatch", block.getNumber(), worldStateRootHash); - // Last fail on WARNING: STATE CONFLICT! block: 1157 worldstate b1d9a978451ef04c1639011d9516473d51c608dbd25906c89be791707008d2de mismatch -// System.exit(-1); - } - } - + this.processBlock(block); + // Remove all wallet transactions as they already approved by the net for (Transaction tx : block.getTransactionsList()) { if (logger.isDebugEnabled()) logger.debug("pending cleanup: tx.hash: [{}]", Hex.toHexString( tx.getHash())); WorldManager.getInstance().removeWalletTransaction(tx); } - logger.info("*** Block chain size: [ {} ]", this.getSize()); - EthereumListener listener = WorldManager.getInstance().getListener(); if (listener != null) listener.trace(String.format("Block chain size: [ %d ]", this.getSize())); - - - + /* if (lastBlock.getNumber() >= 30) { System.out.println("** checkpoint **"); @@ -148,28 +132,42 @@ public class Blockchain { */ } - public void addBlock(Block block) { + public void processBlock(Block block) { if(block.isValid()) { - if (!block.isGenesis()) { for (Transaction tx : block.getTransactionsList()) // TODO: refactor the wallet pending transactions to the world manager WorldManager.getInstance().addWalletTransaction(tx); - WorldManager.getInstance().applyBlock(block); + WorldManager.getInstance().applyBlock(block); + WorldManager.getInstance().getWallet().processBlock(block); } - - this.chainDb.put(ByteUtil.longToBytes(block.getNumber()), block.getEncoded()); - this.index.put(block.getNumber(), block.getHash()); - - WorldManager.getInstance().getWallet().processBlock(block); - this.setLastBlock(block); - if (logger.isDebugEnabled()) - logger.debug("block added {}", block.toFlatString()); + this.storeBlock(block); } else { logger.warn("Invalid block with nr: {}", block.getNumber()); } } + private void storeBlock(Block block) { + /* Debug check to see if the state is still as expected */ + if(logger.isWarnEnabled()) { + String blockStateRootHash = Hex.toHexString(block.getStateRoot()); + String worldStateRootHash = Hex.toHexString(WorldManager.getInstance().getRepository().getWorldState().getRootHash()); + if(!blockStateRootHash.equals(worldStateRootHash)){ + logger.error("ERROR: STATE CONFLICT! block: {} worldstate {} mismatch", block.getNumber(), worldStateRootHash); + // Last conflict on block 1157 -> worldstate b1d9a978451ef04c1639011d9516473d51c608dbd25906c89be791707008d2de + System.exit(-1); // Don't add block + } + } + + this.chainDb.put(ByteUtil.longToBytes(block.getNumber()), block.getEncoded()); + this.index.put(block.getNumber(), block.getHash()); + this.setLastBlock(block); + + if (logger.isDebugEnabled()) + logger.debug("block added {}", block.toFlatString()); + logger.info("*** Block chain size: [ {} ]", this.getSize()); + } + public long getGasPrice() { // In case of the genesis block we don't want to rely on the min gas price return lastBlock.isGenesis() ? lastBlock.getMinGasPrice() : INITIAL_MIN_GAS_PRICE; @@ -188,7 +186,7 @@ public class Blockchain { if (!iterator.hasNext()) { logger.info("DB is empty - adding Genesis"); this.lastBlock = Genesis.getInstance(); - this.addBlock(lastBlock); + this.storeBlock(lastBlock); logger.debug("Block #{} -> {}", Genesis.NUMBER, lastBlock.toFlatString()); } else { logger.debug("Displaying blocks stored in DB sorted on blocknumber"); 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 aadd5eeb..80e1e45d 100644 --- a/ethereumj-core/src/main/java/org/ethereum/manager/WorldManager.java +++ b/ethereumj-core/src/main/java/org/ethereum/manager/WorldManager.java @@ -308,6 +308,10 @@ public class WorldManager { public void applyBlock(Block block) { + if(block.getNumber() == 1157) { + logger.debug("Block 1157"); + } + int i = 0; for (Transaction tx : block.getTransactionsList()) { logger.info("apply block: [ {} ] tx: [ {} ] ", block.getNumber(), i); diff --git a/ethereumj-core/src/main/java/org/ethereum/net/BlockQueue.java b/ethereumj-core/src/main/java/org/ethereum/net/BlockQueue.java index ee25f897..701ca8cb 100644 --- a/ethereumj-core/src/main/java/org/ethereum/net/BlockQueue.java +++ b/ethereumj-core/src/main/java/org/ethereum/net/BlockQueue.java @@ -40,10 +40,10 @@ public class BlockQueue { Block block = blockQueue.poll(); - WorldManager.getInstance().getBlockChain().applyBlock(block); + WorldManager.getInstance().getBlockChain().add(block); } - public void addBlocks(List blockList){ + public void addBlocks(List blockList) { Block lastReceivedBlock = blockList.get(blockList.size() - 1); if (lastReceivedBlock.getNumber() != getLast().getNumber() + 1) return; @@ -61,7 +61,7 @@ public class BlockQueue { logger.trace("Blocks waiting to be proceed in the queue: [ {} ]", blockQueue.size()); } - public Block getLast(){ + public Block getLast() { if (blockQueue.isEmpty()) return WorldManager.getInstance().getBlockChain().getLastBlock(); @@ -69,7 +69,7 @@ public class BlockQueue { return lastBlock; } - private class BlockByIndexComparator implements Comparator{ + private class BlockByIndexComparator implements Comparator { @Override public int compare(Block o1, Block o2) { @@ -83,7 +83,7 @@ public class BlockQueue { } } - public int size(){ + public int size() { return blockQueue.size(); } diff --git a/ethereumj-core/src/main/java/org/ethereum/trie/Trie.java b/ethereumj-core/src/main/java/org/ethereum/trie/Trie.java index 3ae82205..81ea0dd6 100644 --- a/ethereumj-core/src/main/java/org/ethereum/trie/Trie.java +++ b/ethereumj-core/src/main/java/org/ethereum/trie/Trie.java @@ -35,7 +35,7 @@ import org.spongycastle.util.encoders.Hex; * @author: Nick Savers * Created on: 20/05/2014 10:44 */ -public class Trie implements TrieFacade{ +public class Trie implements TrieFacade { private Logger logger = LoggerFactory.getLogger("trie"); diff --git a/ethereumj-core/src/main/resources/system.properties b/ethereumj-core/src/main/resources/system.properties index bbd9bb76..c9468b34 100644 --- a/ethereumj-core/src/main/resources/system.properties +++ b/ethereumj-core/src/main/resources/system.properties @@ -9,8 +9,12 @@ server.acceptConnections = false #peer.discovery.port = 30303 # Peer Server One: peer discovery -peer.discovery.ip = 54.204.10.41 + +# Asimov +peer.discovery.ip = 185.43.109.23 peer.discovery.port = 30303 + +# RomanJ #peer.discovery.ip = 54.211.14.10 #peer.discovery.port = 30303 @@ -30,7 +34,7 @@ peer.discovery.port = 30303 #peer.active.port = 30303 # PoC-5 testnet -peer.active.ip = 54.204.10.41 +peer.active.ip = 185.43.109.23 peer.active.port = 30303 #peer.active.ip = 54.72.69.180 @@ -80,7 +84,7 @@ samples.dir = samples # the existing database will be # destroyed and all the data will be # downloaded from peers again -database.reset = true +database.reset = false # place to save physical storage files database.dir = database @@ -104,14 +108,14 @@ dump.clean.on.restart = true # make changes to tracing options # starting from certain block # -1 don't make any tracing changes -trace.startblock = 1150 +trace.startblock = 1155 # invoke vm program on # message received, # if the vm is not invoked # the balance transfer # occurs anyway [true/false] -play.vm = false +play.vm = true # maximum blocks to ask, # when downloading the chain diff --git a/ethereumj-core/src/test/java/org/ethereum/core/BlockTest.java b/ethereumj-core/src/test/java/org/ethereum/core/BlockTest.java index 8384fc33..654b2ad9 100644 --- a/ethereumj-core/src/test/java/org/ethereum/core/BlockTest.java +++ b/ethereumj-core/src/test/java/org/ethereum/core/BlockTest.java @@ -115,7 +115,7 @@ public class BlockTest { assertEquals(new BigInteger(1, Genesis.DIFFICULTY), difficulty); // Storing genesis because the parent needs to be in the DB for calculation. - WorldManager.getInstance().getBlockChain().addBlock(genesis); + WorldManager.getInstance().getBlockChain().add(genesis); Block block1 = new Block(Hex.decode(block_1)); BigInteger calcDifficulty = new BigInteger(1, block1.calcDifficulty()); @@ -137,7 +137,7 @@ public class BlockTest { assertEquals(Genesis.GAS_LIMIT, gasLimit); // Storing genesis because the parent needs to be in the DB for calculation. - WorldManager.getInstance().getBlockChain().addBlock(genesis); + WorldManager.getInstance().getBlockChain().add(genesis); // Test with block Block block1 = new Block(Hex.decode(block_1)); From f4bab10327d1e90811bb400ee237c89077122748 Mon Sep 17 00:00:00 2001 From: nicksavers Date: Fri, 1 Aug 2014 20:28:34 +0200 Subject: [PATCH 2/7] Define Map interface instead of implementation --- ethereumj-core/src/main/java/org/ethereum/core/Wallet.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/ethereumj-core/src/main/java/org/ethereum/core/Wallet.java b/ethereumj-core/src/main/java/org/ethereum/core/Wallet.java index fb07bd30..aabf2bc2 100644 --- a/ethereumj-core/src/main/java/org/ethereum/core/Wallet.java +++ b/ethereumj-core/src/main/java/org/ethereum/core/Wallet.java @@ -21,6 +21,7 @@ import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.List; +import java.util.Map; /** * The Wallet handles the management of accounts with addresses and private keys. @@ -33,12 +34,12 @@ public class Wallet { // private HashMap rows = new HashMap<>(); // table for a wallet - private HashMap rows = new HashMap(); + private Map rows = new HashMap<>(); private long high; - private List listeners = new ArrayList(); + private List listeners = new ArrayList<>(); - private HashMap transactionMap = new HashMap(); + private Map transactionMap = new HashMap<>(); public void addNewAccount() { Account account = new Account(); From d2ea940992f183f5ec8f58aefe03683cf7a465ee Mon Sep 17 00:00:00 2001 From: nicksavers Date: Sat, 2 Aug 2014 00:52:22 +0200 Subject: [PATCH 3/7] Use sha3 cache for extra performance --- .../java/org/ethereum/core/AccountState.java | 7 +- .../java/org/ethereum/crypto/HashUtil.java | 17 ++- .../java/org/ethereum/crypto/SHA3Helper.java | 127 +++++++++--------- .../main/java/org/ethereum/util/ByteUtil.java | 2 + 4 files changed, 82 insertions(+), 71 deletions(-) diff --git a/ethereumj-core/src/main/java/org/ethereum/core/AccountState.java b/ethereumj-core/src/main/java/org/ethereum/core/AccountState.java index 278d5165..dde54985 100644 --- a/ethereumj-core/src/main/java/org/ethereum/core/AccountState.java +++ b/ethereumj-core/src/main/java/org/ethereum/core/AccountState.java @@ -1,6 +1,7 @@ package org.ethereum.core; -import org.ethereum.crypto.HashUtil; +import static org.ethereum.util.ByteUtil.EMPTY_BYTE_ARRAY; +import static org.ethereum.crypto.HashUtil.EMPTY_DATA_HASH; import org.ethereum.util.RLP; import org.ethereum.util.RLPList; @@ -28,7 +29,7 @@ public class AccountState { * I define a convenient equivalence TRIE (σ[a] s ) ≡ σ[a] s . * It shall be understood that σ[a] s is not a ‘physical’ member * of the account and does not contribute to its later serialisation */ - private byte[] stateRoot = new byte[0]; + private byte[] stateRoot = EMPTY_BYTE_ARRAY; /* The hash of the EVM code of this contract—this is the code * that gets executed should this address receive a message call; @@ -36,7 +37,7 @@ public class AccountState { * after construction. All such code fragments are contained in * the state database under their corresponding hashes for later * retrieval */ - private byte[] codeHash = HashUtil.sha3(new byte[0]); + private byte[] codeHash = EMPTY_DATA_HASH; public AccountState() { this(BigInteger.ZERO, BigInteger.ZERO); diff --git a/ethereumj-core/src/main/java/org/ethereum/crypto/HashUtil.java b/ethereumj-core/src/main/java/org/ethereum/crypto/HashUtil.java index 8ced22bf..c28223e2 100644 --- a/ethereumj-core/src/main/java/org/ethereum/crypto/HashUtil.java +++ b/ethereumj-core/src/main/java/org/ethereum/crypto/HashUtil.java @@ -5,7 +5,10 @@ import static java.util.Arrays.copyOfRange; import java.math.BigInteger; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; +import java.util.HashMap; +import java.util.Map; +import org.ethereum.db.ByteArrayWrapper; import org.ethereum.util.ByteUtil; import org.ethereum.util.RLP; import org.ethereum.util.Utils; @@ -13,7 +16,8 @@ import org.spongycastle.util.encoders.Hex; public class HashUtil { - public static byte[] EMPTY_DATA_HASH = HashUtil.sha3(new byte[0]); + public static Map hashes = new HashMap<>(); + public static final byte[] EMPTY_DATA_HASH = HashUtil.sha3(new byte[0]); private static final MessageDigest sha256digest; @@ -30,13 +34,14 @@ public class HashUtil { } public static byte[] sha3(byte[] input) { - return SHA3Helper.sha3(input); + ByteArrayWrapper byteArray = new ByteArrayWrapper(input); + if(hashes.keySet().contains(byteArray)) + return hashes.get(byteArray); + byte[] result = SHA3Helper.sha3(input); + hashes.put(byteArray, result); + return result; } - public static String sha3String(String input) { - return SHA3Helper.sha3String(input); - } - /** * Calculates RIGTMOST160(SHA3(input)). This is used in address calculations. */ diff --git a/ethereumj-core/src/main/java/org/ethereum/crypto/SHA3Helper.java b/ethereumj-core/src/main/java/org/ethereum/crypto/SHA3Helper.java index 2ad5dea9..2bba8741 100644 --- a/ethereumj-core/src/main/java/org/ethereum/crypto/SHA3Helper.java +++ b/ethereumj-core/src/main/java/org/ethereum/crypto/SHA3Helper.java @@ -7,72 +7,74 @@ import org.spongycastle.util.encoders.Hex; public class SHA3Helper { - public static String sha3String(String message) { - return sha3String(message, new SHA3Digest(256), true); - } + private static int DEFAULT_SIZE = 256; - public static String sha3String(byte[] message) { - return sha3String(message, new SHA3Digest(256), true); - } + public static String sha3String(String message) { + return sha3String(message, new SHA3Digest(DEFAULT_SIZE), true); + } - public static byte[] sha3(String message) { - return sha3(Hex.decode(message), new SHA3Digest(256), true); - } - - public static byte[] sha3(byte[] message) { - return sha3(message, new SHA3Digest(256), true); - } - - protected static String sha3String(String message, Size bitSize) { - SHA3Digest digest = new SHA3Digest(bitSize.bits); - return sha3String(message, digest, true); - } - - protected static String sha3String(byte[] message, Size bitSize) { - SHA3Digest digest = new SHA3Digest(bitSize.bits); - return sha3String(message, digest, true); - } - - protected static String sha3String(String message, Size bitSize, boolean bouncyencoder) { - SHA3Digest digest = new SHA3Digest(bitSize.bits); - return sha3String(message, digest, bouncyencoder); - } - - protected static String sha3string(byte[] message, Size bitSize, boolean bouncyencoder) { - SHA3Digest digest = new SHA3Digest(bitSize.bits); - return sha3String(message, digest, bouncyencoder); - } - - private static String sha3String(String message, SHA3Digest digest, boolean bouncyencoder) { - if (message != null) { - return sha3String(Hex.decode(message), digest, bouncyencoder); - } - throw new NullPointerException("Can't hash a NULL value"); - } + public static String sha3String(byte[] message) { + return sha3String(message, new SHA3Digest(DEFAULT_SIZE), true); + } - private static String sha3String(byte[] message, SHA3Digest digest, boolean bouncyencoder) { - byte[] hash = doSha3(message, digest, bouncyencoder); - if (bouncyencoder) { - return Hex.toHexString(hash); - } else { - BigInteger bigInt = new BigInteger(1, hash); - return bigInt.toString(16); - } - } - - private static byte[] sha3(byte[] message, SHA3Digest digest, boolean bouncyencoder) { - return doSha3(message, digest, bouncyencoder); - } - - private static byte[] doSha3(byte[] message, SHA3Digest digest, boolean bouncyencoder) { - byte[] hash = new byte[digest.getDigestSize()]; + public static byte[] sha3(String message) { + return sha3(Hex.decode(message), new SHA3Digest(DEFAULT_SIZE), true); + } - if (message.length != 0) { - digest.update(message, 0, message.length); - } - digest.doFinal(hash, 0); - return hash; - } + public static byte[] sha3(byte[] message) { + return sha3(message, new SHA3Digest(DEFAULT_SIZE), true); + } + + protected static String sha3String(String message, Size bitSize) { + SHA3Digest digest = new SHA3Digest(bitSize.bits); + return sha3String(message, digest, true); + } + + protected static String sha3String(byte[] message, Size bitSize) { + SHA3Digest digest = new SHA3Digest(bitSize.bits); + return sha3String(message, digest, true); + } + + protected static String sha3String(String message, Size bitSize, boolean bouncyencoder) { + SHA3Digest digest = new SHA3Digest(bitSize.bits); + return sha3String(message, digest, bouncyencoder); + } + + protected static String sha3string(byte[] message, Size bitSize, boolean bouncyencoder) { + SHA3Digest digest = new SHA3Digest(bitSize.bits); + return sha3String(message, digest, bouncyencoder); + } + + private static String sha3String(String message, SHA3Digest digest, boolean bouncyencoder) { + if (message != null) { + return sha3String(Hex.decode(message), digest, bouncyencoder); + } + throw new NullPointerException("Can't hash a NULL value"); + } + + private static String sha3String(byte[] message, SHA3Digest digest, boolean bouncyencoder) { + byte[] hash = doSha3(message, digest, bouncyencoder); + if (bouncyencoder) { + return Hex.toHexString(hash); + } else { + BigInteger bigInt = new BigInteger(1, hash); + return bigInt.toString(16); + } + } + + private static byte[] sha3(byte[] message, SHA3Digest digest, boolean bouncyencoder) { + return doSha3(message, digest, bouncyencoder); + } + + private static byte[] doSha3(byte[] message, SHA3Digest digest, boolean bouncyencoder) { + byte[] hash = new byte[digest.getDigestSize()]; + + if (message.length != 0) { + digest.update(message, 0, message.length); + } + digest.doFinal(hash, 0); + return hash; + } public enum Size { @@ -91,4 +93,5 @@ public class SHA3Helper { return this.bits; } } + } diff --git a/ethereumj-core/src/main/java/org/ethereum/util/ByteUtil.java b/ethereumj-core/src/main/java/org/ethereum/util/ByteUtil.java index 94a3b104..503a7e89 100644 --- a/ethereumj-core/src/main/java/org/ethereum/util/ByteUtil.java +++ b/ethereumj-core/src/main/java/org/ethereum/util/ByteUtil.java @@ -10,6 +10,8 @@ import org.spongycastle.util.encoders.Hex; public class ByteUtil { + public static final byte[] EMPTY_BYTE_ARRAY = new byte[0]; + /** * Creates a copy of bytes and appends b to the end of it */ From cfe42aec5b25776a79589b7f2e74dd2f9887041f Mon Sep 17 00:00:00 2001 From: nicksavers Date: Sat, 2 Aug 2014 01:15:38 +0200 Subject: [PATCH 4/7] Remove unnecessary compression --- ethereumj-core/src/main/java/org/ethereum/db/DatabaseImpl.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ethereumj-core/src/main/java/org/ethereum/db/DatabaseImpl.java b/ethereumj-core/src/main/java/org/ethereum/db/DatabaseImpl.java index 73a26b28..705a2910 100644 --- a/ethereumj-core/src/main/java/org/ethereum/db/DatabaseImpl.java +++ b/ethereumj-core/src/main/java/org/ethereum/db/DatabaseImpl.java @@ -9,6 +9,7 @@ import java.util.Collections; import java.util.List; import org.ethereum.config.SystemProperties; +import org.iq80.leveldb.CompressionType; import org.iq80.leveldb.DB; import org.iq80.leveldb.DBIterator; import org.iq80.leveldb.Options; @@ -34,6 +35,7 @@ public class DatabaseImpl implements Database { this.name = name; Options options = new Options(); options.createIfMissing(true); + options.compressionType(CompressionType.NONE); try { logger.debug("Opening database"); File dbLocation = new File(System.getProperty("user.dir") + "/" + @@ -45,7 +47,6 @@ public class DatabaseImpl implements Database { } logger.debug("Initializing new or existing DB: '" + name + "'"); - options.createIfMissing(true); db = factory.open(fileLocation, options); // logger.debug("Showing database stats"); // String stats = DATABASE.getProperty("leveldb.stats"); From be0f70575b9b086148eb6e35f3f4b6fa65760e73 Mon Sep 17 00:00:00 2001 From: nicksavers Date: Sat, 2 Aug 2014 04:34:29 +0200 Subject: [PATCH 5/7] Switch to LRU for caching sha3 hashes --- .../java/org/ethereum/crypto/HashUtil.java | 15 ++++++------ .../main/java/org/ethereum/util/LRUMap.java | 24 +++++++++++++++++++ 2 files changed, 32 insertions(+), 7 deletions(-) create mode 100644 ethereumj-core/src/main/java/org/ethereum/util/LRUMap.java diff --git a/ethereumj-core/src/main/java/org/ethereum/crypto/HashUtil.java b/ethereumj-core/src/main/java/org/ethereum/crypto/HashUtil.java index c28223e2..39aecb36 100644 --- a/ethereumj-core/src/main/java/org/ethereum/crypto/HashUtil.java +++ b/ethereumj-core/src/main/java/org/ethereum/crypto/HashUtil.java @@ -5,8 +5,6 @@ import static java.util.Arrays.copyOfRange; import java.math.BigInteger; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; -import java.util.HashMap; -import java.util.Map; import org.ethereum.db.ByteArrayWrapper; import org.ethereum.util.ByteUtil; @@ -14,9 +12,12 @@ import org.ethereum.util.RLP; import org.ethereum.util.Utils; import org.spongycastle.util.encoders.Hex; +import org.ethereum.util.LRUMap; + public class HashUtil { - public static Map hashes = new HashMap<>(); + private static final int MAX_ENTRIES = 1000; // Should contain most commonly hashed values + private static LRUMap sha3Cache = new LRUMap<>(0, MAX_ENTRIES); public static final byte[] EMPTY_DATA_HASH = HashUtil.sha3(new byte[0]); private static final MessageDigest sha256digest; @@ -34,11 +35,11 @@ public class HashUtil { } public static byte[] sha3(byte[] input) { - ByteArrayWrapper byteArray = new ByteArrayWrapper(input); - if(hashes.keySet().contains(byteArray)) - return hashes.get(byteArray); + ByteArrayWrapper inputByteArray = new ByteArrayWrapper(input); + if(sha3Cache.keySet().contains(inputByteArray)) + return sha3Cache.get(inputByteArray); byte[] result = SHA3Helper.sha3(input); - hashes.put(byteArray, result); + sha3Cache.put(inputByteArray, result); return result; } diff --git a/ethereumj-core/src/main/java/org/ethereum/util/LRUMap.java b/ethereumj-core/src/main/java/org/ethereum/util/LRUMap.java new file mode 100644 index 00000000..b2fc4b00 --- /dev/null +++ b/ethereumj-core/src/main/java/org/ethereum/util/LRUMap.java @@ -0,0 +1,24 @@ +package org.ethereum.util; + +import java.util.LinkedHashMap; +import java.util.Map; + +/** + * Simple LRU map used for reusing lookup values. + */ +public class LRUMap extends LinkedHashMap { + + private static final long serialVersionUID = 1L; + + protected final int maxEntries; + + public LRUMap(int initialEntries, int maxEntries) { + super(initialEntries, 0.8f, true); + this.maxEntries = maxEntries; + } + + @Override + protected boolean removeEldestEntry(Map.Entry eldest) { + return size() > maxEntries; + } +} \ No newline at end of file From d8063c5ff3e741d9202a978333cd1b402c0fdb24 Mon Sep 17 00:00:00 2001 From: nicksavers Date: Sat, 2 Aug 2014 11:35:37 +0200 Subject: [PATCH 6/7] Re-use static variable for Word with EMPTY_BYTE_ARRAY --- .../main/java/org/ethereum/vm/DataWord.java | 6 +- .../main/java/org/ethereum/vm/Program.java | 27 +- .../src/main/java/org/ethereum/vm/VM.java | 4 +- .../java/org/ethereum/vm/DataWordTest.java | 14 +- .../src/test/java/org/ethereum/vm/VMTest.java | 258 +++++++++--------- 5 files changed, 155 insertions(+), 154 deletions(-) diff --git a/ethereumj-core/src/main/java/org/ethereum/vm/DataWord.java b/ethereumj-core/src/main/java/org/ethereum/vm/DataWord.java index db98ea57..fdf0b4c9 100644 --- a/ethereumj-core/src/main/java/org/ethereum/vm/DataWord.java +++ b/ethereumj-core/src/main/java/org/ethereum/vm/DataWord.java @@ -18,12 +18,12 @@ import java.nio.ByteBuffer; */ public class DataWord implements Comparable { - public static final DataWord ZERO = new DataWord(new byte[32]); // don't push it in to the stack + public static final DataWord ZERO = new DataWord(new byte[32]); // don't push it in to the stack + public static final DataWord ZERO_EMPTY_ARRAY = new DataWord(new byte[0]); // don't push it in to the stack - byte[] data = new byte[32]; + private byte[] data = new byte[32]; public DataWord() { - this.data = new byte[32]; } public DataWord(int num) { 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 c6293856..cc6f5180 100644 --- a/ethereumj-core/src/main/java/org/ethereum/vm/Program.java +++ b/ethereumj-core/src/main/java/org/ethereum/vm/Program.java @@ -3,6 +3,7 @@ package org.ethereum.vm; import org.ethereum.crypto.HashUtil; import org.ethereum.db.ContractDetails; import org.ethereum.db.Repository; +import org.ethereum.util.ByteUtil; import org.ethereum.util.Utils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -25,7 +26,7 @@ public class Program { private int invokeHash; private ProgramListener listener; - Stack stack = new Stack(); + Stack stack = new Stack<>(); ByteBuffer memory = null; DataWord programAddress; @@ -147,7 +148,7 @@ public class Program { } public void memorySave(DataWord addrB, DataWord value) { - memorySave(addrB.data, value.data); + memorySave(addrB.getData(), value.getData()); } public void memorySave(byte[] addr, byte[] value) { @@ -160,7 +161,7 @@ public class Program { public DataWord memoryLoad(DataWord addr) { int address = new BigInteger(1, addr.getData()).intValue(); - allocateMemory(address, DataWord.ZERO.data); + allocateMemory(address, DataWord.ZERO.getData()); byte[] data = new byte[32]; System.arraycopy(memory.array(), address, data , 0 ,32); @@ -465,12 +466,12 @@ public class Program { } public DataWord getOwnerAddress() { - if (invokeData == null) return new DataWord( new byte[0]); + if (invokeData == null) return DataWord.ZERO_EMPTY_ARRAY; return this.programAddress.clone(); } public DataWord getBalance(DataWord address) { - if (invokeData == null) return new DataWord( new byte[0]); + if (invokeData == null) return DataWord.ZERO_EMPTY_ARRAY; BigInteger balance = result.getRepository().getBalance(address.getLast20Bytes()); DataWord balanceData = new DataWord(balance.toByteArray()); @@ -479,43 +480,43 @@ public class Program { } public DataWord getOriginAddress() { - if (invokeData == null) return new DataWord( new byte[0]); + if (invokeData == null) return DataWord.ZERO_EMPTY_ARRAY; return invokeData.getOriginAddress().clone(); } public DataWord getCallerAddress() { - if (invokeData == null) return new DataWord( new byte[0]); + if (invokeData == null) return DataWord.ZERO_EMPTY_ARRAY; return invokeData.getCallerAddress().clone(); } public DataWord getGasPrice() { - if (invokeData == null) return new DataWord( new byte[0]); + if (invokeData == null) return DataWord.ZERO_EMPTY_ARRAY; return invokeData.getMinGasPrice().clone(); } public DataWord getGas() { - if (invokeData == null) return new DataWord( new byte[0]); + if (invokeData == null) return DataWord.ZERO_EMPTY_ARRAY; long afterSpend = invokeData.getGas().longValue() - result.getGasUsed(); return new DataWord(afterSpend); } public DataWord getCallValue() { - if (invokeData == null) return new DataWord( new byte[0]); + if (invokeData == null) return DataWord.ZERO_EMPTY_ARRAY; return invokeData.getCallValue().clone(); } public DataWord getDataSize() { - if (invokeData == null) return new DataWord( new byte[0]); + if (invokeData == null) return DataWord.ZERO_EMPTY_ARRAY; return invokeData.getDataSize().clone(); } public DataWord getDataValue(DataWord index) { - if (invokeData == null) return new DataWord( new byte[0]); + if (invokeData == null) return DataWord.ZERO_EMPTY_ARRAY; return invokeData.getDataValue(index); } public byte[] getDataCopy(DataWord offset, DataWord length) { - if (invokeData == null) return new byte[0]; + if (invokeData == null) return ByteUtil.EMPTY_BYTE_ARRAY; return invokeData.getDataCopy(offset, length); } 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 28c86c72..4d30a7d7 100644 --- a/ethereumj-core/src/main/java/org/ethereum/vm/VM.java +++ b/ethereumj-core/src/main/java/org/ethereum/vm/VM.java @@ -449,7 +449,7 @@ public class VM { if (logger.isInfoEnabled()) hint = "data: " + Hex.toHexString(msgData); - program.memorySave(memOffsetData.data, msgData); + program.memorySave(memOffsetData.getData(), msgData); program.step(); } break; case CODESIZE:{ @@ -759,7 +759,7 @@ public class VM { if (memoryUsage > 0) program.spendGas(GasCost.MEMORY * memoryUsage, OpCode.code(op).name() + " (memory usage)"); - program.fullTrace(); +// program.fullTrace(); } catch (RuntimeException e) { program.stop(); if(e instanceof OutOfGasException) diff --git a/ethereumj-core/src/test/java/org/ethereum/vm/DataWordTest.java b/ethereumj-core/src/test/java/org/ethereum/vm/DataWordTest.java index b13b3621..8544ede4 100644 --- a/ethereumj-core/src/test/java/org/ethereum/vm/DataWordTest.java +++ b/ethereumj-core/src/test/java/org/ethereum/vm/DataWordTest.java @@ -44,11 +44,11 @@ public class DataWordTest { DataWord x = new DataWord(two); x.add(new DataWord(two)); - System.out.println(Hex.toHexString(x.data)); + System.out.println(Hex.toHexString(x.getData())); DataWord y = new DataWord(two); y.add2(new DataWord(two)); - System.out.println(Hex.toHexString(y.data)); + System.out.println(Hex.toHexString(y.getData())); } @Test @@ -60,13 +60,13 @@ public class DataWordTest { DataWord x = new DataWord(three); x.add(new DataWord(three)); - assertEquals(32, x.data.length); - System.out.println(Hex.toHexString(x.data)); + assertEquals(32, x.getData().length); + System.out.println(Hex.toHexString(x.getData())); // FAIL // DataWord y = new DataWord(three); // y.add2(new DataWord(three)); -// System.out.println(Hex.toHexString(y.data)); +// System.out.println(Hex.toHexString(y.getData())); } @Test @@ -85,7 +85,7 @@ public class DataWordTest { DataWord x = new DataWord(one);// System.out.println(x.value()); DataWord y = new DataWord(two);// System.out.println(y.value()); y.mod(x); - assertEquals(32, y.data.length); - assertEquals(expected, Hex.toHexString(y.data)); + assertEquals(32, y.getData().length); + assertEquals(expected, Hex.toHexString(y.getData())); } } 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 c737d80e..520d96fc 100644 --- a/ethereumj-core/src/test/java/org/ethereum/vm/VMTest.java +++ b/ethereumj-core/src/test/java/org/ethereum/vm/VMTest.java @@ -30,7 +30,7 @@ public class VMTest { vm.step(program); program.getResult().getRepository().close(); - assertEquals(expected, Hex.toHexString(program.stack.peek().data).toUpperCase() ); + assertEquals(expected, Hex.toHexString(program.stack.peek().getData()).toUpperCase() ); } @Test // PUSH2 OP @@ -44,7 +44,7 @@ public class VMTest { vm.step(program); program.getResult().getRepository().close(); - assertEquals(expected, Hex.toHexString(program.stack.peek().data).toUpperCase() ); + assertEquals(expected, Hex.toHexString(program.stack.peek().getData()).toUpperCase() ); } @Test // PUSH3 OP @@ -58,7 +58,7 @@ public class VMTest { vm.step(program); program.getResult().getRepository().close(); - assertEquals(expected, Hex.toHexString(program.stack.peek().data).toUpperCase() ); + assertEquals(expected, Hex.toHexString(program.stack.peek().getData()).toUpperCase() ); } @Test // PUSH4 OP @@ -72,7 +72,7 @@ public class VMTest { vm.step(program); program.getResult().getRepository().close(); - assertEquals(expected, Hex.toHexString(program.stack.peek().data).toUpperCase() ); + assertEquals(expected, Hex.toHexString(program.stack.peek().getData()).toUpperCase() ); } @Test // PUSH5 OP @@ -86,7 +86,7 @@ public class VMTest { vm.step(program); program.getResult().getRepository().close(); - assertEquals(expected, Hex.toHexString(program.stack.peek().data).toUpperCase() ); + assertEquals(expected, Hex.toHexString(program.stack.peek().getData()).toUpperCase() ); } @Test // PUSH6 OP @@ -100,7 +100,7 @@ public class VMTest { vm.step(program); program.getResult().getRepository().close(); - assertEquals(expected, Hex.toHexString(program.stack.peek().data).toUpperCase() ); + assertEquals(expected, Hex.toHexString(program.stack.peek().getData()).toUpperCase() ); } @Test // PUSH7 OP @@ -114,7 +114,7 @@ public class VMTest { vm.step(program); program.getResult().getRepository().close(); - assertEquals(expected, Hex.toHexString(program.stack.peek().data).toUpperCase() ); + assertEquals(expected, Hex.toHexString(program.stack.peek().getData()).toUpperCase() ); } @Test // PUSH8 OP @@ -128,7 +128,7 @@ public class VMTest { vm.step(program); program.getResult().getRepository().close(); - assertEquals(expected, Hex.toHexString(program.stack.peek().data).toUpperCase() ); + assertEquals(expected, Hex.toHexString(program.stack.peek().getData()).toUpperCase() ); } @Test // PUSH9 OP @@ -142,7 +142,7 @@ public class VMTest { vm.step(program); program.getResult().getRepository().close(); - assertEquals(expected, Hex.toHexString(program.stack.peek().data).toUpperCase() ); + assertEquals(expected, Hex.toHexString(program.stack.peek().getData()).toUpperCase() ); } @@ -157,7 +157,7 @@ public class VMTest { vm.step(program); program.getResult().getRepository().close(); - assertEquals(expected, Hex.toHexString(program.stack.peek().data).toUpperCase() ); + assertEquals(expected, Hex.toHexString(program.stack.peek().getData()).toUpperCase() ); } @Test // PUSH11 OP @@ -171,7 +171,7 @@ public class VMTest { vm.step(program); program.getResult().getRepository().close(); - assertEquals(expected, Hex.toHexString(program.stack.peek().data).toUpperCase() ); + assertEquals(expected, Hex.toHexString(program.stack.peek().getData()).toUpperCase() ); } @Test // PUSH12 OP @@ -185,7 +185,7 @@ public class VMTest { vm.step(program); program.getResult().getRepository().close(); - assertEquals(expected, Hex.toHexString(program.stack.peek().data).toUpperCase() ); + assertEquals(expected, Hex.toHexString(program.stack.peek().getData()).toUpperCase() ); } @Test // PUSH13 OP @@ -199,7 +199,7 @@ public class VMTest { vm.step(program); program.getResult().getRepository().close(); - assertEquals(expected, Hex.toHexString(program.stack.peek().data).toUpperCase() ); + assertEquals(expected, Hex.toHexString(program.stack.peek().getData()).toUpperCase() ); } @Test // PUSH14 OP @@ -213,7 +213,7 @@ public class VMTest { vm.step(program); program.getResult().getRepository().close(); - assertEquals(expected, Hex.toHexString(program.stack.peek().data).toUpperCase() ); + assertEquals(expected, Hex.toHexString(program.stack.peek().getData()).toUpperCase() ); } @Test // PUSH15 OP @@ -227,7 +227,7 @@ public class VMTest { vm.step(program); program.getResult().getRepository().close(); - assertEquals(expected, Hex.toHexString(program.stack.peek().data).toUpperCase() ); + assertEquals(expected, Hex.toHexString(program.stack.peek().getData()).toUpperCase() ); } @Test // PUSH16 OP @@ -241,7 +241,7 @@ public class VMTest { vm.step(program); program.getResult().getRepository().close(); - assertEquals(expected, Hex.toHexString(program.stack.peek().data).toUpperCase() ); + assertEquals(expected, Hex.toHexString(program.stack.peek().getData()).toUpperCase() ); } @Test // PUSH17 OP @@ -255,7 +255,7 @@ public class VMTest { vm.step(program); program.getResult().getRepository().close(); - assertEquals(expected, Hex.toHexString(program.stack.peek().data).toUpperCase() ); + assertEquals(expected, Hex.toHexString(program.stack.peek().getData()).toUpperCase() ); } @Test // PUSH18 OP @@ -269,7 +269,7 @@ public class VMTest { vm.step(program); program.getResult().getRepository().close(); - assertEquals(expected, Hex.toHexString(program.stack.peek().data).toUpperCase() ); + assertEquals(expected, Hex.toHexString(program.stack.peek().getData()).toUpperCase() ); } @Test // PUSH19 OP @@ -283,7 +283,7 @@ public class VMTest { vm.step(program); program.getResult().getRepository().close(); - assertEquals(expected, Hex.toHexString(program.stack.peek().data).toUpperCase() ); + assertEquals(expected, Hex.toHexString(program.stack.peek().getData()).toUpperCase() ); } @Test // PUSH20 OP @@ -297,7 +297,7 @@ public class VMTest { vm.step(program); program.getResult().getRepository().close(); - assertEquals(expected, Hex.toHexString(program.stack.peek().data).toUpperCase() ); + assertEquals(expected, Hex.toHexString(program.stack.peek().getData()).toUpperCase() ); } @Test // PUSH21 OP @@ -311,7 +311,7 @@ public class VMTest { vm.step(program); program.getResult().getRepository().close(); - assertEquals(expected, Hex.toHexString(program.stack.peek().data).toUpperCase() ); + assertEquals(expected, Hex.toHexString(program.stack.peek().getData()).toUpperCase() ); } @Test // PUSH22 OP @@ -325,7 +325,7 @@ public class VMTest { vm.step(program); program.getResult().getRepository().close(); - assertEquals(expected, Hex.toHexString(program.stack.peek().data).toUpperCase() ); + assertEquals(expected, Hex.toHexString(program.stack.peek().getData()).toUpperCase() ); } @Test // PUSH23 OP @@ -339,7 +339,7 @@ public class VMTest { vm.step(program); program.getResult().getRepository().close(); - assertEquals(expected, Hex.toHexString(program.stack.peek().data).toUpperCase() ); + assertEquals(expected, Hex.toHexString(program.stack.peek().getData()).toUpperCase() ); } @Test // PUSH24 OP @@ -353,7 +353,7 @@ public class VMTest { vm.step(program); program.getResult().getRepository().close(); - assertEquals(expected, Hex.toHexString(program.stack.peek().data).toUpperCase() ); + assertEquals(expected, Hex.toHexString(program.stack.peek().getData()).toUpperCase() ); } @Test // PUSH25 OP @@ -367,7 +367,7 @@ public class VMTest { vm.step(program); program.getResult().getRepository().close(); - assertEquals(expected, Hex.toHexString(program.stack.peek().data).toUpperCase() ); + assertEquals(expected, Hex.toHexString(program.stack.peek().getData()).toUpperCase() ); } @Test // PUSH26 OP @@ -381,7 +381,7 @@ public class VMTest { vm.step(program); program.getResult().getRepository().close(); - assertEquals(expected, Hex.toHexString(program.stack.peek().data).toUpperCase() ); + assertEquals(expected, Hex.toHexString(program.stack.peek().getData()).toUpperCase() ); } @Test // PUSH27 OP @@ -395,7 +395,7 @@ public class VMTest { vm.step(program); program.getResult().getRepository().close(); - assertEquals(expected, Hex.toHexString(program.stack.peek().data).toUpperCase() ); + assertEquals(expected, Hex.toHexString(program.stack.peek().getData()).toUpperCase() ); } @Test // PUSH28 OP @@ -409,7 +409,7 @@ public class VMTest { vm.step(program); program.getResult().getRepository().close(); - assertEquals(expected, Hex.toHexString(program.stack.peek().data).toUpperCase() ); + assertEquals(expected, Hex.toHexString(program.stack.peek().getData()).toUpperCase() ); } @Test // PUSH29 OP @@ -423,7 +423,7 @@ public class VMTest { vm.step(program); program.getResult().getRepository().close(); - assertEquals(expected, Hex.toHexString(program.stack.peek().data).toUpperCase() ); + assertEquals(expected, Hex.toHexString(program.stack.peek().getData()).toUpperCase() ); } @Test // PUSH30 OP @@ -437,7 +437,7 @@ public class VMTest { vm.step(program); program.getResult().getRepository().close(); - assertEquals(expected, Hex.toHexString(program.stack.peek().data).toUpperCase() ); + assertEquals(expected, Hex.toHexString(program.stack.peek().getData()).toUpperCase() ); } @Test // PUSH31 OP @@ -451,7 +451,7 @@ public class VMTest { vm.step(program); program.getResult().getRepository().close(); - assertEquals(expected, Hex.toHexString(program.stack.peek().data).toUpperCase() ); + assertEquals(expected, Hex.toHexString(program.stack.peek().getData()).toUpperCase() ); } @Test // PUSH32 OP @@ -465,7 +465,7 @@ public class VMTest { vm.step(program); program.getResult().getRepository().close(); - assertEquals(expected, Hex.toHexString(program.stack.peek().data).toUpperCase() ); + assertEquals(expected, Hex.toHexString(program.stack.peek().getData()).toUpperCase() ); } @Test(expected=RuntimeException.class) // PUSHN OP mal data @@ -512,7 +512,7 @@ public class VMTest { vm.step(program); program.getResult().getRepository().close(); - assertEquals(expected, Hex.toHexString(program.stack.peek().data).toUpperCase()); + assertEquals(expected, Hex.toHexString(program.stack.peek().getData()).toUpperCase()); } @Test // AND OP @@ -527,7 +527,7 @@ public class VMTest { vm.step(program); program.getResult().getRepository().close(); - assertEquals(expected, Hex.toHexString(program.stack.peek().data).toUpperCase() ); + assertEquals(expected, Hex.toHexString(program.stack.peek().getData()).toUpperCase() ); } @Test(expected=RuntimeException.class) // AND OP mal data @@ -558,7 +558,7 @@ public class VMTest { vm.step(program); program.getResult().getRepository().close(); - assertEquals(expected, Hex.toHexString(program.stack.peek().data).toUpperCase() ); + assertEquals(expected, Hex.toHexString(program.stack.peek().getData()).toUpperCase() ); } @Test // OR OP @@ -573,7 +573,7 @@ public class VMTest { vm.step(program); program.getResult().getRepository().close(); - assertEquals(expected, Hex.toHexString(program.stack.peek().data).toUpperCase() ); + assertEquals(expected, Hex.toHexString(program.stack.peek().getData()).toUpperCase() ); } @Test(expected=RuntimeException.class) // OR OP mal data @@ -604,7 +604,7 @@ public class VMTest { vm.step(program); program.getResult().getRepository().close(); - assertEquals(expected, Hex.toHexString(program.stack.peek().data).toUpperCase() ); + assertEquals(expected, Hex.toHexString(program.stack.peek().getData()).toUpperCase() ); } @Test // XOR OP @@ -619,7 +619,7 @@ public class VMTest { vm.step(program); program.getResult().getRepository().close(); - assertEquals(expected, Hex.toHexString(program.stack.peek().data).toUpperCase() ); + assertEquals(expected, Hex.toHexString(program.stack.peek().getData()).toUpperCase() ); } @@ -651,7 +651,7 @@ public class VMTest { vm.step(program); program.getResult().getRepository().close(); - assertEquals(expected, Hex.toHexString(program.stack.peek().data).toUpperCase() ); + assertEquals(expected, Hex.toHexString(program.stack.peek().getData()).toUpperCase() ); } @Test // BYTE OP @@ -666,7 +666,7 @@ public class VMTest { vm.step(program); program.getResult().getRepository().close(); - assertEquals(expected, Hex.toHexString(program.stack.peek().data).toUpperCase() ); + assertEquals(expected, Hex.toHexString(program.stack.peek().getData()).toUpperCase() ); } @Test // BYTE OP @@ -681,7 +681,7 @@ public class VMTest { vm.step(program); program.getResult().getRepository().close(); - assertEquals(expected, Hex.toHexString(program.stack.peek().data).toUpperCase() ); + assertEquals(expected, Hex.toHexString(program.stack.peek().getData()).toUpperCase() ); } @@ -712,7 +712,7 @@ public class VMTest { vm.step(program); program.getResult().getRepository().close(); - assertEquals(expected, Hex.toHexString(program.stack.peek().data).toUpperCase() ); + assertEquals(expected, Hex.toHexString(program.stack.peek().getData()).toUpperCase() ); } @Test // NOT OP @@ -726,7 +726,7 @@ public class VMTest { vm.step(program); program.getResult().getRepository().close(); - assertEquals(expected, Hex.toHexString(program.stack.peek().data).toUpperCase() ); + assertEquals(expected, Hex.toHexString(program.stack.peek().getData()).toUpperCase() ); } @Test(expected=RuntimeException.class) // NOT OP mal data @@ -757,7 +757,7 @@ public class VMTest { vm.step(program); program.getResult().getRepository().close(); - assertEquals(expected, Hex.toHexString(program.stack.peek().data).toUpperCase() ); + assertEquals(expected, Hex.toHexString(program.stack.peek().getData()).toUpperCase() ); } @Test // EQ OP @@ -772,7 +772,7 @@ public class VMTest { vm.step(program); program.getResult().getRepository().close(); - assertEquals(expected, Hex.toHexString(program.stack.peek().data).toUpperCase() ); + assertEquals(expected, Hex.toHexString(program.stack.peek().getData()).toUpperCase() ); } @Test // EQ OP @@ -787,7 +787,7 @@ public class VMTest { vm.step(program); program.getResult().getRepository().close(); - assertEquals(expected, Hex.toHexString(program.stack.peek().data).toUpperCase()); + assertEquals(expected, Hex.toHexString(program.stack.peek().getData()).toUpperCase()); } @Test(expected=RuntimeException.class) // EQ OP mal data @@ -818,7 +818,7 @@ public class VMTest { vm.step(program); program.getResult().getRepository().close(); - assertEquals(expected, Hex.toHexString(program.stack.peek().data).toUpperCase()); + assertEquals(expected, Hex.toHexString(program.stack.peek().getData()).toUpperCase()); } @Test // GT OP @@ -833,7 +833,7 @@ public class VMTest { vm.step(program); program.getResult().getRepository().close(); - assertEquals(expected, Hex.toHexString(program.stack.peek().data).toUpperCase()); + assertEquals(expected, Hex.toHexString(program.stack.peek().getData()).toUpperCase()); } @Test // GT OP @@ -848,7 +848,7 @@ public class VMTest { vm.step(program); program.getResult().getRepository().close(); - assertEquals(expected, Hex.toHexString(program.stack.peek().data).toUpperCase()); + assertEquals(expected, Hex.toHexString(program.stack.peek().getData()).toUpperCase()); } @Test(expected=RuntimeException.class) // GT OP mal data @@ -879,7 +879,7 @@ public class VMTest { vm.step(program); program.getResult().getRepository().close(); - assertEquals(expected, Hex.toHexString(program.stack.peek().data).toUpperCase()); + assertEquals(expected, Hex.toHexString(program.stack.peek().getData()).toUpperCase()); } @Test // SGT OP @@ -897,7 +897,7 @@ public class VMTest { vm.step(program); program.getResult().getRepository().close(); - assertEquals(expected, Hex.toHexString(program.stack.peek().data).toUpperCase()); + assertEquals(expected, Hex.toHexString(program.stack.peek().getData()).toUpperCase()); } @Test // SGT OP @@ -915,7 +915,7 @@ public class VMTest { vm.step(program); program.getResult().getRepository().close(); - assertEquals(expected, Hex.toHexString(program.stack.peek().data).toUpperCase()); + assertEquals(expected, Hex.toHexString(program.stack.peek().getData()).toUpperCase()); } @Test(expected=RuntimeException.class) // SGT OP mal @@ -947,7 +947,7 @@ public class VMTest { vm.step(program); program.getResult().getRepository().close(); - assertEquals(expected, Hex.toHexString(program.stack.peek().data).toUpperCase()); + assertEquals(expected, Hex.toHexString(program.stack.peek().getData()).toUpperCase()); } @Test // LT OP @@ -962,7 +962,7 @@ public class VMTest { vm.step(program); program.getResult().getRepository().close(); - assertEquals(expected, Hex.toHexString(program.stack.peek().data).toUpperCase()); + assertEquals(expected, Hex.toHexString(program.stack.peek().getData()).toUpperCase()); } @Test // LT OP @@ -977,7 +977,7 @@ public class VMTest { vm.step(program); program.getResult().getRepository().close(); - assertEquals(expected, Hex.toHexString(program.stack.peek().data).toUpperCase()); + assertEquals(expected, Hex.toHexString(program.stack.peek().getData()).toUpperCase()); } @Test(expected=RuntimeException.class) // LT OP mal data @@ -1008,7 +1008,7 @@ public class VMTest { vm.step(program); program.getResult().getRepository().close(); - assertEquals(expected, Hex.toHexString(program.stack.peek().data).toUpperCase()); + assertEquals(expected, Hex.toHexString(program.stack.peek().getData()).toUpperCase()); } @Test // SLT OP @@ -1026,7 +1026,7 @@ public class VMTest { vm.step(program); program.getResult().getRepository().close(); - assertEquals(expected, Hex.toHexString(program.stack.peek().data).toUpperCase()); + assertEquals(expected, Hex.toHexString(program.stack.peek().getData()).toUpperCase()); } @Test // SLT OP @@ -1044,7 +1044,7 @@ public class VMTest { vm.step(program); program.getResult().getRepository().close(); - assertEquals(expected, Hex.toHexString(program.stack.peek().data).toUpperCase()); + assertEquals(expected, Hex.toHexString(program.stack.peek().getData()).toUpperCase()); } @Test(expected=RuntimeException.class) // SLT OP mal @@ -1075,7 +1075,7 @@ public class VMTest { vm.step(program); program.getResult().getRepository().close(); - assertEquals(expected, Hex.toHexString(program.stack.peek().data).toUpperCase()); + assertEquals(expected, Hex.toHexString(program.stack.peek().getData()).toUpperCase()); } @Test // NEG OP @@ -1089,7 +1089,7 @@ public class VMTest { vm.step(program); program.getResult().getRepository().close(); - assertEquals(expected, Hex.toHexString(program.stack.peek().data).toUpperCase()); + assertEquals(expected, Hex.toHexString(program.stack.peek().getData()).toUpperCase()); } @Test // NEG OP @@ -1103,7 +1103,7 @@ public class VMTest { vm.step(program); program.getResult().getRepository().close(); - assertEquals(expected, Hex.toHexString(program.stack.peek().data).toUpperCase()); + assertEquals(expected, Hex.toHexString(program.stack.peek().getData()).toUpperCase()); } @Test(expected=RuntimeException.class) // NEG OP @@ -1134,7 +1134,7 @@ public class VMTest { vm.step(program); program.getResult().getRepository().close(); - assertEquals(expected, Hex.toHexString(program.stack.peek().data).toUpperCase()); + assertEquals(expected, Hex.toHexString(program.stack.peek().getData()).toUpperCase()); } @Test // POP OP @@ -1151,7 +1151,7 @@ public class VMTest { vm.step(program); program.getResult().getRepository().close(); - assertEquals(expected, Hex.toHexString(program.stack.peek().data).toUpperCase()); + assertEquals(expected, Hex.toHexString(program.stack.peek().getData()).toUpperCase()); } @Test(expected=RuntimeException.class) // POP OP mal data @@ -1186,7 +1186,7 @@ public class VMTest { vm.step(program); program.getResult().getRepository().close(); - assertEquals(expected, Hex.toHexString(program.stack.peek().data).toUpperCase()); + assertEquals(expected, Hex.toHexString(program.stack.peek().getData()).toUpperCase()); assertEquals(expectedLen, program.stack.toArray().length); } @@ -1219,7 +1219,7 @@ public class VMTest { vm.step(program); program.getResult().getRepository().close(); - assertEquals(expected, Hex.toHexString(program.stack.peek().data).toUpperCase()); + assertEquals(expected, Hex.toHexString(program.stack.peek().getData()).toUpperCase()); } @Test // SWAP OP @@ -1237,7 +1237,7 @@ public class VMTest { vm.step(program); program.getResult().getRepository().close(); - assertEquals(expected, Hex.toHexString(program.stack.peek().data).toUpperCase()); + assertEquals(expected, Hex.toHexString(program.stack.peek().getData()).toUpperCase()); assertEquals(expectedLen, program.stack.toArray().length); } @@ -1346,7 +1346,7 @@ public class VMTest { program.getResult().getRepository().close(); assertEquals(m_expected, Hex.toHexString(program.memory.array())); - assertEquals(s_expected, Hex.toHexString(program.stack.peek().data).toUpperCase()); + assertEquals(s_expected, Hex.toHexString(program.stack.peek().getData()).toUpperCase()); } @Test // MLOAD OP @@ -1364,7 +1364,7 @@ public class VMTest { program.getResult().getRepository().close(); assertEquals(m_expected, Hex.toHexString(program.memory.array()).toUpperCase()); - assertEquals(s_expected, Hex.toHexString(program.stack.peek().data).toUpperCase()); + assertEquals(s_expected, Hex.toHexString(program.stack.peek().getData()).toUpperCase()); } @@ -1382,7 +1382,7 @@ public class VMTest { program.getResult().getRepository().close(); assertEquals(m_expected, Hex.toHexString(program.memory.array())); - assertEquals(s_expected, Hex.toHexString(program.stack.peek().data).toUpperCase()); + assertEquals(s_expected, Hex.toHexString(program.stack.peek().getData()).toUpperCase()); } @Test // MLOAD OP @@ -1402,7 +1402,7 @@ public class VMTest { program.getResult().getRepository().close(); assertEquals(m_expected, Hex.toHexString(program.memory.array())); - assertEquals(s_expected, Hex.toHexString(program.stack.peek().data).toUpperCase()); + assertEquals(s_expected, Hex.toHexString(program.stack.peek().getData()).toUpperCase()); } @Test // MLOAD OP @@ -1422,7 +1422,7 @@ public class VMTest { program.getResult().getRepository().close(); assertEquals(m_expected, Hex.toHexString(program.memory.array())); - assertEquals(s_expected, Hex.toHexString(program.stack.peek().data).toUpperCase()); + assertEquals(s_expected, Hex.toHexString(program.stack.peek().getData()).toUpperCase()); } @Test(expected=RuntimeException.class) // MLOAD OP mal data @@ -1573,7 +1573,7 @@ public class VMTest { vm.step(program); program.getResult().getRepository().close(); - assertEquals(s_expected, Hex.toHexString(program.stack.peek().data).toUpperCase()); + assertEquals(s_expected, Hex.toHexString(program.stack.peek().getData()).toUpperCase()); } @Test // SLOAD OP @@ -1590,7 +1590,7 @@ public class VMTest { vm.step(program); program.getResult().getRepository().close(); - assertEquals(s_expected, Hex.toHexString(program.stack.peek().data).toUpperCase()); + assertEquals(s_expected, Hex.toHexString(program.stack.peek().getData()).toUpperCase()); } @Test // SLOAD OP @@ -1610,7 +1610,7 @@ public class VMTest { vm.step(program); program.getResult().getRepository().close(); - assertEquals(s_expected, Hex.toHexString(program.stack.peek().data).toUpperCase()); + assertEquals(s_expected, Hex.toHexString(program.stack.peek().getData()).toUpperCase()); } @Test(expected=RuntimeException.class) // SLOAD OP @@ -1637,7 +1637,7 @@ public class VMTest { vm.step(program); program.getResult().getRepository().close(); - assertEquals(s_expected, Hex.toHexString(program.stack.peek().data).toUpperCase()); + assertEquals(s_expected, Hex.toHexString(program.stack.peek().getData()).toUpperCase()); } @@ -1656,7 +1656,7 @@ public class VMTest { vm.step(program); program.getResult().getRepository().close(); - assertEquals(s_expected, Hex.toHexString(program.stack.peek().data).toUpperCase()); + assertEquals(s_expected, Hex.toHexString(program.stack.peek().getData()).toUpperCase()); } @@ -1674,7 +1674,7 @@ public class VMTest { vm.step(program); program.getResult().getRepository().close(); - assertEquals(s_expected, Hex.toHexString(program.stack.peek().data).toUpperCase()); + assertEquals(s_expected, Hex.toHexString(program.stack.peek().getData()).toUpperCase()); } @Test(expected=RuntimeException.class) // JUMP OP mal data @@ -1705,7 +1705,7 @@ public class VMTest { vm.step(program); program.getResult().getRepository().close(); - assertEquals(s_expected, Hex.toHexString(program.stack.peek().data).toUpperCase()); + assertEquals(s_expected, Hex.toHexString(program.stack.peek().getData()).toUpperCase()); } @@ -1727,8 +1727,8 @@ public class VMTest { DataWord item2 = program.stack.pop(); program.getResult().getRepository().close(); - assertEquals(s_expected_1, Hex.toHexString(item1.data).toUpperCase()); - assertEquals(s_expected_2, Hex.toHexString(item2.data).toUpperCase()); + assertEquals(s_expected_1, Hex.toHexString(item1.getData()).toUpperCase()); + assertEquals(s_expected_2, Hex.toHexString(item2.getData()).toUpperCase()); } @Test(expected=RuntimeException.class) // JUMPI OP mal @@ -1775,7 +1775,7 @@ public class VMTest { DataWord item1 = program.stack.pop(); program.getResult().getRepository().close(); - assertEquals(s_expected_1, Hex.toHexString(item1.data).toUpperCase()); + assertEquals(s_expected_1, Hex.toHexString(item1.getData()).toUpperCase()); } @Test // ADD OP @@ -1791,7 +1791,7 @@ public class VMTest { DataWord item1 = program.stack.pop(); program.getResult().getRepository().close(); - assertEquals(s_expected_1, Hex.toHexString(item1.data).toUpperCase()); + assertEquals(s_expected_1, Hex.toHexString(item1.getData()).toUpperCase()); } @Test // ADD OP @@ -1807,7 +1807,7 @@ public class VMTest { DataWord item1 = program.stack.pop(); program.getResult().getRepository().close(); - assertEquals(s_expected_1, Hex.toHexString(item1.data).toUpperCase()); + assertEquals(s_expected_1, Hex.toHexString(item1.getData()).toUpperCase()); } @Test(expected=RuntimeException.class) // ADD OP mal @@ -1838,7 +1838,7 @@ public class VMTest { DataWord item1 = program.stack.pop(); program.getResult().getRepository().close(); - assertEquals(s_expected_1, Hex.toHexString(item1.data).toUpperCase()); + assertEquals(s_expected_1, Hex.toHexString(item1.getData()).toUpperCase()); } @Test // MULL OP @@ -1854,7 +1854,7 @@ public class VMTest { DataWord item1 = program.stack.pop(); program.getResult().getRepository().close(); - assertEquals(s_expected_1, Hex.toHexString(item1.data).toUpperCase()); + assertEquals(s_expected_1, Hex.toHexString(item1.getData()).toUpperCase()); } @Test // MULL OP @@ -1870,7 +1870,7 @@ public class VMTest { DataWord item1 = program.stack.pop(); program.getResult().getRepository().close(); - assertEquals(s_expected_1, Hex.toHexString(item1.data).toUpperCase()); + assertEquals(s_expected_1, Hex.toHexString(item1.getData()).toUpperCase()); } @Test(expected=RuntimeException.class) // MULL OP mal @@ -1901,7 +1901,7 @@ public class VMTest { DataWord item1 = program.stack.pop(); program.getResult().getRepository().close(); - assertEquals(s_expected_1, Hex.toHexString(item1.data).toUpperCase()); + assertEquals(s_expected_1, Hex.toHexString(item1.getData()).toUpperCase()); } @Test // DIV OP @@ -1917,7 +1917,7 @@ public class VMTest { DataWord item1 = program.stack.pop(); program.getResult().getRepository().close(); - assertEquals(s_expected_1, Hex.toHexString(item1.data).toUpperCase()); + assertEquals(s_expected_1, Hex.toHexString(item1.getData()).toUpperCase()); } @@ -1934,7 +1934,7 @@ public class VMTest { DataWord item1 = program.stack.pop(); program.getResult().getRepository().close(); - assertEquals(s_expected_1, Hex.toHexString(item1.data).toUpperCase()); + assertEquals(s_expected_1, Hex.toHexString(item1.getData()).toUpperCase()); } @Test // DIV OP @@ -1950,7 +1950,7 @@ public class VMTest { DataWord item1 = program.stack.pop(); program.getResult().getRepository().close(); - assertEquals(s_expected_1, Hex.toHexString(item1.data).toUpperCase()); + assertEquals(s_expected_1, Hex.toHexString(item1.getData()).toUpperCase()); } @@ -1967,7 +1967,7 @@ public class VMTest { DataWord item1 = program.stack.pop(); program.getResult().getRepository().close(); - assertEquals(s_expected_1, Hex.toHexString(item1.data).toUpperCase()); + assertEquals(s_expected_1, Hex.toHexString(item1.getData()).toUpperCase()); } @Test(expected=RuntimeException.class) // DIV OP @@ -1998,7 +1998,7 @@ public class VMTest { DataWord item1 = program.stack.pop(); program.getResult().getRepository().close(); - assertEquals(s_expected_1, Hex.toHexString(item1.data).toUpperCase()); + assertEquals(s_expected_1, Hex.toHexString(item1.getData()).toUpperCase()); } @Test // SDIV OP @@ -2014,7 +2014,7 @@ public class VMTest { DataWord item1 = program.stack.pop(); program.getResult().getRepository().close(); - assertEquals(s_expected_1, Hex.toHexString(item1.data).toUpperCase()); + assertEquals(s_expected_1, Hex.toHexString(item1.getData()).toUpperCase()); } @Test // SDIV OP @@ -2030,7 +2030,7 @@ public class VMTest { DataWord item1 = program.stack.pop(); program.getResult().getRepository().close(); - assertEquals(s_expected_1, Hex.toHexString(item1.data).toUpperCase()); + assertEquals(s_expected_1, Hex.toHexString(item1.getData()).toUpperCase()); } @Test(expected=RuntimeException.class) // SDIV OP mal @@ -2061,7 +2061,7 @@ public class VMTest { vm.step(program); DataWord item1 = program.stack.pop(); - assertEquals(s_expected_1, Hex.toHexString(item1.data).toUpperCase()); + assertEquals(s_expected_1, Hex.toHexString(item1.getData()).toUpperCase()); program.getResult().getRepository().close(); } @@ -2078,7 +2078,7 @@ public class VMTest { DataWord item1 = program.stack.pop(); program.getResult().getRepository().close(); - assertEquals(s_expected_1, Hex.toHexString(item1.data).toUpperCase()); + assertEquals(s_expected_1, Hex.toHexString(item1.getData()).toUpperCase()); } @Test // SUB OP @@ -2094,7 +2094,7 @@ public class VMTest { DataWord item1 = program.stack.pop(); program.getResult().getRepository().close(); - assertEquals(s_expected_1, Hex.toHexString(item1.data).toUpperCase()); + assertEquals(s_expected_1, Hex.toHexString(item1.getData()).toUpperCase()); } @Test(expected=RuntimeException.class) // SUB OP mal @@ -2123,7 +2123,7 @@ public class VMTest { DataWord item1 = program.stack.pop(); program.getResult().getRepository().close(); - assertEquals(s_expected_1, Hex.toHexString(item1.data).toUpperCase()); + assertEquals(s_expected_1, Hex.toHexString(item1.getData()).toUpperCase()); } @Test // MSIZE OP @@ -2140,7 +2140,7 @@ public class VMTest { DataWord item1 = program.stack.pop(); program.getResult().getRepository().close(); - assertEquals(s_expected_1, Hex.toHexString(item1.data).toUpperCase()); + assertEquals(s_expected_1, Hex.toHexString(item1.getData()).toUpperCase()); } @@ -2175,7 +2175,7 @@ public class VMTest { DataWord item1 = program.stack.pop(); program.getResult().getRepository().close(); - assertEquals(s_expected_1, Hex.toHexString(item1.data).toUpperCase()); + assertEquals(s_expected_1, Hex.toHexString(item1.getData()).toUpperCase()); } @Test // EXP OP @@ -2191,7 +2191,7 @@ public class VMTest { DataWord item1 = program.stack.pop(); program.getResult().getRepository().close(); - assertEquals(s_expected_1, Hex.toHexString(item1.data).toUpperCase()); + assertEquals(s_expected_1, Hex.toHexString(item1.getData()).toUpperCase()); } @Test(expected=RuntimeException.class) // EXP OP mal @@ -2421,7 +2421,7 @@ public class VMTest { DataWord item1 = program.stack.pop(); program.getResult().getRepository().close(); - assertEquals(s_expected_1, Hex.toHexString(item1.data).toUpperCase()); + assertEquals(s_expected_1, Hex.toHexString(item1.getData()).toUpperCase()); } @Test // CALLDATASIZE OP @@ -2437,7 +2437,7 @@ public class VMTest { DataWord item1 = program.stack.pop(); program.getResult().getRepository().close(); - assertEquals(s_expected_1, Hex.toHexString(item1.data).toUpperCase()); + assertEquals(s_expected_1, Hex.toHexString(item1.getData()).toUpperCase()); } @@ -2455,7 +2455,7 @@ public class VMTest { DataWord item1 = program.stack.pop(); program.getResult().getRepository().close(); - assertEquals(s_expected_1, Hex.toHexString(item1.data).toUpperCase()); + assertEquals(s_expected_1, Hex.toHexString(item1.getData()).toUpperCase()); } @Test // CALLDATALOAD OP @@ -2472,7 +2472,7 @@ public class VMTest { DataWord item1 = program.stack.pop(); program.getResult().getRepository().close(); - assertEquals(s_expected_1, Hex.toHexString(item1.data).toUpperCase()); + assertEquals(s_expected_1, Hex.toHexString(item1.getData()).toUpperCase()); } @@ -2490,7 +2490,7 @@ public class VMTest { DataWord item1 = program.stack.pop(); program.getResult().getRepository().close(); - assertEquals(s_expected_1, Hex.toHexString(item1.data).toUpperCase()); + assertEquals(s_expected_1, Hex.toHexString(item1.getData()).toUpperCase()); } @@ -2508,7 +2508,7 @@ public class VMTest { DataWord item1 = program.stack.pop(); program.getResult().getRepository().close(); - assertEquals(s_expected_1, Hex.toHexString(item1.data).toUpperCase()); + assertEquals(s_expected_1, Hex.toHexString(item1.getData()).toUpperCase()); } @Test // CALLDATALOAD OP @@ -2525,7 +2525,7 @@ public class VMTest { DataWord item1 = program.stack.pop(); program.getResult().getRepository().close(); - assertEquals(s_expected_1, Hex.toHexString(item1.data).toUpperCase()); + assertEquals(s_expected_1, Hex.toHexString(item1.getData()).toUpperCase()); } @Test(expected=RuntimeException.class) // CALLDATALOAD OP mal @@ -2675,7 +2675,7 @@ public class VMTest { DataWord item1 = program.stack.pop(); program.getResult().getRepository().close(); - assertEquals(s_expected_1, Hex.toHexString(item1.data).toUpperCase()); + assertEquals(s_expected_1, Hex.toHexString(item1.getData()).toUpperCase()); } @Test // BALANCE OP @@ -2692,7 +2692,7 @@ public class VMTest { DataWord item1 = program.stack.pop(); program.getResult().getRepository().close(); - assertEquals(s_expected_1, Hex.toHexString(item1.data).toUpperCase()); + assertEquals(s_expected_1, Hex.toHexString(item1.getData()).toUpperCase()); } @Test // ORIGIN OP @@ -2708,7 +2708,7 @@ public class VMTest { DataWord item1 = program.stack.pop(); program.getResult().getRepository().close(); - assertEquals(s_expected_1, Hex.toHexString(item1.data).toUpperCase()); + assertEquals(s_expected_1, Hex.toHexString(item1.getData()).toUpperCase()); } @Test // CALLER OP @@ -2724,7 +2724,7 @@ public class VMTest { DataWord item1 = program.stack.pop(); program.getResult().getRepository().close(); - assertEquals(s_expected_1, Hex.toHexString(item1.data).toUpperCase()); + assertEquals(s_expected_1, Hex.toHexString(item1.getData()).toUpperCase()); } @Test // CALLVALUE OP @@ -2740,7 +2740,7 @@ public class VMTest { DataWord item1 = program.stack.pop(); program.getResult().getRepository().close(); - assertEquals(s_expected_1, Hex.toHexString(item1.data).toUpperCase()); + assertEquals(s_expected_1, Hex.toHexString(item1.getData()).toUpperCase()); } @Test // SHA3 OP @@ -2761,7 +2761,7 @@ public class VMTest { DataWord item1 = program.stack.pop(); program.getResult().getRepository().close(); - assertEquals(s_expected_1, Hex.toHexString(item1.data).toUpperCase()); + assertEquals(s_expected_1, Hex.toHexString(item1.getData()).toUpperCase()); } @Test // SHA3 OP @@ -2782,7 +2782,7 @@ public class VMTest { DataWord item1 = program.stack.pop(); program.getResult().getRepository().close(); - assertEquals(s_expected_1, Hex.toHexString(item1.data).toUpperCase()); + assertEquals(s_expected_1, Hex.toHexString(item1.getData()).toUpperCase()); } @Test(expected=RuntimeException.class) // SHA3 OP mal @@ -2817,7 +2817,7 @@ public class VMTest { DataWord item1 = program.stack.pop(); program.getResult().getRepository().close(); - assertEquals(s_expected_1, Hex.toHexString(item1.data).toUpperCase()); + assertEquals(s_expected_1, Hex.toHexString(item1.getData()).toUpperCase()); } @Test // MOD OP @@ -2832,7 +2832,7 @@ public class VMTest { DataWord item1 = program.stack.pop(); program.getResult().getRepository().close(); - assertEquals(s_expected_1, Hex.toHexString(item1.data).toUpperCase()); + assertEquals(s_expected_1, Hex.toHexString(item1.getData()).toUpperCase()); } @Test // MOD OP @@ -2847,7 +2847,7 @@ public class VMTest { DataWord item1 = program.stack.pop(); program.getResult().getRepository().close(); - assertEquals(s_expected_1, Hex.toHexString(item1.data).toUpperCase()); + assertEquals(s_expected_1, Hex.toHexString(item1.getData()).toUpperCase()); } @Test(expected=RuntimeException.class) // MOD OP mal @@ -2879,7 +2879,7 @@ public class VMTest { DataWord item1 = program.stack.pop(); program.getResult().getRepository().close(); - assertEquals(s_expected_1, Hex.toHexString(item1.data).toUpperCase()); + assertEquals(s_expected_1, Hex.toHexString(item1.getData()).toUpperCase()); } @Test // SMOD OP @@ -2896,7 +2896,7 @@ public class VMTest { DataWord item1 = program.stack.pop(); program.getResult().getRepository().close(); - assertEquals(s_expected_1, Hex.toHexString(item1.data).toUpperCase()); + assertEquals(s_expected_1, Hex.toHexString(item1.getData()).toUpperCase()); } @Test // SMOD OP @@ -2913,7 +2913,7 @@ public class VMTest { DataWord item1 = program.stack.pop(); program.getResult().getRepository().close(); - assertEquals(s_expected_1, Hex.toHexString(item1.data).toUpperCase()); + assertEquals(s_expected_1, Hex.toHexString(item1.getData()).toUpperCase()); } @Test(expected=RuntimeException.class) // SMOD OP mal @@ -2944,7 +2944,7 @@ public class VMTest { DataWord item1 = program.stack.pop(); program.getResult().getRepository().close(); - assertEquals(s_expected_1, Hex.toHexString(item1.data).toUpperCase()); + assertEquals(s_expected_1, Hex.toHexString(item1.getData()).toUpperCase()); } @Test // COINBASE OP @@ -2960,7 +2960,7 @@ public class VMTest { DataWord item1 = program.stack.pop(); program.getResult().getRepository().close(); - assertEquals(s_expected_1, Hex.toHexString(item1.data).toUpperCase()); + assertEquals(s_expected_1, Hex.toHexString(item1.getData()).toUpperCase()); } @Test // TIMESTAMP OP @@ -2976,7 +2976,7 @@ public class VMTest { DataWord item1 = program.stack.pop(); program.getResult().getRepository().close(); - assertEquals(s_expected_1, Hex.toHexString(item1.data).toUpperCase()); + assertEquals(s_expected_1, Hex.toHexString(item1.getData()).toUpperCase()); } @Test // NUMBER OP @@ -2992,7 +2992,7 @@ public class VMTest { DataWord item1 = program.stack.pop(); program.getResult().getRepository().close(); - assertEquals(s_expected_1, Hex.toHexString(item1.data).toUpperCase()); + assertEquals(s_expected_1, Hex.toHexString(item1.getData()).toUpperCase()); } @Test // DIFFICULTY OP @@ -3008,7 +3008,7 @@ public class VMTest { DataWord item1 = program.stack.pop(); program.getResult().getRepository().close(); - assertEquals(s_expected_1, Hex.toHexString(item1.data).toUpperCase()); + assertEquals(s_expected_1, Hex.toHexString(item1.getData()).toUpperCase()); } @Test // GASPRICE OP @@ -3024,7 +3024,7 @@ public class VMTest { DataWord item1 = program.stack.pop(); program.getResult().getRepository().close(); - assertEquals(s_expected_1, Hex.toHexString(item1.data).toUpperCase()); + assertEquals(s_expected_1, Hex.toHexString(item1.getData()).toUpperCase()); } @Test // GAS OP @@ -3040,7 +3040,7 @@ public class VMTest { DataWord item1 = program.stack.pop(); program.getResult().getRepository().close(); - assertEquals(s_expected_1, Hex.toHexString(item1.data).toUpperCase()); + assertEquals(s_expected_1, Hex.toHexString(item1.getData()).toUpperCase()); } @Test // GASLIMIT OP @@ -3056,7 +3056,7 @@ public class VMTest { DataWord item1 = program.stack.pop(); program.getResult().getRepository().close(); - assertEquals(s_expected_1, Hex.toHexString(item1.data).toUpperCase()); + assertEquals(s_expected_1, Hex.toHexString(item1.getData()).toUpperCase()); } /* TEST CASE LIST END */ From 2b42ebaac2cad23b570f04777844741e95bf7c33 Mon Sep 17 00:00:00 2001 From: nicksavers Date: Sat, 2 Aug 2014 13:48:38 +0200 Subject: [PATCH 7/7] Use Repository as abstraction layer for Blockchain --- .../main/java/org/ethereum/core/Block.java | 2 +- .../java/org/ethereum/core/Blockchain.java | 331 ++++++++++++++---- .../java/org/ethereum/db/ContractDetails.java | 10 +- .../main/java/org/ethereum/db/Repository.java | 121 +++++-- .../org/ethereum/facade/EthereumImpl.java | 4 +- .../org/ethereum/gui/BlockChainTable.java | 10 +- .../org/ethereum/gui/BlockTableModel.java | 4 +- .../org/ethereum/gui/ContractCallDialog.java | 2 +- .../ethereum/gui/ContractSubmitDialog.java | 4 +- .../java/org/ethereum/gui/PayOutDialog.java | 4 +- .../main/java/org/ethereum/gui/ToolBar.java | 3 +- .../org/ethereum/manager/WorldManager.java | 272 +------------- .../java/org/ethereum/net/BlockQueue.java | 10 +- .../net/client/EthereumFrameDecoder.java | 1 - .../net/client/EthereumProtocolHandler.java | 9 +- .../ethereum/net/message/GetChainMessage.java | 2 +- .../ethereum/net/message/GetPeersMessage.java | 2 +- .../org/ethereum/net/message/PingMessage.java | 10 +- .../main/java/org/ethereum/trie/Cache.java | 5 +- .../src/main/java/org/ethereum/trie/Trie.java | 4 + .../ethereum/util/AdvancedDeviceUtils.java | 3 - .../org/ethereum/vm/ProgramInvokeFactory.java | 2 +- .../main/resources/log4j-detailed.properties | 4 +- .../src/main/resources/log4j.properties | 4 +- .../src/main/resources/system.properties | 2 +- .../java/org/ethereum/core/BlockTest.java | 4 +- 26 files changed, 421 insertions(+), 408 deletions(-) diff --git a/ethereumj-core/src/main/java/org/ethereum/core/Block.java b/ethereumj-core/src/main/java/org/ethereum/core/Block.java index 0cfb9088..745f13c6 100644 --- a/ethereumj-core/src/main/java/org/ethereum/core/Block.java +++ b/ethereumj-core/src/main/java/org/ethereum/core/Block.java @@ -110,7 +110,7 @@ public class Block { } public Block getParent() { - return WorldManager.getInstance().getBlockChain().getByNumber(this.getNumber() - 1); + return WorldManager.getInstance().getBlockchain().getByNumber(this.getNumber() - 1); } public byte[] getParentHash() { diff --git a/ethereumj-core/src/main/java/org/ethereum/core/Blockchain.java b/ethereumj-core/src/main/java/org/ethereum/core/Blockchain.java index 3afb32ae..34a532e0 100644 --- a/ethereumj-core/src/main/java/org/ethereum/core/Blockchain.java +++ b/ethereumj-core/src/main/java/org/ethereum/core/Blockchain.java @@ -1,17 +1,18 @@ package org.ethereum.core; -import org.ethereum.db.DatabaseImpl; +import org.ethereum.db.Repository; import org.ethereum.listener.EthereumListener; import org.ethereum.manager.WorldManager; +import org.ethereum.net.BlockQueue; import org.ethereum.util.AdvancedDeviceUtils; -import org.ethereum.util.ByteUtil; -import org.iq80.leveldb.DBIterator; +import org.ethereum.vm.*; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.spongycastle.util.encoders.Hex; -import java.io.IOException; +import java.math.BigInteger; import java.util.Arrays; +import java.util.Collections; import java.util.HashMap; import java.util.Map; @@ -53,21 +54,39 @@ import static org.ethereum.core.Denomination.SZABO; public class Blockchain { private static Logger logger = LoggerFactory.getLogger("blockchain"); + private static Logger stateLogger = LoggerFactory.getLogger("state"); // to avoid using minGasPrice=0 from Genesis for the wallet private static long INITIAL_MIN_GAS_PRICE = 10 * SZABO.longValue(); - - private DatabaseImpl chainDb; - + + private Repository repository; private Block lastBlock; // keep the index of the chain for // convenient usage, - private Map index = new HashMap<>(); + private Map blockCache = new HashMap<>(); + + private Map pendingTransactions = Collections + .synchronizedMap(new HashMap()); + + private BlockQueue blockQueue = new BlockQueue(); - public Blockchain() { - this.chainDb = new DatabaseImpl("blockchain"); + public Blockchain(Repository repository) { + this.repository = repository; } + + public BlockQueue getBlockQueue() { + return blockQueue; + } + + public Map getBlockCache() { + return this.blockCache; + } + + public long getGasPrice() { + // In case of the genesis block we don't want to rely on the min gas price + return lastBlock.isGenesis() ? lastBlock.getMinGasPrice() : INITIAL_MIN_GAS_PRICE; + } public Block getLastBlock() { return lastBlock; @@ -77,12 +96,19 @@ public class Blockchain { this.lastBlock = block; } + public byte[] getLatestBlockHash() { + if (blockCache.isEmpty()) + return Genesis.getInstance().getHash(); + else + return getLastBlock().getHash(); + } + public int getSize() { - return index.size(); + return blockCache.size(); } public Block getByNumber(long blockNr) { - return new Block(chainDb.get(ByteUtil.longToBytes(blockNr))); + return repository.getBlock(blockNr); } public void add(Block block) { @@ -92,13 +118,13 @@ public class Blockchain { // if it is the first block to add // make sure the parent is genesis - if (index.isEmpty() + if (blockCache.isEmpty() && !Arrays.equals(Genesis.getInstance().getHash(), block.getParentHash())) { return; } // if there is some blocks already keep chain continuity - if (!index.isEmpty()) { + if (!blockCache.isEmpty()) { String hashLast = Hex.toHexString(getLastBlock().getHash()); String blockParentHash = Hex.toHexString(block.getParentHash()); if (!hashLast.equals(blockParentHash)) return; @@ -120,16 +146,7 @@ public class Blockchain { EthereumListener listener = WorldManager.getInstance().getListener(); if (listener != null) listener.trace(String.format("Block chain size: [ %d ]", this.getSize())); - -/* - if (lastBlock.getNumber() >= 30) { - System.out.println("** checkpoint **"); - this.close(); - WorldManager.getInstance().getRepository().close(); - System.exit(1); - } -*/ } public void processBlock(Block block) { @@ -138,7 +155,7 @@ public class Blockchain { for (Transaction tx : block.getTransactionsList()) // TODO: refactor the wallet pending transactions to the world manager WorldManager.getInstance().addWalletTransaction(tx); - WorldManager.getInstance().applyBlock(block); + this.applyBlock(block); WorldManager.getInstance().getWallet().processBlock(block); } this.storeBlock(block); @@ -147,7 +164,7 @@ public class Blockchain { } } - private void storeBlock(Block block) { + public void storeBlock(Block block) { /* Debug check to see if the state is still as expected */ if(logger.isWarnEnabled()) { String blockStateRootHash = Hex.toHexString(block.getStateRoot()); @@ -155,12 +172,13 @@ public class Blockchain { if(!blockStateRootHash.equals(worldStateRootHash)){ logger.error("ERROR: STATE CONFLICT! block: {} worldstate {} mismatch", block.getNumber(), worldStateRootHash); // Last conflict on block 1157 -> worldstate b1d9a978451ef04c1639011d9516473d51c608dbd25906c89be791707008d2de + repository.close(); System.exit(-1); // Don't add block } } - this.chainDb.put(ByteUtil.longToBytes(block.getNumber()), block.getEncoded()); - this.index.put(block.getNumber(), block.getHash()); + this.repository.saveBlock(block); + this.blockCache.put(block.getNumber(), block.getHash()); this.setLastBlock(block); if (logger.isDebugEnabled()) @@ -168,46 +186,233 @@ public class Blockchain { logger.info("*** Block chain size: [ {} ]", this.getSize()); } - public long getGasPrice() { - // In case of the genesis block we don't want to rely on the min gas price - return lastBlock.isGenesis() ? lastBlock.getMinGasPrice() : INITIAL_MIN_GAS_PRICE; - } + public void applyBlock(Block block) { + + int i = 0; + for (Transaction tx : block.getTransactionsList()) { + stateLogger.debug("apply block: [ {} ] tx: [ {} ] ", block.getNumber(), i); + applyTransaction(block, tx, block.getCoinbase()); + repository.dumpState(block.getNumber(), i, tx.getHash()); + ++i; - public byte[] getLatestBlockHash() { - if (index.isEmpty()) - return Genesis.getInstance().getHash(); - else - return getLastBlock().getHash(); - } + } + + // miner reward + if (repository.getAccountState(block.getCoinbase()) == null) + repository.createAccount(block.getCoinbase()); + repository.addBalance(block.getCoinbase(), Block.BLOCK_REWARD); + for (Block uncle : block.getUncleList()) { + repository.addBalance(uncle.getCoinbase(), Block.UNCLE_REWARD); + } + + repository.dumpState(block.getNumber(), 0, + null); + } - public void load() { - DBIterator iterator = chainDb.iterator(); - try { - if (!iterator.hasNext()) { - logger.info("DB is empty - adding Genesis"); - this.lastBlock = Genesis.getInstance(); - this.storeBlock(lastBlock); - logger.debug("Block #{} -> {}", Genesis.NUMBER, lastBlock.toFlatString()); - } else { - logger.debug("Displaying blocks stored in DB sorted on blocknumber"); - for (iterator.seekToFirst(); iterator.hasNext();) { - this.lastBlock = new Block(iterator.next().getValue()); - this.index.put(lastBlock.getNumber(), lastBlock.getHash()); - logger.debug("Block #{} -> {}", lastBlock.getNumber(), lastBlock.toFlatString()); - } - } - } finally { - // Make sure you close the iterator to avoid resource leaks. - try { - iterator.close(); - } catch (IOException e) { - logger.error(e.getMessage(), e); + public void applyTransaction(Block block, Transaction tx, byte[] coinbase) { + + byte[] senderAddress = tx.getSender(); + AccountState senderAccount = repository.getAccountState(senderAddress); + + if (senderAccount == null) { + if (stateLogger.isWarnEnabled()) + stateLogger.warn("No such address: {}", + Hex.toHexString(senderAddress)); + return; + } + + // 1. VALIDATE THE NONCE + BigInteger nonce = senderAccount.getNonce(); + BigInteger txNonce = new BigInteger(1, tx.getNonce()); + if (nonce.compareTo(txNonce) != 0) { + if (stateLogger.isWarnEnabled()) + stateLogger.warn("Invalid nonce account.nonce={} tx.nonce={}", + nonce, txNonce); + return; + } + + // 3. FIND OUT THE TRANSACTION TYPE + byte[] receiverAddress, code = null; + boolean isContractCreation = tx.isContractCreation(); + if (isContractCreation) { + receiverAddress = tx.getContractAddress(); + repository.createAccount(receiverAddress); + if(stateLogger.isDebugEnabled()) + stateLogger.debug("new contract created address={}", + Hex.toHexString(receiverAddress)); + code = tx.getData(); // init code + if (stateLogger.isDebugEnabled()) + stateLogger.debug("running the init for contract: address={}", + Hex.toHexString(receiverAddress)); + } else { + receiverAddress = tx.getReceiveAddress(); + AccountState receiverState = repository.getAccountState(receiverAddress); + if (receiverState == null) { + repository.createAccount(receiverAddress); + if (stateLogger.isDebugEnabled()) + stateLogger.debug("new receiver account created address={}", + Hex.toHexString(receiverAddress)); + } else { + code = repository.getCode(receiverAddress); + if (code != null) { + if (stateLogger.isDebugEnabled()) + stateLogger.debug("calling for existing contract: address={}", + Hex.toHexString(receiverAddress)); + } } } + + // 2.1 UPDATE THE NONCE + // (THIS STAGE IS NOT REVERTED BY ANY EXCEPTION) + repository.increaseNonce(senderAddress); + + // 2.2 PERFORM THE GAS VALUE TX + // (THIS STAGE IS NOT REVERTED BY ANY EXCEPTION) + BigInteger gasDebit = tx.getTotalGasValueDebit(); + + // Debit the actual total gas value from the sender + // the purchased gas will be available for + // the contract in the execution state, + // it can be retrieved using GAS op + if (gasDebit.signum() == 1) { + BigInteger balance = senderAccount.getBalance(); + if (balance.compareTo(gasDebit) == -1) { + logger.debug("No gas to start the execution: sender={}", + Hex.toHexString(senderAddress)); + return; + } + repository.addBalance(senderAddress, gasDebit.negate()); + + // The coinbase get the gas cost + if (coinbase != null) + repository.addBalance(coinbase, gasDebit); + + if (stateLogger.isDebugEnabled()) + stateLogger.debug( + "Before contract execution debit the sender address with gas total cost, " + + "\n sender={} \n gas_debit= {}", + Hex.toHexString(senderAddress), gasDebit); + } + + // 3. START TRACKING FOR REVERT CHANGES OPTION !!! + Repository trackRepository = repository.getTrack(); + trackRepository.startTracking(); + + try { + + // 4. THE SIMPLE VALUE/BALANCE CHANGE + if (tx.getValue() != null) { + + BigInteger senderBalance = senderAccount.getBalance(); + + if (senderBalance.compareTo(new BigInteger(1, tx.getValue())) >= 0) { + repository.addBalance(receiverAddress, + new BigInteger(1, tx.getValue())); + repository.addBalance(senderAddress, + new BigInteger(1, tx.getValue()).negate()); + + if (stateLogger.isDebugEnabled()) + stateLogger.debug("Update value balance \n " + + "sender={}, receiver={}, value={}", + Hex.toHexString(senderAddress), + Hex.toHexString(receiverAddress), + new BigInteger(tx.getValue())); + } + } + + // 5. CREATE OR EXECUTE PROGRAM + if (isContractCreation || code != null) { + Block currBlock = (block == null) ? this.getLastBlock() : block; + + ProgramInvoke programInvoke = ProgramInvokeFactory + .createProgramInvoke(tx, currBlock, trackRepository); + + VM vm = new VM(); + Program program = new Program(code, programInvoke); + + if (CONFIG.playVM()) + vm.play(program); + ProgramResult result = program.getResult(); + applyProgramResult(result, gasDebit, trackRepository, + senderAddress, receiverAddress, coinbase, isContractCreation); + } else { + // refund everything except fee (500 + 5*txdata) + BigInteger gasPrice = new BigInteger(1, tx.getGasPrice()); + long dataFee = tx.getData() == null ? 0: tx.getData().length * GasCost.TXDATA; + long minTxFee = GasCost.TRANSACTION + dataFee; + BigInteger refund = gasDebit.subtract(BigInteger.valueOf( + minTxFee).multiply(gasPrice)); + if (refund.signum() > 0) { + // gas refund + repository.addBalance(senderAddress, refund); + repository.addBalance(coinbase, refund.negate()); + } + } + } catch (RuntimeException e) { + trackRepository.rollback(); + return; + } + trackRepository.commit(); + pendingTransactions.put(Hex.toHexString(tx.getHash()), tx); } - public void close() { - if (this.chainDb != null) - chainDb.close(); - } + /** + * After any contract code finish the run the certain result should take + * place, according the given circumstances + * + * @param result + * @param gasDebit + * @param senderAddress + * @param contractAddress + */ + private void applyProgramResult(ProgramResult result, BigInteger gasDebit, + Repository repository, byte[] senderAddress, + byte[] contractAddress, byte[] coinbase, boolean initResults) { + + if (result.getException() != null + && result.getException() instanceof Program.OutOfGasException) { + stateLogger.debug("contract run halted by OutOfGas: contract={}", + Hex.toHexString(contractAddress)); + throw result.getException(); + } + + BigInteger gasPrice = BigInteger.valueOf(this.getGasPrice()); + BigInteger refund = gasDebit.subtract(BigInteger.valueOf( + result.getGasUsed()).multiply(gasPrice)); + + if (refund.signum() > 0) { + if (stateLogger.isDebugEnabled()) + stateLogger + .debug("After contract execution the sender address refunded with gas leftover, " + + "\n sender={} \n contract={} \n gas_refund= {}", + Hex.toHexString(senderAddress), + Hex.toHexString(contractAddress), refund); + // gas refund + repository.addBalance(senderAddress, refund); + repository.addBalance(coinbase, refund.negate()); + } + + if (initResults) { + // Save the code created by init + byte[] bodyCode = null; + if (result.getHReturn() != null) { + bodyCode = result.getHReturn().array(); + } + + if (bodyCode != null) { + if (stateLogger.isDebugEnabled()) + stateLogger + .debug("saving code of the contract to the db:\n contract={} code={}", + Hex.toHexString(contractAddress), + Hex.toHexString(bodyCode)); + repository.saveCode(contractAddress, bodyCode); + } + } + + // delete the marked to die accounts + if (result.getDeleteAccounts() == null) return; + for (DataWord address : result.getDeleteAccounts()){ + repository.delete(address.getNoLeadZeroesData()); + } + } } diff --git a/ethereumj-core/src/main/java/org/ethereum/db/ContractDetails.java b/ethereumj-core/src/main/java/org/ethereum/db/ContractDetails.java index 706696ee..f2520039 100644 --- a/ethereumj-core/src/main/java/org/ethereum/db/ContractDetails.java +++ b/ethereumj-core/src/main/java/org/ethereum/db/ContractDetails.java @@ -23,15 +23,15 @@ public class ContractDetails { private byte[] rlpEncoded; - private List storageKeys = new ArrayList(); - private List storageValues = new ArrayList(); + private List storageKeys = new ArrayList<>(); + private List storageValues = new ArrayList<>(); private byte[] code; private Trie storageTrie = new Trie(null); - public ContractDetails() { - } + public ContractDetails() { + } public ContractDetails(byte[] rlpCode) { decode(rlpCode); @@ -165,7 +165,7 @@ public class ContractDetails { } public Map getStorage() { - Map storage = new HashMap(); + Map storage = new HashMap<>(); for (int i = 0; storageKeys != null && i < storageKeys.size(); ++i) { storage.put(storageKeys.get(i), storageValues.get(i)); } diff --git a/ethereumj-core/src/main/java/org/ethereum/db/Repository.java b/ethereumj-core/src/main/java/org/ethereum/db/Repository.java index 7f90df9d..1de3bc7b 100644 --- a/ethereumj-core/src/main/java/org/ethereum/db/Repository.java +++ b/ethereumj-core/src/main/java/org/ethereum/db/Repository.java @@ -2,6 +2,9 @@ package org.ethereum.db; import org.codehaus.plexus.util.FileUtils; import org.ethereum.core.AccountState; +import org.ethereum.core.Block; +import org.ethereum.core.Blockchain; +import org.ethereum.core.Genesis; import org.ethereum.crypto.HashUtil; import org.ethereum.json.JSONHelper; import org.ethereum.manager.WorldManager; @@ -9,6 +12,7 @@ import org.ethereum.trie.TrackTrie; import org.ethereum.trie.Trie; import org.ethereum.util.ByteUtil; import org.ethereum.vm.DataWord; +import org.iq80.leveldb.DBIterator; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.spongycastle.util.BigIntegers; @@ -56,18 +60,25 @@ public class Repository { // TODO: Listeners listeners // TODO: cash impl - private DatabaseImpl detailsDB = null; - private DatabaseImpl stateDB = null; - + private DatabaseImpl chainDB = null; + private DatabaseImpl detailsDB = null; + private DatabaseImpl stateDB = null; + + /** + * Create a new Repository DAO + * assuming empty db and thus no stateRoot + * + * @See loadBlockchain() to update the stateRoot + */ public Repository() { - detailsDB = new DatabaseImpl("details"); - contractDetailsDB = new TrackDatabase(detailsDB); - stateDB = new DatabaseImpl("state"); - worldState = new Trie(stateDB.getDb()); - accountStateDB = new TrackTrie(worldState); + chainDB = new DatabaseImpl("blockchain"); + detailsDB = new DatabaseImpl("details"); + contractDetailsDB = new TrackDatabase(detailsDB); + stateDB = new DatabaseImpl("state"); + worldState = new Trie(stateDB.getDb()); + accountStateDB = new TrackTrie(worldState); } - private Repository(TrackTrie accountStateDB, TrackDatabase contractDetailsDB) { this.accountStateDB = accountStateDB; this.contractDetailsDB = contractDetailsDB; @@ -80,27 +91,72 @@ public class Repository { } public void startTracking() { - logger.info("start tracking"); + logger.debug("start tracking"); accountStateDB.startTrack(); contractDetailsDB.startTrack(); } public void commit() { - logger.info("commit changes"); + logger.debug("commit changes"); accountStateDB.commitTrack(); contractDetailsDB.commitTrack(); } public void rollback() { - logger.info("rollback changes"); + logger.debug("rollback changes"); accountStateDB.rollbackTrack(); contractDetailsDB.rollbackTrack(); } + + public Block getBlock(long blockNr) { + return new Block(chainDB.get(ByteUtil.longToBytes(blockNr))); + } + + public void saveBlock(Block block) { + this.chainDB.put(ByteUtil.longToBytes(block.getNumber()), block.getEncoded()); + } + + public Blockchain loadBlockchain() { + Blockchain blockchain = new Blockchain(this); + DBIterator iterator = chainDB.iterator(); + try { + if (!iterator.hasNext()) { + logger.info("DB is empty - adding Genesis"); + blockchain.storeBlock(Genesis.getInstance()); + logger.debug("Block #{} -> {}", Genesis.NUMBER, blockchain.getLastBlock().toFlatString()); + } else { + logger.debug("Displaying blocks stored in DB sorted on blocknumber"); + + for (iterator.seekToFirst(); iterator.hasNext();) { + Block block = new Block(iterator.next().getValue()); + blockchain.getBlockCache().put(block.getNumber(), block.getHash()); + blockchain.setLastBlock(block); + logger.debug("Block #{} -> {}", block.getNumber(), block.toFlatString()); + } + logger.info( + "*** Loaded up to block [ {} ] with stateRoot [ {} ]", + blockchain.getLastBlock().getNumber(), Hex + .toHexString(blockchain.getLastBlock() + .getStateRoot())); + } + } finally { + // Make sure you close the iterator to avoid resource leaks. + try { + iterator.close(); + } catch (IOException e) { + logger.error(e.getMessage(), e); + } + } + // Update world state to latest loaded block from db + this.worldState.setRoot(blockchain.getLastBlock().getStateRoot()); + return blockchain; + } + public AccountState createAccount(byte[] addr) { this.validateAddress(addr); - + // 1. Save AccountState AccountState state = new AccountState(); accountStateDB.update(addr, state.getEncoded()); @@ -109,8 +165,8 @@ public class Repository { ContractDetails details = new ContractDetails(); contractDetailsDB.put(addr, details.getEncoded()); - if (logger.isInfoEnabled()) - logger.info("New account created: [ {} ]", Hex.toHexString(addr)); + if (logger.isDebugEnabled()) + logger.debug("New account created: [ {} ]", Hex.toHexString(addr)); return state; } @@ -122,12 +178,10 @@ public class Repository { public AccountState getAccountState(byte[] addr) { this.validateAddress(addr); - + byte[] accountStateRLP = accountStateDB.get(addr); if (accountStateRLP.length == 0) { - if (logger.isInfoEnabled()) - logger.info("No account: [ {} ]", Hex.toHexString(addr)); return null; } AccountState state = new AccountState(accountStateRLP); @@ -138,18 +192,17 @@ public class Repository { this.validateAddress(addr); - if (logger.isInfoEnabled()) - logger.info("Account: [ {} ]", Hex.toHexString(addr)); + if (logger.isDebugEnabled()) + logger.debug("Get contract details for: [ {} ]", Hex.toHexString(addr)); byte[] accountDetailsRLP = contractDetailsDB.get(addr); - if (accountDetailsRLP == null) { return null; } - if (logger.isInfoEnabled()) - logger.info("Contract details RLP: [ {} ]", Hex.toHexString(accountDetailsRLP)); + if (logger.isDebugEnabled()) + logger.debug("Contract details RLP: [ {} ]", Hex.toHexString(accountDetailsRLP)); ContractDetails details = new ContractDetails(accountDetailsRLP); return details; @@ -167,8 +220,8 @@ public class Repository { BigInteger newBalance = state.addToBalance(value); - if (logger.isInfoEnabled()) - logger.info("Changing balance: account: [ {} ] new balance: [ {} ] delta: [ {} ]", + if (logger.isDebugEnabled()) + logger.debug("Changing balance: account: [ {} ] new balance: [ {} ] delta: [ {} ]", Hex.toHexString(addr), newBalance.toString(), value); accountStateDB.update(addr, state.getEncoded()); @@ -197,8 +250,8 @@ public class Repository { if (state == null) return BigInteger.ZERO; state.incrementNonce(); - if (logger.isInfoEnabled()) - logger.info("Incerement nonce: account: [ {} ] new nonce: [ {} ]", + if (logger.isDebugEnabled()) + logger.debug("Incerement nonce: account: [ {} ] new nonce: [ {} ]", Hex.toHexString(addr), state.getNonce().longValue()); accountStateDB.update(addr, state.getEncoded()); @@ -219,8 +272,8 @@ public class Repository { byte[] storageHash = details.getStorageHash(); state.setStateRoot(storageHash); - if (logger.isInfoEnabled()) - logger.info("Storage key/value saved: account: [ {} ]\n key: [ {} ] value: [ {} ]\n new storageHash: [ {} ]", + if (logger.isDebugEnabled()) + logger.debug("Storage key/value saved: account: [ {} ]\n key: [ {} ] value: [ {} ]\n new storageHash: [ {} ]", Hex.toHexString(addr), Hex.toHexString(key.getNoLeadZeroesData()), Hex.toHexString(value.getNoLeadZeroesData()), @@ -272,8 +325,8 @@ public class Repository { byte[] codeHash = HashUtil.sha3(code); state.setCodeHash(codeHash); - if (logger.isInfoEnabled()) - logger.info("Program code saved:\n account: [ {} ]\n codeHash: [ {} ] \n code: [ {} ]", + if (logger.isDebugEnabled()) + logger.debug("Program code saved:\n account: [ {} ]\n codeHash: [ {} ] \n code: [ {} ]", Hex.toHexString(addr), Hex.toHexString(codeHash), Hex.toHexString(code)); @@ -302,7 +355,7 @@ public class Repository { return stateDB.dumpKeys(); } - public void dumpState(long blockNumber, int txNumber, String txHash) { + public void dumpState(long blockNumber, int txNumber, byte[] txHash) { if (!CONFIG.dumpFull()) return; @@ -318,7 +371,7 @@ public class Repository { String fileName = ""; if (txHash != null) fileName = String.format("%d_%d_%s.dmp", - blockNumber, txNumber, txHash.substring(0, 8)); + blockNumber, txNumber, Hex.toHexString(txHash).substring(0, 8)); else fileName = String.format("%d_c.dmp", blockNumber); @@ -381,6 +434,8 @@ public class Repository { worldState.sync(); } + if (this.chainDB != null) + chainDB.close(); if (this.stateDB != null) stateDB.close(); if (this.detailsDB != null) diff --git a/ethereumj-core/src/main/java/org/ethereum/facade/EthereumImpl.java b/ethereumj-core/src/main/java/org/ethereum/facade/EthereumImpl.java index f7fb5754..7b6c4c1b 100644 --- a/ethereumj-core/src/main/java/org/ethereum/facade/EthereumImpl.java +++ b/ethereumj-core/src/main/java/org/ethereum/facade/EthereumImpl.java @@ -85,13 +85,13 @@ public class EthereumImpl implements Ethereum { @Override public Block getBlockByIndex(long index){ - Block block = WorldManager.getInstance().getBlockChain().getByNumber(index); + Block block = WorldManager.getInstance().getBlockchain().getByNumber(index); return block; } @Override public long getBlockChainSize(){ - return WorldManager.getInstance().getBlockChain().getSize(); + return WorldManager.getInstance().getBlockchain().getSize(); } @Override diff --git a/ethereumj-core/src/main/java/org/ethereum/gui/BlockChainTable.java b/ethereumj-core/src/main/java/org/ethereum/gui/BlockChainTable.java index 0a1d0fbf..9c008179 100644 --- a/ethereumj-core/src/main/java/org/ethereum/gui/BlockChainTable.java +++ b/ethereumj-core/src/main/java/org/ethereum/gui/BlockChainTable.java @@ -74,9 +74,9 @@ public class BlockChainTable extends JFrame { @Override public void actionPerformed(ActionEvent e) { - if (WorldManager.getInstance().getBlockChain().getSize() - 1 < lastFindIndex) return; + if (WorldManager.getInstance().getBlockchain().getSize() - 1 < lastFindIndex) return; - Block block = WorldManager.getInstance().getBlockChain().getByNumber(lastFindIndex); + Block block = WorldManager.getInstance().getBlockchain().getByNumber(lastFindIndex); StringSelection stsel = new StringSelection(block.toString()); Clipboard system = Toolkit.getDefaultToolkit().getSystemClipboard(); system.setContents(stsel,stsel); @@ -96,10 +96,10 @@ public class BlockChainTable extends JFrame { return; } - for (int i = lastFindIndex + 1; i < WorldManager.getInstance().getBlockChain().getSize(); ++i) { + for (int i = lastFindIndex + 1; i < WorldManager.getInstance().getBlockchain().getSize(); ++i) { - if (WorldManager.getInstance().getBlockChain().getSize() - 1 < i) return; - Block block = WorldManager.getInstance().getBlockChain().getByNumber(i); + if (WorldManager.getInstance().getBlockchain().getSize() - 1 < i) return; + Block block = WorldManager.getInstance().getBlockchain().getByNumber(i); boolean found = block.toString().toLowerCase().contains(toFind.toLowerCase()); if (found) { // TODO: now we find the first occur diff --git a/ethereumj-core/src/main/java/org/ethereum/gui/BlockTableModel.java b/ethereumj-core/src/main/java/org/ethereum/gui/BlockTableModel.java index d74685d8..b28fcfe7 100644 --- a/ethereumj-core/src/main/java/org/ethereum/gui/BlockTableModel.java +++ b/ethereumj-core/src/main/java/org/ethereum/gui/BlockTableModel.java @@ -16,7 +16,7 @@ public class BlockTableModel extends AbstractTableModel { public int getRowCount() { fireTableDataChanged(); - int rowCount = WorldManager.getInstance().getBlockChain().getSize(); + int rowCount = WorldManager.getInstance().getBlockchain().getSize(); return rowCount; } @@ -31,7 +31,7 @@ public class BlockTableModel extends AbstractTableModel { // byte[] hash = MainData.instance.getAllBlocks().get(rowIndex).getHash(); // return Hex.toHexString(hash); - Block block = WorldManager.getInstance().getBlockChain().getByNumber(rowIndex); + Block block = WorldManager.getInstance().getBlockchain().getByNumber(rowIndex); if (block == null) return ""; return block.toString(); 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 786d536d..a5884d1c 100644 --- a/ethereumj-core/src/main/java/org/ethereum/gui/ContractCallDialog.java +++ b/ethereumj-core/src/main/java/org/ethereum/gui/ContractCallDialog.java @@ -315,7 +315,7 @@ class ContractCallDialog extends JDialog implements MessageAwareDialog { Transaction tx = createTransaction(); if (tx == null) return; - ProgramPlayDialog.createAndShowGUI(programCode, tx, WorldManager.getInstance().getBlockChain().getLastBlock()); + ProgramPlayDialog.createAndShowGUI(programCode, tx, WorldManager.getInstance().getBlockchain().getLastBlock()); } protected JRootPane createRootPane() { diff --git a/ethereumj-core/src/main/java/org/ethereum/gui/ContractSubmitDialog.java b/ethereumj-core/src/main/java/org/ethereum/gui/ContractSubmitDialog.java index 83c37c5c..c65efc06 100644 --- a/ethereumj-core/src/main/java/org/ethereum/gui/ContractSubmitDialog.java +++ b/ethereumj-core/src/main/java/org/ethereum/gui/ContractSubmitDialog.java @@ -107,7 +107,7 @@ class ContractSubmitDialog extends JDialog implements MessageAwareDialog { contractAddrInput.setText(Hex.toHexString(tx.getContractAddress())); ProgramPlayDialog.createAndShowGUI(tx.getData(), tx, - WorldManager.getInstance().getBlockChain().getLastBlock()); + WorldManager.getInstance().getBlockchain().getLastBlock()); }} ); @@ -301,7 +301,7 @@ class ContractSubmitDialog extends JDialog implements MessageAwareDialog { Account account = ((AccountWrapper)creatorAddressCombo.getSelectedItem()).getAccount(); BigInteger currentBalance = account.getBalance(); - BigInteger gasPrice = BigInteger.valueOf(WorldManager.getInstance().getBlockChain().getGasPrice()); + BigInteger gasPrice = BigInteger.valueOf(WorldManager.getInstance().getBlockchain().getGasPrice()); BigInteger gasInput = new BigInteger( this.gasInput.getText()); boolean canAfford = currentBalance.compareTo(gasPrice.multiply(gasInput)) >= 0; diff --git a/ethereumj-core/src/main/java/org/ethereum/gui/PayOutDialog.java b/ethereumj-core/src/main/java/org/ethereum/gui/PayOutDialog.java index c09a4a1c..c6c5c779 100644 --- a/ethereumj-core/src/main/java/org/ethereum/gui/PayOutDialog.java +++ b/ethereumj-core/src/main/java/org/ethereum/gui/PayOutDialog.java @@ -118,7 +118,7 @@ class PayOutDialog extends JDialog implements MessageAwareDialog { byte[] senderPrivKey = account.getEcKey().getPrivKeyBytes(); byte[] nonce = accountState.getNonce() == BigInteger.ZERO ? null : accountState.getNonce().toByteArray(); - byte[] gasPrice = BigInteger.valueOf( WorldManager.getInstance().getBlockChain().getGasPrice()).toByteArray(); + byte[] gasPrice = BigInteger.valueOf( WorldManager.getInstance().getBlockchain().getGasPrice()).toByteArray(); Transaction tx = new Transaction(nonce, gasPrice, BigIntegers .asUnsignedByteArray(fee), address, BigIntegers @@ -193,7 +193,7 @@ class PayOutDialog extends JDialog implements MessageAwareDialog { // check if the tx is affordable BigInteger ammountValue = new BigInteger(amountText); BigInteger feeValue = new BigInteger(feeText); - BigInteger gasPrice = BigInteger.valueOf(WorldManager.getInstance().getBlockChain().getGasPrice()); + BigInteger gasPrice = BigInteger.valueOf(WorldManager.getInstance().getBlockchain().getGasPrice()); BigInteger currentBalance = accountState.getBalance(); boolean canAfford = gasPrice.multiply(feeValue).add(ammountValue).compareTo(currentBalance) != 1; 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 dc5b18be..5ef3d042 100644 --- a/ethereumj-core/src/main/java/org/ethereum/gui/ToolBar.java +++ b/ethereumj-core/src/main/java/org/ethereum/gui/ToolBar.java @@ -6,6 +6,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.swing.*; + import java.awt.*; import java.awt.event.ItemEvent; import java.awt.event.ItemListener; @@ -225,7 +226,7 @@ public class ToolBar extends JFrame { cp.add(chainToggle); cp.add(walletToggle); - WorldManager.getInstance(); + WorldManager.getInstance().loadBlockchain(); } public static void main(String args[]) { 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 80e1e45d..66a709c8 100644 --- a/ethereumj-core/src/main/java/org/ethereum/manager/WorldManager.java +++ b/ethereumj-core/src/main/java/org/ethereum/manager/WorldManager.java @@ -8,7 +8,6 @@ import java.net.UnknownHostException; import java.util.*; import org.ethereum.core.AccountState; -import org.ethereum.core.Block; import org.ethereum.core.Blockchain; import org.ethereum.core.Transaction; import org.ethereum.core.Wallet; @@ -16,12 +15,10 @@ import org.ethereum.crypto.ECKey; import org.ethereum.crypto.HashUtil; import org.ethereum.db.Repository; import org.ethereum.listener.EthereumListener; -import org.ethereum.net.BlockQueue; import org.ethereum.net.client.ClientPeer; import org.ethereum.net.client.PeerData; import org.ethereum.net.peerdiscovery.PeerDiscovery; import org.ethereum.net.submit.WalletTransaction; -import org.ethereum.vm.*; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.spongycastle.util.encoders.Hex; @@ -37,7 +34,6 @@ import org.spongycastle.util.encoders.Hex; public class WorldManager { private Logger logger = LoggerFactory.getLogger("main"); - private Logger stateLogger = LoggerFactory.getLogger("state"); private Blockchain blockchain; private Repository repository; @@ -47,9 +43,6 @@ public class WorldManager { private List peers = Collections.synchronizedList(new ArrayList()); private ClientPeer activePeer; - private Map pendingTransactions = Collections - .synchronizedMap(new HashMap()); - // This map of transaction designed // to approve the tx by external trusted peer private Map walletTransactions = @@ -59,12 +52,10 @@ public class WorldManager { private static WorldManager instance; - private BlockQueue blockQueue = new BlockQueue(); - - public WorldManager() { - this.blockchain = new Blockchain(); + private WorldManager() { this.repository = new Repository(); - + this.blockchain = new Blockchain(repository); + // Initialize PeerData try { InetAddress ip = InetAddress.getByName(CONFIG.peerDiscoveryIP()); @@ -94,246 +85,9 @@ public class WorldManager { public static WorldManager getInstance() { if(instance == null) { instance = new WorldManager(); - instance.blockchain.load(); } return instance; } - - public void applyTransaction(Block block, Transaction tx, byte[] coinbase) { - - byte[] senderAddress = tx.getSender(); - AccountState senderAccount = repository.getAccountState(senderAddress); - - if (senderAccount == null) { - if (stateLogger.isWarnEnabled()) - stateLogger.warn("No such address: {}", - Hex.toHexString(senderAddress)); - return; - } - - // 1. VALIDATE THE NONCE - BigInteger nonce = senderAccount.getNonce(); - BigInteger txNonce = new BigInteger(1, tx.getNonce()); - if (nonce.compareTo(txNonce) != 0) { - if (stateLogger.isWarnEnabled()) - stateLogger.warn("Invalid nonce account.nonce={} tx.nonce={}", - nonce, txNonce); - return; - } - - // 3. FIND OUT THE TRANSACTION TYPE - byte[] receiverAddress, code = null; - boolean isContractCreation = tx.isContractCreation(); - if (isContractCreation) { - receiverAddress = tx.getContractAddress(); - repository.createAccount(receiverAddress); - stateLogger.info("New contract created address={}", - Hex.toHexString(receiverAddress)); - code = tx.getData(); // init code - if (logger.isInfoEnabled()) - logger.info("running the init for contract: address={}", - Hex.toHexString(receiverAddress)); - } else { - receiverAddress = tx.getReceiveAddress(); - AccountState receiverState = repository.getAccountState(receiverAddress); - if (receiverState == null) { - repository.createAccount(receiverAddress); - if (stateLogger.isInfoEnabled()) - stateLogger.info("New receiver account created address={}", - Hex.toHexString(receiverAddress)); - } else { - code = repository.getCode(receiverAddress); - if (code != null) { - if (logger.isInfoEnabled()) - logger.info("calling for existing contract: address={}", - Hex.toHexString(receiverAddress)); - } - } - } - - // 2.1 UPDATE THE NONCE - // (THIS STAGE IS NOT REVERTED BY ANY EXCEPTION) - repository.increaseNonce(senderAddress); - - // 2.2 PERFORM THE GAS VALUE TX - // (THIS STAGE IS NOT REVERTED BY ANY EXCEPTION) - BigInteger gasDebit = tx.getTotalGasValueDebit(); - - // Debit the actual total gas value from the sender - // the purchased gas will be available for - // the contract in the execution state, - // it can be retrieved using GAS op - if (gasDebit.signum() == 1) { - BigInteger balance = senderAccount.getBalance(); - if (balance.compareTo(gasDebit) == -1) { - logger.info("No gas to start the execution: sender={}", - Hex.toHexString(senderAddress)); - return; - } - repository.addBalance(senderAddress, gasDebit.negate()); - - // The coinbase get the gas cost - if (coinbase != null) - repository.addBalance(coinbase, gasDebit); - - - if (stateLogger.isInfoEnabled()) - stateLogger.info( - "Before contract execution debit the sender address with gas total cost, " - + "\n sender={} \n gas_debit= {}", - Hex.toHexString(senderAddress), gasDebit); - } - - // 3. START TRACKING FOR REVERT CHANGES OPTION !!! - Repository trackRepository = repository.getTrack(); - trackRepository.startTracking(); - - try { - - // 4. THE SIMPLE VALUE/BALANCE CHANGE - if (tx.getValue() != null) { - - BigInteger senderBalance = senderAccount.getBalance(); - - if (senderBalance.compareTo(new BigInteger(1, tx.getValue())) >= 0) { - repository.addBalance(receiverAddress, - new BigInteger(1, tx.getValue())); - repository.addBalance(senderAddress, - new BigInteger(1, tx.getValue()).negate()); - - if (stateLogger.isInfoEnabled()) - stateLogger.info("Update value balance \n " - + "sender={}, receiver={}, value={}", - Hex.toHexString(senderAddress), - Hex.toHexString(receiverAddress), - new BigInteger(tx.getValue())); - } - } - - // 5. CREATE OR EXECUTE PROGRAM - if (isContractCreation || code != null) { - Block currBlock = (block == null) ? blockchain.getLastBlock() : block; - - ProgramInvoke programInvoke = ProgramInvokeFactory - .createProgramInvoke(tx, currBlock, trackRepository); - - VM vm = new VM(); - Program program = new Program(code, programInvoke); - - if (CONFIG.playVM()) - vm.play(program); - ProgramResult result = program.getResult(); - applyProgramResult(result, gasDebit, trackRepository, - senderAddress, receiverAddress, coinbase, isContractCreation); - } else { - // refund everything except fee (500 + 5*txdata) - BigInteger gasPrice = new BigInteger(1, tx.getGasPrice()); - long dataFee = tx.getData() == null ? 0: tx.getData().length * GasCost.TXDATA; - long minTxFee = GasCost.TRANSACTION + dataFee; - BigInteger refund = gasDebit.subtract(BigInteger.valueOf( - minTxFee).multiply(gasPrice)); - if (refund.signum() > 0) { - // gas refund - repository.addBalance(senderAddress, refund); - repository.addBalance(coinbase, refund.negate()); - } - } - } catch (RuntimeException e) { - trackRepository.rollback(); - return; - } - trackRepository.commit(); - pendingTransactions.put(Hex.toHexString(tx.getHash()), tx); - } - - /** - * After any contract code finish the run the certain result should take - * place, according the given circumstances - * - * @param result - * @param gasDebit - * @param senderAddress - * @param contractAddress - */ - private void applyProgramResult(ProgramResult result, BigInteger gasDebit, - Repository repository, byte[] senderAddress, - byte[] contractAddress, byte[] coinbase, boolean initResults) { - - if (result.getException() != null - && result.getException() instanceof Program.OutOfGasException) { - logger.info("contract run halted by OutOfGas: contract={}", - Hex.toHexString(contractAddress)); - throw result.getException(); - } - - BigInteger gasPrice = BigInteger.valueOf(blockchain.getGasPrice()); - BigInteger refund = gasDebit.subtract(BigInteger.valueOf( - result.getGasUsed()).multiply(gasPrice)); - - if (refund.signum() > 0) { - if (stateLogger.isInfoEnabled()) - stateLogger - .info("After contract execution the sender address refunded with gas leftover, " - + "\n sender={} \n contract={} \n gas_refund= {}", - Hex.toHexString(senderAddress), - Hex.toHexString(contractAddress), refund); - // gas refund - repository.addBalance(senderAddress, refund); - repository.addBalance(coinbase, refund.negate()); - } - - if (initResults) { - // Save the code created by init - byte[] bodyCode = null; - if (result.getHReturn() != null) { - bodyCode = result.getHReturn().array(); - } - - if (bodyCode != null) { - repository.saveCode(contractAddress, bodyCode); - if (stateLogger.isInfoEnabled()) - stateLogger - .info("saving code of the contract to the db:\n contract={} code={}", - Hex.toHexString(contractAddress), - Hex.toHexString(bodyCode)); - } - } - - // delete the marked to die accounts - if (result.getDeleteAccounts() == null) return; - for (DataWord address : result.getDeleteAccounts()){ - repository.delete(address.getNoLeadZeroesData()); - } - } - - public void applyBlock(Block block) { - - if(block.getNumber() == 1157) { - logger.debug("Block 1157"); - } - - int i = 0; - for (Transaction tx : block.getTransactionsList()) { - logger.info("apply block: [ {} ] tx: [ {} ] ", block.getNumber(), i); - applyTransaction(block, tx, block.getCoinbase()); - repository.dumpState(block.getNumber(), i, - Hex.toHexString(tx.getHash())); - ++i; - - } - - // miner reward - if (repository.getAccountState(block.getCoinbase()) == null) - repository.createAccount(block.getCoinbase()); - repository.addBalance(block.getCoinbase(), Block.BLOCK_REWARD); - for (Block uncle : block.getUncleList()) { - repository.addBalance(uncle.getCoinbase(), Block.UNCLE_REWARD); - } - - repository.dumpState(block.getNumber(), 0, - null); - - } /*********************************************************************** * 1) the dialog put a pending transaction on the list @@ -361,6 +115,14 @@ public class WorldManager { logger.info("pending transaction removed with hash: {} ", hash); walletTransactions.remove(hash); } + + public void setRepository(Repository repository) { + this.repository = repository; + } + + public void setBlockchain(Blockchain blockchain) { + this.blockchain = blockchain; + } public void setWallet(Wallet wallet) { this.wallet = wallet; @@ -370,9 +132,13 @@ public class WorldManager { return repository; } - public Blockchain getBlockChain() { + public Blockchain getBlockchain() { return blockchain; } + + public void loadBlockchain() { + this.blockchain = repository.loadBlockchain(); + } public Wallet getWallet() { return wallet; @@ -394,7 +160,6 @@ public class WorldManager { this.listener = listener; } - public void addPeers(List newPeers) { for (PeerData peer : newPeers) { if (this.peers.indexOf(peer) == -1) { @@ -420,12 +185,7 @@ public class WorldManager { peerDiscovery.stop(); } - public BlockQueue getBlockQueue() { - return blockQueue; - } - public void close() { - blockchain.close(); repository.close(); } diff --git a/ethereumj-core/src/main/java/org/ethereum/net/BlockQueue.java b/ethereumj-core/src/main/java/org/ethereum/net/BlockQueue.java index 701ca8cb..0a0c416a 100644 --- a/ethereumj-core/src/main/java/org/ethereum/net/BlockQueue.java +++ b/ethereumj-core/src/main/java/org/ethereum/net/BlockQueue.java @@ -20,10 +20,10 @@ public class BlockQueue { private static Logger logger = LoggerFactory.getLogger("blockchain"); - ConcurrentLinkedQueue blockQueue = new ConcurrentLinkedQueue(); - Block lastBlock; + private Queue blockQueue = new ConcurrentLinkedQueue<>(); + private Block lastBlock; - Timer timer = new Timer(); + private Timer timer = new Timer(); public BlockQueue() { @@ -40,7 +40,7 @@ public class BlockQueue { Block block = blockQueue.poll(); - WorldManager.getInstance().getBlockChain().add(block); + WorldManager.getInstance().getBlockchain().add(block); } public void addBlocks(List blockList) { @@ -64,7 +64,7 @@ public class BlockQueue { public Block getLast() { if (blockQueue.isEmpty()) - return WorldManager.getInstance().getBlockChain().getLastBlock(); + return WorldManager.getInstance().getBlockchain().getLastBlock(); return lastBlock; } diff --git a/ethereumj-core/src/main/java/org/ethereum/net/client/EthereumFrameDecoder.java b/ethereumj-core/src/main/java/org/ethereum/net/client/EthereumFrameDecoder.java index 92c85591..1ec014d4 100644 --- a/ethereumj-core/src/main/java/org/ethereum/net/client/EthereumFrameDecoder.java +++ b/ethereumj-core/src/main/java/org/ethereum/net/client/EthereumFrameDecoder.java @@ -3,7 +3,6 @@ package org.ethereum.net.client; import io.netty.buffer.ByteBuf; import io.netty.channel.ChannelHandlerContext; import io.netty.handler.codec.ByteToMessageDecoder; -import io.netty.handler.codec.CorruptedFrameException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/ethereumj-core/src/main/java/org/ethereum/net/client/EthereumProtocolHandler.java b/ethereumj-core/src/main/java/org/ethereum/net/client/EthereumProtocolHandler.java index ad452626..50431bc3 100644 --- a/ethereumj-core/src/main/java/org/ethereum/net/client/EthereumProtocolHandler.java +++ b/ethereumj-core/src/main/java/org/ethereum/net/client/EthereumProtocolHandler.java @@ -183,7 +183,8 @@ public class EthereumProtocolHandler extends ChannelInboundHandlerAdapter { List txList = transactionsMessage.getTransactions(); for(Transaction tx : txList) - WorldManager.getInstance().applyTransaction(null, tx, null); + WorldManager.getInstance().getBlockchain() + .applyTransaction(null, tx, null); logger.info(transactionsMessage.toString()); if (peerListener != null) peerListener.console(transactionsMessage.toString()); @@ -235,7 +236,7 @@ public class EthereumProtocolHandler extends ChannelInboundHandlerAdapter { } if (blockList.isEmpty()) return; - WorldManager.getInstance().getBlockQueue().addBlocks(blockList); + WorldManager.getInstance().getBlockchain().getBlockQueue().addBlocks(blockList); if (peerListener != null) peerListener.console(blocksMessage.toString()); } @@ -318,10 +319,10 @@ public class EthereumProtocolHandler extends ChannelInboundHandlerAdapter { private void sendGetChain() { - if (WorldManager.getInstance().getBlockQueue().size() > + if (WorldManager.getInstance().getBlockchain().getBlockQueue().size() > SystemProperties.CONFIG.maxBlocksQueued()) return; - Block lastBlock = WorldManager.getInstance().getBlockQueue().getLast(); + Block lastBlock = WorldManager.getInstance().getBlockchain().getBlockQueue().getLast(); byte[] hash = lastBlock.getHash(); GetChainMessage chainMessage = diff --git a/ethereumj-core/src/main/java/org/ethereum/net/message/GetChainMessage.java b/ethereumj-core/src/main/java/org/ethereum/net/message/GetChainMessage.java index 6592320a..3af03fde 100644 --- a/ethereumj-core/src/main/java/org/ethereum/net/message/GetChainMessage.java +++ b/ethereumj-core/src/main/java/org/ethereum/net/message/GetChainMessage.java @@ -88,7 +88,7 @@ public class GetChainMessage extends Message { } @Override - public Class getAnswerMessage() { + public Class getAnswerMessage() { return BlocksMessage.class; } diff --git a/ethereumj-core/src/main/java/org/ethereum/net/message/GetPeersMessage.java b/ethereumj-core/src/main/java/org/ethereum/net/message/GetPeersMessage.java index e2b988d1..8fb784fb 100644 --- a/ethereumj-core/src/main/java/org/ethereum/net/message/GetPeersMessage.java +++ b/ethereumj-core/src/main/java/org/ethereum/net/message/GetPeersMessage.java @@ -27,7 +27,7 @@ public class GetPeersMessage extends Message { } @Override - public Class getAnswerMessage() { + public Class getAnswerMessage() { return PeersMessage.class; } } diff --git a/ethereumj-core/src/main/java/org/ethereum/net/message/PingMessage.java b/ethereumj-core/src/main/java/org/ethereum/net/message/PingMessage.java index 99600073..062bed12 100644 --- a/ethereumj-core/src/main/java/org/ethereum/net/message/PingMessage.java +++ b/ethereumj-core/src/main/java/org/ethereum/net/message/PingMessage.java @@ -1,15 +1,7 @@ package org.ethereum.net.message; -import org.ethereum.util.RLP; -import org.ethereum.util.RLPItem; -import org.ethereum.util.RLPList; import org.spongycastle.util.encoders.Hex; -import java.math.BigInteger; -import java.nio.ByteBuffer; - -import static org.ethereum.net.Command.HELLO; - /** * www.ethereumJ.com * @author: Roman Mandeleil @@ -35,7 +27,7 @@ public class PingMessage extends Message { } @Override - public Class getAnswerMessage() { + public Class getAnswerMessage() { return PongMessage.class; } } diff --git a/ethereumj-core/src/main/java/org/ethereum/trie/Cache.java b/ethereumj-core/src/main/java/org/ethereum/trie/Cache.java index 850ab630..04802e60 100644 --- a/ethereumj-core/src/main/java/org/ethereum/trie/Cache.java +++ b/ethereumj-core/src/main/java/org/ethereum/trie/Cache.java @@ -16,13 +16,12 @@ import org.iq80.leveldb.DB; */ public class Cache { - private Map nodes; + private Map nodes = new HashMap<>(); private DB db; private boolean isDirty; public Cache(DB db) { this.db = db; - nodes = new HashMap(); } /** @@ -88,7 +87,7 @@ public class Cache { // If the nodes grows beyond the 200 entries we simple empty it // FIXME come up with something better if (this.nodes.size() > 200) { - this.nodes = new HashMap(); + this.nodes = new HashMap<>(); } } diff --git a/ethereumj-core/src/main/java/org/ethereum/trie/Trie.java b/ethereumj-core/src/main/java/org/ethereum/trie/Trie.java index 81ea0dd6..b533fbba 100644 --- a/ethereumj-core/src/main/java/org/ethereum/trie/Trie.java +++ b/ethereumj-core/src/main/java/org/ethereum/trie/Trie.java @@ -72,6 +72,10 @@ public class Trie implements TrieFacade { return root; } + public void setRoot(Object root) { + this.root = root; + } + public void setCache(Cache cache) { this.cache = cache; } diff --git a/ethereumj-core/src/main/java/org/ethereum/util/AdvancedDeviceUtils.java b/ethereumj-core/src/main/java/org/ethereum/util/AdvancedDeviceUtils.java index ec7153c1..256268fa 100644 --- a/ethereumj-core/src/main/java/org/ethereum/util/AdvancedDeviceUtils.java +++ b/ethereumj-core/src/main/java/org/ethereum/util/AdvancedDeviceUtils.java @@ -1,10 +1,7 @@ package org.ethereum.util; -import com.maxmind.geoip.Location; import org.apache.log4j.PropertyConfigurator; -import org.ethereum.db.IpGeoDB; -import java.net.InetAddress; import java.net.URL; import static org.ethereum.config.SystemProperties.CONFIG; diff --git a/ethereumj-core/src/main/java/org/ethereum/vm/ProgramInvokeFactory.java b/ethereumj-core/src/main/java/org/ethereum/vm/ProgramInvokeFactory.java index 869a7c47..e4f2c13f 100644 --- a/ethereumj-core/src/main/java/org/ethereum/vm/ProgramInvokeFactory.java +++ b/ethereumj-core/src/main/java/org/ethereum/vm/ProgramInvokeFactory.java @@ -24,7 +24,7 @@ public class ProgramInvokeFactory { public static ProgramInvoke createProgramInvoke(Transaction tx, Block block, Repository repository) { // https://ethereum.etherpad.mozilla.org/26 - Block lastBlock = WorldManager.getInstance().getBlockChain().getLastBlock(); + Block lastBlock = WorldManager.getInstance().getBlockchain().getLastBlock(); /*** ADDRESS op ***/ // YP: Get address of currently executing account. diff --git a/ethereumj-core/src/main/resources/log4j-detailed.properties b/ethereumj-core/src/main/resources/log4j-detailed.properties index 672cc173..15d8b9b4 100644 --- a/ethereumj-core/src/main/resources/log4j-detailed.properties +++ b/ethereumj-core/src/main/resources/log4j-detailed.properties @@ -23,9 +23,9 @@ log4j.logger.io.netty = ERROR log4j.logger.wire = ERROR log4j.logger.VM = DEBUG log4j.logger.main = INFO -log4j.logger.state = ERROR +log4j.logger.state = DEBUG log4j.logger.repository = DEBUG -log4j.logger.blockchain = DEBUG +log4j.logger.blockchain = INFO log4j.logger.ui = ERROR log4j.logger.gas = ERROR diff --git a/ethereumj-core/src/main/resources/log4j.properties b/ethereumj-core/src/main/resources/log4j.properties index 518657e3..bba5eecc 100644 --- a/ethereumj-core/src/main/resources/log4j.properties +++ b/ethereumj-core/src/main/resources/log4j.properties @@ -24,8 +24,8 @@ log4j.logger.wire = ERROR log4j.logger.VM = ERROR log4j.logger.main = ERROR log4j.logger.trie = ERROR -log4j.logger.state = ERROR -log4j.logger.repository = ERROR +log4j.logger.state = INFO +log4j.logger.repository = INFO log4j.logger.blockchain = INFO log4j.logger.txs = ERROR log4j.logger.ui = ERROR diff --git a/ethereumj-core/src/main/resources/system.properties b/ethereumj-core/src/main/resources/system.properties index c9468b34..0b3d94c6 100644 --- a/ethereumj-core/src/main/resources/system.properties +++ b/ethereumj-core/src/main/resources/system.properties @@ -99,7 +99,7 @@ coinbase.secret = "monkey" # in JSON form to [dump.dir] # if [dump.full] = true # posible values [true/false] -dump.full = true +dump.full = false dump.dir = dmp # clean the dump dir each start diff --git a/ethereumj-core/src/test/java/org/ethereum/core/BlockTest.java b/ethereumj-core/src/test/java/org/ethereum/core/BlockTest.java index 654b2ad9..e60a8fed 100644 --- a/ethereumj-core/src/test/java/org/ethereum/core/BlockTest.java +++ b/ethereumj-core/src/test/java/org/ethereum/core/BlockTest.java @@ -115,7 +115,7 @@ public class BlockTest { assertEquals(new BigInteger(1, Genesis.DIFFICULTY), difficulty); // Storing genesis because the parent needs to be in the DB for calculation. - WorldManager.getInstance().getBlockChain().add(genesis); + WorldManager.getInstance().getBlockchain().add(genesis); Block block1 = new Block(Hex.decode(block_1)); BigInteger calcDifficulty = new BigInteger(1, block1.calcDifficulty()); @@ -137,7 +137,7 @@ public class BlockTest { assertEquals(Genesis.GAS_LIMIT, gasLimit); // Storing genesis because the parent needs to be in the DB for calculation. - WorldManager.getInstance().getBlockChain().add(genesis); + WorldManager.getInstance().getBlockchain().add(genesis); // Test with block Block block1 = new Block(Hex.decode(block_1));