Skip to content

Add not_found protocol overrides at bip37. - #1106

Merged
evoskuil merged 2 commits into
libbitcoin:masterfrom
echennells:ech99-send-not-found
Sep 11, 2026
Merged

Add not_found protocol overrides at bip37.#1106
evoskuil merged 2 commits into
libbitcoin:masterfrom
echennells:ech99-send-not-found

Conversation

@echennells

@echennells echennells commented Aug 26, 2026

Copy link
Copy Markdown
Contributor

The node stops the channel when a peer requests a block or transaction it cannot serve. bitcoind replies notfound and stays connected. Implements #986.

Reworked per review: the behaviour is a protocol level, not a condition. protocol_block_out_70001 and protocol_transaction_out_70001 derive from the _106 classes and override handle_unservable. The _106 classes retain the stop, as not_found is undefined below bip37, and protocol_block_out_70012 now derives from _70001. The session attaches the derived protocol when bip37 is negotiated.

The reply is gated by peer.enable_not_found, routed through config and parse alongside the other optional peer features.

A hash resolving to no header is answered before the checkpoint height query, which faults the store on a terminal link.

Six cases cover unknown, pruned and unassociated blocks, an unknown transaction, a peer below bip37, and the option disabled. Fixtures live in p2p_setup_fixture.

Depends on libbitcoin/libbitcoin-network#879.

@evoskuil evoskuil left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The correct implementation is more invasive than implemented, as required by the design. Each versioned/negotiated protocol level implies a class to encapsulate the behavior, even if the behavior is optional at that level. This keeps protocol semantics isolated. The vtable cost is negligible, while the organizational advantage is significant. Otherwise we would end up with a perpetually-growing list of conditions on a single protocol class.

const bool node_pruned_;
const bool node_witness_;
const bool allow_overlapped_;
const bool not_found_allowed_;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

enable_not_found_

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Other configurable optional p2p protocol features:

[peer]
enable_alert = false                # send/log alert messages (no send option)
enable_reject = false               # send/log reject messages
enable_address = true               # in/out address messages
enable_address_v2 = false           # in/out address v2 messages
enable_witness_tx = false           # in/out wtxid for tx announcements
enable_compact = false              # in/out compact block announcements
enable_relay = false                # in/out transaction announcements
enable_privacy = true               # opportunistic encryption (bip324)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If this is to be an option (as opposed to version-based), which it should be, then it must be routed through config and parse.

node_witness_(session->node_settings().provide_witness),
allow_overlapped_(session->node_settings().allow_overlapped),
not_found_allowed_(negotiated_version() >=
network::messages::peer::not_found::version_minimum),

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not consistent with protocol versioning design. See existing patterns for adding features at distinct protocol levels. This requires protocol class derivation at the protocol level in which the feature is activated, and then attachment of the derived protocol in the case where it is active.

Comment thread test/functional/p2p.cpp Outdated
}

// A limited node answers for a block it has pruned, and remains unfaulted.
struct p2p_limited_setup_fixture

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't add ad-hoc inline fixtures, there is a dedicated text cpp/hpp for this (and established pattern in server).

// ----------------------------------------------------------------------------

// This protocol is also attached below bip130, and when headers-first is
// disabled, so the peer may be below bip37, where not_found is undefined.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See design comments above.


// This tx could not have been advertised to the peer.
stop(system::error::not_found);
// The protocol is attached above bip37, where not_found is defined.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See design comments above.

@echennells echennells changed the title Send not_found for unservable get_data. Add not_found protocol overrides at bip37. Sep 8, 2026
Report a run of unservable block requests with one not_found rather than
one per item, testing servability with is_associated so that the block is
not fetched twice at a run boundary. The run is accumulated by the 70001
protocol, which knows the message can carry more than one item; the 106
protocol stops the channel on the first, so the send loop asks before it
continues and nothing is accumulated where nothing is reported.

Move the per-item reason to verbose. The channel is no longer stopped, so
an unservable request is ordinary peer input and the log is otherwise
trivially overflowed. The stopping case logs once, in the override that
decides to stop.

Select the transaction protocol by negotiated version, as with blocks,
rather than replacing the 106 protocol outright. That tier is not yet
reachable, as version.relay is read as false below bip37, where the peer
has no way to decline relay.

Add the two protocol headers to node.hpp, and cover the 70001 protocol
where it is attached directly rather than as the 70012 base.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@evoskuil
evoskuil merged commit b78238b into libbitcoin:master Sep 11, 2026
14 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants