Skip to content

Attachment delivery is direct-peer-only — no multi-hop / relayed blob delivery #170

Description

@kitplummer

Summary

Attachment byte delivery is currently direct-peer-only. An attachment can only be delivered to a node that is (a) a direct, mutually-dialed peer of the sender and (b) directly connected to a node that holds the blob. There is no multi-hop delivery and no delivery via a relay peer other than a direct holder — even though the distribution document (CRDT metadata) gossips transitively across the whole mesh.

This is an upstream design limitation in peat-protocol (targeting) and peat-mesh (blob fetch), not a peat-node bug. peat-node only consumes these APIs. Filing here as the consumer-side tracking issue; implementation lands upstream, one PR per repo.

Evidence

Targeting — peat-protocol resolve_targets (storage/file_distribution.rs). Every distribution scope resolves through the sender's known_peers() (direct dials only):

  • AllNodesknown_peers().fmt_short()
  • Nodes { node_ids } → requested ids filtered to known_peers
  • Formationknown_peers today, with a literal // TODO: Query formation membership from Automerge documents
  • Capableknown_peers

A node reachable only transitively (2+ hops) receives the distribution document (gossip is transitive) but is never in target_nodes, so its receive watcher correctly skips it.

Fetch — peat-mesh fetch_blob (storage/iroh_blob_store.rs). The receiver pulls bytes only from its own known_peers. A blob_peer_index exists but is populated from prior direct fetches, not discovery. With no connected peer it errors ("Remote fetch requires P2P connectivity"). There is no "ask the mesh who has blob X" and no store-and-forward relay. (iroh relay_urls is connection-level NAT traversal, not application-level blob multi-hop — the candidate provider set is still known_peers.)

Impact

  • Operators must wire full bidirectional dials between every sender/receiver pair for attachments to work. Across NAT this silently breaks when only one dial direction succeeds: the document syncs over the working direction, but target_nodes (or the blob fetch) excludes the unreachable side, so the file never lands.
  • Defeats the DDIL premise that a file written on one node should propagate through the mesh via whatever connectivity exists — not just to its direct neighbors.

Proposed direction (upstream)

  1. peat-protocol — membership-based targeting. Resolve target_nodes against the gossiped / Automerge mesh-membership set, not the sender's direct known_peers. The existing Formation TODO is the natural seam.
  2. peat-mesh — provider discovery and/or store-and-forward. Either query the mesh for blob providers ("who has blob X?") or have intermediary peers cache and re-provide, so any connected peer holding the blob can serve it — not only a direct holder.

Per-repo work

  • peat-protocol: membership-based resolve_targets
  • peat-mesh: blob provider discovery / store-and-forward relay
  • peat-node: integration + a multi-hop (3-node, non-adjacent sender/receiver) delivery functest once the upstream pieces land

Related

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions