lb_rs/service/
keychain.rs1use std::collections::HashMap;
2use std::sync::{Arc, RwLock};
3
4use crate::Lb;
5use crate::model::account::Account;
6use crate::model::crypto::AESKey;
7use crate::model::errors::{LbErrKind, LbResult};
8use libsecp256k1::PublicKey;
9use tokio::sync::OnceCell;
10use uuid::Uuid;
11
12pub type KeyCache = Arc<RwLock<HashMap<Uuid, AESKey>>>;
13
14#[derive(Default, Clone)]
15pub struct Keychain {
16 key_cache: KeyCache,
17 account: Arc<OnceCell<Account>>,
18 public_key: Arc<OnceCell<PublicKey>>,
19}
20
21impl From<Option<&Account>> for Keychain {
22 fn from(value: Option<&Account>) -> Self {
23 match value {
24 Some(account) => {
25 let account = account.clone();
26 let pk = account.public_key();
27 let key_cache = Default::default();
28
29 Self {
30 account: Arc::new(OnceCell::from(account)),
31 public_key: Arc::new(OnceCell::from(pk)),
32 key_cache,
33 }
34 }
35 None => Self::default(),
36 }
37 }
38}
39
40impl Lb {
41 pub fn get_account(&self) -> LbResult<&Account> {
42 self.keychain.get_account()
43 }
44}
45
46impl Keychain {
47 pub fn get_account(&self) -> LbResult<&Account> {
48 self.account
49 .get()
50 .ok_or_else(|| LbErrKind::AccountNonexistent.into())
51 }
52
53 pub fn get_pk(&self) -> LbResult<PublicKey> {
54 self.public_key
55 .get()
56 .copied()
57 .ok_or_else(|| LbErrKind::AccountNonexistent.into())
58 }
59
60 #[doc(hidden)]
61 pub async fn cache_account(&self, account: Account) -> LbResult<()> {
62 let pk = account.public_key();
63 self.account
64 .set(account)
65 .map_err(|_| LbErrKind::AccountExists)?;
66 self.public_key
67 .set(pk)
68 .map_err(|_| LbErrKind::AccountExists)?;
69
70 Ok(())
71 }
72
73 pub fn contains_aes_key(&self, id: &Uuid) -> LbResult<bool> {
74 Ok(self.key_cache.read()?.contains_key(id))
75 }
76
77 pub fn insert_aes_key(&self, id: Uuid, key: AESKey) -> LbResult<()> {
78 self.key_cache.write()?.insert(id, key);
79 Ok(())
80 }
81
82 pub fn get_aes_key(&self, id: &Uuid) -> LbResult<Option<AESKey>> {
83 Ok(self.key_cache.read()?.get(id).copied())
84 }
85}