Avoid putting conflicting state into the db
This commit is contained in:
parent
202be8f553
commit
d932294c0c
|
@ -13,7 +13,6 @@ import org.spongycastle.util.encoders.Hex;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import static org.ethereum.config.SystemProperties.CONFIG;
|
import static org.ethereum.config.SystemProperties.CONFIG;
|
||||||
|
@ -86,14 +85,13 @@ public class Blockchain {
|
||||||
return new Block(chainDb.get(ByteUtil.longToBytes(blockNr)));
|
return new Block(chainDb.get(ByteUtil.longToBytes(blockNr)));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void applyBlock(Block block) {
|
public void add(Block block) {
|
||||||
|
|
||||||
if (block == null)
|
if (block == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
||||||
// if it is the first block to add
|
// if it is the first block to add
|
||||||
// check that the parent is the genesis
|
// make sure the parent is genesis
|
||||||
if (index.isEmpty()
|
if (index.isEmpty()
|
||||||
&& !Arrays.equals(Genesis.getInstance().getHash(),
|
&& !Arrays.equals(Genesis.getInstance().getHash(),
|
||||||
block.getParentHash())) {
|
block.getParentHash())) {
|
||||||
|
@ -105,38 +103,24 @@ public class Blockchain {
|
||||||
String blockParentHash = Hex.toHexString(block.getParentHash());
|
String blockParentHash = Hex.toHexString(block.getParentHash());
|
||||||
if (!hashLast.equals(blockParentHash)) return;
|
if (!hashLast.equals(blockParentHash)) return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.addBlock(block);
|
|
||||||
if (block.getNumber() >= CONFIG.traceStartBlock() && CONFIG.traceStartBlock() != -1) {
|
if (block.getNumber() >= CONFIG.traceStartBlock() && CONFIG.traceStartBlock() != -1) {
|
||||||
AdvancedDeviceUtils.adjustDetailedTracing(block.getNumber());
|
AdvancedDeviceUtils.adjustDetailedTracing(block.getNumber());
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Debug check to see if the state is still as expected */
|
this.processBlock(block);
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Remove all wallet transactions as they already approved by the net
|
// Remove all wallet transactions as they already approved by the net
|
||||||
for (Transaction tx : block.getTransactionsList()) {
|
for (Transaction tx : block.getTransactionsList()) {
|
||||||
if (logger.isDebugEnabled())
|
if (logger.isDebugEnabled())
|
||||||
logger.debug("pending cleanup: tx.hash: [{}]", Hex.toHexString( tx.getHash()));
|
logger.debug("pending cleanup: tx.hash: [{}]", Hex.toHexString( tx.getHash()));
|
||||||
WorldManager.getInstance().removeWalletTransaction(tx);
|
WorldManager.getInstance().removeWalletTransaction(tx);
|
||||||
}
|
}
|
||||||
logger.info("*** Block chain size: [ {} ]", this.getSize());
|
|
||||||
|
|
||||||
|
|
||||||
EthereumListener listener = WorldManager.getInstance().getListener();
|
EthereumListener listener = WorldManager.getInstance().getListener();
|
||||||
if (listener != null)
|
if (listener != null)
|
||||||
listener.trace(String.format("Block chain size: [ %d ]", this.getSize()));
|
listener.trace(String.format("Block chain size: [ %d ]", this.getSize()));
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
if (lastBlock.getNumber() >= 30) {
|
if (lastBlock.getNumber() >= 30) {
|
||||||
System.out.println("** checkpoint **");
|
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.isValid()) {
|
||||||
|
|
||||||
if (!block.isGenesis()) {
|
if (!block.isGenesis()) {
|
||||||
for (Transaction tx : block.getTransactionsList())
|
for (Transaction tx : block.getTransactionsList())
|
||||||
// TODO: refactor the wallet pending transactions to the world manager
|
// TODO: refactor the wallet pending transactions to the world manager
|
||||||
WorldManager.getInstance().addWalletTransaction(tx);
|
WorldManager.getInstance().addWalletTransaction(tx);
|
||||||
WorldManager.getInstance().applyBlock(block);
|
WorldManager.getInstance().applyBlock(block);
|
||||||
|
WorldManager.getInstance().getWallet().processBlock(block);
|
||||||
}
|
}
|
||||||
|
this.storeBlock(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());
|
|
||||||
} else {
|
} else {
|
||||||
logger.warn("Invalid block with nr: {}", block.getNumber());
|
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() {
|
public long getGasPrice() {
|
||||||
// In case of the genesis block we don't want to rely on the min gas price
|
// 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;
|
return lastBlock.isGenesis() ? lastBlock.getMinGasPrice() : INITIAL_MIN_GAS_PRICE;
|
||||||
|
@ -188,7 +186,7 @@ public class Blockchain {
|
||||||
if (!iterator.hasNext()) {
|
if (!iterator.hasNext()) {
|
||||||
logger.info("DB is empty - adding Genesis");
|
logger.info("DB is empty - adding Genesis");
|
||||||
this.lastBlock = Genesis.getInstance();
|
this.lastBlock = Genesis.getInstance();
|
||||||
this.addBlock(lastBlock);
|
this.storeBlock(lastBlock);
|
||||||
logger.debug("Block #{} -> {}", Genesis.NUMBER, lastBlock.toFlatString());
|
logger.debug("Block #{} -> {}", Genesis.NUMBER, lastBlock.toFlatString());
|
||||||
} else {
|
} else {
|
||||||
logger.debug("Displaying blocks stored in DB sorted on blocknumber");
|
logger.debug("Displaying blocks stored in DB sorted on blocknumber");
|
||||||
|
|
|
@ -308,6 +308,10 @@ public class WorldManager {
|
||||||
|
|
||||||
public void applyBlock(Block block) {
|
public void applyBlock(Block block) {
|
||||||
|
|
||||||
|
if(block.getNumber() == 1157) {
|
||||||
|
logger.debug("Block 1157");
|
||||||
|
}
|
||||||
|
|
||||||
int i = 0;
|
int i = 0;
|
||||||
for (Transaction tx : block.getTransactionsList()) {
|
for (Transaction tx : block.getTransactionsList()) {
|
||||||
logger.info("apply block: [ {} ] tx: [ {} ] ", block.getNumber(), i);
|
logger.info("apply block: [ {} ] tx: [ {} ] ", block.getNumber(), i);
|
||||||
|
|
|
@ -40,10 +40,10 @@ public class BlockQueue {
|
||||||
|
|
||||||
Block block = blockQueue.poll();
|
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);
|
Block lastReceivedBlock = blockList.get(blockList.size() - 1);
|
||||||
if (lastReceivedBlock.getNumber() != getLast().getNumber() + 1) return;
|
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());
|
logger.trace("Blocks waiting to be proceed in the queue: [ {} ]", blockQueue.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
public Block getLast(){
|
public Block getLast() {
|
||||||
|
|
||||||
if (blockQueue.isEmpty())
|
if (blockQueue.isEmpty())
|
||||||
return WorldManager.getInstance().getBlockChain().getLastBlock();
|
return WorldManager.getInstance().getBlockChain().getLastBlock();
|
||||||
|
@ -69,7 +69,7 @@ public class BlockQueue {
|
||||||
return lastBlock;
|
return lastBlock;
|
||||||
}
|
}
|
||||||
|
|
||||||
private class BlockByIndexComparator implements Comparator<Block>{
|
private class BlockByIndexComparator implements Comparator<Block> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int compare(Block o1, Block o2) {
|
public int compare(Block o1, Block o2) {
|
||||||
|
@ -83,7 +83,7 @@ public class BlockQueue {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public int size(){
|
public int size() {
|
||||||
return blockQueue.size();
|
return blockQueue.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -35,7 +35,7 @@ import org.spongycastle.util.encoders.Hex;
|
||||||
* @author: Nick Savers
|
* @author: Nick Savers
|
||||||
* Created on: 20/05/2014 10:44
|
* Created on: 20/05/2014 10:44
|
||||||
*/
|
*/
|
||||||
public class Trie implements TrieFacade{
|
public class Trie implements TrieFacade {
|
||||||
|
|
||||||
private Logger logger = LoggerFactory.getLogger("trie");
|
private Logger logger = LoggerFactory.getLogger("trie");
|
||||||
|
|
||||||
|
|
|
@ -9,8 +9,12 @@ server.acceptConnections = false
|
||||||
#peer.discovery.port = 30303
|
#peer.discovery.port = 30303
|
||||||
|
|
||||||
# Peer Server One: peer discovery
|
# Peer Server One: peer discovery
|
||||||
peer.discovery.ip = 54.204.10.41
|
|
||||||
|
# Asimov
|
||||||
|
peer.discovery.ip = 185.43.109.23
|
||||||
peer.discovery.port = 30303
|
peer.discovery.port = 30303
|
||||||
|
|
||||||
|
# RomanJ
|
||||||
#peer.discovery.ip = 54.211.14.10
|
#peer.discovery.ip = 54.211.14.10
|
||||||
#peer.discovery.port = 30303
|
#peer.discovery.port = 30303
|
||||||
|
|
||||||
|
@ -30,7 +34,7 @@ peer.discovery.port = 30303
|
||||||
#peer.active.port = 30303
|
#peer.active.port = 30303
|
||||||
|
|
||||||
# PoC-5 testnet
|
# PoC-5 testnet
|
||||||
peer.active.ip = 54.204.10.41
|
peer.active.ip = 185.43.109.23
|
||||||
peer.active.port = 30303
|
peer.active.port = 30303
|
||||||
|
|
||||||
#peer.active.ip = 54.72.69.180
|
#peer.active.ip = 54.72.69.180
|
||||||
|
@ -80,7 +84,7 @@ samples.dir = samples
|
||||||
# the existing database will be
|
# the existing database will be
|
||||||
# destroyed and all the data will be
|
# destroyed and all the data will be
|
||||||
# downloaded from peers again
|
# downloaded from peers again
|
||||||
database.reset = true
|
database.reset = false
|
||||||
|
|
||||||
# place to save physical storage files
|
# place to save physical storage files
|
||||||
database.dir = database
|
database.dir = database
|
||||||
|
@ -104,14 +108,14 @@ dump.clean.on.restart = true
|
||||||
# make changes to tracing options
|
# make changes to tracing options
|
||||||
# starting from certain block
|
# starting from certain block
|
||||||
# -1 don't make any tracing changes
|
# -1 don't make any tracing changes
|
||||||
trace.startblock = 1150
|
trace.startblock = 1155
|
||||||
|
|
||||||
# invoke vm program on
|
# invoke vm program on
|
||||||
# message received,
|
# message received,
|
||||||
# if the vm is not invoked
|
# if the vm is not invoked
|
||||||
# the balance transfer
|
# the balance transfer
|
||||||
# occurs anyway [true/false]
|
# occurs anyway [true/false]
|
||||||
play.vm = false
|
play.vm = true
|
||||||
|
|
||||||
# maximum blocks to ask,
|
# maximum blocks to ask,
|
||||||
# when downloading the chain
|
# when downloading the chain
|
||||||
|
|
|
@ -115,7 +115,7 @@ public class BlockTest {
|
||||||
assertEquals(new BigInteger(1, Genesis.DIFFICULTY), difficulty);
|
assertEquals(new BigInteger(1, Genesis.DIFFICULTY), difficulty);
|
||||||
|
|
||||||
// Storing genesis because the parent needs to be in the DB for calculation.
|
// 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));
|
Block block1 = new Block(Hex.decode(block_1));
|
||||||
BigInteger calcDifficulty = new BigInteger(1, block1.calcDifficulty());
|
BigInteger calcDifficulty = new BigInteger(1, block1.calcDifficulty());
|
||||||
|
@ -137,7 +137,7 @@ public class BlockTest {
|
||||||
assertEquals(Genesis.GAS_LIMIT, gasLimit);
|
assertEquals(Genesis.GAS_LIMIT, gasLimit);
|
||||||
|
|
||||||
// Storing genesis because the parent needs to be in the DB for calculation.
|
// 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
|
// Test with block
|
||||||
Block block1 = new Block(Hex.decode(block_1));
|
Block block1 = new Block(Hex.decode(block_1));
|
||||||
|
|
Loading…
Reference in New Issue