Skip to content
This repository has been archived by the owner on Sep 21, 2024. It is now read-only.

Commit

Permalink
feat: Implement a RecordValidator trait for the NameSystem DHT (#129)
Browse files Browse the repository at this point in the history
  • Loading branch information
jsantell authored Nov 9, 2022
1 parent 656fb23 commit ba5560c
Show file tree
Hide file tree
Showing 14 changed files with 428 additions and 66 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions rust/noosphere-ns/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ cid = "~0.8"
serde = "^1"
serde_json = "^1"
futures = "0.3.1"
async-trait = "~0.1"
ucan = { version = "0.7.0-alpha.1" }
ucan-key-support = { version = "0.7.0-alpha.1" }
tokio = { version = "1.15", features = ["io-util", "io-std", "sync", "macros", "rt", "rt-multi-thread"] }
Expand Down
2 changes: 2 additions & 0 deletions rust/noosphere-ns/src/dht/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ use std::io;
pub enum DHTError {
Error(String),
IO(io::ErrorKind),
ValidationError(Vec<u8>),
LibP2PTransportError(Option<libp2p::Multiaddr>),
LibP2PStorageError(KadStorageError),
LibP2PGetRecordError(kad::GetRecordError),
Expand All @@ -34,6 +35,7 @@ impl fmt::Display for DHTError {
DHTError::LibP2PGetProvidersError(e) => write!(fmt, "{:#?}", e),
DHTError::IO(k) => write!(fmt, "{:#?}", k),
DHTError::Error(m) => write!(fmt, "{:#?}", m),
DHTError::ValidationError(_) => write!(fmt, "validation error"),
}
}
}
Expand Down
2 changes: 2 additions & 0 deletions rust/noosphere-ns/src/dht/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,10 @@ mod processor;
mod swarm;
mod types;
mod utils;
mod validator;

pub use config::DHTConfig;
pub use errors::DHTError;
pub use node::{DHTNode, DHTStatus};
pub use types::DHTNetworkInfo;
pub use validator::{DefaultRecordValidator, RecordValidator};
58 changes: 53 additions & 5 deletions rust/noosphere-ns/src/dht/node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use crate::dht::{
processor::DHTProcessor,
types::{DHTMessageClient, DHTNetworkInfo, DHTRequest, DHTResponse},
utils::key_material_to_libp2p_keypair,
DHTConfig,
DHTConfig, DefaultRecordValidator, RecordValidator,
};
use libp2p;
use std::time::Duration;
Expand All @@ -28,9 +28,32 @@ pub enum DHTStatus {
Error(String),
}

/// Represents a DHT node running in a network thread, providing
/// async methods for operating the node.
pub struct DHTNode {
/// Represents a DHT node running in a network thread.
///
/// # Example
///
/// ```
/// use noosphere_ns::dht::{DefaultRecordValidator, DHTConfig, DHTNode};
/// use noosphere_core::authority::generate_ed25519_key;
/// use libp2p::{self, Multiaddr};
/// use std::str::FromStr;
/// use tokio;
///
/// #[tokio::main]
/// async fn main() {
/// let key = generate_ed25519_key();
/// // Note: not a real bootstrap node
/// let bootstrap_peers: Vec<Multiaddr> = vec!["/ip4/127.0.0.50/tcp/33333/p2p/12D3KooWH8WgH9mgbMXrKX4veokUznvEn6Ycwg4qaGNi83nLkoUK".parse().unwrap()];
/// let validator = DHTNode::<DefaultRecordValidator>::validator();
/// let config = DHTConfig {
/// listening_address: Some("/ip4/127.0.0.1/tcp/10000".parse().unwrap()),
/// ..Default::default()
/// };
/// let mut node = DHTNode::new(&key, Some(&bootstrap_peers), validator, &config).unwrap();
/// node.run();
/// }
/// ```
pub struct DHTNode<V: RecordValidator + 'static> {
config: DHTConfig,
state: DHTStatus,
client: Option<DHTMessageClient>,
Expand All @@ -39,17 +62,24 @@ pub struct DHTNode {
peer_id: libp2p::PeerId,
p2p_address: Option<libp2p::Multiaddr>,
bootstrap_peers: Option<Vec<libp2p::Multiaddr>>,
validator: Option<V>,
}

impl DHTNode {
impl<V> DHTNode<V>
where
V: RecordValidator + 'static,
{
/// Creates a new [DHTNode].
/// `bootstrap_peers` is a collection of [String]s in [libp2p::Multiaddr] form of initial
/// peers to connect to during bootstrapping. This collection would be empty in the
/// standalone bootstrap node scenario.
/// `validator` is an object implementing [RecordValidator]. Default validator can be
/// created via `DHTNode::validator()`.
/// `config` is a [DHTConfig] of various configurations for the node.
pub fn new(
key_material: &Ed25519KeyMaterial,
bootstrap_peers: Option<&Vec<libp2p::Multiaddr>>,
validator: V,
config: &DHTConfig,
) -> Result<Self, DHTError> {
let keypair = key_material_to_libp2p_keypair(key_material)?;
Expand All @@ -74,6 +104,7 @@ impl DHTNode {
state: DHTStatus::Initialized,
client: None,
thread_handle: None,
validator: Some(validator),
})
}

Expand All @@ -87,6 +118,7 @@ impl DHTNode {
&self.peer_id,
&self.p2p_address,
&self.bootstrap_peers,
self.validator.take(),
&self.config,
processor,
)?);
Expand Down Expand Up @@ -233,4 +265,20 @@ impl DHTNode {
Ok(())
}
}

/// Returns an instance of [DefaultRecordValidator].
pub fn validator() -> DefaultRecordValidator {
DefaultRecordValidator {}
}
}

impl<V> Drop for DHTNode<V>
where
V: RecordValidator + 'static,
{
fn drop(&mut self) {
if let Some(thread_handle) = self.thread_handle.take() {
thread_handle.abort();
}
}
}
Loading

0 comments on commit ba5560c

Please sign in to comment.