forked from mit-ll/blockchain-simulation-framework
-
Notifications
You must be signed in to change notification settings - Fork 0
/
plot.py
107 lines (81 loc) · 2.94 KB
/
plot.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
import networkx as nx
import matplotlib.pyplot as plt
from graphviz import Digraph
def nodeLabel(node):
"""
Arguments:
node {Node} -- Node to generate graphbiz label for.
Returns:
str -- Graphviz label for node.
"""
tx = node.tx
return '<<B>%d</B><BR/>%s>' % (tx.id, tx.hash[:4])
visited = set()
def dagToDig(miner, node, digraph=None):
"""
Arguments:
miner {Miner} -- Miner object whose blockchain view is the DAG.
node {Node} -- Current node being examined in the DAG.
Keyword Arguments:
digraph {graphviz.Digraph} -- Directed graph being built. (default: {None})
Returns:
graphviz.Digraph -- Graph created from miner's DAG.
"""
global visited
node_id = "%s%d" % (node.tx.hash, miner.id)
if node in visited:
return digraph
if digraph is None:
digraph = Digraph()
digraph.graph_attr['rankdir'] = 'RL'
if node.tx in miner.consensed_tx:
digraph.node(node_id, label=nodeLabel(node), fillcolor='#ffff66', style='filled')
else:
digraph.node(node_id, label=nodeLabel(node))
visited.add(node)
for child in node.children:
child_id = "%s%d" % (child.tx.hash, miner.id)
digraph.edge(child_id, node_id)
dagToDig(miner, child, digraph)
return digraph
def plotDag(miner, fname='test.gv', view_output=True):
"""Plot the DAG of the miner's view of the blockchain.
Arguments:
miner {Miner} -- Miner whose DAG we want to plot.
Keyword Arguments:
fname {str} -- Filename to output Graphviz DOT File. (default: {'test.gv'})
"""
global visited
visited = set()
digraph = dagToDig(miner, miner.root)
digraph.render(fname, view=view_output)
def plotAllDags(miners, fname='testall.gv'):
"""Plot the DAGs of the miners' views of the blockchain.
Arguments:
miners {list(Miner)} -- Miners whose DAGs we want to plot.
Keyword Arguments:
fname {str} -- Filename to output Graphviz DOT File. (default: {'test.gv'})
"""
global visited
first_digraph = None
for miner in miners:
visited = set()
digraph = dagToDig(miner, miner.root)
if not first_digraph:
first_digraph = digraph
else:
first_digraph.subgraph(digraph)
first_digraph.render(fname, view=True)
def simplePlot(graph, pos=None):
"""Displays a simple matplotlib plot of a networkx graph
See https://networkx.github.io/documentation/stable/reference/generated/networkx.drawing.nx_pylab.draw_networkx.html#networkx.drawing.nx_pylab.draw_networkx.
Arguments:
graph {networkx.Graph} -- Graph to plot
Keyword Arguments:
pos {dict} -- Map of graph node id to tuple of x,y coordinates. (default: {None})
"""
if pos:
nx.draw_networkx(graph, with_labels=False, node_size=20, pos=pos)
else:
nx.draw_networkx(graph, with_labels=False, node_size=20)
plt.show()