Skip to content

Conversation

@sandr01d
Copy link
Contributor

@sandr01d sandr01d commented Jan 20, 2025

As discussed with @keks in #1708, this PR is adding a binding for MlsGroup.store_pending_proposals(). We need to serialize/deserialize QueuedProposal so it can be passed in/out of wasm.

@sandr01d sandr01d requested a review from a team as a code owner January 20, 2025 13:17
@sandr01d sandr01d marked this pull request as draft January 20, 2025 13:37
@sandr01d sandr01d force-pushed the wasm-bind-store-pending-proposal branch 2 times, most recently from 446b671 to 4932da1 Compare January 20, 2025 15:52
@sandr01d
Copy link
Contributor Author

I'm determined to implement this, but I need a little guidance.
To implement MlsGroup.store_pending_proposals() we need to be able to convert QueuedProposal from/to a byte array. The reason for this is that MlsGroup.store_pending_proposals() expects a QueuedProposal which is returned from process_message() to JavaScript. Serializing QueuedProposal is straight forward, because we can use the TlsSerialize derive trait. I implemented this in this draft. QueuedProposal can not derive TlsDeserialize because it contains a transitive member of type LeafNode in its AddProposal variant. LeafNode is not supposed to derive TlsDeserialize:

// TODO(#1242): Do not derive `TlsDeserialize`.
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, TlsSerialize, TlsSize)]
pub struct LeafNode {

Adding a QueuedProposalIn in combination with ProposalIn is not an option either, because ProposalIn can only be turned into a Proposal by calling the (private) ProposalIn.verify() function and, as far as I understand, validation is not necessary in this case because the Proposal inside the QueuedProposal would originate from the same device where it is added to the proposal store. Introducing a way to turn a ProposalIn into a Proposal without verification sounds like a a bad idea, since it would allow to use the API in an insecure manner.
Adding a QueuedProposalIn and implementing From<QueuedProposalIn> for QueuedProposal and similar From implementations for all transitive member types of Proposal in the wasm-land only (similar as is done for testing) would be possible.

#[cfg(any(feature = "test-utils", test))]
impl From<ProposalIn> for crate::messages::proposals::Proposal {
fn from(proposal: ProposalIn) -> Self {
match proposal {
ProposalIn::Add(add) => Self::Add(add.into()),
ProposalIn::Update(update) => Self::Update(update.into()),
ProposalIn::Remove(remove) => Self::Remove(remove),
ProposalIn::PreSharedKey(psk) => Self::PreSharedKey(psk),
ProposalIn::ReInit(reinit) => Self::ReInit(reinit),
ProposalIn::ExternalInit(external_init) => Self::ExternalInit(external_init),
ProposalIn::GroupContextExtensions(group_context_extension) => {
Self::GroupContextExtensions(group_context_extension)
}
ProposalIn::AppAck(app_ack) => Self::AppAck(app_ack),
ProposalIn::Custom(other) => Self::Custom(other),
}
}
}

But this would only be a workaround and add quite a lot of code. Any recommendation on how to move this forward @keks?

@sandr01d sandr01d force-pushed the wasm-bind-store-pending-proposal branch from 4932da1 to 8547005 Compare January 20, 2025 17:36
@keks
Copy link
Contributor

keks commented Jan 22, 2025

Hm, yeah I see the problem here. I am not sure adding a QueuedProposalIn would be a good solution here. So far we use that pattern only for protocol messages that are defined in the spec, and the ~In version represents the unvalidation version of that thing. QueuedProposal is a type that we use internally but does not exist in the spec. Therefore I don't feel like we should reuse that pattern.

One option I see would be using serde instead of the tls_codec for de/serialization. The types implement both Serialize and Deserialize and it's also used for storing the proposals in the provider. I don't see why using the same mechanism would be wrong here.

Do you think that would work or am I missing something? Would that unblock you?

I hope this isn't too frustrating, the whole bindings were sort of cobbled together for a proof of concept, that's also why all the docs are missing.

And finally, thank you for the contributions!

@sandr01d
Copy link
Contributor Author

One option I see would be using serde instead of the tls_codec for de/serialization. The types implement both Serialize and Deserialize and it's also used for storing the proposals in the provider. I don't see why using the same mechanism would be wrong here.

We'd have to add a way to (de)serialize serde to binary. bincode would work, but adding it would increase the binary size of the WebAssembly above the threshold defined in the CI. Maybe there is an alternative I'm not aware of?

I hope this isn't too frustrating, the whole bindings were sort of cobbled together for a proof of concept, that's also why all the docs are missing.

Don't worry, I'd say I'm familiar enough by now to be able to work with it just fine.

And finally, thank you for the contributions!

You're welcome and thanks for your help 🙂

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: No status

Development

Successfully merging this pull request may close these issues.

2 participants