commit ef5ad5f22f3d42d0dc7e1e81eaacaad84b3fcda2
parent c454564ed6e094aa36be9fbe7aa9e9113a28710c
Author: ThomasV <thomasv@electrum.org>
Date: Thu, 16 Apr 2020 12:39:12 +0200
extend 'add_peer', 'list_peers' commands to gossip
Diffstat:
3 files changed, 37 insertions(+), 34 deletions(-)
diff --git a/electrum/commands.py b/electrum/commands.py
@@ -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
@@ -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):
@@ -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"),
}
diff --git a/electrum/lnpeer.py b/electrum/lnpeer.py
@@ -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
@@ -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)}")
diff --git a/electrum/lnworker.py b/electrum/lnworker.py
@@ -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
@@ -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,
@@ -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()