2018-02-02 00:36:30 +00:00
|
|
|
from Blockchain import *
|
2018-02-09 00:04:13 +00:00
|
|
|
from copy import *
|
2018-02-02 00:36:30 +00:00
|
|
|
|
|
|
|
class Node(object):
|
|
|
|
'''
|
|
|
|
Node object. params [identity, blockchain (data), verbosity, difficulty]
|
|
|
|
'''
|
|
|
|
def __init__(self, params={}):
|
2018-02-09 00:04:13 +00:00
|
|
|
self.ident = None
|
|
|
|
self.data = {}
|
|
|
|
self.verbose = None
|
|
|
|
self.edges = {}
|
|
|
|
self.mode = None
|
|
|
|
self.targetRate = None
|
2018-02-02 00:36:30 +00:00
|
|
|
try:
|
2018-02-09 00:04:13 +00:00
|
|
|
assert len(params)==5
|
2018-02-02 00:36:30 +00:00
|
|
|
except AssertionError:
|
|
|
|
print("Error, Tried to create malformed node.")
|
|
|
|
else:
|
|
|
|
self.ident = params["ident"]
|
|
|
|
self.data = params["data"]
|
|
|
|
self.verbose = params["verbose"]
|
|
|
|
self.edges = {}
|
2018-02-09 00:04:13 +00:00
|
|
|
self.mode = params["mode"]
|
|
|
|
self.targetRate = params["targetRate"]
|
|
|
|
|
|
|
|
def generateBlock(self, discoTime):
|
|
|
|
newName = newIdent(len(self.data["blockchain"].blocks))
|
|
|
|
t = discoTime
|
|
|
|
s = t+self.data["offset"]
|
|
|
|
diff = self.data["blockchain"].diff
|
|
|
|
params = {"ident":name, "disco":t, "arriv":s, "parent":None, "diff":diff}
|
|
|
|
newBlock = Block(params)
|
|
|
|
self.data["blockchain"].addBlock(newBlock, mode, tr)
|
|
|
|
return newName
|
2018-02-02 00:36:30 +00:00
|
|
|
|
2018-02-09 00:04:13 +00:00
|
|
|
def updateBlockchain(self, incBlocks):
|
2018-02-08 20:06:01 +00:00
|
|
|
# incBlocks shall be a dictionary of block identities (as keys) and their associated blocks (as values)
|
2018-02-02 00:36:30 +00:00
|
|
|
# to be added to the local data. We assume difficulty scores have been reported honestly for now.
|
|
|
|
|
2018-02-09 00:04:13 +00:00
|
|
|
tempData = deepcopy(incBlocks)
|
2018-02-08 20:06:01 +00:00
|
|
|
for key in incBlocks:
|
2018-02-02 00:36:30 +00:00
|
|
|
if key in self.data["blockchain"].blocks:
|
|
|
|
del tempData[key]
|
2018-02-08 20:06:01 +00:00
|
|
|
elif incBlocks[key].parent in self.data["blockchain"].blocks or incBlocks[key].parent is None:
|
2018-02-09 00:04:13 +00:00
|
|
|
self.data["blockchain"].addBlock(incBlocks[key], self.mode, self.targetRate)
|
2018-02-02 00:36:30 +00:00
|
|
|
del tempData[key]
|
2018-02-09 00:04:13 +00:00
|
|
|
incBlocks = deepcopy(tempData)
|
2018-02-02 00:36:30 +00:00
|
|
|
while len(incBlocks)>0:
|
|
|
|
for key in incBlocks:
|
|
|
|
if key in self.data["blockchain"].blocks:
|
|
|
|
del tempData[key]
|
2018-02-08 20:06:01 +00:00
|
|
|
elif incBlocks[key].parent in self.data["blockchain"].blocks:
|
2018-02-09 00:04:13 +00:00
|
|
|
self.data["blockchain"].addBlock(incBlocks[key], self.mode, self.targetRate)
|
|
|
|
del tempData[key]
|
|
|
|
incBlocks = deepcopy(tempData)
|
2018-02-02 00:36:30 +00:00
|
|
|
|
2018-02-09 00:04:13 +00:00
|
|
|
def propagate(self, timeOfProp, blockIdent):
|
2018-02-02 00:36:30 +00:00
|
|
|
for edgeIdent in self.edges:
|
2018-02-09 00:04:13 +00:00
|
|
|
edge = self.edges[edgeIdent]
|
|
|
|
length = e.data["length"]
|
|
|
|
timeOfArrival = timeOfProp + length
|
|
|
|
otherIdent = e.getNeighbor(self.ident)
|
|
|
|
other = e.nodes[otherIdent]
|
|
|
|
bc = other.data["blockchain"]
|
2018-02-02 00:36:30 +00:00
|
|
|
if blockIdent not in bc.blocks:
|
|
|
|
pB = e.data["pendingBlocks"]
|
|
|
|
pendingIdent = newIdent(len(pB))
|
|
|
|
mybc = self.data["blockchain"]
|
2018-02-09 00:04:13 +00:00
|
|
|
blockToProp = mybc.blocks[blockIdent]
|
|
|
|
pendingDat = {"timeOfArrival":timeOfArrival, "destIdent":otherIdent, "block":blockToProp}
|
2018-02-02 00:36:30 +00:00
|
|
|
pB.update({pendingIdent:pendingDat})
|
|
|
|
|
|
|
|
|
|
|
|
class Test_Node(unittest.TestCase):
|
2018-02-08 20:06:01 +00:00
|
|
|
# TODO test each method separately
|
2018-02-09 00:04:13 +00:00
|
|
|
def test_all(self):
|
|
|
|
bill = Blockchain([], verbosity=True)
|
2018-02-08 20:06:01 +00:00
|
|
|
mode="Nakamoto"
|
2018-02-09 00:04:13 +00:00
|
|
|
tr = 1.0/600000.0
|
|
|
|
deltaT = 600000.0
|
|
|
|
bill.targetRate = tr
|
2018-02-08 20:06:01 +00:00
|
|
|
|
|
|
|
name = newIdent(0)
|
2018-02-09 00:04:13 +00:00
|
|
|
t = 0.0
|
|
|
|
s = t
|
2018-02-08 20:06:01 +00:00
|
|
|
diff = 1.0
|
|
|
|
params = {"ident":name, "disco":t, "arriv":s, "parent":None, "diff":diff}
|
|
|
|
genesis = Block(params)
|
2018-02-09 00:04:13 +00:00
|
|
|
bill.addBlock(genesis, mode, tr)
|
2018-02-08 20:06:01 +00:00
|
|
|
|
2018-02-09 00:04:13 +00:00
|
|
|
parent = genesis.ident
|
2018-02-08 20:06:01 +00:00
|
|
|
|
2018-02-09 00:04:13 +00:00
|
|
|
nellyname = newIdent(time.time())
|
|
|
|
mode = "Nakamoto"
|
|
|
|
targetRate = 1.0/600000.0
|
|
|
|
params = {"ident":nellyname, "data":{"offset":0.0, "intensity":1.0, "blockchain":bill}, "verbose":True, "mode":mode, "targetRate":targetRate}
|
2018-02-08 20:06:01 +00:00
|
|
|
nelly = Node(params)
|
|
|
|
|
2018-02-09 00:04:13 +00:00
|
|
|
while len(nelly.data["blockchain"].blocks) < 2015:
|
|
|
|
name = newIdent(len(nelly.data["blockchain"].blocks))
|
|
|
|
diff = nelly.data["blockchain"].diff
|
|
|
|
t += deltaT*diff*(2.0*random.random()-1.0)
|
|
|
|
s = t
|
|
|
|
params = {"ident":name, "disco":t, "arriv":s, "parent":parent, "diff":diff}
|
2018-02-08 20:06:01 +00:00
|
|
|
newBlock = Block(params)
|
|
|
|
nelly.updateBlockchain({newBlock.ident:newBlock})
|
2018-02-09 00:04:13 +00:00
|
|
|
parent = name
|
2018-02-08 20:06:01 +00:00
|
|
|
|
|
|
|
|
2018-02-09 00:04:13 +00:00
|
|
|
while len(nelly.data["blockchain"].blocks) < 5000:
|
|
|
|
name = newIdent(len(nelly.data["blockchain"].blocks))
|
|
|
|
diff = nelly.data["blockchain"].diff
|
|
|
|
t += deltaT*diff
|
|
|
|
s = t
|
|
|
|
params = {"ident":name, "disco":t, "arriv":s, "parent":parent, "diff":diff}
|
2018-02-08 20:06:01 +00:00
|
|
|
newBlock = Block(params)
|
|
|
|
nelly.updateBlockchain({newBlock.ident:newBlock})
|
2018-02-09 00:04:13 +00:00
|
|
|
parent = name
|
2018-02-02 00:36:30 +00:00
|
|
|
|
2018-02-09 00:04:13 +00:00
|
|
|
#suite = unittest.TestLoader().loadTestsFromTestCase(Test_Node)
|
|
|
|
#unittest.TextTestRunner(verbosity=1).run(suite)
|
2018-02-02 00:36:30 +00:00
|
|
|
|