simulator.py 3.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. #!/usr/bin/env python3
  2. import random # For simulation, not cryptography!
  3. import math
  4. import sys
  5. import logging
  6. import network
  7. import dirauth
  8. import relay
  9. import client
  10. class Simulator:
  11. def __init__(self, relaytarget, clienttarget):
  12. self.relaytarget = relaytarget
  13. self.clienttarget = clienttarget
  14. # Some (for now) hard-coded parameters
  15. # The number of directory authorities
  16. numdirauths = 9
  17. # The fraction of relays that are fallback relays
  18. fracfallbackrelays = 0.05
  19. # Start some dirauths
  20. self.dirauthaddrs = []
  21. self.dirauths = []
  22. for i in range(numdirauths):
  23. dira = dirauth.DirAuth(i, numdirauths)
  24. self.dirauths.append(dira)
  25. self.dirauthaddrs.append(dira.netaddr)
  26. # Start some relays
  27. self.relays = []
  28. for i in range(self.relaytarget):
  29. # Relay bandwidths (at least the ones fast enough to get used)
  30. # in the live Tor network (as of Dec 2019) are well approximated
  31. # by (200000-(200000-25000)/3*log10(x)) where x is a
  32. # uniform integer in [1,2500]
  33. x = random.randint(1,2500)
  34. bw = int(200000-(200000-25000)/3*math.log10(x))
  35. self.relays.append(relay.Relay(self.dirauthaddrs, bw, 0))
  36. # The fallback relays are a hardcoded list of a small fraction
  37. # of the relays, used by clients for bootstrapping
  38. numfallbackrelays = int(self.relaytarget * fracfallbackrelays) + 1
  39. fallbackrelays = random.sample(self.relays, numfallbackrelays)
  40. for r in fallbackrelays:
  41. r.set_is_fallbackrelay()
  42. network.thenetwork.setfallbackrelays(fallbackrelays)
  43. # Tick the epoch to build the first consensus
  44. network.thenetwork.nextepoch()
  45. # Start some clients
  46. self.clients = []
  47. for i in range(clienttarget):
  48. self.clients.append(client.Client(self.dirauthaddrs))
  49. # Tick the epoch to bootstrap the clients
  50. network.thenetwork.nextepoch()
  51. # Throw away all the performance statistics to this point
  52. for d in self.dirauths: d.perfstats.reset()
  53. for r in self.relays: r.perfstats.reset()
  54. for c in self.clients: c.perfstats.reset()
  55. if __name__ == '__main__':
  56. # Args: womode snipauthmode networkscale numepochs randseed
  57. if len(sys.argv) != 6:
  58. sys.stderr.write("Usage: womode snipauthmode networkscale numepochs randseed\n")
  59. sys.exit(1)
  60. womode = network.WOMode[sys.argv[1].upper()]
  61. snipauthmode = network.SNIPAuthMode[sys.argv[2].upper()]
  62. networkscale = float(sys.argv[3])
  63. numepochs = int(sys.argv[4])
  64. randseed = int(sys.argv[5])
  65. # Seed the PRNG. On Ubuntu 18.04, this in fact makes future calls
  66. # to (non-cryptographic) random numbers deterministic. On Ubuntu
  67. # 16.04, it does not.
  68. random.seed(randseed)
  69. # Uncomment to see all the debug messages
  70. # logging.basicConfig(level=logging.DEBUG)
  71. # Set the Walking Onions style to use
  72. network.thenetwork.set_wo_style(womode, snipauthmode)
  73. # The steady-state numbers of relays and clients
  74. relaytarget = math.ceil(6500 * networkscale)
  75. clienttarget = math.ceil(2500000 * networkscale)
  76. # Create the simulation
  77. simulator = Simulator(relaytarget, clienttarget)