15 changes: 15 additions & 0 deletions core/src/main/java/org/bitcoinj/script/ScriptBuilder.java
Expand Up @@ -30,6 +30,8 @@

import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkState;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import static org.bitcoinj.script.ScriptOpCodes.*;

/**
Expand Down Expand Up @@ -344,4 +346,17 @@ public static Script createOpReturnScript(byte[] data) {
checkArgument(data.length <= 40);
return new ScriptBuilder().op(OP_RETURN).data(data).build();
}

/**
* Create script data bytes to represent the given block height.
*/
public static byte[] createHeightScriptData(final int height) {
// TODO: Replace with something generic to any integer value
final byte[] int32Buffer = ByteBuffer.allocate(4).order(ByteOrder.LITTLE_ENDIAN).putInt(height).array();
if (int32Buffer[3] == 0) {
return Arrays.copyOf(int32Buffer, 3);
} else {
return int32Buffer;
}
}
}
10 changes: 6 additions & 4 deletions core/src/main/java/org/bitcoinj/testing/FakeTxBuilder.java
Expand Up @@ -167,12 +167,13 @@ public static class BlockPair {
}

/** Emulates receiving a valid block that builds on top of the chain. */
public static BlockPair createFakeBlock(BlockStore blockStore, long version, long timeSeconds,
public static BlockPair createFakeBlock(BlockStore blockStore, long version,
long timeSeconds, int height,
Transaction... transactions) {
try {
Block chainHead = blockStore.getChainHead().getHeader();
Address to = new ECKey().toAddress(chainHead.getParams());
Block b = chainHead.createNextBlock(to, version, timeSeconds);
Block b = chainHead.createNextBlock(to, version, timeSeconds, height);
// Coinbase tx was already added.
for (Transaction tx : transactions) {
tx.getConfidence().setSource(TransactionConfidence.Source.NETWORK);
Expand All @@ -193,8 +194,9 @@ public static BlockPair createFakeBlock(BlockStore blockStore, long version, lon
}

/** Emulates receiving a valid block that builds on top of the chain. */
public static BlockPair createFakeBlock(BlockStore blockStore, Transaction... transactions) {
return createFakeBlock(blockStore, Block.BLOCK_VERSION_GENESIS, Utils.currentTimeSeconds(), transactions);
public static BlockPair createFakeBlock(BlockStore blockStore, Integer height,
Transaction... transactions) {
return createFakeBlock(blockStore, Block.BLOCK_VERSION_GENESIS, Utils.currentTimeSeconds(), height, transactions);
}

public static Block makeSolvedTestBlock(BlockStore blockStore, Address coinsTo) throws BlockStoreException {
Expand Down
Expand Up @@ -68,7 +68,7 @@ protected Transaction sendMoneyToWallet(Wallet wallet, Transaction tx, AbstractB
if (wallet.isPendingTransactionRelevant(tx))
wallet.receivePending(tx, null);
} else {
FakeTxBuilder.BlockPair bp = createFakeBlock(blockStore, tx);
FakeTxBuilder.BlockPair bp = createFakeBlock(blockStore, Block.BLOCK_HEIGHT_GENESIS, tx);
wallet.receiveFromBlock(tx, bp.storedBlock, type, 0);
if (type == AbstractBlockChain.NewBlockType.BEST_CHAIN)
wallet.notifyNewBestBlock(bp.storedBlock);
Expand Down
6 changes: 3 additions & 3 deletions core/src/main/java/org/bitcoinj/utils/VersionTally.java
Expand Up @@ -68,19 +68,19 @@ public void add(final long version) {
}

/**
* Get the count for a block version within the window.
* Get the count of blocks at or above the given version, within the window.
*
* @param version the block version to query.
* @return the count for the block version, or null if the window is not yet
* full.
*/
public Integer getCount(final long version) {
public Integer getCountAtOrAbove(final long version) {
if (versionsStored < versionWindow.length) {
return null;
}
int count = 0;
for (int versionIdx = 0; versionIdx < versionWindow.length; versionIdx++) {
if (versionWindow[versionIdx] == version) {
if (versionWindow[versionIdx] >= version) {
count++;
}
}
Expand Down
Expand Up @@ -37,13 +37,20 @@
import java.util.List;

import static org.bitcoinj.core.Coin.FIFTY_COINS;
import org.bitcoinj.store.BlockStore;
import org.bitcoinj.store.MemoryBlockStore;
import org.bitcoinj.testing.FakeTxBuilder;
import static org.junit.Assert.*;
import org.junit.rules.ExpectedException;

/**
* We don't do any wallet tests here, we leave that to {@link ChainSplitTest}
*/

public abstract class AbstractFullPrunedBlockChainTest {
@org.junit.Rule
public ExpectedException thrown = ExpectedException.none();

private static final Logger log = LoggerFactory.getLogger(AbstractFullPrunedBlockChainTest.class);

protected NetworkParameters params;
Expand Down Expand Up @@ -125,13 +132,14 @@ public void skipScripts() throws Exception {
// to the full StoredUndoableBlock's lying around (ie memory leaks)

ECKey outKey = new ECKey();
int height = 1;

// Build some blocks on genesis block to create a spendable output
Block rollingBlock = params.getGenesisBlock().createNextBlockWithCoinbase(outKey.getPubKey());
Block rollingBlock = params.getGenesisBlock().createNextBlockWithCoinbase(Block.BLOCK_VERSION_GENESIS, outKey.getPubKey(), height++);
chain.add(rollingBlock);
TransactionOutput spendableOutput = rollingBlock.getTransactions().get(0).getOutput(0);
for (int i = 1; i < params.getSpendableCoinbaseDepth(); i++) {
rollingBlock = rollingBlock.createNextBlockWithCoinbase(outKey.getPubKey());
rollingBlock = rollingBlock.createNextBlockWithCoinbase(Block.BLOCK_VERSION_GENESIS, outKey.getPubKey(), height++);
chain.add(rollingBlock);
}

Expand Down Expand Up @@ -164,14 +172,15 @@ public void testFinalizedBlocks() throws Exception {
// to the full StoredUndoableBlock's lying around (ie memory leaks)

ECKey outKey = new ECKey();

int height = 1;

// Build some blocks on genesis block to create a spendable output
Block rollingBlock = params.getGenesisBlock().createNextBlockWithCoinbase(outKey.getPubKey());
Block rollingBlock = params.getGenesisBlock().createNextBlockWithCoinbase(Block.BLOCK_VERSION_GENESIS, outKey.getPubKey(), height++);
chain.add(rollingBlock);
TransactionOutPoint spendableOutput = new TransactionOutPoint(params, 0, rollingBlock.getTransactions().get(0).getHash());
byte[] spendableOutputScriptPubKey = rollingBlock.getTransactions().get(0).getOutputs().get(0).getScriptBytes();
for (int i = 1; i < params.getSpendableCoinbaseDepth(); i++) {
rollingBlock = rollingBlock.createNextBlockWithCoinbase(outKey.getPubKey());
rollingBlock = rollingBlock.createNextBlockWithCoinbase(Block.BLOCK_VERSION_GENESIS, outKey.getPubKey(), height++);
chain.add(rollingBlock);
}

Expand Down Expand Up @@ -237,15 +246,16 @@ public void testGetOpenTransactionOutputs() throws Exception {
// Check that we aren't accidentally leaving any references
// to the full StoredUndoableBlock's lying around (ie memory leaks)
ECKey outKey = new ECKey();
int height = 1;

// Build some blocks on genesis block to create a spendable output
Block rollingBlock = params.getGenesisBlock().createNextBlockWithCoinbase(outKey.getPubKey());
Block rollingBlock = params.getGenesisBlock().createNextBlockWithCoinbase(Block.BLOCK_VERSION_GENESIS, outKey.getPubKey(), height++);
chain.add(rollingBlock);
Transaction transaction = rollingBlock.getTransactions().get(0);
TransactionOutPoint spendableOutput = new TransactionOutPoint(params, 0, transaction.getHash());
byte[] spendableOutputScriptPubKey = transaction.getOutputs().get(0).getScriptBytes();
for (int i = 1; i < params.getSpendableCoinbaseDepth(); i++) {
rollingBlock = rollingBlock.createNextBlockWithCoinbase(outKey.getPubKey());
rollingBlock = rollingBlock.createNextBlockWithCoinbase(Block.BLOCK_VERSION_GENESIS, outKey.getPubKey(), height++);
chain.add(rollingBlock);
}
rollingBlock = rollingBlock.createNextBlock(null);
Expand Down Expand Up @@ -287,15 +297,16 @@ public void testUTXOProviderWithWallet() throws Exception {
// Check that we aren't accidentally leaving any references
// to the full StoredUndoableBlock's lying around (ie memory leaks)
ECKey outKey = new ECKey();
int height = 1;

// Build some blocks on genesis block to create a spendable output.
Block rollingBlock = params.getGenesisBlock().createNextBlockWithCoinbase(outKey.getPubKey());
Block rollingBlock = params.getGenesisBlock().createNextBlockWithCoinbase(Block.BLOCK_VERSION_GENESIS, outKey.getPubKey(), height++);
chain.add(rollingBlock);
Transaction transaction = rollingBlock.getTransactions().get(0);
TransactionOutPoint spendableOutput = new TransactionOutPoint(params, 0, transaction.getHash());
byte[] spendableOutputScriptPubKey = transaction.getOutputs().get(0).getScriptBytes();
for (int i = 1; i < params.getSpendableCoinbaseDepth(); i++) {
rollingBlock = rollingBlock.createNextBlockWithCoinbase(outKey.getPubKey());
rollingBlock = rollingBlock.createNextBlockWithCoinbase(Block.BLOCK_VERSION_GENESIS, outKey.getPubKey(), height++);
chain.add(rollingBlock);
}
rollingBlock = rollingBlock.createNextBlock(null);
Expand Down Expand Up @@ -340,4 +351,58 @@ public void testUTXOProviderWithWallet() throws Exception {
store.close();
} catch (Exception e) {}
}

/**
* Test that if the block height is missing from coinbase of a version 2
* block, it's rejected.
*/
@Test
public void missingHeightFromCoinbase() throws Exception {
final int UNDOABLE_BLOCKS_STORED = params.getMajorityEnforceBlockUpgrade() + 1;
store = createStore(params, UNDOABLE_BLOCKS_STORED);
try {
chain = new FullPrunedBlockChain(params, store);
ECKey outKey = new ECKey();
int height = 1;
Block chainHead = params.getGenesisBlock();

// Build some blocks on genesis block to create a spendable output.

// Put in just enough v1 blocks to stop the v2 blocks from forming a majority
for (height = 1; height <= (params.getMajorityWindow() - params.getMajorityEnforceBlockUpgrade()); height++) {
chainHead = chainHead.createNextBlockWithCoinbase(Block.BLOCK_VERSION_GENESIS,
outKey.getPubKey(), height);
chain.add(chainHead);
}

// Fill the rest of the window in with v2 blocks
for (; height < params.getMajorityWindow(); height++) {
chainHead = chainHead.createNextBlockWithCoinbase(Block.BLOCK_VERSION_BIP34,
outKey.getPubKey(), height);
chain.add(chainHead);
}
// Throw a broken v2 block in before we have a supermajority to enable
// enforcement, which should validate as-is
chainHead = chainHead.createNextBlockWithCoinbase(Block.BLOCK_VERSION_BIP34,
outKey.getPubKey(), height * 2);
chain.add(chainHead);
height++;

// Trying to add a broken v2 block should now result in rejection as
// we have a v2 supermajority
thrown.expect(VerificationException.CoinbaseHeightMismatch.class);
chainHead = chainHead.createNextBlockWithCoinbase(Block.BLOCK_VERSION_BIP34,
outKey.getPubKey(), height * 2);
chain.add(chainHead);
} catch(final VerificationException ex) {
throw (Exception) ex.getCause();
} finally {
try {
store.close();
} catch(Exception e) {
// Catch and drop any exception so a break mid-test doesn't result
// in a new exception being thrown and the original lost
}
}
}
}
32 changes: 17 additions & 15 deletions core/src/test/java/org/bitcoinj/core/BlockChainTest.java
Expand Up @@ -131,11 +131,12 @@ public void testBasicChaining() throws Exception {

@Test
public void receiveCoins() throws Exception {
int height = 1;
// Quick check that we can actually receive coins.
Transaction tx1 = createFakeTx(unitTestParams,
COIN,
wallet.currentReceiveKey().toAddress(unitTestParams));
Block b1 = createFakeBlock(blockStore, tx1).block;
Block b1 = createFakeBlock(blockStore, height, tx1).block;
chain.add(b1);
assertTrue(wallet.getBalance().signum() > 0);
}
Expand All @@ -161,22 +162,22 @@ public void difficultyTransitions() throws Exception {
// artificially shortened period.
Block prev = unitTestParams.getGenesisBlock();
Utils.setMockClock(System.currentTimeMillis()/1000);
for (int i = 0; i < unitTestParams.getInterval() - 1; i++) {
Block newBlock = prev.createNextBlock(coinbaseTo, 1, Utils.currentTimeSeconds());
for (int height = 0; height < unitTestParams.getInterval() - 1; height++) {
Block newBlock = prev.createNextBlock(coinbaseTo, 1, Utils.currentTimeSeconds(), height);
assertTrue(chain.add(newBlock));
prev = newBlock;
// The fake chain should seem to be "fast" for the purposes of difficulty calculations.
Utils.rollMockClock(2);
}
// Now add another block that has no difficulty adjustment, it should be rejected.
try {
chain.add(prev.createNextBlock(coinbaseTo, 1, Utils.currentTimeSeconds()));
chain.add(prev.createNextBlock(coinbaseTo, 1, Utils.currentTimeSeconds(), unitTestParams.getInterval()));
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 = prev.createNextBlock(coinbaseTo, 1, Utils.currentTimeSeconds());
Block b = prev.createNextBlock(coinbaseTo, 1, Utils.currentTimeSeconds(), unitTestParams.getInterval() + 1);
b.setDifficultyTarget(0x201fFFFFL);
b.solve();
assertTrue(chain.add(b));
Expand Down Expand Up @@ -234,23 +235,23 @@ public void badBip66Version() throws Exception {

// Build a historical chain of version 3 blocks
long timeSeconds = 1231006505;
int blockCount = 0;
int height = 0;
FakeTxBuilder.BlockPair chainHead = null;

// Put in just enough v2 blocks to be a minority
for (blockCount = 0; blockCount < (unitTestParams.getMajorityWindow() - unitTestParams.getMajorityRejectBlockOutdated()); blockCount++) {
chainHead = FakeTxBuilder.createFakeBlock(versionBlockStore, Block.BLOCK_VERSION_BIP34, timeSeconds);
for (height = 0; height < (unitTestParams.getMajorityWindow() - unitTestParams.getMajorityRejectBlockOutdated()); height++) {
chainHead = FakeTxBuilder.createFakeBlock(versionBlockStore, Block.BLOCK_VERSION_BIP34, timeSeconds, height);
versionChain.add(chainHead.block);
timeSeconds += 60;
}
// Fill the rest of the window with v3 blocks
for (; blockCount < unitTestParams.getMajorityWindow(); blockCount++) {
chainHead = FakeTxBuilder.createFakeBlock(versionBlockStore, Block.BLOCK_VERSION_BIP66, timeSeconds);
for (; height < unitTestParams.getMajorityWindow(); height++) {
chainHead = FakeTxBuilder.createFakeBlock(versionBlockStore, Block.BLOCK_VERSION_BIP66, timeSeconds, height);
versionChain.add(chainHead.block);
timeSeconds += 60;
}

chainHead = FakeTxBuilder.createFakeBlock(versionBlockStore, Block.BLOCK_VERSION_BIP34, timeSeconds);
chainHead = FakeTxBuilder.createFakeBlock(versionBlockStore, Block.BLOCK_VERSION_BIP34, timeSeconds, height);
// Trying to add a new v2 block should result in rejection
thrown.expect(VerificationException.BlockVersionOutOfDate.class);
try {
Expand Down Expand Up @@ -306,12 +307,13 @@ public void coinbaseTransactionAvailability() throws Exception {
// Create a second wallet to receive the coinbase spend.
Wallet wallet2 = new Wallet(unitTestParams);
ECKey receiveKey = wallet2.freshReceiveKey();
int height = 1;
chain.addWallet(wallet2);

Address addressToSendTo = receiveKey.toAddress(unitTestParams);

// Create a block, sending the coinbase to the coinbaseTo address (which is in the wallet).
Block b1 = unitTestParams.getGenesisBlock().createNextBlockWithCoinbase(wallet.currentReceiveKey().getPubKey());
Block b1 = unitTestParams.getGenesisBlock().createNextBlockWithCoinbase(Block.BLOCK_VERSION_GENESIS, wallet.currentReceiveKey().getPubKey(), height++);
chain.add(b1);

// Check a transaction has been received.
Expand All @@ -335,7 +337,7 @@ public void coinbaseTransactionAvailability() throws Exception {
Transaction tx2 = createFakeTx(unitTestParams, COIN,
new ECKey().toAddress(unitTestParams));

Block b2 = createFakeBlock(blockStore, tx2).block;
Block b2 = createFakeBlock(blockStore, height++, tx2).block;
chain.add(b2);

// Wallet still does not have the coinbase transaction available for spend.
Expand All @@ -355,7 +357,7 @@ public void coinbaseTransactionAvailability() throws Exception {

// Give it one more block - should now be able to spend coinbase transaction. Non relevant tx.
Transaction tx3 = createFakeTx(unitTestParams, COIN, new ECKey().toAddress(unitTestParams));
Block b3 = createFakeBlock(blockStore, tx3).block;
Block b3 = createFakeBlock(blockStore, height++, tx3).block;
chain.add(b3);

// Wallet now has the coinbase transaction available for spend.
Expand All @@ -374,7 +376,7 @@ public void coinbaseTransactionAvailability() throws Exception {
assertEquals(wallet.getBalance(BalanceType.AVAILABLE), ZERO);

// Give it one more block - change from coinbaseSpend should now be available in the first wallet.
Block b4 = createFakeBlock(blockStore, coinbaseSend2).block;
Block b4 = createFakeBlock(blockStore, height++, coinbaseSend2).block;
chain.add(b4);
assertEquals(wallet.getBalance(BalanceType.AVAILABLE), COIN);

Expand Down
15 changes: 8 additions & 7 deletions core/src/test/java/org/bitcoinj/core/BlockTest.java
Expand Up @@ -25,6 +25,7 @@

import java.math.BigInteger;
import java.util.Arrays;
import java.util.EnumSet;

import static org.bitcoinj.core.Utils.HEX;
import static org.junit.Assert.*;
Expand Down Expand Up @@ -57,7 +58,7 @@ public void testWork() throws Exception {
@Test
public void testBlockVerification() throws Exception {
Block block = params.getDefaultSerializer().makeBlock(blockBytes);
block.verify();
block.verify(Block.BLOCK_HEIGHT_GENESIS, EnumSet.noneOf(VerificationFlags.class));
assertEquals("00000000a6e5eb79dcec11897af55e90cd571a4335383a3ccfbc12ec81085935", block.getHashAsString());
}

Expand All @@ -75,7 +76,7 @@ public void testProofOfWork() throws Exception {
Block block = params.getDefaultSerializer().makeBlock(blockBytes);
block.setNonce(12346);
try {
block.verify();
block.verify(Block.BLOCK_HEIGHT_GENESIS, EnumSet.noneOf(VerificationFlags.class));
fail();
} catch (VerificationException e) {
// Expected.
Expand All @@ -84,18 +85,18 @@ public void testProofOfWork() throws Exception {
// from containing artificially weak difficulties.
block.setDifficultyTarget(Block.EASIEST_DIFFICULTY_TARGET);
// Now it should pass.
block.verify();
block.verify(Block.BLOCK_HEIGHT_GENESIS, EnumSet.noneOf(VerificationFlags.class));
// Break the nonce again at the lower difficulty level so we can try solving for it.
block.setNonce(1);
try {
block.verify();
block.verify(Block.BLOCK_HEIGHT_GENESIS, EnumSet.noneOf(VerificationFlags.class));
fail();
} catch (VerificationException e) {
// Expected to fail as the nonce is no longer correct.
}
// Should find an acceptable nonce.
block.solve();
block.verify();
block.verify(Block.BLOCK_HEIGHT_GENESIS, EnumSet.noneOf(VerificationFlags.class));
assertEquals(block.getNonce(), 2);
}

Expand All @@ -108,7 +109,7 @@ public void testBadTransactions() throws Exception {
block.transactions.set(0, tx2);
block.transactions.set(1, tx1);
try {
block.verify();
block.verify(Block.BLOCK_HEIGHT_GENESIS, EnumSet.noneOf(VerificationFlags.class));
fail();
} catch (VerificationException e) {
// We should get here.
Expand Down Expand Up @@ -136,7 +137,7 @@ public void testBitcoinSerialization() throws Exception {
@Test
public void testUpdateLength() {
NetworkParameters params = UnitTestParams.get();
Block block = params.getGenesisBlock().createNextBlockWithCoinbase(new ECKey().getPubKey());
Block block = params.getGenesisBlock().createNextBlockWithCoinbase(Block.BLOCK_VERSION_GENESIS, new ECKey().getPubKey(), Block.BLOCK_HEIGHT_GENESIS);
assertEquals(block.bitcoinSerialize().length, block.length);
final int origBlockLen = block.length;
Transaction tx = new Transaction(params);
Expand Down
2 changes: 1 addition & 1 deletion core/src/test/java/org/bitcoinj/core/ChainSplitTest.java
Expand Up @@ -566,7 +566,7 @@ public void onCoinsReceived(Wallet wallet, Transaction tx, Coin prevBalance, Coi

Block b1 = unitTestParams.getGenesisBlock().createNextBlock(someOtherGuy);
final ECKey coinsTo2 = wallet.freshReceiveKey();
Block b2 = b1.createNextBlockWithCoinbase(coinsTo2.getPubKey());
Block b2 = b1.createNextBlockWithCoinbase(Block.BLOCK_VERSION_GENESIS, coinsTo2.getPubKey(), 2);
Block b3 = b2.createNextBlock(someOtherGuy);

log.debug("Adding block b1");
Expand Down
3 changes: 2 additions & 1 deletion core/src/test/java/org/bitcoinj/core/CoinbaseBlockTest.java
Expand Up @@ -26,6 +26,7 @@
import java.io.IOException;
import java.io.InputStream;
import java.math.BigInteger;
import java.util.EnumSet;
import java.util.List;

import static org.junit.Assert.assertEquals;
Expand Down Expand Up @@ -63,7 +64,7 @@ public void testReceiveCoinbaseTransaction() throws Exception {

// Check block.
assertNotNull(block);
block.verify();
block.verify(169482, EnumSet.noneOf(VerificationFlags.class));
assertEquals(BLOCK_NONCE, block.getNonce());

StoredBlock storedBlock = new StoredBlock(block, BigInteger.ONE, BLOCK_OF_INTEREST); // Nonsense work - not used in test.
Expand Down
Expand Up @@ -177,13 +177,13 @@ public boolean add(Rule element) {
Queue<TransactionOutPointWithValue> spendableOutputs = new LinkedList<TransactionOutPointWithValue>();

int chainHeadHeight = 1;
Block chainHead = params.getGenesisBlock().createNextBlockWithCoinbase(coinbaseOutKeyPubKey);
Block chainHead = params.getGenesisBlock().createNextBlockWithCoinbase(Block.BLOCK_VERSION_GENESIS, coinbaseOutKeyPubKey, chainHeadHeight);
blocks.add(new BlockAndValidity(chainHead, true, false, chainHead.getHash(), 1, "Initial Block"));
spendableOutputs.offer(new TransactionOutPointWithValue(
new TransactionOutPoint(params, 0, chainHead.getTransactions().get(0).getHash()),
FIFTY_COINS, chainHead.getTransactions().get(0).getOutputs().get(0).getScriptPubKey()));
for (int i = 1; i < params.getSpendableCoinbaseDepth(); i++) {
chainHead = chainHead.createNextBlockWithCoinbase(coinbaseOutKeyPubKey);
chainHead = chainHead.createNextBlockWithCoinbase(Block.BLOCK_VERSION_GENESIS, coinbaseOutKeyPubKey, chainHeadHeight);
chainHeadHeight++;
blocks.add(new BlockAndValidity(chainHead, true, false, chainHead.getHash(), i+1, "Initial Block chain output generation"));
spendableOutputs.offer(new TransactionOutPointWithValue(
Expand Down Expand Up @@ -894,7 +894,7 @@ public boolean add(Rule element) {
byte[] outScriptBytes = ScriptBuilder.createOutputScript(ECKey.fromPublicOnly(coinbaseOutKeyPubKey)).getProgram();
{
b44.setDifficultyTarget(b43.block.getDifficultyTarget());
b44.addCoinbaseTransaction(coinbaseOutKeyPubKey, ZERO);
b44.addCoinbaseTransaction(coinbaseOutKeyPubKey, ZERO, chainHeadHeight + 15);

Transaction t = new Transaction(params);
// Entirely invalid scriptPubKey to ensure we aren't pre-verifying too much
Expand Down Expand Up @@ -1768,7 +1768,7 @@ private NewBlock createNextBlock(Block baseBlock, int nextBlockHeight, @Nullable
Coin coinbaseValue = FIFTY_COINS.shiftRight(nextBlockHeight / params.getSubsidyDecreaseBlockCount())
.add((prevOut != null ? prevOut.value.subtract(SATOSHI) : ZERO))
.add(additionalCoinbaseValue == null ? ZERO : additionalCoinbaseValue);
Block block = baseBlock.createNextBlockWithCoinbase(coinbaseOutKeyPubKey, coinbaseValue);
Block block = baseBlock.createNextBlockWithCoinbase(Block.BLOCK_VERSION_GENESIS, coinbaseOutKeyPubKey, coinbaseValue, nextBlockHeight);
Transaction t = new Transaction(params);
if (prevOut != null) {
// Entirely invalid scriptPubKey to ensure we aren't pre-verifying too much
Expand Down
3 changes: 2 additions & 1 deletion core/src/test/java/org/bitcoinj/core/ParseByteCacheTest.java
Expand Up @@ -35,6 +35,7 @@
import static org.junit.Assert.*;

public class ParseByteCacheTest {
private static final int BLOCK_HEIGHT_GENESIS = 0;

private final byte[] txMessage = HEX.withSeparator(" ", 2).decode(
"f9 be b4 d9 74 78 00 00 00 00 00 00 00 00 00 00" +
Expand Down Expand Up @@ -101,7 +102,7 @@ public void setUp() throws Exception {
Transaction tx2 = createFakeTx(unitTestParams, COIN,
new ECKey().toAddress(unitTestParams));

Block b1 = createFakeBlock(blockStore, tx1, tx2).block;
Block b1 = createFakeBlock(blockStore, BLOCK_HEIGHT_GENESIS, tx1, tx2).block;

MessageSerializer bs = unitTestParams.getDefaultSerializer();

Expand Down
6 changes: 4 additions & 2 deletions core/src/test/java/org/bitcoinj/core/PeerGroupTest.java
Expand Up @@ -44,6 +44,8 @@

@RunWith(value = Parameterized.class)
public class PeerGroupTest extends TestWithPeerGroup {
private static final int BLOCK_HEIGHT_GENESIS = 0;

private BlockingQueue<Peer> connectedPeers;
private BlockingQueue<Peer> disconnectedPeers;
private AbstractPeerEventListener listener;
Expand Down Expand Up @@ -274,7 +276,7 @@ public void singleDownloadPeer1() throws Exception {

// Set up a little block chain. We heard about b1 but not b2 (it is pending download). b3 is solved whilst we
// are downloading the chain.
Block b1 = FakeTxBuilder.createFakeBlock(blockStore).block;
Block b1 = FakeTxBuilder.createFakeBlock(blockStore, BLOCK_HEIGHT_GENESIS).block;
blockChain.add(b1);
Block b2 = FakeTxBuilder.makeSolvedTestBlock(b1);
Block b3 = FakeTxBuilder.makeSolvedTestBlock(b2);
Expand Down Expand Up @@ -314,7 +316,7 @@ public void singleDownloadPeer2() throws Exception {
InboundMessageQueuer p1 = connectPeer(1);

// Set up a little block chain.
Block b1 = FakeTxBuilder.createFakeBlock(blockStore).block;
Block b1 = FakeTxBuilder.createFakeBlock(blockStore, BLOCK_HEIGHT_GENESIS).block;
Block b2 = FakeTxBuilder.makeSolvedTestBlock(b1);
Block b3 = FakeTxBuilder.makeSolvedTestBlock(b2);

Expand Down
16 changes: 8 additions & 8 deletions core/src/test/java/org/bitcoinj/core/PeerTest.java
Expand Up @@ -123,7 +123,7 @@ public void shutdown() throws Exception {
@Test
public void chainDownloadEnd2End() throws Exception {
// A full end-to-end test of the chain download process, with a new block being solved in the middle.
Block b1 = createFakeBlock(blockStore).block;
Block b1 = createFakeBlock(blockStore, Block.BLOCK_HEIGHT_GENESIS).block;
blockChain.add(b1);
Block b2 = makeSolvedTestBlock(b1);
Block b3 = makeSolvedTestBlock(b2);
Expand Down Expand Up @@ -199,7 +199,7 @@ public void chainDownloadEnd2End() throws Exception {
public void invTickle() throws Exception {
connect();

Block b1 = createFakeBlock(blockStore).block;
Block b1 = createFakeBlock(blockStore, Block.BLOCK_HEIGHT_GENESIS).block;
blockChain.add(b1);
// Make a missing block.
Block b2 = makeSolvedTestBlock(b1);
Expand Down Expand Up @@ -229,7 +229,7 @@ public void invNoDownload() throws Exception {
connect();

// Make a missing block that we receive.
Block b1 = createFakeBlock(blockStore).block;
Block b1 = createFakeBlock(blockStore, Block.BLOCK_HEIGHT_GENESIS).block;
blockChain.add(b1);
Block b2 = makeSolvedTestBlock(b1);

Expand Down Expand Up @@ -305,7 +305,7 @@ public void invDownloadTxMultiPeer() throws Exception {
// Check that inventory message containing blocks we want is processed correctly.
@Test
public void newBlock() throws Exception {
Block b1 = createFakeBlock(blockStore).block;
Block b1 = createFakeBlock(blockStore, Block.BLOCK_HEIGHT_GENESIS).block;
blockChain.add(b1);
final Block b2 = makeSolvedTestBlock(b1);
// Receive notification of a new block.
Expand Down Expand Up @@ -365,7 +365,7 @@ public synchronized void onBlocksDownloaded(Peer p, Block block, @Nullable Filte
// Check that it starts downloading the block chain correctly on request.
@Test
public void startBlockChainDownload() throws Exception {
Block b1 = createFakeBlock(blockStore).block;
Block b1 = createFakeBlock(blockStore, Block.BLOCK_HEIGHT_GENESIS).block;
blockChain.add(b1);
Block b2 = makeSolvedTestBlock(b1);
blockChain.add(b2);
Expand Down Expand Up @@ -395,7 +395,7 @@ public void onChainDownloadStarted(Peer p, int blocksLeft) {
public void getBlock() throws Exception {
connect();

Block b1 = createFakeBlock(blockStore).block;
Block b1 = createFakeBlock(blockStore, Block.BLOCK_HEIGHT_GENESIS).block;
blockChain.add(b1);
Block b2 = makeSolvedTestBlock(b1);
Block b3 = makeSolvedTestBlock(b2);
Expand All @@ -417,7 +417,7 @@ public void getBlock() throws Exception {
public void getLargeBlock() throws Exception {
connect();

Block b1 = createFakeBlock(blockStore).block;
Block b1 = createFakeBlock(blockStore, Block.BLOCK_HEIGHT_GENESIS).block;
blockChain.add(b1);
Block b2 = makeSolvedTestBlock(b1);
Transaction t = new Transaction(params);
Expand All @@ -444,7 +444,7 @@ public void fastCatchup() throws Exception {
Utils.setMockClock();
// Check that blocks before the fast catchup point are retrieved using getheaders, and after using getblocks.
// This test is INCOMPLETE because it does not check we handle >2000 blocks correctly.
Block b1 = createFakeBlock(blockStore).block;
Block b1 = createFakeBlock(blockStore, Block.BLOCK_HEIGHT_GENESIS).block;
blockChain.add(b1);
Utils.rollMockClock(60 * 10); // 10 minutes later.
Block b2 = makeSolvedTestBlock(b1);
Expand Down
Expand Up @@ -237,7 +237,7 @@ public void onTransactionConfidenceChanged(Wallet wallet, Transaction tx) {
assertEquals(transactions[0], sendResult.tx);
assertEquals(1, transactions[0].getConfidence().numBroadcastPeers());
// Confirm it.
Block b2 = FakeTxBuilder.createFakeBlock(blockStore, t1).block;
Block b2 = FakeTxBuilder.createFakeBlock(blockStore, Block.BLOCK_HEIGHT_GENESIS, t1).block;
inbound(p1, b2);
pingAndWait(p1);
assertNull(outbound(p1));
Expand Down
16 changes: 16 additions & 0 deletions core/src/test/java/org/bitcoinj/core/TransactionTest.java
Expand Up @@ -8,6 +8,8 @@
import org.junit.*;

import java.util.*;
import static org.bitcoinj.core.BlockTest.params;
import static org.bitcoinj.core.Utils.HEX;

import static org.easymock.EasyMock.*;
import static org.junit.Assert.*;
Expand All @@ -27,6 +29,7 @@ public class TransactionTest {

@Before
public void setUp() throws Exception {
Context context = new Context(PARAMS);
dummy = FakeTxBuilder.createFakeTx(PARAMS, Coin.COIN, ADDRESS);
tx = newTransaction();
}
Expand Down Expand Up @@ -303,4 +306,17 @@ public void testPrioSizeCalc() throws Exception {
tx1.getInput(0).setScriptSig(new Script(new byte[111]));
assertEquals(79, tx1.getMessageSizeForPriorityCalc());
}

/**
*
* @throws VerificationException
*/
@Test
public void testCoinbaseHeightCheck() throws VerificationException {
// Coinbase transaction from block 300,000
final byte[] transactionBytes = HEX.decode("01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff4803e09304062f503253482f0403c86d53087ceca141295a00002e522cfabe6d6d7561cf262313da1144026c8f7a43e3899c44f6145f39a36507d36679a8b7006104000000000000000000000001c8704095000000001976a91480ad90d403581fa3bf46086a91b2d9d4125db6c188ac00000000");
final int height = 300000;
final Transaction transaction = params.getDefaultSerializer().makeTransaction(transactionBytes);
transaction.checkCoinBaseHeight(height);
}
}
36 changes: 18 additions & 18 deletions core/src/test/java/org/bitcoinj/core/WalletTest.java
Expand Up @@ -451,7 +451,7 @@ private Wallet spendUnconfirmedChange(Wallet wallet, Transaction t2, KeyParamete
wallet.commitTx(t3);
assertTrue(wallet.isConsistent());
// t2 and t3 gets confirmed in the same block.
BlockPair bp = createFakeBlock(blockStore, t2, t3);
BlockPair bp = createFakeBlock(blockStore, Block.BLOCK_HEIGHT_GENESIS, t2, t3);
wallet.receiveFromBlock(t2, bp.storedBlock, AbstractBlockChain.NewBlockType.BEST_CHAIN, 0);
wallet.receiveFromBlock(t3, bp.storedBlock, AbstractBlockChain.NewBlockType.BEST_CHAIN, 1);
wallet.notifyNewBestBlock(bp.storedBlock);
Expand Down Expand Up @@ -539,7 +539,7 @@ public void balance() throws Exception {
wallet.getBalance(Wallet.BalanceType.ESTIMATED)));

// Now confirm the transaction by including it into a block.
StoredBlock b3 = createFakeBlock(blockStore, spend).storedBlock;
StoredBlock b3 = createFakeBlock(blockStore, Block.BLOCK_HEIGHT_GENESIS, spend).storedBlock;
wallet.receiveFromBlock(spend, b3, BlockChain.NewBlockType.BEST_CHAIN, 0);

// Change is confirmed. We started with 5.50 so we should have 4.50 left.
Expand Down Expand Up @@ -615,7 +615,7 @@ public void onTransactionConfidenceChanged(Wallet wallet, Transaction tx) {
sendMoneyToWallet(send2, AbstractBlockChain.NewBlockType.BEST_CHAIN);
assertEquals(Coin.valueOf(0, 80), wallet.getBalance());
Threading.waitForUserCode();
BlockPair b4 = createFakeBlock(blockStore);
BlockPair b4 = createFakeBlock(blockStore, Block.BLOCK_HEIGHT_GENESIS);
confTxns.clear();
wallet.notifyNewBestBlock(b4.storedBlock);
Threading.waitForUserCode();
Expand Down Expand Up @@ -916,7 +916,7 @@ public void onConfidenceChanged(TransactionConfidence confidence, TransactionCon
assertEquals(TransactionConfidence.ConfidenceType.PENDING,
notifiedTx[0].getConfidence().getConfidenceType());
// Send a block with nothing interesting. Verify we don't get a callback.
wallet.notifyNewBestBlock(createFakeBlock(blockStore).storedBlock);
wallet.notifyNewBestBlock(createFakeBlock(blockStore, Block.BLOCK_HEIGHT_GENESIS).storedBlock);
Threading.waitForUserCode();
assertNull(reasons[0]);
final Transaction t1Copy = params.getDefaultSerializer().makeTransaction(t1.bitcoinSerialize());
Expand Down Expand Up @@ -1151,7 +1151,7 @@ public void pubkeyOnlyScripts() throws Exception {
// TX should have been seen as relevant.
assertEquals(value, wallet.getBalance(Wallet.BalanceType.ESTIMATED));
assertEquals(ZERO, wallet.getBalance(Wallet.BalanceType.AVAILABLE));
Block b1 = createFakeBlock(blockStore, t1).block;
Block b1 = createFakeBlock(blockStore, Block.BLOCK_HEIGHT_GENESIS, t1).block;
chain.add(b1);
// TX should have been seen as relevant, extracted and processed.
assertEquals(value, wallet.getBalance(Wallet.BalanceType.AVAILABLE));
Expand Down Expand Up @@ -1234,7 +1234,7 @@ public void watchingScriptsConfirmed() throws Exception {
Address watchedAddress = key.toAddress(params);
wallet.addWatchedAddress(watchedAddress);
Transaction t1 = createFakeTx(params, CENT, watchedAddress);
StoredBlock b3 = createFakeBlock(blockStore, t1).storedBlock;
StoredBlock b3 = createFakeBlock(blockStore, Block.BLOCK_HEIGHT_GENESIS, t1).storedBlock;
wallet.receiveFromBlock(t1, b3, BlockChain.NewBlockType.BEST_CHAIN, 0);
assertEquals(CENT, wallet.getBalance());

Expand All @@ -1255,7 +1255,7 @@ public void watchingScriptsSentFrom() throws Exception {

Transaction t1 = createFakeTx(params, CENT, watchedAddress);
Transaction t2 = createFakeTx(params, COIN, notMyAddr);
StoredBlock b1 = createFakeBlock(blockStore, t1).storedBlock;
StoredBlock b1 = createFakeBlock(blockStore, Block.BLOCK_HEIGHT_GENESIS, t1).storedBlock;
Transaction st2 = new Transaction(params);
st2.addOutput(CENT, notMyAddr);
st2.addOutput(COIN, notMyAddr);
Expand All @@ -1278,7 +1278,7 @@ public void watchingScriptsBloomFilter() throws Exception {

assertTrue(wallet.isRequiringUpdateAllBloomFilter());
Transaction t1 = createFakeTx(params, CENT, watchedAddress);
StoredBlock b1 = createFakeBlock(blockStore, t1).storedBlock;
StoredBlock b1 = createFakeBlock(blockStore, Block.BLOCK_HEIGHT_GENESIS, t1).storedBlock;

TransactionOutPoint outPoint = new TransactionOutPoint(params, 0, t1);

Expand Down Expand Up @@ -1338,7 +1338,7 @@ public void removeScriptsBloomFilter() throws Exception {

for (Address addr : addressesForRemoval) {
Transaction t1 = createFakeTx(params, CENT, addr);
StoredBlock b1 = createFakeBlock(blockStore, t1).storedBlock;
StoredBlock b1 = createFakeBlock(blockStore, Block.BLOCK_HEIGHT_GENESIS, t1).storedBlock;

TransactionOutPoint outPoint = new TransactionOutPoint(params, 0, t1);

Expand All @@ -1358,7 +1358,7 @@ public void marriedKeychainBloomFilter() throws Exception {
assertTrue(wallet.getBloomFilter(0.001).contains(address.getHash160()));

Transaction t1 = createFakeTx(params, CENT, address);
StoredBlock b1 = createFakeBlock(blockStore, t1).storedBlock;
StoredBlock b1 = createFakeBlock(blockStore, Block.BLOCK_HEIGHT_GENESIS, t1).storedBlock;

TransactionOutPoint outPoint = new TransactionOutPoint(params, 0, t1);

Expand Down Expand Up @@ -1416,15 +1416,15 @@ public void onAfterAutoSave(File newlySavedFile) {
assertEquals(f, results[1]);
results[0] = results[1] = null;

Block b0 = createFakeBlock(blockStore).block;
Block b0 = createFakeBlock(blockStore, Block.BLOCK_HEIGHT_GENESIS).block;
chain.add(b0);
Sha256Hash hash3 = Sha256Hash.of(f);
assertEquals(hash2, hash3); // File has NOT changed yet. Just new blocks with no txns - delayed.
assertNull(results[0]);
assertNull(results[1]);

Transaction t1 = createFakeTx(params, valueOf(5, 0), key);
Block b1 = createFakeBlock(blockStore, t1).block;
Block b1 = createFakeBlock(blockStore, Block.BLOCK_HEIGHT_GENESIS, t1).block;
chain.add(b1);
Sha256Hash hash4 = Sha256Hash.of(f);
assertFalse(hash3.equals(hash4)); // File HAS changed.
Expand All @@ -1451,7 +1451,7 @@ public void onAfterAutoSave(File newlySavedFile) {
wallet.importKey(key2);
assertEquals(hash5, Sha256Hash.of(f)); // File has NOT changed.
Transaction t2 = createFakeTx(params, valueOf(5, 0), key2);
Block b3 = createFakeBlock(blockStore, t2).block;
Block b3 = createFakeBlock(blockStore, Block.BLOCK_HEIGHT_GENESIS, t2).block;
chain.add(b3);
Thread.sleep(2000); // Wait longer than autosave delay. TODO Fix the racyness.
assertEquals(hash5, Sha256Hash.of(f)); // File has still NOT changed.
Expand Down Expand Up @@ -1511,7 +1511,7 @@ public void replayWhilstPending() throws Exception {
// Add a change address to ensure this tx is relevant.
tx2.addOutput(CENT, wallet.getChangeAddress());
wallet.receivePending(tx2, null);
BlockPair bp = createFakeBlock(blockStore, tx1);
BlockPair bp = createFakeBlock(blockStore, Block.BLOCK_HEIGHT_GENESIS, tx1);
wallet.receiveFromBlock(tx1, bp.storedBlock, AbstractBlockChain.NewBlockType.BEST_CHAIN, 0);
wallet.notifyNewBestBlock(bp.storedBlock);
assertEquals(ZERO, wallet.getBalance());
Expand Down Expand Up @@ -2981,31 +2981,31 @@ public Result analyze() {
assertEquals(Coin.ZERO, wallet.getBalance(Wallet.BalanceType.ESTIMATED));
assertTrue(bool.get());
// Confirm it in the same manner as how Bloom filtered blocks do. Verify it shows up.
StoredBlock block = createFakeBlock(blockStore, tx).storedBlock;
StoredBlock block = createFakeBlock(blockStore, Block.BLOCK_HEIGHT_GENESIS, tx).storedBlock;
wallet.notifyTransactionIsInBlock(tx.getHash(), block, AbstractBlockChain.NewBlockType.BEST_CHAIN, 1);
assertEquals(COIN, wallet.getBalance());
}

@Test
public void transactionInBlockNotification() {
final Transaction tx = createFakeTx(params, COIN, myAddress);
StoredBlock block = createFakeBlock(blockStore, tx).storedBlock;
StoredBlock block = createFakeBlock(blockStore, Block.BLOCK_HEIGHT_GENESIS, tx).storedBlock;
wallet.receivePending(tx, null);
boolean notification = wallet.notifyTransactionIsInBlock(tx.getHash(), block, AbstractBlockChain.NewBlockType.BEST_CHAIN, 1);
assertTrue(notification);

Address notMyAddr = new ECKey().toAddress(params);
final Transaction tx2 = createFakeTx(params, COIN, notMyAddr);
wallet.receivePending(tx2, null);
StoredBlock block2 = createFakeBlock(blockStore, tx2).storedBlock;
StoredBlock block2 = createFakeBlock(blockStore, Block.BLOCK_HEIGHT_GENESIS + 1, tx2).storedBlock;
boolean notification2 = wallet.notifyTransactionIsInBlock(tx2.getHash(), block2, AbstractBlockChain.NewBlockType.BEST_CHAIN, 1);
assertFalse(notification2);
}

@Test
public void duplicatedBlock() {
final Transaction tx = createFakeTx(params, COIN, myAddress);
StoredBlock block = createFakeBlock(blockStore, tx).storedBlock;
StoredBlock block = createFakeBlock(blockStore, Block.BLOCK_HEIGHT_GENESIS, tx).storedBlock;
wallet.notifyNewBestBlock(block);
wallet.notifyNewBestBlock(block);
}
Expand Down
Expand Up @@ -226,9 +226,9 @@ public void onAfterAutoSave(File newlySavedFile) {

// Now confirm the settle TX and see if the channel deletes itself from the wallet.
assertEquals(1, StoredPaymentChannelClientStates.getFromWallet(wallet).mapChannels.size());
wallet.notifyNewBestBlock(createFakeBlock(blockStore).storedBlock);
wallet.notifyNewBestBlock(createFakeBlock(blockStore, Block.BLOCK_HEIGHT_GENESIS).storedBlock);
assertEquals(1, StoredPaymentChannelClientStates.getFromWallet(wallet).mapChannels.size());
wallet.notifyNewBestBlock(createFakeBlock(blockStore).storedBlock);
wallet.notifyNewBestBlock(createFakeBlock(blockStore, Block.BLOCK_HEIGHT_GENESIS + 1).storedBlock);
assertEquals(0, StoredPaymentChannelClientStates.getFromWallet(wallet).mapChannels.size());
}

Expand Down
Expand Up @@ -323,7 +323,7 @@ public void testRoundTripMarriedWallet() throws Exception {
@Test
public void coinbaseTxns() throws Exception {
// Covers issue 420 where the outpoint index of a coinbase tx input was being mis-serialized.
Block b = params.getGenesisBlock().createNextBlockWithCoinbase(myKey.getPubKey(), FIFTY_COINS);
Block b = params.getGenesisBlock().createNextBlockWithCoinbase(Block.BLOCK_VERSION_GENESIS, myKey.getPubKey(), FIFTY_COINS, Block.BLOCK_HEIGHT_GENESIS);
Transaction coinbase = b.getTransactions().get(0);
assertTrue(coinbase.isCoinBase());
BlockChain chain = new BlockChain(params, myWallet, new MemoryBlockStore(params));
Expand Down
26 changes: 17 additions & 9 deletions core/src/test/java/org/bitcoinj/utils/VersionTallyTest.java
Expand Up @@ -50,10 +50,10 @@ public void setUp() throws Exception {
public void testNullWhileEmpty() {
VersionTally instance = new VersionTally(unitTestParams);
for (int i = 0; i < unitTestParams.getMajorityWindow(); i++) {
assertNull(instance.getCount(1));
assertNull(instance.getCountAtOrAbove(1));
instance.add(1);
}
assertEquals(unitTestParams.getMajorityWindow(), instance.getCount(1).intValue());
assertEquals(unitTestParams.getMajorityWindow(), instance.getCountAtOrAbove(1).intValue());
}

/**
Expand All @@ -74,16 +74,24 @@ public void testVersionCounts() {

// Fill the tally with 1s
for (int i = 0; i < unitTestParams.getMajorityWindow(); i++) {
assertNull(instance.getCount(1));
assertNull(instance.getCountAtOrAbove(1));
instance.add(1);
}
assertEquals(unitTestParams.getMajorityWindow(), instance.getCount(1).intValue());
assertEquals(unitTestParams.getMajorityWindow(), instance.getCountAtOrAbove(1).intValue());

// Check the count updates as we replace with 2s
for (int i = 0; i < unitTestParams.getMajorityWindow(); i++) {
assertEquals(unitTestParams.getMajorityWindow() - i, instance.getCount(1).intValue());
assertEquals(i, instance.getCount(2).intValue());
assertEquals(i, instance.getCountAtOrAbove(2).intValue());
instance.add(2);
}

// Inject a rogue 1
instance.add(1);
assertEquals(unitTestParams.getMajorityWindow() - 1, instance.getCountAtOrAbove(2).intValue());

// Check we accept high values as well
instance.add(10);
assertEquals(unitTestParams.getMajorityWindow() - 1, instance.getCountAtOrAbove(2).intValue());
}

@Test
Expand All @@ -94,14 +102,14 @@ public void testInitialize() throws BlockStoreException {
// Build a historical chain of version 2 blocks
long timeSeconds = 1231006505;
StoredBlock chainHead = null;
for (int blockCount = 0; blockCount < unitTestParams.getMajorityWindow(); blockCount++) {
chainHead = FakeTxBuilder.createFakeBlock(blockStore, 2, timeSeconds).storedBlock;
for (int height = 0; height < unitTestParams.getMajorityWindow(); height++) {
chainHead = FakeTxBuilder.createFakeBlock(blockStore, 2, timeSeconds, height).storedBlock;
assertEquals(2, chainHead.getHeader().getVersion());
timeSeconds += 60;
}

VersionTally instance = new VersionTally(unitTestParams);
instance.initialize(blockStore, chainHead);
assertEquals(unitTestParams.getMajorityWindow(), instance.getCount(2).intValue());
assertEquals(unitTestParams.getMajorityWindow(), instance.getCountAtOrAbove(2).intValue());
}
}
Expand Up @@ -92,7 +92,7 @@ public void coinAgeOrdering() throws Exception {
// and t3=0.01.
Transaction t1 = checkNotNull(sendMoneyToWallet(COIN, AbstractBlockChain.NewBlockType.BEST_CHAIN));
// Padding block.
wallet.notifyNewBestBlock(FakeTxBuilder.createFakeBlock(blockStore).storedBlock);
wallet.notifyNewBestBlock(FakeTxBuilder.createFakeBlock(blockStore, Block.BLOCK_HEIGHT_GENESIS).storedBlock);
final Coin TWO_COINS = COIN.multiply(2);
Transaction t2 = checkNotNull(sendMoneyToWallet(TWO_COINS, AbstractBlockChain.NewBlockType.BEST_CHAIN));
Transaction t3 = checkNotNull(sendMoneyToWallet(CENT, AbstractBlockChain.NewBlockType.BEST_CHAIN));
Expand Down