mirror of
https://github.com/LBRYFoundation/LBRY-Vault.git
synced 2025-08-31 09:21:39 +00:00
lnrouter: filter out unsuitable channels
This commit is contained in:
parent
42ada7ffc4
commit
ecb6922456
5 changed files with 28 additions and 19 deletions
0
electrum/lnaddr.py
Executable file → Normal file
0
electrum/lnaddr.py
Executable file → Normal file
|
@ -14,6 +14,7 @@ from typing import List
|
|||
|
||||
import aiorpcx
|
||||
|
||||
from .crypto import sha256
|
||||
from . import bitcoin
|
||||
from . import ecc
|
||||
from .ecc import sig_string_from_r_and_s, get_r_and_s_from_sig_string
|
||||
|
@ -921,22 +922,8 @@ class Peer(PrintError):
|
|||
hops_data += [OnionHopsDataSingle(OnionPerHop(b"\x00"*8, amount_msat.to_bytes(8, "big"), (final_cltv_expiry_without_deltas).to_bytes(4, "big")))]
|
||||
onion = new_onion_packet([x.node_id for x in route], secret_key, hops_data, associated_data)
|
||||
amount_msat += total_fee
|
||||
# FIXME this below will probably break with multiple HTLCs
|
||||
msat_local = chan.balance(LOCAL) - amount_msat
|
||||
msat_remote = chan.balance(REMOTE) + amount_msat
|
||||
chan.check_can_pay(amount_msat)
|
||||
htlc = {'amount_msat':amount_msat, 'payment_hash':payment_hash, 'cltv_expiry':final_cltv_expiry_with_deltas}
|
||||
# FIXME if we raise here, this channel will not get blacklisted, and the payment can never succeed,
|
||||
# as we will just keep retrying this same path. using the current blacklisting is not a solution as
|
||||
# then no other payment can use this channel either.
|
||||
# we need finer blacklisting -- e.g. a blacklist for just this "payment session"?
|
||||
# or blacklist entries could store an msat value and also expire
|
||||
if len(chan.htlcs(LOCAL, only_pending=True)) + 1 > chan.config[REMOTE].max_accepted_htlcs:
|
||||
raise PaymentFailure('too many HTLCs already in channel')
|
||||
if htlcsum(chan.htlcs(LOCAL, only_pending=True)) + amount_msat > chan.config[REMOTE].max_htlc_value_in_flight_msat:
|
||||
raise PaymentFailure('HTLC value sum would exceed max allowed: {} msat'.format(chan.config[REMOTE].max_htlc_value_in_flight_msat))
|
||||
if msat_local < 0:
|
||||
# FIXME what about channel_reserve_satoshis? will the remote fail the channel if we go below? test.
|
||||
raise PaymentFailure('not enough local balance')
|
||||
htlc_id = chan.add_htlc(htlc)
|
||||
chan.onion_keys[htlc_id] = secret_key
|
||||
self.attempted_route[(chan.channel_id, htlc_id)] = route
|
||||
|
|
|
@ -143,6 +143,25 @@ class Channel(PrintError):
|
|||
def get_state(self):
|
||||
return self._state
|
||||
|
||||
def check_can_pay(self, amount_msat):
|
||||
# FIXME what about channel_reserve_satoshis? will the remote fail the channel if we go below? test.
|
||||
# FIXME what about tx fees
|
||||
if self.get_state() != 'OPEN':
|
||||
raise PaymentFailure('Channel not open')
|
||||
if self.balance(LOCAL) < amount_msat:
|
||||
raise PaymentFailure('Not enough local balance')
|
||||
if len(self.htlcs(LOCAL, only_pending=True)) + 1 > self.config[REMOTE].max_accepted_htlcs:
|
||||
raise PaymentFailure('Too many HTLCs already in channel')
|
||||
if htlcsum(self.htlcs(LOCAL, only_pending=True)) + amount_msat > self.config[REMOTE].max_htlc_value_in_flight_msat:
|
||||
raise PaymentFailure('HTLC value sum would exceed max allowed: {} msat'.format(chan.config[REMOTE].max_htlc_value_in_flight_msat))
|
||||
|
||||
def can_pay(self, amount_msat):
|
||||
try:
|
||||
self.check_can_pay(amount_msat)
|
||||
except:
|
||||
return False
|
||||
return True
|
||||
|
||||
def set_funding_txo_spentness(self, is_spent: bool):
|
||||
assert isinstance(is_spent, bool)
|
||||
self._is_funding_txo_spent = is_spent
|
||||
|
|
|
@ -519,7 +519,7 @@ class LNPathFinder(PrintError):
|
|||
|
||||
@profiler
|
||||
def find_path_for_payment(self, from_node_id: bytes, to_node_id: bytes,
|
||||
amount_msat: int=None) -> Sequence[Tuple[bytes, bytes]]:
|
||||
amount_msat: int=None, my_channels: dict={}) -> Sequence[Tuple[bytes, bytes]]:
|
||||
"""Return a path between from_node_id and to_node_id.
|
||||
|
||||
Returns a list of (node_id, short_channel_id) representing a path.
|
||||
|
@ -527,6 +527,8 @@ class LNPathFinder(PrintError):
|
|||
i.e. an element reads as, "to get to node_id, travel through short_channel_id"
|
||||
"""
|
||||
if amount_msat is not None: assert type(amount_msat) is int
|
||||
unable_channels = set(map(lambda x: x.short_channel_id, filter(lambda x: not x.can_pay(amount_msat), my_channels.values())))
|
||||
|
||||
# TODO find multiple paths??
|
||||
|
||||
# run Dijkstra
|
||||
|
@ -546,7 +548,8 @@ class LNPathFinder(PrintError):
|
|||
# so there are duplicates in the queue, that we discard now:
|
||||
continue
|
||||
for edge_channel_id in self.channel_db.get_channels_for_node(cur_node):
|
||||
if edge_channel_id in self.blacklist: continue
|
||||
if edge_channel_id in self.blacklist or edge_channel_id in unable_channels:
|
||||
continue
|
||||
channel_info = self.channel_db.get_channel_info(edge_channel_id)
|
||||
node1, node2 = channel_info.node_id_1, channel_info.node_id_2
|
||||
neighbour = node2 if node1 == cur_node else node1
|
||||
|
|
|
@ -280,7 +280,7 @@ class LNWorker(PrintError):
|
|||
for private_route in r_tags:
|
||||
if len(private_route) == 0: continue
|
||||
border_node_pubkey = private_route[0][0]
|
||||
path = self.network.path_finder.find_path_for_payment(self.node_keypair.pubkey, border_node_pubkey, amount_msat)
|
||||
path = self.network.path_finder.find_path_for_payment(self.node_keypair.pubkey, border_node_pubkey, amount_msat, self.channels)
|
||||
if path is None: continue
|
||||
route = self.network.path_finder.create_route_from_path(path, self.node_keypair.pubkey)
|
||||
# we need to shift the node pubkey by one towards the destination:
|
||||
|
@ -293,7 +293,7 @@ class LNWorker(PrintError):
|
|||
break
|
||||
# if could not find route using any hint; try without hint now
|
||||
if route is None:
|
||||
path = self.network.path_finder.find_path_for_payment(self.node_keypair.pubkey, invoice_pubkey, amount_msat)
|
||||
path = self.network.path_finder.find_path_for_payment(self.node_keypair.pubkey, invoice_pubkey, amount_msat, self.channels)
|
||||
if path is None:
|
||||
raise PaymentFailure(_("No path found"))
|
||||
route = self.network.path_finder.create_route_from_path(path, self.node_keypair.pubkey)
|
||||
|
|
Loading…
Add table
Reference in a new issue