@Override
    public boolean add(FilteredBlock block) throws VerificationException, PrunedException {
        boolean success = super.add(block);
        if (success) {
            trackFilteredTransactions(block.getTransactionCount());
        }
        return success;
    }
@Test
    public void coinbaseTransactionAvailability() throws Exception {
        Context.propagate(new Context(100, Coin.ZERO, false, true));
        // Check that a coinbase transaction is only available to spend after NetworkParameters.getSpendableCoinbaseDepth() blocks.

        // Create a second wallet to receive the coinbase spend.
        Wallet wallet2 = Wallet.createDeterministic(BitcoinNetwork.TESTNET, ScriptType.P2PKH);
        ECKey receiveKey = wallet2.freshReceiveKey();
        int height = 1;
        testNetChain.addWallet(wallet2);

        Address addressToSendTo = receiveKey.toAddress(ScriptType.P2PKH, BitcoinNetwork.TESTNET);

        // Create a block, sending the coinbase to the coinbaseTo address (which is in the wallet).
        Block b1 = TESTNET.getGenesisBlock().createNextBlockWithCoinbase(Block.BLOCK_VERSION_GENESIS, testNetWallet.currentReceiveKey().getPubKey(), height++);
        testNetChain.add(b1);
        final Transaction coinbaseTransaction = b1.getTransactions().get(0);

        // Check a transaction has been received.
        assertNotNull(coinbaseTransaction);

        // The coinbase tx is not yet available to spend.
        assertEquals(Coin.ZERO, testNetWallet.getBalance());
        assertEquals(FIFTY_COINS, testNetWallet.getBalance(BalanceType.ESTIMATED));
        assertFalse(testNetWallet.isTransactionMature(coinbaseTransaction));

        // Attempt to spend the coinbase - this should fail as the coinbase is not mature yet.
        try {
            testNetWallet.createSend(addressToSendTo, valueOf(49, 0));
            fail();
        } catch (InsufficientMoneyException e) {
        }

        // Check that the coinbase is unavailable to spend for the next spendableCoinbaseDepth - 2 blocks.
        for (int i = 0; i < TESTNET.getSpendableCoinbaseDepth() - 2; i++) {
            // Non relevant tx - just for fake block creation.
            Transaction tx2 = createFakeTx(TESTNET.network(), COIN, new ECKey().toAddress(ScriptType.P2PKH, TESTNET.network()));

            Block b2 = createFakeBlock(testNetStore, height++, tx2).block;
            testNetChain.add(b2);

            // Wallet still does not have the coinbase transaction available for spend.
            assertEquals(Coin.ZERO, testNetWallet.getBalance());
            assertEquals(FIFTY_COINS, testNetWallet.getBalance(BalanceType.ESTIMATED));

            // The coinbase transaction is still not mature.
            assertFalse(testNetWallet.isTransactionMature(coinbaseTransaction));

            // Attempt to spend the coinbase - this should fail.
            try {
                testNetWallet.createSend(addressToSendTo, valueOf(49, 0));
                fail();
            } catch (InsufficientMoneyException e) {
            }
        }

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

        // Wallet now has the coinbase transaction available for spend.
        assertEquals(FIFTY_COINS, testNetWallet.getBalance());
        assertEquals(FIFTY_COINS, testNetWallet.getBalance(BalanceType.ESTIMATED));
        assertTrue(testNetWallet.isTransactionMature(coinbaseTransaction));

        // Create a spend with the coinbase BTC to the address in the second wallet - this should now succeed.
        Transaction coinbaseSend2 = testNetWallet.createSend(addressToSendTo, valueOf(49, 0));
        assertNotNull(coinbaseSend2);

        // Commit the coinbaseSpend to the first wallet and check the balances decrement.
        testNetWallet.commitTx(coinbaseSend2);
        assertEquals(COIN, testNetWallet.getBalance(BalanceType.ESTIMATED));
        // Available balance is zero as change has not been received from a block yet.
        assertEquals(ZERO, testNetWallet.getBalance(BalanceType.AVAILABLE));

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

        // Check the balances in the second wallet.
        assertEquals(valueOf(49, 0), wallet2.getBalance(BalanceType.ESTIMATED));
        assertEquals(valueOf(49, 0), wallet2.getBalance(BalanceType.AVAILABLE));
    }