1use std::{
16 collections::{BTreeMap, HashMap, HashSet},
17 convert::Infallible,
18 sync::Arc,
19};
20
21use async_trait::async_trait;
22use matrix_sdk_common::{
23 cross_process_lock::{
24 memory_store_helper::{try_take_leased_lock, Lease},
25 CrossProcessLockGeneration,
26 },
27 locks::RwLock as StdRwLock,
28};
29use ruma::{
30 events::secret::request::SecretName, DeviceId, OwnedDeviceId, OwnedRoomId, OwnedTransactionId,
31 OwnedUserId, RoomId, TransactionId, UserId,
32};
33use tokio::sync::{Mutex, RwLock};
34use tracing::warn;
35use vodozemac::Curve25519PublicKey;
36
37use super::{
38 caches::DeviceStore,
39 types::{
40 BackupKeys, Changes, DehydratedDeviceKey, PendingChanges, RoomKeyCounts, RoomSettings,
41 StoredRoomKeyBundleData, TrackedUser,
42 },
43 Account, CryptoStore, InboundGroupSession, Session,
44};
45use crate::{
46 gossiping::{GossipRequest, GossippedSecret, SecretInfo},
47 identities::{DeviceData, UserIdentityData},
48 olm::{
49 OutboundGroupSession, PickledAccount, PickledInboundGroupSession, PickledSession,
50 PrivateCrossSigningIdentity, SenderDataType, StaticAccountData,
51 },
52 store::types::RoomKeyWithheldEntry,
53};
54
55fn encode_key_info(info: &SecretInfo) -> String {
56 match info {
57 SecretInfo::KeyRequest(info) => {
58 format!("{}{}{}", info.room_id(), info.algorithm(), info.session_id())
59 }
60 SecretInfo::SecretRequest(i) => i.as_ref().to_owned(),
61 }
62}
63
64type SessionId = String;
65
66#[derive(Clone, Debug, PartialEq)]
68struct BackupVersion(String);
69
70impl BackupVersion {
71 fn from(s: &str) -> Self {
72 Self(s.to_owned())
73 }
74
75 fn as_str(&self) -> &str {
76 &self.0
77 }
78}
79
80#[derive(Default, Debug)]
82pub struct MemoryStore {
83 static_account: Arc<StdRwLock<Option<StaticAccountData>>>,
84
85 account: StdRwLock<Option<String>>,
86 sessions: StdRwLock<BTreeMap<String, BTreeMap<String, String>>>,
88 inbound_group_sessions: StdRwLock<BTreeMap<OwnedRoomId, HashMap<String, String>>>,
89
90 inbound_group_sessions_backed_up_to:
94 StdRwLock<HashMap<OwnedRoomId, HashMap<SessionId, BackupVersion>>>,
95
96 outbound_group_sessions: StdRwLock<BTreeMap<OwnedRoomId, OutboundGroupSession>>,
97 private_identity: StdRwLock<Option<PrivateCrossSigningIdentity>>,
98 tracked_users: StdRwLock<HashMap<OwnedUserId, TrackedUser>>,
99 olm_hashes: StdRwLock<HashMap<String, HashSet<String>>>,
100 devices: DeviceStore,
101 identities: StdRwLock<HashMap<OwnedUserId, String>>,
102 outgoing_key_requests: StdRwLock<HashMap<OwnedTransactionId, GossipRequest>>,
103 key_requests_by_info: StdRwLock<HashMap<String, OwnedTransactionId>>,
104 direct_withheld_info: StdRwLock<HashMap<OwnedRoomId, HashMap<String, RoomKeyWithheldEntry>>>,
105 custom_values: StdRwLock<HashMap<String, Vec<u8>>>,
106 leases: StdRwLock<HashMap<String, Lease>>,
107 secret_inbox: StdRwLock<HashMap<String, Vec<GossippedSecret>>>,
108 backup_keys: RwLock<BackupKeys>,
109 dehydrated_device_pickle_key: RwLock<Option<DehydratedDeviceKey>>,
110 next_batch_token: RwLock<Option<String>>,
111 room_settings: StdRwLock<HashMap<OwnedRoomId, RoomSettings>>,
112 room_key_bundles:
113 StdRwLock<HashMap<OwnedRoomId, HashMap<OwnedUserId, StoredRoomKeyBundleData>>>,
114
115 save_changes_lock: Arc<Mutex<()>>,
116}
117
118impl MemoryStore {
119 pub fn new() -> Self {
121 Self::default()
122 }
123
124 fn get_static_account(&self) -> Option<StaticAccountData> {
125 self.static_account.read().clone()
126 }
127
128 pub(crate) fn save_devices(&self, devices: Vec<DeviceData>) {
129 for device in devices {
130 let _ = self.devices.add(device);
131 }
132 }
133
134 fn delete_devices(&self, devices: Vec<DeviceData>) {
135 for device in devices {
136 let _ = self.devices.remove(device.user_id(), device.device_id());
137 }
138 }
139
140 fn save_sessions(&self, sessions: Vec<(String, PickledSession)>) {
141 let mut session_store = self.sessions.write();
142
143 for (session_id, pickle) in sessions {
144 let entry = session_store.entry(pickle.sender_key.to_base64()).or_default();
145
146 entry.insert(
148 session_id,
149 serde_json::to_string(&pickle).expect("Failed to serialize olm session"),
150 );
151 }
152 }
153
154 fn save_outbound_group_sessions(&self, sessions: Vec<OutboundGroupSession>) {
155 self.outbound_group_sessions
156 .write()
157 .extend(sessions.into_iter().map(|s| (s.room_id().to_owned(), s)));
158 }
159
160 fn save_private_identity(&self, private_identity: Option<PrivateCrossSigningIdentity>) {
161 *self.private_identity.write() = private_identity;
162 }
163
164 async fn get_inbound_group_sessions_and_backed_up_to(
168 &self,
169 ) -> Result<Vec<(InboundGroupSession, Option<BackupVersion>)>> {
170 let lookup = |s: &InboundGroupSession| {
171 self.inbound_group_sessions_backed_up_to
172 .read()
173 .get(&s.room_id)?
174 .get(s.session_id())
175 .cloned()
176 };
177
178 Ok(self
179 .get_inbound_group_sessions()
180 .await?
181 .into_iter()
182 .map(|s| {
183 let v = lookup(&s);
184 (s, v)
185 })
186 .collect())
187 }
188}
189
190type Result<T> = std::result::Result<T, Infallible>;
191
192#[cfg_attr(target_family = "wasm", async_trait(?Send))]
193#[cfg_attr(not(target_family = "wasm"), async_trait)]
194impl CryptoStore for MemoryStore {
195 type Error = Infallible;
196
197 async fn load_account(&self) -> Result<Option<Account>> {
198 let pickled_account: Option<PickledAccount> = self.account.read().as_ref().map(|acc| {
199 serde_json::from_str(acc)
200 .expect("Deserialization failed: invalid pickled account JSON format")
201 });
202
203 if let Some(pickle) = pickled_account {
204 let account =
205 Account::from_pickle(pickle).expect("From pickle failed: invalid pickle format");
206
207 *self.static_account.write() = Some(account.static_data().clone());
208
209 Ok(Some(account))
210 } else {
211 Ok(None)
212 }
213 }
214
215 async fn load_identity(&self) -> Result<Option<PrivateCrossSigningIdentity>> {
216 Ok(self.private_identity.read().clone())
217 }
218
219 async fn next_batch_token(&self) -> Result<Option<String>> {
220 Ok(self.next_batch_token.read().await.clone())
221 }
222
223 async fn save_pending_changes(&self, changes: PendingChanges) -> Result<()> {
224 let _guard = self.save_changes_lock.lock().await;
225
226 let pickled_account = if let Some(account) = changes.account {
227 *self.static_account.write() = Some(account.static_data().clone());
228 Some(account.pickle())
229 } else {
230 None
231 };
232
233 *self.account.write() = pickled_account.map(|pickle| {
234 serde_json::to_string(&pickle)
235 .expect("Serialization failed: invalid pickled account JSON format")
236 });
237
238 Ok(())
239 }
240
241 async fn save_changes(&self, changes: Changes) -> Result<()> {
242 let _guard = self.save_changes_lock.lock().await;
243
244 let mut pickled_session: Vec<(String, PickledSession)> = Vec::new();
245 for session in changes.sessions {
246 let session_id = session.session_id().to_owned();
247 let pickle = session.pickle().await;
248 pickled_session.push((session_id.clone(), pickle));
249 }
250 self.save_sessions(pickled_session);
251
252 self.save_inbound_group_sessions(changes.inbound_group_sessions, None).await?;
253 self.save_outbound_group_sessions(changes.outbound_group_sessions);
254 self.save_private_identity(changes.private_identity);
255
256 self.save_devices(changes.devices.new);
257 self.save_devices(changes.devices.changed);
258 self.delete_devices(changes.devices.deleted);
259
260 {
261 let mut identities = self.identities.write();
262 for identity in changes.identities.new.into_iter().chain(changes.identities.changed) {
263 identities.insert(
264 identity.user_id().to_owned(),
265 serde_json::to_string(&identity)
266 .expect("UserIdentityData should always serialize to json"),
267 );
268 }
269 }
270
271 {
272 let mut olm_hashes = self.olm_hashes.write();
273 for hash in changes.message_hashes {
274 olm_hashes.entry(hash.sender_key.to_owned()).or_default().insert(hash.hash.clone());
275 }
276 }
277
278 {
279 let mut outgoing_key_requests = self.outgoing_key_requests.write();
280 let mut key_requests_by_info = self.key_requests_by_info.write();
281
282 for key_request in changes.key_requests {
283 let id = key_request.request_id.clone();
284 let info_string = encode_key_info(&key_request.info);
285
286 outgoing_key_requests.insert(id.clone(), key_request);
287 key_requests_by_info.insert(info_string, id);
288 }
289 }
290
291 if let Some(key) = changes.backup_decryption_key {
292 self.backup_keys.write().await.decryption_key = Some(key);
293 }
294
295 if let Some(version) = changes.backup_version {
296 self.backup_keys.write().await.backup_version = Some(version);
297 }
298
299 if let Some(pickle_key) = changes.dehydrated_device_pickle_key {
300 let mut lock = self.dehydrated_device_pickle_key.write().await;
301 *lock = Some(pickle_key);
302 }
303
304 {
305 let mut secret_inbox = self.secret_inbox.write();
306 for secret in changes.secrets {
307 secret_inbox.entry(secret.secret_name.to_string()).or_default().push(secret);
308 }
309 }
310
311 {
312 let mut direct_withheld_info = self.direct_withheld_info.write();
313 for (room_id, data) in changes.withheld_session_info {
314 for (session_id, event) in data {
315 direct_withheld_info
316 .entry(room_id.to_owned())
317 .or_default()
318 .insert(session_id, event);
319 }
320 }
321 }
322
323 if let Some(next_batch_token) = changes.next_batch_token {
324 *self.next_batch_token.write().await = Some(next_batch_token);
325 }
326
327 if !changes.room_settings.is_empty() {
328 let mut settings = self.room_settings.write();
329 settings.extend(changes.room_settings);
330 }
331
332 if !changes.received_room_key_bundles.is_empty() {
333 let mut room_key_bundles = self.room_key_bundles.write();
334 for bundle in changes.received_room_key_bundles {
335 room_key_bundles
336 .entry(bundle.bundle_data.room_id.clone())
337 .or_default()
338 .insert(bundle.sender_user.clone(), bundle);
339 }
340 }
341
342 Ok(())
343 }
344
345 async fn save_inbound_group_sessions(
346 &self,
347 sessions: Vec<InboundGroupSession>,
348 backed_up_to_version: Option<&str>,
349 ) -> Result<()> {
350 for session in sessions {
351 let room_id = session.room_id();
352 let session_id = session.session_id();
353
354 let backed_up = session.backed_up();
356 if backed_up != backed_up_to_version.is_some() {
357 warn!(
358 backed_up,
359 backed_up_to_version,
360 "Session backed-up flag does not correspond to backup version setting",
361 );
362 }
363
364 if let Some(backup_version) = backed_up_to_version {
365 self.inbound_group_sessions_backed_up_to
366 .write()
367 .entry(room_id.to_owned())
368 .or_default()
369 .insert(session_id.to_owned(), BackupVersion::from(backup_version));
370 }
371
372 let pickle = session.pickle().await;
373 self.inbound_group_sessions
374 .write()
375 .entry(session.room_id().to_owned())
376 .or_default()
377 .insert(
378 session.session_id().to_owned(),
379 serde_json::to_string(&pickle)
380 .expect("Pickle pickle data should serialize to json"),
381 );
382 }
383 Ok(())
384 }
385
386 async fn get_sessions(&self, sender_key: &str) -> Result<Option<Vec<Session>>> {
387 let device_keys = self.get_own_device().await?.as_device_keys().clone();
388
389 if let Some(pickles) = self.sessions.read().get(sender_key) {
390 let mut sessions: Vec<Session> = Vec::new();
391 for serialized_pickle in pickles.values() {
392 let pickle: PickledSession = serde_json::from_str(serialized_pickle.as_str())
393 .expect("Pickle pickle deserialization should work");
394 let session = Session::from_pickle(device_keys.clone(), pickle)
395 .expect("Expect from pickle to always work");
396 sessions.push(session);
397 }
398 Ok(Some(sessions))
399 } else {
400 Ok(None)
401 }
402 }
403
404 async fn get_inbound_group_session(
405 &self,
406 room_id: &RoomId,
407 session_id: &str,
408 ) -> Result<Option<InboundGroupSession>> {
409 let pickle: Option<PickledInboundGroupSession> = self
410 .inbound_group_sessions
411 .read()
412 .get(room_id)
413 .and_then(|m| m.get(session_id))
414 .and_then(|ser| {
415 serde_json::from_str(ser).expect("Pickle pickle deserialization should work")
416 });
417
418 Ok(pickle.map(|p| {
419 InboundGroupSession::from_pickle(p).expect("Expect from pickle to always work")
420 }))
421 }
422
423 async fn get_withheld_info(
424 &self,
425 room_id: &RoomId,
426 session_id: &str,
427 ) -> Result<Option<RoomKeyWithheldEntry>> {
428 Ok(self
429 .direct_withheld_info
430 .read()
431 .get(room_id)
432 .and_then(|e| Some(e.get(session_id)?.to_owned())))
433 }
434
435 async fn get_withheld_sessions_by_room_id(
436 &self,
437 room_id: &RoomId,
438 ) -> crate::store::Result<Vec<RoomKeyWithheldEntry>, Self::Error> {
439 Ok(self
440 .direct_withheld_info
441 .read()
442 .get(room_id)
443 .map(|e| e.values().cloned().collect())
444 .unwrap_or_default())
445 }
446
447 async fn get_inbound_group_sessions(&self) -> Result<Vec<InboundGroupSession>> {
448 let inbounds = self
449 .inbound_group_sessions
450 .read()
451 .values()
452 .flat_map(HashMap::values)
453 .map(|ser| {
454 let pickle: PickledInboundGroupSession =
455 serde_json::from_str(ser).expect("Pickle deserialization should work");
456 InboundGroupSession::from_pickle(pickle).expect("Expect from pickle to always work")
457 })
458 .collect();
459 Ok(inbounds)
460 }
461
462 async fn inbound_group_session_counts(
463 &self,
464 backup_version: Option<&str>,
465 ) -> Result<RoomKeyCounts> {
466 let backed_up = if let Some(backup_version) = backup_version {
467 self.get_inbound_group_sessions_and_backed_up_to()
468 .await?
469 .into_iter()
470 .filter(|(_, o)| o.as_ref().is_some_and(|o| o.as_str() == backup_version))
472 .count()
473 } else {
474 0
478 };
479
480 let total = self.inbound_group_sessions.read().values().map(HashMap::len).sum();
481 Ok(RoomKeyCounts { total, backed_up })
482 }
483
484 async fn get_inbound_group_sessions_by_room_id(
485 &self,
486 room_id: &RoomId,
487 ) -> Result<Vec<InboundGroupSession>> {
488 let inbounds = match self.inbound_group_sessions.read().get(room_id) {
489 None => Vec::new(),
490 Some(v) => v
491 .values()
492 .map(|ser| {
493 let pickle: PickledInboundGroupSession =
494 serde_json::from_str(ser).expect("Pickle deserialization should work");
495 InboundGroupSession::from_pickle(pickle)
496 .expect("Expect from pickle to always work")
497 })
498 .collect(),
499 };
500 Ok(inbounds)
501 }
502
503 async fn get_inbound_group_sessions_for_device_batch(
504 &self,
505 sender_key: Curve25519PublicKey,
506 sender_data_type: SenderDataType,
507 after_session_id: Option<String>,
508 limit: usize,
509 ) -> Result<Vec<InboundGroupSession>> {
510 let mut sessions: Vec<_> = self
513 .get_inbound_group_sessions()
514 .await?
515 .into_iter()
516 .filter(|session: &InboundGroupSession| {
517 session.creator_info.curve25519_key == sender_key
518 && session.sender_data.to_type() == sender_data_type
519 })
520 .collect();
521
522 sessions.sort_by_key(|s| s.session_id().to_owned());
524
525 let start_index = {
527 match after_session_id {
528 None => 0,
529 Some(id) => {
530 sessions
533 .iter()
534 .position(|session| session.session_id() > id.as_str())
535 .unwrap_or(sessions.len())
536 }
537 }
538 };
539
540 Ok(sessions.drain(start_index..).take(limit).collect())
542 }
543
544 async fn inbound_group_sessions_for_backup(
545 &self,
546 backup_version: &str,
547 limit: usize,
548 ) -> Result<Vec<InboundGroupSession>> {
549 Ok(self
550 .get_inbound_group_sessions_and_backed_up_to()
551 .await?
552 .into_iter()
553 .filter_map(|(session, backed_up_to)| {
554 if let Some(ref existing_version) = backed_up_to {
555 if existing_version.as_str() == backup_version {
556 return None;
558 }
559 }
560 Some(session)
562 })
563 .take(limit)
564 .collect())
565 }
566
567 async fn mark_inbound_group_sessions_as_backed_up(
568 &self,
569 backup_version: &str,
570 room_and_session_ids: &[(&RoomId, &str)],
571 ) -> Result<()> {
572 for &(room_id, session_id) in room_and_session_ids {
573 let session = self.get_inbound_group_session(room_id, session_id).await?;
574
575 if let Some(session) = session {
576 session.mark_as_backed_up();
577
578 self.inbound_group_sessions_backed_up_to
579 .write()
580 .entry(room_id.to_owned())
581 .or_default()
582 .insert(session_id.to_owned(), BackupVersion::from(backup_version));
583
584 let updated_pickle = session.pickle().await;
586
587 self.inbound_group_sessions.write().entry(room_id.to_owned()).or_default().insert(
588 session_id.to_owned(),
589 serde_json::to_string(&updated_pickle)
590 .expect("Pickle serialization should work"),
591 );
592 }
593 }
594
595 Ok(())
596 }
597
598 async fn reset_backup_state(&self) -> Result<()> {
599 Ok(())
606 }
607
608 async fn load_backup_keys(&self) -> Result<BackupKeys> {
609 Ok(self.backup_keys.read().await.to_owned())
610 }
611
612 async fn load_dehydrated_device_pickle_key(&self) -> Result<Option<DehydratedDeviceKey>> {
613 Ok(self.dehydrated_device_pickle_key.read().await.to_owned())
614 }
615
616 async fn delete_dehydrated_device_pickle_key(&self) -> Result<()> {
617 let mut lock = self.dehydrated_device_pickle_key.write().await;
618 *lock = None;
619 Ok(())
620 }
621
622 async fn get_outbound_group_session(
623 &self,
624 room_id: &RoomId,
625 ) -> Result<Option<OutboundGroupSession>> {
626 Ok(self.outbound_group_sessions.read().get(room_id).cloned())
627 }
628
629 async fn load_tracked_users(&self) -> Result<Vec<TrackedUser>> {
630 Ok(self.tracked_users.read().values().cloned().collect())
631 }
632
633 async fn save_tracked_users(&self, tracked_users: &[(&UserId, bool)]) -> Result<()> {
634 self.tracked_users.write().extend(tracked_users.iter().map(|(user_id, dirty)| {
635 let user_id: OwnedUserId = user_id.to_owned().into();
636 (user_id.clone(), TrackedUser { user_id, dirty: *dirty })
637 }));
638 Ok(())
639 }
640
641 async fn get_device(
642 &self,
643 user_id: &UserId,
644 device_id: &DeviceId,
645 ) -> Result<Option<DeviceData>> {
646 Ok(self.devices.get(user_id, device_id))
647 }
648
649 async fn get_user_devices(
650 &self,
651 user_id: &UserId,
652 ) -> Result<HashMap<OwnedDeviceId, DeviceData>> {
653 Ok(self.devices.user_devices(user_id))
654 }
655
656 async fn get_own_device(&self) -> Result<DeviceData> {
657 let account =
658 self.get_static_account().expect("Expect account to exist when getting own device");
659
660 Ok(self
661 .devices
662 .get(&account.user_id, &account.device_id)
663 .expect("Invalid state: Should always have a own device"))
664 }
665
666 async fn get_user_identity(&self, user_id: &UserId) -> Result<Option<UserIdentityData>> {
667 let serialized = self.identities.read().get(user_id).cloned();
668 match serialized {
669 None => Ok(None),
670 Some(serialized) => {
671 let id: UserIdentityData = serde_json::from_str(serialized.as_str())
672 .expect("Only valid serialized identity are saved");
673 Ok(Some(id))
674 }
675 }
676 }
677
678 async fn is_message_known(&self, message_hash: &crate::olm::OlmMessageHash) -> Result<bool> {
679 Ok(self
680 .olm_hashes
681 .write()
682 .entry(message_hash.sender_key.to_owned())
683 .or_default()
684 .contains(&message_hash.hash))
685 }
686
687 async fn get_outgoing_secret_requests(
688 &self,
689 request_id: &TransactionId,
690 ) -> Result<Option<GossipRequest>> {
691 Ok(self.outgoing_key_requests.read().get(request_id).cloned())
692 }
693
694 async fn get_secret_request_by_info(
695 &self,
696 key_info: &SecretInfo,
697 ) -> Result<Option<GossipRequest>> {
698 let key_info_string = encode_key_info(key_info);
699
700 Ok(self
701 .key_requests_by_info
702 .read()
703 .get(&key_info_string)
704 .and_then(|i| self.outgoing_key_requests.read().get(i).cloned()))
705 }
706
707 async fn get_unsent_secret_requests(&self) -> Result<Vec<GossipRequest>> {
708 Ok(self
709 .outgoing_key_requests
710 .read()
711 .values()
712 .filter(|req| !req.sent_out)
713 .cloned()
714 .collect())
715 }
716
717 async fn delete_outgoing_secret_requests(&self, request_id: &TransactionId) -> Result<()> {
718 let req = self.outgoing_key_requests.write().remove(request_id);
719 if let Some(i) = req {
720 let key_info_string = encode_key_info(&i.info);
721 self.key_requests_by_info.write().remove(&key_info_string);
722 }
723
724 Ok(())
725 }
726
727 async fn get_secrets_from_inbox(
728 &self,
729 secret_name: &SecretName,
730 ) -> Result<Vec<GossippedSecret>> {
731 Ok(self.secret_inbox.write().entry(secret_name.to_string()).or_default().to_owned())
732 }
733
734 async fn delete_secrets_from_inbox(&self, secret_name: &SecretName) -> Result<()> {
735 self.secret_inbox.write().remove(secret_name.as_str());
736
737 Ok(())
738 }
739
740 async fn get_room_settings(&self, room_id: &RoomId) -> Result<Option<RoomSettings>> {
741 Ok(self.room_settings.read().get(room_id).cloned())
742 }
743
744 async fn get_received_room_key_bundle_data(
745 &self,
746 room_id: &RoomId,
747 user_id: &UserId,
748 ) -> Result<Option<StoredRoomKeyBundleData>> {
749 let guard = self.room_key_bundles.read();
750
751 let result = guard.get(room_id).and_then(|bundles| bundles.get(user_id).cloned());
752
753 Ok(result)
754 }
755
756 async fn get_custom_value(&self, key: &str) -> Result<Option<Vec<u8>>> {
757 Ok(self.custom_values.read().get(key).cloned())
758 }
759
760 async fn set_custom_value(&self, key: &str, value: Vec<u8>) -> Result<()> {
761 self.custom_values.write().insert(key.to_owned(), value);
762 Ok(())
763 }
764
765 async fn remove_custom_value(&self, key: &str) -> Result<()> {
766 self.custom_values.write().remove(key);
767 Ok(())
768 }
769
770 async fn try_take_leased_lock(
771 &self,
772 lease_duration_ms: u32,
773 key: &str,
774 holder: &str,
775 ) -> Result<Option<CrossProcessLockGeneration>> {
776 Ok(try_take_leased_lock(&mut self.leases.write(), lease_duration_ms, key, holder))
777 }
778}
779
780#[cfg(test)]
781mod tests {
782 use std::collections::HashMap;
783
784 use matrix_sdk_test::async_test;
785 use ruma::{room_id, user_id, RoomId};
786 use vodozemac::{Curve25519PublicKey, Ed25519PublicKey};
787
788 use super::SessionId;
789 use crate::{
790 identities::device::testing::get_device,
791 olm::{
792 tests::get_account_and_session_test_helper, Account, InboundGroupSession,
793 OlmMessageHash, PrivateCrossSigningIdentity, SenderData,
794 },
795 store::{
796 memorystore::MemoryStore,
797 types::{Changes, DeviceChanges, PendingChanges},
798 CryptoStore,
799 },
800 DeviceData,
801 };
802
803 #[async_test]
804 async fn test_session_store() {
805 let (account, session) = get_account_and_session_test_helper();
806 let own_device = DeviceData::from_account(&account);
807 let store = MemoryStore::new();
808
809 assert!(store.load_account().await.unwrap().is_none());
810
811 store
812 .save_changes(Changes {
813 devices: DeviceChanges { new: vec![own_device], ..Default::default() },
814 ..Default::default()
815 })
816 .await
817 .unwrap();
818 store.save_pending_changes(PendingChanges { account: Some(account) }).await.unwrap();
819
820 store
821 .save_changes(Changes { sessions: (vec![session.clone()]), ..Default::default() })
822 .await
823 .unwrap();
824
825 let sessions = store.get_sessions(&session.sender_key.to_base64()).await.unwrap().unwrap();
826
827 let loaded_session = &sessions[0];
828
829 assert_eq!(&session, loaded_session);
830 }
831
832 #[async_test]
833 async fn test_inbound_group_session_store() {
834 let (account, _) = get_account_and_session_test_helper();
835 let room_id = room_id!("!test:localhost");
836 let curve_key = "Nn0L2hkcCMFKqynTjyGsJbth7QrVmX3lbrksMkrGOAw";
837
838 let (outbound, _) = account.create_group_session_pair_with_defaults(room_id).await;
839 let inbound = InboundGroupSession::new(
840 Curve25519PublicKey::from_base64(curve_key).unwrap(),
841 Ed25519PublicKey::from_base64("ee3Ek+J2LkkPmjGPGLhMxiKnhiX//xcqaVL4RP6EypE").unwrap(),
842 room_id,
843 &outbound.session_key().await,
844 SenderData::unknown(),
845 outbound.settings().algorithm.to_owned(),
846 None,
847 false,
848 )
849 .unwrap();
850
851 let store = MemoryStore::new();
852 store.save_inbound_group_sessions(vec![inbound.clone()], None).await.unwrap();
853
854 let loaded_session =
855 store.get_inbound_group_session(room_id, outbound.session_id()).await.unwrap().unwrap();
856 assert_eq!(inbound, loaded_session);
857 }
858
859 #[async_test]
860 async fn test_backing_up_marks_sessions_as_backed_up() {
861 let room_id = room_id!("!test:localhost");
863 let (store, sessions) = store_with_sessions(2, room_id).await;
864
865 mark_backed_up(&store, room_id, "bkp1", &sessions).await;
867
868 let but = backed_up_tos(&store).await;
870 assert_eq!(but[sessions[0].session_id()], "bkp1");
871 assert_eq!(but[sessions[1].session_id()], "bkp1");
872 }
873
874 #[async_test]
875 async fn test_backing_up_a_second_set_of_sessions_updates_their_backup_order() {
876 let room_id = room_id!("!test:localhost");
878 let (store, sessions) = store_with_sessions(3, room_id).await;
879
880 mark_backed_up(&store, room_id, "bkp1", &sessions[..2]).await;
882
883 mark_backed_up(&store, room_id, "bkp2", &sessions[1..]).await;
885
886 let but = backed_up_tos(&store).await;
888 assert_eq!(but[sessions[0].session_id()], "bkp1");
889 assert_eq!(but[sessions[1].session_id()], "bkp2");
890 assert_eq!(but[sessions[2].session_id()], "bkp2");
891 }
892
893 #[async_test]
894 async fn test_backing_up_again_to_the_same_version_has_no_effect() {
895 let room_id = room_id!("!test:localhost");
897 let (store, sessions) = store_with_sessions(3, room_id).await;
898
899 mark_backed_up(&store, room_id, "bkp1", &sessions[..2]).await;
901
902 mark_backed_up(&store, room_id, "bkp1", &sessions[1..]).await;
904
905 let but = backed_up_tos(&store).await;
907 assert_eq!(but[sessions[0].session_id()], "bkp1");
908 assert_eq!(but[sessions[1].session_id()], "bkp1");
909 assert_eq!(but[sessions[2].session_id()], "bkp1");
910 }
911
912 #[async_test]
913 async fn test_backing_up_to_an_old_backup_version_can_increase_backed_up_to() {
914 let room_id = room_id!("!test:localhost");
917 let (store, sessions) = store_with_sessions(4, room_id).await;
918 mark_backed_up(&store, room_id, "older_bkp", &sessions[..2]).await;
919 mark_backed_up(&store, room_id, "newer_bkp", &sessions[1..2]).await;
920
921 mark_backed_up(&store, room_id, "older_bkp", &sessions[2..]).await;
923
924 let but = backed_up_tos(&store).await;
926 assert_eq!(but[sessions[0].session_id()], "older_bkp");
927 assert_eq!(but[sessions[1].session_id()], "newer_bkp");
928 assert_eq!(but[sessions[2].session_id()], "older_bkp");
929 assert_eq!(but[sessions[3].session_id()], "older_bkp");
930 }
931
932 #[async_test]
933 async fn test_backing_up_to_an_old_backup_version_overwrites_a_newer_one() {
934 let room_id = room_id!("!test:localhost");
936 let (store, sessions) = store_with_sessions(4, room_id).await;
937 mark_backed_up(&store, room_id, "older_bkp", &sessions).await;
938 assert_eq!(backed_up_tos(&store).await[sessions[0].session_id()], "older_bkp");
940 mark_backed_up(&store, room_id, "newer_bkp", &sessions).await;
941 assert_eq!(backed_up_tos(&store).await[sessions[0].session_id()], "newer_bkp");
943
944 mark_backed_up(&store, room_id, "older_bkp", &sessions[..2]).await;
946
947 let but = backed_up_tos(&store).await;
949 assert_eq!(but[sessions[0].session_id()], "older_bkp");
950 assert_eq!(but[sessions[1].session_id()], "older_bkp");
951 assert_eq!(but[sessions[2].session_id()], "newer_bkp");
952 assert_eq!(but[sessions[3].session_id()], "newer_bkp");
953 }
954
955 #[async_test]
956 async fn test_not_backed_up_sessions_are_eligible_for_backup() {
957 let room_id = room_id!("!test:localhost");
959 let (store, sessions) = store_with_sessions(4, room_id).await;
960 mark_backed_up(&store, room_id, "bkp1", &sessions[..2]).await;
961
962 let mut to_backup = store
964 .inbound_group_sessions_for_backup("bkp1", 10)
965 .await
966 .expect("Failed to ask for sessions to backup");
967 to_backup.sort_by_key(|s| s.session_id().to_owned());
968
969 assert_eq!(to_backup, &[sessions[2].clone(), sessions[3].clone()]);
971 }
972
973 #[async_test]
974 async fn test_all_sessions_are_eligible_for_backup_if_version_is_unknown() {
975 let room_id = room_id!("!test:localhost");
977 let (store, sessions) = store_with_sessions(4, room_id).await;
978 mark_backed_up(&store, room_id, "bkp1", &sessions[..2]).await;
979
980 let mut to_backup = store
982 .inbound_group_sessions_for_backup("unknown_bkp", 10)
983 .await
984 .expect("Failed to ask for sessions to backup");
985 to_backup.sort_by_key(|s| s.session_id().to_owned());
986
987 assert_eq!(
989 to_backup,
990 &[sessions[0].clone(), sessions[1].clone(), sessions[2].clone(), sessions[3].clone()]
991 );
992 }
993
994 #[async_test]
995 async fn test_sessions_backed_up_to_a_later_version_are_eligible_for_backup() {
996 let room_id = room_id!("!test:localhost");
998 let (store, sessions) = store_with_sessions(4, room_id).await;
999 mark_backed_up(&store, room_id, "bkp0", &sessions[..1]).await;
1000 mark_backed_up(&store, room_id, "bkp1", &sessions[1..2]).await;
1001 mark_backed_up(&store, room_id, "bkp2", &sessions[2..3]).await;
1002
1003 let mut to_backup = store
1005 .inbound_group_sessions_for_backup("bkp1", 10)
1006 .await
1007 .expect("Failed to ask for sessions to backup");
1008 to_backup.sort_by_key(|s| s.session_id().to_owned());
1009
1010 assert_eq!(
1012 to_backup,
1013 &[
1014 sessions[0].clone(), sessions[2].clone(), sessions[3].clone(), ]
1019 );
1020 }
1021
1022 #[async_test]
1023 async fn test_outbound_group_session_store() {
1024 let (account, _) = get_account_and_session_test_helper();
1026 let room_id = room_id!("!test:localhost");
1027 let (outbound, _) = account.create_group_session_pair_with_defaults(room_id).await;
1028
1029 let store = MemoryStore::new();
1031 store.save_outbound_group_sessions(vec![outbound.clone()]);
1032
1033 let loaded_session = store.get_outbound_group_session(room_id).await.unwrap().unwrap();
1035 assert_eq!(
1036 serde_json::to_string(&outbound.pickle().await).unwrap(),
1037 serde_json::to_string(&loaded_session.pickle().await).unwrap()
1038 );
1039 }
1040
1041 #[async_test]
1042 async fn test_tracked_users_are_stored_once_per_user_id() {
1043 let user1 = user_id!("@user1:s");
1045 let user2 = user_id!("@user2:s");
1046 let user3 = user_id!("@user3:s");
1047 let store = MemoryStore::new();
1048 store.save_tracked_users(&[(user1, true), (user2, true)]).await.unwrap();
1049
1050 store.save_tracked_users(&[(user2, false), (user3, false)]).await.unwrap();
1052
1053 let loaded_tracked_users =
1055 store.load_tracked_users().await.expect("failed to load tracked users");
1056
1057 let tracked_contains = |user_id, dirty| {
1058 loaded_tracked_users.iter().any(|u| u.user_id == user_id && u.dirty == dirty)
1059 };
1060
1061 assert!(tracked_contains(user1, true));
1062 assert!(tracked_contains(user2, false));
1063 assert!(tracked_contains(user3, false));
1064 assert_eq!(loaded_tracked_users.len(), 3);
1065 }
1066
1067 #[async_test]
1068 async fn test_private_identity_store() {
1069 let private_identity = PrivateCrossSigningIdentity::empty(user_id!("@u:s"));
1071
1072 let store = MemoryStore::new();
1074 store.save_private_identity(Some(private_identity.clone()));
1075
1076 let loaded_identity =
1078 store.load_identity().await.expect("failed to load private identity").unwrap();
1079
1080 assert_eq!(loaded_identity.user_id(), user_id!("@u:s"));
1081 }
1082
1083 #[async_test]
1084 async fn test_device_store() {
1085 let device = get_device();
1086 let store = MemoryStore::new();
1087
1088 store.save_devices(vec![device.clone()]);
1089
1090 let loaded_device =
1091 store.get_device(device.user_id(), device.device_id()).await.unwrap().unwrap();
1092
1093 assert_eq!(device, loaded_device);
1094
1095 let user_devices = store.get_user_devices(device.user_id()).await.unwrap();
1096
1097 assert_eq!(&**user_devices.keys().next().unwrap(), device.device_id());
1098 assert_eq!(user_devices.values().next().unwrap(), &device);
1099
1100 let loaded_device = user_devices.get(device.device_id()).unwrap();
1101
1102 assert_eq!(&device, loaded_device);
1103
1104 store.delete_devices(vec![device.clone()]);
1105 assert!(store.get_device(device.user_id(), device.device_id()).await.unwrap().is_none());
1106 }
1107
1108 #[async_test]
1109 async fn test_message_hash() {
1110 let store = MemoryStore::new();
1111
1112 let hash =
1113 OlmMessageHash { sender_key: "test_sender".to_owned(), hash: "test_hash".to_owned() };
1114
1115 let mut changes = Changes::default();
1116 changes.message_hashes.push(hash.clone());
1117
1118 assert!(!store.is_message_known(&hash).await.unwrap());
1119 store.save_changes(changes).await.unwrap();
1120 assert!(store.is_message_known(&hash).await.unwrap());
1121 }
1122
1123 #[async_test]
1124 async fn test_key_counts_of_empty_store_are_zero() {
1125 let store = MemoryStore::new();
1127
1128 let key_counts = store.inbound_group_session_counts(Some("")).await.unwrap();
1130
1131 assert_eq!(key_counts.total, 0);
1133 assert_eq!(key_counts.backed_up, 0);
1134 }
1135
1136 #[async_test]
1137 async fn test_counting_sessions_reports_the_number_of_sessions() {
1138 let room_id = room_id!("!test:localhost");
1140 let (store, _) = store_with_sessions(4, room_id).await;
1141
1142 let key_counts = store.inbound_group_session_counts(Some("bkp")).await.unwrap();
1144
1145 assert_eq!(key_counts.total, 4);
1147 assert_eq!(key_counts.backed_up, 0);
1149 }
1150
1151 #[async_test]
1152 async fn test_counting_backed_up_sessions_reports_the_number_backed_up_in_this_backup() {
1153 let room_id = room_id!("!test:localhost");
1155 let (store, sessions) = store_with_sessions(5, room_id).await;
1156 mark_backed_up(&store, room_id, "bkp", &sessions[..2]).await;
1157
1158 let key_counts = store.inbound_group_session_counts(Some("bkp")).await.unwrap();
1160
1161 assert_eq!(key_counts.total, 5);
1163 assert_eq!(key_counts.backed_up, 2);
1165 }
1166
1167 #[async_test]
1168 async fn test_counting_backed_up_sessions_for_null_backup_reports_zero() {
1169 let room_id = room_id!("!test:localhost");
1171 let (store, sessions) = store_with_sessions(4, room_id).await;
1172 mark_backed_up(&store, room_id, "bkp", &sessions[..2]).await;
1173
1174 let key_counts = store.inbound_group_session_counts(None).await.unwrap();
1176
1177 assert_eq!(key_counts.backed_up, 0);
1179 }
1180
1181 #[async_test]
1182 async fn test_counting_backed_up_sessions_only_reports_sessions_in_the_version_specified() {
1183 let room_id = room_id!("!test:localhost");
1185 let (store, sessions) = store_with_sessions(4, room_id).await;
1186 mark_backed_up(&store, room_id, "bkp1", &sessions[..2]).await;
1187 mark_backed_up(&store, room_id, "bkp2", &sessions[3..]).await;
1188
1189 let key_counts = store.inbound_group_session_counts(Some("bkp2")).await.unwrap();
1191
1192 assert_eq!(key_counts.backed_up, 1);
1194 }
1195
1196 async fn mark_backed_up(
1198 store: &MemoryStore,
1199 room_id: &RoomId,
1200 backup_version: &str,
1201 sessions: &[InboundGroupSession],
1202 ) {
1203 let rooms_and_ids: Vec<_> = sessions.iter().map(|s| (room_id, s.session_id())).collect();
1204
1205 store
1206 .mark_inbound_group_sessions_as_backed_up(backup_version, &rooms_and_ids)
1207 .await
1208 .expect("Failed to mark sessions as backed up");
1209 }
1210
1211 async fn store_with_sessions(
1215 num_sessions: usize,
1216 room_id: &RoomId,
1217 ) -> (MemoryStore, Vec<InboundGroupSession>) {
1218 let (account, _) = get_account_and_session_test_helper();
1219
1220 let mut sessions = Vec::with_capacity(num_sessions);
1221 for _ in 0..num_sessions {
1222 sessions.push(new_session(&account, room_id).await);
1223 }
1224 sessions.sort_by_key(|s| s.session_id().to_owned());
1225
1226 let store = MemoryStore::new();
1227 store.save_inbound_group_sessions(sessions.clone(), None).await.unwrap();
1228
1229 (store, sessions)
1230 }
1231
1232 async fn new_session(account: &Account, room_id: &RoomId) -> InboundGroupSession {
1234 let curve_key = "Nn0L2hkcCMFKqynTjyGsJbth7QrVmX3lbrksMkrGOAw";
1235 let (outbound, _) = account.create_group_session_pair_with_defaults(room_id).await;
1236
1237 InboundGroupSession::new(
1238 Curve25519PublicKey::from_base64(curve_key).unwrap(),
1239 Ed25519PublicKey::from_base64("ee3Ek+J2LkkPmjGPGLhMxiKnhiX//xcqaVL4RP6EypE").unwrap(),
1240 room_id,
1241 &outbound.session_key().await,
1242 SenderData::unknown(),
1243 outbound.settings().algorithm.to_owned(),
1244 None,
1245 false,
1246 )
1247 .unwrap()
1248 }
1249
1250 async fn backed_up_tos(store: &MemoryStore) -> HashMap<SessionId, String> {
1253 store
1254 .get_inbound_group_sessions_and_backed_up_to()
1255 .await
1256 .expect("Unable to get inbound group sessions and backup order")
1257 .iter()
1258 .map(|(s, o)| {
1259 (
1260 s.session_id().to_owned(),
1261 o.as_ref().map(|v| v.as_str().to_owned()).unwrap_or("".to_owned()),
1262 )
1263 })
1264 .collect()
1265 }
1266}
1267
1268#[cfg(test)]
1269mod integration_tests {
1270 use std::{
1271 collections::HashMap,
1272 sync::{Arc, Mutex, OnceLock},
1273 };
1274
1275 use async_trait::async_trait;
1276 use matrix_sdk_common::cross_process_lock::CrossProcessLockGeneration;
1277 use ruma::{
1278 events::secret::request::SecretName, DeviceId, OwnedDeviceId, RoomId, TransactionId, UserId,
1279 };
1280 use vodozemac::Curve25519PublicKey;
1281
1282 use super::MemoryStore;
1283 use crate::{
1284 cryptostore_integration_tests, cryptostore_integration_tests_time,
1285 olm::{
1286 InboundGroupSession, OlmMessageHash, OutboundGroupSession, PrivateCrossSigningIdentity,
1287 SenderDataType, StaticAccountData,
1288 },
1289 store::{
1290 types::{
1291 BackupKeys, Changes, DehydratedDeviceKey, PendingChanges, RoomKeyCounts,
1292 RoomKeyWithheldEntry, RoomSettings, StoredRoomKeyBundleData, TrackedUser,
1293 },
1294 CryptoStore,
1295 },
1296 Account, DeviceData, GossipRequest, GossippedSecret, SecretInfo, Session, UserIdentityData,
1297 };
1298
1299 #[derive(Clone, Debug)]
1302 struct PersistentMemoryStore(Arc<MemoryStore>);
1303
1304 impl PersistentMemoryStore {
1305 fn new() -> Self {
1306 Self(Arc::new(MemoryStore::new()))
1307 }
1308
1309 fn get_static_account(&self) -> Option<StaticAccountData> {
1310 self.0.get_static_account()
1311 }
1312 }
1313
1314 async fn get_store(
1319 name: &str,
1320 _passphrase: Option<&str>,
1321 clear_data: bool,
1322 ) -> PersistentMemoryStore {
1323 static STORES: OnceLock<Mutex<HashMap<String, PersistentMemoryStore>>> = OnceLock::new();
1328 let stores = STORES.get_or_init(|| Mutex::new(HashMap::new()));
1329
1330 let mut stores = stores.lock().unwrap();
1331
1332 if clear_data {
1333 let new_store = PersistentMemoryStore::new();
1335 stores.insert(name.to_owned(), new_store.clone());
1336 new_store
1337 } else {
1338 stores.entry(name.to_owned()).or_insert_with(PersistentMemoryStore::new).clone()
1339 }
1340 }
1341
1342 #[cfg_attr(target_family = "wasm", async_trait(?Send))]
1344 #[cfg_attr(not(target_family = "wasm"), async_trait)]
1345 impl CryptoStore for PersistentMemoryStore {
1346 type Error = <MemoryStore as CryptoStore>::Error;
1347
1348 async fn load_account(&self) -> Result<Option<Account>, Self::Error> {
1349 self.0.load_account().await
1350 }
1351
1352 async fn load_identity(&self) -> Result<Option<PrivateCrossSigningIdentity>, Self::Error> {
1353 self.0.load_identity().await
1354 }
1355
1356 async fn save_changes(&self, changes: Changes) -> Result<(), Self::Error> {
1357 self.0.save_changes(changes).await
1358 }
1359
1360 async fn save_pending_changes(&self, changes: PendingChanges) -> Result<(), Self::Error> {
1361 self.0.save_pending_changes(changes).await
1362 }
1363
1364 async fn save_inbound_group_sessions(
1365 &self,
1366 sessions: Vec<InboundGroupSession>,
1367 backed_up_to_version: Option<&str>,
1368 ) -> Result<(), Self::Error> {
1369 self.0.save_inbound_group_sessions(sessions, backed_up_to_version).await
1370 }
1371
1372 async fn get_sessions(
1373 &self,
1374 sender_key: &str,
1375 ) -> Result<Option<Vec<Session>>, Self::Error> {
1376 self.0.get_sessions(sender_key).await
1377 }
1378
1379 async fn get_inbound_group_session(
1380 &self,
1381 room_id: &RoomId,
1382 session_id: &str,
1383 ) -> Result<Option<InboundGroupSession>, Self::Error> {
1384 self.0.get_inbound_group_session(room_id, session_id).await
1385 }
1386
1387 async fn get_withheld_info(
1388 &self,
1389 room_id: &RoomId,
1390 session_id: &str,
1391 ) -> Result<Option<RoomKeyWithheldEntry>, Self::Error> {
1392 self.0.get_withheld_info(room_id, session_id).await
1393 }
1394
1395 async fn get_withheld_sessions_by_room_id(
1396 &self,
1397 room_id: &RoomId,
1398 ) -> Result<Vec<RoomKeyWithheldEntry>, Self::Error> {
1399 self.0.get_withheld_sessions_by_room_id(room_id).await
1400 }
1401
1402 async fn get_inbound_group_sessions(
1403 &self,
1404 ) -> Result<Vec<InboundGroupSession>, Self::Error> {
1405 self.0.get_inbound_group_sessions().await
1406 }
1407
1408 async fn inbound_group_session_counts(
1409 &self,
1410 backup_version: Option<&str>,
1411 ) -> Result<RoomKeyCounts, Self::Error> {
1412 self.0.inbound_group_session_counts(backup_version).await
1413 }
1414
1415 async fn get_inbound_group_sessions_by_room_id(
1416 &self,
1417 room_id: &RoomId,
1418 ) -> Result<Vec<InboundGroupSession>, Self::Error> {
1419 self.0.get_inbound_group_sessions_by_room_id(room_id).await
1420 }
1421
1422 async fn get_inbound_group_sessions_for_device_batch(
1423 &self,
1424 sender_key: Curve25519PublicKey,
1425 sender_data_type: SenderDataType,
1426 after_session_id: Option<String>,
1427 limit: usize,
1428 ) -> Result<Vec<InboundGroupSession>, Self::Error> {
1429 self.0
1430 .get_inbound_group_sessions_for_device_batch(
1431 sender_key,
1432 sender_data_type,
1433 after_session_id,
1434 limit,
1435 )
1436 .await
1437 }
1438
1439 async fn inbound_group_sessions_for_backup(
1440 &self,
1441 backup_version: &str,
1442 limit: usize,
1443 ) -> Result<Vec<InboundGroupSession>, Self::Error> {
1444 self.0.inbound_group_sessions_for_backup(backup_version, limit).await
1445 }
1446
1447 async fn mark_inbound_group_sessions_as_backed_up(
1448 &self,
1449 backup_version: &str,
1450 room_and_session_ids: &[(&RoomId, &str)],
1451 ) -> Result<(), Self::Error> {
1452 self.0
1453 .mark_inbound_group_sessions_as_backed_up(backup_version, room_and_session_ids)
1454 .await
1455 }
1456
1457 async fn reset_backup_state(&self) -> Result<(), Self::Error> {
1458 self.0.reset_backup_state().await
1459 }
1460
1461 async fn load_backup_keys(&self) -> Result<BackupKeys, Self::Error> {
1462 self.0.load_backup_keys().await
1463 }
1464
1465 async fn load_dehydrated_device_pickle_key(
1466 &self,
1467 ) -> Result<Option<DehydratedDeviceKey>, Self::Error> {
1468 self.0.load_dehydrated_device_pickle_key().await
1469 }
1470
1471 async fn delete_dehydrated_device_pickle_key(&self) -> Result<(), Self::Error> {
1472 self.0.delete_dehydrated_device_pickle_key().await
1473 }
1474
1475 async fn get_outbound_group_session(
1476 &self,
1477 room_id: &RoomId,
1478 ) -> Result<Option<OutboundGroupSession>, Self::Error> {
1479 self.0.get_outbound_group_session(room_id).await
1480 }
1481
1482 async fn load_tracked_users(&self) -> Result<Vec<TrackedUser>, Self::Error> {
1483 self.0.load_tracked_users().await
1484 }
1485
1486 async fn save_tracked_users(&self, users: &[(&UserId, bool)]) -> Result<(), Self::Error> {
1487 self.0.save_tracked_users(users).await
1488 }
1489
1490 async fn get_device(
1491 &self,
1492 user_id: &UserId,
1493 device_id: &DeviceId,
1494 ) -> Result<Option<DeviceData>, Self::Error> {
1495 self.0.get_device(user_id, device_id).await
1496 }
1497
1498 async fn get_user_devices(
1499 &self,
1500 user_id: &UserId,
1501 ) -> Result<HashMap<OwnedDeviceId, DeviceData>, Self::Error> {
1502 self.0.get_user_devices(user_id).await
1503 }
1504
1505 async fn get_own_device(&self) -> Result<DeviceData, Self::Error> {
1506 self.0.get_own_device().await
1507 }
1508
1509 async fn get_user_identity(
1510 &self,
1511 user_id: &UserId,
1512 ) -> Result<Option<UserIdentityData>, Self::Error> {
1513 self.0.get_user_identity(user_id).await
1514 }
1515
1516 async fn is_message_known(
1517 &self,
1518 message_hash: &OlmMessageHash,
1519 ) -> Result<bool, Self::Error> {
1520 self.0.is_message_known(message_hash).await
1521 }
1522
1523 async fn get_outgoing_secret_requests(
1524 &self,
1525 request_id: &TransactionId,
1526 ) -> Result<Option<GossipRequest>, Self::Error> {
1527 self.0.get_outgoing_secret_requests(request_id).await
1528 }
1529
1530 async fn get_secret_request_by_info(
1531 &self,
1532 secret_info: &SecretInfo,
1533 ) -> Result<Option<GossipRequest>, Self::Error> {
1534 self.0.get_secret_request_by_info(secret_info).await
1535 }
1536
1537 async fn get_unsent_secret_requests(&self) -> Result<Vec<GossipRequest>, Self::Error> {
1538 self.0.get_unsent_secret_requests().await
1539 }
1540
1541 async fn delete_outgoing_secret_requests(
1542 &self,
1543 request_id: &TransactionId,
1544 ) -> Result<(), Self::Error> {
1545 self.0.delete_outgoing_secret_requests(request_id).await
1546 }
1547
1548 async fn get_secrets_from_inbox(
1549 &self,
1550 secret_name: &SecretName,
1551 ) -> Result<Vec<GossippedSecret>, Self::Error> {
1552 self.0.get_secrets_from_inbox(secret_name).await
1553 }
1554
1555 async fn delete_secrets_from_inbox(
1556 &self,
1557 secret_name: &SecretName,
1558 ) -> Result<(), Self::Error> {
1559 self.0.delete_secrets_from_inbox(secret_name).await
1560 }
1561
1562 async fn get_room_settings(
1563 &self,
1564 room_id: &RoomId,
1565 ) -> Result<Option<RoomSettings>, Self::Error> {
1566 self.0.get_room_settings(room_id).await
1567 }
1568
1569 async fn get_received_room_key_bundle_data(
1570 &self,
1571 room_id: &RoomId,
1572 user_id: &UserId,
1573 ) -> crate::store::Result<Option<StoredRoomKeyBundleData>, Self::Error> {
1574 self.0.get_received_room_key_bundle_data(room_id, user_id).await
1575 }
1576
1577 async fn get_custom_value(&self, key: &str) -> Result<Option<Vec<u8>>, Self::Error> {
1578 self.0.get_custom_value(key).await
1579 }
1580
1581 async fn set_custom_value(&self, key: &str, value: Vec<u8>) -> Result<(), Self::Error> {
1582 self.0.set_custom_value(key, value).await
1583 }
1584
1585 async fn remove_custom_value(&self, key: &str) -> Result<(), Self::Error> {
1586 self.0.remove_custom_value(key).await
1587 }
1588
1589 async fn try_take_leased_lock(
1590 &self,
1591 lease_duration_ms: u32,
1592 key: &str,
1593 holder: &str,
1594 ) -> Result<Option<CrossProcessLockGeneration>, Self::Error> {
1595 self.0.try_take_leased_lock(lease_duration_ms, key, holder).await
1596 }
1597
1598 async fn next_batch_token(&self) -> Result<Option<String>, Self::Error> {
1599 self.0.next_batch_token().await
1600 }
1601 }
1602
1603 cryptostore_integration_tests!();
1604 cryptostore_integration_tests_time!();
1605}