Moved relevant parts of old mix-client to nymsphinx (#221)
This commit is contained in:
committed by
GitHub
parent
c3e18cedd5
commit
f9d3ee7fc4
Generated
+1
-15
@@ -1504,19 +1504,6 @@ dependencies = [
|
||||
"winapi 0.3.8",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "mix-client"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"log 0.4.8",
|
||||
"nymsphinx",
|
||||
"pretty_env_logger",
|
||||
"rand 0.7.3",
|
||||
"rand_distr",
|
||||
"tokio 0.2.16",
|
||||
"topology",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "mockito"
|
||||
version = "0.23.3"
|
||||
@@ -1625,7 +1612,6 @@ dependencies = [
|
||||
"gateway-client",
|
||||
"gateway-requests",
|
||||
"log 0.4.8",
|
||||
"mix-client",
|
||||
"multi-tcp-client",
|
||||
"nymsphinx",
|
||||
"pem",
|
||||
@@ -1656,7 +1642,6 @@ dependencies = [
|
||||
"gateway-requests",
|
||||
"hmac",
|
||||
"log 0.4.8",
|
||||
"mix-client",
|
||||
"multi-tcp-client",
|
||||
"nymsphinx",
|
||||
"pemstore",
|
||||
@@ -1730,6 +1715,7 @@ version = "0.1.0"
|
||||
dependencies = [
|
||||
"log 0.4.8",
|
||||
"rand 0.7.3",
|
||||
"rand_distr",
|
||||
"sphinx",
|
||||
]
|
||||
|
||||
|
||||
@@ -9,7 +9,6 @@ members = [
|
||||
"clients/webassembly",
|
||||
"common/client-libs/directory-client",
|
||||
"common/client-libs/gateway-client",
|
||||
"common/client-libs/mix-client",
|
||||
"common/client-libs/multi-tcp-client",
|
||||
"common/client-libs/validator-client",
|
||||
"common/config",
|
||||
|
||||
@@ -34,7 +34,6 @@ crypto = {path = "../../common/crypto"}
|
||||
directory-client = { path = "../../common/client-libs/directory-client" }
|
||||
gateway-client = { path = "../../common/client-libs/gateway-client" }
|
||||
gateway-requests = { path = "../../gateway/gateway-requests" }
|
||||
mix-client = { path = "../../common/client-libs/mix-client" }
|
||||
multi-tcp-client = { path = "../../common/client-libs/multi-tcp-client" }
|
||||
nymsphinx = { path = "../../common/nymsphinx" }
|
||||
pemstore = {path = "../../common/pemstore"}
|
||||
|
||||
@@ -17,7 +17,10 @@ use crate::client::topology_control::TopologyAccessor;
|
||||
use futures::task::{Context, Poll};
|
||||
use futures::{Future, Stream, StreamExt};
|
||||
use log::*;
|
||||
use nymsphinx::Destination;
|
||||
use nymsphinx::{
|
||||
utils::{encapsulation, poisson},
|
||||
Destination,
|
||||
};
|
||||
use std::pin::Pin;
|
||||
use std::time::Duration;
|
||||
use tokio::runtime::Handle;
|
||||
@@ -50,8 +53,7 @@ impl<T: NymTopology> Stream for LoopCoverTrafficStream<T> {
|
||||
// we know it's time to send a message, so let's prepare delay for the next one
|
||||
// Get the `now` by looking at the current `delay` deadline
|
||||
let now = self.next_delay.deadline();
|
||||
let next_poisson_delay =
|
||||
mix_client::poisson::sample(self.average_cover_message_sending_delay);
|
||||
let next_poisson_delay = poisson::sample(self.average_cover_message_sending_delay);
|
||||
|
||||
// The next interval value is `next_poisson_delay` after the one that just
|
||||
// yielded.
|
||||
@@ -90,7 +92,7 @@ impl<T: 'static + NymTopology> LoopCoverTrafficStream<T> {
|
||||
Some(route) => route,
|
||||
};
|
||||
|
||||
let cover_message = match mix_client::packet::loop_cover_message_route(
|
||||
let cover_message = match encapsulation::loop_cover_message_route(
|
||||
self.our_info.address.clone(),
|
||||
self.our_info.identifier,
|
||||
route,
|
||||
@@ -120,9 +122,8 @@ impl<T: 'static + NymTopology> LoopCoverTrafficStream<T> {
|
||||
|
||||
async fn run(&mut self) {
|
||||
// we should set initial delay only when we actually start the stream
|
||||
self.next_delay = time::delay_for(mix_client::poisson::sample(
|
||||
self.average_cover_message_sending_delay,
|
||||
));
|
||||
self.next_delay =
|
||||
time::delay_for(poisson::sample(self.average_cover_message_sending_delay));
|
||||
|
||||
while let Some(_) = self.next().await {
|
||||
self.on_new_message().await;
|
||||
|
||||
@@ -19,7 +19,10 @@ use futures::channel::mpsc;
|
||||
use futures::task::{Context, Poll};
|
||||
use futures::{Future, Stream, StreamExt};
|
||||
use log::{error, info, trace, warn};
|
||||
use nymsphinx::{Destination, DestinationAddressBytes};
|
||||
use nymsphinx::{
|
||||
utils::{encapsulation, poisson},
|
||||
Destination, DestinationAddressBytes,
|
||||
};
|
||||
use std::pin::Pin;
|
||||
use std::time::Duration;
|
||||
use tokio::runtime::Handle;
|
||||
@@ -54,7 +57,7 @@ impl<T: NymTopology> Stream for OutQueueControl<T> {
|
||||
// we know it's time to send a message, so let's prepare delay for the next one
|
||||
// Get the `now` by looking at the current `delay` deadline
|
||||
let now = self.next_delay.deadline();
|
||||
let next_poisson_delay = mix_client::poisson::sample(self.average_message_sending_delay);
|
||||
let next_poisson_delay = poisson::sample(self.average_message_sending_delay);
|
||||
|
||||
// The next interval value is `next_poisson_delay` after the one that just
|
||||
// yielded.
|
||||
@@ -118,7 +121,7 @@ impl<T: 'static + NymTopology> OutQueueControl<T> {
|
||||
warn!("No valid topology detected - won't send any real or loop message this time");
|
||||
}
|
||||
let route = route.unwrap();
|
||||
mix_client::packet::loop_cover_message_route(
|
||||
encapsulation::loop_cover_message_route(
|
||||
self.our_info.address.clone(),
|
||||
self.our_info.identifier,
|
||||
route,
|
||||
@@ -131,7 +134,7 @@ impl<T: 'static + NymTopology> OutQueueControl<T> {
|
||||
warn!("No valid topology detected - won't send any real or loop message this time");
|
||||
}
|
||||
let route = route.unwrap();
|
||||
mix_client::packet::encapsulate_message_route(
|
||||
encapsulation::encapsulate_message_route(
|
||||
real_message.0,
|
||||
real_message.1,
|
||||
route,
|
||||
@@ -168,9 +171,7 @@ impl<T: 'static + NymTopology> OutQueueControl<T> {
|
||||
|
||||
pub(crate) async fn run_out_queue_control(mut self) {
|
||||
// we should set initial delay only when we actually start the stream
|
||||
self.next_delay = time::delay_for(mix_client::poisson::sample(
|
||||
self.average_message_sending_delay,
|
||||
));
|
||||
self.next_delay = time::delay_for(poisson::sample(self.average_message_sending_delay));
|
||||
|
||||
info!("starting out queue controller");
|
||||
while let Some(next_message) = self.next().await {
|
||||
|
||||
@@ -17,8 +17,10 @@ use futures::lock::Mutex;
|
||||
use futures::StreamExt;
|
||||
use gateway_client::SphinxPacketReceiver;
|
||||
use log::*;
|
||||
use mix_client::packet::LOOP_COVER_MESSAGE_PAYLOAD;
|
||||
use nymsphinx::chunking::reconstruction::MessageReconstructor;
|
||||
use nymsphinx::{
|
||||
chunking::reconstruction::MessageReconstructor,
|
||||
utils::encapsulation::LOOP_COVER_MESSAGE_PAYLOAD,
|
||||
};
|
||||
use std::sync::Arc;
|
||||
use tokio::runtime::Handle;
|
||||
use tokio::task::JoinHandle;
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
[package]
|
||||
name = "mix-client"
|
||||
version = "0.1.0"
|
||||
authors = ["Dave Hrycyszyn <futurechimp@users.noreply.github.com>", "Jędrzej Stuczyński <andrew@nymtech.net>"]
|
||||
edition = "2018"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
log = "0.4.8"
|
||||
pretty_env_logger = "0.3"
|
||||
rand = "0.7.2"
|
||||
rand_distr = "0.2.2"
|
||||
tokio = { version = "0.2", features = ["full"] }
|
||||
|
||||
## internal
|
||||
nymsphinx = {path = "../../nymsphinx"}
|
||||
topology = {path = "../../topology"}
|
||||
@@ -1,69 +0,0 @@
|
||||
// Copyright 2020 Nym Technologies SA
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use log::*;
|
||||
use nymsphinx::SphinxPacket;
|
||||
use std::net::SocketAddr;
|
||||
use tokio::prelude::*;
|
||||
|
||||
pub mod packet;
|
||||
pub mod poisson;
|
||||
|
||||
pub struct MixClient {}
|
||||
|
||||
impl MixClient {
|
||||
#[allow(clippy::new_without_default)]
|
||||
pub fn new() -> MixClient {
|
||||
MixClient {}
|
||||
}
|
||||
|
||||
// Sends a Sphinx packet to a mixnode.
|
||||
pub async fn send(
|
||||
&self,
|
||||
packet: SphinxPacket,
|
||||
mix_addr: SocketAddr,
|
||||
) -> Result<(), Box<dyn std::error::Error>> {
|
||||
let bytes = packet.to_bytes();
|
||||
debug!("Sending to the following address: {:?}", mix_addr);
|
||||
|
||||
let mut stream = tokio::net::TcpStream::connect(mix_addr).await?;
|
||||
stream.write_all(&bytes[..]).await?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod sending_a_sphinx_packet {
|
||||
// use super::*;
|
||||
// use sphinx::SphinxPacket;
|
||||
|
||||
#[test]
|
||||
fn works() {
|
||||
// arrange
|
||||
// let directory = Client::new();
|
||||
// let message = "Hello, Sphinx!".as_bytes().to_vec();
|
||||
// let mixes = directory.get_mixes();
|
||||
// let destination = directory.get_destination();
|
||||
// let delays = sphinx::header::delays::generate(2);
|
||||
// let packet = SphinxPacket::new(message, &mixes, &destination, &delays).unwrap();
|
||||
// let mix_client = MixClient::new();
|
||||
// let first_hop = mixes.first().unwrap();
|
||||
//
|
||||
// // act
|
||||
// mix_client.send(packet, first_hop);
|
||||
|
||||
// assert
|
||||
// wtf are we supposed to assert here?
|
||||
}
|
||||
}
|
||||
@@ -1,129 +0,0 @@
|
||||
// Copyright 2020 Nym Technologies SA
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use nymsphinx::addressing::nodes::{NymNodeRoutingAddress, NymNodeRoutingAddressError};
|
||||
use nymsphinx::{delays, Destination, DestinationAddressBytes, SURBIdentifier, SphinxPacket};
|
||||
use std::convert::TryFrom;
|
||||
use std::net::SocketAddr;
|
||||
use std::time;
|
||||
use topology::{NymTopology, NymTopologyError};
|
||||
|
||||
pub const LOOP_COVER_MESSAGE_PAYLOAD: &[u8] = b"The cake is a lie!";
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum SphinxPacketEncapsulationError {
|
||||
NoValidProvidersError,
|
||||
InvalidTopologyError,
|
||||
SphinxError(nymsphinx::Error),
|
||||
InvalidFirstMixAddress,
|
||||
}
|
||||
|
||||
impl From<topology::NymTopologyError> for SphinxPacketEncapsulationError {
|
||||
fn from(_: NymTopologyError) -> Self {
|
||||
use SphinxPacketEncapsulationError::*;
|
||||
InvalidTopologyError
|
||||
}
|
||||
}
|
||||
|
||||
impl From<nymsphinx::Error> for SphinxPacketEncapsulationError {
|
||||
fn from(err: nymsphinx::Error) -> Self {
|
||||
SphinxPacketEncapsulationError::SphinxError(err)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<NymNodeRoutingAddressError> for SphinxPacketEncapsulationError {
|
||||
fn from(_: NymNodeRoutingAddressError) -> Self {
|
||||
use SphinxPacketEncapsulationError::*;
|
||||
InvalidFirstMixAddress
|
||||
}
|
||||
}
|
||||
|
||||
#[deprecated(note = "please use loop_cover_message_route instead")]
|
||||
pub fn loop_cover_message<T: NymTopology>(
|
||||
our_address: DestinationAddressBytes,
|
||||
surb_id: SURBIdentifier,
|
||||
topology: &T,
|
||||
average_delay: time::Duration,
|
||||
) -> Result<(SocketAddr, SphinxPacket), SphinxPacketEncapsulationError> {
|
||||
let destination = Destination::new(our_address, surb_id);
|
||||
|
||||
#[allow(deprecated)]
|
||||
encapsulate_message(
|
||||
destination,
|
||||
LOOP_COVER_MESSAGE_PAYLOAD.to_vec(),
|
||||
topology,
|
||||
average_delay,
|
||||
)
|
||||
}
|
||||
|
||||
pub fn loop_cover_message_route(
|
||||
our_address: DestinationAddressBytes,
|
||||
surb_id: SURBIdentifier,
|
||||
route: Vec<nymsphinx::Node>,
|
||||
average_delay: time::Duration,
|
||||
) -> Result<(SocketAddr, SphinxPacket), SphinxPacketEncapsulationError> {
|
||||
let destination = Destination::new(our_address, surb_id);
|
||||
|
||||
encapsulate_message_route(
|
||||
destination,
|
||||
LOOP_COVER_MESSAGE_PAYLOAD.to_vec(),
|
||||
route,
|
||||
average_delay,
|
||||
)
|
||||
}
|
||||
|
||||
#[deprecated(note = "please use encapsulate_message_route instead")]
|
||||
pub fn encapsulate_message<T: NymTopology>(
|
||||
recipient: Destination,
|
||||
message: Vec<u8>,
|
||||
topology: &T,
|
||||
average_delay: time::Duration,
|
||||
) -> Result<(SocketAddr, SphinxPacket), SphinxPacketEncapsulationError> {
|
||||
let mut providers = topology.providers();
|
||||
if providers.is_empty() {
|
||||
return Err(SphinxPacketEncapsulationError::NoValidProvidersError);
|
||||
}
|
||||
// unwrap is fine here as we asserted there is at least single provider
|
||||
let provider = providers.pop().unwrap().into();
|
||||
|
||||
let route = topology.random_route_to(provider)?;
|
||||
|
||||
let delays = delays::generate_from_average_duration(route.len(), average_delay);
|
||||
|
||||
// build the packet
|
||||
let packet = SphinxPacket::new(message, &route[..], &recipient, &delays, None)?;
|
||||
|
||||
// we know the mix route must be valid otherwise we would have already returned an error
|
||||
let first_node_address =
|
||||
NymNodeRoutingAddress::try_from(route.first().unwrap().address.clone())?;
|
||||
|
||||
Ok((first_node_address.into(), packet))
|
||||
}
|
||||
|
||||
pub fn encapsulate_message_route(
|
||||
recipient: Destination,
|
||||
message: Vec<u8>,
|
||||
route: Vec<nymsphinx::Node>,
|
||||
average_delay: time::Duration,
|
||||
) -> Result<(SocketAddr, SphinxPacket), SphinxPacketEncapsulationError> {
|
||||
let delays = delays::generate_from_average_duration(route.len(), average_delay);
|
||||
|
||||
// build the packet
|
||||
let packet = SphinxPacket::new(message, &route[..], &recipient, &delays, None)?;
|
||||
|
||||
let first_node_address =
|
||||
NymNodeRoutingAddress::try_from(route.first().unwrap().address.clone())?;
|
||||
|
||||
Ok((first_node_address.into(), packet))
|
||||
}
|
||||
@@ -9,6 +9,7 @@ edition = "2018"
|
||||
[dependencies]
|
||||
log = "0.4.8"
|
||||
rand = {version = "0.7.3", features = ["wasm-bindgen"]}
|
||||
rand_distr = "0.2.2"
|
||||
|
||||
## will be moved to proper dependencies once released
|
||||
sphinx = { git = "https://github.com/nymtech/sphinx", rev="72368ea048472823f7f9e78eed77a2c3d30a471f" }
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
|
||||
pub mod addressing;
|
||||
pub mod chunking;
|
||||
pub mod utils;
|
||||
|
||||
// Future consideration: currently in a lot of places, the payloads have randomised content
|
||||
// which is not a perfect testing strategy as it might not detect some edge cases I never would
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
// Copyright 2020 Nym Technologies SA
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use crate::addressing::nodes::{NymNodeRoutingAddress, NymNodeRoutingAddressError};
|
||||
use crate::{delays, Destination, DestinationAddressBytes, SURBIdentifier, SphinxPacket};
|
||||
use crate::{Error as SphinxError, Node as SphinxNode};
|
||||
use std::convert::TryFrom;
|
||||
use std::net::SocketAddr;
|
||||
use std::time;
|
||||
|
||||
pub const LOOP_COVER_MESSAGE_PAYLOAD: &[u8] = b"The cake is a lie!";
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum SphinxPacketEncapsulationError {
|
||||
NoValidProvidersError,
|
||||
InvalidTopologyError,
|
||||
SphinxError(SphinxError),
|
||||
InvalidFirstMixAddress,
|
||||
}
|
||||
|
||||
impl From<SphinxError> for SphinxPacketEncapsulationError {
|
||||
fn from(err: SphinxError) -> Self {
|
||||
SphinxPacketEncapsulationError::SphinxError(err)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<NymNodeRoutingAddressError> for SphinxPacketEncapsulationError {
|
||||
fn from(_: NymNodeRoutingAddressError) -> Self {
|
||||
use SphinxPacketEncapsulationError::*;
|
||||
InvalidFirstMixAddress
|
||||
}
|
||||
}
|
||||
|
||||
pub fn loop_cover_message_route(
|
||||
our_address: DestinationAddressBytes,
|
||||
surb_id: SURBIdentifier,
|
||||
route: Vec<SphinxNode>,
|
||||
average_delay: time::Duration,
|
||||
) -> Result<(SocketAddr, SphinxPacket), SphinxPacketEncapsulationError> {
|
||||
let destination = Destination::new(our_address, surb_id);
|
||||
|
||||
encapsulate_message_route(
|
||||
destination,
|
||||
LOOP_COVER_MESSAGE_PAYLOAD.to_vec(),
|
||||
route,
|
||||
average_delay,
|
||||
)
|
||||
}
|
||||
|
||||
pub fn encapsulate_message_route(
|
||||
recipient: Destination,
|
||||
message: Vec<u8>,
|
||||
route: Vec<SphinxNode>,
|
||||
average_delay: time::Duration,
|
||||
) -> Result<(SocketAddr, SphinxPacket), SphinxPacketEncapsulationError> {
|
||||
let delays = delays::generate_from_average_duration(route.len(), average_delay);
|
||||
|
||||
// build the packet
|
||||
let packet = SphinxPacket::new(message, &route[..], &recipient, &delays, None)?;
|
||||
|
||||
let first_node_address =
|
||||
NymNodeRoutingAddress::try_from(route.first().unwrap().address.clone())?;
|
||||
|
||||
Ok((first_node_address.into(), packet))
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
pub mod encapsulation;
|
||||
pub mod poisson;
|
||||
@@ -31,12 +31,6 @@ multi-tcp-client = { path = "../common/client-libs/multi-tcp-client" }
|
||||
nymsphinx = { path = "../common/nymsphinx" }
|
||||
pemstore = { path = "../common/pemstore" }
|
||||
|
||||
# this dependency is due to requiring to know content of loop message. however, mix-client module itself
|
||||
# is going to be removed or renamed at some point as it no longer servers its purpose of sending traffic to mix network
|
||||
# and only provides utility functions
|
||||
mix-client = { path = "../common/client-libs/mix-client" }
|
||||
|
||||
|
||||
[dependencies.tungstenite]
|
||||
version = "0.10.0"
|
||||
default-features = false
|
||||
|
||||
@@ -21,8 +21,10 @@ use crypto::encryption;
|
||||
use futures::channel::oneshot;
|
||||
use futures::lock::Mutex;
|
||||
use log::*;
|
||||
use mix_client::packet::LOOP_COVER_MESSAGE_PAYLOAD;
|
||||
use nymsphinx::{DestinationAddressBytes, Error as SphinxError, ProcessedPacket, SphinxPacket};
|
||||
use nymsphinx::{
|
||||
utils::encapsulation::LOOP_COVER_MESSAGE_PAYLOAD, DestinationAddressBytes,
|
||||
Error as SphinxError, ProcessedPacket, SphinxPacket,
|
||||
};
|
||||
use std::collections::HashMap;
|
||||
use std::io;
|
||||
use std::ops::Deref;
|
||||
|
||||
Reference in New Issue
Block a user