research-lab/source-code/Spectre/BlockHandler.py
2017-12-14 00:24:20 -07:00

668 lines
34 KiB
Python

'''
A handler for Block.py that takes a collection of blocks (which
only reference parents) as input data. It uses a doubly-linked
tree to determine precedent relationships efficiently, and it can
use that precedence relationship to produce a reduced/robust pre-
cedence relationship as output (the spectre precedence relationship
between blocks.
Another handler will extract a coherent/robust list of non-conflict-
ing transactions from a reduced/robust BlockHandler object.
'''
from Block import *
import random
class BlockHandler(object):
def __init__(self):
#print("Initializing")
# Initialize a BlockHandler object.
self.data = None
self.blocks = {} # Set of blocks (which track parents)
self.family = {} # Doubly linked list tracks parent-and-child links
self.invDLL = {} # subset of blocks unlikely to be re-orged
self.roots = [] # list of root blockIdents
self.leaves = [] # list of leaf blockIdents
self.antichains = []
self.vids = []
self.antichainCutoff = 600 # stop re-orging after this many layers
self.pendingVotes = {}
self.votes = {}
self.totalVotes = {}
def addBlock(self, b):
#print("Adding block")
# Take a single block b and add to self.blocks, record family
# relations, update leaf monitor, update root monitor if nec-
# essary
diffDict = {copy.deepcopy(b.ident):copy.deepcopy(b)}
try:
assert b.ident not in self.blocks
except AssertionError:
print("Woops, tried to add a block with ident in self.blocks, overwriting old block")
self.blocks.update(diffDict)
try:
assert b.ident not in self.leaves
except AssertionError:
print("Woops, tried to add a block to leaf set that is already in the leafset, aborting.")
self.leaves.append(b.ident) # New block is always a leaf
try:
assert b.ident not in self.family
except AssertionError:
print("woops, tried to add a block that already has a recorded family history, aborting.")
self.family.update({b.ident:{"parents":b.parents, "children":[]}})
# Add fam history fam (new blocks have no children yet)
# Now update each parent's family history to reflect the new child
if b.parents is not None:
if len(b.parents)>0:
for parentIdent in b.parents:
if parentIdent not in self.family:
# This should never occur.
print("Hey, what? confusedTravolta.gif... parentIdent not in self.family, parent not correct somehow.")
self.family.update({parentIdent:{}})
if "parents" not in self.family[parentIdent]:
# This should never occur.
print("Hey, what? confusedTravolta.gif... family history of parent lacks sub-dict for parentage, parent not correct somehow")
self.family[parentIdent].update({"parents":[]})
if "children" not in self.family[parentIdent]:
# This should never occur.
print("Hey, what? confusedTravolta.gif... family history of parent lacks sub-dict for children, parent not correct somehow")
self.family[parentIdent].update({"children":[]})
if self.blocks[parentIdent].parents is not None:
for pid in self.blocks[parentIdent].parents:
if pid not in self.family[parentIdent]["parents"]:
self.family[parentIdent]["parents"].append(pid)
#for p in self.blocks[parentIdent].parents: self.family[parentIdent]["parents"].append(p)
# Update "children" sub-dict of family history of parent
self.family[parentIdent]["children"].append(b.ident)
# If the parent was previously a leaf, it is no longer
if parentIdent in self.leaves:
self.leaves.remove(parentIdent)
else:
if b.ident not in self.roots:
self.roots.append(b.ident)
if b.ident not in self.leaves:
self.leaves.append(b.ident)
if b.ident not in self.family:
self.family.update({b.ident:{"parents":{}, "children":{}}})
else:
if b.ident not in self.roots:
self.roots.append(b.ident)
if b.ident not in self.leaves:
self.leaves.append(b.ident)
if b.ident not in self.family:
self.family.update({b.ident:{"parents":{}, "children":{}}})
pass
def hasAncestor(self, xid, yid):
# Return true if y is an ancestor of x
assert xid in self.blocks
assert yid in self.blocks
q = deque()
found = False
if self.blocks[xid].parents is not None:
for pid in self.blocks[xid].parents:
if pid==yid:
found = True
break
q.append(pid)
while(len(q)>0 and not found):
xid = q.popleft()
if self.blocks[xid].parents is not None:
if len(self.blocks[xid].parents) > 0:
for pid in self.blocks[xid].parents:
if pid==yid:
found = True
q.append(pid)
return found
def pruneLeaves(self):
#print("Pruning leaves")
out = BlockHandler()
q = deque()
for rootIdent in self.roots:
q.append(rootIdent)
while(len(q)>0):
thisIdent = q.popleft()
if thisIdent not in self.leaves:
out.addBlock(self.blocks[thisIdent])
for chIdent in self.family[thisIdent]["children"]:
q.append(chIdent)
return out
def leafBackAntichain(self):
#print("Computing antichain")
temp = copy.deepcopy(self)
decomposition = []
vulnIdents = []
decomposition.append([])
for lid in temp.leaves:
decomposition[-1].append(lid)
vulnIdents = copy.deepcopy(decomposition[-1])
temp = temp.pruneLeaves()
while(len(temp.blocks)>0 and len(decomposition) < self.antichainCutoff):
decomposition.append([])
for lid in temp.leaves:
decomposition[-1].append(lid)
for xid in decomposition[-1]:
if xid not in vulnIdents:
vulnIdents.append(xid)
temp = temp.pruneLeaves()
return decomposition, vulnIdents
def transmitVote(self, votingIdents):
(vid, xid, yid) = votingIdents
q = deque()
for wid in self.blocks[vid].parents:
if wid in self.vids:
q.append(wid)
while(len(q)>0):
wid = q.popleft()
if (wid,xid,yid) not in self.pendingVotes:
self.pendingVotes.update({(wid,xid,yid):0})
if (wid,yid,xid) not in self.pendingVotes:
self.pendingVotes.update({(wid,yid,xid):0})
self.pendingVotes[(wid,xid,yid)]+=1
self.pendingVotes[(wid,yid,xid)]-=1
#print(self.blocks[wid].parents)
for pid in self.blocks[wid].parents:
if pid in self.vids:
q.append(pid)
def voteFor(self, votingIdents, touched):
(vid, xid, yid) = votingIdents
self.votes.update({(vid,xid,yid):1, (vid,yid,xid):-1})
touched.update({(vid,xid,yid):True, (vid,yid,xid):True})
self.transmitVote((vid,xid,yid))
return touched
def sumPendingVote(self, vid, touched):
pastR = self.pastOf(vid)
for xid in self.vids:
for yid in self.vids:
if (vid, xid, yid) in self.pendingVotes:
if self.pendingVotes[(vid,xid,yid)] > 0:
touched = self.voteFor((vid,xid,yid), touched)
elif self.pendingVotes[(vid,xid,yid)] <0:
touched = self.voteFor((vid,yid,xid), touched)
else:
self.votes.update({(vid,xid,yid): 0, (vid,yid,xid): 0})
touched.update({(vid,xid,yid): True, (vid,yid,xid): True})
#R = self.pastOf(vid)
#touched = R.vote(touched)
return touched
def vote(self,touchedIn={}):
U, V = self.leafBackAntichain()
self.antichains = U
self.vids = V
touched = touchedIn
for i in range(len(U)):
for vid in U[i]: # ID of voting block
touched = self.sumPendingVote(vid, touched)
for j in range(i+1):
for xid in U[j]: # Voting block compares self to xid
# Note if j=i, xid and vid are incomparable.
# If j < i, then xid may have vid as an ancestor.
# vid can never have xid as an ancestor.
# In all cases, vid votes that vid precedes xid
if xid==vid:
continue
else:
touched = self.voteFor((vid,vid,xid),touched)
# For each ancestor of xid that is not an ancestor of vid,
# we can apply the same!
q = deque()
for pid in self.blocks[xid].parents:
if pid in self.vids and not self.hasAncestor(vid,pid):
q.append(pid)
while(len(q)>0):
wid = q.popleft()
for pid in self.blocks[wid].parents:
if pid in self.vids and not self.hasAncestor(vid, pid):
q.append(pid)
touched = self.voteFor((vid,vid,wid),touched)
R = self.pastOf(vid)
R.vote()
for xid in R.blocks:
touched = self.voteFor((vid,xid,vid), touched)
for yid in R.blocks:
if (xid, yid) in R.totalVotes:
if R.totalVotes[(xid,yid)]:
touched = self.voteFor((vid,xid,yid), touched)
elif (yid, xid) in R.totalVotes:
if R.totalVotes[(yid,xid)]:
touched = self.voteFor((vid, yid, xid), touched)
self.computeTotalVotes()
return touched
def computeTotalVotes(self):
for xid in self.vids:
for yid in self.vids:
s = 0
found = False
for vid in self.vids:
if (vid, xid, yid) in self.votes or (vid, yid, xid) in self.votes:
found = True
if self.votes[(vid, xid, yid)]==1:
s+= 1
elif self.votes[(vid,yid,xid)]==-1:
s-= 1
if found:
if s > 0:
self.totalVotes.update({(xid, yid):True, (yid,xid):False})
elif s < 0:
self.totalVotes.update({(xid,yid):False, (yid,xid):True})
elif s==0:
self.totalVotes.update({(xid,yid):False, (yid,xid):False})
else:
if (xid,yid) in self.totalVotes:
del self.totalVotes[(xid,yid)]
if (yid,xid) in self.totalVotes:
del self.totalVotes[(yid,xid)]
def pastOf(self, xid):
R = BlockHandler()
identsToAdd = {}
q = deque()
for pid in self.blocks[xid].parents:
q.append(pid)
while(len(q)>0):
yid = q.popleft()
if yid not in identsToAdd:
identsToAdd.update({yid:True})
for pid in self.blocks[yid].parents:
q.append(pid)
for rid in self.roots:
if rid in identsToAdd:
q.append(rid)
while(len(q)>0):
yid = q.popleft()
if yid not in R.blocks:
R.addBlock(self.blocks[yid])
for pid in self.family[yid]["children"]:
if pid in identsToAdd:
q.append(pid)
return R
class Test_BlockHandler(unittest.TestCase):
def test_betterTest(self):
R = BlockHandler()
self.assertTrue(R.data is None)
self.assertEqual(len(R.blocks),0)
self.assertEqual(type(R.blocks),type({}))
self.assertEqual(len(R.family),0)
self.assertEqual(type(R.family),type({}))
self.assertEqual(len(R.invDLL),0)
self.assertEqual(type(R.invDLL),type({}))
self.assertEqual(len(R.roots),0)
self.assertEqual(type(R.leaves),type([]))
self.assertEqual(len(R.leaves),0)
self.assertEqual(R.antichainCutoff,600)
self.assertEqual(type(R.roots),type([]))
self.assertEqual(len(R.pendingVotes),0)
self.assertEqual(type(R.pendingVotes),type({}))
self.assertEqual(len(R.votes),0)
self.assertEqual(type(R.votes),type({}))
gen = Block() # genesis block
self.assertTrue(gen.data is None)
self.assertEqual(gen.parents,[])
msg = str(0) + str(None) + str([])
self.assertEqual(gen.ident, hash(msg))
block0 = gen
block1 = Block(parentsIn=[block0.ident], dataIn={"timestamp":time.time(), "txns":"pair of zircon encrusted tweezers"})
block2 = Block(parentsIn=[block1.ident], dataIn={"timestamp":time.time(), "txns":"watch out for that yellow snow"})
block3 = Block(parentsIn=[block1.ident], dataIn={"timestamp":time.time(), "txns":"he had the stank foot"})
block4 = Block(parentsIn=[block2.ident, block3.ident], dataIn={"timestamp":time.time(), "txns":"come here fido"})
block5 = Block(parentsIn=[block3.ident], dataIn={"timestamp":time.time(), "txns":"applied rotation on her sugar plum"})
block6 = Block(parentsIn=[block5.ident], dataIn={"timestamp":time.time(), "txns":"listen to frank zappa for the love of all that is good"})
R.addBlock(block0)
self.assertTrue(block0.ident in R.leaves)
self.assertTrue(block0.ident in R.roots)
R.addBlock(block1)
self.assertTrue(block1.ident in R.leaves and block0.ident not in R.leaves)
R.addBlock(block2)
self.assertTrue(block2.ident in R.leaves and block1.ident not in R.leaves)
R.addBlock(block3)
self.assertTrue(block3.ident in R.leaves and block2.ident in R.leaves and block1.ident not in R.leaves)
R.addBlock(block4)
self.assertTrue(block4.ident in R.leaves and block3.ident not in R.leaves and block2.ident not in R.leaves)
R.addBlock(block5)
self.assertTrue(block4.ident in R.leaves and block5.ident in R.leaves and block3.ident not in R.leaves)
R.addBlock(block6)
self.assertTrue(block4.ident in R.leaves and block6.ident in R.leaves and block5.ident not in R.leaves)
self.assertEqual(len(R.blocks), 7)
self.assertEqual(len(R.family), 7)
self.assertEqual(len(R.invDLL), 0)
self.assertEqual(len(R.roots), 1)
self.assertEqual(len(R.leaves),2)
self.assertEqual(R.antichainCutoff, 600)
self.assertEqual(len(R.pendingVotes),0)
self.assertEqual(len(R.votes),0)
self.assertTrue( R.hasAncestor(block6.ident, block0.ident) and not R.hasAncestor(block0.ident, block6.ident))
self.assertTrue( R.hasAncestor(block5.ident, block0.ident) and not R.hasAncestor(block0.ident, block5.ident))
self.assertTrue( R.hasAncestor(block4.ident, block0.ident) and not R.hasAncestor(block0.ident, block4.ident))
self.assertTrue( R.hasAncestor(block3.ident, block0.ident) and not R.hasAncestor(block0.ident, block3.ident))
self.assertTrue( R.hasAncestor(block2.ident, block0.ident) and not R.hasAncestor(block0.ident, block2.ident))
self.assertTrue( R.hasAncestor(block1.ident, block0.ident) and not R.hasAncestor(block0.ident, block1.ident))
self.assertTrue( R.hasAncestor(block6.ident, block1.ident) and not R.hasAncestor(block1.ident, block6.ident))
self.assertTrue( R.hasAncestor(block5.ident, block1.ident) and not R.hasAncestor(block1.ident, block5.ident))
self.assertTrue( R.hasAncestor(block4.ident, block1.ident) and not R.hasAncestor(block1.ident, block4.ident))
self.assertTrue( R.hasAncestor(block3.ident, block1.ident) and not R.hasAncestor(block1.ident, block3.ident))
self.assertTrue( R.hasAncestor(block2.ident, block1.ident) and not R.hasAncestor(block1.ident, block2.ident))
self.assertTrue(not R.hasAncestor(block0.ident, block1.ident) and R.hasAncestor(block1.ident, block0.ident))
self.assertTrue(not R.hasAncestor(block6.ident, block2.ident) and not R.hasAncestor(block2.ident, block6.ident))
self.assertTrue(not R.hasAncestor(block5.ident, block2.ident) and not R.hasAncestor(block2.ident, block5.ident))
self.assertTrue( R.hasAncestor(block4.ident, block2.ident) and not R.hasAncestor(block2.ident, block4.ident))
self.assertTrue(not R.hasAncestor(block3.ident, block2.ident) and not R.hasAncestor(block2.ident, block3.ident))
self.assertTrue(not R.hasAncestor(block1.ident, block2.ident) and R.hasAncestor(block2.ident, block1.ident))
self.assertTrue(not R.hasAncestor(block0.ident, block2.ident) and R.hasAncestor(block2.ident, block0.ident))
self.assertTrue( R.hasAncestor(block6.ident, block3.ident) and not R.hasAncestor(block3.ident, block6.ident))
self.assertTrue( R.hasAncestor(block5.ident, block3.ident) and not R.hasAncestor(block3.ident, block5.ident))
self.assertTrue( R.hasAncestor(block4.ident, block3.ident) and not R.hasAncestor(block3.ident, block4.ident))
self.assertTrue(not R.hasAncestor(block2.ident, block3.ident) and not R.hasAncestor(block3.ident, block2.ident))
self.assertTrue(not R.hasAncestor(block1.ident, block3.ident) and R.hasAncestor(block3.ident, block1.ident))
self.assertTrue(not R.hasAncestor(block0.ident, block3.ident) and R.hasAncestor(block3.ident, block0.ident))
self.assertTrue(not R.hasAncestor(block6.ident, block4.ident) and not R.hasAncestor(block4.ident, block6.ident))
self.assertTrue(not R.hasAncestor(block5.ident, block4.ident) and not R.hasAncestor(block4.ident, block5.ident))
self.assertTrue(not R.hasAncestor(block3.ident, block4.ident) and R.hasAncestor(block4.ident, block3.ident))
self.assertTrue(not R.hasAncestor(block2.ident, block4.ident) and R.hasAncestor(block4.ident, block2.ident))
self.assertTrue(not R.hasAncestor(block1.ident, block4.ident) and R.hasAncestor(block4.ident, block1.ident))
self.assertTrue(not R.hasAncestor(block0.ident, block4.ident) and R.hasAncestor(block4.ident, block0.ident))
self.assertTrue( R.hasAncestor(block6.ident, block5.ident) and not R.hasAncestor(block5.ident, block6.ident))
self.assertTrue(not R.hasAncestor(block4.ident, block5.ident) and not R.hasAncestor(block5.ident, block4.ident))
self.assertTrue(not R.hasAncestor(block3.ident, block5.ident) and R.hasAncestor(block5.ident, block3.ident))
self.assertTrue(not R.hasAncestor(block2.ident, block5.ident) and not R.hasAncestor(block5.ident, block2.ident))
self.assertTrue(not R.hasAncestor(block1.ident, block5.ident) and R.hasAncestor(block5.ident, block1.ident))
self.assertTrue(not R.hasAncestor(block0.ident, block5.ident) and R.hasAncestor(block5.ident, block0.ident))
self.assertTrue(not R.hasAncestor(block5.ident, block6.ident) and R.hasAncestor(block6.ident, block5.ident))
self.assertTrue(not R.hasAncestor(block4.ident, block6.ident) and not R.hasAncestor(block6.ident, block4.ident))
self.assertTrue(not R.hasAncestor(block3.ident, block6.ident) and R.hasAncestor(block6.ident, block3.ident))
self.assertTrue(not R.hasAncestor(block2.ident, block6.ident) and not R.hasAncestor(block6.ident, block2.ident))
self.assertTrue(not R.hasAncestor(block1.ident, block6.ident) and R.hasAncestor(block6.ident, block1.ident))
self.assertTrue(not R.hasAncestor(block0.ident, block6.ident) and R.hasAncestor(block6.ident, block0.ident))
R = R.pruneLeaves()
self.assertEqual(len(R.blocks), 5)
self.assertEqual(len(R.family), 5)
self.assertEqual(len(R.invDLL), 0)
self.assertEqual(len(R.roots), 1)
self.assertEqual(len(R.leaves),2)
self.assertEqual(R.antichainCutoff, 600)
self.assertEqual(len(R.pendingVotes),0)
self.assertEqual(len(R.votes),0)
self.assertTrue( R.hasAncestor(block5.ident, block0.ident) and not R.hasAncestor(block0.ident, block5.ident))
self.assertTrue( R.hasAncestor(block3.ident, block0.ident) and not R.hasAncestor(block0.ident, block3.ident))
self.assertTrue( R.hasAncestor(block2.ident, block0.ident) and not R.hasAncestor(block0.ident, block2.ident))
self.assertTrue( R.hasAncestor(block1.ident, block0.ident) and not R.hasAncestor(block0.ident, block1.ident))
self.assertTrue( R.hasAncestor(block5.ident, block1.ident) and not R.hasAncestor(block1.ident, block5.ident))
self.assertTrue( R.hasAncestor(block3.ident, block1.ident) and not R.hasAncestor(block1.ident, block3.ident))
self.assertTrue( R.hasAncestor(block2.ident, block1.ident) and not R.hasAncestor(block1.ident, block2.ident))
self.assertTrue(not R.hasAncestor(block0.ident, block1.ident) and R.hasAncestor(block1.ident, block0.ident))
self.assertTrue(not R.hasAncestor(block5.ident, block2.ident) and not R.hasAncestor(block2.ident, block5.ident))
self.assertTrue(not R.hasAncestor(block3.ident, block2.ident) and not R.hasAncestor(block2.ident, block3.ident))
self.assertTrue(not R.hasAncestor(block1.ident, block2.ident) and R.hasAncestor(block2.ident, block1.ident))
self.assertTrue(not R.hasAncestor(block0.ident, block2.ident) and R.hasAncestor(block2.ident, block0.ident))
self.assertTrue( R.hasAncestor(block5.ident, block3.ident) and not R.hasAncestor(block3.ident, block5.ident))
self.assertTrue(not R.hasAncestor(block2.ident, block3.ident) and not R.hasAncestor(block3.ident, block2.ident))
self.assertTrue(not R.hasAncestor(block1.ident, block3.ident) and R.hasAncestor(block3.ident, block1.ident))
self.assertTrue(not R.hasAncestor(block0.ident, block3.ident) and R.hasAncestor(block3.ident, block0.ident))
self.assertTrue(not R.hasAncestor(block3.ident, block5.ident) and R.hasAncestor(block5.ident, block3.ident))
self.assertTrue(not R.hasAncestor(block2.ident, block5.ident) and not R.hasAncestor(block5.ident, block2.ident))
self.assertTrue(not R.hasAncestor(block1.ident, block5.ident) and R.hasAncestor(block5.ident, block1.ident))
self.assertTrue(not R.hasAncestor(block0.ident, block5.ident) and R.hasAncestor(block5.ident, block0.ident))
## Formal unit tests for leafBackAntichain() to follow: visual inspection reveals this does what it says on the tin.
#R.vote()
#print(R.votes)
def test_big_bertha(self):
R = BlockHandler()
gen = Block() # genesis block
msg = str(0) + str(None) + str([])
block0 = gen
block1 = Block(parentsIn=[block0.ident], dataIn={"timestamp":time.time(), "txns":"pair of zircon encrusted tweezers"})
block2 = Block(parentsIn=[block1.ident], dataIn={"timestamp":time.time(), "txns":"watch out for that yellow snow"})
block3 = Block(parentsIn=[block1.ident], dataIn={"timestamp":time.time(), "txns":"he had the stank foot"})
block4 = Block(parentsIn=[block2.ident, block3.ident], dataIn={"timestamp":time.time(), "txns":"come here fido"})
block5 = Block(parentsIn=[block3.ident], dataIn={"timestamp":time.time(), "txns":"applied rotation on her sugar plum"})
block6 = Block(parentsIn=[block5.ident], dataIn={"timestamp":time.time(), "txns":"listen to frank zappa for the love of all that is good"})
R.addBlock(block0)
R.addBlock(block1)
R.addBlock(block2)
R.addBlock(block3)
R.addBlock(block4)
R.addBlock(block5)
R.addBlock(block6)
names = {0:block0.ident, 1:block1.ident, 2:block2.ident, 3:block3.ident, 4:block4.ident, 5:block5.ident, 6:block6.ident}
# Testing voteFor
# Verify all roots have children
for rid in R.roots:
self.assertFalse(len(R.family[rid]["children"])==0)
# Verify that all children of all roots have children and collect grandchildren idents
gc = []
for rid in R.roots:
for cid in R.family[rid]["children"]:
self.assertFalse(len(R.family[cid]["children"]) == 0)
gc = gc + R.family[cid]["children"]
# Pick a random grandchild of the root.
gcid = random.choice(gc)
# Pick a random block with gcid in its past
vid = random.choice(list(R.blocks.keys()))
while(not R.hasAncestor(vid, gcid)):
vid = random.choice(list(R.blocks.keys()))
# Pick a random pair of blocks for gcid and vid to vote on.
xid = random.choice(list(R.blocks.keys()))
yid = random.choice(list(R.blocks.keys()))
# Have vid cast vote that xid < yid
R.voteFor((vid,xid,yid),{})
# Verify that R.votes has correct entries
self.assertEqual(R.votes[(vid,xid,yid)], 1)
self.assertEqual(R.votes[(vid,yid,xid)],-1)
# Check that for each ancestor of vid, that they received an appropriate pending vote
q = deque()
for pid in R.blocks[vid].parents:
if pid in R.vids:
q.append(pid)
while(len(q)>0):
wid = q.popleft()
self.assertEqual(R.pendingVotes[(wid,xid,yid)],1)
for pid in R.blocks[wid].parents:
if pid in R.vids:
q.append(pid)
# Now we are going to mess around with how voting at gcid interacts with the above.
# First, we let gcid cast a vote that xid < yid and check that it propagates appropriately as above.
R.voteFor((gcid,xid,yid),{})
self.assertEqual(R.votes[(gcid,xid,yid)],1)
self.assertEqual(R.votes[(gcid,yid,xid)],-1)
for pid in R.blocks[gcid].parents:
if pid in R.vids:
q.append(gpid)
while(len(q)>0):
wid = q.popleft()
self.assertEqual(R.pendingVotes[(wid,xid,yid)],2)
self.assertEqual(R.pendingVotes[(wid,yid,xid)],-2)
for pid in R.blocks[wid].parents:
if pid in R.vids:
q.append(pid)
# Now we are going to have gcid cast the opposite vote. this should change what is stored in R.votes
# but also change pending votes below gcid
R.voteFor((gcid,yid,xid),{})
self.assertEqual(R.votes[(gcid,xid,yid)],-1)
self.assertEqual(R.votes[(gcid,yid,xid)],1)
for pid in R.blocks[gcid].parents:
if pid in R.vids:
q.append(gpid)
while(len(q)>0):
wid = q.popleft()
self.assertEqual(R.pendingVotes[(wid,xid,yid)],0)
self.assertEqual(R.pendingVotes[(wid,yid,xid)],0)
for pid in R.blocks[wid].parents:
if pid in R.vids:
q.append(pid)
# Do again, now pending votes should be negative
R.voteFor((gcid,yid,xid),{})
self.assertEqual(R.votes[(gcid,xid,yid)],-1)
self.assertEqual(R.votes[(gcid,yid,xid)],1)
for pid in R.blocks[gcid].parents:
if pid in R.vids:
q.append(gpid)
while(len(q)>0):
wid = q.popleft()
self.assertEqual(R.pendingVotes[(wid,xid,yid)],-1)
self.assertEqual(R.pendingVotes[(wid,yid,xid)],1)
for pid in R.blocks[wid].parents:
if pid in R.vids:
q.append(pid)
# Test sumPendingVotes
R.sumPendingVote(gcid, {})
self.assertTrue((gcid,xid,yid) in R.votes)
self.assertTrue((gcid,yid,xid) in R.votes)
self.assertEqual(R.votes[(gcid,xid,yid)],-1)
self.assertEqual(R.votes[(gcid,yid,xid)],1)
touched = R.vote()
print("\n ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ====")
print("Antichain layers:\n")
for layer in R.antichains:
print(layer)
print("\n ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ====")
for key in R.votes:
print("key = ", key, ", vote = ", R.votes[key])
print("\n ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ====")
for key in R.totalVotes:
print("key = ", key, ", vote = ", R.totalVotes[key])
print("\n ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ====")
self.assertTrue((names[0], names[1]) in R.totalVotes and (names[1], names[0]) in R.totalVotes)
self.assertTrue(R.totalVotes[(names[0], names[1])] and not R.totalVotes[(names[1], names[0])])
self.assertTrue((names[0], names[2]) in R.totalVotes and (names[2], names[0]) in R.totalVotes)
self.assertTrue(R.totalVotes[(names[0], names[2])] and not R.totalVotes[(names[2], names[0])])
self.assertTrue((names[0], names[3]) in R.totalVotes and (names[3], names[0]) in R.totalVotes)
self.assertTrue(R.totalVotes[(names[0], names[3])] and not R.totalVotes[(names[3], names[0])])
self.assertTrue((names[0], names[4]) in R.totalVotes and (names[4], names[0]) in R.totalVotes)
self.assertTrue(R.totalVotes[(names[0], names[4])] and not R.totalVotes[(names[4], names[0])])
self.assertTrue((names[0], names[5]) in R.totalVotes and (names[5], names[0]) in R.totalVotes)
self.assertTrue(R.totalVotes[(names[0], names[5])] and not R.totalVotes[(names[5], names[0])])
self.assertTrue((names[0], names[6]) in R.totalVotes and (names[6], names[0]) in R.totalVotes)
self.assertTrue(R.totalVotes[(names[0], names[6])] and not R.totalVotes[(names[6], names[0])])
#### #### #### ####
self.assertTrue((names[1], names[2]) in R.totalVotes and (names[2], names[1]) in R.totalVotes)
self.assertTrue(R.totalVotes[(names[1], names[2])] and not R.totalVotes[(names[2], names[1])])
self.assertTrue((names[1], names[3]) in R.totalVotes and (names[3], names[1]) in R.totalVotes)
self.assertTrue(R.totalVotes[(names[1], names[3])] and not R.totalVotes[(names[3], names[1])])
self.assertTrue((names[1], names[4]) in R.totalVotes and (names[4], names[1]) in R.totalVotes)
self.assertTrue(R.totalVotes[(names[1], names[4])] and not R.totalVotes[(names[4], names[1])])
self.assertTrue((names[1], names[5]) in R.totalVotes and (names[5], names[1]) in R.totalVotes)
self.assertTrue(R.totalVotes[(names[1], names[5])] and not R.totalVotes[(names[5], names[1])])
self.assertTrue((names[1], names[6]) in R.totalVotes and (names[6], names[1]) in R.totalVotes)
self.assertTrue(R.totalVotes[(names[1], names[6])] and not R.totalVotes[(names[6], names[1])])
#### #### #### ####
self.assertTrue((names[2], names[3]) in R.totalVotes and (names[3], names[2]) in R.totalVotes)
self.assertTrue(not R.totalVotes[(names[2], names[3])] and R.totalVotes[(names[3], names[2])])
self.assertTrue((names[2], names[4]) in R.totalVotes and (names[4], names[2]) in R.totalVotes)
self.assertTrue(R.totalVotes[(names[2], names[4])] and not R.totalVotes[(names[4], names[2])])
self.assertTrue((names[2], names[5]) in R.totalVotes and (names[5], names[2]) in R.totalVotes)
self.assertTrue(not R.totalVotes[(names[2], names[5])] and R.totalVotes[(names[5], names[2])])
self.assertTrue((names[2], names[6]) in R.totalVotes and (names[6], names[2]) in R.totalVotes)
#print("2,6 ", R.totalVotes[(names[2], names[6])])
#print("6,2 ", R.totalVotes[(names[6], names[2])])
self.assertTrue(not R.totalVotes[(names[2], names[6])] and R.totalVotes[(names[6], names[2])])
#### #### #### ####
self.assertTrue((names[3], names[4]) in R.totalVotes and (names[4], names[3]) in R.totalVotes)
self.assertTrue(R.totalVotes[(names[3], names[4])] and not R.totalVotes[(names[4], names[3])])
self.assertTrue((names[3], names[5]) in R.totalVotes and (names[5], names[3]) in R.totalVotes)
self.assertTrue(R.totalVotes[(names[3], names[5])] and not R.totalVotes[(names[5], names[3])])
self.assertTrue((names[3], names[6]) in R.totalVotes and (names[6], names[3]) in R.totalVotes)
self.assertTrue(R.totalVotes[(names[3], names[6])] and not R.totalVotes[(names[6], names[3])])
#### #### #### ####
self.assertTrue((names[4], names[5]) in R.totalVotes and (names[5], names[4]) in R.totalVotes)
self.assertTrue(not R.totalVotes[(names[4], names[5])] and R.totalVotes[(names[5], names[4])])
self.assertTrue((names[4], names[6]) in R.totalVotes and (names[6], names[4]) in R.totalVotes)
self.assertTrue(not R.totalVotes[(names[4], names[6])] and R.totalVotes[(names[6], names[4])])
#### #### #### ####
self.assertTrue((names[5], names[6]) in R.totalVotes and (names[6], names[5]) in R.totalVotes)
self.assertTrue(R.totalVotes[(names[5], names[6])] and not R.totalVotes[(names[6], names[5])])
#print(R.votes)
suite = unittest.TestLoader().loadTestsFromTestCase(Test_BlockHandler)
unittest.TextTestRunner(verbosity=1).run(suite)