Feature/addressing move (#169)
* Moved 'addressing' to nymsphinx + slightly better API + tests * Replaced all usages of above in the project * Removed 'split_and_encapsulate_message' from chunking API to get rid of circular dependency + to prefer usage of TopologyAccessor * changes in Cargo.lock * formatting
This commit is contained in:
committed by
GitHub
parent
d859a98367
commit
b564cd935e
Generated
+4
-15
@@ -17,14 +17,6 @@ dependencies = [
|
||||
"tokio 0.1.22",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "addressing"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"log 0.4.8",
|
||||
"pretty_env_logger",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "adler32"
|
||||
version = "1.0.4"
|
||||
@@ -931,13 +923,13 @@ dependencies = [
|
||||
name = "healthcheck"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"addressing",
|
||||
"crypto",
|
||||
"directory-client",
|
||||
"futures 0.3.4",
|
||||
"itertools",
|
||||
"log 0.4.8",
|
||||
"multi-tcp-client",
|
||||
"nymsphinx",
|
||||
"pretty_env_logger",
|
||||
"provider-client",
|
||||
"rand 0.7.3",
|
||||
@@ -1432,8 +1424,8 @@ dependencies = [
|
||||
name = "mix-client"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"addressing",
|
||||
"log 0.4.8",
|
||||
"nymsphinx",
|
||||
"pretty_env_logger",
|
||||
"rand 0.7.3",
|
||||
"rand_distr",
|
||||
@@ -1537,7 +1529,6 @@ dependencies = [
|
||||
name = "nym-client"
|
||||
version = "0.5.0"
|
||||
dependencies = [
|
||||
"addressing",
|
||||
"bs58",
|
||||
"built",
|
||||
"clap",
|
||||
@@ -1572,7 +1563,6 @@ dependencies = [
|
||||
name = "nym-mixnode"
|
||||
version = "0.5.0"
|
||||
dependencies = [
|
||||
"addressing",
|
||||
"bs58",
|
||||
"built",
|
||||
"clap",
|
||||
@@ -1585,6 +1575,7 @@ dependencies = [
|
||||
"futures 0.3.4",
|
||||
"log 0.4.8",
|
||||
"multi-tcp-client",
|
||||
"nymsphinx",
|
||||
"pemstore",
|
||||
"pretty_env_logger",
|
||||
"serde",
|
||||
@@ -1654,11 +1645,9 @@ dependencies = [
|
||||
name = "nymsphinx"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"addressing",
|
||||
"log 0.4.8",
|
||||
"rand 0.7.3",
|
||||
"sphinx",
|
||||
"topology",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2858,10 +2847,10 @@ dependencies = [
|
||||
name = "topology"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"addressing",
|
||||
"bs58",
|
||||
"itertools",
|
||||
"log 0.4.8",
|
||||
"nymsphinx",
|
||||
"pretty_env_logger",
|
||||
"rand 0.7.3",
|
||||
"serde",
|
||||
|
||||
@@ -9,7 +9,6 @@ members = [
|
||||
"common/clients/multi-tcp-client",
|
||||
"common/clients/provider-client",
|
||||
"common/clients/validator-client",
|
||||
"common/addressing",
|
||||
"common/config",
|
||||
"common/crypto",
|
||||
"common/healthcheck",
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
[package]
|
||||
name = "addressing"
|
||||
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]
|
||||
log = "0.4"
|
||||
pretty_env_logger = "0.3"
|
||||
@@ -1,80 +0,0 @@
|
||||
use std::convert::{TryFrom, TryInto};
|
||||
use std::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr};
|
||||
|
||||
pub enum AddressType {
|
||||
V4,
|
||||
V6,
|
||||
}
|
||||
|
||||
impl Into<u8> for AddressType {
|
||||
fn into(self) -> u8 {
|
||||
use AddressType::*;
|
||||
|
||||
match self {
|
||||
V4 => 4,
|
||||
V6 => 6,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum AddressTypeError {
|
||||
InvalidPrefixError,
|
||||
}
|
||||
|
||||
impl TryFrom<u8> for AddressType {
|
||||
type Error = AddressTypeError;
|
||||
|
||||
fn try_from(value: u8) -> Result<Self, Self::Error> {
|
||||
use AddressType::*;
|
||||
use AddressTypeError::*;
|
||||
|
||||
match value {
|
||||
4 => Ok(V4),
|
||||
6 => Ok(V6),
|
||||
_ => Err(InvalidPrefixError),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// FLAG || port || octets || zeropad
|
||||
pub fn encoded_bytes_from_socket_address(address: SocketAddr) -> [u8; 32] {
|
||||
let port_bytes = address.port().to_be_bytes();
|
||||
|
||||
let encoded_host: Vec<u8> = match address.ip() {
|
||||
IpAddr::V4(ip) => std::iter::once(AddressType::V4.into())
|
||||
.chain(port_bytes.iter().cloned())
|
||||
.chain(ip.octets().iter().cloned())
|
||||
.chain(std::iter::repeat(0))
|
||||
.take(32)
|
||||
.collect(),
|
||||
IpAddr::V6(ip) => std::iter::once(AddressType::V6.into())
|
||||
.chain(port_bytes.iter().cloned())
|
||||
.chain(ip.octets().iter().cloned())
|
||||
.chain(std::iter::repeat(0))
|
||||
.take(32)
|
||||
.collect(),
|
||||
};
|
||||
|
||||
let mut address_bytes = [0u8; 32];
|
||||
address_bytes.copy_from_slice(&encoded_host[..32]);
|
||||
|
||||
address_bytes
|
||||
}
|
||||
|
||||
pub fn socket_address_from_encoded_bytes(b: [u8; 32]) -> Result<SocketAddr, AddressTypeError> {
|
||||
let address_type: AddressType = b[0].try_into()?;
|
||||
|
||||
let port: u16 = u16::from_be_bytes([b[1], b[2]]);
|
||||
|
||||
let ip = match address_type {
|
||||
AddressType::V4 => IpAddr::V4(Ipv4Addr::new(b[3], b[4], b[5], b[6])),
|
||||
AddressType::V6 => {
|
||||
let mut address_octets = [0u8; 16];
|
||||
address_octets.copy_from_slice(&b[3..19]);
|
||||
IpAddr::V6(Ipv6Addr::from(address_octets))
|
||||
}
|
||||
};
|
||||
|
||||
Ok(SocketAddr::new(ip, port))
|
||||
}
|
||||
@@ -14,7 +14,7 @@ rand_distr = "0.2.2"
|
||||
tokio = { version = "0.2", features = ["full"] }
|
||||
|
||||
## internal
|
||||
addressing = {path = "../../addressing"}
|
||||
nymsphinx = {path = "../../nymsphinx"}
|
||||
topology = {path = "../../topology"}
|
||||
|
||||
## will be moved to proper dependencies once released
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use addressing;
|
||||
use addressing::AddressTypeError;
|
||||
use nymsphinx::addressing::nodes::{NymNodeRoutingAddress, NymNodeRoutingAddressError};
|
||||
use sphinx::route::{Destination, DestinationAddressBytes, SURBIdentifier};
|
||||
use sphinx::SphinxPacket;
|
||||
use std::convert::TryFrom;
|
||||
use std::net::SocketAddr;
|
||||
use std::time;
|
||||
use topology::{NymTopology, NymTopologyError};
|
||||
@@ -32,8 +32,8 @@ impl From<sphinx::header::SphinxUnwrapError> for SphinxPacketEncapsulationError
|
||||
}
|
||||
}
|
||||
|
||||
impl From<AddressTypeError> for SphinxPacketEncapsulationError {
|
||||
fn from(_: AddressTypeError) -> Self {
|
||||
impl From<NymNodeRoutingAddressError> for SphinxPacketEncapsulationError {
|
||||
fn from(_: NymNodeRoutingAddressError) -> Self {
|
||||
use SphinxPacketEncapsulationError::*;
|
||||
InvalidFirstMixAddress
|
||||
}
|
||||
@@ -96,9 +96,9 @@ pub fn encapsulate_message<T: NymTopology>(
|
||||
|
||||
// we know the mix route must be valid otherwise we would have already returned an error
|
||||
let first_node_address =
|
||||
addressing::socket_address_from_encoded_bytes(route.first().unwrap().address.to_bytes())?;
|
||||
NymNodeRoutingAddress::try_from(route.first().unwrap().address.clone())?;
|
||||
|
||||
Ok((first_node_address, packet))
|
||||
Ok((first_node_address.into(), packet))
|
||||
}
|
||||
|
||||
pub fn encapsulate_message_route(
|
||||
@@ -113,7 +113,7 @@ pub fn encapsulate_message_route(
|
||||
let packet = sphinx::SphinxPacket::new(message, &route[..], &recipient, &delays)?;
|
||||
|
||||
let first_node_address =
|
||||
addressing::socket_address_from_encoded_bytes(route.first().unwrap().address.to_bytes())?;
|
||||
NymNodeRoutingAddress::try_from(route.first().unwrap().address.clone())?;
|
||||
|
||||
Ok((first_node_address, packet))
|
||||
Ok((first_node_address.into(), packet))
|
||||
}
|
||||
|
||||
@@ -18,10 +18,10 @@ serde_derive = "1.0.104"
|
||||
tokio = { version = "0.2", features = ["full"] }
|
||||
|
||||
## internal
|
||||
addressing = {path = "../addressing" }
|
||||
crypto = { path = "../crypto" }
|
||||
directory-client = { path = "../clients/directory-client" }
|
||||
multi-tcp-client = { path = "../clients/multi-tcp-client" }
|
||||
nymsphinx = {path = "../nymsphinx" }
|
||||
provider-client = { path = "../clients/provider-client" }
|
||||
sfw-provider-requests = { path = "../../sfw-provider/sfw-provider-requests" }
|
||||
topology = {path = "../topology" }
|
||||
|
||||
@@ -1,10 +1,13 @@
|
||||
use crypto::identity::MixIdentityKeyPair;
|
||||
use itertools::Itertools;
|
||||
use log::{debug, error, info, trace, warn};
|
||||
use nymsphinx::addressing::nodes::NymNodeRoutingAddress;
|
||||
use provider_client::{ProviderClient, ProviderClientError};
|
||||
use sphinx::header::delays::Delay;
|
||||
use sphinx::route::{Destination, Node as SphinxNode};
|
||||
use std::collections::HashMap;
|
||||
use std::convert::TryFrom;
|
||||
use std::net::SocketAddr;
|
||||
use std::time::Duration;
|
||||
use topology::provider;
|
||||
|
||||
@@ -217,9 +220,10 @@ impl PathChecker {
|
||||
.expect("We checked the path to contain at least one entry");
|
||||
|
||||
// we generated the bytes data so unwrap is fine
|
||||
let first_node_address =
|
||||
addressing::socket_address_from_encoded_bytes(layer_one_mix.address.to_bytes())
|
||||
.unwrap();
|
||||
let first_node_address: SocketAddr =
|
||||
NymNodeRoutingAddress::try_from(layer_one_mix.address.clone())
|
||||
.unwrap()
|
||||
.into();
|
||||
|
||||
let delays: Vec<_> = path.iter().map(|_| Delay::new_from_nanos(0)).collect();
|
||||
|
||||
|
||||
@@ -10,12 +10,6 @@ edition = "2018"
|
||||
log = "0.4.8"
|
||||
rand = "0.7.3"
|
||||
|
||||
# TODO: eventually move this functionality to this crate and remove `addressing` completely
|
||||
addressing = {path = "../addressing" }
|
||||
|
||||
topology = {path = "../topology" }
|
||||
|
||||
|
||||
## will be moved to proper dependencies once released
|
||||
sphinx = { git = "https://github.com/nymtech/sphinx", rev="44d8f2aece5049eaa4fe84b7948758ce82b4b80d" }
|
||||
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
pub mod nodes;
|
||||
@@ -0,0 +1,206 @@
|
||||
use sphinx::constants::NODE_ADDRESS_LENGTH;
|
||||
use sphinx::route::NodeAddressBytes;
|
||||
use std::convert::{TryFrom, TryInto};
|
||||
use std::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr};
|
||||
|
||||
/// This module is responsible for encoding and decoding node routing information, so that
|
||||
/// they could be later put into an appropriate field in a sphinx header.
|
||||
/// Currently, that routing information is an IP address, but in principle it can be anything
|
||||
/// for as long as it's going to fit in the field.
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum NymNodeRoutingAddressError {
|
||||
InsufficientNumberOfBytesAvailableError,
|
||||
InvalidIPVersion,
|
||||
}
|
||||
|
||||
/// Current representation of Node routing information used in Nym system.
|
||||
/// At this point of time it is a simple `SocketAddr`.
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
|
||||
pub struct NymNodeRoutingAddress(SocketAddr);
|
||||
|
||||
impl NymNodeRoutingAddress {
|
||||
/// Minimum number of bytes that need to be available to represent self.
|
||||
/// The value has no upper bound as when converted into bytes, it's always
|
||||
/// padded with zeroes to be exactly NODE_ADDRESS_LENGTH long.
|
||||
pub fn bytes_min_len(&self) -> usize {
|
||||
match self.0 {
|
||||
SocketAddr::V4(_) => 7,
|
||||
SocketAddr::V6(_) => 19,
|
||||
}
|
||||
}
|
||||
|
||||
/// Converts self into a vector of bytes.
|
||||
/// Note, this represents a generic bytes vector, not necessarily a NodeAddressBytes
|
||||
/// and hence is not zero-padded.
|
||||
pub fn as_bytes(&self) -> Vec<u8> {
|
||||
let port_bytes = self.0.port().to_be_bytes();
|
||||
let ip_octets_vec = match self.0.ip() {
|
||||
IpAddr::V4(ip) => ip.octets().to_vec(),
|
||||
IpAddr::V6(ip) => ip.octets().to_vec(),
|
||||
};
|
||||
|
||||
std::iter::once(self.addr_type_as_u8())
|
||||
.chain(port_bytes.iter().cloned())
|
||||
.chain(ip_octets_vec.iter().cloned())
|
||||
.collect()
|
||||
}
|
||||
|
||||
/// Tries to recover `Self` from a bytes slice.
|
||||
/// Does not care if it's zero-padded or not.
|
||||
pub fn try_from_bytes(b: &[u8]) -> Result<Self, NymNodeRoutingAddressError> {
|
||||
// the bare minimum to represent `Self` is 7 bytes (for the shorter V4 version)
|
||||
if b.len() < 7 {
|
||||
return Err(NymNodeRoutingAddressError::InsufficientNumberOfBytesAvailableError);
|
||||
}
|
||||
|
||||
let ip_version = b[0];
|
||||
let port: u16 = u16::from_be_bytes([b[1], b[2]]);
|
||||
let ip = match ip_version {
|
||||
4 => IpAddr::V4(Ipv4Addr::new(b[3], b[4], b[5], b[6])),
|
||||
6 => {
|
||||
if b.len() < 19 {
|
||||
return Err(
|
||||
NymNodeRoutingAddressError::InsufficientNumberOfBytesAvailableError,
|
||||
);
|
||||
}
|
||||
let mut address_octets = [0u8; 16];
|
||||
address_octets.copy_from_slice(&b[3..19]);
|
||||
IpAddr::V6(Ipv6Addr::from(address_octets))
|
||||
}
|
||||
_ => return Err(NymNodeRoutingAddressError::InvalidIPVersion),
|
||||
};
|
||||
|
||||
Ok(Self(SocketAddr::new(ip, port)))
|
||||
}
|
||||
|
||||
/// Single byte representation of self ip version.
|
||||
pub fn addr_type_as_u8(&self) -> u8 {
|
||||
match self.0 {
|
||||
SocketAddr::V4(_) => 4,
|
||||
SocketAddr::V6(_) => 6,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Considering `NymNodeRoutingAddress` is equivalent to a `SocketAddr` at this point,
|
||||
/// it makes perfect sense to allow the bilateral transformation.
|
||||
impl From<SocketAddr> for NymNodeRoutingAddress {
|
||||
fn from(addr: SocketAddr) -> Self {
|
||||
Self(addr)
|
||||
}
|
||||
}
|
||||
|
||||
/// Considering `NymNodeRoutingAddress` is equivalent to a `SocketAddr` at this point,
|
||||
/// it makes perfect sense to allow the bilateral transformation.
|
||||
impl Into<SocketAddr> for NymNodeRoutingAddress {
|
||||
fn into(self) -> SocketAddr {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl TryInto<NodeAddressBytes> for NymNodeRoutingAddress {
|
||||
type Error = NymNodeRoutingAddressError;
|
||||
|
||||
/// `NymNodeRoutingAddress` (as a `SocketAddr`) is represented the following way:
|
||||
/// VersionFlag || port || octets || zeropad
|
||||
/// VersionFlag is one byte representing whether self is ipv4 or ipv6 address,
|
||||
/// port is 16bit big endian representation of port value
|
||||
/// octets is bytes representation of octets making up the ip address of the socket address
|
||||
/// (either 4 bytes for ipv4 or 16 bytes for ipv6)
|
||||
/// zeropad is padding of 0 for the `NymNodeRoutingAddress` to be
|
||||
/// exactly `NODE_ADDRESS_LENGTH` long.
|
||||
fn try_into(self) -> Result<NodeAddressBytes, Self::Error> {
|
||||
// first check if we have enough bytes to represent `self`:
|
||||
if self.bytes_min_len() > NODE_ADDRESS_LENGTH {
|
||||
return Err(NymNodeRoutingAddressError::InsufficientNumberOfBytesAvailableError);
|
||||
}
|
||||
|
||||
let unpadded_address = self.as_bytes();
|
||||
let padded_address: Vec<_> = unpadded_address
|
||||
.into_iter()
|
||||
.chain(std::iter::repeat(0))
|
||||
.take(NODE_ADDRESS_LENGTH)
|
||||
.collect();
|
||||
|
||||
let mut node_address_bytes = [0u8; 32];
|
||||
node_address_bytes.copy_from_slice(&padded_address);
|
||||
|
||||
Ok(NodeAddressBytes::from_bytes(node_address_bytes))
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<NodeAddressBytes> for NymNodeRoutingAddress {
|
||||
type Error = NymNodeRoutingAddressError;
|
||||
|
||||
fn try_from(value: NodeAddressBytes) -> Result<Self, Self::Error> {
|
||||
Self::try_from_bytes(value.as_bytes())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn nym_node_routing_address_can_be_converted_to_and_from_bytes_for_v4_address() {
|
||||
let address = NymNodeRoutingAddress(SocketAddr::new(IpAddr::from([1, 2, 3, 4]), 42));
|
||||
let address_bytes = address.as_bytes();
|
||||
assert_eq!(
|
||||
address,
|
||||
NymNodeRoutingAddress::try_from_bytes(&address_bytes).unwrap()
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn nym_node_routing_address_can_be_converted_to_and_from_bytes_for_v6_address() {
|
||||
let address = NymNodeRoutingAddress(SocketAddr::new(
|
||||
IpAddr::from([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]),
|
||||
42,
|
||||
));
|
||||
let address_bytes = address.as_bytes();
|
||||
assert_eq!(
|
||||
address,
|
||||
NymNodeRoutingAddress::try_from_bytes(&address_bytes).unwrap()
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn nym_node_routing_address_can_be_converted_to_and_from_bytes_for_empty_v4_address() {
|
||||
let address = NymNodeRoutingAddress(SocketAddr::new(IpAddr::from([0, 0, 0, 0]), 42));
|
||||
let address_bytes = address.as_bytes();
|
||||
assert_eq!(
|
||||
address,
|
||||
NymNodeRoutingAddress::try_from_bytes(&address_bytes).unwrap()
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn nym_node_routing_address_can_be_converted_to_and_from_bytes_for_empty_v6_address() {
|
||||
let address = NymNodeRoutingAddress(SocketAddr::new(
|
||||
IpAddr::from([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]),
|
||||
42,
|
||||
));
|
||||
let address_bytes = address.as_bytes();
|
||||
assert_eq!(
|
||||
address,
|
||||
NymNodeRoutingAddress::try_from_bytes(&address_bytes).unwrap()
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn nym_node_routing_address_can_be_converted_to_and_from_node_address_bytes_with_no_data_loss()
|
||||
{
|
||||
let address_v4 = NymNodeRoutingAddress(SocketAddr::new(IpAddr::from([1, 2, 3, 4]), 42));
|
||||
let address_v6 = NymNodeRoutingAddress(SocketAddr::new(
|
||||
IpAddr::from([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]),
|
||||
42,
|
||||
));
|
||||
|
||||
let node_address1: NodeAddressBytes = address_v4.try_into().unwrap();
|
||||
let node_address2: NodeAddressBytes = address_v6.try_into().unwrap();
|
||||
|
||||
assert_eq!(address_v4, node_address1.try_into().unwrap());
|
||||
assert_eq!(address_v6, node_address2.try_into().unwrap());
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,4 @@
|
||||
use crate::chunking::set::split_into_sets;
|
||||
use addressing::AddressTypeError;
|
||||
use sphinx::route::{Destination, Node};
|
||||
use std::net::SocketAddr;
|
||||
use std::time;
|
||||
use topology::{NymTopology, NymTopologyError};
|
||||
|
||||
pub mod fragment;
|
||||
pub mod reconstruction;
|
||||
@@ -48,25 +43,6 @@ pub enum ChunkingError {
|
||||
UnexpectedFragmentCount,
|
||||
}
|
||||
|
||||
impl From<topology::NymTopologyError> for ChunkingError {
|
||||
fn from(_: NymTopologyError) -> Self {
|
||||
use ChunkingError::*;
|
||||
NoValidRoutesAvailableError
|
||||
}
|
||||
}
|
||||
|
||||
// this will later be completely removed when `addressing` crate is moved into this crate
|
||||
impl From<AddressTypeError> for ChunkingError {
|
||||
fn from(_: AddressTypeError) -> Self {
|
||||
use ChunkingError::*;
|
||||
InvalidTopologyError
|
||||
}
|
||||
}
|
||||
|
||||
// the user of this library can either prepare payloads for sphinx packets that he needs to
|
||||
// encapsulate themselves by creating [sphinx] headers.
|
||||
// or alternatively provide network topology and get bytes ready to be sent over the network
|
||||
|
||||
/// Takes the entire message and splits it into bytes chunks that will fit into sphinx packets
|
||||
/// directly. After receiving they can be combined using `reconstruction::MessageReconstructor`
|
||||
/// to obtain the original message back.
|
||||
@@ -78,43 +54,3 @@ pub fn split_and_prepare_payloads(message: &[u8]) -> Vec<Vec<u8>> {
|
||||
.map(|fragment| fragment.into_bytes())
|
||||
.collect()
|
||||
}
|
||||
|
||||
// note that for very long messages, this function will take a very long time to complete
|
||||
// due to expensive sphinx wrapping operations
|
||||
|
||||
/// Takes the entire message and splits it into bytes chunks that are then encapsulated into
|
||||
/// sphinx packets usingn provided network topology. The resultant bytes chunks can be sent
|
||||
/// directly on the wire to the `SocketAddr` part of the tuple.
|
||||
/// After being received back by a client they can be combined using `reconstruction::MessageReconstructor`
|
||||
/// to obtain the original message back.
|
||||
pub fn split_and_encapsulate_message<T: NymTopology>(
|
||||
message: &[u8],
|
||||
// TODO: in the future this will require also a specific provider of this particular recipient
|
||||
recipient: Destination,
|
||||
average_delay: time::Duration,
|
||||
topology: &T,
|
||||
) -> Result<Vec<(SocketAddr, Vec<u8>)>, ChunkingError> {
|
||||
let ready_payloads = split_and_prepare_payloads(message);
|
||||
|
||||
let mut providers = topology.providers();
|
||||
if providers.is_empty() {
|
||||
return Err(ChunkingError::NoValidProvidersError);
|
||||
}
|
||||
let provider: Node = providers.pop().unwrap().into();
|
||||
|
||||
let mut encapsulated_sphinx_packets = Vec::new();
|
||||
for message_fragment in ready_payloads {
|
||||
let route = topology.route_to(provider.clone())?;
|
||||
let delays =
|
||||
sphinx::header::delays::generate_from_average_duration(route.len(), average_delay);
|
||||
let packet =
|
||||
sphinx::SphinxPacket::new(message_fragment, &route[..], &recipient, &delays).unwrap(); // this cannot fail unless there's an underlying bug which we must find and fix anyway
|
||||
let first_node_address = addressing::socket_address_from_encoded_bytes(
|
||||
route.first().unwrap().address.to_bytes(),
|
||||
)?;
|
||||
|
||||
encapsulated_sphinx_packets.push((first_node_address, packet.to_bytes()));
|
||||
}
|
||||
|
||||
Ok(encapsulated_sphinx_packets)
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
pub mod addressing;
|
||||
pub mod chunking;
|
||||
|
||||
// Future consideration: currently in a lot of places, the payloads have randomised content
|
||||
|
||||
@@ -15,7 +15,7 @@ rand = "0.7.2"
|
||||
serde = { version = "1.0.104", features = ["derive"] }
|
||||
|
||||
## internal
|
||||
addressing = {path = "../addressing"}
|
||||
nymsphinx = {path = "../nymsphinx"}
|
||||
version-checker = {path = "../version-checker" }
|
||||
|
||||
## will be moved to proper dependencies once released
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
use crate::filter;
|
||||
use nymsphinx::addressing::nodes::NymNodeRoutingAddress;
|
||||
use sphinx::route::Node as SphinxNode;
|
||||
use sphinx::route::NodeAddressBytes;
|
||||
use std::convert::TryInto;
|
||||
use std::net::SocketAddr;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
@@ -29,10 +30,10 @@ impl filter::Versioned for Node {
|
||||
|
||||
impl Into<SphinxNode> for Node {
|
||||
fn into(self) -> SphinxNode {
|
||||
let address_bytes = addressing::encoded_bytes_from_socket_address(self.host);
|
||||
let node_address_bytes = NymNodeRoutingAddress::from(self.host).try_into().unwrap();
|
||||
let key_bytes = self.get_pub_key_bytes();
|
||||
let key = sphinx::key::new(key_bytes);
|
||||
|
||||
SphinxNode::new(NodeAddressBytes::from_bytes(address_bytes), key)
|
||||
SphinxNode::new(node_address_bytes, key)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
use crate::filter;
|
||||
use nymsphinx::addressing::nodes::NymNodeRoutingAddress;
|
||||
use sphinx::route::Node as SphinxNode;
|
||||
use sphinx::route::NodeAddressBytes;
|
||||
use std::convert::TryInto;
|
||||
use std::net::SocketAddr;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
@@ -35,10 +36,12 @@ impl filter::Versioned for Node {
|
||||
|
||||
impl Into<SphinxNode> for Node {
|
||||
fn into(self) -> SphinxNode {
|
||||
let address_bytes = addressing::encoded_bytes_from_socket_address(self.mixnet_listener);
|
||||
let node_address_bytes = NymNodeRoutingAddress::from(self.mixnet_listener)
|
||||
.try_into()
|
||||
.unwrap();
|
||||
let key_bytes = self.get_pub_key_bytes();
|
||||
let key = sphinx::key::new(key_bytes);
|
||||
|
||||
SphinxNode::new(NodeAddressBytes::from_bytes(address_bytes), key)
|
||||
SphinxNode::new(node_address_bytes, key)
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -20,11 +20,11 @@ serde = { version = "1.0.104", features = ["derive"] }
|
||||
tokio = { version = "0.2", features = ["full"] }
|
||||
|
||||
## internal
|
||||
addressing = {path = "../common/addressing" }
|
||||
config = {path = "../common/config"}
|
||||
crypto = {path = "../common/crypto"}
|
||||
directory-client = { path = "../common/clients/directory-client" }
|
||||
multi-tcp-client = { path = "../common/clients/multi-tcp-client" }
|
||||
nymsphinx = {path = "../common/nymsphinx" }
|
||||
pemstore = {path = "../common/pemstore"}
|
||||
topology = {path = "../common/topology"}
|
||||
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
use crate::node::metrics;
|
||||
use addressing::AddressTypeError;
|
||||
use crypto::encryption;
|
||||
use log::*;
|
||||
use nymsphinx::addressing::nodes::{NymNodeRoutingAddress, NymNodeRoutingAddressError};
|
||||
use sphinx::header::delays::Delay as SphinxDelay;
|
||||
use sphinx::route::NodeAddressBytes;
|
||||
use sphinx::{ProcessedPacket, SphinxPacket};
|
||||
use std::convert::TryFrom;
|
||||
use std::net::SocketAddr;
|
||||
use std::ops::Deref;
|
||||
use std::sync::Arc;
|
||||
@@ -32,8 +33,8 @@ impl From<sphinx::ProcessingError> for MixProcessingError {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<addressing::AddressTypeError> for MixProcessingError {
|
||||
fn from(_: AddressTypeError) -> Self {
|
||||
impl From<NymNodeRoutingAddressError> for MixProcessingError {
|
||||
fn from(_: NymNodeRoutingAddressError) -> Self {
|
||||
use MixProcessingError::*;
|
||||
|
||||
InvalidHopAddress
|
||||
@@ -68,8 +69,7 @@ impl PacketProcessor {
|
||||
forward_address: NodeAddressBytes,
|
||||
delay: SphinxDelay,
|
||||
) -> Result<MixProcessingResult, MixProcessingError> {
|
||||
let next_hop_address =
|
||||
addressing::socket_address_from_encoded_bytes(forward_address.to_bytes())?;
|
||||
let next_hop_address: SocketAddr = NymNodeRoutingAddress::try_from(forward_address)?.into();
|
||||
|
||||
// Delay packet for as long as required
|
||||
tokio::time::delay_for(delay.to_duration()).await;
|
||||
|
||||
@@ -28,7 +28,6 @@ tokio = { version = "0.2", features = ["full"] }
|
||||
tokio-tungstenite = "0.10.1"
|
||||
|
||||
## internal
|
||||
addressing = {path = "../common/addressing" }
|
||||
config = {path = "../common/config"}
|
||||
crypto = {path = "../common/crypto"}
|
||||
directory-client = { path = "../common/clients/directory-client" }
|
||||
|
||||
Reference in New Issue
Block a user