From a3e713ace8b6dd97b6048b267e51e74f5a386f5f Mon Sep 17 00:00:00 2001 From: Patrick Strateman Date: Wed, 10 Feb 2021 15:15:55 -0500 Subject: [PATCH] net: latch IBD across restarts this prevents a network wide failure in the event that all or most listening nodes are restarted at approximately the same time --- src/test/util/validation.cpp | 1 + src/validation.cpp | 15 +++++++++++++++ 2 files changed, 16 insertions(+) diff --git a/src/test/util/validation.cpp b/src/test/util/validation.cpp index 1aed492c3c037..24083bd98d0ca 100644 --- a/src/test/util/validation.cpp +++ b/src/test/util/validation.cpp @@ -11,6 +11,7 @@ void TestChainState::ResetIbd() { m_cached_finished_ibd = false; + fs::remove(GetDataDir() / ".ibd_complete"); assert(IsInitialBlockDownload()); } diff --git a/src/validation.cpp b/src/validation.cpp index 8f7d36bfd3ffb..5a5899a7ee2a3 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -1294,8 +1295,11 @@ void CChainState::InitCoinsCache(size_t cache_size_bytes) // `const` so that `CValidationInterface` clients (which are given a `const CChainState*`) // can call it. // +// The file .ibd_complete is used to latch the datadir to IBD false across restarts +// bool CChainState::IsInitialBlockDownload() const { + static const fs::path latch_filename = GetDataDir() / ".ibd_complete"; // Optimization: pre-test latch before taking the lock. if (m_cached_finished_ibd.load(std::memory_order_relaxed)) return false; @@ -1303,6 +1307,11 @@ bool CChainState::IsInitialBlockDownload() const LOCK(cs_main); if (m_cached_finished_ibd.load(std::memory_order_relaxed)) return false; + if (fs::exists(latch_filename)) { + LogPrintf("Leaving InitialBlockDownload (latching to false)\n"); + m_cached_finished_ibd.store(true, std::memory_order_relaxed); + return false; + } if (fImporting || fReindex) return true; if (m_chain.Tip() == nullptr) @@ -1312,6 +1321,12 @@ bool CChainState::IsInitialBlockDownload() const if (m_chain.Tip()->GetBlockTime() < (GetTime() - nMaxTipAge)) return true; LogPrintf("Leaving InitialBlockDownload (latching to false)\n"); + FILE* f = fsbridge::fopen(latch_filename, "wb"); + if (f) { + fclose(f); + } else { + LogPrintf("Failed to write %s\n", latch_filename.string().c_str()); + } m_cached_finished_ibd.store(true, std::memory_order_relaxed); return false; }