@@ -129,6 +129,8 @@ static constexpr unsigned int INVENTORY_BROADCAST_MAX = 7 * INVENTORY_BROADCAST_
129
129
static constexpr unsigned int AVG_FEEFILTER_BROADCAST_INTERVAL = 10 * 60 ;
130
130
/* * Maximum feefilter broadcast delay after significant change. */
131
131
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 ;
132
134
133
135
struct COrphanTx {
134
136
// 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
1983
1985
* @param[in] pfrom The peer that we received the request from
1984
1986
* @param[in] chain_params Chain parameters
1985
1987
* @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
1986
1989
* @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
1987
1991
* @param[out] stop_index The CBlockIndex for the stop_hash block, if the request can be serviced.
1988
1992
* @param[out] filter_index The filter index, if the request can be serviced.
1989
1993
* @return True if the request can be serviced.
1990
1994
*/
1991
1995
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,
1994
1998
const CBlockIndex*& stop_index,
1995
1999
BlockFilterIndex*& filter_index)
1996
2000
{
@@ -2017,6 +2021,21 @@ static bool PrepareBlockFilterRequest(CNode* pfrom, const CChainParams& chain_pa
2017
2021
}
2018
2022
}
2019
2023
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
+
2020
2039
filter_index = GetBlockFilterIndex (filter_type);
2021
2040
if (!filter_index) {
2022
2041
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
2026
2045
return true ;
2027
2046
}
2028
2047
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
+
2029
2103
/* *
2030
2104
* Handle a getcfcheckpt request.
2031
2105
*
@@ -2048,7 +2122,8 @@ static void ProcessGetCFCheckPt(CNode* pfrom, CDataStream& vRecv, const CChainPa
2048
2122
2049
2123
const CBlockIndex* stop_index;
2050
2124
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 (),
2052
2127
stop_index, filter_index)) {
2053
2128
return ;
2054
2129
}
@@ -3385,6 +3460,11 @@ bool ProcessMessage(CNode* pfrom, const std::string& msg_type, CDataStream& vRec
3385
3460
return true ;
3386
3461
}
3387
3462
3463
+ if (msg_type == NetMsgType::GETCFHEADERS) {
3464
+ ProcessGetCFHeaders (pfrom, vRecv, chainparams, connman);
3465
+ return true ;
3466
+ }
3467
+
3388
3468
if (msg_type == NetMsgType::GETCFCHECKPT) {
3389
3469
ProcessGetCFCheckPt (pfrom, vRecv, chainparams, connman);
3390
3470
return true ;
0 commit comments