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