3
0
mirror of https://github.com/Qortal/altcoinj.git synced 2025-02-11 17:55:53 +00:00

Move the next header creation method out of BlockTest and into Block, as it is useful for other unit tests as well.

This commit is contained in:
Mike Hearn 2011-03-27 22:32:17 +00:00
parent 88212f6bfa
commit 65b80720bd
2 changed files with 43 additions and 31 deletions

View File

@ -35,25 +35,28 @@ import static com.google.bitcoin.core.Utils.*;
public class Block extends Message {
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. */
transient private byte[] hash;
private transient byte[] hash;
/** Special case constructor, used for the genesis node and unit tests. */
Block(NetworkParameters params) {
@ -429,6 +432,9 @@ public class Block extends Message {
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) {
@ -445,4 +451,24 @@ public class Block extends Message {
coinbase.outputs.add(new TransactionOutput(params, 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);
}
}

View File

@ -71,27 +71,11 @@ public class BlockChainTest {
assertTrue(testNetChain.add(b2));
}
private Block createNextBlock(Address to, Block prev) throws VerificationException {
return createNextBlock(to, prev, Block.EASIEST_DIFFICULTY_TARGET, System.currentTimeMillis() / 1000);
}
private Block createNextBlock(Address to, Block prev, long difficultyTarget,
long time) throws VerificationException {
Block b = new Block(prev.params);
b.setDifficultyTarget(difficultyTarget);
b.addCoinbaseTransaction(to);
b.setPrevBlockHash(prev.getHash());
b.setTime(time);
b.solve();
b.verify();
return b;
}
@Test
public void testUnconnectedBlocks() throws Exception {
Block b1 = createNextBlock(coinbaseTo, unitTestParams.genesisBlock);
Block b2 = createNextBlock(coinbaseTo, b1);
Block b3 = createNextBlock(coinbaseTo, b2);
Block b1 = unitTestParams.genesisBlock.createNextBlock(coinbaseTo);
Block b2 = b1.createNextBlock(coinbaseTo);
Block b3 = b2.createNextBlock(coinbaseTo);
// Connected.
assertTrue(chain.add(b1));
// Unconnected.
@ -111,8 +95,8 @@ public class BlockChainTest {
}
});
Block b1 = createNextBlock(coinbaseTo, unitTestParams.genesisBlock);
Block b2 = createNextBlock(coinbaseTo, b1);
Block b1 = unitTestParams.genesisBlock.createNextBlock(coinbaseTo);
Block b2 = b1.createNextBlock(coinbaseTo);
assertTrue(chain.add(b1));
assertTrue(chain.add(b2));
assertFalse(flags[0]);
@ -128,12 +112,12 @@ public class BlockChainTest {
//
// Nothing should happen at this point. We saw b2 first so it takes priority.
Address someOtherGuy = new ECKey().toAddress(unitTestParams);
Block b3 = createNextBlock(someOtherGuy, b1);
Block b3 = b1.createNextBlock(someOtherGuy);
assertTrue(chain.add(b3));
assertFalse(flags[0]); // No re-org took place.
assertEquals("100.00", Utils.bitcoinValueToFriendlyString(wallet.getBalance()));
// Now we add another block to make the alternative chain longer.
assertTrue(chain.add(createNextBlock(someOtherGuy, b3)));
assertTrue(chain.add(b3.createNextBlock(someOtherGuy)));
assertTrue(flags[0]); // Re-org took place.
flags[0] = false;
//
@ -145,8 +129,8 @@ public class BlockChainTest {
// These tests do not pass currently, as wallet handling of re-orgs isn't implemented.
assertEquals("50.00", Utils.bitcoinValueToFriendlyString(wallet.getBalance()));
// ... and back to the first testNetChain
Block b5 = createNextBlock(coinbaseTo, b2);
Block b6 = createNextBlock(coinbaseTo, b5);
Block b5 = b2.createNextBlock(coinbaseTo);
Block b6 = b5.createNextBlock(coinbaseTo);
assertTrue(chain.add(b5));
assertTrue(chain.add(b6));
//
@ -164,7 +148,7 @@ public class BlockChainTest {
Block prev = unitTestParams.genesisBlock;
Block.fakeClock = System.currentTimeMillis() / 1000;
for (int i = 0; i < unitTestParams.interval - 1; i++) {
Block newBlock = createNextBlock(coinbaseTo, prev, Block.EASIEST_DIFFICULTY_TARGET, Block.fakeClock);
Block newBlock = prev.createNextBlock(coinbaseTo, Block.fakeClock);
assertTrue(chain.add(newBlock));
prev = newBlock;
// The fake chain should seem to be "fast" for the purposes of difficulty calculations.
@ -172,13 +156,15 @@ public class BlockChainTest {
}
// Now add another block that has no difficulty adjustment, it should be rejected.
try {
chain.add(createNextBlock(coinbaseTo, prev));
chain.add(prev.createNextBlock(coinbaseTo));
fail();
} catch (VerificationException e) {
}
// Create a new block with the right difficulty target given our blistering speed relative to the huge amount
// of time it's supposed to take (set in the unit test network parameters).
Block b = createNextBlock(coinbaseTo, prev, 0x201fFFFFL, Block.fakeClock);
Block b = prev.createNextBlock(coinbaseTo, Block.fakeClock);
b.setDifficultyTarget(0x201fFFFFL);
b.solve();
assertTrue(chain.add(b));
// Successfully traversed a difficulty transition period.
}