Skip to content

Commit

Permalink
Enforce v4 block switchover
Browse files Browse the repository at this point in the history
This enforces the switch over to block v4 once a supermajority is met, as
per BIP65.
  • Loading branch information
Ross Nicoll authored and schildbach committed Oct 28, 2015
1 parent 1c8a60d commit 344c4c3
Show file tree
Hide file tree
Showing 3 changed files with 25 additions and 7 deletions.
9 changes: 5 additions & 4 deletions core/src/main/java/org/bitcoinj/core/AbstractBlockChain.java
Original file line number Diff line number Diff line change
Expand Up @@ -544,12 +544,13 @@ private void connectBlock(final Block block, StoredBlock storedPrev, boolean exp
if (expensiveChecks && block.getTimeSeconds() <= getMedianTimestampOfRecentBlocks(head, blockStore))
throw new VerificationException("Block's timestamp is too early");

// BIP 66: Enforce block version 3 once it's a supermajority of blocks
// BIP 66 & 65: Enforce block version 3/4 once they are a supermajority of blocks
// NOTE: This requires 1,000 blocks since the last checkpoint (on main
// net, less on test) in order to be applied. It is also limited to
// stopping addition of new v2 blocks to the tip of the chain.
if (block.getVersion() == Block.BLOCK_VERSION_BIP34) {
final Integer count = versionTally.getCountAtOrAbove(Block.BLOCK_VERSION_BIP66);
// stopping addition of new v2/3 blocks to the tip of the chain.
if (block.getVersion() == Block.BLOCK_VERSION_BIP34
|| block.getVersion() == Block.BLOCK_VERSION_BIP66) {
final Integer count = versionTally.getCountAtOrAbove(block.getVersion() + 1);
if (count != null
&& count >= params.getMajorityRejectBlockOutdated()) {
throw new VerificationException.BlockVersionOutOfDate(block.getVersion());
Expand Down
2 changes: 2 additions & 0 deletions core/src/main/java/org/bitcoinj/core/Block.java
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,8 @@ public enum VerifyFlag {
public static final long BLOCK_VERSION_BIP34 = 2;
/** Block version introduced in BIP 66: Strict DER signatures */
public static final long BLOCK_VERSION_BIP66 = 3;
/** Block version introduced in BIP 65: OP_CHECKLOCKTIMEVERIFY */
public static final long BLOCK_VERSION_BIP65 = 4;

// Fields defined as part of the protocol format.
private long version;
Expand Down
21 changes: 18 additions & 3 deletions core/src/test/java/org/bitcoinj/core/BlockChainTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
import java.util.Locale;

import static org.bitcoinj.core.Coin.*;
import org.bitcoinj.store.BlockStoreException;
import static org.bitcoinj.testing.FakeTxBuilder.createFakeBlock;
import static org.bitcoinj.testing.FakeTxBuilder.createFakeTx;
import static org.junit.Assert.*;
Expand Down Expand Up @@ -230,6 +231,20 @@ public void badDifficulty() throws Exception {
*/
@Test
public void badBip66Version() throws Exception {
testDeprecatedBlockVersion(Block.BLOCK_VERSION_BIP34, Block.BLOCK_VERSION_BIP66);
}

/**
* Test that version 3 blocks are rejected once version 4 blocks are a super
* majority.
*/
@Test
public void badBip65Version() throws Exception {
testDeprecatedBlockVersion(Block.BLOCK_VERSION_BIP66, Block.BLOCK_VERSION_BIP65);
}

private void testDeprecatedBlockVersion(final long deprecatedVersion, final long newVersion)
throws Exception {
final BlockStore versionBlockStore = new MemoryBlockStore(unitTestParams);
final BlockChain versionChain = new BlockChain(unitTestParams, versionBlockStore);

Expand All @@ -240,18 +255,18 @@ public void badBip66Version() throws Exception {

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

chainHead = FakeTxBuilder.createFakeBlock(versionBlockStore, Block.BLOCK_VERSION_BIP34, timeSeconds, height);
chainHead = FakeTxBuilder.createFakeBlock(versionBlockStore, deprecatedVersion, timeSeconds, height);
// Trying to add a new v2 block should result in rejection
thrown.expect(VerificationException.BlockVersionOutOfDate.class);
try {
Expand Down

0 comments on commit 344c4c3

Please sign in to comment.