diff --git a/src/net.cpp b/src/net.cpp index 03ed7e7fc..b4b43c3ba 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -2710,6 +2710,7 @@ CNode::CNode(NodeId idIn, ServiceFlags nLocalServicesIn, int nMyStartingHeightIn fOneShot = false; m_manual_connection = false; fClient = false; // set by version message + m_limited_node = false; // set by version message fFeeler = false; fSuccessfullyConnected = false; fDisconnect = false; diff --git a/src/net.h b/src/net.h index 0542ec1aa..db0a1e62b 100644 --- a/src/net.h +++ b/src/net.h @@ -643,6 +643,7 @@ public: bool fOneShot; bool m_manual_connection; bool fClient; + bool m_limited_node; //after BIP159 const bool fInbound; std::atomic_bool fSuccessfullyConnected; std::atomic_bool fDisconnect; diff --git a/src/net_processing.cpp b/src/net_processing.cpp index f63371291..55d404d91 100644 --- a/src/net_processing.cpp +++ b/src/net_processing.cpp @@ -892,6 +892,7 @@ void PeerLogicValidation::UpdatedBlockTip(const CBlockIndex *pindexNew, const CB const int nNewHeight = pindexNew->nHeight; connman->SetBestHeight(nNewHeight); + g_initial_block_download_completed = !fInitialDownload; if (!fInitialDownload) { // Find the hashes of all blocks that weren't previously in the best chain. std::vector vHashes; @@ -1642,7 +1643,13 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr pfrom->cleanSubVer = cleanSubVer; } pfrom->nStartingHeight = nStartingHeight; - pfrom->fClient = !(nServices & NODE_NETWORK); + + // set nodes not relaying blocks and tx and not serving (parts) of the historical blockchain as "clients" + pfrom->fClient = (!(nServices & NODE_NETWORK) && !(nServices & NODE_NETWORK_LIMITED)); + + // set nodes not capable of serving the complete blockchain history as "limited nodes" + pfrom->m_limited_node = (!(nServices & NODE_NETWORK) && (nServices & NODE_NETWORK_LIMITED)); + { LOCK(pfrom->cs_filter); pfrom->fRelayTxes = fRelay; // set to true after we get the first filter* message @@ -3611,7 +3618,7 @@ bool PeerLogicValidation::SendMessages(CNode* pto, std::atomic& interruptM // Message: getdata (blocks) // std::vector vGetData; - if (!pto->fClient && (fFetch || !IsInitialBlockDownload()) && state.nBlocksInFlight < MAX_BLOCKS_IN_TRANSIT_PER_PEER) { + if (!pto->fClient && ((fFetch && !pto->m_limited_node) || !IsInitialBlockDownload()) && state.nBlocksInFlight < MAX_BLOCKS_IN_TRANSIT_PER_PEER) { std::vector vToDownload; NodeId staller = -1; FindNextBlocksToDownload(pto->GetId(), MAX_BLOCKS_IN_TRANSIT_PER_PEER - state.nBlocksInFlight, vToDownload, staller, consensusParams); diff --git a/src/protocol.cpp b/src/protocol.cpp index c412ad9ff..ea78ab685 100644 --- a/src/protocol.cpp +++ b/src/protocol.cpp @@ -12,6 +12,8 @@ # include #endif +std::atomic g_initial_block_download_completed(false); + namespace NetMsgType { const char *VERSION="version"; const char *VERACK="verack"; diff --git a/src/protocol.h b/src/protocol.h index ec5f55e4f..4907c38e5 100644 --- a/src/protocol.h +++ b/src/protocol.h @@ -15,6 +15,7 @@ #include #include +#include #include #include @@ -277,6 +278,7 @@ enum ServiceFlags : uint64_t { // BIP process. }; +extern std::atomic g_initial_block_download_completed; /** * Gets the set of service flags which are "desirable" for a given peer. * @@ -302,6 +304,9 @@ enum ServiceFlags : uint64_t { * should be updated appropriately to filter for the same nodes. */ static ServiceFlags GetDesirableServiceFlags(ServiceFlags services) { + if ((services & NODE_NETWORK_LIMITED) && g_initial_block_download_completed) { + return ServiceFlags(NODE_NETWORK_LIMITED | NODE_WITNESS); + } return ServiceFlags(NODE_NETWORK | NODE_WITNESS); }