electrum

Electrum Bitcoin wallet
git clone https://git.parazyd.org/electrum
Log | Files | Refs | Submodules

commit 15a7626b1498d7cdd67e9db0b5b2b08cf5908229
parent 1e15dbab814b98bbd3d0abacb7a329f7a84c0103
Author: thomasv <thomasv@gitorious>
Date:   Fri, 26 Oct 2012 13:43:20 +0200

spv: request previous headers recursively in order to support blockchain reorgs

Diffstat:
Mlib/verifier.py | 43+++++++++++++++++++++----------------------
1 file changed, 21 insertions(+), 22 deletions(-)

diff --git a/lib/verifier.py b/lib/verifier.py @@ -25,7 +25,7 @@ from bitcoin import * class WalletVerifier(threading.Thread): - """ Simple Verification Protocol """ + """ Simple Payment Verification """ def __init__(self, interface, config): threading.Thread.__init__(self) @@ -76,14 +76,6 @@ class WalletVerifier(threading.Thread): requested_chunks.append(i) 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 for tx in self.transactions: if tx not in self.verified_tx: @@ -127,12 +119,22 @@ class WalletVerifier(threading.Thread): # process pending headers if pending_headers_changed: 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: if self.verify_header(header): - self.pending_headers.remove(header) + done.append(header) 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 + + for header in done: self.pending_headers.remove(header) pending_headers_changed = False self.interface.trigger_callback('updated') @@ -192,7 +194,7 @@ class WalletVerifier(threading.Thread): prev_header = self.read_header(height -1) if not prev_header: print "no previous header", height - return + return False #prev_hash = prev_header.get('block_height') prev_hash = self.hash_header(prev_header) @@ -202,18 +204,14 @@ class WalletVerifier(threading.Thread): assert prev_hash == header.get('prev_block_hash') assert bits == header.get('bits') assert eval('0x'+_hash) < target - ok = True except: print "verify header failed", header - raise - # this could be caused by a reorg. request the previous header - ok = False - #request previous one - - if ok: - self.save_header(header) - print "verify header: ok", height - return True + # this can be caused by a reorg. returning False will request the previous header. + return False + + self.save_header(header) + print "verify header: ok", height + return True @@ -268,6 +266,7 @@ class WalletVerifier(threading.Thread): self.set_local_height() def save_header(self, header): + # todo: invalidate tx verifications if we rewind data = self.header_to_string(header).decode('hex') assert len(data) == 80 height = header.get('block_height')