research-lab/source-code/Spectre/BlockHandler.py

124 lines
5.3 KiB
Python
Raw Normal View History

2017-12-12 18:15:56 +00:00
'''
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-
2017-12-12 22:33:05 +00:00
ing transactions from a reduced/robust BlockHandler object.
2017-12-12 18:15:56 +00:00
'''
from Block import *
2017-12-12 22:33:05 +00:00
class BlockHandler(object):
2017-12-12 18:15:56 +00:00
def __init__(self):
2017-12-12 22:33:24 +00:00
#print("Initializing")
2017-12-12 22:33:05 +00:00
# Initialize a BlockHandler object.
2017-12-12 18:15:56 +00:00
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 = {} # dict {blockIdent : block} root blocks
self.leaves = {}
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])
def _addBlock(self, b):
2017-12-12 22:33:24 +00:00
#print("Adding block")
2017-12-12 18:15:56 +00:00
# Take a single block b and add to self.blocks, record family
# relations, update leaf monitor, update root monitor if nec-
# essary
2017-12-12 22:33:24 +00:00
diffDict = {copy.deepcopy(b.ident):copy.deepcopy(b)}
2017-12-12 18:15:56 +00:00
2017-12-12 22:33:24 +00:00
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.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
# 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:{}})
2017-12-12 18:15:56 +00:00
2017-12-12 22:33:24 +00:00
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":{}})
# Make sure grandparents are stored correctly (does nothing if already stored correctly)
self.family[parentIdent]["parents"].update(self.blocks[parentIdent].parents)
2017-12-12 18:15:56 +00:00
2017-12-12 22:33:24 +00:00
# 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":{}}})
2017-12-12 18:15:56 +00:00
class Test_RoBlock(unittest.TestCase):
2017-12-12 22:33:05 +00:00
def test_BlockHandler(self):
R = BlockHandler()
2017-12-12 22:33:24 +00:00
b = Block(dataIn="zirconium encrusted tweezers", parentsIn={})
2017-12-12 18:15:56 +00:00
R._addBlock(b)
2017-12-12 22:33:24 +00:00
diffDict = {copy.deepcopy(b.ident) : copy.deepcopy(b)}
#print("Differential ", diffDict)
b = Block(dataIn="brontosaurus slippers do not exist", parentsIn=copy.deepcopy(diffDict))
2017-12-12 18:15:56 +00:00
R._addBlock(b)
2017-12-12 22:33:24 +00:00
#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"])
2017-12-12 18:15:56 +00:00
suite = unittest.TestLoader().loadTestsFromTestCase(Test_RoBlock)
unittest.TextTestRunner(verbosity=1).run(suite)