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);
596 bool ProcessOrphanTx(Peer& peer)
606 void ProcessHeadersMessage(
CNode& pfrom, Peer& peer,
608 bool via_compact_block)
620 bool CheckHeadersAreContinuous(const
std::vector<
CBlockHeader>& headers) const;
639 bool IsContinuationOfLowWorkHeadersSync(Peer& peer,
CNode& pfrom,
653 bool TryLowWorkHeadersSync(Peer& peer,
CNode& pfrom,
668 void HeadersDirectFetchBlocks(
CNode& pfrom, const Peer& peer, const
CBlockIndex& last_header);
670 void UpdatePeerStateForReceivedHeaders(
CNode& pfrom, Peer& peer, const
CBlockIndex& last_header,
bool received_new_header,
bool may_have_more_headers)
678 void AddTxAnnouncement(const
CNode&
node, const
GenTxid& gtxid,
std::chrono::microseconds current_time)
683 template <
typename... Args>
684 void MakeAndPushMessage(
CNode&
node, std::string msg_type, Args&&...
args)
const 690 void PushNodeVersion(
CNode& pnode,
const Peer& peer);
696 void MaybeSendPing(
CNode& node_to, Peer& peer, std::chrono::microseconds now);
728 std::unique_ptr<TxReconciliationTracker> m_txreconciliation;
731 std::atomic<int> m_best_height{-1};
733 std::atomic<std::chrono::seconds> m_best_block_time{0s};
738 const Options m_opts;
740 bool RejectIncomingTxs(
const CNode& peer)
const;
748 mutable Mutex m_peer_mutex;
755 std::map<NodeId, PeerRef> m_peer_map
GUARDED_BY(m_peer_mutex);
765 uint32_t GetFetchFlags(
const Peer& peer)
const;
767 std::atomic<std::chrono::microseconds> m_next_inv_to_inbounds{0us};
784 std::atomic<int> m_wtxid_relay_peers{0};
795 bool AlreadyHaveTx(
const GenTxid& gtxid)
850 Mutex m_recent_confirmed_transactions_mutex;
859 std::chrono::microseconds NextInvToInbounds(std::chrono::microseconds now,
860 std::chrono::seconds average_interval);
864 Mutex m_most_recent_block_mutex;
865 std::shared_ptr<const CBlock> m_most_recent_block
GUARDED_BY(m_most_recent_block_mutex);
866 std::shared_ptr<const CBlockHeaderAndShortTxIDs> m_most_recent_compact_block
GUARDED_BY(m_most_recent_block_mutex);
868 std::unique_ptr<const std::map<uint256, CTransactionRef>> m_most_recent_block_txs
GUARDED_BY(m_most_recent_block_mutex);
872 Mutex m_headers_presync_mutex;
880 using HeadersPresyncStats = std::pair<arith_uint256, std::optional<std::pair<int64_t, uint32_t>>>;
882 std::map<NodeId, HeadersPresyncStats> m_headers_presync_stats
GUARDED_BY(m_headers_presync_mutex) {};
886 std::atomic_bool m_headers_presync_should_signal{
false};
956 std::atomic<
std::chrono::seconds> m_last_tip_update{0s};
962 void ProcessGetData(
CNode& pfrom, Peer& peer,
const std::atomic<bool>& interruptMsgProc)
967 void ProcessBlock(
CNode&
node,
const std::shared_ptr<const CBlock>& block,
bool force_processing,
bool min_pow_checked);
995 std::vector<std::pair<uint256, CTransactionRef>> vExtraTxnForCompact
GUARDED_BY(g_msgproc_mutex);
997 size_t vExtraTxnForCompactIt
GUARDED_BY(g_msgproc_mutex) = 0;
1009 int64_t ApproximateBestBlockDepth() const;
1019 void ProcessGetBlockData(
CNode& pfrom, Peer& peer, const
CInv& inv)
1037 bool PrepareBlockFilterRequest(
CNode&
node, Peer& peer,
1039 const
uint256& stop_hash, uint32_t max_height_diff,
1090 std::map<NodeId, CNodeState>::const_iterator it = m_node_states.find(pnode);
1091 if (it == m_node_states.end())
1098 return const_cast<CNodeState*
>(std::as_const(*this).State(pnode));
1106 static bool IsAddrCompatible(
const Peer& peer,
const CAddress& addr)
1111 void PeerManagerImpl::AddAddressKnown(Peer& peer,
const CAddress& addr)
1113 assert(peer.m_addr_known);
1114 peer.m_addr_known->insert(addr.
GetKey());
1117 void PeerManagerImpl::PushAddress(Peer& peer,
const CAddress& addr)
1122 assert(peer.m_addr_known);
1123 if (addr.
IsValid() && !peer.m_addr_known->contains(addr.
GetKey()) && IsAddrCompatible(peer, addr)) {
1125 peer.m_addrs_to_send[m_rng.randrange(peer.m_addrs_to_send.size())] = addr;
1127 peer.m_addrs_to_send.push_back(addr);
1132 static void AddKnownTx(Peer& peer,
const uint256& hash)
1134 auto tx_relay = peer.GetTxRelay();
1135 if (!tx_relay)
return;
1137 LOCK(tx_relay->m_tx_inventory_mutex);
1138 tx_relay->m_tx_inventory_known_filter.insert(hash);
1142 static bool CanServeBlocks(
const Peer& peer)
1149 static bool IsLimitedPeer(
const Peer& peer)
1156 static bool CanServeWitnesses(
const Peer& peer)
1161 std::chrono::microseconds PeerManagerImpl::NextInvToInbounds(std::chrono::microseconds now,
1162 std::chrono::seconds average_interval)
1164 if (m_next_inv_to_inbounds.load() < now) {
1170 return m_next_inv_to_inbounds;
1173 bool PeerManagerImpl::IsBlockRequested(
const uint256& hash)
1175 return mapBlocksInFlight.count(hash);
1178 bool PeerManagerImpl::IsBlockRequestedFromOutbound(
const uint256& hash)
1180 for (
auto range = mapBlocksInFlight.equal_range(hash); range.first != range.second; range.first++) {
1181 auto [nodeid, block_it] = range.first->second;
1183 if (!nodestate.m_is_inbound)
return true;
1189 void PeerManagerImpl::RemoveBlockRequest(
const uint256& hash, std::optional<NodeId> from_peer)
1191 auto range = mapBlocksInFlight.equal_range(hash);
1192 if (range.first == range.second) {
1200 while (range.first != range.second) {
1201 auto [node_id, list_it] = range.first->second;
1203 if (from_peer && *from_peer != node_id) {
1210 if (state.vBlocksInFlight.begin() == list_it) {
1212 state.m_downloading_since = std::max(state.m_downloading_since, GetTime<std::chrono::microseconds>());
1214 state.vBlocksInFlight.erase(list_it);
1216 if (state.vBlocksInFlight.empty()) {
1218 m_peers_downloading_from--;
1220 state.m_stalling_since = 0us;
1222 range.first = mapBlocksInFlight.erase(range.first);
1226 bool PeerManagerImpl::BlockRequested(
NodeId nodeid,
const CBlockIndex& block, std::list<QueuedBlock>::iterator** pit)
1230 CNodeState *state =
State(nodeid);
1231 assert(state !=
nullptr);
1236 for (
auto range = mapBlocksInFlight.equal_range(hash); range.first != range.second; range.first++) {
1237 if (range.first->second.first == nodeid) {
1239 *pit = &range.first->second.second;
1246 RemoveBlockRequest(hash, nodeid);
1248 std::list<QueuedBlock>::iterator it = state->vBlocksInFlight.insert(state->vBlocksInFlight.end(),
1250 if (state->vBlocksInFlight.size() == 1) {
1252 state->m_downloading_since = GetTime<std::chrono::microseconds>();
1253 m_peers_downloading_from++;
1255 auto itInFlight = mapBlocksInFlight.insert(std::make_pair(hash, std::make_pair(nodeid, it)));
1257 *pit = &itInFlight->second.second;
1262 void PeerManagerImpl::MaybeSetPeerAsAnnouncingHeaderAndIDs(
NodeId nodeid)
1269 if (m_opts.ignore_incoming_txs)
return;
1271 CNodeState* nodestate =
State(nodeid);
1272 if (!nodestate || !nodestate->m_provides_cmpctblocks) {
1277 int num_outbound_hb_peers = 0;
1278 for (std::list<NodeId>::iterator it = lNodesAnnouncingHeaderAndIDs.begin(); it != lNodesAnnouncingHeaderAndIDs.end(); it++) {
1279 if (*it == nodeid) {
1280 lNodesAnnouncingHeaderAndIDs.erase(it);
1281 lNodesAnnouncingHeaderAndIDs.push_back(nodeid);
1284 CNodeState *state =
State(*it);
1285 if (state !=
nullptr && !state->m_is_inbound) ++num_outbound_hb_peers;
1287 if (nodestate->m_is_inbound) {
1290 if (lNodesAnnouncingHeaderAndIDs.size() >= 3 && num_outbound_hb_peers == 1) {
1291 CNodeState *remove_node =
State(lNodesAnnouncingHeaderAndIDs.front());
1292 if (remove_node !=
nullptr && !remove_node->m_is_inbound) {
1295 std::swap(lNodesAnnouncingHeaderAndIDs.front(), *std::next(lNodesAnnouncingHeaderAndIDs.begin()));
1301 if (lNodesAnnouncingHeaderAndIDs.size() >= 3) {
1304 m_connman.
ForNode(lNodesAnnouncingHeaderAndIDs.front(), [
this](
CNode* pnodeStop){
1307 pnodeStop->m_bip152_highbandwidth_to =
false;
1310 lNodesAnnouncingHeaderAndIDs.pop_front();
1315 lNodesAnnouncingHeaderAndIDs.push_back(pfrom->
GetId());
1320 bool PeerManagerImpl::TipMayBeStale()
1324 if (m_last_tip_update.load() == 0s) {
1325 m_last_tip_update = GetTime<std::chrono::seconds>();
1327 return m_last_tip_update.load() < GetTime<std::chrono::seconds>() - std::chrono::seconds{consensusParams.
nPowTargetSpacing * 3} && mapBlocksInFlight.empty();
1330 int64_t PeerManagerImpl::ApproximateBestBlockDepth()
const 1335 bool PeerManagerImpl::CanDirectFetch()
1342 if (state->pindexBestKnownBlock && pindex == state->pindexBestKnownBlock->GetAncestor(pindex->nHeight))
1344 if (state->pindexBestHeaderSent && pindex == state->pindexBestHeaderSent->GetAncestor(pindex->nHeight))
1349 void PeerManagerImpl::ProcessBlockAvailability(
NodeId nodeid) {
1350 CNodeState *state =
State(nodeid);
1351 assert(state !=
nullptr);
1353 if (!state->hashLastUnknownBlock.IsNull()) {
1356 if (state->pindexBestKnownBlock ==
nullptr || pindex->
nChainWork >= state->pindexBestKnownBlock->nChainWork) {
1357 state->pindexBestKnownBlock = pindex;
1359 state->hashLastUnknownBlock.SetNull();
1364 void PeerManagerImpl::UpdateBlockAvailability(
NodeId nodeid,
const uint256 &hash) {
1365 CNodeState *state =
State(nodeid);
1366 assert(state !=
nullptr);
1368 ProcessBlockAvailability(nodeid);
1373 if (state->pindexBestKnownBlock ==
nullptr || pindex->
nChainWork >= state->pindexBestKnownBlock->nChainWork) {
1374 state->pindexBestKnownBlock = pindex;
1378 state->hashLastUnknownBlock = hash;
1383 void PeerManagerImpl::FindNextBlocksToDownload(
const Peer& peer,
unsigned int count, std::vector<const CBlockIndex*>& vBlocks,
NodeId& nodeStaller)
1388 vBlocks.reserve(vBlocks.size() +
count);
1389 CNodeState *state =
State(peer.m_id);
1390 assert(state !=
nullptr);
1393 ProcessBlockAvailability(peer.m_id);
1395 if (state->pindexBestKnownBlock ==
nullptr || state->pindexBestKnownBlock->nChainWork < m_chainman.
ActiveChain().
Tip()->
nChainWork || state->pindexBestKnownBlock->nChainWork < m_chainman.
MinimumChainWork()) {
1400 if (state->pindexLastCommonBlock ==
nullptr) {
1403 state->pindexLastCommonBlock = m_chainman.
ActiveChain()[std::min(state->pindexBestKnownBlock->nHeight, m_chainman.
ActiveChain().
Height())];
1408 state->pindexLastCommonBlock =
LastCommonAncestor(state->pindexLastCommonBlock, state->pindexBestKnownBlock);
1409 if (state->pindexLastCommonBlock == state->pindexBestKnownBlock)
1412 const CBlockIndex *pindexWalk = state->pindexLastCommonBlock;
1418 FindNextBlocks(vBlocks, peer, state, pindexWalk,
count, nWindowEnd, &m_chainman.
ActiveChain(), &nodeStaller);
1421 void PeerManagerImpl::TryDownloadingHistoricalBlocks(
const Peer& peer,
unsigned int count, std::vector<const CBlockIndex*>& vBlocks,
const CBlockIndex *from_tip,
const CBlockIndex* target_block)
1426 if (vBlocks.size() >=
count) {
1430 vBlocks.reserve(
count);
1433 if (state->pindexBestKnownBlock ==
nullptr || state->pindexBestKnownBlock->GetAncestor(target_block->
nHeight) != target_block) {
1450 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)
1452 std::vector<const CBlockIndex*> vToFetch;
1453 int nMaxHeight = std::min<int>(state->pindexBestKnownBlock->nHeight, nWindowEnd + 1);
1455 while (pindexWalk->
nHeight < nMaxHeight) {
1459 int nToFetch = std::min(nMaxHeight - pindexWalk->
nHeight, std::max<int>(
count - vBlocks.size(), 128));
1460 vToFetch.resize(nToFetch);
1461 pindexWalk = state->pindexBestKnownBlock->GetAncestor(pindexWalk->
nHeight + nToFetch);
1462 vToFetch[nToFetch - 1] = pindexWalk;
1463 for (
unsigned int i = nToFetch - 1; i > 0; i--) {
1464 vToFetch[i - 1] = vToFetch[i]->
pprev;
1482 state->pindexLastCommonBlock = pindex;
1483 }
else if (!IsBlockRequested(pindex->
GetBlockHash())) {
1485 if (pindex->
nHeight > nWindowEnd) {
1487 if (vBlocks.size() == 0 && waitingfor != peer.m_id) {
1489 if (nodeStaller) *nodeStaller = waitingfor;
1493 vBlocks.push_back(pindex);
1494 if (vBlocks.size() ==
count) {
1497 }
else if (waitingfor == -1) {
1499 waitingfor = mapBlocksInFlight.lower_bound(pindex->
GetBlockHash())->second.first;
1507 void PeerManagerImpl::PushNodeVersion(
CNode& pnode,
const Peer& peer)
1509 uint64_t my_services{peer.m_our_services};
1510 const int64_t nTime{
count_seconds(GetTime<std::chrono::seconds>())};
1512 const int nNodeStartingHeight{m_best_height};
1519 const bool tx_relay{!RejectIncomingTxs(pnode)};
1526 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);
1532 void PeerManagerImpl::AddTxAnnouncement(
const CNode&
node,
const GenTxid& gtxid, std::chrono::microseconds current_time)
1540 const CNodeState* state =
State(nodeid);
1550 const bool preferred = state->fPreferredDownload;
1556 m_txrequest.ReceivedInv(nodeid, gtxid, preferred, current_time + delay);
1559 void PeerManagerImpl::UpdateLastBlockAnnounceTime(
NodeId node, int64_t time_in_seconds)
1563 if (state) state->m_last_block_announcement = time_in_seconds;
1571 m_node_states.emplace_hint(m_node_states.end(), std::piecewise_construct, std::forward_as_tuple(nodeid), std::forward_as_tuple(
node.IsInboundConn()));
1572 assert(m_txrequest.Count(nodeid) == 0);
1574 PeerRef peer = std::make_shared<Peer>(nodeid, our_services);
1577 m_peer_map.emplace_hint(m_peer_map.end(), nodeid, peer);
1579 if (!
node.IsInboundConn()) {
1580 PushNodeVersion(
node, *peer);
1584 void PeerManagerImpl::ReattemptInitialBroadcast(
CScheduler& scheduler)
1588 for (
const auto& txid : unbroadcast_txids) {
1591 if (tx !=
nullptr) {
1600 const std::chrono::milliseconds delta = 10min +
GetRandMillis(5min);
1601 scheduler.
scheduleFromNow([&] { ReattemptInitialBroadcast(scheduler); }, delta);
1604 void PeerManagerImpl::FinalizeNode(
const CNode&
node)
1616 PeerRef peer = RemovePeer(nodeid);
1618 misbehavior =
WITH_LOCK(peer->m_misbehavior_mutex,
return peer->m_misbehavior_score);
1619 m_wtxid_relay_peers -= peer->m_wtxid_relay;
1620 assert(m_wtxid_relay_peers >= 0);
1622 CNodeState *state =
State(nodeid);
1623 assert(state !=
nullptr);
1625 if (state->fSyncStarted)
1628 for (
const QueuedBlock& entry : state->vBlocksInFlight) {
1629 auto range = mapBlocksInFlight.equal_range(entry.pindex->GetBlockHash());
1630 while (range.first != range.second) {
1631 auto [node_id, list_it] = range.first->second;
1632 if (node_id != nodeid) {
1635 range.first = mapBlocksInFlight.erase(range.first);
1640 m_txrequest.DisconnectedPeer(nodeid);
1641 if (m_txreconciliation) m_txreconciliation->ForgetPeer(nodeid);
1642 m_num_preferred_download_peers -= state->fPreferredDownload;
1643 m_peers_downloading_from -= (!state->vBlocksInFlight.empty());
1644 assert(m_peers_downloading_from >= 0);
1645 m_outbound_peers_with_protect_from_disconnect -= state->m_chain_sync.m_protect;
1646 assert(m_outbound_peers_with_protect_from_disconnect >= 0);
1648 m_node_states.erase(nodeid);
1650 if (m_node_states.empty()) {
1652 assert(mapBlocksInFlight.empty());
1653 assert(m_num_preferred_download_peers == 0);
1654 assert(m_peers_downloading_from == 0);
1655 assert(m_outbound_peers_with_protect_from_disconnect == 0);
1656 assert(m_wtxid_relay_peers == 0);
1657 assert(m_txrequest.Size() == 0);
1661 if (
node.fSuccessfullyConnected && misbehavior == 0 &&
1662 !
node.IsBlockOnlyConn() && !
node.IsInboundConn()) {
1669 LOCK(m_headers_presync_mutex);
1670 m_headers_presync_stats.erase(nodeid);
1675 bool PeerManagerImpl::HasAllDesirableServiceFlags(
ServiceFlags services)
const 1692 PeerRef PeerManagerImpl::GetPeerRef(
NodeId id)
const 1695 auto it = m_peer_map.find(
id);
1696 return it != m_peer_map.end() ? it->second :
nullptr;
1699 PeerRef PeerManagerImpl::RemovePeer(
NodeId id)
1703 auto it = m_peer_map.find(
id);
1704 if (it != m_peer_map.end()) {
1705 ret = std::move(it->second);
1706 m_peer_map.erase(it);
1715 const CNodeState* state =
State(nodeid);
1716 if (state ==
nullptr)
1718 stats.
nSyncHeight = state->pindexBestKnownBlock ? state->pindexBestKnownBlock->nHeight : -1;
1719 stats.
nCommonHeight = state->pindexLastCommonBlock ? state->pindexLastCommonBlock->nHeight : -1;
1720 for (
const QueuedBlock& queue : state->vBlocksInFlight) {
1726 PeerRef peer = GetPeerRef(nodeid);
1727 if (peer ==
nullptr)
return false;
1736 auto ping_wait{0us};
1737 if ((0 != peer->m_ping_nonce_sent) && (0 != peer->m_ping_start.load().count())) {
1738 ping_wait = GetTime<std::chrono::microseconds>() - peer->m_ping_start.load();
1741 if (
auto tx_relay = peer->GetTxRelay(); tx_relay !=
nullptr) {
1754 LOCK(peer->m_headers_sync_mutex);
1755 if (peer->m_headers_sync) {
1763 void PeerManagerImpl::AddToCompactExtraTransactions(
const CTransactionRef& tx)
1765 if (m_opts.max_extra_txs <= 0)
1767 if (!vExtraTxnForCompact.size())
1768 vExtraTxnForCompact.resize(m_opts.max_extra_txs);
1769 vExtraTxnForCompact[vExtraTxnForCompactIt] = std::make_pair(tx->GetWitnessHash(), tx);
1770 vExtraTxnForCompactIt = (vExtraTxnForCompactIt + 1) % m_opts.max_extra_txs;
1773 void PeerManagerImpl::Misbehaving(Peer& peer,
int howmuch,
const std::string& message)
1777 LOCK(peer.m_misbehavior_mutex);
1778 const int score_before{peer.m_misbehavior_score};
1779 peer.m_misbehavior_score += howmuch;
1780 const int score_now{peer.m_misbehavior_score};
1782 const std::string message_prefixed = message.empty() ?
"" : (
": " + message);
1783 std::string warning;
1786 warning =
" DISCOURAGE THRESHOLD EXCEEDED";
1787 peer.m_should_discourage =
true;
1791 peer.m_id, score_before, score_now, warning, message_prefixed);
1795 bool via_compact_block,
const std::string& message)
1797 PeerRef peer{GetPeerRef(nodeid)};
1808 if (!via_compact_block) {
1809 if (peer) Misbehaving(*peer, 100, message);
1816 CNodeState *node_state =
State(nodeid);
1817 if (node_state ==
nullptr) {
1823 if (!via_compact_block && !node_state->m_is_inbound) {
1824 if (peer) Misbehaving(*peer, 100, message);
1832 if (peer) Misbehaving(*peer, 100, message);
1837 if (peer) Misbehaving(*peer, 10, message);
1843 if (message !=
"") {
1851 PeerRef peer{GetPeerRef(nodeid)};
1857 if (peer) Misbehaving(*peer, 100,
"");
1877 bool PeerManagerImpl::BlockRequestAllowed(
const CBlockIndex* pindex)
1886 std::optional<std::string> PeerManagerImpl::FetchBlock(
NodeId peer_id,
const CBlockIndex& block_index)
1891 PeerRef peer = GetPeerRef(peer_id);
1892 if (peer ==
nullptr)
return "Peer does not exist";
1895 if (!CanServeWitnesses(*peer))
return "Pre-SegWit peer";
1900 RemoveBlockRequest(block_index.
GetBlockHash(), std::nullopt);
1903 if (!BlockRequested(peer_id, block_index))
return "Already requested from this peer";
1915 if (!success)
return "Peer not fully connected";
1919 return std::nullopt;
1926 return std::make_unique<PeerManagerImpl>(connman, addrman, banman, chainman, pool, opts);
1932 : m_rng{opts.deterministic_rng},
1934 m_chainparams(chainman.GetParams()),
1938 m_chainman(chainman),
1944 if (opts.reconcile_txs) {
1949 void PeerManagerImpl::StartScheduledTasks(
CScheduler& scheduler)
1959 const std::chrono::milliseconds delta = 10min +
GetRandMillis(5min);
1960 scheduler.
scheduleFromNow([&] { ReattemptInitialBroadcast(scheduler); }, delta);
1969 void PeerManagerImpl::BlockConnected(
1971 const std::shared_ptr<const CBlock>& pblock,
1976 m_last_tip_update = GetTime<std::chrono::seconds>();
1979 auto stalling_timeout = m_block_stalling_timeout.load();
1983 if (m_block_stalling_timeout.compare_exchange_strong(stalling_timeout, new_timeout)) {
1996 LOCK(m_recent_confirmed_transactions_mutex);
1997 for (
const auto& ptx : pblock->vtx) {
1998 m_recent_confirmed_transactions.insert(ptx->GetHash().ToUint256());
1999 if (ptx->HasWitness()) {
2000 m_recent_confirmed_transactions.insert(ptx->GetWitnessHash().ToUint256());
2006 for (
const auto& ptx : pblock->vtx) {
2007 m_txrequest.ForgetTxHash(ptx->GetHash());
2008 m_txrequest.ForgetTxHash(ptx->GetWitnessHash());
2013 void PeerManagerImpl::BlockDisconnected(
const std::shared_ptr<const CBlock> &block,
const CBlockIndex* pindex)
2023 LOCK(m_recent_confirmed_transactions_mutex);
2024 m_recent_confirmed_transactions.reset();
2031 void PeerManagerImpl::NewPoWValidBlock(
const CBlockIndex *pindex,
const std::shared_ptr<const CBlock>& pblock)
2033 auto pcmpctblock = std::make_shared<const CBlockHeaderAndShortTxIDs>(*pblock);
2037 if (pindex->
nHeight <= m_highest_fast_announce)
2039 m_highest_fast_announce = pindex->
nHeight;
2043 uint256 hashBlock(pblock->GetHash());
2044 const std::shared_future<CSerializedNetMsg> lazy_ser{
2048 auto most_recent_block_txs = std::make_unique<std::map<uint256, CTransactionRef>>();
2049 for (
const auto& tx : pblock->vtx) {
2050 most_recent_block_txs->emplace(tx->GetHash(), tx);
2051 most_recent_block_txs->emplace(tx->GetWitnessHash(), tx);
2054 LOCK(m_most_recent_block_mutex);
2055 m_most_recent_block_hash = hashBlock;
2056 m_most_recent_block = pblock;
2057 m_most_recent_compact_block = pcmpctblock;
2058 m_most_recent_block_txs = std::move(most_recent_block_txs);
2066 ProcessBlockAvailability(pnode->
GetId());
2070 if (state.m_requested_hb_cmpctblocks && !PeerHasHeader(&state, pindex) && PeerHasHeader(&state, pindex->
pprev)) {
2072 LogPrint(
BCLog::NET,
"%s sending header-and-ids %s to peer=%d\n",
"PeerManager::NewPoWValidBlock",
2073 hashBlock.ToString(), pnode->
GetId());
2076 PushMessage(*pnode, ser_cmpctblock.Copy());
2077 state.pindexBestHeaderSent = pindex;
2086 void PeerManagerImpl::UpdatedBlockTip(
const CBlockIndex *pindexNew,
const CBlockIndex *pindexFork,
bool fInitialDownload)
2088 SetBestBlock(pindexNew->
nHeight, std::chrono::seconds{pindexNew->GetBlockTime()});
2091 if (fInitialDownload)
return;
2094 std::vector<uint256> vHashes;
2096 while (pindexToAnnounce != pindexFork) {
2098 pindexToAnnounce = pindexToAnnounce->
pprev;
2108 for (
auto& it : m_peer_map) {
2109 Peer& peer = *it.second;
2110 LOCK(peer.m_block_inv_mutex);
2112 peer.m_blocks_for_headers_relay.push_back(hash);
2129 std::map<uint256, std::pair<NodeId, bool>>::iterator it = mapBlockSource.find(hash);
2134 it != mapBlockSource.end() &&
2135 State(it->second.first)) {
2136 MaybePunishNodeForBlock( it->second.first, state, !it->second.second);
2146 mapBlocksInFlight.count(hash) == mapBlocksInFlight.size()) {
2147 if (it != mapBlockSource.end()) {
2148 MaybeSetPeerAsAnnouncingHeaderAndIDs(it->second.first);
2151 if (it != mapBlockSource.end())
2152 mapBlockSource.erase(it);
2161 bool PeerManagerImpl::AlreadyHaveTx(
const GenTxid& gtxid)
2169 m_recent_rejects.reset();
2174 if (m_orphanage.
HaveTx(gtxid))
return true;
2177 LOCK(m_recent_confirmed_transactions_mutex);
2178 if (m_recent_confirmed_transactions.contains(hash))
return true;
2181 return m_recent_rejects.contains(hash) || m_mempool.
exists(gtxid);
2184 bool PeerManagerImpl::AlreadyHaveBlock(
const uint256& block_hash)
2189 void PeerManagerImpl::SendPings()
2192 for(
auto& it : m_peer_map) it.second->m_ping_queued =
true;
2195 void PeerManagerImpl::RelayTransaction(
const uint256& txid,
const uint256& wtxid)
2198 for(
auto& it : m_peer_map) {
2199 Peer& peer = *it.second;
2200 auto tx_relay = peer.GetTxRelay();
2201 if (!tx_relay)
continue;
2203 LOCK(tx_relay->m_tx_inventory_mutex);
2209 if (tx_relay->m_next_inv_send_time == 0s)
continue;
2211 const uint256& hash{peer.m_wtxid_relay ? wtxid : txid};
2212 if (!tx_relay->m_tx_inventory_known_filter.contains(hash)) {
2213 tx_relay->m_tx_inventory_to_send.insert(hash);
2218 void PeerManagerImpl::RelayAddress(
NodeId originator,
2234 const auto current_time{GetTime<std::chrono::seconds>()};
2242 unsigned int nRelayNodes = (fReachable || (hasher.Finalize() & 1)) ? 2 : 1;
2244 std::array<std::pair<uint64_t, Peer*>, 2> best{{{0,
nullptr}, {0,
nullptr}}};
2245 assert(nRelayNodes <= best.size());
2249 for (
auto& [
id, peer] : m_peer_map) {
2250 if (peer->m_addr_relay_enabled &&
id != originator && IsAddrCompatible(*peer, addr)) {
2252 for (
unsigned int i = 0; i < nRelayNodes; i++) {
2253 if (hashKey > best[i].first) {
2254 std::copy(best.begin() + i, best.begin() + nRelayNodes - 1, best.begin() + i + 1);
2255 best[i] = std::make_pair(hashKey, peer.get());
2262 for (
unsigned int i = 0; i < nRelayNodes && best[i].first != 0; i++) {
2263 PushAddress(*best[i].second, addr);
2267 void PeerManagerImpl::ProcessGetBlockData(
CNode& pfrom, Peer& peer,
const CInv& inv)
2269 std::shared_ptr<const CBlock> a_recent_block;
2270 std::shared_ptr<const CBlockHeaderAndShortTxIDs> a_recent_compact_block;
2272 LOCK(m_most_recent_block_mutex);
2273 a_recent_block = m_most_recent_block;
2274 a_recent_compact_block = m_most_recent_compact_block;
2277 bool need_activate_chain =
false;
2289 need_activate_chain =
true;
2293 if (need_activate_chain) {
2295 if (!m_chainman.
ActiveChainstate().ActivateBestChain(state, a_recent_block)) {
2305 if (!BlockRequestAllowed(pindex)) {
2306 LogPrint(
BCLog::NET,
"%s: ignoring request from peer=%i for old block that isn't in the main chain\n", __func__, pfrom.
GetId());
2322 LogPrint(
BCLog::NET,
"Ignore block request below NODE_NETWORK_LIMITED threshold, disconnect peer=%d\n", pfrom.
GetId());
2332 std::shared_ptr<const CBlock> pblock;
2333 if (a_recent_block && a_recent_block->GetHash() == pindex->
GetBlockHash()) {
2334 pblock = a_recent_block;
2338 std::vector<uint8_t> block_data;
2340 assert(!
"cannot load block from disk");
2346 std::shared_ptr<CBlock> pblockRead = std::make_shared<CBlock>();
2348 assert(!
"cannot load block from disk");
2350 pblock = pblockRead;
2358 bool sendMerkleBlock =
false;
2360 if (
auto tx_relay = peer.GetTxRelay(); tx_relay !=
nullptr) {
2361 LOCK(tx_relay->m_bloom_filter_mutex);
2362 if (tx_relay->m_bloom_filter) {
2363 sendMerkleBlock =
true;
2364 merkleBlock =
CMerkleBlock(*pblock, *tx_relay->m_bloom_filter);
2367 if (sendMerkleBlock) {
2375 typedef std::pair<unsigned int, uint256> PairType;
2387 if (a_recent_compact_block && a_recent_compact_block->header.GetHash() == pindex->
GetBlockHash()) {
2400 LOCK(peer.m_block_inv_mutex);
2402 if (inv.
hash == peer.m_continuation_block) {
2406 std::vector<CInv> vInv;
2409 peer.m_continuation_block.SetNull();
2417 auto txinfo = m_mempool.
info_for_relay(gtxid, tx_relay.m_last_inv_sequence);
2419 return std::move(txinfo.tx);
2424 LOCK(m_most_recent_block_mutex);
2425 if (m_most_recent_block_txs !=
nullptr) {
2426 auto it = m_most_recent_block_txs->find(gtxid.
GetHash());
2427 if (it != m_most_recent_block_txs->end())
return it->second;
2434 void PeerManagerImpl::ProcessGetData(
CNode& pfrom, Peer& peer,
const std::atomic<bool>& interruptMsgProc)
2438 auto tx_relay = peer.GetTxRelay();
2440 std::deque<CInv>::iterator it = peer.m_getdata_requests.begin();
2441 std::vector<CInv> vNotFound;
2446 while (it != peer.m_getdata_requests.end() && it->IsGenTxMsg()) {
2447 if (interruptMsgProc)
return;
2452 const CInv &inv = *it++;
2454 if (tx_relay ==
nullptr) {
2464 MakeAndPushMessage(pfrom,
NetMsgType::TX, maybe_with_witness(*tx));
2467 vNotFound.push_back(inv);
2473 if (it != peer.m_getdata_requests.end() && !pfrom.
fPauseSend) {
2474 const CInv &inv = *it++;
2476 ProcessGetBlockData(pfrom, peer, inv);
2482 peer.m_getdata_requests.erase(peer.m_getdata_requests.begin(), it);
2484 if (!vNotFound.empty()) {
2503 uint32_t PeerManagerImpl::GetFetchFlags(
const Peer& peer)
const 2505 uint32_t nFetchFlags = 0;
2506 if (CanServeWitnesses(peer)) {
2515 for (
size_t i = 0; i < req.
indexes.size(); i++) {
2517 Misbehaving(peer, 100,
"getblocktxn with out-of-bounds tx indices");
2526 bool PeerManagerImpl::CheckHeadersPoW(
const std::vector<CBlockHeader>& headers,
const Consensus::Params& consensusParams, Peer& peer)
2530 Misbehaving(peer, 100,
"header with invalid proof of work");
2535 if (!CheckHeadersAreContinuous(headers)) {
2536 Misbehaving(peer, 20,
"non-continuous headers sequence");
2567 void PeerManagerImpl::HandleFewUnconnectingHeaders(
CNode& pfrom, Peer& peer,
2568 const std::vector<CBlockHeader>& headers)
2570 peer.m_num_unconnecting_headers_msgs++;
2573 if (MaybeSendGetHeaders(pfrom,
GetLocator(best_header), peer)) {
2574 LogPrint(
BCLog::NET,
"received header %s: missing prev block %s, sending getheaders (%d) to end (peer=%d, m_num_unconnecting_headers_msgs=%d)\n",
2576 headers[0].hashPrevBlock.ToString(),
2577 best_header->nHeight,
2578 pfrom.
GetId(), peer.m_num_unconnecting_headers_msgs);
2589 Misbehaving(peer, 20,
strprintf(
"%d non-connecting headers", peer.m_num_unconnecting_headers_msgs));
2593 bool PeerManagerImpl::CheckHeadersAreContinuous(
const std::vector<CBlockHeader>& headers)
const 2597 if (!hashLastBlock.
IsNull() && header.hashPrevBlock != hashLastBlock) {
2600 hashLastBlock = header.GetHash();
2605 bool PeerManagerImpl::IsContinuationOfLowWorkHeadersSync(Peer& peer,
CNode& pfrom, std::vector<CBlockHeader>& headers)
2607 if (peer.m_headers_sync) {
2608 auto result = peer.m_headers_sync->ProcessNextHeaders(headers, headers.size() ==
MAX_HEADERS_RESULTS);
2609 if (result.request_more) {
2610 auto locator = peer.m_headers_sync->NextHeadersRequestLocator();
2612 Assume(!locator.vHave.empty());
2613 if (!locator.vHave.empty()) {
2620 bool sent_getheaders = MaybeSendGetHeaders(pfrom, locator, peer);
2621 if (sent_getheaders) {
2623 locator.vHave.front().ToString(), pfrom.
GetId());
2625 LogPrint(
BCLog::NET,
"error sending next getheaders (from %s) to continue sync with peer=%d\n",
2626 locator.vHave.front().ToString(), pfrom.
GetId());
2632 peer.m_headers_sync.reset(
nullptr);
2637 LOCK(m_headers_presync_mutex);
2638 m_headers_presync_stats.erase(pfrom.
GetId());
2641 HeadersPresyncStats stats;
2642 stats.first = peer.m_headers_sync->GetPresyncWork();
2644 stats.second = {peer.m_headers_sync->GetPresyncHeight(),
2645 peer.m_headers_sync->GetPresyncTime()};
2649 LOCK(m_headers_presync_mutex);
2650 m_headers_presync_stats[pfrom.
GetId()] = stats;
2651 auto best_it = m_headers_presync_stats.find(m_headers_presync_bestpeer);
2652 bool best_updated =
false;
2653 if (best_it == m_headers_presync_stats.end()) {
2657 const HeadersPresyncStats* stat_best{
nullptr};
2658 for (
const auto& [peer, stat] : m_headers_presync_stats) {
2659 if (!stat_best || stat > *stat_best) {
2664 m_headers_presync_bestpeer = peer_best;
2665 best_updated = (peer_best == pfrom.
GetId());
2666 }
else if (best_it->first == pfrom.
GetId() || stats > best_it->second) {
2668 m_headers_presync_bestpeer = pfrom.
GetId();
2669 best_updated =
true;
2671 if (best_updated && stats.second.has_value()) {
2673 m_headers_presync_should_signal =
true;
2677 if (result.success) {
2680 headers.swap(result.pow_validated_headers);
2683 return result.success;
2691 bool PeerManagerImpl::TryLowWorkHeadersSync(Peer& peer,
CNode& pfrom,
const CBlockIndex* chain_start_header, std::vector<CBlockHeader>& headers)
2698 arith_uint256 minimum_chain_work = GetAntiDoSWorkThreshold();
2702 if (total_work < minimum_chain_work) {
2716 LOCK(peer.m_headers_sync_mutex);
2718 chain_start_header, minimum_chain_work));
2723 (void)IsContinuationOfLowWorkHeadersSync(peer, pfrom, headers);
2737 bool PeerManagerImpl::IsAncestorOfBestHeaderOrTip(
const CBlockIndex* header)
2739 if (header ==
nullptr) {
2741 }
else if (m_chainman.m_best_header !=
nullptr && header == m_chainman.m_best_header->GetAncestor(header->
nHeight)) {
2749 bool PeerManagerImpl::MaybeSendGetHeaders(
CNode& pfrom,
const CBlockLocator& locator, Peer& peer)
2757 peer.m_last_getheaders_timestamp = current_time;
2768 void PeerManagerImpl::HeadersDirectFetchBlocks(
CNode& pfrom,
const Peer& peer,
const CBlockIndex& last_header)
2771 CNodeState *nodestate =
State(pfrom.
GetId());
2774 std::vector<const CBlockIndex*> vToFetch;
2782 vToFetch.push_back(pindexWalk);
2784 pindexWalk = pindexWalk->
pprev;
2795 std::vector<CInv> vGetData;
2802 uint32_t nFetchFlags = GetFetchFlags(peer);
2804 BlockRequested(pfrom.
GetId(), *pindex);
2808 if (vGetData.size() > 1) {
2813 if (vGetData.size() > 0) {
2814 if (!m_opts.ignore_incoming_txs &&
2815 nodestate->m_provides_cmpctblocks &&
2816 vGetData.size() == 1 &&
2817 mapBlocksInFlight.size() == 1 &&
2833 void PeerManagerImpl::UpdatePeerStateForReceivedHeaders(
CNode& pfrom, Peer& peer,
2834 const CBlockIndex& last_header,
bool received_new_header,
bool may_have_more_headers)
2836 if (peer.m_num_unconnecting_headers_msgs > 0) {
2837 LogPrint(
BCLog::NET,
"peer=%d: resetting m_num_unconnecting_headers_msgs (%d -> 0)\n", pfrom.
GetId(), peer.m_num_unconnecting_headers_msgs);
2839 peer.m_num_unconnecting_headers_msgs = 0;
2842 CNodeState *nodestate =
State(pfrom.
GetId());
2851 nodestate->m_last_block_announcement =
GetTime();
2859 if (nodestate->pindexBestKnownBlock && nodestate->pindexBestKnownBlock->nChainWork < m_chainman.
MinimumChainWork()) {
2869 LogPrintf(
"Disconnecting outbound peer %d -- headers chain has insufficient work\n", pfrom.
GetId());
2881 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) {
2883 nodestate->m_chain_sync.m_protect =
true;
2884 ++m_outbound_peers_with_protect_from_disconnect;
2889 void PeerManagerImpl::ProcessHeadersMessage(
CNode& pfrom, Peer& peer,
2890 std::vector<CBlockHeader>&& headers,
2891 bool via_compact_block)
2893 size_t nCount = headers.size();
2900 LOCK(peer.m_headers_sync_mutex);
2901 if (peer.m_headers_sync) {
2902 peer.m_headers_sync.reset(
nullptr);
2903 LOCK(m_headers_presync_mutex);
2904 m_headers_presync_stats.erase(pfrom.
GetId());
2913 if (!CheckHeadersPoW(headers, m_chainparams.
GetConsensus(), peer)) {
2928 bool already_validated_work =
false;
2931 bool have_headers_sync =
false;
2933 LOCK(peer.m_headers_sync_mutex);
2935 already_validated_work = IsContinuationOfLowWorkHeadersSync(peer, pfrom, headers);
2947 if (headers.empty()) {
2951 have_headers_sync = !!peer.m_headers_sync;
2956 bool headers_connect_blockindex{chain_start_header !=
nullptr};
2958 if (!headers_connect_blockindex) {
2963 HandleFewUnconnectingHeaders(pfrom, peer, headers);
2965 Misbehaving(peer, 10,
"invalid header received");
2978 if (IsAncestorOfBestHeaderOrTip(last_received_header)) {
2979 already_validated_work =
true;
2987 already_validated_work =
true;
2993 if (!already_validated_work && TryLowWorkHeadersSync(peer, pfrom,
2994 chain_start_header, headers)) {
3006 bool received_new_header{last_received_header ==
nullptr};
3012 MaybePunishNodeForBlock(pfrom.
GetId(), state, via_compact_block,
"invalid header received");
3021 if (MaybeSendGetHeaders(pfrom,
GetLocator(pindexLast), peer)) {
3023 pindexLast->
nHeight, pfrom.
GetId(), peer.m_starting_height);
3027 UpdatePeerStateForReceivedHeaders(pfrom, peer, *pindexLast, received_new_header, nCount ==
MAX_HEADERS_RESULTS);
3030 HeadersDirectFetchBlocks(pfrom, peer, *pindexLast);
3035 bool PeerManagerImpl::ProcessOrphanTx(Peer& peer)
3045 const Txid& orphanHash = porphanTx->GetHash();
3046 const Wtxid& orphan_wtxid = porphanTx->GetWitnessHash();
3055 RelayTransaction(orphanHash, porphanTx->GetWitnessHash());
3057 m_orphanage.
EraseTx(orphanHash);
3059 AddToCompactExtraTransactions(removedTx);
3075 MaybePunishNodeForTx(peer.m_id, state);
3094 m_recent_rejects.insert(porphanTx->GetWitnessHash().ToUint256());
3106 m_recent_rejects.insert(porphanTx->GetHash().ToUint256());
3109 m_orphanage.
EraseTx(orphanHash);
3117 bool PeerManagerImpl::PrepareBlockFilterRequest(
CNode&
node, Peer& peer,
3119 const uint256& stop_hash, uint32_t max_height_diff,
3123 const bool supported_filter_type =
3126 if (!supported_filter_type) {
3128 node.GetId(),
static_cast<uint8_t
>(filter_type));
3129 node.fDisconnect =
true;
3138 if (!stop_index || !BlockRequestAllowed(stop_index)) {
3141 node.fDisconnect =
true;
3146 uint32_t stop_height = stop_index->
nHeight;
3147 if (start_height > stop_height) {
3149 "start height %d and stop height %d\n",
3150 node.GetId(), start_height, stop_height);
3151 node.fDisconnect =
true;
3154 if (stop_height - start_height >= max_height_diff) {
3156 node.GetId(), stop_height - start_height + 1, max_height_diff);
3157 node.fDisconnect =
true;
3162 if (!filter_index) {
3172 uint8_t filter_type_ser;
3173 uint32_t start_height;
3176 vRecv >> filter_type_ser >> start_height >> stop_hash;
3182 if (!PrepareBlockFilterRequest(
node, peer, filter_type, start_height, stop_hash,
3187 std::vector<BlockFilter> filters;
3189 LogPrint(
BCLog::NET,
"Failed to find block filter in index: filter_type=%s, start_height=%d, stop_hash=%s\n",
3194 for (
const auto& filter : filters) {
3201 uint8_t filter_type_ser;
3202 uint32_t start_height;
3205 vRecv >> filter_type_ser >> start_height >> stop_hash;
3211 if (!PrepareBlockFilterRequest(
node, peer, filter_type, start_height, stop_hash,
3217 if (start_height > 0) {
3219 stop_index->
GetAncestor(static_cast<int>(start_height - 1));
3221 LogPrint(
BCLog::NET,
"Failed to find block filter header in index: filter_type=%s, block_hash=%s\n",
3227 std::vector<uint256> filter_hashes;
3229 LogPrint(
BCLog::NET,
"Failed to find block filter hashes in index: filter_type=%s, start_height=%d, stop_hash=%s\n",
3243 uint8_t filter_type_ser;
3246 vRecv >> filter_type_ser >> stop_hash;
3252 if (!PrepareBlockFilterRequest(
node, peer, filter_type, 0, stop_hash,
3253 std::numeric_limits<uint32_t>::max(),
3254 stop_index, filter_index)) {
3262 for (
int i = headers.size() - 1; i >= 0; i--) {
3267 LogPrint(
BCLog::NET,
"Failed to find block filter header in index: filter_type=%s, block_hash=%s\n",
3279 void PeerManagerImpl::ProcessBlock(
CNode&
node,
const std::shared_ptr<const CBlock>& block,
bool force_processing,
bool min_pow_checked)
3281 bool new_block{
false};
3282 m_chainman.
ProcessNewBlock(block, force_processing, min_pow_checked, &new_block);
3284 node.m_last_block_time = GetTime<std::chrono::seconds>();
3289 RemoveBlockRequest(block->GetHash(), std::nullopt);
3292 mapBlockSource.erase(block->GetHash());
3296 void PeerManagerImpl::ProcessCompactBlockTxns(
CNode& pfrom, Peer& peer,
const BlockTransactions& block_transactions)
3298 std::shared_ptr<CBlock> pblock = std::make_shared<CBlock>();
3299 bool fBlockRead{
false};
3303 auto range_flight = mapBlocksInFlight.equal_range(block_transactions.
blockhash);
3304 size_t already_in_flight = std::distance(range_flight.first, range_flight.second);
3305 bool requested_block_from_this_peer{
false};
3308 bool first_in_flight = already_in_flight == 0 || (range_flight.first->second.first == pfrom.
GetId());
3310 while (range_flight.first != range_flight.second) {
3311 auto [node_id, block_it] = range_flight.first->second;
3312 if (node_id == pfrom.
GetId() && block_it->partialBlock) {
3313 requested_block_from_this_peer =
true;
3316 range_flight.first++;
3319 if (!requested_block_from_this_peer) {
3328 Misbehaving(peer, 100,
"invalid compact block/non-matching block transactions");
3331 if (first_in_flight) {
3333 std::vector<CInv> invs;
3338 LogPrint(
BCLog::NET,
"Peer %d sent us a compact block but it failed to reconstruct, waiting on first download to complete\n", pfrom.
GetId());
3367 mapBlockSource.emplace(block_transactions.
blockhash, std::make_pair(pfrom.
GetId(),
false));
3377 ProcessBlock(pfrom, pblock,
true,
true);
3382 void PeerManagerImpl::ProcessMessage(
CNode& pfrom,
const std::string& msg_type,
DataStream& vRecv,
3383 const std::chrono::microseconds time_received,
3384 const std::atomic<bool>& interruptMsgProc)
3390 PeerRef peer = GetPeerRef(pfrom.
GetId());
3391 if (peer ==
nullptr)
return;
3401 uint64_t nNonce = 1;
3404 std::string cleanSubVer;
3405 int starting_height = -1;
3408 vRecv >> nVersion >> Using<CustomUintFormatter<8>>(nServices) >> nTime;
3423 LogPrint(
BCLog::NET,
"peer=%d does not offer the expected services (%08x offered, %08x expected); disconnecting\n", pfrom.
GetId(), nServices, GetDesirableServiceFlags(nServices));
3435 if (!vRecv.
empty()) {
3443 if (!vRecv.
empty()) {
3444 std::string strSubVer;
3448 if (!vRecv.
empty()) {
3449 vRecv >> starting_height;
3469 PushNodeVersion(pfrom, *peer);
3482 if (greatest_common_version >= 70016) {
3491 peer->m_their_services = nServices;
3495 pfrom.cleanSubVer = cleanSubVer;
3497 peer->m_starting_height = starting_height;
3507 (fRelay || (peer->m_our_services &
NODE_BLOOM))) {
3508 auto*
const tx_relay = peer->SetTxRelay();
3510 LOCK(tx_relay->m_bloom_filter_mutex);
3511 tx_relay->m_relay_txs = fRelay;
3523 const auto* tx_relay = peer->GetTxRelay();
3524 if (tx_relay &&
WITH_LOCK(tx_relay->m_bloom_filter_mutex,
return tx_relay->m_relay_txs) &&
3526 const uint64_t recon_salt = m_txreconciliation->PreRegisterPeer(pfrom.
GetId());
3539 m_num_preferred_download_peers += state->fPreferredDownload;
3545 bool send_getaddr{
false};
3547 send_getaddr = SetupAddressRelay(pfrom, *peer);
3557 peer->m_getaddr_sent =
true;
3581 std::string remoteAddr;
3586 LogPrint(
BCLog::NET,
"receive version message: %s: version %d, blocks=%d, us=%s, txrelay=%d, peer=%d%s%s\n",
3589 remoteAddr, (mapped_as ?
strprintf(
", mapped_as=%d", mapped_as) :
""));
3591 int64_t nTimeOffset = nTime -
GetTime();
3600 if (greatest_common_version <= 70012) {
3601 const auto finalAlert{
ParseHex(
"60010000000000000000000000ffffff7f00000000ffffff7ffeffff7f01ffffff7f00000000ffffff7f00ffffff7f002f555247454e543a20416c657274206b657920636f6d70726f6d697365642c2075706772616465207265717569726564004630440220653febd6410f470f6bae11cad19c48413becb1ac2c17f908fd0fd53bdc3abd5202206d0e9c96fe88d4a0f01ed9dedae2b6f9e00da94cad0fecaae66ecf689bf71b50")};
3602 MakeAndPushMessage(pfrom,
"alert",
Span{finalAlert});
3629 LogPrintf(
"New %s %s peer connected: version: %d, blocks=%d, peer=%d%s%s\n",
3632 pfrom.
nVersion.load(), peer->m_starting_height,
3634 (mapped_as ?
strprintf(
", mapped_as=%d", mapped_as) :
""));
3646 if (m_txreconciliation) {
3647 if (!peer->m_wtxid_relay || !m_txreconciliation->IsPeerRegistered(pfrom.
GetId())) {
3651 m_txreconciliation->ForgetPeer(pfrom.
GetId());
3655 if (
auto tx_relay = peer->GetTxRelay()) {
3664 tx_relay->m_tx_inventory_mutex,
3665 return tx_relay->m_tx_inventory_to_send.empty() &&
3666 tx_relay->m_next_inv_send_time == 0s));
3674 peer->m_prefers_headers =
true;
3679 bool sendcmpct_hb{
false};
3680 uint64_t sendcmpct_version{0};
3681 vRecv >> sendcmpct_hb >> sendcmpct_version;
3687 CNodeState* nodestate =
State(pfrom.
GetId());
3688 nodestate->m_provides_cmpctblocks =
true;
3689 nodestate->m_requested_hb_cmpctblocks = sendcmpct_hb;
3706 if (!peer->m_wtxid_relay) {
3707 peer->m_wtxid_relay =
true;
3708 m_wtxid_relay_peers++;
3727 peer->m_wants_addrv2 =
true;
3735 if (!m_txreconciliation) {
3747 if (RejectIncomingTxs(pfrom)) {
3756 const auto* tx_relay = peer->GetTxRelay();
3757 if (!tx_relay || !
WITH_LOCK(tx_relay->m_bloom_filter_mutex,
return tx_relay->m_relay_txs)) {
3763 uint32_t peer_txreconcl_version;
3764 uint64_t remote_salt;
3765 vRecv >> peer_txreconcl_version >> remote_salt;
3768 peer_txreconcl_version, remote_salt);
3793 const auto ser_params{
3801 std::vector<CAddress> vAddr;
3803 vRecv >> ser_params(vAddr);
3805 if (!SetupAddressRelay(pfrom, *peer)) {
3812 Misbehaving(*peer, 20,
strprintf(
"%s message size = %u", msg_type, vAddr.size()));
3817 std::vector<CAddress> vAddrOk;
3818 const auto current_a_time{Now<NodeSeconds>()};
3821 const auto current_time{GetTime<std::chrono::microseconds>()};
3824 const auto time_diff = std::max(current_time - peer->m_addr_token_timestamp, 0us);
3828 peer->m_addr_token_timestamp = current_time;
3831 uint64_t num_proc = 0;
3832 uint64_t num_rate_limit = 0;
3833 Shuffle(vAddr.begin(), vAddr.end(), m_rng);
3836 if (interruptMsgProc)
3840 if (peer->m_addr_token_bucket < 1.0) {
3846 peer->m_addr_token_bucket -= 1.0;
3855 addr.
nTime = current_a_time - 5 * 24h;
3857 AddAddressKnown(*peer, addr);
3864 if (addr.
nTime > current_a_time - 10min && !peer->m_getaddr_sent && vAddr.size() <= 10 && addr.
IsRoutable()) {
3866 RelayAddress(pfrom.
GetId(), addr, reachable);
3870 vAddrOk.push_back(addr);
3873 peer->m_addr_processed += num_proc;
3874 peer->m_addr_rate_limited += num_rate_limit;
3875 LogPrint(
BCLog::NET,
"Received addr: %u addresses (%u processed, %u rate-limited) from peer=%d\n",
3876 vAddr.size(), num_proc, num_rate_limit, pfrom.
GetId());
3878 m_addrman.
Add(vAddrOk, pfrom.
addr, 2h);
3879 if (vAddr.size() < 1000) peer->m_getaddr_sent =
false;
3890 std::vector<CInv> vInv;
3894 Misbehaving(*peer, 20,
strprintf(
"inv message size = %u", vInv.size()));
3898 const bool reject_tx_invs{RejectIncomingTxs(pfrom)};
3902 const auto current_time{GetTime<std::chrono::microseconds>()};
3905 for (
CInv& inv : vInv) {
3906 if (interruptMsgProc)
return;
3911 if (peer->m_wtxid_relay) {
3918 const bool fAlreadyHave = AlreadyHaveBlock(inv.
hash);
3921 UpdateBlockAvailability(pfrom.
GetId(), inv.
hash);
3929 best_block = &inv.
hash;
3932 if (reject_tx_invs) {
3938 const bool fAlreadyHave = AlreadyHaveTx(gtxid);
3941 AddKnownTx(*peer, inv.
hash);
3943 AddTxAnnouncement(pfrom, gtxid, current_time);
3950 if (best_block !=
nullptr) {
3962 if (state.fSyncStarted || (!peer->m_inv_triggered_getheaders_before_sync && *best_block != m_last_block_inv_triggering_headers_sync)) {
3963 if (MaybeSendGetHeaders(pfrom,
GetLocator(m_chainman.m_best_header), *peer)) {
3965 m_chainman.m_best_header->nHeight, best_block->ToString(),
3968 if (!state.fSyncStarted) {
3969 peer->m_inv_triggered_getheaders_before_sync =
true;
3973 m_last_block_inv_triggering_headers_sync = *best_block;
3982 std::vector<CInv> vInv;
3986 Misbehaving(*peer, 20,
strprintf(
"getdata message size = %u", vInv.size()));
3992 if (vInv.size() > 0) {
3997 LOCK(peer->m_getdata_requests_mutex);
3998 peer->m_getdata_requests.insert(peer->m_getdata_requests.end(), vInv.begin(), vInv.end());
3999 ProcessGetData(pfrom, *peer, interruptMsgProc);
4008 vRecv >> locator >> hashStop;
4024 std::shared_ptr<const CBlock> a_recent_block;
4026 LOCK(m_most_recent_block_mutex);
4027 a_recent_block = m_most_recent_block;
4030 if (!m_chainman.
ActiveChainstate().ActivateBestChain(state, a_recent_block)) {
4044 LogPrint(
BCLog::NET,
"getblocks %d to %s limit %d from peer=%d\n", (pindex ? pindex->
nHeight : -1), hashStop.IsNull() ?
"end" : hashStop.ToString(), nLimit, pfrom.
GetId());
4060 if (--nLimit <= 0) {
4064 WITH_LOCK(peer->m_block_inv_mutex, {peer->m_continuation_block = pindex->GetBlockHash();});
4075 std::shared_ptr<const CBlock> recent_block;
4077 LOCK(m_most_recent_block_mutex);
4078 if (m_most_recent_block_hash == req.blockhash)
4079 recent_block = m_most_recent_block;
4083 SendBlockTransactions(pfrom, *peer, *recent_block, req);
4101 SendBlockTransactions(pfrom, *peer, block, req);
4115 WITH_LOCK(peer->m_getdata_requests_mutex, peer->m_getdata_requests.push_back(inv));
4123 vRecv >> locator >> hashStop;
4145 if (m_chainman.
ActiveTip() ==
nullptr ||
4147 LogPrint(
BCLog::NET,
"Ignoring getheaders from peer=%d because active chain has too little work; sending empty response\n", pfrom.
GetId());
4154 CNodeState *nodestate =
State(pfrom.
GetId());
4164 if (!BlockRequestAllowed(pindex)) {
4165 LogPrint(
BCLog::NET,
"%s: ignoring request from peer=%i for old block header that isn't in the main chain\n", __func__, pfrom.
GetId());
4178 std::vector<CBlock> vHeaders;
4180 LogPrint(
BCLog::NET,
"getheaders %d to %s from peer=%d\n", (pindex ? pindex->nHeight : -1), hashStop.IsNull() ?
"end" : hashStop.ToString(), pfrom.
GetId());
4183 vHeaders.emplace_back(pindex->GetBlockHeader());
4184 if (--nLimit <= 0 || pindex->GetBlockHash() == hashStop)
4199 nodestate->pindexBestHeaderSent = pindex ? pindex : m_chainman.
ActiveChain().
Tip();
4205 if (RejectIncomingTxs(pfrom)) {
4220 const uint256& txid = ptx->GetHash();
4221 const uint256& wtxid = ptx->GetWitnessHash();
4223 const uint256& hash = peer->m_wtxid_relay ? wtxid : txid;
4224 AddKnownTx(*peer, hash);
4228 m_txrequest.ReceivedResponse(pfrom.
GetId(), txid);
4229 if (tx.
HasWitness()) m_txrequest.ReceivedResponse(pfrom.
GetId(), wtxid);
4249 LogPrintf(
"Not relaying non-mempool transaction %s (wtxid=%s) from forcerelay peer=%d\n",
4252 LogPrintf(
"Force relaying tx %s (wtxid=%s) from peer=%d\n",
4281 m_txrequest.ForgetTxHash(tx.
GetHash());
4295 AddToCompactExtraTransactions(removedTx);
4300 bool fRejectedParents =
false;
4304 std::vector<uint256> unique_parents;
4305 unique_parents.reserve(tx.
vin.size());
4310 std::sort(unique_parents.begin(), unique_parents.end());
4311 unique_parents.erase(std::unique(unique_parents.begin(), unique_parents.end()), unique_parents.end());
4312 for (
const uint256& parent_txid : unique_parents) {
4313 if (m_recent_rejects.contains(parent_txid)) {
4314 fRejectedParents =
true;
4318 if (!fRejectedParents) {
4319 const auto current_time{GetTime<std::chrono::microseconds>()};
4321 for (
const uint256& parent_txid : unique_parents) {
4328 AddKnownTx(*peer, parent_txid);
4329 if (!AlreadyHaveTx(gtxid)) AddTxAnnouncement(pfrom, gtxid, current_time);
4333 AddToCompactExtraTransactions(ptx);
4337 m_txrequest.ForgetTxHash(tx.
GetHash());
4341 m_orphanage.
LimitOrphans(m_opts.max_orphan_txs, m_rng);
4354 m_txrequest.ForgetTxHash(tx.
GetHash());
4384 m_txrequest.ForgetTxHash(tx.
GetHash());
4387 AddToCompactExtraTransactions(ptx);
4398 MaybePunishNodeForTx(pfrom.
GetId(), state);
4412 vRecv >> cmpctblock;
4414 bool received_new_header =
false;
4424 MaybeSendGetHeaders(pfrom,
GetLocator(m_chainman.m_best_header), *peer);
4434 received_new_header =
true;
4442 MaybePunishNodeForBlock(pfrom.
GetId(), state,
true,
"invalid header via cmpctblock");
4447 if (received_new_header) {
4448 LogInfo(
"Saw new cmpctblock header hash=%s peer=%d\n",
4449 blockhash.ToString(), pfrom.
GetId());
4452 bool fProcessBLOCKTXN =
false;
4456 bool fRevertToHeaderProcessing =
false;
4460 std::shared_ptr<CBlock> pblock = std::make_shared<CBlock>();
4461 bool fBlockReconstructed =
false;
4469 CNodeState *nodestate =
State(pfrom.
GetId());
4474 nodestate->m_last_block_announcement =
GetTime();
4480 auto range_flight = mapBlocksInFlight.equal_range(pindex->
GetBlockHash());
4481 size_t already_in_flight = std::distance(range_flight.first, range_flight.second);
4482 bool requested_block_from_this_peer{
false};
4485 bool first_in_flight = already_in_flight == 0 || (range_flight.first->second.first == pfrom.
GetId());
4487 while (range_flight.first != range_flight.second) {
4488 if (range_flight.first->second.first == pfrom.
GetId()) {
4489 requested_block_from_this_peer =
true;
4492 range_flight.first++;
4497 if (requested_block_from_this_peer) {
4500 std::vector<CInv> vInv(1);
4501 vInv[0] =
CInv(
MSG_BLOCK | GetFetchFlags(*peer), blockhash);
4508 if (!already_in_flight && !CanDirectFetch()) {
4516 requested_block_from_this_peer) {
4517 std::list<QueuedBlock>::iterator* queuedBlockIt =
nullptr;
4518 if (!BlockRequested(pfrom.
GetId(), *pindex, &queuedBlockIt)) {
4519 if (!(*queuedBlockIt)->partialBlock)
4532 Misbehaving(*peer, 100,
"invalid compact block");
4535 if (first_in_flight) {
4537 std::vector<CInv> vInv(1);
4538 vInv[0] =
CInv(
MSG_BLOCK | GetFetchFlags(*peer), blockhash);
4548 for (
size_t i = 0; i < cmpctblock.BlockTxCount(); i++) {
4553 fProcessBLOCKTXN =
true;
4554 }
else if (first_in_flight) {
4561 IsBlockRequestedFromOutbound(blockhash) ||
4580 ReadStatus status = tempBlock.InitData(cmpctblock, vExtraTxnForCompact);
4585 std::vector<CTransactionRef> dummy;
4586 status = tempBlock.FillBlock(*pblock, dummy);
4588 fBlockReconstructed =
true;
4592 if (requested_block_from_this_peer) {
4595 std::vector<CInv> vInv(1);
4596 vInv[0] =
CInv(
MSG_BLOCK | GetFetchFlags(*peer), blockhash);
4601 fRevertToHeaderProcessing =
true;
4606 if (fProcessBLOCKTXN) {
4609 return ProcessCompactBlockTxns(pfrom, *peer, txn);
4612 if (fRevertToHeaderProcessing) {
4618 return ProcessHeadersMessage(pfrom, *peer, {cmpctblock.header},
true);
4621 if (fBlockReconstructed) {
4626 mapBlockSource.emplace(pblock->GetHash(), std::make_pair(pfrom.
GetId(),
false));
4637 ProcessBlock(pfrom, pblock,
true,
true);
4644 RemoveBlockRequest(pblock->GetHash(), std::nullopt);
4661 return ProcessCompactBlockTxns(pfrom, *peer, resp);
4674 peer->m_last_getheaders_timestamp = {};
4676 std::vector<CBlockHeader> headers;
4681 Misbehaving(*peer, 20,
strprintf(
"headers message size = %u", nCount));
4684 headers.resize(nCount);
4685 for (
unsigned int n = 0; n < nCount; n++) {
4686 vRecv >> headers[n];
4690 ProcessHeadersMessage(pfrom, *peer, std::move(headers),
false);
4694 if (m_headers_presync_should_signal.exchange(
false)) {
4695 HeadersPresyncStats stats;
4697 LOCK(m_headers_presync_mutex);
4698 auto it = m_headers_presync_stats.find(m_headers_presync_bestpeer);
4699 if (it != m_headers_presync_stats.end()) stats = it->second;
4717 std::shared_ptr<CBlock> pblock = std::make_shared<CBlock>();
4728 Misbehaving(*peer, 100,
"mutated block");
4733 bool forceProcessing =
false;
4734 const uint256 hash(pblock->GetHash());
4735 bool min_pow_checked =
false;
4740 forceProcessing = IsBlockRequested(hash);
4741 RemoveBlockRequest(hash, pfrom.
GetId());
4745 mapBlockSource.emplace(hash, std::make_pair(pfrom.
GetId(),
true));
4749 min_pow_checked =
true;
4752 ProcessBlock(pfrom, pblock, forceProcessing, min_pow_checked);
4769 Assume(SetupAddressRelay(pfrom, *peer));
4773 if (peer->m_getaddr_recvd) {
4777 peer->m_getaddr_recvd =
true;
4779 peer->m_addrs_to_send.clear();
4780 std::vector<CAddress> vAddr;
4786 for (
const CAddress &addr : vAddr) {
4787 PushAddress(*peer, addr);
4815 if (
auto tx_relay = peer->GetTxRelay(); tx_relay !=
nullptr) {
4816 LOCK(tx_relay->m_tx_inventory_mutex);
4817 tx_relay->m_send_mempool =
true;
4843 const auto ping_end = time_received;
4846 bool bPingFinished =
false;
4847 std::string sProblem;
4849 if (nAvail >=
sizeof(
nonce)) {
4853 if (peer->m_ping_nonce_sent != 0) {
4854 if (
nonce == peer->m_ping_nonce_sent) {
4856 bPingFinished =
true;
4857 const auto ping_time = ping_end - peer->m_ping_start.load();
4858 if (ping_time.count() >= 0) {
4863 sProblem =
"Timing mishap";
4867 sProblem =
"Nonce mismatch";
4870 bPingFinished =
true;
4871 sProblem =
"Nonce zero";
4875 sProblem =
"Unsolicited pong without ping";
4879 bPingFinished =
true;
4880 sProblem =
"Short payload";
4883 if (!(sProblem.empty())) {
4887 peer->m_ping_nonce_sent,
4891 if (bPingFinished) {
4892 peer->m_ping_nonce_sent = 0;
4899 LogPrint(
BCLog::NET,
"filterload received despite not offering bloom services from peer=%d; disconnecting\n", pfrom.
GetId());
4906 if (!filter.IsWithinSizeConstraints())
4909 Misbehaving(*peer, 100,
"too-large bloom filter");
4910 }
else if (
auto tx_relay = peer->GetTxRelay(); tx_relay !=
nullptr) {
4912 LOCK(tx_relay->m_bloom_filter_mutex);
4913 tx_relay->m_bloom_filter.reset(
new CBloomFilter(filter));
4914 tx_relay->m_relay_txs =
true;
4924 LogPrint(
BCLog::NET,
"filteradd received despite not offering bloom services from peer=%d; disconnecting\n", pfrom.
GetId());
4928 std::vector<unsigned char> vData;
4936 }
else if (
auto tx_relay = peer->GetTxRelay(); tx_relay !=
nullptr) {
4937 LOCK(tx_relay->m_bloom_filter_mutex);
4938 if (tx_relay->m_bloom_filter) {
4939 tx_relay->m_bloom_filter->insert(vData);
4945 Misbehaving(*peer, 100,
"bad filteradd message");
4952 LogPrint(
BCLog::NET,
"filterclear received despite not offering bloom services from peer=%d; disconnecting\n", pfrom.
GetId());
4956 auto tx_relay = peer->GetTxRelay();
4957 if (!tx_relay)
return;
4960 LOCK(tx_relay->m_bloom_filter_mutex);
4961 tx_relay->m_bloom_filter =
nullptr;
4962 tx_relay->m_relay_txs =
true;
4971 vRecv >> newFeeFilter;
4973 if (
auto tx_relay = peer->GetTxRelay(); tx_relay !=
nullptr) {
4974 tx_relay->m_fee_filter_received = newFeeFilter;
4982 ProcessGetCFilters(pfrom, *peer, vRecv);
4987 ProcessGetCFHeaders(pfrom, *peer, vRecv);
4992 ProcessGetCFCheckPt(pfrom, *peer, vRecv);
4997 std::vector<CInv> vInv;
5001 for (
CInv &inv : vInv) {
5005 m_txrequest.ReceivedResponse(pfrom.
GetId(), inv.
hash);
5017 bool PeerManagerImpl::MaybeDiscourageAndDisconnect(
CNode& pnode, Peer& peer)
5020 LOCK(peer.m_misbehavior_mutex);
5023 if (!peer.m_should_discourage)
return false;
5025 peer.m_should_discourage =
false;
5030 LogPrintf(
"Warning: not punishing noban peer %d!\n", peer.m_id);
5036 LogPrintf(
"Warning: not punishing manually connected peer %d!\n", peer.m_id);
5056 bool PeerManagerImpl::ProcessMessages(
CNode* pfrom, std::atomic<bool>& interruptMsgProc)
5060 PeerRef peer = GetPeerRef(pfrom->
GetId());
5061 if (peer ==
nullptr)
return false;
5064 LOCK(peer->m_getdata_requests_mutex);
5065 if (!peer->m_getdata_requests.empty()) {
5066 ProcessGetData(*pfrom, *peer, interruptMsgProc);
5070 const bool processed_orphan = ProcessOrphanTx(*peer);
5075 if (processed_orphan)
return true;
5080 LOCK(peer->m_getdata_requests_mutex);
5081 if (!peer->m_getdata_requests.empty())
return true;
5094 bool fMoreWork = poll_result->second;
5096 TRACE6(net, inbound_message,
5105 if (m_opts.capture_messages) {
5110 ProcessMessage(*pfrom,
msg.m_type,
msg.m_recv,
msg.m_time, interruptMsgProc);
5111 if (interruptMsgProc)
return false;
5113 LOCK(peer->m_getdata_requests_mutex);
5114 if (!peer->m_getdata_requests.empty()) fMoreWork =
true;
5122 }
catch (
const std::exception& e) {
5131 void PeerManagerImpl::ConsiderEviction(
CNode& pto, Peer& peer, std::chrono::seconds time_in_seconds)
5144 if (state.pindexBestKnownBlock !=
nullptr && state.pindexBestKnownBlock->nChainWork >= m_chainman.
ActiveChain().
Tip()->
nChainWork) {
5145 if (state.m_chain_sync.m_timeout != 0s) {
5146 state.m_chain_sync.m_timeout = 0s;
5147 state.m_chain_sync.m_work_header =
nullptr;
5148 state.m_chain_sync.m_sent_getheaders =
false;
5150 }
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)) {
5156 state.m_chain_sync.m_work_header = m_chainman.
ActiveChain().
Tip();
5157 state.m_chain_sync.m_sent_getheaders =
false;
5158 }
else if (state.m_chain_sync.m_timeout > 0s && time_in_seconds > state.m_chain_sync.m_timeout) {
5162 if (state.m_chain_sync.m_sent_getheaders) {
5164 LogPrintf(
"Disconnecting outbound peer %d for old chain, best known block = %s\n", pto.
GetId(), state.pindexBestKnownBlock !=
nullptr ? state.pindexBestKnownBlock->GetBlockHash().ToString() :
"<none>");
5167 assert(state.m_chain_sync.m_work_header);
5172 MaybeSendGetHeaders(pto,
5173 GetLocator(state.m_chain_sync.m_work_header->pprev),
5175 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());
5176 state.m_chain_sync.m_sent_getheaders =
true;
5188 void PeerManagerImpl::EvictExtraOutboundPeers(std::chrono::seconds now)
5197 std::pair<NodeId, std::chrono::seconds> youngest_peer{-1, 0}, next_youngest_peer{-1, 0};
5201 if (pnode->
GetId() > youngest_peer.first) {
5202 next_youngest_peer = youngest_peer;
5203 youngest_peer.first = pnode->
GetId();
5207 NodeId to_disconnect = youngest_peer.first;
5208 if (youngest_peer.second > next_youngest_peer.second) {
5211 to_disconnect = next_youngest_peer.first;
5220 CNodeState *node_state =
State(pnode->
GetId());
5221 if (node_state ==
nullptr ||
5224 LogPrint(
BCLog::NET,
"disconnecting extra block-relay-only peer=%d (last block received at time %d)\n",
5228 LogPrint(
BCLog::NET,
"keeping block-relay-only peer=%d chosen for eviction (connect time: %d, blocks_in_flight: %d)\n",
5244 int64_t oldest_block_announcement = std::numeric_limits<int64_t>::max();
5253 if (state ==
nullptr)
return;
5255 if (state->m_chain_sync.m_protect)
return;
5259 if (state->m_last_block_announcement < oldest_block_announcement || (state->m_last_block_announcement == oldest_block_announcement && pnode->
GetId() > worst_peer)) {
5260 worst_peer = pnode->
GetId();
5261 oldest_block_announcement = state->m_last_block_announcement;
5264 if (worst_peer != -1) {
5275 LogPrint(
BCLog::NET,
"disconnecting extra outbound peer=%d (last block announcement received at time %d)\n", pnode->
GetId(), oldest_block_announcement);
5279 LogPrint(
BCLog::NET,
"keeping outbound peer=%d chosen for eviction (connect time: %d, blocks_in_flight: %d)\n",
5296 void PeerManagerImpl::CheckForStaleTipAndEvictPeers()
5300 auto now{GetTime<std::chrono::seconds>()};
5302 EvictExtraOutboundPeers(now);
5304 if (now > m_stale_tip_check_time) {
5308 LogPrintf(
"Potential stale tip detected, will try using extra outbound peer (last tip update: %d seconds ago)\n",
5317 if (!m_initial_sync_finished && CanDirectFetch()) {
5319 m_initial_sync_finished =
true;
5323 void PeerManagerImpl::MaybeSendPing(
CNode& node_to, Peer& peer, std::chrono::microseconds now)
5326 peer.m_ping_nonce_sent &&
5336 bool pingSend =
false;
5338 if (peer.m_ping_queued) {
5343 if (peer.m_ping_nonce_sent == 0 && now > peer.m_ping_start.load() +
PING_INTERVAL) {
5351 nonce = GetRand<uint64_t>();
5352 }
while (
nonce == 0);
5353 peer.m_ping_queued =
false;
5354 peer.m_ping_start = now;
5356 peer.m_ping_nonce_sent =
nonce;
5360 peer.m_ping_nonce_sent = 0;
5366 void PeerManagerImpl::MaybeSendAddr(
CNode&
node, Peer& peer, std::chrono::microseconds current_time)
5369 if (!peer.m_addr_relay_enabled)
return;
5371 LOCK(peer.m_addr_send_times_mutex);
5374 peer.m_next_local_addr_send < current_time) {
5381 if (peer.m_next_local_addr_send != 0us) {
5382 peer.m_addr_known->reset();
5385 CAddress local_addr{*local_service, peer.m_our_services, Now<NodeSeconds>()};
5386 PushAddress(peer, local_addr);
5392 if (current_time <= peer.m_next_addr_send)
return;
5405 bool ret = peer.m_addr_known->contains(addr.
GetKey());
5406 if (!
ret) peer.m_addr_known->insert(addr.
GetKey());
5409 peer.m_addrs_to_send.erase(std::remove_if(peer.m_addrs_to_send.begin(), peer.m_addrs_to_send.end(), addr_already_known),
5410 peer.m_addrs_to_send.end());
5413 if (peer.m_addrs_to_send.empty())
return;
5415 if (peer.m_wants_addrv2) {
5420 peer.m_addrs_to_send.clear();
5423 if (peer.m_addrs_to_send.capacity() > 40) {
5424 peer.m_addrs_to_send.shrink_to_fit();
5428 void PeerManagerImpl::MaybeSendSendHeaders(
CNode&
node, Peer& peer)
5436 CNodeState &state = *
State(
node.GetId());
5437 if (state.pindexBestKnownBlock !=
nullptr &&
5444 peer.m_sent_sendheaders =
true;
5449 void PeerManagerImpl::MaybeSendFeefilter(
CNode& pto, Peer& peer, std::chrono::microseconds current_time)
5451 if (m_opts.ignore_incoming_txs)
return;
5467 if (peer.m_fee_filter_sent == MAX_FILTER) {
5470 peer.m_next_send_feefilter = 0us;
5473 if (current_time > peer.m_next_send_feefilter) {
5474 CAmount filterToSend = m_fee_filter_rounder.round(currentFilter);
5477 if (filterToSend != peer.m_fee_filter_sent) {
5479 peer.m_fee_filter_sent = filterToSend;
5486 (currentFilter < 3 * peer.m_fee_filter_sent / 4 || currentFilter > 4 * peer.m_fee_filter_sent / 3)) {
5492 class CompareInvMempoolOrder
5497 explicit CompareInvMempoolOrder(
CTxMemPool *_mempool,
bool use_wtxid)
5500 m_wtxid_relay = use_wtxid;
5503 bool operator()(std::set<uint256>::iterator a, std::set<uint256>::iterator b)
5507 return mp->CompareDepthAndScore(*b, *a, m_wtxid_relay);
5512 bool PeerManagerImpl::RejectIncomingTxs(
const CNode& peer)
const 5522 bool PeerManagerImpl::SetupAddressRelay(
const CNode&
node, Peer& peer)
5527 if (
node.IsBlockOnlyConn())
return false;
5529 if (!peer.m_addr_relay_enabled.exchange(
true)) {
5533 peer.m_addr_known = std::make_unique<CRollingBloomFilter>(5000, 0.001);
5539 bool PeerManagerImpl::SendMessages(
CNode* pto)
5543 PeerRef peer = GetPeerRef(pto->
GetId());
5544 if (!peer)
return false;
5549 if (MaybeDiscourageAndDisconnect(*pto, *peer))
return true;
5555 const auto current_time{GetTime<std::chrono::microseconds>()};
5563 MaybeSendPing(*pto, *peer, current_time);
5568 MaybeSendAddr(*pto, *peer, current_time);
5570 MaybeSendSendHeaders(*pto, *peer);
5578 if (m_chainman.m_best_header ==
nullptr) {
5585 bool sync_blocks_and_headers_from_peer =
false;
5586 if (state.fPreferredDownload) {
5587 sync_blocks_and_headers_from_peer =
true;
5598 if (m_num_preferred_download_peers == 0 || mapBlocksInFlight.empty()) {
5599 sync_blocks_and_headers_from_peer =
true;
5605 if ((nSyncStarted == 0 && sync_blocks_and_headers_from_peer) || m_chainman.m_best_header->Time() >
NodeClock::now() - 24h) {
5606 const CBlockIndex* pindexStart = m_chainman.m_best_header;
5614 if (pindexStart->
pprev)
5615 pindexStart = pindexStart->
pprev;
5616 if (MaybeSendGetHeaders(*pto,
GetLocator(pindexStart), *peer)) {
5619 state.fSyncStarted =
true;
5643 LOCK(peer->m_block_inv_mutex);
5644 std::vector<CBlock> vHeaders;
5645 bool fRevertToInv = ((!peer->m_prefers_headers &&
5646 (!state.m_requested_hb_cmpctblocks || peer->m_blocks_for_headers_relay.size() > 1)) ||
5649 ProcessBlockAvailability(pto->
GetId());
5651 if (!fRevertToInv) {
5652 bool fFoundStartingHeader =
false;
5656 for (
const uint256& hash : peer->m_blocks_for_headers_relay) {
5661 fRevertToInv =
true;
5664 if (pBestIndex !=
nullptr && pindex->
pprev != pBestIndex) {
5676 fRevertToInv =
true;
5679 pBestIndex = pindex;
5680 if (fFoundStartingHeader) {
5683 }
else if (PeerHasHeader(&state, pindex)) {
5685 }
else if (pindex->
pprev ==
nullptr || PeerHasHeader(&state, pindex->
pprev)) {
5688 fFoundStartingHeader =
true;
5693 fRevertToInv =
true;
5698 if (!fRevertToInv && !vHeaders.empty()) {
5699 if (vHeaders.size() == 1 && state.m_requested_hb_cmpctblocks) {
5703 vHeaders.front().GetHash().ToString(), pto->
GetId());
5705 std::optional<CSerializedNetMsg> cached_cmpctblock_msg;
5707 LOCK(m_most_recent_block_mutex);
5708 if (m_most_recent_block_hash == pBestIndex->
GetBlockHash()) {
5712 if (cached_cmpctblock_msg.has_value()) {
5713 PushMessage(*pto, std::move(cached_cmpctblock_msg.value()));
5721 state.pindexBestHeaderSent = pBestIndex;
5722 }
else if (peer->m_prefers_headers) {
5723 if (vHeaders.size() > 1) {
5726 vHeaders.front().GetHash().ToString(),
5727 vHeaders.back().GetHash().ToString(), pto->
GetId());
5730 vHeaders.front().GetHash().ToString(), pto->
GetId());
5733 state.pindexBestHeaderSent = pBestIndex;
5735 fRevertToInv =
true;
5741 if (!peer->m_blocks_for_headers_relay.empty()) {
5742 const uint256& hashToAnnounce = peer->m_blocks_for_headers_relay.back();
5755 if (!PeerHasHeader(&state, pindex)) {
5756 peer->m_blocks_for_inv_relay.push_back(hashToAnnounce);
5762 peer->m_blocks_for_headers_relay.clear();
5768 std::vector<CInv> vInv;
5770 LOCK(peer->m_block_inv_mutex);
5774 for (
const uint256& hash : peer->m_blocks_for_inv_relay) {
5781 peer->m_blocks_for_inv_relay.clear();
5784 if (
auto tx_relay = peer->GetTxRelay(); tx_relay !=
nullptr) {
5785 LOCK(tx_relay->m_tx_inventory_mutex);
5788 if (tx_relay->m_next_inv_send_time < current_time) {
5789 fSendTrickle =
true;
5799 LOCK(tx_relay->m_bloom_filter_mutex);
5800 if (!tx_relay->m_relay_txs) tx_relay->m_tx_inventory_to_send.clear();
5804 if (fSendTrickle && tx_relay->m_send_mempool) {
5805 auto vtxinfo = m_mempool.
infoAll();
5806 tx_relay->m_send_mempool =
false;
5807 const CFeeRate filterrate{tx_relay->m_fee_filter_received.load()};
5809 LOCK(tx_relay->m_bloom_filter_mutex);
5811 for (
const auto& txinfo : vtxinfo) {
5814 peer->m_wtxid_relay ?
5815 txinfo.tx->GetWitnessHash().ToUint256() :
5816 txinfo.tx->GetHash().ToUint256(),
5818 tx_relay->m_tx_inventory_to_send.erase(inv.
hash);
5821 if (txinfo.fee < filterrate.GetFee(txinfo.vsize)) {
5824 if (tx_relay->m_bloom_filter) {
5825 if (!tx_relay->m_bloom_filter->IsRelevantAndUpdate(*txinfo.tx))
continue;
5827 tx_relay->m_tx_inventory_known_filter.insert(inv.
hash);
5828 vInv.push_back(inv);
5839 std::vector<std::set<uint256>::iterator> vInvTx;
5840 vInvTx.reserve(tx_relay->m_tx_inventory_to_send.size());
5841 for (std::set<uint256>::iterator it = tx_relay->m_tx_inventory_to_send.begin(); it != tx_relay->m_tx_inventory_to_send.end(); it++) {
5842 vInvTx.push_back(it);
5844 const CFeeRate filterrate{tx_relay->m_fee_filter_received.load()};
5847 CompareInvMempoolOrder compareInvMempoolOrder(&m_mempool, peer->m_wtxid_relay);
5848 std::make_heap(vInvTx.begin(), vInvTx.end(), compareInvMempoolOrder);
5851 unsigned int nRelayedTransactions = 0;
5852 LOCK(tx_relay->m_bloom_filter_mutex);
5855 while (!vInvTx.empty() && nRelayedTransactions < broadcast_max) {
5857 std::pop_heap(vInvTx.begin(), vInvTx.end(), compareInvMempoolOrder);
5858 std::set<uint256>::iterator it = vInvTx.back();
5863 tx_relay->m_tx_inventory_to_send.erase(it);
5865 if (tx_relay->m_tx_inventory_known_filter.contains(hash)) {
5874 if (txinfo.fee < filterrate.GetFee(txinfo.vsize)) {
5877 if (tx_relay->m_bloom_filter && !tx_relay->m_bloom_filter->IsRelevantAndUpdate(*txinfo.tx))
continue;
5879 vInv.push_back(inv);
5880 nRelayedTransactions++;
5885 tx_relay->m_tx_inventory_known_filter.insert(hash);
5890 tx_relay->m_last_inv_sequence = m_mempool.
GetSequence();
5897 auto stalling_timeout = m_block_stalling_timeout.load();
5898 if (state.m_stalling_since.count() && state.m_stalling_since < current_time - stalling_timeout) {
5907 if (stalling_timeout != new_timeout && m_block_stalling_timeout.compare_exchange_strong(stalling_timeout, new_timeout)) {
5917 if (state.vBlocksInFlight.size() > 0) {
5918 QueuedBlock &queuedBlock = state.vBlocksInFlight.front();
5919 int nOtherPeersWithValidatedDownloads = m_peers_downloading_from - 1;
5927 if (state.fSyncStarted && peer->m_headers_sync_timeout < std::chrono::microseconds::max()) {
5929 if (m_chainman.m_best_header->Time() <=
NodeClock::now() - 24h) {
5930 if (current_time > peer->m_headers_sync_timeout && nSyncStarted == 1 && (m_num_preferred_download_peers - state.fPreferredDownload >= 1)) {
5947 state.fSyncStarted =
false;
5949 peer->m_headers_sync_timeout = 0us;
5955 peer->m_headers_sync_timeout = std::chrono::microseconds::max();
5961 ConsiderEviction(*pto, *peer, GetTime<std::chrono::seconds>());
5966 std::vector<CInv> vGetData;
5968 std::vector<const CBlockIndex*> vToDownload;
5970 auto get_inflight_budget = [&state]() {
5976 FindNextBlocksToDownload(*peer, get_inflight_budget(), vToDownload, staller);
5978 TryDownloadingHistoricalBlocks(
5980 get_inflight_budget(),
5982 Assert(m_chainman.GetSnapshotBaseBlock()));
5985 uint32_t nFetchFlags = GetFetchFlags(*peer);
5987 BlockRequested(pto->
GetId(), *pindex);
5991 if (state.vBlocksInFlight.empty() && staller != -1) {
5992 if (
State(staller)->m_stalling_since == 0us) {
5993 State(staller)->m_stalling_since = current_time;
6002 std::vector<std::pair<NodeId, GenTxid>> expired;
6003 auto requestable = m_txrequest.GetRequestable(pto->
GetId(), current_time, &expired);
6004 for (
const auto& entry : expired) {
6005 LogPrint(
BCLog::NET,
"timeout of inflight %s %s from peer=%d\n", entry.second.IsWtxid() ?
"wtx" :
"tx",
6006 entry.second.GetHash().ToString(), entry.first);
6008 for (
const GenTxid& gtxid : requestable) {
6009 if (!AlreadyHaveTx(gtxid)) {
6021 m_txrequest.ForgetTxHash(gtxid.
GetHash());
6026 if (!vGetData.empty())
6029 MaybeSendFeefilter(*pto, *peer, current_time);
std::shared_ptr< const CTransaction > CTransactionRef
static constexpr unsigned int INVENTORY_BROADCAST_PER_SECOND
Maximum rate of inventory items to send per second.
const char * GETCFILTERS
getcfilters requests compact filters for a range of blocks.
static Mutex g_msgproc_mutex
Mutex for anything that is only accessed via the msg processing thread.
arith_uint256 nChainWork
(memory only) Total amount of work (expected number of hashes) in the chain up to and including this ...
static std::unique_ptr< PeerManager > make(CConnman &connman, AddrMan &addrman, BanMan *banman, ChainstateManager &chainman, CTxMemPool &pool, Options opts)
enum ReadStatus_t ReadStatus
const char * PING
The ping message is sent periodically to help confirm that the receiving peer is still connected...
static constexpr auto TXID_RELAY_DELAY
How long to delay requesting transactions via txids, if we have wtxid-relaying peers.
node::BlockManager m_blockman
A single BlockManager instance is shared across each constructed chainstate to avoid duplicating bloc...
BlockFilterIndex is used to store and retrieve block filters, hashes, and headers for a range of bloc...
static constexpr auto INBOUND_INVENTORY_BROADCAST_INTERVAL
Average delay between trickled inventory transmissions for inbound peers.
const char * FILTERLOAD
The filterload message tells the receiving peer to filter all relayed transactions and requested merk...
const char * MERKLEBLOCK
The merkleblock message is a reply to a getdata message which requested a block using the inventory t...
std::atomic_bool fPauseSend
invalid by consensus rules
bool HaveNumChainTxs() const
Check whether this block's and all previous blocks' transactions have been downloaded (and stored to ...
std::chrono::time_point< NodeClock > time_point
const char * BLOCKTXN
Contains a BlockTransactions.
static GenTxid Wtxid(const uint256 &hash)
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 unsigned int INVENTORY_BROADCAST_MAX
Maximum number of inventory items to send per transmission.
static const int MAX_BLOCKTXN_DEPTH
Maximum depth of blocks we're willing to respond to GETBLOCKTXN requests for.
const char * SENDADDRV2
The sendaddrv2 message signals support for receiving ADDRV2 messages (BIP155).
ReadStatus FillBlock(CBlock &block, const std::vector< CTransactionRef > &vtx_missing)
std::vector< Byte > ParseHex(std::string_view hex_str)
Like TryParseHex, but returns an empty vector on invalid input.
ServiceFlags
nServices flags
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...
bool IsPruneMode() const
Whether running in -prune mode.
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.
#define LogPrint(category,...)
int64_t GetBlockTime() const
Describes a place in the block chain to another node such that if the other node doesn't have the sam...
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.
CBlockIndex * pprev
pointer to the index of the predecessor of this block
std::vector< TxMempoolInfo > infoAll() const
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 ...
virtual void StartScheduledTasks(CScheduler &scheduler)=0
Begin running background tasks, should only be called once.
uint64_t m_addr_rate_limited
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...
virtual void UnitTestMisbehaving(NodeId peer_id, int howmuch)=0
std::string ToString() const
RecursiveMutex & GetNodesMutex() const LOCK_RETURNED(m_nodes_mutex)
bool exists(const GenTxid >xid) const
ReconciliationRegisterResult
We don't have the previous block the checked one is built on.
Data structure to keep track of, and schedule, transaction downloads from peers.
const char * GETADDR
The getaddr message requests an addr message from the receiving node, preferably one with lots of IP ...
uint64_t ReadCompactSize(Stream &is, bool range_check=true)
Decode a CompactSize-encoded variable-length integer.
std::atomic_bool m_has_all_wanted_services
Whether this peer provides all services that we want.
static constexpr auto HEADERS_DOWNLOAD_TIMEOUT_PER_HEADER
Provides an interface for creating and interacting with one or two chainstates: an IBD chainstate gen...
std::vector< uint16_t > indexes
bool IsOutboundOrBlockRelayConn() const
static const int WTXID_RELAY_VERSION
"wtxidrelay" command for wtxid-based relay starts with this version
bool IsMsgFilteredBlk() const
An in-memory indexed chain of blocks.
const std::chrono::seconds m_connected
Unix epoch time at peer connection.
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.cpp.
size_t DynamicMemoryUsage() const
void Discourage(const CNetAddr &net_addr) EXCLUSIVE_LOCKS_REQUIRED(!m_banned_mutex)
const std::optional< std::list< CTransactionRef > > m_replaced_transactions
Mempool transactions replaced by the tx.
static constexpr auto AVG_FEEFILTER_BROADCAST_INTERVAL
Average delay between feefilter broadcasts in seconds.
reverse_range< T > reverse_iterate(T &x)
transaction was not validated because package failed
invalid proof of work or time too old
const char * SENDCMPCT
Contains a 1-byte bool and 8-byte LE version number.
A class to track orphan transactions (failed on TX_MISSING_INPUTS) Since we cannot distinguish orphan...
BlockFilterIndex * GetBlockFilterIndex(BlockFilterType filter_type)
Get a block filter index by type.
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 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...
constexpr auto GetRandMillis
const CBlockIndex * LastCommonAncestor(const CBlockIndex *pa, const CBlockIndex *pb)
Find the last common ancestor two blocks have.
transaction was missing some of its inputs
bool IsMsgCmpctBlk() 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...
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 IsFeelerConn() const
CChain & ActiveChain() const EXCLUSIVE_LOCKS_REQUIRED(GetMutex())
All parent headers found, difficulty matches, timestamp >= median previous, checkpoint.
bool MoneyRange(const CAmount &nValue)
CBlockHeader GetBlockHeader() const
static constexpr auto HEADERS_RESPONSE_TIME
How long to wait for a peer to respond to a getheaders request.
int Height() const
Return the maximal height in the chain.
static constexpr unsigned int INVENTORY_BROADCAST_TARGET
Target number of tx inventory items to send per transmission.
BloomFilter is a probabilistic filter which SPV clients provide so that we can filter the transaction...
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.
static constexpr SerParams V2_NETWORK
static constexpr unsigned int DEFAULT_MIN_RELAY_TX_FEE
Default for -minrelaytxfee, minimum relay fee for transactions.
unsigned long size() const
const char * CFHEADERS
cfheaders is a response to a getcfheaders request containing a filter header and a vector of filter h...
Only first tx is coinbase, 2 <= coinbase input script length <= 100, transactions valid...
void SetCommonVersion(int greatest_common_version)
uint64_t GetSequence() const EXCLUSIVE_LOCKS_REQUIRED(cs)
RollingBloomFilter is a probabilistic "keep track of most recently inserted" set. ...
static constexpr auto AVG_ADDRESS_BROADCAST_INTERVAL
Average delay between peer address broadcasts.
const TxValidationState m_state
Contains information about why the transaction failed.
bool Contains(Network net) const EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
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...
CChainParams defines various tweakable parameters of a given instance of the Bitcoin system...
violated mempool's fee/size/descendant/RBF/etc limits
static constexpr auto NONPREF_PEER_TX_DELAY
How long to delay requesting transactions from non-preferred peers.
the block header may be on a too-little-work chain
inputs (covered by txid) failed policy rules
void SetTryNewOutboundPeer(bool flag)
void ignore(size_t num_ignore)
const uint32_t MSG_WITNESS_FLAG
getdata message type flags
const ResultType m_result_type
Result type.
void LimitOrphans(unsigned int max_orphans, FastRandomContext &rng) EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
Limit the orphanage to the given maximum.
bool ReadBlockFromDisk(CBlock &block, const FlatFilePos &pos) const
Functions for disk access for blocks.
uint64_t GetLocalNonce() const
bool SeenLocal(const CService &addr)
vote for a local address
transaction spends a coinbase too early, or violates locktime/sequence locks
static const unsigned int NODE_NETWORK_LIMITED_ALLOW_CONN_BLOCKS
Window, in blocks, for connecting to NODE_NETWORK_LIMITED peers.
const char * CFILTER
cfilter is a response to a getcfilters request containing a single compact filter.
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.
static constexpr auto STALE_CHECK_INTERVAL
How frequently to check for stale tips.
const char * PONG
The pong message replies to a ping message, proving to the pinging node that the ponging node is stil...
bool MultipleManualOrFullOutboundConns(Network net) const EXCLUSIVE_LOCKS_REQUIRED(m_nodes_mutex)
State
The various states a (txhash,peer) pair can be in.
static constexpr std::chrono::minutes TIMEOUT_INTERVAL
Time after which to disconnect, after waiting for a ping response (or inactivity).
static constexpr double BLOCK_DOWNLOAD_TIMEOUT_PER_PEER
Additional block download timeout per parallel downloading peer (i.e.
static const int MIN_PEER_PROTO_VERSION
disconnect from peers older than this proto version
initial value. Tx has not yet been rejected
virtual void BlockChecked(const CBlock &, const BlockValidationState &)
Notifies listeners of a block validation result.
const char * WTXIDRELAY
Indicates that a node prefers to relay transactions via wtxid, rather than txid.
bool GetTryNewOutboundPeer() const
static constexpr uint32_t MAX_GETCFILTERS_SIZE
Maximum number of compact filters that may be requested with one getcfilters.
enum Network GetNetwork() const
const char * HEADERS
The headers message sends one or more block headers to a node which previously requested certain head...
const char * GETCFCHECKPT
getcfcheckpt requests evenly spaced compact filter headers, enabling parallelized download and valida...
std::string ToStringAddrPort() const
bool IsRelayable() const
Whether this address should be relayed to other peers even if we can't reach it ourselves.
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...
CSerializedNetMsg Make(std::string msg_type, Args &&... args)
const std::vector< CTxIn > vin
bool HaveTxToReconsider(NodeId peer) EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
Does this peer have any work to do?
const char * INV
The inv message (inventory message) transmits one or more inventories of objects known to the transmi...
Stochastic address manager.
bool IsBanned(const CNetAddr &net_addr) EXCLUSIVE_LOCKS_REQUIRED(!m_banned_mutex)
Return whether net_addr is banned.
Transaction validation functions.
static constexpr double BLOCK_DOWNLOAD_TIMEOUT_BASE
Block download timeout base, expressed in multiples of the block interval (i.e.
bool ForNode(NodeId id, std::function< bool(CNode *pnode)> func)
static const int SENDHEADERS_VERSION
"sendheaders" command and announcing blocks with headers starts with this version ...
Functions to serialize / deserialize common bitcoin types.
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 DisconnectNode(const std::string &node)
int EraseTx(const Txid &txid) EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
Erase an orphan by txid.
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.
int GetExtraBlockRelayCount() const
int64_t CAmount
Amount in satoshis (Can be negative)
std::chrono::time_point< NodeClock, std::chrono::seconds > NodeSeconds
std::string TransportTypeAsString(TransportProtocolType transport_type)
Convert TransportProtocolType enum to a string value.
uint256 GetBlockHash() const
static constexpr auto BLOCK_STALLING_TIMEOUT_MAX
Maximum timeout for stalling block download.
std::string SanitizeString(std::string_view str, int rule)
Remove unsafe chars.
static constexpr auto PING_INTERVAL
Time between pings automatically sent out for latency probing and keepalive.
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...
std::string ToString(const T &t)
Locale-independent version of std::to_string.
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).
GenTxid ToGenTxid(const CInv &inv)
Convert a TX/WITNESS_TX/WTX CInv to a GenTxid.
initial value. Block has not yet been rejected
Outputs do not overspend inputs, no double spends, coinbase output ok, no immature coinbase spends...
void SetAddrLocal(const CService &addrLocalIn) EXCLUSIVE_LOCKS_REQUIRED(!m_addr_local_mutex)
May not be called more than once.
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.
static constexpr auto EXTRA_PEER_CHECK_INTERVAL
How frequently to check for extra outbound peers and disconnect.
Used to relay blocks as header + vector<merkle branch> to filtered nodes.
const char * GETHEADERS
The getheaders message requests a headers message that provides block headers starting from a particu...
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.
CAmount m_fee_filter_received
const char * SENDTXRCNCL
Contains a 4-byte version number and an 8-byte salt.
virtual void InitializeNode(CNode &node, ServiceFlags our_services)=0
Initialize a peer (setup state, queue any initial messages)
std::optional< CService > GetLocalAddrForPeer(CNode &node)
Returns a local address that we should advertise to this peer.
bool BackgroundSyncInProgress() const EXCLUSIVE_LOCKS_REQUIRED(GetMutex())
The state of a background sync (for net processing)
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.
static const int INVALID_CB_NO_BAN_VERSION
not banning for invalid compact blocks starts with this version
uint64_t m_addr_processed
std::atomic_bool m_bloom_filter_loaded
Whether this peer has loaded a bloom filter.
Invalid by a change to consensus rules more recent than SegWit.
Scripts & signatures ok. Implies all parents are either at least VALID_SCRIPTS, or are ASSUMED_VALID...
Transaction might have a witness prior to SegWit activation, or witness may have been malleated (whic...
const std::unique_ptr< Transport > m_transport
Transport serializer/deserializer.
ChainstateRole
This enum describes the various roles a specific Chainstate instance can take.
std::vector< CTransactionRef > txn
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.wikipedia.org/wiki/Exponential_distribution).
this block was cached as being invalid and we didn't store the reason why
std::atomic_bool m_relays_txs
Whether we should relay transactions to this peer.
An input of a transaction.
bool IsDiscouraged(const CNetAddr &net_addr) EXCLUSIVE_LOCKS_REQUIRED(!m_banned_mutex)
Return whether net_addr is discouraged.
static const unsigned int NODE_NETWORK_LIMITED_MIN_BLOCKS
Minimum blocks required to signal NODE_NETWORK_LIMITED.
static constexpr auto MAX_FEEFILTER_CHANGE_DELAY
Maximum feefilter broadcast delay after significant change.
static const unsigned int MAX_CMPCTBLOCKS_INFLIGHT_PER_BLOCK
Maximum number of outstanding CMPCTBLOCK requests for the same block.
void StartExtraBlockRelayPeers()
Double ended buffer combining vector and stream-like interfaces.
const char * ADDRV2
The addrv2 message relays connection information for peers on the network just like the addr message...
std::string ToString() const
the block failed to meet one of our checkpoints
bool LookupFilterHeader(const CBlockIndex *block_index, uint256 &header_out) EXCLUSIVE_LOCKS_REQUIRED(!m_cs_headers_cache)
Get a single filter header by block.
bool Contains(const CBlockIndex *pindex) const
Efficiently check whether a block is present in this chain.
A combination of a network address (CNetAddr) and a (TCP) port.
Transport protocol agnostic message container.
int64_t nPowTargetSpacing
void EraseForPeer(NodeId peer) EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
Erase all orphans announced by a peer (eg, after that peer disconnects)
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...
const char * SENDHEADERS
Indicates that a node prefers to receive new block announcements via a "headers" message rather than ...
const char * MEMPOOL
The mempool message requests the TXIDs of transactions that the receiving node has verified as valid ...
constexpr int64_t count_microseconds(std::chrono::microseconds t)
static const unsigned int MAX_HEADERS_RESULTS
Number of headers sent in one getheaders result.
static constexpr SerParams V1
bool IsProxy(const CNetAddr &addr)
virtual void UpdatedBlockTip(const CBlockIndex *pindexNew, const CBlockIndex *pindexFork, bool fInitialDownload)
Notifies listeners when the block chain tip advances.
bool LoadingBlocks() const
bool IsManualConn() const
virtual void FinalizeNode(const CNode &node)=0
Handle removal of a peer (clear state)
int GetExtraFullOutboundCount() const
A CService with information about it as peer.
std::string ToString() const
virtual bool IgnoresIncomingTxs()=0
Whether this node ignores txs received over p2p.
static constexpr size_t MAX_ADDR_TO_SEND
The maximum number of address records permitted in an ADDR message.
void Connected(const CService &addr, NodeSeconds time=Now< NodeSeconds >())
We have successfully connected to this peer.
static constexpr uint64_t CMPCTBLOCKS_VERSION
The compactblocks version we support.
std::vector< unsigned char > GetKey() const
static constexpr auto OUTBOUND_INVENTORY_BROADCAST_INTERVAL
Average delay between trickled inventory transmissions for outbound peers.
const CFeeRate m_min_relay_feerate
CBlockIndex * ActiveTip() const EXCLUSIVE_LOCKS_REQUIRED(GetMutex())
#define LogPrintLevel(category, level,...)
static const int PROTOCOL_VERSION
network protocol versioning
static constexpr uint64_t RANDOMIZER_ID_ADDRESS_RELAY
SHA256("main address relay")[0:8].
static constexpr uint32_t MAX_GETCFHEADERS_SIZE
Maximum number of cf hashes that may be requested with one getcfheaders.
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.
const char * ADDR
The addr (IP address) message relays connection information for peers on the network.
bool ExpectServicesFromConn() const
virtual ServiceFlags GetDesirableServiceFlags(ServiceFlags services) const =0
Gets the set of service flags which are "desirable" for a given peer.
bool GetNetworkActive() const
static const int DISCOURAGEMENT_THRESHOLD
Threshold for marking a node to be discouraged, e.g.
uint64_t Finalize() const
Compute the 64-bit SipHash-2-4 of the data written so far.
const char * FILTERCLEAR
The filterclear message tells the receiving peer to remove a previously-set bloom filter...
std::string ToString() const
std::atomic< bool > m_bip152_highbandwidth_to
std::vector< uint256 > vHave
RecursiveMutex & GetMutex() const LOCK_RETURNED(
Alias for cs_main.
virtual std::optional< std::string > FetchBlock(NodeId peer_id, const CBlockIndex &block_index)=0
Attempt to manually fetch block from a given peer.
const char * NOTFOUND
The notfound message is a reply to a getdata message which requested an object the receiving node doe...
NodeSeconds nTime
Always included in serialization. The behavior is unspecified if the value is not representable as ui...
CSipHasher GetDeterministicRandomizer(uint64_t id) const
Get a unique deterministic randomizer.
const bool m_inbound_onion
Whether this peer is an inbound onion, i.e. connected via our Tor onion service.
Parameters that influence chain consensus.
static const int MAX_CMPCTBLOCK_DEPTH
Maximum depth of blocks we're willing to serve as compact blocks to peers when requested.
void PongReceived(std::chrono::microseconds ping_time)
A ping-pong round trip has completed successfully.
const char * BLOCK
The block message transmits a single serialized block.
CBlockIndex * LookupBlockIndex(const uint256 &hash) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
std::atomic_bool fDisconnect
std::string strSubVersion
Subversion as sent to the P2P network in version messages.
const char * FEEFILTER
The feefilter message tells the receiving peer not to inv us any txs which do not meet the specified ...
const char * GETCFHEADERS
getcfheaders requests a compact filter header and the filter hashes for a range of blocks...
CFeeRate GetMinFee(size_t sizelimit) const
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...
constexpr bool IsNull() const
bool IsMsgWitnessBlk() const
fails some policy, but might be acceptable if submitted in a (different) package
static const int BIP0031_VERSION
BIP 0031, pong message, is enabled for all versions AFTER this one.
size_t Size() EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
Return how many entries exist in the orphange.
Validation result for a transaction evaluated by MemPoolAccept (single or package).
#define WITH_LOCK(cs, code)
Run code while locking a mutex.
#define Assume(val)
Assume is the identity function.
256-bit unsigned big integer.
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.
static bool MayHaveUsefulAddressDB(ServiceFlags services)
Checks if a peer with the given service flags may be capable of having a robust address-storage DB...
std::chrono::seconds PowTargetSpacing() const
constexpr int64_t count_seconds(std::chrono::seconds t)
std::chrono::microseconds m_ping_wait
TxMempoolInfo info_for_relay(const GenTxid >xid, uint64_t last_sequence) const
Returns info for a transaction if its entry_sequence < last_sequence.
bool CheckIncomingNonce(uint64_t nonce)
static const int SHORT_IDS_BLOCKS_VERSION
short-id-based block download starts with this version
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...
const char * GETBLOCKS
The getblocks message requests an inv message that provides block header hashes starting from a parti...
static constexpr int32_t MAX_PEER_TX_ANNOUNCEMENTS
Maximum number of transactions to consider for requesting, per peer.
static constexpr int CFCHECKPT_INTERVAL
Interval between compact filter checkpoints.
bool IsBlockOnlyConn() const
Transaction is missing a witness.
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.
const char * VERACK
The verack message acknowledges a previously-received version message, informing the connecting node ...
void scheduleFromNow(Function f, std::chrono::milliseconds delta) EXCLUSIVE_LOCKS_REQUIRED(!newTaskMutex)
Call f once after the delta has passed.
ServiceFlags their_services
invalid by consensus rules (excluding any below reasons)
static constexpr auto ROTATE_ADDR_RELAY_DEST_INTERVAL
Delay between rotating the peers we relay a particular address to.
static time_point now() noexcept
Return current system time or mocked time, if set.
void Shuffle(I first, I last, R &&rng)
More efficient than using std::shuffle on a FastRandomContext.
static const unsigned int MAX_GETDATA_SZ
Limit to avoid sending big packets.
const arith_uint256 & MinimumChainWork() const
ServiceFlags nServices
Serialized as uint64_t in V1, and as CompactSize in V2.
#define EXCLUSIVE_LOCKS_REQUIRED(...)
std::vector< CTransactionRef > vtx
const char * CMPCTBLOCK
Contains a CBlockHeaderAndShortTxIDs object - providing a header and list of "short txids"...
virtual void CheckForStaleTipAndEvictPeers()=0
Evict extra outbound peers.
the block's data didn't match the data committed to by the PoW
virtual bool GetNodeStateStats(NodeId nodeid, CNodeStateStats &stats) const =0
Get statistics from node state.
void WakeMessageHandler() EXCLUSIVE_LOCKS_REQUIRED(!mutexMsgProc)
CTxMemPool stores valid-according-to-the-current-best-chain transactions that may be included in the ...
#define LogDebug(category,...)
static constexpr auto BLOCK_STALLING_TIMEOUT_DEFAULT
Default time during which a peer must stall block download progress before being disconnected.
#define LOCKS_EXCLUDED(...)
static constexpr auto HEADERS_DOWNLOAD_TIMEOUT_BASE
Headers download timeout.
virtual void SendPings()=0
Send ping message to all peers.
std::set< uint256 > GetUnbroadcastTxs() const
Returns transactions in unbroadcast set.
const char * VERSION
The version message provides information about the transmitting node to the receiving node at the beg...
uint32_t GetMappedAS(const CNetAddr &addr) const
std::vector< std::pair< unsigned int, uint256 > > vMatchedTxn
Public only for unit testing and relay testing (not relayed).
The block chain is a tree shaped structure starting with the genesis block at the root...
const CChainParams & Params()
Return the currently selected parameters.
bool AddTx(const CTransactionRef &tx, NodeId peer) EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
Add a new orphan transaction.
void EraseForBlock(const CBlock &block) EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
Erase all orphans included in or invalidated by a new block.
static const unsigned int BLOCK_DOWNLOAD_WINDOW
Size of the "block download window": how far ahead of our current height do we fetch? Larger windows tolerate larger download speed differences between peer, but increase the potential degree of disordering of blocks on disk (which make reindexing and pruning harder).
static const unsigned int MAX_INV_SZ
The maximum number of entries in an 'inv' protocol message.
virtual void RelayTransaction(const uint256 &txid, const uint256 &wtxid)=0
Relay transaction to all peers.
bool ReadRawBlockFromDisk(std::vector< uint8_t > &block, const FlatFilePos &pos) const
bool IsTxAvailable(size_t index) const
A block this one builds on is invalid.
TxMempoolInfo info(const GenTxid >xid) const
void SetServices(const CService &addr, ServiceFlags nServices)
Update an entry's service bits.
#define TRACE6(context, event, a, b, c, d, e, f)
bool IsInitialBlockDownload() const
Check whether we are doing an initial block download (synchronizing from disk or network) ...
static const unsigned int MAX_SCRIPT_ELEMENT_SIZE
CBlockIndex * Tip() const
Returns the index entry for the tip of this chain, or nullptr if none.
#define LIMITED_STRING(obj, n)
std::atomic< int64_t > nTimeOffset
const char * GETDATA
The getdata message requests one or more data objects from another node.
Fee rate in satoshis per kilovirtualbyte: CAmount / kvB.
static constexpr auto OVERLOADED_PEER_TX_DELAY
How long to delay requesting transactions from overloaded peers (see MAX_PEER_TX_REQUEST_IN_FLIGHT).
constexpr auto MakeUCharSpan(V &&v) -> decltype(UCharSpanCast(Span
Like the Span constructor, but for (const) unsigned char member types only.
static constexpr auto CHAIN_SYNC_TIMEOUT
Timeout for (unprotected) outbound peers to sync to our chainwork.
std::atomic_bool fSuccessfullyConnected
fSuccessfullyConnected is set to true on receiving VERACK from the peer.
static constexpr CAmount MAX_MONEY
No amount larger than this (in satoshi) is valid.
#define AssertLockNotHeld(cs)
static const unsigned int MAX_SUBVERSION_LENGTH
Maximum length of the user agent string in version message.
std::atomic< int > nVersion
Invalid by a change to consensus rules more recent than SegWit.
arith_uint256 CalculateHeadersWork(const std::vector< CBlockHeader > &headers)
Return the sum of the work on a given set of headers.
const CBlockIndex * GetBackgroundSyncTip() const EXCLUSIVE_LOCKS_REQUIRED(GetMutex())
The tip of the background sync chain.
std::string ConnectionTypeAsString() const
static size_t RecursiveDynamicUsage(const CScript &script)
bool ShouldRunInactivityChecks(const CNode &node, std::chrono::seconds now) const
Return true if we should disconnect the peer for failing an inactivity check.
const char * CFCHECKPT
cfcheckpt is a response to a getcfcheckpt request containing a vector of evenly spaced filter headers...
ReadStatus InitData(const CBlockHeaderAndShortTxIDs &cmpctblock, const std::vector< std::pair< uint256, CTransactionRef >> &extra_txn)
virtual void BlockConnected(ChainstateRole role, const std::shared_ptr< const CBlock > &block, const CBlockIndex *pindex)
Notifies listeners of a block being connected.
this node does not have a mempool so can't validate the transaction
CTransactionRef get(const uint256 &hash) const
static bool LogAcceptCategory(BCLog::LogFlags category, BCLog::Level level)
Return true if log accepts specified category, at the specified level.
block timestamp was > 2 hours in the future (or our clock is bad)
static const unsigned int MAX_BLOCKS_TO_ANNOUNCE
Maximum number of headers to announce when relaying blocks with headers message.
std::atomic< bool > m_bip152_highbandwidth_from
CBlockLocator GetLocator(const CBlockIndex *index)
Get a locator for a block index entry.
const uint256 & ToUint256() const LIFETIMEBOUND
void RemoveUnbroadcastTx(const uint256 &txid, const bool unchecked=false)
Removes a transaction from the unbroadcast set.
bool IsAddrFetchConn() const
arith_uint256 GetBlockProof(const CBlockIndex &block)
A Span is an object that can refer to a contiguous sequence of objects.
const char * TX
The tx message transmits a single transaction.
static const unsigned int MAX_LOCATOR_SZ
The maximum number of entries in a locator.
The basic transaction that is broadcasted on the network and contained in blocks. ...
int nHeight
height of the entry in the chain. The genesis block has height 0
FlatFilePos GetBlockPos() const EXCLUSIVE_LOCKS_REQUIRED(
Information about a peer.
const Consensus::Params & GetConsensus() const
static constexpr auto MINIMUM_CONNECT_TIME
Minimum time an outbound-peer-eviction candidate must be connected for, in order to evict...
std::vector< int > vHeightInFlight
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...
void ForEachNode(const NodeFn &func)
Simple class for background tasks that should be run periodically or once "after a while"...
static constexpr int32_t MAX_PEER_TX_REQUEST_IN_FLIGHT
Maximum number of in-flight transaction requests from a peer.
CBlockIndex * GetAncestor(int height)
Efficiently find an ancestor of this block.
full block available in blk*.dat
virtual bool SendMessages(CNode *pnode) EXCLUSIVE_LOCKS_REQUIRED(g_msgproc_mutex)=0
Send queued protocol messages to a given node.
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.
void AddTimeData(const CNetAddr &ip, int64_t nOffsetSample)
static constexpr SerParams V1_NETWORK
int64_t GetTime()
DEPRECATED, see GetTime.
int GetCommonVersion() const
bool HaveTx(const GenTxid >xid) const EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
Check if we already have an orphan transaction (by txid or wtxid)
const std::string m_addr_name
bool IsAddrV1Compatible() const
Check if the current object can be serialized in pre-ADDRv2/BIP155 format.
bool HasPermission(NetPermissionFlags permission) const
bool IsInboundConn() const
RecursiveMutex cs_main
Mutex to guard access to validation specific variables, such as reading or changing the chainstate...
static constexpr int HISTORICAL_BLOCK_AGE
Age after which a block is considered historical for purposes of rate limiting block relay...
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.
static constexpr double MAX_ADDR_RATE_PER_SECOND
The maximum rate of address records we're willing to process on average.
Tx already in mempool or conflicts with a tx in the chain (if it conflicts with another tx in mempool...
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 ...
otherwise didn't meet our local policy rules
static const int FEEFILTER_VERSION
"feefilter" tells peers to filter invs to you by fee starts with this version
void scheduleEvery(Function f, std::chrono::milliseconds delta) EXCLUSIVE_LOCKS_REQUIRED(!newTaskMutex)
Repeat f until the scheduler is stopped.
A generic txid reference (txid or wtxid).
CAmount GetFeePerK() const
Return the fee in satoshis for a vsize of 1000 vbytes.
virtual bool ProcessMessages(CNode *pnode, std::atomic< bool > &interrupt) EXCLUSIVE_LOCKS_REQUIRED(g_msgproc_mutex)=0
Process protocol messages received from a given node.
bool GetUseAddrmanOutgoing() const
static constexpr auto AVG_LOCAL_ADDRESS_BROADCAST_INTERVAL
Average delay between local address broadcasts.
bool m_addr_relay_enabled
unsigned int nTx
Number of transactions in this block.
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...
static GenTxid Txid(const uint256 &hash)
const Wtxid & GetWitnessHash() const LIFETIMEBOUND
static constexpr auto GETDATA_TX_INTERVAL
How long to wait before downloading a transaction from an additional peer.
const uint256 & GetHash() const LIFETIMEBOUND
const char * FILTERADD
The filteradd message tells the receiving peer to add a single element to a previously-set bloom filt...
RecursiveMutex cs
This mutex needs to be locked when accessing mapTx or other members that are guarded by it...
bool IsFullOutboundConn() const
#define Assert(val)
Identity function.
const Txid & GetHash() const LIFETIMEBOUND
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...
static const int MAX_NUM_UNCONNECTING_HEADERS_MSGS
Maximum number of unconnecting headers announcements before DoS score.
static constexpr TransactionSerParams TX_WITH_WITNESS
static constexpr TransactionSerParams TX_NO_WITNESS
ReachableNets g_reachable_nets
const std::string & BlockFilterTypeName(BlockFilterType filter_type)
Get the human-readable name for a filter type.
const char * GETBLOCKTXN
Contains a BlockTransactionsRequest Peer should respond with "blocktxn" message.
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.
static constexpr uint32_t TXRECONCILIATION_VERSION
Supported transaction reconciliation protocol version.
MempoolAcceptResult ProcessTransaction(const CTransactionRef &tx, bool test_accept=false) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
Try to add a transaction to the memory pool.