BlockChain refactoring:

+ keep only index of block hash numbers in the cach
+ for the full block data, query DB
This commit is contained in:
romanman 2014-06-09 10:51:31 +01:00
parent b3bf0f024c
commit bb8291457a
9 changed files with 49 additions and 27 deletions

View File

@ -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

View File

@ -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<Block> {
public class Blockchain {
private static final long serialVersionUID = -143590724563460486L;
@ -36,6 +37,10 @@ public class Blockchain extends ArrayList<Block> {
private long gasPrice = 1000;
private Block lastBlock;
// keep the index of the chain for
// convenient usage, <block_number, block_hash>
private HashMap<Long, byte[]> index = new HashMap<Long, byte[]>();
// This map of transaction designed
// to approve the tx by external trusted peer
private Map<String, WalletTransaction> walletTransactions =
@ -50,7 +55,17 @@ public class Blockchain extends ArrayList<Block> {
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<Block> blocks) {
if (blocks.isEmpty())
@ -60,15 +75,14 @@ public class Blockchain extends ArrayList<Block> {
// 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<Block> {
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<Block> {
// 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<Block> {
}
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<Block> {
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();
}

View File

@ -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

View File

@ -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();
}
}

View File

@ -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;

View File

@ -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);

View File

@ -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

View File

@ -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

View File

@ -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