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