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:
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)