This commit is contained in:
Youngjoon Lee 2024-12-13 13:10:03 +09:00
parent d2a88fc2e4
commit 53d0c2649d
No known key found for this signature in database
GPG Key ID: 303963A54A81DD4D
5 changed files with 93 additions and 31 deletions

View File

@ -27,6 +27,7 @@ uuid = { version = "1", features = ["fast-rng", "v4"] }
tracing-appender = "0.2" tracing-appender = "0.2"
cached = "0.54.0" cached = "0.54.0"
polars = "0.44" polars = "0.44"
humantime-serde = "1.1.1"
[dev-dependencies] [dev-dependencies]
tracing-subscriber = "0.3" tracing-subscriber = "0.3"

View File

@ -4,7 +4,7 @@
"north america:north america": "50ms", "north america:north america": "50ms",
"north america:europe": "100ms", "north america:europe": "100ms",
"north america:asia": "120ms", "north america:asia": "120ms",
"europe:europe": "50ms", "europe:europe": "10ms",
"europe:asia": "100ms", "europe:asia": "100ms",
"europe:north america": "120ms", "europe:north america": "120ms",
"asia:north america": "100ms", "asia:north america": "100ms",
@ -12,43 +12,43 @@
"asia:asia": "40ms" "asia:asia": "40ms"
}, },
"regions": { "regions": {
"north america": 0.4, "north america": 0.0,
"europe": 0.4, "europe": 1.0,
"asia": 0.3 "asia": 0.0
} }
}, },
"node_settings": { "node_settings": {
"timeout": "1000ms" "timeout": "1000ms"
}, },
"step_time": "40ms", "step_time": "10ms",
"runner_settings": "Sync", "runner_settings": "Sync",
"stream_settings": { "stream_settings": {
"path": "test.json" "path": "test.json"
}, },
"node_count": 10, "node_count": 100,
"seed": 0, "seed": 0,
"record_settings": {}, "record_settings": {},
"wards": [ "wards": [
{ {
"sum": 10 "sum": 1000
} }
], ],
"data_message_lottery_interval": "20s", "data_message_lottery_interval": "20s",
"stake_proportion": 1.0, "stake_proportion": 0.0,
"conn_maintenance": { "conn_maintenance": {
"peering_degree": 4, "peering_degree": 2,
"max_peering_degree": 8, "max_peering_degree": 2,
"monitor": { "monitor": {
"time_window": "20s", "time_window": "200s",
"expected_effective_messages": 0.0, "expected_effective_messages": "0.0",
"effective_message_tolerance": 0.0, "effective_message_tolerance": "0.0",
"expected_drop_messages": 0.0, "expected_drop_messages": "0.0",
"drop_message_tolerance": 0.0 "drop_message_tolerance": "0.0"
} }
}, },
"epoch_duration": "432000s", "epoch_duration": "200s",
"slot_duration": "20s", "slot_duration": "1s",
"slots_per_epoch": 21600, "slots_per_epoch": 200,
"number_of_hops": 2, "number_of_hops": 2,
"persistent_transmission": { "persistent_transmission": {
"max_emission_frequency": 1.0, "max_emission_frequency": 1.0,

View File

@ -106,6 +106,7 @@ impl SimulationApp {
settings.simulation_settings.clone(), settings.simulation_settings.clone(),
no_netcap, no_netcap,
MixnodeSettings { MixnodeSettings {
step_time: settings.simulation_settings.step_time,
membership: node_ids.clone(), membership: node_ids.clone(),
topology: topology.clone(), topology: topology.clone(),
data_message_lottery_interval: settings.data_message_lottery_interval, data_message_lottery_interval: settings.data_message_lottery_interval,

View File

@ -8,6 +8,7 @@ pub mod topology;
use crate::node::mix::consensus_streams::{Epoch, Slot}; use crate::node::mix::consensus_streams::{Epoch, Slot};
use cached::{Cached, TimedCache}; use cached::{Cached, TimedCache};
use consensus_streams::CounterInterval;
use crossbeam::channel; use crossbeam::channel;
use futures::Stream; use futures::Stream;
use lottery::StakeLottery; use lottery::StakeLottery;
@ -39,6 +40,7 @@ use serde::{Deserialize, Serialize};
use sha2::{Digest, Sha256}; use sha2::{Digest, Sha256};
use state::MixnodeState; use state::MixnodeState;
use std::collections::HashSet; use std::collections::HashSet;
use std::ops::Mul;
use std::{pin::pin, task::Poll, time::Duration}; use std::{pin::pin, task::Poll, time::Duration};
use stream_wrapper::CrossbeamReceiverStream; use stream_wrapper::CrossbeamReceiverStream;
use topology::Topology; use topology::Topology;
@ -54,6 +56,7 @@ impl PayloadSize for MixMessage {
#[derive(Deserialize)] #[derive(Deserialize)]
pub struct MixnodeSettings { pub struct MixnodeSettings {
pub step_time: Duration,
pub membership: Vec<NodeId>, pub membership: Vec<NodeId>,
pub topology: Topology, pub topology: Topology,
pub data_message_lottery_interval: Duration, pub data_message_lottery_interval: Duration,
@ -71,6 +74,7 @@ type Sha256Hash = [u8; 32];
/// This node implementation only used for testing different streaming implementation purposes. /// This node implementation only used for testing different streaming implementation purposes.
pub struct MixNode { pub struct MixNode {
step_time: Duration,
id: NodeId, id: NodeId,
state: MixnodeState, state: MixnodeState,
network_interface: InMemoryNetworkInterface<MixMessage>, network_interface: InMemoryNetworkInterface<MixMessage>,
@ -82,7 +86,7 @@ pub struct MixNode {
conn_maintenance: ConnectionMaintenance<NodeId, MockMixMessage, ChaCha12Rng>, conn_maintenance: ConnectionMaintenance<NodeId, MockMixMessage, ChaCha12Rng>,
conn_maintenance_update_time_sender: channel::Sender<Duration>, conn_maintenance_update_time_sender: channel::Sender<Duration>,
conn_maintenance_interval: Interval, conn_maintenance_interval: CounterInterval,
persistent_sender: channel::Sender<Vec<u8>>, persistent_sender: channel::Sender<Vec<u8>>,
persistent_update_time_sender: channel::Sender<Duration>, persistent_update_time_sender: channel::Sender<Duration>,
persistent_transmission_messages: PersistentTransmissionStream< persistent_transmission_messages: PersistentTransmissionStream<
@ -103,7 +107,9 @@ pub struct MixNode {
>, >,
epoch_update_sender: channel::Sender<Duration>, epoch_update_sender: channel::Sender<Duration>,
slot_update_sender: channel::Sender<Duration>, slot_update_sender: channel::Sender<Duration>,
slot_update_sender_new: channel::Sender<Duration>,
cover_traffic: CoverTraffic<Epoch, Slot, MockMixMessage>, cover_traffic: CoverTraffic<Epoch, Slot, MockMixMessage>,
slot_scheduler: Slot,
} }
impl MixNode { impl MixNode {
@ -156,7 +162,7 @@ impl MixNode {
let (conn_maintenance_update_time_sender, conn_maintenance_update_time_receiver) = let (conn_maintenance_update_time_sender, conn_maintenance_update_time_receiver) =
channel::unbounded(); channel::unbounded();
let (persistent_sender, persistent_receiver) = channel::unbounded(); let (persistent_sender, persistent_receiver) = channel::unbounded();
let conn_maintenance_interval = Interval::new( let conn_maintenance_interval = CounterInterval::new(
settings.conn_maintenance.monitor.unwrap().time_window, settings.conn_maintenance.monitor.unwrap().time_window,
conn_maintenance_update_time_receiver, conn_maintenance_update_time_receiver,
); );
@ -186,8 +192,8 @@ impl MixNode {
ChaCha12Rng::from_rng(&mut rng_generator).unwrap(), ChaCha12Rng::from_rng(&mut rng_generator).unwrap(),
blend_update_time_receiver, blend_update_time_receiver,
( (
1, 0,
settings.message_blend.temporal_processor.max_delay_seconds, settings.message_blend.temporal_processor.max_delay_seconds / 2,
), ),
); );
let blend_messages = CrossbeamReceiverStream::new(blend_receiver).blend( let blend_messages = CrossbeamReceiverStream::new(blend_receiver).blend(
@ -200,6 +206,7 @@ impl MixNode {
// tier 3 cover traffic // tier 3 cover traffic
let (epoch_update_sender, epoch_updater_update_receiver) = channel::unbounded(); let (epoch_update_sender, epoch_updater_update_receiver) = channel::unbounded();
let (slot_update_sender, slot_updater_update_receiver) = channel::unbounded(); let (slot_update_sender, slot_updater_update_receiver) = channel::unbounded();
let (slot_update_sender_new, slot_updater_update_receiver_new) = channel::unbounded();
let cover_traffic: CoverTraffic<Epoch, Slot, MockMixMessage> = CoverTraffic::new( let cover_traffic: CoverTraffic<Epoch, Slot, MockMixMessage> = CoverTraffic::new(
settings.cover_traffic_settings, settings.cover_traffic_settings,
Epoch::new(settings.epoch_duration, epoch_updater_update_receiver), Epoch::new(settings.epoch_duration, epoch_updater_update_receiver),
@ -209,8 +216,14 @@ impl MixNode {
slot_updater_update_receiver, slot_updater_update_receiver,
), ),
); );
let slot_scheduler = Slot::new(
settings.cover_traffic_settings.slots_per_epoch,
settings.slot_duration,
slot_updater_update_receiver_new,
);
Self { Self {
step_time: settings.step_time,
id, id,
network_interface, network_interface,
// We're not coupling this lifespan with the steps now, but it's okay // We're not coupling this lifespan with the steps now, but it's okay
@ -236,7 +249,9 @@ impl MixNode {
blend_messages, blend_messages,
epoch_update_sender, epoch_update_sender,
slot_update_sender, slot_update_sender,
slot_update_sender_new,
cover_traffic, cover_traffic,
slot_scheduler,
} }
} }
@ -270,6 +285,16 @@ impl MixNode {
.into_iter() .into_iter()
.inspect(|msg| { .inspect(|msg| {
self.conn_maintenance.record_effective_message(&msg.from); self.conn_maintenance.record_effective_message(&msg.from);
let log = MessageLog {
payload_id: "received".to_string(),
step_id: self.state.step_id,
elapsed: self.step_time.mul(self.state.step_id.try_into().unwrap()),
node_id: self.id.index(),
};
tracing::info!(
"CoverMessageReceived {}",
serde_json::to_string(&log).unwrap()
);
}) })
// Retain only messages that have not been seen before // Retain only messages that have not been seen before
.filter(|msg| { .filter(|msg| {
@ -297,6 +322,7 @@ impl MixNode {
self.blend_update_time_sender.send(elapsed).unwrap(); self.blend_update_time_sender.send(elapsed).unwrap();
self.epoch_update_sender.send(elapsed).unwrap(); self.epoch_update_sender.send(elapsed).unwrap();
self.slot_update_sender.send(elapsed).unwrap(); self.slot_update_sender.send(elapsed).unwrap();
self.slot_update_sender_new.send(elapsed).unwrap();
} }
fn log_message_generated(&self, msg_type: &str, payload: &Payload) { fn log_message_generated(&self, msg_type: &str, payload: &Payload) {
@ -311,6 +337,7 @@ impl MixNode {
let log = MessageLog { let log = MessageLog {
payload_id: payload.id(), payload_id: payload.id(),
step_id: self.state.step_id, step_id: self.state.step_id,
elapsed: self.step_time.mul(self.state.step_id.try_into().unwrap()),
node_id: self.id.index(), node_id: self.id.index(),
}; };
tracing::info!("{}: {}", tag, serde_json::to_string(&log).unwrap()); tracing::info!("{}: {}", tag, serde_json::to_string(&log).unwrap());
@ -389,14 +416,16 @@ impl Node for MixNode {
} }
// Proceed connection maintenance if interval is reached. // Proceed connection maintenance if interval is reached.
if let Poll::Ready(Some(_)) = pin!(&mut self.conn_maintenance_interval).poll_next(&mut cx) { if let Poll::Ready(Some(i)) = pin!(&mut self.conn_maintenance_interval).poll_next(&mut cx) {
let (monitors, _, _) = self.conn_maintenance.reset().unwrap(); if i > 0 {
let effective_messages_series = Series::from_iter( let (monitors, _, _) = self.conn_maintenance.reset().unwrap();
monitors let effective_messages_series = Series::from_iter(
.values() monitors
.map(|monitor| monitor.effective_messages.to_num::<u64>()), .values()
); .map(|monitor| monitor.effective_messages.to_num::<u64>()),
self.log_monitors(&effective_messages_series); );
self.log_monitors(&effective_messages_series);
}
} }
// Handle incoming messages // Handle incoming messages
@ -415,6 +444,13 @@ impl Node for MixNode {
if let Poll::Ready(Some(msg)) = pin!(&mut self.blend_messages).poll_next(&mut cx) { if let Poll::Ready(Some(msg)) = pin!(&mut self.blend_messages).poll_next(&mut cx) {
match msg { match msg {
MixOutgoingMessage::Outbound(msg) => { MixOutgoingMessage::Outbound(msg) => {
let log = MessageLog {
payload_id: "after_blend".to_string(),
step_id: self.state.step_id,
elapsed: self.step_time.mul(self.state.step_id.try_into().unwrap()),
node_id: self.id.index(),
};
tracing::info!("CoverAfterBlend: {}", serde_json::to_string(&log).unwrap());
self.persistent_sender.send(msg).unwrap(); self.persistent_sender.send(msg).unwrap();
} }
MixOutgoingMessage::FullyUnwrapped(payload) => { MixOutgoingMessage::FullyUnwrapped(payload) => {
@ -427,6 +463,18 @@ impl Node for MixNode {
} }
// Generate a cover message probabilistically // Generate a cover message probabilistically
// if let Poll::Ready(Some(slot)) = pin!(&mut self.slot_scheduler).poll_next(&mut cx) {
// // if slot == self.id.index() {
// if slot == 0 {
// let payload = Payload::new();
// self.log_message_generated("Cover", &payload);
// let message = self
// .crypto_processor
// .wrap_message(payload.as_bytes())
// .unwrap();
// self.persistent_sender.send(message).unwrap();
// }
// }
if let Poll::Ready(Some(_)) = pin!(&mut self.cover_traffic).poll_next(&mut cx) { if let Poll::Ready(Some(_)) = pin!(&mut self.cover_traffic).poll_next(&mut cx) {
let payload = Payload::new(); let payload = Payload::new();
self.log_message_generated("Cover", &payload); self.log_message_generated("Cover", &payload);
@ -466,6 +514,8 @@ impl Node for MixNode {
struct MessageLog { struct MessageLog {
payload_id: PayloadId, payload_id: PayloadId,
step_id: usize, step_id: usize,
#[serde(with = "humantime_serde")]
elapsed: Duration,
node_id: usize, node_id: usize,
} }

View File

@ -58,7 +58,12 @@ impl TemporalRelease {
(min_delay, max_delay): (u64, u64), (min_delay, max_delay): (u64, u64),
) -> Self { ) -> Self {
let mut random_sleeps = Box::new(std::iter::repeat_with(move || { let mut random_sleeps = Box::new(std::iter::repeat_with(move || {
Duration::from_secs((rng.next_u64() % (max_delay + 1)).max(min_delay)) if min_delay == max_delay {
tracing::info!("Temporal release: fixed delay: {}", min_delay);
Duration::from_secs(min_delay)
} else {
Duration::from_secs(rng.next_u64() % (max_delay - min_delay) + min_delay)
}
})); }));
let current_sleep = random_sleeps.next().unwrap(); let current_sleep = random_sleeps.next().unwrap();
Self { Self {
@ -71,6 +76,11 @@ impl TemporalRelease {
pub fn update(&mut self, elapsed: Duration) -> bool { pub fn update(&mut self, elapsed: Duration) -> bool {
self.elapsed += elapsed; self.elapsed += elapsed;
if self.elapsed >= self.current_sleep { if self.elapsed >= self.current_sleep {
tracing::info!(
"Temporal update: elapsed:{:?}, current_sleep:{:?}",
self.elapsed,
self.current_sleep
);
self.elapsed = Duration::from_secs(0); self.elapsed = Duration::from_secs(0);
self.current_sleep = self.random_sleeps.next().unwrap(); self.current_sleep = self.random_sleeps.next().unwrap();
true true