Files
meshcore-spec/versions/v0.1.0/10-payload-trace.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

107 lines
3.8 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 10: Payload — Trace
### Overview
The TRACE payload enables path discovery with per-hop signal quality measurement.
A trace packet travels along a specified direct path, and each intermediate node
appends its received SNR value to the packet's path field. When the trace reaches
its final hop, the accumulated SNR values and node hashes are delivered.
### Payload Type
Header payload type field: `0x09` (TRACE)
### Wire Format
The trace payload has a fixed 9-byte header followed by an optional path hashes
section (appended when sent via direct routing):
```
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Tag (uint32_le) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Auth Code (uint32_le) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Flags | Path Hashes (variable) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
```
### Fields
| Field | Offset | Size | Type | Description |
|-------|--------|------|------|-------------|
| tag | 0 | 4 bytes | uint32_le | Random tag set by the initiator for correlation |
| auth_code | 4 | 4 bytes | uint32_le | Authentication code |
| flags | 8 | 1 byte | uint8 | Flags (see below) |
| path_hashes | 9 | variable | raw | Node hashes for the path to trace (appended for direct send) |
### Flags Field
```
Bit: 7 6 5 4 3 2 1 0
+---+---+---+---+---+---+---+---+
| Reserved | S1 S0|
+---+---+---+---+---+---+---+---+
```
| Bits | Description |
|------|-------------|
| 0-1 | Path hash size for the trace path hashes (as a power of 2: 0=1 byte, 1=2 bytes, 2=4 bytes) |
| 2-7 | Reserved (must be zero) |
Note: The flags field path hash size encoding (`1 << (flags & 0x03)`) differs
from the packet path_len encoding (`(code >> 6) + 1`).
### Direct Sending
When a TRACE packet is sent via direct routing, the path hashes are appended
directly to the payload (after the 9-byte header), not placed in the packet's
path field. The packet's path field is instead used to accumulate SNR values
from intermediate nodes.
```
On creation: payload = [tag(4)][auth_code(4)][flags(1)] (9 bytes)
On sendDirect: payload += path_hashes (9 + N bytes)
packet.path_len = 0 (path used for SNR)
```
### SNR Accumulation
As each intermediate node forwards a TRACE packet, it appends its received SNR
value as a single signed byte to the packet's path field:
```
path[path_len++] = (int8_t)(SNR × 4)
```
The SNR value is stored as SNR × 4 for 0.25 dB precision, matching the format
used in RxMeta frames.
### Trace Completion
A TRACE is considered complete when the path_len counter (used as an offset into
the path hashes in the payload) reaches or exceeds the remaining path hashes.
At that point, `onTraceRecv` is called with:
- The accumulated SNR values (in packet.path)
- The path hashes (in packet.payload, after byte 9)
- The path length (number of hops traversed)
### Minimum Size
- Minimum payload: 9 bytes (tag + auth_code + flags, no path hashes)
### Cross-References
- [Section 16: Packet Hash](16-packet-hash.md) — TRACE packets include path_len in hash
- Test vectors: [`corpus/payloads/trace/`](https://github.com/swaits/meshcore-spec/tree/v0.1.0/corpus/payloads/trace/)
### Reference Implementation
- `Mesh::createTrace()` in `src/Mesh.cpp` — Creation (9-byte base)
- `Mesh::sendDirect()` — Path appended to payload for TRACE type
- `Mesh::onRecvPacket()`, TRACE handling — SNR accumulation and completion check