Merge branch 'develop' of github.com:nymtech/nym-client into develop
This commit is contained in:
Generated
+8
@@ -941,6 +941,7 @@ dependencies = [
|
||||
"reqwest 0.9.22 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_json 1.0.44 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"sfw-provider-requests 0.1.0",
|
||||
"sphinx 0.1.0",
|
||||
"tokio 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
@@ -1402,6 +1403,13 @@ dependencies = [
|
||||
"url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sfw-provider-requests"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"sphinx 0.1.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sha2"
|
||||
version = "0.8.0"
|
||||
|
||||
@@ -15,6 +15,8 @@ pem = "0.7.0"
|
||||
reqwest = "0.9.22"
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
sphinx = { path = "../sphinx" }
|
||||
sfw-provider-requests = { path = "../nym-sfw-provider/sfw-provider-requests" }
|
||||
|
||||
tokio = { version = "0.2", features = ["full"] }
|
||||
|
||||
[dev-dependencies]
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
use sphinx::route::Node as MixNode;
|
||||
use sphinx::SphinxPacket;
|
||||
use tokio::prelude::*;
|
||||
use sfw_provider_requests::*;
|
||||
use std::net::Shutdown;
|
||||
use std::time::Duration;
|
||||
use sfw_provider_requests::requests::{PullRequest, ProviderRequest};
|
||||
use sfw_provider_requests::responses::{PullResponse, ProviderResponse};
|
||||
|
||||
pub struct ProviderClient {}
|
||||
|
||||
|
||||
impl ProviderClient {
|
||||
pub fn new() -> Self {
|
||||
ProviderClient {}
|
||||
}
|
||||
|
||||
pub async fn retrieve_messages(
|
||||
&self,
|
||||
// provider: &MixNode,
|
||||
) -> Result<(), Box<dyn std::error::Error>> {
|
||||
let address = [42; 32];
|
||||
let pull_request = PullRequest::new(address);
|
||||
let bytes = pull_request.to_bytes();
|
||||
|
||||
let mut socket = tokio::net::TcpStream::connect("127.0.0.1:9000").await?;
|
||||
println!("keep alive: {:?}", socket.keepalive());
|
||||
socket.set_keepalive(Some(tokio::time::Duration::from_secs(2)));
|
||||
socket.write_all(&bytes[..]).await?;
|
||||
if let Err(e) = socket.shutdown(Shutdown::Write) {
|
||||
eprintln!("failed to close write part of the socket; err = {:?}", e)
|
||||
}
|
||||
|
||||
let mut response = Vec::new();
|
||||
socket.read_to_end(&mut response).await?;
|
||||
if let Err(e) = socket.shutdown(Shutdown::Read) {
|
||||
eprintln!("failed to close read part of the socket; err = {:?}", e)
|
||||
}
|
||||
|
||||
println!("Received the following response: {:?}", response);
|
||||
let parsed_response = PullResponse::from_bytes(&response).unwrap();
|
||||
for message in parsed_response.messages {
|
||||
println!("Received: {:?}", String::from_utf8(message).unwrap())
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
+9
-49
@@ -1,60 +1,20 @@
|
||||
use crate::banner;
|
||||
use crate::identity::mixnet;
|
||||
use crate::persistence::pathfinder::Pathfinder;
|
||||
use crate::persistence::pemstore::PemStore;
|
||||
use clap::ArgMatches;
|
||||
use dirs;
|
||||
use pem::{encode, Pem};
|
||||
use std::fs::File;
|
||||
use std::io::prelude::*;
|
||||
|
||||
pub fn execute(matches: &ArgMatches) {
|
||||
println!("{}", banner());
|
||||
println!("Initialising client...");
|
||||
|
||||
let id = matches.value_of("id").unwrap(); // required for now
|
||||
let id = matches.value_of("id").unwrap().to_string(); // required for now
|
||||
let pathfinder = Pathfinder::new(id);
|
||||
|
||||
// don't unwrap it, pass it as it is, if it's None, choose a random
|
||||
let _provider_id = matches.value_of("provider");
|
||||
let _init_local = matches.is_present("local");
|
||||
|
||||
let os_config_dir = dirs::config_dir().unwrap();
|
||||
let nym_client_config_dir = os_config_dir.join("nym").join("clients").join(id);
|
||||
|
||||
println!("Writing keypairs to {:?}...", nym_client_config_dir);
|
||||
write_pem_files(nym_client_config_dir);
|
||||
println!("Writing keypairs to {:?}...", pathfinder.config_dir);
|
||||
let mix_keys = mixnet::KeyPair::new();
|
||||
let pem_store = PemStore::new(pathfinder);
|
||||
pem_store.write(mix_keys);
|
||||
|
||||
println!("Client configuration completed.\n\n\n")
|
||||
}
|
||||
|
||||
fn write_pem_files(nym_client_config_dir: std::path::PathBuf) {
|
||||
std::fs::create_dir_all(nym_client_config_dir.clone()).unwrap();
|
||||
|
||||
let (private, public) = sphinx::crypto::keygen();
|
||||
write_pem_file(
|
||||
nym_client_config_dir.clone(),
|
||||
String::from("private.pem"),
|
||||
private.to_bytes().to_vec(),
|
||||
String::from("SPHINX CURVE25519 PRIVATE KEY"),
|
||||
);
|
||||
write_pem_file(
|
||||
nym_client_config_dir.clone(),
|
||||
String::from("public.pem"),
|
||||
public.to_bytes().to_vec(),
|
||||
String::from("SPHINX CURVE25519 PUBLIC KEY"),
|
||||
);
|
||||
}
|
||||
|
||||
fn write_pem_file(
|
||||
nym_client_config_dir: std::path::PathBuf,
|
||||
filename: String,
|
||||
data: Vec<u8>,
|
||||
tag: String,
|
||||
) {
|
||||
let pem = Pem {
|
||||
tag,
|
||||
contents: data,
|
||||
};
|
||||
let key = encode(&pem);
|
||||
|
||||
let full_path = nym_client_config_dir.join(filename);
|
||||
let mut file = File::create(full_path).unwrap();
|
||||
file.write_all(key.as_bytes()).unwrap();
|
||||
}
|
||||
|
||||
+18
-9
@@ -1,8 +1,9 @@
|
||||
use crate::clients::directory;
|
||||
use crate::clients::directory::presence::{MixNodePresence, Topology};
|
||||
use crate::clients::directory::presence::Topology;
|
||||
use crate::clients::directory::requests::presence_topology_get::PresenceTopologyGetRequester;
|
||||
use crate::clients::directory::DirectoryClient;
|
||||
use crate::clients::mix::MixClient;
|
||||
use crate::clients::provider::ProviderClient;
|
||||
use crate::utils::bytes;
|
||||
use base64;
|
||||
use clap::ArgMatches;
|
||||
@@ -15,10 +16,7 @@ use tokio::time::{interval_at, Instant};
|
||||
|
||||
pub fn execute(matches: &ArgMatches) {
|
||||
let custom_cfg = matches.value_of("customCfg");
|
||||
println!(
|
||||
"Going to start client with custom config of: {:?}",
|
||||
custom_cfg
|
||||
);
|
||||
println!("Starting client with config: {:?}", custom_cfg);
|
||||
|
||||
// Grab the network topology from the remote directory server
|
||||
let topology = get_topology();
|
||||
@@ -35,7 +33,7 @@ pub fn execute(matches: &ArgMatches) {
|
||||
interval.tick().await;
|
||||
let message = format!("Hello, Sphinx {}", i).as_bytes().to_vec();
|
||||
|
||||
let route_len = 3;
|
||||
let route_len = 2;
|
||||
|
||||
// data needed to generate a new Sphinx packet
|
||||
let route = route_from(&topology, route_len);
|
||||
@@ -51,6 +49,14 @@ pub fn execute(matches: &ArgMatches) {
|
||||
let result = mix_client.send(packet, route.first().unwrap()).await;
|
||||
println!("packet sent: {:?}", i);
|
||||
i += 1;
|
||||
|
||||
// retrieve messages every now and then
|
||||
if i % 3 == 0 {
|
||||
interval.tick().await;
|
||||
println!("going to retrieve messages!");
|
||||
let provider_client = ProviderClient::new();
|
||||
provider_client.retrieve_messages().await.unwrap();
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -76,10 +82,13 @@ fn route_from(topology: &Topology, route_len: usize) -> Vec<SphinxNode> {
|
||||
let decoded_key_bytes = base64::decode_config(&mix.pub_key, base64::URL_SAFE).unwrap();
|
||||
let key_bytes = bytes::zero_pad_to_32(decoded_key_bytes);
|
||||
let key = MontgomeryPoint(key_bytes);
|
||||
let sphinx_node = SphinxNode {
|
||||
let mut sphinx_node = SphinxNode {
|
||||
address: address_bytes,
|
||||
pub_key: key,
|
||||
};
|
||||
|
||||
// temporary to make it work locally:
|
||||
sphinx_node.pub_key = Default::default();
|
||||
route.push(sphinx_node);
|
||||
}
|
||||
route
|
||||
@@ -88,7 +97,7 @@ fn route_from(topology: &Topology, route_len: usize) -> Vec<SphinxNode> {
|
||||
// TODO: where do we retrieve this guy from?
|
||||
fn get_destination() -> Destination {
|
||||
Destination {
|
||||
address: [0u8; 32],
|
||||
identifier: [0u8; 16],
|
||||
address: [42u8; 32],
|
||||
identifier: [1u8; 16],
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
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) -> Vec<u8> {
|
||||
self.private.to_bytes().to_vec()
|
||||
}
|
||||
|
||||
pub fn public_bytes(&self) -> Vec<u8> {
|
||||
self.public.to_bytes().to_vec()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
pub mod mixnet;
|
||||
@@ -0,0 +1 @@
|
||||
// TODO types for Validator keys will go in here once we hook this up.
|
||||
@@ -3,6 +3,8 @@ use std::process;
|
||||
|
||||
mod clients;
|
||||
mod commands;
|
||||
mod identity;
|
||||
mod persistence;
|
||||
mod utils;
|
||||
|
||||
fn main() {
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
pub mod pathfinder;
|
||||
pub mod pemstore;
|
||||
@@ -0,0 +1,21 @@
|
||||
use std::path::PathBuf;
|
||||
|
||||
pub struct Pathfinder {
|
||||
pub config_dir: PathBuf,
|
||||
pub private_mix_key: PathBuf,
|
||||
pub public_mix_key: PathBuf,
|
||||
}
|
||||
|
||||
impl Pathfinder {
|
||||
pub fn new(id: String) -> Pathfinder {
|
||||
let os_config_dir = dirs::config_dir().unwrap(); // grabs the OS default config dir
|
||||
let config_dir = os_config_dir.join("nym").join("clients").join(id);
|
||||
let private_mix_key = config_dir.join("private.pem");
|
||||
let public_mix_key = config_dir.join("public.pem");
|
||||
Pathfinder {
|
||||
config_dir,
|
||||
private_mix_key,
|
||||
public_mix_key,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
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 struct PemStore {
|
||||
config_dir: PathBuf,
|
||||
private_mix_key: PathBuf,
|
||||
public_mix_key: PathBuf,
|
||||
}
|
||||
|
||||
impl PemStore {
|
||||
pub fn new(pathfinder: Pathfinder) -> PemStore {
|
||||
PemStore {
|
||||
config_dir: pathfinder.config_dir,
|
||||
private_mix_key: pathfinder.private_mix_key,
|
||||
public_mix_key: pathfinder.public_mix_key,
|
||||
}
|
||||
}
|
||||
|
||||
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());
|
||||
|
||||
KeyPair::from_bytes(private, public)
|
||||
}
|
||||
|
||||
fn read_file(&self, filepath: PathBuf) -> Vec<u8> {
|
||||
let mut pem_bytes = File::open(filepath).unwrap();
|
||||
let mut buf = Vec::new();
|
||||
pem_bytes.read_to_end(&mut buf).unwrap();
|
||||
let pem = parse(&buf).unwrap();
|
||||
pem.contents
|
||||
}
|
||||
// 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) {
|
||||
std::fs::create_dir_all(self.config_dir.clone()).unwrap();
|
||||
|
||||
self.write_pem_file(
|
||||
self.private_mix_key.clone(),
|
||||
key_pair.private_bytes(),
|
||||
String::from("SPHINX CURVE25519 PRIVATE KEY"),
|
||||
);
|
||||
self.write_pem_file(
|
||||
self.public_mix_key.clone(),
|
||||
key_pair.public_bytes(),
|
||||
String::from("SPHINX CURVE25519 PUBLIC KEY"),
|
||||
);
|
||||
}
|
||||
|
||||
fn write_pem_file(&self, filepath: PathBuf, data: Vec<u8>, tag: String) {
|
||||
let pem = Pem {
|
||||
tag,
|
||||
contents: data,
|
||||
};
|
||||
let key = encode(&pem);
|
||||
|
||||
let mut file = File::create(filepath).unwrap();
|
||||
file.write_all(key.as_bytes()).unwrap();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
// TODO: we can put all the TOML config templating code in here once we get to that.
|
||||
Reference in New Issue
Block a user