Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

MeshCore Protocol Specification

Section 0: Overview

Spec version: v0.1.0 · see Spec Versions for the full list of frozen releases.

Status and Provenance

This is an unofficial, independent specification. It is not part of the upstream MeshCore project, not affiliated with or endorsed by its maintainers, and not authored by them. Read this section before relying on the spec for anything load-bearing.

This document was primarily written by an AI (Claude, by Anthropic — mostly the Opus 4.x family) under the direction of SWaits, with human proofreading and editing on top. Substantive edits — additions, audit passes, errata fixes — are produced through model-driven analysis of the upstream MeshCore C++ source and reviewed before commit.

The upstream MeshCore C++ firmware is the source of truth for all protocol behavior. This spec is downstream and derivative. Whenever the spec and the upstream C++ disagree, upstream wins — and a fix to this spec is filed against this repo, not against MeshCore. Each substantive change in CHANGELOG.md records the upstream commit hash it was validated against.

Refinements have also been driven in part by observations from building DongLoRa firmware and apps against live MeshCore deployments. Where DongLoRa behavior diverges from upstream, this spec follows upstream and treats the DongLoRa side as a follow-up bug, not a spec change.

Conformance against the test corpus is a useful signal but not a substitute for cross-checking against upstream firmware. If you find a divergence from upstream, please file an issue — that is exactly the kind of report this project exists to catch.

Spec Versions

The published site preserves prior spec versions alongside the rolling latest build. The URL layout is:

  • https://swaits.github.io/meshcore-spec/latest/ — built from the tip of main. May change between any two visits.
  • https://swaits.github.io/meshcore-spec/v0.1.0/ (and likewise for any future vX.Y.Z) — a frozen content snapshot. Suitable for citing or for certifying an implementation against.

Frozen versions live as their own directory in the repo (versions/vX.Y.Z/) — a literal copy of src/ taken at release time. This deliberately separates content (versioned, frozen) from site infrastructure (theme, picker, build pipeline; lives at the repo root and is unversioned). Every deploy rebuilds every published version using today’s infrastructure, so site improvements show up everywhere without backporting.

The version-picker in the top-right of every page lists every published version; switching keeps you on the same chapter where it exists in the target version. Spec versions use semver and are independent of the upstream MeshCore firmware’s own versioning — each release records the upstream commit hash it was validated against in CHANGELOG.md.

Scope

This specification covers:

  • The packet wire format (framing, header, path, payload)
  • All payload types and their binary encodings
  • Cryptographic operations (encryption, signing, key exchange, hashing)
  • The BLE/Serial companion protocol
  • The KISS modem protocol
  • The bridge protocol (RS232/ESP-NOW)

It does NOT cover:

  • Application-level behavior (e.g., room server logic, repeater policies)
  • Radio-layer parameters (LoRa spreading factor, bandwidth, frequency)
  • Duty cycle management or transmission scheduling
  • User interface or companion app behavior

Terminology

The key words “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “MAY”, and “OPTIONAL” in this document are to be interpreted as described in RFC 2119.

Additional terms used throughout:

TermDefinition
PacketThe fundamental transmission unit in MeshCore.
HeaderThe first byte of a packet, encoding route type, payload type, and protocol version.
PathA sequence of node hashes representing the route a packet has taken or should follow.
HashA truncated prefix of a node’s Ed25519 public key, used for routing.
PayloadThe data portion of a packet, whose structure depends on the payload type.
Transport CodesOptional 4-byte field present in transport-mode packets, used for regional scoping.
MACMessage Authentication Code — a 2-byte truncated HMAC-SHA256 used for integrity verification.
MTUMaximum Transmission Unit — 255 bytes for MeshCore.
Flood RoutingRouting mode where packets are broadcast and repeated by intermediate nodes, building up the path as they travel.
Direct RoutingRouting mode where the path is supplied by the sender and the packet follows a specific route.

Byte Order

All multi-byte integer fields in MeshCore are encoded in little-endian byte order unless explicitly stated otherwise. The one exception is CayenneLPP sensor data, which uses big-endian encoding.

Notation

  • Binary data is shown as hex bytes separated by spaces: 0D 00 EF BE AD DE
  • Bit fields are shown in binary with MSB first: 0bVVPPPPRR
  • Bit numbering is LSB = bit 0, MSB = bit 7
  • Field sizes are in bytes unless noted as bits
  • [field(N)] denotes a field of N bytes
  • [field(N)?] denotes an optional field of N bytes

Protocol Constants

These constants define the fundamental limits of the protocol:

ConstantValueDescription
MAX_TRANS_UNIT255Maximum packet size on the wire (bytes)
MAX_PACKET_PAYLOAD184Maximum payload size (bytes)
MAX_PATH_SIZE64Maximum path size (bytes)
PUB_KEY_SIZE32Ed25519 public key size (bytes)
PRV_KEY_SIZE64Ed25519 private key size (bytes)
SIGNATURE_SIZE64Ed25519 signature size (bytes)
CIPHER_KEY_SIZE16AES-128 key size (bytes)
CIPHER_BLOCK_SIZE16AES-128 block size (bytes)
CIPHER_MAC_SIZE2Truncated HMAC-SHA256 MAC size (bytes)
PATH_HASH_SIZE1Default path hash size for v1 (bytes)
MAX_HASH_SIZE8Maximum hash size for deduplication (bytes)
MAX_ADVERT_DATA_SIZE32Maximum advertisement app data size (bytes)

Protocol Versions

The protocol version is encoded in bits 6-7 of the header byte:

VersionValueStatusDescription
V10x00Active1-byte src/dest hashes, 2-byte MAC
V20x01ReservedFuture (e.g., 2-byte hashes, 4-byte MAC)
V30x02ReservedFuture
V40x03ReservedFuture

Currently only V1 is defined. Implementations MUST support V1. Implementations SHOULD reject packets with unrecognized version values unless they have explicit support for that version.

Document Organization

SectionTitleDescription
00OverviewThis document
01Wire FormatPacket framing and field layout
02HeaderHeader byte encoding
03PathPath length encoding and path field
04Payload: ACKAcknowledgment payload
05Payload: AdvertisementNode advertisement and app data
06Payload: EncryptedREQ/RESPONSE/TXT_MSG payloads
07Payload: Anonymous RequestAnonymous request payload
08Payload: GroupGroup text and data payloads
09Payload: Path ReturnEncrypted path return payload
10Payload: TracePath trace payload
11Payload: MultipartMulti-packet payload
12Payload: ControlControl and discovery payloads
13Payload: Raw CustomCustom raw payload
14CryptographyAES-128, HMAC-SHA256, encrypt-then-MAC
15IdentityEd25519 keys, ECDH, key hashing
16Packet HashSHA-256 deduplication hashing
17RoutingFlood and direct routing behavior
18Companion ProtocolBLE/Serial companion communication
19KISS ProtocolKISS modem framing and extensions
20Bridge ProtocolRS232/ESP-NOW bridge framing

References