mirror of
https://github.com/monero-project/research-lab.git
synced 2024-12-22 11:39:32 +00:00
Block and blockchain working, computing fucking difficulty correctly finally
This commit is contained in:
parent
7c8aa16609
commit
f51f35669a
13 changed files with 6752 additions and 130 deletions
|
@ -51,9 +51,49 @@ class Blockchain(object):
|
|||
elif tempCumDiff == maxCumDiff:
|
||||
self.miningIdents.append(ident)
|
||||
#print("leaf ident = ", str(ident), ", and tempCumDiff = ", str(tempCumDiff), " and maxCumDiff = ", str(maxCumDiff))
|
||||
|
||||
assert len(self.miningIdents) > 0
|
||||
|
||||
class Test_Blockchain(unittest.TestCase):
|
||||
def test_addBlock(self):
|
||||
bill = Blockchain([], verbosity=True)
|
||||
|
||||
name = newIdent(0)
|
||||
t = time.time()
|
||||
s = t+random.random()
|
||||
diff = 1.0
|
||||
params = {"ident":name, "disco":t, "arriv":s, "parent":None, "diff":diff}
|
||||
genesis = Block(params)
|
||||
|
||||
self.assertEqual(genesis.ident,name)
|
||||
self.assertEqual(genesis.discoTimestamp,t)
|
||||
self.assertEqual(genesis.arrivTimestamp,s)
|
||||
self.assertTrue(genesis.parent is None)
|
||||
self.assertEqual(genesis.diff,diff)
|
||||
|
||||
bill.addBlock(genesis)
|
||||
|
||||
self.assertTrue(genesis.ident in bill.blocks)
|
||||
self.assertTrue(genesis.ident in bill.leaves)
|
||||
self.assertEqual(len(bill.miningIdents),1)
|
||||
self.assertEqual(genesis.ident, bill.miningIdents[0])
|
||||
self.assertEqual(len(bill.blocks),1)
|
||||
|
||||
name = newIdent(1)
|
||||
t = time.time()
|
||||
s = t+random.random()
|
||||
diff = 1.0
|
||||
params = {"ident":name, "disco":t, "arriv":s, "parent":genesis.ident, "diff":diff}
|
||||
blockA = Block(params)
|
||||
bill.addBlock(blockA)
|
||||
|
||||
self.assertTrue(blockA.ident in bill.blocks)
|
||||
self.assertTrue(blockA.ident in bill.leaves)
|
||||
self.assertTrue(genesis.ident not in bill.leaves)
|
||||
self.assertEqual(len(bill.miningIdents),1)
|
||||
self.assertEqual(blockA.ident, bill.miningIdents[0])
|
||||
self.assertEqual(len(bill.blocks),2)
|
||||
|
||||
|
||||
def test_bc(self):
|
||||
bill = Blockchain([], verbosity=True)
|
||||
|
||||
|
@ -115,7 +155,7 @@ class Test_Blockchain(unittest.TestCase):
|
|||
self.assertTrue(bill.blocks[genesis.ident].parent is None)
|
||||
|
||||
bill.whichLeaf()
|
||||
print(bill.miningIdents)
|
||||
#print(bill.miningIdents)
|
||||
|
||||
self.assertEqual(type(bill.miningIdents), type([]))
|
||||
self.assertTrue(len(bill.miningIdents), 2)
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
from Blockchain import *
|
||||
import copy
|
||||
|
||||
class Node(object):
|
||||
'''
|
||||
|
@ -17,12 +18,9 @@ class Node(object):
|
|||
self.edges = {}
|
||||
|
||||
def updateBlockchain(self, incBlocks, diffUpdateRate=1, mode="Nakamoto", targetRate=1.0/1209600.0):
|
||||
# dataToUpdate shall be a dictionary of block identities (as keys) and their associated blocks (as values)
|
||||
# incBlocks shall be a dictionary of block identities (as keys) and their associated blocks (as values)
|
||||
# to be added to the local data. We assume difficulty scores have been reported honestly for now.
|
||||
|
||||
# Stash a copy of incoming blocks so removing keys won't shrink the size of the dictionary over which
|
||||
# we are looping.
|
||||
|
||||
if self.verbose:
|
||||
print("\t\t Updating blockchain.")
|
||||
|
||||
|
@ -36,18 +34,19 @@ class Node(object):
|
|||
if self.verbose:
|
||||
print("\t\t Now tempData has " + str(len(tempData)) + " entries.")
|
||||
|
||||
for key in incBlocks.blocks:
|
||||
for key in incBlocks:
|
||||
if key in self.data["blockchain"].blocks:
|
||||
del tempData[key]
|
||||
elif incBlocks.blocks[key].parent in self.data["blockchain"].blocks or incBlocks[key].parent is None:
|
||||
self.data["blockchain"].addBlock(incBlocks.blocks[key])
|
||||
elif incBlocks[key].parent in self.data["blockchain"].blocks or incBlocks[key].parent is None:
|
||||
self.data["blockchain"].addBlock(incBlocks[key])
|
||||
self.data["blockchain"].whichLeaf()
|
||||
#if len(self.data["blockchain"]) % diffUpdateRate == 0:
|
||||
# self.updateDifficulty(mode, targetRate)
|
||||
del tempData[key]
|
||||
incBlocks = copy.deepcopy(tempData)
|
||||
|
||||
if self.verbose:
|
||||
print("\t\t Now incBlocks has " + str(len(incBlocks.blocks)) + " entries.")
|
||||
print("\t\t Now incBlocks has " + str(len(incBlocks)) + " entries.")
|
||||
|
||||
if self.verbose:
|
||||
print("\t\tRemaining steps (while loop)")
|
||||
|
@ -58,8 +57,9 @@ class Node(object):
|
|||
for key in incBlocks:
|
||||
if key in self.data["blockchain"].blocks:
|
||||
del tempData[key]
|
||||
elif incBlocks.blocks[key].parent in self.data["blockchain"].blocks:
|
||||
self.data["blockchain"].addBlock(incBlocks.blocks[key])
|
||||
elif incBlocks[key].parent in self.data["blockchain"].blocks:
|
||||
self.data["blockchain"].addBlock(incBlocks[key])
|
||||
self.data["blockchain"].whichLeaf()
|
||||
del tempData[key]
|
||||
incBlocks = copy.deepcopy(tempData)
|
||||
if self.verbose:
|
||||
|
@ -71,9 +71,15 @@ class Node(object):
|
|||
# Note for default, targetRate = two weeks/period, seven days/week, 24 hours/day, 60 minutes/hour, 60 seconds/minute) = 1209600 seconds/period
|
||||
if mode=="Nakamoto":
|
||||
# Use MLE estimate of poisson process, compare to targetRate, update by multiplying by resulting ratio.
|
||||
if self.verbose:
|
||||
print("Beginning update of difficulty with Nakamoto method")
|
||||
count = 2016
|
||||
bc = self.data["blockchain"]
|
||||
ident = bc.miningIdent
|
||||
if self.verbose:
|
||||
print("Checking that blockchain is 2016*n blocks long and some mining identity has been set")
|
||||
if len(bc.blocks) % 2016 == 0 and len(bc.miningIdents) > 0:
|
||||
|
||||
ident = random.choice(bc.miningIdents)
|
||||
topTime = copy.deepcopy(bc.blocks[ident].discoTimestamp)
|
||||
parent = bc.blocks[ident].parent
|
||||
count = count - 1
|
||||
|
@ -89,11 +95,17 @@ class Node(object):
|
|||
botTime = copy.deepcopy(bc.blocks[ident].discoTimestamp)
|
||||
|
||||
# Algebra is okay:
|
||||
assert 0 <= 2016 - count and 2016 - count < 2017
|
||||
assert topTime != botTime
|
||||
|
||||
# MLE estimate of arrivals per second:
|
||||
mleDiscoRate = float(2016 - count)/float(topTime - botTime)
|
||||
mleDiscoRate = float(2015)/float(topTime - botTime)
|
||||
|
||||
# Rates can't be negative, but this estimate could be (although it's highly unlikely given Bitcoin's standard choices
|
||||
# of difficulty update rate, etc.
|
||||
mleDiscoRate = abs(mleDiscoRate)
|
||||
|
||||
if self.verbose:
|
||||
print("MLE disco rate = " + str(mleDiscoRate) + " and targetRate = " + str(targetRate))
|
||||
# Rate must be positive... so the MLE for block arrival rate
|
||||
# assuming a Poisson process _is not even well-defined_ as
|
||||
# an estimate for block arrival rate assuming timestamps are
|
||||
|
@ -101,38 +113,66 @@ class Node(object):
|
|||
|
||||
# We use it nonetheless.
|
||||
|
||||
# How much should difficulty change?
|
||||
self.diff = self.diff*(mleDiscoRate/targetRate)
|
||||
if self.verbose:
|
||||
print("MLE discovery rate = " + str(mleDiscoRate))
|
||||
print("Difficulty before adjustment = " + str(self.diff))
|
||||
|
||||
# Update difficulty multiplicatively
|
||||
self.diff = self.diff*mleDiscoRate/targetRate
|
||||
|
||||
if self.verbose:
|
||||
print("Difficulty after adjustment = ", str(self.diff))
|
||||
|
||||
elif mode=="vanSaberhagen":
|
||||
# Similar to above, except use 1200 blocks, discard top 120 and bottom 120 after sorting.
|
||||
# 4 minute blocks in the original cryptonote, I believe... targetRate = 1.0/
|
||||
# 4 minutes/period, 60 seconds/minute ~ 240 seconds/period
|
||||
assert targetRate==1.0/240.0
|
||||
# assert targetRate==1.0/240.0
|
||||
count = 1200
|
||||
ident = self.data.miningIdent
|
||||
bc = self.data["blockchain"]
|
||||
bc.whichLeaf()
|
||||
assert self.diff != 0.0
|
||||
if len(bc.blocks) > 120:
|
||||
assert type(bc.miningIdents)==type([])
|
||||
assert len(bc.miningIdents) > 0
|
||||
ident = random.choice(bc.miningIdents)
|
||||
bl = []
|
||||
bl.append(copy.deepcopy(self.data.blocks[ident].discoTimestamp))
|
||||
parent = self.data.blocks[ident].parent
|
||||
bl.append(copy.deepcopy(bc.blocks[ident].discoTimestamp))
|
||||
parent = bc.blocks[ident].parent
|
||||
count = count - 1
|
||||
while count > 0 and parent is not NOne:
|
||||
while count > 0 and parent is not None:
|
||||
ident = copy.deepcopy(parent)
|
||||
bl.append(copy.deepcopy(self.data.blocks[ident].discoTimestamp))
|
||||
parent = self.data.blocks[ident].parent
|
||||
bl.append(copy.deepcopy(bc.blocks[ident].discoTimestamp))
|
||||
parent = bc.blocks[ident].parent
|
||||
count = count-1
|
||||
# sort
|
||||
bl = sorted(bl)
|
||||
assert len(bl)<=1200
|
||||
|
||||
#print("Sample size = " + str(len(bl)))
|
||||
# remove 10 and 90 %-iles
|
||||
numOutliers = round(len(bl)/5)//2
|
||||
assert numOutliers <= 120
|
||||
#print("Number of outliers = " + str(numOutliers))
|
||||
if numOutliers > 0:
|
||||
bl = bl[numOutliers:-numOutliers]
|
||||
#print("New Sample Size = " + str(len(bl)))
|
||||
|
||||
# remove outliers
|
||||
bl = bl[120:-120]
|
||||
|
||||
# get topTime and botTime
|
||||
if self.verbose:
|
||||
print("bl[0] = " + str(bl[0]) + ",\tbl[-1] = " + str(bl[-1]))
|
||||
topTime = bl[-1]
|
||||
botTime = bl[0]
|
||||
if self.verbose:
|
||||
print("list of timestamps = " + str(bl))
|
||||
print("topTime = " + str(bl[-1]))
|
||||
print("botTime = " + str(bl[0]))
|
||||
|
||||
# Assert algebra will work
|
||||
assert 0 <= 960 - count and 960 - count < 961
|
||||
assert topTime > botTime
|
||||
# 1200 - 2*120 = 1200 - 240 = 960
|
||||
assert 0 < len(bl) and len(bl) < 961
|
||||
assert topTime - botTime >= 0.0
|
||||
|
||||
# Sort of the MLE: # blocks/difference in reported times
|
||||
# But not the MLE, since the reported times may not be
|
||||
|
@ -158,20 +198,26 @@ class Node(object):
|
|||
# lambda ~ (1.0/(stdev))*(2/skewness)**(1.0/3.0)
|
||||
assert targetRate==1.0/120.0
|
||||
count = 1200
|
||||
ident = self.data.miningIdent
|
||||
bc = self.data["blockchain"]
|
||||
if len(bc.miningIdents) > 0:
|
||||
ident = random.choice(bc.miningIdents)
|
||||
|
||||
bl = []
|
||||
bl.append(copy.deepcopy(self.data.blocks[ident].discoTimestamp))
|
||||
parent = self.data.blocks[ident].parent
|
||||
bl.append(copy.deepcopy(bc.blocks[ident].discoTimestamp))
|
||||
parent = bc.blocks[ident].parent
|
||||
count = count - 1
|
||||
while count > 0 and parent is not NOne:
|
||||
while count > 0 and parent is not None:
|
||||
ident = copy.deepcopy(parent)
|
||||
bl.append(copy.deepcopy(self.data.blocks[ident].discoTimestamp))
|
||||
parent = self.data.blocks[ident].parent
|
||||
bl.append(copy.deepcopy(bc.blocks[ident].discoTimestamp))
|
||||
parent = bc.blocks[ident].parent
|
||||
count = count-1
|
||||
if len(bl) > 120:
|
||||
sk = skew(bl)
|
||||
va = var(bl)
|
||||
stdv = sqrt(va)
|
||||
lam = (1.0/stdv)*(2.0/sk)**(1.0/3.0)
|
||||
else:
|
||||
lam = targetRate # we will not change difficulty unless we have at least 120 blocks of data (arbitrarily selected)
|
||||
self.diff = self.diff*(lam/targetRate)
|
||||
else:
|
||||
print("Error, invalid difficulty mode entered.")
|
||||
|
@ -193,77 +239,701 @@ class Node(object):
|
|||
|
||||
|
||||
class Test_Node(unittest.TestCase):
|
||||
def test_node(self):
|
||||
verbose = True
|
||||
nellyIdent = newIdent(0)
|
||||
bill = Blockchain([], verbosity=verbose)
|
||||
# TODO test each method separately
|
||||
'''def test_nakamoto(self):
|
||||
print("Beginning test of Nakamoto difficulty adjustment")
|
||||
print("Setting initial values")
|
||||
target = 100.0 # rate = blocks/s
|
||||
verbose = False
|
||||
deltaT = 1.0/target # forced wait time
|
||||
arrivalList = []
|
||||
mode="Nakamoto"
|
||||
|
||||
print("Generating node")
|
||||
nellyIdent = newIdent(0)
|
||||
offset = random.random()
|
||||
intensity = random.random()
|
||||
|
||||
print("Generating initial blockchain")
|
||||
# Create a new initial blockchain object
|
||||
bill = Blockchain([], verbosity=verbose)
|
||||
name = newIdent(0)
|
||||
t = time.time()
|
||||
s = t+1
|
||||
t += offset
|
||||
arrivalList.append(t)
|
||||
s = t+random.random()
|
||||
diff = 1.0
|
||||
oldDiff = copy.deepcopy(diff)
|
||||
params = {"ident":name, "disco":t, "arriv":s, "parent":None, "diff":diff}
|
||||
genesis = Block(params)
|
||||
print("Adding block")
|
||||
bill.addBlock(genesis)
|
||||
bill.whichLeaf()
|
||||
|
||||
# Check that it consists only of the genesis block
|
||||
self.assertTrue(len(bill.blocks)==1)
|
||||
self.assertTrue(genesis.ident in bill.blocks)
|
||||
self.assertTrue(genesis.parent is None)
|
||||
|
||||
print("Finish creating node")
|
||||
# Create node with this blockchain.
|
||||
nodeData = {"blockchain":bill, "intensity":intensity, "offset":offset}
|
||||
params = {"ident":nellyIdent, "data":nodeData, "diff":diff, "verbose":verbose}
|
||||
nelly = Node(params)
|
||||
|
||||
# Check node creation worked
|
||||
self.assertEqual(nelly.ident, nellyIdent)
|
||||
self.assertEqual(nelly.data["blockchain"], bill)
|
||||
self.assertEqual(nelly.diff, diff)
|
||||
self.assertEqual(nelly.data["intensity"], intensity)
|
||||
self.assertEqual(nelly.data["offset"], offset)
|
||||
|
||||
# Sleep and add a block on top of genesis
|
||||
if verbose:
|
||||
print("sleeping")
|
||||
time.sleep(deltaT)
|
||||
|
||||
print("Giving genesis block a child")
|
||||
name = newIdent(1)
|
||||
t = time.time()
|
||||
t += nelly.data["offset"]
|
||||
arrivalList.append(t)
|
||||
s = t+random.random()
|
||||
diff = oldDiff
|
||||
params = {"ident":name, "disco":t, "arriv":s, "parent":genesis.ident, "diff":diff}
|
||||
blockA = Block(params)
|
||||
nelly.updateBlockchain({blockA.ident:blockA})
|
||||
oldIdent = blockA.ident
|
||||
|
||||
# Check this worked
|
||||
self.assertEqual(len(nelly.data["blockchain"].blocks),2)
|
||||
self.assertTrue(blockA.ident in nelly.data["blockchain"].blocks)
|
||||
self.assertTrue(genesis.ident in nelly.data["blockchain"].blocks)
|
||||
self.assertEqual(genesis.ident, nelly.data["blockchain"].blocks[blockA.ident].parent)
|
||||
|
||||
print("Updating difficulty")
|
||||
# Update the difficulty score
|
||||
nelly.updateDifficulty(mode, targetRate = target) # With only two blocks, nothing should change.
|
||||
self.assertEqual(nelly.diff, oldDiff)
|
||||
|
||||
# Print regardless of verbosity:
|
||||
print("Now generating first difficulty adjustment period.")
|
||||
|
||||
# Now we are going to fast forward to right before the first difficulty adjustment.
|
||||
N = len(nelly.data["blockchain"].blocks)
|
||||
while(N < 2015):
|
||||
if N % 100 == 0:
|
||||
print("\tN=" + str(N))
|
||||
name = newIdent(N)
|
||||
t = time.time()
|
||||
t += nelly.data["offset"]
|
||||
arrivalList.append(t)
|
||||
s = t+random.random()
|
||||
diff = nelly.diff
|
||||
oldDiff = diff
|
||||
params = {"ident":name, "disco":t, "arriv":s, "parent":oldIdent, "diff":diff}
|
||||
oldIdent = copy.deepcopy(name)
|
||||
block = Block(params)
|
||||
nelly.updateBlockchain({block.ident:block})
|
||||
|
||||
# Check this worked
|
||||
self.assertEqual(len(nelly.data["blockchain"].blocks),N+1)
|
||||
self.assertTrue(block.ident in nelly.data["blockchain"].blocks)
|
||||
|
||||
# Update the difficulty score
|
||||
nelly.updateDifficulty(mode, targetRate = target) # With N < 2016, nothing should change.
|
||||
self.assertEqual(nelly.diff, oldDiff)
|
||||
N = len(nelly.data["blockchain"].blocks)
|
||||
time.sleep(deltaT)
|
||||
|
||||
name = newIdent(N)
|
||||
t = time.time()
|
||||
t += nelly.data["offset"]
|
||||
arrivalList.append(t)
|
||||
s = t+random.random()
|
||||
diff = oldDiff
|
||||
params = {"ident":name, "disco":t, "arriv":s, "parent":oldIdent, "diff":diff}
|
||||
block = Block(params)
|
||||
nelly.updateBlockchain({block.ident:block})
|
||||
|
||||
# Check this worked
|
||||
self.assertEqual(len(nelly.data["blockchain"].blocks),N+1)
|
||||
self.assertTrue(block.ident in nelly.data["blockchain"].blocks)
|
||||
|
||||
# Update the difficulty score
|
||||
nelly.updateDifficulty(mode, targetRate = target) # With N < 2016, nothing should change.
|
||||
# Note: 2016 blocks is 2015 block inter-arrival times.
|
||||
expRatioNumerator = float(2015)/(arrivalList[-1] - arrivalList[-2016])
|
||||
expRatio = expRatioNumerator/target
|
||||
expDiff = oldDiff*expRatio
|
||||
self.assertEqual(nelly.diff, expDiff)
|
||||
|
||||
# The following should fail, because our sample size is incorrect.
|
||||
expRatioNumerator = float(2016)/(arrivalList[-1] - arrivalList[-2016])
|
||||
expRatio = expRatioNumerator/target
|
||||
expDiff = oldDiff*expRatio
|
||||
self.assertFalse(nelly.diff - expDiff == 0.0)
|
||||
|
||||
|
||||
# Print regardless of verbosity:
|
||||
print("Now generating second difficulty adjustment period.")
|
||||
|
||||
# Now we are going to fast forward to right before the next difficulty adjustment.
|
||||
# This time, though, we are going to re-set the block inter-arrival time deltaT
|
||||
# to half. This should drive difficulty up.
|
||||
lastDifficultyScore = copy.deepcopy(nelly.diff)
|
||||
N = len(nelly.data["blockchain"].blocks)
|
||||
while(N < 4031):
|
||||
if N % 100 == 0:
|
||||
print("\tN=" + str(N))
|
||||
name = newIdent(N)
|
||||
t = time.time()
|
||||
t += nelly.data["offset"]
|
||||
arrivalList.append(t)
|
||||
s = t+random.random()
|
||||
diff = nelly.diff
|
||||
oldDiff = diff
|
||||
params = {"ident":name, "disco":t, "arriv":s, "parent":oldIdent, "diff":diff}
|
||||
oldIdent = copy.deepcopy(name)
|
||||
block = Block(params)
|
||||
nelly.updateBlockchain({block.ident:block})
|
||||
|
||||
# Check this worked
|
||||
self.assertEqual(len(nelly.data["blockchain"].blocks),N+1)
|
||||
self.assertTrue(block.ident in nelly.data["blockchain"].blocks)
|
||||
|
||||
# Update the difficulty score
|
||||
nelly.updateDifficulty(mode, targetRate = target) # With N < 2016, nothing should change.
|
||||
self.assertEqual(nelly.diff, oldDiff)
|
||||
N = len(nelly.data["blockchain"].blocks)
|
||||
time.sleep(0.01*deltaT)
|
||||
|
||||
# Now if we add a single new block, we should trigger difficulty adjustment.
|
||||
name = newIdent(N)
|
||||
t = time.time()
|
||||
t += nelly.data["offset"]
|
||||
arrivalList.append(t)
|
||||
s = t+random.random()
|
||||
diff = oldDiff
|
||||
params = {"ident":name, "disco":t, "arriv":s, "parent":oldIdent, "diff":diff}
|
||||
block = Block(params)
|
||||
nelly.updateBlockchain({block.ident:block})
|
||||
|
||||
# Check this worked
|
||||
self.assertEqual(len(nelly.data["blockchain"].blocks),N+1)
|
||||
self.assertTrue(block.ident in nelly.data["blockchain"].blocks)
|
||||
|
||||
# Update the difficulty score.
|
||||
nelly.updateDifficulty(mode, targetRate = target)
|
||||
expRatioNumerator = float(2015)/(arrivalList[-1] - arrivalList[-2016])
|
||||
expRatio = expRatioNumerator/target
|
||||
expDiff = oldDiff*expRatio
|
||||
print("expRatio = " + str(expRatio) + ", lastDifficultyScore = " + str(lastDifficultyScore) + ", new difficulty = " + str(nelly.diff))
|
||||
self.assertEqual(nelly.diff, expDiff)
|
||||
'''
|
||||
|
||||
|
||||
|
||||
|
||||
def test_vs(self):
|
||||
print("Beginning test of vanSaberhagen difficulty adjustment.")
|
||||
print("Setting initial values")
|
||||
target = 10.0 # 1.0/240.0 # rate = blocks/s
|
||||
verbose = False
|
||||
deltaT = 1.0/target # forced wait time
|
||||
arrivalList = []
|
||||
mode="vanSaberhagen"
|
||||
|
||||
print("Instantiating new node")
|
||||
nellyIdent = newIdent(0)
|
||||
offset = random.random()
|
||||
intensity = random.random()
|
||||
|
||||
print("Creating new blockchain for new node")
|
||||
# Create a new initial blockchain object
|
||||
bill = Blockchain([], verbosity=verbose)
|
||||
name = newIdent(0)
|
||||
t = time.time()
|
||||
t += offset
|
||||
arrivalList.append(t)
|
||||
s = t+random.random()
|
||||
diff = 1.0
|
||||
params = {"ident":name, "disco":t, "arriv":s, "parent":None, "diff":diff}
|
||||
genesis = Block(params)
|
||||
print("Adding genesis block")
|
||||
bill.addBlock(genesis)
|
||||
bill.whichLeaf()
|
||||
|
||||
time.sleep(10)
|
||||
# Check that it consists only of the genesis block
|
||||
self.assertTrue(len(bill.blocks)==1)
|
||||
self.assertTrue(genesis.ident in bill.blocks)
|
||||
self.assertTrue(genesis.parent is None)
|
||||
self.assertTrue(genesis.ident in bill.leaves)
|
||||
|
||||
print("Making node")
|
||||
# Create node with this blockchain.
|
||||
nodeData = {"blockchain":bill, "intensity":intensity, "offset":offset}
|
||||
params = {"ident":nellyIdent, "data":nodeData, "diff":diff, "verbose":verbose}
|
||||
nelly = Node(params)
|
||||
|
||||
# Check node creation worked
|
||||
self.assertEqual(nelly.ident, nellyIdent)
|
||||
self.assertEqual(nelly.data["blockchain"], bill)
|
||||
self.assertEqual(nelly.diff, diff)
|
||||
self.assertEqual(nelly.data["intensity"], intensity)
|
||||
self.assertEqual(nelly.data["offset"], offset)
|
||||
|
||||
# Sleep and add a block on top of genesis
|
||||
if verbose:
|
||||
print("sleeping")
|
||||
time.sleep(deltaT)
|
||||
|
||||
print("Give genesis a child")
|
||||
name = newIdent(1)
|
||||
t = time.time()
|
||||
s = t+1
|
||||
diff = 1.0
|
||||
t += nelly.data["offset"]
|
||||
arrivalList.append(t)
|
||||
s = t+random.random()
|
||||
oldDiff = copy.deepcopy(diff)
|
||||
diff = copy.deepcopy(nelly.diff)
|
||||
assert diff != 0.0
|
||||
params = {"ident":name, "disco":t, "arriv":s, "parent":genesis.ident, "diff":diff}
|
||||
blockA = Block(params)
|
||||
bill.addBlock(blockA)
|
||||
nelly.updateBlockchain({blockA.ident:blockA})
|
||||
oldIdent = blockA.ident
|
||||
|
||||
# Nodes need an identity and a blockchain object and verbosity and difficulty
|
||||
nodeData = {"blockchain":bill, "intensity":random.random(), "offset":random.random()}
|
||||
params = {"ident":name, "data":nodeData, "diff":diff, "verbose":verbose}
|
||||
nelly = Node(params)
|
||||
nelly.updateDifficulty(mode="Nakamoto")
|
||||
# Check this worked
|
||||
self.assertEqual(len(nelly.data["blockchain"].blocks),2)
|
||||
self.assertTrue(blockA.ident in nelly.data["blockchain"].blocks)
|
||||
self.assertTrue(genesis.ident in nelly.data["blockchain"].blocks)
|
||||
self.assertEqual(genesis.ident, nelly.data["blockchain"].blocks[blockA.ident].parent)
|
||||
|
||||
time.sleep(9)
|
||||
# Update the difficulty score
|
||||
nelly.updateDifficulty(mode, targetRate = target) # With only two blocks, nothing should change.
|
||||
assert nelly.diff != 0.0
|
||||
self.assertEqual(nelly.diff, oldDiff)
|
||||
self.assertFalse(nelly.diff == -0.0)
|
||||
|
||||
name = newIdent(len(nelly.data))
|
||||
# Print regardless of verbosity:
|
||||
print("Now generating fulls sample size.")
|
||||
|
||||
# Now we are going to fast forward to a "full sample size" period of time.
|
||||
N = len(nelly.data["blockchain"].blocks)
|
||||
while(N < 1200):
|
||||
name = newIdent(N)
|
||||
if N % 100 == 0:
|
||||
print("\tNow adding block N=" + str(N))
|
||||
t = time.time()
|
||||
s = t + 1
|
||||
params = {"ident":name, "disco":t, "arriv":s, "parent":blockA.ident, "diff":diff}
|
||||
blockB = Block(params)
|
||||
nelly.updateBlockchain({blockB.ident:blockB})
|
||||
t += nelly.data["offset"]
|
||||
arrivalList.append(t)
|
||||
s = t+random.random()
|
||||
oldDiff = copy.deepcopy(diff)
|
||||
diff = copy.deepcopy(nelly.diff)
|
||||
assert diff != 0.0
|
||||
params = {"ident":name, "disco":t, "arriv":s, "parent":oldIdent, "diff":diff}
|
||||
oldIdent = copy.deepcopy(name)
|
||||
block = Block(params)
|
||||
nelly.updateBlockchain({block.ident:block})
|
||||
|
||||
time.sleep(8)
|
||||
# Check this worked
|
||||
self.assertEqual(len(nelly.data["blockchain"].blocks),N+1)
|
||||
self.assertTrue(block.ident in nelly.data["blockchain"].blocks)
|
||||
|
||||
name = newIdent(len(nelly.data))
|
||||
# Update the difficulty score
|
||||
nelly.updateDifficulty(mode, targetRate = target) # With N < 100, nothing should change.
|
||||
if N < 100:
|
||||
self.assertEqual(nelly.diff, oldDiff)
|
||||
N = len(nelly.data["blockchain"].blocks)
|
||||
time.sleep(0.5*deltaT)
|
||||
|
||||
print("Adding one more block")
|
||||
name = newIdent(N)
|
||||
t = time.time()
|
||||
s = t + 1
|
||||
params = {"ident":name, "disco":t, "arriv":s, "parent":blockA.ident, "diff":diff}
|
||||
blockC = Block(params)
|
||||
nelly.updateBlockchain({blockC.ident:blockC})
|
||||
t += nelly.data["offset"]
|
||||
arrivalList.append(t)
|
||||
s = t+random.random()
|
||||
oldDiff = diff
|
||||
diff = nelly.diff
|
||||
assert diff != 0.0
|
||||
params = {"ident":name, "disco":t, "arriv":s, "parent":oldIdent, "diff":nelly.diff}
|
||||
block = Block(params)
|
||||
nelly.updateBlockchain({block.ident:block})
|
||||
|
||||
time.sleep(1)
|
||||
name = newIdent(len(nelly.data))
|
||||
# Check this worked
|
||||
self.assertEqual(len(nelly.data["blockchain"].blocks),N+1)
|
||||
self.assertTrue(block.ident in nelly.data["blockchain"].blocks)
|
||||
|
||||
# Update the difficulty score
|
||||
nelly.updateDifficulty(mode, targetRate = target) # With N < 2016, nothing should change.
|
||||
# Note: 2016 blocks is 2015 block inter-arrival times.
|
||||
print(str(arrivalList[-120]) + ", " + str(arrivalList[-1080]) + ", " + str(arrivalList[-120]-arrivalList[-1080]) + ", " + str(float(959)/(arrivalList[-120]-arrivalList[-1080]))+ ", " + str(float(float(959)/(arrivalList[-120]-arrivalList[-1080]))/float(target)))
|
||||
expRatioNumerator = float(959)/(arrivalList[-120] - arrivalList[-1080])
|
||||
expRatio = expRatioNumerator/target
|
||||
print(expRatio)
|
||||
expDiff = oldDiff*expRatio
|
||||
print(expDiff)
|
||||
print("expDiff = " + str(expDiff) + " and nelly.diff = " + str(nelly.diff))
|
||||
self.assertEqual(nelly.diff, expDiff)
|
||||
|
||||
|
||||
# Print regardless of verbosity:
|
||||
print("Now fast forwarding past the tail end of the last period..")
|
||||
# Now we are going to fast forward to right before the next difficulty adjustment.
|
||||
# This time, though, we are going to re-set the block inter-arrival time deltaT
|
||||
# to half. This should drive difficulty up.
|
||||
lastDifficultyScore = copy.deepcopy(nelly.diff)
|
||||
N = len(nelly.data["blockchain"].blocks)
|
||||
while(N < 1700):
|
||||
name = newIdent(N)
|
||||
t = time.time()
|
||||
s = t + 1
|
||||
params = {"ident":name, "disco":t, "arriv":s, "parent":blockC.ident, "diff":diff}
|
||||
blockD = Block(params)
|
||||
nelly.updateBlockchain({blockD.ident:blockD})
|
||||
t += nelly.data["offset"]
|
||||
arrivalList.append(t)
|
||||
s = t+random.random()
|
||||
diff = nelly.diff
|
||||
oldDiff = diff
|
||||
params = {"ident":name, "disco":t, "arriv":s, "parent":oldIdent, "diff":diff}
|
||||
oldIdent = copy.deepcopy(name)
|
||||
block = Block(params)
|
||||
nelly.updateBlockchain({block.ident:block})
|
||||
|
||||
time.sleep(7)
|
||||
name = newIdent(len(nelly.data))
|
||||
# Check this worked
|
||||
self.assertEqual(len(nelly.data["blockchain"].blocks),N+1)
|
||||
self.assertTrue(block.ident in nelly.data["blockchain"].blocks)
|
||||
|
||||
# Update the difficulty score
|
||||
nelly.updateDifficulty(mode, targetRate = target) # With N < 2016, nothing should change.
|
||||
self.assertEqual(nelly.diff, oldDiff)
|
||||
N = len(nelly.data["blockchain"].blocks)
|
||||
time.sleep(0.01*deltaT)
|
||||
|
||||
# Now if we add a single new block, we should trigger difficulty adjustment.
|
||||
name = newIdent(N)
|
||||
t = time.time()
|
||||
s = t + 1
|
||||
params = {"ident":name, "disco":t, "arriv":s, "parent":blockD.ident, "diff":diff}
|
||||
blockE = Block(params)
|
||||
nelly.updateBlockchain({blockE.ident:blockE})
|
||||
t += nelly.data["offset"]
|
||||
arrivalList.append(t)
|
||||
s = t+random.random()
|
||||
diff = oldDiff
|
||||
params = {"ident":name, "disco":t, "arriv":s, "parent":oldIdent, "diff":diff}
|
||||
block = Block(params)
|
||||
nelly.updateBlockchain({block.ident:block})
|
||||
|
||||
# Check this worked
|
||||
self.assertEqual(len(nelly.data["blockchain"].blocks),N+1)
|
||||
self.assertTrue(block.ident in nelly.data["blockchain"].blocks)
|
||||
|
||||
# Update the difficulty score.
|
||||
nelly.updateDifficulty(mode, targetRate = target)
|
||||
expRatioNumerator = float(959)/(arrivalList[-120] - arrivalList[-1080])
|
||||
expRatio = expRatioNumerator/target
|
||||
expDiff = oldDiff*expRatio
|
||||
print("expRatio = " + str(expRatio) + ", lastDifficultyScore = " + str(lastDifficultyScore) + ", new difficulty = " + str(nelly.diff))
|
||||
self.assertEqual(nelly.diff, expDiff)
|
||||
|
||||
|
||||
time.sleep(6)
|
||||
name = newIdent(len(nelly.data))
|
||||
|
||||
def test_modexp(self):
|
||||
pass
|
||||
|
||||
'''# Check this worked
|
||||
if mode == "Nakamoto":
|
||||
# In this case we take simple MLE estimate
|
||||
ratio = 1.0/abs(t1-t)
|
||||
print("Nakamoto mle = " + str(ratio))
|
||||
ratio = ratio/target
|
||||
print("Normalized = " + str(ratio))
|
||||
print("New diff = " + str(ratio*oldDiff))
|
||||
self.assertEqual(nelly.diff, ratio*oldDiff)
|
||||
elif mode == "vanSaberhagen":
|
||||
# In this case, with only 2 blocks, we just use simple MLE again
|
||||
ratio = 1.0/abs(t1-t)
|
||||
ratio = ratio/target
|
||||
self.assertEqual(nelly.diff, ratio*oldDiff)
|
||||
elif mode == "MOM:expModGauss":
|
||||
self.assertEqual(nelly.diff, 1.0)
|
||||
# With at least 120 blocks of data...
|
||||
#sk = skew(bl)
|
||||
#va = var(bl)
|
||||
#stdv = sqrt(va)
|
||||
#lam = (1.0/stdv)*(2.0/sk)**(1.0/3.0)
|
||||
#self.diff = self.diff*(lam/targetRate)
|
||||
# Otherwise, set to 1.0
|
||||
else:
|
||||
print("what world are you living in?")
|
||||
|
||||
if verbose:
|
||||
print("sleeping 1 seconds")
|
||||
time.sleep(deltaT/5.0)
|
||||
|
||||
listOfTimes = [copy.deepcopy(t), copy.deepcopy(t1)]
|
||||
listOfBlocks = []
|
||||
|
||||
N = len(nelly.data["blockchain"].blocks)
|
||||
lastIdent = blockA.ident
|
||||
|
||||
bail = False
|
||||
while N < 10 and not bail:
|
||||
# Generate new block
|
||||
name = newIdent(N)
|
||||
t = time.time()
|
||||
s = t + 1
|
||||
params = {"ident":name, "disco":t, "arriv":s, "parent":blockE.ident, "diff":diff}
|
||||
blockF = Block(params)
|
||||
nelly.updateBlockchain({blockF.ident:blockF})
|
||||
t += nelly.data["offset"]
|
||||
s = t+random.random()
|
||||
oldDiff = copy.deepcopy(nelly.diff)
|
||||
print("Current difficulty = ", oldDiff)
|
||||
params = {"ident":name, "disco":t, "arriv":s, "parent":lastIdent, "diff":oldDiff}
|
||||
newBlock = Block(params)
|
||||
|
||||
# Append new block to running list along with creation time
|
||||
listOfBlocks.append(newBlock)
|
||||
listOfTimes.append(copy.deepcopy(t))
|
||||
|
||||
# Update nelly's blockchain with newBlock
|
||||
nelly.updateBlockchain({newBlock.ident:newBlock})
|
||||
lastIdent = name
|
||||
|
||||
# Quick check that this worked:
|
||||
self.assertTrue(name in nelly.data["blockchain"].blocks)
|
||||
self.assertEqual(len(nelly.data["blockchain"].blocks), N+1)
|
||||
N = len(nelly.data["blockchain"].blocks)
|
||||
|
||||
# Update difficulty
|
||||
nelly.updateDifficulty(mode, targetRate = 100.0)
|
||||
|
||||
# Quick check that this worked:
|
||||
if mode == "Nakamoto":
|
||||
# In this case we take use top block and genesis block
|
||||
ratio = float(len(nelly.data["blockchain"].blocks) - 1)/(listOfTimes[-1] - listOfTimes[0])
|
||||
ratio = ratio / target
|
||||
self.assertEqual(nelly.diff, ratio*oldDiff)
|
||||
print("Hoped for difficulty = " + str(oldDiff*ratio) + ", and computed = " + str(nelly.diff))
|
||||
elif mode == "vanSaberhagen":
|
||||
# This case coincides with nakamoto until block 10
|
||||
ratio = float( len(nelly.data["blockchain"].blocks) - 1)/(listOfTimes[-1] - listOfTimes[0])
|
||||
ratio = ratio / target
|
||||
self.assertEqual(nelly.diff, ratio*oldDiff)
|
||||
elif mode == "MOM:expModGauss":
|
||||
self.assertEqual(nelly.diff, 1.0)
|
||||
# With at least 120 blocks of data...
|
||||
#sk = skew(bl)
|
||||
#va = var(bl)
|
||||
#stdv = sqrt(va)
|
||||
#lam = (1.0/stdv)*(2.0/sk)**(1.0/3.0)
|
||||
#self.diff = self.diff*(lam/targetRate)
|
||||
# Otherwise, set to 1.0
|
||||
else:
|
||||
print("what world are you living in?")
|
||||
|
||||
# Sleep a random time
|
||||
print("Sleeping a random sub-second, working on block " + str(N))
|
||||
deltaT = deltaT*ratio
|
||||
time.sleep(deltaT/5.0)
|
||||
|
||||
while N < 120 and not bail:
|
||||
# Generate new block
|
||||
name = newIdent(N)
|
||||
t = time.time()
|
||||
t += nelly.data["offset"]
|
||||
s = t+random.random()
|
||||
oldDiff = copy.deepcopy(nelly.diff)
|
||||
params = {"ident":name, "disco":t, "arriv":s, "parent":lastIdent, "diff":oldDiff}
|
||||
newBlock = Block(params)
|
||||
|
||||
# Append new block to running list along with creation time
|
||||
listOfBlocks.append(newBlock)
|
||||
listOfTimes.append(copy.deepcopy(t))
|
||||
|
||||
# Update nelly's blockchain with newBlock
|
||||
nelly.updateBlockchain({newBlock.ident:newBlock})
|
||||
lastIdent = name
|
||||
|
||||
# Quick check that this worked:
|
||||
self.assertTrue(name in nelly.data["blockchain"].blocks)
|
||||
self.assertEqual(len(nelly.data["blockchain"].blocks), N+1)
|
||||
N = len(nelly.data["blockchain"].blocks)
|
||||
|
||||
# Update difficulty
|
||||
nelly.updateDifficulty(mode, targetRate = 100.0)
|
||||
|
||||
# Quick check that this worked:
|
||||
if mode == "Nakamoto":
|
||||
# In this case we take use top block and genesis block
|
||||
ratio = float(len(nelly.data["blockchain"].blocks)-1)/(listOfTimes[-1] - listOfTimes[0])
|
||||
ratio = ratio / target
|
||||
self.assertEqual(nelly.diff, oldDiff*ratio)
|
||||
print("Hoped for difficulty = " + str(oldDiff*ratio) + ", and computed = " + str(nelly.diff))
|
||||
elif mode == "vanSaberhagen":
|
||||
# This case no longer coincides with Nakamoto...
|
||||
numOutliers = len(nelly.data["blockchain"].blocks)//10
|
||||
numOutliers = min(numOutliers, 120)
|
||||
ratio = float(len(nelly.data["blockchain"].blocks) - 2*numOutliers - 1)/(listOfTimes[-numOutliers] - listOfTimes[numOutliers])
|
||||
ratio = ratio / target
|
||||
self.assertEqual(nelly.diff, oldDiff*ratio)
|
||||
elif mode == "MOM:expModGauss":
|
||||
# With at least 120 blocks of data...
|
||||
count = 1200
|
||||
bl = []
|
||||
bl.append(copy.deepcopy(bc.blocks[lastIdent].discoTimestamp))
|
||||
parent = bc.blocks[lastIdent].parent
|
||||
count = count - 1
|
||||
while count > 0 and parent is not None:
|
||||
ident = copy.deepcopy(parent)
|
||||
bl.append(copy.deepcopy(bc.blocks[ident].discoTimestamp))
|
||||
parent = bc.blocks[ident].parent
|
||||
count = count-1
|
||||
if len(bl) > 120:
|
||||
sk = skew(bl)
|
||||
va = var(bl)
|
||||
stdv = sqrt(va)
|
||||
lam = (1.0/stdv)*(2.0/sk)**(1.0/3.0)
|
||||
else:
|
||||
lam = target
|
||||
ratio = lam/target
|
||||
self.assertEqual(nelly.diff, oldDiff*ratio)
|
||||
|
||||
else:
|
||||
print("what world are you living in?")
|
||||
|
||||
# Sleep a random time
|
||||
print("Sleeping a random sub-second, working on block " + str(N))
|
||||
deltaT = deltaT*ratio
|
||||
time.sleep(deltaT/5.0)
|
||||
|
||||
while N < 2400 and not bail:
|
||||
# Generate new block
|
||||
name = newIdent(N)
|
||||
t = time.time()
|
||||
t += nelly.data["offset"]
|
||||
s = t+random.random()
|
||||
oldDiff = copy.deepcopy(nelly.diff)
|
||||
params = {"ident":name, "disco":t, "arriv":s, "parent":lastIdent, "diff":oldDiff}
|
||||
newBlock = Block(params)
|
||||
|
||||
# Append new block to running list along with creation time
|
||||
listOfBlocks.append(newBlock)
|
||||
listOfTimes.append(copy.deepcopy(t))
|
||||
|
||||
# Update nelly's blockchain with newBlock
|
||||
nelly.updateBlockchain({newBlock.ident:newBlock})
|
||||
lastIdent = name
|
||||
|
||||
# Quick check that this worked:
|
||||
self.assertTrue(name in nelly.data["blockchain"].blocks)
|
||||
self.assertEqual(len(nelly.data["blockchain"].blocks), N+1)
|
||||
N = len(nelly.data["blockchain"].blocks)
|
||||
|
||||
# Update difficulty
|
||||
nelly.updateDifficulty(mode, targetRate = 100.0)
|
||||
|
||||
# Quick check that this worked:
|
||||
if mode == "Nakamoto":
|
||||
# In this case we take use top block and genesis block
|
||||
ratio = float(len(nelly.data["blockchain"].blocks)-1)/(listOfTimes[-1] - listOfTimes[0])
|
||||
ratio = ratio / target
|
||||
self.assertEqual(nelly.diff, oldDiff*ratio)
|
||||
print("Hoped for difficulty = " + str(oldDiff*ratio) + ", and computed = " + str(nelly.diff))
|
||||
elif mode == "vanSaberhagen":
|
||||
# This case no longer coincides with Nakamoto...
|
||||
numOutliers = len(nelly.data["blockchain"].blocks)//10
|
||||
numOutliers = min(numOutliers, 120)
|
||||
ratio = float(len(nelly.data["blockchain"].blocks) - 2*numOutliers - 1)/(listOfTimes[-numOutliers] - listOfTimes[numOutliers])
|
||||
ratio = ratio / target
|
||||
self.assertEqual(nelly.diff, ratio*oldDiff)
|
||||
elif mode == "MOM:expModGauss":
|
||||
# With at least 120 blocks of data...
|
||||
count = 1200
|
||||
bl = []
|
||||
bl.append(copy.deepcopy(bc.blocks[lastIdent].discoTimestamp))
|
||||
parent = bc.blocks[lastIdent].parent
|
||||
count = count - 1
|
||||
while count > 0 and parent is not None:
|
||||
ident = copy.deepcopy(parent)
|
||||
bl.append(copy.deepcopy(bc.blocks[ident].discoTimestamp))
|
||||
parent = bc.blocks[ident].parent
|
||||
count = count-1
|
||||
if len(bl) > 120:
|
||||
sk = skew(bl)
|
||||
va = var(bl)
|
||||
stdv = sqrt(va)
|
||||
lam = (1.0/stdv)*(2.0/sk)**(1.0/3.0)
|
||||
else:
|
||||
lam = targetRate
|
||||
ratio = lam/targetRate
|
||||
self.assertEqual(nelly.diff, ratio*oldDiff)
|
||||
|
||||
else:
|
||||
print("what world are you living in?")
|
||||
|
||||
# Sleep a random time
|
||||
print("Sleeping a random sub-second, working on block " + str(N))
|
||||
deltaT = deltaT*ratio
|
||||
time.sleep(deltaT/5.0)
|
||||
|
||||
|
||||
while N < 3600 and not bail:
|
||||
# Generate new block
|
||||
name = newIdent(N)
|
||||
t = time.time()
|
||||
t += nelly.data["offset"]
|
||||
s = t+random.random()
|
||||
oldDiff = nelly.diff
|
||||
params = {"ident":name, "disco":t, "arriv":s, "parent":lastIdent, "diff":oldDiff}
|
||||
newBlock = Block(params)
|
||||
|
||||
# Append new block to running list along with creation time
|
||||
listOfBlocks.append(newBlock)
|
||||
listOfTimes.append(copy.deepcopy(t))
|
||||
|
||||
# Update nelly's blockchain with newBlock
|
||||
nelly.updateBlockchain({newBlock.ident:newBlock})
|
||||
lastIdent = name
|
||||
|
||||
# Quick check that this worked:
|
||||
self.assertTrue(name in nelly.data["blockchain"].blocks)
|
||||
self.assertEqual(len(nelly.data["blockchain"].blocks), N+1)
|
||||
N = len(nelly.data["blockchain"].blocks)
|
||||
|
||||
# Update difficulty
|
||||
nelly.updateDifficulty(mode, targetRate = 100.0)
|
||||
|
||||
# Quick check that this worked:
|
||||
if mode == "Nakamoto":
|
||||
# In this case we take use top block and genesis block
|
||||
ratio = float(2400)/(listOfTimes[-1] - listOfTimes[-2400])
|
||||
self.assertEqual(nelly.diff, ratio*oldDiff)
|
||||
elif mode == "vanSaberhagen":
|
||||
# This case no longer coincides with Nakamoto...
|
||||
numOutliers = len(nelly.data["blockchain"].blocks)//10
|
||||
numOutliers = min(numOutliers, 120)
|
||||
ratio = float(len(nelly.data["blockchain"].blocks) - 2*numOutliers)/(listOfTimes[-numOutliers] - listOfTimes[numOutliers])
|
||||
self.assertEqual(nelly.diff, ratio*oldDiff)
|
||||
elif mode == "MOM:expModGauss":
|
||||
# With at least 120 blocks of data...
|
||||
count = 1200
|
||||
bl = []
|
||||
bl.append(copy.deepcopy(bc.blocks[lastIdent].discoTimestamp))
|
||||
parent = bc.blocks[lastIdent].parent
|
||||
count = count - 1
|
||||
while count > 0 and parent is not None:
|
||||
ident = copy.deepcopy(parent)
|
||||
bl.append(copy.deepcopy(bc.blocks[ident].discoTimestamp))
|
||||
parent = bc.blocks[ident].parent
|
||||
count = count-1
|
||||
if len(bl) > 120:
|
||||
sk = skew(bl)
|
||||
va = var(bl)
|
||||
stdv = sqrt(va)
|
||||
lam = (1.0/stdv)*(2.0/sk)**(1.0/3.0)
|
||||
else:
|
||||
lam = targetRate
|
||||
ratio = lam/targetRate
|
||||
self.assertEqual(nelly.diff, ratio*oldDiff)
|
||||
|
||||
else:
|
||||
print("what world are you living in?")
|
||||
|
||||
# Sleep a random time
|
||||
print("Sleeping a random sub-second, working on block " + str(N))
|
||||
deltaT = deltaT*ratio
|
||||
time.sleep(deltaT/5.0)'''
|
||||
|
||||
|
||||
suite = unittest.TestLoader().loadTestsFromTestCase(Test_Node)
|
||||
|
|
46
source-code/Poisson-Graphs/new/Block.py
Normal file
46
source-code/Poisson-Graphs/new/Block.py
Normal file
|
@ -0,0 +1,46 @@
|
|||
import unittest, random, time
|
||||
|
||||
def newIdent(params):
|
||||
nonce = params
|
||||
# Generate new random identity.
|
||||
return hash(str(nonce) + str(random.random()))
|
||||
#### #### #### #### #### #### #### #### #### #### #### #### #### #### #### ####
|
||||
class Block(object):
|
||||
'''
|
||||
Each block has: an identity, a timestamp of discovery (possibly false),
|
||||
has a timestamp of arrival at the local node (possibly unnecessary), a
|
||||
parent block's identity, and a difficulty score.
|
||||
'''
|
||||
def __init__(self, params={}):
|
||||
self.ident = None
|
||||
self.discoTimestamp = None
|
||||
self.arrivTimestamp = None
|
||||
self.parent = None
|
||||
self.diff = None
|
||||
try:
|
||||
assert len(params)==5
|
||||
except AssertionError:
|
||||
print("Error in Block(): Tried to add a malformed block. We received params = " + str(params) + ", but should have had something of the form {\"ident\":ident, \"disco\":disco, \"arriv\":arriv, \"parent\":parent, \"diff\":diff}.")
|
||||
self.ident = params["ident"]
|
||||
self.discoTimestamp = params["disco"]
|
||||
self.arrivTimestamp = params["arriv"]
|
||||
self.parent = params["parent"]
|
||||
self.diff = params["diff"]
|
||||
|
||||
class Test_Block(unittest.TestCase):
|
||||
def test_b(self):
|
||||
#bill = Block()
|
||||
name = newIdent(0)
|
||||
t = time.time()
|
||||
s = t+1
|
||||
diff = 1.0
|
||||
params = {"ident":name, "disco":t, "arriv":s, "parent":None, "diff":diff}
|
||||
bill = Block(params)
|
||||
self.assertEqual(bill.ident,name)
|
||||
self.assertEqual(bill.discoTimestamp,t)
|
||||
self.assertEqual(bill.arrivTimestamp,t+1)
|
||||
self.assertTrue(bill.parent is None)
|
||||
self.assertEqual(bill.diff,diff)
|
||||
|
||||
suite = unittest.TestLoader().loadTestsFromTestCase(Test_Block)
|
||||
unittest.TextTestRunner(verbosity=1).run(suite)
|
46
source-code/Poisson-Graphs/new/Block.py~
Normal file
46
source-code/Poisson-Graphs/new/Block.py~
Normal file
|
@ -0,0 +1,46 @@
|
|||
import unittest, random, time
|
||||
|
||||
def newIdent(params):
|
||||
nonce = params
|
||||
# Generate new random identity.
|
||||
return hash(str(nonce) + str(random.random()))
|
||||
#### #### #### #### #### #### #### #### #### #### #### #### #### #### #### ####
|
||||
class Block(object):
|
||||
'''
|
||||
Each block has: an identity, a timestamp of discovery (possibly false),
|
||||
has a timestamp of arrival at the local node (possibly unnecessary), a
|
||||
parent block's identity, and a difficulty score.
|
||||
'''
|
||||
def __init__(self, params={}):
|
||||
self.ident = None
|
||||
self.discoTimestamp = None
|
||||
self.arrivTimestamp = None
|
||||
self.parent = None
|
||||
self.diff = None
|
||||
try:
|
||||
assert len(params)==5
|
||||
except AssertionError:
|
||||
print("Error in Block(): Tried to add a malformed block. We received params = " + str(params) + ", but should have had something of the form {\"ident\":ident, \"disco\":disco, \"arriv\":arriv, \"parent\":parent, \"diff\":diff}.")
|
||||
self.ident = params["ident"]
|
||||
self.discoTimestamp = params["disco"]
|
||||
self.arrivTimestamp = params["arriv"]
|
||||
self.parent = params["parent"]
|
||||
self.diff = params["diff"]
|
||||
|
||||
class Test_Block(unittest.TestCase):
|
||||
def test_b(self):
|
||||
#bill = Block()
|
||||
name = newIdent(0)
|
||||
t = time.time()
|
||||
s = t+1
|
||||
diff = 1.0
|
||||
params = {"ident":name, "disco":t, "arriv":s, "parent":None, "diff":diff}
|
||||
bill = Block(params)
|
||||
self.assertEqual(bill.ident,name)
|
||||
self.assertEqual(bill.discoTimestamp,t)
|
||||
self.assertEqual(bill.arrivTimestamp,t+1)
|
||||
self.assertTrue(bill.parent is None)
|
||||
self.assertEqual(bill.diff,diff)
|
||||
|
||||
suite = unittest.TestLoader().loadTestsFromTestCase(Test_Block)
|
||||
unittest.TextTestRunner(verbosity=1).run(suite)
|
1142
source-code/Poisson-Graphs/new/Blockchain.py
Normal file
1142
source-code/Poisson-Graphs/new/Blockchain.py
Normal file
File diff suppressed because it is too large
Load diff
1142
source-code/Poisson-Graphs/new/Blockchain.py~
Normal file
1142
source-code/Poisson-Graphs/new/Blockchain.py~
Normal file
File diff suppressed because it is too large
Load diff
116
source-code/Poisson-Graphs/new/Node.py
Normal file
116
source-code/Poisson-Graphs/new/Node.py
Normal file
|
@ -0,0 +1,116 @@
|
|||
from Blockchain import *
|
||||
|
||||
class Node(object):
|
||||
'''
|
||||
Node object. params [identity, blockchain (data), verbosity, difficulty]
|
||||
'''
|
||||
def __init__(self, params={}):
|
||||
try:
|
||||
assert len(params)==5
|
||||
except AssertionError:
|
||||
print("Error, Tried to create malformed node.")
|
||||
else:
|
||||
self.ident = params["ident"]
|
||||
self.data = params["data"]
|
||||
self.verbose = params["verbose"]
|
||||
self.edges = {}
|
||||
self.mode = params["mode"]
|
||||
self.targetRate = params["targetRate"]
|
||||
|
||||
def generateBlock(self, discoTime, nonce):
|
||||
newName = newIdent(nonce)
|
||||
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
|
||||
|
||||
def updateBlockchain(self, incBlocks):
|
||||
# incBlocks shall be a dictionary of block identities (as keys) and their associated blocks (as values)
|
||||
# to be added to the local data. We assume difficulty scores have been reported honestly for now.
|
||||
|
||||
tempData = copy.deepcopy(incBlocks)
|
||||
for key in incBlocks:
|
||||
if key in self.data["blockchain"].blocks:
|
||||
del tempData[key]
|
||||
elif incBlocks[key].parent in self.data["blockchain"].blocks or incBlocks[key].parent is None:
|
||||
self.data["blockchain"].addBlock(incBlocks[key], self.mode, self.targetRate)
|
||||
del tempData[key]
|
||||
incBlocks = copy.deepcopy(tempData)
|
||||
while len(incBlocks)>0:
|
||||
for key in incBlocks:
|
||||
if key in self.data["blockchain"].blocks:
|
||||
del tempData[key]
|
||||
elif incBlocks[key].parent in self.data["blockchain"].blocks:
|
||||
self.data["blockchain"].addBlock(incBlocks[key], self.mode, self.targetRate)
|
||||
del tempData[key]
|
||||
incBlocks = copy.deepcopy(tempData)
|
||||
|
||||
def propagate(self, timeOfProp, blockIdent):
|
||||
for edgeIdent in self.edges:
|
||||
edge = self.edges[edgeIdent]
|
||||
length = e.data["length"]
|
||||
timeOfArrival = timeOfProp + length
|
||||
otherIdent = e.getNeighbor(self.ident)
|
||||
other = e.nodes[otherIdent]
|
||||
bc = other.data["blockchain"]
|
||||
if blockIdent not in bc.blocks:
|
||||
pB = e.data["pendingBlocks"]
|
||||
pendingIdent = newIdent(len(pB))
|
||||
mybc = self.data["blockchain"]
|
||||
blockToProp = mybc.blocks[blockIdent]
|
||||
pendingDat = {"timeOfArrival":timeOfArrival, "destIdent":otherIdent, "block":blockToProp}
|
||||
pB.update({pendingIdent:pendingDat})
|
||||
|
||||
|
||||
class Test_Node(unittest.TestCase):
|
||||
# TODO test each method separately
|
||||
def test_all(self):
|
||||
bill = Blockchain([], verbosity=True)
|
||||
mode="Nakamoto"
|
||||
tr = 1.0/600000.0
|
||||
deltaT = 600000.0
|
||||
bill.targetRate = tr
|
||||
|
||||
name = newIdent(0)
|
||||
t = 0.0
|
||||
s = t
|
||||
diff = 1.0
|
||||
params = {"ident":name, "disco":t, "arriv":s, "parent":None, "diff":diff}
|
||||
genesis = Block(params)
|
||||
bill.addBlock(genesis, mode, tr)
|
||||
|
||||
parent = genesis.ident
|
||||
|
||||
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}
|
||||
nelly = Node(params)
|
||||
|
||||
while len(nelly.data["blockchain"].blocks) < 2015:
|
||||
name = newIdent(0)
|
||||
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}
|
||||
newBlock = Block(params)
|
||||
bill.addBlock(newBlock, mode, tr)
|
||||
parent = name
|
||||
|
||||
|
||||
while len(nelly.data["blockchain"].blocks) < 5000:
|
||||
name = newIdent(0)
|
||||
diff = nelly.data["blockchain"].diff
|
||||
t += deltaT*diff
|
||||
s = t
|
||||
params = {"ident":name, "disco":t, "arriv":s, "parent":parent, "diff":diff}
|
||||
newBlock = Block(params)
|
||||
bill.addBlock(newBlock, mode, tr)
|
||||
parent = name
|
||||
|
||||
suite = unittest.TestLoader().loadTestsFromTestCase(Test_Node)
|
||||
unittest.TextTestRunner(verbosity=1).run(suite)
|
||||
|
116
source-code/Poisson-Graphs/new/Node.py~
Normal file
116
source-code/Poisson-Graphs/new/Node.py~
Normal file
|
@ -0,0 +1,116 @@
|
|||
from Blockchain import *
|
||||
|
||||
class Node(object):
|
||||
'''
|
||||
Node object. params [identity, blockchain (data), verbosity, difficulty]
|
||||
'''
|
||||
def __init__(self, params={}):
|
||||
try:
|
||||
assert len(params)==5
|
||||
except AssertionError:
|
||||
print("Error, Tried to create malformed node.")
|
||||
else:
|
||||
self.ident = params["ident"]
|
||||
self.data = params["data"]
|
||||
self.verbose = params["verbose"]
|
||||
self.edges = {}
|
||||
self.mode = params["mode"]
|
||||
self.targetRate = params["targetRate"]
|
||||
|
||||
def generateBlock(self, discoTime, nonce):
|
||||
newName = newIdent(nonce)
|
||||
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
|
||||
|
||||
def updateBlockchain(self, incBlocks):
|
||||
# incBlocks shall be a dictionary of block identities (as keys) and their associated blocks (as values)
|
||||
# to be added to the local data. We assume difficulty scores have been reported honestly for now.
|
||||
|
||||
tempData = copy.deepcopy(incBlocks)
|
||||
for key in incBlocks:
|
||||
if key in self.data["blockchain"].blocks:
|
||||
del tempData[key]
|
||||
elif incBlocks[key].parent in self.data["blockchain"].blocks or incBlocks[key].parent is None:
|
||||
self.data["blockchain"].addBlock(incBlocks[key], self.mode, self.targetRate)
|
||||
del tempData[key]
|
||||
incBlocks = copy.deepcopy(tempData)
|
||||
while len(incBlocks)>0:
|
||||
for key in incBlocks:
|
||||
if key in self.data["blockchain"].blocks:
|
||||
del tempData[key]
|
||||
elif incBlocks[key].parent in self.data["blockchain"].blocks:
|
||||
self.data["blockchain"].addBlock(incBlocks[key], self.mode, self.targetRate)
|
||||
del tempData[key]
|
||||
incBlocks = copy.deepcopy(tempData)
|
||||
|
||||
def propagate(self, timeOfProp, blockIdent):
|
||||
for edgeIdent in self.edges:
|
||||
edge = self.edges[edgeIdent]
|
||||
length = e.data["length"]
|
||||
timeOfArrival = timeOfProp + length
|
||||
otherIdent = e.getNeighbor(self.ident)
|
||||
other = e.nodes[otherIdent]
|
||||
bc = other.data["blockchain"]
|
||||
if blockIdent not in bc.blocks:
|
||||
pB = e.data["pendingBlocks"]
|
||||
pendingIdent = newIdent(len(pB))
|
||||
mybc = self.data["blockchain"]
|
||||
blockToProp = mybc.blocks[blockIdent]
|
||||
pendingDat = {"timeOfArrival":timeOfArrival, "destIdent":otherIdent, "block":blockToProp}
|
||||
pB.update({pendingIdent:pendingDat})
|
||||
|
||||
|
||||
class Test_Node(unittest.TestCase):
|
||||
# TODO test each method separately
|
||||
def test_all(self):
|
||||
bill = Blockchain([], verbosity=True)
|
||||
mode="Nakamoto"
|
||||
tr = 1.0/600000.0
|
||||
deltaT = 600000.0
|
||||
bill.targetRate = tr
|
||||
|
||||
name = newIdent(0)
|
||||
t = 0.0
|
||||
s = t
|
||||
diff = 1.0
|
||||
params = {"ident":name, "disco":t, "arriv":s, "parent":None, "diff":diff}
|
||||
genesis = Block(params)
|
||||
bill.addBlock(genesis, mode, tr)
|
||||
|
||||
parent = genesis.ident
|
||||
|
||||
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}
|
||||
nelly = Node(params)
|
||||
|
||||
while len(nelly.data["blockchain"].blocks) < 2015:
|
||||
name = newIdent(0)
|
||||
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}
|
||||
newBlock = Block(params)
|
||||
bill.addBlock(newBlock, mode, tr)
|
||||
parent = name
|
||||
|
||||
|
||||
while len(nelly.data["blockchain"].blocks) < 5000:
|
||||
name = newIdent(0)
|
||||
diff = nelly.data["blockchain"].diff
|
||||
t += deltaT*diff
|
||||
s = t
|
||||
params = {"ident":name, "disco":t, "arriv":s, "parent":parent, "diff":diff}
|
||||
newBlock = Block(params)
|
||||
bill.addBlock(newBlock, mode, tr)
|
||||
parent = name
|
||||
|
||||
suite = unittest.TestLoader().loadTestsFromTestCase(Test_Node)
|
||||
unittest.TextTestRunner(verbosity=1).run(suite)
|
||||
|
BIN
source-code/Poisson-Graphs/new/__pycache__/Block.cpython-35.pyc
Normal file
BIN
source-code/Poisson-Graphs/new/__pycache__/Block.cpython-35.pyc
Normal file
Binary file not shown.
Binary file not shown.
2501
source-code/Poisson-Graphs/new/output.txt
Normal file
2501
source-code/Poisson-Graphs/new/output.txt
Normal file
File diff suppressed because it is too large
Load diff
602
source-code/Poisson-Graphs/new/outputM.txt
Normal file
602
source-code/Poisson-Graphs/new/outputM.txt
Normal file
|
@ -0,0 +1,602 @@
|
|||
time,rateConstant,difficulty
|
||||
0.0,1.0,1.0
|
||||
1.0,1.0,1.0
|
||||
2.0,1.0,1.0
|
||||
3.0,1.0,1.0
|
||||
4.0,1.0,1.0
|
||||
5.0,1.0,1.0
|
||||
6.0,1.0,1.0
|
||||
7.0,1.0,1.0
|
||||
8.0,1.0,1.0
|
||||
9.0,1.0,1.0
|
||||
10.0,1.0,1.0
|
||||
11.0,1.0,1.0
|
||||
12.0,1.0,1.0
|
||||
13.0,1.0,1.0
|
||||
14.0,1.0,1.0
|
||||
15.0,1.0,1.0
|
||||
16.0,1.0,1.0
|
||||
17.0,1.0,1.0
|
||||
18.0,1.0,1.0
|
||||
19.0,1.0,1.0
|
||||
20.0,1.0,1.0
|
||||
21.0,1.0,1.0
|
||||
22.0,1.0,1.0
|
||||
23.0,1.0,1.0
|
||||
24.0,1.0,1.0
|
||||
25.0,1.0,1.0
|
||||
26.0,1.0,1.0
|
||||
27.0,1.0,1.0
|
||||
28.0,1.0,1.0
|
||||
29.0,1.0,1.0
|
||||
30.0,1.0,1.0
|
||||
31.0,1.0,1.0
|
||||
32.0,1.0,1.0
|
||||
33.0,1.0,1.0
|
||||
34.0,1.0,1.0
|
||||
35.0,1.0,1.0
|
||||
36.0,1.0,1.0
|
||||
37.0,1.0,1.0
|
||||
38.0,1.0,1.0
|
||||
39.0,1.0,1.0
|
||||
40.0,1.0,1.0
|
||||
41.0,1.0,1.0
|
||||
42.0,1.0,1.0
|
||||
43.0,1.0,1.0
|
||||
44.0,1.0,1.0
|
||||
45.0,1.0,1.0
|
||||
46.0,1.0,1.0
|
||||
47.0,1.0,1.0
|
||||
48.0,1.0,1.0
|
||||
49.0,1.0,1.0
|
||||
50.0,1.0,1.0
|
||||
51.0,1.0,1.0
|
||||
52.0,1.0,1.0
|
||||
53.0,1.0,1.0
|
||||
54.0,1.0,1.0
|
||||
55.0,1.0,1.0
|
||||
56.0,1.0,1.0
|
||||
57.0,1.0,1.0
|
||||
58.0,1.0,1.0
|
||||
59.0,1.0,1.0
|
||||
60.0,1.0,1.0
|
||||
61.0,1.0,1.0
|
||||
62.0,1.0,1.0
|
||||
63.0,1.0,1.0
|
||||
64.0,1.0,1.0
|
||||
65.0,1.0,1.0
|
||||
66.0,1.0,1.0
|
||||
67.0,1.0,1.0
|
||||
68.0,1.0,1.0
|
||||
69.0,1.0,1.0
|
||||
70.0,1.0,1.0
|
||||
71.0,1.0,1.0
|
||||
72.0,1.0,1.0
|
||||
73.0,1.0,1.0
|
||||
74.0,1.0,1.0
|
||||
75.0,1.0,1.0
|
||||
76.0,1.0,1.0
|
||||
77.0,1.0,1.0
|
||||
78.0,1.0,1.0
|
||||
79.0,1.0,1.0
|
||||
80.0,1.0,1.0
|
||||
81.0,1.0,1.0
|
||||
82.0,1.0,1.0
|
||||
83.0,1.0,1.0
|
||||
84.0,1.0,1.0
|
||||
85.0,1.0,1.0
|
||||
86.0,1.0,1.0
|
||||
87.0,1.0,1.0
|
||||
88.0,1.0,1.0
|
||||
89.0,1.0,1.0
|
||||
90.0,1.0,1.0
|
||||
91.0,1.0,1.0
|
||||
92.0,1.0,1.0
|
||||
93.0,1.0,1.0
|
||||
94.0,1.0,1.0
|
||||
95.0,1.0,1.0
|
||||
96.0,1.0,1.0
|
||||
97.0,1.0,1.0
|
||||
98.0,1.0,1.0
|
||||
99.0,1.0,1.0
|
||||
100.0,1.0,1.0
|
||||
101.0,1.0,1.0
|
||||
102.0,1.0,1.0
|
||||
103.0,1.0,1.0
|
||||
104.0,1.0,1.0
|
||||
105.0,1.0,1.0
|
||||
106.0,1.0,1.0
|
||||
107.0,1.0,1.0
|
||||
108.0,1.0,1.0
|
||||
109.0,1.0,1.0
|
||||
110.0,1.0,1.0
|
||||
111.0,1.0,1.0
|
||||
112.0,1.0,1.0
|
||||
113.0,1.0,1.0
|
||||
114.0,1.0,1.0
|
||||
115.0,1.0,1.0
|
||||
116.0,1.0,1.0
|
||||
117.0,1.0,1.0
|
||||
118.0,1.0,1.0
|
||||
119.0,1.0,1.0
|
||||
120.0,1.0,1.0
|
||||
121.0,1.0,1.0
|
||||
122.0,1.0,1.0
|
||||
123.0,1.0,1.0
|
||||
124.0,1.0,1.0
|
||||
125.0,1.0,1.0
|
||||
126.0,1.0,1.0
|
||||
127.0,1.0,1.0
|
||||
128.0,1.0,1.0
|
||||
129.0,1.0,1.0
|
||||
130.0,1.0,1.0
|
||||
131.0,1.0,1.0
|
||||
132.0,1.0,1.0
|
||||
133.0,1.0,1.0
|
||||
134.0,1.0,1.0
|
||||
135.0,1.0,1.0
|
||||
136.0,1.0,1.0
|
||||
137.0,1.0,1.0
|
||||
138.0,1.0,1.0
|
||||
139.0,1.0,1.0
|
||||
140.0,1.0,1.0
|
||||
141.0,1.0,1.0
|
||||
142.0,1.0,1.0
|
||||
143.0,1.0,1.0
|
||||
144.0,1.0,1.0
|
||||
145.0,1.0,1.0
|
||||
146.0,1.0,1.0
|
||||
147.0,1.0,1.0
|
||||
148.0,1.0,1.0
|
||||
149.0,1.0,1.0
|
||||
150.0,1.0,1.0
|
||||
151.0,1.0,1.0
|
||||
152.0,1.0,1.0
|
||||
153.0,1.0,1.0
|
||||
154.0,1.0,1.0
|
||||
155.0,1.0,1.0
|
||||
156.0,1.0,1.0
|
||||
157.0,1.0,1.0
|
||||
158.0,1.0,1.0
|
||||
159.0,1.0,1.0
|
||||
160.0,1.0,1.0
|
||||
161.0,1.0,1.0
|
||||
162.0,1.0,1.0
|
||||
163.0,1.0,1.0
|
||||
164.0,1.0,1.0
|
||||
165.0,1.0,1.0
|
||||
166.0,1.0,1.0
|
||||
167.0,1.0,1.0
|
||||
168.0,1.0,1.0
|
||||
169.0,1.0,1.0
|
||||
170.0,1.0,1.0
|
||||
171.0,1.0,1.0
|
||||
172.0,1.0,1.0
|
||||
173.0,1.0,1.0
|
||||
174.0,1.0,1.0
|
||||
175.0,1.0,1.0
|
||||
176.0,1.0,1.0
|
||||
177.0,1.0,1.0
|
||||
178.0,1.0,1.0
|
||||
179.0,1.0,1.0
|
||||
180.0,1.0,1.0
|
||||
181.0,1.0,1.0
|
||||
182.0,1.0,1.0
|
||||
183.0,1.0,1.0
|
||||
184.0,1.0,1.0
|
||||
185.0,1.0,1.0
|
||||
186.0,1.0,1.0
|
||||
187.0,1.0,1.0
|
||||
188.0,1.0,1.0
|
||||
189.0,1.0,1.0
|
||||
190.0,1.0,1.0
|
||||
191.0,1.0,1.0
|
||||
192.0,1.0,1.0
|
||||
193.0,1.0,1.0
|
||||
194.0,1.0,1.0
|
||||
195.0,1.0,1.0
|
||||
196.0,1.0,1.0
|
||||
197.0,1.0,1.0
|
||||
198.0,1.0,1.0
|
||||
199.0,1.0,1.0
|
||||
200.0,1.0,1.0
|
||||
201.0,1.0,1.0
|
||||
202.0,1.0,1.0
|
||||
203.0,1.0,1.0
|
||||
204.0,1.0,1.0
|
||||
205.0,1.0,1.0
|
||||
206.0,1.0,1.0
|
||||
207.0,1.0,1.0
|
||||
208.0,1.0,1.0
|
||||
209.0,1.0,1.0
|
||||
210.0,1.0,1.0
|
||||
211.0,1.0,1.0
|
||||
212.0,1.0,1.0
|
||||
213.0,1.0,1.0
|
||||
214.0,1.0,1.0
|
||||
215.0,1.0,1.0
|
||||
216.0,1.0,1.0
|
||||
217.0,1.0,1.0
|
||||
218.0,1.0,1.0
|
||||
219.0,1.0,1.0
|
||||
220.0,1.0,1.0
|
||||
221.0,1.0,1.0
|
||||
222.0,1.0,1.0
|
||||
223.0,1.0,1.0
|
||||
224.0,1.0,1.0
|
||||
225.0,1.0,1.0
|
||||
226.0,1.0,1.0
|
||||
227.0,1.0,1.0
|
||||
228.0,1.0,1.0
|
||||
229.0,1.0,1.0
|
||||
230.0,1.0,1.0
|
||||
231.0,1.0,1.0
|
||||
232.0,1.0,1.0
|
||||
233.0,1.0,1.0
|
||||
234.0,1.0,1.0
|
||||
235.0,1.0,1.0
|
||||
236.0,1.0,1.0
|
||||
237.0,1.0,1.0
|
||||
238.0,1.0,1.0
|
||||
239.0,1.0,1.0
|
||||
240.0,1.0,1.0
|
||||
241.0,1.0,1.0
|
||||
242.0,1.0,1.0
|
||||
243.0,1.0,1.0
|
||||
244.0,1.0,1.0
|
||||
245.0,1.0,1.0
|
||||
246.0,1.0,1.0
|
||||
247.0,1.0,1.0
|
||||
248.0,1.0,1.0
|
||||
249.0,1.0,1.0
|
||||
250.0,1.0,1.0
|
||||
251.0,1.0,1.0
|
||||
252.0,1.0,1.0
|
||||
253.0,1.0,1.0
|
||||
254.0,1.0,1.0
|
||||
255.0,1.0,1.0
|
||||
256.0,1.0,1.0
|
||||
257.0,1.0,1.0
|
||||
258.0,1.0,1.0
|
||||
259.0,1.0,1.0
|
||||
260.0,1.0,1.0
|
||||
261.0,1.0,1.0
|
||||
262.0,1.0,1.0
|
||||
263.0,1.0,1.0
|
||||
264.0,1.0,1.0
|
||||
265.0,1.0,1.0
|
||||
266.0,1.0,1.0
|
||||
267.0,1.0,1.0
|
||||
268.0,1.0,1.0
|
||||
269.0,1.0,1.0
|
||||
270.0,1.0,1.0
|
||||
271.0,1.0,1.0
|
||||
272.0,1.0,1.0
|
||||
273.0,1.0,1.0
|
||||
274.0,1.0,1.0
|
||||
275.0,1.0,1.0
|
||||
276.0,1.0,1.0
|
||||
277.0,1.0,1.0
|
||||
278.0,1.0,1.0
|
||||
279.0,1.0,1.0
|
||||
280.0,1.0,1.0
|
||||
281.0,1.0,1.0
|
||||
282.0,1.0,1.0
|
||||
283.0,1.0,1.0
|
||||
284.0,1.0,1.0
|
||||
285.0,1.0,1.0
|
||||
286.0,1.0,1.0
|
||||
287.0,1.0,1.0
|
||||
288.0,1.0,1.0
|
||||
289.0,1.0,1.0
|
||||
290.0,1.0,1.0
|
||||
291.0,1.0,1.0
|
||||
292.0,1.0,1.0
|
||||
293.0,1.0,1.0
|
||||
294.0,1.0,1.0
|
||||
295.0,1.0,1.0
|
||||
296.0,1.0,1.0
|
||||
297.0,1.0,1.0
|
||||
298.0,1.0,1.0
|
||||
299.0,1.0,1.0
|
||||
300.0,1.0,1.0
|
||||
301.0,1.0,1.0
|
||||
302.0,1.0,1.0
|
||||
303.0,1.0,1.0
|
||||
304.0,1.0,1.0
|
||||
305.0,1.0,1.0
|
||||
306.0,1.0,1.0
|
||||
307.0,1.0,1.0
|
||||
308.0,1.0,1.0
|
||||
309.0,1.0,1.0
|
||||
310.0,1.0,1.0
|
||||
311.0,1.0,1.0
|
||||
312.0,1.0,1.0
|
||||
313.0,1.0,1.0
|
||||
314.0,1.0,1.0
|
||||
315.0,1.0,1.0
|
||||
316.0,1.0,1.0
|
||||
317.0,1.0,1.0
|
||||
318.0,1.0,1.0
|
||||
319.0,1.0,1.0
|
||||
320.0,1.0,1.0
|
||||
321.0,1.0,1.0
|
||||
322.0,1.0,1.0
|
||||
323.0,1.0,1.0
|
||||
324.0,1.0,1.0
|
||||
325.0,1.0,1.0
|
||||
326.0,1.0,1.0
|
||||
327.0,1.0,1.0
|
||||
328.0,1.0,1.0
|
||||
329.0,1.0,1.0
|
||||
330.0,1.0,1.0
|
||||
331.0,1.0,1.0
|
||||
332.0,1.0,1.0
|
||||
333.0,1.0,1.0
|
||||
334.0,1.0,1.0
|
||||
335.0,1.0,1.0
|
||||
336.0,1.0,1.0
|
||||
337.0,1.0,1.0
|
||||
338.0,1.0,1.0
|
||||
339.0,1.0,1.0
|
||||
340.0,1.0,1.0
|
||||
341.0,1.0,1.0
|
||||
342.0,1.0,1.0
|
||||
343.0,1.0,1.0
|
||||
344.0,1.0,1.0
|
||||
345.0,1.0,1.0
|
||||
346.0,1.0,1.0
|
||||
347.0,1.0,1.0
|
||||
348.0,1.0,1.0
|
||||
349.0,1.0,1.0
|
||||
350.0,1.0,1.0
|
||||
351.0,1.0,1.0
|
||||
352.0,1.0,1.0
|
||||
353.0,1.0,1.0
|
||||
354.0,1.0,1.0
|
||||
355.0,1.0,1.0
|
||||
356.0,1.0,1.0
|
||||
357.0,1.0,1.0
|
||||
358.0,1.0,1.0
|
||||
359.0,1.0,1.0
|
||||
360.0,1.0,1.0
|
||||
361.0,1.0,1.0
|
||||
362.0,1.0,1.0
|
||||
363.0,1.0,1.0
|
||||
364.0,1.0,1.0
|
||||
365.0,1.0,1.0
|
||||
366.0,1.0,1.0
|
||||
367.0,1.0,1.0
|
||||
368.0,1.0,1.0
|
||||
369.0,1.0,1.0
|
||||
370.0,1.0,1.0
|
||||
371.0,1.0,1.0
|
||||
372.0,1.0,1.0
|
||||
373.0,1.0,1.0
|
||||
374.0,1.0,1.0
|
||||
375.0,1.0,1.0
|
||||
376.0,1.0,1.0
|
||||
377.0,1.0,1.0
|
||||
378.0,1.0,1.0
|
||||
379.0,1.0,1.0
|
||||
380.0,1.0,1.0
|
||||
381.0,1.0,1.0
|
||||
382.0,1.0,1.0
|
||||
383.0,1.0,1.0
|
||||
384.0,1.0,1.0
|
||||
385.0,1.0,1.0
|
||||
386.0,1.0,1.0
|
||||
387.0,1.0,1.0
|
||||
388.0,1.0,1.0
|
||||
389.0,1.0,1.0
|
||||
390.0,1.0,1.0
|
||||
391.0,1.0,1.0
|
||||
392.0,1.0,1.0
|
||||
393.0,1.0,1.0
|
||||
394.0,1.0,1.0
|
||||
395.0,1.0,1.0
|
||||
396.0,1.0,1.0
|
||||
397.0,1.0,1.0
|
||||
398.0,1.0,1.0
|
||||
399.0,1.0,1.0
|
||||
400.0,1.0,1.0
|
||||
401.0,1.0,1.0
|
||||
402.0,1.0,1.0
|
||||
403.0,1.0,1.0
|
||||
404.0,1.0,1.0
|
||||
405.0,1.0,1.0
|
||||
406.0,1.0,1.0
|
||||
407.0,1.0,1.0
|
||||
408.0,1.0,1.0
|
||||
409.0,1.0,1.0
|
||||
410.0,1.0,1.0
|
||||
411.0,1.0,1.0
|
||||
412.0,1.0,1.0
|
||||
413.0,1.0,1.0
|
||||
414.0,1.0,1.0
|
||||
415.0,1.0,1.0
|
||||
416.0,1.0,1.0
|
||||
417.0,1.0,1.0
|
||||
418.0,1.0,1.0
|
||||
419.0,1.0,1.0
|
||||
420.0,1.0,1.0
|
||||
421.0,1.0,1.0
|
||||
422.0,1.0,1.0
|
||||
423.0,1.0,1.0
|
||||
424.0,1.0,1.0
|
||||
425.0,1.0,1.0
|
||||
426.0,1.0,1.0
|
||||
427.0,1.0,1.0
|
||||
428.0,1.0,1.0
|
||||
429.0,1.0,1.0
|
||||
430.0,1.0,1.0
|
||||
431.0,1.0,1.0
|
||||
432.0,1.0,1.0
|
||||
433.0,1.0,1.0
|
||||
434.0,1.0,1.0
|
||||
435.0,1.0,1.0
|
||||
436.0,1.0,1.0
|
||||
437.0,1.0,1.0
|
||||
438.0,1.0,1.0
|
||||
439.0,1.0,1.0
|
||||
440.0,1.0,1.0
|
||||
441.0,1.0,1.0
|
||||
442.0,1.0,1.0
|
||||
443.0,1.0,1.0
|
||||
444.0,1.0,1.0
|
||||
445.0,1.0,1.0
|
||||
446.0,1.0,1.0
|
||||
447.0,1.0,1.0
|
||||
448.0,1.0,1.0
|
||||
449.0,1.0,1.0
|
||||
450.0,1.0,1.0
|
||||
451.0,1.0,1.0
|
||||
452.0,1.0,1.0
|
||||
453.0,1.0,1.0
|
||||
454.0,1.0,1.0
|
||||
455.0,1.0,1.0
|
||||
456.0,1.0,1.0
|
||||
457.0,1.0,1.0
|
||||
458.0,1.0,1.0
|
||||
459.0,1.0,1.0
|
||||
460.0,1.0,1.0
|
||||
461.0,1.0,1.0
|
||||
462.0,1.0,1.0
|
||||
463.0,1.0,1.0
|
||||
464.0,1.0,1.0
|
||||
465.0,1.0,1.0
|
||||
466.0,1.0,1.0
|
||||
467.0,1.0,1.0
|
||||
468.0,1.0,1.0
|
||||
469.0,1.0,1.0
|
||||
470.0,1.0,1.0
|
||||
471.0,1.0,1.0
|
||||
472.0,1.0,1.0
|
||||
473.0,1.0,1.0
|
||||
474.0,1.0,1.0
|
||||
475.0,1.0,1.0
|
||||
476.0,1.0,1.0
|
||||
477.0,1.0,1.0
|
||||
478.0,1.0,1.0
|
||||
479.0,1.0,1.0
|
||||
480.0,1.0,1.0
|
||||
481.0,1.0,1.0
|
||||
482.0,1.0,1.0
|
||||
483.0,1.0,1.0
|
||||
484.0,1.0,1.0
|
||||
485.0,1.0,1.0
|
||||
486.0,1.0,1.0
|
||||
487.0,1.0,1.0
|
||||
488.0,1.0,1.0
|
||||
489.0,1.0,1.0
|
||||
490.0,1.0,1.0
|
||||
491.0,1.0,1.0
|
||||
492.0,1.0,1.0
|
||||
493.0,1.0,1.0
|
||||
494.0,1.0,1.0
|
||||
495.0,1.0,1.0
|
||||
496.0,1.0,1.0
|
||||
497.0,1.0,1.0
|
||||
498.0,1.0,1.0
|
||||
499.0,1.0,1.0
|
||||
500.0,1.0,1.0
|
||||
501.0,1.0,1.0
|
||||
502.0,1.0,1.0
|
||||
503.0,1.0,1.0
|
||||
504.0,1.0,1.0
|
||||
505.0,1.0,1.0
|
||||
506.0,1.0,1.0
|
||||
507.0,1.0,1.0
|
||||
508.0,1.0,1.0
|
||||
509.0,1.0,1.0
|
||||
510.0,1.0,1.0
|
||||
511.0,1.0,1.0
|
||||
512.0,1.0,1.0
|
||||
513.0,1.0,1.0
|
||||
514.0,1.0,1.0
|
||||
515.0,1.0,1.0
|
||||
516.0,1.0,1.0
|
||||
517.0,1.0,1.0
|
||||
518.0,1.0,1.0
|
||||
519.0,1.0,1.0
|
||||
520.0,1.0,1.0
|
||||
521.0,1.0,1.0
|
||||
522.0,1.0,1.0
|
||||
523.0,1.0,1.0
|
||||
524.0,1.0,1.0
|
||||
525.0,1.0,1.0
|
||||
526.0,1.0,1.0
|
||||
527.0,1.0,1.0
|
||||
528.0,1.0,1.0
|
||||
529.0,1.0,1.0
|
||||
530.0,1.0,1.0
|
||||
531.0,1.0,1.0
|
||||
532.0,1.0,1.0
|
||||
533.0,1.0,1.0
|
||||
534.0,1.0,1.0
|
||||
535.0,1.0,1.0
|
||||
536.0,1.0,1.0
|
||||
537.0,1.0,1.0
|
||||
538.0,1.0,1.0
|
||||
539.0,1.0,1.0
|
||||
540.0,1.0,1.0
|
||||
541.0,1.0,1.0
|
||||
542.0,1.0,1.0
|
||||
543.0,1.0,1.0
|
||||
544.0,1.0,1.0
|
||||
545.0,1.0,1.0
|
||||
546.0,1.0,1.0
|
||||
547.0,1.0,1.0
|
||||
548.0,1.0,1.0
|
||||
549.0,1.0,1.0
|
||||
550.0,1.0,1.0
|
||||
551.0,1.0,1.0
|
||||
552.0,1.0,1.0
|
||||
553.0,1.0,1.0
|
||||
554.0,1.0,1.0
|
||||
555.0,1.0,1.0
|
||||
556.0,1.0,1.0
|
||||
557.0,1.0,1.0
|
||||
558.0,1.0,1.0
|
||||
559.0,1.0,1.0
|
||||
560.0,1.0,1.0
|
||||
561.0,1.0,1.0
|
||||
562.0,1.0,1.0
|
||||
563.0,1.0,1.0
|
||||
564.0,1.0,1.0
|
||||
565.0,1.0,1.0
|
||||
566.0,1.0,1.0
|
||||
567.0,1.0,1.0
|
||||
568.0,1.0,1.0
|
||||
569.0,1.0,1.0
|
||||
570.0,1.0,1.0
|
||||
571.0,1.0,1.0
|
||||
572.0,1.0,1.0
|
||||
573.0,1.0,1.0
|
||||
574.0,1.0,1.0
|
||||
575.0,1.0,1.0
|
||||
576.0,1.0,1.0
|
||||
577.0,1.0,1.0
|
||||
578.0,1.0,1.0
|
||||
579.0,1.0,1.0
|
||||
580.0,1.0,1.0
|
||||
581.0,1.0,1.0
|
||||
582.0,1.0,1.0
|
||||
583.0,1.0,1.0
|
||||
584.0,1.0,1.0
|
||||
585.0,1.0,1.0
|
||||
586.0,1.0,1.0
|
||||
587.0,1.0,1.0
|
||||
588.0,1.0,1.0
|
||||
589.0,1.0,1.0
|
||||
590.0,1.0,1.0
|
||||
591.0,1.0,1.0
|
||||
592.0,1.0,1.0
|
||||
593.0,1.0,1.0
|
||||
594.0,1.0,1.0
|
||||
595.0,1.0,1.0
|
||||
596.0,1.0,1.0
|
||||
597.0,1.0,1.0
|
||||
598.0,1.0,1.0
|
||||
599.0,1.0,1.0
|
||||
600.0,1.0,1.0
|
201
source-code/Poisson-Graphs/new/outputM.txt~
Normal file
201
source-code/Poisson-Graphs/new/outputM.txt~
Normal file
|
@ -0,0 +1,201 @@
|
|||
time,rateConstant,difficulty
|
||||
0.0,1.0,1.0
|
||||
120458.46590012926,1.0,1.0
|
||||
240605.33373578714,1.0,1.0
|
||||
360287.44233708055,1.0,1.0
|
||||
480034.84471731156,1.0,1.0
|
||||
601021.4072874074,1.0,1.0
|
||||
720155.9397105722,1.0,1.0
|
||||
840557.1097845419,1.0,1.0
|
||||
960142.4715273783,1.0,1.0
|
||||
1080326.4196690398,1.0,1.0
|
||||
1200228.3567496322,1.0,1.0
|
||||
1321393.1769845556,1.0,1.0
|
||||
1442403.7637959223,1.0,1.0
|
||||
1563312.6884154421,1.0,1.0
|
||||
1683650.3562759135,1.0,1.0
|
||||
1804242.0878089573,1.0,1.0
|
||||
1923957.6270508477,1.0,1.0
|
||||
2043603.5193920576,1.0,1.0
|
||||
2162815.4440224506,1.0,1.0
|
||||
2282288.929005547,1.0,1.0
|
||||
2402114.705755926,1.0,1.0
|
||||
2522303.585101224,1.0,1.0
|
||||
2643267.2988593285,1.0,1.0
|
||||
2762617.5338163865,1.0,1.0
|
||||
2882563.380726947,1.0,1.0
|
||||
3003489.532699132,1.0,1.0
|
||||
3124641.562256374,1.0,1.0
|
||||
3245100.9215427977,1.0,1.0
|
||||
3365536.420458877,1.0,1.0
|
||||
3484337.996609595,1.0,1.0
|
||||
3604694.7847104715,1.0,1.0
|
||||
3724951.576782264,1.0,1.0
|
||||
3846026.69613723,1.0,1.0
|
||||
3967024.7982774274,1.0,1.0
|
||||
4085911.063711746,1.0,1.0
|
||||
4205815.028144305,1.0,1.0
|
||||
4325421.232620401,1.0,1.0
|
||||
4444827.052513202,1.0,1.0
|
||||
4565099.154304211,1.0,1.0
|
||||
4686236.387124661,1.0,1.0
|
||||
4806734.051850467,1.0,1.0
|
||||
4926566.647937627,1.0,1.0
|
||||
5045488.866484466,1.0,1.0
|
||||
5166502.755345808,1.0,1.0
|
||||
5287233.653263695,1.0,1.0
|
||||
5407908.334559678,1.0,1.0
|
||||
5528786.366282915,1.0,1.0
|
||||
5647678.3122160155,1.0,1.0
|
||||
5767244.089580304,1.0,1.0
|
||||
5886473.651601109,1.0,1.0
|
||||
6006435.897878854,1.0,1.0
|
||||
6125341.27352921,1.0,1.0
|
||||
6245479.785253891,1.0,1.0
|
||||
6365523.236878065,1.0,1.0
|
||||
6485749.795878896,1.0,1.0
|
||||
6605240.444894265,1.0,1.0
|
||||
6724686.210446132,1.0,1.0
|
||||
6844155.218750592,1.0,1.0
|
||||
6963341.181369955,1.0,1.0
|
||||
7082695.6923123505,1.0,1.0
|
||||
7203655.141225615,1.0,1.0
|
||||
7322627.204840391,1.0,1.0
|
||||
7441799.159546731,1.0,1.0
|
||||
7562822.49932097,1.0,1.0
|
||||
7683323.524066307,1.0,1.0
|
||||
7804477.48899398,1.0,1.0
|
||||
7923457.857637024,1.0,1.0
|
||||
8043898.249303401,1.0,1.0
|
||||
8164187.296374614,1.0,1.0
|
||||
8283469.107294493,1.0,1.0
|
||||
8402627.723784521,1.0,1.0
|
||||
8523745.89200794,1.0,1.0
|
||||
8643778.9729813,1.0,1.0
|
||||
8764635.624631569,1.0,1.0
|
||||
8885538.059417976,1.0,1.0
|
||||
9006433.79263568,1.0,1.0
|
||||
9127489.588015186,1.0,1.0
|
||||
9247569.28782317,1.0,1.0
|
||||
9367958.084440755,1.0,1.0
|
||||
9487586.29442678,1.0,1.0
|
||||
9606427.886281481,1.0,1.0
|
||||
9725872.946140163,1.0,1.0
|
||||
9846820.596317865,1.0,1.0
|
||||
9966080.313457007,1.0,1.0
|
||||
10085765.108573573,1.0,1.0
|
||||
10206008.374459436,1.0,1.0
|
||||
10326807.845790997,1.0,1.0
|
||||
10447513.423168132,1.0,1.0
|
||||
10566795.347145824,1.0,1.0
|
||||
10686179.997466285,1.0,1.0
|
||||
10805522.808373246,1.0,1.0
|
||||
10925591.945700001,1.0,1.0
|
||||
11045387.795286857,1.0,1.0
|
||||
11165651.717103494,1.0,1.0
|
||||
11286830.098064246,1.0,1.0
|
||||
11406728.71699933,1.0,1.0
|
||||
11525922.789870113,1.0,1.0
|
||||
11646476.03903497,1.0,1.0
|
||||
11766081.434268286,1.0,1.0
|
||||
11886554.737807736,1.0,1.0
|
||||
12006591.066234503,1.0,1.0
|
||||
12125475.542528223,1.0,1.0
|
||||
12245282.608027933,1.0,1.0
|
||||
12364566.337023206,1.0,1.0
|
||||
12484001.537563423,1.0,1.0
|
||||
12604914.58673975,1.0,1.0
|
||||
12725797.319719713,1.0,1.0
|
||||
12844665.121160349,1.0,1.0
|
||||
12964577.111847764,1.0,1.0
|
||||
13083664.372389417,1.0,1.0
|
||||
13204397.122438395,1.0,1.0
|
||||
13324189.80038166,1.0,1.0
|
||||
13445349.787586372,1.0,1.0
|
||||
13564667.751049513,1.0,1.0
|
||||
13684270.141374838,1.0,1.0
|
||||
13804933.175467426,1.0,1.0
|
||||
13926075.032552686,1.0,1.0
|
||||
14045914.739095576,1.0,1.0
|
||||
14166631.90042476,1.0,1.0
|
||||
14286319.61550191,1.0,1.0
|
||||
14406521.722056692,1.0,0.434741782576
|
||||
14527069.972553544,1.0,0.19008730551
|
||||
14647876.788742132,1.0,0.0840528337448
|
||||
14766882.452974409,1.0,0.037302520528
|
||||
14886464.10335911,1.0,0.0165590754676
|
||||
15006383.983595744,1.0,0.00734675515331
|
||||
15125494.942906044,1.0,0.00323569454228
|
||||
15246686.831929097,1.0,0.00142738653296
|
||||
15365567.953963466,1.0,0.000625305203658
|
||||
15485210.071059253,1.0,0.00027137099116
|
||||
15605744.64157258,1.0,0.00011715461834
|
||||
15726806.733151415,1.0,5.07010986398e-05
|
||||
15847473.63409661,1.0,2.20995440742e-05
|
||||
15967616.71119521,1.0,9.7101015984e-06
|
||||
16087483.017800437,1.0,4.29503052419e-06
|
||||
16208328.180223988,1.0,1.92536966438e-06
|
||||
16328269.772618307,1.0,8.74191715802e-07
|
||||
16448898.77254663,1.0,4.04296324402e-07
|
||||
16569068.683560552,1.0,1.90818902578e-07
|
||||
16689986.260285133,1.0,9.28633545485e-08
|
||||
16810906.032656457,1.0,4.72143204458e-08
|
||||
16930289.120968327,1.0,2.49711320542e-08
|
||||
17050753.779718515,1.0,1.3892256413e-08
|
||||
17170600.427019596,1.0,8.15844774794e-09
|
||||
17289713.01359109,1.0,4.99225078962e-09
|
||||
17410383.421790008,1.0,3.25190780354e-09
|
||||
17530744.28431112,1.0,2.30869255122e-09
|
||||
17649863.36025036,1.0,1.75633116174e-09
|
||||
17771007.11205409,1.0,1.56057621444e-09
|
||||
17891565.791564044,1.0,2.04725172611e-09
|
||||
18010728.55130284,1.0,3.28303372549e-09
|
||||
18131143.8843602,1.0,3.25496154055e-09
|
||||
18251685.45446652,1.0,2.60736708269e-09
|
||||
18371507.007102486,1.0,1.85630105501e-09
|
||||
18491403.948076807,1.0,1.21928659457e-09
|
||||
18611553.039604228,1.0,7.49792394597e-10
|
||||
18730744.251551468,1.0,4.45186327526e-10
|
||||
18849856.685056694,1.0,2.61385070862e-10
|
||||
18968926.062500622,1.0,1.55149613051e-10
|
||||
19088067.33909847,1.0,9.51850841053e-11
|
||||
19207594.13354391,1.0,6.1434055957e-11
|
||||
19328017.11208744,1.0,4.14815251504e-11
|
||||
19448814.951942917,1.0,2.86357848006e-11
|
||||
19567841.28162038,1.0,2.11150220091e-11
|
||||
19688388.179414563,1.0,1.6406642243e-11
|
||||
19807627.873820234,1.0,1.43187359575e-11
|
||||
19928483.04169874,1.0,1.35913238196e-11
|
||||
20048557.76424465,1.0,1.4331290576e-11
|
||||
20167664.74191137,1.0,2.37342192382e-11
|
||||
20287610.467802733,1.0,3.14063325262e-11
|
||||
20408382.62417472,1.0,3.36556321046e-11
|
||||
20527817.08243184,1.0,3.00938650991e-11
|
||||
20646637.59478427,1.0,2.24650389033e-11
|
||||
20766577.880066067,1.0,1.49080962166e-11
|
||||
20885785.934438772,1.0,8.89077367161e-12
|
||||
21005536.07104386,1.0,4.87060433801e-12
|
||||
21124902.305172637,1.0,2.47052077112e-12
|
||||
21244885.7076036,1.0,1.17786853388e-12
|
||||
21364581.43746038,1.0,5.31532928098e-13
|
||||
21484493.676516064,1.0,2.28757375026e-13
|
||||
21603916.644479226,1.0,9.40324531004e-14
|
||||
21723733.860411238,1.0,3.70938898759e-14
|
||||
21844771.38186735,1.0,1.42162474893e-14
|
||||
21964794.368862327,1.0,5.30817642226e-15
|
||||
22085627.151319932,1.0,1.94525471916e-15
|
||||
22205153.52382764,1.0,6.9852514309e-16
|
||||
22324878.40351138,1.0,2.45757880538e-16
|
||||
22444702.60558849,1.0,8.47565473955e-17
|
||||
22564133.40356277,1.0,2.8611824903e-17
|
||||
22684916.550748322,1.0,9.50429614301e-18
|
||||
22804924.811821572,1.0,3.10972949853e-18
|
||||
22924555.89776567,1.0,1.00142181128e-18
|
||||
23044673.155832924,1.0,3.17850639386e-19
|
||||
23164255.219417505,1.0,9.93453168398e-20
|
||||
23283874.042637054,1.0,3.05585142432e-20
|
||||
23403159.90787814,1.0,9.23510334381e-21
|
||||
23522146.490881946,1.0,2.7354446299e-21
|
||||
23641985.23572208,1.0,7.94854774163e-22
|
||||
23760806.412928328,1.0,2.26044417743e-22
|
||||
23881715.30956635,1.0,6.31881915952e-23
|
Loading…
Reference in a new issue