hopr_db_sql/
resolver.rs

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        // Inserting to the table directly to avoid cache
68
69        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        // Inserting to the table via API to insert into cache as well
99
100        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        // Inserting to the table directly to avoid cache
120
121        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        // Inserting to the table via API to insert into cache as well
152
153        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}