mirror of
https://github.com/aljazceru/lightning.git
synced 2026-01-08 08:34:31 +01:00
lightnind: use aliases in routehints for private channels.
We *should* remember the channel type, since this is only required if they set the channel_type to include option_scid_alias. However, since we support channel upgrade, channel_type really needs a new table. I have a patch for that, from my abandoned original "fastopen" branch for aliases, but it's too big a chance for rc2 IMHO. Meanwhile, we allow exposeprivatechannels's scids to be either real or the aliases. Signed-off-by: Rusty Russell <rusty@rustcorp.com.au> Changelog-Added: Protocol: invoice routehints will use fake short-channel-ids for private channels if channel opened with option_scid_alias-supporting peer.
This commit is contained in:
committed by
neil saitug
parent
b479e9a9fa
commit
cfe6b06fb5
@@ -54,7 +54,7 @@ If specified, *exposeprivatechannels* overrides the default route hint
|
||||
logic, which will use unpublished channels only if there are no
|
||||
published channels. If *true* unpublished channels are always considered
|
||||
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 (or a remote alias), only those specific channels
|
||||
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:
|
||||
|
||||
@@ -171,7 +171,10 @@ routehint_candidates(const tal_t *ctx,
|
||||
/* Consider only hints they gave */
|
||||
if (hints) {
|
||||
log_debug(ld->log, "We have hints!");
|
||||
if (!scid_in_arr(hints, &r->short_channel_id)) {
|
||||
/* Allow specification by alias, too */
|
||||
if (!scid_in_arr(hints, &r->short_channel_id)
|
||||
&& (!candidate.c->alias[REMOTE]
|
||||
|| !scid_in_arr(hints, candidate.c->alias[REMOTE]))) {
|
||||
log_debug(ld->log, "scid %s not in hints",
|
||||
type_to_string(tmpctx,
|
||||
struct short_channel_id,
|
||||
@@ -204,6 +207,22 @@ routehint_candidates(const tal_t *ctx,
|
||||
continue;
|
||||
}
|
||||
|
||||
/* BOLT-channel-type #2:
|
||||
* - if `channel_type` has `option_scid_alias` set:
|
||||
* - MUST NOT use the real `short_channel_id` in
|
||||
* BOLT 11 `r` fields.
|
||||
*/
|
||||
/* FIXME: We don't remember the type explicitly, so
|
||||
* we just assume all private channels negotiated since
|
||||
* we had alias support want this. */
|
||||
|
||||
/* Note explicit flag test here: if we're told to expose all
|
||||
* private channels, then "is_public" is forced true */
|
||||
if (!(candidate.c->channel_flags & CHANNEL_FLAGS_ANNOUNCE_CHANNEL)
|
||||
&& candidate.c->alias[REMOTE]) {
|
||||
r->short_channel_id = *candidate.c->alias[REMOTE];
|
||||
}
|
||||
|
||||
/* OK, finish it and append to one of the arrays. */
|
||||
if (is_public) {
|
||||
log_debug(ld->log, "%s: added to public",
|
||||
|
||||
@@ -226,6 +226,7 @@ def test_invoice_routeboost_private(node_factory, bitcoind):
|
||||
# Make sure channel is totally public.
|
||||
wait_for(lambda: [c['public'] for c in l2.rpc.listchannels(scid_dummy)['channels']] == [True, True])
|
||||
|
||||
alias = only_one(only_one(l1.rpc.listpeers(l2.info['id'])['peers'])['channels'])['alias']['local']
|
||||
# Since there's only one route, it will reluctantly hint that even
|
||||
# though it's private
|
||||
inv = l2.rpc.invoice(amount_msat=123456, label="inv0", description="?")
|
||||
@@ -237,7 +238,9 @@ def test_invoice_routeboost_private(node_factory, bitcoind):
|
||||
# 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']
|
||||
# It uses our private alias!
|
||||
assert r['short_channel_id'] != l1.rpc.listchannels()['channels'][0]['short_channel_id']
|
||||
assert r['short_channel_id'] == alias
|
||||
assert r['fee_base_msat'] == 1
|
||||
assert r['fee_proportional_millionths'] == 10
|
||||
assert r['cltv_expiry_delta'] == 6
|
||||
@@ -261,7 +264,7 @@ def test_invoice_routeboost_private(node_factory, bitcoind):
|
||||
# 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['short_channel_id'] == alias
|
||||
assert r['fee_base_msat'] == 1
|
||||
assert r['fee_proportional_millionths'] == 10
|
||||
assert r['cltv_expiry_delta'] == 6
|
||||
@@ -276,7 +279,7 @@ def test_invoice_routeboost_private(node_factory, bitcoind):
|
||||
# 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['short_channel_id'] == alias
|
||||
assert r['fee_base_msat'] == 1
|
||||
assert r['fee_proportional_millionths'] == 10
|
||||
assert r['cltv_expiry_delta'] == 6
|
||||
@@ -308,7 +311,7 @@ def test_invoice_routeboost_private(node_factory, bitcoind):
|
||||
# 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['short_channel_id'] == alias
|
||||
assert r['fee_base_msat'] == 1
|
||||
assert r['fee_proportional_millionths'] == 10
|
||||
assert r['cltv_expiry_delta'] == 6
|
||||
@@ -322,7 +325,7 @@ def test_invoice_routeboost_private(node_factory, bitcoind):
|
||||
# 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'] == scid
|
||||
assert r['short_channel_id'] == alias
|
||||
assert r['fee_base_msat'] == 1
|
||||
assert r['fee_proportional_millionths'] == 10
|
||||
assert r['cltv_expiry_delta'] == 6
|
||||
@@ -345,7 +348,7 @@ def test_invoice_routeboost_private(node_factory, bitcoind):
|
||||
# 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'] == scid
|
||||
assert r['short_channel_id'] == alias
|
||||
assert r['fee_base_msat'] == 1
|
||||
assert r['fee_proportional_millionths'] == 10
|
||||
assert r['cltv_expiry_delta'] == 6
|
||||
@@ -365,7 +368,7 @@ def test_invoice_routeboost_private(node_factory, bitcoind):
|
||||
# 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['short_channel_id'] == alias
|
||||
assert r['fee_base_msat'] == 1
|
||||
assert r['fee_proportional_millionths'] == 10
|
||||
assert r['cltv_expiry_delta'] == 6
|
||||
|
||||
@@ -5062,7 +5062,8 @@ gives a routehint straight to us causes an issue
|
||||
|
||||
inv = l3.rpc.invoice(10, "test", "test")['bolt11']
|
||||
decoded = l3.rpc.decodepay(inv)
|
||||
assert(only_one(only_one(decoded['routes']))['short_channel_id'] == scid23)
|
||||
assert(only_one(only_one(decoded['routes']))['short_channel_id']
|
||||
== only_one(only_one(l3.rpc.listpeers()['peers'])['channels'])['alias']['remote'])
|
||||
|
||||
l3.stop()
|
||||
with pytest.raises(RpcError, match=r'Destination .* is not reachable directly and all routehints were unusable'):
|
||||
|
||||
Reference in New Issue
Block a user