Request: block filter peers being disconnected due to invalid block requests

During the recent 2-block reorg at 941880 I noticed while inspecting the log files of a node that was stalled for 10 minutes (link :radioactive: big file) that one of it’s peers was sending blockfilter requests for the blocks this node was stalled from receiving:

[net] peer requested invalid block hash: 95b0d0f836f18d78dfbae435fb37bf6fff2e37a4fc01c20be8495bc3ea4fbb58, disconnecting peer=8502032, [...]

A node with a similar version message then proceeds to continually reconnect after being disconnected and asking for more forbidden filters :).

Note, this behavior on the part of the requesting client is a violation of BIP-0157 which states:

StopHash MUST be known to belong to a block accepted by the receiving peer. This is the case if the peer had previously sent a headers or inv message with that block or any descendents. A node that receives getcfheaders with an unknown StopHash SHOULD NOT respond.

But it seems some BIP157 light clients are not complying, and I’m curious to learn what clients out there are getting disconnected for this reason, could anyone that has debug=net logging enabled share the results of the following awk script which prints the associated version strings of compact blocks peers that violate this rule:

awk -F'peer=' '
    BEGIN {
        print "| peer | version | blockhash |";
        print "|------|---------|-----------|";
    }
    # 2026-03-23T15:23:40.335605Z [msghand] [../../src/net_processing.cpp:3691] [ProcessMessage] [net] receive version message: /btcwire:0.5.0/neutrino:0.12.0-beta/: [etc...], peer=8502032, [etc...]
    /receive version message/ {
        v=$1; 
        sub(/.*receive version message: /, "", v); 
        sub(/: .*/, "", v); 
        sub(/: .*/, "", v); 

        p=$2;
        sub(/,.*/, "", p);
            
        ver[p]=v;
    } 
    # 2026-03-23T15:23:52.623454Z [msghand] [../../src/net_processing.cpp:3281] [PrepareBlockFilterRequest] [net] peer requested invalid block hash: 95b0d0f836f18d78dfbae435fb37bf6fff2e37a4fc01c20be8495bc3ea4fbb58, disconnecting peer=8502032, [...]
    /invalid block hash/ {
        h=$1; 
        sub(/.*invalid block hash: /, "", h); 
        sub(/,.*/, "", h); 

        p=$2;
        sub(/,.*/, "", p);

        print "| "p" | "ver[p]" | "h" |";
    }
' debug.log

One-line form:

awk -F'peer=' 'BEGIN{print "| Peer | Block Hash | Version |";print "|------|------------|---------|";}/receive version message/{v=$1;sub(/.*receive version message: /, "", v);sub(/: .*/, "", v);sub(/: .*/, "", v);p=$2;sub(/,.*/, "", p);ver[p]=v;}/invalid block hash/{h=$1;sub(/.*invalid block hash: /, "", h);sub(/,.*/, "", h);p=$2;sub(/,.*/, "", p);print "| "p" | "h" | "ver[p]" |";}' debug.log

This bitcoin core issue is also relevant: bitcoin/bitcoin#29655

All of the nodes on the log sample I analyzed had the same version string: /btcwire:0.5.0/neutrino:0.12.0-beta/

peer version blockhash
8531836 /btcwire:0.5.0/neutrino:0.12.0-beta/ 00000000000000000000bd4930a5982911e7749eb491886206e71abdc1ec0cc6
8532044 /btcwire:0.5.0/neutrino:0.12.0-beta/ 00000000000000000000bd4930a5982911e7749eb491886206e71abdc1ec0cc6
8532234 /btcwire:0.5.0/neutrino:0.12.0-beta/ 0000000000000000000085ebdcd669c404195dbfeccbee902fc646dadc367a20
8532026 /btcwire:0.5.0/neutrino:0.12.0-beta/ 0000000000000000000085ebdcd669c404195dbfeccbee902fc646dadc367a20
8541062 /btcwire:0.5.0/neutrino:0.12.0-beta/ 95b0d0f836f18d78dfbae435fb37bf6fff2e37a4fc01c20be8495bc3ea4fbb58
8539079 /btcwire:0.5.0/neutrino:0.12.0-beta/ 00000000000000000001f8562235e11fc74d5eea589e4c37b671b4213e89f52f
1 Like

I have one node that I have net debug logs for and that has blockfilterindex=1. I ran your awk script against my logs since 2026-01-01.

In total, I have 1734 entries of this happening. All but four clients have btcwire:0.5.0/neutrino:0.12.0-beta as the user agent. For three I don’t have a user agent in the output (probably connected to me before 2026-01-01 and the version message is in a different log file), and for one I have /btcwire:0.5.0/zap-desktop:0.7.7-beta/.

I have IP logging enabled on my nodes, so my output includes IPs. Not posting these here, but can share privately, if that’s interesting to you.

Looking some of these IPs up, it seems they all belong to a diverse set of cloud hosters (Digital Ocean, Hetzner, Google Cloud, some Swedish cloud hosters, …). I didn’t check all IPs, but the only residential IP I saw was for the zap-desktop:0.7.7-beta user agent. This led me to believe that these are LN nodes hosted in the cloud. Looking some of the IPs up on https://amboss.space and 1ml.com shows that there are actually LN nodes running behind these. I don’t know if you can fingerprint/identify LN node implemenations by behavior if you just have their IP addresses, but my guess would be that btcwire:0.5.0/neutrino:0.12.0-beta/ is LND?

Looking at block hashes, I have 1166 (67%) entries with 95b0d0f836f18d78dfbae435fb37bf6fff2e37a4fc01c20be8495bc3ea4fbb58. I could not find a mention of this on GitHub besides on your net: cbfilters: Don't disconnect peers for requesting unknown blocks. by davidgumberg · Pull Request #34933 · bitcoin/bitcoin · GitHub PR. I didn’t check BIP 157 yet. It might be hardcoded somewhere, but encoded.

I looked a few of the remaining block hashes up in a block explorer and they all seem to be valid.

data (without peer column)

1 Like

On top of that, do you see any events of “Failed to find block filter in index” logs (followed by ignoring the request, not disconnection)? As brought up in CFilters reject and disconnect peers with a valid block hash · Issue #29655 · bitcoin/bitcoin · GitHub this might happen even with BIP157 compliant peers who send their request right after they receive the INV for the block (but the node hasn’t indexed the block yet because that happens in another thread). This would need to be fixed withing Core, if it actually was an issue.

I’ve found a single occurence of Failed to find block filter in index from December 2024 on the blockfilterindex=1 node. This seems to be a floresta peer=1580012 that (at least back then) would request a getcfilters for a block we hadn’t connected and neither inv’ed to it yet.

2024-12-21T19:45:35.353185Z [msghand] [net_processing.cpp:3580] [ProcessMessage] [net] receive version message: /Floresta:0.7.0/: version 70016, blocks=0, us=X, txrelay=0, peer=1580012, peeraddr=Y
...
2024-12-21T22:52:54.450806Z [msghand] [net_processing.cpp:4330] [ProcessMessage] Saw new cmpctblock header hash=000000000000000000009f27b05ec8d4a533b8ad61f670b8441e3a656a2ad084 peer=Z
2024-12-21T22:52:54.558481Z [msghand] [blockencodings.cpp:220] [FillBlock] [cmpctblock] Successfully reconstructed block 000000000000000000009f27b05ec8d4a533b8ad61f670b8441e3a656a2ad084 with 1 txn prefilled, 2081 txn from mempool (incl at least 16 from extra pool) and 28 txn requested
...
2024-12-21T22:52:55.700045Z [scheduler] [validationinterface.cpp:215] [operator()] [validation] BlockConnected: block hash=000000000000000000009f27b05ec8d4a533b8ad61f670b8441e3a656a2ad084 block height=875798
2024-12-21T22:52:55.704025Z [msghand] [net_processing.cpp:3382] [ProcessMessage] [net] received: getcfilters (37 bytes) peer=1580012
2024-12-21T22:52:55.704055Z [msghand] [net_processing.cpp:3183] [ProcessGetCFilters] [net] Failed to find block filter in index: filter_type=basic, start_height=875798, stop_hash=000000000000000000009f27b05ec8d4a533b8ad61f670b8441e3a656a2ad084
2024-12-21T22:52:55.713134Z [scheduler] [validationinterface.cpp:179] [operator()] [validation] UpdatedBlockTip: new block hash=000000000000000000009f27b05ec8d4a533b8ad61f670b8441e3a656a2ad084 fork block hash=00000000000000000000f9038e041a74a5b69790258b1ed9c17573e161bbeca2 (in IBD=false)
...
2024-12-21T22:52:55.713346Z [msghand] [net_processing.cpp:5651] [SendMessages] [net] SendMessages: sending inv peer=1580012 hash=000000000000000000009f27b05ec8d4a533b8ad61f670b8441e3a656a2ad084
1 Like

I don’t have much to add here, but I think 95b0d0f836f18d78dfbae435fb37bf6fff2e37a4fc01c20be8495bc3ea4fbb58 could be a case of a neutrino light-client with a corrupted database. For some reason, I remember there being a few database corruption issues which would make sense since the hash is not a block hash. Maybe it could be a `cfheader` hash? Are those requests all from the same peer?

Good point. I didn’t notice this while initially looking at the data, but all of these 95b0d0f836f18d78dfbae435fb37bf6fff2e37a4fc01c20be8495bc3ea4fbb58 hashes come from 176.126.84.91. The first connection I’ve logged is from 2025-08-29.

1 Like

The reason why all the nodes have the same version message is that neutrino has not updated it’s version message since 0.12.0

Current master: