Avoid putting conflicting state into the db

This commit is contained in:
nicksavers 2014-07-31 22:28:00 +02:00
parent 202be8f553
commit d932294c0c
6 changed files with 53 additions and 47 deletions

View File

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

View File

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

View File

@ -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<Block> blockList){
public void addBlocks(List<Block> 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<Block>{
private class BlockByIndexComparator implements Comparator<Block> {
@Override
public int compare(Block o1, Block o2) {
@ -83,7 +83,7 @@ public class BlockQueue {
}
}
public int size(){
public int size() {
return blockQueue.size();
}

View File

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

View File

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

View File

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