/** * Removes the current wallet from the block chain and closes the block store */ private void closeBlockstore() { // Remove the wallet from the block chain before closing the blockstore if (WalletManager.INSTANCE.getCurrentWalletSummary().isPresent() && blockChain != null) { log.debug("Removing wallet from blockChain..."); blockChain.removeWallet(WalletManager.INSTANCE.getCurrentWalletSummary().get().getWallet()); blockChain = null; // need to recreate it when a new blockstore is created } // Close the blockstore if (blockStore != null) { try { // The blockstore can throw an NPE internally log.debug("When the blockstore was closed the height was {}", blockStore.getChainHead() == null ? "unknown" : blockStore.getChainHead().getHeight()); blockStore.close(); } catch (BlockStoreException e) { log.warn("BlockStoreException: Blockstore was already closed or not closed cleanly: {}", e.getMessage()); } catch (NullPointerException e) { // Internal bug in Bitcoinj } } else { log.debug("blockStore was not present"); } blockStore = null; }
@Test public void rollbackBlockStore() throws Exception { // This test simulates an issue on Android, that causes the VM to crash while receiving a block, so that the // block store is persisted but the wallet is not. Block b1 = PARAMS.getGenesisBlock().createNextBlock(coinbaseTo); Block b2 = b1.createNextBlock(coinbaseTo); // Add block 1, no frills. assertTrue(chain.add(b1)); assertEquals(b1.cloneAsHeader(), chain.getChainHead().getHeader()); assertEquals(1, chain.getBestChainHeight()); assertEquals(1, wallet.getLastBlockSeenHeight()); // Add block 2 while wallet is disconnected, to simulate crash. chain.removeWallet(wallet); assertTrue(chain.add(b2)); assertEquals(b2.cloneAsHeader(), chain.getChainHead().getHeader()); assertEquals(2, chain.getBestChainHeight()); assertEquals(1, wallet.getLastBlockSeenHeight()); // Add wallet back. This will detect the height mismatch and repair the damage done. chain.addWallet(wallet); assertEquals(b1.cloneAsHeader(), chain.getChainHead().getHeader()); assertEquals(1, chain.getBestChainHeight()); assertEquals(1, wallet.getLastBlockSeenHeight()); // Now add block 2 correctly. assertTrue(chain.add(b2)); assertEquals(b2.cloneAsHeader(), chain.getChainHead().getHeader()); assertEquals(2, chain.getBestChainHeight()); assertEquals(2, wallet.getLastBlockSeenHeight()); } }