|
8 | 8 | #include <addrman.h> |
9 | 9 | #include <banman.h> |
10 | 10 | #include <blockencodings.h> |
| 11 | +#include <blockfilter.h> |
11 | 12 | #include <chainparams.h> |
12 | 13 | #include <consensus/validation.h> |
13 | 14 | #include <hash.h> |
| 15 | +#include <index/blockfilterindex.h> |
14 | 16 | #include <validation.h> |
15 | 17 | #include <merkleblock.h> |
16 | 18 | #include <netmessagemaker.h> |
@@ -127,6 +129,8 @@ static constexpr unsigned int INVENTORY_BROADCAST_MAX = 7 * INVENTORY_BROADCAST_ |
127 | 129 | static constexpr unsigned int AVG_FEEFILTER_BROADCAST_INTERVAL = 10 * 60; |
128 | 130 | /** Maximum feefilter broadcast delay after significant change. */ |
129 | 131 | static constexpr unsigned int MAX_FEEFILTER_CHANGE_DELAY = 5 * 60; |
| 132 | +/** Interval between compact filter checkpoints. See BIP 157. */ |
| 133 | +static constexpr int CFCHECKPT_INTERVAL = 1000; |
130 | 134 |
|
131 | 135 | struct COrphanTx { |
132 | 136 | // When modifying, adapt the copy of this definition in tests/DoS_tests. |
@@ -1969,6 +1973,107 @@ void static ProcessOrphanTx(CConnman* connman, CTxMemPool& mempool, std::set<uin |
1969 | 1973 | } |
1970 | 1974 | } |
1971 | 1975 |
|
| 1976 | +/** |
| 1977 | + * Validation logic for compact filters request handling. |
| 1978 | + * |
| 1979 | + * May disconnect from the peer in the case of a bad request. |
| 1980 | + * |
| 1981 | + * @param[in] pfrom The peer that we received the request from |
| 1982 | + * @param[in] chain_params Chain parameters |
| 1983 | + * @param[in] filter_type The filter type the request is for. Must be basic filters. |
| 1984 | + * @param[in] stop_hash The stop_hash for the request |
| 1985 | + * @param[out] stop_index The CBlockIndex for the stop_hash block, if the request can be serviced. |
| 1986 | + * @param[out] filter_index The filter index, if the request can be serviced. |
| 1987 | + * @return True if the request can be serviced. |
| 1988 | + */ |
| 1989 | +static bool PrepareBlockFilterRequest(CNode* pfrom, const CChainParams& chain_params, |
| 1990 | + BlockFilterType filter_type, |
| 1991 | + const uint256& stop_hash, |
| 1992 | + const CBlockIndex*& stop_index, |
| 1993 | + const BlockFilterIndex*& filter_index) |
| 1994 | +{ |
| 1995 | + const bool supported_filter_type = |
| 1996 | + (filter_type == BlockFilterType::BASIC && |
| 1997 | + gArgs.GetBoolArg("-peerblockfilters", DEFAULT_PEERBLOCKFILTERS)); |
| 1998 | + if (!supported_filter_type) { |
| 1999 | + LogPrint(BCLog::NET, "peer %d requested unsupported block filter type: %d\n", |
| 2000 | + pfrom->GetId(), static_cast<uint8_t>(filter_type)); |
| 2001 | + pfrom->fDisconnect = true; |
| 2002 | + return false; |
| 2003 | + } |
| 2004 | + |
| 2005 | + { |
| 2006 | + LOCK(cs_main); |
| 2007 | + stop_index = LookupBlockIndex(stop_hash); |
| 2008 | + |
| 2009 | + // Check that the stop block exists and the peer would be allowed to fetch it. |
| 2010 | + if (!stop_index || !BlockRequestAllowed(stop_index, chain_params.GetConsensus())) { |
| 2011 | + LogPrint(BCLog::NET, "peer %d requested invalid block hash: %s\n", |
| 2012 | + pfrom->GetId(), stop_hash.ToString()); |
| 2013 | + pfrom->fDisconnect = true; |
| 2014 | + return false; |
| 2015 | + } |
| 2016 | + } |
| 2017 | + |
| 2018 | + filter_index = GetBlockFilterIndex(filter_type); |
| 2019 | + if (!filter_index) { |
| 2020 | + LogPrint(BCLog::NET, "Filter index for supported type %s not found\n", BlockFilterTypeName(filter_type)); |
| 2021 | + return false; |
| 2022 | + } |
| 2023 | + |
| 2024 | + return true; |
| 2025 | +} |
| 2026 | + |
| 2027 | +/** |
| 2028 | + * Handle a getcfcheckpt request. |
| 2029 | + * |
| 2030 | + * May disconnect from the peer in the case of a bad request. |
| 2031 | + * |
| 2032 | + * @param[in] pfrom The peer that we received the request from |
| 2033 | + * @param[in] vRecv The raw message received |
| 2034 | + * @param[in] chain_params Chain parameters |
| 2035 | + * @param[in] connman Pointer to the connection manager |
| 2036 | + */ |
| 2037 | +static void ProcessGetCFCheckPt(CNode* pfrom, CDataStream& vRecv, const CChainParams& chain_params, |
| 2038 | + CConnman* connman) |
| 2039 | +{ |
| 2040 | + uint8_t filter_type_ser; |
| 2041 | + uint256 stop_hash; |
| 2042 | + |
| 2043 | + vRecv >> filter_type_ser >> stop_hash; |
| 2044 | + |
| 2045 | + const BlockFilterType filter_type = static_cast<BlockFilterType>(filter_type_ser); |
| 2046 | + |
| 2047 | + const CBlockIndex* stop_index; |
| 2048 | + const BlockFilterIndex* filter_index; |
| 2049 | + if (!PrepareBlockFilterRequest(pfrom, chain_params, filter_type, stop_hash, |
| 2050 | + stop_index, filter_index)) { |
| 2051 | + return; |
| 2052 | + } |
| 2053 | + |
| 2054 | + std::vector<uint256> headers(stop_index->nHeight / CFCHECKPT_INTERVAL); |
| 2055 | + |
| 2056 | + // Populate headers. |
| 2057 | + const CBlockIndex* block_index = stop_index; |
| 2058 | + for (int i = headers.size() - 1; i >= 0; i--) { |
| 2059 | + int height = (i + 1) * CFCHECKPT_INTERVAL; |
| 2060 | + block_index = block_index->GetAncestor(height); |
| 2061 | + |
| 2062 | + if (!filter_index->LookupFilterHeader(block_index, headers[i])) { |
| 2063 | + LogPrint(BCLog::NET, "Failed to find block filter header in index: filter_type=%s, block_hash=%s\n", |
| 2064 | + BlockFilterTypeName(filter_type), block_index->GetBlockHash().ToString()); |
| 2065 | + return; |
| 2066 | + } |
| 2067 | + } |
| 2068 | + |
| 2069 | + CSerializedNetMsg msg = CNetMsgMaker(pfrom->GetSendVersion()) |
| 2070 | + .Make(NetMsgType::CFCHECKPT, |
| 2071 | + filter_type_ser, |
| 2072 | + stop_index->GetBlockHash(), |
| 2073 | + headers); |
| 2074 | + connman->PushMessage(pfrom, std::move(msg)); |
| 2075 | +} |
| 2076 | + |
1972 | 2077 | bool ProcessMessage(CNode* pfrom, const std::string& msg_type, CDataStream& vRecv, int64_t nTimeReceived, const CChainParams& chainparams, CTxMemPool& mempool, CConnman* connman, BanMan* banman, const std::atomic<bool>& interruptMsgProc) |
1973 | 2078 | { |
1974 | 2079 | LogPrint(BCLog::NET, "received: %s (%u bytes) peer=%d\n", SanitizeString(msg_type), vRecv.size(), pfrom->GetId()); |
@@ -3274,6 +3379,11 @@ bool ProcessMessage(CNode* pfrom, const std::string& msg_type, CDataStream& vRec |
3274 | 3379 | return true; |
3275 | 3380 | } |
3276 | 3381 |
|
| 3382 | + if (msg_type == NetMsgType::GETCFCHECKPT) { |
| 3383 | + ProcessGetCFCheckPt(pfrom, vRecv, chainparams, connman); |
| 3384 | + return true; |
| 3385 | + } |
| 3386 | + |
3277 | 3387 | if (msg_type == NetMsgType::NOTFOUND) { |
3278 | 3388 | // Remove the NOTFOUND transactions from the peer |
3279 | 3389 | LOCK(cs_main); |
|
0 commit comments