fix #750
[electrum-nvc.git] / lib / verifier.py
index 5a86164..c97c5e7 100644 (file)
@@ -27,18 +27,17 @@ from bitcoin import *
 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):
@@ -46,7 +45,7 @@ class TxVerifier(threading.Thread):
         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:
@@ -90,27 +89,32 @@ class TxVerifier(threading.Thread):
 
     def stop(self):
         with self.lock: self.running = False
-        self.interface.poke('verifier')
 
     def is_running(self):
         with self.lock: return self.running
 
     def run(self):
+        with self.lock:
+            self.running = True
+        requested_merkle = []
 
         while self.is_running():
             # request missing tx
-            if all_chunks:
-                for tx_hash, tx_height in self.transactions.items():
-                    if tx_hash not in self.verified_tx:
-                        if self.merkle_roots.get(tx_hash) is None and tx_hash not in requested_merkle:
+            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:
+                        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)
-                            self.interface.send([ ('blockchain.transaction.get_merkle',[tx_hash, tx_height]) ], 'txverifier')
                             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'):
@@ -132,17 +136,16 @@ class TxVerifier(threading.Thread):
         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
-        header = self.read_header(tx_height)
         timestamp = header.get('timestamp')
         with self.lock:
             self.verified_tx[tx_hash] = (tx_height, timestamp, pos)
         print_error("verified %s"%tx_hash)
-        self.storage.set_key('verified_tx3', self.verified_tx, True)
-        self.interface.trigger_callback('updated')
+        self.storage.put('verified_tx3', self.verified_tx, True)
+        self.network.trigger_callback('updated')
 
 
     def hash_merkle_root(self, merkle_s, target_hash, pos):
@@ -154,4 +157,14 @@ class TxVerifier(threading.Thread):
 
 
 
-
+    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)