blockchain: store reference to parent_id instead of parent, so that it gets updated after swap

This commit is contained in:
ThomasV 2017-07-20 15:05:47 +02:00
parent c3615d0aa7
commit c522c6b4d0
2 changed files with 20 additions and 16 deletions

View file

@ -69,8 +69,8 @@ def read_blockchains(config):
l = sorted(l, key = lambda x: int(x.split('_')[1])) l = sorted(l, key = lambda x: int(x.split('_')[1]))
for filename in l: for filename in l:
checkpoint = int(filename.split('_')[2]) checkpoint = int(filename.split('_')[2])
parent = blockchains[int(filename.split('_')[1])] parent_id = int(filename.split('_')[1])
b = Blockchain(config, checkpoint, parent) b = Blockchain(config, checkpoint, parent_id)
blockchains[b.checkpoint] = b blockchains[b.checkpoint] = b
return blockchains return blockchains
@ -93,14 +93,17 @@ class Blockchain(util.PrintError):
'''Manages blockchain headers and their verification''' '''Manages blockchain headers and their verification'''
def __init__(self, config, checkpoint, parent): def __init__(self, config, checkpoint, parent_id):
self.config = config self.config = config
self.catch_up = None # interface catching up self.catch_up = None # interface catching up
self.checkpoint = checkpoint self.checkpoint = checkpoint
self.parent = parent self.parent_id = parent_id
def parent(self):
return blockchains[self.parent_id]
def get_max_child(self): def get_max_child(self):
children = filter(lambda y: y.parent==self, blockchains.values()) children = filter(lambda y: y.parent_id==self.checkpoint, blockchains.values())
return max([x.checkpoint for x in children]) if children else None return max([x.checkpoint for x in children]) if children else None
def get_checkpoint(self): def get_checkpoint(self):
@ -119,7 +122,7 @@ class Blockchain(util.PrintError):
return header_hash == self.get_hash(height) return header_hash == self.get_hash(height)
def fork(parent, checkpoint): def fork(parent, checkpoint):
self = Blockchain(parent.config, checkpoint, parent) self = Blockchain(parent.config, checkpoint, parent.checkpoint)
# create file # create file
open(self.path(), 'w+').close() open(self.path(), 'w+').close()
return self return self
@ -166,7 +169,7 @@ class Blockchain(util.PrintError):
def path(self): def path(self):
d = util.get_headers_dir(self.config) d = util.get_headers_dir(self.config)
filename = 'blockchain_headers' if self.parent is None else 'fork_%d_%d'%(self.parent.checkpoint, self.checkpoint) filename = 'blockchain_headers' if self.parent_id is None else 'fork_%d_%d'%(self.parent_id, self.checkpoint)
return os.path.join(d, filename) return os.path.join(d, filename)
def save_chunk(self, index, chunk): def save_chunk(self, index, chunk):
@ -179,13 +182,14 @@ class Blockchain(util.PrintError):
f.seek(d) f.seek(d)
f.write(chunk) f.write(chunk)
# order files # order files
if self.parent and self.parent.get_branch_size() < self.get_branch_size(): if self.parent_id is not None and self.parent().get_branch_size() < self.size():
self.swap_with_parent() self.swap_with_parent()
def swap_with_parent(self): def swap_with_parent(self):
self.print_error("swap", self.checkpoint, self.parent.checkpoint) self.print_error("swap", self.checkpoint, self.parent_id)
parent = self.parent parent_id = self.parent_id
checkpoint = self.checkpoint checkpoint = self.checkpoint
parent = self.parent()
size = parent.get_branch_size() size = parent.get_branch_size()
with open(parent.path(), 'rb+') as f: with open(parent.path(), 'rb+') as f:
f.seek((checkpoint - parent.checkpoint)*80) f.seek((checkpoint - parent.checkpoint)*80)
@ -204,7 +208,7 @@ class Blockchain(util.PrintError):
for b in blockchains.values(): for b in blockchains.values():
b.old_path = b.path() b.old_path = b.path()
# swap parameters # swap parameters
self.parent = parent.parent; parent.parent = self self.parent_id = parent.parent_id; parent.parent_id = parent_id
self.checkpoint = parent.checkpoint; parent.checkpoint = checkpoint self.checkpoint = parent.checkpoint; parent.checkpoint = checkpoint
# move files # move files
for b in blockchains.values(): for b in blockchains.values():
@ -226,13 +230,13 @@ class Blockchain(util.PrintError):
f.seek(delta * 80) f.seek(delta * 80)
f.write(data) f.write(data)
# order files # order files
if self.parent and self.parent.get_branch_size() < self.get_branch_size(): if self.parent_id is not None and self.parent().get_branch_size() < self.size():
self.swap_with_parent() self.swap_with_parent()
def read_header(self, height): def read_header(self, height):
assert self.parent != self assert self.parent_id != self.checkpoint
if height < self.checkpoint: if height < self.checkpoint:
return self.parent.read_header(height) return self.parent().read_header(height)
if height > self.height(): if height > self.height():
return return
delta = height - self.checkpoint delta = height - self.checkpoint

View file

@ -835,9 +835,9 @@ class Network(util.DaemonThread):
if branch is not None: if branch is not None:
if branch.check_header(interface.bad_header): if branch.check_header(interface.bad_header):
interface.print_error('joining chain', interface.bad) interface.print_error('joining chain', interface.bad)
elif branch.parent.check_header(header): elif branch.parent().check_header(header):
interface.print_error('reorg', interface.bad, interface.tip) interface.print_error('reorg', interface.bad, interface.tip)
interface.blockchain = branch.parent interface.blockchain = branch.parent()
else: else:
# should not happen # should not happen
raise BaseException('error') raise BaseException('error')