2022-09-19 17:31:01 +03:00
|
|
|
// 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 <node/txreconciliation.h>
|
|
|
|
|
|
|
|
#include <util/check.h>
|
|
|
|
#include <util/system.h>
|
|
|
|
|
|
|
|
#include <unordered_map>
|
|
|
|
#include <variant>
|
|
|
|
|
|
|
|
|
|
|
|
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<NodeId, std::variant<uint64_t, TxReconciliationState>> 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;
|
|
|
|
}
|
2021-03-20 12:50:02 +02:00
|
|
|
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
}
|
2022-09-19 17:31:01 +03:00
|
|
|
};
|
|
|
|
|
|
|
|
TxReconciliationTracker::TxReconciliationTracker() : m_impl{std::make_unique<TxReconciliationTracker::Impl>()} {}
|
|
|
|
|
|
|
|
TxReconciliationTracker::~TxReconciliationTracker() = default;
|
|
|
|
|
|
|
|
uint64_t TxReconciliationTracker::PreRegisterPeer(NodeId peer_id)
|
|
|
|
{
|
|
|
|
return m_impl->PreRegisterPeer(peer_id);
|
|
|
|
}
|
2021-03-20 12:50:02 +02:00
|
|
|
|
|
|
|
void TxReconciliationTracker::ForgetPeer(NodeId peer_id)
|
|
|
|
{
|
|
|
|
m_impl->ForgetPeer(peer_id);
|
|
|
|
}
|