Browse Source

Start on the simulation orchestrator

Ian Goldberg 4 years ago
parent
commit
704d798e17
1 changed files with 98 additions and 0 deletions
  1. 98 0
      simulator.py

+ 98 - 0
simulator.py

@@ -0,0 +1,98 @@
+#!/usr/bin/env python3
+
+import random # For simulation, not cryptography!
+import math
+import sys
+import logging
+
+import network
+import dirauth
+import relay
+import client
+
+class Simulator:
+    def __init__(self, relaytarget, clienttarget):
+        self.relaytarget = relaytarget
+        self.clienttarget = clienttarget
+
+        # Some (for now) hard-coded parameters
+
+        # The number of directory authorities
+        numdirauths = 9
+
+        # The fraction of relays that are fallback relays
+        fracfallbackrelays = 0.05
+
+        # Start some dirauths
+        self.dirauthaddrs = []
+        self.dirauths = []
+        for i in range(numdirauths):
+            dira = dirauth.DirAuth(i, numdirauths)
+            self.dirauths.append(dira)
+            self.dirauthaddrs.append(dira.netaddr)
+
+        # Start some relays
+        self.relays = []
+        for i in range(self.relaytarget):
+            # Relay bandwidths (at least the ones fast enough to get used)
+            # in the live Tor network (as of Dec 2019) are well approximated
+            # by (200000-(200000-25000)/3*log10(x)) where x is a
+            # uniform integer in [1,2500]
+            x = random.randint(1,2500)
+            bw = int(200000-(200000-25000)/3*math.log10(x))
+            self.relays.append(relay.Relay(self.dirauthaddrs, bw, 0))
+
+        # The fallback relays are a hardcoded list of a small fraction
+        # of the relays, used by clients for bootstrapping
+        numfallbackrelays = int(self.relaytarget * fracfallbackrelays) + 1
+        fallbackrelays = random.sample(self.relays, numfallbackrelays)
+        for r in fallbackrelays:
+            r.set_is_fallbackrelay()
+        network.thenetwork.setfallbackrelays(fallbackrelays)
+
+        # Tick the epoch to build the first consensus
+        network.thenetwork.nextepoch()
+
+        # Start some clients
+        self.clients = []
+        for i in range(clienttarget):
+            self.clients.append(client.Client(self.dirauthaddrs))
+
+        # Tick the epoch to bootstrap the clients
+        network.thenetwork.nextepoch()
+
+        # Throw away all the performance statistics to this point
+        for d in self.dirauths: d.perfstats.reset()
+        for r in self.relays: r.perfstats.reset()
+        for c in self.clients: c.perfstats.reset()
+
+
+if __name__ == '__main__':
+    # Args: womode snipauthmode networkscale numepochs randseed
+    if len(sys.argv) != 6:
+        sys.stderr.write("Usage: womode snipauthmode networkscale numepochs randseed\n")
+        sys.exit(1)
+
+    womode = network.WOMode[sys.argv[1].upper()]
+    snipauthmode = network.SNIPAuthMode[sys.argv[2].upper()]
+    networkscale = float(sys.argv[3])
+    numepochs = int(sys.argv[4])
+    randseed = int(sys.argv[5])
+
+    # Seed the PRNG.  On Ubuntu 18.04, this in fact makes future calls
+    # to (non-cryptographic) random numbers deterministic.  On Ubuntu
+    # 16.04, it does not.
+    random.seed(randseed)
+
+    # Uncomment to see all the debug messages
+    # logging.basicConfig(level=logging.DEBUG)
+
+    # Set the Walking Onions style to use
+    network.thenetwork.set_wo_style(womode, snipauthmode)
+
+    # The steady-state numbers of relays and clients
+    relaytarget = math.ceil(6500 * networkscale)
+    clienttarget = math.ceil(2500000 * networkscale)
+
+    # Create the simulation
+    simulator = Simulator(relaytarget, clienttarget)