mirror of
https://github.com/ElementsProject/elements.git
synced 2026-08-14 12:43:40 +02:00
Merge UP TO 551c8e9526 into merged_master (UP TO bitcoin/bitcoin#26349)
Includes FIXMEs for a few functional tests
This commit is contained in:
commit
ca0a68b350
295 changed files with 5068 additions and 1834 deletions
|
|
@ -20,6 +20,7 @@
|
|||
#include <netbase.h>
|
||||
#include <netmessagemaker.h>
|
||||
#include <node/blockstorage.h>
|
||||
#include <node/txreconciliation.h>
|
||||
#include <policy/fees.h>
|
||||
#include <policy/policy.h>
|
||||
#include <policy/settings.h>
|
||||
|
|
@ -264,19 +265,14 @@ struct Peer {
|
|||
/** The feerate in the most recent BIP133 `feefilter` message sent to the peer.
|
||||
* It is *not* a p2p protocol violation for the peer to send us
|
||||
* transactions with a lower fee rate than this. See BIP133. */
|
||||
CAmount m_fee_filter_sent{0};
|
||||
CAmount m_fee_filter_sent GUARDED_BY(NetEventsInterface::g_msgproc_mutex){0};
|
||||
/** Timestamp after which we will send the next BIP133 `feefilter` message
|
||||
* to the peer. */
|
||||
std::chrono::microseconds m_next_send_feefilter{0};
|
||||
std::chrono::microseconds m_next_send_feefilter GUARDED_BY(NetEventsInterface::g_msgproc_mutex){0};
|
||||
|
||||
struct TxRelay {
|
||||
mutable RecursiveMutex m_bloom_filter_mutex;
|
||||
/** Whether the peer wishes to receive transaction announcements.
|
||||
*
|
||||
* This is initially set based on the fRelay flag in the received
|
||||
* `version` message. If initially set to false, it can only be flipped
|
||||
* to true if we have offered the peer NODE_BLOOM services and it sends
|
||||
* us a `filterload` or `filterclear` message. See BIP37. */
|
||||
/** Whether we relay transactions to this peer. */
|
||||
bool m_relay_txs GUARDED_BY(m_bloom_filter_mutex){false};
|
||||
/** A bloom filter for which transactions to announce to the peer. See BIP37. */
|
||||
std::unique_ptr<CBloomFilter> m_bloom_filter PT_GUARDED_BY(m_bloom_filter_mutex) GUARDED_BY(m_bloom_filter_mutex){nullptr};
|
||||
|
|
@ -298,7 +294,7 @@ struct Peer {
|
|||
std::atomic<std::chrono::seconds> m_last_mempool_req{0s};
|
||||
/** The next time after which we will send an `inv` message containing
|
||||
* transaction announcements to this peer. */
|
||||
std::chrono::microseconds m_next_inv_send_time{0};
|
||||
std::chrono::microseconds m_next_inv_send_time GUARDED_BY(NetEventsInterface::g_msgproc_mutex){0};
|
||||
|
||||
/** Minimum fee rate with which to filter transaction announcements to this node. See BIP133. */
|
||||
std::atomic<CAmount> m_fee_filter_received{0};
|
||||
|
|
@ -319,7 +315,7 @@ struct Peer {
|
|||
};
|
||||
|
||||
/** A vector of addresses to send to the peer, limited to MAX_ADDR_TO_SEND. */
|
||||
std::vector<CAddress> m_addrs_to_send;
|
||||
std::vector<CAddress> m_addrs_to_send GUARDED_BY(NetEventsInterface::g_msgproc_mutex);
|
||||
/** Probabilistic filter to track recent addr messages relayed with this
|
||||
* peer. Used to avoid relaying redundant addresses to this peer.
|
||||
*
|
||||
|
|
@ -329,7 +325,7 @@ struct Peer {
|
|||
*
|
||||
* Presence of this filter must correlate with m_addr_relay_enabled.
|
||||
**/
|
||||
std::unique_ptr<CRollingBloomFilter> m_addr_known;
|
||||
std::unique_ptr<CRollingBloomFilter> m_addr_known GUARDED_BY(NetEventsInterface::g_msgproc_mutex);
|
||||
/** Whether we are participating in address relay with this connection.
|
||||
*
|
||||
* We set this bool to true for outbound peers (other than
|
||||
|
|
@ -346,7 +342,7 @@ struct Peer {
|
|||
* initialized.*/
|
||||
std::atomic_bool m_addr_relay_enabled{false};
|
||||
/** Whether a getaddr request to this peer is outstanding. */
|
||||
bool m_getaddr_sent{false};
|
||||
bool m_getaddr_sent GUARDED_BY(NetEventsInterface::g_msgproc_mutex){false};
|
||||
/** Guards address sending timers. */
|
||||
mutable Mutex m_addr_send_times_mutex;
|
||||
/** Time point to send the next ADDR message to this peer. */
|
||||
|
|
@ -357,12 +353,12 @@ struct Peer {
|
|||
* messages, indicating a preference to receive ADDRv2 instead of ADDR ones. */
|
||||
std::atomic_bool m_wants_addrv2{false};
|
||||
/** Whether this peer has already sent us a getaddr message. */
|
||||
bool m_getaddr_recvd{false};
|
||||
bool m_getaddr_recvd GUARDED_BY(NetEventsInterface::g_msgproc_mutex){false};
|
||||
/** Number of addresses that can be processed from this peer. Start at 1 to
|
||||
* permit self-announcement. */
|
||||
double m_addr_token_bucket{1.0};
|
||||
double m_addr_token_bucket GUARDED_BY(NetEventsInterface::g_msgproc_mutex){1.0};
|
||||
/** When m_addr_token_bucket was last updated */
|
||||
std::chrono::microseconds m_addr_token_timestamp{GetTime<std::chrono::microseconds>()};
|
||||
std::chrono::microseconds m_addr_token_timestamp GUARDED_BY(NetEventsInterface::g_msgproc_mutex){GetTime<std::chrono::microseconds>()};
|
||||
/** Total number of addresses that were dropped due to rate limiting. */
|
||||
std::atomic<uint64_t> m_addr_rate_limited{0};
|
||||
/** Total number of addresses that were processed (excludes rate-limited ones). */
|
||||
|
|
@ -372,7 +368,7 @@ struct Peer {
|
|||
std::set<uint256> m_orphan_work_set GUARDED_BY(g_cs_orphans);
|
||||
|
||||
/** Whether we've sent this peer a getheaders in response to an inv prior to initial-headers-sync completing */
|
||||
bool m_inv_triggered_getheaders_before_sync{false};
|
||||
bool m_inv_triggered_getheaders_before_sync GUARDED_BY(NetEventsInterface::g_msgproc_mutex){false};
|
||||
|
||||
/** Protects m_getdata_requests **/
|
||||
Mutex m_getdata_requests_mutex;
|
||||
|
|
@ -380,7 +376,7 @@ struct Peer {
|
|||
std::deque<CInv> m_getdata_requests GUARDED_BY(m_getdata_requests_mutex);
|
||||
|
||||
/** Time of the last getheaders message to this peer */
|
||||
NodeClock::time_point m_last_getheaders_timestamp{};
|
||||
NodeClock::time_point m_last_getheaders_timestamp GUARDED_BY(NetEventsInterface::g_msgproc_mutex){};
|
||||
|
||||
/** Protects m_headers_sync **/
|
||||
Mutex m_headers_sync_mutex;
|
||||
|
|
@ -515,9 +511,9 @@ public:
|
|||
void InitializeNode(CNode& node, ServiceFlags our_services) override EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex);
|
||||
void FinalizeNode(const CNode& node) override EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex, !m_headers_presync_mutex);
|
||||
bool ProcessMessages(CNode* pfrom, std::atomic<bool>& interrupt) override
|
||||
EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex, !m_recent_confirmed_transactions_mutex, !m_most_recent_block_mutex, !m_headers_presync_mutex);
|
||||
bool SendMessages(CNode* pto) override EXCLUSIVE_LOCKS_REQUIRED(pto->cs_sendProcessing)
|
||||
EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex, !m_recent_confirmed_transactions_mutex, !m_most_recent_block_mutex);
|
||||
EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex, !m_recent_confirmed_transactions_mutex, !m_most_recent_block_mutex, !m_headers_presync_mutex, g_msgproc_mutex);
|
||||
bool SendMessages(CNode* pto) override
|
||||
EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex, !m_recent_confirmed_transactions_mutex, !m_most_recent_block_mutex, g_msgproc_mutex);
|
||||
|
||||
/** Implement PeerManager */
|
||||
void StartScheduledTasks(CScheduler& scheduler) override;
|
||||
|
|
@ -532,12 +528,12 @@ public:
|
|||
void UnitTestMisbehaving(NodeId peer_id, int howmuch) override EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex) { Misbehaving(*Assert(GetPeerRef(peer_id)), howmuch, ""); };
|
||||
void ProcessMessage(CNode& pfrom, const std::string& msg_type, CDataStream& vRecv,
|
||||
const std::chrono::microseconds time_received, const std::atomic<bool>& interruptMsgProc) override
|
||||
EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex, !m_recent_confirmed_transactions_mutex, !m_most_recent_block_mutex, !m_headers_presync_mutex);
|
||||
EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex, !m_recent_confirmed_transactions_mutex, !m_most_recent_block_mutex, !m_headers_presync_mutex, g_msgproc_mutex);
|
||||
void UpdateLastBlockAnnounceTime(NodeId node, int64_t time_in_seconds) override;
|
||||
|
||||
private:
|
||||
/** Consider evicting an outbound peer based on the amount of time they've been behind our tip */
|
||||
void ConsiderEviction(CNode& pto, Peer& peer, std::chrono::seconds time_in_seconds) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
|
||||
void ConsiderEviction(CNode& pto, Peer& peer, std::chrono::seconds time_in_seconds) EXCLUSIVE_LOCKS_REQUIRED(cs_main, g_msgproc_mutex);
|
||||
|
||||
/** If we have extra outbound peers, try to disconnect the one with the oldest block announcement */
|
||||
void EvictExtraOutboundPeers(std::chrono::seconds now) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
|
||||
|
|
@ -601,7 +597,7 @@ private:
|
|||
void ProcessHeadersMessage(CNode& pfrom, Peer& peer,
|
||||
std::vector<CBlockHeader>&& headers,
|
||||
bool via_compact_block)
|
||||
EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex, !m_headers_presync_mutex);
|
||||
EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex, !m_headers_presync_mutex, g_msgproc_mutex);
|
||||
/** Various helpers for headers processing, invoked by ProcessHeadersMessage() */
|
||||
/** Return true if headers are continuous and have valid proof-of-work (DoS points assigned on failure) */
|
||||
bool CheckHeadersPoW(const std::vector<CBlockHeader>& headers, const Consensus::Params& consensusParams, Peer& peer);
|
||||
|
|
@ -610,7 +606,7 @@ private:
|
|||
/** Deal with state tracking and headers sync for peers that send the
|
||||
* occasional non-connecting header (this can happen due to BIP 130 headers
|
||||
* announcements for blocks interacting with the 2hr (MAX_FUTURE_BLOCK_TIME) rule). */
|
||||
void HandleFewUnconnectingHeaders(CNode& pfrom, Peer& peer, const std::vector<CBlockHeader>& headers);
|
||||
void HandleFewUnconnectingHeaders(CNode& pfrom, Peer& peer, const std::vector<CBlockHeader>& headers) EXCLUSIVE_LOCKS_REQUIRED(g_msgproc_mutex);
|
||||
/** Return true if the headers connect to each other, false otherwise */
|
||||
bool CheckHeadersAreContinuous(const std::vector<CBlockHeader>& headers) const;
|
||||
/** Try to continue a low-work headers sync that has already begun.
|
||||
|
|
@ -633,7 +629,7 @@ private:
|
|||
*/
|
||||
bool IsContinuationOfLowWorkHeadersSync(Peer& peer, CNode& pfrom,
|
||||
std::vector<CBlockHeader>& headers)
|
||||
EXCLUSIVE_LOCKS_REQUIRED(peer.m_headers_sync_mutex, !m_headers_presync_mutex);
|
||||
EXCLUSIVE_LOCKS_REQUIRED(peer.m_headers_sync_mutex, !m_headers_presync_mutex, g_msgproc_mutex);
|
||||
/** Check work on a headers chain to be processed, and if insufficient,
|
||||
* initiate our anti-DoS headers sync mechanism.
|
||||
*
|
||||
|
|
@ -649,7 +645,7 @@ private:
|
|||
bool TryLowWorkHeadersSync(Peer& peer, CNode& pfrom,
|
||||
const CBlockIndex* chain_start_header,
|
||||
std::vector<CBlockHeader>& headers)
|
||||
EXCLUSIVE_LOCKS_REQUIRED(!peer.m_headers_sync_mutex, !m_peer_mutex, !m_headers_presync_mutex);
|
||||
EXCLUSIVE_LOCKS_REQUIRED(!peer.m_headers_sync_mutex, !m_peer_mutex, !m_headers_presync_mutex, g_msgproc_mutex);
|
||||
|
||||
/** Return true if the given header is an ancestor of
|
||||
* m_chainman.m_best_header or our current tip */
|
||||
|
|
@ -659,7 +655,7 @@ private:
|
|||
* We don't issue a getheaders message if we have a recent one outstanding.
|
||||
* This returns true if a getheaders is actually sent, and false otherwise.
|
||||
*/
|
||||
bool MaybeSendGetHeaders(CNode& pfrom, const CBlockLocator& locator, Peer& peer);
|
||||
bool MaybeSendGetHeaders(CNode& pfrom, const CBlockLocator& locator, Peer& peer) EXCLUSIVE_LOCKS_REQUIRED(g_msgproc_mutex);
|
||||
/** Potentially fetch blocks from this peer upon receipt of a new headers tip */
|
||||
void HeadersDirectFetchBlocks(CNode& pfrom, const Peer& peer, const CBlockIndex* pindexLast);
|
||||
/** Update peer state based on received headers message */
|
||||
|
|
@ -683,10 +679,10 @@ private:
|
|||
void MaybeSendPing(CNode& node_to, Peer& peer, std::chrono::microseconds now);
|
||||
|
||||
/** Send `addr` messages on a regular schedule. */
|
||||
void MaybeSendAddr(CNode& node, Peer& peer, std::chrono::microseconds current_time);
|
||||
void MaybeSendAddr(CNode& node, Peer& peer, std::chrono::microseconds current_time) EXCLUSIVE_LOCKS_REQUIRED(g_msgproc_mutex);
|
||||
|
||||
/** Send a single `sendheaders` message, after we have completed headers sync with a peer. */
|
||||
void MaybeSendSendHeaders(CNode& node, Peer& peer);
|
||||
void MaybeSendSendHeaders(CNode& node, Peer& peer) EXCLUSIVE_LOCKS_REQUIRED(g_msgproc_mutex);
|
||||
|
||||
/** Relay (gossip) an address to a few randomly chosen nodes.
|
||||
*
|
||||
|
|
@ -695,10 +691,10 @@ private:
|
|||
* @param[in] fReachable Whether the address' network is reachable. We relay unreachable
|
||||
* addresses less.
|
||||
*/
|
||||
void RelayAddress(NodeId originator, const CAddress& addr, bool fReachable) EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex);
|
||||
void RelayAddress(NodeId originator, const CAddress& addr, bool fReachable) EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex, g_msgproc_mutex);
|
||||
|
||||
/** Send `feefilter` message. */
|
||||
void MaybeSendFeefilter(CNode& node, Peer& peer, std::chrono::microseconds current_time);
|
||||
void MaybeSendFeefilter(CNode& node, Peer& peer, std::chrono::microseconds current_time) EXCLUSIVE_LOCKS_REQUIRED(g_msgproc_mutex);
|
||||
|
||||
const CChainParams& m_chainparams;
|
||||
CConnman& m_connman;
|
||||
|
|
@ -708,6 +704,7 @@ private:
|
|||
ChainstateManager& m_chainman;
|
||||
CTxMemPool& m_mempool;
|
||||
TxRequestTracker m_txrequest GUARDED_BY(::cs_main);
|
||||
std::unique_ptr<TxReconciliationTracker> m_txreconciliation;
|
||||
|
||||
/** The height of the best chain */
|
||||
std::atomic<int> m_best_height{-1};
|
||||
|
|
@ -751,7 +748,7 @@ private:
|
|||
int nSyncStarted GUARDED_BY(cs_main) = 0;
|
||||
|
||||
/** Hash of the last block we received via INV */
|
||||
uint256 m_last_block_inv_triggering_headers_sync{};
|
||||
uint256 m_last_block_inv_triggering_headers_sync GUARDED_BY(g_msgproc_mutex){};
|
||||
|
||||
/**
|
||||
* Sources of received blocks, saved to be able punish them when processing
|
||||
|
|
@ -863,7 +860,7 @@ private:
|
|||
std::atomic_bool m_headers_presync_should_signal{false};
|
||||
|
||||
/** Height of the highest block announced using BIP 152 high-bandwidth mode. */
|
||||
int m_highest_fast_announce{0};
|
||||
int m_highest_fast_announce GUARDED_BY(::cs_main){0};
|
||||
|
||||
/** Have we requested this block from a peer */
|
||||
bool IsBlockRequested(const uint256& hash) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
|
||||
|
|
@ -1010,7 +1007,10 @@ private:
|
|||
* @return True if address relay is enabled with peer
|
||||
* False if address relay is disallowed
|
||||
*/
|
||||
bool SetupAddressRelay(const CNode& node, Peer& peer);
|
||||
bool SetupAddressRelay(const CNode& node, Peer& peer) EXCLUSIVE_LOCKS_REQUIRED(g_msgproc_mutex);
|
||||
|
||||
void AddAddressKnown(Peer& peer, const CAddress& addr) EXCLUSIVE_LOCKS_REQUIRED(g_msgproc_mutex);
|
||||
void PushAddress(Peer& peer, const CAddress& addr, FastRandomContext& insecure_rand) EXCLUSIVE_LOCKS_REQUIRED(g_msgproc_mutex);
|
||||
};
|
||||
|
||||
const CNodeState* PeerManagerImpl::State(NodeId pnode) const EXCLUSIVE_LOCKS_REQUIRED(cs_main)
|
||||
|
|
@ -1036,13 +1036,13 @@ static bool IsAddrCompatible(const Peer& peer, const CAddress& addr)
|
|||
return peer.m_wants_addrv2 || addr.IsAddrV1Compatible();
|
||||
}
|
||||
|
||||
static void AddAddressKnown(Peer& peer, const CAddress& addr)
|
||||
void PeerManagerImpl::AddAddressKnown(Peer& peer, const CAddress& addr)
|
||||
{
|
||||
assert(peer.m_addr_known);
|
||||
peer.m_addr_known->insert(addr.GetKey());
|
||||
}
|
||||
|
||||
static void PushAddress(Peer& peer, const CAddress& addr, FastRandomContext& insecure_rand)
|
||||
void PeerManagerImpl::PushAddress(Peer& peer, const CAddress& addr, FastRandomContext& insecure_rand)
|
||||
{
|
||||
// Known checking here is only to save space from duplicates.
|
||||
// Before sending, we'll filter it again for known addresses that were
|
||||
|
|
@ -1295,7 +1295,7 @@ void PeerManagerImpl::FindNextBlocksToDownload(const Peer& peer, unsigned int co
|
|||
// Make sure pindexBestKnownBlock is up to date, we'll need it.
|
||||
ProcessBlockAvailability(peer.m_id);
|
||||
|
||||
if (state->pindexBestKnownBlock == nullptr || state->pindexBestKnownBlock->nChainWork < m_chainman.ActiveChain().Tip()->nChainWork || state->pindexBestKnownBlock->nChainWork < nMinimumChainWork) {
|
||||
if (state->pindexBestKnownBlock == nullptr || state->pindexBestKnownBlock->nChainWork < m_chainman.ActiveChain().Tip()->nChainWork || state->pindexBestKnownBlock->nChainWork < m_chainman.MinimumChainWork()) {
|
||||
// This peer has nothing interesting.
|
||||
return;
|
||||
}
|
||||
|
|
@ -1384,7 +1384,7 @@ void PeerManagerImpl::PushNodeVersion(CNode& pnode, const Peer& peer)
|
|||
CService addr_you = addr.IsRoutable() && !IsProxy(addr) && addr.IsAddrV1Compatible() ? addr : CService();
|
||||
uint64_t your_services{addr.nServices};
|
||||
|
||||
const bool tx_relay = !m_ignore_incoming_txs && !pnode.IsBlockOnlyConn() && !pnode.IsFeelerConn();
|
||||
const bool tx_relay{!RejectIncomingTxs(pnode)};
|
||||
m_connman.PushMessage(&pnode, CNetMsgMaker(INIT_PROTO_VERSION).Make(NetMsgType::VERSION, PROTOCOL_VERSION, my_services, nTime,
|
||||
your_services, addr_you, // Together the pre-version-31402 serialization of CAddress "addrYou" (without nTime)
|
||||
my_services, CService(), // Together the pre-version-31402 serialization of CAddress "addrMe" (without nTime)
|
||||
|
|
@ -1498,6 +1498,7 @@ void PeerManagerImpl::FinalizeNode(const CNode& node)
|
|||
}
|
||||
WITH_LOCK(g_cs_orphans, m_orphanage.EraseForPeer(nodeid));
|
||||
m_txrequest.DisconnectedPeer(nodeid);
|
||||
if (m_txreconciliation) m_txreconciliation->ForgetPeer(nodeid);
|
||||
m_num_preferred_download_peers -= state->fPreferredDownload;
|
||||
m_peers_downloading_from -= (state->nBlocksInFlight != 0);
|
||||
assert(m_peers_downloading_from >= 0);
|
||||
|
|
@ -1782,6 +1783,11 @@ PeerManagerImpl::PeerManagerImpl(CConnman& connman, AddrMan& addrman,
|
|||
m_mempool(pool),
|
||||
m_ignore_incoming_txs(ignore_incoming_txs)
|
||||
{
|
||||
// While Erlay support is incomplete, it must be enabled explicitly via -txreconciliation.
|
||||
// This argument can go away after Erlay support is complete.
|
||||
if (gArgs.GetBoolArg("-txreconciliation", DEFAULT_TXRECONCILIATION_ENABLE)) {
|
||||
m_txreconciliation = std::make_unique<TxReconciliationTracker>(TXRECONCILIATION_VERSION);
|
||||
}
|
||||
}
|
||||
|
||||
void PeerManagerImpl::StartScheduledTasks(CScheduler& scheduler)
|
||||
|
|
@ -2390,7 +2396,7 @@ arith_uint256 PeerManagerImpl::GetAntiDoSWorkThreshold()
|
|||
// near our tip.
|
||||
near_chaintip_work = tip->nChainWork - std::min<arith_uint256>(144*GetBlockProof(*tip), tip->nChainWork);
|
||||
}
|
||||
return std::max(near_chaintip_work, arith_uint256(nMinimumChainWork));
|
||||
return std::max(near_chaintip_work, m_chainman.MinimumChainWork());
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -2563,14 +2569,22 @@ bool PeerManagerImpl::TryLowWorkHeadersSync(Peer& peer, CNode& pfrom, const CBlo
|
|||
|
||||
// Now a HeadersSyncState object for tracking this synchronization is created,
|
||||
// process the headers using it as normal.
|
||||
return IsContinuationOfLowWorkHeadersSync(peer, pfrom, headers);
|
||||
if (!IsContinuationOfLowWorkHeadersSync(peer, pfrom, headers)) {
|
||||
// Something went wrong, reset the headers sync.
|
||||
peer.m_headers_sync.reset(nullptr);
|
||||
LOCK(m_headers_presync_mutex);
|
||||
m_headers_presync_stats.erase(peer.m_id);
|
||||
}
|
||||
} else {
|
||||
LogPrint(BCLog::NET, "Ignoring low-work chain (height=%u) from peer=%d\n", chain_start_header->nHeight + headers.size(), pfrom.GetId());
|
||||
// Since this is a low-work headers chain, no further processing is required.
|
||||
headers = {};
|
||||
return true;
|
||||
}
|
||||
|
||||
// The peer has not yet given us a chain that meets our work threshold,
|
||||
// so we want to prevent further processing of the headers in any case.
|
||||
headers = {};
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -2700,14 +2714,14 @@ void PeerManagerImpl::UpdatePeerStateForReceivedHeaders(CNode& pfrom,
|
|||
if (m_chainman.ActiveChainstate().IsInitialBlockDownload() && !may_have_more_headers) {
|
||||
// If the peer has no more headers to give us, then we know we have
|
||||
// their tip.
|
||||
if (nodestate->pindexBestKnownBlock && nodestate->pindexBestKnownBlock->nChainWork < nMinimumChainWork) {
|
||||
if (nodestate->pindexBestKnownBlock && nodestate->pindexBestKnownBlock->nChainWork < m_chainman.MinimumChainWork()) {
|
||||
// This peer has too little work on their headers chain to help
|
||||
// us sync -- disconnect if it is an outbound disconnection
|
||||
// candidate.
|
||||
// Note: We compare their tip to nMinimumChainWork (rather than
|
||||
// Note: We compare their tip to the minumum chain work (rather than
|
||||
// m_chainman.ActiveChain().Tip()) because we won't start block download
|
||||
// until we have a headers chain that has at least
|
||||
// nMinimumChainWork, even if a peer has a chain past our tip,
|
||||
// the minimum chain work, even if a peer has a chain past our tip,
|
||||
// as an anti-DoS measure.
|
||||
if (pfrom.IsOutboundOrBlockRelayConn()) {
|
||||
LogPrintf("Disconnecting outbound peer %d -- headers chain has insufficient work\n", pfrom.GetId());
|
||||
|
|
@ -2877,7 +2891,7 @@ void PeerManagerImpl::ProcessHeadersMessage(CNode& pfrom, Peer& peer,
|
|||
|
||||
// If we don't have the last header, then this peer will have given us
|
||||
// something new (if these headers are valid).
|
||||
bool received_new_header{last_received_header != nullptr};
|
||||
bool received_new_header{last_received_header == nullptr};
|
||||
|
||||
// Now process all the headers.
|
||||
BlockValidationState state;
|
||||
|
|
@ -3188,6 +3202,8 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
|
|||
const std::chrono::microseconds time_received,
|
||||
const std::atomic<bool>& interruptMsgProc)
|
||||
{
|
||||
AssertLockHeld(g_msgproc_mutex);
|
||||
|
||||
LogPrint(BCLog::NET, "received: %s (%u bytes) peer=%d\n", SanitizeString(msg_type), vRecv.size(), pfrom.GetId());
|
||||
|
||||
PeerRef peer = GetPeerRef(pfrom.GetId());
|
||||
|
|
@ -3289,8 +3305,6 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
|
|||
m_connman.PushMessage(&pfrom, msg_maker.Make(NetMsgType::SENDADDRV2));
|
||||
}
|
||||
|
||||
m_connman.PushMessage(&pfrom, msg_maker.Make(NetMsgType::VERACK));
|
||||
|
||||
pfrom.m_has_all_wanted_services = HasAllDesirableServiceFlags(nServices);
|
||||
peer->m_their_services = nServices;
|
||||
pfrom.SetAddrLocal(addrMe);
|
||||
|
|
@ -3300,10 +3314,11 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
|
|||
}
|
||||
peer->m_starting_height = starting_height;
|
||||
|
||||
// We only initialize the m_tx_relay data structure if:
|
||||
// - this isn't an outbound block-relay-only connection; and
|
||||
// - fRelay=true or we're offering NODE_BLOOM to this peer
|
||||
// (NODE_BLOOM means that the peer may turn on tx relay later)
|
||||
// We only initialize the Peer::TxRelay m_relay_txs data structure if:
|
||||
// - this isn't an outbound block-relay-only connection, and
|
||||
// - fRelay=true (the peer wishes to receive transaction announcements)
|
||||
// or we're offering NODE_BLOOM to this peer. NODE_BLOOM means that
|
||||
// the peer may turn on transaction relay later.
|
||||
if (!pfrom.IsBlockOnlyConn() &&
|
||||
(fRelay || (peer->m_our_services & NODE_BLOOM))) {
|
||||
auto* const tx_relay = peer->SetTxRelay();
|
||||
|
|
@ -3314,6 +3329,25 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
|
|||
if (fRelay) pfrom.m_relays_txs = true;
|
||||
}
|
||||
|
||||
if (greatest_common_version >= WTXID_RELAY_VERSION && m_txreconciliation) {
|
||||
// Per BIP-330, we announce txreconciliation support if:
|
||||
// - protocol version per the VERSION message supports WTXID_RELAY;
|
||||
// - we intended to exchange transactions over this connection while establishing it
|
||||
// and the peer indicated support for transaction relay in the VERSION message;
|
||||
// - we are not in -blocksonly mode.
|
||||
if (pfrom.m_relays_txs && !m_ignore_incoming_txs) {
|
||||
const uint64_t recon_salt = m_txreconciliation->PreRegisterPeer(pfrom.GetId());
|
||||
// We suggest our txreconciliation role (initiator/responder) based on
|
||||
// the connection direction.
|
||||
m_connman.PushMessage(&pfrom, msg_maker.Make(NetMsgType::SENDTXRCNCL,
|
||||
!pfrom.IsInboundConn(),
|
||||
pfrom.IsInboundConn(),
|
||||
TXRECONCILIATION_VERSION, recon_salt));
|
||||
}
|
||||
}
|
||||
|
||||
m_connman.PushMessage(&pfrom, msg_maker.Make(NetMsgType::VERACK));
|
||||
|
||||
// Potentially mark this peer as a preferred download peer.
|
||||
{
|
||||
LOCK(cs_main);
|
||||
|
|
@ -3441,6 +3475,16 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
|
|||
// they may wish to request compact blocks from us
|
||||
m_connman.PushMessage(&pfrom, msgMaker.Make(NetMsgType::SENDCMPCT, /*high_bandwidth=*/false, /*version=*/CMPCTBLOCKS_VERSION));
|
||||
}
|
||||
|
||||
if (m_txreconciliation) {
|
||||
if (!peer->m_wtxid_relay || !m_txreconciliation->IsPeerRegistered(pfrom.GetId())) {
|
||||
// We could have optimistically pre-registered/registered the peer. In that case,
|
||||
// we should forget about the reconciliation state here if this wasn't followed
|
||||
// by WTXIDRELAY (since WTXIDRELAY can't be announced later).
|
||||
m_txreconciliation->ForgetPeer(pfrom.GetId());
|
||||
}
|
||||
}
|
||||
|
||||
pfrom.fSuccessfullyConnected = true;
|
||||
return;
|
||||
}
|
||||
|
|
@ -3504,6 +3548,58 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
|
|||
return;
|
||||
}
|
||||
|
||||
// Received from a peer demonstrating readiness to announce transactions via reconciliations.
|
||||
// This feature negotiation must happen between VERSION and VERACK to avoid relay problems
|
||||
// from switching announcement protocols after the connection is up.
|
||||
if (msg_type == NetMsgType::SENDTXRCNCL) {
|
||||
if (!m_txreconciliation) {
|
||||
LogPrintLevel(BCLog::NET, BCLog::Level::Debug, "sendtxrcncl from peer=%d ignored, as our node does not have txreconciliation enabled\n", pfrom.GetId());
|
||||
return;
|
||||
}
|
||||
|
||||
if (pfrom.fSuccessfullyConnected) {
|
||||
// Disconnect peers that send a SENDTXRCNCL message after VERACK.
|
||||
LogPrintLevel(BCLog::NET, BCLog::Level::Debug, "sendtxrcncl received after verack from peer=%d; disconnecting\n", pfrom.GetId());
|
||||
pfrom.fDisconnect = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!peer->GetTxRelay()) {
|
||||
// Disconnect peers that send a SENDTXRCNCL message even though we indicated we don't
|
||||
// support transaction relay.
|
||||
LogPrintLevel(BCLog::NET, BCLog::Level::Debug, "sendtxrcncl received from peer=%d to which we indicated no tx relay; disconnecting\n", pfrom.GetId());
|
||||
pfrom.fDisconnect = true;
|
||||
return;
|
||||
}
|
||||
|
||||
bool is_peer_initiator, is_peer_responder;
|
||||
uint32_t peer_txreconcl_version;
|
||||
uint64_t remote_salt;
|
||||
vRecv >> is_peer_initiator >> is_peer_responder >> peer_txreconcl_version >> remote_salt;
|
||||
|
||||
if (m_txreconciliation->IsPeerRegistered(pfrom.GetId())) {
|
||||
// A peer is already registered, meaning we already received SENDTXRCNCL from them.
|
||||
LogPrintLevel(BCLog::NET, BCLog::Level::Debug, "txreconciliation protocol violation from peer=%d (sendtxrcncl received from already registered peer); disconnecting\n", pfrom.GetId());
|
||||
pfrom.fDisconnect = true;
|
||||
return;
|
||||
}
|
||||
|
||||
const ReconciliationRegisterResult result = m_txreconciliation->RegisterPeer(pfrom.GetId(), pfrom.IsInboundConn(),
|
||||
is_peer_initiator, is_peer_responder,
|
||||
peer_txreconcl_version,
|
||||
remote_salt);
|
||||
|
||||
// If it's a protocol violation, disconnect.
|
||||
// If the peer was not found (but something unexpected happened) or it was registered,
|
||||
// nothing to be done.
|
||||
if (result == ReconciliationRegisterResult::PROTOCOL_VIOLATION) {
|
||||
LogPrintLevel(BCLog::NET, BCLog::Level::Debug, "txreconciliation protocol violation from peer=%d; disconnecting\n", pfrom.GetId());
|
||||
pfrom.fDisconnect = true;
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (!pfrom.fSuccessfullyConnected) {
|
||||
LogPrint(BCLog::NET, "Unsupported message \"%s\" prior to verack from peer=%d\n", SanitizeString(msg_type), pfrom.GetId());
|
||||
return;
|
||||
|
|
@ -3858,12 +3954,12 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
|
|||
// Note that if we were to be on a chain that forks from the checkpointed
|
||||
// chain, then serving those headers to a peer that has seen the
|
||||
// checkpointed chain would cause that peer to disconnect us. Requiring
|
||||
// that our chainwork exceed nMinimumChainWork is a protection against
|
||||
// that our chainwork exceed the mimimum chain work is a protection against
|
||||
// being fed a bogus chain when we started up for the first time and
|
||||
// getting partitioned off the honest network for serving that chain to
|
||||
// others.
|
||||
if (m_chainman.ActiveTip() == nullptr ||
|
||||
(m_chainman.ActiveTip()->nChainWork < nMinimumChainWork && !pfrom.HasPermission(NetPermissionFlags::Download))) {
|
||||
(m_chainman.ActiveTip()->nChainWork < m_chainman.MinimumChainWork() && !pfrom.HasPermission(NetPermissionFlags::Download))) {
|
||||
LogPrint(BCLog::NET, "Ignoring getheaders from peer=%d because active chain has too little work; sending empty response\n", pfrom.GetId());
|
||||
// Just respond with an empty headers message, to tell the peer to
|
||||
// go away but not treat us as unresponsive.
|
||||
|
|
@ -4341,7 +4437,7 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
|
|||
// (eg disk space). Because we only try to reconstruct blocks when
|
||||
// we're close to caught up (via the CanDirectFetch() requirement
|
||||
// above, combined with the behavior of not requesting blocks until
|
||||
// we have a chain with at least nMinimumChainWork), and we ignore
|
||||
// we have a chain with at least the minimum chain work), and we ignore
|
||||
// compact blocks with less work than our tip, it is safe to treat
|
||||
// reconstructed compact blocks as having been requested.
|
||||
ProcessBlock(pfrom, pblock, /*force_processing=*/true, /*min_pow_checked=*/true);
|
||||
|
|
@ -4815,6 +4911,8 @@ bool PeerManagerImpl::MaybeDiscourageAndDisconnect(CNode& pnode, Peer& peer)
|
|||
|
||||
bool PeerManagerImpl::ProcessMessages(CNode* pfrom, std::atomic<bool>& interruptMsgProc)
|
||||
{
|
||||
AssertLockHeld(g_msgproc_mutex);
|
||||
|
||||
bool fMoreWork = false;
|
||||
|
||||
PeerRef peer = GetPeerRef(pfrom->GetId());
|
||||
|
|
@ -5166,7 +5264,7 @@ void PeerManagerImpl::MaybeSendAddr(CNode& node, Peer& peer, std::chrono::micros
|
|||
|
||||
// Remove addr records that the peer already knows about, and add new
|
||||
// addrs to the m_addr_known filter on the same pass.
|
||||
auto addr_already_known = [&peer](const CAddress& addr) {
|
||||
auto addr_already_known = [&peer](const CAddress& addr) EXCLUSIVE_LOCKS_REQUIRED(g_msgproc_mutex) {
|
||||
bool ret = peer.m_addr_known->contains(addr.GetKey());
|
||||
if (!ret) peer.m_addr_known->insert(addr.GetKey());
|
||||
return ret;
|
||||
|
|
@ -5205,7 +5303,7 @@ void PeerManagerImpl::MaybeSendSendHeaders(CNode& node, Peer& peer)
|
|||
LOCK(cs_main);
|
||||
CNodeState &state = *State(node.GetId());
|
||||
if (state.pindexBestKnownBlock != nullptr &&
|
||||
state.pindexBestKnownBlock->nChainWork > nMinimumChainWork) {
|
||||
state.pindexBestKnownBlock->nChainWork > m_chainman.MinimumChainWork()) {
|
||||
// Tell our peer we prefer to receive headers rather than inv's
|
||||
// We send this to non-NODE NETWORK peers as well, because even
|
||||
// non-NODE NETWORK peers can announce blocks (such as pruning
|
||||
|
|
@ -5284,6 +5382,7 @@ bool PeerManagerImpl::RejectIncomingTxs(const CNode& peer) const
|
|||
{
|
||||
// block-relay-only peers may never send txs to us
|
||||
if (peer.IsBlockOnlyConn()) return true;
|
||||
if (peer.IsFeelerConn()) return true;
|
||||
// In -blocksonly mode, peers need the 'relay' permission to send txs to us
|
||||
if (m_ignore_incoming_txs && !peer.HasPermission(NetPermissionFlags::Relay)) return true;
|
||||
return false;
|
||||
|
|
@ -5307,6 +5406,8 @@ bool PeerManagerImpl::SetupAddressRelay(const CNode& node, Peer& peer)
|
|||
|
||||
bool PeerManagerImpl::SendMessages(CNode* pto)
|
||||
{
|
||||
AssertLockHeld(g_msgproc_mutex);
|
||||
|
||||
PeerRef peer = GetPeerRef(pto->GetId());
|
||||
if (!peer) return false;
|
||||
const Consensus::Params& consensusParams = m_chainparams.GetConsensus();
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue