mirror of
https://github.com/monero-project/research-lab.git
synced 2024-12-22 11:39:32 +00:00
Architecture present for whole sims and transcripts.
This commit is contained in:
parent
f51f35669a
commit
956c59ad24
17 changed files with 1210 additions and 7324 deletions
File diff suppressed because it is too large
Load diff
|
@ -4,7 +4,7 @@ class Edge(object):
|
|||
'''
|
||||
Edge object. Has an identity, some data, and a dict of nodes.
|
||||
'''
|
||||
def __init__(self, params=["", {}, True]):
|
||||
def __init__(self, params):
|
||||
try:
|
||||
assert len(params)==3
|
||||
except AssertionError:
|
||||
|
@ -29,66 +29,11 @@ class Edge(object):
|
|||
|
||||
class Test_Edge(unittest.TestCase):
|
||||
def test_e(self):
|
||||
nellyIdent = newIdent(0)
|
||||
bill = Blockchain([], verbosity=True)
|
||||
|
||||
name = newIdent(0)
|
||||
t = time.time()
|
||||
diff = 1.0
|
||||
params = [name, t, t+1, None, diff, bill.verbose] # Genesis block has no parent, so parent = None
|
||||
genesis = Block(params)
|
||||
bill.addBlock(genesis)
|
||||
|
||||
time.sleep(10)
|
||||
|
||||
name = newIdent(1)
|
||||
t = time.time()
|
||||
diff = 1.0
|
||||
params = [name, t, t+1, genesis.ident, diff, bill.verbose]
|
||||
blockA = Block(params)
|
||||
bill.addBlock(blockA)
|
||||
|
||||
# Nodes need an identity and a blockchain object and verbosity and difficulty
|
||||
nelly = Node([nellyIdent, copy.deepcopy(bill), bill.verbosity, diff])
|
||||
nelly.updateDifficulty(mode="Nakamoto")
|
||||
|
||||
time.sleep(9)
|
||||
|
||||
name = newIdent(len(nelly.data))
|
||||
t = time.time()
|
||||
params = [name, t, t+1, blockA.ident, nelly.diff, nelly.verbose]
|
||||
blockB = Block(params)
|
||||
nelly.updateBlockchain({blockB.ident:blockB})
|
||||
|
||||
time.sleep(8)
|
||||
|
||||
name = newIdent(len(nelly.data))
|
||||
t = time.time()
|
||||
params = [name, t, t+1, blockB.ident, nelly.diff, nelly.verbose]
|
||||
blockC = Block(params)
|
||||
nelly.updateBlockchain({blockC.ident:blockC})
|
||||
|
||||
time.sleep(1)
|
||||
name = newIdent(len(nelly.data))
|
||||
t = time.time()
|
||||
params = [name, t, t+1, blockB.ident, nelly.diff, nelly.verbose] # Fork off
|
||||
blockD = Block(params)
|
||||
nelly.updateBlockchain({blockD.ident:blockD})
|
||||
|
||||
time.sleep(7)
|
||||
name = newIdent(len(nelly.data))
|
||||
t = time.time()
|
||||
params = [name, t, t+1, blockD.ident, nelly.diff, nelly.verbose]
|
||||
blockE = Block(params)
|
||||
nelly.updateBlockchain({blockE.ident:blockE})
|
||||
|
||||
|
||||
time.sleep(6)
|
||||
name = newIdent(len(nelly.data))
|
||||
t = time.time()
|
||||
params = [name, t, t+1, blockE.ident, nelly.diff, nelly.verbose]
|
||||
blockF = Block(params)
|
||||
nelly.updateBlockchain({blockF.ident:blockF})
|
||||
nelly = Node(params)
|
||||
milly = Node(params)
|
||||
ed = Edge(params)
|
||||
ed.nodes.update({nelly.ident:nelly, milly.ident:milly})
|
||||
self.assertEqual(len(self.nodes),2)
|
||||
|
||||
|
||||
suite = unittest.TestLoader().loadTestsFromTestCase(Test_Edge)
|
||||
|
|
|
@ -1,307 +0,0 @@
|
|||
import unittest, copy, random, math, time
|
||||
from scipy.stats import skew
|
||||
from numpy import var
|
||||
from numpy import random as nprandom
|
||||
|
||||
#TODO: Node.data["blockchain"] != node.data
|
||||
|
||||
def newIdent(params):
|
||||
nonce = params
|
||||
# Generate new random identity.
|
||||
return hash(str(nonce) + str(random.random()))
|
||||
|
||||
def newIntensity(params):
|
||||
mode = params
|
||||
if mode=="uniform":
|
||||
return random.random()
|
||||
|
||||
def newOffset(params):
|
||||
mode = params
|
||||
if mode=="unifDST":
|
||||
r = 2.0*random.random() - 1.0 # hours
|
||||
r = 60.0*60.0*r #60 min/hr, 60 sec/min
|
||||
return r
|
||||
if mode=="sumOfSkellams":
|
||||
# This mode uses a skellam distribution, which is
|
||||
# the difference of two poisson-distributed random
|
||||
# variables.
|
||||
# HourOffset = skellam
|
||||
# SecondOffset = skellam
|
||||
# TotalOffset = 60*60*HourOffset + 60*MinuteOffset + SecondOffset
|
||||
# Each skellam = poisson(1) - poisson(1)
|
||||
# Reasoning: We consider most computers' local time offset from UTC
|
||||
# to be a two time-scale random variable, one on the hour scale and one on
|
||||
# the second scale. We make
|
||||
x = nprandom.poisson(1, (2,2))
|
||||
totalOffset = 60.0*60.0*float(x[0][0] - x[1][0]) + float((x[0][1] - x[1][1]))
|
||||
return totalOffset
|
||||
|
||||
|
||||
class FishGraph(StochasticProcess):
|
||||
'''
|
||||
Stochastic process on a graph
|
||||
with the graph growing in a stochastic process too
|
||||
'''
|
||||
# TODO: Check if output.txt exists before beginning. If so, clear it and create a new one.
|
||||
# TODO: Instead of/in addition to storing graph data in a text file, can we plot with ggplot in R?
|
||||
def __init__(self, params=None, verbosity=True):
|
||||
# Initialize
|
||||
|
||||
assert "maxTime" in params
|
||||
self.maxTime = copy.deepcopy(params["maxTime"])
|
||||
del params["maxTime"]
|
||||
|
||||
assert "numNodes" in params
|
||||
numNodes = params["numNodes"]
|
||||
del params["numNodes"]
|
||||
|
||||
self.data = params
|
||||
self.t = 0.0
|
||||
self.state = Graph()
|
||||
self.filename = "output.txt"
|
||||
self.verbose = verbosity
|
||||
|
||||
# Create graph
|
||||
self.state.createGraph(numNodes, self.data["probEdge"], self.data["maxNeighbors"])
|
||||
|
||||
# Update node data
|
||||
for nIdent in self.state.nodes:
|
||||
n = self.state.nodes[nIdent]
|
||||
difficulty = 1.0
|
||||
intensity = newIntensity(params="uniform")
|
||||
offset = newOffset(params="sumOfSkellams")
|
||||
dat = {"intensity":intensity, "offset":offset, "blockchain":Blockchain([], verbosity=self.verbose)}
|
||||
n.data.update(dat)
|
||||
|
||||
# Update edge data.
|
||||
for eIdent in self.state.edges:
|
||||
e = self.state.edges[eIdent]
|
||||
e.data.update({"pendingBlocks":{}})
|
||||
|
||||
def go(self):
|
||||
assert self.maxTime > 0.0
|
||||
while self.t <= self.maxTime and len(self.state.nodes) > 0:
|
||||
deltaT = self.getNextTime()
|
||||
self.updateState(self.t, deltaT)
|
||||
self.record()
|
||||
|
||||
def getNextTime(self):
|
||||
# Each Poisson process event generates an exponential random variable.
|
||||
# The smallest of these is selected
|
||||
# The rate of the smallest determines event type.
|
||||
eventTag = None
|
||||
|
||||
u = 0.0
|
||||
while(u == 0.0):
|
||||
u = copy.deepcopy(random.random())
|
||||
u = -1.0*math.log(copy.deepcopy(u))/self.data["birthRate"] # Time until next stochastic birth
|
||||
eventTag = "birth"
|
||||
|
||||
v = 0.0
|
||||
while(v == 0.0):
|
||||
v = copy.deepcopy(random.random())
|
||||
v = -1.0*math.log(copy.deepcopy(v))/self.data["deathRate"] # Time until next stochastic death
|
||||
if v < u:
|
||||
u = copy.deepcopy(v)
|
||||
eventTag = "death"
|
||||
|
||||
for nIdent in self.state.nodes:
|
||||
n = self.state.nodes[nIdent] # n.ident = nIdent
|
||||
v = 0.0
|
||||
while(v == 0.0):
|
||||
v = copy.deepcopy(random.random())
|
||||
v = -1.0*math.log(copy.deepcopy(v))/n.data["intensity"]
|
||||
if v < u:
|
||||
u = copy.deepcopy(v)
|
||||
eventTag = ["discovery", n.ident]
|
||||
|
||||
# Now that all the STOCHASTIC arrivals have been decided,
|
||||
# We check if any of the deterministic events fire off instead.
|
||||
for eIdent in self.state.edges:
|
||||
e = self.state.edges[eIdent] # e.ident = eIdent
|
||||
pB = e.data["pendingBlocks"]
|
||||
if len(pB) > 0:
|
||||
for pendingIdent in pB:
|
||||
arrivalInfo = pB[pendingIdent]
|
||||
v = arrivalInfo["timeOfArrival"] - self.t
|
||||
if v < u and 0.0 < v:
|
||||
u = copy.deepcopy(v)
|
||||
eventTag = ["arrival", e.ident, pendingIdent]
|
||||
|
||||
deltaT = (u, eventTag)
|
||||
# Formats:
|
||||
# eventTag = ["arrival", e.ident, pendingIdent]
|
||||
# eventTag = ["discovery", n.ident]
|
||||
# eventTag = "death"
|
||||
# eventTag = "birth"
|
||||
return deltaT
|
||||
|
||||
def updateState(self, t, deltaT, mode="Nakamoto", targetRate=1.0/1209600.0):
|
||||
# Depending on eventTag, update the state...
|
||||
u = deltaT[0]
|
||||
shout = ""
|
||||
eventTag = deltaT[1]
|
||||
|
||||
if type(eventTag)==type("birthordeath"):
|
||||
if eventTag == "death":
|
||||
# Picks random nodeIdent and kills it
|
||||
toDie = random.choice(list(self.state.nodes.keys()))
|
||||
x = len(self.state.nodes)
|
||||
shout += "DEATH, Pop(Old)=" + str(x) + ", Pop(New)="
|
||||
if self.verbose:
|
||||
print(shout)
|
||||
self.state.delNode(toDie)
|
||||
y = len(self.state.nodes)
|
||||
assert y == x - 1
|
||||
shout += str(y) + "\n"
|
||||
|
||||
elif eventTag == "birth":
|
||||
# Adds node with some randomly determined edges
|
||||
x = len(self.state.nodes)
|
||||
shout += "BIRTH, Pop(Old)=" + str(x) + ", Pop(New)="
|
||||
if self.verbose:
|
||||
print(shout)
|
||||
nIdent = self.state.addNode()
|
||||
n = self.state.nodes[nIdent]
|
||||
intensity = random.random()/1000.0
|
||||
offset = 2.0*random.random() - 1.0
|
||||
n.data.update({"intensity":intensity, "offset":offset, "blockchain":{}})
|
||||
# Auto syncs new node.
|
||||
for eIdent in n.edges:
|
||||
e = n.edges[eIdent]
|
||||
e.data.update({"pendingBlocks":{}})
|
||||
mIdent = e.getNeighbor(n.ident)
|
||||
m = self.state.nodes[mIdent]
|
||||
mdata = m.data["blockchain"]
|
||||
n.updateBlockchain(mdata)
|
||||
y = len(self.state.nodes)
|
||||
assert y == x + 1
|
||||
shout += str(y) + "\n"
|
||||
else:
|
||||
print("Error: eventTag had length 1 but was neighter a birth or a death, this shouldn't happen so this else case will eventually be removed, I guess? Our eventTag = ", eventTag)
|
||||
elif len(eventTag)==2:
|
||||
# Block is discovered and plunked into each edge's pendingBlock list.
|
||||
|
||||
shout += "DISCOVERY\n"
|
||||
if self.verbose:
|
||||
print(shout)
|
||||
|
||||
if self.verbose:
|
||||
print("Checking formation of eventTag = [\"discovery\", nodeIdent]")
|
||||
assert eventTag[0]=="discovery"
|
||||
assert eventTag[1] in self.state.nodes
|
||||
|
||||
if self.verbose:
|
||||
print("Retrieving discoverer's identity")
|
||||
nIdent = eventTag[1] # get founding node's identity
|
||||
|
||||
if self.verbose:
|
||||
print("Retrieving discoverer")
|
||||
n = self.state.nodes[nIdent] # get founding node
|
||||
|
||||
if self.verbose:
|
||||
print("Computing discoverer's wall clock")
|
||||
s = self.t + n.data["offset"] # get founding node's wall clock
|
||||
|
||||
|
||||
if self.verbose:
|
||||
print("Generating new block identity")
|
||||
newBlockIdent = newIdent(len(n.data["blockchain"].blocks)) # generate new identity
|
||||
|
||||
if self.verbose:
|
||||
print("Setting timestamps")
|
||||
disco = s
|
||||
arriv = s
|
||||
|
||||
if self.verbose:
|
||||
print("Retrieving parent")
|
||||
parent = n.data["blockchain"].miningIdent
|
||||
|
||||
if self.verbose:
|
||||
print("getting difficulty")
|
||||
diff = copy.deepcopy(n.diff)
|
||||
|
||||
if self.verbose:
|
||||
print("setting verbosity")
|
||||
verbosity = self.verbose
|
||||
|
||||
if self.verbose:
|
||||
print("Initializing a new block")
|
||||
newBlock = Block([newBlockIdent, disco, arriv, parent, diff, verbosity])
|
||||
|
||||
if self.verbose:
|
||||
print("Updating discovering node's blockchain")
|
||||
n.updateBlockchain({newBlockIdent:newBlock})
|
||||
|
||||
if self.verbose:
|
||||
print("Computing discoverer's new difficulty")
|
||||
n.updateDifficulty(mode, targetRate)
|
||||
|
||||
if self.verbose:
|
||||
print("propagating new block.")
|
||||
n.propagate(self.t, newBlockIdent)
|
||||
|
||||
if self.verbose:
|
||||
print("discovery complete")
|
||||
|
||||
elif len(eventTag)==3:
|
||||
#eventTag = ("arrival", e.ident, pendingIdent)
|
||||
# A block deterministically arrives at the end of an edge.
|
||||
|
||||
assert eventTag[0]=="arrival"
|
||||
shout += "ARRIVAL"
|
||||
if self.verbose:
|
||||
print(shout)
|
||||
|
||||
eIdent = eventTag[1]
|
||||
pendingIdent = eventTag[2]
|
||||
e = self.state.edges[eIdent]
|
||||
pB = e.data["pendingBlocks"]
|
||||
arrivalInfo = pB[pendingIdent] # arrivalInfo = {"timeOfArrival":toa, "destIdent":mIdent, "block":newBlock}
|
||||
|
||||
assert arrivalInfo["destIdent"] in self.state.nodes
|
||||
assert self.t + u == arrivalInfo["timeOfArrival"]
|
||||
receiver = self.state.nodes[arrivalInfo["destIdent"]]
|
||||
arriv = self.t + u + receiver.data["offset"]
|
||||
newBlock = arrivalInfo["block"]
|
||||
newBlock.arrivTimestamp = copy.deepcopy(arriv)
|
||||
receiver.updateBlockchain({newBlock.ident:newBlock})
|
||||
receiver.updateDifficulty(mode, targetRate)
|
||||
receiver.propagate(self.t, newBlock.ident)
|
||||
|
||||
else:
|
||||
print("Error: eventTag was not a string, or not an array length 2 or 3. In fact, we have eventTag = ", eventTag)
|
||||
|
||||
if self.verbose:
|
||||
print("u = ", u)
|
||||
self.t += u
|
||||
if self.verbose:
|
||||
print(str(self.t) + "\t" + shout)
|
||||
|
||||
def record(self):
|
||||
with open(self.filename, "a") as f:
|
||||
line = ""
|
||||
# Format will be edgeIdent,nodeAident,nodeBident
|
||||
line += str("t=" + str(self.t) + ",")
|
||||
ordKeyList = sorted(list(self.state.edges.keys()))
|
||||
for key in ordKeyList:
|
||||
entry = []
|
||||
entry.append(key)
|
||||
nodeKeyList = sorted(list(self.state.edges[key].nodes))
|
||||
for kkey in nodeKeyList:
|
||||
entry.append(kkey)
|
||||
line += str(entry) + ","
|
||||
f.write(line + "\n")
|
||||
|
||||
class Test_FishGraph(unittest.TestCase):
|
||||
def test_fishGraph(self):
|
||||
for i in range(10):
|
||||
params = {"numNodes":10, "probEdge":0.5, "maxNeighbors":10, "maxTime":10.0, "birthRate":0.1, "deathRate":0.1}
|
||||
greg = FishGraph(params, verbosity=True)
|
||||
greg.go()
|
||||
|
||||
|
||||
suite = unittest.TestLoader().loadTestsFromTestCase(Test_FishGraph)
|
||||
unittest.TextTestRunner(verbosity=1).run(suite)
|
||||
|
||||
|
|
@ -1,101 +1,187 @@
|
|||
from Edge import *
|
||||
from Blockchain import *
|
||||
from Node import *
|
||||
from Edge import *
|
||||
from copy import *
|
||||
|
||||
def newIntensity(params):
|
||||
x = random.random()
|
||||
return x
|
||||
|
||||
def newOffset(params):
|
||||
x = 2.0*random.random() - 1.0
|
||||
return x
|
||||
|
||||
class Graph(object):
|
||||
'''
|
||||
Graph object. Contains some data, a dict of nodes, and a dict of edges.
|
||||
Explanation
|
||||
'''
|
||||
def __init__(self, params={}, verbosity=True):
|
||||
self.data=params
|
||||
self.verbose = verbosity
|
||||
def __init__(self, params):
|
||||
self.nodes = {}
|
||||
self.edges = {}
|
||||
self.mode = params[0]
|
||||
self.targetRate = params[1]
|
||||
self.numInitNodes = params[2]
|
||||
self.maxNeighbors = params[3]
|
||||
self.probEdge = params[4]
|
||||
self.verbosity = params[5]
|
||||
self.startTime = deepcopy(time.time())
|
||||
self.runTime = params[6]
|
||||
self.globalTime = deepcopy(self.startTime)
|
||||
self.birthRate = params[7]
|
||||
self.deathRate = params[8]
|
||||
self.data = params[9]
|
||||
|
||||
def createGraph(self, numNodes, probEdge, maxNeighbors):
|
||||
# Create a new random graph with numNodes nodes, a
|
||||
# likelihood any unordered pair of vertices has an edge
|
||||
# probEdge, and maximum number of neighbors per node
|
||||
# maxNeighbors.
|
||||
self.blankBlockchain = Blockchain()
|
||||
self.blankBlockchain.targetRate = self.data["targetRate"]
|
||||
self.blankBlockchain.mode = self.data["mode"]
|
||||
|
||||
# First, include inputted information into self.data
|
||||
self.data.update({"probEdge":probEdge, "maxNeighbors":maxNeighbors})
|
||||
self._createInit()
|
||||
|
||||
|
||||
def _createInit(self):
|
||||
# For simplicity, all nodes will have a genesis block with t=0.0 and no offset
|
||||
for i in range(self.numInitNodes):
|
||||
offset = newOffset()
|
||||
intens = newIntensity()
|
||||
name = newIdent(len(self.nodes))
|
||||
dat = {"offset":offset, "intensity":intens, "blockchain":deepcopy(self.blankBlockchain)}
|
||||
params = {"ident":name, "data":dat, "verbose":self.verbosity, "mode":self.mode, "targetRate":self.targetRate}
|
||||
nelly = Node(params)
|
||||
self.nodes.update({nelly.ident:nelly})
|
||||
t = self.startTime
|
||||
self.nodes[nelly.ident].generateBlock(t, i)
|
||||
|
||||
touched = {}
|
||||
for xNode in self.nodes:
|
||||
for yNode in self.nodes:
|
||||
notSameNode = (xNode != yNode)
|
||||
xNodeHasRoom = (len(self.nodes[xNode].edges) < self.maxNeighbors)
|
||||
yNodeHasRoom = (len(self.ndoes[yNode].edges) < self.maxNeighbors)
|
||||
xyNotTouched = ((xNode, yNode) not in touched)
|
||||
yxNotTouched = ((yNode, xNode) not in touched)
|
||||
if notSameNode and xNodeHasRoom and yNodeHasRoom and xyNotTouched and yxNotTouched:
|
||||
touched.update({(xNode,yNode):True, (yNode,xNode):True})
|
||||
if random.random() < self.probEdge:
|
||||
params = [newIdent(len(self.edges)), {}, self.verbosity]
|
||||
ed = Edge(params)
|
||||
ed.nodes.update({xNode:self.nodes[xNode], yNode:self.nodes[yNode]})
|
||||
self.edges.update({ed.ident:ed})
|
||||
self.nodes[xNode].edges.update({ed.ident:ed})
|
||||
self.nodes[yNode].edges.update({ed.ident:ed})
|
||||
|
||||
def eventNodeJoins(self, t):
|
||||
# timestamp,nodeJoins,numberNeighbors,neighbor1.ident,edge1.ident,neighbor2.ident,edge2.ident,...,
|
||||
out = ""
|
||||
neighbors = []
|
||||
for xNode in self.nodes:
|
||||
xNodeHasRoom = (len(self.nodes[xNode].edges) < self.maxNeighbors)
|
||||
iStillHasRoom = (len(neighbors) < self.maxNeighbors)
|
||||
if xNodeHasRoom and and iStillHasRoom and random.random() < self.probEdge:
|
||||
neighbors.append(xNode)
|
||||
|
||||
|
||||
newNodeName = newIdent(len(self.nodes))
|
||||
offset = newOffset()
|
||||
intens = newIntensity()
|
||||
dat = {"offset":offset, "intensity":intens, "blockchain":deepcopy(self.blankBlockchain)}
|
||||
params = {"ident":newNodeName, "data":dat, "verbose":self.verbosity, "mode":self.mode, "targetRate":self.targetRate}
|
||||
newNode = Node(params)
|
||||
self.nodes.update({newNode.ident:newNode})
|
||||
self.nodes[newNode.ident].generateBlock(self.startTime, 0)
|
||||
|
||||
out = str(t) + ",nodeJoins," + str(newNode.ident) + "," + str(len(neighbors)) + ","
|
||||
for neighbor in neighbors:
|
||||
out += neighbor + ","
|
||||
params = [newIdent(len(self.edges)), {}, self.verbosity]
|
||||
ed = Edge(params)
|
||||
ed.nodes.update({neighbor:self.nodes[neighbor], newNode.ident:self.nodes[newNode.ident]})
|
||||
out += ed.ident + ","
|
||||
self.edges.update({ed.ident:ed})
|
||||
self.nodes[neighbor].edges.update({ed.ident:ed})
|
||||
self.nodes[newNode.ident].edges.update({ed.ident:ed})
|
||||
return out
|
||||
|
||||
def eventNodeLeaves(self, t):
|
||||
out = str(t) + ",nodeLeaves,"
|
||||
leaverIdent = random.choice(list(self.nodes.keys()))
|
||||
out += str(leaverIdent) + ","
|
||||
leaver = self.nodes[leaverIdent]
|
||||
neighbors = []
|
||||
for ed in leaver.edges:
|
||||
neighbors.append((ed.Ident, ed.getNeighbor(leaverIdent)))
|
||||
for neighbor in neighbors:
|
||||
edIdent = neighbor[0]
|
||||
neiIdent = neighbor[1]
|
||||
del self.nodes[neiIdent].edges[edIdent]
|
||||
del self.edges[edIdent]
|
||||
del self.nodes[leaverIdent]
|
||||
return out
|
||||
|
||||
|
||||
def eventBlockDiscovery(self, discoIdent, t):
|
||||
out = str(t) + ",blockDisco," + str(discoIdent) + ","
|
||||
blockIdent = self.nodes[discoIdent].generateBlock(t)
|
||||
out += str(blockIdent)
|
||||
self.nodes[discoIdent].propagate(t, blockIdent)
|
||||
return out
|
||||
|
||||
def eventBlockArrival(self, destNodeIdent, edgeIdent, blockIdent, t):
|
||||
out = str(t) + ",blockArriv," + str(destNodeIdent) + "," + str(edgeIdent) + "," + str(blockIdent) + ","
|
||||
destNode = self.nodes[destNodeIdent]
|
||||
edge = self.edges[edgeIdent]
|
||||
block = deepcopy(edge.data["pendingBlocks"][blockIdent])
|
||||
block.arrivTimestamp = t + self.nodes[destNodeIdent].data["offset"]
|
||||
self.nodes[destNodeIdent].updateBlockchain({blockIdent:block})
|
||||
return out
|
||||
|
||||
def go(self):
|
||||
with open(self.filename,"w") as writeFile:
|
||||
writeFile.write("timestamp,eventId,eventData\n")
|
||||
|
||||
while self.globalTime - self.startTime< self.runTime:
|
||||
u = -1.0*math.log(1.0-random.random())/self.birthRate
|
||||
eventType = ("nodeJoins", None)
|
||||
|
||||
v = -1.0*math.log(1.0-random.random())/self.deathRate
|
||||
if v < u:
|
||||
eventType = ("nodeLeaves", None)
|
||||
u = v
|
||||
|
||||
for nodeIdent in self.nodes:
|
||||
localBlockDiscoRate = self.nodes[nodeIdent].data["intensity"]/self.nodes[nodeIdent].data["blockchain"].diff
|
||||
v = -1.0*math.log(1.0-random.random())/localBlockDiscoRate
|
||||
if v < u:
|
||||
eventType = ("blockDisco", nodeIdent)
|
||||
u = v
|
||||
|
||||
for edgeIdent in self.edges:
|
||||
edge = self.edges[edgeIdent]
|
||||
pB = edge.data["pendingBlocks"]
|
||||
for pendingIdent in pB:
|
||||
pendingData = pB[pendingIdent] # pendingDat = {"timeOfArrival":timeOfArrival, "destIdent":otherIdent, "block":blockToProp}
|
||||
if pendingData["timeOfArrival"] - self.globalTime < u:
|
||||
eventTime = ("blockArriv", (pendingData["destIdent"], edgeIdent, pendingData["block"]))
|
||||
u = v
|
||||
|
||||
self.globalTime += u
|
||||
out = ""
|
||||
if eventTime[0] == "nodeJoins":
|
||||
out = self.eventNodeJoins(self.globalTime)
|
||||
elif eventTime[0] == "nodeLeaves":
|
||||
out = self.eventNodeLeaves(self.globalTime)
|
||||
elif eventTime[0] == "blockDisco":
|
||||
out = self.eventBlockDiscovery(eventTime[1], self.globalTime)
|
||||
elif eventTime[0] == "blockArriv":
|
||||
out = self.eventBlockArrival(eventTime[1], eventTime[2], eventTime[3], self.globalTime)
|
||||
else:
|
||||
print("WHAAAA")
|
||||
|
||||
with open(self.filename, "a") as writeFile:
|
||||
writeFile.write(out + "\n")
|
||||
|
||||
# Next, for each node to be added, create the node and name it.
|
||||
for i in range(numNodes):
|
||||
nIdent = newIdent(i)
|
||||
bl = Blockchain([], verbosity=True)
|
||||
dat = {"blockchain":bl, "intensity":newIntensity(["uniform"]), "offset":newOffset("sumOfSkellams")}
|
||||
# A node needs an ident, a data object, a verbosity, and a difficulty
|
||||
n = Node([nIdent, dat, self.verbose, 1.0])
|
||||
self.nodes.update({n.ident:n})
|
||||
|
||||
# Next, for each possible node pair, decide if an edge exists.
|
||||
touched = {} # Dummy list of node pairs we have already considered.
|
||||
for nIdent in self.nodes:
|
||||
n = self.nodes[nIdent] # Pick a node
|
||||
for mIdent in self.nodes:
|
||||
m = self.nodes[mIdent] # Pick a pair element
|
||||
notSameNode = (nIdent != mIdent) # Ensure we aren't dealing with (x,x)
|
||||
nOpenSlots = (len(n.edges) < self.data["maxNeighbors"]) # ensure both nodes have open slots available for new edges
|
||||
mOpenSlots = (len(m.edges) < self.data["maxNeighbors"])
|
||||
untouched = ((nIdent, mIdent) not in touched) # make sure the pair and its transposition have not been touched
|
||||
dehcuotnu = ((mIdent, nIdent) not in touched)
|
||||
if notSameNode and nOpenSlots and mOpenSlots and untouched and dehcuotnu:
|
||||
# Mark pair as touhed
|
||||
touched.update({(nIdent,mIdent):True, (mIdent,nIdent):True})
|
||||
if random.random() < self.data["probEdge"]:
|
||||
# Determine if edge should exist and if so, add it.
|
||||
nonce = len(self.edges)
|
||||
e = Edge([newIdent(nonce),{"length":random.random(), "pendingBlocks":[]},self.verbose])
|
||||
e.nodes.update({n.ident:n, m.ident:m})
|
||||
self.nodes[nIdent].edges.update({e.ident:e})
|
||||
self.nodes[mIdent].edges.update({e.ident:e})
|
||||
self.edges.update({e.ident:e})
|
||||
|
||||
def addNode(self):
|
||||
# Add new node
|
||||
n = Node([newIdent(len(self.nodes)), {}, self.verbose, 1.0])
|
||||
self.nodes.update({n.ident:n})
|
||||
for mIdent in self.nodes:
|
||||
# For every other node, check if an edge should exist and if so add it.
|
||||
m = self.nodes[mIdent]
|
||||
notSameNode = (n.ident != mIdent)
|
||||
nOpenSlots = (len(n.edges) < self.data["maxNeighbors"])
|
||||
mOpenSlots = (len(m.edges) < self.data["maxNeighbors"])
|
||||
if notSameNode and nOpenSlots and mOpenSlots and random.random() < self.data["probEdge"]:
|
||||
nonce = len(self.edges)
|
||||
e = Edge([newIdent(nonce), {"length":random.random(), "pendingBlocks":[]}, self.verbose])
|
||||
e.nodes.update({n.ident:n, m.ident:m})
|
||||
n.edges.update({e.ident:e})
|
||||
self.nodes[mIdent].edges.update({e.ident:e})
|
||||
self.edges.update({e.ident:e})
|
||||
return n.ident
|
||||
|
||||
def delNode(self, ident):
|
||||
# Remove a node and wipe all memory of its edges from history.
|
||||
edgesToDelete = self.nodes[ident].edges
|
||||
for edgeIdent in edgesToDelete:
|
||||
e = edgesToDelete[edgeIdent]
|
||||
otherIdent = e.getNeighbor(ident)
|
||||
del self.edges[edgeIdent]
|
||||
del self.nodes[otherIdent].edges[edgeIdent]
|
||||
del self.nodes[ident]
|
||||
|
||||
class Test_Graph(unittest.TestCase):
|
||||
def test_graph(self):
|
||||
greg = Graph()
|
||||
greg.createGraph(3, 0.5, 10)
|
||||
self.assertEqual(len(greg.nodes),3)
|
||||
greg.addNode()
|
||||
self.assertEqual(len(greg.nodes),4)
|
||||
for edge in greg.edges:
|
||||
self.assertEqual(len(greg.edges[edge].nodes),2)
|
||||
nodeToKill = random.choice(list(greg.nodes.keys()))
|
||||
greg.delNode(nodeToKill)
|
||||
for edge in greg.edges:
|
||||
self.assertEqual(len(greg.edges[edge].nodes),2)
|
||||
for nodeIdent in greg.edges[edge].nodes:
|
||||
self.assertTrue(nodeIdent in greg.nodes)
|
||||
|
||||
suite = unittest.TestLoader().loadTestsFromTestCase(Test_Graph)
|
||||
unittest.TextTestRunner(verbosity=1).run(suite)
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,53 +0,0 @@
|
|||
import unittest, random, time
|
||||
|
||||
class StochasticProcess(object):
|
||||
'''
|
||||
Stochastic processes have a clock and a state.
|
||||
The clock moves forward, and then the state updates.
|
||||
More detail requires knowledge of the underlying stochProc.
|
||||
'''
|
||||
def __init__(self, params=None):
|
||||
# initialize with initial data
|
||||
self.data = params
|
||||
self.t = 0.0 # should always start at t=0.0
|
||||
self.state = 0.0 # magic number
|
||||
self.maxTime = 1000.0 # magic number
|
||||
self.saveFile = "output.csv"
|
||||
self.verbose = True
|
||||
|
||||
def go(self):
|
||||
# Executes stochastic process.
|
||||
assert self.maxTime > 0.0 # Check loop will eventually terminate.
|
||||
t = self.t
|
||||
while t <= self.maxTime:
|
||||
deltaT = self.getNextTime() # Pick the next "time until event" and a description of the event.
|
||||
self.updateState(t, deltaT) # Update state with deltaT input
|
||||
t = self.t
|
||||
if self.verbose:
|
||||
print("Recording...")
|
||||
self.record()
|
||||
|
||||
def getNextTime(self):
|
||||
return 1 # Magic number right now
|
||||
|
||||
def updateState(self, t, deltaT):
|
||||
# Update the state of the system. In this case,
|
||||
# we are doing a random walk on the integers.
|
||||
self.state += random.randrange(-1,2,1) # [-1, 0, 1]
|
||||
self.t += deltaT
|
||||
|
||||
def record(self):
|
||||
with open(self.saveFile,"w") as recordKeeper:
|
||||
line = str(self.t) + ",\t" + str(self.state) + "\n"
|
||||
recordKeeper.write(line)
|
||||
|
||||
class Test_StochasticProcess(unittest.TestCase):
|
||||
def test_sp(self):
|
||||
sally = StochasticProcess()
|
||||
sally.verbose = False
|
||||
sally.go()
|
||||
|
||||
suite = unittest.TestLoader().loadTestsFromTestCase(Test_StochasticProcess)
|
||||
unittest.TextTestRunner(verbosity=1).run(suite)
|
||||
|
||||
|
|
@ -1,46 +0,0 @@
|
|||
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)
|
|
@ -1,46 +0,0 @@
|
|||
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)
|
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
@ -1,116 +0,0 @@
|
|||
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)
|
||||
|
|
@ -1,116 +0,0 @@
|
|||
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)
|
||||
|
Binary file not shown.
Binary file not shown.
File diff suppressed because it is too large
Load diff
|
@ -1,602 +0,0 @@
|
|||
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
|
|
@ -1,201 +0,0 @@
|
|||
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