Skip to main content

lb_rs/service/
keychain.rs

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