core_crypto/mls/conversation/immutable/
credential.rs1use std::{collections::HashMap, sync::Arc};
2
3use openmls::{
4 group::QueuedProposal,
5 prelude::{
6 Credential as MlsCredential, CredentialWithKey, LeafNode, LeafNodeIndex, Proposal, Sender, SignaturePublicKey,
7 },
8};
9
10use super::{Error, Result};
11use crate::{ClientId, Credential, LeafError, RecursiveError};
12
13impl super::Conversation {
14 fn extract_own_updated_node_from_proposals<'a>(
15 own_index: &LeafNodeIndex,
16 pending_proposals: impl Iterator<Item = &'a QueuedProposal>,
17 ) -> Option<&'a LeafNode> {
18 pending_proposals
19 .filter_map(|proposal| {
20 if let Sender::Member(index) = proposal.sender()
21 && index == own_index
22 && let Proposal::Update(update_proposal) = proposal.proposal()
23 {
24 Some(update_proposal.leaf_node())
25 } else {
26 None
27 }
28 })
29 .last()
30 }
31
32 pub(crate) async fn find_current_credential(&self) -> Result<Arc<Credential>> {
34 let group = self.group().await;
37 let own_leaf =
38 Self::extract_own_updated_node_from_proposals(&group.own_leaf_index(), group.pending_proposals())
39 .or_else(|| group.own_leaf())
40 .ok_or(LeafError::InternalMlsError)?;
41 let credential = self
42 .session
43 .find_credential_by_public_key(own_leaf.signature_key())
44 .await
45 .map_err(RecursiveError::mls_client("finding current credential"))?;
46 Ok(credential)
47 }
48
49 pub async fn members(&self) -> HashMap<Vec<u8>, MlsCredential> {
51 self.group().await.members().fold(HashMap::new(), |mut acc, kp| {
55 let credential = kp.credential;
56 let id = credential.identity().to_vec();
57 acc.entry(id).or_insert(credential);
58 acc
59 })
60 }
61
62 pub async fn members_with_key(&self) -> Result<HashMap<ClientId, CredentialWithKey>> {
64 self.group()
65 .await
66 .members()
67 .map(|member| {
68 let credential = member.credential;
69 let id: ClientId = credential
70 .identity()
71 .try_into()
72 .map_err(RecursiveError::mls_client("client id from bytes"))?;
73
74 let credential = CredentialWithKey {
75 credential,
76 signature_key: SignaturePublicKey::from(member.signature_key),
77 };
78
79 Ok((id, credential))
80 })
81 .collect()
82 }
83
84 pub(crate) async fn own_mls_credential(&self) -> Result<MlsCredential> {
85 let credential = self
86 .group()
87 .await
88 .own_leaf_node()
89 .ok_or(Error::MlsGroupInvalidState("own_leaf_node not present in group"))?
90 .credential()
91 .to_owned();
92 Ok(credential)
93 }
94}