URI: 
       talways save headers on disk - electrum - Electrum Bitcoin wallet
  HTML git clone https://git.parazyd.org/electrum
   DIR Log
   DIR Files
   DIR Refs
   DIR Submodules
       ---
   DIR commit 47e3630dd5b8cea309012e4454e4f6096ec56c4a
   DIR parent 12b62fb27dd6c642fc42b8bb78a4e698a5ea88e7
  HTML Author: ThomasV <thomasv@electrum.org>
       Date:   Wed, 19 Jul 2017 11:14:11 +0200
       
       always save headers on disk
       
       Diffstat:
         M lib/blockchain.py                   |      73 +++++++++----------------------
       
       1 file changed, 21 insertions(+), 52 deletions(-)
       ---
   DIR diff --git a/lib/blockchain.py b/lib/blockchain.py
       t@@ -95,8 +95,6 @@ class Blockchain(util.PrintError):
                self.config = config
                self.filename = filename
                self.catch_up = None # interface catching up
       -        self.is_saved = True
       -        self.headers = []
                if filename == 'blockchain_headers':
                    self.parent = None
                    self.checkpoint = 0
       t@@ -128,18 +126,16 @@ class Blockchain(util.PrintError):
            def fork(parent, checkpoint):
                filename = 'fork_%d_%d'%(parent.checkpoint, checkpoint)
                self = Blockchain(parent.config, filename)
       -        self.is_saved = False
       +        # create file
       +        open(self.path(), 'w+').close()
                return self
        
            def height(self):
                return self.checkpoint + self.size() - 1
        
            def size(self):
       -        if self.is_saved:
       -            p = self.path()
       -            return os.path.getsize(p)/80 if os.path.exists(p) else 0
       -        else:
       -            return len(self.headers)
       +        p = self.path()
       +        return os.path.getsize(p)/80 if os.path.exists(p) else 0
        
            def verify_header(self, header, prev_header, bits, target):
                prev_hash = hash_header(prev_header)
       t@@ -179,8 +175,6 @@ class Blockchain(util.PrintError):
                return os.path.join(d, self.filename)
        
            def save_chunk(self, index, chunk):
       -        if not self.is_saved:
       -            self.save()
                filename = self.path()
                d = (index * 2016 - self.checkpoint) * 80
                if d < 0:
       t@@ -190,75 +184,50 @@ class Blockchain(util.PrintError):
                    f.seek(d)
                    f.write(chunk)
        
       -    def save(self):
       -        # recursively save parents if they have not been saved
       -        if self.parent and not self.parent.is_saved:
       -            self.parent.save()
       -        open(self.path(), 'w+').close()
       -        for h in self.headers:
       -            self.write_header(h)
       -        self.headers = []
       -        self.is_saved = True
       -        self.print_error("saved", self.filename)
       -
            def swap_with_parent(self):
                self.print_error("swap", self.filename, self.parent.filename)
       +        assert self.size() == self.get_branch_size()
                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
       +        size = parent.get_branch_size()
                with open(parent.path(), 'rb+') as f:
                    f.seek((checkpoint - parent.checkpoint)*80)
       +            parent_data = f.read(size*80)
       +            f.seek((checkpoint - parent.checkpoint)*80)
       +            f.truncate()
       +        with open(self.path(), 'rb+') as f:
       +            my_data = f.read()
       +            f.seek(0)
                    f.truncate()
       -        parent.is_saved = False
       -        # swap chains
       +            f.write(parent_data)
       +        with open(parent.path(), 'rb+') as f:
       +            f.seek((checkpoint - parent.checkpoint)*80)
       +            f.write(my_data)
       +        # swap parameters
                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
                # update pointers
                blockchains[self.checkpoint] = self
                blockchains[parent.checkpoint] = parent
        
            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) > N:
       -                if self.parent.get_branch_size() <= N:
       -                    self.swap_with_parent()
       -                else:
       -                    self.save()
       -            return
       -        self.write_header(header)
       -
       -    def write_header(self, header):
                filename = self.path()
                delta = header.get('block_height') - self.checkpoint
                data = serialize_header(header).decode('hex')
       -        assert delta * 80 == os.path.getsize(filename)
       +        assert delta == self.size()
                assert len(data) == 80
                with open(filename, 'rb+') as f:
                    f.seek(delta * 80)
                    f.write(data)
       +        # order files
       +        if self.parent and self.parent.get_branch_size() < self.get_branch_size():
       +            self.swap_with_parent()
        
            def read_header(self, height):
                if height < self.checkpoint:
                    return self.parent.read_header(height)
                delta = height - self.checkpoint
       -        if not self.is_saved:
       -            if delta >= len(self.headers):
       -                return None
       -            header = self.headers[delta]
       -            assert header.get('block_height') == height
       -            return header
                name = self.path()
                if os.path.exists(name):
                    f = open(name, 'rb')