From 070b8fdf6d64cd7b723cdd428a4b1b6c83d736d1 Mon Sep 17 00:00:00 2001 From: Youngjoon Lee <5462944+youngjoon-lee@users.noreply.github.com> Date: Mon, 8 Jul 2024 18:34:05 +0900 Subject: [PATCH] reorganize configs --- mixnet/sim/config.py | 128 +++++++++++++++++++++------------------ mixnet/sim/config.yaml | 34 ++++++----- mixnet/sim/connection.py | 2 +- mixnet/sim/simulation.py | 10 +-- 4 files changed, 92 insertions(+), 82 deletions(-) diff --git a/mixnet/sim/config.py b/mixnet/sim/config.py index ebd79df..58700d3 100644 --- a/mixnet/sim/config.py +++ b/mixnet/sim/config.py @@ -14,8 +14,9 @@ from mixnet.config import NodeConfig @dataclass class Config: simulation: SimulationConfig + network: NetworkConfig logic: LogicConfig - mixnet: MixnetConfig + mix: MixConfig @classmethod def load(cls, yaml_path: str) -> Config: @@ -29,26 +30,53 @@ class Config: # Validations config.simulation.validate() + config.network.validate() config.logic.validate() - config.mixnet.validate() + config.mix.validate() return config + def node_configs(self) -> list[NodeConfig]: + return [ + NodeConfig( + self._gen_private_key(i), + self.network.peering.degree, + self.mix.transmission_rate_per_sec, + ) + for i in range(self.network.num_nodes) + ] + + def _gen_private_key(self, node_idx: int) -> X25519PrivateKey: + return X25519PrivateKey.from_private_bytes( + hashlib.sha256(node_idx.to_bytes(4, "big")).digest()[:32] + ) + @dataclass class SimulationConfig: # Desired duration of the simulation in seconds # Since the simulation uses discrete time steps, the actual duration may be longer or shorter. duration_sec: int - network: NetworkConfig def validate(self): assert self.duration_sec > 0 - self.network.validate() @dataclass class NetworkConfig: + # Total number of nodes in the entire network. + num_nodes: int + latency: LatencyConfig + peering: PeeringConfig + + def validate(self): + assert self.num_nodes > 0 + self.latency.validate() + self.peering.validate() + + +@dataclass +class LatencyConfig: # Maximum network latency between nodes in seconds. # A constant latency will be chosen randomly for each connection within the range [0, max_latency_sec]. max_latency_sec: float @@ -64,6 +92,42 @@ class NetworkConfig: return int(self.seed.random() * self.max_latency_sec * 1000) / 1000 +@dataclass +class PeeringConfig: + # Target number of peers each node can connect to (both inbound and outbound). + degree: int + + def validate(self): + assert self.degree > 0 + + +@dataclass +class MixConfig: + # Global constant transmission rate of each connection in messages per second. + transmission_rate_per_sec: int + mix_path: MixPathConfig + + def validate(self): + assert self.transmission_rate_per_sec > 0 + self.mix_path.validate() + + +@dataclass +class MixPathConfig: + # Maximum number of mix nodes to be chosen for a Sphinx packet. + max_length: int + # Seed for the random number generator used to determine the mix path. + seed: random.Random + + def validate(self): + assert self.max_length > 0 + assert self.seed is not None + + +def seed_to_random(seed: int) -> random.Random: + return random.Random(seed) + + @dataclass class LogicConfig: sender_lottery: LotteryConfig @@ -85,59 +149,3 @@ class LotteryConfig: assert self.interval_sec > 0 assert self.probability >= 0 assert self.seed is not None - - -@dataclass -class MixnetConfig: - # Total number of nodes in the entire network. - num_nodes: int - # Global constant transmission rate of each connection in messages per second. - transmission_rate_per_sec: int - peering: PeeringConfig - mix_path: MixPathConfig - - def validate(self): - assert self.num_nodes > 0 - assert self.transmission_rate_per_sec > 0 - self.peering.validate() - self.mix_path.validate() - - def node_configs(self) -> list[NodeConfig]: - return [ - NodeConfig( - self._gen_private_key(i), - self.peering.degree, - self.transmission_rate_per_sec, - ) - for i in range(self.num_nodes) - ] - - def _gen_private_key(self, node_idx: int) -> X25519PrivateKey: - return X25519PrivateKey.from_private_bytes( - hashlib.sha256(node_idx.to_bytes(4, "big")).digest()[:32] - ) - - -@dataclass -class PeeringConfig: - # Target number of peers each node can connect to (both inbound and outbound). - degree: int - - def validate(self): - assert self.degree > 0 - - -@dataclass -class MixPathConfig: - # Maximum number of mix nodes to be chosen for a Sphinx packet. - max_length: int - # Seed for the random number generator used to determine the mix path. - seed: random.Random - - def validate(self): - assert self.max_length > 0 - assert self.seed is not None - - -def seed_to_random(seed: int) -> random.Random: - return random.Random(seed) diff --git a/mixnet/sim/config.yaml b/mixnet/sim/config.yaml index bbe5465..2fcf733 100644 --- a/mixnet/sim/config.yaml +++ b/mixnet/sim/config.yaml @@ -2,32 +2,34 @@ simulation: # Desired duration of the simulation in seconds # Since the simulation uses discrete time steps, the actual duration may be longer or shorter. duration_sec: 1000 - network: + +network: + # Total number of nodes in the entire network. + num_nodes: 5 + latency: # Maximum network latency between nodes in seconds. # A constant latency will be chosen randomly for each connection within the range [0, max_latency_sec]. max_latency_sec: 0.1 # Seed for the random number generator used to determine the network latencies. seed: 0 + peering: + # Target number of peers each node can connect to (both inbound and outbound). + degree: 6 + +mix: + # Global constant transmission rate of each connection in messages per second. + transmission_rate_per_sec: 10 + mix_path: + # Maximum number of mix nodes to be chosen for a Sphinx packet. + max_length: 3 + # Seed for the random number generator used to determine the mix path. + seed: 3 logic: sender_lottery: # Interval between lottery draws in seconds. interval_sec: 1 # Probability of a node being selected as a sender in each lottery draw. - probability: 0.001 + probability: 0.000 # Seed for the random number generator used to determine the lottery winners. seed: 10 - -mixnet: - # Total number of nodes in the entire network. - num_nodes: 5 - # Global constant transmission rate of each connection in messages per second. - transmission_rate_per_sec: 10 - peering: - # Target number of peers each node can connect to (both inbound and outbound). - degree: 6 - mix_path: - # Maximum number of mix nodes to be chosen for a Sphinx packet. - max_length: 3 - # Seed for the random number generator used to determine the mix path. - seed: 3 diff --git a/mixnet/sim/connection.py b/mixnet/sim/connection.py index 0cba337..a9a4467 100644 --- a/mixnet/sim/connection.py +++ b/mixnet/sim/connection.py @@ -32,7 +32,7 @@ class MeteredRemoteSimplexConnection(SimplexConnection): recv_node_states: list[NodeState], ): self.framework = framework - self.latency = config.random_latency() + self.latency = config.latency.random_latency() self.send_queue = framework.queue() self.mid_queue = framework.queue() self.recv_queue = framework.queue() diff --git a/mixnet/sim/simulation.py b/mixnet/sim/simulation.py index e1775c2..c88692a 100644 --- a/mixnet/sim/simulation.py +++ b/mixnet/sim/simulation.py @@ -32,17 +32,17 @@ class Simulation: assert False # unreachable def init_nodes(self) -> tuple[list[Node], ConnectionStats, AllNodeStates]: - node_configs = self.config.mixnet.node_configs() + node_configs = self.config.node_configs() global_config = GlobalConfig( MixMembership( [ NodeInfo(node_config.private_key.public_key()) for node_config in node_configs ], - self.config.mixnet.mix_path.seed, + self.config.mix.mix_path.seed, ), - self.config.mixnet.transmission_rate_per_sec, - self.config.mixnet.mix_path.max_length, + self.config.mix.transmission_rate_per_sec, + self.config.mix.mix_path.max_length, ) nodes = [ Node(self.framework, node_config, global_config) @@ -74,7 +74,7 @@ class Simulation: self, sender_states: list[NodeState], receiver_states: list[NodeState] ) -> MeteredRemoteSimplexConnection: return MeteredRemoteSimplexConnection( - self.config.simulation.network, + self.config.network, self.framework, sender_states, receiver_states,