mirror of
https://github.com/LBRYFoundation/LBRY-Vault.git
synced 2025-08-31 17:31:36 +00:00
ln: store network addresses for channel counterparties in channels
So we can reconnect to them without relying on gossip db.
This commit is contained in:
parent
942e03e3ae
commit
fa0ef9c548
3 changed files with 38 additions and 15 deletions
|
@ -27,10 +27,12 @@ from collections import namedtuple, defaultdict
|
||||||
import binascii
|
import binascii
|
||||||
import json
|
import json
|
||||||
from enum import IntEnum
|
from enum import IntEnum
|
||||||
from typing import Optional, Dict, List, Tuple, NamedTuple, Set, Callable, Iterable, Sequence, TYPE_CHECKING
|
from typing import Optional, Dict, List, Tuple, NamedTuple, Set, Callable, Iterable, Sequence, TYPE_CHECKING, Iterator
|
||||||
import time
|
import time
|
||||||
import threading
|
import threading
|
||||||
|
|
||||||
|
from aiorpcx import NetAddress
|
||||||
|
|
||||||
from . import ecc
|
from . import ecc
|
||||||
from . import constants
|
from . import constants
|
||||||
from .util import bfh, bh2u
|
from .util import bfh, bh2u
|
||||||
|
@ -47,7 +49,7 @@ from .lnutil import (Outpoint, LocalConfig, RemoteConfig, Keypair, OnlyPubkeyKey
|
||||||
HTLC_TIMEOUT_WEIGHT, HTLC_SUCCESS_WEIGHT, extract_ctn_from_tx_and_chan, UpdateAddHtlc,
|
HTLC_TIMEOUT_WEIGHT, HTLC_SUCCESS_WEIGHT, extract_ctn_from_tx_and_chan, UpdateAddHtlc,
|
||||||
funding_output_script, SENT, RECEIVED, LOCAL, REMOTE, HTLCOwner, make_commitment_outputs,
|
funding_output_script, SENT, RECEIVED, LOCAL, REMOTE, HTLCOwner, make_commitment_outputs,
|
||||||
ScriptHtlc, PaymentFailure, calc_onchain_fees, RemoteMisbehaving, make_htlc_output_witness_script,
|
ScriptHtlc, PaymentFailure, calc_onchain_fees, RemoteMisbehaving, make_htlc_output_witness_script,
|
||||||
ShortChannelID, map_htlcs_to_ctx_output_idxs)
|
ShortChannelID, map_htlcs_to_ctx_output_idxs, LNPeerAddr)
|
||||||
from .lnsweep import create_sweeptxs_for_our_ctx, create_sweeptxs_for_their_ctx
|
from .lnsweep import create_sweeptxs_for_our_ctx, create_sweeptxs_for_their_ctx
|
||||||
from .lnsweep import create_sweeptx_for_their_revoked_htlc, SweepInfo
|
from .lnsweep import create_sweeptx_for_their_revoked_htlc, SweepInfo
|
||||||
from .lnhtlc import HTLCManager
|
from .lnhtlc import HTLCManager
|
||||||
|
@ -183,6 +185,20 @@ class Channel(Logger):
|
||||||
def get_remote_update(self) -> Optional[bytes]:
|
def get_remote_update(self) -> Optional[bytes]:
|
||||||
return bfh(self.storage.get('remote_update')) if self.storage.get('remote_update') else None
|
return bfh(self.storage.get('remote_update')) if self.storage.get('remote_update') else None
|
||||||
|
|
||||||
|
def add_or_update_peer_addr(self, peer: LNPeerAddr) -> None:
|
||||||
|
if 'peer_network_addresses' not in self.storage:
|
||||||
|
self.storage['peer_network_addresses'] = {}
|
||||||
|
now = int(time.time())
|
||||||
|
self.storage['peer_network_addresses'][peer.net_addr_str()] = now
|
||||||
|
|
||||||
|
def get_peer_addresses(self) -> Iterator[LNPeerAddr]:
|
||||||
|
# sort by timestamp: most recent first
|
||||||
|
addrs = sorted(self.storage.get('peer_network_addresses', {}).items(),
|
||||||
|
key=lambda x: x[1], reverse=True)
|
||||||
|
for net_addr_str, ts in addrs:
|
||||||
|
net_addr = NetAddress.from_string(net_addr_str)
|
||||||
|
yield LNPeerAddr(host=str(net_addr.host), port=net_addr.port, pubkey=self.node_id)
|
||||||
|
|
||||||
def get_outgoing_gossip_channel_update(self) -> bytes:
|
def get_outgoing_gossip_channel_update(self) -> bytes:
|
||||||
if self._outgoing_channel_update is not None:
|
if self._outgoing_channel_update is not None:
|
||||||
return self._outgoing_channel_update
|
return self._outgoing_channel_update
|
||||||
|
|
|
@ -202,6 +202,8 @@ class Peer(Logger):
|
||||||
raise GracefulDisconnect(f"{str(e)}")
|
raise GracefulDisconnect(f"{str(e)}")
|
||||||
if isinstance(self.transport, LNTransport):
|
if isinstance(self.transport, LNTransport):
|
||||||
self.channel_db.add_recent_peer(self.transport.peer_addr)
|
self.channel_db.add_recent_peer(self.transport.peer_addr)
|
||||||
|
for chan in self.channels.values():
|
||||||
|
chan.add_or_update_peer_addr(self.transport.peer_addr)
|
||||||
self._received_init = True
|
self._received_init = True
|
||||||
self.maybe_set_initialized()
|
self.maybe_set_initialized()
|
||||||
|
|
||||||
|
@ -597,6 +599,8 @@ class Peer(Logger):
|
||||||
lnworker=self.lnworker,
|
lnworker=self.lnworker,
|
||||||
initial_feerate=feerate)
|
initial_feerate=feerate)
|
||||||
chan.storage['funding_inputs'] = [txin.prevout.to_json() for txin in funding_tx.inputs()]
|
chan.storage['funding_inputs'] = [txin.prevout.to_json() for txin in funding_tx.inputs()]
|
||||||
|
if isinstance(self.transport, LNTransport):
|
||||||
|
chan.add_or_update_peer_addr(self.transport.peer_addr)
|
||||||
sig_64, _ = chan.sign_next_commitment()
|
sig_64, _ = chan.sign_next_commitment()
|
||||||
self.temp_id_to_id[temp_channel_id] = channel_id
|
self.temp_id_to_id[temp_channel_id] = channel_id
|
||||||
self.send_message("funding_created",
|
self.send_message("funding_created",
|
||||||
|
@ -695,6 +699,8 @@ class Peer(Logger):
|
||||||
lnworker=self.lnworker,
|
lnworker=self.lnworker,
|
||||||
initial_feerate=feerate)
|
initial_feerate=feerate)
|
||||||
chan.storage['init_timestamp'] = int(time.time())
|
chan.storage['init_timestamp'] = int(time.time())
|
||||||
|
if isinstance(self.transport, LNTransport):
|
||||||
|
chan.add_or_update_peer_addr(self.transport.peer_addr)
|
||||||
remote_sig = funding_created['signature']
|
remote_sig = funding_created['signature']
|
||||||
chan.receive_new_commitment(remote_sig, [])
|
chan.receive_new_commitment(remote_sig, [])
|
||||||
sig_64, _ = chan.sign_next_commitment()
|
sig_64, _ = chan.sign_next_commitment()
|
||||||
|
|
|
@ -1313,24 +1313,25 @@ class LNWallet(LNWorker):
|
||||||
|
|
||||||
@ignore_exceptions
|
@ignore_exceptions
|
||||||
@log_exceptions
|
@log_exceptions
|
||||||
async def reestablish_peer_for_given_channel(self, chan):
|
async def reestablish_peer_for_given_channel(self, chan: Channel) -> None:
|
||||||
now = time.time()
|
now = time.time()
|
||||||
# try last good address first
|
peer_addresses = []
|
||||||
peer = self.channel_db.get_last_good_address(chan.node_id)
|
# will try last good address first, from gossip
|
||||||
if peer:
|
last_good_addr = self.channel_db.get_last_good_address(chan.node_id)
|
||||||
|
if last_good_addr:
|
||||||
|
peer_addresses.append(last_good_addr)
|
||||||
|
# will try addresses for node_id from gossip
|
||||||
|
addrs_from_gossip = self.channel_db.get_node_addresses(chan.node_id) or []
|
||||||
|
for host, port, ts in addrs_from_gossip:
|
||||||
|
peer_addresses.append(LNPeerAddr(host, port, chan.node_id))
|
||||||
|
# will try addresses stored in channel storage
|
||||||
|
peer_addresses += list(chan.get_peer_addresses())
|
||||||
|
# now select first one that has not failed recently
|
||||||
|
for peer in peer_addresses:
|
||||||
last_tried = self._last_tried_peer.get(peer, 0)
|
last_tried = self._last_tried_peer.get(peer, 0)
|
||||||
if last_tried + PEER_RETRY_INTERVAL_FOR_CHANNELS < now:
|
if last_tried + PEER_RETRY_INTERVAL_FOR_CHANNELS < now:
|
||||||
await self._add_peer(peer.host, peer.port, peer.pubkey)
|
await self._add_peer(peer.host, peer.port, peer.pubkey)
|
||||||
return
|
return
|
||||||
# try random address for node_id
|
|
||||||
addresses = self.channel_db.get_node_addresses(chan.node_id)
|
|
||||||
if not addresses:
|
|
||||||
return
|
|
||||||
host, port, t = random.choice(list(addresses))
|
|
||||||
peer = LNPeerAddr(host, port, chan.node_id)
|
|
||||||
last_tried = self._last_tried_peer.get(peer, 0)
|
|
||||||
if last_tried + PEER_RETRY_INTERVAL_FOR_CHANNELS < now:
|
|
||||||
await self._add_peer(host, port, chan.node_id)
|
|
||||||
|
|
||||||
async def reestablish_peers_and_channels(self):
|
async def reestablish_peers_and_channels(self):
|
||||||
while True:
|
while True:
|
||||||
|
|
Loading…
Add table
Reference in a new issue