Skip to content

Node message types are absent from peer_registry #862

Description

@echennells

A node cannot send a block to a peer. The block is found and its size computed correctly, then zero bytes are written and the channel is dropped.

Present on master (9099a906, libbitcoin-node 2b377d16) in default configuration. This is the v1 transport; enable_privacy defaults to false.

Steps to trigger

  1. Run bs with inbound connections enabled.
  2. Connect a peer and complete the version/verack handshake.
  3. Send getdata with MSG_BLOCK (or MSG_WITNESS_BLOCK) and the hash of a block the node holds.
  4. The peer receives zero bytes and the node closes the connection.

MSG_TX on the same channel serves normally. bitcoind answers the same request with the block and stays connected.

Observed

Recv getdata from [...] (37 bytes)
Send block to [...] (285 bytes)
Send failure block to [...] (0 bytes) bad data stream
Inbound peer channel stop [...] bad data stream

Mechanism

channel_peer::send type-erases the message and carries a registry index instead:

out.message = rpc::any_t{ system::to_shared(message) };
out.index   = rpc::peer_registry::index_of<Message>();

peer_dispatch.hpp registers 35 types, all messages::peer::*; the only "block" entry is messages::peer::block. libbitcoin-node sends its own node::messages::block, which is not registered, so index_of returns unknown (= size = 35) and peer_registry::to_frame returns null. That becomes bad_stream and stops the channel.

The 285 in the log is message.size(), logged before serialization is attempted. index_of is constexpr, so nothing on the wire affects it.

Introduced by

01d95d9f "Write bip324 messages natively", which replaced serialization at the send site with the registry lookup. git log -S index_of -- channel_peer.hpp returns only this commit.

Why tests didn't catch it

Each registered message is tested here with index_of<T>() then commands().at(index), which throws for unknown. All 35 registered types have one. node::messages::block cannot have one — the test lives in the repo that has no knowledge of node's types.

libbitcoin-node's test/messages/block.cpp passes, because node::messages::block::serialize is correct in isolation; nothing calls it. Its test/protocols/protocol.cpp is BOOST_REQUIRE(true).

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions