1use async_trait::async_trait;
2use hopr_crypto_types::types::OffchainPublicKey;
3use hopr_db_api::{
4 errors::{DbError, Result},
5 resolver::HoprDbResolverOperations,
6};
7use hopr_primitive_types::primitives::Address;
8
9use crate::{accounts::HoprDbAccountOperations, db::HoprDb};
10
11#[async_trait]
12impl HoprDbResolverOperations for HoprDb {
13 async fn resolve_packet_key(&self, onchain_key: &Address) -> Result<Option<OffchainPublicKey>> {
14 Ok(self
15 .translate_key(None, *onchain_key)
16 .await?
17 .map(|k| k.try_into())
18 .transpose()
19 .map_err(|_e| DbError::LogicalError("failed to transpose the translated key".into()))?)
20 }
21
22 async fn resolve_chain_key(&self, offchain_key: &OffchainPublicKey) -> Result<Option<Address>> {
23 Ok(self
24 .translate_key(None, *offchain_key)
25 .await?
26 .map(|k| k.try_into())
27 .transpose()
28 .map_err(|_e| DbError::LogicalError("failed to transpose the translated key".into()))?)
29 }
30}
31
32#[cfg(test)]
33mod tests {
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 use super::*;
40
41 #[tokio::test]
42 async fn test_get_offchain_key_should_return_nothing_if_a_mapping_to_chain_key_does_not_exist() -> anyhow::Result<()>
43 {
44 let db = HoprDb::new_in_memory(ChainKeypair::random()).await?;
45
46 let chain = ChainKeypair::random().public().to_address();
47
48 let actual_pk = db.resolve_packet_key(&chain).await?;
49 assert_eq!(actual_pk, None, "offchain key should not be present");
50 Ok(())
51 }
52
53 #[tokio::test]
54 async fn test_get_chain_key_should_return_nothing_if_a_mapping_to_offchain_key_does_not_exist() -> anyhow::Result<()>
55 {
56 let db = HoprDb::new_in_memory(ChainKeypair::random()).await?;
57
58 let packet = *OffchainKeypair::random().public();
59
60 let actual_ck = db.resolve_chain_key(&packet).await?;
61 assert_eq!(actual_ck, None, "chain key should not be present");
62 Ok(())
63 }
64
65 #[tokio::test]
66 async fn test_get_chain_key_should_succeed_if_a_mapping_to_offchain_key_exists() -> anyhow::Result<()> {
67 let db = HoprDb::new_in_memory(ChainKeypair::random()).await?;
68
69 let chain_1 = ChainKeypair::random().public().to_address();
72 let packet_1 = *OffchainKeypair::random().public();
73 let account_1 = hopr_db_entity::account::ActiveModel {
74 chain_key: Set(chain_1.to_hex()),
75 packet_key: Set(packet_1.to_hex()),
76 ..Default::default()
77 };
78
79 let chain_2 = ChainKeypair::random().public().to_address();
80 let packet_2 = *OffchainKeypair::random().public();
81 let account_2 = hopr_db_entity::account::ActiveModel {
82 chain_key: Set(chain_2.to_hex()),
83 packet_key: Set(packet_2.to_hex()),
84 ..Default::default()
85 };
86
87 hopr_db_entity::account::Entity::insert_many([account_1, account_2])
88 .exec(&db.index_db)
89 .await?;
90
91 let actual_ck = db.resolve_chain_key(&packet_1).await?;
92 assert_eq!(actual_ck, Some(chain_1), "chain keys must match");
93 Ok(())
94 }
95
96 #[tokio::test]
97 async fn test_get_chain_key_should_succeed_if_a_mapping_to_offchain_key_exists_with_cache() -> anyhow::Result<()> {
98 let db = HoprDb::new_in_memory(ChainKeypair::random()).await?;
99
100 let chain_1 = ChainKeypair::random().public().to_address();
103 let packet_1 = *OffchainKeypair::random().public();
104 db.insert_account(
105 None,
106 AccountEntry {
107 public_key: packet_1,
108 chain_addr: chain_1,
109 entry_type: AccountType::NotAnnounced,
110 published_at: 1,
111 },
112 )
113 .await?;
114
115 let chain_2 = ChainKeypair::random().public().to_address();
116 let packet_2 = *OffchainKeypair::random().public();
117 db.insert_account(
118 None,
119 AccountEntry {
120 public_key: packet_2,
121 chain_addr: chain_2,
122 entry_type: AccountType::NotAnnounced,
123 published_at: 1,
124 },
125 )
126 .await?;
127
128 let actual_ck = db.resolve_chain_key(&packet_1).await?;
129 assert_eq!(actual_ck, Some(chain_1), "chain keys must match");
130 Ok(())
131 }
132
133 #[tokio::test]
134 async fn test_get_offchain_key_should_succeed_if_a_mapping_to_chain_key_exists() -> anyhow::Result<()> {
135 let db = HoprDb::new_in_memory(ChainKeypair::random()).await?;
136
137 let chain_1 = ChainKeypair::random().public().to_address();
140 let packet_1 = *OffchainKeypair::random().public();
141 let account_1 = hopr_db_entity::account::ActiveModel {
142 chain_key: Set(chain_1.to_hex()),
143 packet_key: Set(packet_1.to_hex()),
144 ..Default::default()
145 };
146
147 let chain_2 = ChainKeypair::random().public().to_address();
148 let packet_2 = *OffchainKeypair::random().public();
149 let account_2 = hopr_db_entity::account::ActiveModel {
150 chain_key: Set(chain_2.to_hex()),
151 packet_key: Set(packet_2.to_hex()),
152 ..Default::default()
153 };
154
155 hopr_db_entity::account::Entity::insert_many([account_1, account_2])
156 .exec(&db.index_db)
157 .await?;
158
159 let actual_pk = db.resolve_packet_key(&chain_2).await?;
160
161 assert_eq!(actual_pk, Some(packet_2), "packet keys must match");
162 Ok(())
163 }
164
165 #[tokio::test]
166 async fn test_get_offchain_key_should_succeed_if_a_mapping_to_chain_key_exists_with_cache() -> anyhow::Result<()> {
167 let db = HoprDb::new_in_memory(ChainKeypair::random()).await?;
168
169 let chain_1 = ChainKeypair::random().public().to_address();
172 let packet_1 = *OffchainKeypair::random().public();
173 db.insert_account(
174 None,
175 AccountEntry {
176 public_key: packet_1,
177 chain_addr: chain_1,
178 entry_type: AccountType::NotAnnounced,
179 published_at: 1,
180 },
181 )
182 .await?;
183
184 let chain_2 = ChainKeypair::random().public().to_address();
185 let packet_2 = *OffchainKeypair::random().public();
186 db.insert_account(
187 None,
188 AccountEntry {
189 public_key: packet_2,
190 chain_addr: chain_2,
191 entry_type: AccountType::NotAnnounced,
192 published_at: 1,
193 },
194 )
195 .await?;
196
197 let actual_pk = db.resolve_packet_key(&chain_2).await?;
198
199 assert_eq!(actual_pk, Some(packet_2), "packet keys must match");
200 Ok(())
201 }
202}