Files
meshcore-spec/versions/v0.1.0/09-payload-path.md
T
swaitsandClaude Opus 4.7 f83d4088e3 spec: link corpus references to GitHub, version-aware
Every "Test vectors: \`corpus/...\`" mention in the spec is now a
markdown link pointing at the corresponding file or directory on
GitHub. Each version build resolves its links to the correct git
ref:

  - /latest/ -> https://github.com/swaits/meshcore-spec/tree/main/corpus/...
  - /v0.1.0/ -> https://github.com/swaits/meshcore-spec/tree/v0.1.0/corpus/...
  - future /vX.Y.Z/ -> /tree/vX.Y.Z/corpus/...

Two changes:

1. src/*.md (18 files): the inline-code corpus paths in each
   "Cross-References" section are now markdown links. Directories
   point at /tree/main/corpus/..., individual .json files point at
   /blob/main/corpus/.... CHANGELOG and other non-corpus main links
   are intentionally left pointing at main — the canonical history
   lives there regardless of which version you're reading.

2. justfile: `cut-version` now also runs a sed over the snapshot's
   *.md files replacing /tree/main/corpus -> /tree/<VERSION>/corpus
   and /blob/main/corpus -> /blob/<VERSION>/corpus. So a freshly-cut
   version is self-consistent.

versions/v0.1.0/* regenerated by re-running
`just cut-version v0.1.0` after the new src/ links + recipe sed
landed.

Tagging the release commit (`git tag v0.1.0`) is now REQUIRED — not
"optional" — because the rendered /v0.1.0/ pages reference
/tree/v0.1.0/corpus/... on GitHub. Without the tag the links 404.
cut-version's output now says so.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-12 10:35:09 -06:00

3.5 KiB
Raw Blame History

MeshCore Protocol Specification

Section 9: Payload — Path Return

Overview

The PATH payload carries an encrypted return path from one node to another. It uses the same dest_hash + src_hash + encrypt-then-MAC envelope as REQ/RESPONSE/ TXT_MSG, but the decrypted contents contain routing path data and optional extra application data.

Payload Type

Header payload type field: 0x08 (PATH)

Wire Format (Outer)

 0
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| dest_hash(1)  |  src_hash(1)  |    Cipher MAC (2 bytes)       |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                                                               |
|              Ciphertext (N × 16 bytes, N ≥ 1)                |
|                                                               |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

The outer format is identical to Section 6.

Decrypted Inner Format

+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|  path_len(1)  |         Path (hash_count × hash_size)        |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| extra_type(1) |         Extra Data (variable)                 |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Field Size Type Description
path_len 1 byte encoded Same bitfield encoding as packet path_len (see Section 3)
path hash_count × hash_size raw The return path to the sender
extra_type 1 byte uint8 Type of extra data (lower 4 bits used; upper 4 reserved)
extra remaining raw Extra data (may include trailing zero padding from AES)

Extra Type Values

Value Description
0x00 No meaningful extra data (reciprocal path)
0xFF Dummy/padding (used when no real extra data; followed by 4 random bytes)
Other Application-defined

When creating a path return with no extra data, the reference implementation appends 0xFF as extra_type followed by 4 random bytes to ensure the packet hash is unique.

Encoding

  1. Build the inner plaintext: a. Write path_len byte (encoded hash_size and hash_count). b. Write path bytes (hash_count × hash_size). c. If extra data is provided: write extra_type (lower 4 bits), write extra. d. If no extra data: write 0xFF, write 4 random bytes.
  2. Encrypt the inner plaintext using encrypt-then-MAC with the shared secret.
  3. Prepend dest_hash and src_hash.

Decoding

  1. Decode the outer envelope (dest_hash, src_hash, MAC, ciphertext) as in Section 6.
  2. After decryption: a. Read 1 byte as path_len. Decode hash_size and hash_count. b. Read hash_count × hash_size bytes as the path. c. Read 1 byte as extra_type (use lower 4 bits only). d. Remaining bytes are extra data (may include AES zero-padding).

Cross-References

Reference Implementation

  • Mesh::createPathReturn() in src/Mesh.cpp — Encoding
  • Mesh::onRecvPacket(), PATH case within REQ/RESPONSE/TXT_MSG handling — Decoding