|
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.
|
@@ -1965,6 +1969,107 @@ void static ProcessOrphanTx(CConnman* connman, CTxMemPool& mempool, std::set<uin
|
1965 | 1969 | }
|
1966 | 1970 | }
|
1967 | 1971 |
|
| 1972 | +/** |
| 1973 | + * Validation logic for compact filters request handling. |
| 1974 | + * |
| 1975 | + * May disconnect from the peer in the case of a bad request. |
| 1976 | + * |
| 1977 | + * @param[in] pfrom The peer that we received the request from |
| 1978 | + * @param[in] chain_params Chain parameters |
| 1979 | + * @param[in] filter_type The filter type the request is for. Must be basic filters. |
| 1980 | + * @param[in] stop_hash The stop_hash for the request |
| 1981 | + * @param[out] stop_index The CBlockIndex for the stop_hash block, if the request can be serviced. |
| 1982 | + * @param[out] filter_index The filter index, if the request can be serviced. |
| 1983 | + * @return True if the request can be serviced. |
| 1984 | + */ |
| 1985 | +static bool PrepareBlockFilterRequest(CNode* pfrom, const CChainParams& chain_params, |
| 1986 | + BlockFilterType filter_type, |
| 1987 | + const uint256& stop_hash, |
| 1988 | + const CBlockIndex*& stop_index, |
| 1989 | + const BlockFilterIndex*& filter_index) |
| 1990 | +{ |
| 1991 | + const bool supported_filter_type = |
| 1992 | + (filter_type == BlockFilterType::BASIC && |
| 1993 | + gArgs.GetBoolArg("-peerblockfilters", DEFAULT_PEERBLOCKFILTERS)); |
| 1994 | + if (!supported_filter_type) { |
| 1995 | + LogPrint(BCLog::NET, "peer %d requested unsupported block filter type: %d\n", |
| 1996 | + pfrom->GetId(), static_cast<uint8_t>(filter_type)); |
| 1997 | + pfrom->fDisconnect = true; |
| 1998 | + return false; |
| 1999 | + } |
| 2000 | + |
| 2001 | + { |
| 2002 | + LOCK(cs_main); |
| 2003 | + stop_index = LookupBlockIndex(stop_hash); |
| 2004 | + |
| 2005 | + // Check that the stop block exists and the peer would be allowed to fetch it. |
| 2006 | + if (!stop_index || !BlockRequestAllowed(stop_index, chain_params.GetConsensus())) { |
| 2007 | + LogPrint(BCLog::NET, "peer %d requested invalid block hash: %s\n", |
| 2008 | + pfrom->GetId(), stop_hash.ToString()); |
| 2009 | + pfrom->fDisconnect = true; |
| 2010 | + return false; |
| 2011 | + } |
| 2012 | + } |
| 2013 | + |
| 2014 | + filter_index = GetBlockFilterIndex(filter_type); |
| 2015 | + if (!filter_index) { |
| 2016 | + LogPrint(BCLog::NET, "Filter index for supported type %s not found\n", BlockFilterTypeName(filter_type)); |
| 2017 | + return false; |
| 2018 | + } |
| 2019 | + |
| 2020 | + return true; |
| 2021 | +} |
| 2022 | + |
| 2023 | +/** |
| 2024 | + * Handle a getcfcheckpt request. |
| 2025 | + * |
| 2026 | + * May disconnect from the peer in the case of a bad request. |
| 2027 | + * |
| 2028 | + * @param[in] pfrom The peer that we received the request from |
| 2029 | + * @param[in] vRecv The raw message received |
| 2030 | + * @param[in] chain_params Chain parameters |
| 2031 | + * @param[in] connman Pointer to the connection manager |
| 2032 | + */ |
| 2033 | +static void ProcessGetCFCheckPt(CNode* pfrom, CDataStream& vRecv, const CChainParams& chain_params, |
| 2034 | + CConnman* connman) |
| 2035 | +{ |
| 2036 | + uint8_t filter_type_ser; |
| 2037 | + uint256 stop_hash; |
| 2038 | + |
| 2039 | + vRecv >> filter_type_ser >> stop_hash; |
| 2040 | + |
| 2041 | + const BlockFilterType filter_type = static_cast<BlockFilterType>(filter_type_ser); |
| 2042 | + |
| 2043 | + const CBlockIndex* stop_index; |
| 2044 | + const BlockFilterIndex* filter_index; |
| 2045 | + if (!PrepareBlockFilterRequest(pfrom, chain_params, filter_type, stop_hash, |
| 2046 | + stop_index, filter_index)) { |
| 2047 | + return; |
| 2048 | + } |
| 2049 | + |
| 2050 | + std::vector<uint256> headers(stop_index->nHeight / CFCHECKPT_INTERVAL); |
| 2051 | + |
| 2052 | + // Populate headers. |
| 2053 | + const CBlockIndex* block_index = stop_index; |
| 2054 | + for (int i = headers.size() - 1; i >= 0; i--) { |
| 2055 | + int height = (i + 1) * CFCHECKPT_INTERVAL; |
| 2056 | + block_index = block_index->GetAncestor(height); |
| 2057 | + |
| 2058 | + if (!filter_index->LookupFilterHeader(block_index, headers[i])) { |
| 2059 | + LogPrint(BCLog::NET, "Failed to find block filter header in index: filter_type=%s, block_hash=%s\n", |
| 2060 | + BlockFilterTypeName(filter_type), block_index->GetBlockHash().ToString()); |
| 2061 | + return; |
| 2062 | + } |
| 2063 | + } |
| 2064 | + |
| 2065 | + CSerializedNetMsg msg = CNetMsgMaker(pfrom->GetSendVersion()) |
| 2066 | + .Make(NetMsgType::CFCHECKPT, |
| 2067 | + filter_type_ser, |
| 2068 | + stop_index->GetBlockHash(), |
| 2069 | + headers); |
| 2070 | + connman->PushMessage(pfrom, std::move(msg)); |
| 2071 | +} |
| 2072 | + |
1968 | 2073 | 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)
|
1969 | 2074 | {
|
1970 | 2075 | LogPrint(BCLog::NET, "received: %s (%u bytes) peer=%d\n", SanitizeString(msg_type), vRecv.size(), pfrom->GetId());
|
@@ -3270,6 +3375,11 @@ bool ProcessMessage(CNode* pfrom, const std::string& msg_type, CDataStream& vRec
|
3270 | 3375 | return true;
|
3271 | 3376 | }
|
3272 | 3377 |
|
| 3378 | + if (msg_type == NetMsgType::GETCFCHECKPT) { |
| 3379 | + ProcessGetCFCheckPt(pfrom, vRecv, chainparams, connman); |
| 3380 | + return true; |
| 3381 | + } |
| 3382 | + |
3273 | 3383 | if (msg_type == NetMsgType::NOTFOUND) {
|
3274 | 3384 | // Remove the NOTFOUND transactions from the peer
|
3275 | 3385 | LOCK(cs_main);
|
|
0 commit comments