Skip to content

Commit f6b58c1

Browse files
jimpojnewbery
authored andcommitted
[net processing] Message handling for getcfheaders.
if -peerblockfilters is configured, handle requests for cfheaders.
1 parent 3bdc7c2 commit f6b58c1

File tree

3 files changed

+100
-5
lines changed

3 files changed

+100
-5
lines changed

src/net_processing.cpp

Lines changed: 83 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,8 @@ static constexpr unsigned int INVENTORY_BROADCAST_MAX = 7 * INVENTORY_BROADCAST_
129129
static constexpr unsigned int AVG_FEEFILTER_BROADCAST_INTERVAL = 10 * 60;
130130
/** Maximum feefilter broadcast delay after significant change. */
131131
static constexpr unsigned int MAX_FEEFILTER_CHANGE_DELAY = 5 * 60;
132+
/** Maximum number of cf hashes that may be requested with one getcfheaders. See BIP 157. */
133+
static constexpr uint32_t MAX_GETCFHEADERS_SIZE = 2000;
132134

133135
struct COrphanTx {
134136
// When modifying, adapt the copy of this definition in tests/DoS_tests.
@@ -1983,14 +1985,16 @@ void static ProcessOrphanTx(CConnman* connman, CTxMemPool& mempool, std::set<uin
19831985
* @param[in] pfrom The peer that we received the request from
19841986
* @param[in] chain_params Chain parameters
19851987
* @param[in] filter_type The filter type the request is for. Must be basic filters.
1988+
* @param[in] start_height The start height for the request
19861989
* @param[in] stop_hash The stop_hash for the request
1990+
* @param[in] max_height_diff The maximum number of items permitted to request, as specified in BIP 157
19871991
* @param[out] stop_index The CBlockIndex for the stop_hash block, if the request can be serviced.
19881992
* @param[out] filter_index The filter index, if the request can be serviced.
19891993
* @return True if the request can be serviced.
19901994
*/
19911995
static bool PrepareBlockFilterRequest(CNode* pfrom, const CChainParams& chain_params,
1992-
BlockFilterType filter_type,
1993-
const uint256& stop_hash,
1996+
BlockFilterType filter_type, uint32_t start_height,
1997+
const uint256& stop_hash, uint32_t max_height_diff,
19941998
const CBlockIndex*& stop_index,
19951999
BlockFilterIndex*& filter_index)
19962000
{
@@ -2017,6 +2021,21 @@ static bool PrepareBlockFilterRequest(CNode* pfrom, const CChainParams& chain_pa
20172021
}
20182022
}
20192023

2024+
uint32_t stop_height = stop_index->nHeight;
2025+
if (start_height > stop_height) {
2026+
LogPrint(BCLog::NET, "peer %d sent invalid getcfilters/getcfheaders with " /* Continued */
2027+
"start height %d and stop height %d\n",
2028+
pfrom->GetId(), start_height, stop_height);
2029+
pfrom->fDisconnect = true;
2030+
return false;
2031+
}
2032+
if (stop_height - start_height >= max_height_diff) {
2033+
LogPrint(BCLog::NET, "peer %d requested too many cfilters/cfheaders: %d / %d\n",
2034+
pfrom->GetId(), stop_height - start_height + 1, max_height_diff);
2035+
pfrom->fDisconnect = true;
2036+
return false;
2037+
}
2038+
20202039
filter_index = GetBlockFilterIndex(filter_type);
20212040
if (!filter_index) {
20222041
LogPrint(BCLog::NET, "Filter index for supported type %s not found\n", BlockFilterTypeName(filter_type));
@@ -2026,6 +2045,61 @@ static bool PrepareBlockFilterRequest(CNode* pfrom, const CChainParams& chain_pa
20262045
return true;
20272046
}
20282047

2048+
/**
2049+
* Handle a cfheaders request.
2050+
*
2051+
* May disconnect from the peer in the case of a bad request.
2052+
*
2053+
* @param[in] pfrom The peer that we received the request from
2054+
* @param[in] vRecv The raw message received
2055+
* @param[in] chain_params Chain parameters
2056+
* @param[in] connman Pointer to the connection manager
2057+
*/
2058+
static void ProcessGetCFHeaders(CNode* pfrom, CDataStream& vRecv, const CChainParams& chain_params,
2059+
CConnman* connman)
2060+
{
2061+
uint8_t filter_type_ser;
2062+
uint32_t start_height;
2063+
uint256 stop_hash;
2064+
2065+
vRecv >> filter_type_ser >> start_height >> stop_hash;
2066+
2067+
const BlockFilterType filter_type = static_cast<BlockFilterType>(filter_type_ser);
2068+
2069+
const CBlockIndex* stop_index;
2070+
BlockFilterIndex* filter_index;
2071+
if (!PrepareBlockFilterRequest(pfrom, chain_params, filter_type, start_height, stop_hash,
2072+
MAX_GETCFHEADERS_SIZE, stop_index, filter_index)) {
2073+
return;
2074+
}
2075+
2076+
uint256 prev_header;
2077+
if (start_height > 0) {
2078+
const CBlockIndex* const prev_block =
2079+
stop_index->GetAncestor(static_cast<int>(start_height - 1));
2080+
if (!filter_index->LookupFilterHeader(prev_block, prev_header)) {
2081+
LogPrint(BCLog::NET, "Failed to find block filter header in index: filter_type=%s, block_hash=%s\n",
2082+
BlockFilterTypeName(filter_type), prev_block->GetBlockHash().ToString());
2083+
return;
2084+
}
2085+
}
2086+
2087+
std::vector<uint256> filter_hashes;
2088+
if (!filter_index->LookupFilterHashRange(start_height, stop_index, filter_hashes)) {
2089+
LogPrint(BCLog::NET, "Failed to find block filter hashes in index: filter_type=%s, start_height=%d, stop_hash=%s\n",
2090+
BlockFilterTypeName(filter_type), start_height, stop_hash.ToString());
2091+
return;
2092+
}
2093+
2094+
CSerializedNetMsg msg = CNetMsgMaker(pfrom->GetSendVersion())
2095+
.Make(NetMsgType::CFHEADERS,
2096+
filter_type_ser,
2097+
stop_index->GetBlockHash(),
2098+
prev_header,
2099+
filter_hashes);
2100+
connman->PushMessage(pfrom, std::move(msg));
2101+
}
2102+
20292103
/**
20302104
* Handle a getcfcheckpt request.
20312105
*
@@ -2048,7 +2122,8 @@ static void ProcessGetCFCheckPt(CNode* pfrom, CDataStream& vRecv, const CChainPa
20482122

20492123
const CBlockIndex* stop_index;
20502124
BlockFilterIndex* filter_index;
2051-
if (!PrepareBlockFilterRequest(pfrom, chain_params, filter_type, stop_hash,
2125+
if (!PrepareBlockFilterRequest(pfrom, chain_params, filter_type, /*start_height=*/0, stop_hash,
2126+
/*max_height_diff=*/std::numeric_limits<uint32_t>::max(),
20522127
stop_index, filter_index)) {
20532128
return;
20542129
}
@@ -3385,6 +3460,11 @@ bool ProcessMessage(CNode* pfrom, const std::string& msg_type, CDataStream& vRec
33853460
return true;
33863461
}
33873462

3463+
if (msg_type == NetMsgType::GETCFHEADERS) {
3464+
ProcessGetCFHeaders(pfrom, vRecv, chainparams, connman);
3465+
return true;
3466+
}
3467+
33883468
if (msg_type == NetMsgType::GETCFCHECKPT) {
33893469
ProcessGetCFCheckPt(pfrom, vRecv, chainparams, connman);
33903470
return true;

src/protocol.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@ const char *SENDCMPCT="sendcmpct";
4040
const char *CMPCTBLOCK="cmpctblock";
4141
const char *GETBLOCKTXN="getblocktxn";
4242
const char *BLOCKTXN="blocktxn";
43+
const char *GETCFHEADERS="getcfheaders";
44+
const char *CFHEADERS="cfheaders";
4345
const char *GETCFCHECKPT="getcfcheckpt";
4446
const char *CFCHECKPT="cfcheckpt";
4547
} // namespace NetMsgType
@@ -73,6 +75,8 @@ const static std::string allNetMessageTypes[] = {
7375
NetMsgType::CMPCTBLOCK,
7476
NetMsgType::GETBLOCKTXN,
7577
NetMsgType::BLOCKTXN,
78+
NetMsgType::GETCFHEADERS,
79+
NetMsgType::CFHEADERS,
7680
NetMsgType::GETCFCHECKPT,
7781
NetMsgType::CFCHECKPT,
7882
};

src/protocol.h

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,19 @@ extern const char* GETBLOCKTXN;
225225
* @since protocol version 70014 as described by BIP 152
226226
*/
227227
extern const char* BLOCKTXN;
228+
/**
229+
* getcfheaders requests a compact filter header and the filter hashes for a
230+
* range of blocks, which can then be used to reconstruct the filter headers
231+
* for those blocks.
232+
* Only available with service bit NODE_COMPACT_FILTERS as described by
233+
* BIP 157 & 158.
234+
*/
235+
extern const char* GETCFHEADERS;
236+
/**
237+
* cfheaders is a response to a getcfheaders request containing a filter header
238+
* and a vector of filter hashes for each subsequent block in the requested range.
239+
*/
240+
extern const char* CFHEADERS;
228241
/**
229242
* getcfcheckpt requests evenly spaced compact filter headers, enabling
230243
* parallelized download and validation of the headers between them.
@@ -235,8 +248,6 @@ extern const char* GETCFCHECKPT;
235248
/**
236249
* cfcheckpt is a response to a getcfcheckpt request containing a vector of
237250
* evenly spaced filter headers for blocks on the requested chain.
238-
* Only available with service bit NODE_COMPACT_FILTERS as described by
239-
* BIP 157 & 158.
240251
*/
241252
extern const char* CFCHECKPT;
242253
}; // namespace NetMsgType

0 commit comments

Comments
 (0)