Skip to content

Commit

Permalink
Initiate swarm with private net when psk provided in config
Browse files Browse the repository at this point in the history
  • Loading branch information
sandreae committed Jun 25, 2024
1 parent ec2ac4f commit 58ab076
Show file tree
Hide file tree
Showing 5 changed files with 60 additions and 6 deletions.
23 changes: 21 additions & 2 deletions aquadoggo/src/api/config_file.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use std::str::FromStr;
use std::sync::OnceLock;

use anyhow::{anyhow, Result};
use libp2p::PeerId;
use libp2p::{pnet::PreSharedKey, PeerId};
use p2panda_rs::schema::SchemaId;
use serde::{Deserialize, Deserializer, Serialize, Serializer};
use tempfile::TempDir;
Expand Down Expand Up @@ -116,14 +116,23 @@ pub struct ConfigFile {
#[serde(default = "default_http_port")]
pub http_port: u16,

/// protocol (TCP/QUIC) used for node-node communication and data replication. Defaults to QUIC.
/// protocol (TCP/QUIC) used for node-node communication and data replication. Defaults to QUIC.
#[serde(default)]
pub transport: Transport,

/// TCP / QUIC port for node-node communication and data replication. Defaults to 2022.
#[serde(default = "default_node_port")]
pub node_port: u16,

/// Pre-shared key formatted as a 64 digit hexadecimal string.
///
/// When provided a private network will be made with only peers knowing the psk being able
/// to form connections.
///
/// WARNING: Private networks are only supported when using TCP for the transport layer.
#[serde(default)]
pub psk: Option<String>,

/// Path to folder where blobs (large binary files) are persisted. Defaults to a temporary
/// directory.
///
Expand Down Expand Up @@ -219,6 +228,7 @@ impl Default for ConfigFile {
fn default() -> Self {
Self {
transport: Transport::default(),
psk: None,
log_level: default_log_level(),
allow_schema_ids: UncheckedAllowList::default(),
database_url: default_database_url(),
Expand Down Expand Up @@ -298,6 +308,14 @@ impl TryFrom<ConfigFile> for Configuration {
.map(From::from)
.collect();

// `PreSharedKey` expects to parse key string from a multi-line string in the following format.
let psk = if let Some(psk) = value.psk {
let formatted_psk = format!("/key/swarm/psk/1.0.0/\n/base16/\n{}", psk);
Some(PreSharedKey::from_str(&formatted_psk)?)
} else {
None
};

Ok(Configuration {
allow_schema_ids,
database_url: value.database_url,
Expand All @@ -307,6 +325,7 @@ impl TryFrom<ConfigFile> for Configuration {
worker_pool_size: value.worker_pool_size,
network: NetworkConfiguration {
transport: value.transport,
psk,
port: value.node_port,
mdns: value.mdns,
direct_node_addresses,
Expand Down
7 changes: 6 additions & 1 deletion aquadoggo/src/network/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,12 @@ pub struct NetworkConfiguration {
/// protocol (TCP/QUIC) used for node-node communication and data replication.
pub transport: Transport,

/// Establish a private net secured by this pre-shared key.
/// Pre-shared key formatted as a 64 digit hexadecimal string.
///
/// When provided a private network will be made with only peers knowing the psk being able
/// to form connections.
///
/// WARNING: Private networks are only supported when using TCP for the transport layer.
pub psk: Option<PreSharedKey>,

/// QUIC or TCP port for node-node communication and data replication.
Expand Down
7 changes: 6 additions & 1 deletion aquadoggo/src/network/service.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,12 +47,17 @@ pub async fn network_service(
tx: ServiceSender,
tx_ready: ServiceReadySender,
) -> Result<()> {
let network_config = context.config.network.clone();
let mut network_config = context.config.network.clone();
let key_pair = identity::to_libp2p_key_pair(&context.key_pair);
let local_peer_id = key_pair.public().to_peer_id();

info_or_print(&format!("Peer id: {local_peer_id}"));

if network_config.psk.is_some() && network_config.transport == Transport::QUIC {
warn!("Private net not supported for QUIC transport protocol, switching to TCP");
network_config.transport = Transport::TCP;
}

let mut swarm = match network_config.transport {
Transport::QUIC => build_quic_swarm(&network_config, key_pair),
Transport::TCP => build_tcp_swarm(&network_config, key_pair),
Expand Down
20 changes: 19 additions & 1 deletion aquadoggo_cli/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ struct Cli {
#[serde(skip_serializing_if = "Option::is_none")]
http_port: Option<u16>,

/// protocol (TCP/QUIC) used for node-node communication and data replication. Defaults to QUIC.
/// protocol (TCP/QUIC) used for node-node communication and data replication. Defaults to QUIC.
#[arg(short = 'q', long, value_name = "TRANSPORT")]
#[serde(skip_serializing_if = "Option::is_none")]
pub transport: Option<String>,
Expand All @@ -122,6 +122,16 @@ struct Cli {
#[serde(skip_serializing_if = "Option::is_none")]
node_port: Option<u16>,

/// Pre-shared key formatted as a 64 digit hexadecimal string.
///
/// When provided a private network will be made with only peers knowing the psk being able
/// to form connections.
///
/// WARNING: Private networks are only supported when using TCP for the transport layer.
#[arg(short = 'y', long, value_name = "PSK")]
#[serde(skip_serializing_if = "Option::is_none")]
pub psk: Option<String>,

/// Path to folder where blobs (large binary files) are persisted. Defaults to a temporary
/// directory.
///
Expand Down Expand Up @@ -381,12 +391,19 @@ pub fn print_config(
"disabled"
};

let pnet = if config.network.psk.is_some() {
"enabled"
} else {
"disabled"
};

format!(
r"Allow schema IDs: {}
Database URL: {}
mDNS: {}
Private key: {}
Relay mode: {}
Private Net: {}
Node is ready!
",
Expand All @@ -395,5 +412,6 @@ Node is ready!
mdns.blue(),
private_key.blue(),
relay_mode.blue(),
pnet.blue()
)
}
9 changes: 8 additions & 1 deletion aquadoggo_cli/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use std::convert::TryInto;
use std::str::FromStr;

use anyhow::Context;
use aquadoggo::{AllowList, Configuration, Node};
use aquadoggo::{AllowList, Configuration, Node, Transport};
use env_logger::WriteStyle;
use log::{warn, LevelFilter};

Expand Down Expand Up @@ -73,6 +73,13 @@ async fn main() -> anyhow::Result<()> {

/// Show some hopefully helpful warnings around common configuration issues.
fn show_warnings(config: &Configuration, is_temporary_blobs_path: bool) {
if config.network.psk.is_some() && config.network.transport == Transport::QUIC {
warn!(
"Your node is configured with a pre-shared key and uses QUIC transport. Private
nets are not supported when using QUIC therefore TCP will be enforced. "
);
}

match &config.allow_schema_ids {
AllowList::Set(values) => {
if values.is_empty() && !config.network.relay_mode {
Expand Down

0 comments on commit 58ab076

Please sign in to comment.