diff --git a/nomos-mix/core/src/persistent_transmission.rs b/nomos-mix/core/src/persistent_transmission.rs index abb36a8a..b73be82a 100644 --- a/nomos-mix/core/src/persistent_transmission.rs +++ b/nomos-mix/core/src/persistent_transmission.rs @@ -148,6 +148,7 @@ enum CoinError { mod tests { use super::*; use futures::StreamExt; + use nomos_mix_message::mock::MockMixMessage; use tokio::sync::mpsc; macro_rules! assert_interval { @@ -188,7 +189,8 @@ mod tests { let lower_bound = expected_emission_interval - torelance; let upper_bound = expected_emission_interval + torelance; // prepare stream - let mut persistent_transmission_stream = stream.persistent_transmission(settings); + let mut persistent_transmission_stream: PersistentTransmissionStream<_, MockMixMessage> = + stream.persistent_transmission(settings); // Messages must be scheduled in non-blocking manner. schedule_sender.send(vec![1]).unwrap(); schedule_sender.send(vec![2]).unwrap(); @@ -213,16 +215,14 @@ mod tests { ); assert_interval!(&mut last_time, lower_bound, upper_bound); - assert_eq!( - persistent_transmission_stream.next().await.unwrap(), - DROP_MESSAGE.to_vec() - ); + assert!(MockMixMessage::is_drop_message( + &persistent_transmission_stream.next().await.unwrap() + )); assert_interval!(&mut last_time, lower_bound, upper_bound); - assert_eq!( - persistent_transmission_stream.next().await.unwrap(), - DROP_MESSAGE.to_vec() - ); + assert!(MockMixMessage::is_drop_message( + &persistent_transmission_stream.next().await.unwrap() + )); assert_interval!(&mut last_time, lower_bound, upper_bound); // Schedule a new message and check if it is emitted at the next interval diff --git a/nomos-mix/message/src/mock/mod.rs b/nomos-mix/message/src/mock/mod.rs index 4fa0a4da..18b99424 100644 --- a/nomos-mix/message/src/mock/mod.rs +++ b/nomos-mix/message/src/mock/mod.rs @@ -3,22 +3,21 @@ use crate::{Error, MixMessage}; // /// A mock implementation of the Sphinx encoding. -pub type NodeId = [u8; NODE_ID_SIZE]; -const NODE_ID_SIZE: usize = 32; -const DUMMY_NODE_ID: NodeId = [0; NODE_ID_SIZE]; +const PRIVATE_KEY_SIZE: usize = 32; +const PUBLIC_KEY_SIZE: usize = 32; const PADDED_PAYLOAD_SIZE: usize = 2048; const PAYLOAD_PADDING_SEPARATOR: u8 = 0x01; const PAYLOAD_PADDING_SEPARATOR_SIZE: usize = 1; const MAX_LAYERS: usize = 5; -pub const MESSAGE_SIZE: usize = NODE_ID_SIZE * MAX_LAYERS + PADDED_PAYLOAD_SIZE; +pub const MESSAGE_SIZE: usize = PUBLIC_KEY_SIZE * MAX_LAYERS + PADDED_PAYLOAD_SIZE; #[derive(Clone, Debug)] pub struct MockMixMessage; impl MixMessage for MockMixMessage { - type PublicKey = [u8; 32]; - type PrivateKey = [u8; 32]; + type PublicKey = [u8; PUBLIC_KEY_SIZE]; + type PrivateKey = [u8; PRIVATE_KEY_SIZE]; const DROP_MESSAGE: &'static [u8] = &[0; MESSAGE_SIZE]; /// The length of the encoded message is fixed to [`MESSAGE_SIZE`] bytes. @@ -39,7 +38,7 @@ impl MixMessage for MockMixMessage { message.extend(public_key); }); // If there is any remaining layers, fill them with zeros. - (0..MAX_LAYERS - public_keys.len()).for_each(|_| message.extend(&DUMMY_NODE_ID)); + (0..MAX_LAYERS - public_keys.len()).for_each(|_| message.extend(&[0; PUBLIC_KEY_SIZE])); // Append payload with padding message.extend(payload); @@ -55,8 +54,6 @@ impl MixMessage for MockMixMessage { message: &[u8], private_key: &Self::PrivateKey, ) -> Result<(Vec, bool), Error> { - let public_key_size = std::mem::size_of::(); - if message.len() != MESSAGE_SIZE { return Err(Error::InvalidMixMessage); } @@ -64,13 +61,13 @@ impl MixMessage for MockMixMessage { let public_key = x25519_dalek::PublicKey::from(&x25519_dalek::StaticSecret::from(*private_key)) .to_bytes(); - if message[0..public_key_size] != public_key { + if message[0..PUBLIC_KEY_SIZE] != public_key { return Err(Error::MsgUnwrapNotAllowed); } // If this is the last layer - if message[public_key_size..public_key_size * 2] == DUMMY_NODE_ID { - let padded_payload = &message[public_key_size * MAX_LAYERS..]; + if message[PUBLIC_KEY_SIZE..PUBLIC_KEY_SIZE * 2] == [0; PUBLIC_KEY_SIZE] { + let padded_payload = &message[PUBLIC_KEY_SIZE * MAX_LAYERS..]; // remove the payload padding match padded_payload .iter() @@ -85,36 +82,44 @@ impl MixMessage for MockMixMessage { } let mut new_message: Vec = Vec::with_capacity(MESSAGE_SIZE); - new_message.extend(&message[public_key_size..public_key_size * MAX_LAYERS]); - new_message.extend(&DUMMY_NODE_ID); - new_message.extend(&message[public_key_size * MAX_LAYERS..]); // padded payload + new_message.extend(&message[PUBLIC_KEY_SIZE..PUBLIC_KEY_SIZE * MAX_LAYERS]); + new_message.extend(&[0; PUBLIC_KEY_SIZE]); + new_message.extend(&message[PUBLIC_KEY_SIZE * MAX_LAYERS..]); // padded payload Ok((new_message, false)) } } #[cfg(test)] mod tests { - use crate::NODE_ID_SIZE; - use super::*; #[test] fn message() { - let node_ids = [[1; NODE_ID_SIZE], [2; NODE_ID_SIZE], [3; NODE_ID_SIZE]]; + let private_keys = [ + x25519_dalek::StaticSecret::random(), + x25519_dalek::StaticSecret::random(), + x25519_dalek::StaticSecret::random(), + ]; + let public_keys = private_keys + .iter() + .map(|k| x25519_dalek::PublicKey::from(k).to_bytes()) + .collect::>(); let payload = [7; 10]; - let message = new_message(&payload, &node_ids).unwrap(); + let message = MockMixMessage::build_message(&payload, &public_keys).unwrap(); assert_eq!(message.len(), MESSAGE_SIZE); - let (message, is_fully_unwrapped) = unwrap_message(&message, &node_ids[0]).unwrap(); + let (message, is_fully_unwrapped) = + MockMixMessage::unwrap_message(&message, &private_keys[0].to_bytes()).unwrap(); assert!(!is_fully_unwrapped); assert_eq!(message.len(), MESSAGE_SIZE); - let (message, is_fully_unwrapped) = unwrap_message(&message, &node_ids[1]).unwrap(); + let (message, is_fully_unwrapped) = + MockMixMessage::unwrap_message(&message, &private_keys[1].to_bytes()).unwrap(); assert!(!is_fully_unwrapped); assert_eq!(message.len(), MESSAGE_SIZE); let (unwrapped_payload, is_fully_unwrapped) = - super::unwrap_message(&message, &node_ids[2]).unwrap(); + MockMixMessage::unwrap_message(&message, &private_keys[2].to_bytes()).unwrap(); assert!(is_fully_unwrapped); assert_eq!(unwrapped_payload, payload); } diff --git a/nomos-mix/network/src/lib.rs b/nomos-mix/network/src/lib.rs index e61330e1..6db526e4 100644 --- a/nomos-mix/network/src/lib.rs +++ b/nomos-mix/network/src/lib.rs @@ -14,7 +14,7 @@ mod test { swarm::{dummy, NetworkBehaviour, SwarmEvent}, Multiaddr, PeerId, Swarm, SwarmBuilder, }; - use nomos_mix_message::MESSAGE_SIZE; + use nomos_mix_message::mock::MockMixMessage; use tokio::select; use crate::{behaviour::Config, error::Error, Behaviour, Event}; @@ -43,7 +43,7 @@ mod test { // Swamr2 publishes a message. let task = async { - let msg = vec![1; MESSAGE_SIZE]; + let msg = vec![1; 10]; let mut msg_published = false; let mut publish_try_interval = tokio::time::interval(Duration::from_secs(1)); loop { @@ -98,7 +98,7 @@ mod test { // Expect all publish attempts to fail with [`Error::NoPeers`] // because swarm2 doesn't have any peers that support the mix protocol. - let msg = vec![1; MESSAGE_SIZE]; + let msg = vec![1; 10]; let mut publish_try_interval = tokio::time::interval(Duration::from_secs(1)); let mut publish_try_count = 0; loop { @@ -116,7 +116,7 @@ mod test { } } - fn new_swarm(key: Keypair) -> Swarm { + fn new_swarm(key: Keypair) -> Swarm> { new_swarm_with_behaviour( key, Behaviour::new(Config { diff --git a/nomos-services/data-availability/tests/Cargo.toml b/nomos-services/data-availability/tests/Cargo.toml index aec0f82d..53a87f63 100644 --- a/nomos-services/data-availability/tests/Cargo.toml +++ b/nomos-services/data-availability/tests/Cargo.toml @@ -25,6 +25,7 @@ nomos-storage = { path = "../../../nomos-services/storage", features = ["rocksdb nomos-network = { path = "../../network", features = ["mock"] } nomos-mix-service = { path = "../../mix" } nomos-mix = { path = "../../../nomos-mix/core" } +nomos-mix-message = { path = "../../../nomos-mix/message" } nomos-libp2p = { path = "../../../nomos-libp2p" } libp2p = { version = "0.53.2", features = ["ed25519"] } once_cell = "1.19" diff --git a/nomos-services/data-availability/tests/src/common.rs b/nomos-services/data-availability/tests/src/common.rs index 3aaeb578..29052433 100644 --- a/nomos-services/data-availability/tests/src/common.rs +++ b/nomos-services/data-availability/tests/src/common.rs @@ -5,6 +5,8 @@ use nomos_mix::membership::Node; use nomos_mix::message_blend::{ CryptographicProcessorSettings, MessageBlendSettings, TemporalProcessorSettings, }; +use nomos_mix_message::mock::MockMixMessage; +use nomos_mix_message::MixMessage; use std::path::PathBuf; use std::time::Duration; // crates @@ -191,7 +193,7 @@ pub struct TestDaNetworkSettings { pub struct TestMixSettings { pub backend: Libp2pMixBackendSettings, pub private_key: x25519_dalek::StaticSecret, - pub membership: Vec, + pub membership: Vec::PublicKey>>, } pub fn new_node( diff --git a/testnet/cfgsync/Cargo.toml b/testnet/cfgsync/Cargo.toml index d63ee69c..318760ab 100644 --- a/testnet/cfgsync/Cargo.toml +++ b/testnet/cfgsync/Cargo.toml @@ -10,6 +10,7 @@ nomos-executor = { path = "../../nodes/nomos-executor" } nomos-libp2p = { path = "../../nomos-libp2p" } nomos-node = { path = "../../nodes/nomos-node" } nomos-mix = { path = "../../nomos-mix/core" } +nomos-mix-message = { path = "../../nomos-mix/message" } nomos-tracing = { path = "../../nomos-tracing" } nomos-tracing-service = { path = "../../nomos-services/tracing" } rand = "0.8" diff --git a/testnet/cfgsync/src/config.rs b/testnet/cfgsync/src/config.rs index 49a6e8f9..31a610af 100644 --- a/testnet/cfgsync/src/config.rs +++ b/testnet/cfgsync/src/config.rs @@ -3,6 +3,7 @@ use std::{collections::HashMap, net::Ipv4Addr, str::FromStr}; // crates use nomos_libp2p::{Multiaddr, PeerId}; use nomos_mix::membership::Node; +use nomos_mix_message::{mock::MockMixMessage, MixMessage}; use nomos_tracing::{logging::loki::LokiConfig, tracing::otlp::OtlpTracingConfig}; use nomos_tracing_service::{FilterLayer, LoggerLayer, TracingSettings}; use rand::{thread_rng, Rng}; @@ -171,7 +172,10 @@ fn update_da_peer_addresses( .collect() } -fn update_mix_membership(hosts: Vec, membership: Vec) -> Vec { +fn update_mix_membership( + hosts: Vec, + membership: Vec::PublicKey>>, +) -> Vec::PublicKey>> { membership .into_iter() .zip(hosts) diff --git a/tests/Cargo.toml b/tests/Cargo.toml index a324a6f1..8624f54e 100644 --- a/tests/Cargo.toml +++ b/tests/Cargo.toml @@ -12,6 +12,7 @@ nomos-executor = { path = "../nodes/nomos-executor", default-features = false } nomos-network = { path = "../nomos-services/network", features = ["libp2p"] } nomos-mix-service = { path = "../nomos-services/mix", features = ["libp2p"] } nomos-mix = { path = "../nomos-mix/core" } +nomos-mix-message = { path = "../nomos-mix/message" } cryptarchia-consensus = { path = "../nomos-services/cryptarchia-consensus" } nomos-tracing = { path = "../nomos-tracing" } nomos-tracing-service = { path = "../nomos-services/tracing" } diff --git a/tests/src/topology/configs/mix.rs b/tests/src/topology/configs/mix.rs index 9fabed41..35676f94 100644 --- a/tests/src/topology/configs/mix.rs +++ b/tests/src/topology/configs/mix.rs @@ -2,6 +2,7 @@ use std::str::FromStr; use nomos_libp2p::{ed25519, Multiaddr}; use nomos_mix::membership::Node; +use nomos_mix_message::{mock::MockMixMessage, MixMessage}; use nomos_mix_service::backends::libp2p::Libp2pMixBackendSettings; use crate::get_available_port; @@ -10,7 +11,7 @@ use crate::get_available_port; pub struct GeneralMixConfig { pub backend: Libp2pMixBackendSettings, pub private_key: x25519_dalek::StaticSecret, - pub membership: Vec, + pub membership: Vec::PublicKey>>, } pub fn create_mix_configs(ids: &[[u8; 32]]) -> Vec { @@ -45,7 +46,7 @@ pub fn create_mix_configs(ids: &[[u8; 32]]) -> Vec { configs } -fn mix_nodes(configs: &[GeneralMixConfig]) -> Vec { +fn mix_nodes(configs: &[GeneralMixConfig]) -> Vec::PublicKey>> { configs .iter() .map(|config| Node {