hopr_chain_connector/connector/
keys.rs

1use hopr_api::chain::{HoprKeyIdent, HoprSphinxHeaderSpec, HoprSphinxSuite};
2use hopr_crypto_types::prelude::OffchainPublicKey;
3use hopr_primitive_types::prelude::Address;
4
5use crate::{backend::Backend, connector::HoprBlockchainConnector, errors::ConnectorError};
6
7pub struct HoprKeyMapper<B> {
8    pub(crate) id_to_key: moka::sync::Cache<HoprKeyIdent, Option<OffchainPublicKey>, ahash::RandomState>,
9    pub(crate) key_to_id: moka::sync::Cache<OffchainPublicKey, Option<HoprKeyIdent>, ahash::RandomState>,
10    pub(crate) backend: std::sync::Arc<B>,
11}
12
13impl<B> Clone for HoprKeyMapper<B> {
14    fn clone(&self) -> Self {
15        Self {
16            id_to_key: self.id_to_key.clone(),
17            key_to_id: self.key_to_id.clone(),
18            backend: self.backend.clone(),
19        }
20    }
21}
22
23impl<B> hopr_api::chain::KeyIdMapper<HoprSphinxSuite, HoprSphinxHeaderSpec> for HoprKeyMapper<B>
24where
25    B: Backend + Send + Sync + 'static,
26{
27    fn map_key_to_id(&self, key: &OffchainPublicKey) -> Option<HoprKeyIdent> {
28        self.key_to_id.get_with_by_ref(key, || {
29            tracing::warn!(%key, "cache miss on map_key_to_id");
30            match self.backend.get_account_by_key(key) {
31                Ok(Some(account)) => Some(account.key_id),
32                Ok(None) => None,
33                Err(error) => {
34                    tracing::error!(%error, %key, "failed to get account by key");
35                    None
36                }
37            }
38        })
39    }
40
41    fn map_id_to_public(&self, id: &HoprKeyIdent) -> Option<OffchainPublicKey> {
42        self.id_to_key.get_with_by_ref(id, || {
43            tracing::warn!(%id, "cache miss on map_id_to_public");
44            match self.backend.get_account_by_id(id) {
45                Ok(Some(account)) => Some(account.public_key),
46                Ok(None) => None,
47                Err(error) => {
48                    tracing::error!(%error, %id, "failed to get account by id");
49                    None
50                }
51            }
52        })
53    }
54}
55
56#[async_trait::async_trait]
57impl<B, C, P, R> hopr_api::chain::ChainKeyOperations for HoprBlockchainConnector<C, B, P, R>
58where
59    B: Backend + Send + Sync + 'static,
60    C: Send + Sync,
61    P: Send + Sync,
62    R: Send + Sync,
63{
64    type Error = ConnectorError;
65    type Mapper = HoprKeyMapper<B>;
66
67    async fn chain_key_to_packet_key(&self, chain: &Address) -> Result<Option<OffchainPublicKey>, Self::Error> {
68        self.check_connection_state()?;
69
70        let backend = self.backend.clone();
71        let chain_key = *chain;
72        Ok(self
73            .chain_to_packet
74            .try_get_with_by_ref(&chain_key, async move {
75                tracing::warn!(%chain_key, "cache miss on chain_key_to_packet_key");
76                match hopr_async_runtime::prelude::spawn_blocking(move || backend.get_account_by_address(&chain_key))
77                    .await
78                {
79                    Ok(Ok(value)) => Ok(value.map(|account| account.public_key)),
80                    Ok(Err(e)) => Err(ConnectorError::BackendError(e.into())),
81                    Err(e) => Err(ConnectorError::BackendError(e.into())),
82                }
83            })
84            .await?)
85    }
86
87    async fn packet_key_to_chain_key(&self, packet: &OffchainPublicKey) -> Result<Option<Address>, Self::Error> {
88        self.check_connection_state()?;
89
90        let backend = self.backend.clone();
91        let packet_key = *packet;
92        Ok(self
93            .packet_to_chain
94            .try_get_with_by_ref(&packet_key, async move {
95                tracing::warn!(%packet_key, "cache miss on packet_key_to_chain_key");
96                match hopr_async_runtime::prelude::spawn_blocking(move || backend.get_account_by_key(&packet_key)).await
97                {
98                    Ok(Ok(value)) => Ok(value.map(|account| account.chain_addr)),
99                    Ok(Err(e)) => Err(ConnectorError::BackendError(e.into())),
100                    Err(e) => Err(ConnectorError::BackendError(e.into())),
101                }
102            })
103            .await?)
104    }
105
106    fn key_id_mapper_ref(&self) -> &Self::Mapper {
107        &self.mapper
108    }
109}