Merge branch 'develop' into feature/validator_health_checker
This commit is contained in:
@@ -7,7 +7,3 @@ jobs:
|
||||
allow_failures:
|
||||
- rust: nightly
|
||||
fast_finish: true
|
||||
|
||||
before_script:
|
||||
- git clone --depth=50 --branch=develop https://github.com/nymtech/sphinx.git /home/travis/build/nymtech/sphinx
|
||||
- ls
|
||||
|
||||
Generated
+957
-903
File diff suppressed because it is too large
Load Diff
@@ -6,6 +6,9 @@ members = [
|
||||
"clients/mix-client",
|
||||
"clients/provider-client",
|
||||
"clients/validator-client",
|
||||
"common/addressing",
|
||||
"common/crypto",
|
||||
"common/topology",
|
||||
"mixnode",
|
||||
"sfw-provider",
|
||||
"sfw-provider/sfw-provider-requests",
|
||||
|
||||
@@ -14,7 +14,7 @@ The platform is composed of multiple Rust crates. Top-level crates include:
|
||||
|
||||
#### Prerequisites
|
||||
|
||||
* Rust 1.39 or later. Stable works.
|
||||
* [Rust](https://www.rust-lang.org/tools/install) 1.39 or later. Stable works.
|
||||
* The `nym` platform repo (this one).
|
||||
* Checkout the [Sphinx](https://github.com/nymtech/sphinx) repo beside the `nym` repo.
|
||||
|
||||
@@ -23,17 +23,17 @@ Your directory structure should look like this:
|
||||
```
|
||||
$ tree -L 1
|
||||
├── nym
|
||||
│ ├── client
|
||||
│ ├── mixnode
|
||||
│ ├── README.md
|
||||
│ └── sfw-provider
|
||||
├── sphinx
|
||||
```
|
||||
|
||||
`cargo build` will build the software.
|
||||
Change directory in `nym` and then `cargo build` will build the software.
|
||||
|
||||
As with any other Rust project, there are other ways to build:
|
||||
|
||||
* `cargo build --release` will build an optimized release version for use in production
|
||||
* `cargo test` will run unit and integration tests for the crate (once)
|
||||
* `cargo watch -x test` will run tests whenever you change a file in the crate. Very handy in development.
|
||||
|
||||
Binaries can be found at `target/debug/` if you've done `cargo build` (without specifying `--release`).
|
||||
|
||||
Production binaries can be found at `target/release/` if you've done `cargo build --release`.
|
||||
|
||||
@@ -7,7 +7,8 @@ edition = "2018"
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
log = "0.4.8"
|
||||
tokio = { version = "0.2", features = ["full"] }
|
||||
|
||||
## will be moved to proper dependencies once released
|
||||
sphinx = { path = "../../../sphinx" }
|
||||
sphinx = { git = "https://github.com/nymtech/sphinx", rev="50ba6c4bbeb9be59257f32ff1e8f734e4fd82633" }
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
use log::*;
|
||||
use sphinx::SphinxPacket;
|
||||
use std::net::SocketAddr;
|
||||
use tokio::prelude::*;
|
||||
@@ -17,7 +18,7 @@ impl MixClient {
|
||||
) -> Result<(), Box<dyn std::error::Error>> {
|
||||
let bytes = packet.to_bytes();
|
||||
|
||||
println!("socket addr: {:?}", mix_addr);
|
||||
info!("socket addr: {:?}", mix_addr);
|
||||
|
||||
let mut stream = tokio::net::TcpStream::connect(mix_addr).await?;
|
||||
stream.write_all(&bytes[..]).await?;
|
||||
|
||||
@@ -16,8 +16,10 @@ base64 = "0.11.0"
|
||||
clap = "2.33.0"
|
||||
curve25519-dalek = "1.2.3"
|
||||
dirs = "2.0.2"
|
||||
env_logger = "0.7.1"
|
||||
futures = "0.3.1"
|
||||
hex = "0.4.0"
|
||||
log = "0.4.8"
|
||||
pem = "0.7.0"
|
||||
rand = "0.7.2"
|
||||
rand_distr = "0.2.2"
|
||||
@@ -29,6 +31,7 @@ tungstenite = "0.9.2"
|
||||
|
||||
## internal
|
||||
addressing = {path = "../../common/addressing" }
|
||||
crypto = {path = "../../common/crypto"}
|
||||
directory-client = { path = "../directory-client" }
|
||||
mix-client = { path = "../mix-client" }
|
||||
provider-client = { path = "../provider-client" }
|
||||
@@ -36,7 +39,7 @@ sfw-provider-requests = { path = "../../sfw-provider/sfw-provider-requests" }
|
||||
topology = {path = "../../common/topology" }
|
||||
|
||||
## will be moved to proper dependencies once released
|
||||
sphinx = { path = "../../../sphinx" }
|
||||
sphinx = { git = "https://github.com/nymtech/sphinx", rev="50ba6c4bbeb9be59257f32ff1e8f734e4fd82633" }
|
||||
|
||||
# putting this explicitly below everything and most likely, the next time we look into it, it will already have a proper release
|
||||
tokio-tungstenite = { git = "https://github.com/dbcfd/tokio-tungstenite", rev="6dc2018cbfe8fe7ddd75ff977343086503135b38" }
|
||||
|
||||
@@ -7,9 +7,12 @@ use futures::join;
|
||||
use futures::lock::Mutex as FMutex;
|
||||
use futures::select;
|
||||
use futures::{SinkExt, StreamExt};
|
||||
use log::*;
|
||||
use sfw_provider_requests::AuthToken;
|
||||
use sphinx::route::{Destination, DestinationAddressBytes};
|
||||
use sphinx::SphinxPacket;
|
||||
use std::io;
|
||||
use std::io::prelude::*;
|
||||
use std::net::SocketAddr;
|
||||
use std::sync::Arc;
|
||||
use std::time::Duration;
|
||||
@@ -39,14 +42,17 @@ impl MixTrafficController {
|
||||
async fn run(mut rx: mpsc::UnboundedReceiver<MixMessage>) {
|
||||
let mix_client = mix_client::MixClient::new();
|
||||
while let Some(mix_message) = rx.next().await {
|
||||
println!(
|
||||
info!(
|
||||
"[MIX TRAFFIC CONTROL] - got a mix_message for {:?}",
|
||||
mix_message.0
|
||||
);
|
||||
let send_res = mix_client.send(mix_message.1, mix_message.0).await;
|
||||
match send_res {
|
||||
Ok(_) => println!("We successfully sent the message!"),
|
||||
Err(e) => eprintln!("We failed to send the message :( - {:?}", e),
|
||||
Ok(_) => {
|
||||
print!(".");
|
||||
io::stdout().flush().ok().expect("Could not flush stdout");
|
||||
}
|
||||
Err(e) => error!("We failed to send the message :( - {:?}", e),
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -70,7 +76,7 @@ impl ReceivedMessagesBuffer {
|
||||
}
|
||||
|
||||
async fn add_new_messages(buf: Arc<FMutex<Self>>, msgs: Vec<Vec<u8>>) {
|
||||
println!("Adding new messages to the buffer! {:?}", msgs);
|
||||
info!("Adding new messages to the buffer! {:?}", msgs);
|
||||
let mut unlocked = buf.lock().await;
|
||||
unlocked.messages.extend(msgs);
|
||||
}
|
||||
@@ -150,7 +156,7 @@ impl NymClient {
|
||||
topology: Topology,
|
||||
) {
|
||||
loop {
|
||||
println!("[LOOP COVER TRAFFIC STREAM] - next cover message!");
|
||||
info!("[LOOP COVER TRAFFIC STREAM] - next cover message!");
|
||||
let delay = utils::poisson::sample(LOOP_COVER_AVERAGE_DELAY);
|
||||
let delay_duration = Duration::from_secs_f64(delay);
|
||||
tokio::time::delay_for(delay_duration).await;
|
||||
@@ -169,13 +175,13 @@ impl NymClient {
|
||||
topology: Topology,
|
||||
) {
|
||||
loop {
|
||||
println!("[OUT QUEUE] here I will be sending real traffic (or loop cover if nothing is available)");
|
||||
info!("[OUT QUEUE] here I will be sending real traffic (or loop cover if nothing is available)");
|
||||
// TODO: consider replacing select macro with our own proper future definition with polling
|
||||
let traffic_message = select! {
|
||||
real_message = input_rx.next() => {
|
||||
println!("[OUT QUEUE] - we got a real message!");
|
||||
info!("[OUT QUEUE] - we got a real message!");
|
||||
if real_message.is_none() {
|
||||
eprintln!("Unexpected 'None' real message!");
|
||||
error!("Unexpected 'None' real message!");
|
||||
std::process::exit(1);
|
||||
}
|
||||
let real_message = real_message.unwrap();
|
||||
@@ -184,7 +190,7 @@ impl NymClient {
|
||||
},
|
||||
|
||||
default => {
|
||||
println!("[OUT QUEUE] - no real message - going to send extra loop cover");
|
||||
info!("[OUT QUEUE] - no real message - going to send extra loop cover");
|
||||
utils::sphinx::loop_cover_message(our_info.address, our_info.identifier, &topology)
|
||||
}
|
||||
};
|
||||
@@ -208,7 +214,7 @@ impl NymClient {
|
||||
loop {
|
||||
let delay_duration = Duration::from_secs_f64(FETCH_MESSAGES_DELAY);
|
||||
tokio::time::delay_for(delay_duration).await;
|
||||
println!("[FETCH MSG] - Polling provider...");
|
||||
info!("[FETCH MSG] - Polling provider...");
|
||||
let messages = provider_client.retrieve_messages().await.unwrap();
|
||||
let good_messages = messages
|
||||
.into_iter()
|
||||
@@ -228,7 +234,7 @@ impl NymClient {
|
||||
let provider_client_listener_address: SocketAddr = topology
|
||||
.get_mix_provider_nodes()
|
||||
.first()
|
||||
.unwrap()
|
||||
.expect("Could not get a provider from the supplied network topology, are you using the right directory server?")
|
||||
.client_listener;
|
||||
|
||||
let mut provider_client = provider_client::ProviderClient::new(
|
||||
@@ -243,7 +249,7 @@ impl NymClient {
|
||||
None => {
|
||||
let auth_token = provider_client.register().await.unwrap();
|
||||
provider_client.update_token(auth_token);
|
||||
println!("Obtained new token! - {:?}", auth_token);
|
||||
info!("Obtained new token! - {:?}", auth_token);
|
||||
}
|
||||
Some(token) => println!("Already got the token! - {:?}", token),
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
use crate::banner;
|
||||
use crate::identity::mixnet;
|
||||
use crate::persistence::pathfinder::Pathfinder;
|
||||
use crate::persistence::pemstore::PemStore;
|
||||
use clap::ArgMatches;
|
||||
use crypto::identity::MixnetIdentityKeyPair;
|
||||
|
||||
pub fn execute(matches: &ArgMatches) {
|
||||
println!("{}", banner());
|
||||
@@ -12,9 +12,9 @@ pub fn execute(matches: &ArgMatches) {
|
||||
let pathfinder = Pathfinder::new(id);
|
||||
|
||||
println!("Writing keypairs to {:?}...", pathfinder.config_dir);
|
||||
let mix_keys = mixnet::KeyPair::new();
|
||||
let mix_keys = crypto::identity::DummyMixIdentityKeyPair::new();
|
||||
let pem_store = PemStore::new(pathfinder);
|
||||
pem_store.write(mix_keys);
|
||||
pem_store.write_identity(mix_keys);
|
||||
|
||||
println!("Client configuration completed.\n\n\n")
|
||||
}
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
pub mod init;
|
||||
pub mod run;
|
||||
pub mod tcpsocket;
|
||||
pub mod websocket;
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
use crate::banner;
|
||||
//use crate::clients::NymClient;
|
||||
//use crate::persistence::pemstore;
|
||||
use clap::ArgMatches;
|
||||
|
||||
pub fn execute(_matches: &ArgMatches) {
|
||||
println!("{}", banner());
|
||||
panic!("For time being this command is deprecated! Please use 'websocket' instead");
|
||||
//
|
||||
// let is_local = matches.is_present("local");
|
||||
// let id = matches.value_of("id").unwrap().to_string();
|
||||
// println!("Starting client...");
|
||||
//
|
||||
// let keypair = pemstore::read_keypair_from_disk(id);
|
||||
// let client = NymClient::new(keypair.public_bytes(), is_local);
|
||||
// client.start("127.0.0.1:9000".parse().unwrap()).unwrap();
|
||||
}
|
||||
@@ -3,6 +3,7 @@ use crate::clients::{NymClient, SocketType};
|
||||
use crate::persistence::pemstore;
|
||||
|
||||
use clap::ArgMatches;
|
||||
use crypto::identity::{MixnetIdentityKeyPair, MixnetIdentityPublicKey};
|
||||
use std::net::ToSocketAddrs;
|
||||
|
||||
pub fn execute(matches: &ArgMatches) {
|
||||
@@ -28,11 +29,15 @@ pub fn execute(matches: &ArgMatches) {
|
||||
.next()
|
||||
.expect("Failed to extract the socket address from the iterator");
|
||||
|
||||
let keypair = pemstore::read_keypair_from_disk(id);
|
||||
let auth_token = None;
|
||||
let keypair = pemstore::read_mix_identity_keypair_from_disk(id);
|
||||
// TODO: reading auth_token from disk (if exists);
|
||||
|
||||
let mut temporary_address = [0u8; 32];
|
||||
let public_key_bytes = keypair.public_key().to_bytes();
|
||||
temporary_address.copy_from_slice(&public_key_bytes[..]);
|
||||
let auth_token = None;
|
||||
let client = NymClient::new(
|
||||
keypair.public_bytes(),
|
||||
temporary_address,
|
||||
socket_address.clone(),
|
||||
directory_server,
|
||||
auth_token,
|
||||
|
||||
@@ -3,6 +3,7 @@ use crate::clients::{NymClient, SocketType};
|
||||
use crate::persistence::pemstore;
|
||||
|
||||
use clap::ArgMatches;
|
||||
use crypto::identity::{MixnetIdentityKeyPair, MixnetIdentityPublicKey};
|
||||
use std::net::ToSocketAddrs;
|
||||
|
||||
pub fn execute(matches: &ArgMatches) {
|
||||
@@ -28,11 +29,15 @@ pub fn execute(matches: &ArgMatches) {
|
||||
.next()
|
||||
.expect("Failed to extract the socket address from the iterator");
|
||||
|
||||
let keypair = pemstore::read_keypair_from_disk(id);
|
||||
let keypair = pemstore::read_mix_identity_keypair_from_disk(id);
|
||||
// TODO: reading auth_token from disk (if exists);
|
||||
|
||||
let mut temporary_address = [0u8; 32];
|
||||
let public_key_bytes = keypair.public_key().to_bytes();
|
||||
temporary_address.copy_from_slice(&public_key_bytes[..]);
|
||||
let auth_token = None;
|
||||
let client = NymClient::new(
|
||||
keypair.public_bytes(),
|
||||
temporary_address,
|
||||
socket_address,
|
||||
directory_server,
|
||||
auth_token,
|
||||
|
||||
@@ -1,33 +0,0 @@
|
||||
use curve25519_dalek::montgomery::MontgomeryPoint;
|
||||
use curve25519_dalek::scalar::Scalar;
|
||||
|
||||
// This keypair serves as the user's identity within the Mixnet
|
||||
pub struct KeyPair {
|
||||
pub private: Scalar,
|
||||
pub public: MontgomeryPoint,
|
||||
}
|
||||
|
||||
impl KeyPair {
|
||||
pub fn new() -> KeyPair {
|
||||
let (private, public) = sphinx::crypto::keygen();
|
||||
KeyPair { private, public }
|
||||
}
|
||||
|
||||
pub fn from_bytes(private_bytes: Vec<u8>, public_bytes: Vec<u8>) -> KeyPair {
|
||||
let mut bytes = [0; 32];
|
||||
bytes.copy_from_slice(&private_bytes[..]);
|
||||
let private = Scalar::from_canonical_bytes(bytes).unwrap();
|
||||
let mut bytes = [0; 32];
|
||||
bytes.copy_from_slice(&public_bytes[..]);
|
||||
let public = MontgomeryPoint(bytes);
|
||||
KeyPair { private, public }
|
||||
}
|
||||
|
||||
pub fn private_bytes(&self) -> [u8; 32] {
|
||||
self.private.to_bytes()
|
||||
}
|
||||
|
||||
pub fn public_bytes(&self) -> [u8; 32] {
|
||||
self.public.to_bytes()
|
||||
}
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
pub mod mixnet;
|
||||
@@ -1 +0,0 @@
|
||||
// TODO types for Validator keys will go in here once we hook this up.
|
||||
@@ -1,7 +1,6 @@
|
||||
#![recursion_limit = "256"]
|
||||
|
||||
pub mod clients;
|
||||
pub mod identity;
|
||||
pub mod persistence;
|
||||
pub mod sockets;
|
||||
pub mod utils;
|
||||
|
||||
@@ -1,16 +1,19 @@
|
||||
#![recursion_limit = "256"]
|
||||
|
||||
use clap::{App, Arg, ArgMatches, SubCommand};
|
||||
use env_logger;
|
||||
use log::*;
|
||||
use std::process;
|
||||
|
||||
pub mod clients;
|
||||
mod commands;
|
||||
mod identity;
|
||||
mod persistence;
|
||||
mod sockets;
|
||||
pub mod utils;
|
||||
|
||||
fn main() {
|
||||
env_logger::init();
|
||||
|
||||
let arg_matches = App::new("Nym Client")
|
||||
.version(built_info::PKG_VERSION)
|
||||
.author("Nymtech")
|
||||
@@ -30,22 +33,6 @@ fn main() {
|
||||
.takes_value(true)
|
||||
)
|
||||
)
|
||||
.subcommand(
|
||||
SubCommand::with_name("run")
|
||||
.about("Run a persistent Nym client process")
|
||||
.arg(Arg::with_name("id")
|
||||
.long("id")
|
||||
.help("Id of the nym-mixnet-client we want to run.")
|
||||
.takes_value(true)
|
||||
.required(true)
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name("directory")
|
||||
.long("directory")
|
||||
.help("Address of the directory server the client is getting topology from")
|
||||
.takes_value(true),
|
||||
)
|
||||
)
|
||||
.subcommand(
|
||||
SubCommand::with_name("tcpsocket")
|
||||
.about("Run Nym client that listens for bytes on a TCP socket")
|
||||
@@ -96,7 +83,7 @@ fn main() {
|
||||
.get_matches();
|
||||
|
||||
if let Err(e) = execute(arg_matches) {
|
||||
println!("{}", e);
|
||||
error!("{}", e);
|
||||
process::exit(1);
|
||||
}
|
||||
}
|
||||
@@ -109,7 +96,6 @@ pub mod built_info {
|
||||
fn execute(matches: ArgMatches) -> Result<(), String> {
|
||||
match matches.subcommand() {
|
||||
("init", Some(m)) => Ok(commands::init::execute(m)),
|
||||
("run", Some(m)) => Ok(commands::run::execute(m)),
|
||||
("tcpsocket", Some(m)) => Ok(commands::tcpsocket::execute(m)),
|
||||
("websocket", Some(m)) => Ok(commands::websocket::execute(m)),
|
||||
_ => Err(usage()),
|
||||
|
||||
@@ -1,17 +1,22 @@
|
||||
use crate::identity::mixnet::KeyPair;
|
||||
use crate::persistence::pathfinder::Pathfinder;
|
||||
use pem::{encode, parse, Pem};
|
||||
use std::fs::File;
|
||||
use std::io::prelude::*;
|
||||
use std::path::PathBuf;
|
||||
|
||||
pub fn read_keypair_from_disk(id: String) -> KeyPair {
|
||||
pub fn read_mix_identity_keypair_from_disk(
|
||||
id: String,
|
||||
) -> crypto::identity::DummyMixIdentityKeyPair {
|
||||
let pathfinder = Pathfinder::new(id);
|
||||
let pem_store = PemStore::new(pathfinder);
|
||||
let keypair = pem_store.read();
|
||||
let keypair = pem_store.read_identity();
|
||||
keypair
|
||||
}
|
||||
|
||||
pub fn read_mix_encryption_keypair_from_disk(id: String) -> crypto::encryption::x25519::KeyPair {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
pub struct PemStore {
|
||||
config_dir: PathBuf,
|
||||
private_mix_key: PathBuf,
|
||||
@@ -27,42 +32,62 @@ impl PemStore {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn read(&self) -> KeyPair {
|
||||
let private = self.read_file(self.private_mix_key.clone());
|
||||
let public = self.read_file(self.public_mix_key.clone());
|
||||
pub fn read_identity<IDPair, Priv, Pub>(&self) -> IDPair
|
||||
where
|
||||
IDPair: crypto::identity::MixnetIdentityKeyPair<Priv, Pub>,
|
||||
Priv: crypto::identity::MixnetIdentityPrivateKey,
|
||||
Pub: crypto::identity::MixnetIdentityPublicKey,
|
||||
{
|
||||
let private_pem = self.read_pem_file(self.private_mix_key.clone());
|
||||
let public_pem = self.read_pem_file(self.public_mix_key.clone());
|
||||
|
||||
KeyPair::from_bytes(private, public)
|
||||
let key_pair = IDPair::from_bytes(&private_pem.contents, &public_pem.contents);
|
||||
|
||||
assert_eq!(key_pair.private_key().pem_type(), private_pem.tag);
|
||||
assert_eq!(key_pair.public_key().pem_type(), public_pem.tag);
|
||||
|
||||
key_pair
|
||||
}
|
||||
|
||||
fn read_file(&self, filepath: PathBuf) -> Vec<u8> {
|
||||
let mut pem_bytes = File::open(filepath).unwrap();
|
||||
fn read_pem_file(&self, filepath: PathBuf) -> Pem {
|
||||
let mut pem_bytes = File::open(filepath).expect("Could not open stored keys from disk.");
|
||||
let mut buf = Vec::new();
|
||||
pem_bytes.read_to_end(&mut buf).unwrap();
|
||||
let pem = parse(&buf).unwrap();
|
||||
pem.contents
|
||||
pem_bytes
|
||||
.read_to_end(&mut buf)
|
||||
.expect("PEM bytes reading failed.");
|
||||
let pem = parse(&buf).expect("PEM parsing failed while reading keys");
|
||||
|
||||
pem
|
||||
}
|
||||
// This should be refactored and made more generic for when we have other kinds of
|
||||
// KeyPairs that we want to persist (e.g. validator keypairs, or keys for
|
||||
// signing vs encryption). However, for the moment, it does the job.
|
||||
pub fn write(&self, key_pair: KeyPair) {
|
||||
pub fn write_identity<IDPair, Priv, Pub>(&self, key_pair: IDPair)
|
||||
where
|
||||
IDPair: crypto::identity::MixnetIdentityKeyPair<Priv, Pub>,
|
||||
Priv: crypto::identity::MixnetIdentityPrivateKey,
|
||||
Pub: crypto::identity::MixnetIdentityPublicKey,
|
||||
{
|
||||
std::fs::create_dir_all(self.config_dir.clone()).unwrap();
|
||||
|
||||
let private_key = key_pair.private_key();
|
||||
let public_key = key_pair.public_key();
|
||||
self.write_pem_file(
|
||||
self.private_mix_key.clone(),
|
||||
key_pair.private_bytes(),
|
||||
String::from("SPHINX CURVE25519 PRIVATE KEY"),
|
||||
private_key.to_bytes(),
|
||||
private_key.pem_type(),
|
||||
);
|
||||
self.write_pem_file(
|
||||
self.public_mix_key.clone(),
|
||||
key_pair.public_bytes(),
|
||||
String::from("SPHINX CURVE25519 PUBLIC KEY"),
|
||||
public_key.to_bytes(),
|
||||
public_key.pem_type(),
|
||||
);
|
||||
}
|
||||
|
||||
fn write_pem_file(&self, filepath: PathBuf, data: [u8; 32], tag: String) {
|
||||
fn write_pem_file(&self, filepath: PathBuf, data: Vec<u8>, tag: String) {
|
||||
let pem = Pem {
|
||||
tag,
|
||||
contents: data.to_vec(),
|
||||
contents: data,
|
||||
};
|
||||
let key = encode(&pem);
|
||||
|
||||
|
||||
@@ -34,7 +34,7 @@ pub fn encapsulate_message<T: NymTopology>(
|
||||
let packet = sphinx::SphinxPacket::new(message, &route[..], &recipient, &delays).unwrap();
|
||||
|
||||
let first_node_address =
|
||||
addressing::socket_address_from_encoded_bytes(route.first().unwrap().address);
|
||||
addressing::socket_address_from_encoded_bytes(route.first().unwrap().address.to_bytes());
|
||||
|
||||
(first_node_address, packet)
|
||||
}
|
||||
|
||||
@@ -8,10 +8,11 @@ edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
futures = "0.3.1"
|
||||
log = "0.4.8"
|
||||
tokio = { version = "0.2", features = ["full"] }
|
||||
|
||||
## internal
|
||||
sfw-provider-requests = { path = "../../sfw-provider/sfw-provider-requests" }
|
||||
|
||||
## will be moved to proper dependencies once released
|
||||
sphinx = { path = "../../../sphinx" }
|
||||
sphinx = { git = "https://github.com/nymtech/sphinx", rev="50ba6c4bbeb9be59257f32ff1e8f734e4fd82633" }
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
use futures::io::Error;
|
||||
use log::info;
|
||||
use sfw_provider_requests::requests::{ProviderRequest, PullRequest, RegisterRequest};
|
||||
use sfw_provider_requests::responses::{
|
||||
ProviderResponse, ProviderResponseError, PullResponse, RegisterResponse,
|
||||
@@ -64,7 +65,7 @@ impl ProviderClient {
|
||||
|
||||
pub async fn send_request(&self, bytes: Vec<u8>) -> Result<Vec<u8>, ProviderClientError> {
|
||||
let mut socket = tokio::net::TcpStream::connect(self.provider_network_address).await?;
|
||||
println!("keep alive: {:?}", socket.keepalive());
|
||||
info!("keep alive: {:?}", socket.keepalive());
|
||||
socket.set_keepalive(Some(Duration::from_secs(2))).unwrap();
|
||||
socket.write_all(&bytes[..]).await?;
|
||||
if let Err(_e) = socket.shutdown(Shutdown::Write) {
|
||||
@@ -91,7 +92,7 @@ impl ProviderClient {
|
||||
let bytes = pull_request.to_bytes();
|
||||
|
||||
let response = self.send_request(bytes).await?;
|
||||
println!("Received the following response: {:?}", response);
|
||||
info!("Received the following response: {:?}", response);
|
||||
|
||||
let parsed_response = PullResponse::from_bytes(&response)?;
|
||||
Ok(parsed_response.messages)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
[package]
|
||||
name = "addressing"
|
||||
version = "0.1.0"
|
||||
authors = ["Jedrzej Stuczynski <jedrzej.stuczynski@gmail.com>"]
|
||||
authors = ["Jedrzej Stuczynski <andrew@nymtech.net>"]
|
||||
edition = "2018"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
[package]
|
||||
name = "crypto"
|
||||
version = "0.1.0"
|
||||
authors = ["Jedrzej Stuczynski <andrew@nymtech.net"]
|
||||
edition = "2018"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
base64 = "0.11.0"
|
||||
curve25519-dalek = "1.2.3"
|
||||
rand = "0.7.2"
|
||||
rand_os = "0.1"
|
||||
@@ -0,0 +1,39 @@
|
||||
use crate::PemStorable;
|
||||
|
||||
pub mod x25519;
|
||||
|
||||
pub trait MixnetEncryptionKeyPair<Priv, Pub>
|
||||
where
|
||||
Priv: MixnetEncryptionPrivateKey,
|
||||
Pub: MixnetEncryptionPublicKey,
|
||||
{
|
||||
fn new() -> Self;
|
||||
fn private_key(&self) -> &Priv;
|
||||
fn public_key(&self) -> &Pub;
|
||||
fn from_bytes(priv_bytes: &[u8], pub_bytes: &[u8]) -> Self;
|
||||
|
||||
// TODO: encryption related methods
|
||||
}
|
||||
|
||||
pub trait MixnetEncryptionPublicKey:
|
||||
Sized + PemStorable + for<'a> From<&'a <Self as MixnetEncryptionPublicKey>::PrivateKeyMaterial>
|
||||
{
|
||||
// we need to couple public and private keys together
|
||||
type PrivateKeyMaterial: MixnetEncryptionPrivateKey<PublicKeyMaterial = Self>;
|
||||
|
||||
fn to_bytes(&self) -> Vec<u8>;
|
||||
fn from_bytes(b: &[u8]) -> Self;
|
||||
}
|
||||
|
||||
pub trait MixnetEncryptionPrivateKey: Sized + PemStorable {
|
||||
// we need to couple public and private keys together
|
||||
type PublicKeyMaterial: MixnetEncryptionPublicKey<PrivateKeyMaterial = Self>;
|
||||
|
||||
/// Returns the associated public key
|
||||
fn public_key(&self) -> Self::PublicKeyMaterial {
|
||||
self.into()
|
||||
}
|
||||
|
||||
fn to_bytes(&self) -> Vec<u8>;
|
||||
fn from_bytes(b: &[u8]) -> Self;
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
use crate::encryption::{
|
||||
MixnetEncryptionKeyPair, MixnetEncryptionPrivateKey, MixnetEncryptionPublicKey,
|
||||
};
|
||||
use crate::PemStorable;
|
||||
use curve25519_dalek::montgomery::MontgomeryPoint;
|
||||
use curve25519_dalek::scalar::Scalar;
|
||||
|
||||
// TODO: ensure this is a proper name for this considering we are not implementing entire DH here
|
||||
|
||||
const CURVE_GENERATOR: MontgomeryPoint = curve25519_dalek::constants::X25519_BASEPOINT;
|
||||
|
||||
pub struct KeyPair {
|
||||
pub(crate) private_key: PrivateKey,
|
||||
pub(crate) public_key: PublicKey,
|
||||
}
|
||||
|
||||
impl MixnetEncryptionKeyPair<PrivateKey, PublicKey> for KeyPair {
|
||||
fn new() -> Self {
|
||||
let mut rng = rand_os::OsRng::new().unwrap();
|
||||
let private_key_value = Scalar::random(&mut rng);
|
||||
let public_key_value = CURVE_GENERATOR * private_key_value;
|
||||
|
||||
KeyPair {
|
||||
private_key: PrivateKey(private_key_value),
|
||||
public_key: PublicKey(public_key_value),
|
||||
}
|
||||
}
|
||||
|
||||
fn private_key(&self) -> &PrivateKey {
|
||||
&self.private_key
|
||||
}
|
||||
|
||||
fn public_key(&self) -> &PublicKey {
|
||||
&self.public_key
|
||||
}
|
||||
|
||||
fn from_bytes(priv_bytes: &[u8], pub_bytes: &[u8]) -> Self {
|
||||
KeyPair {
|
||||
private_key: PrivateKey::from_bytes(priv_bytes),
|
||||
public_key: PublicKey::from_bytes(pub_bytes),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// COPY IS DERIVED ONLY TEMPORARILY UNTIL https://github.com/nymtech/nym/issues/47 is fixed
|
||||
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
|
||||
pub struct PrivateKey(pub Scalar);
|
||||
|
||||
impl MixnetEncryptionPrivateKey for PrivateKey {
|
||||
type PublicKeyMaterial = PublicKey;
|
||||
|
||||
fn to_bytes(&self) -> Vec<u8> {
|
||||
self.0.to_bytes().to_vec()
|
||||
}
|
||||
|
||||
fn from_bytes(b: &[u8]) -> Self {
|
||||
let mut bytes = [0; 32];
|
||||
bytes.copy_from_slice(&b[..]);
|
||||
let key = Scalar::from_canonical_bytes(bytes).unwrap();
|
||||
Self(key)
|
||||
}
|
||||
}
|
||||
|
||||
impl PemStorable for PrivateKey {
|
||||
fn pem_type(&self) -> String {
|
||||
String::from("X25519 PRIVATE KEY")
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Eq, PartialEq)]
|
||||
pub struct PublicKey(pub MontgomeryPoint);
|
||||
|
||||
impl<'a> From<&'a PrivateKey> for PublicKey {
|
||||
fn from(pk: &'a PrivateKey) -> Self {
|
||||
PublicKey(CURVE_GENERATOR * pk.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl MixnetEncryptionPublicKey for PublicKey {
|
||||
type PrivateKeyMaterial = PrivateKey;
|
||||
|
||||
fn to_bytes(&self) -> Vec<u8> {
|
||||
self.0.to_bytes().to_vec()
|
||||
}
|
||||
|
||||
fn from_bytes(b: &[u8]) -> Self {
|
||||
let mut bytes = [0; 32];
|
||||
bytes.copy_from_slice(&b[..]);
|
||||
let key = MontgomeryPoint(bytes);
|
||||
Self(key)
|
||||
}
|
||||
}
|
||||
|
||||
impl PemStorable for PublicKey {
|
||||
fn pem_type(&self) -> String {
|
||||
String::from("X25519 PUBLIC KEY")
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,147 @@
|
||||
use crate::encryption::{
|
||||
MixnetEncryptionKeyPair, MixnetEncryptionPrivateKey, MixnetEncryptionPublicKey,
|
||||
};
|
||||
use crate::{encryption, PemStorable};
|
||||
use curve25519_dalek::scalar::Scalar;
|
||||
|
||||
pub trait MixnetIdentityKeyPair<Priv, Pub>
|
||||
where
|
||||
Priv: MixnetIdentityPrivateKey,
|
||||
Pub: MixnetIdentityPublicKey,
|
||||
{
|
||||
fn new() -> Self;
|
||||
fn private_key(&self) -> &Priv;
|
||||
fn public_key(&self) -> &Pub;
|
||||
fn from_bytes(priv_bytes: &[u8], pub_bytes: &[u8]) -> Self;
|
||||
|
||||
// TODO: signing related methods
|
||||
}
|
||||
|
||||
pub trait MixnetIdentityPublicKey:
|
||||
Sized + PemStorable + for<'a> From<&'a <Self as MixnetIdentityPublicKey>::PrivateKeyMaterial>
|
||||
{
|
||||
// we need to couple public and private keys together
|
||||
type PrivateKeyMaterial: MixnetIdentityPrivateKey<PublicKeyMaterial = Self>;
|
||||
|
||||
fn to_bytes(&self) -> Vec<u8>;
|
||||
fn from_bytes(b: &[u8]) -> Self;
|
||||
}
|
||||
|
||||
pub trait MixnetIdentityPrivateKey: Sized + PemStorable {
|
||||
// we need to couple public and private keys together
|
||||
type PublicKeyMaterial: MixnetIdentityPublicKey<PrivateKeyMaterial = Self>;
|
||||
|
||||
/// Returns the associated public key
|
||||
fn public_key(&self) -> Self::PublicKeyMaterial {
|
||||
self.into()
|
||||
}
|
||||
|
||||
fn to_bytes(&self) -> Vec<u8>;
|
||||
fn from_bytes(b: &[u8]) -> Self;
|
||||
}
|
||||
|
||||
// same for validator
|
||||
|
||||
// for time being define a dummy identity using x25519 encryption keys (as we've done so far)
|
||||
// and replace it with proper keys, like ed25519 later on
|
||||
|
||||
pub struct DummyMixIdentityKeyPair {
|
||||
pub private_key: DummyMixIdentityPrivateKey,
|
||||
pub public_key: DummyMixIdentityPublicKey,
|
||||
}
|
||||
|
||||
impl MixnetIdentityKeyPair<DummyMixIdentityPrivateKey, DummyMixIdentityPublicKey>
|
||||
for DummyMixIdentityKeyPair
|
||||
{
|
||||
fn new() -> Self {
|
||||
let keypair = encryption::x25519::KeyPair::new();
|
||||
DummyMixIdentityKeyPair {
|
||||
private_key: DummyMixIdentityPrivateKey(keypair.private_key),
|
||||
public_key: DummyMixIdentityPublicKey(keypair.public_key),
|
||||
}
|
||||
}
|
||||
|
||||
fn private_key(&self) -> &DummyMixIdentityPrivateKey {
|
||||
&self.private_key
|
||||
}
|
||||
|
||||
fn public_key(&self) -> &DummyMixIdentityPublicKey {
|
||||
&self.public_key
|
||||
}
|
||||
|
||||
fn from_bytes(priv_bytes: &[u8], pub_bytes: &[u8]) -> Self {
|
||||
DummyMixIdentityKeyPair {
|
||||
private_key: DummyMixIdentityPrivateKey::from_bytes(priv_bytes),
|
||||
public_key: DummyMixIdentityPublicKey::from_bytes(pub_bytes),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Eq, PartialEq)]
|
||||
pub struct DummyMixIdentityPublicKey(encryption::x25519::PublicKey);
|
||||
|
||||
impl MixnetIdentityPublicKey for DummyMixIdentityPublicKey {
|
||||
type PrivateKeyMaterial = DummyMixIdentityPrivateKey;
|
||||
|
||||
fn to_bytes(&self) -> Vec<u8> {
|
||||
self.0.to_bytes()
|
||||
}
|
||||
|
||||
fn from_bytes(b: &[u8]) -> Self {
|
||||
Self(encryption::x25519::PublicKey::from_bytes(b))
|
||||
}
|
||||
}
|
||||
|
||||
impl PemStorable for DummyMixIdentityPublicKey {
|
||||
fn pem_type(&self) -> String {
|
||||
format!("DUMMY KEY BASED ON {}", self.0.pem_type())
|
||||
}
|
||||
}
|
||||
|
||||
impl DummyMixIdentityPublicKey {
|
||||
pub fn to_b64_string(&self) -> String {
|
||||
base64::encode_config(&self.to_bytes(), base64::URL_SAFE)
|
||||
}
|
||||
|
||||
fn from_b64_string(val: String) -> Self {
|
||||
Self::from_bytes(&base64::decode_config(&val, base64::URL_SAFE).unwrap())
|
||||
}
|
||||
}
|
||||
|
||||
// COPY IS DERIVED ONLY TEMPORARILY UNTIL https://github.com/nymtech/nym/issues/47 is fixed
|
||||
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
|
||||
pub struct DummyMixIdentityPrivateKey(pub encryption::x25519::PrivateKey);
|
||||
|
||||
impl<'a> From<&'a DummyMixIdentityPrivateKey> for DummyMixIdentityPublicKey {
|
||||
fn from(pk: &'a DummyMixIdentityPrivateKey) -> Self {
|
||||
let private_ref = &pk.0;
|
||||
let public: encryption::x25519::PublicKey = private_ref.into();
|
||||
DummyMixIdentityPublicKey(public)
|
||||
}
|
||||
}
|
||||
|
||||
impl MixnetIdentityPrivateKey for DummyMixIdentityPrivateKey {
|
||||
type PublicKeyMaterial = DummyMixIdentityPublicKey;
|
||||
|
||||
fn to_bytes(&self) -> Vec<u8> {
|
||||
self.0.to_bytes()
|
||||
}
|
||||
|
||||
fn from_bytes(b: &[u8]) -> Self {
|
||||
Self(encryption::x25519::PrivateKey::from_bytes(b))
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: this will be implemented differently by using the proper trait
|
||||
impl DummyMixIdentityPrivateKey {
|
||||
pub fn as_scalar(self) -> Scalar {
|
||||
let encryption_key = self.0;
|
||||
encryption_key.0
|
||||
}
|
||||
}
|
||||
|
||||
impl PemStorable for DummyMixIdentityPrivateKey {
|
||||
fn pem_type(&self) -> String {
|
||||
format!("DUMMY KEY BASED ON {}", self.0.pem_type())
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
pub mod encryption;
|
||||
pub mod identity;
|
||||
|
||||
// TODO: this trait will need to be moved elsewhere, probably to some 'persistence' crate
|
||||
// but since it will need to be used by all identities, it's not really appropriate if it lived in nym-client
|
||||
|
||||
pub trait PemStorable {
|
||||
fn pem_type(&self) -> String;
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
[package]
|
||||
name = "topology"
|
||||
version = "0.1.0"
|
||||
authors = ["Jedrzej Stuczynski <andrew@nymtech.net"]
|
||||
authors = ["Jedrzej Stuczynski <andrew@nymtech.net>"]
|
||||
edition = "2018"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
@@ -18,4 +18,4 @@ serde = { version = "1.0.104", features = ["derive"] }
|
||||
addressing = {path = "../addressing"}
|
||||
|
||||
## will be moved to proper dependencies once released
|
||||
sphinx = { path = "../../../sphinx" }
|
||||
sphinx = { git = "https://github.com/nymtech/sphinx", rev="50ba6c4bbeb9be59257f32ff1e8f734e4fd82633" }
|
||||
|
||||
@@ -2,7 +2,7 @@ use addressing;
|
||||
use curve25519_dalek::montgomery::MontgomeryPoint;
|
||||
use itertools::Itertools;
|
||||
use rand::seq::IteratorRandom;
|
||||
use sphinx::route::Node as SphinxNode;
|
||||
use sphinx::route::{Node as SphinxNode, NodeAddressBytes};
|
||||
use std::cmp::max;
|
||||
use std::collections::HashMap;
|
||||
use std::net::SocketAddr;
|
||||
@@ -24,7 +24,7 @@ impl Into<SphinxNode> for MixNode {
|
||||
key_bytes.copy_from_slice(&decoded_key_bytes[..]);
|
||||
let key = MontgomeryPoint(key_bytes);
|
||||
|
||||
SphinxNode::new(address_bytes, key)
|
||||
SphinxNode::new(NodeAddressBytes::from_bytes(address_bytes), key)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -51,7 +51,7 @@ impl Into<SphinxNode> for MixProviderNode {
|
||||
key_bytes.copy_from_slice(&decoded_key_bytes[..]);
|
||||
let key = MontgomeryPoint(key_bytes);
|
||||
|
||||
SphinxNode::new(address_bytes, key)
|
||||
SphinxNode::new(NodeAddressBytes::from_bytes(address_bytes), key)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -19,7 +19,7 @@ addressing = {path = "../common/addressing" }
|
||||
directory-client = { path = "../clients/directory-client" }
|
||||
|
||||
## will be moved to proper dependencies once released
|
||||
sphinx = { path = "../../sphinx" }
|
||||
sphinx = { git = "https://github.com/nymtech/sphinx", rev="50ba6c4bbeb9be59257f32ff1e8f734e4fd82633" }
|
||||
|
||||
[build-dependencies]
|
||||
built = "0.3.2"
|
||||
|
||||
+1
-17
@@ -2,26 +2,10 @@
|
||||
|
||||
A Rust mixnode implementation.
|
||||
|
||||
## Building
|
||||
|
||||
* check out the code
|
||||
* [install rust](https://www.rust-lang.org/tools/install) (stable)
|
||||
* `cargo build --release` (for a production build)
|
||||
|
||||
The built binary can be found at `target/release/nym-mixnode`
|
||||
|
||||
## Usage
|
||||
|
||||
* `nym-mixnode` prints a help message showing usage options
|
||||
* `nym-mixnode run --help` prints a help message showing usage options for the run command
|
||||
* `nym-mixnode run --layer 1` will start the mixnode in layer 1 (coordinate with other people to find out which layer you need to start yours in)
|
||||
* `nym-mixnode run --layer 1 --host x.x.x.x` will start the mixnode in layer 1 and bind to the specified host IP address. Coordinate with other people in your network to find out which layer needs coverage.
|
||||
|
||||
By default, the Nym Mixnode will start on port 1789. If desired, you can change the port using the `--port` option.
|
||||
|
||||
### Dependencies
|
||||
|
||||
It's important to download the following repositories before building the mixnode:
|
||||
|
||||
* https://github.com/nymtech/nym-client
|
||||
* https://github.com/nymtech/nym-sfw-provider
|
||||
* https://github.com/nymtech/sphinx
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
use addressing;
|
||||
use sphinx::route::NodeAddressBytes;
|
||||
use std::error::Error;
|
||||
use std::net::SocketAddr;
|
||||
use tokio::prelude::*;
|
||||
@@ -10,9 +11,9 @@ pub struct MixPeer {
|
||||
|
||||
impl MixPeer {
|
||||
// note that very soon `next_hop_address` will be changed to `next_hop_metadata`
|
||||
pub fn new(next_hop_address: [u8; 32]) -> MixPeer {
|
||||
pub fn new(next_hop_address: NodeAddressBytes) -> MixPeer {
|
||||
let next_hop_socket_address =
|
||||
addressing::socket_address_from_encoded_bytes(next_hop_address);
|
||||
addressing::socket_address_from_encoded_bytes(next_hop_address.to_bytes());
|
||||
MixPeer {
|
||||
connection: next_hop_socket_address,
|
||||
}
|
||||
|
||||
@@ -21,12 +21,12 @@ serde_json = "1.0.44"
|
||||
hmac = "0.7.1"
|
||||
|
||||
## internal
|
||||
crypto = {path = "../common/crypto"}
|
||||
directory-client = { path = "../clients/directory-client" }
|
||||
nym-client = { path = "../clients/nym-client" } # TODO: this is only due to dependecy on 'KeyPair'. Perhaps identity should be moved into own crate?
|
||||
sfw-provider-requests = { path = "./sfw-provider-requests" }
|
||||
|
||||
## will be moved to proper dependencies once released
|
||||
sphinx = { path = "../../sphinx" }
|
||||
sphinx = { git = "https://github.com/nymtech/sphinx", rev="50ba6c4bbeb9be59257f32ff1e8f734e4fd82633" }
|
||||
|
||||
[build-dependencies]
|
||||
built = "0.3.2"
|
||||
|
||||
@@ -7,4 +7,4 @@ edition = "2018"
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
sphinx = { path = "../../../sphinx" }
|
||||
sphinx = { git = "https://github.com/nymtech/sphinx", rev="50ba6c4bbeb9be59257f32ff1e8f734e4fd82633" }
|
||||
|
||||
+10
-22
@@ -1,6 +1,6 @@
|
||||
use crate::provider::ServiceProvider;
|
||||
use clap::{App, Arg, ArgMatches, SubCommand};
|
||||
use nym_client::identity::mixnet::KeyPair;
|
||||
use crypto::identity::{MixnetIdentityKeyPair, MixnetIdentityPrivateKey, MixnetIdentityPublicKey};
|
||||
use std::net::ToSocketAddrs;
|
||||
use std::path::PathBuf;
|
||||
use std::process;
|
||||
@@ -71,15 +71,14 @@ fn main() {
|
||||
}
|
||||
|
||||
fn run(matches: &ArgMatches) {
|
||||
println!("{}", banner());
|
||||
let config = new_config(matches);
|
||||
let provider = ServiceProvider::new(&config);
|
||||
let provider = ServiceProvider::new(config);
|
||||
|
||||
provider.start().unwrap()
|
||||
}
|
||||
|
||||
fn new_config(matches: &ArgMatches) -> provider::Config {
|
||||
println!("Running the service provider!");
|
||||
|
||||
let directory_server = matches
|
||||
.value_of("directory")
|
||||
.unwrap_or("https://directory.nymtech.net")
|
||||
@@ -101,7 +100,7 @@ fn new_config(matches: &ArgMatches) -> provider::Config {
|
||||
Err(err) => panic!("Invalid client port value provided - {:?}", err),
|
||||
};
|
||||
|
||||
let key_pair = KeyPair::new(); // TODO: persist this so keypairs don't change every restart
|
||||
let key_pair = crypto::identity::DummyMixIdentityKeyPair::new(); // TODO: persist this so keypairs don't change every restart
|
||||
let store_dir = PathBuf::from(
|
||||
matches
|
||||
.value_of("storeDir")
|
||||
@@ -113,14 +112,9 @@ fn new_config(matches: &ArgMatches) -> provider::Config {
|
||||
.unwrap_or("/tmp/nym-provider/registered_clients"),
|
||||
);
|
||||
|
||||
println!("The value of mix_host is: {:?}", mix_host);
|
||||
println!("The value of mix_port is: {:?}", mix_port);
|
||||
println!("The value of client_host is: {:?}", client_host);
|
||||
println!("The value of client_port is: {:?}", client_port);
|
||||
println!("The value of key is: {:?}", key_pair.private.clone());
|
||||
println!("The value of store_dir is: {:?}", store_dir);
|
||||
println!("store_dir is: {:?}", store_dir);
|
||||
println!(
|
||||
"The value of registered_client_ledger_dir is: {:?}",
|
||||
"registered_client_ledger_dir is: {:?}",
|
||||
registered_client_ledger_dir
|
||||
);
|
||||
|
||||
@@ -136,21 +130,15 @@ fn new_config(matches: &ArgMatches) -> provider::Config {
|
||||
.next()
|
||||
.expect("Failed to extract the socket address from the iterator");
|
||||
|
||||
println!(
|
||||
"The full combined mix socket address is {}",
|
||||
mix_socket_address
|
||||
);
|
||||
println!(
|
||||
"The full combined client socket address is {}",
|
||||
client_socket_address
|
||||
);
|
||||
println!("Listening for mixnet packets on {}", mix_socket_address);
|
||||
println!("Listening for client requests on {}", client_socket_address);
|
||||
|
||||
provider::Config {
|
||||
mix_socket_address,
|
||||
directory_server,
|
||||
public_key: key_pair.public,
|
||||
public_key: key_pair.public_key,
|
||||
client_socket_address,
|
||||
secret_key: key_pair.private,
|
||||
secret_key: key_pair.private_key,
|
||||
store_dir: PathBuf::from(store_dir),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
use crate::provider::storage::{ClientStorage, StoreError};
|
||||
use crate::provider::ClientLedger;
|
||||
use crypto::identity::{DummyMixIdentityPrivateKey, MixnetIdentityPrivateKey};
|
||||
use curve25519_dalek::scalar::Scalar;
|
||||
use futures::lock::Mutex as FMutex;
|
||||
use hmac::{Hmac, Mac};
|
||||
@@ -53,14 +54,14 @@ impl From<io::Error> for ClientProcessingError {
|
||||
pub(crate) struct ClientProcessingData {
|
||||
store_dir: PathBuf,
|
||||
registered_clients_ledger: Arc<FMutex<ClientLedger>>,
|
||||
secret_key: Scalar,
|
||||
secret_key: DummyMixIdentityPrivateKey,
|
||||
}
|
||||
|
||||
impl ClientProcessingData {
|
||||
pub(crate) fn new(
|
||||
store_dir: PathBuf,
|
||||
registered_clients_ledger: Arc<FMutex<ClientLedger>>,
|
||||
secret_key: Scalar,
|
||||
secret_key: DummyMixIdentityPrivateKey,
|
||||
) -> Self {
|
||||
ClientProcessingData {
|
||||
store_dir,
|
||||
@@ -150,7 +151,7 @@ impl ClientRequestProcessor {
|
||||
std::fs::create_dir_all(full_store_dir)
|
||||
}
|
||||
|
||||
fn generate_new_auth_token(data: Vec<u8>, key: Scalar) -> AuthToken {
|
||||
fn generate_new_auth_token(data: Vec<u8>, key: DummyMixIdentityPrivateKey) -> AuthToken {
|
||||
let mut auth_token_raw =
|
||||
HmacSha256::new_varkey(&key.to_bytes()).expect("HMAC can take key of any size");
|
||||
auth_token_raw.input(&data);
|
||||
@@ -232,7 +233,7 @@ mod create_storage_dir {
|
||||
#[test]
|
||||
fn it_creates_a_correct_storage_directory() {
|
||||
let client_address: DestinationAddressBytes = [1u8; 32];
|
||||
let store_dir = Path::new("./foo/");
|
||||
let store_dir = Path::new("/tmp/");
|
||||
ClientRequestProcessor::create_storage_dir(client_address, store_dir).unwrap();
|
||||
}
|
||||
}
|
||||
@@ -245,7 +246,7 @@ mod generating_new_auth_token {
|
||||
fn for_the_same_input_generates_the_same_auth_token() {
|
||||
let data1 = vec![1u8; 55];
|
||||
let data2 = vec![1u8; 55];
|
||||
let key = Scalar::from_bytes_mod_order([1u8; 32]);
|
||||
let key = DummyMixIdentityPrivateKey::from_bytes(&[1u8; 32]);
|
||||
let token1 = ClientRequestProcessor::generate_new_auth_token(data1, key);
|
||||
let token2 = ClientRequestProcessor::generate_new_auth_token(data2, key);
|
||||
assert_eq!(token1, token2);
|
||||
@@ -255,14 +256,14 @@ mod generating_new_auth_token {
|
||||
fn for_different_inputs_generates_different_auth_tokens() {
|
||||
let data1 = vec![1u8; 55];
|
||||
let data2 = vec![2u8; 55];
|
||||
let key = Scalar::from_bytes_mod_order([1u8; 32]);
|
||||
let key = DummyMixIdentityPrivateKey::from_bytes(&[1u8; 32]);
|
||||
let token1 = ClientRequestProcessor::generate_new_auth_token(data1, key);
|
||||
let token2 = ClientRequestProcessor::generate_new_auth_token(data2, key);
|
||||
assert_ne!(token1, token2);
|
||||
|
||||
let data1 = vec![1u8; 50];
|
||||
let data2 = vec![2u8; 55];
|
||||
let key = Scalar::from_bytes_mod_order([1u8; 32]);
|
||||
let key = DummyMixIdentityPrivateKey::from_bytes(&[1u8; 32]);
|
||||
let token1 = ClientRequestProcessor::generate_new_auth_token(data1, key);
|
||||
let token2 = ClientRequestProcessor::generate_new_auth_token(data2, key);
|
||||
assert_ne!(token1, token2);
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
use crate::provider::storage::StoreData;
|
||||
use crypto::identity::DummyMixIdentityPrivateKey;
|
||||
use curve25519_dalek::scalar::Scalar;
|
||||
use sphinx::{ProcessedPacket, SphinxPacket};
|
||||
use std::path::PathBuf;
|
||||
@@ -35,12 +36,12 @@ impl From<std::io::Error> for MixProcessingError {
|
||||
// ProcessingData defines all data required to correctly unwrap sphinx packets
|
||||
#[derive(Debug, Clone)]
|
||||
pub(crate) struct MixProcessingData {
|
||||
secret_key: Scalar,
|
||||
secret_key: DummyMixIdentityPrivateKey,
|
||||
pub(crate) store_dir: PathBuf,
|
||||
}
|
||||
|
||||
impl MixProcessingData {
|
||||
pub(crate) fn new(secret_key: Scalar, store_dir: PathBuf) -> Self {
|
||||
pub(crate) fn new(secret_key: DummyMixIdentityPrivateKey, store_dir: PathBuf) -> Self {
|
||||
MixProcessingData {
|
||||
secret_key,
|
||||
store_dir,
|
||||
@@ -62,7 +63,7 @@ impl MixPacketProcessor {
|
||||
let packet = SphinxPacket::from_bytes(packet_data.to_vec())?;
|
||||
let read_processing_data = processing_data.read().unwrap();
|
||||
let (client_address, client_surb_id, payload) =
|
||||
match packet.process(read_processing_data.secret_key) {
|
||||
match packet.process(read_processing_data.secret_key.as_scalar()) {
|
||||
ProcessedPacket::ProcessedPacketFinalHop(client_address, surb_id, payload) => {
|
||||
(client_address, surb_id, payload)
|
||||
}
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
use crate::provider::client_handling::{ClientProcessingData, ClientRequestProcessor};
|
||||
use crate::provider::mix_handling::{MixPacketProcessor, MixProcessingData};
|
||||
use crate::provider::storage::ClientStorage;
|
||||
use curve25519_dalek::montgomery::MontgomeryPoint;
|
||||
use curve25519_dalek::scalar::Scalar;
|
||||
use crypto::identity::{
|
||||
DummyMixIdentityPrivateKey, DummyMixIdentityPublicKey, MixnetIdentityPublicKey,
|
||||
};
|
||||
use directory_client::presence::MixProviderClient;
|
||||
use futures::io::Error;
|
||||
use futures::lock::Mutex as FMutex;
|
||||
@@ -29,18 +30,11 @@ pub struct Config {
|
||||
pub client_socket_address: SocketAddr,
|
||||
pub directory_server: String,
|
||||
pub mix_socket_address: SocketAddr,
|
||||
pub public_key: MontgomeryPoint,
|
||||
pub secret_key: Scalar,
|
||||
pub public_key: DummyMixIdentityPublicKey,
|
||||
pub secret_key: DummyMixIdentityPrivateKey,
|
||||
pub store_dir: PathBuf,
|
||||
}
|
||||
|
||||
impl Config {
|
||||
pub fn public_key_string(public_key: MontgomeryPoint) -> String {
|
||||
let key_bytes = public_key.to_bytes().to_vec();
|
||||
base64::encode_config(&key_bytes, base64::URL_SAFE)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum ProviderError {
|
||||
TcpListenerBindingError,
|
||||
@@ -94,7 +88,7 @@ impl ClientLedger {
|
||||
fn current_clients(&self) -> Vec<MixProviderClient> {
|
||||
self.0
|
||||
.iter()
|
||||
.map(|(_, &v)| Config::public_key_string(MontgomeryPoint(v)))
|
||||
.map(|(_, v)| base64::encode_config(v, base64::URL_SAFE))
|
||||
.map(|pub_key| MixProviderClient { pub_key })
|
||||
.collect()
|
||||
}
|
||||
@@ -109,14 +103,14 @@ pub struct ServiceProvider {
|
||||
directory_server: String,
|
||||
mix_network_address: SocketAddr,
|
||||
client_network_address: SocketAddr,
|
||||
secret_key: Scalar,
|
||||
public_key: MontgomeryPoint,
|
||||
public_key: DummyMixIdentityPublicKey,
|
||||
secret_key: DummyMixIdentityPrivateKey,
|
||||
store_dir: PathBuf,
|
||||
registered_clients_ledger: ClientLedger,
|
||||
}
|
||||
|
||||
impl ServiceProvider {
|
||||
pub fn new(config: &Config) -> Self {
|
||||
pub fn new(config: Config) -> Self {
|
||||
ServiceProvider {
|
||||
mix_network_address: config.mix_socket_address,
|
||||
client_network_address: config.client_socket_address,
|
||||
@@ -238,7 +232,7 @@ impl ServiceProvider {
|
||||
|
||||
async fn start_mixnet_listening(
|
||||
address: SocketAddr,
|
||||
secret_key: Scalar,
|
||||
secret_key: DummyMixIdentityPrivateKey,
|
||||
store_dir: PathBuf,
|
||||
) -> Result<(), ProviderError> {
|
||||
let mut listener = tokio::net::TcpListener::bind(address).await?;
|
||||
@@ -260,7 +254,7 @@ impl ServiceProvider {
|
||||
address: SocketAddr,
|
||||
store_dir: PathBuf,
|
||||
client_ledger: Arc<FMutex<ClientLedger>>,
|
||||
secret_key: Scalar,
|
||||
secret_key: DummyMixIdentityPrivateKey,
|
||||
) -> Result<(), ProviderError> {
|
||||
let mut listener = tokio::net::TcpListener::bind(address).await?;
|
||||
let processing_data =
|
||||
@@ -299,7 +293,7 @@ impl ServiceProvider {
|
||||
let presence_future = rt.spawn(presence_notifier.run());
|
||||
let mix_future = rt.spawn(ServiceProvider::start_mixnet_listening(
|
||||
self.mix_network_address,
|
||||
self.secret_key,
|
||||
self.secret_key.clone(),
|
||||
self.store_dir.clone(),
|
||||
));
|
||||
let client_future = rt.spawn(ServiceProvider::start_client_listening(
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
use crate::provider::{ClientLedger, Config};
|
||||
use crypto::identity::DummyMixIdentityPublicKey;
|
||||
use curve25519_dalek::montgomery::MontgomeryPoint;
|
||||
use directory_client::presence::MixProviderPresence;
|
||||
use directory_client::requests::presence_providers_post::PresenceMixProviderPoster;
|
||||
@@ -21,7 +22,7 @@ impl Notifier {
|
||||
directory_server_address: String,
|
||||
client_listener: SocketAddr,
|
||||
mixnet_listener: SocketAddr,
|
||||
pub_key: MontgomeryPoint,
|
||||
pub_key: DummyMixIdentityPublicKey,
|
||||
client_ledger: Arc<FMutex<ClientLedger>>,
|
||||
) -> Notifier {
|
||||
let directory_config = directory_client::Config {
|
||||
@@ -33,7 +34,7 @@ impl Notifier {
|
||||
net_client,
|
||||
client_listener: client_listener.to_string(),
|
||||
mixnet_listener: mixnet_listener.to_string(),
|
||||
pub_key: Config::public_key_string(pub_key),
|
||||
pub_key: pub_key.to_b64_string(),
|
||||
client_ledger,
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user