MLS Commit Ordering and Group Self-Healing

This is another problem that was brought up by @gecko in the chat; and I feel like it is also one of the weaker parts of the spec at the moment.

The short version is: MLS requires everyone in a group to apply commits in the same order, and Cryptid’s dumb-pipe server design creates a problem with that because they are deliberately content-unaware and can’t act as a central authoritative queue. This can (and most likely will) lead to people bricking their own group states.

Here’s what I think might help, but it comes at a wee bit of cost.

We do a 3 layer approach with the following layers:

Layer 1 — Server side commit sequencing

We can add 2 fields to the message envelope for commit messages only:

  • an opaque group_token (Blake3 of the group ID)
  • a commit_sequence number.

The server can use these to maintain per group commit ordering and buffer briefly if a later sequence number arrives before an earlier one while rejecting clear sequence violations.

The privacy cost of this would be that the server learns that an opaque token exists and can count commits associated with it. It learns nothing about group membership or whatever goes on in the group itself. I think this is a minimal and acceptable metadata leak, but I’d definitely like more feedback about this.

This does require leaking the fact that a message is a commit, which is in direct conflict with the current design goals where message types are fully hidden. I personally think that “this is a group state change” reveals far less than the social graph metadata the server already unavoidably sees from delivery patterns.

Layer 2 — Client-side epoch fencing

Clients should keep track of their current epoch and when they receive a commit for epoch N+K when sitting at epoch N, rather than erroring out, they should buffer the commit and request gap commits by sequence number from the server. So the request would look like “give me sequence numbers X through Y for group token Z”.

Layer 3 — External Commit Self healing

For situations where the gap commits are just fully gone, clients can self heal using MLS external commits. The flow might look like:

  1. Detect epoch gap, request missing commits by sequence number
  2. If unavailable, fetch current GroupInfo from server
  3. Construct and send an External Commit
  4. Rejoin current epoch, back in sync

From the user’s perspective this could look like a “resyncing…” indicator at worst and not a borked room that requires admin intervention to re-add them.

This requires servers to store the latest GroupInfo blob (opaque) per group, keyed on the opaque group token I mentioned earlier.

Quorum ACK Gate for Commit Proposals

On top of the 3 layers thing, we should probably make it so that new commits can only be proposed once a quorum of currently active members has ACKed the previous commit.

Critically, this would gate proposals and not commit applications. “Currently active” needs a proper definition though. Maybe members seen within the last N minutes? The gate should open regardless after a hard timeout so that offline members don’t deadlock commits forever.

I have questions

  • How big/small should the activity window be for the quorum gate?
  • Should the group_token rotate with epochs or stay stable for the group lifetime? I feel like rotating it would be best for privacy, but it’ll require a lot of work to get right.
  • Is leaking the commit flag an acceptable choice? Alternatively, we could probably use a separate out-of-band sequencing channel so the main envelope stays fully opaque?
1 Like

Would this require that each group has a “home” relay? I don’t really like this either way, I think it exposes too much information to the servers for something we can just do on clients anyway

also not a huge fan of this, it leaks metadata about commits to the server but if its unavoidable probably better than kicking devices out permanently. Personally i’d prefer polling all the devices known to the dropped client asking for the groupinfo tho, in the worst case requiring a qr code scan/link paste from an active user

I don’t think it would. I feel like all servers involved would just keep track based on the messages flowing through them.

I mean, we could just handle this on the client side at the application level. Something like peer assisted recovery or something. Maybe we could have a SyncRequest SystemOperation message that pokes clients for the missing commits? We’d need to think this through carefully though because it complicates client logic quite a bit.

Yeah… it felt very not great as I was typing it out but I wanted to get the brain dump out before I forgot about it.

Out of band resyncing is definitely doable I think. It could even use the same mechanism as the SyncRequest thing from earlier maybe.

We can add 2 fields to the message envelope for commit messages only:

  • an opaque group_token (Blake3 of the group ID)

  • a commit_sequence number.

The server can use these to maintain per group commit ordering and buffer briefly if a later sequence number arrives before an earlier one while rejecting clear sequence violations.

But from what I understand this means we have to trust the server to correctly queue and re-order commit messages for clients, this isn’t just a privacy leak, it would also mean the server can actively disrupt chats in a specific way to corrupt group changes, instead of the previous design where (as far as I know) the server can only indiscriminately DoS messages.

That also seems kind of bad, and we should probably avoid giving the server the ability to conduct more advanced attacks on group state like this if possible.

1 Like

Oh yeah, this is no longer the way forward with the double envelope system we’re doing (as mentioned in Cryptid Protocol: Major Spec Rewrite: What's Changing and Why ). :sweat_smile:
The server is pretty much not going to be involved in whatever solution we end up reaching.

I keep wondering if we should make it so that each mailbox is an RMQ queue and we let RMQ handle the ordering and stuff for us. :thinking:

1 Like