Owner: @Youngjoon Lee

<aside> 🚧 This document was written before we design the new protocol at the offsite (Jun 2024). Now this document is deprecated. All live documents can be found from the root document.

</aside>

Purpose

How the simulation works

The simulation is configured by a YAML file as below.

The simulation is run during running_time which is in simulation time unit. For details, please see Time in simulation. For simplicity, sim_time_per_second can be configured, which is used to calculate bandwidth usages.

For every message_interval, each node rolls a dice to decide whether to send a real message or not. The probability of sending a real message per interval is set by real_message_prob. If a node decides not to send a real message, it rolls a dice once again to decide whether to send a cover message, which depends on cover_message_prob. This mechanism is to roughly simulate Cryptarchia.

If num_mix_layers is 0, a payload is not encapsulated by Sphinx. If not, a message sender chooses mix nodes uniformly at random and encapsulates a payload to a Sphinx message. For each layer, only one node can unwrap the message. After unwrapping the message, the node broadcasts the unwrapped message to the network again, so that it can be eventually delivered to the next mix node.

Two P2P broadcasting types are supported: 1-to-all | gossip. If gossip is selected, connection_density is used similar as the degree of libp2p gossipsub. The network latency between nodes can be configured by max_network_latency.

simulation:
  # The simulation uses a virtual time. Please see README for more details.
  running_time: 30

mixnet:
  num_nodes: 100
  # A number of mix nodes selected by a message sender through which the Sphinx message goes through
  # If 0, the message is broadcast directly to all nodes without being Sphinx-encoded.
  num_mix_layers: 0
  # A size of a message payload in bytes (e.g. the size of a block proposal)
  payload_size: 320
  # An interval of sending a new real/cover message
  # A probability of actually sending a message depends on the following parameters.
  message_interval: 1
  # A probability of sending a real message within a cycle
  real_message_prob: 0.01
  # A weight of real message emission probability of some nodes
  # Each weight is multiplied to the real_message_prob of the node being at the same position in the node list.
  # The length of the list should be <= p2p.num_nodes. i.e. some nodes won't have a weight.
  real_message_prob_weights: []
  # A probability of sending a cover message within a cycle if not sending a real message
  cover_message_prob: 0.02
  # A maximum preparation time (computation time) for a message sender before sending the message
  max_message_prep_time: 0
  # A maximum delay of messages mixed in a mix node
  max_mix_delay: 0.30

p2p:
  # Broadcasting type: 1-to-all | gossip
  type: "gossip"
  # A connection density, only if the type is gossip
  connection_density: 6
  # A maximum network latency between nodes directly connected with each other
  max_network_latency: 0.20

measurement:
    # How many times in simulation represent 1 second in real time
    sim_time_per_second: 1

adversary:
  # A discrete time window for the adversary to observe inputs and outputs of a certain node
  io_observation_window: 1

The following plot with the simplest setting is just to show how each node works over time. Because of real_message_prob: 0.03, message emissions are intermittent. If cover_message_prob is set, egress/ingress will be observed more frequently.

It takes max_network_latency at most until a message is transmitted between two nodes. But, because it’s set very short (0.20), the ingress is shown at the same time point as the egress in the plot.

Untitled

1-to-all Broadcasting

The section describes the result of measuring bandwidth usages (ingress & egress) by running the simulation with 1-to-all broadcasting for 30 simulation time period. For simplicity, 1 simulation time is converted to 1 second of real time.

simulation:
  running_time: 30
mixnet:
  num_nodes: [10, 200, 400, 600, 800, 1000]
  num_mix_layers: [0, 2, 4]
  payload_size: 320
  message_interval: 1
  real_message_prob: 0.01
  real_message_prob_weights: []
  cover_message_prob: [0, 0.02]
  max_message_prep_time: 0
  max_mix_delay: 0
p2p:
  type: ["1-to-all", "gossip"]
  connection_density: 6
  max_network_latency: 0.20

Although a payload is 320 bytes, the actual size of message transmitted between nodes depends on the number of mix layers due to Sphinx encoding, as below:

# Mix Layers Message Size (bytes)
0 320
2 1,408
4 2,464