Support getcfheaders
requests when -peerblockfilters
is set.
Does not advertise compact filter support in version messages.
Support getcfheaders
requests when -peerblockfilters
is set.
Does not advertise compact filter support in version messages.
The following sections might be updated with supplementary metadata relevant to reviewers and maintainers.
Reviewers, this pull request conflicts with the following ones:
If you consider this pull request important, please also help to review the conflicting pull requests. Ideally, start with the one that should be merged first.
2050+ * @param[in] vRecv The raw message received
2051+ * @param[in] chain_params Chain parameters
2052+ * @param[in] connman Pointer to the connection manager
2053+ */
2054+static void ProcessGetCFHeaders(CNode* pfrom, CDataStream& vRecv, const CChainParams& chain_params,
2055+ CConnman* connman)
0 CConnman& connman)
Any reason why this is a pointer, but missing the nullptr check?
Mixing the two combines the worst of each option.
(Same for pfrom)
Process*()
functions in net_processing. Rather than introduce a new style for just this function, I think it makes sense to change it everywhere in net_processing in a refactor PR.
RelayTransaction
, which properly passes connman. Obviously a non-blocking nit, so feel free to close this conversation.
2029+ LogPrint(BCLog::NET, "peer %d requested too many cfilters/cfheaders: %d / %d\n",
2030+ pfrom->GetId(), stop_height - start_height + 1, max_height_diff);
2031+ pfrom->fDisconnect = true;
2032+ return false;
2033+ }
2034+
Given these checks aren’t necessary for ProcessGetCFCheckPt, would they be more suitable in separate function? Then the caller wouldn’t have to know which values to pass to make the checks succeed.
Downside is you might fetch the BlockFilterIndex
even though these checks may later fail.
I think this makes more sense if you also look at the full changes in #18876, where this function is common logic for getcfheaders and getcfilters, and the max number of headers that can be requested is 2000, and the max number of filters that can be requested in 1000.
I agree that the getcfcheckpt logic passing in 0
and std::numeric_limits<uint32_t>::max()
is a bit ugly. I could change it to pass in optionals, but that seems more aesthetic than anything.
113+ node0.send_and_ping(request)
114+ response = node0.last_message['cfheaders']
115+ assert_equal(
116+ compute_last_header(response.prev_header, response.hashes),
117+ int(main_cfcheckpt, 16)
118+ )
compute_last_header
?
Concept ACK
For testing, what’s the general approach been for testing bad requests? BIP 157 says to not respond, but we are disconnecting the peer in these cases.
Force pushed the branch to:
m_headers_cache
that didn’t make it into #18960 (https://github.com/bitcoin/bitcoin/pull/18960#discussion_r428395728)1984@@ -1983,14 +1985,16 @@ void static ProcessOrphanTx(CConnman* connman, CTxMemPool& mempool, std::set<uin
1985 * @param[in] pfrom The peer that we received the request from
1986 * @param[in] chain_params Chain parameters
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
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
nit: This threw me off initially (similar to what @jkczyz noted below). The BIP gives a specific number, why do we not just use the constant? I think this could help make it a little less confusing.
0 * [@param](/bitcoin-bitcoin/contributor/param/)[in] max_height_diff The maximum number of headers or filters permitted to request, as specified in BIP 157
ACK 4376797f6c9962ec92b5ce6e61dc622b56d2a6f7
Reviewed the code, played with the tests, and ran them locally.
FWIW, I have added the tests I suggested in the review club, feel free to copy them from there: https://github.com/fjahr/bitcoin/commit/36d6854d2b4ed0afa556ccbe0ec72c4cb141a4c9
what’s the general approach been for testing bad requests? BIP 157 says to not respond, but we are disconnecting the peer in these cases.
I don’t have a strong opinion about whether to disconnect or drop bad requests. Generally I prefer simply dropping bad requests to prevent bugs becoming network partition possibilities, but in this case:
I’m inclined to keep it as a disconnect since that’s the only way we have to communicate to the client that there’s a problem with the request, but I’m happy to change it if others disagree.
the peers sending us these requests are light clients, so the downside of disconnecting them is small.
I agree here. Generally the nicest thing you can do to misbehaving light clients is to disconnect them as early as possible. This way the misbehaviour bug will be hopefully caught early in the design and testing process of the light client. If not, at least in production it will be another indicator that something is wrong and users can file bugs. If the connection was kept alive, and without replying it might just time out on the light client and they’d think we are the ones misbehaving.
I was about to suggest to put a small comment in the source code to document this, but I wasn’t exactly sure where to put it.
2121@@ -2048,7 +2122,9 @@ static void ProcessGetCFCheckPt(CNode* pfrom, CDataStream& vRecv, const CChainPa
2122
2123 const CBlockIndex* stop_index;
2124 BlockFilterIndex* filter_index;
2125- if (!PrepareBlockFilterRequest(pfrom, chain_params, filter_type, stop_hash,
2126+ if (!PrepareBlockFilterRequest(pfrom, chain_params, filter_type, /*start_height=*/0, stop_hash,
2127+ /*max_height_diff=*/std::numeric_limits<uint32_t>::max(),
2128+
in commit db20d456f0 [net processing] Message handling for getcfheaders.
Why add an empty newline in the params?
224@@ -225,6 +225,17 @@ extern const char* GETBLOCKTXN;
225 * @since protocol version 70014 as described by BIP 152
226 */
227 extern const char* BLOCKTXN;
228+/**
229+ * getcfheaders requests compact filter headers for a range of blocks.
230+ * Only available with service bit NODE_COMPACT_FILTERS as described by
231+ * BIP 157 & 158.
232+ */
233+extern const char *GETCFHEADERS;
style-nit in commit db20d456f0 (according to clang-format):
0extern const char* GETCFHEADERS;
Some style nits that can be ignored
re-ACK 4376797f6c, only change since my previous review #18876 (comment) is adding a spurious new line and a new commit with documentation 🐣
Signature:
0-----BEGIN PGP SIGNED MESSAGE-----
1Hash: SHA512
2
3re-ACK 4376797f6c, only change since my previous review [#18876 (comment)](/bitcoin-bitcoin/18876/#issuecomment-627322015) is adding a spurious new line and a new commit with documentation 🐣
4-----BEGIN PGP SIGNATURE-----
5
6iQGzBAEBCgAdFiEE+rVPoUahrI9sLGYTzit1aX5ppUgFAlwqrYAACgkQzit1aX5p
7pUjc3gv+MB5VIjvGWjT85TlCzHERqu35XeRFo+DTLBUhkp1NGk1Uymar3cF68jOW
80W0Keide4ZEBCc1sz7mnhsXBBL6XhijSgGS7fTdjw9Iab8944dW11IzDmMFcHWwc
9cglhfriS8Rpa3FUeq+FPrNI7zEA4UyHrXcIiUUzXkXBRK0yooTrpFzGMlS6HnB8+
10MmzIuUaFTEKnIJA3exIAls8225TzmnIuPrSHtpNi+91RVpTnV1ZMAo++jBbcPE/p
11riNswV/Yc/zG06xiO2YgleTyfip8FwjydEMaekkQUSL62IucTFQY0rHqeEWvysFr
12L69g2vdnVDUgVLxiOrzLIUdhLjYxsjvyOUdXgC36UxpUERi2TuXzmMu0OWFSkChs
13soAvIWL0hFt4oV/PTgBpxJPKrFtWgifwVy3l8iyZ07eVsGr0Z+YfNDwY6DWCJsM/
14d+RG0asZEtOjdkwZF/PAc9tTWPsP/fLXiHO3z7928dASyT5+pKdaKOCSCeKH1+6p
15lg1V3U+3
16=0qw1
17-----END PGP SIGNATURE-----
Timestamp of file with hash 40b1dadd7d8694410c23fb4d6f045b454bee5f2bf365f49994dc7f713b58f816 -
38@@ -39,6 +39,7 @@ class BlockFilterIndex final : public BaseIndex
39 size_t WriteFilterToDisk(FlatFilePos& pos, const BlockFilter& filter);
40
41 Mutex m_cs_headers_cache;
42+ //* cache of block hash to filter header, to avoid disk access when responding to getcfcheckpt. */
To match the other comments in the class, this one should also use the Doxygen starting delimiter (= C-Style comment with two ‘*’s, see http://www.doxygen.nl/manual/docblocks.html#cppblock):
0 /** cache of block hash to filter header, to avoid disk access when responding to getcfcheckpt. */
231+ * BIP 157 & 158.
232+ */
233+extern const char *GETCFHEADERS;
234+/**
235+ * cfheaders is a response to a getcfheaders request containing a vector of
236+ * filter headers for each block in the requested range.
if -peerblockfilters is configured, handle requests for cfheaders.
CFCHECKPOINT
in protocol.h
247@@ -235,8 +248,6 @@ extern const char* GETCFCHECKPT;
248 /**
249 * cfcheckpt is a response to a getcfcheckpt request containing a vector of
250 * evenly spaced filter headers for blocks on the requested chain.
251- * Only available with service bit NODE_COMPACT_FILTERS as described by
252- * BIP 157 & 158.
cfheaders
and cfilter
, so I’m removing it from here for consistency. It seems obvious that NODE_COMPACT_FILTERS
is required since it’s a response to getcfcheckpt
, which requires NODE_COMPACT_FILTERS
.
re-ACK 5308c97cca , only change is doc related 🗂
Signature:
0-----BEGIN PGP SIGNED MESSAGE-----
1Hash: SHA512
2
3re-ACK 5308c97cca , only change is doc related 🗂
4-----BEGIN PGP SIGNATURE-----
5
6iQGzBAEBCgAdFiEE+rVPoUahrI9sLGYTzit1aX5ppUgFAlwqrYAACgkQzit1aX5p
7pUi5SgwAwz0FXCPt6ETbRNPe2chK9XeE0E40zYsq0hAJ/rw7G3/Rk2LyC9TG2GoW
8OaJw75Eg80fAu7ImWcTHiUyhKSlIZKJR9QPKC02RImsFZ66UotzFZ0mefsgtkoh0
92bvUJXabSlrOkwt8y12oED2YS0Cgf3OG2DJCPtCGOq9kZUyK+4Ef5stvG6YiYF1/
10GZ+WwyO1iL8G8nPZue3239QgMb3bvX6JxIB8q5oipmMzILg8ja7o/0Cxp1QYdxNF
118tK5nZn0kF4xlDaHrusuWIwgNcPGUYlHbCeCuZoXnompyHn/meyTp2yndmEAp72J
12ILVkp9Nkzs7o7Q1vAZM7YCWOxHdw7ncDTq0tdcpr9BPtorlHvKWIsUJHvUBTd2el
13mlJJaiM5WNq+yISCld8ItK+utub4g95zrfZWyzvs4pLZQTID9tQCtN8U/919zTn1
14OUjYFoy+2AmssmJFtM+CkjJgcSAf6KHYcGXJyY4hhqLvhMsmv5SrW1EYJdy6AW5g
15YbOfPwLk
16=5MJF
17-----END PGP SIGNATURE-----
Timestamp of file with hash eed11e440452664f3996d83b9c085e9a4c0ab77e69ea219b1fe7181017bc09a1 -
124+ start_height=1,
125+ stop_hash=int(stale_block_hash, 16)
126+ )
127+ node0.send_and_ping(request)
128+ response = node0.last_message['cfheaders']
129+ assert_equal(len(response.hashes), 1000)
331@@ -330,6 +332,7 @@ def on_close(self):
332 def on_addr(self, message): pass
333 def on_block(self, message): pass
334 def on_blocktxn(self, message): pass
335+ def on_cfheaders(self, message): pass