Skip to main content

On hardware today

Offline Protocol’s IntelligenceMesh Relay is a dedicated ESP32 node (ESP32-PICO-V3-02, Bluetooth LE 4.2 as both peripheral and central) that relays Offline Protocol mesh traffic over Bluetooth LE today. Power it on and it discovers nearby mesh devices and carries their encrypted messages, extending the range of any app built on the SDK with no setup. To build Offline Protocol into your own hardware, choose a role: a full peer in Rust, or the constrained leaf for firmware.

Full peer

The Rust crates implement protocol state, routing, reliability, MLS and service discovery. Platform code supplies transport I/O and persistent storage. Use a full peer when the device must manage sessions, route traffic or host the complete coordination stack. Start from the versioned SDK workspace, its architecture and transport bridges.

Built-in file stores

A host without a platform keystore can use the stores in offline-protocol from v0.28.0, behind the default file-store feature: A wrong key is refused at open with FileStoreError::WrongStoreKey before any record is read. Each store locks its directory while open; a second engine over the same directories fails with FileStoreError::InUse. The replicated_notes example runs on them. Bindings reach the same stores through initialize_mls_with_file_stores; Python exposes them as store_key options.

Constrained leaf

offline-protocol-leaf is a firmware component for a constrained device. It processes protocol frames and participates in MLS as a member that never issues commits. A full peer creates the group and performs membership commits; the leaf joins, receives, responds and persists its state. Two leaves cannot establish a session with each other on their own. Pair the device with a phone, Linux host or another full peer over a compatible radio path.

Build targets

The leaf builds without default features (--no-default-features --features bare-metal-rng) for these bare-metal targets, and CI builds and lints it for each of them: The Xtensa chips (ESP32, ESP32-S2, ESP32-S3) use a toolchain outside rustup and are not among the leaf’s build targets. The leaf README has the full table. To put the leaf in a firmware image, link it with the device’s radio, a flash driver behind LeafStore, a hardware entropy source behind getrandom, and a time source at pairing; firmware responsibilities has each one. The ESP32-C3, ESP32-C2 and Cortex-M0 targets have no atomic compare-and-swap, so firmware on them links a critical-section implementation; build the store handle with shared_store, which works on every target.

WASI

The leaf also builds for wasm32-wasip1, and CI gates both halves: the no_std build without bare-metal-rng, where getrandom reads the runtime’s random_get, and the std build through the wasi_host_shim example. The shim takes the time and the frames from the runtime over its standard streams and prints the frames the device owes. On WASI, entropy is the runtime’s random_get, so every key is as strong as the runtime’s source. For a browser, use the browser binding, a full node built for wasm32-unknown-unknown; the leaf does not target it. From an SDK checkout:

Firmware responsibilities

The MCU does not inherit the phone or Python relay client. For internet transport, implement a firmware client with connection, authentication and address proof, or use a companion full peer that already has the client. An existing direct upload from the MCU to its own backend can remain unchanged.

Qualify the target

Measure flash, RAM, latency, power, storage endurance and restart behaviour on the selected part and radio stack. Define the full-peer/leaf topology before quoting device capacity or transport support. See the leaf source and contract and commercial integration route.

Install the Rust crates

Use Rust 1.87 or newer. The thirteen offline-protocol crates, including offline-protocol-web for the browser from v0.31.0, are published to crates.io at 0.33.0. For a full peer:
For a constrained device:
Do not combine bare-metal-rng with the default std feature. Register getrandom::register_custom_getrandom! with the device’s hardware entropy source; enabling the feature alone does not supply randomness. A missing or predictable entropy implementation makes key generation unusable or unsafe. The leaf API centers on LeafDevice and LeafStore; a leaf requires a compatible full peer for session establishment. Two leaves cannot establish that session with each other.