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 789d547a..d9af2975 100644
--- a/ethereumj-core/src/main/java/org/ethereum/core/Blockchain.java
+++ b/ethereumj-core/src/main/java/org/ethereum/core/Blockchain.java
@@ -15,17 +15,33 @@ import java.util.*;
import static org.ethereum.core.Denomination.*;
-/*
- *
- * www.ethereumJ.com
- * @author: Nick Savers
- * Created on: 20/05/2014 10:44
- *
+/**
+ * The Ethereum blockchain is in many ways similar to the Bitcoin blockchain,
+ * although it does have some differences.
+ *
+ * The main difference between Ethereum and Bitcoin with regard to the blockchain architecture
+ * is that, unlike Bitcoin, Ethereum blocks contain a copy of both the transaction list
+ * and the most recent state. Aside from that, two other values, the block number and
+ * the difficulty, are also stored in the block.
+ *
+ * The block validation algorithm in Ethereum is as follows:
+ *
+ * - Check if the previous block referenced exists and is valid.
+ * - Check that the timestamp of the block is greater than that of the referenced previous block and less than 15 minutes into the future
+ * - Check that the block number, difficulty, transaction root, uncle root and gas limit (various low-level Ethereum-specific concepts) are valid.
+ * - Check that the proof of work on the block is valid.
+ * - Let S[0] be the STATE_ROOT of the previous block.
+ * - Let TX be the block's transaction list, with n transactions.
+ * For all in in 0...n-1, set S[i+1] = APPLY(S[i],TX[i]).
+ * If any applications returns an error, or if the total gas consumed in the block
+ * up until this point exceeds the GASLIMIT, return an error.
+ * - Let S_FINAL be S[n], but adding the block reward paid to the miner.
+ * - Check if S_FINAL is the same as the STATE_ROOT. If it is, the block is valid; otherwise, it is not valid.
+ *
+ * See Ethereum Whitepaper
*/
public class Blockchain {
- private static final long serialVersionUID = -143590724563460486L;
-
private static Logger logger = LoggerFactory.getLogger("blockchain");
// to avoid using minGasPrice=0 from Genesis for the wallet
@@ -113,7 +129,7 @@ public class Blockchain {
setLastBlock(block);
index.put(block.getNumber(), block.getParentHash());
} else {
- logger.warn("Invalid block with nr: " + block.getNumber());
+ logger.warn("Invalid block with nr: {}", block.getNumber());
}
}
@@ -130,7 +146,7 @@ public class Blockchain {
*/
public WalletTransaction addWalletTransaction(Transaction transaction) {
String hash = Hex.toHexString(transaction.getHash());
- logger.info("pending transaction placed hash: {} ", hash );
+ logger.info("pending transaction placed hash: {}", hash );
WalletTransaction walletTransaction = this.walletTransactions.get(hash);
if (walletTransaction != null)
@@ -144,7 +160,7 @@ public class Blockchain {
public void removeWalletTransaction(Transaction transaction){
String hash = Hex.toHexString(transaction.getHash());
- logger.info("pending transaction removed with hash: {} ", hash );
+ logger.info("pending transaction removed with hash: {} ", hash);
walletTransactions.remove(hash);
}
@@ -162,7 +178,7 @@ public class Blockchain {
logger.info("DB is empty - adding Genesis");
this.lastBlock = Genesis.getInstance();
this.addBlock(lastBlock);
- logger.debug("Block #" + Genesis.NUMBER + " -> " + lastBlock.toFlatString());
+ logger.debug("Block #{} -> {}", Genesis.NUMBER, lastBlock.toFlatString());
db.put(ByteUtil.longToBytes(Genesis.NUMBER), lastBlock.getEncoded());
}
@@ -172,7 +188,7 @@ public class Blockchain {
this.lastBlock = new Block(db.get(ByteUtil.longToBytes(blockNr)));
// in case of cold load play the contracts
WorldManager.instance.applyBlock(lastBlock);
- logger.debug("Block #" + lastBlock.getNumber() + " -> " + lastBlock.toFlatString());
+ logger.debug("Block #{} -> {}", lastBlock.getNumber(), lastBlock.toFlatString());
this.addBlock(lastBlock);
blockNr = lastBlock.getNumber()+1;
}