-
Notifications
You must be signed in to change notification settings - Fork 37.7k
Serve BIP 157 compact filters #16442
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
The following sections might be updated with supplementary metadata relevant to reviewers and maintainers. ConflictsReviewers, 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. |
Nice! Thanks for working on this.
I think so,... because some users may want to use the blockfilters only "internal", more specific, to rescan wallets (especially in prune mode), though functionality hasn't been added to Bitcoin Core yet
I'd say yes. But unsure since I think we also signal NODE_NETWORK when in IBD. |
Concept ACK - will review within the next few days. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just reviewed the first bit but I presume some of these comments will apply later too.
src/net.cpp
Outdated
@@ -2597,7 +2599,18 @@ uint64_t CConnman::GetTotalBytesSent() | |||
|
|||
ServiceFlags CConnman::GetLocalServices() const | |||
{ | |||
return nLocalServices; | |||
uint64_t local_services = nLocalServices; | |||
if (local_services & NODE_COMPACT_FILTERS) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please dont add more node logic in net.cpp - if you want node logic put it in net_processing. But, honestly, this should be handled either by init checking these conditions or by the filtering code itself.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The point of this code is that the filter index may be building in the background and we don't want to signal NODE_COMPACT_FILTERS to peers until it is in sync. Then as soon as it does finish syncing, turn it on.
I'm not sure this is the best way to do this so, I'm open to suggestions (this is the subject of two of the questions in the PR description). Another option would be to have a separate CLI flag for signalling NODE_COMPACT_FILTERS, which also blocks the net threads until the filter indices are in sync. That way the user can sync the filter index in the background, then shut down the node and restart with the BIP 157 net stuff enabled. Thoughts?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I spent a few minutes writing an indignant comment about how we should be okay with taking this small hack on as technical debt, but it actually looks like it might be pretty easy to address @TheBlueMatt's concerns by adding a method to CConman
(eg AddLocalService(ServiceFlags flag)
) that just modifies nLocalServices
. The indexing code could call it on sync completion. Any reason not to do that?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(FWIW I hate the idea of blocking net threads while waiting for filter indices to sync, and slightly less hate requiring a restart to serve the filters.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@jamesob Yes, that would work too, but I wouldn't want to index to call CConmann directly. It should do it through some sort of callback to avoid coupling them, which just creates more indirection. I think this approach is a bit easier, but I'd be OK with a callback that updates nLocalServices
as well.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just had an offline conversation with @sdaftuar here (with regard to #16847) which I think is relevant. Dynamically flipping nLocalServices
bits doesn't make a ton of sense because we'd need to disconnect and reconnect to all of our peers in order for the flip to have any effect.
When thinking about this, it's instructive to look at how IBD works: we don't flip NODE_NETWORK
off and on once we've started and finished IBD; instead net_processing just behaves differently during IBD and peers are able to gracefully handle nodes that signal NODE_NETWORK but haven't completed the sync yet and therefore drop getheaders messages.
I think the way forward in this case is to do something analogous: signal NODE_COMPACT_FILTERS
from startup when appropriate and ensure that nodes seeking block filters account for the fact that a peer they request filters from may be in the process of building them.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Dynamically flipping nLocalServices bits doesn't make a ton of sense because we'd need to disconnect and reconnect to all of our peers in order for the flip to have any effect.
I disagree with this. New inbound connections will see that the service bit has been flipped. And clients who need the filters wouldn't connect until it is on, so it's not like any inbound connections need to periodically disconnect/reconnect. And if I understand correctly, we re-advertise our local address with service bits to each peer every day on average, so the network should see the change eventually without the node operator having to do anything.
instead net_processing just behaves differently during IBD and peers are able to gracefully handle nodes that signal NODE_NETWORK but haven't completed the sync yet and therefore drop getheaders messages.
This feels a bit different because the version
message includes a start height indicating how far behind the node is. I suppose clients could also just request checkpoints and determine how far behind a node's filter index is at least to within 1,000 blocks though.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In any case, can you simply modify nLocalServices
directly when the index has finished syncing? Or does other code that accesses it directly need to see the bit set even before sync is done?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have removed the dynamic flipping in accordance with reviewers' suggestions.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Code looks great! Especially the tests. A few small comments, but this is very close to an ACK from me.
Review checklist
-
7da4f23 net: Signal NODE_COMPACT_FILTERS if the block filter index is on.
-
cfc3095 net: Define new BIP 157 protocol messages.
-
7bbf08c net: Message handling for GETCFILTERS.
-
abc58d6 net: Message handling for GETCFHEADERS.
Inconsistent return type (false instead of true).
-
9da9daa net: Message handling for GETCFCHECKPT.
Inconsistent return type (false instead of true).
-
bbb909c blockfilter: Fix default (de)?serialization of BlockFilter.
-
ab0ea72 test: Functional tests for cfilters P2P interface.
Nice tests!
-
77653ec net: Synchronize cfilter request handling with block filter index.
-
f928bdd test: Exercise cache update code during getcfcheckpt handling.
-
3499e88 net: Cache compact filter checkpoints in memory.
Tests
Built and run locally for about a day so far with no problems. Synced filters
from somewhere in the mid 500ks.
Confirmed that the service bit flips appropriately: During filter syncing:
$ ./src/bitcoin-cli -datadir=/data/bitcoin getnetworkinfo
...
"localservices": "0000000000000409",
After filter syncing:
$ ./src/bitcoin-cli -datadir=/data/bitcoin getnetworkinfo
...
"localservices": "0000000000000449",
The comprehensive functional test coverage is cause for optimism.
s << m_block_hash | ||
<< static_cast<uint8_t>(m_filter_type) | ||
s << static_cast<uint8_t>(m_filter_type) | ||
<< m_block_hash |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These changes don't require reindexing because we manually spell out the serialization format when writing to disk (and same with reads) instead of using these serialization ops, right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right
Concept ACK
Yes, suggest defaulting to
I guess it's already built, but I'd be fine with moving that to a followup (and kick the On macOS 10.14.6 when configured with |
BIP 157 is controversial, so I think yes. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Concept ACK. Reviewed each commit and ran tests for each of them. I also did a full IBD and verified that the NODE_COMPACT_FILTERS
flag is flipped on.
src/net_processing.cpp
Outdated
* is updated asynchronously, has not been synchronized with the net processing thread. In that | ||
* case, block for a short time until the filter index is updated, then retry the lookup. | ||
*/ | ||
static bool QueryFilterIndexWithRetry(BaseIndex* index, bool& in_sync, std::function<bool()> fn) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Rather than block the message handler thread until the filter index has synced, is there much downside to ignoring messages when a filter query fails because it is not yet synced? (i.e. not sending anything back to the peer as implemented before 77653ec)
By the spec in BIP 157, clients should be downloading from multiple peers so they wouldn't be wasting much bandwidth because of dropped messages caused by this. Blocking the message handler thread just seems to have more downsides IMO.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It just makes the client logic more complicated as they need to have timeouts and if the index is active (like it has gotten in sync once since the node has been running), it should catch up to the tip pretty fast.
I spun up a temporary testnet node in case anyone wants to test the p2p behavior: |
test/functional/p2p_cfilters.py
Outdated
computed_cfhash = uint256_from_str(hash256(cfilter.filter_data)) | ||
assert_equal(computed_cfhash, cfhash) | ||
|
||
# Check thet peers can fetch cfilters for stale blocks. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should be "that"? :-)
Recent questions have come up regarding dynamic service registration (see bitcoin#16442 (comment) and the assumeutxo project, which needs to dynamically flip NODE_NETWORK). While investigating how dynamic service registration might work, I was confused about how we convey local services to peers. This adds some documentation that hopefully clarifies this process.
Recent questions have come up regarding dynamic service registration (see bitcoin#16442 (comment) and the assumeutxo project, which needs to dynamically flip NODE_NETWORK). While investigating how dynamic service registration might work, I was confused about how we convey local services to peers. This adds some documentation that hopefully clarifies this process.
Recent questions have come up regarding dynamic service registration (see bitcoin#16442 (comment) and the assumeutxo project, which needs to dynamically flip NODE_NETWORK). While investigating how dynamic service registration might work, I was confused about how we convey local services to peers. This adds some documentation that hopefully clarifies this process.
…ertised 82e53f3 doc: add comments clarifying how local services are advertised (James O'Beirne) Pull request description: Recent questions have come up regarding dynamic service registration (see #16442 (comment) and the assumeutxo project ~~which needs to dynamically flip NODE_NETWORK~~). While investigating how dynamic service registration might work, I was confused about how we convey local services to peers. This adds some documentation that hopefully clarifies this process. ACKs for top commit: laanwj: ACK 82e53f3 darosior: ACK 82e53f3 Tree-SHA512: a30c1020387d7a75b5b3cdde45f8b7f2ae46293da97e6227b2ee17e290b93deb5b16c0bbc2b1676972300e5c3c2ad74eb8b3910d6b93e028dac1ae2700468ef9
…are advertised 82e53f3 doc: add comments clarifying how local services are advertised (James O'Beirne) Pull request description: Recent questions have come up regarding dynamic service registration (see bitcoin#16442 (comment) and the assumeutxo project ~~which needs to dynamically flip NODE_NETWORK~~). While investigating how dynamic service registration might work, I was confused about how we convey local services to peers. This adds some documentation that hopefully clarifies this process. ACKs for top commit: laanwj: ACK 82e53f3 darosior: ACK 82e53f3 Tree-SHA512: a30c1020387d7a75b5b3cdde45f8b7f2ae46293da97e6227b2ee17e290b93deb5b16c0bbc2b1676972300e5c3c2ad74eb8b3910d6b93e028dac1ae2700468ef9
@jimpo any plans to address feedback here? It'd be great to see this PR move towards merge. |
@MarcoFalke It's not a question of node resources management, but a more broader concern about light clients current scalability model. Even with a low-bandwidth protocol such as BIP157/158, you may still have a huge discrepancy between the numbers of requesting clients and opt-in public peers to serve them. At its heart, you will always have a incentives conflict between clients asking for resources and offering nothing back and full-node operators. Unless your light client protocol is so ridiculous cheap to rely on niceness of a subset of nodes operators offering free resources, it won't scale for thousands or millions of clients. And it's likely you will always have a ratio disequilibrium between numbers of clients and numbers of full-node, even worst their growth rate won't be the same, first one are so much easier to setup. I have been through mailing posts about BIP157/158 design but haven't seen any realistic projections and specially what people do aim to achieve by integrating this at the p2p layer. I do understand people may be interested to use compact filters for their own Neutrino-style client and if so they should use the RPC interface. I'm worried about wallet vendors building such chain access backend for people not connecting to their own full-node but directly to the broader network, which maybe fine now because you have really few BIP157 clients, but going to hit a bandwidth scalability wall few years from now instead of pursing better solutions. Maybe I'm completely wrong, missing some numbers and I would be super glad to read about what have been previously thought on this issue. In the meanwhile I'm Concept NACK on this and happy to bring it during next meeting and explained issues as I perceived it on the ml. Note, that doesn't restrain to get this PR ready for merge. |
@ariard please take discussion of light-client scalability to the mailing list. Comments on this PR should be for review of the implementation. |
@ariard This is an optional feature, not enabled by default. It might make some sense to support it for trusted peers only (missing from this PR), although protocols like Stratum are probably better for that purpose (but nobody has implemented it for Core to date). @jnewbery Concept NACKs, and the explanation therefore (required by dev notes!) do belong on PRs... I think I'm going to mirror @ariard's Concept NACK. We do have bloom already for trusted peers, and using this for public peers does indeed harm the network. We can't stop anyone else from deploying it, but with Core's monopoly, that hardly matters. |
@ariard Of course there are always questions about incentives to provide public data for free by nodes, but that problem isn't unique to BIP157 - you can also question if nodes have reason to provide blocks, transactions, to participate in relay, ... etc. Perhaps there is a future where all these things eventually have to be paid for, but for now, trying to solve this perfectly would just lead you to the conclusion that all non-miner nodes should be turned off, and if someone wants to audit the chain they can connect directly to miners. The relevant question is how BIP157 costs compare to services already offered, which doesn't seem very bad to me. |
@luke-jr Certainly reasons to reject an implementation of a BIP should go on a PR, but you have principled objections to a BIP - which seems to be the case here - it is much more useful to have that criticism be visible more widely. It would be strange if there is apparent consensus that a BIP is a good idea, and then having it not be implemented in Core because of an argument only presented there. |
Github doesn't allow PRs to be transferred, so I've opened #18876 for the new branch. |
@luke-jr Yes I noticed that's an optional feature, used the term opt-in somehow IIRC. @sipa that's the right but you may have an indirect incentive to relay blocks and likely-to-be-blocks to foster network robustness and make your transactions more censorship-resistant. Killing a light client doesn't increase or decrease network security ? Anyway, thanks for your comments, throw a lengthy argumentation on the mailing list on this. |
…g on index sync state Github-Pull: bitcoin#16442 Rebased-From: 9e182b0
…advertised Summary: PR description: > Recent questions have come up regarding dynamic service registration > (see bitcoin/bitcoin#16442 (comment) > and the assumeutxo project > While investigating how dynamic service registration might work, I was > confused about how we convey local services to peers. This adds some > documentation that hopefully clarifies this process. Backport of [[bitcoin/bitcoin#16847 | PR16847]] Test Plan: `ninja` (code comments only) Reviewers: O1 Bitcoin ABC, #bitcoin_abc, jasonbcox Reviewed By: O1 Bitcoin ABC, #bitcoin_abc, jasonbcox Differential Revision: https://reviews.bitcoinabc.org/D8010
…are advertised 82e53f3 doc: add comments clarifying how local services are advertised (James O'Beirne) Pull request description: Recent questions have come up regarding dynamic service registration (see bitcoin#16442 (comment) and the assumeutxo project ~~which needs to dynamically flip NODE_NETWORK~~). While investigating how dynamic service registration might work, I was confused about how we convey local services to peers. This adds some documentation that hopefully clarifies this process. ACKs for top commit: laanwj: ACK 82e53f3 darosior: ACK 82e53f3 Tree-SHA512: a30c1020387d7a75b5b3cdde45f8b7f2ae46293da97e6227b2ee17e290b93deb5b16c0bbc2b1676972300e5c3c2ad74eb8b3910d6b93e028dac1ae2700468ef9
…are advertised 82e53f3 doc: add comments clarifying how local services are advertised (James O'Beirne) Pull request description: Recent questions have come up regarding dynamic service registration (see bitcoin#16442 (comment) and the assumeutxo project ~~which needs to dynamically flip NODE_NETWORK~~). While investigating how dynamic service registration might work, I was confused about how we convey local services to peers. This adds some documentation that hopefully clarifies this process. ACKs for top commit: laanwj: ACK 82e53f3 darosior: ACK 82e53f3 Tree-SHA512: a30c1020387d7a75b5b3cdde45f8b7f2ae46293da97e6227b2ee17e290b93deb5b16c0bbc2b1676972300e5c3c2ad74eb8b3910d6b93e028dac1ae2700468ef9
…are advertised 82e53f3 doc: add comments clarifying how local services are advertised (James O'Beirne) Pull request description: Recent questions have come up regarding dynamic service registration (see bitcoin#16442 (comment) and the assumeutxo project ~~which needs to dynamically flip NODE_NETWORK~~). While investigating how dynamic service registration might work, I was confused about how we convey local services to peers. This adds some documentation that hopefully clarifies this process. ACKs for top commit: laanwj: ACK 82e53f3 darosior: ACK 82e53f3 Tree-SHA512: a30c1020387d7a75b5b3cdde45f8b7f2ae46293da97e6227b2ee17e290b93deb5b16c0bbc2b1676972300e5c3c2ad74eb8b3910d6b93e028dac1ae2700468ef9
…are advertised 82e53f3 doc: add comments clarifying how local services are advertised (James O'Beirne) Pull request description: Recent questions have come up regarding dynamic service registration (see bitcoin#16442 (comment) and the assumeutxo project ~~which needs to dynamically flip NODE_NETWORK~~). While investigating how dynamic service registration might work, I was confused about how we convey local services to peers. This adds some documentation that hopefully clarifies this process. ACKs for top commit: laanwj: ACK 82e53f3 darosior: ACK 82e53f3 Tree-SHA512: a30c1020387d7a75b5b3cdde45f8b7f2ae46293da97e6227b2ee17e290b93deb5b16c0bbc2b1676972300e5c3c2ad74eb8b3910d6b93e028dac1ae2700468ef9
…are advertised 82e53f3 doc: add comments clarifying how local services are advertised (James O'Beirne) Pull request description: Recent questions have come up regarding dynamic service registration (see bitcoin#16442 (comment) and the assumeutxo project ~~which needs to dynamically flip NODE_NETWORK~~). While investigating how dynamic service registration might work, I was confused about how we convey local services to peers. This adds some documentation that hopefully clarifies this process. ACKs for top commit: laanwj: ACK 82e53f3 darosior: ACK 82e53f3 Tree-SHA512: a30c1020387d7a75b5b3cdde45f8b7f2ae46293da97e6227b2ee17e290b93deb5b16c0bbc2b1676972300e5c3c2ad74eb8b3910d6b93e028dac1ae2700468ef9
…are advertised 82e53f3 doc: add comments clarifying how local services are advertised (James O'Beirne) Pull request description: Recent questions have come up regarding dynamic service registration (see bitcoin#16442 (comment) and the assumeutxo project ~~which needs to dynamically flip NODE_NETWORK~~). While investigating how dynamic service registration might work, I was confused about how we convey local services to peers. This adds some documentation that hopefully clarifies this process. ACKs for top commit: laanwj: ACK 82e53f3 darosior: ACK 82e53f3 Tree-SHA512: a30c1020387d7a75b5b3cdde45f8b7f2ae46293da97e6227b2ee17e290b93deb5b16c0bbc2b1676972300e5c3c2ad74eb8b3910d6b93e028dac1ae2700468ef9
…are advertised 82e53f3 doc: add comments clarifying how local services are advertised (James O'Beirne) Pull request description: Recent questions have come up regarding dynamic service registration (see bitcoin#16442 (comment) and the assumeutxo project ~~which needs to dynamically flip NODE_NETWORK~~). While investigating how dynamic service registration might work, I was confused about how we convey local services to peers. This adds some documentation that hopefully clarifies this process. ACKs for top commit: laanwj: ACK 82e53f3 darosior: ACK 82e53f3 Tree-SHA512: a30c1020387d7a75b5b3cdde45f8b7f2ae46293da97e6227b2ee17e290b93deb5b16c0bbc2b1676972300e5c3c2ad74eb8b3910d6b93e028dac1ae2700468ef9
…are advertised 82e53f3 doc: add comments clarifying how local services are advertised (James O'Beirne) Pull request description: Recent questions have come up regarding dynamic service registration (see bitcoin#16442 (comment) and the assumeutxo project ~~which needs to dynamically flip NODE_NETWORK~~). While investigating how dynamic service registration might work, I was confused about how we convey local services to peers. This adds some documentation that hopefully clarifies this process. ACKs for top commit: laanwj: ACK 82e53f3 darosior: ACK 82e53f3 Tree-SHA512: a30c1020387d7a75b5b3cdde45f8b7f2ae46293da97e6227b2ee17e290b93deb5b16c0bbc2b1676972300e5c3c2ad74eb8b3910d6b93e028dac1ae2700468ef9
…are advertised 82e53f3 doc: add comments clarifying how local services are advertised (James O'Beirne) Pull request description: Recent questions have come up regarding dynamic service registration (see bitcoin#16442 (comment) and the assumeutxo project ~~which needs to dynamically flip NODE_NETWORK~~). While investigating how dynamic service registration might work, I was confused about how we convey local services to peers. This adds some documentation that hopefully clarifies this process. ACKs for top commit: laanwj: ACK 82e53f3 darosior: ACK 82e53f3 Tree-SHA512: a30c1020387d7a75b5b3cdde45f8b7f2ae46293da97e6227b2ee17e290b93deb5b16c0bbc2b1676972300e5c3c2ad74eb8b3910d6b93e028dac1ae2700468ef9
…are advertised 82e53f3 doc: add comments clarifying how local services are advertised (James O'Beirne) Pull request description: Recent questions have come up regarding dynamic service registration (see bitcoin#16442 (comment) and the assumeutxo project ~~which needs to dynamically flip NODE_NETWORK~~). While investigating how dynamic service registration might work, I was confused about how we convey local services to peers. This adds some documentation that hopefully clarifies this process. ACKs for top commit: laanwj: ACK 82e53f3 darosior: ACK 82e53f3 Tree-SHA512: a30c1020387d7a75b5b3cdde45f8b7f2ae46293da97e6227b2ee17e290b93deb5b16c0bbc2b1676972300e5c3c2ad74eb8b3910d6b93e028dac1ae2700468ef9
…are advertised 82e53f3 doc: add comments clarifying how local services are advertised (James O'Beirne) Pull request description: Recent questions have come up regarding dynamic service registration (see bitcoin#16442 (comment) and the assumeutxo project ~~which needs to dynamically flip NODE_NETWORK~~). While investigating how dynamic service registration might work, I was confused about how we convey local services to peers. This adds some documentation that hopefully clarifies this process. ACKs for top commit: laanwj: ACK 82e53f3 darosior: ACK 82e53f3 Tree-SHA512: a30c1020387d7a75b5b3cdde45f8b7f2ae46293da97e6227b2ee17e290b93deb5b16c0bbc2b1676972300e5c3c2ad74eb8b3910d6b93e028dac1ae2700468ef9
…are advertised 82e53f3 doc: add comments clarifying how local services are advertised (James O'Beirne) Pull request description: Recent questions have come up regarding dynamic service registration (see bitcoin#16442 (comment) and the assumeutxo project ~~which needs to dynamically flip NODE_NETWORK~~). While investigating how dynamic service registration might work, I was confused about how we convey local services to peers. This adds some documentation that hopefully clarifies this process. ACKs for top commit: laanwj: ACK 82e53f3 darosior: ACK 82e53f3 Tree-SHA512: a30c1020387d7a75b5b3cdde45f8b7f2ae46293da97e6227b2ee17e290b93deb5b16c0bbc2b1676972300e5c3c2ad74eb8b3910d6b93e028dac1ae2700468ef9
This enables nodes to serve block filters compliant with BIP 157. This is the last PR required for BIP 157/158 compatibility.
If the node has the block filter index enabled, once the index is in sync, the node will begin signaling the BIP 158 service bit and responding to BIP 157 requests. On invalid requests, the node disconnects the offending peer.
This is tested using functional tests. I have also synced an lnd testnet node using the neutrino backend connected to a Core node running this code.
Questions:
-blockfilterindex
to enable serving of filters from the index?boost::shared_lock
around the checkpoint cache acceptable?