SDKs and platforms

How do I use Offline Protocol from Rust?

Add the offline-protocol crate from crates.io with cargo add offline-protocol. The crates are I/O-free protocol engines that queue, route, encrypt and select transports but never open a socket or touch a radio for the protocol, so a Rust consumer writes the platform bridge that performs the sends and feeds in received bytes. Built-in file stores cover key and state storage on hosts without a keystore, and the crates need Rust 1.87 or newer.

TL;DR

cargo add offline-protocol gives you the full protocol engine, which leaves network and radio I/O to your platform bridge. The bridge drains each transport's outbound queue, performs the send, reports the result and injects received bytes. Built-in file stores handle keys and state on hosts without a keystore. The crates need Rust 1.87 or newer.

Learning objectives

After reading this article you will be able to:

  • Identify which offline-protocol crates a full peer or a constrained device needs
  • Describe what a platform bridge must do for each transport the engine queues
  • Set up storage with the built-in file stores on a host without a keystore

Offline Protocol Rust crates on crates.io

The Rust SDK is a set of offline-protocol crates on crates.io, and the main one is added with a single command:

cargo add offline-protocol

offline-protocol is the main protocol engine, with encryption on by default. It builds on sibling crates, each with one job:

CrateRole
offline-protocol-coreCore types and data structures
offline-protocol-sealedSealed-envelope codec, address derivation and signing payloads, shared with bare-metal leaf nodes
offline-protocol-transportThe transport abstraction for Bluetooth LE, Wi-Fi, internet, Reticulum and Nostr
offline-protocol-routerDORS routing and relay management
offline-protocol-reliabilityAcknowledgments, retries and deduplication
offline-protocol-mlsEnd-to-end encryption with MLS (RFC 9420)
offline-protocol-servicesService discovery and request and response over the mesh
offline-protocol-dataReplicated documents (CRDT) that merge after offline edits
offline-protocol-leafA constrained device as a member that never commits, for bare metal
offline-protocol-webThe engine for the experimental browser binding

Crate versions match the release: offline-protocol 0.31.0 is the same release as the npm and PyPI packages of that number. The crates are AGPL-3.0-only, with a commercial licence available.

I/O-free protocol engine

The Rust crates are I/O-free protocol engines for everything that moves a message. They keep status, send and receive queues, metrics and Bluetooth LE fragmentation state, and they route, encrypt and pick a transport, but they never open a socket or touch a radio for the protocol itself. The one socket they do open is the telemetry pipe’s HTTPS upload, and only once an app enables telemetry with a key.

That split is what lets the same engine sit inside an iOS app, an Android app and a Python gateway. It also defines the work: the React Native and Python packages ship the platform bridges, and when you consume the crates directly with cargo add, you write the bridge yourself.

Platform bridge responsibilities

A platform bridge owns the real sockets, relays and radios, and the offline-protocol-transport crate documents its contract. The protocol engine talks to each transport through the Transport trait, where send() enqueues and receive() dequeues. The bridge works the other side of the same queues:

  • Drain outbound work with get_next_message(), get_next_signed_event() or, for Bluetooth LE, get_next_fragment().
  • Perform the send over the real link.
  • Report the outcome with confirm_sent() or report_send_failure().
  • Inject inbound bytes with on_data_received() or on_fragment_received().
  • Drive availability with on_status_changed().

Until a bridge is attached, send() only queues messages, and for every transport except Bluetooth LE, start() does not mark the transport available, so send() returns TransportNotAvailable. In a pure Rust integration, your bridge marks the transport available, drains the queues and does the I/O. Most transports signal pending work through a set_on_messages_available callback, so no poll timer is needed; the internet transport is the exception and must be polled.

The bridge also supplies persistent storage for the target, and storage is the other half of what the platforms page lists for a Rust integration.

Built-in file stores for Rust hosts

The offline-protocol crate includes file stores for a host with no platform keystore, behind its default file-store feature:

TypeRole
SealedFileMlsStorageMLS material sealed with ChaCha20-Poly1305 under keys derived from an operator-supplied store key and the account namespace
FileProtocolStateStorageProtocol state in the same format the iOS, Android and Python providers write
FileStorePair::openOpens both stores together and refuses directory pairs the engine would lose data over
EnvStoreKey, StaticStoreKeyStore key from the OFFLINE_PROTOCOL_STORE_KEY environment variable, or from bytes the host already holds

A wrong key is refused at open with FileStoreError::WrongStoreKey before any record is read. Each store locks its directory while open, so a second engine over the same directories fails with FileStoreError::InUse. Because the state format is shared, a state directory opens under any binding for the same account. The SDK’s replicated_notes example runs on these stores.

Rust version requirement

The crates need Rust 1.87 or newer, the rust-version the workspace manifest declares. Building the native library behind the other bindings from source is a separate case: the Python, C and Flutter docs ask for Rust 1.91 or newer for that build.

offline-protocol-leaf for microcontrollers

offline-protocol-leaf is the crate for firmware that takes part in the encrypted mesh, on a device such as a lock or a sensor. It builds without default features for bare-metal targets, the no_std style of Rust used in firmware, and its build targets include ESP32-C6, ESP32-H2, ESP32-C3 and ESP32-C2 (RISC-V), Cortex-M0, Cortex-M33 and WASI.

A leaf is an MLS group member that receives, responds and persists its state, and a full peer, such as a phone or a Linux host, creates the group and handles membership changes. Firmware supplies the radio I/O, a hardware entropy source, the time at pairing and durable storage through LeafStore. Which microcontrollers can run Offline Protocol? has the full target table, and Can a microcontroller run end-to-end encrypted mesh messaging? covers the memory and design questions.

Rust crates or a ready binding

Use the crates directly when you need the engine inside your own Rust program, a platform no binding covers, or firmware. If you want transports already wired, a ready binding saves the bridge work: React Native on phones, or Python on macOS, Linux and Windows hosts, ships Bluetooth LE, peer-stream and relay bridges over the same engine.

Frequently asked questions

Does the offline-protocol crate open sockets or Bluetooth connections?

No. The crates queue, route, encrypt and select transports, and a platform bridge does the actual I/O. The one socket they open is the telemetry pipe's HTTPS upload, and only after an app enables telemetry with a key.

What happens if I call send() without a bridge attached?

Messages wait in the transport's queue until a bridge sends them. For every transport except Bluetooth LE, start() alone does not mark the transport available; the bridge does, and until then send() returns TransportNotAvailable.

Which Rust version do the crates need?

Rust 1.87 or newer, the minimum the workspace manifest declares. Building the native library behind the Python, C and Flutter bindings from source is documented with Rust 1.91 or newer.

Which Offline Protocol crate do I use on a microcontroller?

offline-protocol-leaf, which builds without default features for bare-metal targets such as ESP32 RISC-V chips and Cortex-M. It joins encrypted groups that a full peer, such as a phone or a Linux host, sets up.

Can I run the Rust engine in a browser?

Yes. The offline-protocol-web crate on crates.io is the engine for the experimental browser binding, and the JavaScript that runs it is in the SDK repository. That JavaScript is not on npm yet, so you build it from source.

Sources

Build it with Offline Protocol

The Rust page covers a full peer, the built-in file stores, the constrained leaf crate and its build targets, and what firmware must supply.

Read the Rust and embedded docs