123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105 |
- #!/usr/bin/env python3
- import random # For simulation, not cryptography!
- import math
- import sys
- import logging
- import resource
- 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)
- logging.basicConfig(level=logging.INFO)
- # 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)
- network.thenetwork.nextepoch()
- maxmemmib = resource.getrusage(resource.RUSAGE_SELF).ru_maxrss/1024
- logging.info("%d MiB used", maxmemmib)
|