URI: 
       tinterface: refuse to overwrite blockchain of main interface - electrum - Electrum Bitcoin wallet
  HTML git clone https://git.parazyd.org/electrum
   DIR Log
   DIR Files
   DIR Refs
   DIR Submodules
       ---
   DIR commit 9161e8c8f4f7300c9a61ba2991cfe63a696f1bbc
   DIR parent 7e1a784fcaeebf3613d9e64aaa926b7d3d60f5ba
  HTML Author: SomberNight <somber.night@protonmail.com>
       Date:   Wed, 19 Sep 2018 17:56:42 +0200
       
       interface: refuse to overwrite blockchain of main interface
       
       in case of conflicting forks
       
       Diffstat:
         M electrum/interface.py               |      18 ++++++++++++++++++
         M electrum/network.py                 |      19 ++++++++++++++-----
       
       2 files changed, 32 insertions(+), 5 deletions(-)
       ---
   DIR diff --git a/electrum/interface.py b/electrum/interface.py
       t@@ -503,11 +503,14 @@ class Interface(PrintError):
                    # is assumed to be expensive; especially as forks below the max
                    # checkpoint are ignored.
                    self.print_error("new fork at bad height {}. conflict!!".format(bad))
       +            assert self.blockchain != branch
                    ismocking = type(branch) is dict
                    if ismocking:
                        self.print_error("TODO replace blockchain")
                        return 'fork_conflict', height
                    self.print_error('forkpoint conflicts with existing fork', branch.path())
       +            self._raise_if_fork_conflicts_with_default_server(branch)
       +            self._disconnect_from_interfaces_on_conflicting_blockchain(branch)
                    branch.write(b'', 0)
                    branch.save_header(bad_header)
                    self.blockchain = branch
       t@@ -524,6 +527,21 @@ class Interface(PrintError):
                    assert b.forkpoint == bad
                    return 'fork_noconflict', height
        
       +    def _raise_if_fork_conflicts_with_default_server(self, chain_to_delete: Blockchain) -> None:
       +        main_interface = self.network.interface
       +        if not main_interface: return
       +        if main_interface == self: return
       +        chain_of_default_server = main_interface.blockchain
       +        if not chain_of_default_server: return
       +        if chain_to_delete == chain_of_default_server:
       +            raise GracefulDisconnect('refusing to overwrite blockchain of default server')
       +
       +    def _disconnect_from_interfaces_on_conflicting_blockchain(self, chain: Blockchain) -> None:
       +        ifaces = self.network.disconnect_from_interfaces_on_given_blockchain(chain)
       +        if not ifaces: return
       +        servers = [interface.server for interface in ifaces]
       +        self.print_error("forcing disconnect of other interfaces: {}".format(servers))
       +
            async def _search_headers_backwards(self, height, header):
                async def iterate():
                    nonlocal height, header
   DIR diff --git a/electrum/network.py b/electrum/network.py
       t@@ -32,7 +32,7 @@ import json
        import sys
        import ipaddress
        import asyncio
       -from typing import NamedTuple, Optional
       +from typing import NamedTuple, Optional, Sequence
        
        import dns
        import dns.resolver
       t@@ -43,6 +43,7 @@ from .util import PrintError, print_error, aiosafe, bfh
        from .bitcoin import COIN
        from . import constants
        from . import blockchain
       +from .blockchain import Blockchain
        from .interface import Interface, serialize_server, deserialize_server
        from .version import PROTOCOL_VERSION
        from .simple_config import SimpleConfig
       t@@ -708,14 +709,22 @@ class Network(PrintError):
        
            @with_interface_lock
            def get_blockchains(self):
       -        out = {}
       +        out = {}  # blockchain_id -> list(interfaces)
                with blockchain.blockchains_lock: blockchain_items = list(blockchain.blockchains.items())
       -        for k, b in blockchain_items:
       -            r = list(filter(lambda i: i.blockchain==b, list(self.interfaces.values())))
       +        for chain_id, bc in blockchain_items:
       +            r = list(filter(lambda i: i.blockchain==bc, list(self.interfaces.values())))
                    if r:
       -                out[k] = r
       +                out[chain_id] = r
                return out
        
       +    @with_interface_lock
       +    def disconnect_from_interfaces_on_given_blockchain(self, chain: Blockchain) -> Sequence[Interface]:
       +        chain_id = chain.forkpoint
       +        ifaces = self.get_blockchains().get(chain_id) or []
       +        for interface in ifaces:
       +            self.connection_down(interface.server)
       +        return ifaces
       +
            def follow_chain(self, index):
                bc = blockchain.blockchains.get(index)
                if bc: