mls_spec/group/
group_info.rs1use crate::{
2 SensitiveBytes,
3 crypto::Mac,
4 defs::{LeafIndex, ProtocolVersion},
5 group::extensions::{Extension, ExternalPub, RatchetTreeExtension},
6 key_schedule::GroupContext,
7 messages::MlsMessage,
8 tree::RatchetTree,
9};
10
11#[derive(Debug, Clone, PartialEq, Eq, tls_codec::TlsSerialize, tls_codec::TlsSize)]
12#[cfg_attr(feature = "serde", derive(serde::Serialize))]
13pub struct GroupInfoTBS<'a> {
14 pub group_context: &'a GroupContext,
15 pub extensions: &'a [Extension],
16 pub confirmation_tag: &'a Mac,
17 pub signer: &'a LeafIndex,
18}
19
20#[derive(
21 Debug,
22 Clone,
23 PartialEq,
24 Eq,
25 tls_codec::TlsSerialize,
26 tls_codec::TlsDeserialize,
27 tls_codec::TlsSize,
28)]
29#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
30pub struct GroupInfo {
31 pub group_context: GroupContext,
32 pub extensions: Vec<Extension>,
33 pub confirmation_tag: Mac,
34 pub signer: LeafIndex,
35 pub signature: SensitiveBytes,
36}
37
38impl GroupInfo {
39 pub fn to_tbs(&self) -> GroupInfoTBS<'_> {
40 GroupInfoTBS {
41 group_context: &self.group_context,
42 extensions: &self.extensions,
43 confirmation_tag: &self.confirmation_tag,
44 signer: &self.signer,
45 }
46 }
47
48 pub fn ratchet_tree(&self) -> Option<&RatchetTree> {
50 self.extensions.iter().find_map(|ext| {
51 if let Extension::RatchetTree(RatchetTreeExtension { ratchet_tree }) = ext {
52 Some(ratchet_tree)
53 } else {
54 None
55 }
56 })
57 }
58
59 pub fn external_pub(&self) -> Option<&[u8]> {
61 self.extensions.iter().find_map(|ext| {
62 if let Extension::ExternalPub(ExternalPub { external_pub }) = ext {
63 Some(external_pub.as_slice())
64 } else {
65 None
66 }
67 })
68 }
69
70 pub fn into_mls_message(self, protocol_version: ProtocolVersion) -> MlsMessage {
71 MlsMessage {
72 version: protocol_version,
73 content: crate::messages::MlsMessageContent::GroupInfo(self),
74 }
75 }
76}
77
78#[cfg(test)]
79mod tests {
80 use crate::generate_roundtrip_test;
81
82 use super::*;
83
84 generate_roundtrip_test!(can_roundtrip_groupinfo, {
85 GroupInfo {
86 group_context: GroupContext::with_group_id(vec![]),
87 extensions: vec![],
88 confirmation_tag: vec![].into(),
89 signer: 0,
90 signature: vec![].into(),
91 }
92 });
93}