1use crate::{DhtClient, DhtConfig, NameResolver, NameSystem};
2use anyhow::Result;
3use async_trait::async_trait;
4use libp2p::Multiaddr;
5use noosphere_core::{
6 authority::generate_ed25519_key,
7 data::{Did, LinkRecord},
8};
9use std::collections::HashMap;
10use tokio::sync::Mutex;
11use ucan::store::UcanJwtStore;
12
13pub struct NameSystemNetwork {
15 nodes: Vec<NameSystem>,
16 address: Multiaddr,
17}
18
19impl NameSystemNetwork {
20 pub fn nodes(&self) -> &Vec<NameSystem> {
22 &self.nodes
23 }
24
25 pub fn nodes_mut(&mut self) -> &mut Vec<NameSystem> {
27 &mut self.nodes
28 }
29
30 pub fn get(&self, index: usize) -> Option<&NameSystem> {
32 self.nodes.get(index)
33 }
34
35 pub fn get_mut(&mut self, index: usize) -> Option<&mut NameSystem> {
37 self.nodes.get_mut(index)
38 }
39
40 pub fn address(&self) -> &Multiaddr {
42 &self.address
43 }
44
45 pub async fn generate<S: UcanJwtStore + Clone + 'static>(
50 node_count: usize,
51 store: Option<S>,
52 ) -> Result<Self> {
53 let mut bootstrap_address: Option<Multiaddr> = None;
54 let mut nodes = vec![];
55 for _ in 0..node_count {
56 let key = generate_ed25519_key();
57 let node = NameSystem::new(&key, DhtConfig::default(), store.clone())?;
58 let address = node.listen("/ip4/127.0.0.1/tcp/0".parse()?).await?;
59 if let Some(address) = bootstrap_address.as_ref() {
60 node.add_peers(vec![address.to_owned()]).await?;
61 } else {
62 bootstrap_address = Some(address);
63 }
64 nodes.push(node);
65 }
66 Ok(NameSystemNetwork {
67 nodes,
68 address: bootstrap_address.unwrap(),
69 })
70 }
71}
72
73pub struct KeyValueNameResolver {
74 store: Mutex<HashMap<Did, LinkRecord>>,
75}
76
77impl KeyValueNameResolver {
78 pub fn new() -> Self {
79 KeyValueNameResolver {
80 store: Mutex::new(HashMap::new()),
81 }
82 }
83}
84
85impl Default for KeyValueNameResolver {
86 fn default() -> Self {
87 Self::new()
88 }
89}
90
91#[async_trait]
92impl NameResolver for KeyValueNameResolver {
93 async fn publish(&self, record: LinkRecord) -> Result<()> {
94 let mut store = self.store.lock().await;
95 let did_id = Did(record.to_sphere_identity().into());
96 store.insert(did_id, record);
97 Ok(())
98 }
99
100 async fn resolve(&self, identity: &Did) -> Result<Option<LinkRecord>> {
101 let store = self.store.lock().await;
102 Ok(store.get(identity).map(|record| record.to_owned()))
103 }
104}
105
106#[cfg(test)]
107mod test {
108 use super::*;
109 use crate::name_resolver_tests;
110 async fn before_name_resolver_tests() -> Result<KeyValueNameResolver> {
111 Ok(KeyValueNameResolver::new())
112 }
113 name_resolver_tests!(KeyValueNameResolver, before_name_resolver_tests);
114}