Browse Source

Merge remote-tracking branch 'remotes/bitromortac-fork/2107-fix-self-payments'

patch-4
SomberNight 4 years ago
parent
commit
55c988d540
No known key found for this signature in database GPG Key ID: B33B5F232C6271E9
  1. 28
      electrum/lnrouter.py
  2. 26
      electrum/lnworker.py

28
electrum/lnrouter.py

@ -517,7 +517,7 @@ class LNPathFinder(Logger):
nodeA: bytes,
nodeB: bytes,
invoice_amount_msat: int,
my_channels: Dict[ShortChannelID, 'Channel'] = None,
my_sending_channels: Dict[ShortChannelID, 'Channel'] = None,
private_route_edges: Dict[ShortChannelID, RouteEdge] = None,
) -> Dict[bytes, PathEdge]:
# note: we don't lock self.channel_db, so while the path finding runs,
@ -551,24 +551,24 @@ class LNPathFinder(Logger):
edge_endnode, my_channels={}, private_route_edges=private_route_edges)
else: # in the next steps, we only take sending channels
channels_for_endnode = self.channel_db.get_channels_for_node(
edge_endnode, my_channels=my_channels, private_route_edges={})
edge_endnode, my_channels=my_sending_channels, private_route_edges={})
else:
channels_for_endnode = self.channel_db.get_channels_for_node(
edge_endnode, my_channels=my_channels, private_route_edges=private_route_edges)
edge_endnode, my_channels=my_sending_channels, private_route_edges=private_route_edges)
for edge_channel_id in channels_for_endnode:
assert isinstance(edge_channel_id, bytes)
if blacklist and edge_channel_id in blacklist:
continue
channel_info = self.channel_db.get_channel_info(
edge_channel_id, my_channels=my_channels, private_route_edges=private_route_edges)
edge_channel_id, my_channels=my_sending_channels, private_route_edges=private_route_edges)
if channel_info is None:
continue
edge_startnode = channel_info.node2_id if channel_info.node1_id == edge_endnode else channel_info.node1_id
is_mine = edge_channel_id in my_channels
is_mine = edge_channel_id in my_sending_channels
if is_mine:
if edge_startnode == nodeA: # payment outgoing, on our channel
if not my_channels[edge_channel_id].can_pay(amount_msat, check_frozen=True):
if not my_sending_channels[edge_channel_id].can_pay(amount_msat, check_frozen=True):
continue
edge_cost, fee_for_edge_msat = self._edge_cost(
short_channel_id=edge_channel_id,
@ -577,7 +577,7 @@ class LNPathFinder(Logger):
payment_amt_msat=amount_msat,
ignore_costs=(edge_startnode == nodeA),
is_mine=is_mine,
my_channels=my_channels,
my_channels=my_sending_channels,
private_route_edges=private_route_edges)
alt_dist_to_neighbour = distance_from_start[edge_endnode] + edge_cost
if alt_dist_to_neighbour < distance_from_start[edge_startnode]:
@ -601,21 +601,21 @@ class LNPathFinder(Logger):
nodeA: bytes,
nodeB: bytes,
invoice_amount_msat: int,
my_channels: Dict[ShortChannelID, 'Channel'] = None,
my_sending_channels: Dict[ShortChannelID, 'Channel'] = None,
private_route_edges: Dict[ShortChannelID, RouteEdge] = None,
) -> Optional[LNPaymentPath]:
"""Return a path from nodeA to nodeB."""
assert type(nodeA) is bytes
assert type(nodeB) is bytes
assert type(invoice_amount_msat) is int
if my_channels is None:
my_channels = {}
if my_sending_channels is None:
my_sending_channels = {}
previous_hops = self.get_shortest_path_hops(
nodeA=nodeA,
nodeB=nodeB,
invoice_amount_msat=invoice_amount_msat,
my_channels=my_channels,
my_sending_channels=my_sending_channels,
private_route_edges=private_route_edges)
if nodeA not in previous_hops:
@ -677,7 +677,7 @@ class LNPathFinder(Logger):
nodeB: bytes,
invoice_amount_msat: int,
path = None,
my_channels: Dict[ShortChannelID, 'Channel'] = None,
my_sending_channels: Dict[ShortChannelID, 'Channel'] = None,
private_route_edges: Dict[ShortChannelID, RouteEdge] = None,
) -> Optional[LNPaymentRoute]:
route = None
@ -686,9 +686,9 @@ class LNPathFinder(Logger):
nodeA=nodeA,
nodeB=nodeB,
invoice_amount_msat=invoice_amount_msat,
my_channels=my_channels,
my_sending_channels=my_sending_channels,
private_route_edges=private_route_edges)
if path:
route = self.create_route_from_path(
path, my_channels=my_channels, private_route_edges=private_route_edges)
path, my_channels=my_sending_channels, private_route_edges=private_route_edges)
return route

26
electrum/lnworker.py

@ -1467,11 +1467,12 @@ class LNWallet(LNWorker):
invoice_features = LnFeatures(invoice_features)
trampoline_features = LnFeatures.VAR_ONION_OPT
local_height = self.network.get_local_height()
active_channels = [chan for chan in self.channels.values() if chan.is_active() and not chan.is_frozen_for_sending()]
my_active_channels = [chan for chan in self.channels.values() if
chan.is_active() and not chan.is_frozen_for_sending()]
try:
# try to send over a single channel
if not self.channel_db:
for chan in active_channels:
for chan in my_active_channels:
if not self.is_trampoline_peer(chan.node_id):
continue
if chan.node_id == invoice_pubkey:
@ -1522,7 +1523,7 @@ class LNWallet(LNWorker):
min_cltv_expiry=min_cltv_expiry,
r_tags=r_tags,
invoice_features=invoice_features,
channels=active_channels,
my_sending_channels=my_active_channels,
full_path=full_path
)
)
@ -1530,9 +1531,8 @@ class LNWallet(LNWorker):
except NoPathFound:
if not invoice_features.supports(LnFeatures.BASIC_MPP_OPT):
raise
channels_with_funds = {
(chan.channel_id, chan.node_id): int(chan.available_to_spend(HTLCOwner.LOCAL))
for chan in active_channels}
channels_with_funds = {(chan.channel_id, chan.node_id): int(chan.available_to_spend(HTLCOwner.LOCAL))
for chan in my_active_channels}
self.logger.info(f"channels_with_funds: {channels_with_funds}")
# for trampoline mpp payments we have to restrict ourselves to pay
# to a single node due to some incompatibility in Eclair, see:
@ -1603,7 +1603,7 @@ class LNWallet(LNWorker):
min_cltv_expiry=min_cltv_expiry,
r_tags=r_tags,
invoice_features=invoice_features,
channels=[channel],
my_sending_channels=[channel],
full_path=None
)
)
@ -1623,13 +1623,11 @@ class LNWallet(LNWorker):
min_cltv_expiry: int,
r_tags,
invoice_features: int,
channels: List[Channel],
my_sending_channels: List[Channel],
full_path: Optional[LNPaymentPath]) -> LNPaymentRoute:
scid_to_my_channels = {
chan.short_channel_id: chan for chan in channels
if chan.short_channel_id is not None
}
my_sending_channels = {chan.short_channel_id: chan for chan in my_sending_channels
if chan.short_channel_id is not None}
# Collect all private edges from route hints.
# Note: if some route hints are multiple edges long, and these paths cross each other,
# we allow our path finding to cross the paths; i.e. the route hints are not isolated.
@ -1647,7 +1645,7 @@ class LNWallet(LNWorker):
channel_policy = self.channel_db.get_policy_for_node(
short_channel_id=short_channel_id,
node_id=start_node,
my_channels=scid_to_my_channels)
my_channels=my_sending_channels)
if channel_policy:
fee_base_msat = channel_policy.fee_base_msat
fee_proportional_millionths = channel_policy.fee_proportional_millionths
@ -1670,7 +1668,7 @@ class LNWallet(LNWorker):
nodeB=invoice_pubkey,
invoice_amount_msat=amount_msat,
path=full_path,
my_channels=scid_to_my_channels,
my_sending_channels=my_sending_channels,
private_route_edges=private_route_edges)
except NoChannelPolicy as e:
raise NoPathFound() from e

Loading…
Cancel
Save