Browse Source

invoice: ignore dead-end heuristic on explicitly specified channels.

This makes testing easier, and makes sense: lightningd might not
*know* about other connected channels, depending on gossip, but if the
user specifies it we should obey it.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Changelog-Changed: JSON: `invoice` `exposeprivatechannels` now includes explicitly named channels even if they seem like dead-ends.
register-keysend-plugin
Rusty Russell 5 years ago
committed by neil saitug
parent
commit
df31af5221
  1. 2
      doc/lightning-invoice.7
  2. 2
      doc/lightning-invoice.7.md
  3. 6
      lightningd/invoice.c
  4. 26
      tests/test_invoices.py

2
doc/lightning-invoice.7

@ -61,7 +61,7 @@ logic, which will use unpublished channels only if there are no
published channels\. If \fItrue\fR unpublished channels are always considered published channels\. If \fItrue\fR unpublished channels are always considered
as a route hint candidate; if \fIfalse\fR, never\. If it is a short channel id as a route hint candidate; if \fIfalse\fR, never\. If it is a short channel id
(e\.g\. \fI1x1x3\fR) or array of short channel ids, only those specific channels (e\.g\. \fI1x1x3\fR) or array of short channel ids, only those specific channels
will be considered candidates, even if they are public\. will be considered candidates, even if they are public or dead-ends\.
The route hint is selected from the set of incoming channels of which: The route hint is selected from the set of incoming channels of which:

2
doc/lightning-invoice.7.md

@ -56,7 +56,7 @@ logic, which will use unpublished channels only if there are no
published channels. If *true* unpublished channels are always considered published channels. If *true* unpublished channels are always considered
as a route hint candidate; if *false*, never. If it is a short channel id as a route hint candidate; if *false*, never. If it is a short channel id
(e.g. *1x1x3*) or array of short channel ids, only those specific channels (e.g. *1x1x3*) or array of short channel ids, only those specific channels
will be considered candidates, even if they are public. will be considered candidates, even if they are public or dead-ends.
The route hint is selected from the set of incoming channels of which: The route hint is selected from the set of incoming channels of which:
peer’s balance minus their reserves is at least *msatoshi*, state is peer’s balance minus their reserves is at least *msatoshi*, state is

6
lightningd/invoice.c

@ -640,7 +640,11 @@ static void gossipd_incoming_channels_reply(struct subd *gossipd,
&inchans[i].short_channel_id)) { &inchans[i].short_channel_id)) {
tal_arr_remove(&inchans, i); tal_arr_remove(&inchans, i);
tal_arr_remove(&inchan_deadends, i); tal_arr_remove(&inchan_deadends, i);
} i--;
} else
/* If they specify directly, we don't
* care if it's a deadend */
inchan_deadends[i] = false;
} }
/* If they told us to use scids and we couldn't, fail. */ /* If they told us to use scids and we couldn't, fail. */

26
tests/test_invoices.py

@ -284,13 +284,13 @@ def test_invoice_routeboost_private(node_factory, bitcoind):
assert r['cltv_expiry_delta'] == 6 assert r['cltv_expiry_delta'] == 6
# Ask it explicitly to use a channel it can't (insufficient capacity) # Ask it explicitly to use a channel it can't (insufficient capacity)
inv = l2.rpc.invoice(msatoshi=10, label="inv5", description="?", exposeprivatechannels=scid2) inv = l2.rpc.invoice(msatoshi=(10**5) * 1000 + 1, label="inv5", description="?", exposeprivatechannels=scid2)
assert 'warning_deadends' in inv assert 'warning_deadends' not in inv
assert 'warning_capacity' not in inv assert 'warning_capacity' in inv
assert 'warning_offline' not in inv assert 'warning_offline' not in inv
# Give it two options and it will pick one with suff capacity. # Give it two options and it will pick one with suff capacity.
inv = l2.rpc.invoice(msatoshi=10, label="inv6", description="?", exposeprivatechannels=[scid2, scid]) inv = l2.rpc.invoice(msatoshi=(10**5) * 1000 + 1, label="inv6", description="?", exposeprivatechannels=[scid2, scid])
assert 'warning_capacity' not in inv assert 'warning_capacity' not in inv
assert 'warning_offline' not in inv assert 'warning_offline' not in inv
assert 'warning_deadends' not in inv assert 'warning_deadends' not in inv
@ -302,6 +302,24 @@ def test_invoice_routeboost_private(node_factory, bitcoind):
assert r['fee_proportional_millionths'] == 10 assert r['fee_proportional_millionths'] == 10
assert r['cltv_expiry_delta'] == 6 assert r['cltv_expiry_delta'] == 6
# It will use an explicit exposeprivatechannels even if it thinks its a dead-end
l0.rpc.close(l1.info['id'])
l0.wait_for_channel_onchain(l1.info['id'])
bitcoind.generate_block(1)
wait_for(lambda: l2.rpc.listchannels(scid_dummy)['channels'] == [])
inv = l2.rpc.invoice(msatoshi=123456, label="inv7", description="?", exposeprivatechannels=scid)
assert 'warning_capacity' not in inv
assert 'warning_offline' not in inv
assert 'warning_deadends' not in inv
# Route array has single route with single element.
r = only_one(only_one(l1.rpc.decodepay(inv['bolt11'])['routes']))
assert r['pubkey'] == l1.info['id']
assert r['short_channel_id'] == l1.rpc.listchannels()['channels'][0]['short_channel_id']
assert r['fee_base_msat'] == 1
assert r['fee_proportional_millionths'] == 10
assert r['cltv_expiry_delta'] == 6
def test_invoice_expiry(node_factory, executor): def test_invoice_expiry(node_factory, executor):
l1, l2 = node_factory.line_graph(2, fundchannel=True) l1, l2 = node_factory.line_graph(2, fundchannel=True)

Loading…
Cancel
Save