modularization
This commit is contained in:
parent
bfa4fe617f
commit
94dbd35fea
@ -60,6 +60,7 @@ mix:
|
||||
cryptographic_processor:
|
||||
private_key: [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]
|
||||
num_mix_layers: 1
|
||||
message_settings:
|
||||
temporal_processor:
|
||||
max_delay_seconds: 5
|
||||
membership:
|
||||
|
@ -9,15 +9,16 @@ pub struct CryptographicProcessor<R, M>
|
||||
where
|
||||
M: MixMessage,
|
||||
{
|
||||
settings: CryptographicProcessorSettings<M::PrivateKey>,
|
||||
settings: CryptographicProcessorSettings<M::PrivateKey, M::Settings>,
|
||||
membership: Membership<M>,
|
||||
rng: R,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
pub struct CryptographicProcessorSettings<K> {
|
||||
pub struct CryptographicProcessorSettings<K, S> {
|
||||
pub private_key: K,
|
||||
pub num_mix_layers: usize,
|
||||
pub message_settings: S,
|
||||
}
|
||||
|
||||
impl<R, M> CryptographicProcessor<R, M>
|
||||
@ -27,7 +28,7 @@ where
|
||||
M::PublicKey: Clone + PartialEq,
|
||||
{
|
||||
pub fn new(
|
||||
settings: CryptographicProcessorSettings<M::PrivateKey>,
|
||||
settings: CryptographicProcessorSettings<M::PrivateKey, M::Settings>,
|
||||
membership: Membership<M>,
|
||||
rng: R,
|
||||
) -> Self {
|
||||
@ -38,7 +39,7 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
pub fn wrap_message(&mut self, message: &[u8]) -> Result<Vec<u8>, nomos_mix_message::Error> {
|
||||
pub fn wrap_message(&mut self, message: &[u8]) -> Result<Vec<u8>, M::Error> {
|
||||
// TODO: Use the actual Sphinx encoding instead of mock.
|
||||
let public_keys = self
|
||||
.membership
|
||||
@ -47,13 +48,14 @@ where
|
||||
.map(|node| node.public_key.clone())
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
M::build_message(message, &public_keys)
|
||||
M::build_message(message, &public_keys, &self.settings.message_settings)
|
||||
}
|
||||
|
||||
pub fn unwrap_message(
|
||||
&self,
|
||||
message: &[u8],
|
||||
) -> Result<(Vec<u8>, bool), nomos_mix_message::Error> {
|
||||
M::unwrap_message(message, &self.settings.private_key)
|
||||
pub fn unwrap_message(&self, message: &[u8]) -> Result<(Vec<u8>, bool), M::Error> {
|
||||
M::unwrap_message(
|
||||
message,
|
||||
&self.settings.private_key,
|
||||
&self.settings.message_settings,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -4,6 +4,7 @@ pub mod temporal;
|
||||
pub use crypto::CryptographicProcessorSettings;
|
||||
use futures::{Stream, StreamExt};
|
||||
use rand::RngCore;
|
||||
use std::fmt::Debug;
|
||||
use std::marker::PhantomData;
|
||||
use std::pin::Pin;
|
||||
use std::task::{Context, Poll};
|
||||
@ -25,8 +26,9 @@ pub struct MessageBlendSettings<M>
|
||||
where
|
||||
M: MixMessage,
|
||||
M::PrivateKey: Serialize + DeserializeOwned,
|
||||
M::Settings: Serialize + DeserializeOwned,
|
||||
{
|
||||
pub cryptographic_processor: CryptographicProcessorSettings<M::PrivateKey>,
|
||||
pub cryptographic_processor: CryptographicProcessorSettings<M::PrivateKey, M::Settings>,
|
||||
pub temporal_processor: TemporalSchedulerSettings,
|
||||
}
|
||||
|
||||
@ -52,6 +54,8 @@ where
|
||||
M: MixMessage,
|
||||
M::PrivateKey: Serialize + DeserializeOwned,
|
||||
M::PublicKey: Clone + PartialEq,
|
||||
M::Settings: Serialize + DeserializeOwned,
|
||||
M::Error: Debug,
|
||||
Scheduler: Stream<Item = ()> + Unpin + Send + Sync + 'static,
|
||||
{
|
||||
pub fn new(
|
||||
@ -91,9 +95,6 @@ where
|
||||
tracing::error!("Failed to send message to the outbound channel: {e:?}");
|
||||
}
|
||||
}
|
||||
Err(nomos_mix_message::Error::MsgUnwrapNotAllowed) => {
|
||||
tracing::debug!("Message cannot be unwrapped by this node");
|
||||
}
|
||||
Err(e) => {
|
||||
tracing::error!("Failed to unwrap message: {:?}", e);
|
||||
}
|
||||
@ -108,6 +109,8 @@ where
|
||||
M: MixMessage + Unpin,
|
||||
M::PrivateKey: Serialize + DeserializeOwned + Unpin,
|
||||
M::PublicKey: Clone + PartialEq + Unpin,
|
||||
M::Settings: Serialize + DeserializeOwned + Unpin,
|
||||
M::Error: Debug,
|
||||
Scheduler: Stream<Item = ()> + Unpin + Send + Sync + 'static,
|
||||
{
|
||||
type Item = MixOutgoingMessage;
|
||||
@ -126,6 +129,8 @@ where
|
||||
M: MixMessage,
|
||||
M::PrivateKey: Serialize + DeserializeOwned,
|
||||
M::PublicKey: Clone + PartialEq,
|
||||
M::Settings: Serialize + DeserializeOwned,
|
||||
M::Error: Debug,
|
||||
Scheduler: Stream<Item = ()> + Unpin + Send + Sync + 'static,
|
||||
{
|
||||
fn blend(
|
||||
@ -155,6 +160,8 @@ where
|
||||
M: MixMessage,
|
||||
M::PrivateKey: Clone + Serialize + DeserializeOwned + PartialEq,
|
||||
M::PublicKey: Clone + Serialize + DeserializeOwned + PartialEq,
|
||||
M::Settings: Clone + Serialize + DeserializeOwned,
|
||||
M::Error: Debug,
|
||||
S: Stream<Item = ()> + Unpin + Send + Sync + 'static,
|
||||
{
|
||||
}
|
||||
|
@ -5,6 +5,7 @@ edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
rand_chacha = "0.3"
|
||||
serde = { version = "1", features = ["derive"] }
|
||||
sha2 = "0.10"
|
||||
sphinx-packet = "0.2"
|
||||
thiserror = "1.0.65"
|
||||
|
@ -1,22 +0,0 @@
|
||||
#[derive(thiserror::Error, Debug)]
|
||||
pub enum Error {
|
||||
#[error("Invalid mix message format")]
|
||||
InvalidMixMessage,
|
||||
#[error("Payload is too large")]
|
||||
PayloadTooLarge,
|
||||
#[error("Invalid number of layers")]
|
||||
InvalidNumberOfLayers,
|
||||
#[error("Sphinx packet error: {0}")]
|
||||
SphinxPacketError(#[from] sphinx_packet::Error),
|
||||
#[error("Invalid packet")]
|
||||
InvalidPacket,
|
||||
#[error("Invalid routing flag: {0}")]
|
||||
InvalidRoutingFlag(u8),
|
||||
#[error("Invalid routing length: {0}")]
|
||||
InvalidEncryptedRoutingInfoLength(usize),
|
||||
#[error("ConsistentLengthLayeredEncryptionError: {0}")]
|
||||
ConsistentLengthLayeredEncryptionError(#[from] crate::layered_cipher::Error),
|
||||
#[error("Unwrapping a message is not allowed to this node")]
|
||||
/// e.g. the message cannot be unwrapped using the private key provided
|
||||
MsgUnwrapNotAllowed,
|
||||
}
|
@ -1,17 +1,18 @@
|
||||
mod error;
|
||||
mod layered_cipher;
|
||||
pub mod mock;
|
||||
pub mod packet;
|
||||
mod routing;
|
||||
|
||||
pub use error::Error;
|
||||
pub mod sphinx;
|
||||
|
||||
pub trait MixMessage {
|
||||
type PublicKey;
|
||||
type PrivateKey;
|
||||
type Settings;
|
||||
type Error;
|
||||
const DROP_MESSAGE: &'static [u8];
|
||||
|
||||
fn build_message(payload: &[u8], public_keys: &[Self::PublicKey]) -> Result<Vec<u8>, Error>;
|
||||
fn build_message(
|
||||
payload: &[u8],
|
||||
public_keys: &[Self::PublicKey],
|
||||
settings: &Self::Settings,
|
||||
) -> Result<Vec<u8>, Self::Error>;
|
||||
/// Unwrap the message one layer.
|
||||
///
|
||||
/// This function returns the unwrapped message and a boolean indicating whether the message was fully unwrapped.
|
||||
@ -22,31 +23,9 @@ pub trait MixMessage {
|
||||
fn unwrap_message(
|
||||
message: &[u8],
|
||||
private_key: &Self::PrivateKey,
|
||||
) -> Result<(Vec<u8>, bool), Error>;
|
||||
settings: &Self::Settings,
|
||||
) -> Result<(Vec<u8>, bool), Self::Error>;
|
||||
fn is_drop_message(message: &[u8]) -> bool {
|
||||
message == Self::DROP_MESSAGE
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn concat_bytes(bytes_list: &[&[u8]]) -> Vec<u8> {
|
||||
let mut buf = Vec::with_capacity(bytes_list.iter().map(|bytes| bytes.len()).sum());
|
||||
bytes_list
|
||||
.iter()
|
||||
.for_each(|bytes| buf.extend_from_slice(bytes));
|
||||
buf
|
||||
}
|
||||
|
||||
pub(crate) fn parse_bytes<'a>(data: &'a [u8], sizes: &[usize]) -> Result<Vec<&'a [u8]>, String> {
|
||||
let mut i = 0;
|
||||
sizes
|
||||
.iter()
|
||||
.map(|&size| {
|
||||
if i + size > data.len() {
|
||||
return Err("The sum of sizes exceeds the length of the input slice".to_string());
|
||||
}
|
||||
let slice = &data[i..i + size];
|
||||
i += size;
|
||||
Ok(slice)
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
12
nomos-mix/message/src/mock/error.rs
Normal file
12
nomos-mix/message/src/mock/error.rs
Normal file
@ -0,0 +1,12 @@
|
||||
#[derive(thiserror::Error, Debug)]
|
||||
pub enum Error {
|
||||
#[error("Invalid mix message format")]
|
||||
InvalidMixMessage,
|
||||
#[error("Payload is too large")]
|
||||
PayloadTooLarge,
|
||||
#[error("Invalid number of layers")]
|
||||
InvalidNumberOfLayers,
|
||||
#[error("Unwrapping a message is not allowed to this node")]
|
||||
/// e.g. the message cannot be unwrapped using the private key provided
|
||||
MsgUnwrapNotAllowed,
|
||||
}
|
@ -1,4 +1,8 @@
|
||||
use crate::{Error, MixMessage};
|
||||
pub mod error;
|
||||
|
||||
use error::Error;
|
||||
|
||||
use crate::MixMessage;
|
||||
// TODO: Remove all the mock below once the actual implementation is integrated to the system.
|
||||
//
|
||||
/// A mock implementation of the Sphinx encoding.
|
||||
@ -17,13 +21,19 @@ pub struct MockMixMessage;
|
||||
impl MixMessage for MockMixMessage {
|
||||
type PublicKey = [u8; NODE_ID_SIZE];
|
||||
type PrivateKey = [u8; NODE_ID_SIZE];
|
||||
type Settings = ();
|
||||
type Error = Error;
|
||||
const DROP_MESSAGE: &'static [u8] = &[0; MESSAGE_SIZE];
|
||||
|
||||
/// The length of the encoded message is fixed to [`MESSAGE_SIZE`] bytes.
|
||||
/// The [`MAX_LAYERS`] number of [`NodeId`]s are concatenated in front of the payload.
|
||||
/// The payload is zero-padded to the end.
|
||||
///
|
||||
fn build_message(payload: &[u8], public_keys: &[Self::PublicKey]) -> Result<Vec<u8>, Error> {
|
||||
fn build_message(
|
||||
payload: &[u8],
|
||||
public_keys: &[Self::PublicKey],
|
||||
_: &Self::Settings,
|
||||
) -> Result<Vec<u8>, Self::Error> {
|
||||
// In this mock, we don't encrypt anything. So, we use public key as just a node ID.
|
||||
let node_ids = public_keys;
|
||||
if node_ids.is_empty() || node_ids.len() > MAX_LAYERS {
|
||||
@ -54,7 +64,8 @@ impl MixMessage for MockMixMessage {
|
||||
fn unwrap_message(
|
||||
message: &[u8],
|
||||
private_key: &Self::PrivateKey,
|
||||
) -> Result<(Vec<u8>, bool), Error> {
|
||||
_: &Self::Settings,
|
||||
) -> Result<(Vec<u8>, bool), Self::Error> {
|
||||
if message.len() != MESSAGE_SIZE {
|
||||
return Err(Error::InvalidMixMessage);
|
||||
}
|
||||
@ -96,21 +107,21 @@ mod tests {
|
||||
fn message() {
|
||||
let node_ids = (0..3).map(|i| [i; NODE_ID_SIZE]).collect::<Vec<_>>();
|
||||
let payload = [7; 10];
|
||||
let message = MockMixMessage::build_message(&payload, &node_ids).unwrap();
|
||||
let message = MockMixMessage::build_message(&payload, &node_ids, &()).unwrap();
|
||||
assert_eq!(message.len(), MESSAGE_SIZE);
|
||||
|
||||
let (message, is_fully_unwrapped) =
|
||||
MockMixMessage::unwrap_message(&message, &node_ids[0]).unwrap();
|
||||
MockMixMessage::unwrap_message(&message, &node_ids[0], &()).unwrap();
|
||||
assert!(!is_fully_unwrapped);
|
||||
assert_eq!(message.len(), MESSAGE_SIZE);
|
||||
|
||||
let (message, is_fully_unwrapped) =
|
||||
MockMixMessage::unwrap_message(&message, &node_ids[1]).unwrap();
|
||||
MockMixMessage::unwrap_message(&message, &node_ids[1], &()).unwrap();
|
||||
assert!(!is_fully_unwrapped);
|
||||
assert_eq!(message.len(), MESSAGE_SIZE);
|
||||
|
||||
let (unwrapped_payload, is_fully_unwrapped) =
|
||||
MockMixMessage::unwrap_message(&message, &node_ids[2]).unwrap();
|
||||
MockMixMessage::unwrap_message(&message, &node_ids[2], &()).unwrap();
|
||||
assert!(is_fully_unwrapped);
|
||||
assert_eq!(unwrapped_payload, payload);
|
||||
}
|
||||
|
13
nomos-mix/message/src/sphinx/error.rs
Normal file
13
nomos-mix/message/src/sphinx/error.rs
Normal file
@ -0,0 +1,13 @@
|
||||
#[derive(thiserror::Error, Debug)]
|
||||
pub enum Error {
|
||||
#[error("Sphinx packet error: {0}")]
|
||||
SphinxPacketError(#[from] sphinx_packet::Error),
|
||||
#[error("Invalid packet bytes")]
|
||||
InvalidPacketBytes,
|
||||
#[error("Invalid routing flag: {0}")]
|
||||
InvalidRoutingFlag(u8),
|
||||
#[error("Invalid routing length: {0}")]
|
||||
InvalidEncryptedRoutingInfoLength(usize),
|
||||
#[error("ConsistentLengthLayeredEncryptionError: {0}")]
|
||||
ConsistentLengthLayeredEncryptionError(#[from] super::layered_cipher::Error),
|
||||
}
|
@ -13,14 +13,14 @@ use sphinx_packet::{
|
||||
},
|
||||
};
|
||||
|
||||
use crate::{concat_bytes, parse_bytes};
|
||||
use super::{concat_bytes, parse_bytes};
|
||||
|
||||
#[derive(thiserror::Error, Debug)]
|
||||
pub enum Error {
|
||||
#[error("Invalid data length")]
|
||||
InvalidDataLength,
|
||||
#[error("Invalid params")]
|
||||
InvalidParams,
|
||||
#[error("Invalid cipher text length")]
|
||||
InvalidCipherTextLength,
|
||||
#[error("Invalid encryption param")]
|
||||
InvalidEncryptionParam,
|
||||
#[error("Integrity MAC verification failed")]
|
||||
IntegrityMacVerificationFailed,
|
||||
}
|
||||
@ -96,7 +96,7 @@ impl<D: ConsistentLengthLayeredCipherData> ConsistentLengthLayeredCipher<D> {
|
||||
/// Perform the layered encryption.
|
||||
pub fn encrypt(&self, params: &[EncryptionParam<D>]) -> Result<(Vec<u8>, HeaderIntegrityMac)> {
|
||||
if params.is_empty() || params.len() > self.max_layers {
|
||||
return Err(Error::InvalidParams);
|
||||
return Err(Error::InvalidEncryptionParam);
|
||||
}
|
||||
|
||||
params
|
||||
@ -147,13 +147,16 @@ impl<D: ConsistentLengthLayeredCipherData> ConsistentLengthLayeredCipher<D> {
|
||||
&self,
|
||||
params: &[EncryptionParam<D>],
|
||||
) -> Result<(Vec<u8>, HeaderIntegrityMac)> {
|
||||
let last_param = params.last().ok_or(Error::InvalidParams)?;
|
||||
let last_param = params.last().ok_or(Error::InvalidEncryptionParam)?;
|
||||
|
||||
// Build fillers that will be appended to the last data.
|
||||
// The number of fillers must be the same as the number of intermediate layers
|
||||
// that will be decrypted later.
|
||||
// (excluding the last layer) that will be decrypted later.
|
||||
let fillers = self.build_fillers(¶ms[..params.len() - 1]);
|
||||
// Random bytes is used to fill the space between data and fillers.
|
||||
// Header integrity MAC doesn't need to be included in the last layer
|
||||
// because there is no next encrypted layer.
|
||||
// Instead, random bytes are used to fill the space between data and fillers.
|
||||
// The size of random bytes depends on the [`self.max_layers`].
|
||||
let random_bytes = random_bytes(self.total_size() - D::size() - fillers.len());
|
||||
|
||||
// First, concat the data and the random bytes, and encrypt it.
|
||||
@ -195,7 +198,7 @@ impl<D: ConsistentLengthLayeredCipherData> ConsistentLengthLayeredCipher<D> {
|
||||
key: &Key,
|
||||
) -> Result<(Vec<u8>, HeaderIntegrityMac, Vec<u8>)> {
|
||||
if encrypted_total_data.len() != self.total_size() {
|
||||
return Err(Error::InvalidDataLength);
|
||||
return Err(Error::InvalidCipherTextLength);
|
||||
}
|
||||
// If a wrong key is used, the decryption should fail.
|
||||
if !mac.verify(key.integrity_mac_key, encrypted_total_data) {
|
87
nomos-mix/message/src/sphinx/mod.rs
Normal file
87
nomos-mix/message/src/sphinx/mod.rs
Normal file
@ -0,0 +1,87 @@
|
||||
use error::Error;
|
||||
use packet::{Packet, UnpackedPacket};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::MixMessage;
|
||||
|
||||
pub mod error;
|
||||
mod layered_cipher;
|
||||
pub mod packet;
|
||||
mod routing;
|
||||
|
||||
pub struct SphinxMessage;
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct SphinxMessageSettings {
|
||||
pub max_layers: usize,
|
||||
pub max_payload_size: usize,
|
||||
}
|
||||
|
||||
const ASYM_KEY_SIZE: usize = 32;
|
||||
|
||||
impl MixMessage for SphinxMessage {
|
||||
type PublicKey = [u8; ASYM_KEY_SIZE];
|
||||
type PrivateKey = [u8; ASYM_KEY_SIZE];
|
||||
type Settings = SphinxMessageSettings;
|
||||
type Error = Error;
|
||||
|
||||
// TODO: Remove DROP_MESSAGE. Currently, an arbitrary size (2048) is used,
|
||||
// but we've decided to remove drop messages from the spec.
|
||||
const DROP_MESSAGE: &'static [u8] = &[0; 2048];
|
||||
|
||||
fn build_message(
|
||||
payload: &[u8],
|
||||
public_keys: &[Self::PublicKey],
|
||||
settings: &Self::Settings,
|
||||
) -> Result<Vec<u8>, Self::Error> {
|
||||
let packet = Packet::build(
|
||||
&public_keys
|
||||
.iter()
|
||||
.map(|k| x25519_dalek::PublicKey::from(*k))
|
||||
.collect::<Vec<_>>(),
|
||||
settings.max_layers,
|
||||
payload,
|
||||
settings.max_payload_size,
|
||||
)?;
|
||||
Ok(packet.to_bytes())
|
||||
}
|
||||
|
||||
fn unwrap_message(
|
||||
message: &[u8],
|
||||
private_key: &Self::PrivateKey,
|
||||
settings: &Self::Settings,
|
||||
) -> Result<(Vec<u8>, bool), Self::Error> {
|
||||
let packet = Packet::from_bytes(message, settings.max_layers)?;
|
||||
let unpacked_packet = packet.unpack(
|
||||
&x25519_dalek::StaticSecret::from(*private_key),
|
||||
settings.max_layers,
|
||||
)?;
|
||||
match unpacked_packet {
|
||||
UnpackedPacket::ToForward(packet) => Ok((packet.to_bytes(), false)),
|
||||
UnpackedPacket::FullyUnpacked(payload) => Ok((payload, true)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn concat_bytes(bytes_list: &[&[u8]]) -> Vec<u8> {
|
||||
let mut buf = Vec::with_capacity(bytes_list.iter().map(|bytes| bytes.len()).sum());
|
||||
bytes_list
|
||||
.iter()
|
||||
.for_each(|bytes| buf.extend_from_slice(bytes));
|
||||
buf
|
||||
}
|
||||
|
||||
fn parse_bytes<'a>(data: &'a [u8], sizes: &[usize]) -> Result<Vec<&'a [u8]>, String> {
|
||||
let mut i = 0;
|
||||
sizes
|
||||
.iter()
|
||||
.map(|&size| {
|
||||
if i + size > data.len() {
|
||||
return Err("The sum of sizes exceeds the length of the input slice".to_string());
|
||||
}
|
||||
let slice = &data[i..i + size];
|
||||
i += size;
|
||||
Ok(slice)
|
||||
})
|
||||
.collect()
|
||||
}
|
@ -1,4 +1,3 @@
|
||||
use crate::{concat_bytes, parse_bytes, routing::EncryptedRoutingInformation, Error};
|
||||
use sphinx_packet::{
|
||||
constants::NODE_ADDRESS_LENGTH,
|
||||
header::{
|
||||
@ -8,6 +7,10 @@ use sphinx_packet::{
|
||||
payload::Payload,
|
||||
};
|
||||
|
||||
use crate::sphinx::ASYM_KEY_SIZE;
|
||||
|
||||
use super::{concat_bytes, error::Error, parse_bytes, routing::EncryptedRoutingInformation};
|
||||
|
||||
/// A packet that contains a header and a payload.
|
||||
/// The header and payload are encrypted for the selected recipients.
|
||||
/// This packet can be serialized and sent over the network.
|
||||
@ -33,7 +36,7 @@ impl Packet {
|
||||
recipient_pubkeys: &[x25519_dalek::PublicKey],
|
||||
max_layers: usize,
|
||||
payload: &[u8],
|
||||
payload_size: usize,
|
||||
max_payload_size: usize,
|
||||
) -> Result<Self, Error> {
|
||||
// Derive `[sphinx_packet::header::keys::KeyMaterial]` for all recipients.
|
||||
let ephemeral_privkey = x25519_dalek::StaticSecret::random();
|
||||
@ -52,7 +55,7 @@ impl Packet {
|
||||
let payload = sphinx_packet::payload::Payload::encapsulate_message(
|
||||
payload,
|
||||
&payload_keys,
|
||||
payload_size,
|
||||
max_payload_size,
|
||||
)?;
|
||||
|
||||
Ok(Packet {
|
||||
@ -157,7 +160,7 @@ impl Packet {
|
||||
}
|
||||
|
||||
pub fn from_bytes(data: &[u8], max_layers: usize) -> Result<Self, Error> {
|
||||
let ephemeral_public_key_size = 32;
|
||||
let ephemeral_public_key_size = ASYM_KEY_SIZE;
|
||||
let encrypted_routing_info_size = EncryptedRoutingInformation::size(max_layers);
|
||||
let parsed = parse_bytes(
|
||||
data,
|
||||
@ -167,7 +170,7 @@ impl Packet {
|
||||
data.len() - ephemeral_public_key_size - encrypted_routing_info_size,
|
||||
],
|
||||
)
|
||||
.map_err(|_| Error::InvalidPacket)?;
|
||||
.map_err(|_| Error::InvalidPacketBytes)?;
|
||||
|
||||
Ok(Packet {
|
||||
header: Header {
|
||||
@ -269,13 +272,13 @@ mod tests {
|
||||
// Build a packet
|
||||
let max_layers = 5;
|
||||
let payload = [10u8; 512];
|
||||
let packet = Packet::build(&recipient_pubkeys, max_layers, &payload, 1024).unwrap();
|
||||
let max_payload_size = 1024;
|
||||
let packet =
|
||||
Packet::build(&recipient_pubkeys, max_layers, &payload, max_payload_size).unwrap();
|
||||
|
||||
// Calculate the expected packet size
|
||||
let pubkey_size = 32;
|
||||
let payload_size = 1024;
|
||||
let packet_size =
|
||||
pubkey_size + EncryptedRoutingInformation::size(max_layers) + payload_size;
|
||||
ASYM_KEY_SIZE + EncryptedRoutingInformation::size(max_layers) + max_payload_size;
|
||||
|
||||
// The serialized packet size must be the same as the expected size.
|
||||
assert_eq!(packet.to_bytes().len(), packet_size);
|
@ -7,12 +7,13 @@ use sphinx_packet::{
|
||||
},
|
||||
};
|
||||
|
||||
use crate::{
|
||||
use super::{
|
||||
concat_bytes,
|
||||
error::Error,
|
||||
layered_cipher::{
|
||||
ConsistentLengthLayeredCipher, ConsistentLengthLayeredCipherData, EncryptionParam, Key,
|
||||
},
|
||||
parse_bytes, Error,
|
||||
parse_bytes,
|
||||
};
|
||||
|
||||
/// A routing information that will be contained in a packet header
|
@ -224,6 +224,7 @@ pub fn new_node(
|
||||
cryptographic_processor: CryptographicProcessorSettings {
|
||||
private_key: mix_config.private_key.to_bytes(),
|
||||
num_mix_layers: 1,
|
||||
message_settings: (),
|
||||
},
|
||||
temporal_processor: TemporalSchedulerSettings {
|
||||
max_delay_seconds: 2,
|
||||
|
@ -161,6 +161,7 @@ pub fn create_executor_config(config: GeneralConfig) -> Config {
|
||||
cryptographic_processor: CryptographicProcessorSettings {
|
||||
private_key: config.mix_config.private_key.to_bytes(),
|
||||
num_mix_layers: 1,
|
||||
message_settings: (),
|
||||
},
|
||||
temporal_processor: TemporalSchedulerSettings {
|
||||
max_delay_seconds: 2,
|
||||
|
@ -247,6 +247,7 @@ pub fn create_validator_config(config: GeneralConfig) -> Config {
|
||||
cryptographic_processor: CryptographicProcessorSettings {
|
||||
private_key: config.mix_config.private_key.to_bytes(),
|
||||
num_mix_layers: 1,
|
||||
message_settings: (),
|
||||
},
|
||||
temporal_processor: TemporalSchedulerSettings {
|
||||
max_delay_seconds: 2,
|
||||
|
Loading…
x
Reference in New Issue
Block a user