Enforce v4 block switchover

This enforces the switch over to block v4 once a supermajority is met, as
per BIP65.
This commit is contained in:
Ross Nicoll 2015-10-27 21:26:48 +00:00 committed by Andreas Schildbach
parent 1c8a60d2ef
commit 344c4c3baa
3 changed files with 25 additions and 7 deletions

View file

@ -544,12 +544,13 @@ public abstract class AbstractBlockChain {
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());

View file

@ -84,6 +84,8 @@ public class Block extends Message {
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;

View file

@ -38,6 +38,7 @@ import java.util.Date;
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.*;
@ -230,6 +231,20 @@ public class BlockChainTest {
*/
@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);
@ -240,18 +255,18 @@ public class BlockChainTest {
// 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 {