hopr_chain_connector/connector/
keys.rs1use 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}