diff options
Diffstat (limited to 'src/net_processing.cpp')
-rw-r--r-- | src/net_processing.cpp | 91 |
1 files changed, 71 insertions, 20 deletions
diff --git a/src/net_processing.cpp b/src/net_processing.cpp index 159036a237..404b33a977 100644 --- a/src/net_processing.cpp +++ b/src/net_processing.cpp @@ -129,6 +129,8 @@ static constexpr unsigned int INVENTORY_BROADCAST_MAX = 7 * INVENTORY_BROADCAST_ static constexpr unsigned int AVG_FEEFILTER_BROADCAST_INTERVAL = 10 * 60; /** Maximum feefilter broadcast delay after significant change. */ static constexpr unsigned int MAX_FEEFILTER_CHANGE_DELAY = 5 * 60; +/** Maximum number of compact filters that may be requested with one getcfilters. See BIP 157. */ +static constexpr uint32_t MAX_GETCFILTERS_SIZE = 1000; /** Maximum number of cf hashes that may be requested with one getcfheaders. See BIP 157. */ static constexpr uint32_t MAX_GETCFHEADERS_SIZE = 2000; @@ -827,7 +829,8 @@ void PeerLogicValidation::ReattemptInitialBroadcast(CScheduler& scheduler) const } } - // schedule next run for 10-15 minutes in the future + // Schedule next run for 10-15 minutes in the future. + // We add randomness on every cycle to avoid the possibility of P2P fingerprinting. const std::chrono::milliseconds delta = std::chrono::minutes{10} + GetRandMillis(std::chrono::minutes{5}); scheduler.scheduleFromNow([&] { ReattemptInitialBroadcast(scheduler); }, delta); } @@ -1998,7 +2001,7 @@ void static ProcessOrphanTx(CConnman* connman, CTxMemPool& mempool, std::set<uin * @param[out] filter_index The filter index, if the request can be serviced. * @return True if the request can be serviced. */ -static bool PrepareBlockFilterRequest(CNode* pfrom, const CChainParams& chain_params, +static bool PrepareBlockFilterRequest(CNode& pfrom, const CChainParams& chain_params, BlockFilterType filter_type, uint32_t start_height, const uint256& stop_hash, uint32_t max_height_diff, const CBlockIndex*& stop_index, @@ -2009,8 +2012,8 @@ static bool PrepareBlockFilterRequest(CNode* pfrom, const CChainParams& chain_pa gArgs.GetBoolArg("-peerblockfilters", DEFAULT_PEERBLOCKFILTERS)); if (!supported_filter_type) { LogPrint(BCLog::NET, "peer %d requested unsupported block filter type: %d\n", - pfrom->GetId(), static_cast<uint8_t>(filter_type)); - pfrom->fDisconnect = true; + pfrom.GetId(), static_cast<uint8_t>(filter_type)); + pfrom.fDisconnect = true; return false; } @@ -2021,8 +2024,8 @@ static bool PrepareBlockFilterRequest(CNode* pfrom, const CChainParams& chain_pa // Check that the stop block exists and the peer would be allowed to fetch it. if (!stop_index || !BlockRequestAllowed(stop_index, chain_params.GetConsensus())) { LogPrint(BCLog::NET, "peer %d requested invalid block hash: %s\n", - pfrom->GetId(), stop_hash.ToString()); - pfrom->fDisconnect = true; + pfrom.GetId(), stop_hash.ToString()); + pfrom.fDisconnect = true; return false; } } @@ -2031,14 +2034,14 @@ static bool PrepareBlockFilterRequest(CNode* pfrom, const CChainParams& chain_pa if (start_height > stop_height) { LogPrint(BCLog::NET, "peer %d sent invalid getcfilters/getcfheaders with " /* Continued */ "start height %d and stop height %d\n", - pfrom->GetId(), start_height, stop_height); - pfrom->fDisconnect = true; + pfrom.GetId(), start_height, stop_height); + pfrom.fDisconnect = true; return false; } if (stop_height - start_height >= max_height_diff) { LogPrint(BCLog::NET, "peer %d requested too many cfilters/cfheaders: %d / %d\n", - pfrom->GetId(), stop_height - start_height + 1, max_height_diff); - pfrom->fDisconnect = true; + pfrom.GetId(), stop_height - start_height + 1, max_height_diff); + pfrom.fDisconnect = true; return false; } @@ -2052,6 +2055,49 @@ static bool PrepareBlockFilterRequest(CNode* pfrom, const CChainParams& chain_pa } /** + * Handle a cfilters request. + * + * May disconnect from the peer in the case of a bad request. + * + * @param[in] pfrom The peer that we received the request from + * @param[in] vRecv The raw message received + * @param[in] chain_params Chain parameters + * @param[in] connman Pointer to the connection manager + */ +static void ProcessGetCFilters(CNode& pfrom, CDataStream& vRecv, const CChainParams& chain_params, + CConnman& connman) +{ + uint8_t filter_type_ser; + uint32_t start_height; + uint256 stop_hash; + + vRecv >> filter_type_ser >> start_height >> stop_hash; + + const BlockFilterType filter_type = static_cast<BlockFilterType>(filter_type_ser); + + const CBlockIndex* stop_index; + BlockFilterIndex* filter_index; + if (!PrepareBlockFilterRequest(pfrom, chain_params, filter_type, start_height, stop_hash, + MAX_GETCFILTERS_SIZE, stop_index, filter_index)) { + return; + } + + std::vector<BlockFilter> filters; + + if (!filter_index->LookupFilterRange(start_height, stop_index, filters)) { + LogPrint(BCLog::NET, "Failed to find block filter in index: filter_type=%s, start_height=%d, stop_hash=%s\n", + BlockFilterTypeName(filter_type), start_height, stop_hash.ToString()); + return; + } + + for (const auto& filter : filters) { + CSerializedNetMsg msg = CNetMsgMaker(pfrom.GetSendVersion()) + .Make(NetMsgType::CFILTER, filter); + connman.PushMessage(&pfrom, std::move(msg)); + } +} + +/** * Handle a cfheaders request. * * May disconnect from the peer in the case of a bad request. @@ -2061,8 +2107,8 @@ static bool PrepareBlockFilterRequest(CNode* pfrom, const CChainParams& chain_pa * @param[in] chain_params Chain parameters * @param[in] connman Pointer to the connection manager */ -static void ProcessGetCFHeaders(CNode* pfrom, CDataStream& vRecv, const CChainParams& chain_params, - CConnman* connman) +static void ProcessGetCFHeaders(CNode& pfrom, CDataStream& vRecv, const CChainParams& chain_params, + CConnman& connman) { uint8_t filter_type_ser; uint32_t start_height; @@ -2097,13 +2143,13 @@ static void ProcessGetCFHeaders(CNode* pfrom, CDataStream& vRecv, const CChainPa return; } - CSerializedNetMsg msg = CNetMsgMaker(pfrom->GetSendVersion()) + CSerializedNetMsg msg = CNetMsgMaker(pfrom.GetSendVersion()) .Make(NetMsgType::CFHEADERS, filter_type_ser, stop_index->GetBlockHash(), prev_header, filter_hashes); - connman->PushMessage(pfrom, std::move(msg)); + connman.PushMessage(&pfrom, std::move(msg)); } /** @@ -2116,8 +2162,8 @@ static void ProcessGetCFHeaders(CNode* pfrom, CDataStream& vRecv, const CChainPa * @param[in] chain_params Chain parameters * @param[in] connman Pointer to the connection manager */ -static void ProcessGetCFCheckPt(CNode* pfrom, CDataStream& vRecv, const CChainParams& chain_params, - CConnman* connman) +static void ProcessGetCFCheckPt(CNode& pfrom, CDataStream& vRecv, const CChainParams& chain_params, + CConnman& connman) { uint8_t filter_type_ser; uint256 stop_hash; @@ -2149,12 +2195,12 @@ static void ProcessGetCFCheckPt(CNode* pfrom, CDataStream& vRecv, const CChainPa } } - CSerializedNetMsg msg = CNetMsgMaker(pfrom->GetSendVersion()) + CSerializedNetMsg msg = CNetMsgMaker(pfrom.GetSendVersion()) .Make(NetMsgType::CFCHECKPT, filter_type_ser, stop_index->GetBlockHash(), headers); - connman->PushMessage(pfrom, std::move(msg)); + connman.PushMessage(&pfrom, std::move(msg)); } bool ProcessMessage(CNode* pfrom, const std::string& msg_type, CDataStream& vRecv, int64_t nTimeReceived, const CChainParams& chainparams, ChainstateManager& chainman, CTxMemPool& mempool, CConnman* connman, BanMan* banman, const std::atomic<bool>& interruptMsgProc) @@ -3466,13 +3512,18 @@ bool ProcessMessage(CNode* pfrom, const std::string& msg_type, CDataStream& vRec return true; } + if (msg_type == NetMsgType::GETCFILTERS) { + ProcessGetCFilters(*pfrom, vRecv, chainparams, *connman); + return true; + } + if (msg_type == NetMsgType::GETCFHEADERS) { - ProcessGetCFHeaders(pfrom, vRecv, chainparams, connman); + ProcessGetCFHeaders(*pfrom, vRecv, chainparams, *connman); return true; } if (msg_type == NetMsgType::GETCFCHECKPT) { - ProcessGetCFCheckPt(pfrom, vRecv, chainparams, connman); + ProcessGetCFCheckPt(*pfrom, vRecv, chainparams, *connman); return true; } |