1use async_trait::async_trait;
2use hopr_crypto_types::types::OffchainPublicKey;
3use hopr_db_api::errors::DbError;
4use hopr_db_api::{errors::Result, resolver::HoprDbResolverOperations};
5use hopr_primitive_types::primitives::Address;
6
7use crate::accounts::HoprDbAccountOperations;
8use crate::db::HoprDb;
9
10#[async_trait]
11impl HoprDbResolverOperations for HoprDb {
12 async fn resolve_packet_key(&self, onchain_key: &Address) -> Result<Option<OffchainPublicKey>> {
13 Ok(self
14 .translate_key(None, *onchain_key)
15 .await?
16 .map(|k| k.try_into())
17 .transpose()
18 .map_err(|_e| DbError::LogicalError("failed to transpose the translated key".into()))?)
19 }
20
21 async fn resolve_chain_key(&self, offchain_key: &OffchainPublicKey) -> Result<Option<Address>> {
22 Ok(self
23 .translate_key(None, *offchain_key)
24 .await?
25 .map(|k| k.try_into())
26 .transpose()
27 .map_err(|_e| DbError::LogicalError("failed to transpose the translated key".into()))?)
28 }
29}
30
31#[cfg(test)]
32mod tests {
33 use super::*;
34 use hopr_crypto_types::prelude::{ChainKeypair, Keypair, OffchainKeypair};
35 use hopr_internal_types::account::{AccountEntry, AccountType};
36 use hopr_primitive_types::prelude::ToHex;
37 use sea_orm::{EntityTrait, Set};
38
39 #[async_std::test]
40 async fn test_get_offchain_key_should_return_nothing_if_a_mapping_to_chain_key_does_not_exist() -> anyhow::Result<()>
41 {
42 let db = HoprDb::new_in_memory(ChainKeypair::random()).await?;
43
44 let chain = ChainKeypair::random().public().to_address();
45
46 let actual_pk = db.resolve_packet_key(&chain).await?;
47 assert_eq!(actual_pk, None, "offchain key should not be present");
48 Ok(())
49 }
50
51 #[async_std::test]
52 async fn test_get_chain_key_should_return_nothing_if_a_mapping_to_offchain_key_does_not_exist() -> anyhow::Result<()>
53 {
54 let db = HoprDb::new_in_memory(ChainKeypair::random()).await?;
55
56 let packet = *OffchainKeypair::random().public();
57
58 let actual_ck = db.resolve_chain_key(&packet).await?;
59 assert_eq!(actual_ck, None, "chain key should not be present");
60 Ok(())
61 }
62
63 #[async_std::test]
64 async fn test_get_chain_key_should_succeed_if_a_mapping_to_offchain_key_exists() -> anyhow::Result<()> {
65 let db = HoprDb::new_in_memory(ChainKeypair::random()).await?;
66
67 let chain_1 = ChainKeypair::random().public().to_address();
70 let packet_1 = *OffchainKeypair::random().public();
71 let account_1 = hopr_db_entity::account::ActiveModel {
72 chain_key: Set(chain_1.to_hex()),
73 packet_key: Set(packet_1.to_hex()),
74 ..Default::default()
75 };
76
77 let chain_2 = ChainKeypair::random().public().to_address();
78 let packet_2 = *OffchainKeypair::random().public();
79 let account_2 = hopr_db_entity::account::ActiveModel {
80 chain_key: Set(chain_2.to_hex()),
81 packet_key: Set(packet_2.to_hex()),
82 ..Default::default()
83 };
84
85 hopr_db_entity::account::Entity::insert_many([account_1, account_2])
86 .exec(&db.index_db)
87 .await?;
88
89 let actual_ck = db.resolve_chain_key(&packet_1).await?;
90 assert_eq!(actual_ck, Some(chain_1), "chain keys must match");
91 Ok(())
92 }
93
94 #[async_std::test]
95 async fn test_get_chain_key_should_succeed_if_a_mapping_to_offchain_key_exists_with_cache() -> anyhow::Result<()> {
96 let db = HoprDb::new_in_memory(ChainKeypair::random()).await?;
97
98 let chain_1 = ChainKeypair::random().public().to_address();
101 let packet_1 = *OffchainKeypair::random().public();
102 db.insert_account(None, AccountEntry::new(packet_1, chain_1, AccountType::NotAnnounced))
103 .await?;
104
105 let chain_2 = ChainKeypair::random().public().to_address();
106 let packet_2 = *OffchainKeypair::random().public();
107 db.insert_account(None, AccountEntry::new(packet_2, chain_2, AccountType::NotAnnounced))
108 .await?;
109
110 let actual_ck = db.resolve_chain_key(&packet_1).await?;
111 assert_eq!(actual_ck, Some(chain_1), "chain keys must match");
112 Ok(())
113 }
114
115 #[async_std::test]
116 async fn test_get_offchain_key_should_succeed_if_a_mapping_to_chain_key_exists() -> anyhow::Result<()> {
117 let db = HoprDb::new_in_memory(ChainKeypair::random()).await?;
118
119 let chain_1 = ChainKeypair::random().public().to_address();
122 let packet_1 = *OffchainKeypair::random().public();
123 let account_1 = hopr_db_entity::account::ActiveModel {
124 chain_key: Set(chain_1.to_hex()),
125 packet_key: Set(packet_1.to_hex()),
126 ..Default::default()
127 };
128
129 let chain_2 = ChainKeypair::random().public().to_address();
130 let packet_2 = *OffchainKeypair::random().public();
131 let account_2 = hopr_db_entity::account::ActiveModel {
132 chain_key: Set(chain_2.to_hex()),
133 packet_key: Set(packet_2.to_hex()),
134 ..Default::default()
135 };
136
137 hopr_db_entity::account::Entity::insert_many([account_1, account_2])
138 .exec(&db.index_db)
139 .await?;
140
141 let actual_pk = db.resolve_packet_key(&chain_2).await?;
142
143 assert_eq!(actual_pk, Some(packet_2), "packet keys must match");
144 Ok(())
145 }
146
147 #[async_std::test]
148 async fn test_get_offchain_key_should_succeed_if_a_mapping_to_chain_key_exists_with_cache() -> anyhow::Result<()> {
149 let db = HoprDb::new_in_memory(ChainKeypair::random()).await?;
150
151 let chain_1 = ChainKeypair::random().public().to_address();
154 let packet_1 = *OffchainKeypair::random().public();
155 db.insert_account(None, AccountEntry::new(packet_1, chain_1, AccountType::NotAnnounced))
156 .await?;
157
158 let chain_2 = ChainKeypair::random().public().to_address();
159 let packet_2 = *OffchainKeypair::random().public();
160 db.insert_account(None, AccountEntry::new(packet_2, chain_2, AccountType::NotAnnounced))
161 .await?;
162
163 let actual_pk = db.resolve_packet_key(&chain_2).await?;
164
165 assert_eq!(actual_pk, Some(packet_2), "packet keys must match");
166 Ok(())
167 }
168}