Repository: bitcoin/bitcoin
File: src/validation.h (C/C++)

Code before:
     * - Clarify that the method will acquire a mutex that heavily affects
     *   overall performance.
     * - Force call sites to think how long they need to acquire the mutex to
     *   get consistent results.
     */
    RecursiveMutex& GetMutex() const LOCK_RETURNED(::cs_main) { return ::cs_main; }

    const util::SignalInterrupt& m_interrupt;
    const Options m_options;
    //! A single BlockManager instance is shared across each constructed
    //! chainstate to avoid duplicating block metadata.
    node::BlockManager m_blockman;

    ValidationCache m_validation_cache;

    /**
     * Whether initial block download has ended and IsInitialBlockDownload
     * should return false from now on.
     *
     * Mutable because we need to be able to mark IsInitialBlockDownload()
     * const, which latches this for caching purposes.
     */
    mutable std::atomic_bool m_cached_finished_ibd{false};

    /** Latch that becomes true once the active tip has met IsTipRecent(). */
    mutable std::atomic_bool m_cached_tip_recent{false};

    /**
     * Every received block is assigned a unique and increasing identifier, so we
     * know which one to give priority in case of a fork.
     */
    /** Blocks loaded from disk are assigned id SEQ_ID_INIT_FROM_DISK{1}
     * (SEQ_ID_BEST_CHAIN_FROM_DISK{0} if they belong to the best chain loaded from disk),
     * so start the counter after that. **/
    int32_t nBlockSequenceId GUARDED_BY(::cs_main) = SEQ_ID_INIT_FROM_DISK + 1;
    /** Decreasing counter (used by subsequent preciousblock calls). */
    int32_t nBlockReverseSequenceId = -1;
    /** chainwork for the last block that preciousblock has been applied to. */
    arith_uint256 nLastPreciousChainwork = 0;

    // Reset the memory-only sequence counters we use to track block arrival
    // (used by tests to reset state)
    void ResetBlockSequenceCounters() EXCLUSIVE_LOCKS_REQUIRED(::cs_main)
    {
        AssertLockHeld(::cs_main);
        nBlockSequenceId = SEQ_ID_INIT_FROM_DISK + 1;
        nBlockReverseSequenceId = -1;
    }


    /** Best header we've seen so far for which the block is not known to be invalid

Review comment (performance):
I think having both `m_cached_tip_recent` and `m_cached_finished_ibd` may be more complicated than necessary. Probably the reason for it is that `IsIBD()` should latch to true also after `ImportBlocks()` without having to wait for a new block.
Would it work to instead have just one atomic called `m_cached_finished_ibd` that is only set when `LoadingBlocks()` is false, ans set it in a function `ChainstateManager::MaybeExitIBD()`  that would be called both from `ChainstateManager::SetTip` (within the current approach, see also my other comment about that) and at the end of `ImportBlocks()` when `ImportingNow` went out of scope`?

Code after:
     * - Clarify that the method will acquire a mutex that heavily affects
     *   overall performance.
     * - Force call sites to think how long they need to acquire the mutex to
     *   get consistent results.
     */
    RecursiveMutex& GetMutex() const LOCK_RETURNED(::cs_main) { return ::cs_main; }

    const util::SignalInterrupt& m_interrupt;
    const Options m_options;
    //! A single BlockManager instance is shared across each constructed
    //! chainstate to avoid duplicating block metadata.
    node::BlockManager m_blockman;

    ValidationCache m_validation_cache;

    /**
     * Whether initial block download (IBD) is ongoing.
     *
     * This value is used for lock-free IBD checks, and latches from true to
     * false once block loading has finished and the current chain tip has
     * enough work and is recent.
     */
    std::atomic_bool m_cached_is_ibd{true};

    /**
     * Every received block is assigned a unique and increasing identifier, so we
     * know which one to give priority in case of a fork.
     */
    /** Blocks loaded from disk are assigned id SEQ_ID_INIT_FROM_DISK{1}
     * (SEQ_ID_BEST_CHAIN_FROM_DISK{0} if they belong to the best chain loaded from disk),
     * so start the counter after that. **/
    int32_t nBlockSequenceId GUARDED_BY(::cs_main) = SEQ_ID_INIT_FROM_DISK + 1;
    /** Decreasing counter (used by subsequent preciousblock calls). */
    int32_t nBlockReverseSequenceId = -1;
    /** chainwork for the last block that preciousblock has been applied to. */
    arith_uint256 nLastPreciousChainwork = 0;

    // Reset the memory-only sequence counters we use to track block arrival
    // (used by tests to reset state)
    void ResetBlockSequenceCounters() EXCLUSIVE_LOCKS_REQUIRED(::cs_main)
    {
        AssertLockHeld(::cs_main);
        nBlockSequenceId = SEQ_ID_INIT_FROM_DISK + 1;
        nBlockReverseSequenceId = -1;
    }


    /** Best header we've seen so far for which the block is not known to be invalid
        (used, among others, for getheaders queries' starting points).
        In case of multiple best headers with the same work, it could point to any
        because CBlockIndexWorkComparator tiebreaker rules are not applied. */