Skip to content

Instantly share code, notes, and snippets.

@tomrittervg
Created October 16, 2014 03:06
Show Gist options
  • Save tomrittervg/582dde1fb41bda2649fd to your computer and use it in GitHub Desktop.
Save tomrittervg/582dde1fb41bda2649fd to your computer and use it in GitHub Desktop.
Tor Consensus Sim
#!/usr/bin/env python
class DirAuth:
def __init__(self, nickname):
self._nickname = nickname
self._trustedDirAuths = []
self._collectedVotes = set()
def setTrustedDirAuths(self, trustedDirAuths):
self._trustedDirAuths = trustedDirAuths
if self._nickname in [str(n) for n in self._trustedDirAuths]:
raise Exception("Do not include self in trustedDirAuths")
self._trustedDirAuthsNicknames = [str(n) for n in self._trustedDirAuths]
def __str__(self):
return self._nickname
def vote(self):
self._collectedVotes = set()
self._collectedVotes.add(self._nickname)
def recieveVote(self, v):
if v in self._trustedDirAuthsNicknames:
self._collectedVotes.add(v)
def retrieveVote(self):
return self._nickname
def retrieveVoteFor(self, target):
if target in self._collectedVotes:
return target
return ""
def postVotes(self, brokenRoutes):
for d in self._trustedDirAuths:
if str(d) not in brokenRoutes:
d.recieveVote(self._nickname)
def fetchVotes(self, brokenRoutes):
for d in self._trustedDirAuths:
if str(d) in self._collectedVotes:
continue
for e in self._trustedDirAuths:
if str(e) not in brokenRoutes:
retrieved = e.retrieveVoteFor(str(d))
if retrieved: self._collectedVotes.add(retrieved)
def calculateConsensus(self):
return "".join([v.replace('auth', '') for v in self._collectedVotes])
def debug(self):
return " ".join([v.replace('auth', '') for v in self._collectedVotes])
class Network:
def __init__(self, dirAuths):
self._dirAuths = dirAuths
self._trafficRules = {}
for d in dirAuths:
self._trafficRules[str(d)] = set()
def vote(self):
for d in self._dirAuths:
d.vote()
for d in self._dirAuths:
d.postVotes(self._trafficRules[str(d)])
for d in self._dirAuths:
d.fetchVotes(self._trafficRules[str(d)])
def calculateConsensus(self):
self.vote()
consensuses = {}
for d in self._dirAuths:
if d.calculateConsensus() not in consensuses:
consensuses[d.calculateConsensus()] = 1
else:
consensuses[d.calculateConsensus()] += 1
return consensuses
def validConsensus(self):
c = self.calculateConsensus()
if max(c.itervalues()) > len(self._dirAuths) / 2.0:
return True
return False
def createBlock(self, source, dest, symmetric):
if dest == "*":
for i in self._dirAuths:
if str(i) != source:
self._trafficRules[source].add(str(i))
elif source == "*":
for i in self._dirAuths:
if str(i) != dest:
self._trafficRules[str(i)].add(dest)
else:
self._trafficRules[source].add(dest)
if symmetric: self.createBlock(dest, source, False)
def removeBlock(self, source, dest, symmetric):
if dest == "*":
for i in self._dirAuths:
if str(i) != source:
if str(i) in self._trafficRules[source]: self._trafficRules[source].remove(str(i))
elif source == "*":
for i in self._dirAuths:
if str(i) != dest:
if dest in self._trafficRules[str(i)]: self._trafficRules[str(i)].remove(dest)
else:
if dest in self._trafficRules[source]: self._trafficRules[source].remove(dest)
if symmetric: self.removeBlock(dest, source, False)
def debug(self):
s = ""
for d in self._dirAuths:
s += str(d) + ": " + d.debug() + "\n"
return s
# Help Functions
def populateAllDirAuthstoAll(dirAuths):
for d in dirAuths:
d.setTrustedDirAuths([x for x in dirAuths if x != d])
def omitLastDirAuthFromN(dirAuths, n):
#Set the first count - N DirAuths to all DirAuths
for i in range(0, len(dirAuths) - n - 1):
dirAuths[i].setTrustedDirAuths([x for x in dirAuths if x != dirAuths[i]])
#Set the middle DirAuths to all but the newbie
for i in range(len(dirAuths) - n - 1, len(dirAuths)-1):
dirAuths[i].setTrustedDirAuths([x for x in dirAuths if x != dirAuths[i] and x != dirAuths[-1]])
#Set the last DirAuth (the newbie) to all DirAuths
dirAuths[-1].setTrustedDirAuths([x for x in dirAuths if x != dirAuths[-1]])
if __name__ == "__main__":
dirAuths = [DirAuth('auth1'), DirAuth('auth2'), DirAuth('auth3'), DirAuth('auth4'), DirAuth('auth5')]
omitLastDirAuthFromN(dirAuths, 3)
n = Network(dirAuths)
#n.createBlock('auth2', '*', True)
#n.createBlock('auth2', '*', True)
#n.removeBlock('auth1', 'auth2', True)
if not n.validConsensus():
print "Invalid Consensus"
print "\t", n.calculateConsensus()
else:
print "Valid Consensus"
print "\t", n.calculateConsensus()
#print n.debug()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment