102 lines
3.0 KiB
Python
Raw Normal View History

2024-05-17 14:54:23 +09:00
from __future__ import annotations
2024-05-14 21:19:46 +09:00
from dataclasses import dataclass
2024-05-15 16:53:26 +09:00
from typing import Self
import dacite
import yaml
2024-05-14 21:19:46 +09:00
@dataclass
class Config:
2024-05-17 14:54:23 +09:00
simulation: SimulationConfig
mixnet: MixnetConfig
p2p: P2pConfig
2024-05-18 00:31:29 +09:00
measurement: MeasurementConfig
2024-05-17 14:54:23 +09:00
adversary: AdversaryConfig
@classmethod
def load(cls, yaml_path: str) -> Self:
with open(yaml_path, "r") as f:
data = yaml.safe_load(f)
config = dacite.from_dict(data_class=Config, data=data)
# Validations
config.simulation.validate()
config.mixnet.validate()
config.p2p.validate()
2024-05-18 00:31:29 +09:00
config.measurement.validate()
2024-05-17 14:54:23 +09:00
config.adversary.validate()
return config
@dataclass
class SimulationConfig:
2024-05-14 21:19:46 +09:00
running_time: int
2024-05-17 14:54:23 +09:00
def validate(self):
assert self.running_time > 0
@dataclass
class MixnetConfig:
2024-05-14 21:19:46 +09:00
num_nodes: int
num_mix_layers: int
# A size of a message payload in bytes (e.g. the size of a block proposal)
payload_size: int
2024-05-15 18:55:17 +09:00
# An interval of sending a new real/cover message
# A probability of actually sending a message depends on the following parameters.
2024-05-14 21:19:46 +09:00
message_interval: int
2024-05-15 18:55:17 +09:00
# A probability of sending a real message within one cycle
real_message_prob: float
# A weight of real message emission probability of some nodes
2024-05-20 10:03:24 +09:00
# Each weight is multiplied to the real_message_prob of the node being at the same position in the node list.
2024-05-16 17:13:43 +09:00
# The length of the list should be <= num_nodes. i.e. some nodes won't have a weight.
2024-05-15 18:55:17 +09:00
real_message_prob_weights: list[float]
# A probability of sending a cover message within one cycle if not sending a real message
2024-05-15 16:53:26 +09:00
cover_message_prob: float
2024-05-15 18:55:17 +09:00
# A maximum preparation time (delay) before sending the message
2024-05-14 21:19:46 +09:00
max_message_prep_time: float
2024-05-16 17:13:43 +09:00
# A maximum delay of messages mixed in a mix node
max_mix_delay: float
2024-05-15 16:53:26 +09:00
2024-05-17 14:54:23 +09:00
def validate(self):
assert self.num_nodes > 0
assert 0 < self.num_mix_layers <= self.num_nodes
assert self.payload_size > 0
2024-05-17 14:54:23 +09:00
assert self.message_interval > 0
assert self.real_message_prob > 0
assert len(self.real_message_prob_weights) <= self.num_nodes
for weight in self.real_message_prob_weights:
2024-05-15 18:55:17 +09:00
assert weight >= 1
2024-05-17 14:54:23 +09:00
assert self.cover_message_prob >= 0
assert self.max_message_prep_time >= 0
assert self.max_mix_delay >= 0
2024-05-15 16:53:26 +09:00
2024-05-17 14:54:23 +09:00
@dataclass
class P2pConfig:
# A maximum network latency between nodes directly connected with each other
max_network_latency: float
def validate(self):
assert self.max_network_latency >= 0
2024-05-18 00:31:29 +09:00
@dataclass
class MeasurementConfig:
# How many times in simulation represent 1 second in real time
sim_time_per_second: float
def validate(self):
assert self.sim_time_per_second > 0
2024-05-17 14:54:23 +09:00
@dataclass
class AdversaryConfig:
# A discrete time window for the adversary to observe inputs and outputs of a certain node
io_observation_window: int
def validate(self):
2024-05-18 00:31:29 +09:00
assert self.io_observation_window >= 1