mirror of
https://github.com/logos-blockchain/logos-blockchain-specs.git
synced 2026-01-06 23:23:09 +00:00
add seeds
This commit is contained in:
parent
a260047cef
commit
3067a5d6b4
@ -1,7 +1,8 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import hashlib
|
||||
import random
|
||||
from dataclasses import dataclass
|
||||
from dataclasses import dataclass, field
|
||||
from typing import List
|
||||
|
||||
from cryptography.hazmat.primitives.asymmetric.x25519 import (
|
||||
@ -26,10 +27,19 @@ class NodeConfig:
|
||||
peering_degree: int
|
||||
mix_path_length: int # TODO: use this when creating Sphinx packets
|
||||
|
||||
def id(self, short=False) -> str:
|
||||
id = (
|
||||
hashlib.sha256(self.private_key.public_key().public_bytes_raw())
|
||||
.digest()
|
||||
.hex()
|
||||
)
|
||||
return id[:8] if short else id
|
||||
|
||||
|
||||
@dataclass
|
||||
class MixMembership:
|
||||
nodes: List[NodeInfo]
|
||||
rng: random.Random = field(default_factory=random.Random)
|
||||
|
||||
def generate_route(self, num_hops: int, last_mix: NodeInfo) -> list[NodeInfo]:
|
||||
"""
|
||||
@ -43,7 +53,7 @@ class MixMembership:
|
||||
"""
|
||||
Choose a mix node as a mix destination that will reconstruct a message from Sphinx packets.
|
||||
"""
|
||||
return random.choice(self.nodes)
|
||||
return self.rng.choice(self.nodes)
|
||||
|
||||
|
||||
@dataclass
|
||||
|
||||
@ -62,7 +62,7 @@ class Node:
|
||||
if msg_with_flag is not None:
|
||||
flag, msg = PacketBuilder.parse_msg_and_flag(msg_with_flag)
|
||||
if flag == MessageFlag.MESSAGE_FLAG_REAL:
|
||||
print(f"Broadcasting message finally: {msg}")
|
||||
print(f"{self.config.id(True)}: Broadcasting message finally: {msg}")
|
||||
await self.broadcast_channel.put(msg)
|
||||
|
||||
def connect(
|
||||
@ -93,7 +93,7 @@ class Node:
|
||||
)
|
||||
|
||||
async def send_message(self, msg: bytes):
|
||||
print(f"Sending message: {msg}")
|
||||
print(f"{self.config.id(True)}: Sending message: {msg}")
|
||||
for packet, _ in PacketBuilder.build_real_packets(
|
||||
msg, self.global_config.membership
|
||||
):
|
||||
|
||||
@ -1,5 +1,7 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import hashlib
|
||||
import random
|
||||
from dataclasses import dataclass
|
||||
|
||||
import dacite
|
||||
@ -19,7 +21,11 @@ class Config:
|
||||
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.from_dict(
|
||||
data_class=Config,
|
||||
data=data,
|
||||
config=dacite.Config(type_hooks={random.Random: seed_to_random}),
|
||||
)
|
||||
|
||||
# Validations
|
||||
config.simulation.validate()
|
||||
@ -41,33 +47,72 @@ class SimulationConfig:
|
||||
|
||||
@dataclass
|
||||
class LogicConfig:
|
||||
lottery_interval_sec: float
|
||||
sender_prob: float
|
||||
sender_lottery: LotteryConfig
|
||||
|
||||
def validate(self):
|
||||
assert self.lottery_interval_sec > 0
|
||||
assert self.sender_prob > 0
|
||||
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_degree: int
|
||||
max_mix_path_length: int
|
||||
peering: PeeringConfig
|
||||
mix_path: MixPathConfig
|
||||
|
||||
def validate(self):
|
||||
assert self.num_nodes > 0
|
||||
assert self.transmission_rate_per_sec > 0
|
||||
assert self.peering_degree > 0
|
||||
assert self.max_mix_path_length > 0
|
||||
self.peering.validate()
|
||||
self.mix_path.validate()
|
||||
|
||||
def node_configs(self) -> list[NodeConfig]:
|
||||
return [
|
||||
NodeConfig(
|
||||
X25519PrivateKey.generate(),
|
||||
self.peering_degree,
|
||||
self._gen_private_key(i),
|
||||
self.peering.degree,
|
||||
self.transmission_rate_per_sec,
|
||||
)
|
||||
for _ in range(self.num_nodes)
|
||||
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
|
||||
seed: random.Random
|
||||
|
||||
def validate(self):
|
||||
assert self.degree > 0
|
||||
assert self.seed is not None
|
||||
|
||||
|
||||
@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)
|
||||
|
||||
@ -3,11 +3,17 @@ simulation:
|
||||
net_latency_sec: 0.01
|
||||
|
||||
logic:
|
||||
lottery_interval_sec: 1
|
||||
sender_prob: 0.01
|
||||
sender_lottery:
|
||||
interval_sec: 1
|
||||
probability: 0.01
|
||||
seed: 10
|
||||
|
||||
mixnet:
|
||||
num_nodes: 5
|
||||
transmission_rate_per_sec: 10
|
||||
peering_degree: 6
|
||||
max_mix_path_length: 3
|
||||
peering:
|
||||
degree: 6
|
||||
seed: 0
|
||||
mix_path:
|
||||
max_length: 3
|
||||
seed: 3
|
||||
|
||||
@ -1,5 +1,3 @@
|
||||
import random
|
||||
|
||||
import usim
|
||||
|
||||
import mixnet.framework.usim as usimfw
|
||||
@ -16,7 +14,6 @@ class Simulation:
|
||||
framework: Framework
|
||||
|
||||
def __init__(self, config: Config):
|
||||
random.seed()
|
||||
self.config = config
|
||||
|
||||
async def run(self):
|
||||
@ -39,10 +36,11 @@ class Simulation:
|
||||
[
|
||||
NodeInfo(node_config.private_key.public_key())
|
||||
for node_config in node_configs
|
||||
]
|
||||
],
|
||||
self.config.mixnet.mix_path.seed,
|
||||
),
|
||||
self.config.mixnet.transmission_rate_per_sec,
|
||||
self.config.mixnet.max_mix_path_length,
|
||||
self.config.mixnet.mix_path.max_length,
|
||||
)
|
||||
nodes = [
|
||||
Node(self.framework, node_config, global_config)
|
||||
@ -66,7 +64,8 @@ class Simulation:
|
||||
return MeteredRemoteSimplexConnection(self.config.simulation, self.framework)
|
||||
|
||||
async def run_logic(self, node: Node):
|
||||
lottery_config = self.config.logic.sender_lottery
|
||||
while True:
|
||||
await (usim.time + self.config.logic.lottery_interval_sec)
|
||||
if random.random() < self.config.logic.sender_prob:
|
||||
await (usim.time + lottery_config.interval_sec)
|
||||
if lottery_config.seed.random() < lottery_config.probability:
|
||||
await node.send_message(b"selected block")
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user