mirror of
https://github.com/monero-project/research-lab.git
synced 2024-11-16 15:57:37 +00:00
voteFor, pendingVotes, transmitVote working
This commit is contained in:
parent
ba5049ddcc
commit
1445943246
2 changed files with 410 additions and 61 deletions
|
@ -20,18 +20,19 @@ class Block(object):
|
|||
b1 = Block(dataIn = otherStuff, parentsIn = { b0.ident : b0 })
|
||||
|
||||
"""
|
||||
def __init__(self, dataIn=None, parentsIn=None):
|
||||
def __init__(self, dataIn=None, parentsIn=[]):
|
||||
# Initialize with empty payload, no identity, and empty parents.
|
||||
self.data = dataIn
|
||||
self.ident = hash(str(0))
|
||||
assert type(parentsIn)==type([])
|
||||
self.parents = parentsIn
|
||||
self.addParents({})
|
||||
self._recomputeIdent()
|
||||
|
||||
def addParents(self, parentsIn): # dict of parents
|
||||
def addParents(self, parentsIn=[]): # list of parentIdents
|
||||
if self.parents is None:
|
||||
self.parents = parentsIn
|
||||
else:
|
||||
self.parents.update(parentsIn)
|
||||
self.parents = self.parents + parentsIn
|
||||
self._recomputeIdent()
|
||||
|
||||
def _recomputeIdent(self):
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
ing transactions from a reduced/robust BlockHandler object.
|
||||
'''
|
||||
from Block import *
|
||||
import random
|
||||
|
||||
class BlockHandler(object):
|
||||
def __init__(self):
|
||||
|
@ -19,17 +20,52 @@ class BlockHandler(object):
|
|||
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 = {} # dict {blockIdent : block} root blocks
|
||||
self.leaves = {}
|
||||
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 = {}
|
||||
|
||||
def _addBlocks(self, blocksIn):
|
||||
print("Adding Blocks")
|
||||
# Take dict of {blockIdent : block} and call _addBlock on each.
|
||||
for b in blocksIn:
|
||||
self._addBlock(blocksIn[b])
|
||||
self.oldVotes = {}
|
||||
def sumPendingVote(self, vid, touched):
|
||||
for (xid,yid) in zip(self.vids,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})
|
||||
return touched
|
||||
|
||||
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 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 _addBlock(self, b):
|
||||
#print("Adding block")
|
||||
|
@ -49,73 +85,385 @@ class BlockHandler(object):
|
|||
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.update(diffDict) # New block is always a leaf
|
||||
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
|
||||
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 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 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 "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 "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":[]})
|
||||
|
||||
# Make sure grandparents are stored correctly (does nothing if already stored correctly)
|
||||
self.family[parentIdent]["parents"].update(self.blocks[parentIdent].parents)
|
||||
|
||||
# Update "children" sub-dict of family history of parent
|
||||
self.family[parentIdent]["children"].update(diffDict)
|
||||
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:
|
||||
del self.leaves[parentIdent]
|
||||
# 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.update(diffDict)
|
||||
self.leaves.update(diffDict)
|
||||
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":{}}})
|
||||
|
||||
|
||||
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
|
||||
|
||||
class Test_RoBlock(unittest.TestCase):
|
||||
def test_BlockHandler(self):
|
||||
def test_betterTest(self):
|
||||
R = BlockHandler()
|
||||
b = Block(dataIn="zirconium encrusted tweezers", parentsIn={})
|
||||
R._addBlock(b)
|
||||
diffDict = {copy.deepcopy(b.ident) : copy.deepcopy(b)}
|
||||
#print("Differential ", diffDict)
|
||||
b = Block(dataIn="brontosaurus slippers do not exist", parentsIn=copy.deepcopy(diffDict))
|
||||
R._addBlock(b)
|
||||
#print("Blocks ", R.blocks)
|
||||
#print("Family ", R.family)
|
||||
#print("Leaves ", R.leaves)
|
||||
self.assertEqual(len(R.blocks),2)
|
||||
self.assertEqual(len(R.family),2)
|
||||
self.assertEqual(len(R.leaves),1)
|
||||
#print("Differential ", diffDict)
|
||||
key, value = diffDict.popitem()
|
||||
#print("Differential ", diffDict)
|
||||
#print("Outputted values ", key, value)
|
||||
#print("b.ident should = leaf.ident", b.ident)
|
||||
self.assertTrue(key in R.blocks)
|
||||
self.assertTrue(b.ident in R.blocks)
|
||||
self.assertTrue(key in R.family[b.ident]["parents"])
|
||||
self.assertTrue(b.ident in R.family[key]["children"])
|
||||
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)
|
||||
|
||||
# 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[vid].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[vid].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,yid)],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[vid].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,yid)],-1)
|
||||
for pid in R.blocks[wid].parents:
|
||||
if pid in R.vids:
|
||||
q.append(pid)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#R.vote()
|
||||
#print(R.votes)
|
||||
|
||||
|
||||
|
||||
|
|
Loading…
Reference in a new issue