electrum

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

commit 50ad656c87fe59e5756a64a12ce31968bb3e1301
parent 1316e4f70d3df951c804a9a82be0648b149756a6
Author: ThomasV <thomasv@electrum.org>
Date:   Tue, 18 Jul 2017 18:10:22 +0200

blockchain: swap a chain with its parent, if the parent branch is too short to be saved on disk

Diffstat:
Mlib/blockchain.py | 42++++++++++++++++++++++++++++++++++++++----
Mlib/network.py | 1-
2 files changed, 38 insertions(+), 5 deletions(-)

diff --git a/lib/blockchain.py b/lib/blockchain.py @@ -65,8 +65,8 @@ blockchains = {} def read_blockchains(config): blockchains[0] = Blockchain(config, 'blockchain_headers') - # fixme: sort - l = sorted(filter(lambda x: x.startswith('fork_'), os.listdir(config.path))) + l = filter(lambda x: x.startswith('fork_'), os.listdir(config.path)) + l = sorted(l, key = lambda x: int(x.split('_')[1])) for x in l: b = Blockchain(config, x) blockchains[b.checkpoint] = b @@ -106,6 +106,15 @@ class Blockchain(util.PrintError): else: raise BaseException('') + def get_max_child(self): + children = filter(lambda y: y.parent==self, blockchains.values()) + return max([x.checkpoint for x in children]) if children else None + + def get_branch_size(self): + mc = self.get_max_child() + checkpoint = mc if mc is not None else self.checkpoint + return self.height() - checkpoint + def check_header(self, header): header_hash = hash_header(header) height = header.get('block_height') @@ -187,13 +196,38 @@ class Blockchain(util.PrintError): self.is_saved = True self.print_error("saved", self.filename) + def swap_with_parent(self): + self.print_error("swap") + parent = self.parent + checkpoint = self.checkpoint + # copy headers + parent.headers = [parent.read_header(h) for h in range(checkpoint, checkpoint + parent.get_branch_size())] + # truncate parent file + with open(parent.path(), 'rb+') as f: + f.seek(checkpoint*80) + f.truncate() + parent.is_saved = False + # swap chains + fn = self.filename; self.filename = parent.filename; parent.filename = fn + self.parent = parent.parent; parent.parent = parent + self.checkpoint = parent.checkpoint; parent.checkpoint = checkpoint + # write my headers + for h in self.headers: + self.write_header(h) + self.headers = [] + self.is_saved = True + def save_header(self, header): + N = 10 height = header.get('block_height') if not self.is_saved: assert height == self.checkpoint + len(self.headers) self.headers.append(header) - if len(self.headers) > 10 and self.parent.size() > 10: - self.save() + if len(self.headers) > N: + if self.parent.get_branch_size() <= N: + self.swap_with_parent() + else: + self.save() return self.write_header(header) diff --git a/lib/network.py b/lib/network.py @@ -862,7 +862,6 @@ class Network(util.DaemonThread): else: interface.print_error('already catching up') next_height = None - # todo: garbage collect blockchain objects self.notify('updated') elif interface.mode == 'catch_up':