@@ -139,6 +139,9 @@ static constexpr bool DEFAULT_REST_ENABLE{false};
139139static constexpr bool DEFAULT_I2P_ACCEPT_INCOMING{true };
140140static constexpr bool DEFAULT_STOPAFTERBLOCKIMPORT{false };
141141
142+ // ! Check if initial sync is done with no change in block height or queued downloads every 30s
143+ static constexpr auto SYNC_CHECK_INTERVAL{30s};
144+
142145#ifdef WIN32
143146// Win32 LevelDB doesn't use filedescriptors, and the ones used for
144147// accessing block files don't count towards the fd_set size limit
@@ -1108,6 +1111,44 @@ bool AppInitLockDataDirectory()
11081111 return true ;
11091112}
11101113
1114+ /* *
1115+ * Once initial block sync is finished and no change in block height or queued downloads,
1116+ * sync utxo state to protect against data loss
1117+ */
1118+ static void SyncCoinsTipAfterChainSync (const NodeContext& node)
1119+ {
1120+ LOCK (node.chainman ->GetMutex ());
1121+ if (node.chainman ->IsInitialBlockDownload ()) {
1122+ LogDebug (BCLog::COINDB, " Node is still in IBD, rescheduling post-IBD chainstate disk sync...\n " );
1123+ node.scheduler ->scheduleFromNow ([&node] {
1124+ SyncCoinsTipAfterChainSync (node);
1125+ }, SYNC_CHECK_INTERVAL);
1126+ return ;
1127+ }
1128+
1129+ static auto last_chain_height{-1 };
1130+ const auto current_height{node.chainman ->ActiveHeight ()};
1131+ if (last_chain_height != current_height) {
1132+ LogDebug (BCLog::COINDB, " Chain height updated since last check, rescheduling post-IBD chainstate disk sync...\n " );
1133+ last_chain_height = current_height;
1134+ node.scheduler ->scheduleFromNow ([&node] {
1135+ SyncCoinsTipAfterChainSync (node);
1136+ }, SYNC_CHECK_INTERVAL);
1137+ return ;
1138+ }
1139+
1140+ if (node.peerman ->GetNumberOfPeersWithValidatedDownloads () > 0 ) {
1141+ LogDebug (BCLog::COINDB, " Still downloading blocks from peers, rescheduling post-IBD chainstate disk sync...\n " );
1142+ node.scheduler ->scheduleFromNow ([&node] {
1143+ SyncCoinsTipAfterChainSync (node);
1144+ }, SYNC_CHECK_INTERVAL);
1145+ return ;
1146+ }
1147+
1148+ LogDebug (BCLog::COINDB, " Finished syncing to tip, syncing chainstate to disk\n " );
1149+ node.chainman ->ActiveChainstate ().CoinsTip ().Sync ();
1150+ }
1151+
11111152bool AppInitInterfaces (NodeContext& node)
11121153{
11131154 node.chain = node.init ->makeChain ();
@@ -1985,6 +2026,12 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)
19852026 StartupNotify (args);
19862027#endif
19872028
2029+ if (node.chainman ->IsInitialBlockDownload ()) {
2030+ node.scheduler ->scheduleFromNow ([&node] {
2031+ SyncCoinsTipAfterChainSync (node);
2032+ }, SYNC_CHECK_INTERVAL);
2033+ }
2034+
19882035 return true ;
19892036}
19902037
0 commit comments