From 1aaa0abd5389fd454a7c53462901f384c78dfc91 Mon Sep 17 00:00:00 2001 From: Youngjoon Lee <5462944+youngjoon-lee@users.noreply.github.com> Date: Mon, 3 Jun 2024 15:10:32 +0900 Subject: [PATCH] add min_network_latency and min_mix_delay for easy window adjustments --- mixnet/v2/sim/adversary.py | 4 +++- mixnet/v2/sim/analysis.py | 26 +++++++++++++++----------- mixnet/v2/sim/config.py | 18 +++++++++++++++--- mixnet/v2/sim/config.yaml | 8 ++++++-- mixnet/v2/sim/p2p.py | 2 +- 5 files changed, 40 insertions(+), 18 deletions(-) diff --git a/mixnet/v2/sim/adversary.py b/mixnet/v2/sim/adversary.py index 35696c2..ad3f53a 100644 --- a/mixnet/v2/sim/adversary.py +++ b/mixnet/v2/sim/adversary.py @@ -60,7 +60,9 @@ class Adversary: if delta > 0: senders.add(sender) # Iterate remaining events that will remain in the new window, and accumulate msg_cnt - for _, delta, sender in queue: + for t, delta, sender in queue: + if t >= self.env.now - self.config.adversary.io_window_moving_interval: + break msg_cnt += delta if delta > 0: senders.add(sender) diff --git a/mixnet/v2/sim/analysis.py b/mixnet/v2/sim/analysis.py index 647fc67..f92b6a6 100644 --- a/mixnet/v2/sim/analysis.py +++ b/mixnet/v2/sim/analysis.py @@ -165,6 +165,7 @@ class Analysis: print(df.describe()) plt.figure(figsize=(6, 6)) seaborn.boxplot(data=df, y="hops", medianprops={"color": "red", "linewidth": 2.5}) + plt.ylim(bottom=0) plt.title("Message hops distribution") plt.show() @@ -202,7 +203,17 @@ class Analysis: suspected_senders = ({node.id: count for node, count in suspected_senders.items()}) print(f"suspected nodes count: {len(suspected_senders)}") - # Extract keys and values from the Counter + # Create the bar plot for original sender counts + original_senders = ({node.id: count for node, count in self.sim.p2p.measurement.original_senders.items()}) + plt.figure(figsize=(12, 8)) + plt.bar(list(original_senders.keys()), list(original_senders.values())) + plt.xlabel('Node ID') + plt.ylabel('Counts') + plt.title('Original Sender Counts') + plt.xlim(-1, self.config.mixnet.num_nodes) + plt.show() + + # Create the bar plot for suspected sender counts keys = list(suspected_senders.keys()) values = list(suspected_senders.values()) # Create the bar plot @@ -211,24 +222,17 @@ class Analysis: plt.xlabel('Node ID') plt.ylabel('Counts') plt.title('Suspected Sender Counts') + plt.xlim(-1, self.config.mixnet.num_nodes) plt.show() - # Create the bar plot for original sender counts - original_senders = ({node.id: count for node, count in self.sim.p2p.measurement.original_senders.items()}) - plt.figure(figsize=(12, 8)) - plt.bar(list(original_senders.keys()), list(original_senders.values())) - plt.xlabel('Node ID') - plt.ylabel('Counts') - plt.title('Original Sender Counts') - plt.show() - - # Create the bar plot for original sender counts + # Create the bar plot for broadcasters broadcasters = ({node.id: count for node, count in self.sim.p2p.broadcasters.items()}) plt.figure(figsize=(12, 8)) plt.bar(list(broadcasters.keys()), list(broadcasters.values())) plt.xlabel('Node ID') plt.ylabel('Counts') plt.title('Broadcasters') + plt.xlim(-1, self.config.mixnet.num_nodes) plt.show() # Calculate the mean and standard deviation of the counts diff --git a/mixnet/v2/sim/config.py b/mixnet/v2/sim/config.py index d3672f1..ef02bc8 100644 --- a/mixnet/v2/sim/config.py +++ b/mixnet/v2/sim/config.py @@ -1,4 +1,6 @@ from __future__ import annotations + +import random from dataclasses import dataclass from typing import Self @@ -26,7 +28,7 @@ class Config: config.p2p.validate() config.measurement.validate() config.adversary.validate() - + return config def description(self): @@ -64,6 +66,7 @@ class MixnetConfig: # A maximum preparation time (computation time) for a message sender before sending the message max_message_prep_time: float # A maximum delay of messages mixed in a mix node + min_mix_delay: float max_mix_delay: float def validate(self): @@ -77,13 +80,14 @@ class MixnetConfig: assert weight >= 1 assert self.cover_message_prob >= 0 assert self.max_message_prep_time >= 0 - assert self.max_mix_delay >= 0 + assert 0 <= self.min_mix_delay <= self.max_mix_delay def description(self): return ( f"payload: {self.payload_size} bytes\n" f"num_nodes: {self.num_nodes}\n" f"num_mix_layers: {self.num_mix_layers}\n" + f"min_mix_delay: {self.min_mix_delay}\n" f"max_mix_delay: {self.max_mix_delay}\n" f"msg_interval: {self.message_interval}\n" f"real_msg_prob: {self.real_message_prob:.2f}\n" @@ -93,6 +97,9 @@ class MixnetConfig: def is_mixing_on(self) -> bool: return self.num_mix_layers > 0 + def random_mix_delay(self) -> float: + return random.uniform(self.min_mix_delay, self.max_mix_delay) + @dataclass class P2PConfig: @@ -101,6 +108,7 @@ class P2PConfig: # A connection density, only if the type is gossip connection_density: int # A maximum network latency between nodes directly connected with each other + min_network_latency: float max_network_latency: float TYPE_ONE_TO_ALL = "1-to-all" @@ -110,15 +118,19 @@ class P2PConfig: assert self.type in [self.TYPE_ONE_TO_ALL, self.TYPE_GOSSIP] if self.type == self.TYPE_GOSSIP: assert self.connection_density > 0 - assert self.max_network_latency >= 0 + assert 0 < self.min_network_latency <= self.max_network_latency def description(self): return ( f"p2p_type: {self.type}\n" f"conn_density: {self.connection_density}\n" + f"min_net_latency: {self.min_network_latency:.2f}\n" f"max_net_latency: {self.max_network_latency:.2f}" ) + def random_network_latency(self) -> float: + return random.uniform(self.min_network_latency, self.max_network_latency) + @dataclass class MeasurementConfig: diff --git a/mixnet/v2/sim/config.yaml b/mixnet/v2/sim/config.yaml index c53ad36..5233959 100644 --- a/mixnet/v2/sim/config.yaml +++ b/mixnet/v2/sim/config.yaml @@ -23,7 +23,8 @@ mixnet: # A maximum preparation time (computation time) for a message sender before sending the message max_message_prep_time: 0 # A maximum delay of messages mixed in a mix node - max_mix_delay: 0 + min_mix_delay: 0.0 + max_mix_delay: 0.0 p2p: # Broadcasting type: 1-to-all | gossip @@ -31,6 +32,7 @@ p2p: # A connection density, only if the type is gossip connection_density: 6 # A maximum network latency between nodes directly connected with each other + min_network_latency: 0.10 max_network_latency: 0.20 measurement: @@ -39,7 +41,9 @@ measurement: adversary: # A time window for the adversary to observe inputs and outputs of each node - io_window_size: 0.20 + # Recommendation: Same as `mixnet.max_mix_delay + (p2p.max_network_latency - p2p.min_network_latency)` + io_window_size: 0.10 # A moving interval of the time window for the adversary to observe inputs and outputs of each node # This must be smaller or equal to io_window_size. + # Recommendation: Same as `p2p.min_network_latency` io_window_moving_interval: 0.10 \ No newline at end of file diff --git a/mixnet/v2/sim/p2p.py b/mixnet/v2/sim/p2p.py index 5508e39..aed0425 100644 --- a/mixnet/v2/sim/p2p.py +++ b/mixnet/v2/sim/p2p.py @@ -50,7 +50,7 @@ class P2P(ABC): self.measurement.measure_egress(sender, msg) # simulate network latency - yield self.env.timeout(random.uniform(0, self.config.p2p.max_network_latency)) + yield self.env.timeout(self.config.p2p.random_network_latency()) self.measurement.measure_ingress(receiver, msg) self.adversary.observe_receiving_node(sender, receiver)