mirror of
https://github.com/LBRYFoundation/LBRY-Vault.git
synced 2025-08-29 16:31:29 +00:00
add LN gossip sync progress estimate indicator to Qt GUI
This commit is contained in:
parent
fd56fb9189
commit
67d24bf129
4 changed files with 50 additions and 9 deletions
|
@ -271,6 +271,7 @@ class ChannelDB(SqlDB):
|
||||||
self.num_channels = len(self._channels)
|
self.num_channels = len(self._channels)
|
||||||
self.num_policies = len(self._policies)
|
self.num_policies = len(self._policies)
|
||||||
self.network.trigger_callback('channel_db', self.num_nodes, self.num_channels, self.num_policies)
|
self.network.trigger_callback('channel_db', self.num_nodes, self.num_channels, self.num_policies)
|
||||||
|
self.network.trigger_callback('ln_gossip_sync_progress')
|
||||||
|
|
||||||
def get_channel_ids(self):
|
def get_channel_ids(self):
|
||||||
with self.lock:
|
with self.lock:
|
||||||
|
@ -590,19 +591,30 @@ class ChannelDB(SqlDB):
|
||||||
self._channels_for_node[channel_info.node2_id].add(channel_info.short_channel_id)
|
self._channels_for_node[channel_info.node2_id].add(channel_info.short_channel_id)
|
||||||
self.logger.info(f'load data {len(self._channels)} {len(self._policies)} {len(self._channels_for_node)}')
|
self.logger.info(f'load data {len(self._channels)} {len(self._policies)} {len(self._channels_for_node)}')
|
||||||
self.update_counts()
|
self.update_counts()
|
||||||
self.logger.info(f'semi-orphaned channels: {self.get_num_incomplete_channels()}')
|
(nchans_with_0p, nchans_with_1p, nchans_with_2p) = self.get_num_channels_partitioned_by_policy_count()
|
||||||
|
self.logger.info(f'num_channels_partitioned_by_policy_count. '
|
||||||
|
f'0p: {nchans_with_0p}, 1p: {nchans_with_1p}, 2p: {nchans_with_2p}')
|
||||||
self.data_loaded.set()
|
self.data_loaded.set()
|
||||||
|
|
||||||
def get_num_incomplete_channels(self) -> int:
|
def get_num_channels_partitioned_by_policy_count(self) -> Tuple[int, int, int]:
|
||||||
found = set()
|
chans_with_zero_policies = set()
|
||||||
|
chans_with_one_policies = set()
|
||||||
|
chans_with_two_policies = set()
|
||||||
with self.lock:
|
with self.lock:
|
||||||
_channels = self._channels.copy()
|
_channels = self._channels.copy()
|
||||||
for short_channel_id, ci in _channels.items():
|
for short_channel_id, ci in _channels.items():
|
||||||
p1 = self.get_policy_for_node(short_channel_id, ci.node1_id)
|
p1 = self.get_policy_for_node(short_channel_id, ci.node1_id)
|
||||||
p2 = self.get_policy_for_node(short_channel_id, ci.node2_id)
|
p2 = self.get_policy_for_node(short_channel_id, ci.node2_id)
|
||||||
if p1 is None or p2 is not None:
|
if p1 is not None and p2 is not None:
|
||||||
found.add(short_channel_id)
|
chans_with_two_policies.add(short_channel_id)
|
||||||
return len(found)
|
elif p1 is None and p2 is None:
|
||||||
|
chans_with_zero_policies.add(short_channel_id)
|
||||||
|
else:
|
||||||
|
chans_with_one_policies.add(short_channel_id)
|
||||||
|
nchans_with_0p = len(chans_with_zero_policies)
|
||||||
|
nchans_with_1p = len(chans_with_one_policies)
|
||||||
|
nchans_with_2p = len(chans_with_two_policies)
|
||||||
|
return nchans_with_0p, nchans_with_1p, nchans_with_2p
|
||||||
|
|
||||||
def get_policy_for_node(self, short_channel_id: bytes, node_id: bytes, *,
|
def get_policy_for_node(self, short_channel_id: bytes, node_id: bytes, *,
|
||||||
my_channels: Dict[ShortChannelID, 'Channel'] = None) -> Optional['Policy']:
|
my_channels: Dict[ShortChannelID, 'Channel'] = None) -> Optional['Policy']:
|
||||||
|
|
|
@ -265,7 +265,7 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, Logger):
|
||||||
'new_transaction', 'status',
|
'new_transaction', 'status',
|
||||||
'banner', 'verified', 'fee', 'fee_histogram', 'on_quotes',
|
'banner', 'verified', 'fee', 'fee_histogram', 'on_quotes',
|
||||||
'on_history', 'channel', 'channels_updated',
|
'on_history', 'channel', 'channels_updated',
|
||||||
'invoice_status', 'request_status']
|
'invoice_status', 'request_status', 'ln_gossip_sync_progress']
|
||||||
# To avoid leaking references to "self" that prevent the
|
# To avoid leaking references to "self" that prevent the
|
||||||
# window from being GC-ed when closed, callbacks should be
|
# window from being GC-ed when closed, callbacks should be
|
||||||
# methods of this class only, and specifically not be
|
# methods of this class only, and specifically not be
|
||||||
|
@ -430,6 +430,8 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, Logger):
|
||||||
pass
|
pass
|
||||||
elif event == 'fee_histogram':
|
elif event == 'fee_histogram':
|
||||||
self.history_model.on_fee_histogram()
|
self.history_model.on_fee_histogram()
|
||||||
|
elif event == 'ln_gossip_sync_progress':
|
||||||
|
self.update_lightning_icon()
|
||||||
else:
|
else:
|
||||||
self.logger.info(f"unexpected network event: {event} {args}")
|
self.logger.info(f"unexpected network event: {event} {args}")
|
||||||
|
|
||||||
|
@ -2085,6 +2087,20 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, Logger):
|
||||||
self.coincontrol_label.setText(msg)
|
self.coincontrol_label.setText(msg)
|
||||||
self.coincontrol_sb.setVisible(True)
|
self.coincontrol_sb.setVisible(True)
|
||||||
|
|
||||||
|
def update_lightning_icon(self): # TODO rate-limit?
|
||||||
|
self.lightning_button.setMaximumWidth(25 + 4 * char_width_in_lineedit())
|
||||||
|
cur, total = self.network.lngossip.get_sync_progress_estimate()
|
||||||
|
# self.logger.debug(f"updating lngossip sync progress estimate: cur={cur}, total={total}")
|
||||||
|
if cur is None or total is None:
|
||||||
|
progress_str = "??%"
|
||||||
|
else:
|
||||||
|
if total > 0:
|
||||||
|
progress_percent = 100 * cur // total
|
||||||
|
else:
|
||||||
|
progress_percent = 0
|
||||||
|
progress_str = f"{progress_percent}%"
|
||||||
|
self.lightning_button.setText(progress_str)
|
||||||
|
|
||||||
def update_lock_icon(self):
|
def update_lock_icon(self):
|
||||||
icon = read_QIcon("lock.png") if self.wallet.has_password() else read_QIcon("unlock.png")
|
icon = read_QIcon("lock.png") if self.wallet.has_password() else read_QIcon("unlock.png")
|
||||||
self.password_button.setIcon(icon)
|
self.password_button.setIcon(icon)
|
||||||
|
|
|
@ -125,7 +125,7 @@ class Peer(Logger):
|
||||||
self.initialized.set_result(True)
|
self.initialized.set_result(True)
|
||||||
|
|
||||||
def is_initialized(self):
|
def is_initialized(self):
|
||||||
return self.initialized.done() and self.initialized.result() == True
|
return self.initialized.done() and self.initialized.result() is True
|
||||||
|
|
||||||
async def initialize(self):
|
async def initialize(self):
|
||||||
if isinstance(self.transport, LNTransport):
|
if isinstance(self.transport, LNTransport):
|
||||||
|
|
|
@ -198,7 +198,7 @@ class LNWorker(Logger):
|
||||||
def peer_closed(self, peer: Peer) -> None:
|
def peer_closed(self, peer: Peer) -> None:
|
||||||
self.peers.pop(peer.pubkey)
|
self.peers.pop(peer.pubkey)
|
||||||
|
|
||||||
def num_peers(self):
|
def num_peers(self) -> int:
|
||||||
return sum([p.is_initialized() for p in self.peers.values()])
|
return sum([p.is_initialized() for p in self.peers.values()])
|
||||||
|
|
||||||
def start_network(self, network: 'Network'):
|
def start_network(self, network: 'Network'):
|
||||||
|
@ -359,14 +359,27 @@ class LNGossip(LNWorker):
|
||||||
self.unknown_ids.update(new)
|
self.unknown_ids.update(new)
|
||||||
self.network.trigger_callback('unknown_channels', len(self.unknown_ids))
|
self.network.trigger_callback('unknown_channels', len(self.unknown_ids))
|
||||||
self.network.trigger_callback('gossip_peers', self.num_peers())
|
self.network.trigger_callback('gossip_peers', self.num_peers())
|
||||||
|
self.network.trigger_callback('ln_gossip_sync_progress')
|
||||||
|
|
||||||
def get_ids_to_query(self):
|
def get_ids_to_query(self):
|
||||||
N = 500
|
N = 500
|
||||||
l = list(self.unknown_ids)
|
l = list(self.unknown_ids)
|
||||||
self.unknown_ids = set(l[N:])
|
self.unknown_ids = set(l[N:])
|
||||||
self.network.trigger_callback('unknown_channels', len(self.unknown_ids))
|
self.network.trigger_callback('unknown_channels', len(self.unknown_ids))
|
||||||
|
self.network.trigger_callback('ln_gossip_sync_progress')
|
||||||
return l[0:N]
|
return l[0:N]
|
||||||
|
|
||||||
|
def get_sync_progress_estimate(self) -> Tuple[Optional[int], Optional[int]]:
|
||||||
|
if self.num_peers() == 0:
|
||||||
|
return None, None
|
||||||
|
num_db_channels = self.channel_db.num_channels
|
||||||
|
nchans_with_0p, nchans_with_1p, nchans_with_2p = self.channel_db.get_num_channels_partitioned_by_policy_count()
|
||||||
|
# some channels will never have two policies (only one is in gossip?...)
|
||||||
|
# so if we have at least 1 policy for a channel, we consider that channel "complete" here
|
||||||
|
current_est = num_db_channels - nchans_with_0p
|
||||||
|
total_est = len(self.unknown_ids) + num_db_channels
|
||||||
|
return current_est, total_est
|
||||||
|
|
||||||
|
|
||||||
class LNWallet(LNWorker):
|
class LNWallet(LNWorker):
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue