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:
parent
88212f6bfa
commit
65b80720bd
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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.
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user