electrum

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

commit 2a9f5db5769e52958bc3c4f94ca53d58a8baf9d7
parent 531cdeffa9abbbbfdc4f2326dd6af252ace1b0d9
Author: SomberNight <somber.night@protonmail.com>
Date:   Fri,  3 Aug 2018 19:06:23 +0200

blockchain.py: fix: chunks in checkpoint region were not getting saved if we were on a fork

Diffstat:
Melectrum/blockchain.py | 35++++++++++++++++++++++++++++-------
1 file changed, 28 insertions(+), 7 deletions(-)

diff --git a/electrum/blockchain.py b/electrum/blockchain.py @@ -115,10 +115,17 @@ class Blockchain(util.PrintError): self.forkpoint = forkpoint self.checkpoints = constants.net.CHECKPOINTS self.parent_id = parent_id - self.lock = threading.Lock() + assert parent_id != forkpoint + self.lock = threading.RLock() with self.lock: self.update_size() + def with_lock(func): + def func_wrapper(self, *args, **kwargs): + with self.lock: + return func(self, *args, **kwargs) + return func_wrapper + def parent(self): return blockchains[self.parent_id] @@ -186,15 +193,27 @@ class Blockchain(util.PrintError): filename = 'blockchain_headers' if self.parent_id is None else os.path.join('forks', 'fork_%d_%d'%(self.parent_id, self.forkpoint)) return os.path.join(d, filename) + @with_lock def save_chunk(self, index, chunk): - d = (index * 2016 - self.forkpoint) * 80 - if d < 0: - chunk = chunk[-d:] - d = 0 - truncate = index >= len(self.checkpoints) - self.write(chunk, d, truncate) + chunk_within_checkpoint_region = index < len(self.checkpoints) + # chunks in checkpoint region are the responsibility of the 'main chain' + if chunk_within_checkpoint_region and self.parent_id is not None: + main_chain = blockchains[0] + main_chain.save_chunk(index, chunk) + return + + delta_height = (index * 2016 - self.forkpoint) + delta_bytes = delta_height * 80 + # if this chunk contains our forkpoint, only save the part after forkpoint + # (the part before is the responsibility of the parent) + if delta_bytes < 0: + chunk = chunk[-delta_bytes:] + delta_bytes = 0 + truncate = not chunk_within_checkpoint_region + self.write(chunk, delta_bytes, truncate) self.swap_with_parent() + @with_lock def swap_with_parent(self): if self.parent_id is None: return @@ -253,9 +272,11 @@ class Blockchain(util.PrintError): os.fsync(f.fileno()) self.update_size() + @with_lock def save_header(self, header): delta = header.get('block_height') - self.forkpoint data = bfh(serialize_header(header)) + # headers are only _appended_ to the end: assert delta == self.size() assert len(data) == 80 self.write(data, delta*80)