forked from awemany/valorder
-
Notifications
You must be signed in to change notification settings - Fork 0
/
validate.py
executable file
·101 lines (80 loc) · 2.94 KB
/
validate.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
#!/usr/bin/env python3
import collections
import pickle
import pprint
from parameters import *
# OTI: _Output _then _Input validation (name for tomtomtom7's scheme, unless there's a
# better one available?)
# utxo0: UTXO set after N_CHAIN transactions and just before start of block
stream, utxo0, utxo_final = pickle.load(open("stream.dat", "rb"))
block = stream[-N_BLOCK:]
# keep access stats
stats=collections.Counter()
n_workers = 5
assert N_BLOCK % n_workers == 0
# OTI_Worker:
# validation 'worker' that validates outputs first then inputs, like it is
# proposed for doing validation exploiting the DAG property and update the stats for
# global vs. local UTXO accesses.
def OTI_Worker_processOutputs(global_utxo, local_utxo, chunk):
for txid, inputs, outputs in chunk:
# Note: no explicit output loop here as outputs are simply abstracted as an integer
# save into local set
stats["local_writes"]+=1
local_utxo[txid] = outputs
def OTI_Worker_processInputs(global_utxo, local_utxo, chunk):
for txid, inputs, outputs in chunk:
for inp in inputs:
stats["local_reads"]+=1
stats["local_writes"]+=1
if inp in local_utxo:
local_utxo[inp]-=1
if local_utxo[inp] == 0:
del local_utxo[inp]
else:
local_utxo[inp]=-1
def OTI_Worker_Commit(global_utxo, local_utxo):
for txid, delta in local_utxo.items():
stats["local_reads"]+=1
stats["global_writes"]+=1
if txid in global_utxo:
global_utxo[txid]+=delta
else:
global_utxo[txid]=delta
def ValidateOutsThenIns(utxo, block):
# validate using n_workers "workers" on UTXO set utxo before block arrives.
# Use the 'outputs first, then inputs' approach like it is proposed
# for doing validation exploiting the DAG property.
# The block is in the given order
chunk_size = N_BLOCK // n_workers
chunks = [block[i * chunk_size : (i+1) * chunk_size] for i in range(n_workers)]
local_utxo={}
for chunk in chunks:
OTI_Worker_processOutputs(utxo, local_utxo, chunk)
for chunk in chunks:
OTI_Worker_processInputs(utxo, local_utxo, chunk)
OTI_Worker_Commit(utxo, local_utxo)
for k in list(utxo.keys()):
if utxo[k] == 0:
del utxo[k]
return utxo
def ValidateSequential(utxo, block):
""" Simple sequential validation for code testing, no stats. """
for txid, inputs, outputs in block:
for inp in inputs:
utxo[inp]-=1
if utxo[inp] == 0:
del utxo[inp]
utxo[txid]=outputs
return utxo
stats.clear()
utxo_val0=ValidateOutsThenIns(utxo0.copy(), block)
assert utxo_val0 == utxo_final
pp=pprint.PrettyPrinter(indent = 4)
print("Natural:")
pp.pprint(stats)
stats.clear()
utxo_val1=ValidateOutsThenIns(utxo0.copy(), sorted(block))
assert utxo_val1 == utxo_final
print("Lexicographic:")
pp.pprint(stats)