189 std::unique_ptr<PartiallyDownloadedBlock> partialBlock;
223 std::atomic<ServiceFlags> m_their_services{
NODE_NONE};
226 Mutex m_misbehavior_mutex;
228 int m_misbehavior_score
GUARDED_BY(m_misbehavior_mutex){0};
230 bool m_should_discourage
GUARDED_BY(m_misbehavior_mutex){
false};
233 Mutex m_block_inv_mutex;
237 std::vector<uint256> m_blocks_for_inv_relay
GUARDED_BY(m_block_inv_mutex);
241 std::vector<uint256> m_blocks_for_headers_relay
GUARDED_BY(m_block_inv_mutex);
249 std::atomic<int> m_starting_height{-1};
252 std::atomic<uint64_t> m_ping_nonce_sent{0};
254 std::atomic<std::chrono::microseconds> m_ping_start{0us};
256 std::atomic<bool> m_ping_queued{
false};
259 std::atomic<bool> m_wtxid_relay{
false};
271 bool m_relay_txs
GUARDED_BY(m_bloom_filter_mutex){
false};
273 std::unique_ptr<CBloomFilter> m_bloom_filter
PT_GUARDED_BY(m_bloom_filter_mutex)
GUARDED_BY(m_bloom_filter_mutex){
nullptr};
284 std::set<uint256> m_tx_inventory_to_send
GUARDED_BY(m_tx_inventory_mutex);
288 bool m_send_mempool
GUARDED_BY(m_tx_inventory_mutex){
false};
291 std::chrono::microseconds m_next_inv_send_time
GUARDED_BY(m_tx_inventory_mutex){0};
297 std::atomic<CAmount> m_fee_filter_received{0};
303 LOCK(m_tx_relay_mutex);
305 m_tx_relay = std::make_unique<Peer::TxRelay>();
306 return m_tx_relay.get();
311 return WITH_LOCK(m_tx_relay_mutex,
return m_tx_relay.get());
340 std::atomic_bool m_addr_relay_enabled{
false};
344 mutable Mutex m_addr_send_times_mutex;
346 std::chrono::microseconds m_next_addr_send
GUARDED_BY(m_addr_send_times_mutex){0};
348 std::chrono::microseconds m_next_local_addr_send
GUARDED_BY(m_addr_send_times_mutex){0};
351 std::atomic_bool m_wants_addrv2{
false};
360 std::atomic<uint64_t> m_addr_rate_limited{0};
362 std::atomic<uint64_t> m_addr_processed{0};
368 Mutex m_getdata_requests_mutex;
370 std::deque<CInv> m_getdata_requests
GUARDED_BY(m_getdata_requests_mutex);
376 Mutex m_headers_sync_mutex;
379 std::unique_ptr<HeadersSyncState> m_headers_sync
PT_GUARDED_BY(m_headers_sync_mutex)
GUARDED_BY(m_headers_sync_mutex) {};
382 std::atomic<bool> m_sent_sendheaders{
false};
395 , m_our_services{our_services}
399 mutable Mutex m_tx_relay_mutex;
402 std::unique_ptr<TxRelay> m_tx_relay
GUARDED_BY(m_tx_relay_mutex);
405 using PeerRef = std::shared_ptr<Peer>;
417 uint256 hashLastUnknownBlock{};
423 bool fSyncStarted{
false};
425 std::chrono::microseconds m_stalling_since{0us};
426 std::list<QueuedBlock> vBlocksInFlight;
428 std::chrono::microseconds m_downloading_since{0us};
430 bool fPreferredDownload{
false};
432 bool m_requested_hb_cmpctblocks{
false};
434 bool m_provides_cmpctblocks{
false};
460 struct ChainSyncTimeoutState {
462 std::chrono::seconds m_timeout{0s};
466 bool m_sent_getheaders{
false};
468 bool m_protect{
false};
471 ChainSyncTimeoutState m_chain_sync;
474 int64_t m_last_block_announcement{0};
477 const bool m_is_inbound;
479 CNodeState(
bool is_inbound) : m_is_inbound(is_inbound) {}
506 EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex, !m_recent_confirmed_transactions_mutex, !m_most_recent_block_mutex, !m_headers_presync_mutex, g_msgproc_mutex);
508 EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex, !m_recent_confirmed_transactions_mutex, !m_most_recent_block_mutex, g_msgproc_mutex);
519 void SetBestBlock(
int height,
std::chrono::seconds time)
override
521 m_best_height = height;
522 m_best_block_time = time;
526 const std::chrono::microseconds time_received,
const std::atomic<bool>& interruptMsgProc)
override
527 EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex, !m_recent_confirmed_transactions_mutex, !m_most_recent_block_mutex, !m_headers_presync_mutex, g_msgproc_mutex);
553 void Misbehaving(Peer& peer,
int howmuch,
const std::string& message);
566 bool via_compact_block,
const std::string& message =
"")
583 bool MaybeDiscourageAndDisconnect(
CNode& pnode, Peer& peer);
591 bool maybe_add_extra_compact_tx)
610 bool ProcessOrphanTx(Peer& peer)
620 void ProcessHeadersMessage(
CNode& pfrom, Peer& peer,
622 bool via_compact_block)
634 bool CheckHeadersAreContinuous(const
std::vector<
CBlockHeader>& headers) const;
653 bool IsContinuationOfLowWorkHeadersSync(Peer& peer,
CNode& pfrom,
667 bool TryLowWorkHeadersSync(Peer& peer,
CNode& pfrom,
682 void HeadersDirectFetchBlocks(
CNode& pfrom, const Peer& peer, const
CBlockIndex& last_header);
684 void UpdatePeerStateForReceivedHeaders(
CNode& pfrom, Peer& peer, const
CBlockIndex& last_header,
bool received_new_header,
bool may_have_more_headers)
692 void AddTxAnnouncement(const
CNode&
node, const
GenTxid& gtxid,
std::chrono::microseconds current_time)
697 template <
typename... Args>
698 void MakeAndPushMessage(
CNode&
node, std::string msg_type, Args&&...
args)
const
704 void PushNodeVersion(
CNode& pnode,
const Peer& peer);
710 void MaybeSendPing(
CNode& node_to, Peer& peer, std::chrono::microseconds now);
742 std::unique_ptr<TxReconciliationTracker> m_txreconciliation;
745 std::atomic<int> m_best_height{-1};
747 std::atomic<std::chrono::seconds> m_best_block_time{0s};
752 const Options m_opts;
754 bool RejectIncomingTxs(
const CNode& peer)
const;
762 mutable Mutex m_peer_mutex;
769 std::map<NodeId, PeerRef> m_peer_map
GUARDED_BY(m_peer_mutex);
779 uint32_t GetFetchFlags(
const Peer& peer)
const;
781 std::atomic<std::chrono::microseconds> m_next_inv_to_inbounds{0us};
798 std::atomic<int> m_wtxid_relay_peers{0};
809 bool AlreadyHaveTx(
const GenTxid& gtxid)
864 Mutex m_recent_confirmed_transactions_mutex;
873 std::chrono::microseconds NextInvToInbounds(std::chrono::microseconds now,
874 std::chrono::seconds average_interval);
878 Mutex m_most_recent_block_mutex;
879 std::shared_ptr<const CBlock> m_most_recent_block
GUARDED_BY(m_most_recent_block_mutex);
880 std::shared_ptr<const CBlockHeaderAndShortTxIDs> m_most_recent_compact_block
GUARDED_BY(m_most_recent_block_mutex);
882 std::unique_ptr<const std::map<uint256, CTransactionRef>> m_most_recent_block_txs
GUARDED_BY(m_most_recent_block_mutex);
886 Mutex m_headers_presync_mutex;
894 using HeadersPresyncStats = std::pair<arith_uint256, std::optional<std::pair<int64_t, uint32_t>>>;
896 std::map<NodeId, HeadersPresyncStats> m_headers_presync_stats
GUARDED_BY(m_headers_presync_mutex) {};
900 std::atomic_bool m_headers_presync_should_signal{
false};
970 std::atomic<
std::chrono::seconds> m_last_tip_update{0s};
976 void ProcessGetData(
CNode& pfrom, Peer& peer,
const std::atomic<bool>& interruptMsgProc)
981 void ProcessBlock(
CNode&
node,
const std::shared_ptr<const CBlock>& block,
bool force_processing,
bool min_pow_checked);
1009 std::vector<CTransactionRef> vExtraTxnForCompact
GUARDED_BY(g_msgproc_mutex);
1011 size_t vExtraTxnForCompactIt
GUARDED_BY(g_msgproc_mutex) = 0;
1023 int64_t ApproximateBestBlockDepth() const;
1033 void ProcessGetBlockData(
CNode& pfrom, Peer& peer, const
CInv& inv)
1051 bool PrepareBlockFilterRequest(
CNode&
node, Peer& peer,
1053 const
uint256& stop_hash, uint32_t max_height_diff,
1104 std::map<NodeId, CNodeState>::const_iterator it = m_node_states.find(pnode);
1105 if (it == m_node_states.end())
1112 return const_cast<CNodeState*
>(std::as_const(*this).State(pnode));
1120 static bool IsAddrCompatible(
const Peer& peer,
const CAddress& addr)
1125 void PeerManagerImpl::AddAddressKnown(Peer& peer,
const CAddress& addr)
1127 assert(peer.m_addr_known);
1128 peer.m_addr_known->insert(addr.
GetKey());
1131 void PeerManagerImpl::PushAddress(Peer& peer,
const CAddress& addr)
1136 assert(peer.m_addr_known);
1137 if (addr.
IsValid() && !peer.m_addr_known->contains(addr.
GetKey()) && IsAddrCompatible(peer, addr)) {
1139 peer.m_addrs_to_send[m_rng.randrange(peer.m_addrs_to_send.size())] = addr;
1141 peer.m_addrs_to_send.push_back(addr);
1146 static void AddKnownTx(Peer& peer,
const uint256& hash)
1148 auto tx_relay = peer.GetTxRelay();
1149 if (!tx_relay)
return;
1151 LOCK(tx_relay->m_tx_inventory_mutex);
1152 tx_relay->m_tx_inventory_known_filter.insert(hash);
1156 static bool CanServeBlocks(
const Peer& peer)
1163 static bool IsLimitedPeer(
const Peer& peer)
1170 static bool CanServeWitnesses(
const Peer& peer)
1175 std::chrono::microseconds PeerManagerImpl::NextInvToInbounds(std::chrono::microseconds now,
1176 std::chrono::seconds average_interval)
1178 if (m_next_inv_to_inbounds.load() < now) {
1184 return m_next_inv_to_inbounds;
1187 bool PeerManagerImpl::IsBlockRequested(
const uint256& hash)
1189 return mapBlocksInFlight.count(hash);
1192 bool PeerManagerImpl::IsBlockRequestedFromOutbound(
const uint256& hash)
1194 for (
auto range = mapBlocksInFlight.equal_range(hash); range.first != range.second; range.first++) {
1195 auto [nodeid, block_it] = range.first->second;
1196 CNodeState& nodestate = *
Assert(State(nodeid));
1197 if (!nodestate.m_is_inbound)
return true;
1203 void PeerManagerImpl::RemoveBlockRequest(
const uint256& hash, std::optional<NodeId> from_peer)
1205 auto range = mapBlocksInFlight.equal_range(hash);
1206 if (range.first == range.second) {
1214 while (range.first != range.second) {
1215 auto [node_id, list_it] = range.first->second;
1217 if (from_peer && *from_peer != node_id) {
1222 CNodeState& state = *
Assert(State(node_id));
1224 if (state.vBlocksInFlight.begin() == list_it) {
1226 state.m_downloading_since = std::max(state.m_downloading_since, GetTime<std::chrono::microseconds>());
1228 state.vBlocksInFlight.erase(list_it);
1230 if (state.vBlocksInFlight.empty()) {
1232 m_peers_downloading_from--;
1234 state.m_stalling_since = 0us;
1236 range.first = mapBlocksInFlight.erase(range.first);
1240 bool PeerManagerImpl::BlockRequested(
NodeId nodeid,
const CBlockIndex& block, std::list<QueuedBlock>::iterator** pit)
1244 CNodeState *state = State(nodeid);
1245 assert(state !=
nullptr);
1250 for (
auto range = mapBlocksInFlight.equal_range(hash); range.first != range.second; range.first++) {
1251 if (range.first->second.first == nodeid) {
1253 *pit = &range.first->second.second;
1260 RemoveBlockRequest(hash, nodeid);
1262 std::list<QueuedBlock>::iterator it = state->vBlocksInFlight.insert(state->vBlocksInFlight.end(),
1263 {&block, std::unique_ptr<PartiallyDownloadedBlock>(pit ? new PartiallyDownloadedBlock(&m_mempool) : nullptr)});
1264 if (state->vBlocksInFlight.size() == 1) {
1266 state->m_downloading_since = GetTime<std::chrono::microseconds>();
1267 m_peers_downloading_from++;
1269 auto itInFlight = mapBlocksInFlight.insert(std::make_pair(hash, std::make_pair(nodeid, it)));
1271 *pit = &itInFlight->second.second;
1276 void PeerManagerImpl::MaybeSetPeerAsAnnouncingHeaderAndIDs(
NodeId nodeid)
1283 if (m_opts.ignore_incoming_txs)
return;
1285 CNodeState* nodestate = State(nodeid);
1286 if (!nodestate || !nodestate->m_provides_cmpctblocks) {
1291 int num_outbound_hb_peers = 0;
1292 for (std::list<NodeId>::iterator it = lNodesAnnouncingHeaderAndIDs.begin(); it != lNodesAnnouncingHeaderAndIDs.end(); it++) {
1293 if (*it == nodeid) {
1294 lNodesAnnouncingHeaderAndIDs.erase(it);
1295 lNodesAnnouncingHeaderAndIDs.push_back(nodeid);
1298 CNodeState *state = State(*it);
1299 if (state !=
nullptr && !state->m_is_inbound) ++num_outbound_hb_peers;
1301 if (nodestate->m_is_inbound) {
1304 if (lNodesAnnouncingHeaderAndIDs.size() >= 3 && num_outbound_hb_peers == 1) {
1305 CNodeState *remove_node = State(lNodesAnnouncingHeaderAndIDs.front());
1306 if (remove_node !=
nullptr && !remove_node->m_is_inbound) {
1309 std::swap(lNodesAnnouncingHeaderAndIDs.front(), *std::next(lNodesAnnouncingHeaderAndIDs.begin()));
1315 if (lNodesAnnouncingHeaderAndIDs.size() >= 3) {
1318 m_connman.
ForNode(lNodesAnnouncingHeaderAndIDs.front(), [
this](
CNode* pnodeStop){
1319 MakeAndPushMessage(*pnodeStop, NetMsgType::SENDCMPCT, false, CMPCTBLOCKS_VERSION);
1321 pnodeStop->m_bip152_highbandwidth_to = false;
1324 lNodesAnnouncingHeaderAndIDs.pop_front();
1329 lNodesAnnouncingHeaderAndIDs.push_back(pfrom->
GetId());
1334 bool PeerManagerImpl::TipMayBeStale()
1338 if (m_last_tip_update.load() == 0s) {
1339 m_last_tip_update = GetTime<std::chrono::seconds>();
1341 return m_last_tip_update.load() < GetTime<std::chrono::seconds>() - std::chrono::seconds{consensusParams.
nPowTargetSpacing * 3} && mapBlocksInFlight.empty();
1344 int64_t PeerManagerImpl::ApproximateBestBlockDepth()
const
1349 bool PeerManagerImpl::CanDirectFetch()
1356 if (state->pindexBestKnownBlock && pindex == state->pindexBestKnownBlock->GetAncestor(pindex->nHeight))
1358 if (state->pindexBestHeaderSent && pindex == state->pindexBestHeaderSent->GetAncestor(pindex->nHeight))
1363 void PeerManagerImpl::ProcessBlockAvailability(
NodeId nodeid) {
1364 CNodeState *state = State(nodeid);
1365 assert(state !=
nullptr);
1367 if (!state->hashLastUnknownBlock.IsNull()) {
1370 if (state->pindexBestKnownBlock ==
nullptr || pindex->
nChainWork >= state->pindexBestKnownBlock->nChainWork) {
1371 state->pindexBestKnownBlock = pindex;
1373 state->hashLastUnknownBlock.SetNull();
1378 void PeerManagerImpl::UpdateBlockAvailability(
NodeId nodeid,
const uint256 &hash) {
1379 CNodeState *state = State(nodeid);
1380 assert(state !=
nullptr);
1382 ProcessBlockAvailability(nodeid);
1387 if (state->pindexBestKnownBlock ==
nullptr || pindex->
nChainWork >= state->pindexBestKnownBlock->nChainWork) {
1388 state->pindexBestKnownBlock = pindex;
1392 state->hashLastUnknownBlock = hash;
1397 void PeerManagerImpl::FindNextBlocksToDownload(
const Peer& peer,
unsigned int count, std::vector<const CBlockIndex*>& vBlocks,
NodeId& nodeStaller)
1402 vBlocks.reserve(vBlocks.size() +
count);
1403 CNodeState *state = State(peer.m_id);
1404 assert(state !=
nullptr);
1407 ProcessBlockAvailability(peer.m_id);
1409 if (state->pindexBestKnownBlock ==
nullptr || state->pindexBestKnownBlock->nChainWork < m_chainman.
ActiveChain().
Tip()->
nChainWork || state->pindexBestKnownBlock->nChainWork < m_chainman.
MinimumChainWork()) {
1414 if (state->pindexLastCommonBlock ==
nullptr) {
1417 state->pindexLastCommonBlock = m_chainman.
ActiveChain()[std::min(state->pindexBestKnownBlock->nHeight, m_chainman.
ActiveChain().
Height())];
1422 state->pindexLastCommonBlock =
LastCommonAncestor(state->pindexLastCommonBlock, state->pindexBestKnownBlock);
1423 if (state->pindexLastCommonBlock == state->pindexBestKnownBlock)
1426 const CBlockIndex *pindexWalk = state->pindexLastCommonBlock;
1432 FindNextBlocks(vBlocks, peer, state, pindexWalk,
count, nWindowEnd, &m_chainman.
ActiveChain(), &nodeStaller);
1435 void PeerManagerImpl::TryDownloadingHistoricalBlocks(
const Peer& peer,
unsigned int count, std::vector<const CBlockIndex*>& vBlocks,
const CBlockIndex *from_tip,
const CBlockIndex* target_block)
1440 if (vBlocks.size() >=
count) {
1444 vBlocks.reserve(
count);
1445 CNodeState *state =
Assert(State(peer.m_id));
1447 if (state->pindexBestKnownBlock ==
nullptr || state->pindexBestKnownBlock->GetAncestor(target_block->
nHeight) != target_block) {
1464 void PeerManagerImpl::FindNextBlocks(std::vector<const CBlockIndex*>& vBlocks,
const Peer& peer, CNodeState *state,
const CBlockIndex *pindexWalk,
unsigned int count,
int nWindowEnd,
const CChain* activeChain,
NodeId* nodeStaller)
1466 std::vector<const CBlockIndex*> vToFetch;
1467 int nMaxHeight = std::min<int>(state->pindexBestKnownBlock->nHeight, nWindowEnd + 1);
1468 bool is_limited_peer = IsLimitedPeer(peer);
1470 while (pindexWalk->
nHeight < nMaxHeight) {
1474 int nToFetch = std::min(nMaxHeight - pindexWalk->
nHeight, std::max<int>(
count - vBlocks.size(), 128));
1475 vToFetch.resize(nToFetch);
1476 pindexWalk = state->pindexBestKnownBlock->
GetAncestor(pindexWalk->
nHeight + nToFetch);
1477 vToFetch[nToFetch - 1] = pindexWalk;
1478 for (
unsigned int i = nToFetch - 1; i > 0; i--) {
1479 vToFetch[i - 1] = vToFetch[i]->
pprev;
1499 state->pindexLastCommonBlock = pindex;
1506 if (waitingfor == -1) {
1508 waitingfor = mapBlocksInFlight.lower_bound(pindex->
GetBlockHash())->second.first;
1514 if (pindex->
nHeight > nWindowEnd) {
1516 if (vBlocks.size() == 0 && waitingfor != peer.m_id) {
1518 if (nodeStaller) *nodeStaller = waitingfor;
1528 vBlocks.push_back(pindex);
1529 if (vBlocks.size() ==
count) {
1538 void PeerManagerImpl::PushNodeVersion(
CNode& pnode,
const Peer& peer)
1540 uint64_t my_services{peer.m_our_services};
1541 const int64_t nTime{
count_seconds(GetTime<std::chrono::seconds>())};
1543 const int nNodeStartingHeight{m_best_height};
1550 const bool tx_relay{!RejectIncomingTxs(pnode)};
1557 LogPrint(
BCLog::NET,
"send version message: version %d, blocks=%d, them=%s, txrelay=%d, peer=%d\n",
PROTOCOL_VERSION, nNodeStartingHeight, addr_you.
ToStringAddrPort(), tx_relay, nodeid);
1563 void PeerManagerImpl::AddTxAnnouncement(
const CNode&
node,
const GenTxid& gtxid, std::chrono::microseconds current_time)
1571 const CNodeState* state = State(nodeid);
1581 const bool preferred = state->fPreferredDownload;
1587 m_txrequest.ReceivedInv(nodeid, gtxid, preferred, current_time + delay);
1590 void PeerManagerImpl::UpdateLastBlockAnnounceTime(
NodeId node, int64_t time_in_seconds)
1593 CNodeState *state = State(
node);
1594 if (state) state->m_last_block_announcement = time_in_seconds;
1602 m_node_states.emplace_hint(m_node_states.end(), std::piecewise_construct, std::forward_as_tuple(nodeid), std::forward_as_tuple(
node.IsInboundConn()));
1603 assert(m_txrequest.Count(nodeid) == 0);
1610 PeerRef peer = std::make_shared<Peer>(nodeid, our_services);
1613 m_peer_map.emplace_hint(m_peer_map.end(), nodeid, peer);
1615 if (!
node.IsInboundConn()) {
1616 PushNodeVersion(
node, *peer);
1620 void PeerManagerImpl::ReattemptInitialBroadcast(
CScheduler& scheduler)
1624 for (
const auto& txid : unbroadcast_txids) {
1627 if (tx !=
nullptr) {
1628 RelayTransaction(txid, tx->GetWitnessHash());
1636 const std::chrono::milliseconds delta = 10min +
GetRandMillis(5min);
1637 scheduler.
scheduleFromNow([&] { ReattemptInitialBroadcast(scheduler); }, delta);
1640 void PeerManagerImpl::FinalizeNode(
const CNode&
node)
1652 PeerRef peer = RemovePeer(nodeid);
1654 misbehavior =
WITH_LOCK(peer->m_misbehavior_mutex,
return peer->m_misbehavior_score);
1655 m_wtxid_relay_peers -= peer->m_wtxid_relay;
1656 assert(m_wtxid_relay_peers >= 0);
1658 CNodeState *state = State(nodeid);
1659 assert(state !=
nullptr);
1661 if (state->fSyncStarted)
1664 for (
const QueuedBlock& entry : state->vBlocksInFlight) {
1665 auto range = mapBlocksInFlight.equal_range(entry.pindex->GetBlockHash());
1666 while (range.first != range.second) {
1667 auto [node_id, list_it] = range.first->second;
1668 if (node_id != nodeid) {
1671 range.first = mapBlocksInFlight.erase(range.first);
1676 m_txrequest.DisconnectedPeer(nodeid);
1677 if (m_txreconciliation) m_txreconciliation->ForgetPeer(nodeid);
1678 m_num_preferred_download_peers -= state->fPreferredDownload;
1679 m_peers_downloading_from -= (!state->vBlocksInFlight.empty());
1680 assert(m_peers_downloading_from >= 0);
1681 m_outbound_peers_with_protect_from_disconnect -= state->m_chain_sync.m_protect;
1682 assert(m_outbound_peers_with_protect_from_disconnect >= 0);
1684 m_node_states.erase(nodeid);
1686 if (m_node_states.empty()) {
1688 assert(mapBlocksInFlight.empty());
1689 assert(m_num_preferred_download_peers == 0);
1690 assert(m_peers_downloading_from == 0);
1691 assert(m_outbound_peers_with_protect_from_disconnect == 0);
1692 assert(m_wtxid_relay_peers == 0);
1693 assert(m_txrequest.Size() == 0);
1697 if (
node.fSuccessfullyConnected && misbehavior == 0 &&
1698 !
node.IsBlockOnlyConn() && !
node.IsInboundConn()) {
1705 LOCK(m_headers_presync_mutex);
1706 m_headers_presync_stats.erase(nodeid);
1711 bool PeerManagerImpl::HasAllDesirableServiceFlags(
ServiceFlags services)
const
1714 return !(GetDesirableServiceFlags(services) & (~services));
1728 PeerRef PeerManagerImpl::GetPeerRef(
NodeId id)
const
1731 auto it = m_peer_map.find(
id);
1732 return it != m_peer_map.end() ? it->second :
nullptr;
1735 PeerRef PeerManagerImpl::RemovePeer(
NodeId id)
1739 auto it = m_peer_map.find(
id);
1740 if (it != m_peer_map.end()) {
1741 ret = std::move(it->second);
1742 m_peer_map.erase(it);
1751 const CNodeState* state = State(nodeid);
1752 if (state ==
nullptr)
1754 stats.
nSyncHeight = state->pindexBestKnownBlock ? state->pindexBestKnownBlock->nHeight : -1;
1755 stats.
nCommonHeight = state->pindexLastCommonBlock ? state->pindexLastCommonBlock->nHeight : -1;
1756 for (
const QueuedBlock& queue : state->vBlocksInFlight) {
1762 PeerRef peer = GetPeerRef(nodeid);
1763 if (peer ==
nullptr)
return false;
1772 auto ping_wait{0us};
1773 if ((0 != peer->m_ping_nonce_sent) && (0 != peer->m_ping_start.load().count())) {
1774 ping_wait = GetTime<std::chrono::microseconds>() - peer->m_ping_start.load();
1777 if (
auto tx_relay = peer->GetTxRelay(); tx_relay !=
nullptr) {
1790 LOCK(peer->m_headers_sync_mutex);
1791 if (peer->m_headers_sync) {
1799 void PeerManagerImpl::AddToCompactExtraTransactions(
const CTransactionRef& tx)
1801 if (m_opts.max_extra_txs <= 0)
1803 if (!vExtraTxnForCompact.size())
1804 vExtraTxnForCompact.resize(m_opts.max_extra_txs);
1805 vExtraTxnForCompact[vExtraTxnForCompactIt] = tx;
1806 vExtraTxnForCompactIt = (vExtraTxnForCompactIt + 1) % m_opts.max_extra_txs;
1809 void PeerManagerImpl::Misbehaving(Peer& peer,
int howmuch,
const std::string& message)
1813 LOCK(peer.m_misbehavior_mutex);
1814 const int score_before{peer.m_misbehavior_score};
1815 peer.m_misbehavior_score += howmuch;
1816 const int score_now{peer.m_misbehavior_score};
1818 const std::string message_prefixed = message.empty() ?
"" : (
": " + message);
1819 std::string warning;
1822 warning =
" DISCOURAGE THRESHOLD EXCEEDED";
1823 peer.m_should_discourage =
true;
1827 peer.m_id, score_before, score_now, warning, message_prefixed);
1831 bool via_compact_block,
const std::string& message)
1833 PeerRef peer{GetPeerRef(nodeid)};
1844 if (!via_compact_block) {
1845 if (peer) Misbehaving(*peer, 100, message);
1852 CNodeState *node_state = State(nodeid);
1853 if (node_state ==
nullptr) {
1859 if (!via_compact_block && !node_state->m_is_inbound) {
1860 if (peer) Misbehaving(*peer, 100, message);
1868 if (peer) Misbehaving(*peer, 100, message);
1873 if (peer) Misbehaving(*peer, 10, message);
1879 if (message !=
"") {
1887 PeerRef peer{GetPeerRef(nodeid)};
1893 if (peer) Misbehaving(*peer, 100,
"");
1913 bool PeerManagerImpl::BlockRequestAllowed(
const CBlockIndex* pindex)
1922 std::optional<std::string> PeerManagerImpl::FetchBlock(
NodeId peer_id,
const CBlockIndex& block_index)
1927 PeerRef peer = GetPeerRef(peer_id);
1928 if (peer ==
nullptr)
return "Peer does not exist";
1931 if (!CanServeWitnesses(*peer))
return "Pre-SegWit peer";
1936 RemoveBlockRequest(block_index.
GetBlockHash(), std::nullopt);
1939 if (!BlockRequested(peer_id, block_index))
return "Already requested from this peer";
1951 if (!success)
return "Peer not fully connected";
1955 return std::nullopt;
1962 return std::make_unique<PeerManagerImpl>(connman, addrman, banman, chainman, pool, opts);
1968 : m_rng{opts.deterministic_rng},
1970 m_chainparams(chainman.GetParams()),
1974 m_chainman(chainman),
1980 if (opts.reconcile_txs) {
1985 void PeerManagerImpl::StartScheduledTasks(
CScheduler& scheduler)
1995 const std::chrono::milliseconds delta = 10min +
GetRandMillis(5min);
1996 scheduler.
scheduleFromNow([&] { ReattemptInitialBroadcast(scheduler); }, delta);
2005 void PeerManagerImpl::BlockConnected(
2007 const std::shared_ptr<const CBlock>& pblock,
2012 m_last_tip_update = GetTime<std::chrono::seconds>();
2015 auto stalling_timeout = m_block_stalling_timeout.load();
2019 if (m_block_stalling_timeout.compare_exchange_strong(stalling_timeout, new_timeout)) {
2032 LOCK(m_recent_confirmed_transactions_mutex);
2033 for (
const auto& ptx : pblock->vtx) {
2034 m_recent_confirmed_transactions.insert(ptx->GetHash().ToUint256());
2035 if (ptx->HasWitness()) {
2036 m_recent_confirmed_transactions.insert(ptx->GetWitnessHash().ToUint256());
2042 for (
const auto& ptx : pblock->vtx) {
2043 m_txrequest.ForgetTxHash(ptx->GetHash());
2044 m_txrequest.ForgetTxHash(ptx->GetWitnessHash());
2049 void PeerManagerImpl::BlockDisconnected(
const std::shared_ptr<const CBlock> &block,
const CBlockIndex* pindex)
2059 LOCK(m_recent_confirmed_transactions_mutex);
2060 m_recent_confirmed_transactions.reset();
2067 void PeerManagerImpl::NewPoWValidBlock(
const CBlockIndex *pindex,
const std::shared_ptr<const CBlock>& pblock)
2069 auto pcmpctblock = std::make_shared<const CBlockHeaderAndShortTxIDs>(*pblock);
2073 if (pindex->
nHeight <= m_highest_fast_announce)
2075 m_highest_fast_announce = pindex->
nHeight;
2079 uint256 hashBlock(pblock->GetHash());
2080 const std::shared_future<CSerializedNetMsg> lazy_ser{
2084 auto most_recent_block_txs = std::make_unique<std::map<uint256, CTransactionRef>>();
2085 for (
const auto& tx : pblock->vtx) {
2086 most_recent_block_txs->emplace(tx->GetHash(), tx);
2087 most_recent_block_txs->emplace(tx->GetWitnessHash(), tx);
2090 LOCK(m_most_recent_block_mutex);
2091 m_most_recent_block_hash = hashBlock;
2092 m_most_recent_block = pblock;
2093 m_most_recent_compact_block = pcmpctblock;
2094 m_most_recent_block_txs = std::move(most_recent_block_txs);
2102 ProcessBlockAvailability(pnode->
GetId());
2103 CNodeState &state = *State(pnode->
GetId());
2106 if (state.m_requested_hb_cmpctblocks && !PeerHasHeader(&state, pindex) && PeerHasHeader(&state, pindex->
pprev)) {
2108 LogPrint(
BCLog::NET,
"%s sending header-and-ids %s to peer=%d\n",
"PeerManager::NewPoWValidBlock",
2109 hashBlock.ToString(), pnode->
GetId());
2112 PushMessage(*pnode, ser_cmpctblock.Copy());
2113 state.pindexBestHeaderSent = pindex;
2122 void PeerManagerImpl::UpdatedBlockTip(
const CBlockIndex *pindexNew,
const CBlockIndex *pindexFork,
bool fInitialDownload)
2124 SetBestBlock(pindexNew->
nHeight, std::chrono::seconds{pindexNew->GetBlockTime()});
2127 if (fInitialDownload)
return;
2130 std::vector<uint256> vHashes;
2132 while (pindexToAnnounce != pindexFork) {
2134 pindexToAnnounce = pindexToAnnounce->
pprev;
2144 for (
auto& it : m_peer_map) {
2145 Peer& peer = *it.second;
2146 LOCK(peer.m_block_inv_mutex);
2148 peer.m_blocks_for_headers_relay.push_back(hash);
2165 std::map<uint256, std::pair<NodeId, bool>>::iterator it = mapBlockSource.find(hash);
2170 it != mapBlockSource.end() &&
2171 State(it->second.first)) {
2172 MaybePunishNodeForBlock( it->second.first, state, !it->second.second);
2182 mapBlocksInFlight.count(hash) == mapBlocksInFlight.size()) {
2183 if (it != mapBlockSource.end()) {
2184 MaybeSetPeerAsAnnouncingHeaderAndIDs(it->second.first);
2187 if (it != mapBlockSource.end())
2188 mapBlockSource.erase(it);
2197 bool PeerManagerImpl::AlreadyHaveTx(
const GenTxid& gtxid)
2205 m_recent_rejects.reset();
2210 if (m_orphanage.
HaveTx(gtxid))
return true;
2213 LOCK(m_recent_confirmed_transactions_mutex);
2214 if (m_recent_confirmed_transactions.contains(hash))
return true;
2217 return m_recent_rejects.contains(hash) || m_mempool.
exists(gtxid);
2220 bool PeerManagerImpl::AlreadyHaveBlock(
const uint256& block_hash)
2225 void PeerManagerImpl::SendPings()
2228 for(
auto& it : m_peer_map) it.second->m_ping_queued =
true;
2231 void PeerManagerImpl::RelayTransaction(
const uint256& txid,
const uint256& wtxid)
2234 for(
auto& it : m_peer_map) {
2235 Peer& peer = *it.second;
2236 auto tx_relay = peer.GetTxRelay();
2237 if (!tx_relay)
continue;
2239 LOCK(tx_relay->m_tx_inventory_mutex);
2245 if (tx_relay->m_next_inv_send_time == 0s)
continue;
2247 const uint256& hash{peer.m_wtxid_relay ? wtxid : txid};
2248 if (!tx_relay->m_tx_inventory_known_filter.contains(hash)) {
2249 tx_relay->m_tx_inventory_to_send.insert(hash);
2254 void PeerManagerImpl::RelayAddress(
NodeId originator,
2270 const auto current_time{GetTime<std::chrono::seconds>()};
2278 unsigned int nRelayNodes = (fReachable || (hasher.Finalize() & 1)) ? 2 : 1;
2280 std::array<std::pair<uint64_t, Peer*>, 2> best{{{0,
nullptr}, {0,
nullptr}}};
2281 assert(nRelayNodes <= best.size());
2285 for (
auto& [
id, peer] : m_peer_map) {
2286 if (peer->m_addr_relay_enabled &&
id != originator && IsAddrCompatible(*peer, addr)) {
2288 for (
unsigned int i = 0; i < nRelayNodes; i++) {
2289 if (hashKey > best[i].first) {
2290 std::copy(best.begin() + i, best.begin() + nRelayNodes - 1, best.begin() + i + 1);
2291 best[i] = std::make_pair(hashKey, peer.get());
2298 for (
unsigned int i = 0; i < nRelayNodes && best[i].first != 0; i++) {
2299 PushAddress(*best[i].second, addr);
2303 void PeerManagerImpl::ProcessGetBlockData(
CNode& pfrom, Peer& peer,
const CInv& inv)
2305 std::shared_ptr<const CBlock> a_recent_block;
2306 std::shared_ptr<const CBlockHeaderAndShortTxIDs> a_recent_compact_block;
2308 LOCK(m_most_recent_block_mutex);
2309 a_recent_block = m_most_recent_block;
2310 a_recent_compact_block = m_most_recent_compact_block;
2313 bool need_activate_chain =
false;
2325 need_activate_chain =
true;
2329 if (need_activate_chain) {
2331 if (!m_chainman.
ActiveChainstate().ActivateBestChain(state, a_recent_block)) {
2341 if (!BlockRequestAllowed(pindex)) {
2342 LogPrint(
BCLog::NET,
"%s: ignoring request from peer=%i for old block that isn't in the main chain\n", __func__, pfrom.
GetId());
2358 LogPrint(
BCLog::NET,
"Ignore block request below NODE_NETWORK_LIMITED threshold, disconnect peer=%d\n", pfrom.
GetId());
2368 std::shared_ptr<const CBlock> pblock;
2369 if (a_recent_block && a_recent_block->GetHash() == pindex->
GetBlockHash()) {
2370 pblock = a_recent_block;
2374 std::vector<uint8_t> block_data;
2376 assert(!
"cannot load block from disk");
2382 std::shared_ptr<CBlock> pblockRead = std::make_shared<CBlock>();
2384 assert(!
"cannot load block from disk");
2386 pblock = pblockRead;
2394 bool sendMerkleBlock =
false;
2396 if (
auto tx_relay = peer.GetTxRelay(); tx_relay !=
nullptr) {
2397 LOCK(tx_relay->m_bloom_filter_mutex);
2398 if (tx_relay->m_bloom_filter) {
2399 sendMerkleBlock =
true;
2400 merkleBlock =
CMerkleBlock(*pblock, *tx_relay->m_bloom_filter);
2403 if (sendMerkleBlock) {
2411 typedef std::pair<unsigned int, uint256> PairType;
2423 if (a_recent_compact_block && a_recent_compact_block->header.GetHash() == pindex->
GetBlockHash()) {
2436 LOCK(peer.m_block_inv_mutex);
2438 if (inv.
hash == peer.m_continuation_block) {
2442 std::vector<CInv> vInv;
2445 peer.m_continuation_block.SetNull();
2453 auto txinfo = m_mempool.
info_for_relay(gtxid, tx_relay.m_last_inv_sequence);
2455 return std::move(txinfo.tx);
2460 LOCK(m_most_recent_block_mutex);
2461 if (m_most_recent_block_txs !=
nullptr) {
2462 auto it = m_most_recent_block_txs->find(gtxid.
GetHash());
2463 if (it != m_most_recent_block_txs->end())
return it->second;
2470 void PeerManagerImpl::ProcessGetData(
CNode& pfrom, Peer& peer,
const std::atomic<bool>& interruptMsgProc)
2474 auto tx_relay = peer.GetTxRelay();
2476 std::deque<CInv>::iterator it = peer.m_getdata_requests.begin();
2477 std::vector<CInv> vNotFound;
2482 while (it != peer.m_getdata_requests.end() && it->IsGenTxMsg()) {
2483 if (interruptMsgProc)
return;
2488 const CInv &inv = *it++;
2490 if (tx_relay ==
nullptr) {
2500 MakeAndPushMessage(pfrom,
NetMsgType::TX, maybe_with_witness(*tx));
2503 vNotFound.push_back(inv);
2509 if (it != peer.m_getdata_requests.end() && !pfrom.
fPauseSend) {
2510 const CInv &inv = *it++;
2512 ProcessGetBlockData(pfrom, peer, inv);
2518 peer.m_getdata_requests.erase(peer.m_getdata_requests.begin(), it);
2520 if (!vNotFound.empty()) {
2539 uint32_t PeerManagerImpl::GetFetchFlags(
const Peer& peer)
const
2541 uint32_t nFetchFlags = 0;
2542 if (CanServeWitnesses(peer)) {
2551 for (
size_t i = 0; i < req.
indexes.size(); i++) {
2553 Misbehaving(peer, 100,
"getblocktxn with out-of-bounds tx indices");
2562 bool PeerManagerImpl::CheckHeadersPoW(
const std::vector<CBlockHeader>& headers,
const Consensus::Params& consensusParams, Peer& peer)
2566 Misbehaving(peer, 100,
"header with invalid proof of work");
2571 if (!CheckHeadersAreContinuous(headers)) {
2572 Misbehaving(peer, 20,
"non-continuous headers sequence");
2603 void PeerManagerImpl::HandleFewUnconnectingHeaders(
CNode& pfrom, Peer& peer,
2604 const std::vector<CBlockHeader>& headers)
2606 peer.m_num_unconnecting_headers_msgs++;
2609 if (MaybeSendGetHeaders(pfrom,
GetLocator(best_header), peer)) {
2610 LogPrint(
BCLog::NET,
"received header %s: missing prev block %s, sending getheaders (%d) to end (peer=%d, m_num_unconnecting_headers_msgs=%d)\n",
2612 headers[0].hashPrevBlock.ToString(),
2613 best_header->nHeight,
2614 pfrom.
GetId(), peer.m_num_unconnecting_headers_msgs);
2625 Misbehaving(peer, 20,
strprintf(
"%d non-connecting headers", peer.m_num_unconnecting_headers_msgs));
2629 bool PeerManagerImpl::CheckHeadersAreContinuous(
const std::vector<CBlockHeader>& headers)
const
2633 if (!hashLastBlock.
IsNull() && header.hashPrevBlock != hashLastBlock) {
2636 hashLastBlock = header.GetHash();
2641 bool PeerManagerImpl::IsContinuationOfLowWorkHeadersSync(Peer& peer,
CNode& pfrom, std::vector<CBlockHeader>& headers)
2643 if (peer.m_headers_sync) {
2644 auto result = peer.m_headers_sync->ProcessNextHeaders(headers, headers.size() ==
MAX_HEADERS_RESULTS);
2645 if (result.request_more) {
2646 auto locator = peer.m_headers_sync->NextHeadersRequestLocator();
2648 Assume(!locator.vHave.empty());
2649 if (!locator.vHave.empty()) {
2656 bool sent_getheaders = MaybeSendGetHeaders(pfrom, locator, peer);
2657 if (sent_getheaders) {
2659 locator.vHave.front().ToString(), pfrom.
GetId());
2661 LogPrint(
BCLog::NET,
"error sending next getheaders (from %s) to continue sync with peer=%d\n",
2662 locator.vHave.front().ToString(), pfrom.
GetId());
2668 peer.m_headers_sync.reset(
nullptr);
2673 LOCK(m_headers_presync_mutex);
2674 m_headers_presync_stats.erase(pfrom.
GetId());
2677 HeadersPresyncStats stats;
2678 stats.first = peer.m_headers_sync->GetPresyncWork();
2680 stats.second = {peer.m_headers_sync->GetPresyncHeight(),
2681 peer.m_headers_sync->GetPresyncTime()};
2685 LOCK(m_headers_presync_mutex);
2686 m_headers_presync_stats[pfrom.
GetId()] = stats;
2687 auto best_it = m_headers_presync_stats.find(m_headers_presync_bestpeer);
2688 bool best_updated =
false;
2689 if (best_it == m_headers_presync_stats.end()) {
2693 const HeadersPresyncStats* stat_best{
nullptr};
2694 for (
const auto& [peer, stat] : m_headers_presync_stats) {
2695 if (!stat_best || stat > *stat_best) {
2700 m_headers_presync_bestpeer = peer_best;
2701 best_updated = (peer_best == pfrom.
GetId());
2702 }
else if (best_it->first == pfrom.
GetId() || stats > best_it->second) {
2704 m_headers_presync_bestpeer = pfrom.
GetId();
2705 best_updated =
true;
2707 if (best_updated && stats.second.has_value()) {
2709 m_headers_presync_should_signal =
true;
2713 if (result.success) {
2716 headers.swap(result.pow_validated_headers);
2719 return result.success;
2727 bool PeerManagerImpl::TryLowWorkHeadersSync(Peer& peer,
CNode& pfrom,
const CBlockIndex* chain_start_header, std::vector<CBlockHeader>& headers)
2734 arith_uint256 minimum_chain_work = GetAntiDoSWorkThreshold();
2738 if (total_work < minimum_chain_work) {
2752 LOCK(peer.m_headers_sync_mutex);
2754 chain_start_header, minimum_chain_work));
2759 (void)IsContinuationOfLowWorkHeadersSync(peer, pfrom, headers);
2773 bool PeerManagerImpl::IsAncestorOfBestHeaderOrTip(
const CBlockIndex* header)
2775 if (header ==
nullptr) {
2777 }
else if (m_chainman.m_best_header !=
nullptr && header == m_chainman.m_best_header->GetAncestor(header->
nHeight)) {
2785 bool PeerManagerImpl::MaybeSendGetHeaders(
CNode& pfrom,
const CBlockLocator& locator, Peer& peer)
2793 peer.m_last_getheaders_timestamp = current_time;
2804 void PeerManagerImpl::HeadersDirectFetchBlocks(
CNode& pfrom,
const Peer& peer,
const CBlockIndex& last_header)
2807 CNodeState *nodestate = State(pfrom.
GetId());
2810 std::vector<const CBlockIndex*> vToFetch;
2818 vToFetch.push_back(pindexWalk);
2820 pindexWalk = pindexWalk->
pprev;
2831 std::vector<CInv> vGetData;
2838 uint32_t nFetchFlags = GetFetchFlags(peer);
2840 BlockRequested(pfrom.
GetId(), *pindex);
2844 if (vGetData.size() > 1) {
2849 if (vGetData.size() > 0) {
2850 if (!m_opts.ignore_incoming_txs &&
2851 nodestate->m_provides_cmpctblocks &&
2852 vGetData.size() == 1 &&
2853 mapBlocksInFlight.size() == 1 &&
2869 void PeerManagerImpl::UpdatePeerStateForReceivedHeaders(
CNode& pfrom, Peer& peer,
2870 const CBlockIndex& last_header,
bool received_new_header,
bool may_have_more_headers)
2872 if (peer.m_num_unconnecting_headers_msgs > 0) {
2873 LogPrint(
BCLog::NET,
"peer=%d: resetting m_num_unconnecting_headers_msgs (%d -> 0)\n", pfrom.
GetId(), peer.m_num_unconnecting_headers_msgs);
2875 peer.m_num_unconnecting_headers_msgs = 0;
2878 CNodeState *nodestate = State(pfrom.
GetId());
2887 nodestate->m_last_block_announcement =
GetTime();
2895 if (nodestate->pindexBestKnownBlock && nodestate->pindexBestKnownBlock->nChainWork < m_chainman.
MinimumChainWork()) {
2905 LogPrintf(
"Disconnecting outbound peer %d -- headers chain has insufficient work\n", pfrom.
GetId());
2917 if (m_outbound_peers_with_protect_from_disconnect < MAX_OUTBOUND_PEERS_TO_PROTECT_FROM_DISCONNECT && nodestate->pindexBestKnownBlock->nChainWork >= m_chainman.
ActiveChain().
Tip()->
nChainWork && !nodestate->m_chain_sync.m_protect) {
2919 nodestate->m_chain_sync.m_protect =
true;
2920 ++m_outbound_peers_with_protect_from_disconnect;
2925 void PeerManagerImpl::ProcessHeadersMessage(
CNode& pfrom, Peer& peer,
2926 std::vector<CBlockHeader>&& headers,
2927 bool via_compact_block)
2929 size_t nCount = headers.size();
2936 LOCK(peer.m_headers_sync_mutex);
2937 if (peer.m_headers_sync) {
2938 peer.m_headers_sync.reset(
nullptr);
2939 LOCK(m_headers_presync_mutex);
2940 m_headers_presync_stats.erase(pfrom.
GetId());
2949 if (!CheckHeadersPoW(headers, m_chainparams.
GetConsensus(), peer)) {
2964 bool already_validated_work =
false;
2967 bool have_headers_sync =
false;
2969 LOCK(peer.m_headers_sync_mutex);
2971 already_validated_work = IsContinuationOfLowWorkHeadersSync(peer, pfrom, headers);
2983 if (headers.empty()) {
2987 have_headers_sync = !!peer.m_headers_sync;
2992 bool headers_connect_blockindex{chain_start_header !=
nullptr};
2994 if (!headers_connect_blockindex) {
2999 HandleFewUnconnectingHeaders(pfrom, peer, headers);
3001 Misbehaving(peer, 10,
"invalid header received");
3014 if (IsAncestorOfBestHeaderOrTip(last_received_header)) {
3015 already_validated_work =
true;
3023 already_validated_work =
true;
3029 if (!already_validated_work && TryLowWorkHeadersSync(peer, pfrom,
3030 chain_start_header, headers)) {
3042 bool received_new_header{last_received_header ==
nullptr};
3048 MaybePunishNodeForBlock(pfrom.
GetId(), state, via_compact_block,
"invalid header received");
3057 if (MaybeSendGetHeaders(pfrom,
GetLocator(pindexLast), peer)) {
3059 pindexLast->
nHeight, pfrom.
GetId(), peer.m_starting_height);
3063 UpdatePeerStateForReceivedHeaders(pfrom, peer, *pindexLast, received_new_header, nCount ==
MAX_HEADERS_RESULTS);
3066 HeadersDirectFetchBlocks(pfrom, peer, *pindexLast);
3072 bool maybe_add_extra_compact_tx)
3079 ptx->GetHash().ToString(),
3080 ptx->GetWitnessHash().ToString(),
3100 m_recent_rejects.insert(ptx->GetWitnessHash().ToUint256());
3101 m_txrequest.ForgetTxHash(ptx->GetWitnessHash());
3111 m_recent_rejects.insert(ptx->GetHash().ToUint256());
3112 m_txrequest.ForgetTxHash(ptx->GetHash());
3115 AddToCompactExtraTransactions(ptx);
3119 MaybePunishNodeForTx(nodeid, state);
3124 LogDebug(
BCLog::TXPACKAGES,
" removed orphan tx %s (wtxid=%s)\n", ptx->GetHash().ToString(), ptx->GetWitnessHash().ToString());
3128 void PeerManagerImpl::ProcessValidTx(
NodeId nodeid,
const CTransactionRef& tx,
const std::list<CTransactionRef>& replaced_transactions)
3136 m_txrequest.ForgetTxHash(tx->GetHash());
3137 m_txrequest.ForgetTxHash(tx->GetWitnessHash());
3141 m_orphanage.
EraseTx(tx->GetHash());
3145 tx->GetHash().ToString(),
3146 tx->GetWitnessHash().ToString(),
3149 RelayTransaction(tx->GetHash(), tx->GetWitnessHash());
3152 AddToCompactExtraTransactions(removedTx);
3156 bool PeerManagerImpl::ProcessOrphanTx(Peer& peer)
3166 const Txid& orphanHash = porphanTx->GetHash();
3167 const Wtxid& orphan_wtxid = porphanTx->GetWitnessHash();
3172 std::list<CTransactionRef> empty_replacement_list;
3186 ProcessInvalidTx(peer.m_id, porphanTx, state,
false);
3195 bool PeerManagerImpl::PrepareBlockFilterRequest(
CNode&
node, Peer& peer,
3197 const uint256& stop_hash, uint32_t max_height_diff,
3201 const bool supported_filter_type =
3204 if (!supported_filter_type) {
3206 node.GetId(),
static_cast<uint8_t
>(filter_type));
3207 node.fDisconnect =
true;
3216 if (!stop_index || !BlockRequestAllowed(stop_index)) {
3219 node.fDisconnect =
true;
3224 uint32_t stop_height = stop_index->
nHeight;
3225 if (start_height > stop_height) {
3227 "start height %d and stop height %d\n",
3228 node.GetId(), start_height, stop_height);
3229 node.fDisconnect =
true;
3232 if (stop_height - start_height >= max_height_diff) {
3234 node.GetId(), stop_height - start_height + 1, max_height_diff);
3235 node.fDisconnect =
true;
3240 if (!filter_index) {
3250 uint8_t filter_type_ser;
3251 uint32_t start_height;
3254 vRecv >> filter_type_ser >> start_height >> stop_hash;
3260 if (!PrepareBlockFilterRequest(
node, peer, filter_type, start_height, stop_hash,
3265 std::vector<BlockFilter> filters;
3267 LogPrint(
BCLog::NET,
"Failed to find block filter in index: filter_type=%s, start_height=%d, stop_hash=%s\n",
3272 for (
const auto& filter : filters) {
3279 uint8_t filter_type_ser;
3280 uint32_t start_height;
3283 vRecv >> filter_type_ser >> start_height >> stop_hash;
3289 if (!PrepareBlockFilterRequest(
node, peer, filter_type, start_height, stop_hash,
3295 if (start_height > 0) {
3297 stop_index->
GetAncestor(
static_cast<int>(start_height - 1));
3299 LogPrint(
BCLog::NET,
"Failed to find block filter header in index: filter_type=%s, block_hash=%s\n",
3305 std::vector<uint256> filter_hashes;
3307 LogPrint(
BCLog::NET,
"Failed to find block filter hashes in index: filter_type=%s, start_height=%d, stop_hash=%s\n",
3321 uint8_t filter_type_ser;
3324 vRecv >> filter_type_ser >> stop_hash;
3330 if (!PrepareBlockFilterRequest(
node, peer, filter_type, 0, stop_hash,
3331 std::numeric_limits<uint32_t>::max(),
3332 stop_index, filter_index)) {
3340 for (
int i = headers.size() - 1; i >= 0; i--) {
3345 LogPrint(
BCLog::NET,
"Failed to find block filter header in index: filter_type=%s, block_hash=%s\n",
3357 void PeerManagerImpl::ProcessBlock(
CNode&
node,
const std::shared_ptr<const CBlock>& block,
bool force_processing,
bool min_pow_checked)
3359 bool new_block{
false};
3360 m_chainman.
ProcessNewBlock(block, force_processing, min_pow_checked, &new_block);
3362 node.m_last_block_time = GetTime<std::chrono::seconds>();
3367 RemoveBlockRequest(block->GetHash(), std::nullopt);
3370 mapBlockSource.erase(block->GetHash());
3374 void PeerManagerImpl::ProcessCompactBlockTxns(
CNode& pfrom, Peer& peer,
const BlockTransactions& block_transactions)
3376 std::shared_ptr<CBlock> pblock = std::make_shared<CBlock>();
3377 bool fBlockRead{
false};
3381 auto range_flight = mapBlocksInFlight.equal_range(block_transactions.
blockhash);
3382 size_t already_in_flight = std::distance(range_flight.first, range_flight.second);
3383 bool requested_block_from_this_peer{
false};
3386 bool first_in_flight = already_in_flight == 0 || (range_flight.first->second.first == pfrom.
GetId());
3388 while (range_flight.first != range_flight.second) {
3389 auto [node_id, block_it] = range_flight.first->second;
3390 if (node_id == pfrom.
GetId() && block_it->partialBlock) {
3391 requested_block_from_this_peer =
true;
3394 range_flight.first++;
3397 if (!requested_block_from_this_peer) {
3406 Misbehaving(peer, 100,
"invalid compact block/non-matching block transactions");
3409 if (first_in_flight) {
3411 std::vector<CInv> invs;
3416 LogPrint(
BCLog::NET,
"Peer %d sent us a compact block but it failed to reconstruct, waiting on first download to complete\n", pfrom.
GetId());
3445 mapBlockSource.emplace(block_transactions.
blockhash, std::make_pair(pfrom.
GetId(),
false));
3455 ProcessBlock(pfrom, pblock,
true,
true);
3460 void PeerManagerImpl::ProcessMessage(
CNode& pfrom,
const std::string& msg_type,
DataStream& vRecv,
3461 const std::chrono::microseconds time_received,
3462 const std::atomic<bool>& interruptMsgProc)
3468 PeerRef peer = GetPeerRef(pfrom.
GetId());
3469 if (peer ==
nullptr)
return;
3479 uint64_t nNonce = 1;
3482 std::string cleanSubVer;
3483 int starting_height = -1;
3486 vRecv >> nVersion >> Using<CustomUintFormatter<8>>(nServices) >> nTime;
3501 LogPrint(
BCLog::NET,
"peer=%d does not offer the expected services (%08x offered, %08x expected); disconnecting\n", pfrom.
GetId(), nServices, GetDesirableServiceFlags(nServices));
3513 if (!vRecv.
empty()) {
3521 if (!vRecv.
empty()) {
3522 std::string strSubVer;
3526 if (!vRecv.
empty()) {
3527 vRecv >> starting_height;
3547 PushNodeVersion(pfrom, *peer);
3560 if (greatest_common_version >= 70016) {
3569 peer->m_their_services = nServices;
3573 pfrom.cleanSubVer = cleanSubVer;
3575 peer->m_starting_height = starting_height;
3585 (fRelay || (peer->m_our_services &
NODE_BLOOM))) {
3586 auto*
const tx_relay = peer->SetTxRelay();
3588 LOCK(tx_relay->m_bloom_filter_mutex);
3589 tx_relay->m_relay_txs = fRelay;
3601 const auto* tx_relay = peer->GetTxRelay();
3602 if (tx_relay &&
WITH_LOCK(tx_relay->m_bloom_filter_mutex,
return tx_relay->m_relay_txs) &&
3604 const uint64_t recon_salt = m_txreconciliation->PreRegisterPeer(pfrom.
GetId());
3615 CNodeState* state = State(pfrom.
GetId());
3617 m_num_preferred_download_peers += state->fPreferredDownload;
3623 bool send_getaddr{
false};
3625 send_getaddr = SetupAddressRelay(pfrom, *peer);
3635 peer->m_getaddr_sent =
true;
3659 std::string remoteAddr;
3664 LogPrint(
BCLog::NET,
"receive version message: %s: version %d, blocks=%d, us=%s, txrelay=%d, peer=%d%s%s\n",
3667 remoteAddr, (mapped_as ?
strprintf(
", mapped_as=%d", mapped_as) :
""));
3669 int64_t nTimeOffset = nTime -
GetTime();
3678 if (greatest_common_version <= 70012) {
3679 const auto finalAlert{
ParseHex(
"60010000000000000000000000ffffff7f00000000ffffff7ffeffff7f01ffffff7f00000000ffffff7f00ffffff7f002f555247454e543a20416c657274206b657920636f6d70726f6d697365642c2075706772616465207265717569726564004630440220653febd6410f470f6bae11cad19c48413becb1ac2c17f908fd0fd53bdc3abd5202206d0e9c96fe88d4a0f01ed9dedae2b6f9e00da94cad0fecaae66ecf689bf71b50")};
3680 MakeAndPushMessage(pfrom,
"alert",
Span{finalAlert});
3707 LogPrintf(
"New %s %s peer connected: version: %d, blocks=%d, peer=%d%s%s\n",
3710 pfrom.
nVersion.load(), peer->m_starting_height,
3712 (mapped_as ?
strprintf(
", mapped_as=%d", mapped_as) :
""));
3724 if (m_txreconciliation) {
3725 if (!peer->m_wtxid_relay || !m_txreconciliation->IsPeerRegistered(pfrom.
GetId())) {
3729 m_txreconciliation->ForgetPeer(pfrom.
GetId());
3733 if (
auto tx_relay = peer->GetTxRelay()) {
3742 tx_relay->m_tx_inventory_mutex,
3743 return tx_relay->m_tx_inventory_to_send.empty() &&
3744 tx_relay->m_next_inv_send_time == 0s));
3752 peer->m_prefers_headers =
true;
3757 bool sendcmpct_hb{
false};
3758 uint64_t sendcmpct_version{0};
3759 vRecv >> sendcmpct_hb >> sendcmpct_version;
3765 CNodeState* nodestate = State(pfrom.
GetId());
3766 nodestate->m_provides_cmpctblocks =
true;
3767 nodestate->m_requested_hb_cmpctblocks = sendcmpct_hb;
3784 if (!peer->m_wtxid_relay) {
3785 peer->m_wtxid_relay =
true;
3786 m_wtxid_relay_peers++;
3805 peer->m_wants_addrv2 =
true;
3813 if (!m_txreconciliation) {
3825 if (RejectIncomingTxs(pfrom)) {
3834 const auto* tx_relay = peer->GetTxRelay();
3835 if (!tx_relay || !
WITH_LOCK(tx_relay->m_bloom_filter_mutex,
return tx_relay->m_relay_txs)) {
3841 uint32_t peer_txreconcl_version;
3842 uint64_t remote_salt;
3843 vRecv >> peer_txreconcl_version >> remote_salt;
3846 peer_txreconcl_version, remote_salt);
3871 const auto ser_params{
3879 std::vector<CAddress> vAddr;
3881 vRecv >> ser_params(vAddr);
3883 if (!SetupAddressRelay(pfrom, *peer)) {
3890 Misbehaving(*peer, 20,
strprintf(
"%s message size = %u", msg_type, vAddr.size()));
3895 std::vector<CAddress> vAddrOk;
3896 const auto current_a_time{Now<NodeSeconds>()};
3899 const auto current_time{GetTime<std::chrono::microseconds>()};
3902 const auto time_diff = std::max(current_time - peer->m_addr_token_timestamp, 0us);
3906 peer->m_addr_token_timestamp = current_time;
3909 uint64_t num_proc = 0;
3910 uint64_t num_rate_limit = 0;
3911 Shuffle(vAddr.begin(), vAddr.end(), m_rng);
3914 if (interruptMsgProc)
3918 if (peer->m_addr_token_bucket < 1.0) {
3924 peer->m_addr_token_bucket -= 1.0;
3933 addr.
nTime = current_a_time - 5 * 24h;
3935 AddAddressKnown(*peer, addr);
3942 if (addr.
nTime > current_a_time - 10min && !peer->m_getaddr_sent && vAddr.size() <= 10 && addr.
IsRoutable()) {
3944 RelayAddress(pfrom.
GetId(), addr, reachable);
3948 vAddrOk.push_back(addr);
3951 peer->m_addr_processed += num_proc;
3952 peer->m_addr_rate_limited += num_rate_limit;
3953 LogPrint(
BCLog::NET,
"Received addr: %u addresses (%u processed, %u rate-limited) from peer=%d\n",
3954 vAddr.size(), num_proc, num_rate_limit, pfrom.
GetId());
3956 m_addrman.
Add(vAddrOk, pfrom.
addr, 2h);
3957 if (vAddr.size() < 1000) peer->m_getaddr_sent =
false;
3968 std::vector<CInv> vInv;
3972 Misbehaving(*peer, 20,
strprintf(
"inv message size = %u", vInv.size()));
3976 const bool reject_tx_invs{RejectIncomingTxs(pfrom)};
3980 const auto current_time{GetTime<std::chrono::microseconds>()};
3983 for (
CInv& inv : vInv) {
3984 if (interruptMsgProc)
return;
3989 if (peer->m_wtxid_relay) {
3996 const bool fAlreadyHave = AlreadyHaveBlock(inv.
hash);
3999 UpdateBlockAvailability(pfrom.
GetId(), inv.
hash);
4007 best_block = &inv.
hash;
4010 if (reject_tx_invs) {
4016 const bool fAlreadyHave = AlreadyHaveTx(gtxid);
4019 AddKnownTx(*peer, inv.
hash);
4021 AddTxAnnouncement(pfrom, gtxid, current_time);
4028 if (best_block !=
nullptr) {
4040 if (state.fSyncStarted || (!peer->m_inv_triggered_getheaders_before_sync && *best_block != m_last_block_inv_triggering_headers_sync)) {
4041 if (MaybeSendGetHeaders(pfrom,
GetLocator(m_chainman.m_best_header), *peer)) {
4043 m_chainman.m_best_header->nHeight, best_block->ToString(),
4046 if (!state.fSyncStarted) {
4047 peer->m_inv_triggered_getheaders_before_sync =
true;
4051 m_last_block_inv_triggering_headers_sync = *best_block;
4060 std::vector<CInv> vInv;
4064 Misbehaving(*peer, 20,
strprintf(
"getdata message size = %u", vInv.size()));
4070 if (vInv.size() > 0) {
4075 LOCK(peer->m_getdata_requests_mutex);
4076 peer->m_getdata_requests.insert(peer->m_getdata_requests.end(), vInv.begin(), vInv.end());
4077 ProcessGetData(pfrom, *peer, interruptMsgProc);
4086 vRecv >> locator >> hashStop;
4102 std::shared_ptr<const CBlock> a_recent_block;
4104 LOCK(m_most_recent_block_mutex);
4105 a_recent_block = m_most_recent_block;
4108 if (!m_chainman.
ActiveChainstate().ActivateBestChain(state, a_recent_block)) {
4123 for (; pindex; pindex = m_chainman.
ActiveChain().Next(pindex))
4138 if (--nLimit <= 0) {
4142 WITH_LOCK(peer->m_block_inv_mutex, {peer->m_continuation_block = pindex->GetBlockHash();});
4153 std::shared_ptr<const CBlock> recent_block;
4155 LOCK(m_most_recent_block_mutex);
4156 if (m_most_recent_block_hash == req.
blockhash)
4157 recent_block = m_most_recent_block;
4161 SendBlockTransactions(pfrom, *peer, *recent_block, req);
4179 SendBlockTransactions(pfrom, *peer, block, req);
4193 WITH_LOCK(peer->m_getdata_requests_mutex, peer->m_getdata_requests.push_back(inv));
4201 vRecv >> locator >> hashStop;
4223 if (m_chainman.
ActiveTip() ==
nullptr ||
4225 LogPrint(
BCLog::NET,
"Ignoring getheaders from peer=%d because active chain has too little work; sending empty response\n", pfrom.
GetId());
4232 CNodeState *nodestate = State(pfrom.
GetId());
4242 if (!BlockRequestAllowed(pindex)) {
4243 LogPrint(
BCLog::NET,
"%s: ignoring request from peer=%i for old block header that isn't in the main chain\n", __func__, pfrom.
GetId());
4256 std::vector<CBlock> vHeaders;
4259 for (; pindex; pindex = m_chainman.
ActiveChain().Next(pindex))
4262 if (--nLimit <= 0 || pindex->GetBlockHash() == hashStop)
4277 nodestate->pindexBestHeaderSent = pindex ? pindex : m_chainman.
ActiveChain().
Tip();
4283 if (RejectIncomingTxs(pfrom)) {
4298 const uint256& txid = ptx->GetHash();
4299 const uint256& wtxid = ptx->GetWitnessHash();
4301 const uint256& hash = peer->m_wtxid_relay ? wtxid : txid;
4302 AddKnownTx(*peer, hash);
4306 m_txrequest.ReceivedResponse(pfrom.
GetId(), txid);
4307 if (tx.
HasWitness()) m_txrequest.ReceivedResponse(pfrom.
GetId(), wtxid);
4327 LogPrintf(
"Not relaying non-mempool transaction %s (wtxid=%s) from forcerelay peer=%d\n",
4330 LogPrintf(
"Force relaying tx %s (wtxid=%s) from peer=%d\n",
4362 bool fRejectedParents =
false;
4366 std::vector<uint256> unique_parents;
4367 unique_parents.reserve(tx.
vin.size());
4372 std::sort(unique_parents.begin(), unique_parents.end());
4373 unique_parents.erase(std::unique(unique_parents.begin(), unique_parents.end()), unique_parents.end());
4374 for (
const uint256& parent_txid : unique_parents) {
4375 if (m_recent_rejects.contains(parent_txid)) {
4376 fRejectedParents =
true;
4380 if (!fRejectedParents) {
4381 const auto current_time{GetTime<std::chrono::microseconds>()};
4383 for (
const uint256& parent_txid : unique_parents) {
4390 AddKnownTx(*peer, parent_txid);
4391 if (!AlreadyHaveTx(gtxid)) AddTxAnnouncement(pfrom, gtxid, current_time);
4395 AddToCompactExtraTransactions(ptx);
4399 m_txrequest.ForgetTxHash(tx.
GetHash());
4403 m_orphanage.
LimitOrphans(m_opts.max_orphan_txs, m_rng);
4416 m_txrequest.ForgetTxHash(tx.
GetHash());
4421 ProcessInvalidTx(pfrom.
GetId(), ptx, state,
true);
4435 vRecv >> cmpctblock;
4437 bool received_new_header =
false;
4447 MaybeSendGetHeaders(pfrom,
GetLocator(m_chainman.m_best_header), *peer);
4457 received_new_header =
true;
4465 MaybePunishNodeForBlock(pfrom.
GetId(), state,
true,
"invalid header via cmpctblock");
4470 if (received_new_header) {
4471 LogInfo(
"Saw new cmpctblock header hash=%s peer=%d\n",
4472 blockhash.ToString(), pfrom.
GetId());
4475 bool fProcessBLOCKTXN =
false;
4479 bool fRevertToHeaderProcessing =
false;
4483 std::shared_ptr<CBlock> pblock = std::make_shared<CBlock>();
4484 bool fBlockReconstructed =
false;
4492 CNodeState *nodestate = State(pfrom.
GetId());
4497 nodestate->m_last_block_announcement =
GetTime();
4503 auto range_flight = mapBlocksInFlight.equal_range(pindex->
GetBlockHash());
4504 size_t already_in_flight = std::distance(range_flight.first, range_flight.second);
4505 bool requested_block_from_this_peer{
false};
4508 bool first_in_flight = already_in_flight == 0 || (range_flight.first->second.first == pfrom.
GetId());
4510 while (range_flight.first != range_flight.second) {
4511 if (range_flight.first->second.first == pfrom.
GetId()) {
4512 requested_block_from_this_peer =
true;
4515 range_flight.first++;
4520 if (requested_block_from_this_peer) {
4523 std::vector<CInv> vInv(1);
4524 vInv[0] =
CInv(
MSG_BLOCK | GetFetchFlags(*peer), blockhash);
4531 if (!already_in_flight && !CanDirectFetch()) {
4539 requested_block_from_this_peer) {
4540 std::list<QueuedBlock>::iterator* queuedBlockIt =
nullptr;
4541 if (!BlockRequested(pfrom.
GetId(), *pindex, &queuedBlockIt)) {
4542 if (!(*queuedBlockIt)->partialBlock)
4555 Misbehaving(*peer, 100,
"invalid compact block");
4558 if (first_in_flight) {
4560 std::vector<CInv> vInv(1);
4561 vInv[0] =
CInv(
MSG_BLOCK | GetFetchFlags(*peer), blockhash);
4571 for (
size_t i = 0; i < cmpctblock.
BlockTxCount(); i++) {
4576 fProcessBLOCKTXN =
true;
4577 }
else if (first_in_flight) {
4584 IsBlockRequestedFromOutbound(blockhash) ||
4603 ReadStatus status = tempBlock.InitData(cmpctblock, vExtraTxnForCompact);
4608 std::vector<CTransactionRef> dummy;
4609 status = tempBlock.FillBlock(*pblock, dummy);
4611 fBlockReconstructed =
true;
4615 if (requested_block_from_this_peer) {
4618 std::vector<CInv> vInv(1);
4619 vInv[0] =
CInv(
MSG_BLOCK | GetFetchFlags(*peer), blockhash);
4624 fRevertToHeaderProcessing =
true;
4629 if (fProcessBLOCKTXN) {
4632 return ProcessCompactBlockTxns(pfrom, *peer, txn);
4635 if (fRevertToHeaderProcessing) {
4641 return ProcessHeadersMessage(pfrom, *peer, {cmpctblock.
header},
true);
4644 if (fBlockReconstructed) {
4649 mapBlockSource.emplace(pblock->GetHash(), std::make_pair(pfrom.
GetId(),
false));
4660 ProcessBlock(pfrom, pblock,
true,
true);
4667 RemoveBlockRequest(pblock->GetHash(), std::nullopt);
4684 return ProcessCompactBlockTxns(pfrom, *peer, resp);
4697 peer->m_last_getheaders_timestamp = {};
4699 std::vector<CBlockHeader> headers;
4704 Misbehaving(*peer, 20,
strprintf(
"headers message size = %u", nCount));
4707 headers.resize(nCount);
4708 for (
unsigned int n = 0; n < nCount; n++) {
4709 vRecv >> headers[n];
4713 ProcessHeadersMessage(pfrom, *peer, std::move(headers),
false);
4717 if (m_headers_presync_should_signal.exchange(
false)) {
4718 HeadersPresyncStats stats;
4720 LOCK(m_headers_presync_mutex);
4721 auto it = m_headers_presync_stats.find(m_headers_presync_bestpeer);
4722 if (it != m_headers_presync_stats.end()) stats = it->second;
4740 std::shared_ptr<CBlock> pblock = std::make_shared<CBlock>();
4751 Misbehaving(*peer, 100,
"mutated block");
4756 bool forceProcessing =
false;
4757 const uint256 hash(pblock->GetHash());
4758 bool min_pow_checked =
false;
4763 forceProcessing = IsBlockRequested(hash);
4764 RemoveBlockRequest(hash, pfrom.
GetId());
4768 mapBlockSource.emplace(hash, std::make_pair(pfrom.
GetId(),
true));
4772 min_pow_checked =
true;
4775 ProcessBlock(pfrom, pblock, forceProcessing, min_pow_checked);
4792 Assume(SetupAddressRelay(pfrom, *peer));
4796 if (peer->m_getaddr_recvd) {
4800 peer->m_getaddr_recvd =
true;
4802 peer->m_addrs_to_send.clear();
4803 std::vector<CAddress> vAddr;
4809 for (
const CAddress &addr : vAddr) {
4810 PushAddress(*peer, addr);
4838 if (
auto tx_relay = peer->GetTxRelay(); tx_relay !=
nullptr) {
4839 LOCK(tx_relay->m_tx_inventory_mutex);
4840 tx_relay->m_send_mempool =
true;
4866 const auto ping_end = time_received;
4869 bool bPingFinished =
false;
4870 std::string sProblem;
4872 if (nAvail >=
sizeof(
nonce)) {
4876 if (peer->m_ping_nonce_sent != 0) {
4877 if (
nonce == peer->m_ping_nonce_sent) {
4879 bPingFinished =
true;
4880 const auto ping_time = ping_end - peer->m_ping_start.load();
4881 if (ping_time.count() >= 0) {
4886 sProblem =
"Timing mishap";
4890 sProblem =
"Nonce mismatch";
4893 bPingFinished =
true;
4894 sProblem =
"Nonce zero";
4898 sProblem =
"Unsolicited pong without ping";
4902 bPingFinished =
true;
4903 sProblem =
"Short payload";
4906 if (!(sProblem.empty())) {
4910 peer->m_ping_nonce_sent,
4914 if (bPingFinished) {
4915 peer->m_ping_nonce_sent = 0;
4922 LogPrint(
BCLog::NET,
"filterload received despite not offering bloom services from peer=%d; disconnecting\n", pfrom.
GetId());
4932 Misbehaving(*peer, 100,
"too-large bloom filter");
4933 }
else if (
auto tx_relay = peer->GetTxRelay(); tx_relay !=
nullptr) {
4935 LOCK(tx_relay->m_bloom_filter_mutex);
4936 tx_relay->m_bloom_filter.reset(
new CBloomFilter(filter));
4937 tx_relay->m_relay_txs =
true;
4947 LogPrint(
BCLog::NET,
"filteradd received despite not offering bloom services from peer=%d; disconnecting\n", pfrom.
GetId());
4951 std::vector<unsigned char> vData;
4959 }
else if (
auto tx_relay = peer->GetTxRelay(); tx_relay !=
nullptr) {
4960 LOCK(tx_relay->m_bloom_filter_mutex);
4961 if (tx_relay->m_bloom_filter) {
4962 tx_relay->m_bloom_filter->insert(vData);
4968 Misbehaving(*peer, 100,
"bad filteradd message");
4975 LogPrint(
BCLog::NET,
"filterclear received despite not offering bloom services from peer=%d; disconnecting\n", pfrom.
GetId());
4979 auto tx_relay = peer->GetTxRelay();
4980 if (!tx_relay)
return;
4983 LOCK(tx_relay->m_bloom_filter_mutex);
4984 tx_relay->m_bloom_filter =
nullptr;
4985 tx_relay->m_relay_txs =
true;
4994 vRecv >> newFeeFilter;
4996 if (
auto tx_relay = peer->GetTxRelay(); tx_relay !=
nullptr) {
4997 tx_relay->m_fee_filter_received = newFeeFilter;
5005 ProcessGetCFilters(pfrom, *peer, vRecv);
5010 ProcessGetCFHeaders(pfrom, *peer, vRecv);
5015 ProcessGetCFCheckPt(pfrom, *peer, vRecv);
5020 std::vector<CInv> vInv;
5024 for (
CInv &inv : vInv) {
5028 m_txrequest.ReceivedResponse(pfrom.
GetId(), inv.
hash);
5040 bool PeerManagerImpl::MaybeDiscourageAndDisconnect(
CNode& pnode, Peer& peer)
5043 LOCK(peer.m_misbehavior_mutex);
5046 if (!peer.m_should_discourage)
return false;
5048 peer.m_should_discourage =
false;
5053 LogPrintf(
"Warning: not punishing noban peer %d!\n", peer.m_id);
5059 LogPrintf(
"Warning: not punishing manually connected peer %d!\n", peer.m_id);
5079 bool PeerManagerImpl::ProcessMessages(
CNode* pfrom, std::atomic<bool>& interruptMsgProc)
5083 PeerRef peer = GetPeerRef(pfrom->
GetId());
5084 if (peer ==
nullptr)
return false;
5087 LOCK(peer->m_getdata_requests_mutex);
5088 if (!peer->m_getdata_requests.empty()) {
5089 ProcessGetData(*pfrom, *peer, interruptMsgProc);
5093 const bool processed_orphan = ProcessOrphanTx(*peer);
5098 if (processed_orphan)
return true;
5103 LOCK(peer->m_getdata_requests_mutex);
5104 if (!peer->m_getdata_requests.empty())
return true;
5117 bool fMoreWork = poll_result->second;
5119 TRACE6(net, inbound_message,
5128 if (m_opts.capture_messages) {
5133 ProcessMessage(*pfrom,
msg.m_type,
msg.m_recv,
msg.m_time, interruptMsgProc);
5134 if (interruptMsgProc)
return false;
5136 LOCK(peer->m_getdata_requests_mutex);
5137 if (!peer->m_getdata_requests.empty()) fMoreWork =
true;
5145 }
catch (
const std::exception& e) {
5154 void PeerManagerImpl::ConsiderEviction(
CNode& pto, Peer& peer, std::chrono::seconds time_in_seconds)
5158 CNodeState &state = *State(pto.
GetId());
5167 if (state.pindexBestKnownBlock !=
nullptr && state.pindexBestKnownBlock->nChainWork >= m_chainman.
ActiveChain().
Tip()->
nChainWork) {
5168 if (state.m_chain_sync.m_timeout != 0s) {
5169 state.m_chain_sync.m_timeout = 0s;
5170 state.m_chain_sync.m_work_header =
nullptr;
5171 state.m_chain_sync.m_sent_getheaders =
false;
5173 }
else if (state.m_chain_sync.m_timeout == 0s || (state.m_chain_sync.m_work_header !=
nullptr && state.pindexBestKnownBlock !=
nullptr && state.pindexBestKnownBlock->nChainWork >= state.m_chain_sync.m_work_header->nChainWork)) {
5179 state.m_chain_sync.m_work_header = m_chainman.
ActiveChain().
Tip();
5180 state.m_chain_sync.m_sent_getheaders =
false;
5181 }
else if (state.m_chain_sync.m_timeout > 0s && time_in_seconds > state.m_chain_sync.m_timeout) {
5185 if (state.m_chain_sync.m_sent_getheaders) {
5187 LogPrintf(
"Disconnecting outbound peer %d for old chain, best known block = %s\n", pto.
GetId(), state.pindexBestKnownBlock !=
nullptr ? state.pindexBestKnownBlock->GetBlockHash().ToString() :
"<none>");
5190 assert(state.m_chain_sync.m_work_header);
5195 MaybeSendGetHeaders(pto,
5196 GetLocator(state.m_chain_sync.m_work_header->pprev),
5198 LogPrint(
BCLog::NET,
"sending getheaders to outbound peer=%d to verify chain work (current best known block:%s, benchmark blockhash: %s)\n", pto.
GetId(), state.pindexBestKnownBlock !=
nullptr ? state.pindexBestKnownBlock->GetBlockHash().ToString() :
"<none>", state.m_chain_sync.m_work_header->GetBlockHash().ToString());
5199 state.m_chain_sync.m_sent_getheaders =
true;
5211 void PeerManagerImpl::EvictExtraOutboundPeers(std::chrono::seconds now)
5220 std::pair<NodeId, std::chrono::seconds> youngest_peer{-1, 0}, next_youngest_peer{-1, 0};
5224 if (pnode->
GetId() > youngest_peer.first) {
5225 next_youngest_peer = youngest_peer;
5226 youngest_peer.first = pnode->GetId();
5227 youngest_peer.second = pnode->m_last_block_time;
5230 NodeId to_disconnect = youngest_peer.first;
5231 if (youngest_peer.second > next_youngest_peer.second) {
5234 to_disconnect = next_youngest_peer.first;
5243 CNodeState *node_state = State(pnode->
GetId());
5244 if (node_state ==
nullptr ||
5247 LogPrint(
BCLog::NET,
"disconnecting extra block-relay-only peer=%d (last block received at time %d)\n",
5251 LogPrint(
BCLog::NET,
"keeping block-relay-only peer=%d chosen for eviction (connect time: %d, blocks_in_flight: %d)\n",
5267 int64_t oldest_block_announcement = std::numeric_limits<int64_t>::max();
5270 AssertLockHeld(::cs_main);
5274 if (!pnode->IsFullOutboundConn() || pnode->fDisconnect) return;
5275 CNodeState *state = State(pnode->GetId());
5276 if (state == nullptr) return;
5278 if (state->m_chain_sync.m_protect) return;
5281 if (!m_connman.MultipleManualOrFullOutboundConns(pnode->addr.GetNetwork())) return;
5282 if (state->m_last_block_announcement < oldest_block_announcement || (state->m_last_block_announcement == oldest_block_announcement && pnode->GetId() > worst_peer)) {
5283 worst_peer = pnode->GetId();
5284 oldest_block_announcement = state->m_last_block_announcement;
5287 if (worst_peer != -1) {
5296 CNodeState &state = *State(pnode->
GetId());
5298 LogPrint(
BCLog::NET,
"disconnecting extra outbound peer=%d (last block announcement received at time %d)\n", pnode->
GetId(), oldest_block_announcement);
5302 LogPrint(
BCLog::NET,
"keeping outbound peer=%d chosen for eviction (connect time: %d, blocks_in_flight: %d)\n",
5319 void PeerManagerImpl::CheckForStaleTipAndEvictPeers()
5323 auto now{GetTime<std::chrono::seconds>()};
5325 EvictExtraOutboundPeers(now);
5327 if (now > m_stale_tip_check_time) {
5331 LogPrintf(
"Potential stale tip detected, will try using extra outbound peer (last tip update: %d seconds ago)\n",
5340 if (!m_initial_sync_finished && CanDirectFetch()) {
5342 m_initial_sync_finished =
true;
5346 void PeerManagerImpl::MaybeSendPing(
CNode& node_to, Peer& peer, std::chrono::microseconds now)
5349 peer.m_ping_nonce_sent &&
5359 bool pingSend =
false;
5361 if (peer.m_ping_queued) {
5366 if (peer.m_ping_nonce_sent == 0 && now > peer.m_ping_start.load() +
PING_INTERVAL) {
5374 nonce = GetRand<uint64_t>();
5375 }
while (
nonce == 0);
5376 peer.m_ping_queued =
false;
5377 peer.m_ping_start = now;
5379 peer.m_ping_nonce_sent =
nonce;
5383 peer.m_ping_nonce_sent = 0;
5389 void PeerManagerImpl::MaybeSendAddr(
CNode&
node, Peer& peer, std::chrono::microseconds current_time)
5392 if (!peer.m_addr_relay_enabled)
return;
5394 LOCK(peer.m_addr_send_times_mutex);
5397 peer.m_next_local_addr_send < current_time) {
5404 if (peer.m_next_local_addr_send != 0us) {
5405 peer.m_addr_known->reset();
5408 CAddress local_addr{*local_service, peer.m_our_services, Now<NodeSeconds>()};
5409 PushAddress(peer, local_addr);
5415 if (current_time <= peer.m_next_addr_send)
return;
5428 bool ret = peer.m_addr_known->contains(addr.
GetKey());
5429 if (!
ret) peer.m_addr_known->insert(addr.
GetKey());
5432 peer.m_addrs_to_send.erase(std::remove_if(peer.m_addrs_to_send.begin(), peer.m_addrs_to_send.end(), addr_already_known),
5433 peer.m_addrs_to_send.end());
5436 if (peer.m_addrs_to_send.empty())
return;
5438 if (peer.m_wants_addrv2) {
5443 peer.m_addrs_to_send.clear();
5446 if (peer.m_addrs_to_send.capacity() > 40) {
5447 peer.m_addrs_to_send.shrink_to_fit();
5451 void PeerManagerImpl::MaybeSendSendHeaders(
CNode&
node, Peer& peer)
5459 CNodeState &state = *State(
node.GetId());
5460 if (state.pindexBestKnownBlock !=
nullptr &&
5467 peer.m_sent_sendheaders =
true;
5472 void PeerManagerImpl::MaybeSendFeefilter(
CNode& pto, Peer& peer, std::chrono::microseconds current_time)
5474 if (m_opts.ignore_incoming_txs)
return;
5490 if (peer.m_fee_filter_sent == MAX_FILTER) {
5493 peer.m_next_send_feefilter = 0us;
5496 if (current_time > peer.m_next_send_feefilter) {
5497 CAmount filterToSend = m_fee_filter_rounder.round(currentFilter);
5500 if (filterToSend != peer.m_fee_filter_sent) {
5502 peer.m_fee_filter_sent = filterToSend;
5509 (currentFilter < 3 * peer.m_fee_filter_sent / 4 || currentFilter > 4 * peer.m_fee_filter_sent / 3)) {
5515 class CompareInvMempoolOrder
5520 explicit CompareInvMempoolOrder(
CTxMemPool *_mempool,
bool use_wtxid)
5523 m_wtxid_relay = use_wtxid;
5526 bool operator()(std::set<uint256>::iterator a, std::set<uint256>::iterator b)
5530 return mp->CompareDepthAndScore(*b, *a, m_wtxid_relay);
5535 bool PeerManagerImpl::RejectIncomingTxs(
const CNode& peer)
const
5545 bool PeerManagerImpl::SetupAddressRelay(
const CNode&
node, Peer& peer)
5550 if (
node.IsBlockOnlyConn())
return false;
5552 if (!peer.m_addr_relay_enabled.exchange(
true)) {
5556 peer.m_addr_known = std::make_unique<CRollingBloomFilter>(5000, 0.001);
5562 bool PeerManagerImpl::SendMessages(
CNode* pto)
5566 PeerRef peer = GetPeerRef(pto->
GetId());
5567 if (!peer)
return false;
5572 if (MaybeDiscourageAndDisconnect(*pto, *peer))
return true;
5578 const auto current_time{GetTime<std::chrono::microseconds>()};
5586 MaybeSendPing(*pto, *peer, current_time);
5591 MaybeSendAddr(*pto, *peer, current_time);
5593 MaybeSendSendHeaders(*pto, *peer);
5598 CNodeState &state = *State(pto->
GetId());
5601 if (m_chainman.m_best_header ==
nullptr) {
5608 bool sync_blocks_and_headers_from_peer =
false;
5609 if (state.fPreferredDownload) {
5610 sync_blocks_and_headers_from_peer =
true;
5621 if (m_num_preferred_download_peers == 0 || mapBlocksInFlight.empty()) {
5622 sync_blocks_and_headers_from_peer =
true;
5628 if ((nSyncStarted == 0 && sync_blocks_and_headers_from_peer) || m_chainman.m_best_header->Time() >
NodeClock::now() - 24h) {
5629 const CBlockIndex* pindexStart = m_chainman.m_best_header;
5637 if (pindexStart->
pprev)
5638 pindexStart = pindexStart->
pprev;
5639 if (MaybeSendGetHeaders(*pto,
GetLocator(pindexStart), *peer)) {
5642 state.fSyncStarted =
true;
5666 LOCK(peer->m_block_inv_mutex);
5667 std::vector<CBlock> vHeaders;
5668 bool fRevertToInv = ((!peer->m_prefers_headers &&
5669 (!state.m_requested_hb_cmpctblocks || peer->m_blocks_for_headers_relay.size() > 1)) ||
5672 ProcessBlockAvailability(pto->
GetId());
5674 if (!fRevertToInv) {
5675 bool fFoundStartingHeader =
false;
5679 for (
const uint256& hash : peer->m_blocks_for_headers_relay) {
5684 fRevertToInv =
true;
5687 if (pBestIndex !=
nullptr && pindex->
pprev != pBestIndex) {
5699 fRevertToInv =
true;
5702 pBestIndex = pindex;
5703 if (fFoundStartingHeader) {
5706 }
else if (PeerHasHeader(&state, pindex)) {
5708 }
else if (pindex->
pprev ==
nullptr || PeerHasHeader(&state, pindex->
pprev)) {
5711 fFoundStartingHeader =
true;
5716 fRevertToInv =
true;
5721 if (!fRevertToInv && !vHeaders.empty()) {
5722 if (vHeaders.size() == 1 && state.m_requested_hb_cmpctblocks) {
5726 vHeaders.front().GetHash().ToString(), pto->
GetId());
5728 std::optional<CSerializedNetMsg> cached_cmpctblock_msg;
5730 LOCK(m_most_recent_block_mutex);
5731 if (m_most_recent_block_hash == pBestIndex->
GetBlockHash()) {
5735 if (cached_cmpctblock_msg.has_value()) {
5736 PushMessage(*pto, std::move(cached_cmpctblock_msg.value()));
5744 state.pindexBestHeaderSent = pBestIndex;
5745 }
else if (peer->m_prefers_headers) {
5746 if (vHeaders.size() > 1) {
5749 vHeaders.front().GetHash().ToString(),
5750 vHeaders.back().GetHash().ToString(), pto->
GetId());
5753 vHeaders.front().GetHash().ToString(), pto->
GetId());
5756 state.pindexBestHeaderSent = pBestIndex;
5758 fRevertToInv =
true;
5764 if (!peer->m_blocks_for_headers_relay.empty()) {
5765 const uint256& hashToAnnounce = peer->m_blocks_for_headers_relay.back();
5778 if (!PeerHasHeader(&state, pindex)) {
5779 peer->m_blocks_for_inv_relay.push_back(hashToAnnounce);
5785 peer->m_blocks_for_headers_relay.clear();
5791 std::vector<CInv> vInv;
5793 LOCK(peer->m_block_inv_mutex);
5797 for (
const uint256& hash : peer->m_blocks_for_inv_relay) {
5804 peer->m_blocks_for_inv_relay.clear();
5807 if (
auto tx_relay = peer->GetTxRelay(); tx_relay !=
nullptr) {
5808 LOCK(tx_relay->m_tx_inventory_mutex);
5811 if (tx_relay->m_next_inv_send_time < current_time) {
5812 fSendTrickle =
true;
5822 LOCK(tx_relay->m_bloom_filter_mutex);
5823 if (!tx_relay->m_relay_txs) tx_relay->m_tx_inventory_to_send.clear();
5827 if (fSendTrickle && tx_relay->m_send_mempool) {
5828 auto vtxinfo = m_mempool.
infoAll();
5829 tx_relay->m_send_mempool =
false;
5830 const CFeeRate filterrate{tx_relay->m_fee_filter_received.load()};
5832 LOCK(tx_relay->m_bloom_filter_mutex);
5834 for (
const auto& txinfo : vtxinfo) {
5837 peer->m_wtxid_relay ?
5838 txinfo.tx->GetWitnessHash().ToUint256() :
5839 txinfo.tx->GetHash().ToUint256(),
5841 tx_relay->m_tx_inventory_to_send.erase(inv.
hash);
5844 if (txinfo.fee < filterrate.GetFee(txinfo.vsize)) {
5847 if (tx_relay->m_bloom_filter) {
5848 if (!tx_relay->m_bloom_filter->IsRelevantAndUpdate(*txinfo.tx))
continue;
5850 tx_relay->m_tx_inventory_known_filter.insert(inv.
hash);
5851 vInv.push_back(inv);
5862 std::vector<std::set<uint256>::iterator> vInvTx;
5863 vInvTx.reserve(tx_relay->m_tx_inventory_to_send.size());
5864 for (std::set<uint256>::iterator it = tx_relay->m_tx_inventory_to_send.begin(); it != tx_relay->m_tx_inventory_to_send.end(); it++) {
5865 vInvTx.push_back(it);
5867 const CFeeRate filterrate{tx_relay->m_fee_filter_received.load()};
5870 CompareInvMempoolOrder compareInvMempoolOrder(&m_mempool, peer->m_wtxid_relay);
5871 std::make_heap(vInvTx.begin(), vInvTx.end(), compareInvMempoolOrder);
5874 unsigned int nRelayedTransactions = 0;
5875 LOCK(tx_relay->m_bloom_filter_mutex);
5878 while (!vInvTx.empty() && nRelayedTransactions < broadcast_max) {
5880 std::pop_heap(vInvTx.begin(), vInvTx.end(), compareInvMempoolOrder);
5881 std::set<uint256>::iterator it = vInvTx.back();
5886 tx_relay->m_tx_inventory_to_send.erase(it);
5888 if (tx_relay->m_tx_inventory_known_filter.contains(hash)) {
5897 if (txinfo.fee < filterrate.GetFee(txinfo.vsize)) {
5900 if (tx_relay->m_bloom_filter && !tx_relay->m_bloom_filter->IsRelevantAndUpdate(*txinfo.tx))
continue;
5902 vInv.push_back(inv);
5903 nRelayedTransactions++;
5908 tx_relay->m_tx_inventory_known_filter.insert(hash);
5913 tx_relay->m_last_inv_sequence = m_mempool.
GetSequence();
5920 auto stalling_timeout = m_block_stalling_timeout.load();
5921 if (state.m_stalling_since.count() && state.m_stalling_since < current_time - stalling_timeout) {
5930 if (stalling_timeout != new_timeout && m_block_stalling_timeout.compare_exchange_strong(stalling_timeout, new_timeout)) {
5940 if (state.vBlocksInFlight.size() > 0) {
5941 QueuedBlock &queuedBlock = state.vBlocksInFlight.front();
5942 int nOtherPeersWithValidatedDownloads = m_peers_downloading_from - 1;
5950 if (state.fSyncStarted && peer->m_headers_sync_timeout < std::chrono::microseconds::max()) {
5952 if (m_chainman.m_best_header->Time() <=
NodeClock::now() - 24h) {
5953 if (current_time > peer->m_headers_sync_timeout && nSyncStarted == 1 && (m_num_preferred_download_peers - state.fPreferredDownload >= 1)) {
5970 state.fSyncStarted =
false;
5972 peer->m_headers_sync_timeout = 0us;
5978 peer->m_headers_sync_timeout = std::chrono::microseconds::max();
5984 ConsiderEviction(*pto, *peer, GetTime<std::chrono::seconds>());
5989 std::vector<CInv> vGetData;
5991 std::vector<const CBlockIndex*> vToDownload;
5993 auto get_inflight_budget = [&state]() {
5999 FindNextBlocksToDownload(*peer, get_inflight_budget(), vToDownload, staller);
6001 TryDownloadingHistoricalBlocks(
6003 get_inflight_budget(),
6005 Assert(m_chainman.GetSnapshotBaseBlock()));
6008 uint32_t nFetchFlags = GetFetchFlags(*peer);
6010 BlockRequested(pto->
GetId(), *pindex);
6014 if (state.vBlocksInFlight.empty() && staller != -1) {
6015 if (State(staller)->m_stalling_since == 0us) {
6016 State(staller)->m_stalling_since = current_time;
6025 std::vector<std::pair<NodeId, GenTxid>> expired;
6026 auto requestable = m_txrequest.GetRequestable(pto->
GetId(), current_time, &expired);
6027 for (
const auto& entry : expired) {
6028 LogPrint(
BCLog::NET,
"timeout of inflight %s %s from peer=%d\n", entry.second.IsWtxid() ?
"wtx" :
"tx",
6029 entry.second.GetHash().ToString(), entry.first);
6031 for (
const GenTxid& gtxid : requestable) {
6032 if (!AlreadyHaveTx(gtxid)) {
6044 m_txrequest.ForgetTxHash(gtxid.
GetHash());
6049 if (!vGetData.empty())
6052 MaybeSendFeefilter(*pto, *peer, current_time);
static constexpr CAmount MAX_MONEY
No amount larger than this (in satoshi) is valid.
bool MoneyRange(const CAmount &nValue)
int64_t CAmount
Amount in satoshis (Can be negative)
enum ReadStatus_t ReadStatus
const std::string & BlockFilterTypeName(BlockFilterType filter_type)
Get the human-readable name for a filter type.
BlockFilterIndex * GetBlockFilterIndex(BlockFilterType filter_type)
Get a block filter index by type.
static constexpr int CFCHECKPT_INTERVAL
Interval between compact filter checkpoints.
arith_uint256 GetBlockProof(const CBlockIndex &block)
CBlockLocator GetLocator(const CBlockIndex *index)
Get a locator for a block index entry.
const CBlockIndex * LastCommonAncestor(const CBlockIndex *pa, const CBlockIndex *pb)
Find the last common ancestor two blocks have.
int64_t GetBlockProofEquivalentTime(const CBlockIndex &to, const CBlockIndex &from, const CBlockIndex &tip, const Consensus::Params ¶ms)
Return the time it would take to redo the work difference between from and to, assuming the current h...
@ BLOCK_VALID_CHAIN
Outputs do not overspend inputs, no double spends, coinbase output ok, no immature coinbase spends,...
@ BLOCK_VALID_TRANSACTIONS
Only first tx is coinbase, 2 <= coinbase input script length <= 100, transactions valid,...
@ BLOCK_VALID_SCRIPTS
Scripts & signatures ok.
@ BLOCK_VALID_TREE
All parent headers found, difficulty matches, timestamp >= median previous, checkpoint.
@ BLOCK_HAVE_DATA
full block available in blk*.dat
const CChainParams & Params()
Return the currently selected parameters.
#define Assert(val)
Identity function.
#define Assume(val)
Assume is the identity function.
Stochastic address manager.
void Connected(const CService &addr, NodeSeconds time=Now< NodeSeconds >())
We have successfully connected to this peer.
bool Good(const CService &addr, NodeSeconds time=Now< NodeSeconds >())
Mark an address record as accessible and attempt to move it to addrman's tried table.
bool Add(const std::vector< CAddress > &vAddr, const CNetAddr &source, std::chrono::seconds time_penalty=0s)
Attempt to add one or more addresses to addrman's new table.
void SetServices(const CService &addr, ServiceFlags nServices)
Update an entry's service bits.
bool IsBanned(const CNetAddr &net_addr) EXCLUSIVE_LOCKS_REQUIRED(!m_banned_mutex)
Return whether net_addr is banned.
bool IsDiscouraged(const CNetAddr &net_addr) EXCLUSIVE_LOCKS_REQUIRED(!m_banned_mutex)
Return whether net_addr is discouraged.
void Discourage(const CNetAddr &net_addr) EXCLUSIVE_LOCKS_REQUIRED(!m_banned_mutex)
BlockFilterIndex is used to store and retrieve block filters, hashes, and headers for a range of bloc...
bool LookupFilterRange(int start_height, const CBlockIndex *stop_index, std::vector< BlockFilter > &filters_out) const
Get a range of filters between two heights on a chain.
bool LookupFilterHashRange(int start_height, const CBlockIndex *stop_index, std::vector< uint256 > &hashes_out) const
Get a range of filter hashes between two heights on a chain.
bool LookupFilterHeader(const CBlockIndex *block_index, uint256 &header_out) EXCLUSIVE_LOCKS_REQUIRED(!m_cs_headers_cache)
Get a single filter header by block.
std::vector< CTransactionRef > txn
std::vector< uint16_t > indexes
A CService with information about it as peer.
ServiceFlags nServices
Serialized as uint64_t in V1, and as CompactSize in V2.
static constexpr SerParams V1_NETWORK
NodeSeconds nTime
Always included in serialization. The behavior is unspecified if the value is not representable as ui...
static constexpr SerParams V2_NETWORK
size_t BlockTxCount() const
std::vector< CTransactionRef > vtx
The block chain is a tree shaped structure starting with the genesis block at the root,...
CBlockIndex * pprev
pointer to the index of the predecessor of this block
CBlockHeader GetBlockHeader() const
arith_uint256 nChainWork
(memory only) Total amount of work (expected number of hashes) in the chain up to and including this ...
bool HaveNumChainTxs() const
Check whether this block and all previous blocks back to the genesis block or an assumeutxo snapshot ...
uint256 GetBlockHash() const
int64_t GetBlockTime() const
unsigned int nTx
Number of transactions in this block.
bool IsValid(enum BlockStatus nUpTo=BLOCK_VALID_TRANSACTIONS) const EXCLUSIVE_LOCKS_REQUIRED(
Check whether this block index entry is valid up to the passed validity level.
CBlockIndex * GetAncestor(int height)
Efficiently find an ancestor of this block.
int nHeight
height of the entry in the chain. The genesis block has height 0
FlatFilePos GetBlockPos() const EXCLUSIVE_LOCKS_REQUIRED(
BloomFilter is a probabilistic filter which SPV clients provide so that we can filter the transaction...
bool IsWithinSizeConstraints() const
True if the size is <= MAX_BLOOM_FILTER_SIZE and the number of hash functions is <= MAX_HASH_FUNCS (c...
An in-memory indexed chain of blocks.
CBlockIndex * Next(const CBlockIndex *pindex) const
Find the successor of a block in this chain, or nullptr if the given index is not found or is the tip...
CBlockIndex * Tip() const
Returns the index entry for the tip of this chain, or nullptr if none.
int Height() const
Return the maximal height in the chain.
bool Contains(const CBlockIndex *pindex) const
Efficiently check whether a block is present in this chain.
CChainParams defines various tweakable parameters of a given instance of the Bitcoin system.
const Consensus::Params & GetConsensus() const
void ForEachNode(const NodeFn &func)
RecursiveMutex & GetNodesMutex() const LOCK_RETURNED(m_nodes_mutex)
bool ForNode(NodeId id, std::function< bool(CNode *pnode)> func)
bool GetNetworkActive() const
bool GetTryNewOutboundPeer() const
void SetTryNewOutboundPeer(bool flag)
int GetExtraBlockRelayCount() const
void WakeMessageHandler() EXCLUSIVE_LOCKS_REQUIRED(!mutexMsgProc)
bool OutboundTargetReached(bool historicalBlockServingLimit) const EXCLUSIVE_LOCKS_REQUIRED(!m_total_bytes_sent_mutex)
check if the outbound target is reached if param historicalBlockServingLimit is set true,...
void StartExtraBlockRelayPeers()
bool DisconnectNode(const std::string &node)
CSipHasher GetDeterministicRandomizer(uint64_t id) const
Get a unique deterministic randomizer.
uint32_t GetMappedAS(const CNetAddr &addr) const
int GetExtraFullOutboundCount() const
std::vector< CAddress > GetAddresses(size_t max_addresses, size_t max_pct, std::optional< Network > network, const bool filtered=true) const
Return all or many randomly selected addresses, optionally by network.
bool CheckIncomingNonce(uint64_t nonce)
bool ShouldRunInactivityChecks(const CNode &node, std::chrono::seconds now) const
Return true if we should disconnect the peer for failing an inactivity check.
bool GetUseAddrmanOutgoing() const
Fee rate in satoshis per kilovirtualbyte: CAmount / kvB.
CAmount GetFeePerK() const
Return the fee in satoshis for a vsize of 1000 vbytes.
bool IsMsgCmpctBlk() const
std::string ToString() const
bool IsMsgFilteredBlk() const
bool IsMsgWitnessBlk() const
Used to relay blocks as header + vector<merkle branch> to filtered nodes.
std::vector< std::pair< unsigned int, uint256 > > vMatchedTxn
Public only for unit testing and relay testing (not relayed).
bool IsRelayable() const
Whether this address should be relayed to other peers even if we can't reach it ourselves.
static constexpr SerParams V1
bool IsAddrV1Compatible() const
Check if the current object can be serialized in pre-ADDRv2/BIP155 format.
Transport protocol agnostic message container.
Information about a peer.
bool IsFeelerConn() const
const std::chrono::seconds m_connected
Unix epoch time at peer connection.
bool ExpectServicesFromConn() const
std::atomic< int > nVersion
std::atomic_bool m_has_all_wanted_services
Whether this peer provides all services that we want.
bool IsInboundConn() const
bool HasPermission(NetPermissionFlags permission) const
bool IsOutboundOrBlockRelayConn() const
bool IsManualConn() const
std::atomic< int64_t > nTimeOffset
const std::string m_addr_name
std::string ConnectionTypeAsString() const
void SetCommonVersion(int greatest_common_version)
std::atomic< bool > m_bip152_highbandwidth_to
std::atomic_bool m_relays_txs
Whether we should relay transactions to this peer.
std::atomic< bool > m_bip152_highbandwidth_from
void PongReceived(std::chrono::microseconds ping_time)
A ping-pong round trip has completed successfully.
std::atomic_bool fSuccessfullyConnected
fSuccessfullyConnected is set to true on receiving VERACK from the peer.
bool IsAddrFetchConn() const
uint64_t GetLocalNonce() const
void SetAddrLocal(const CService &addrLocalIn) EXCLUSIVE_LOCKS_REQUIRED(!m_addr_local_mutex)
May not be called more than once.
bool IsBlockOnlyConn() const
int GetCommonVersion() const
bool IsFullOutboundConn() const
std::atomic_bool fPauseSend
std::optional< std::pair< CNetMessage, bool > > PollMessage() EXCLUSIVE_LOCKS_REQUIRED(!m_msg_process_queue_mutex)
Poll the next message from the processing queue of this connection.
std::atomic_bool m_bloom_filter_loaded
Whether this peer has loaded a bloom filter.
const std::unique_ptr< Transport > m_transport
Transport serializer/deserializer.
const bool m_inbound_onion
Whether this peer is an inbound onion, i.e. connected via our Tor onion service.
std::atomic< std::chrono::seconds > m_last_block_time
UNIX epoch time of the last block received from this peer that we had not yet seen (e....
std::atomic_bool fDisconnect
std::atomic< std::chrono::seconds > m_last_tx_time
UNIX epoch time of the last transaction received from this peer that we had not yet seen (e....
RollingBloomFilter is a probabilistic "keep track of most recently inserted" set.
Simple class for background tasks that should be run periodically or once "after a while".
void scheduleEvery(Function f, std::chrono::milliseconds delta) EXCLUSIVE_LOCKS_REQUIRED(!newTaskMutex)
Repeat f until the scheduler is stopped.
void scheduleFromNow(Function f, std::chrono::milliseconds delta) EXCLUSIVE_LOCKS_REQUIRED(!newTaskMutex)
Call f once after the delta has passed.
A combination of a network address (CNetAddr) and a (TCP) port.
std::string ToStringAddrPort() const
std::vector< unsigned char > GetKey() const
uint64_t Finalize() const
Compute the 64-bit SipHash-2-4 of the data written so far.
CSipHasher & Write(uint64_t data)
Hash a 64-bit integer worth of data It is treated as if this was the little-endian interpretation of ...
The basic transaction that is broadcasted on the network and contained in blocks.
const Txid & GetHash() const LIFETIMEBOUND
const Wtxid & GetWitnessHash() const LIFETIMEBOUND
const std::vector< CTxIn > vin
An input of a transaction.
CTxMemPool stores valid-according-to-the-current-best-chain transactions that may be included in the ...
void RemoveUnbroadcastTx(const uint256 &txid, const bool unchecked=false)
Removes a transaction from the unbroadcast set.
RecursiveMutex cs
This mutex needs to be locked when accessing mapTx or other members that are guarded by it.
CFeeRate GetMinFee(size_t sizelimit) const
CTransactionRef get(const uint256 &hash) const
size_t DynamicMemoryUsage() const
std::vector< TxMempoolInfo > infoAll() const
TxMempoolInfo info(const GenTxid >xid) const
std::set< uint256 > GetUnbroadcastTxs() const
Returns transactions in unbroadcast set.
const CFeeRate m_min_relay_feerate
uint64_t GetSequence() const EXCLUSIVE_LOCKS_REQUIRED(cs)
TxMempoolInfo info_for_relay(const GenTxid >xid, uint64_t last_sequence) const
Returns info for a transaction if its entry_sequence < last_sequence.
bool exists(const GenTxid >xid) const
unsigned long size() const
virtual void NewPoWValidBlock(const CBlockIndex *pindex, const std::shared_ptr< const CBlock > &block)
Notifies listeners that a block which builds directly on our current tip has been received and connec...
virtual void BlockConnected(ChainstateRole role, const std::shared_ptr< const CBlock > &block, const CBlockIndex *pindex)
Notifies listeners of a block being connected.
virtual void BlockChecked(const CBlock &, const BlockValidationState &)
Notifies listeners of a block validation result.
virtual void UpdatedBlockTip(const CBlockIndex *pindexNew, const CBlockIndex *pindexFork, bool fInitialDownload)
Notifies listeners when the block chain tip advances.
virtual void BlockDisconnected(const std::shared_ptr< const CBlock > &block, const CBlockIndex *pindex)
Notifies listeners of a block being disconnected Provides the block that was disconnected.
Provides an interface for creating and interacting with one or two chainstates: an IBD chainstate gen...
CChain & ActiveChain() const EXCLUSIVE_LOCKS_REQUIRED(GetMutex())
SnapshotCompletionResult MaybeCompleteSnapshotValidation() EXCLUSIVE_LOCKS_REQUIRED(const CBlockIndex *GetSnapshotBaseBlock() const EXCLUSIVE_LOCKS_REQUIRED(Chainstate ActiveChainstate)() const
Once the background validation chainstate has reached the height which is the base of the UTXO snapsh...
const arith_uint256 & MinimumChainWork() const
MempoolAcceptResult ProcessTransaction(const CTransactionRef &tx, bool test_accept=false) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
Try to add a transaction to the memory pool.
bool IsInitialBlockDownload() const
Check whether we are doing an initial block download (synchronizing from disk or network)
RecursiveMutex & GetMutex() const LOCK_RETURNED(
Alias for cs_main.
bool ProcessNewBlock(const std::shared_ptr< const CBlock > &block, bool force_processing, bool min_pow_checked, bool *new_block) LOCKS_EXCLUDED(cs_main)
Process an incoming block.
bool BackgroundSyncInProgress() const EXCLUSIVE_LOCKS_REQUIRED(GetMutex())
The state of a background sync (for net processing)
CBlockIndex * ActiveTip() const EXCLUSIVE_LOCKS_REQUIRED(GetMutex())
const CBlockIndex * GetBackgroundSyncTip() const EXCLUSIVE_LOCKS_REQUIRED(GetMutex())
The tip of the background sync chain.
void ReportHeadersPresync(const arith_uint256 &work, int64_t height, int64_t timestamp)
This is used by net_processing to report pre-synchronization progress of headers, as headers are not ...
bool ProcessNewBlockHeaders(const std::vector< CBlockHeader > &block, bool min_pow_checked, BlockValidationState &state, const CBlockIndex **ppindex=nullptr) LOCKS_EXCLUDED(cs_main)
Process incoming block headers.
node::BlockManager m_blockman
A single BlockManager instance is shared across each constructed chainstate to avoid duplicating bloc...
Double ended buffer combining vector and stream-like interfaces.
void ignore(size_t num_ignore)
A generic txid reference (txid or wtxid).
const uint256 & GetHash() const LIFETIMEBOUND
static GenTxid Wtxid(const uint256 &hash)
static GenTxid Txid(const uint256 &hash)
static Mutex g_msgproc_mutex
Mutex for anything that is only accessed via the msg processing thread.
virtual bool SendMessages(CNode *pnode) EXCLUSIVE_LOCKS_REQUIRED(g_msgproc_mutex)=0
Send queued protocol messages to a given node.
virtual void FinalizeNode(const CNode &node)=0
Handle removal of a peer (clear state)
virtual bool HasAllDesirableServiceFlags(ServiceFlags services) const =0
Callback to determine whether the given set of service flags are sufficient for a peer to be "relevan...
virtual bool ProcessMessages(CNode *pnode, std::atomic< bool > &interrupt) EXCLUSIVE_LOCKS_REQUIRED(g_msgproc_mutex)=0
Process protocol messages received from a given node.
virtual void InitializeNode(CNode &node, ServiceFlags our_services)=0
Initialize a peer (setup state, queue any initial messages)
static bool HasFlag(NetPermissionFlags flags, NetPermissionFlags f)
ReadStatus InitData(const CBlockHeaderAndShortTxIDs &cmpctblock, const std::vector< CTransactionRef > &extra_txn)
bool IsTxAvailable(size_t index) const
ReadStatus FillBlock(CBlock &block, const std::vector< CTransactionRef > &vtx_missing)
virtual void ProcessMessage(CNode &pfrom, const std::string &msg_type, DataStream &vRecv, const std::chrono::microseconds time_received, const std::atomic< bool > &interruptMsgProc) EXCLUSIVE_LOCKS_REQUIRED(g_msgproc_mutex)=0
Process a single message from a peer.
static std::unique_ptr< PeerManager > make(CConnman &connman, AddrMan &addrman, BanMan *banman, ChainstateManager &chainman, CTxMemPool &pool, Options opts)
virtual void SendPings()=0
Send ping message to all peers.
virtual std::optional< std::string > FetchBlock(NodeId peer_id, const CBlockIndex &block_index)=0
Attempt to manually fetch block from a given peer.
virtual ServiceFlags GetDesirableServiceFlags(ServiceFlags services) const =0
Gets the set of service flags which are "desirable" for a given peer.
virtual void StartScheduledTasks(CScheduler &scheduler)=0
Begin running background tasks, should only be called once.
virtual bool IgnoresIncomingTxs()=0
Whether this node ignores txs received over p2p.
virtual void UnitTestMisbehaving(NodeId peer_id, int howmuch)=0
virtual bool GetNodeStateStats(NodeId nodeid, CNodeStateStats &stats) const =0
Get statistics from node state.
virtual void UpdateLastBlockAnnounceTime(NodeId node, int64_t time_in_seconds)=0
This function is used for testing the stale tip eviction logic, see denialofservice_tests....
virtual void CheckForStaleTipAndEvictPeers()=0
Evict extra outbound peers.
bool Contains(Network net) const EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
A Span is an object that can refer to a contiguous sequence of objects.
A class to track orphan transactions (failed on TX_MISSING_INPUTS) Since we cannot distinguish orphan...
bool HaveTxToReconsider(NodeId peer) EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
Does this peer have any work to do?
void AddChildrenToWorkSet(const CTransaction &tx) EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
Add any orphans that list a particular tx as a parent into the from peer's work set.
void LimitOrphans(unsigned int max_orphans, FastRandomContext &rng) EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
Limit the orphanage to the given maximum.
void EraseForBlock(const CBlock &block) EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
Erase all orphans included in or invalidated by a new block.
bool AddTx(const CTransactionRef &tx, NodeId peer) EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
Add a new orphan transaction.
bool HaveTx(const GenTxid >xid) const EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
Check if we already have an orphan transaction (by txid or wtxid)
size_t Size() EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
Return how many entries exist in the orphange.
CTransactionRef GetTxToReconsider(NodeId peer) EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
Extract a transaction from a peer's work set Returns nullptr if there are no transactions to work on.
int EraseTx(const Txid &txid) EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
Erase an orphan by txid.
void EraseForPeer(NodeId peer) EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
Erase all orphans announced by a peer (eg, after that peer disconnects)
Data structure to keep track of, and schedule, transaction downloads from peers.
std::string ToString() const
256-bit unsigned big integer.
constexpr bool IsNull() const
std::string ToString() const
bool ReadBlockFromDisk(CBlock &block, const FlatFilePos &pos) const
Functions for disk access for blocks.
CBlockIndex * LookupBlockIndex(const uint256 &hash) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
bool ReadRawBlockFromDisk(std::vector< uint8_t > &block, const FlatFilePos &pos) const
bool LoadingBlocks() const
bool IsPruneMode() const
Whether running in -prune mode.
std::string ToString() const
const uint256 & ToUint256() const LIFETIMEBOUND
std::string TransportTypeAsString(TransportProtocolType transport_type)
Convert TransportProtocolType enum to a string value.
@ BLOCK_CHECKPOINT
the block failed to meet one of our checkpoints
@ BLOCK_RECENT_CONSENSUS_CHANGE
Invalid by a change to consensus rules more recent than SegWit.
@ BLOCK_HEADER_LOW_WORK
the block header may be on a too-little-work chain
@ BLOCK_INVALID_HEADER
invalid proof of work or time too old
@ BLOCK_CACHED_INVALID
this block was cached as being invalid and we didn't store the reason why
@ BLOCK_CONSENSUS
invalid by consensus rules (excluding any below reasons)
@ BLOCK_MISSING_PREV
We don't have the previous block the checked one is built on.
@ BLOCK_INVALID_PREV
A block this one builds on is invalid.
@ BLOCK_MUTATED
the block's data didn't match the data committed to by the PoW
@ BLOCK_TIME_FUTURE
block timestamp was > 2 hours in the future (or our clock is bad)
@ BLOCK_RESULT_UNSET
initial value. Block has not yet been rejected
@ TX_MISSING_INPUTS
transaction was missing some of its inputs
@ TX_MEMPOOL_POLICY
violated mempool's fee/size/descendant/RBF/etc limits
@ TX_UNKNOWN
transaction was not validated because package failed
@ TX_PREMATURE_SPEND
transaction spends a coinbase too early, or violates locktime/sequence locks
@ TX_INPUTS_NOT_STANDARD
inputs (covered by txid) failed policy rules
@ TX_WITNESS_STRIPPED
Transaction is missing a witness.
@ TX_CONFLICT
Tx already in mempool or conflicts with a tx in the chain (if it conflicts with another tx in mempool...
@ TX_RECENT_CONSENSUS_CHANGE
Invalid by a change to consensus rules more recent than SegWit.
@ TX_NOT_STANDARD
otherwise didn't meet our local policy rules
@ TX_WITNESS_MUTATED
Transaction might have a witness prior to SegWit activation, or witness may have been malleated (whic...
@ TX_NO_MEMPOOL
this node does not have a mempool so can't validate the transaction
@ TX_RESULT_UNSET
initial value. Tx has not yet been rejected
@ TX_CONSENSUS
invalid by consensus rules
@ TX_RECONSIDERABLE
fails some policy, but might be acceptable if submitted in a (different) package
static size_t RecursiveDynamicUsage(const CScript &script)
RecursiveMutex cs_main
Mutex to guard access to validation specific variables, such as reading or changing the chainstate.
bool DeploymentActiveAfter(const CBlockIndex *pindexPrev, const Consensus::Params ¶ms, Consensus::BuriedDeployment dep, [[maybe_unused]] VersionBitsCache &versionbitscache)
Determine if a deployment is active for the next block.
bool DeploymentActiveAt(const CBlockIndex &index, const Consensus::Params ¶ms, Consensus::BuriedDeployment dep, [[maybe_unused]] VersionBitsCache &versionbitscache)
Determine if a deployment is active for this block.
ChainstateRole
This enum describes the various roles a specific Chainstate instance can take.
#define LogPrintLevel(category, level,...)
#define LogPrint(category,...)
static bool LogAcceptCategory(BCLog::LogFlags category, BCLog::Level level)
Return true if log accepts specified category, at the specified level.
#define LogDebug(category,...)
Transaction validation functions.
CSerializedNetMsg Make(std::string msg_type, Args &&... args)
const char * FILTERLOAD
The filterload message tells the receiving peer to filter all relayed transactions and requested merk...
const char * CFHEADERS
cfheaders is a response to a getcfheaders request containing a filter header and a vector of filter h...
const char * CFILTER
cfilter is a response to a getcfilters request containing a single compact filter.
const char * BLOCK
The block message transmits a single serialized block.
const char * FILTERCLEAR
The filterclear message tells the receiving peer to remove a previously-set bloom filter.
const char * HEADERS
The headers message sends one or more block headers to a node which previously requested certain head...
const char * ADDRV2
The addrv2 message relays connection information for peers on the network just like the addr message,...
const char * SENDHEADERS
Indicates that a node prefers to receive new block announcements via a "headers" message rather than ...
const char * PONG
The pong message replies to a ping message, proving to the pinging node that the ponging node is stil...
const char * SENDCMPCT
Contains a 1-byte bool and 8-byte LE version number.
const char * GETADDR
The getaddr message requests an addr message from the receiving node, preferably one with lots of IP ...
const char * GETCFCHECKPT
getcfcheckpt requests evenly spaced compact filter headers, enabling parallelized download and valida...
const char * NOTFOUND
The notfound message is a reply to a getdata message which requested an object the receiving node doe...
const char * CMPCTBLOCK
Contains a CBlockHeaderAndShortTxIDs object - providing a header and list of "short txids".
const char * SENDTXRCNCL
Contains a 4-byte version number and an 8-byte salt.
const char * MEMPOOL
The mempool message requests the TXIDs of transactions that the receiving node has verified as valid ...
const char * GETCFILTERS
getcfilters requests compact filters for a range of blocks.
const char * TX
The tx message transmits a single transaction.
const char * FILTERADD
The filteradd message tells the receiving peer to add a single element to a previously-set bloom filt...
const char * ADDR
The addr (IP address) message relays connection information for peers on the network.
const char * VERSION
The version message provides information about the transmitting node to the receiving node at the beg...
const char * GETBLOCKS
The getblocks message requests an inv message that provides block header hashes starting from a parti...
const char * FEEFILTER
The feefilter message tells the receiving peer not to inv us any txs which do not meet the specified ...
const char * GETHEADERS
The getheaders message requests a headers message that provides block headers starting from a particu...
const char * GETDATA
The getdata message requests one or more data objects from another node.
const char * VERACK
The verack message acknowledges a previously-received version message, informing the connecting node ...
const char * BLOCKTXN
Contains a BlockTransactions.
const char * GETCFHEADERS
getcfheaders requests a compact filter header and the filter hashes for a range of blocks,...
const char * SENDADDRV2
The sendaddrv2 message signals support for receiving ADDRV2 messages (BIP155).
const char * WTXIDRELAY
Indicates that a node prefers to relay transactions via wtxid, rather than txid.
const char * PING
The ping message is sent periodically to help confirm that the receiving peer is still connected.
const char * MERKLEBLOCK
The merkleblock message is a reply to a getdata message which requested a block using the inventory t...
const char * CFCHECKPT
cfcheckpt is a response to a getcfcheckpt request containing a vector of evenly spaced filter headers...
const char * GETBLOCKTXN
Contains a BlockTransactionsRequest Peer should respond with "blocktxn" message.
const char * INV
The inv message (inventory message) transmits one or more inventories of objects known to the transmi...
Functions to serialize / deserialize common bitcoin types.
std::optional< CService > GetLocalAddrForPeer(CNode &node)
Returns a local address that we should advertise to this peer.
std::string strSubVersion
Subversion as sent to the P2P network in version messages.
std::function< void(const CAddress &addr, const std::string &msg_type, Span< const unsigned char > data, bool is_incoming)> CaptureMessage
Defaults to CaptureMessageToFile(), but can be overridden by unit tests.
bool SeenLocal(const CService &addr)
vote for a local address
static const unsigned int MAX_SUBVERSION_LENGTH
Maximum length of the user agent string in version message.
static constexpr std::chrono::minutes TIMEOUT_INTERVAL
Time after which to disconnect, after waiting for a ping response (or inactivity).
static constexpr auto HEADERS_RESPONSE_TIME
How long to wait for a peer to respond to a getheaders request.
static constexpr size_t MAX_ADDR_TO_SEND
The maximum number of address records permitted in an ADDR message.
static constexpr size_t MAX_ADDR_PROCESSING_TOKEN_BUCKET
The soft limit of the address processing token bucket (the regular MAX_ADDR_RATE_PER_SECOND based inc...
static const int MAX_BLOCKS_IN_TRANSIT_PER_PEER
Number of blocks that can be requested at any given time from a single peer.
static constexpr auto BLOCK_STALLING_TIMEOUT_DEFAULT
Default time during which a peer must stall block download progress before being disconnected.
static constexpr auto AVG_FEEFILTER_BROADCAST_INTERVAL
Average delay between feefilter broadcasts in seconds.
static constexpr auto EXTRA_PEER_CHECK_INTERVAL
How frequently to check for extra outbound peers and disconnect.
static const unsigned int BLOCK_DOWNLOAD_WINDOW
Size of the "block download window": how far ahead of our current height do we fetch?...
static constexpr int STALE_RELAY_AGE_LIMIT
Age after which a stale block will no longer be served if requested as protection against fingerprint...
static constexpr int HISTORICAL_BLOCK_AGE
Age after which a block is considered historical for purposes of rate limiting block relay.
static constexpr auto ROTATE_ADDR_RELAY_DEST_INTERVAL
Delay between rotating the peers we relay a particular address to.
static const int MAX_NUM_UNCONNECTING_HEADERS_MSGS
Maximum number of unconnecting headers announcements before DoS score.
static constexpr auto MINIMUM_CONNECT_TIME
Minimum time an outbound-peer-eviction candidate must be connected for, in order to evict.
static constexpr auto CHAIN_SYNC_TIMEOUT
Timeout for (unprotected) outbound peers to sync to our chainwork.
static constexpr auto OUTBOUND_INVENTORY_BROADCAST_INTERVAL
Average delay between trickled inventory transmissions for outbound peers.
static const unsigned int NODE_NETWORK_LIMITED_MIN_BLOCKS
Minimum blocks required to signal NODE_NETWORK_LIMITED.
static constexpr auto AVG_LOCAL_ADDRESS_BROADCAST_INTERVAL
Average delay between local address broadcasts.
static const int MAX_BLOCKTXN_DEPTH
Maximum depth of blocks we're willing to respond to GETBLOCKTXN requests for.
static constexpr int32_t MAX_PEER_TX_REQUEST_IN_FLIGHT
Maximum number of in-flight transaction requests from a peer.
static constexpr uint64_t CMPCTBLOCKS_VERSION
The compactblocks version we support.
static constexpr auto OVERLOADED_PEER_TX_DELAY
How long to delay requesting transactions from overloaded peers (see MAX_PEER_TX_REQUEST_IN_FLIGHT).
static constexpr int32_t MAX_OUTBOUND_PEERS_TO_PROTECT_FROM_DISCONNECT
Protect at least this many outbound peers from disconnection due to slow/ behind headers chain.
static constexpr auto INBOUND_INVENTORY_BROADCAST_INTERVAL
Average delay between trickled inventory transmissions for inbound peers.
static constexpr auto MAX_FEEFILTER_CHANGE_DELAY
Maximum feefilter broadcast delay after significant change.
static constexpr uint32_t MAX_GETCFILTERS_SIZE
Maximum number of compact filters that may be requested with one getcfilters.
static constexpr auto HEADERS_DOWNLOAD_TIMEOUT_BASE
Headers download timeout.
static const unsigned int MAX_GETDATA_SZ
Limit to avoid sending big packets.
static constexpr double BLOCK_DOWNLOAD_TIMEOUT_BASE
Block download timeout base, expressed in multiples of the block interval (i.e.
static constexpr auto STALE_CHECK_INTERVAL
How frequently to check for stale tips.
static constexpr auto AVG_ADDRESS_BROADCAST_INTERVAL
Average delay between peer address broadcasts.
static const unsigned int MAX_LOCATOR_SZ
The maximum number of entries in a locator.
static constexpr unsigned int INVENTORY_BROADCAST_TARGET
Target number of tx inventory items to send per transmission.
static constexpr int32_t MAX_PEER_TX_ANNOUNCEMENTS
Maximum number of transactions to consider for requesting, per peer.
static constexpr auto TXID_RELAY_DELAY
How long to delay requesting transactions via txids, if we have wtxid-relaying peers.
static constexpr double BLOCK_DOWNLOAD_TIMEOUT_PER_PEER
Additional block download timeout per parallel downloading peer (i.e.
static constexpr double MAX_ADDR_RATE_PER_SECOND
The maximum rate of address records we're willing to process on average.
static constexpr auto PING_INTERVAL
Time between pings automatically sent out for latency probing and keepalive.
static const int MAX_CMPCTBLOCK_DEPTH
Maximum depth of blocks we're willing to serve as compact blocks to peers when requested.
static constexpr auto GETDATA_TX_INTERVAL
How long to wait before downloading a transaction from an additional peer.
static const unsigned int MAX_BLOCKS_TO_ANNOUNCE
Maximum number of headers to announce when relaying blocks with headers message.
static const unsigned int NODE_NETWORK_LIMITED_ALLOW_CONN_BLOCKS
Window, in blocks, for connecting to NODE_NETWORK_LIMITED peers.
static constexpr uint32_t MAX_GETCFHEADERS_SIZE
Maximum number of cf hashes that may be requested with one getcfheaders.
static constexpr auto BLOCK_STALLING_TIMEOUT_MAX
Maximum timeout for stalling block download.
static constexpr auto HEADERS_DOWNLOAD_TIMEOUT_PER_HEADER
static constexpr uint64_t RANDOMIZER_ID_ADDRESS_RELAY
SHA256("main address relay")[0:8].
static constexpr unsigned int INVENTORY_BROADCAST_MAX
Maximum number of inventory items to send per transmission.
static const unsigned int MAX_HEADERS_RESULTS
Number of headers sent in one getheaders result.
static constexpr size_t MAX_PCT_ADDR_TO_SEND
the maximum percentage of addresses from our addrman to return in response to a getaddr message.
static const unsigned int MAX_INV_SZ
The maximum number of entries in an 'inv' protocol message.
static constexpr auto NONPREF_PEER_TX_DELAY
How long to delay requesting transactions from non-preferred peers.
static constexpr unsigned int INVENTORY_BROADCAST_PER_SECOND
Maximum rate of inventory items to send per second.
static const unsigned int MAX_CMPCTBLOCKS_INFLIGHT_PER_BLOCK
Maximum number of outstanding CMPCTBLOCK requests for the same block.
static const int DISCOURAGEMENT_THRESHOLD
Threshold for marking a node to be discouraged, e.g.
ReachableNets g_reachable_nets
bool IsProxy(const CNetAddr &addr)
static constexpr unsigned int DEFAULT_MIN_RELAY_TX_FEE
Default for -minrelaytxfee, minimum relay fee for transactions.
static constexpr TransactionSerParams TX_NO_WITNESS
static constexpr TransactionSerParams TX_WITH_WITNESS
std::shared_ptr< const CTransaction > CTransactionRef
GenTxid ToGenTxid(const CInv &inv)
Convert a TX/WITNESS_TX/WTX CInv to a GenTxid.
const uint32_t MSG_WITNESS_FLAG
getdata message type flags
@ MSG_WTX
Defined in BIP 339.
@ MSG_CMPCT_BLOCK
Defined in BIP152.
@ MSG_WITNESS_BLOCK
Defined in BIP144.
ServiceFlags
nServices flags
static bool MayHaveUsefulAddressDB(ServiceFlags services)
Checks if a peer with the given service flags may be capable of having a robust address-storage DB.
static const int WTXID_RELAY_VERSION
"wtxidrelay" command for wtxid-based relay starts with this version
static const int SHORT_IDS_BLOCKS_VERSION
short-id-based block download starts with this version
static const int SENDHEADERS_VERSION
"sendheaders" command and announcing blocks with headers starts with this version
static const int PROTOCOL_VERSION
network protocol versioning
static const int FEEFILTER_VERSION
"feefilter" tells peers to filter invs to you by fee starts with this version
static const int MIN_PEER_PROTO_VERSION
disconnect from peers older than this proto version
static const int INVALID_CB_NO_BAN_VERSION
not banning for invalid compact blocks starts with this version
static const int BIP0031_VERSION
BIP 0031, pong message, is enabled for all versions AFTER this one.
std::chrono::microseconds GetExponentialRand(std::chrono::microseconds now, std::chrono::seconds average_interval)
Return a timestamp in the future sampled from an exponential distribution (https://en....
constexpr auto GetRandMillis
void Shuffle(I first, I last, R &&rng)
More efficient than using std::shuffle on a FastRandomContext.
reverse_range< T > reverse_iterate(T &x)
static const unsigned int MAX_SCRIPT_ELEMENT_SIZE
#define LIMITED_STRING(obj, n)
uint64_t ReadCompactSize(Stream &is, bool range_check=true)
Decode a CompactSize-encoded variable-length integer.
constexpr auto MakeUCharSpan(V &&v) -> decltype(UCharSpanCast(Span{std::forward< V >(v)}))
Like the Span constructor, but for (const) unsigned char member types only.
std::vector< Byte > ParseHex(std::string_view hex_str)
Like TryParseHex, but returns an empty vector on invalid input.
std::string ToString(const T &t)
Locale-independent version of std::to_string.
Describes a place in the block chain to another node such that if the other node doesn't have the sam...
std::vector< uint256 > vHave
std::chrono::microseconds m_ping_wait
std::vector< int > vHeightInFlight
CAmount m_fee_filter_received
bool m_addr_relay_enabled
uint64_t m_addr_rate_limited
uint64_t m_addr_processed
ServiceFlags their_services
Parameters that influence chain consensus.
int64_t nPowTargetSpacing
std::chrono::seconds PowTargetSpacing() const
Validation result for a transaction evaluated by MemPoolAccept (single or package).
const ResultType m_result_type
Result type.
const std::optional< std::list< CTransactionRef > > m_replaced_transactions
Mempool transactions replaced by the tx.
const TxValidationState m_state
Contains information about why the transaction failed.
static time_point now() noexcept
Return current system time or mocked time, if set.
std::chrono::time_point< NodeClock > time_point
#define AssertLockNotHeld(cs)
#define WITH_LOCK(cs, code)
Run code while locking a mutex.
#define EXCLUSIVE_LOCKS_REQUIRED(...)
#define LOCKS_EXCLUDED(...)
constexpr int64_t count_microseconds(std::chrono::microseconds t)
constexpr int64_t count_seconds(std::chrono::seconds t)
std::chrono::time_point< NodeClock, std::chrono::seconds > NodeSeconds
void AddTimeData(const CNetAddr &ip, int64_t nOffsetSample)
#define TRACE6(context, event, a, b, c, d, e, f)
ReconciliationRegisterResult
static constexpr uint32_t TXRECONCILIATION_VERSION
Supported transaction reconciliation protocol version.
std::string SanitizeString(std::string_view str, int rule)
Remove unsafe chars.
bool IsBlockMutated(const CBlock &block, bool check_witness_root)
Check if a block has been mutated (with respect to its merkle root and witness commitments).
bool HasValidProofOfWork(const std::vector< CBlockHeader > &headers, const Consensus::Params &consensusParams)
Check with the proof of work on each blockheader matches the value in nBits.
arith_uint256 CalculateClaimedHeadersWork(const std::vector< CBlockHeader > &headers)
Return the sum of the claimed work on a given set of headers.
static const unsigned int MIN_BLOCKS_TO_KEEP
Block files containing a block-height within MIN_BLOCKS_TO_KEEP of ActiveChain().Tip() will not be pr...