/ casper / networksim.py
networksim.py
 1  from distributions import transform, normal_distribution
 2  import random
 3  
 4  
 5  class NetworkSimulator():
 6  
 7      def __init__(self, latency=50):
 8          self.agents = []
 9          self.latency_distribution_sample = transform(normal_distribution(latency, (latency * 2) // 5), lambda x: max(x, 0))
10          self.time = 0
11          self.objqueue = {}
12          self.peers = {}
13          self.reliability = 0.9
14  
15      def generate_peers(self, num_peers=5):
16          self.peers = {}
17          for a in self.agents:
18              p = []
19              while len(p) <= num_peers // 2:
20                  p.append(random.choice(self.agents))
21                  if p[-1] == a:
22                      p.pop()
23              self.peers[a.id] = self.peers.get(a.id, []) + p
24              for peer in p:
25                  self.peers[peer.id] = self.peers.get(peer.id, []) + [a]
26  
27      def tick(self):
28          if self.time in self.objqueue:
29              for recipient, obj in self.objqueue[self.time]:
30                  if random.random() < self.reliability:
31                      recipient.on_receive(obj)
32              del self.objqueue[self.time]
33          for a in self.agents:
34              a.tick()
35          self.time += 1
36  
37      def run(self, steps):
38          for i in range(steps):
39              self.tick()
40  
41      def broadcast(self, sender, obj):
42          for p in self.peers[sender.id]:
43              recv_time = self.time + self.latency_distribution_sample()
44              if recv_time not in self.objqueue:
45                  self.objqueue[recv_time] = []
46              self.objqueue[recv_time].append((p, obj))
47  
48      def direct_send(self, to_id, obj):
49          for a in self.agents:
50              if a.id == to_id:
51                  recv_time = self.time + self.latency_distribution_sample()
52                  if recv_time not in self.objqueue:
53                      self.objqueue[recv_time] = []
54                  self.objqueue[recv_time].append((a, obj))
55  
56      def knock_offline_random(self, n):
57          ko = {}
58          while len(ko) < n:
59              c = random.choice(self.agents)
60              ko[c.id] = c
61          for c in ko.values():
62              self.peers[c.id] = []
63          for a in self.agents:
64              self.peers[a.id] = [x for x in self.peers[a.id] if x.id not in ko]
65  
66      def partition(self):
67          a = {}
68          while len(a) < len(self.agents) / 2:
69              c = random.choice(self.agents)
70              a[c.id] = c
71          for c in self.agents:
72              if c.id in a:
73                  self.peers[c.id] = [x for x in self.peers[c.id] if x.id in a]
74              else:
75                  self.peers[c.id] = [x for x in self.peers[c.id] if x.id not in a]