nym-sphinx-wasm: various cleanups on packet creation
This commit is contained in:
+62
-22
@@ -14,15 +14,18 @@
|
||||
use crypto::identity::MixIdentityPublicKey;
|
||||
use curve25519_dalek::montgomery::MontgomeryPoint;
|
||||
use nymsphinx::addressing::nodes::NymNodeRoutingAddress;
|
||||
use nymsphinx::chunking::split_and_prepare_payloads;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde_json;
|
||||
use sphinx::header::delays;
|
||||
use sphinx::route::DestinationAddressBytes;
|
||||
use sphinx::route::NodeAddressBytes;
|
||||
use sphinx::route::{Destination, Node};
|
||||
use sphinx::SphinxPacket;
|
||||
use std::convert::TryFrom;
|
||||
use std::convert::TryInto;
|
||||
use std::net::SocketAddr;
|
||||
use std::time::Duration;
|
||||
|
||||
use wasm_bindgen::prelude::*;
|
||||
|
||||
mod utils;
|
||||
@@ -36,12 +39,12 @@ const IDENTIFIER_LENGTH: usize = 16;
|
||||
static ALLOC: wee_alloc::WeeAlloc = wee_alloc::WeeAlloc::INIT;
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub struct Route {
|
||||
pub struct JsonRoute {
|
||||
nodes: Vec<NodeData>,
|
||||
}
|
||||
|
||||
#[wasm_bindgen]
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[derive(Clone, Serialize, Deserialize)]
|
||||
pub struct NodeData {
|
||||
address: String,
|
||||
public_key: String,
|
||||
@@ -54,36 +57,73 @@ pub struct NodeData {
|
||||
/// Message chunking is currently not implemented. If the message exceeds the
|
||||
/// capacity of a single Sphinx packet, the extra information will be discarded.
|
||||
#[wasm_bindgen]
|
||||
pub fn create_sphinx_packet(rout: String, msg: &str, destination: &str) -> Vec<u8> {
|
||||
pub fn create_sphinx_packet(raw_route: &str, msg: &str, destination: &str) -> Vec<u8> {
|
||||
utils::set_panic_hook(); // nicer js errors.
|
||||
|
||||
let r: Route = serde_json::from_str(&rout).unwrap();
|
||||
let mut route: Vec<Node> = vec![];
|
||||
for node in r.nodes.iter() {
|
||||
let address = node.address.parse().unwrap();
|
||||
let public_key = public_key_from_str(&node.public_key);
|
||||
let n = NymNodeRoutingAddress(address);
|
||||
let x = Node::new(n.try_into().unwrap(), public_key);
|
||||
route.push(x);
|
||||
}
|
||||
let route = sphinx_route_from(raw_route);
|
||||
|
||||
let average_delay = Duration::from_secs_f64(1.0);
|
||||
let average_delay = Duration::from_secs_f64(0.1);
|
||||
let delays = delays::generate_from_average_duration(route.len(), average_delay);
|
||||
let dest_bytes = DestinationAddressBytes::from_base58_string(destination.to_owned());
|
||||
let dest = Destination::new(dest_bytes, [4u8; IDENTIFIER_LENGTH]);
|
||||
let message = split_and_prepare_payloads(&msg.as_bytes()).pop().unwrap();
|
||||
let sphinx_packet = match SphinxPacket::new(message, &route, &dest, &delays).unwrap() {
|
||||
SphinxPacket { header, payload } => SphinxPacket { header, payload },
|
||||
};
|
||||
|
||||
let mut message = nymsphinx::chunking::split_and_prepare_payloads(&msg.as_bytes());
|
||||
let sphinx_packet =
|
||||
match SphinxPacket::new(message.pop().unwrap(), &route, &dest, &delays).unwrap() {
|
||||
SphinxPacket { header, payload } => SphinxPacket { header, payload },
|
||||
};
|
||||
|
||||
sphinx_packet.to_bytes()
|
||||
payload(sphinx_packet, route)
|
||||
}
|
||||
|
||||
fn public_key_from_str(s: &str) -> MontgomeryPoint {
|
||||
/// Concatenate the first mix address bytes with the Sphinx packet.
|
||||
///
|
||||
/// The Nym gateway node has no idea what is inside the Sphinx packet, or where
|
||||
/// it should send a packet it receives. So we prepend the packet with the
|
||||
/// address bytes of the first mix inside the packet, so that the gateway can
|
||||
/// forward the packet to it.
|
||||
fn payload(sphinx_packet: SphinxPacket, route: Vec<Node>) -> Vec<u8> {
|
||||
let mut packet = sphinx_packet.to_bytes();
|
||||
let mut first_mix_address = route.first().unwrap().clone().address.to_bytes().to_vec();
|
||||
let mut bytes: Vec<u8> = vec![];
|
||||
bytes.append(&mut first_mix_address);
|
||||
bytes.append(&mut packet);
|
||||
bytes
|
||||
}
|
||||
|
||||
fn sphinx_route_from(raw_route: &str) -> Vec<Node> {
|
||||
let json_route: JsonRoute = serde_json::from_str(raw_route).unwrap();
|
||||
|
||||
assert!(
|
||||
json_route.nodes.len() > 0,
|
||||
"Sphinx packet must route to at least one mixnode."
|
||||
);
|
||||
|
||||
let mut sphinx_route: Vec<Node> = vec![];
|
||||
for node_data in json_route.nodes.iter() {
|
||||
let x = Node::try_from(node_data.clone()).expect("Malformed NodeData");
|
||||
sphinx_route.push(x);
|
||||
}
|
||||
sphinx_route
|
||||
}
|
||||
|
||||
// Converts a base58 &str into a public key (MontgomeryPoint)
|
||||
//
|
||||
// A TryInto would be nice here but this crate doesn't own MontgomeryPoint.
|
||||
fn public_key_from(s: &str) -> MontgomeryPoint {
|
||||
let src = MixIdentityPublicKey::from_base58_string(s.to_owned()).to_bytes();
|
||||
let mut dest: [u8; 32] = [0; 32];
|
||||
dest.copy_from_slice(&src);
|
||||
MontgomeryPoint(dest)
|
||||
}
|
||||
|
||||
impl TryFrom<NodeData> for Node {
|
||||
type Error = ();
|
||||
|
||||
fn try_from(node_data: NodeData) -> Result<Self, Self::Error> {
|
||||
let parsed: SocketAddr = node_data.address.parse().unwrap();
|
||||
let address: NodeAddressBytes = NymNodeRoutingAddress(parsed).try_into().unwrap();
|
||||
|
||||
let pub_key = public_key_from(&node_data.public_key);
|
||||
|
||||
Ok(Node { address, pub_key })
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user