/ src / core / api / tests.rs
tests.rs
  1  use super::*;
  2  
  3  use crate::core::{build_key_package_message, create_group, prepare_to_join, process_inbound};
  4  use crate::ds::WELCOME_SUBTOPIC;
  5  use crate::mls_crypto::{MemoryDeMlsStorage, MlsService, parse_wallet_address};
  6  
  7  fn setup_mls(wallet_hex: &str) -> MlsService<MemoryDeMlsStorage> {
  8      let storage = MemoryDeMlsStorage::new();
  9      let mls = MlsService::new(storage);
 10      let wallet = parse_wallet_address(wallet_hex).unwrap();
 11      mls.init(wallet).unwrap();
 12      mls
 13  }
 14  
 15  fn setup_steward(
 16      group_name: &str,
 17      wallet_hex: &str,
 18  ) -> (MlsService<MemoryDeMlsStorage>, GroupHandle) {
 19      let mls = setup_mls(wallet_hex);
 20      let handle = create_group(group_name, &mls).unwrap();
 21      (mls, handle)
 22  }
 23  
 24  fn setup_joiner(
 25      group_name: &str,
 26      wallet_hex: &str,
 27  ) -> (MlsService<MemoryDeMlsStorage>, GroupHandle, OutboundPacket) {
 28      let mls = setup_mls(wallet_hex);
 29      let handle = prepare_to_join(group_name);
 30      let kp_packet = build_key_package_message(&handle, &mls, b"test-app-id").unwrap();
 31      (mls, handle, kp_packet)
 32  }
 33  
 34  fn steward_add_joiner(
 35      steward_mls: &MlsService<MemoryDeMlsStorage>,
 36      steward_handle: &mut GroupHandle,
 37      joiner_kp_packet: &OutboundPacket,
 38  ) -> (OutboundPacket, OutboundPacket) {
 39      use std::sync::atomic::{AtomicU32, Ordering};
 40      static PROPOSAL_COUNTER: AtomicU32 = AtomicU32::new(200);
 41  
 42      let result = process_inbound(
 43          steward_handle,
 44          &joiner_kp_packet.payload,
 45          WELCOME_SUBTOPIC,
 46          steward_mls,
 47      )
 48      .unwrap();
 49  
 50      let gur = match result {
 51          ProcessResult::GetUpdateRequest(gur) => gur,
 52          other => panic!("Expected GetUpdateRequest, got {:?}", other),
 53      };
 54  
 55      let proposal_id = PROPOSAL_COUNTER.fetch_add(1, Ordering::Relaxed);
 56      steward_handle.insert_approved_proposal(proposal_id, gur);
 57      let app_id = b"test-app-id";
 58      let packets = create_commit_candidate(steward_handle, steward_mls, app_id).unwrap();
 59  
 60      let finalize = finalize_freeze_round(steward_handle, steward_mls, false, app_id).unwrap();
 61      let welcome_packet = match finalize {
 62          FreezeFinalizeResult::Applied { result, outbound } => {
 63              assert!(
 64                  matches!(result, ProcessResult::GroupUpdated),
 65                  "Expected GroupUpdated, got {:?}",
 66                  result
 67              );
 68              outbound
 69                  .into_iter()
 70                  .find(|p| p.subtopic == WELCOME_SUBTOPIC)
 71                  .expect("Expected deferred welcome packet from finalize_freeze_round")
 72          }
 73          other => panic!("Expected Applied, got {:?}", other),
 74      };
 75  
 76      let batch_packet = packets
 77          .iter()
 78          .find(|p| p.subtopic == APP_MSG_SUBTOPIC)
 79          .expect("Expected batch proposals packet")
 80          .clone();
 81  
 82      (welcome_packet, batch_packet)
 83  }
 84  
 85  #[test]
 86  fn test_validate_batch_proposals_action_mismatch() {
 87      let group_name = "validate-action-mismatch";
 88      let (steward_mls, mut steward_handle) =
 89          setup_steward(group_name, "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266");
 90      let (joiner_mls, mut joiner_handle, kp_packet) =
 91          setup_joiner(group_name, "0x70997970C51812dc3A010C7d01b50e0d17dc79C8");
 92  
 93      let (welcome_packet, _) = steward_add_joiner(&steward_mls, &mut steward_handle, &kp_packet);
 94      process_inbound(
 95          &mut joiner_handle,
 96          &welcome_packet.payload,
 97          WELCOME_SUBTOPIC,
 98          &joiner_mls,
 99      )
100      .unwrap();
101  
102      let (_joiner2_mls, _joiner2_handle, kp2_packet) =
103          setup_joiner(group_name, "0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC");
104      let result = process_inbound(
105          &mut steward_handle,
106          &kp2_packet.payload,
107          WELCOME_SUBTOPIC,
108          &steward_mls,
109      )
110      .unwrap();
111      let gur = match result {
112          ProcessResult::GetUpdateRequest(gur) => gur,
113          other => panic!("Expected GetUpdateRequest, got {:?}", other),
114      };
115  
116      let proposal_id: ProposalId = 43;
117      joiner_handle.insert_approved_proposal(proposal_id, gur);
118  
119      let steward_id = steward_handle.steward_identity().unwrap().to_vec();
120      let local_proposals = joiner_handle.approved_proposals();
121  
122      // Pass wrong MLS actions (empty) while local has an add proposal
123      let result = validate_commit_candidate(
124          &joiner_handle,
125          &local_proposals,
126          &steward_id,
127          &[], // empty actions, should mismatch
128      )
129      .unwrap();
130  
131      match result {
132          Some(ProcessResult::ViolationDetected(evidence)) => {
133              use crate::protos::de_mls::messages::v1::ViolationType;
134              assert_eq!(
135                  evidence.violation_type,
136                  ViolationType::BrokenMlsProposal as i32
137              );
138          }
139          other => panic!("Expected Some(ViolationDetected), got {:?}", other),
140      }
141  }