De-MLS
Decentralized MLS — end-to-end encrypted group messaging with consensus-based membership over gossipsub-like networks. de-mls implements the Decentralized MLS Off-Chain Consensus protocol on top of OpenMLS: MLS cryptography for the secure channel, and a hashgraph-like consensus service for proposal voting and steward election.
The library's product is a single per-conversation handle — Conversation —
modeled on OpenMLS's MlsGroup. It owns every protocol decision (MLS encryption,
proposal voting, steward commits, freeze timing); transport and identity stay on
your side of the boundary. It runs synchronously and is generic over its
consensus, scoring, and steward plug-ins.
Looking for a runnable app? An example integration — a gateway, a Waku delivery service, and a Dioxus desktop client wired onto this library — lives in the de-mls-poc repository.
What you own vs. what de-mls owns
You provide: identity (opaque member-id bytes and the map from a member to its transport address), the transport itself, the OpenMLS provider (crypto + storage), key-package minting, and the registry of conversations.
de-mls owns: the protocol — MLS commits, proposal voting, steward election,
and freeze timing — along with the per-conversation state behind it: proposal
queues, deduplication, the steward list, peer scores, and the Conversation
state machine.
The Conversation API
use Conversation;
use ;
// Create a conversation you steward, or join one from a welcome:
let mut convo: =
create?;
// let joined = Conversation::join(&provider, welcome_bytes, sync_bytes, …, &signer)?; // Ok(None) = not for us
// Drive it once per wakeup cycle, then drain its products:
convo.process_inbound?; // feed inbound bytes
convo.poll; // tick timers / freeze / commits
for event in convo.drain_events
for out in convo.drain_outbound
The conversation is pull-based: it buffers outbound for you to publish, and
reports its next deadline via next_wakeup_in(), advancing when you call
poll(). Membership and chat are plain methods: add_member / sponsor_member,
remove_member, vote, send_message, leave.
Default plug-in implementations (consensus over hashgraph-like-consensus,
in-memory peer-score storage, the deterministic steward list) live in
de_mls::defaults — adopt them wholesale or swap any one.
A complete, runnable construction — creator and joiner built straight from
direct arguments — is in
tests/standalone_construction.rs.
Build & test
RUSTDOCFLAGS='-Dwarnings'
Building requires the Rust toolchain (edition 2024) and protoc, which
build.rs uses to compile the protobuf definitions.
Documentation
- API: every public trait carries its contract in rustdoc — run
cargo doc -p de-mls --open. - Living example:
tests/standalone_construction.rsbuilds a creator and a joiner straight from direct arguments. - Protocol: de-mls follows the Decentralized MLS Off-Chain Consensus specification.
Contributing
Issues and pull requests are welcome. Please include reproduction steps, relevant logs, and test coverage where possible.
License
Licensed under either of MIT or Apache-2.0 at your option.