From bb8291457a3e9203c682fddf0785c989211061bc Mon Sep 17 00:00:00 2001 From: romanman Date: Mon, 9 Jun 2014 10:51:31 +0100 Subject: [PATCH] BlockChain refactoring: + keep only index of block hash numbers in the cach + for the full block data, query DB --- .../main/java/org/ethereum/core/Block.java | 2 +- .../java/org/ethereum/core/Blockchain.java | 41 +++++++++++++------ .../org/ethereum/gui/BlockChainTable.java | 10 ++--- .../org/ethereum/gui/BlockTableModel.java | 8 +++- .../org/ethereum/manager/WorldManager.java | 1 - .../net/client/EthereumProtocolHandler.java | 1 + .../ethereum/net/message/GetChainMessage.java | 3 ++ .../src/main/resources/log4j.properties | 2 +- .../src/main/resources/system.properties | 8 ++-- 9 files changed, 49 insertions(+), 27 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 19d50480..2d4c079d 100644 --- a/ethereumj-core/src/main/java/org/ethereum/core/Block.java +++ b/ethereumj-core/src/main/java/org/ethereum/core/Block.java @@ -78,7 +78,7 @@ public class Block { private void parseRLP() { - RLPList params = (RLPList) RLP.decode2(rlpEncoded); + RLPList params = RLP.decode2(rlpEncoded); RLPList block = (RLPList) params.get(0); // Parse Header 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 39cda83f..72628836 100644 --- a/ethereumj-core/src/main/java/org/ethereum/core/Blockchain.java +++ b/ethereumj-core/src/main/java/org/ethereum/core/Blockchain.java @@ -10,6 +10,7 @@ import org.slf4j.LoggerFactory; import org.spongycastle.util.encoders.Hex; import java.io.IOException; +import java.nio.ByteBuffer; import java.util.*; import static org.ethereum.core.Denomination.*; @@ -21,7 +22,7 @@ import static org.ethereum.core.Denomination.*; * Created on: 20/05/2014 10:44 * */ -public class Blockchain extends ArrayList { +public class Blockchain { private static final long serialVersionUID = -143590724563460486L; @@ -36,6 +37,10 @@ public class Blockchain extends ArrayList { private long gasPrice = 1000; private Block lastBlock; + // keep the index of the chain for + // convenient usage, + private HashMap index = new HashMap(); + // This map of transaction designed // to approve the tx by external trusted peer private Map walletTransactions = @@ -50,7 +55,17 @@ public class Blockchain extends ArrayList { public Block getLastBlock() { return lastBlock; } - + + public int getSize(){ + return index.size(); + } + + public Block getByNumber(int rowIndex){ + byte[] parentHash = index.get((long)rowIndex); + if (parentHash == null) return null; + return new Block(db.get(parentHash)); + } + public void addBlocks(List blocks) { if (blocks.isEmpty()) @@ -60,15 +75,14 @@ public class Blockchain extends ArrayList { // if it is the first block to add // check that the parent is the genesis - if (this.isEmpty() + if (index.isEmpty() && !Arrays.equals(StaticMessages.GENESIS_HASH, firstBlockToAdd.getParentHash())) { return; } // if there is some blocks already keep chain continuity - if (!this.isEmpty()) { - Block lastBlock = this.get(this.size() - 1); - String hashLast = Hex.toHexString(lastBlock.getHash()); + if (!index.isEmpty()) { + String hashLast = Hex.toHexString(getLastBlock().getHash()); String blockParentHash = Hex.toHexString(firstBlockToAdd.getParentHash()); if (!hashLast.equals(blockParentHash)) return; } @@ -87,7 +101,7 @@ public class Blockchain extends ArrayList { removeWalletTransaction(tx); } } - logger.info("*** Block chain size: [ {} ]", this.size()); + logger.info("*** Block chain size: [ {} ]", index.size()); } private void addBlock(Block block) { @@ -97,9 +111,10 @@ public class Blockchain extends ArrayList { // on this price will use default 10000000000000 // todo: refactor this longValue some constant defaults class 10000000000000L this.gasPrice = block.isGenesis() ? INITIAL_MIN_GAS_PRICE : block.getMinGasPrice(); - if(lastBlock == null || block.getNumber() > lastBlock.getNumber()) + if(lastBlock == null || block.getNumber() > lastBlock.getNumber()){ this.lastBlock = block; - this.add(block); + index.put(block.getNumber(), block.getParentHash()); + } } } @@ -135,7 +150,7 @@ public class Blockchain extends ArrayList { } public byte[] getLatestBlockHash(){ - if (this.isEmpty()) + if (index.isEmpty()) return StaticMessages.GENESIS_HASH; else return lastBlock.getHash(); @@ -147,15 +162,15 @@ public class Blockchain extends ArrayList { if (!iterator.hasNext()) { logger.info("DB is empty - adding Genesis"); Block genesis = Genesis.getInstance(); - this.addBlock(genesis); + 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()) + this.addBlock(new Block(db.get(parentHash))); + if (logger.isDebugEnabled()) logger.debug("Block: " + lastBlock.getNumber() + " ---> " + lastBlock.toFlatString()); parentHash = lastBlock.getHash(); } 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 1e70ba2e..9cea4ae3 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 (MainData.instance.getBlockchain().size() - 1 < lastFindIndex) return; + if (MainData.instance.getBlockchain().getSize() - 1 < lastFindIndex) return; - Block block = MainData.instance.getBlockchain().get(lastFindIndex); + Block block = MainData.instance.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 < MainData.instance.getBlockchain().size(); ++i) { + for (int i = lastFindIndex + 1; i < MainData.instance.getBlockchain().getSize(); ++i) { - if (MainData.instance.getBlockchain().size() - 1 < i) return; - Block block = MainData.instance.getBlockchain().get(i); + if (MainData.instance.getBlockchain().getSize() - 1 < i) return; + Block block = MainData.instance.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 0c9a54a5..733404cf 100644 --- a/ethereumj-core/src/main/java/org/ethereum/gui/BlockTableModel.java +++ b/ethereumj-core/src/main/java/org/ethereum/gui/BlockTableModel.java @@ -1,5 +1,6 @@ package org.ethereum.gui; +import org.ethereum.core.Block; import org.ethereum.manager.MainData; import javax.swing.table.AbstractTableModel; @@ -15,7 +16,7 @@ public class BlockTableModel extends AbstractTableModel { public int getRowCount() { fireTableDataChanged(); - int rowCount = MainData.instance.getBlockchain().size(); + int rowCount = MainData.instance.getBlockchain().getSize(); return rowCount; } @@ -30,6 +31,9 @@ public class BlockTableModel extends AbstractTableModel { // byte[] hash = MainData.instance.getAllBlocks().get(rowIndex).getHash(); // return Hex.toHexString(hash); - return MainData.instance.getBlockchain().get(rowIndex).toString(); + Block block = MainData.instance.getBlockchain().getByNumber(rowIndex); + if (block == null) return ""; + + return block.toString(); } } 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 d319469a..7599d27f 100644 --- a/ethereumj-core/src/main/java/org/ethereum/manager/WorldManager.java +++ b/ethereumj-core/src/main/java/org/ethereum/manager/WorldManager.java @@ -2,7 +2,6 @@ package org.ethereum.manager; import org.ethereum.core.AccountState; import org.ethereum.core.Block; -import org.ethereum.core.Blockchain; import org.ethereum.core.Transaction; import org.ethereum.crypto.HashUtil; import org.ethereum.db.Database; 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 06cc6e50..a36cc745 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 @@ -359,6 +359,7 @@ public class EthereumProtocolHandler extends ChannelInboundHandlerAdapter { byte[] hash = MainData.instance.getBlockchain().getLatestBlockHash(); GetChainMessage chainMessage = new GetChainMessage((byte)100, hash); + chainMessage.toString(); ByteBuf buffer = ctx.alloc().buffer(chainMessage.getPayload().length + 8); buffer.writeBytes(StaticMessages.MAGIC_PACKET); 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 cd05e657..b8593f85 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 @@ -34,6 +34,7 @@ public class GetChainMessage extends Message { encodedElements[0] = new byte[]{0x14}; int i = 1; for (byte[] hash : blockHashList){ + this.blockHashList.add(hash); byte[] element = RLP.encodeElement(hash); encodedElements[i] = element; ++i; @@ -41,6 +42,8 @@ public class GetChainMessage extends Message { encodedElements[i] = RLP.encodeByte(number); this.payload = RLP.encodeList(encodedElements); + this.parsed = true; + } @Override diff --git a/ethereumj-core/src/main/resources/log4j.properties b/ethereumj-core/src/main/resources/log4j.properties index fe6fe205..6b5e5b3b 100644 --- a/ethereumj-core/src/main/resources/log4j.properties +++ b/ethereumj-core/src/main/resources/log4j.properties @@ -8,7 +8,7 @@ log4j.appender.stdout.layout=org.apache.log4j.PatternLayout log4j.appender.stdout.layout.ConversionPattern= %d{HH:mm:ss} [%c{1}] %m%n # filter noisy classes -log4j.logger.org.ethereum.net = FATAL +log4j.logger.org.ethereum.net = INFO log4j.logger.org.ethereum.net.peerdiscovery = WARN log4j.logger.java.nio = WARN log4j.logger.io.netty = FATAL diff --git a/ethereumj-core/src/main/resources/system.properties b/ethereumj-core/src/main/resources/system.properties index 431a3648..b4b81916 100644 --- a/ethereumj-core/src/main/resources/system.properties +++ b/ethereumj-core/src/main/resources/system.properties @@ -16,8 +16,8 @@ peer.discovery.port = 30303 # that is the peer through # we get the chain: [54.201.28.117] port: [30303] # ZeroGox -peer.active.ip = 54.204.10.41 -peer.active.port = 30303 +#peer.active.ip = 54.204.10.41 +#peer.active.port = 30303 # Some dude in Canada #peer.active.ip = 131.104.247.135 @@ -29,8 +29,8 @@ peer.active.port = 30303 # RomanJ general -#peer.active.ip = 54.211.14.10 -#peer.active.port = 50505 +peer.active.ip = 54.211.14.10 +peer.active.port = 50505 #peer.active.ip = 151.64.223.120 #peer.active.port = 30304