reorganize configs

This commit is contained in:
Youngjoon Lee 2024-07-08 18:34:05 +09:00
parent f3eb148f47
commit 070b8fdf6d
No known key found for this signature in database
GPG Key ID: B4253AFBA618BF4D
4 changed files with 92 additions and 82 deletions

View File

@ -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)

View File

@ -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

View File

@ -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()

View File

@ -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,