hopr_db_sql/
resolver.rs

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        // Inserting to the table directly to avoid cache
70
71        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        // Inserting to the table via API to insert into cache as well
101
102        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        // Inserting to the table directly to avoid cache
138
139        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        // Inserting to the table via API to insert into cache as well
170
171        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}