Appearance
Routing information: header vs routing block vs encrypted tail
This page answers: where does “the route” live? — for flood and strict source route traffic — under the current dynamic header (minimum 16-byte base, 20 bytes with HAS_DST_ID, 16-bit channelHash / messageId).
Stateless repeaters (no predictive tables)
Repeaters do not consult nextHop RAM tables or distance-vector databases for third-party frames. They:
| Information | Where it lives |
|---|---|
| Who sent | srcId in the base header |
| Who is addressed | Optional dstId when HAS_DST_ID |
| How far it may travel | ttlRaw in the base header (policy-capped — see Routing) |
| Forward path / breadcrumbs | Routing block in the plaintext tail before the AES-CCM inner region when ttlRaw & 0x80 (HAS_ROUTE_BLOCK) |
| Duplicate suppression | RAM cache keyed by (channelHash, srcId, sessionId, messageId, fragmentWord) |
Omitting the routing block at origin (normative)
Do not require a routing block on every flood. That wastes bytes.
When hopControl bit 7 is clear (HAS_ROUTE_BLOCK == 0), no routing block exists on the wire — there is no pathCount field and no placeholder at that position. The application tail (ciphertext+MIC) immediately follows the last enabled prefix block (optional region/fragment if present, else the base header).
Originators MAY omit the routing block on flood frames when no path breadcrumbs are needed yet.
The first relay that forwards a flood frame with no routing block (ttlRaw & 0x80 == 0) MUST, during that forwarding operation:
- Insert a new routing block (
pathCount = 1, localhashSizefingerprint) before the encrypted application tail (shift ciphertext+MIC right). Originators MAY omit the routing block entirely — there is nopathCount=0placeholder. - Set
hopControl |= 0x80(HAS_ROUTE_BLOCK). - Decrement
HOP_LIMITper Routing. - Verify the full Mesh PDU remains ≤ 255 bytes.
Any relay that chooses to forward a flood frame that lacks a routing block MUST insert the routing block as part of that forward (same steps). Repeaters MUST NOT mutate verFlags.
This is allowed because:
- The routing block is outside the encrypted inner payload and excluded from CCM AAD.
hopControlis zero-masked in AAD at offset0x04, so relays need not re-encrypt.- Repeaters MUST NOT mutate
verFlags. - Repeaters MUST NOT exceed the 255-byte PHY payload limit.
Routing block (normative)
When hopControl bit 7 (HAS_ROUTE_BLOCK, wire ttlRaw & 0x80) is set, the routing block begins after the optional Region and optional Fragment blocks (see Packet layout).
| Field | Size | Description |
|---|---|---|
pathCount | 1 | Number of path entries (0–63 typical; product caps MAY differ). |
pathHashes | pathCount × hashSize | Each entry hashSize bytes: pathHash = SHA256("LowMesh/route-fingerprint/1" || uint32_le(nodeId32))[0..hashSize-1] — see Routing. |
Wire bytes: 1 + pathCount × hashSize.
Flood append (normative sketch)
When FLOOD is set and the node rebroadcasts:
- Verify hop budget, duplicate cache, and PHY growth policy (≤ 255 bytes total).
- If
(ttlRaw & 0x80) == 0: no routing block is present — the relay MUST insert one (pathCount = 1, localhashSizefingerprint) before the encrypted application tail, setttlRaw |= 0x80, then decrement hops:ttlRaw = (ttlRaw & 0xC0) | ((hopLimit - 1) & 0x3F)(withhopLimit = ttlRaw & 0x3Fbefore the decrement).verFlagsMUST NOT change. - If
ttlRawbit 7 is already set: appendhashSizebytes topathHashes, incrementpathCount, then decrement hop count inttlRawthe same way (upper bits preserved). - Shift the encrypted inner tail right as needed without re-encrypting: the routing block is outside AES-CCM AAD, and
ttlRawis zero-masked in AAD — see Channels & security.
Strict source route (sketch)
Originators MAY pre-fill pathHashes with ordered fingerprints; relays verify their position in the path and forward toward the next hop per product rules (see firmware reference sourceRouteRelayRole).
Security (normative): The routing block is outside CCM AAD so repeaters can modify or grow flood breadcrumbs without re-encrypting. That is correct for flood path recording. Strict source-route instructions that affect security, authorization, or delivery guarantees MUST be authenticated inside the encrypted application body or by a separate routeAuth mechanism. Strict source routes carried only in the plaintext routing block are advisory unless authenticated by a higher-layer routeAuth field — MUST NOT be treated as trusted authorization by themselves. Do not change flood breadcrumb behavior: the routing block remains mutable for relay insertion and appending.
Crypto boundary note
On all channelHash values, only the application tail after the routing block is AES-256-CCM-4 protected (including 0x0000). The base header, region block, fragment block, and routing block are plaintext with respect to the channel PSK MIC, but the AAD policy authenticates an explicit prefix — see Channels & security.
See also
- Packet layout — dynamic base + modular tail
- Routing — TTL ceilings, flood, duplicate suppression
- Payloads — inner
payloadTypebodies - Channels & security — CCM-4, dynamic AAD,
ttlRawmasking at0x04