mirror of
https://github.com/logos-co/nomos-specs.git
synced 2025-02-02 18:44:11 +00:00
117 lines
2.4 KiB
Python
117 lines
2.4 KiB
Python
from __future__ import annotations
|
|
|
|
import hashlib
|
|
import random
|
|
from dataclasses import dataclass
|
|
|
|
import dacite
|
|
import yaml
|
|
from pysphinx.sphinx import X25519PrivateKey
|
|
|
|
from mixnet.config import NodeConfig
|
|
|
|
|
|
@dataclass
|
|
class Config:
|
|
simulation: SimulationConfig
|
|
logic: LogicConfig
|
|
mixnet: MixnetConfig
|
|
|
|
@classmethod
|
|
def load(cls, yaml_path: str) -> Config:
|
|
with open(yaml_path, "r") as f:
|
|
data = yaml.safe_load(f)
|
|
config = dacite.from_dict(
|
|
data_class=Config,
|
|
data=data,
|
|
config=dacite.Config(type_hooks={random.Random: seed_to_random}),
|
|
)
|
|
|
|
# Validations
|
|
config.simulation.validate()
|
|
config.logic.validate()
|
|
config.mixnet.validate()
|
|
|
|
return config
|
|
|
|
|
|
@dataclass
|
|
class SimulationConfig:
|
|
duration_sec: int
|
|
net_latency_sec: float
|
|
|
|
def validate(self):
|
|
assert self.duration_sec > 0
|
|
assert self.net_latency_sec > 0
|
|
|
|
|
|
@dataclass
|
|
class LogicConfig:
|
|
sender_lottery: LotteryConfig
|
|
|
|
def validate(self):
|
|
self.sender_lottery.validate()
|
|
|
|
|
|
@dataclass
|
|
class LotteryConfig:
|
|
interval_sec: float
|
|
probability: float
|
|
seed: random.Random
|
|
|
|
def validate(self):
|
|
assert self.interval_sec > 0
|
|
assert self.probability > 0
|
|
assert self.seed is not None
|
|
|
|
|
|
@dataclass
|
|
class MixnetConfig:
|
|
num_nodes: int
|
|
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:
|
|
degree: int
|
|
|
|
def validate(self):
|
|
assert self.degree > 0
|
|
|
|
|
|
@dataclass
|
|
class MixPathConfig:
|
|
max_length: int
|
|
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)
|