-
Notifications
You must be signed in to change notification settings - Fork 21
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #36 from Nuhvi/rust
Mainline support
- Loading branch information
Showing
18 changed files
with
1,304 additions
and
263 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,6 @@ | ||
[package] | ||
name = "pkarr" | ||
version = "0.3.0" | ||
version = "1.0.0" | ||
authors = ["Nuh <[email protected]>"] | ||
edition = "2021" | ||
description = "Public-Key Addressable Resource Records (Pkarr); publish and resolve DNS records over Mainline DHT" | ||
|
@@ -12,13 +12,48 @@ categories = ["networking", "p2p", "routing"] | |
[dependencies] | ||
bytes = "1.5.0" | ||
ed25519-dalek = { version = "2.0.0", features = ["rand_core"] } | ||
mainline = { version = "1.0.0", optional = true } | ||
rand = "0.8.5" | ||
reqwest = { version = "0.11", default-features = false, features = ["rustls-tls"] } | ||
reqwest = { version = "0.11", default-features = false, features = ["rustls-tls", "blocking"], optional = true} | ||
self_cell = "1.0.2" | ||
simple-dns = "0.5.6" | ||
thiserror = "1.0.49" | ||
url = "2.4.1" | ||
z32 = "1.0.0" | ||
|
||
[dev-dependencies] | ||
clap = { version = "4.4.8", features = ["derive"] } | ||
tokio = { version = "1.32.0", features = ["tokio-macros", "macros", "rt-multi-thread"] } | ||
|
||
[features] | ||
async= [] | ||
dht = ["mainline"] | ||
relay = ["reqwest"] | ||
|
||
full = ["dht", "relay", "async"] | ||
default = ["dht"] | ||
|
||
[[example]] | ||
name = "relay-client" | ||
path = "examples/relay-client.rs" | ||
required-features = ["relay"] | ||
|
||
[[example]] | ||
name = "async-relay-client" | ||
path = "examples/async/relay-client.rs" | ||
required-features = ["relay", "async"] | ||
|
||
[[example]] | ||
name = "async-publish" | ||
path = "examples/async/publish.rs" | ||
required-features = ["async"] | ||
|
||
[[example]] | ||
name = "async-resolve" | ||
path = "examples/async/resolve.rs" | ||
required-features = ["async"] | ||
|
||
[[example]] | ||
name = "async-resolve-most-recent" | ||
path = "examples/async/resolve-most-recent.rs" | ||
required-features = ["async"] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
# Pkarr | ||
|
||
Rust implementation of [Pkarr](pkarr.org). | ||
|
||
Publish and resolve DNS packets over Mainline DHT. | ||
|
||
**[API Docs](https://docs.rs/pkarr/latest/pkarr/)** | ||
|
||
## Get started | ||
|
||
Check the [Examples](https://github.com/Nuhvi/pkarr/tree/main/pkarr/examples). |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
# Examples | ||
|
||
## Publish | ||
|
||
```sh | ||
cargo run --example publish | ||
``` | ||
|
||
## Resolve Eager | ||
|
||
```sh | ||
cargo run --example resolve <zbase32 public key from Publish step> | ||
``` | ||
|
||
## Resolve Most Recent | ||
|
||
```sh | ||
cargo run --example resolve-most-recent <zbase32 public key from Publish step> | ||
``` | ||
|
||
## Relay | ||
|
||
```sh | ||
cargo run --example relay-client | ||
``` | ||
|
||
## Async Publish | ||
|
||
```sh | ||
cargo run --example async-publish --features="async" | ||
``` | ||
|
||
## Async Resolve Eager | ||
|
||
```sh | ||
cargo run --example async-resolve --features="async" <zbase32 public key from Publish step> | ||
``` | ||
|
||
## Resolve Most Recent | ||
|
||
```sh | ||
cargo run --example async-resolve-most-recent --features="async" <zbase32 public key from Publish step> | ||
``` | ||
|
||
## Relay | ||
|
||
```sh | ||
cargo run --example async-relay-client --features="relay async" | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
//! This example shows how to publish [ResourceRecord]s directly to the DHT. | ||
//! | ||
//! Change the `Keypair::random()` to your own keypair to publish your own records. | ||
//! Change the `packet.answers` to your own records. | ||
//! | ||
//! run this example from the project root: | ||
//! $ cargo run --example publish | ||
use std::time::Instant; | ||
|
||
use pkarr::{dns, Keypair, PkarrClient, Result, SignedPacket}; | ||
|
||
#[tokio::main] | ||
async fn main() -> Result<()> { | ||
let client = PkarrClient::new(); | ||
|
||
let keypair = Keypair::random(); | ||
|
||
let mut packet = dns::Packet::new_reply(0); | ||
packet.answers.push(dns::ResourceRecord::new( | ||
dns::Name::new("_foo").unwrap(), | ||
dns::CLASS::IN, | ||
30, | ||
dns::rdata::RData::TXT("bar".try_into()?), | ||
)); | ||
|
||
let signed_packet = SignedPacket::from_packet(&keypair, &packet)?; | ||
|
||
let instant = Instant::now(); | ||
|
||
println!("\nPublishing {} ...", keypair.to_uri_string()); | ||
|
||
match client.publish(&signed_packet).await { | ||
Ok(metadata) => { | ||
println!( | ||
"\nSuccessfully published in {:?} to {} nodes", | ||
instant.elapsed(), | ||
metadata.stored_at().len() | ||
); | ||
} | ||
Err(err) => { | ||
println!("\nFailed to publish {} \n {}", keypair.public_key(), err); | ||
} | ||
}; | ||
|
||
Ok(()) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
//! This example shows how to publish and resolve [ResourceRecord]s to and from a Pkarr | ||
//! [relay](https://github.com/Nuhvi/pkarr/blob/main/design/relays.md). | ||
//! | ||
//! In this example, we publish both an A and CNAME records as well as a TXT record representing | ||
//! [Iroh](https://iroh.computer/) DERP regions used by Peer with the same Ed25519 key. | ||
//! | ||
//! For the purpose of this example we use the default Pkarr relay for both | ||
//! publishing and resolving, but you can override `relay1` and `relay2` to | ||
//! with your own locally running relays. | ||
//! | ||
//! Publishing takes a few seconds as the relay only responds after sending the PUT | ||
//! request to all the nearest nodes to the Pkarr key. | ||
//! | ||
//! Resolving on the other hand is optimistic and the relay will retun the first | ||
//! response it gets. | ||
//! | ||
//! run this example from the project root: | ||
//! $ cargo run --example relay-client | ||
use std::time::Instant; | ||
|
||
use pkarr::{dns, url::Url, Keypair, PkarrClient, Result, SignedPacket, DEFAULT_PKARR_RELAY}; | ||
|
||
#[tokio::main] | ||
async fn main() -> Result<()> { | ||
let keypair = Keypair::random(); | ||
|
||
let relay1 = DEFAULT_PKARR_RELAY; | ||
let relay2 = DEFAULT_PKARR_RELAY; | ||
|
||
// Publisher | ||
{ | ||
println!("\nPublishing {} ...\n", keypair.to_uri_string()); | ||
let mut packet = dns::Packet::new_reply(0); | ||
packet.answers.push(dns::ResourceRecord::new( | ||
dns::Name::new("_derp_region.iroh.").unwrap(), | ||
dns::CLASS::IN, | ||
30, | ||
dns::rdata::RData::A(dns::rdata::A { | ||
address: std::net::Ipv4Addr::new(52, 30, 229, 248).into(), | ||
}), | ||
)); | ||
packet.answers.push(dns::ResourceRecord::new( | ||
dns::Name::new("_derp_region.iroh.").unwrap(), | ||
dns::CLASS::IN, | ||
30, | ||
dns::rdata::RData::CNAME( | ||
dns::Name::new("eu.derp.iroh.network") | ||
.expect("is valid name") | ||
.into(), | ||
), | ||
)); | ||
packet.answers.push(dns::ResourceRecord::new( | ||
dns::Name::new("_derp_region.iroh.").unwrap(), | ||
dns::CLASS::IN, | ||
30, | ||
dns::rdata::RData::TXT("url=eu.derp.iroh.network:33000".try_into()?), | ||
)); | ||
|
||
let signed_packet = SignedPacket::from_packet(&keypair, &packet)?; | ||
|
||
let client = PkarrClient::new(); | ||
client | ||
.relay_put(&Url::parse(relay1).unwrap(), signed_packet) | ||
.await?; | ||
|
||
println!("Published {}", keypair.to_uri_string()); | ||
} | ||
|
||
// Resolver | ||
{ | ||
println!("\nResolving {}...\n", keypair.to_uri_string()); | ||
let reader = PkarrClient::new(); | ||
|
||
let instant = Instant::now(); | ||
|
||
let signed_packet = reader | ||
.relay_get(&Url::parse(relay2).unwrap(), keypair.public_key()) | ||
.await?; | ||
|
||
println!("Resolved in {:?} \n{}", instant.elapsed(), signed_packet); | ||
} | ||
|
||
Ok(()) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
//! This example shows how to resolve [ResourceRecord]s directly from the DHT. | ||
//! | ||
//! run this example from the project root: | ||
//! $ cargo run --example resolve <zbase32 encoded key> | ||
use std::time::Instant; | ||
|
||
use pkarr::{PkarrClient, PublicKey}; | ||
|
||
use clap::Parser; | ||
|
||
#[derive(Parser)] | ||
#[command(author, version, about, long_about = None)] | ||
struct Cli { | ||
/// z32 public_key | ||
public_key: String, | ||
} | ||
|
||
#[tokio::main] | ||
async fn main() { | ||
let cli = Cli::parse(); | ||
|
||
let client = PkarrClient::new(); | ||
|
||
let str: &str = &cli.public_key; | ||
let public_key: PublicKey = str.try_into().expect("Invalid zbase32 encoded key"); | ||
|
||
let instant = Instant::now(); | ||
|
||
println!("\nResolving {} ...", public_key.to_uri_string()); | ||
|
||
if let Some(signed_packet) = client.resolve_most_recent(public_key).await { | ||
println!("\nResolved in {:?} {}", instant.elapsed(), signed_packet); | ||
} else { | ||
println!("\nFailed to resolve {}", str); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
//! This example shows how to resolve [ResourceRecord]s directly from the DHT. | ||
//! | ||
//! run this example from the project root: | ||
//! $ cargo run --example resolve <zbase32 encoded key> | ||
use std::time::Instant; | ||
|
||
use pkarr::{PkarrClient, PublicKey}; | ||
|
||
use clap::Parser; | ||
|
||
#[derive(Parser)] | ||
#[command(author, version, about, long_about = None)] | ||
struct Cli { | ||
/// z32 public_key | ||
public_key: String, | ||
} | ||
|
||
#[tokio::main] | ||
async fn main() { | ||
let cli = Cli::parse(); | ||
|
||
let client = PkarrClient::new(); | ||
|
||
let str: &str = &cli.public_key; | ||
let public_key: PublicKey = str.try_into().expect("Invalid zbase32 encoded key"); | ||
|
||
let instant = Instant::now(); | ||
|
||
println!("\nResolving {} ...", public_key.to_uri_string()); | ||
|
||
if let Some(signed_packet) = client.resolve(public_key).await { | ||
println!("\nResolved in {:?} {}", instant.elapsed(), signed_packet); | ||
} else { | ||
println!("\nFailed to resolve {}", str); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
//! This example shows how to publish [ResourceRecord]s directly to the DHT. | ||
//! | ||
//! Change the `Keypair::random()` to your own keypair to publish your own records. | ||
//! Change the `packet.answers` to your own records. | ||
//! | ||
//! run this example from the project root: | ||
//! $ cargo run --example publish | ||
use std::time::Instant; | ||
|
||
use pkarr::{dns, Keypair, PkarrClient, Result, SignedPacket}; | ||
|
||
fn main() -> Result<()> { | ||
let client = PkarrClient::new(); | ||
|
||
let keypair = Keypair::random(); | ||
|
||
let mut packet = dns::Packet::new_reply(0); | ||
packet.answers.push(dns::ResourceRecord::new( | ||
dns::Name::new("_foo").unwrap(), | ||
dns::CLASS::IN, | ||
30, | ||
dns::rdata::RData::TXT("bar".try_into()?), | ||
)); | ||
|
||
let signed_packet = SignedPacket::from_packet(&keypair, &packet)?; | ||
|
||
let instant = Instant::now(); | ||
|
||
println!("\nPublishing {} ...", keypair.to_uri_string()); | ||
|
||
match client.publish(&signed_packet) { | ||
Ok(metadata) => { | ||
println!( | ||
"\nSuccessfully published in {:?} to {} nodes", | ||
instant.elapsed(), | ||
metadata.stored_at().len(), | ||
); | ||
} | ||
Err(err) => { | ||
println!("\nFailed to publish {} \n {}", keypair.public_key(), err); | ||
} | ||
}; | ||
|
||
Ok(()) | ||
} |
Oops, something went wrong.