openmls/group/
group_context.rs1use openmls_traits::crypto::OpenMlsCrypto;
4use openmls_traits::types::Ciphersuite;
5
6use super::*;
7use crate::{
8 error::LibraryError,
9 framing::{mls_auth_content::AuthenticatedContent, ConfirmedTranscriptHashInput},
10 versions::ProtocolVersion,
11};
12
13#[derive(
30 Debug,
31 Clone,
32 PartialEq,
33 Eq,
34 Serialize,
35 Deserialize,
36 TlsSerialize,
37 TlsDeserialize,
38 TlsDeserializeBytes,
39 TlsSize,
40)]
41pub struct GroupContext {
42 protocol_version: ProtocolVersion,
43 ciphersuite: Ciphersuite,
44 group_id: GroupId,
45 epoch: GroupEpoch,
46 tree_hash: VLBytes,
47 confirmed_transcript_hash: VLBytes,
48 extensions: Extensions,
49}
50
51#[cfg(any(feature = "test-utils", test))]
52impl GroupContext {
53 pub(crate) fn set_epoch(&mut self, epoch: GroupEpoch) {
54 self.epoch = epoch;
55 }
56
57 #[cfg(test)]
59 pub(crate) fn set_ciphersuite(&mut self, ciphersuite: Ciphersuite) {
60 self.ciphersuite = ciphersuite;
61 }
62}
63
64impl GroupContext {
65 pub(crate) fn new(
67 ciphersuite: Ciphersuite,
68 group_id: GroupId,
69 epoch: impl Into<GroupEpoch>,
70 tree_hash: Vec<u8>,
71 confirmed_transcript_hash: Vec<u8>,
72 extensions: Extensions,
73 ) -> Self {
74 GroupContext {
75 ciphersuite,
76 protocol_version: ProtocolVersion::Mls10,
77 group_id,
78 epoch: epoch.into(),
79 tree_hash: tree_hash.into(),
80 confirmed_transcript_hash: confirmed_transcript_hash.into(),
81 extensions,
82 }
83 }
84
85 pub(crate) fn create_initial_group_context(
87 ciphersuite: Ciphersuite,
88 group_id: GroupId,
89 tree_hash: Vec<u8>,
90 extensions: Extensions,
91 ) -> Self {
92 Self::new(ciphersuite, group_id, 0, tree_hash, vec![], extensions)
94 }
95
96 pub(crate) fn increment_epoch(&mut self) {
98 self.epoch.increment()
99 }
100
101 pub(crate) fn update_tree_hash(&mut self, new_tree_hash: Vec<u8>) {
103 self.tree_hash = new_tree_hash.into()
104 }
105
106 pub(crate) fn update_confirmed_transcript_hash(
109 &mut self,
110 crypto: &impl OpenMlsCrypto,
111 interim_transcript_hash: &[u8],
112 authenticated_content: &AuthenticatedContent,
113 ) -> Result<(), LibraryError> {
114 let confirmed_transcript_hash = {
115 let input = ConfirmedTranscriptHashInput::try_from(authenticated_content)
116 .map_err(|_| LibraryError::custom("PublicMessage did not contain a commit"))?;
117
118 input.calculate_confirmed_transcript_hash(
119 crypto,
120 self.ciphersuite,
121 interim_transcript_hash,
122 )?
123 };
124
125 self.confirmed_transcript_hash = confirmed_transcript_hash.into();
126
127 Ok(())
128 }
129
130 pub fn protocol_version(&self) -> ProtocolVersion {
132 self.protocol_version
133 }
134
135 pub fn ciphersuite(&self) -> Ciphersuite {
137 self.ciphersuite
138 }
139
140 pub fn group_id(&self) -> &GroupId {
142 &self.group_id
143 }
144
145 pub fn epoch(&self) -> GroupEpoch {
147 self.epoch
148 }
149
150 pub fn tree_hash(&self) -> &[u8] {
152 self.tree_hash.as_slice()
153 }
154
155 pub fn confirmed_transcript_hash(&self) -> &[u8] {
157 self.confirmed_transcript_hash.as_slice()
158 }
159
160 pub(crate) fn set_extensions(&mut self, extensions: Extensions) {
161 self.extensions = extensions;
162 }
163
164 pub fn extensions(&self) -> &Extensions {
166 &self.extensions
167 }
168
169 pub fn required_capabilities(&self) -> Option<&RequiredCapabilitiesExtension> {
171 self.extensions.required_capabilities()
172 }
173}