URI: 
       textend 'add_peer', 'list_peers' commands to gossip - electrum - Electrum Bitcoin wallet
  HTML git clone https://git.parazyd.org/electrum
   DIR Log
   DIR Files
   DIR Refs
   DIR Submodules
       ---
   DIR commit ef5ad5f22f3d42d0dc7e1e81eaacaad84b3fcda2
   DIR parent c454564ed6e094aa36be9fbe7aa9e9113a28710c
  HTML Author: ThomasV <thomasv@electrum.org>
       Date:   Thu, 16 Apr 2020 12:39:12 +0200
       
       extend 'add_peer', 'list_peers' commands to gossip
       
       Diffstat:
         M electrum/commands.py                |      13 +++++++++----
         M electrum/lnpeer.py                  |       9 +++++----
         M electrum/lnworker.py                |      49 +++++++++++++++----------------
       
       3 files changed, 37 insertions(+), 34 deletions(-)
       ---
   DIR diff --git a/electrum/commands.py b/electrum/commands.py
       t@@ -53,6 +53,7 @@ from .wallet import Abstract_Wallet, create_new_wallet, restore_wallet_from_text
        from .address_synchronizer import TX_HEIGHT_LOCAL
        from .mnemonic import Mnemonic
        from .lnutil import SENT, RECEIVED
       +from .lnutil import LnFeatures
        from .lnutil import ln_dummy_address
        from .lnpeer import channel_id_from_funding_tx
        from .plugin import run_hook
       t@@ -965,18 +966,21 @@ class Commands:
        
            # lightning network commands
            @command('wn')
       -    async def add_peer(self, connection_string, timeout=20, wallet: Abstract_Wallet = None):
       -        await wallet.lnworker.add_peer(connection_string)
       +    async def add_peer(self, connection_string, timeout=20, gossip=False, wallet: Abstract_Wallet = None):
       +        lnworker = self.network.lngossip if gossip else wallet.lnworker
       +        await lnworker.add_peer(connection_string)
                return True
        
            @command('wn')
       -    async def list_peers(self, wallet: Abstract_Wallet = None):
       +    async def list_peers(self, gossip=False, wallet: Abstract_Wallet = None):
       +        lnworker = self.network.lngossip if gossip else wallet.lnworker
                return [{
                    'node_id':p.pubkey.hex(),
                    'address':p.transport.name(),
                    'initialized':p.is_initialized(),
       +            'features': str(LnFeatures(p.features)),
                    'channels': [c.funding_outpoint.to_str() for c in p.channels.values()],
       -        } for p in wallet.lnworker.peers.values()]
       +        } for p in lnworker.peers.values()]
        
            @command('wpn')
            async def open_channel(self, connection_string, amount, push_amount=0, password=None, wallet: Abstract_Wallet = None):
       t@@ -1165,6 +1169,7 @@ command_options = {
            'from_height': (None, "Only show transactions that confirmed after given block height"),
            'to_height':   (None, "Only show transactions that confirmed before given block height"),
            'iknowwhatimdoing': (None, "Acknowledge that I understand the full implications of what I am about to do"),
       +    'gossip':      (None, "Apply command to gossip node instead of wallet"),
        }
        
        
   DIR diff --git a/electrum/lnpeer.py b/electrum/lnpeer.py
       t@@ -74,6 +74,7 @@ class Peer(Logger):
                self.lnworker = lnworker
                self.privkey = self.transport.privkey  # local privkey
                self.features = self.lnworker.features
       +        self.their_features = 0
                self.node_ids = [self.pubkey, privkey_to_pubkey(self.privkey)]
                self.network = lnworker.network
                self.channel_db = lnworker.network.channel_db
       t@@ -200,15 +201,15 @@ class Peer(Logger):
                if self._received_init:
                    self.logger.info("ALREADY INITIALIZED BUT RECEIVED INIT")
                    return
       -        their_features = LnFeatures(int.from_bytes(payload['features'], byteorder="big"))
       +        self.their_features = LnFeatures(int.from_bytes(payload['features'], byteorder="big"))
                their_globalfeatures = int.from_bytes(payload['globalfeatures'], byteorder="big")
       -        their_features |= their_globalfeatures
       +        self.their_features |= their_globalfeatures
                # check transitive dependencies for received features
       -        if not their_features.validate_transitive_dependecies():
       +        if not self.their_features.validate_transitive_dependecies():
                    raise GracefulDisconnect("remote did not set all dependencies for the features they sent")
                # check if features are compatible, and set self.features to what we negotiated
                try:
       -            self.features = ln_compare_features(self.features, their_features)
       +            self.features = ln_compare_features(self.features, self.their_features)
                except IncompatibleLightningFeatures as e:
                    self.initialized.set_exception(e)
                    raise GracefulDisconnect(f"{str(e)}")
   DIR diff --git a/electrum/lnworker.py b/electrum/lnworker.py
       t@@ -392,6 +392,29 @@ class LNWorker(Logger, NetworkRetryManager[LNPeerAddr]):
                    peer.close_and_cleanup()
                self._clear_addr_retry_times()
        
       +    @log_exceptions
       +    async def add_peer(self, connect_str: str) -> Peer:
       +        node_id, rest = extract_nodeid(connect_str)
       +        peer = self._peers.get(node_id)
       +        if not peer:
       +            if rest is not None:
       +                host, port = split_host_port(rest)
       +            else:
       +                addrs = self.channel_db.get_node_addresses(node_id)
       +                if not addrs:
       +                    raise ConnStringFormatError(_('Don\'t know any addresses for node:') + ' ' + bh2u(node_id))
       +                host, port, timestamp = self.choose_preferred_address(addrs)
       +            port = int(port)
       +            # Try DNS-resolving the host (if needed). This is simply so that
       +            # the caller gets a nice exception if it cannot be resolved.
       +            try:
       +                await asyncio.get_event_loop().getaddrinfo(host, port)
       +            except socket.gaierror:
       +                raise ConnStringFormatError(_('Hostname does not resolve (getaddrinfo failed)'))
       +            # add peer
       +            peer = await self._add_peer(host, port, node_id)
       +        return peer
       +
        
        class LNGossip(LNWorker):
            max_age = 14*24*3600
       t@@ -716,9 +739,6 @@ class LNWallet(LNWorker):
                        self.logger.info('REBROADCASTING CLOSING TX')
                        await self.network.try_broadcasting(force_close_tx, 'force-close')
        
       -
       -
       -
            @log_exceptions
            async def _open_channel_coroutine(self, *, connect_str: str, funding_tx: PartialTransaction,
                                              funding_sat: int, push_sat: int,
       t@@ -750,29 +770,6 @@ class LNWallet(LNWorker):
                channels_db[chan.channel_id.hex()] = chan.storage
                self.wallet.save_backup()
        
       -    @log_exceptions
       -    async def add_peer(self, connect_str: str) -> Peer:
       -        node_id, rest = extract_nodeid(connect_str)
       -        peer = self._peers.get(node_id)
       -        if not peer:
       -            if rest is not None:
       -                host, port = split_host_port(rest)
       -            else:
       -                addrs = self.channel_db.get_node_addresses(node_id)
       -                if not addrs:
       -                    raise ConnStringFormatError(_('Don\'t know any addresses for node:') + ' ' + bh2u(node_id))
       -                host, port, timestamp = self.choose_preferred_address(addrs)
       -            port = int(port)
       -            # Try DNS-resolving the host (if needed). This is simply so that
       -            # the caller gets a nice exception if it cannot be resolved.
       -            try:
       -                await asyncio.get_event_loop().getaddrinfo(host, port)
       -            except socket.gaierror:
       -                raise ConnStringFormatError(_('Hostname does not resolve (getaddrinfo failed)'))
       -            # add peer
       -            peer = await self._add_peer(host, port, node_id)
       -        return peer
       -
            def mktx_for_open_channel(self, *, coins: Sequence[PartialTxInput], funding_sat: int,
                                      fee_est=None) -> PartialTransaction:
                dummy_address = ln_dummy_address()