docs/SOURCE_ROUTING.md
This document specifies the Source-Based Routing extension (v2) for the BitChat protocol. This upgrade enables efficient unicast routing across the mesh by allowing senders to specify an explicit path of intermediate relays.
Status: Implemented in Android and iOS. Backward compatible (v1 clients ignore routing data).
To support source routing and larger payloads, the packet format has been upgraded to Version 2.
Key Rule: The HAS_ROUTE (0x08) flag is only valid if the packet version >= 2. Relays receiving a v1 packet must ignore this flag even if set.
The following diagram illustrates the structural differences between a standard v1 packet and a source-routed v2 packet.
+-------------------+---------------------------------------------------------+
| Fixed Header (14) | Variable Sections |
+-------------------+----------+-------------+------------------+-------------+
| Ver: 1 (1B) | SenderID | RecipientID | Payload | Signature |
| Type, TTL, etc. | (8B) | (8B) | (Length in Head) | (64B) |
| Len: 2 Bytes | | (Optional) | | (Optional) |
+-------------------+----------+-------------+------------------+-------------+
+-------------------+-----------------------------------------------------------------------------+
| Fixed Header (16) | Variable Sections |
+-------------------+----------+-------------+-----------------------+------------------+-------------+
| Ver: 2 (1B) | SenderID | RecipientID | SOURCE ROUTE | Payload | Signature |
| Type, TTL, etc. | (8B) | (8B) | (Variable) | (Length in Head) | (64B) |
| Len: 4 Bytes | | (Required*) | Only if HAS_ROUTE=1 | | (Optional) |
+-------------------+----------+-------------+-----------------------+------------------+-------------+
(*) Note: A Route can be attached to any packet type that has a RecipientID (flag HAS_RECIPIENT set).
| Field | Size (v1) | Size (v2) | Description |
|---|---|---|---|
| Version | 1 byte | 1 byte | 0x01 vs 0x02 |
| Payload Length | 2 bytes | 4 bytes | UInt32 in v2 to support large files. Excludes route/IDs/sig. |
| Total Size | 14 bytes | 16 bytes | V2 header is 2 bytes larger. |
The Source Route field is a variable-length list of intermediate hops that the packet must traverse.
RecipientID.Count (1 byte): Number of intermediate hops (N).Hops (N * 8 bytes): Sequence of Peer IDs.The route list MUST contain only the intermediate relays between the sender and the recipient.
SenderID (it is already in the packet).RecipientID (it is already in the packet).Example:
Topology: Alice (Sender) -> Bob -> Charlie -> Dave (Recipient)
SenderID: AliceRecipientID: DaveRoute: [Bob, Charlie] (Count = 2)To calculate routes, nodes need a view of the network topology. This is achieved via a Neighbor List extension to the IdentityAnnouncement packet.
IdentityAnnouncement packets contain a TLV (Type-Length-Value) payload.0x04 (Direct Neighbors).TLV Structure (Type 0x04):
[Type: 0x04] [Length: 1B] [Count: 1B] [NeighborID1 (8B)] [NeighborID2 (8B)] ...
Nodes receiving this TLV update their local mesh graph, linking the sender to the listed neighbors.
To prevent spoofing and routing through stale connections, the Mesh Graph service implements a strict two-way handshake verification:
When a large source-routed packet (e.g., File Transfer) exceeds the MTU and requires fragmentation:
Why? If fragments were sent as v1 packets or without routes, they would fall back to flooding, negating the bandwidth benefits of source routing for large data transfers.
Source routing is fully secured by the existing Ed25519 signature scheme.
SenderID's public key.Signature Input Construction:
Serialize the packet exactly as transmitted, but temporarily set TTL = 0 and remove the Signature bytes.
When a node receives a packet not addressed to itself:
Version >= 2?HAS_ROUTE flag set?i.i + 1.i is the last index, the Next Hop is the RecipientID.sendToPeer) to the Next Hop.