Skip to content

Retrieval Layer Gaps & Implementation Roadmap

This document outlines the remaining technical gaps between the current implementation of the substratum-retrieval crate and the production-grade requirements defined in the Technical Specification.

For authentication and authorization gaps on SwarmCommand handlers, see Swarm Command Security Gaps.

1. WebSocket-to-ByteStream Bridge

Current State: crates/ingress/src/router.rs uses a tokio::io::duplex mock as a placeholder for the actual WebSocket connection.

Gap: Axum's WebSocket is message-based (Binary/Text frames), while libp2p requires a byte-oriented stream (AsyncRead/AsyncWrite).

Requirement: Implement a wrapper for axum::extract::ws::WebSocket that:

  • Buffers incoming binary frames to satisfy poll_read.
  • Wraps outgoing bytes into binary frames for poll_write.
  • Handles WebSocket-level pings/pongs to keep the connection alive.

2. PSK Cryptographic Enforcement

Current State: PnetStream in crates/retrieval/src/transport.rs accepts a PSK but currently passes poll_read/poll_write calls directly to the inner stream without transformation.

Gap: The libp2p-pnet protector must be actively applied to the stream to encrypt/decrypt traffic using the XSalsa20 cipher.

Requirement: Integrate the libp2p-pnet crate's logic into PnetStream or use the standard libp2p_pnet::PnetConfig within the transport pipeline correctly.

3. Bitswap & Blockstore Integration

Current State: SubstratumBehaviour only implements Ping and Identify.

Gap: There is no mechanism to actually request or serve IPFS blocks (CIDs).

Requirement:

  • Add libp2p-bitswap to the behaviour.
  • Implement a Blockstore trait (using redb or RocksDB) for persistent local storage.
  • Connect Bitswap to the Blockstore so that WANT-BLOCK requests can be satisfied from disk.

4. Swarm Actor Command Expansion

Current State: SwarmActor only supports InjectConnection.

Gap: The rest of the system (Axum/Ingress) cannot yet ask the swarm to fetch a specific file.

Requirement: Add SwarmCommand::GetBlock(Cid, oneshot::Sender<Vec<u8>>) and implement the logic to:

  1. Check local Blockstore.
  2. If missing, broadcast a Bitswap WANT to the swarm.
  3. Return the bytes via the oneshot channel once retrieved.

5. Static Bootstrapping (The Triangle)

Current State: Nodes run in isolation unless manually connected.

Gap: Per ADR 03, we do not use a public DHT. Nodes must know how to find the "Global Triangle" nodes.

Requirement: Update SwarmActor to read a list of bootstrap multiaddrs from Config and automatically initiate connections on startup.

6. Multi-Jurisdictional Pinning

Current State: Uploads are local to a single node.

Gap: The spec requires uploads to be pinned across all three Triangle nodes (US, EU, Asia).

Requirement: Implement a "Pinning Coordinator" that, upon a successful upload to the Gateway, sends a SwarmCommand::Pin(Cid) to ensure the other two nodes in the swarm fetch and persist the data.