Skip to content

Commit

Permalink
mixnet v2
Browse files Browse the repository at this point in the history
  • Loading branch information
youngjoon-lee committed Jun 26, 2024
1 parent 422359a commit 9f58a72
Show file tree
Hide file tree
Showing 17 changed files with 209 additions and 670 deletions.
21 changes: 0 additions & 21 deletions mixnet/README.md

This file was deleted.

13 changes: 0 additions & 13 deletions mixnet/bls.py

This file was deleted.

118 changes: 0 additions & 118 deletions mixnet/client.py

This file was deleted.

100 changes: 23 additions & 77 deletions mixnet/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,110 +2,56 @@

import random
from dataclasses import dataclass
from typing import List, TypeAlias
from typing import List

from cryptography.hazmat.primitives.asymmetric.x25519 import (
X25519PrivateKey,
X25519PublicKey,
)
from pysphinx.node import Node

from mixnet.bls import BlsPrivateKey, BlsPublicKey
from mixnet.fisheryates import FisherYates
from pysphinx.sphinx import Node as SphinxNode


@dataclass
class MixnetConfig:
topology_config: MixnetTopologyConfig
mixclient_config: MixClientConfig
mixnode_config: MixNodeConfig
node_configs: List[NodeConfig]
membership: MixMembership


@dataclass
class MixnetTopologyConfig:
mixnode_candidates: List[MixNodeInfo]
size: MixnetTopologySize
entropy: bytes
class NodeConfig:
private_key: X25519PrivateKey
transmission_rate_per_sec: int # Global Transmission Rate


@dataclass
class MixClientConfig:
emission_rate_per_min: int # Poisson rate parameter: lambda
redundancy: int
topology: MixnetTopology


@dataclass
class MixNodeConfig:
encryption_private_key: X25519PrivateKey
delay_rate_per_min: int # Poisson rate parameter: mu


@dataclass
class MixnetTopology:
# In production, this can be a 1-D array, which is accessible by indexes.
# Here, we use a 2-D array for readability.
layers: List[List[MixNodeInfo]]

def __init__(
self,
config: MixnetTopologyConfig,
) -> None:
"""
Build a new topology deterministically using an entropy and a given set of candidates.
"""
shuffled = FisherYates.shuffle(config.mixnode_candidates, config.entropy)
sampled = shuffled[: config.size.num_total_mixnodes()]

layers = []
for layer_id in range(config.size.num_layers):
start = layer_id * config.size.num_mixnodes_per_layer
layer = sampled[start : start + config.size.num_mixnodes_per_layer]
layers.append(layer)
self.layers = layers
class MixMembership:
nodes: List[NodeInfo]

def generate_route(self, mix_destination: MixNodeInfo) -> list[MixNodeInfo]:
def generate_route(self, num_hops: int, last_mix: NodeInfo) -> list[NodeInfo]:
"""
Generate a mix route for a Sphinx packet.
The pre-selected mix_destination is used as a last mix node in the route,
so that associated packets can be merged together into a original message.
"""
route = [random.choice(layer) for layer in self.layers[:-1]]
route.append(mix_destination)
route = [self.choose() for _ in range(num_hops - 1)]
route.append(last_mix)
return route

def choose_mix_destination(self) -> MixNodeInfo:
def choose(self) -> NodeInfo:
"""
Choose a mix node from the last mix layer as a mix destination
that will reconstruct a message from Sphinx packets.
Choose a mix node as a mix destination that will reconstruct a message from Sphinx packets.
"""
return random.choice(self.layers[-1])
return random.choice(self.nodes)


@dataclass
class MixnetTopologySize:
num_layers: int
num_mixnodes_per_layer: int

def num_total_mixnodes(self) -> int:
return self.num_layers * self.num_mixnodes_per_layer


# 32-byte that represents an IP address and a port of a mix node.
NodeAddress: TypeAlias = bytes


@dataclass
class MixNodeInfo:
identity_private_key: BlsPrivateKey
encryption_private_key: X25519PrivateKey
addr: NodeAddress

def identity_public_key(self) -> BlsPublicKey:
return self.identity_private_key.get_g1()
class NodeInfo:
private_key: X25519PrivateKey

def encryption_public_key(self) -> X25519PublicKey:
return self.encryption_private_key.public_key()
def public_key(self) -> X25519PublicKey:
return self.private_key.public_key()

def sphinx_node(self) -> Node:
return Node(self.encryption_private_key, self.addr)
def sphinx_node(self) -> SphinxNode:
# TODO: Use a pre-signed incentive tx, instead of NodeAddress
dummy_node_addr = bytes(32)
return SphinxNode(self.private_key, dummy_node_addr)
21 changes: 0 additions & 21 deletions mixnet/fisheryates.py

This file was deleted.

62 changes: 0 additions & 62 deletions mixnet/mixnet.py

This file was deleted.

Loading

0 comments on commit 9f58a72

Please sign in to comment.