udpate ffs again

This commit is contained in:
Brandon Goodell 2017-12-12 15:33:24 -07:00
parent cdaeb98d1d
commit ba5049ddcc
2 changed files with 81 additions and 206 deletions

View file

@ -16,18 +16,15 @@ class Block(object):
and updates parents to include.
_recomputeIdent : recomputes identity
Usage:
b0 = Block()
b0.data = ...
b1 = Block()
b1.data = ...
b1.addParents({b0.ident:b0})
b0 = Block(dataIn = stuff, parentsIn = None)
b1 = Block(dataIn = otherStuff, parentsIn = { b0.ident : b0 })
"""
def __init__(self):
def __init__(self, dataIn=None, parentsIn=None):
# Initialize with empty payload, no identity, and empty parents.
self.data = None
self.data = dataIn
self.ident = hash(str(0))
self.parents = None
self.parents = parentsIn
self.addParents({})
def addParents(self, parentsIn): # dict of parents

View file

@ -13,7 +13,7 @@ from Block import *
class BlockHandler(object):
def __init__(self):
print("Initializing")
#print("Initializing")
# Initialize a BlockHandler object.
self.data = None
self.blocks = {} # Set of blocks (which track parents)
@ -32,214 +32,92 @@ class BlockHandler(object):
self._addBlock(blocksIn[b])
def _addBlock(self, b):
print("Adding block")
#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 = {b.ident:b}
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)
self.family.update({b.ident:{}})
self.family[b.ident].update({"parents":b.parents, "children":{}})
for parentIdent in b.parents:
if parentIdent not in self.family:
self.family.update({parentIdent:{}})
if "parents" not in self.family[parentIdent]:
self.family[parentIdent].update({"parents":{}})
if "children" not in self.family[parentIdent]:
self.family[parentIdent].update({"children":{}})
self.family[parentIdent]["parents"].update(b.parents)
self.family[parentIdent]["children"].update(diffDict)
if parentIdent in self.leaves:
del self.leaves[parentIdent]
if len(b.parents)==0 and b.ident not in self.roots:
self.roots.update(diffDict)
self.leaves.update(diffDict)
def inPast(self, x, y):
print("Testing if in past")
# Return true if y is an ancestor of x
q = deque()
for pid in self.blocks[x].parents:
if pid==y:
return True
break
q.append(pid)
while(len(q)>0):
nxtIdent = q.popleft()
if len(self.blocks[nxtIdent].parents) > 0:
for pid in self.blocks[nxtIdent].parents:
if pid==y:
return True
break
q.append(pid)
return False
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.update(diffDict) # 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
def vote(self):
print("Voting")
# Compute partial spectre vote for top several layers of
# the dag.
(U, vids) = self.leafBackAntichain()
self.votes = {}
# 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:{}})
q = deque()
self.pendingVotes = {}
for i in range(len(U)):
for leafId in U[i]:
if i > 0:
self.sumPendingVotes(leafId, vids)
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":{}})
for x in U[i]:
if x != leafId:
q.append(x)
while(len(q)>0):
x = q.popleft()
if (leafId, leafId, x) not in self.votes:
self.votes.update({(leafId, leafId, x):1})
else:
try:
assert self.votes[(leafId, leafId, x)]==1
except AssertionError:
print("Woops, we found (leafId, leafId, x) as a key in self.votes while running vote(), and it should be +1, but it isn't:\n\n", (leafId, leafId, x), self.votes[(leafId, leafId, x)], "\n\n")
if (leafId, x, leafId) not in self.votes:
self.votes.update({(leafId, x, leafId):-1})
else:
try:
assert self.votes[(leafId,x,leafId)]==-1
except AssertionError:
print("Woops, we found (leafId, x, leafId) as a key in self.votes while running vote(), and it should be +1, but it isn't:\n\n", (leafId, x, leafId), self.votes[(leafId, x, leafId)], "\n\n")
self.transmitVote(leafId, leafId, x)
for pid in self.blocks[x].parents:
if not self.inPast(leafId, pid) and pid in vids and pid != leafId:
q.append(pid)
print(self.votes)
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":{}})
def sumPendingVotes(self, blockId, vulnIds):
print("Summing pending votes")
# For a blockId, take all pending votes for vulnerable IDs (x,y)
# if the net is positive vote 1, if the net is negative vote -1
# otherwise vote 0.
for x in vulnIds:
for y in vulnIds:
if (blockId, x, y) in self.pendingVotes:
if self.pendingVotes[(blockId, x, y)] > 0:
if (blockId, x, y) not in self.votes:
self.votes.update({(blockId, x, y):1})
else:
try:
assert self.votes[(blockId,x,y)]==1
except AssertionError:
print("Woops, we found (blockId, x, y) as a key in self.votes, and it should be +1, but it isn't:\n\n", (blockId, x, y), self.votes[(blockId, x,y)], "\n\n")
if (blockId, y, x) not in self.votes:
self.votes.update({(blockId, y, x):-1})
else:
try:
assert self.votes[(blockId,y,x)]==-1
except AssertionError:
print("Woops, we found (blockId, y, x) as a key in self.votes, and it should be -1, but it isn't:\n\n", (blockId, y, x), self.votes[(blockId, y,x)], "\n\n")
self.transmitVote(blockId, x, y)
elif self.pendingVotes[(blockId, x, y)] < 0:
if (blockId, x, y) not in self.votes:
self.votes.update({(blockId, x, y):-1})
else:
try:
assert self.votes[(blockId,x,y)]==-1
except AssertionError:
print("Woops, we found (blockId, x, y) as a key in self.votes, and it should be -1, but it isn't:\n\n", (blockId, x, y), self.votes[(blockId, x,y)], "\n\n")
# Make sure grandparents are stored correctly (does nothing if already stored correctly)
self.family[parentIdent]["parents"].update(self.blocks[parentIdent].parents)
if (blockId, y, x) not in self.votes:
self.votes.update({(blockId, y, x):1})
else:
try:
assert self.votes[(blockId,y,x)]==1
except AssertionError:
print("Woops, we found (blockId, y, x) as a key in self.votes, and it should be +1, but it isn't:\n\n", (blockId, x, y), self.votes[(blockId, x,y)], "\n\n")
self.transmitVote(blockId, y, x)
else:
if (blockId, x, y) not in self.votes:
self.votes.update({(blockId, x, y):0})
else:
try:
assert self.votes[(blockId,x,y)]==0
except AssertionError:
print("Woops, we found (blockId, x, y) as a key in self.votes, and it should be 0, but it isn't:\n\n", (blockId, x, y), self.votes[(blockId, x,y)], "\n\n")
if (blockId, y, x) not in self.votes:
self.votes.update({(blockId, y, x):0})
else:
try:
assert self.votes[(blockId,y,x)]==0
except AssertionError:
print("Woops, we found (blockId, y, x) as a key in self.votes, and it should be 0, but it isn't:\n\n", (blockId, y, x), self.votes[(blockId, y,x)], "\n\n")
# Update "children" sub-dict of family history of parent
self.family[parentIdent]["children"].update(diffDict)
# If the parent was previously a leaf, it is no longer
if parentIdent in self.leaves:
del self.leaves[parentIdent]
else:
if b.ident not in self.roots:
self.roots.update(diffDict)
self.leaves.update(diffDict)
self.family.update({b.ident:{"parents":{}, "children":{}}})
def transmitVote(self, v, x, y):
print("Transmitting votes")
q = deque()
for pid in self.blocks[v].parents:
q.append(pid)
while(len(q)>0):
print("Length of queue = ", len(q))
nxtPid = q.popleft()
if (nxtPid, x, y) not in self.pendingVotes:
self.pendingVotes.update({(nxtPid,x,y):1})
self.pendingVotes.update({(nxtPid,y,x):-1})
else:
self.pendingVotes[(nxtPid,x,y)] += 1
self.pendingVotes[(nxtPid,y,x)] -= 1
if len(self.blocks[nxtPid].parents) > 0:
for pid in self.blocks[nxtPid].parents:
if pid != nxtPid:
q.append(pid)
def leafBackAntichain(self):
print("Computing antichain")
temp = copy.deepcopy(self)
decomposition = []
vulnIdents = None
decomposition.append(temp.leaves)
vulnIdents = decomposition[-1]
temp = temp.pruneLeaves()
while(len(temp.blocks)>0 and len(decomposition) < self.antichainCutoff):
decomposition.append(temp.leaves)
for xid in decomposition[-1]:
if xid not in vulnIdents:
vulnIdents.update({xid:decomposition[-1][xid]})
temp = temp.pruneLeaves()
return decomposition, vulnIdents
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
class Test_RoBlock(unittest.TestCase):
def test_BlockHandler(self):
R = BlockHandler()
b = Block()
b.data = "zirconium encrusted tweezers"
b._recomputeIdent()
b = Block(dataIn="zirconium encrusted tweezers", parentsIn={})
R._addBlock(b)
b = Block()
b.data = "brontosaurus slippers cannot exist"
b.addParents(R.leaves)
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"])
R.vote()
suite = unittest.TestLoader().loadTestsFromTestCase(Test_RoBlock)
unittest.TextTestRunner(verbosity=1).run(suite)