diff --git a/src/test/chainstate_write_tests.cpp b/src/test/chainstate_write_tests.cpp index 01e000115d7..6699846c58c 100644 --- a/src/test/chainstate_write_tests.cpp +++ b/src/test/chainstate_write_tests.cpp @@ -85,6 +85,7 @@ BOOST_FIXTURE_TEST_CASE(write_during_multiblock_activation, TestChain100Setup) // Set m_next_write to current time chainstate.FlushStateToDisk(state_dummy, FlushStateMode::FORCE_FLUSH); + BOOST_CHECK_EQUAL(WITH_LOCK(::cs_main, return chainstate.GetLastFlushedBlock()), second_from_tip->pprev); m_node.validation_signals->SyncWithValidationInterfaceQueue(); // The periodic flush interval is between 50 and 70 minutes (inclusive) // The next call to a PERIODIC write will flush @@ -101,6 +102,7 @@ BOOST_FIXTURE_TEST_CASE(write_during_multiblock_activation, TestChain100Setup) // inside the outer loop. m_node.validation_signals->SyncWithValidationInterfaceQueue(); BOOST_CHECK_EQUAL(sub->m_flushed_at_block, second_from_tip); + BOOST_CHECK_EQUAL(WITH_LOCK(::cs_main, return chainstate.GetLastFlushedBlock()), second_from_tip); } BOOST_AUTO_TEST_SUITE_END() diff --git a/src/validation.cpp b/src/validation.cpp index bd05376be00..9df377fb167 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -2823,6 +2823,7 @@ bool Chainstate::FlushStateToDisk( } // Flush the chainstate (which may refer to block index entries). empty_cache ? CoinsTip().Flush() : CoinsTip().Sync(); + m_last_flushed_block = m_blockman.LookupBlockIndex(CoinsTip().GetBestBlock()); full_flush_completed = true; TRACEPOINT(utxocache, flush, int64_t{Ticks(NodeClock::now() - nNow)}, @@ -4584,6 +4585,7 @@ bool Chainstate::LoadChainTip() } m_chain.SetTip(*pindex); m_chainman.UpdateIBDStatus(); + m_last_flushed_block = pindex; tip = m_chain.Tip(); // nSequenceId is one of the keys used to sort setBlockIndexCandidates. Ensure all diff --git a/src/validation.h b/src/validation.h index 2aac1e90078..d89ad3539e4 100644 --- a/src/validation.h +++ b/src/validation.h @@ -840,6 +840,9 @@ public: std::string ToString() EXCLUSIVE_LOCKS_REQUIRED(::cs_main); + //! Get the last block that was flushed to disk. + const CBlockIndex* GetLastFlushedBlock() const EXCLUSIVE_LOCKS_REQUIRED(::cs_main) { return m_last_flushed_block; } + //! Indirection necessary to make lock annotations work with an optional mempool. RecursiveMutex* MempoolMutex() const LOCK_RETURNED(m_mempool->cs) { @@ -890,6 +893,7 @@ protected: EXCLUSIVE_LOCKS_REQUIRED(::cs_main); NodeClock::time_point m_next_write{NodeClock::time_point::max()}; + const CBlockIndex* m_last_flushed_block GUARDED_BY(::cs_main){nullptr}; /** * In case of an invalid snapshot, rename the coins leveldb directory so