Skip to main content

river_core/room_state/
member.rs

1use crate::room_state::ban::BansV1;
2use crate::room_state::ChatRoomParametersV1;
3use crate::util::{sign_struct, truncated_base32, verify_struct};
4use crate::ChatRoomStateV1;
5use ed25519_dalek::{Signature, SigningKey, VerifyingKey};
6use freenet_scaffold::util::{fast_hash, FastHash};
7use freenet_scaffold::ComposableState;
8use serde::{Deserialize, Serialize};
9use std::collections::{HashMap, HashSet};
10use std::fmt;
11use std::fmt::{Debug, Display};
12use std::hash::{Hash, Hasher};
13
14/*
15Note that the owner should not be in the members list but for most purposes (eg. sending messages)
16they should be treated as if they are in the list. The reason is to avoid storing the owner's
17VerifyingKey twice because it's already stored in the ChatRoomParametersV1.
18*/
19
20#[derive(Serialize, Deserialize, Eq, PartialEq, Clone, Debug, Default)]
21pub struct MembersV1 {
22    pub members: Vec<AuthorizedMember>,
23}
24
25impl ComposableState for MembersV1 {
26    type ParentState = ChatRoomStateV1;
27    type Summary = HashSet<MemberId>;
28    type Delta = MembersDelta;
29    type Parameters = ChatRoomParametersV1;
30
31    fn verify(
32        &self,
33        parent_state: &Self::ParentState,
34        parameters: &Self::Parameters,
35    ) -> Result<(), String> {
36        if self.members.is_empty() {
37            return Ok(());
38        }
39
40        if self.members.len() > parent_state.configuration.configuration.max_members {
41            return Err(format!(
42                "Too many members: {} > {}",
43                self.members.len(),
44                parent_state.configuration.configuration.max_members
45            ));
46        }
47
48        let owner_id = parameters.owner_id();
49        let members_by_id = self.members_by_member_id();
50
51        for member in &self.members {
52            if member.member.id() == owner_id {
53                return Err("Owner should not be included in the members list".to_string());
54            }
55            if member.member.member_vk == parameters.owner {
56                return Err(
57                    "Member cannot have the same verifying key as the room owner".to_string(),
58                );
59            }
60            if member.member.invited_by == member.member.id() {
61                return Err("Self-invitation detected".to_string());
62            }
63
64            // Verify the full invite chain with Ed25519 signature checks
65            self.get_invite_chain_with_lookup(member, parameters, &members_by_id)?;
66        }
67        Ok(())
68    }
69    fn summarize(
70        &self,
71        _parent_state: &Self::ParentState,
72        _parameters: &Self::Parameters,
73    ) -> Self::Summary {
74        self.members.iter().map(|m| m.member.id()).collect()
75    }
76
77    fn delta(
78        &self,
79        _parent_state: &Self::ParentState,
80        _parameters: &Self::Parameters,
81        old_state_summary: &Self::Summary,
82    ) -> Option<Self::Delta> {
83        let added = self
84            .members
85            .iter()
86            .filter(|m| !old_state_summary.contains(&m.member.id()))
87            .cloned()
88            .collect::<Vec<_>>();
89        if added.is_empty() {
90            None
91        } else {
92            Some(MembersDelta { added })
93        }
94    }
95
96    fn apply_delta(
97        &mut self,
98        parent_state: &Self::ParentState,
99        parameters: &Self::Parameters,
100        delta: &Option<Self::Delta>,
101    ) -> Result<(), String> {
102        let max_members = parent_state.configuration.configuration.max_members;
103
104        if let Some(delta) = delta {
105            // Build a combined lookup map that includes both existing members
106            // AND members being added in this delta. This is necessary because
107            // during merge, a member and their inviter may both be in the delta
108            // (e.g., member B invited by member A, both being added from the
109            // other state). Without this, verify would fail with "Inviter not found".
110            let mut combined_members_by_id = self.members_by_member_id();
111            for member in &delta.added {
112                combined_members_by_id
113                    .entry(member.member.id())
114                    .or_insert(member);
115            }
116
117            // Verify that all new members have valid invites
118            for member in &delta.added {
119                self.verify_member_invite_with_lookup(member, parameters, &combined_members_by_id)?;
120            }
121
122            // Add ALL new members (deduplicated), let remove_excess_members handle trimming.
123            // This ensures CRDT convergence: regardless of delta order, the same set of
124            // members will be kept based on the deterministic removal criteria.
125            for member in &delta.added {
126                // Skip if this member already exists
127                if self
128                    .members
129                    .iter()
130                    .any(|m| m.member.id() == member.member.id())
131                {
132                    continue;
133                }
134                self.members.push(member.clone());
135            }
136        }
137
138        // Always check for and remove banned members
139        self.remove_banned_members(&parent_state.bans, parameters);
140
141        // Always enforce max members limit
142        self.remove_excess_members(parameters, max_members);
143
144        // Sort for deterministic ordering (CRDT convergence requirement)
145        self.members.sort_by_key(|m| m.member.id());
146
147        Ok(())
148    }
149}
150
151impl MembersV1 {
152    /// Verify a member's invite chain using a pre-built lookup map.
153    /// The lookup map should include both existing members AND delta members
154    /// when called during apply_delta, so that inviters in the same delta
155    /// can be found.
156    fn verify_member_invite_with_lookup(
157        &self,
158        member: &AuthorizedMember,
159        parameters: &ChatRoomParametersV1,
160        members_by_id: &HashMap<MemberId, &AuthorizedMember>,
161    ) -> Result<(), String> {
162        if member.member.invited_by == parameters.owner_id() {
163            // Member was invited by the owner, verify signature against owner's key
164            member
165                .verify_signature(&parameters.owner)
166                .map_err(|e| format!("Invalid signature for member invited by owner: {}", e))?;
167        } else {
168            // Member was invited by another member, verify the invite chain
169            self.get_invite_chain_with_lookup(member, parameters, members_by_id)?;
170        }
171        Ok(())
172    }
173}
174
175impl MembersV1 {
176    /// Returns true if the given member_id invited the target_id, properly handling both
177    /// regular members and the room owner. Use this instead of checking the members list directly.
178    pub fn is_inviter_of(
179        &self,
180        member_id: MemberId,
181        target_id: MemberId,
182        params: &ChatRoomParametersV1,
183    ) -> bool {
184        if member_id == params.owner_id() {
185            // Check if target was invited by owner
186            self.members
187                .iter()
188                .find(|m| m.member.id() == target_id)
189                .map(|m| m.member.invited_by == member_id)
190                .unwrap_or(false)
191        } else {
192            // Check regular members
193            self.members
194                .iter()
195                .find(|m| m.member.id() == target_id)
196                .map(|m| m.member.invited_by == member_id)
197                .unwrap_or(false)
198        }
199    }
200
201    /// Note: doesn't include owner
202    pub fn members_by_member_id(&self) -> HashMap<MemberId, &AuthorizedMember> {
203        self.members.iter().map(|m| (m.member.id(), m)).collect()
204    }
205
206    /// Checks if there are any banned members or members downstream of banned members in the invite chain
207    pub fn has_banned_members(&self, bans_v1: &BansV1, parameters: &ChatRoomParametersV1) -> bool {
208        self.check_banned_members(bans_v1, parameters).is_some()
209    }
210
211    /// Removes banned members or members downstream of banned members in the invite chain
212    fn remove_banned_members(&mut self, bans_v1: &BansV1, _parameters: &ChatRoomParametersV1) {
213        let mut banned_ids = HashSet::new();
214        for ban in &bans_v1.0 {
215            banned_ids.insert(ban.ban.banned_user);
216            banned_ids.extend(self.get_downstream_members(ban.ban.banned_user));
217        }
218        self.members
219            .retain(|m| !banned_ids.contains(&m.member.id()));
220    }
221
222    /// Helper function to get all downstream members of a given member
223    fn get_downstream_members(&self, member_id: MemberId) -> HashSet<MemberId> {
224        let mut downstream = HashSet::new();
225        let mut to_check = vec![member_id];
226        while let Some(current) = to_check.pop() {
227            for member in &self.members {
228                if member.member.invited_by == current {
229                    downstream.insert(member.member.id());
230                    to_check.push(member.member.id());
231                }
232            }
233        }
234        downstream
235    }
236
237    /// If the number of members exceeds the specified limit, remove the members with the longest invite chains
238    /// until the limit is satisfied. When chain lengths are equal, remove the member with the highest MemberId
239    /// for deterministic ordering (CRDT convergence requirement).
240    fn remove_excess_members(&mut self, parameters: &ChatRoomParametersV1, max_members: usize) {
241        if self.members.len() <= max_members {
242            return;
243        }
244
245        let members_by_id = self.members_by_member_id();
246        let owner_id = parameters.owner_id();
247
248        // Pre-compute chain lengths once for all members (no Ed25519 verification needed)
249        let mut chain_lengths: Vec<(MemberId, usize)> = self
250            .members
251            .iter()
252            .map(|m| {
253                let len = Self::invite_chain_length(m, owner_id, &members_by_id);
254                (m.member.id(), len)
255            })
256            .collect();
257
258        // Sort by chain length descending, then by MemberId descending for deterministic tie-breaking
259        chain_lengths.sort_by(|a, b| b.1.cmp(&a.1).then_with(|| b.0.cmp(&a.0)));
260
261        // Collect IDs to remove
262        let excess = self.members.len() - max_members;
263        let ids_to_remove: HashSet<MemberId> = chain_lengths
264            .iter()
265            .take(excess)
266            .map(|(id, _)| *id)
267            .collect();
268
269        self.members
270            .retain(|m| !ids_to_remove.contains(&m.member.id()));
271    }
272
273    /// Checks for banned members and returns a set of member IDs to be removed if any are found.
274    /// Uses chain walking without Ed25519 verification since we only need to check membership,
275    /// not cryptographic validity.
276    fn check_banned_members(
277        &self,
278        bans_v1: &BansV1,
279        parameters: &ChatRoomParametersV1,
280    ) -> Option<HashSet<MemberId>> {
281        let banned_user_ids: HashSet<MemberId> =
282            bans_v1.0.iter().map(|b| b.ban.banned_user).collect();
283        if banned_user_ids.is_empty() {
284            return None;
285        }
286
287        let members_by_id = self.members_by_member_id();
288        let owner_id = parameters.owner_id();
289        let mut result = HashSet::new();
290
291        for m in &self.members {
292            // Walk the invite chain without Ed25519 verification
293            let chain_ids = Self::invite_chain_ids(m, owner_id, &members_by_id);
294            if chain_ids.iter().any(|id| banned_user_ids.contains(id)) {
295                result.insert(m.member.id());
296            }
297        }
298
299        if result.is_empty() {
300            None
301        } else {
302            Some(result)
303        }
304    }
305
306    /// Get the full invite chain with Ed25519 signature verification at each link.
307    /// This is the authoritative verification used by `verify()`.
308    pub fn get_invite_chain(
309        &self,
310        member: &AuthorizedMember,
311        parameters: &ChatRoomParametersV1,
312    ) -> Result<Vec<AuthorizedMember>, String> {
313        let members_by_id = self.members_by_member_id();
314        self.get_invite_chain_with_lookup(member, parameters, &members_by_id)
315    }
316
317    /// Get the full invite chain with Ed25519 signature verification, using a pre-built
318    /// HashMap for O(1) member lookups instead of linear scans.
319    fn get_invite_chain_with_lookup(
320        &self,
321        member: &AuthorizedMember,
322        parameters: &ChatRoomParametersV1,
323        members_by_id: &HashMap<MemberId, &AuthorizedMember>,
324    ) -> Result<Vec<AuthorizedMember>, String> {
325        let mut invite_chain = Vec::new();
326        let mut current_member = member;
327        let owner_id = parameters.owner_id();
328        let mut visited_members = HashSet::new();
329
330        loop {
331            if !visited_members.insert(current_member.member.id()) {
332                return Err(format!(
333                    "Circular invite chain detected for member {:?}",
334                    current_member.member.id()
335                ));
336            }
337
338            if current_member.member.invited_by == current_member.member.id() {
339                return Err(format!(
340                    "Self-invitation detected for member {:?}",
341                    current_member.member.id()
342                ));
343            }
344
345            if current_member.member.invited_by == owner_id {
346                current_member
347                    .verify_signature(&parameters.owner)
348                    .map_err(|e| {
349                        format!(
350                            "Invalid signature for member {:?} invited by owner: {}",
351                            current_member.member.id(),
352                            e
353                        )
354                    })?;
355                break;
356            } else {
357                let inviter = members_by_id
358                    .get(&current_member.member.invited_by)
359                    .ok_or_else(|| {
360                        format!(
361                            "Inviter {:?} not found for member {:?}",
362                            current_member.member.invited_by,
363                            current_member.member.id()
364                        )
365                    })?;
366
367                current_member
368                    .verify_signature(&inviter.member.member_vk)
369                    .map_err(|e| {
370                        format!(
371                            "Invalid signature for member {:?}: {}",
372                            current_member.member.id(),
373                            e
374                        )
375                    })?;
376
377                invite_chain.push((*inviter).clone());
378                current_member = inviter;
379            }
380        }
381
382        Ok(invite_chain)
383    }
384
385    /// Walk the invite chain and return the length WITHOUT Ed25519 signature verification.
386    /// Used by `remove_excess_members` where we only need chain length for comparison.
387    fn invite_chain_length(
388        member: &AuthorizedMember,
389        owner_id: MemberId,
390        members_by_id: &HashMap<MemberId, &AuthorizedMember>,
391    ) -> usize {
392        let mut length = 0;
393        let mut current_id = member.member.invited_by;
394        let mut visited = HashSet::new();
395        visited.insert(member.member.id());
396
397        while current_id != owner_id {
398            if !visited.insert(current_id) {
399                break; // Circular chain — will be caught by verify()
400            }
401            length += 1;
402            match members_by_id.get(&current_id) {
403                Some(inviter) => current_id = inviter.member.invited_by,
404                None => break, // Missing inviter — will be caught by verify()
405            }
406        }
407        length
408    }
409
410    /// Walk the invite chain and return all member IDs in the chain WITHOUT Ed25519 verification.
411    /// Used by `check_banned_members` where we only need to check if any chain member is banned.
412    fn invite_chain_ids(
413        member: &AuthorizedMember,
414        owner_id: MemberId,
415        members_by_id: &HashMap<MemberId, &AuthorizedMember>,
416    ) -> Vec<MemberId> {
417        let mut chain_ids = vec![member.member.id()];
418        let mut current_id = member.member.invited_by;
419        let mut visited = HashSet::new();
420        visited.insert(member.member.id());
421
422        while current_id != owner_id {
423            if !visited.insert(current_id) {
424                break;
425            }
426            chain_ids.push(current_id);
427            match members_by_id.get(&current_id) {
428                Some(inviter) => current_id = inviter.member.invited_by,
429                None => break,
430            }
431        }
432        chain_ids
433    }
434}
435
436#[derive(Serialize, Deserialize, Eq, PartialEq, Clone, Debug)]
437pub struct MembersDelta {
438    added: Vec<AuthorizedMember>,
439}
440
441impl MembersDelta {
442    pub fn new(added: Vec<AuthorizedMember>) -> Self {
443        MembersDelta { added }
444    }
445
446    pub fn added(&self) -> &[AuthorizedMember] {
447        &self.added
448    }
449
450    pub fn into_added(self) -> Vec<AuthorizedMember> {
451        self.added
452    }
453}
454
455// TODO: need to generalize to support multiple authorization mechanisms such as ghost keys
456
457#[derive(Serialize, Deserialize, Eq, PartialEq, Clone, Debug)]
458pub struct AuthorizedMember {
459    pub member: Member,
460    pub signature: Signature,
461}
462
463impl AuthorizedMember {
464    pub fn new(member: Member, inviter_signing_key: &SigningKey) -> Self {
465        assert_eq!(
466            member.invited_by,
467            VerifyingKey::from(inviter_signing_key).into(),
468            "The member's invited_by must match the inviter's signing key"
469        );
470        Self {
471            member: member.clone(),
472            signature: sign_struct(&member, inviter_signing_key),
473        }
474    }
475
476    /// Create an AuthorizedMember with a pre-computed signature.
477    /// Use this when signing is done externally (e.g., via delegate).
478    pub fn with_signature(member: Member, signature: Signature) -> Self {
479        Self { member, signature }
480    }
481
482    pub fn verify_signature(&self, inviter_vk: &VerifyingKey) -> Result<(), String> {
483        verify_struct(&self.member, &self.signature, inviter_vk)
484            .map_err(|e| format!("Invalid signature: {}", e))
485    }
486}
487
488impl Hash for AuthorizedMember {
489    fn hash<H: Hasher>(&self, state: &mut H) {
490        self.member.hash(state);
491    }
492}
493
494#[derive(Serialize, Deserialize, Eq, PartialEq, Hash, Clone)]
495pub struct Member {
496    pub owner_member_id: MemberId,
497    pub invited_by: MemberId,
498    pub member_vk: VerifyingKey,
499}
500
501impl fmt::Debug for Member {
502    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
503        f.debug_struct("Member")
504            .field(
505                "public_key",
506                &format_args!("{}", truncated_base32(self.member_vk.as_bytes())),
507            )
508            .finish()
509    }
510}
511
512/*
513Finding a VerifyingKey that would have a MemberId collision would require approximately
5143 * 10^59 years on current hardware.
515*/
516#[derive(Eq, PartialEq, Hash, Serialize, Deserialize, Clone, Ord, PartialOrd, Copy)]
517pub struct MemberId(pub FastHash);
518
519impl Display for MemberId {
520    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
521        write!(f, "{}", truncated_base32(&self.0 .0.to_le_bytes()))
522    }
523}
524
525impl Debug for MemberId {
526    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
527        write!(
528            f,
529            "MemberId({})",
530            truncated_base32(&self.0 .0.to_le_bytes())
531        )
532    }
533}
534
535impl From<&VerifyingKey> for MemberId {
536    fn from(vk: &VerifyingKey) -> Self {
537        MemberId(fast_hash(&vk.to_bytes()))
538    }
539}
540
541impl From<VerifyingKey> for MemberId {
542    fn from(vk: VerifyingKey) -> Self {
543        MemberId(fast_hash(&vk.to_bytes()))
544    }
545}
546
547impl Member {
548    pub fn id(&self) -> MemberId {
549        self.member_vk.into()
550    }
551}
552
553#[cfg(test)]
554mod tests {
555    use super::*;
556    use crate::room_state::ban::{AuthorizedUserBan, UserBan};
557    use ed25519_dalek::SigningKey;
558    use rand::rngs::OsRng;
559    use std::time::SystemTime;
560
561    fn create_test_member(owner_id: MemberId, invited_by: MemberId) -> (Member, SigningKey) {
562        let signing_key = SigningKey::generate(&mut OsRng);
563        let verifying_key = signing_key.verifying_key();
564        let member = Member {
565            owner_member_id: owner_id,
566            invited_by,
567            member_vk: verifying_key,
568        };
569        (member, signing_key)
570    }
571
572    #[test]
573    fn test_members_verify() {
574        let owner_signing_key = SigningKey::generate(&mut OsRng);
575        let owner_verifying_key = VerifyingKey::from(&owner_signing_key);
576        let owner_id = owner_verifying_key.into();
577
578        let (member1, member1_signing_key) = create_test_member(owner_id, owner_id);
579        let (member2, _) = create_test_member(owner_id, member1.id());
580
581        let authorized_member1 = AuthorizedMember::new(member1.clone(), &owner_signing_key);
582        let authorized_member2 = AuthorizedMember::new(member2.clone(), &member1_signing_key);
583
584        let members = MembersV1 {
585            members: vec![authorized_member1.clone(), authorized_member2.clone()],
586        };
587
588        println!("Member1 ID: {:?}", member1.id());
589        println!("Member2 ID: {:?}", member2.id());
590        println!("Owner ID: {:?}", owner_id);
591
592        let mut parent_state = ChatRoomStateV1::default();
593        parent_state.configuration.configuration.max_members = 3;
594        let parameters = ChatRoomParametersV1 {
595            owner: owner_verifying_key,
596        };
597
598        let result = members.verify(&parent_state, &parameters);
599        println!("Verification result: {:?}", result);
600        assert!(result.is_ok(), "Verification failed: {:?}", result);
601
602        // Test that including the owner in the members list fails verification
603        let owner_member = Member {
604            owner_member_id: owner_id,
605            invited_by: owner_id,
606            member_vk: owner_verifying_key,
607        };
608        let authorized_owner = AuthorizedMember::new(owner_member, &owner_signing_key);
609        let members_with_owner = MembersV1 {
610            members: vec![authorized_owner, authorized_member1, authorized_member2],
611        };
612        let result_with_owner = members_with_owner.verify(&parent_state, &parameters);
613        println!("Verification result with owner: {:?}", result_with_owner);
614        assert!(
615            result_with_owner.is_err(),
616            "Verification should fail when owner is included: {:?}",
617            result_with_owner
618        );
619    }
620
621    #[test]
622    fn test_members_summarize() {
623        let owner_signing_key = SigningKey::generate(&mut OsRng);
624        let owner_verifying_key = VerifyingKey::from(&owner_signing_key);
625        let owner_id = owner_verifying_key.into();
626
627        let (member1, member1_signing_key) = create_test_member(owner_id, owner_id);
628        let (member2, _) = create_test_member(owner_id, member1.id());
629
630        let authorized_member1 = AuthorizedMember::new(member1.clone(), &owner_signing_key);
631        let authorized_member2 = AuthorizedMember::new(member2.clone(), &member1_signing_key);
632
633        let members = MembersV1 {
634            members: vec![authorized_member1, authorized_member2],
635        };
636
637        let parent_state = ChatRoomStateV1::default();
638        let parameters = ChatRoomParametersV1 {
639            owner: owner_verifying_key,
640        };
641
642        let summary = members.summarize(&parent_state, &parameters);
643        assert_eq!(summary.len(), 2);
644        assert!(summary.contains(&member1.id()));
645        assert!(summary.contains(&member2.id()));
646    }
647
648    #[test]
649    fn test_members_delta() {
650        let owner_signing_key = SigningKey::generate(&mut OsRng);
651        let owner_verifying_key = VerifyingKey::from(&owner_signing_key);
652        let owner_id = owner_verifying_key.into();
653
654        let (member1, member1_signing_key) = create_test_member(owner_id, owner_id);
655        let (member2, _) = create_test_member(owner_id, member1.id());
656        let (member3, _) = create_test_member(owner_id, member1.id());
657
658        let authorized_member1 = AuthorizedMember::new(member1.clone(), &owner_signing_key);
659        let authorized_member2 = AuthorizedMember::new(member2.clone(), &member1_signing_key);
660        let authorized_member3 = AuthorizedMember::new(member3.clone(), &member1_signing_key);
661
662        let old_members = MembersV1 {
663            members: vec![authorized_member1.clone(), authorized_member2.clone()],
664        };
665
666        let new_members = MembersV1 {
667            members: vec![authorized_member1.clone(), authorized_member3.clone()],
668        };
669
670        let parent_state = ChatRoomStateV1::default();
671        let parameters = ChatRoomParametersV1 {
672            owner: owner_verifying_key,
673        };
674
675        let old_summary = old_members.summarize(&parent_state, &parameters);
676        let delta = new_members
677            .delta(&parent_state, &parameters, &old_summary)
678            .unwrap();
679
680        assert_eq!(delta.added.len(), 1);
681        assert_eq!(delta.added[0].member.id(), member3.id());
682    }
683
684    #[test]
685    fn test_members_apply_delta_simple() {
686        let owner_signing_key = SigningKey::generate(&mut OsRng);
687        let owner_verifying_key = VerifyingKey::from(&owner_signing_key);
688        let owner_id = owner_verifying_key.into();
689
690        let (member1, member1_signing_key) = create_test_member(owner_id, owner_id);
691        let (member2, _) = create_test_member(owner_id, member1.id());
692        let (member3, _) = create_test_member(owner_id, member1.id());
693
694        let authorized_member1 = AuthorizedMember::new(member1.clone(), &owner_signing_key);
695        let authorized_member2 = AuthorizedMember::new(member2.clone(), &member1_signing_key);
696        let authorized_member3 = AuthorizedMember::new(member3.clone(), &member1_signing_key);
697
698        let original_members = MembersV1 {
699            members: vec![authorized_member1.clone(), authorized_member2.clone()],
700        };
701
702        let delta = MembersDelta {
703            added: vec![authorized_member3.clone()],
704        };
705
706        let mut parent_state = ChatRoomStateV1::default();
707        parent_state.configuration.configuration.max_members = 3;
708
709        let parameters = ChatRoomParametersV1 {
710            owner: owner_verifying_key,
711        };
712
713        let mut modified_members = original_members.clone();
714
715        assert!(modified_members
716            .apply_delta(&parent_state, &parameters, &Some(delta))
717            .is_ok());
718
719        assert_eq!(modified_members.members.len(), 3);
720        assert!(modified_members
721            .members
722            .iter()
723            .any(|m| m.member.id() == member1.id()));
724        assert!(modified_members
725            .members
726            .iter()
727            .any(|m| m.member.id() == member3.id()));
728        assert!(modified_members
729            .members
730            .iter()
731            .any(|m| m.member.id() == member2.id()));
732    }
733
734    #[test]
735    fn test_authorized_member_validate() {
736        let owner_signing_key = SigningKey::generate(&mut OsRng);
737        let owner_verifying_key = VerifyingKey::from(&owner_signing_key);
738        let owner_id = owner_verifying_key.into();
739
740        let (member1, member1_signing_key) = create_test_member(owner_id, owner_id);
741        let (member2, _) = create_test_member(owner_id, member1.id());
742
743        let authorized_member1 = AuthorizedMember::new(member1.clone(), &owner_signing_key);
744        let authorized_member2 = AuthorizedMember::new(member2.clone(), &member1_signing_key);
745
746        assert!(authorized_member1
747            .verify_signature(&owner_verifying_key)
748            .is_ok());
749        assert!(authorized_member2
750            .verify_signature(&member1.member_vk)
751            .is_ok());
752
753        // Test with invalid signature
754        let invalid_member2 = AuthorizedMember {
755            member: member2.clone(),
756            signature: Signature::from_bytes(&[0; 64]),
757        };
758        assert!(invalid_member2
759            .verify_signature(&member1.member_vk)
760            .is_err());
761    }
762
763    #[test]
764    fn test_member_id() {
765        let owner_id = MemberId(FastHash(0));
766        let (member, _) = create_test_member(owner_id, owner_id);
767        let member_id = member.id();
768
769        assert_eq!(member_id, member.member_vk.into());
770    }
771
772    #[test]
773    fn test_verify_self_invited_member() {
774        let owner_signing_key = SigningKey::generate(&mut OsRng);
775        let owner_verifying_key = VerifyingKey::from(&owner_signing_key);
776        let owner_id = owner_verifying_key.into();
777
778        let (mut member, member_signing_key) = create_test_member(owner_id, owner_id);
779        member.invited_by = member.id(); // Self-invite
780
781        let authorized_member = AuthorizedMember::new(member, &member_signing_key);
782
783        let members = MembersV1 {
784            members: vec![authorized_member],
785        };
786
787        let parent_state = ChatRoomStateV1::default();
788        let parameters = ChatRoomParametersV1 {
789            owner: owner_verifying_key,
790        };
791
792        let result = members.verify(&parent_state, &parameters);
793        assert!(result.is_err());
794        assert!(result.unwrap_err().contains("Self-invitation detected"));
795    }
796
797    #[test]
798    fn test_verify_circular_invite_chain() {
799        let owner_signing_key = SigningKey::generate(&mut OsRng);
800        let owner_verifying_key = VerifyingKey::from(&owner_signing_key);
801        let owner_id = owner_verifying_key.into();
802
803        let (mut member1, member1_signing_key) = create_test_member(owner_id, owner_id);
804        let (member2, member2_signing_key) = create_test_member(owner_id, member1.id());
805        let (member3, member3_signing_key) = create_test_member(owner_id, member2.id());
806        member1.invited_by = member3.id(); // Create a circular chain
807
808        let authorized_member1 = AuthorizedMember::new(member1, &member3_signing_key);
809        let authorized_member2 = AuthorizedMember::new(member2, &member1_signing_key);
810        let authorized_member3 = AuthorizedMember::new(member3, &member2_signing_key);
811
812        let members = MembersV1 {
813            members: vec![authorized_member1, authorized_member2, authorized_member3],
814        };
815
816        let parent_state = ChatRoomStateV1::default();
817        let parameters = ChatRoomParametersV1 {
818            owner: owner_verifying_key,
819        };
820
821        let result = members.verify(&parent_state, &parameters);
822        assert!(result.is_err());
823        assert!(result
824            .unwrap_err()
825            .contains("Circular invite chain detected"));
826    }
827
828    #[test]
829    fn test_check_invite_chain() {
830        let owner_signing_key = SigningKey::generate(&mut OsRng);
831        let owner_verifying_key = VerifyingKey::from(&owner_signing_key);
832        let owner_id = owner_verifying_key.into();
833
834        // Test case 1: Valid invite chain
835        let (member1, member1_signing_key) = create_test_member(owner_id, owner_id);
836        let (member2, member2_signing_key) = create_test_member(owner_id, member1.id());
837        let (member3, _) = create_test_member(owner_id, member2.id());
838
839        let authorized_member1 = AuthorizedMember::new(member1.clone(), &owner_signing_key);
840        let authorized_member2 = AuthorizedMember::new(member2, &member1_signing_key);
841        let authorized_member3 = AuthorizedMember::new(member3, &member2_signing_key);
842
843        let members = MembersV1 {
844            members: vec![authorized_member1, authorized_member2.clone()],
845        };
846
847        let parameters = ChatRoomParametersV1 {
848            owner: owner_verifying_key,
849        };
850
851        let result = members.get_invite_chain(&authorized_member3, &parameters);
852        assert!(result.is_ok());
853        assert_eq!(result.unwrap().len(), 2);
854
855        // Test case 2: Circular invite chain
856        let (mut circular_member1, circular_member1_signing_key) =
857            create_test_member(owner_id, owner_id);
858        let (circular_member2, circular_member2_signing_key) =
859            create_test_member(owner_id, circular_member1.id());
860        circular_member1.invited_by = circular_member2.id();
861
862        let circular_authorized_member1 =
863            AuthorizedMember::new(circular_member1, &circular_member2_signing_key);
864        let circular_authorized_member2 =
865            AuthorizedMember::new(circular_member2, &circular_member1_signing_key);
866
867        let circular_members = MembersV1 {
868            members: vec![
869                circular_authorized_member1.clone(),
870                circular_authorized_member2,
871            ],
872        };
873
874        let result = circular_members.get_invite_chain(&circular_authorized_member1, &parameters);
875        assert!(result.is_err());
876        assert!(result
877            .clone()
878            .unwrap_err()
879            .contains("Circular invite chain detected"));
880
881        // Test case 3: Missing inviter
882        let non_existent_inviter_id = MemberId(FastHash(999));
883        let (orphan_member, _) = create_test_member(owner_id, non_existent_inviter_id);
884        let orphan_authorized_member = AuthorizedMember {
885            member: orphan_member,
886            signature: Signature::from_bytes(&[0; 64]), // Use a dummy signature
887        };
888
889        let result = members.get_invite_chain(&orphan_authorized_member, &parameters);
890        assert!(result.is_err());
891        let err = result.unwrap_err();
892        assert!(err.contains("Inviter"), "Error message: {}", err);
893        assert!(err.contains("not found"), "Error message: {}", err);
894
895        // Test case 4: Invalid signature
896        let (invalid_member, _) = create_test_member(owner_id, member1.id());
897        let invalid_authorized_member = AuthorizedMember {
898            member: invalid_member,
899            signature: Signature::from_bytes(&[0; 64]),
900        };
901
902        let result = members.get_invite_chain(&invalid_authorized_member, &parameters);
903        assert!(result.is_err());
904        assert!(result.unwrap_err().contains("Invalid signature"));
905    }
906
907    #[test]
908    fn test_has_banned_members() {
909        let owner_signing_key = SigningKey::generate(&mut OsRng);
910        let owner_verifying_key = VerifyingKey::from(&owner_signing_key);
911        let owner_id = owner_verifying_key.into();
912
913        let (member1, member1_signing_key) = create_test_member(owner_id, owner_id);
914        let (member2, member2_signing_key) = create_test_member(owner_id, member1.id());
915        let (member3, _) = create_test_member(owner_id, member2.id());
916
917        let authorized_member1 = AuthorizedMember::new(member1.clone(), &owner_signing_key);
918        let authorized_member2 = AuthorizedMember::new(member2.clone(), &member1_signing_key);
919        let authorized_member3 = AuthorizedMember::new(member3.clone(), &member2_signing_key);
920
921        let members = MembersV1 {
922            members: vec![authorized_member1, authorized_member2, authorized_member3],
923        };
924
925        let parameters = ChatRoomParametersV1 {
926            owner: owner_verifying_key,
927        };
928
929        // Test case 1: No banned members
930        let empty_bans = BansV1(vec![]);
931        assert!(!members.has_banned_members(&empty_bans, &parameters));
932
933        // Test case 2: One banned member
934        let banned_member = UserBan {
935            owner_member_id: owner_id,
936            banned_at: SystemTime::now(),
937            banned_user: member2.id(),
938        };
939        let authorized_ban = AuthorizedUserBan::new(banned_member, owner_id, &owner_signing_key);
940        let bans = BansV1(vec![authorized_ban]);
941        assert!(members.has_banned_members(&bans, &parameters));
942    }
943
944    #[test]
945    fn test_remove_banned_members() {
946        let owner_signing_key = SigningKey::generate(&mut OsRng);
947        let owner_verifying_key = VerifyingKey::from(&owner_signing_key);
948        let owner_id = owner_verifying_key.into();
949
950        let (member1, member1_signing_key) = create_test_member(owner_id, owner_id);
951        let (member2, member2_signing_key) = create_test_member(owner_id, member1.id());
952        let (member3, _) = create_test_member(owner_id, member2.id());
953        let (member4, _) = create_test_member(owner_id, member1.id());
954
955        let authorized_member1 = AuthorizedMember::new(member1.clone(), &owner_signing_key);
956        let authorized_member2 = AuthorizedMember::new(member2.clone(), &member1_signing_key);
957        let authorized_member3 = AuthorizedMember::new(member3.clone(), &member2_signing_key);
958        let authorized_member4 = AuthorizedMember::new(member4.clone(), &member1_signing_key);
959
960        let mut members = MembersV1 {
961            members: vec![
962                authorized_member1.clone(),
963                authorized_member2.clone(),
964                authorized_member3.clone(),
965                authorized_member4.clone(),
966            ],
967        };
968
969        let parameters = ChatRoomParametersV1 {
970            owner: owner_verifying_key,
971        };
972
973        // Test case 1: No banned members
974        let empty_bans = BansV1(vec![]);
975        members.remove_banned_members(&empty_bans, &parameters);
976        assert_eq!(members.members.len(), 4);
977
978        // Test case 2: One banned member
979        let banned_member = UserBan {
980            owner_member_id: owner_id,
981            banned_at: SystemTime::now(),
982            banned_user: member2.id(),
983        };
984        let authorized_ban = AuthorizedUserBan::new(banned_member, owner_id, &owner_signing_key);
985        let bans = BansV1(vec![authorized_ban]);
986        members.remove_banned_members(&bans, &parameters);
987        assert_eq!(members.members.len(), 2);
988        assert!(members
989            .members
990            .iter()
991            .any(|m| m.member.id() == member1.id()));
992        assert!(members
993            .members
994            .iter()
995            .any(|m| m.member.id() == member4.id()));
996        assert!(!members
997            .members
998            .iter()
999            .any(|m| m.member.id() == member2.id()));
1000        assert!(!members
1001            .members
1002            .iter()
1003            .any(|m| m.member.id() == member3.id()));
1004
1005        // Test case 3: Banning a member with no downstream members
1006        members = MembersV1 {
1007            members: vec![
1008                authorized_member1,
1009                authorized_member2,
1010                authorized_member3,
1011                authorized_member4,
1012            ],
1013        };
1014        let banned_member = UserBan {
1015            owner_member_id: owner_id,
1016            banned_at: SystemTime::now(),
1017            banned_user: member4.id(),
1018        };
1019        let authorized_ban = AuthorizedUserBan::new(banned_member, owner_id, &owner_signing_key);
1020        let bans = BansV1(vec![authorized_ban]);
1021        members.remove_banned_members(&bans, &parameters);
1022        assert_eq!(members.members.len(), 3);
1023        assert!(members
1024            .members
1025            .iter()
1026            .any(|m| m.member.id() == member1.id()));
1027        assert!(members
1028            .members
1029            .iter()
1030            .any(|m| m.member.id() == member2.id()));
1031        assert!(members
1032            .members
1033            .iter()
1034            .any(|m| m.member.id() == member3.id()));
1035        assert!(!members
1036            .members
1037            .iter()
1038            .any(|m| m.member.id() == member4.id()));
1039    }
1040
1041    #[test]
1042    fn test_remove_excess_members() {
1043        let owner_signing_key = SigningKey::generate(&mut OsRng);
1044        let owner_verifying_key = VerifyingKey::from(&owner_signing_key);
1045        let owner_id = owner_verifying_key.into();
1046
1047        let (member1, member1_signing_key) = create_test_member(owner_id, owner_id);
1048        let (member2, member2_signing_key) = create_test_member(owner_id, member1.id());
1049        let (member3, _) = create_test_member(owner_id, member2.id());
1050
1051        let authorized_member1 = AuthorizedMember::new(member1.clone(), &owner_signing_key);
1052        let authorized_member2 = AuthorizedMember::new(member2.clone(), &member1_signing_key);
1053        let authorized_member3 = AuthorizedMember::new(member3.clone(), &member2_signing_key);
1054
1055        let mut members = MembersV1 {
1056            members: vec![authorized_member1, authorized_member2, authorized_member3],
1057        };
1058
1059        let parameters = ChatRoomParametersV1 {
1060            owner: owner_verifying_key,
1061        };
1062
1063        // Test case 1: No excess members
1064        members.remove_excess_members(&parameters, 3);
1065        assert_eq!(members.members.len(), 3);
1066
1067        // Test case 2: One excess member
1068        members.remove_excess_members(&parameters, 2);
1069        assert_eq!(members.members.len(), 2);
1070        assert!(members
1071            .members
1072            .iter()
1073            .any(|m| m.member.id() == member1.id()));
1074        assert!(members
1075            .members
1076            .iter()
1077            .any(|m| m.member.id() == member2.id()));
1078        assert!(!members
1079            .members
1080            .iter()
1081            .any(|m| m.member.id() == member3.id()));
1082    }
1083
1084    #[test]
1085    fn test_members_by_member_id() {
1086        let owner_signing_key = SigningKey::generate(&mut OsRng);
1087        let owner_verifying_key = VerifyingKey::from(&owner_signing_key);
1088        let owner_id = owner_verifying_key.into();
1089
1090        let (member1, member1_signing_key) = create_test_member(owner_id, owner_id);
1091        let (member2, _) = create_test_member(owner_id, member1.id());
1092
1093        let authorized_member1 = AuthorizedMember::new(member1.clone(), &owner_signing_key);
1094        let authorized_member2 = AuthorizedMember::new(member2.clone(), &member1_signing_key);
1095
1096        let members = MembersV1 {
1097            members: vec![authorized_member1.clone(), authorized_member2.clone()],
1098        };
1099
1100        let members_map = members.members_by_member_id();
1101
1102        assert_eq!(members_map.len(), 2);
1103        assert_eq!(
1104            members_map.get(&member1.id()).unwrap().member.id(),
1105            member1.id()
1106        );
1107        assert_eq!(
1108            members_map.get(&member2.id()).unwrap().member.id(),
1109            member2.id()
1110        );
1111    }
1112
1113    #[test]
1114    fn test_invite_chain_length() {
1115        let owner_signing_key = SigningKey::generate(&mut OsRng);
1116        let owner_verifying_key = VerifyingKey::from(&owner_signing_key);
1117        let owner_id: MemberId = owner_verifying_key.into();
1118
1119        // Build a chain: owner -> m1 -> m2 -> m3
1120        let (member1, member1_signing_key) = create_test_member(owner_id, owner_id);
1121        let (member2, member2_signing_key) = create_test_member(owner_id, member1.id());
1122        let (member3, _) = create_test_member(owner_id, member2.id());
1123
1124        let auth_m1 = AuthorizedMember::new(member1.clone(), &owner_signing_key);
1125        let auth_m2 = AuthorizedMember::new(member2.clone(), &member1_signing_key);
1126        let auth_m3 = AuthorizedMember::new(member3.clone(), &member2_signing_key);
1127
1128        let members = MembersV1 {
1129            members: vec![auth_m1.clone(), auth_m2.clone(), auth_m3.clone()],
1130        };
1131        let members_by_id = members.members_by_member_id();
1132
1133        // Depth 0: member directly invited by owner
1134        assert_eq!(
1135            MembersV1::invite_chain_length(&auth_m1, owner_id, &members_by_id),
1136            0
1137        );
1138        // Depth 1: one hop from owner
1139        assert_eq!(
1140            MembersV1::invite_chain_length(&auth_m2, owner_id, &members_by_id),
1141            1
1142        );
1143        // Depth 2: two hops from owner
1144        assert_eq!(
1145            MembersV1::invite_chain_length(&auth_m3, owner_id, &members_by_id),
1146            2
1147        );
1148    }
1149
1150    #[test]
1151    fn test_invite_chain_ids() {
1152        let owner_signing_key = SigningKey::generate(&mut OsRng);
1153        let owner_verifying_key = VerifyingKey::from(&owner_signing_key);
1154        let owner_id: MemberId = owner_verifying_key.into();
1155
1156        // Build a chain: owner -> m1 -> m2 -> m3
1157        let (member1, member1_signing_key) = create_test_member(owner_id, owner_id);
1158        let (member2, member2_signing_key) = create_test_member(owner_id, member1.id());
1159        let (member3, _) = create_test_member(owner_id, member2.id());
1160
1161        let auth_m1 = AuthorizedMember::new(member1.clone(), &owner_signing_key);
1162        let auth_m2 = AuthorizedMember::new(member2.clone(), &member1_signing_key);
1163        let auth_m3 = AuthorizedMember::new(member3.clone(), &member2_signing_key);
1164
1165        let members = MembersV1 {
1166            members: vec![auth_m1.clone(), auth_m2.clone(), auth_m3.clone()],
1167        };
1168        let members_by_id = members.members_by_member_id();
1169
1170        // m1 (depth 0): chain is just [m1] (no ancestors other than owner)
1171        let ids = MembersV1::invite_chain_ids(&auth_m1, owner_id, &members_by_id);
1172        assert_eq!(ids, vec![member1.id()]);
1173
1174        // m2 (depth 1): chain is [m2, m1]
1175        let ids = MembersV1::invite_chain_ids(&auth_m2, owner_id, &members_by_id);
1176        assert_eq!(ids, vec![member2.id(), member1.id()]);
1177
1178        // m3 (depth 2): chain is [m3, m2, m1]
1179        let ids = MembersV1::invite_chain_ids(&auth_m3, owner_id, &members_by_id);
1180        assert_eq!(ids, vec![member3.id(), member2.id(), member1.id()]);
1181    }
1182
1183    #[test]
1184    fn test_members_apply_delta_complex() {
1185        let owner_signing_key = SigningKey::generate(&mut OsRng);
1186        let owner_verifying_key = VerifyingKey::from(&owner_signing_key);
1187        let owner_id = owner_verifying_key.into();
1188
1189        let (member1, member1_signing_key) = create_test_member(owner_id, owner_id);
1190        let (member2, _) = create_test_member(owner_id, member1.id());
1191        let (member3, _) = create_test_member(owner_id, member1.id());
1192        let (member4, _) = create_test_member(owner_id, member1.id());
1193
1194        let authorized_member1 = AuthorizedMember::new(member1.clone(), &owner_signing_key);
1195        let authorized_member2 = AuthorizedMember::new(member2.clone(), &member1_signing_key);
1196        let authorized_member3 = AuthorizedMember::new(member3.clone(), &member1_signing_key);
1197        let authorized_member4 = AuthorizedMember::new(member4.clone(), &member1_signing_key);
1198
1199        let mut members = MembersV1 {
1200            members: vec![authorized_member1.clone(), authorized_member2.clone()],
1201        };
1202
1203        let mut parent_state = ChatRoomStateV1::default();
1204        parent_state.configuration.configuration.max_members = 3;
1205
1206        let parameters = ChatRoomParametersV1 {
1207            owner: owner_verifying_key,
1208        };
1209
1210        // Test applying delta that would exceed max_members
1211        // Now ALL members are added first, then excess removed deterministically:
1212        // - member1 has shortest invite chain (invited by owner)
1213        // - member2, member3, member4 all have same chain length (invited by member1)
1214        // - One of member2/3/4 is removed based on highest MemberId (deterministic tie-breaker)
1215        let delta = MembersDelta {
1216            added: vec![authorized_member3.clone(), authorized_member4.clone()],
1217        };
1218
1219        let result = members.apply_delta(&parent_state, &parameters, &Some(delta));
1220        assert!(result.is_ok());
1221        assert_eq!(members.members.len(), 3);
1222        // member1 is always kept (shortest invite chain)
1223        assert!(members
1224            .members
1225            .iter()
1226            .any(|m| m.member.id() == member1.id()));
1227        // Exactly 2 of [member2, member3, member4] are kept
1228        let kept_count = [member2.id(), member3.id(), member4.id()]
1229            .iter()
1230            .filter(|id| members.members.iter().any(|m| m.member.id() == **id))
1231            .count();
1232        assert_eq!(
1233            kept_count, 2,
1234            "Exactly 2 of the 3 equal-chain-length members should be kept"
1235        );
1236
1237        // Test applying delta with already existing member
1238        let delta = MembersDelta {
1239            added: vec![authorized_member2.clone()],
1240        };
1241
1242        let result = members.apply_delta(&parent_state, &parameters, &Some(delta));
1243        assert!(result.is_ok());
1244        assert_eq!(members.members.len(), 3);
1245    }
1246
1247    #[test]
1248    fn test_remove_excess_members_edge_cases() {
1249        let owner_signing_key = SigningKey::generate(&mut OsRng);
1250        let owner_verifying_key = VerifyingKey::from(&owner_signing_key);
1251        let owner_id = owner_verifying_key.into();
1252
1253        let (member1, member1_signing_key) = create_test_member(owner_id, owner_id);
1254        let (member2, _) = create_test_member(owner_id, member1.id());
1255
1256        let authorized_member1 = AuthorizedMember::new(member1.clone(), &owner_signing_key);
1257        let authorized_member2 = AuthorizedMember::new(member2.clone(), &member1_signing_key);
1258
1259        let mut members = MembersV1 {
1260            members: vec![authorized_member1.clone(), authorized_member2.clone()],
1261        };
1262
1263        let parameters = ChatRoomParametersV1 {
1264            owner: owner_verifying_key,
1265        };
1266
1267        // Test with max_members set to 0
1268        members.remove_excess_members(&parameters, 0);
1269        assert_eq!(members.members.len(), 0);
1270
1271        // Reset members
1272        members.members = vec![authorized_member1.clone(), authorized_member2.clone()];
1273
1274        // Test with max_members greater than current number of members
1275        members.remove_excess_members(&parameters, 3);
1276        assert_eq!(members.members.len(), 2);
1277    }
1278
1279    #[test]
1280    #[should_panic(expected = "The member's invited_by must match the inviter's signing key")]
1281    fn test_authorized_member_new_mismatch() {
1282        let owner_signing_key = SigningKey::generate(&mut OsRng);
1283        let owner_verifying_key = VerifyingKey::from(&owner_signing_key);
1284        let owner_id = owner_verifying_key.into();
1285
1286        let (member, _) = create_test_member(owner_id, owner_id);
1287        let wrong_signing_key = SigningKey::generate(&mut OsRng);
1288
1289        AuthorizedMember::new(member, &wrong_signing_key);
1290    }
1291
1292    #[test]
1293    fn test_members_verify_edge_cases() {
1294        let owner_signing_key = SigningKey::generate(&mut OsRng);
1295        let owner_verifying_key = VerifyingKey::from(&owner_signing_key);
1296        let owner_id = owner_verifying_key.into();
1297
1298        let mut parent_state = ChatRoomStateV1::default();
1299        parent_state.configuration.configuration.max_members = 2;
1300
1301        let parameters = ChatRoomParametersV1 {
1302            owner: owner_verifying_key,
1303        };
1304
1305        // Test with empty member list
1306        let empty_members = MembersV1 { members: vec![] };
1307        assert!(empty_members.verify(&parent_state, &parameters).is_ok());
1308
1309        // Test with maximum allowed number of members
1310        let (member1, member1_signing_key) = create_test_member(owner_id, owner_id);
1311        let (member2, _) = create_test_member(owner_id, member1.id());
1312
1313        let authorized_member1 = AuthorizedMember::new(member1.clone(), &owner_signing_key);
1314        let authorized_member2 = AuthorizedMember::new(member2.clone(), &member1_signing_key);
1315
1316        let max_members = MembersV1 {
1317            members: vec![authorized_member1, authorized_member2],
1318        };
1319        assert!(max_members.verify(&parent_state, &parameters).is_ok());
1320
1321        // Test with members invited by non-existent members
1322        let non_existent_signing_key = SigningKey::generate(&mut OsRng);
1323        let non_existent_verifying_key = VerifyingKey::from(&non_existent_signing_key);
1324        let non_existent_id = non_existent_verifying_key.into();
1325        let (invalid_member, _) = create_test_member(owner_id, non_existent_id);
1326        let invalid_authorized_member =
1327            AuthorizedMember::new(invalid_member, &non_existent_signing_key);
1328
1329        let invalid_members = MembersV1 {
1330            members: vec![invalid_authorized_member],
1331        };
1332        assert!(invalid_members.verify(&parent_state, &parameters).is_err());
1333    }
1334
1335    #[test]
1336    fn test_room_owner_key_not_allowed_in_members() {
1337        let owner_signing_key = SigningKey::generate(&mut OsRng);
1338        let owner_verifying_key = VerifyingKey::from(&owner_signing_key);
1339        let owner_id = owner_verifying_key.into();
1340
1341        let owner_member = Member {
1342            owner_member_id: owner_id,
1343            invited_by: owner_id,
1344            member_vk: owner_verifying_key,
1345        };
1346
1347        let authorized_owner_member = AuthorizedMember::new(owner_member, &owner_signing_key);
1348
1349        let members = MembersV1 {
1350            members: vec![authorized_owner_member],
1351        };
1352
1353        let mut parent_state = ChatRoomStateV1::default();
1354        parent_state.configuration.configuration.max_members = 2;
1355
1356        let parameters = ChatRoomParametersV1 {
1357            owner: owner_verifying_key,
1358        };
1359
1360        let result = members.verify(&parent_state, &parameters);
1361        assert!(
1362            result.is_err(),
1363            "Room owner should not be allowed in the members list"
1364        );
1365        assert!(result
1366            .unwrap_err()
1367            .contains("Owner should not be included in the members list"));
1368    }
1369}