// Copyright (c) 2022 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include #include #include #include #include namespace { /** * Keeps track of txreconciliation-related per-peer state. */ class TxReconciliationState { }; } // namespace /** Actual implementation for TxReconciliationTracker's data structure. */ class TxReconciliationTracker::Impl { private: mutable Mutex m_txreconciliation_mutex; /** * Keeps track of txreconciliation states of eligible peers. * For pre-registered peers, the locally generated salt is stored. * For registered peers, the locally generated salt is forgotten, and the state (including * "full" salt) is stored instead. */ std::unordered_map> m_states GUARDED_BY(m_txreconciliation_mutex); public: explicit Impl() {} uint64_t PreRegisterPeer(NodeId peer_id) EXCLUSIVE_LOCKS_REQUIRED(!m_txreconciliation_mutex) { AssertLockNotHeld(m_txreconciliation_mutex); LOCK(m_txreconciliation_mutex); // We do not support txreconciliation salt/version updates. assert(m_states.find(peer_id) == m_states.end()); LogPrintLevel(BCLog::TXRECONCILIATION, BCLog::Level::Debug, "Pre-register peer=%d\n", peer_id); const uint64_t local_salt{GetRand(UINT64_MAX)}; // We do this exactly once per peer (which are unique by NodeId, see GetNewNodeId) so it's // safe to assume we don't have this record yet. Assert(m_states.emplace(peer_id, local_salt).second); return local_salt; } void ForgetPeer(NodeId peer_id) EXCLUSIVE_LOCKS_REQUIRED(!m_txreconciliation_mutex) { AssertLockNotHeld(m_txreconciliation_mutex); LOCK(m_txreconciliation_mutex); if (m_states.erase(peer_id)) { LogPrintLevel(BCLog::TXRECONCILIATION, BCLog::Level::Debug, "Forget txreconciliation state of peer=%d\n", peer_id); } } }; TxReconciliationTracker::TxReconciliationTracker() : m_impl{std::make_unique()} {} TxReconciliationTracker::~TxReconciliationTracker() = default; uint64_t TxReconciliationTracker::PreRegisterPeer(NodeId peer_id) { return m_impl->PreRegisterPeer(peer_id); } void TxReconciliationTracker::ForgetPeer(NodeId peer_id) { m_impl->ForgetPeer(peer_id); }