From de0f67ae3b93c84b3a6da0b07272748214d4f854 Mon Sep 17 00:00:00 2001 From: nicksavers Date: Tue, 3 Jun 2014 23:35:29 +0200 Subject: [PATCH 1/3] Impl faster ADD --- .../main/java/org/ethereum/vm/DataWord.java | 16 ++++- .../java/org/ethereum/vm/DataWordTest.java | 72 +++++++++++++++++++ 2 files changed, 87 insertions(+), 1 deletion(-) create mode 100644 ethereumj-core/src/test/java/org/ethereum/vm/DataWordTest.java 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 3408a102..052b1bdb 100644 --- a/ethereumj-core/src/main/java/org/ethereum/vm/DataWord.java +++ b/ethereumj-core/src/main/java/org/ethereum/vm/DataWord.java @@ -97,7 +97,7 @@ public class DataWord { // todo: add can be done in more efficient way // todo without BigInteger quick hack - public void add(DataWord word){ + public void add2(DataWord word){ BigInteger result = value().add( word.value() ); byte[] bytes = result.toByteArray(); @@ -106,6 +106,20 @@ public class DataWord { System.arraycopy(bytes, 0, data.array(), 32 - bytes.length, bytes.length); this.data = data.array(); } + + // By : Holger + // From : http://stackoverflow.com/a/24023466/459349 + public void add(DataWord word) { + if (this.data.length != 32 || word.data.length != 32) + throw new IllegalArgumentException(); + byte[] result = new byte[32]; + for (int i = 31, overflow = 0; i >= 0; i--) { + int v = (this.data[i] & 0xff) + (word.data[i] & 0xff) + overflow; + result[i] = (byte) v; + overflow = v >>> 8; + } + this.data = result; + } // todo: mull can be done in more efficient way // todo: with shift left shift right trick diff --git a/ethereumj-core/src/test/java/org/ethereum/vm/DataWordTest.java b/ethereumj-core/src/test/java/org/ethereum/vm/DataWordTest.java new file mode 100644 index 00000000..f1495688 --- /dev/null +++ b/ethereumj-core/src/test/java/org/ethereum/vm/DataWordTest.java @@ -0,0 +1,72 @@ +package org.ethereum.vm; + +import static org.junit.Assert.*; + +import java.math.BigInteger; + +import org.junit.Test; + +public class DataWordTest { + + @Test + public void testAddPerformance() { + boolean enabled = true; + + if(enabled) { + byte[] one = new byte[] { 0x01, 0x31, 0x54, 0x41, 0x01, 0x31, 0x54, + 0x41, 0x01, 0x31, 0x54, 0x41, 0x01, 0x31, 0x54, 0x41, 0x01, + 0x31, 0x54, 0x41, 0x01, 0x31, 0x54, 0x41, 0x01, 0x31, 0x54, + 0x41, 0x01, 0x31, 0x54, 0x41 }; // Random value + + int ITERATIONS = 10000000; + + long now1 = System.currentTimeMillis(); + for (int i = 0; i < ITERATIONS; i++) { + DataWord x = new DataWord(one); + x.add(x); + } + System.out.println("Add1: " + (System.currentTimeMillis() - now1) + "ms"); + + long now2 = System.currentTimeMillis(); + for (int i = 0; i < ITERATIONS; i++) { + DataWord x = new DataWord(one); + x.add2(x); + } + System.out.println("Add2: " + (System.currentTimeMillis() - now2) + "ms"); + } else { + System.out.println("ADD performance test is disabled."); + } + } + + @Test + public void testAdd2() { + byte[] two = new byte[32]; + two[31] = 0x01; // 0x00000000000000000000000000000000000000000000000000000000000001 + + DataWord x = new DataWord(two); + x.add(new DataWord(two)); + System.out.println(new BigInteger(1, x.data)); + + DataWord y = new DataWord(two); + y.add2(new DataWord(two)); + System.out.println(new BigInteger(1, y.data)); + } + + @Test + public void testAdd3() { + byte[] three = new byte[32]; + for (int i = 0; i < three.length; i++) { + three[i] = (byte) 0xff; + } + + DataWord x = new DataWord(three); + x.add(new DataWord(three)); + assertEquals(32, x.data.length); + System.out.println(new BigInteger(1, x.data)); + + // FAIL +// DataWord y = new DataWord(three); +// y.add2(new DataWord(three)); +// System.out.println(new BigInteger(1, y.data)); + } +} From 4868ecfc0e705be861c41ebaddf22af2e590b006 Mon Sep 17 00:00:00 2001 From: nicksavers Date: Wed, 4 Jun 2014 07:57:31 +0200 Subject: [PATCH 2/3] Remove array length check from DataWord and use better test --- .../main/java/org/ethereum/vm/DataWord.java | 68 +++++++++---------- .../src/main/java/org/ethereum/vm/VM.java | 2 +- .../java/org/ethereum/vm/DataWordTest.java | 13 ++-- .../src/test/java/org/ethereum/vm/VMTest.java | 1 - 4 files changed, 38 insertions(+), 46 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 052b1bdb..58e8e303 100644 --- a/ethereumj-core/src/main/java/org/ethereum/vm/DataWord.java +++ b/ethereumj-core/src/main/java/org/ethereum/vm/DataWord.java @@ -7,34 +7,31 @@ import java.math.BigInteger; import java.nio.ByteBuffer; /** - * www.ethereumJ.com - * User: Roman Mandeleil - * Created on: 01/06/2014 19:47 + * DataWord is the 32-byte array representation of a 256-bit number + * Calculations can be done on this word with other DataWords */ - public class DataWord { static DataWord ZERO = new DataWord(new byte[32]); // don't push it in to the stack byte[] data = new byte[32]; - public DataWord(){ - data = new byte[32]; - } + public DataWord() { + data = new byte[32]; + } - public DataWord(int num){ - ByteBuffer bInt = ByteBuffer.allocate(4).putInt(num); - ByteBuffer data = ByteBuffer.allocate(32); - System.arraycopy(bInt.array(), 0, data.array(), 28, 4); - this.data = data.array(); - } + public DataWord(int num) { + ByteBuffer bInt = ByteBuffer.allocate(4).putInt(num); + ByteBuffer data = ByteBuffer.allocate(32); + System.arraycopy(bInt.array(), 0, data.array(), 28, 4); + this.data = data.array(); + } - public DataWord(byte[] data){ - if (data == null || data.length > 32) - throw new RuntimeException("bad push data: " + data); - - System.arraycopy(data, 0, this.data, 32 - data.length, data.length); - } + public DataWord(byte[] data) { + if (data == null || data.length > 32) + throw new RuntimeException("bad push data: " + data); + System.arraycopy(data, 0, this.data, 32 - data.length, data.length); + } public byte[] getData() { return data; @@ -95,8 +92,19 @@ public class DataWord { } } - // todo: add can be done in more efficient way - // todo without BigInteger quick hack + // By : Holger + // From : http://stackoverflow.com/a/24023466/459349 + public void add(DataWord word) { + byte[] result = new byte[32]; + for (int i = 31, overflow = 0; i >= 0; i--) { + int v = (this.data[i] & 0xff) + (word.data[i] & 0xff) + overflow; + result[i] = (byte) v; + overflow = v >>> 8; + } + this.data = result; + } + + // old add-method with BigInteger quick hack public void add2(DataWord word){ BigInteger result = value().add( word.value() ); @@ -107,24 +115,10 @@ public class DataWord { this.data = data.array(); } - // By : Holger - // From : http://stackoverflow.com/a/24023466/459349 - public void add(DataWord word) { - if (this.data.length != 32 || word.data.length != 32) - throw new IllegalArgumentException(); - byte[] result = new byte[32]; - for (int i = 31, overflow = 0; i >= 0; i--) { - int v = (this.data[i] & 0xff) + (word.data[i] & 0xff) + overflow; - result[i] = (byte) v; - overflow = v >>> 8; - } - this.data = result; - } - - // todo: mull can be done in more efficient way + // todo: mul can be done in more efficient way // todo: with shift left shift right trick // todo without BigInteger quick hack - public void mull(DataWord word){ + public void mul(DataWord word){ BigInteger result = value().multiply( word.value() ); byte[] bytes = result.toByteArray(); 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 52e51166..e0726e1b 100644 --- a/ethereumj-core/src/main/java/org/ethereum/vm/VM.java +++ b/ethereumj-core/src/main/java/org/ethereum/vm/VM.java @@ -55,7 +55,7 @@ public class VM { DataWord word1 = program.stackPop(); DataWord word2 = program.stackPop(); - word1.mull(word2); + word1.mul(word2); program.stackPush(word1); program.step(); } 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 f1495688..229c0860 100644 --- a/ethereumj-core/src/test/java/org/ethereum/vm/DataWordTest.java +++ b/ethereumj-core/src/test/java/org/ethereum/vm/DataWordTest.java @@ -2,9 +2,8 @@ package org.ethereum.vm; import static org.junit.Assert.*; -import java.math.BigInteger; - import org.junit.Test; +import org.spongycastle.util.encoders.Hex; public class DataWordTest { @@ -41,15 +40,15 @@ public class DataWordTest { @Test public void testAdd2() { byte[] two = new byte[32]; - two[31] = 0x01; // 0x00000000000000000000000000000000000000000000000000000000000001 + two[31] = (byte) 0xff; // 0x000000000000000000000000000000000000000000000000000000000000ff DataWord x = new DataWord(two); x.add(new DataWord(two)); - System.out.println(new BigInteger(1, x.data)); + System.out.println(Hex.toHexString(x.data)); DataWord y = new DataWord(two); y.add2(new DataWord(two)); - System.out.println(new BigInteger(1, y.data)); + System.out.println(Hex.toHexString(y.data)); } @Test @@ -62,11 +61,11 @@ public class DataWordTest { DataWord x = new DataWord(three); x.add(new DataWord(three)); assertEquals(32, x.data.length); - System.out.println(new BigInteger(1, x.data)); + System.out.println(Hex.toHexString(x.data)); // FAIL // DataWord y = new DataWord(three); // y.add2(new DataWord(three)); -// System.out.println(new BigInteger(1, y.data)); +// System.out.println(Hex.toHexString(y.data)); } } 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 40f03122..1d038f3a 100644 --- a/ethereumj-core/src/test/java/org/ethereum/vm/VMTest.java +++ b/ethereumj-core/src/test/java/org/ethereum/vm/VMTest.java @@ -1,6 +1,5 @@ package org.ethereum.vm; -import org.ethereum.crypto.HashUtil; import org.junit.Test; import org.spongycastle.util.encoders.Hex; From d12e079b6474c922f22736ceecc908e721e6a73d Mon Sep 17 00:00:00 2001 From: nicksavers Date: Thu, 5 Jun 2014 01:05:05 +0200 Subject: [PATCH 3/3] Continue from last block in DB --- .../org/ethereum/config/SystemProperties.java | 30 ++-- .../java/org/ethereum/core/AccountState.java | 2 +- .../java/org/ethereum/core/Blockchain.java | 132 ++++++++++-------- .../main/java/org/ethereum/core/Genesis.java | 15 +- .../java/org/ethereum/core/StateObject.java | 2 +- .../java/org/ethereum/core/Transaction.java | 4 +- .../main/java/org/ethereum/crypto/ECKey.java | 11 +- .../main/java/org/ethereum/db/Database.java | 36 ----- .../main/java/org/ethereum/db/IpGeoDB.java | 51 ++++--- .../ethereum/gui/ContractSubmitDialog.java | 15 +- .../java/org/ethereum/gui/DialogWorker.java | 26 ++-- .../org/ethereum/gui/MessageAwareDialog.java | 14 +- .../java/org/ethereum/gui/PayOutDialog.java | 11 +- .../org/ethereum/gui/ProgramPlayDialog.java | 16 +-- .../ethereum/net/message/StaticMessages.java | 2 +- .../net/submit/PendingTransaction.java | 6 +- .../java/org/ethereum/trie/TrieIterator.java | 10 +- .../src/main/resources/system.properties | 2 +- .../java/org/ethereum/core/BlockTest.java | 4 +- .../ethereum/vm/ProgramInvokeMockImpl.java | 2 - 20 files changed, 187 insertions(+), 204 deletions(-) diff --git a/ethereumj-core/src/main/java/org/ethereum/config/SystemProperties.java b/ethereumj-core/src/main/java/org/ethereum/config/SystemProperties.java index 49084588..f9133d1f 100644 --- a/ethereumj-core/src/main/java/org/ethereum/config/SystemProperties.java +++ b/ethereumj-core/src/main/java/org/ethereum/config/SystemProperties.java @@ -19,13 +19,20 @@ public class SystemProperties { private static Logger logger = LoggerFactory.getLogger(SystemProperties.class); + private static int DEFAULT_TX_APPROVE_TIMEOUT = 10; + private static String DEFAULT_DISCOVERY_PEER = "54.201.28.117"; + private static int DEFAULT_DISCOVERY_PORT = 30303; + private static String DEFAULT_ACTIVE_PEER_IP = "54.201.28.117"; + private static int DEFAULT_ACTIVE_PORT = 30303; + private static String DEFAULT_SAMPLES_DIR = "samples"; + public static SystemProperties CONFIG = new SystemProperties(); private Properties prop = new Properties(); private InputStream input = null; public SystemProperties() { - try { - + + try { File file = null; String dir = System.getProperty("user.dir"); String fileName = dir + "/config/system.properties"; @@ -41,7 +48,6 @@ public class SystemProperties { return; } } - //load a properties file from class path, inside static method prop.load(input); @@ -77,18 +83,17 @@ public class SystemProperties { public int transactionApproveTimeout(){ if (prop.isEmpty()) - return 10; + return DEFAULT_TX_APPROVE_TIMEOUT; return Integer.parseInt(prop.getProperty("transaction.approve.timeout")); } - public String peerDiscoveryIP(){ - if(prop.isEmpty()) return "54.201.28.117"; + if(prop.isEmpty()) return DEFAULT_DISCOVERY_PEER; return prop.getProperty("peer.discovery.ip"); } public int peerDiscoveryPort(){ - if(prop.isEmpty()) return 30303; + if(prop.isEmpty()) return DEFAULT_DISCOVERY_PORT; return Integer.parseInt(prop.getProperty("peer.discovery.port")); } @@ -98,21 +103,21 @@ public class SystemProperties { } public String activePeerIP(){ - if(prop.isEmpty()) return "54.201.28.117"; + if(prop.isEmpty()) return DEFAULT_ACTIVE_PEER_IP; return prop.getProperty("peer.active.ip"); } public int activePeerPort(){ - if(prop.isEmpty()) return 30303; + if(prop.isEmpty()) return DEFAULT_ACTIVE_PORT; return Integer.parseInt(prop.getProperty("peer.active.port")); } public String samplesDir(){ - if(prop.isEmpty()) return "samples"; + if(prop.isEmpty()) return DEFAULT_SAMPLES_DIR; return prop.getProperty("samples.dir"); } - public String toString() { + public void print() { Enumeration e = prop.propertyNames(); while (e.hasMoreElements()) { String key = (String) e.nextElement(); @@ -120,11 +125,10 @@ public class SystemProperties { if (!key.equals("null")) logger.info("Key: " + key + ", Value: " + value); } - return ""; } public static void main(String args[]){ SystemProperties systemProperties = new SystemProperties(); - logger.info(systemProperties.toString()); + systemProperties.print(); } } 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 1c984a5b..5a45814a 100644 --- a/ethereumj-core/src/main/java/org/ethereum/core/AccountState.java +++ b/ethereumj-core/src/main/java/org/ethereum/core/AccountState.java @@ -27,7 +27,7 @@ public class AccountState { * * Since I typically wish to refer not to the trie’s root hash * but to the underlying set of key/value pairs stored within, - * I define a convenient equi valence TRIE (σ[a] s ) ≡ σ[a] s . + * 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]; 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 b7549ba1..2c08d939 100644 --- a/ethereumj-core/src/main/java/org/ethereum/core/Blockchain.java +++ b/ethereumj-core/src/main/java/org/ethereum/core/Blockchain.java @@ -1,7 +1,6 @@ package org.ethereum.core; import java.io.IOException; -import java.math.BigInteger; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; @@ -20,31 +19,22 @@ import org.spongycastle.util.encoders.Hex; public class Blockchain extends ArrayList { + private static final long serialVersionUID = -143590724563460486L; + private static Logger logger = LoggerFactory.getLogger(Blockchain.class); private Database db; private Wallet wallet; private long gasPrice = 1000; - private Block lastBlock = new Genesis(); + private Block lastBlock; - private Map pendingTransactions = - Collections.synchronizedMap(new HashMap()); + private Map pendingTransactions = + Collections.synchronizedMap(new HashMap()); public Blockchain(Wallet wallet) { this.db = Config.CHAIN_DB; this.wallet = wallet; - - // Redesign fetch all to get the chain ordered - byte[] payload = db.get(Genesis.PARENT_HASH); - - while (payload != null) { - - Block block = new Block(payload); - this.add(block); - lastBlock = block; - wallet.processBlock(block); - payload = db.get(block.getHash()); - } + this.loadChain(); } public Block getLastBlock() { @@ -55,59 +45,65 @@ public class Blockchain extends ArrayList { // TODO: redesign this part when the state part and the genesis block is ready - if (blocks.isEmpty()) return; + if (blocks.isEmpty()) + return; Block firstBlockToAdd = blocks.get(blocks.size() - 1); // if it is the first block to add // check that the parent is the genesis - if (this.isEmpty() && - !Arrays.equals(StaticMessages.GENESIS_HASH, firstBlockToAdd.getParentHash())){ - return; - } + if (this.isEmpty() + && !Arrays.equals(StaticMessages.GENESIS_HASH, + firstBlockToAdd.getParentHash())) { + return; + } // if there is some blocks already keep chain continuity - if (!this.isEmpty() ){ + if (!this.isEmpty()) { Block lastBlock = this.get(this.size() - 1); String hashLast = Hex.toHexString(lastBlock.getHash()); String blockParentHash = Hex.toHexString(firstBlockToAdd.getParentHash()); if (!hashLast.equals(blockParentHash)) return; } for (int i = blocks.size() - 1; i >= 0 ; --i){ - Block block = blocks.get(i); - this.add(block); - if(block.getNumber() > lastBlock.getNumber()) lastBlock = block; - + Block block = blocks.get(i); + this.addBlock(block); db.put(block.getParentHash(), block.getEncoded()); - if (logger.isDebugEnabled()) logger.debug("block added to the chain with hash: {}", Hex.toHexString(block.getHash())); - this.gasPrice = block.getMinGasPrice(); - - wallet.processBlock(block); } // Remove all pending transactions as they already approved by the net - for (Block block : blocks){ - for (Transaction tx : block.getTransactionsList()){ + for (Block block : blocks) { + for (Transaction tx : block.getTransactionsList()) { if (logger.isDebugEnabled()) logger.debug("pending cleanup: tx.hash: [{}]", Hex.toHexString( tx.getHash())); removePendingTransaction(tx); } } - logger.info("*** Block chain size: [ {} ]", this.size()); } - /* - * 1) the dialog put a pending transaction on the list - * 2) the dialog send the transaction to a net - * 3) wherever the transaction got in from the wire it will change to approve state - * 4) only after the approve a) Wallet state changes - * 5) After the block is received with that tx the pending been clean up - */ + private void addBlock(Block block) { + this.wallet.processBlock(block); + this.gasPrice = block.getMinGasPrice(); + if(lastBlock == null || block.getNumber() > lastBlock.getNumber()) + this.lastBlock = block; + this.add(block); + } + + public long getGasPrice() { + return gasPrice; + } + + /*********************************************************************** + * 1) the dialog put a pending transaction on the list + * 2) the dialog send the transaction to a net + * 3) wherever the transaction got in from the wire it will change to approve state + * 4) only after the approve a) Wallet state changes + * 5) After the block is received with that tx the pending been clean up + */ public PendingTransaction addPendingTransaction(Transaction transaction) { - - BigInteger hash = new BigInteger(transaction.getHash()); - logger.info("pending transaction placed hash: {} ", hash.toString(16) ); + String hash = Hex.toHexString(transaction.getHash()); + logger.info("pending transaction placed hash: {} ", hash ); PendingTransaction pendingTransaction = pendingTransactions.get(hash); if (pendingTransaction != null) @@ -120,24 +116,44 @@ public class Blockchain extends ArrayList { } public void removePendingTransaction(Transaction transaction){ - - BigInteger hash = new BigInteger(transaction.getHash()); - logger.info("pending transaction removed with hash: {} ", hash.toString(16) ); + String hash = Hex.toHexString(transaction.getHash()); + logger.info("pending transaction removed with hash: {} ", hash ); pendingTransactions.remove(hash); } - public long getGasPrice() { - return gasPrice; - } - public byte[] getLatestBlockHash(){ - - if (this.isEmpty()) - return StaticMessages.GENESIS_HASH; - else{ - - return lastBlock.getHash(); - } - + if (this.isEmpty()) + return StaticMessages.GENESIS_HASH; + else + return lastBlock.getHash(); } + + public void loadChain() { + DBIterator iterator = db.iterator(); + try { + if (!iterator.hasNext()) { + logger.info("DB is empty - adding Genesis"); + Block genesis = Genesis.getInstance(); + this.addBlock(genesis); + logger.debug("Block: " + genesis.getNumber() + " ---> " + genesis.toFlatString()); + db.put(genesis.getParentHash(), genesis.getEncoded()); + } else { + logger.debug("Displaying blocks stored in DB sorted on blocknumber"); + byte[] parentHash = Genesis.PARENT_HASH; // get Genesis block by parentHash + for (iterator.seekToFirst(); iterator.hasNext(); iterator.next()) { + this.addBlock(new Block(db.get(parentHash))); + if (logger.isDebugEnabled()) + logger.debug("Block: " + lastBlock.getNumber() + " ---> " + lastBlock.toFlatString()); + parentHash = lastBlock.getHash(); + } + } + } finally { + // Make sure you close the iterator to avoid resource leaks. + try { + iterator.close(); + } catch (IOException e) { + logger.error(e.getMessage(), e); + } + } + } } diff --git a/ethereumj-core/src/main/java/org/ethereum/core/Genesis.java b/ethereumj-core/src/main/java/org/ethereum/core/Genesis.java index 6e438297..b103f379 100644 --- a/ethereumj-core/src/main/java/org/ethereum/core/Genesis.java +++ b/ethereumj-core/src/main/java/org/ethereum/core/Genesis.java @@ -29,8 +29,10 @@ public class Genesis extends Block { public static long TIMESTAMP = 0; public static byte[] EXTRA_DATA = new byte[0]; public static byte[] NONCE = HashUtil.sha3(new byte[]{42}); - - public Genesis() { + + private static Block instance; + + private Genesis() { super(PARENT_HASH, UNCLES_HASH, COINBASE, TX_TRIE_ROOT, DIFFICULTY, NUMBER, MIN_GAS_PRICE, GAS_LIMIT, GAS_USED, TIMESTAMP, EXTRA_DATA, NONCE, null, null); @@ -53,9 +55,16 @@ public class Genesis extends Block { this.updateState(Hex.decode("6c386a4b26f73c802f34673f7248bb118f97424a"), acct.getEncoded()); // # (R) this.updateState(Hex.decode("cd2a3d9f938e13cd947ec05abc7fe734df8dd826"), acct.getEncoded()); - System.out.println(Hex.toHexString(this.getStateRoot())); logger.info("Genesis-hash: " + Hex.toHexString(this.getHash())); + logger.info("Genesis-stateRoot: " + Hex.toHexString(this.getStateRoot())); Config.CHAIN_DB.put(getParentHash(), getEncoded()); } + + public static Block getInstance() { + if (instance == null) { + instance = new Genesis(); + } + return instance; + } } diff --git a/ethereumj-core/src/main/java/org/ethereum/core/StateObject.java b/ethereumj-core/src/main/java/org/ethereum/core/StateObject.java index aa0eca02..7162d61c 100644 --- a/ethereumj-core/src/main/java/org/ethereum/core/StateObject.java +++ b/ethereumj-core/src/main/java/org/ethereum/core/StateObject.java @@ -160,7 +160,7 @@ public class StateObject { // Converts an transaction in to a state object public static StateObject createContract(Transaction tx, GoState state) { // Create contract if there's no recipient - if (tx.isContract()) { + if (tx.isContractCreation()) { // FIXME byte[] txHash = tx.getHash(); byte[] contractAddress = copyOfRange(txHash, 12, txHash.length); diff --git a/ethereumj-core/src/main/java/org/ethereum/core/Transaction.java b/ethereumj-core/src/main/java/org/ethereum/core/Transaction.java index 65db0692..db482d26 100644 --- a/ethereumj-core/src/main/java/org/ethereum/core/Transaction.java +++ b/ethereumj-core/src/main/java/org/ethereum/core/Transaction.java @@ -164,14 +164,14 @@ public class Transaction { public byte[] getContractAddress(){ - if (!isContract()) return null; + if (!isContractCreation()) return null; byte[] encSender = RLP.encodeElement(getSender()); byte[] encNonce = RLP.encodeElement(nonce); return HashUtil.sha3omit12(RLP.encodeList(encSender, encNonce)); } - public boolean isContract() { + public boolean isContractCreation() { return Arrays.equals(this.receiveAddress, ZERO_ADDRESS); } diff --git a/ethereumj-core/src/main/java/org/ethereum/crypto/ECKey.java b/ethereumj-core/src/main/java/org/ethereum/crypto/ECKey.java index 20d9dfa7..e5a8870f 100644 --- a/ethereumj-core/src/main/java/org/ethereum/crypto/ECKey.java +++ b/ethereumj-core/src/main/java/org/ethereum/crypto/ECKey.java @@ -47,7 +47,7 @@ import org.spongycastle.util.encoders.Base64; import org.spongycastle.util.encoders.Hex; public class ECKey implements Serializable { - private static final Logger log = LoggerFactory.getLogger(ECKey.class); + private static final Logger logger = LoggerFactory.getLogger(ECKey.class); /** The parameters of the secp256k1 curve that Bitcoin uses. */ public static final ECDomainParameters CURVE; @@ -448,11 +448,10 @@ public class ECKey implements Serializable { signer.init(false, params); try { return signer.verifySignature(data, signature.r, signature.s); - } catch (NullPointerException e) { - // Bouncy Castle contains a bug that can cause NPEs given specially crafted signatures. Those signatures - // are inherently invalid/attack sigs so we just fail them here rather than crash the thread. - log.error("Caught NPE inside bouncy castle"); - e.printStackTrace(); + } catch (NullPointerException npe) { + // Bouncy Castle contains a bug that can cause NPEs given specially crafted signatures. + // Those signatures are inherently invalid/attack sigs so we just fail them here rather than crash the thread. + logger.error("Caught NPE inside bouncy castle", npe); return false; } } diff --git a/ethereumj-core/src/main/java/org/ethereum/db/Database.java b/ethereumj-core/src/main/java/org/ethereum/db/Database.java index ba8c0edf..78e61c28 100644 --- a/ethereumj-core/src/main/java/org/ethereum/db/Database.java +++ b/ethereumj-core/src/main/java/org/ethereum/db/Database.java @@ -4,19 +4,13 @@ import static org.iq80.leveldb.impl.Iq80DBFactory.factory; import java.io.File; import java.io.IOException; -import java.util.HashMap; -import java.util.Map; import org.ethereum.config.SystemProperties; -import org.ethereum.core.Block; -import org.ethereum.core.Genesis; -import org.ethereum.net.message.StaticMessages; import org.iq80.leveldb.DB; import org.iq80.leveldb.DBIterator; import org.iq80.leveldb.Options; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.spongycastle.util.encoders.Hex; /** * Generic interface for Ethereum database @@ -47,8 +41,6 @@ public class Database { logger.debug("Initializing new or existing DB: '" + name + "'"); options.createIfMissing(true); db = factory.open(new File(name), options); - - printDB(); // logger.debug("Showing database stats"); // String stats = DATABASE.getProperty("leveldb.stats"); // logger.debug(stats); @@ -68,34 +60,6 @@ public class Database { } } - public void printDB() { - DBIterator iterator = db.iterator(); - try { - Map blocks = new HashMap(); - int count = 0; - if (!iterator.hasNext()) { - logger.info("DB is empty"); - } else { - logger.info("Displaying blocks stored in DB sorted on key"); - } - for (iterator.seekToFirst(); iterator.hasNext(); iterator.next()) { - byte[] key = iterator.peekNext().getKey(); - byte[] value = iterator.peekNext().getValue(); - Block block = new Block(value); - blocks.put(new Long(block.getNumber()), block); - logger.info("Block: " + count + " Key: " + Hex.toHexString(key) + " ---> " + block.toFlatString()); - count++; - } - } finally { - // Make sure you close the iterator to avoid resource leaks. - try { - iterator.close(); - } catch (IOException e) { - e.printStackTrace(); - } - } - } - /** Insert object(value) (key = sha3(value)) */ public void put(byte[] key, byte[] value) { db.put(key, value); diff --git a/ethereumj-core/src/main/java/org/ethereum/db/IpGeoDB.java b/ethereumj-core/src/main/java/org/ethereum/db/IpGeoDB.java index 0fc1ac10..16dc28d4 100644 --- a/ethereumj-core/src/main/java/org/ethereum/db/IpGeoDB.java +++ b/ethereumj-core/src/main/java/org/ethereum/db/IpGeoDB.java @@ -4,6 +4,9 @@ import java.io.File; import java.net.InetAddress; import java.net.URL; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import com.maxmind.geoip.Location; import com.maxmind.geoip.LookupService; @@ -14,27 +17,30 @@ import com.maxmind.geoip.LookupService; */ public class IpGeoDB { // change - static{ - try { - File file = null; - try { + private static Logger logger = LoggerFactory.getLogger(IpGeoDB.class); + + static { + try { + File file = null; + try { - String dir = System.getProperty("user.dir"); - String fileName = dir + "/config/GeoLiteCity.dat"; - file = new File(fileName); - if (!file.exists()){ - URL geiIpDBFile = ClassLoader.getSystemResource("GeoLiteCity.dat"); - file = new File(geiIpDBFile.toURI()); - } - } catch (Throwable th) { - th.printStackTrace(); - System.exit(-1); - } - cl = new LookupService(file); - } catch (Throwable e) { - e.printStackTrace(); - } - } + String dir = System.getProperty("user.dir"); + String fileName = dir + "/config/GeoLiteCity.dat"; + file = new File(fileName); + if (!file.exists()) { + URL geiIpDBFile = ClassLoader + .getSystemResource("GeoLiteCity.dat"); + file = new File(geiIpDBFile.toURI()); + } + } catch (Throwable th) { + logger.error(th.getMessage(), th); + System.exit(-1); + } + cl = new LookupService(file); + } catch (Throwable e) { + logger.error(e.getMessage(), e); + } + } private static LookupService cl; @@ -42,9 +48,8 @@ public class IpGeoDB { // change try { return cl.getLocation(ip); } catch (Throwable e) { - // todo: think about this exception, maybe you can do something more reasonable - System.out.println(e.getMessage()); -// e.printStackTrace(); + // TODO: think about this exception, maybe you can do something more reasonable + logger.error(e.getMessage(), e); } return null; } 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 cf655044..d9c9dde0 100644 --- a/ethereumj-core/src/main/java/org/ethereum/gui/ContractSubmitDialog.java +++ b/ethereumj-core/src/main/java/org/ethereum/gui/ContractSubmitDialog.java @@ -22,17 +22,16 @@ import java.math.BigInteger; import java.net.URL; import java.util.Collection; - - /** * www.ethereumJ.com * User: Roman Mandeleil * Created on: 18/05/14 22:21 */ -class ContractSubmitDialog extends JDialog implements MessageAwareDialog{ +class ContractSubmitDialog extends JDialog implements MessageAwareDialog { - - ContractSubmitDialog dialog; + private static final long serialVersionUID = -3622984456084608996L; + + ContractSubmitDialog dialog; JComboBox creatorAddressCombo; final JTextField gasInput; final JTextField contractAddrInput; @@ -101,7 +100,6 @@ class ContractSubmitDialog extends JDialog implements MessageAwareDialog{ }} ); - JLabel statusMessage = new JLabel(""); statusMessage.setBounds(50, 360, 400, 50); statusMessage.setHorizontalAlignment(SwingConstants.CENTER); @@ -291,8 +289,6 @@ class ContractSubmitDialog extends JDialog implements MessageAwareDialog{ } - - public static void main(String args[]) { AccountState as = new AccountState(); @@ -319,8 +315,7 @@ class ContractSubmitDialog extends JDialog implements MessageAwareDialog{ String valueShort = Utils.getValueShortString(addressState.getBalance()); String result = - String.format(" By: [%s] %s", - addressShort, valueShort); + String.format(" By: [%s] %s", addressShort, valueShort); return result; } diff --git a/ethereumj-core/src/main/java/org/ethereum/gui/DialogWorker.java b/ethereumj-core/src/main/java/org/ethereum/gui/DialogWorker.java index f0f8907e..53275532 100644 --- a/ethereumj-core/src/main/java/org/ethereum/gui/DialogWorker.java +++ b/ethereumj-core/src/main/java/org/ethereum/gui/DialogWorker.java @@ -4,8 +4,11 @@ import org.ethereum.core.Transaction; import org.ethereum.manager.MainData; import org.ethereum.net.submit.TransactionExecutor; import org.ethereum.net.submit.TransactionTask; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import javax.swing.*; + import java.util.concurrent.ExecutionException; import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; @@ -18,13 +21,14 @@ import static org.ethereum.config.SystemProperties.CONFIG; * User: Roman Mandeleil * Created on: 26/05/2014 12:27 */ - public class DialogWorker extends SwingWorker { - Transaction tx; - MessageAwareDialog dialog; + private static Logger logger = LoggerFactory.getLogger(DialogWorker.class); + + private Transaction tx; + private MessageAwareDialog dialog; - DialogWorker(Transaction tx, MessageAwareDialog dialog) { + public DialogWorker(Transaction tx, MessageAwareDialog dialog) { this.tx = tx; this.dialog = dialog; } @@ -32,21 +36,21 @@ public class DialogWorker extends SwingWorker { @Override protected Object doInBackground() throws Exception { TransactionTask transactionTask = new TransactionTask(tx); - Future future = TransactionExecutor.instance.submitTransaction(transactionTask); + Future future = TransactionExecutor.instance.submitTransaction(transactionTask); dialog.infoStatusMsg("Transaction sent to the network, waiting for approve"); try { future.get(CONFIG.transactionApproveTimeout(), TimeUnit.SECONDS); - } catch (TimeoutException e1) { - e1.printStackTrace(); + } catch (TimeoutException toe) { + logger.error(toe.getMessage(), toe); dialog.alertStatusMsg("Transaction wasn't approved, network timeout"); return null; - } catch (InterruptedException e1) { - e1.printStackTrace(); + } catch (InterruptedException ie) { + logger.error(ie.getMessage(), ie); dialog.alertStatusMsg("Transaction wasn't approved"); return null; - } catch (ExecutionException e1) { - e1.printStackTrace(); + } catch (ExecutionException ee) { + logger.error(ee.getMessage(), ee); dialog.alertStatusMsg("Transaction wasn't approved"); return null; } finally { diff --git a/ethereumj-core/src/main/java/org/ethereum/gui/MessageAwareDialog.java b/ethereumj-core/src/main/java/org/ethereum/gui/MessageAwareDialog.java index 18cffe96..5343a6f9 100644 --- a/ethereumj-core/src/main/java/org/ethereum/gui/MessageAwareDialog.java +++ b/ethereumj-core/src/main/java/org/ethereum/gui/MessageAwareDialog.java @@ -1,16 +1,12 @@ package org.ethereum.gui; -import javax.swing.*; -import java.awt.*; - /** - * www.ethereumJ.com - * User: Roman Mandeleil - * Created on: 26/05/2014 12:29 + * This interface describes the methods required + * for any dialog that displays info- and alert status messages. */ - public interface MessageAwareDialog { - public void infoStatusMsg(final String text); - public void alertStatusMsg(final String text); + public void infoStatusMsg(final String text); + + public void alertStatusMsg(final String text); } 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 a922cef9..eb76932c 100644 --- a/ethereumj-core/src/main/java/org/ethereum/gui/PayOutDialog.java +++ b/ethereumj-core/src/main/java/org/ethereum/gui/PayOutDialog.java @@ -22,12 +22,14 @@ import javax.swing.*; * User: Roman Mandeleil * Created on: 18/05/14 22:21 */ -class PayOutDialog extends JDialog implements MessageAwareDialog{ +class PayOutDialog extends JDialog implements MessageAwareDialog { - PayOutDialog dialog; + private static final long serialVersionUID = -2838121935782110981L; - AccountState addressState = null; - JLabel statusMsg = null; + private PayOutDialog dialog; + + private AccountState addressState = null; + private JLabel statusMsg = null; final JTextField receiverInput; final JTextField amountInput; @@ -124,7 +126,6 @@ class PayOutDialog extends JDialog implements MessageAwareDialog{ try { tx.sign(senderPrivKey); } catch (Exception e1) { - dialog.alertStatusMsg("Failed to sign the transaction"); return; } diff --git a/ethereumj-core/src/main/java/org/ethereum/gui/ProgramPlayDialog.java b/ethereumj-core/src/main/java/org/ethereum/gui/ProgramPlayDialog.java index db905113..471984a0 100644 --- a/ethereumj-core/src/main/java/org/ethereum/gui/ProgramPlayDialog.java +++ b/ethereumj-core/src/main/java/org/ethereum/gui/ProgramPlayDialog.java @@ -1,8 +1,6 @@ package org.ethereum.gui; -import org.ethereum.vm.DataWord; import org.ethereum.vm.Program; -import org.ethereum.vm.ProgramInvoke; import org.ethereum.vm.VM; import org.spongycastle.util.encoders.Hex; @@ -12,7 +10,6 @@ import javax.swing.event.ChangeListener; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; -import java.awt.event.WindowListener; import java.util.*; import java.util.List; @@ -22,7 +19,8 @@ import java.util.List; * Created on: 02/06/2014 16:58 */ -public class ProgramPlayDialog extends JPanel implements ActionListener, ChangeListener, Program.ProgramListener { +public class ProgramPlayDialog extends JPanel implements ActionListener, + ChangeListener, Program.ProgramListener { public List outputList; public JTextArea console; @@ -95,8 +93,6 @@ public class ProgramPlayDialog extends JPanel implements ActionListener, ChangeL @Override public void actionPerformed(ActionEvent e) { - - } @Override @@ -111,7 +107,6 @@ public class ProgramPlayDialog extends JPanel implements ActionListener, ChangeL console.setCaretPosition(0); } - /** * Create the GUI and show it. For thread safety, * this method should be invoked from the @@ -119,8 +114,6 @@ public class ProgramPlayDialog extends JPanel implements ActionListener, ChangeL */ public static void createAndShowGUI() { - - ProgramPlayDialog ppd = new ProgramPlayDialog(); //Create and set up the window. @@ -130,7 +123,6 @@ public class ProgramPlayDialog extends JPanel implements ActionListener, ChangeL frame.setPreferredSize(new Dimension(580, 500)); frame.setLocation(400, 200); - //Add content to the window. frame.add(ppd, BorderLayout.CENTER); @@ -138,7 +130,6 @@ public class ProgramPlayDialog extends JPanel implements ActionListener, ChangeL frame.pack(); frame.setVisible(true); ppd.setFocus(); - } @Override @@ -151,10 +142,9 @@ public class ProgramPlayDialog extends JPanel implements ActionListener, ChangeL /* Turn off metal's use of bold fonts */ UIManager.put("swing.boldMetal", Boolean.FALSE); - //Schedule a job for the event-dispatching thread: //creating and showing this application's GUI. - javax.swing.SwingUtilities.invokeLater(new Runnable() { + SwingUtilities.invokeLater(new Runnable() { public void run() { createAndShowGUI(); } diff --git a/ethereumj-core/src/main/java/org/ethereum/net/message/StaticMessages.java b/ethereumj-core/src/main/java/org/ethereum/net/message/StaticMessages.java index 5027bbc7..4fa06b5b 100644 --- a/ethereumj-core/src/main/java/org/ethereum/net/message/StaticMessages.java +++ b/ethereumj-core/src/main/java/org/ethereum/net/message/StaticMessages.java @@ -16,7 +16,7 @@ public class StaticMessages { public static final byte[] GET_TRANSACTIONS = Hex.decode("2240089100000002C116"); public static final byte[] DISCONNECT_08 = Hex.decode("2240089100000003C20108"); - public static final byte[] GENESIS_HASH = Hex.decode("77ef4fdaf389dca53236bcf7f72698e154eab2828f86fbc4fc6cd9225d285c89"); // (new Genesis()).getHash(); + public static final byte[] GENESIS_HASH = Hex.decode("77ef4fdaf389dca53236bcf7f72698e154eab2828f86fbc4fc6cd9225d285c89"); public static final byte[] MAGIC_PACKET = Hex.decode("22400891"); static { diff --git a/ethereumj-core/src/main/java/org/ethereum/net/submit/PendingTransaction.java b/ethereumj-core/src/main/java/org/ethereum/net/submit/PendingTransaction.java index 56f50af2..775d56c9 100644 --- a/ethereumj-core/src/main/java/org/ethereum/net/submit/PendingTransaction.java +++ b/ethereumj-core/src/main/java/org/ethereum/net/submit/PendingTransaction.java @@ -10,14 +10,16 @@ import org.ethereum.core.Transaction; public class PendingTransaction { - Transaction tx; + private Transaction tx; int approved = 0; // each time the tx got from the wire this value increased public PendingTransaction(Transaction tx) { this.tx = tx; } - public void incApproved(){++this.approved;} + public void incApproved() { + ++this.approved; + } public int getApproved() { return approved; diff --git a/ethereumj-core/src/main/java/org/ethereum/trie/TrieIterator.java b/ethereumj-core/src/main/java/org/ethereum/trie/TrieIterator.java index 57c5c943..20148ebb 100644 --- a/ethereumj-core/src/main/java/org/ethereum/trie/TrieIterator.java +++ b/ethereumj-core/src/main/java/org/ethereum/trie/TrieIterator.java @@ -7,12 +7,12 @@ import static org.ethereum.util.CompactEncoder.unpackToNibbles; public class TrieIterator { - Trie trie; - String key; - String value; + private Trie trie; + private String key; + private String value; - List shas; - List values; + private List shas; + private List values; public TrieIterator(Trie t) { this.trie = t; diff --git a/ethereumj-core/src/main/resources/system.properties b/ethereumj-core/src/main/resources/system.properties index aaa27411..8925ac14 100644 --- a/ethereumj-core/src/main/resources/system.properties +++ b/ethereumj-core/src/main/resources/system.properties @@ -69,4 +69,4 @@ 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 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 12f09aa9..2210d050 100644 --- a/ethereumj-core/src/test/java/org/ethereum/core/BlockTest.java +++ b/ethereumj-core/src/test/java/org/ethereum/core/BlockTest.java @@ -22,7 +22,7 @@ public class BlockTest { // from RLP encoding byte[] genesisBytes = Hex.decode(CPP_PoC5_GENESIS_HEX_RLP_ENCODED); Block genesisFromRLP = new Block(genesisBytes); - Genesis genesis = new Genesis(); + Block genesis = Genesis.getInstance(); assertEquals(Hex.toHexString(genesis.getHash()), Hex.toHexString(genesisFromRLP.getHash())); assertEquals(Hex.toHexString(genesis.getParentHash()), Hex.toHexString(genesisFromRLP.getParentHash())); assertEquals(Hex.toHexString(genesis.getStateRoot()), Hex.toHexString(genesisFromRLP.getStateRoot())); @@ -48,7 +48,7 @@ public class BlockTest { B32(sha3(B(42))) ) */ - Block genesis = new Genesis(); + Block genesis = Genesis.getInstance(); assertEquals(CPP_PoC5_GENESIS_HEX_RLP_ENCODED, Hex.toHexString(genesis.getEncoded())); // Not really a good test because this compares Genesis.getHash() to itself diff --git a/ethereumj-core/src/test/java/org/ethereum/vm/ProgramInvokeMockImpl.java b/ethereumj-core/src/test/java/org/ethereum/vm/ProgramInvokeMockImpl.java index a23b983b..f7257730 100644 --- a/ethereumj-core/src/test/java/org/ethereum/vm/ProgramInvokeMockImpl.java +++ b/ethereumj-core/src/test/java/org/ethereum/vm/ProgramInvokeMockImpl.java @@ -4,8 +4,6 @@ import org.ethereum.crypto.ECKey; import org.ethereum.crypto.HashUtil; import org.spongycastle.util.encoders.Hex; -import java.util.List; - /** * www.ethereumJ.com * User: Roman Mandeleil