self.interface = interface
self.transactions = [] # monitored transactions
self.interface.register_channel('verifier')
- self.verified_tx = config.get('verified_tx',{})
+
+ self.verified_tx = config.get('verified_tx',{}) # height of verified tx
self.merkle_roots = config.get('merkle_roots',{}) # hashed by me
+
self.targets = config.get('targets',{}) # compute targets
self.lock = threading.Lock()
self.pending_headers = [] # headers that have not been verified
def get_confirmations(self, tx):
""" return the number of confirmations of a monitored transaction. """
with self.lock:
- assert tx in self.transactions
- return (self.local_height - self.verified_tx[tx] + 1) if tx in self.verified_tx else 0
+ if tx in self.transactions:
+ return (self.local_height - self.verified_tx[tx] + 1) if tx in self.verified_tx else 0
+ else:
+ return 0
- def add(self, tx):
+ def add(self, tx_hash):
""" add a transaction to the list of monitored transactions. """
with self.lock:
- if tx not in self.transactions:
- self.transactions.append(tx)
+ if tx_hash not in self.transactions:
+ self.transactions.append(tx_hash)
def run(self):
requested_merkle = []
all_chunks = True
print_error("downloaded all chunks")
- # request missing tx merkle
- for tx in self.transactions:
- if tx not in self.verified_tx:
- if tx not in requested_merkle:
- requested_merkle.append(tx)
- self.request_merkle(tx)
- #break
-
+ # request missing tx
+ if all_chunks:
+ for tx_hash in self.transactions:
+ if tx_hash not in self.verified_tx:
+ 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]) ], 'verifier')
+ requested_merkle.append(tx_hash)
# process pending headers
if self.pending_headers and all_chunks:
self.pending_headers.sort(key=lambda x: x.get('block_height'))
# print "pending headers", map(lambda x: x.get('block_height'), self.pending_headers)
-
-
self.interface.trigger_callback('updated')
- def request_merkle(self, tx_hash):
- self.interface.send([ ('blockchain.transaction.get_merkle',[tx_hash]) ], 'verifier')
-
def verify_merkle(self, tx_hash, result):
tx_height = result.get('block_height')
self.merkle_roots[tx_hash] = self.hash_merkle_root(result['merkle'], tx_hash, result.get('pos'))
header = self.read_header(tx_height)
- if header:
- assert header.get('merkle_root') == self.merkle_roots[tx_hash]
- self.verified_tx[tx_hash] = tx_height
- print_error("verified %s"%tx_hash)
- self.config.set_key('verified_tx', self.verified_tx, True)
-
+ 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
+ print_error("verified %s"%tx_hash)
+ self.config.set_key('verified_tx', self.verified_tx, True)
def verify_chunk(self, index, hexdata):
data = hexdata.decode('hex')
# undo verifications
for tx_hash, tx_height in self.verified_tx.items():
if tx_height >= height:
- print "redoing", tx_hash
+ print_error("redoing", tx_hash)
self.verified_tx.pop(tx_hash)
+ if tx_hash in self.merkle_roots: self.merkle_roots.pop(tx_hash)
# return False to request previous header.
return False
self.save_header(header)
- print_error("verify header: ok %d"%height)
+ print_error("verify header:", _hash, height)
return True
def save_chunk(self, index, chunk):
filename = self.path()
if os.path.exists(filename):
- f = open(filename,'rw+')
+ f = open(filename,'rb+')
else:
- print "creating file", filename
- f = open(filename,'w+')
+ print_error( "creating file", filename )
+ f = open(filename,'wb+')
f.seek(index*2016*80)
h = f.write(chunk)
f.close()
assert len(data) == 80
height = header.get('block_height')
filename = self.path()
- f = open(filename,'rw+')
+ f = open(filename,'rb+')
f.seek(height*80)
h = f.write(data)
f.close()