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

91 lines
3.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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](06-payload-encrypted.md).
### 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](03-path.md)) |
| 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](06-payload-encrypted.md).
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
- [Section 3: Path](03-path.md) — Path length encoding
- [Section 6: Encrypted Payloads](06-payload-encrypted.md) — Outer envelope format
- [Section 14: Cryptography](14-crypto.md) — Encrypt-then-MAC
- Test vectors: [`corpus/payloads/path-return/`](https://github.com/swaits/meshcore-spec/tree/v0.1.0/corpus/payloads/path-return/)
### Reference Implementation
- `Mesh::createPathReturn()` in `src/Mesh.cpp` — Encoding
- `Mesh::onRecvPacket()`, PATH case within REQ/RESPONSE/TXT_MSG handling — Decoding