class TxVerifier(threading.Thread):
""" Simple Payment Verification """
- def __init__(self, interface, blockchain, storage):
+ def __init__(self, network, storage):
threading.Thread.__init__(self)
self.daemon = True
self.storage = storage
- self.blockchain = blockchain
- self.interface = interface
+ self.network = network
self.transactions = {} # requested verifications (with height sent by the requestor)
- self.interface.register_channel('txverifier')
self.verified_tx = storage.get('verified_tx3',{}) # height, timestamp of verified transactions
self.merkle_roots = storage.get('merkle_roots',{}) # hashed by me
self.lock = threading.Lock()
self.running = False
+ self.queue = Queue.Queue()
def get_confirmations(self, tx):
with self.lock:
if tx in self.verified_tx:
height, timestamp, pos = self.verified_tx[tx]
- conf = (self.blockchain.local_height - height + 1)
+ conf = (self.network.get_local_height() - height + 1)
if conf <= 0: timestamp = None
elif tx in self.transactions:
def stop(self):
with self.lock: self.running = False
- self.interface.poke('verifier')
def is_running(self):
with self.lock: return self.running
# request missing tx
for tx_hash, tx_height in self.transactions.items():
if tx_hash not in self.verified_tx:
+ # do not request merkle branch before headers are available
+ if tx_height > self.network.blockchain.height():
+ continue
if self.merkle_roots.get(tx_hash) is None and tx_hash not in requested_merkle:
- print_error('requesting merkle', tx_hash)
- self.interface.send([ ('blockchain.transaction.get_merkle',[tx_hash, tx_height]) ], 'txverifier')
- requested_merkle.append(tx_hash)
+ if self.network.send([ ('blockchain.transaction.get_merkle',[tx_hash, tx_height]) ], lambda i,r: self.queue.put(r)):
+ print_error('requesting merkle', tx_hash)
+ requested_merkle.append(tx_hash)
try:
- r = self.interface.get_response('txverifier',timeout=1)
+ r = self.queue.get(timeout=1)
except Queue.Empty:
continue
+
if not r: continue
if r.get('error'):
tx_height = result.get('block_height')
pos = result.get('pos')
self.merkle_roots[tx_hash] = self.hash_merkle_root(result['merkle'], tx_hash, pos)
- header = self.blockchain.read_header(tx_height)
+ header = self.network.get_header(tx_height)
if not header: return
assert header.get('merkle_root') == self.merkle_roots[tx_hash]
# we passed all the tests
self.verified_tx[tx_hash] = (tx_height, timestamp, pos)
print_error("verified %s"%tx_hash)
self.storage.put('verified_tx3', self.verified_tx, True)
- self.interface.trigger_callback('updated')
+ self.network.trigger_callback('updated')
def hash_merkle_root(self, merkle_s, target_hash, pos):
-
+ def undo_verifications(self, height):
+ with self.lock:
+ items = self.verified_tx.items()[:]
+ for tx_hash, item in items:
+ tx_height, timestamp, pos = item
+ if tx_height >= height:
+ print_error("redoing", tx_hash)
+ with self.lock:
+ self.verified_tx.pop(tx_hash)
+ if tx_hash in self.merkle_roots:
+ self.merkle_roots.pop(tx_hash)