blockchain: swap a chain with its parent, if the parent branch is too short to be saved on disk
This commit is contained in:
parent
1316e4f70d
commit
50ad656c87
|
@ -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,12 +196,37 @@ 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:
|
||||
if len(self.headers) > N:
|
||||
if self.parent.get_branch_size() <= N:
|
||||
self.swap_with_parent()
|
||||
else:
|
||||
self.save()
|
||||
return
|
||||
self.write_header(header)
|
||||
|
|
|
@ -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':
|
||||
|
|
Loading…
Reference in New Issue