-
Notifications
You must be signed in to change notification settings - Fork 171
Bugfix: repair rescan when sync stuck and allow sync to continue #1332
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
81dd5fc
ccb7452
76e575b
46af75f
fcddf1c
408952f
00fd624
ae89816
5867cc9
a0bd337
1a28458
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -120,6 +120,9 @@ | |
| import java.util.Set; | ||
| import java.util.concurrent.Executor; | ||
| import java.util.concurrent.Executors; | ||
| import java.util.concurrent.ScheduledExecutorService; | ||
| import java.util.concurrent.ScheduledFuture; | ||
| import java.util.concurrent.ScheduledThreadPoolExecutor; | ||
| import java.util.concurrent.TimeUnit; | ||
| import java.util.concurrent.atomic.AtomicBoolean; | ||
| import java.util.concurrent.atomic.AtomicInteger; | ||
|
|
@@ -990,11 +993,13 @@ public void onCreate() { | |
| } | ||
|
|
||
| try { | ||
| log.info("loading blockchain file"); | ||
| blockStore = new SPVBlockStore(Constants.NETWORK_PARAMETERS, blockChainFile); | ||
| blockStore.getChainHead(); // detect corruptions as early as possible | ||
|
|
||
| log.info("loading header file"); | ||
| headerStore = new SPVBlockStore(Constants.NETWORK_PARAMETERS, headerChainFile); | ||
| headerStore.getChainHead(); // detect corruptions as early as possible | ||
| verifyBlockStores(); | ||
|
|
||
| final long earliestKeyCreationTime = wallet.getEarliestKeyCreationTime(); | ||
|
|
||
|
|
@@ -1139,6 +1144,7 @@ public int onStartCommand(final Intent intent, final int flags, final int startI | |
| log.info("will remove blockchain on service shutdown"); | ||
|
|
||
| resetBlockchainOnShutdown = true; | ||
| config.setResetBlockchainPending(); | ||
| stopSelf(); | ||
| } else if (BlockchainService.ACTION_WIPE_WALLET.equals(action)) { | ||
| log.info("will remove blockchain and delete walletFile on service shutdown"); | ||
|
|
@@ -1290,6 +1296,9 @@ public void onDestroy() { | |
| } | ||
| //Clear the blockchain identity | ||
| WalletApplicationExt.INSTANCE.clearDatabases(application, false); | ||
| if (resetBlockchainOnShutdown) { | ||
| config.clearResetBlockchainPending(); | ||
| } | ||
| } | ||
|
|
||
| closeStream(mnlistinfoBootStrapStream); | ||
|
|
@@ -1481,4 +1490,103 @@ private void closeStream(InputStream mnlistinfoBootStrapStream) { | |
| } | ||
| } | ||
| } | ||
|
|
||
| // TODO: should we have a backup blockchain file? | ||
| // private NewBestBlockListener newBestBlockListener = block -> { | ||
| // try { | ||
| // backupBlockStore.put(block); | ||
| // } catch (BlockStoreException x) { | ||
| // throw new RuntimeException(x); | ||
| // } | ||
| // }; | ||
|
|
||
| private boolean verifyBlockStore(BlockStore store) throws BlockStoreException { | ||
| StoredBlock cursor = store.getChainHead(); | ||
| for (int i = 0; i < 10; ++i) { | ||
| cursor = cursor.getPrev(store); | ||
| if (cursor == null || cursor.getHeader().equals(Constants.NETWORK_PARAMETERS.getGenesisBlock())) { | ||
| break; | ||
| } | ||
| } | ||
| return true; | ||
| } | ||
|
|
||
| private boolean verifyBlockStore(BlockStore store, ScheduledExecutorService scheduledExecutorService) { | ||
| try { | ||
| ScheduledFuture<Boolean> future = scheduledExecutorService.schedule(() -> verifyBlockStore(store), 100, TimeUnit.MILLISECONDS); | ||
| return future.get(1, TimeUnit.SECONDS); | ||
| } catch (Exception e) { | ||
| log.warn("verification of blockstore failed:", e); | ||
| return false; | ||
| } | ||
| } | ||
|
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This will verify that the blockStore's can be accessed and give a time limit. When the blockchain was accessed during sync, the thread froze. So this was added to check for the freeze earlier. Turns out, though, that with one user that this check seemed to "warm up" the blockStore and the sync thread didn't freeze later. |
||
|
|
||
| // TODO: should we have a backup blockchain file? | ||
| // public static void copyFile(File source, File destination) throws IOException { | ||
| // try (FileChannel sourceChannel = new FileInputStream(source).getChannel(); | ||
| // FileChannel destChannel = new FileOutputStream(destination).getChannel()) { | ||
| // sourceChannel.transferTo(0, sourceChannel.size(), destChannel); | ||
| // } | ||
| // } | ||
|
Comment on lines
+1524
to
+1530
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. When we thought that the blockchain file was corrupt, I thought to back it up and have a means of restoring it. I will leave this for now and think a bit more about it. The backup file may not be necessary. |
||
| // | ||
| // | ||
| // private void replaceBlockStore(BlockStore a, File aFile, BlockStore b, File bFile) throws BlockStoreException { | ||
| // try { | ||
| // a.close(); | ||
| // b.close(); | ||
| // copyFile(bFile, aFile); | ||
| // } catch (IOException e) { | ||
| // throw new RuntimeException(e); | ||
| // } | ||
| // } | ||
|
|
||
| private void verifyBlockStores() throws BlockStoreException { | ||
| ScheduledExecutorService scheduledExecutorService = new ScheduledThreadPoolExecutor(1); | ||
| log.info("verifying backupBlockStore"); | ||
| // boolean verifiedBackupBlockStore = false; | ||
| boolean verifiedHeaderStore = false; | ||
| boolean verifiedBlockStore = false; | ||
| // if (!(verifiedBackupBlockStore = verifyBlockStore(backupBlockStore, scheduledExecutorService))) { | ||
| // log.info("backupBlockStore verification failed"); | ||
| // } | ||
|
|
||
| log.info("verifying headerStore"); | ||
| if (!(verifiedHeaderStore = verifyBlockStore(headerStore, scheduledExecutorService))) { | ||
| log.info("headerStore verification failed"); | ||
| } | ||
|
|
||
| log.info("verifying blockStore"); | ||
| if (!(verifiedBlockStore = verifyBlockStore(blockStore, scheduledExecutorService))) { | ||
| log.info("blockStore verification failed"); | ||
| } | ||
| // TODO: should we have a backup blockchain file? | ||
| // if (!verifiedBlockStore) { | ||
| // if (verifiedBackupBlockStore && | ||
| // !backupBlockStore.getChainHead().getHeader().getHash().equals(Constants.NETWORK_PARAMETERS.getGenesisBlock().getHash())) { | ||
| // log.info("replacing blockStore with backup"); | ||
| // replaceBlockStore(blockStore, blockChainFile, backupBlockStore, backupBlockChainFile); | ||
| // log.info("reloading blockStore"); | ||
| // blockStore = new SPVBlockStore(Constants.NETWORK_PARAMETERS, blockChainFile); | ||
| // blockStore.getChainHead(); // detect corruptions as early as possible | ||
| // log.info("reloading backup blockchain file"); | ||
| // backupBlockStore = new SPVBlockStore(Constants.NETWORK_PARAMETERS, blockChainFile); | ||
| // backupBlockStore.getChainHead(); // detect corruptions as early as possible | ||
| // verifyBlockStores(); | ||
| // } /*else if (verifiedHeaderStore) { | ||
| // log.info("replacing blockStore with header"); | ||
| // replaceBlockStore(blockStore, blockChainFile, headerStore, headerChainFile); | ||
| // log.info("reloading blockStore"); | ||
| // blockStore = new SPVBlockStore(Constants.NETWORK_PARAMETERS, blockChainFile); | ||
| // blockStore.getChainHead(); // detect corruptions as early as possible | ||
| // log.info("reloading header file"); | ||
| // headerStore = new SPVBlockStore(Constants.NETWORK_PARAMETERS, headerChainFile); | ||
| // headerStore.getChainHead(); // detect corruptions as early as possible | ||
| // verifyBlockStores(); | ||
| // } else*/ { | ||
| // // get blocks from platform here... | ||
| // throw new BlockStoreException("can't verify and recover"); | ||
| // } | ||
| // } | ||
| log.info("blockstore files verified: {}, {}", verifiedBlockStore, verifiedHeaderStore); | ||
| } | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This was added to check to see if it was possible to access the blockStore. The theory was that the blockStore file was corrupted and this resulted in a freeze when accessing the file.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So far this test passed, even with a device with sync problems.