electrum

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

commit d71c9d5be3034bd41d5538284d7b79a495ff2bbb
parent 622f459c416cb825af8bac9bddb663647a33445f
Author: ThomasV <thomasv@electrum.org>
Date:   Mon, 24 Jul 2017 15:54:42 +0200

make blockchain.size() threadsafe

Diffstat:
Mlib/blockchain.py | 56+++++++++++++++++++++++++++++++++++++-------------------
Mlib/network.py | 3+--
2 files changed, 38 insertions(+), 21 deletions(-)

diff --git a/lib/blockchain.py b/lib/blockchain.py @@ -27,6 +27,8 @@ import os import util +import threading + import bitcoin from bitcoin import * @@ -101,6 +103,9 @@ class Blockchain(util.PrintError): self.catch_up = None # interface catching up self.checkpoint = checkpoint self.parent_id = parent_id + self.lock = threading.Lock() + with self.lock: + self.update_size() def parent(self): return blockchains[self.parent_id] @@ -124,18 +129,23 @@ class Blockchain(util.PrintError): height = header.get('block_height') return header_hash == self.get_hash(height) - def fork(parent, checkpoint): + def fork(parent, header): + checkpoint = header.get('block_height') self = Blockchain(parent.config, checkpoint, parent.checkpoint) - # create file open(self.path(), 'w+').close() + self.save_header(header) return self def height(self): return self.checkpoint + self.size() - 1 def size(self): + with self.lock: + return self._size + + def update_size(self): p = self.path() - return os.path.getsize(p)/80 if os.path.exists(p) else 0 + self._size = os.path.getsize(p)/80 if os.path.exists(p) else 0 def verify_header(self, header, prev_header, bits, target): prev_hash = hash_header(prev_header) @@ -181,9 +191,11 @@ class Blockchain(util.PrintError): if d < 0: chunk = chunk[-d:] d = 0 - with open(filename, 'rb+') as f: - f.seek(d) - f.write(chunk) + with self.lock: + with open(filename, 'rb+') as f: + f.seek(d) + f.write(chunk) + self.update_size() self.swap_with_parent() def swap_with_parent(self): @@ -199,16 +211,20 @@ class Blockchain(util.PrintError): with open(parent.path(), 'rb+') as f: f.seek((checkpoint - parent.checkpoint)*80) parent_data = f.read(parent_branch_size*80) - f.seek((checkpoint - parent.checkpoint)*80) - f.truncate() - with open(self.path(), 'rb+') as f: - my_data = f.read() - f.seek(0) - f.truncate() - f.write(parent_data) - with open(parent.path(), 'rb+') as f: - f.seek((checkpoint - parent.checkpoint)*80) - f.write(my_data) + with self.lock: + with open(self.path(), 'rb+') as f: + my_data = f.read() + f.seek(0) + f.truncate() + f.write(parent_data) + self.update_size() + with parent.lock: + with open(parent.path(), 'rb+') as f: + f.seek((checkpoint - parent.checkpoint)*80) + f.truncate() + f.seek((checkpoint - parent.checkpoint)*80) + f.write(my_data) + parent.update_size() # store file path for b in blockchains.values(): b.old_path = b.path() @@ -231,9 +247,11 @@ class Blockchain(util.PrintError): data = serialize_header(header).decode('hex') assert delta == self.size() assert len(data) == 80 - with open(filename, 'rb+') as f: - f.seek(delta * 80) - f.write(data) + with self.lock: + with open(filename, 'rb+') as f: + f.seek(delta * 80) + f.write(data) + self.update_size() # order files self.swap_with_parent() diff --git a/lib/network.py b/lib/network.py @@ -854,8 +854,7 @@ class Network(util.DaemonThread): if bh > interface.good: if not interface.blockchain.check_header(interface.bad_header): if interface.blockchain.can_connect(interface.bad_header, check_height=False): - b = interface.blockchain.fork(interface.bad) - b.save_header(interface.bad_header) + b = interface.blockchain.fork(interface.bad_header) self.blockchains[interface.bad] = b interface.blockchain = b interface.print_error("new chain", b.checkpoint)