spv: request previous headers recursively in order to support blockchain reorgs
This commit is contained in:
parent
1e15dbab81
commit
15a7626b14
|
@ -25,7 +25,7 @@ from bitcoin import *
|
||||||
|
|
||||||
|
|
||||||
class WalletVerifier(threading.Thread):
|
class WalletVerifier(threading.Thread):
|
||||||
""" Simple Verification Protocol """
|
""" Simple Payment Verification """
|
||||||
|
|
||||||
def __init__(self, interface, config):
|
def __init__(self, interface, config):
|
||||||
threading.Thread.__init__(self)
|
threading.Thread.__init__(self)
|
||||||
|
@ -76,14 +76,6 @@ class WalletVerifier(threading.Thread):
|
||||||
requested_chunks.append(i)
|
requested_chunks.append(i)
|
||||||
break
|
break
|
||||||
|
|
||||||
# request missing headers
|
|
||||||
if not requested_chunks and self.local_height:
|
|
||||||
for i in range(self.local_height + 1, self.height + 1):
|
|
||||||
if i not in requested_headers:
|
|
||||||
print "requesting header", i
|
|
||||||
self.interface.send([ ('blockchain.block.get_header',[i])], 'verifier')
|
|
||||||
requested_headers.append(i)
|
|
||||||
|
|
||||||
# request missing tx merkle
|
# request missing tx merkle
|
||||||
for tx in self.transactions:
|
for tx in self.transactions:
|
||||||
if tx not in self.verified_tx:
|
if tx not in self.verified_tx:
|
||||||
|
@ -127,12 +119,22 @@ class WalletVerifier(threading.Thread):
|
||||||
# process pending headers
|
# process pending headers
|
||||||
if pending_headers_changed:
|
if pending_headers_changed:
|
||||||
self.pending_headers.sort(key=lambda x: x.get('block_height'))
|
self.pending_headers.sort(key=lambda x: x.get('block_height'))
|
||||||
print "pending headers", map(lambda x: x.get('block_height'), self.pending_headers)
|
# print "pending headers", map(lambda x: x.get('block_height'), self.pending_headers)
|
||||||
|
done = []
|
||||||
for header in self.pending_headers:
|
for header in self.pending_headers:
|
||||||
if self.verify_header(header):
|
if self.verify_header(header):
|
||||||
self.pending_headers.remove(header)
|
done.append(header)
|
||||||
else:
|
else:
|
||||||
|
# request previous header
|
||||||
|
i = header.get('block_height') - 1
|
||||||
|
if i not in requested_headers:
|
||||||
|
print "requesting header", i
|
||||||
|
self.interface.send([ ('blockchain.block.get_header',[i])], 'verifier')
|
||||||
|
requested_headers.append(i)
|
||||||
|
# no point continuing
|
||||||
break
|
break
|
||||||
|
|
||||||
|
for header in done: self.pending_headers.remove(header)
|
||||||
pending_headers_changed = False
|
pending_headers_changed = False
|
||||||
|
|
||||||
self.interface.trigger_callback('updated')
|
self.interface.trigger_callback('updated')
|
||||||
|
@ -192,7 +194,7 @@ class WalletVerifier(threading.Thread):
|
||||||
prev_header = self.read_header(height -1)
|
prev_header = self.read_header(height -1)
|
||||||
if not prev_header:
|
if not prev_header:
|
||||||
print "no previous header", height
|
print "no previous header", height
|
||||||
return
|
return False
|
||||||
|
|
||||||
#prev_hash = prev_header.get('block_height')
|
#prev_hash = prev_header.get('block_height')
|
||||||
prev_hash = self.hash_header(prev_header)
|
prev_hash = self.hash_header(prev_header)
|
||||||
|
@ -202,18 +204,14 @@ class WalletVerifier(threading.Thread):
|
||||||
assert prev_hash == header.get('prev_block_hash')
|
assert prev_hash == header.get('prev_block_hash')
|
||||||
assert bits == header.get('bits')
|
assert bits == header.get('bits')
|
||||||
assert eval('0x'+_hash) < target
|
assert eval('0x'+_hash) < target
|
||||||
ok = True
|
|
||||||
except:
|
except:
|
||||||
print "verify header failed", header
|
print "verify header failed", header
|
||||||
raise
|
# this can be caused by a reorg. returning False will request the previous header.
|
||||||
# this could be caused by a reorg. request the previous header
|
return False
|
||||||
ok = False
|
|
||||||
#request previous one
|
|
||||||
|
|
||||||
if ok:
|
self.save_header(header)
|
||||||
self.save_header(header)
|
print "verify header: ok", height
|
||||||
print "verify header: ok", height
|
return True
|
||||||
return True
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -268,6 +266,7 @@ class WalletVerifier(threading.Thread):
|
||||||
self.set_local_height()
|
self.set_local_height()
|
||||||
|
|
||||||
def save_header(self, header):
|
def save_header(self, header):
|
||||||
|
# todo: invalidate tx verifications if we rewind
|
||||||
data = self.header_to_string(header).decode('hex')
|
data = self.header_to_string(header).decode('hex')
|
||||||
assert len(data) == 80
|
assert len(data) == 80
|
||||||
height = header.get('block_height')
|
height = header.get('block_height')
|
||||||
|
|
Loading…
Reference in New Issue