/** 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 } } }