2023-01-20 11:13:50 -08:00
|
|
|
import pprint
|
2023-01-21 21:35:33 -08:00
|
|
|
import bisect
|
2023-01-20 11:13:50 -08:00
|
|
|
|
|
|
|
class SupplyDeltas:
|
|
|
|
def __init__(self, zcashd, fr_addrs, miner_deltas, flush_interval = 500):
|
|
|
|
self.zcashd = zcashd
|
|
|
|
self.fr_addrs = fr_addrs
|
|
|
|
self.miner_deltas = miner_deltas
|
|
|
|
|
|
|
|
self.delta_count = 0
|
|
|
|
self.delta_total = 0
|
|
|
|
self.delta_cache = []
|
|
|
|
self.flush_interval = flush_interval
|
|
|
|
|
|
|
|
deltas_flat = [pair for deltas in miner_deltas.values() for pair in deltas]
|
|
|
|
for (deltaHeight, delta) in sorted(deltas_flat):
|
|
|
|
self.AddSupplyDelta(deltaHeight, delta)
|
|
|
|
|
|
|
|
def AddSupplyDelta(self, deltaHeight, delta):
|
|
|
|
assert len(self.delta_cache) == 0 or deltaHeight > self.delta_cache[-1][0]
|
|
|
|
|
|
|
|
self.delta_count += 1
|
|
|
|
self.delta_total += delta
|
|
|
|
self.delta_cache.append((deltaHeight, self.delta_total))
|
|
|
|
|
|
|
|
def DeviationAtHeight(self, height):
|
2023-01-21 21:35:33 -08:00
|
|
|
i = bisect.bisect(self.delta_cache, height, key=lambda x: x[0])
|
|
|
|
return 0 if i == 0 else self.delta_cache[i - 1][1]
|
2023-01-20 11:13:50 -08:00
|
|
|
|
|
|
|
def SaveMismatch(self, block, theoretical, empirical):
|
|
|
|
height = block['height']
|
|
|
|
coinbase_tx = block['tx'][0]
|
|
|
|
delta = theoretical - empirical
|
|
|
|
|
|
|
|
print('Mismatch at height {}: {} != {} ({}) miner_deltas: {}'.format(
|
|
|
|
height,
|
|
|
|
theoretical,
|
|
|
|
empirical,
|
|
|
|
delta,
|
|
|
|
len(self.miner_deltas),
|
|
|
|
))
|
|
|
|
|
|
|
|
# if delta ever goes negative, we will halt
|
|
|
|
if delta >= 0:
|
|
|
|
miner_addrs = set([addr for out in coinbase_tx['vout'] for addr in out['scriptPubKey'].get('addresses', [])]) - self.fr_addrs
|
|
|
|
if len(miner_addrs) > 0:
|
|
|
|
self.miner_deltas.setdefault(",".join(sorted(miner_addrs)), []).append((height, delta))
|
|
|
|
self.AddSupplyDelta(height, delta)
|
|
|
|
if self.delta_count % 500 == 0:
|
|
|
|
with open("delta_cache.{}.out".format(self.delta_count), 'w', encoding="utf8") as f:
|
|
|
|
pprint.pprint(self.miner_deltas, stream = f, indent = 4)
|
|
|
|
|
|
|
|
return True
|
|
|
|
|
|
|
|
pprint.pprint(coinbase_tx['vout'], indent = 4)
|
|
|
|
return False
|
|
|
|
|
|
|
|
def PrintDeltas(self):
|
|
|
|
with open("delta_cache.out", 'w', encoding="utf8") as f:
|
|
|
|
pprint.pprint(self.miner_deltas, stream = f, indent = 4)
|