/**
* Copyright 2011 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.bitcoin.core;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.math.BigInteger;
import java.util.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import static com.google.bitcoin.core.Utils.*;
/**
* A block is the foundation of the BitCoin system. It records a set of {@link Transaction}s together with
* some data that links it into a place in the global block chain, and proves that a difficult calculation was done
* over its contents. See the BitCoin technical paper for more detail on blocks.<p>
*
* To get a block, you can either build one from the raw bytes you can get from another implementation,
* or request one specifically using {@link Peer#getBlock(byte[])}, or grab one from a downloaded {@link BlockChain}.
*/
public class Block extends Message {
private static final Logger log = LoggerFactory.getLogger(Block.class);
private static final long serialVersionUID = 2738848929966035281L;
/** How many bytes are required to represent a block header. */
public static final int HEADER_SIZE = 80;
static final long ALLOWED_TIME_DRIFT = 2 * 60 * 60; // Same value as official client.
/** A value for difficultyTarget (nBits) that allows half of all possible hash solutions. Used in unit testing. */
static final long EASIEST_DIFFICULTY_TARGET = 0x207fFFFFL;
// For unit testing. If not zero, use this instead of the current time.
static long fakeClock = 0;
private long version;
private byte[] prevBlockHash;
private byte[] merkleRoot;
private long time;
private long difficultyTarget; // "nBits"
private long nonce;
/** If null, it means this object holds only the headers. */
List<Transaction> transactions;
/** Stores the hash of the block. If null, getHash() will recalculate it. */
private transient byte[] hash;
/** Special case constructor, used for the genesis node and unit tests. */
Block(NetworkParameters params) {
super(params);
// Set up a few basic things. We are not complete after this though.
version = 1;
difficultyTarget = 0x1d07fff8L;
time = System.currentTimeMillis() / 1000;
prevBlockHash = new byte[32]; // All zeros.
}
/** Constructs a block object from the BitCoin wire format. */
public Block(NetworkParameters params, byte[] payloadBytes) throws ProtocolException {
super(params, payloadBytes, 0);
}
void parse() throws ProtocolException {
version = readUint32();
prevBlockHash = readHash();
merkleRoot = readHash();
time = readUint32();
difficultyTarget = readUint32();
nonce = readUint32();
hash = Utils.reverseBytes(Utils.doubleDigest(bytes, 0, cursor));
if (cursor == bytes.length) {
// This message is just a header, it has no transactions.
return;
}
int numTransactions = (int) readVarInt();
transactions = new ArrayList<Transaction>(numTransactions);
for (int i = 0; i < numTransactions; i++) {
Transaction tx = new Transaction(params, bytes, cursor);
transactions.add(tx);
cursor += tx.getMessageSize();
}
}
private void writeHeader(OutputStream stream) throws IOException {
Utils.uint32ToByteStreamLE(version, stream);
stream.write(Utils.reverseBytes(prevBlockHash));
stream.write(Utils.reverseBytes(getMerkleRoot()));
Utils.uint32ToByteStreamLE(time, stream);
Utils.uint32ToByteStreamLE(difficultyTarget, stream);
Utils.uint32ToByteStreamLE(nonce, stream);
}
@Override
void bitcoinSerializeToStream(OutputStream stream) throws IOException {
writeHeader(stream);
// We may only have enough data to write the header.
if (transactions == null) return;
stream.write(new VarInt(transactions.size()).encode());
for (Transaction tx : transactions) {
tx.bitcoinSerializeToStream(stream);
}
}
/**
* Calculates the block hash by serializing the block and hashing the resulting bytes.
*/
private byte[] calculateHash() {
try {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
writeHeader(bos);
return Utils.reverseBytes(doubleDigest(bos.toByteArray()));
} catch (IOException e) {
throw new RuntimeException(e); // Cannot happen.
}
}
/**
* Returns the hash of the block (which for a valid, solved block should be below the target) in the form seen
* on the block explorer. If you call this on block 1 in the production chain, you will get
* "00000000839a8e6886ab5951d76f411475428afc90947ee320161bbf18eb6048".
*/
public String getHashAsString() {
return Utils.bytesToHexString(getHash());
}
/**
* Returns the hash of the block (which for a valid, solved block should be below the target). Big endian.
*/
public byte[] getHash() {
if (hash == null)
hash = calculateHash();
return hash;
}
/** The number that is one greater than the largest representable SHA-256 hash. */
static private BigInteger LARGEST_HASH = BigInteger.ONE.shiftLeft(256);
/**
* Returns the work represented by this block.<p>
*
* Work is defined as the number of tries needed to solve a block in the average case. Consider a difficulty
* target that covers 5% of all possible hash values. Then the work of the block will be 20. As the target gets
* lower, the amount of work goes up.
*/
public BigInteger getWork() throws VerificationException {
BigInteger target = getDifficultyTargetAsInteger();
return LARGEST_HASH.divide(target.add(BigInteger.ONE));
}
/** Returns a copy of the block, but without any transactions. */
public Block cloneAsHeader() {
try {
Block block = new Block(params, bitcoinSerialize());
block.transactions = null;
return block;
} catch (ProtocolException e) {
// Should not be able to happen unless our state is internally inconsistent.
throw new RuntimeException(e);
}
}
/**
* Returns a multi-line string containing a description of the contents of the block. Use for debugging purposes
* only.
*/
@Override
public String toString() {
StringBuffer s = new StringBuffer("v" + version + " block: \n" +
" previous block: " + bytesToHexString(prevBlockHash) + "\n" +
" merkle root: " + bytesToHexString(getMerkleRoot()) + "\n" +
" time: [" + time + "] " + new Date(time * 1000).toString() + "\n" +
" difficulty target (nBits): " + difficultyTarget + "\n" +
" nonce: " + nonce + "\n");
if (transactions != null && transactions.size() > 0) {
s.append(" with ").append(transactions.size()).append(" transaction(s):\n");
for (Transaction tx : transactions) {
s.append(tx.toString());
}
}
return s.toString();
}
/**
* Finds a value of nonce that makes the blocks hash lower than the difficulty target. This is called mining,
* but solve() is far too slow to do real mining with. It exists only for unit testing purposes and is not a part
* of the public API.
*
* This can loop forever if a solution cannot be found solely by incrementing nonce. It doesn't change extraNonce.
*/
void solve() {
while (true) {
try {
// Is our proof of work valid yet?
if (checkProofOfWork(false)) return;
// No, so increment the nonce and try again.
setNonce(getNonce() + 1);
} catch (VerificationException e) {
throw new RuntimeException(e); // Cannot happen.
}
}
}
/**
* Returns the difficulty target as a 256 bit value that can be compared to a SHA-256 hash. Inside a block the
* target is represented using a compact form. If this form decodes to a value that is out of bounds,
* an exception is thrown.
*/
public BigInteger getDifficultyTargetAsInteger() throws VerificationException {
BigInteger target = Utils.decodeCompactBits(difficultyTarget);
if (target.compareTo(BigInteger.valueOf(0)) <= 0 || target.compareTo(params.proofOfWorkLimit) > 0)
throw new VerificationException("Difficulty target is bad: " + target.toString());
return target;
}
/** Returns true if the hash of the block is OK (lower than difficulty target). */
private boolean checkProofOfWork(boolean throwException) throws VerificationException {
// This part is key - it is what proves the block was as difficult to make as it claims
// to be. Note however that in the context of this function, the block can claim to be
// as difficult as it wants to be .... if somebody was able to take control of our network
// connection and fork us onto a different chain, they could send us valid blocks with
// ridiculously easy difficulty and this function would accept them.
//
// To prevent this attack from being possible, elsewhere we check that the difficultyTarget
// field is of the right value. This requires us to have the preceeding blocks.
BigInteger target = getDifficultyTargetAsInteger();
BigInteger h = new BigInteger(1, getHash());
if (h.compareTo(target) > 0) {
// Proof of work check failed!
if (throwException)
throw new VerificationException("Hash is higher than target: " + getHashAsString() + " vs " +
target.toString(16));
else
return false;
}
return true;
}
private void checkTimestamp() throws VerificationException {
// Allow injection of a fake clock to allow unit testing.
long currentTime = fakeClock != 0 ? fakeClock : System.currentTimeMillis() / 1000;
if (time > currentTime + ALLOWED_TIME_DRIFT)
throw new VerificationException("Block too far in future");
}
private void checkMerkleHash() throws VerificationException {
List<byte[]> tree = buildMerkleTree();
byte[] calculatedRoot = tree.get(tree.size() - 1);
if (!Arrays.equals(calculatedRoot, merkleRoot)) {
log.error("Merkle tree did not verify: ");
for (byte[] b : tree) log.error(Utils.bytesToHexString(b));
throw new VerificationException("Merkle hashes do not match: " +
bytesToHexString(calculatedRoot) + " vs " + bytesToHexString(merkleRoot));
}
}
private byte[] calculateMerkleRoot() {
List<byte[]> tree = buildMerkleTree();
return tree.get(tree.size() - 1);
}
private List<byte[]> buildMerkleTree() {
// The Merkle root is based on a tree of hashes calculated from the transactions:
//
// root
// / \
// / \
// A B
// / \ / \
// t1 t2 t3 t4
//
// The tree is represented as a list: t1,t2,t3,t4,A,B,root where each entry is a hash.
//
// The hashing algorithm is double SHA-256. The leaves are a hash of the serialized contents of the
// transaction. The interior nodes are hashes of the concenation of the two child hashes.
//
// This structure allows the creation of proof that a transaction was included into a block without having to
// provide the full block contents. Instead, you can provide only a Merkle branch. For example to prove tx2 was
// in a block you can just provide tx2, the hash(tx1) and B. Now the other party has everything they need to
// derive the root, which can be checked against the block header. These proofs aren't used right now but
// will be helpful later when we want to download partial block contents.
//
// Note that if the number of transactions is not a power of two the last tx is repeated to make it so (see
// tx3 above). A tree with 5 transactions would look like this:
//
// root
// / \
// / \
// 1 6
// / \ / \
// 2 3 4 5
// / \ / \ / \ / \
// t1 t2 t3 t4 t5 t5 t5 t5
ArrayList<byte[]> tree = new ArrayList<byte[]>();
// Start by adding all the hashes of the transactions as leaves of the tree.
for (Transaction t : transactions) {
tree.add(t.getHash().hash);
}
int levelOffset = 0; // Offset in the list where the currently processed level starts.
// Step through each level, stopping when we reach the root (levelSize == 1).
for (int levelSize = transactions.size(); levelSize > 1; levelSize = (levelSize + 1) / 2) {
// For each pair of nodes on that level:
for (int left = 0; left < levelSize; left += 2) {
// The right hand node can be the same as the left hand, in the case where we don't have enough
// transactions to be a power of two.
int right = Math.min(left + 1, levelSize - 1);
byte[] leftBytes = Utils.reverseBytes(tree.get(levelOffset + left));
byte[] rightBytes = Utils.reverseBytes(tree.get(levelOffset + right));
tree.add(Utils.reverseBytes(doubleDigestTwoBuffers(leftBytes, 0, 32, rightBytes, 0, 32)));
}
// Move to the next level.
levelOffset += levelSize;
}
return tree;
}
private void checkTransactions() throws VerificationException {
// The first transaction in a block must always be a coinbase transaction.
if (!transactions.get(0).isCoinBase())
throw new VerificationException("First tx is not coinbase");
// The rest must not be.
for (int i = 1; i < transactions.size(); i++) {
if (transactions.get(i).isCoinBase())
throw new VerificationException("TX " + i + " is coinbase when it should not be.");
}
}
/**
* Checks the block data to ensure it follows the rules laid out in the network parameters. Specifically, throws
* an exception if the proof of work is invalid, if the timestamp is too far from what it should be, or if the
* transactions don't hash to the value in the merkle root field. This is <b>not</b> everything that is required
* for a block to be valid, only what is checkable independent of the chain.
*
* @throws VerificationException
*/
public void verify() throws VerificationException {
// Prove that this block is OK. It might seem that we can just ignore most of these checks given that the
// network is also verifying the blocks, but we cannot as it'd open us to a variety of obscure attacks.
//
// Firstly we need to ensure this block does in fact represent real work done. If the difficulty is high
// enough, it's probably been done by the network.
checkProofOfWork(true);
checkTimestamp();
// Now we need to check that the body of the block actually matches the headers. The network won't generate
// an invalid block, but if we didn't validate this then an untrusted man-in-the-middle could obtain the next
// valid block from the network and simply replace the transactions in it with their own fictional
// transactions that reference spent or non-existant inputs.
if (transactions != null) {
assert transactions.size() > 0;
checkTransactions();
checkMerkleHash();
}
}
@Override
public boolean equals(Object o) {
if (!(o instanceof Block)) return false;
Block other = (Block) o;
return Arrays.equals(getHash(), other.getHash());
}
@Override
public int hashCode() {
return Arrays.hashCode(getHash());
}
/** Returns the merkle root in big endian form, calculating it from transactions if necessary. */
public byte[] getMerkleRoot() {
if (merkleRoot == null)
merkleRoot = calculateMerkleRoot();
return merkleRoot;
}
/** Exists only for unit testing. */
void setMerkleRoot(byte[] value) {
merkleRoot = value;
hash = null;
}
/** Adds a transaction to this block. */
void addTransaction(Transaction t) {
if (transactions == null) {
transactions = new ArrayList<Transaction>();
}
transactions.add(t);
// Force a recalculation next time the values are needed.
merkleRoot = null;
hash = null;
}
/** Returns the version of the block data structure as defined by the BitCoin protocol. */
public long getVersion() {
return version;
}
/** Returns the hash of the previous block in the chain, as defined by the block header. */
public byte[] getPrevBlockHash() {
return prevBlockHash;
}
void setPrevBlockHash(byte[] prevBlockHash) {
this.prevBlockHash = prevBlockHash;
this.hash = null;
}
/** Returns the time at which the block was solved and broadcast, according to the clock of the solving node. */
public long getTime() {
return time;
}
void setTime(long time) {
this.time = time;
this.hash = null;
}
/**
* Returns the difficulty of the proof of work that this block should meet encoded in compact form. The
* {@link BlockChain} verifies that this is not too easy by looking at the length of the chain when the block is
* added. To find the actual value the hash should be compared against, use getDifficultyTargetBI.
*/
public long getDifficultyTarget() {
return difficultyTarget;
}
void setDifficultyTarget(long compactForm) {
this.difficultyTarget = compactForm;
this.hash = null;
}
/**
* Returns the nonce, an arbitrary value that exists only to make the hash of the block header fall below the
* difficulty target.
*/
public long getNonce() {
return nonce;
}
void setNonce(long nonce) {
this.nonce = nonce;
this.hash = null;
}
/////////////////////////////////////////////////////////////////////////////////////////////////
// Unit testing related methods.
static private int coinbaseCounter;
/** Adds a coinbase transaction to the block. This exists for unit tests. */
void addCoinbaseTransaction(Address to) {
transactions = new ArrayList<Transaction>();
Transaction coinbase = new Transaction(params);
// A real coinbase transaction has some stuff in the scriptSig like the extraNonce and difficulty. The
// transactions are distinguished by every TX output going to a different key.
//
// Here we will do things a bit differently so a new address isn't needed every time. We'll put a simple
// counter in the scriptSig so every transaction has a different hash. The output is also different.
// Real coinbase transactions use <pubkey> OP_CHECKSIG rather than a send to an address though there's
// nothing in the system that enforces that and both are just as valid.
coinbase.inputs.add(new TransactionInput(params, coinbase, new byte[] { (byte) coinbaseCounter++ } ));
coinbase.outputs.add(new TransactionOutput(params, coinbase, Utils.toNanoCoins(50, 0), to));
transactions.add(coinbase);
}
/** Returns a solved block that builds on top of this one. This exists for unit tests. */
Block createNextBlock(Address to, long time) {
Block b = new Block(params);
b.setDifficultyTarget(difficultyTarget);
b.addCoinbaseTransaction(to);
b.setPrevBlockHash(getHash());
b.setTime(time);
b.solve();
try {
b.verify();
} catch (VerificationException e) {
throw new RuntimeException(e); // Cannot happen.
}
return b;
}
Block createNextBlock(Address to) {
return createNextBlock(to, System.currentTimeMillis() / 1000);
}
}