diff --git a/contrib/msggen/msggen/schema.json b/contrib/msggen/msggen/schema.json index 08f23654c..6caadaf47 100644 --- a/contrib/msggen/msggen/schema.json +++ b/contrib/msggen/msggen/schema.json @@ -474,8 +474,7 @@ "request": { "required": [ "layer", - "short_channel_id", - "direction" + "short_channel_id_dir" ], "properties": { "layer": { @@ -484,16 +483,10 @@ "The name of the layer to apply this change to." ] }, - "short_channel_id": { - "type": "short_channel_id", + "short_channel_id_dir": { + "type": "short_channel_id_dir", "description": [ - "The short channel id to apply this change to." - ] - }, - "direction": { - "type": "u32", - "description": [ - "The direction to apply this change to." + "The short channel id and direction to apply this change to." ] }, "minimum_msat": { @@ -518,21 +511,14 @@ "constraint": { "type": "object", "required": [ - "short_channel_id", - "direction", + "short_channel_id_dir", "timestamp" ], "properties": { - "short_channel_id": { - "type": "short_channel_id", + "short_channel_id_dir": { + "type": "short_channel_id_dir", "description": [ - "The *short_channel_id* specified." - ] - }, - "direction": { - "type": "u32", - "description": [ - "The *direction* specified." + "The *short_channel_id* and *direction* specified." ] }, "timestamp": { @@ -713,20 +699,13 @@ "items": { "type": "object", "required": [ - "short_channel_id", - "direction" + "short_channel_id_dir" ], "properties": { - "short_channel_id": { - "type": "short_channel_id", + "short_channel_id_dir": { + "type": "short_channel_id_dir", "description": [ - "The short channel id." - ] - }, - "direction": { - "type": "u32", - "description": [ - "The direction." + "The short channel id and direction" ] }, "maximum_msat": { @@ -787,21 +766,14 @@ "type": "object", "additionalProperties": true, "required": [ - "short_channel_id", - "direction", + "short_channel_id_dir", "amount_msat" ], "properties": { - "short_channel_id": { - "type": "short_channel_id", + "short_channel_id_dir": { + "type": "short_channel_id_dir", "description": [ - "The channel joining these nodes." - ] - }, - "direction": { - "type": "u32", - "description": [ - "0 if this channel is traversed from lesser to greater **id**, otherwise 1." + "The channel and direction joining these nodes." ] }, "amount_msat": { @@ -859,21 +831,14 @@ "type": "object", "additionalProperties": true, "required": [ - "short_channel_id", - "direction", + "short_channel_id_dir", "amount_msat" ], "properties": { - "short_channel_id": { - "type": "short_channel_id", + "short_channel_id_dir": { + "type": "short_channel_id_dir", "description": [ - "The channel joining these nodes." - ] - }, - "direction": { - "type": "u32", - "description": [ - "0 if this channel is traversed from lesser to greater **id**, otherwise 1." + "The channel and direction joining these nodes." ] }, "amount_msat": { @@ -14435,23 +14400,16 @@ "type": "object", "additionalProperties": false, "required": [ - "short_channel_id", - "direction", + "short_channel_id_dir", "next_node_id", "amount_msat", "delay" ], "properties": { - "short_channel_id": { - "type": "short_channel_id", + "short_channel_id_dir": { + "type": "short_channel_id_dir", "description": [ - "The channel joining these nodes." - ] - }, - "direction": { - "type": "u32", - "description": [ - "0 if this channel is traversed from lesser to greater **id**, otherwise 1." + "The channel and direction joining these nodes." ] }, "amount_msat": { diff --git a/doc/schemas/lightning-askrene-inform-channel.json b/doc/schemas/lightning-askrene-inform-channel.json index 8ba0f90f6..7deb95b77 100644 --- a/doc/schemas/lightning-askrene-inform-channel.json +++ b/doc/schemas/lightning-askrene-inform-channel.json @@ -12,8 +12,7 @@ "request": { "required": [ "layer", - "short_channel_id", - "direction" + "short_channel_id_dir" ], "properties": { "layer": { @@ -22,16 +21,10 @@ "The name of the layer to apply this change to." ] }, - "short_channel_id": { - "type": "short_channel_id", + "short_channel_id_dir": { + "type": "short_channel_id_dir", "description": [ - "The short channel id to apply this change to." - ] - }, - "direction": { - "type": "u32", - "description": [ - "The direction to apply this change to." + "The short channel id and direction to apply this change to." ] }, "minimum_msat": { @@ -56,21 +49,14 @@ "constraint": { "type": "object", "required": [ - "short_channel_id", - "direction", + "short_channel_id_dir", "timestamp" ], "properties": { - "short_channel_id": { - "type": "short_channel_id", + "short_channel_id_dir": { + "type": "short_channel_id_dir", "description": [ - "The *short_channel_id* specified." - ] - }, - "direction": { - "type": "u32", - "description": [ - "The *direction* specified." + "The *short_channel_id* and *direction* specified." ] }, "timestamp": { diff --git a/doc/schemas/lightning-askrene-listlayers.json b/doc/schemas/lightning-askrene-listlayers.json index 20d579539..7b6eed74d 100644 --- a/doc/schemas/lightning-askrene-listlayers.json +++ b/doc/schemas/lightning-askrene-listlayers.json @@ -140,20 +140,13 @@ "items": { "type": "object", "required": [ - "short_channel_id", - "direction" + "short_channel_id_dir" ], "properties": { - "short_channel_id": { - "type": "short_channel_id", + "short_channel_id_dir": { + "type": "short_channel_id_dir", "description": [ - "The short channel id." - ] - }, - "direction": { - "type": "u32", - "description": [ - "The direction." + "The short channel id and direction" ] }, "maximum_msat": { diff --git a/doc/schemas/lightning-askrene-reserve.json b/doc/schemas/lightning-askrene-reserve.json index 7b91e3800..070920021 100644 --- a/doc/schemas/lightning-askrene-reserve.json +++ b/doc/schemas/lightning-askrene-reserve.json @@ -22,21 +22,14 @@ "type": "object", "additionalProperties": true, "required": [ - "short_channel_id", - "direction", + "short_channel_id_dir", "amount_msat" ], "properties": { - "short_channel_id": { - "type": "short_channel_id", + "short_channel_id_dir": { + "type": "short_channel_id_dir", "description": [ - "The channel joining these nodes." - ] - }, - "direction": { - "type": "u32", - "description": [ - "0 if this channel is traversed from lesser to greater **id**, otherwise 1." + "The channel and direction joining these nodes." ] }, "amount_msat": { diff --git a/doc/schemas/lightning-askrene-unreserve.json b/doc/schemas/lightning-askrene-unreserve.json index 377595a5c..eeadf8058 100644 --- a/doc/schemas/lightning-askrene-unreserve.json +++ b/doc/schemas/lightning-askrene-unreserve.json @@ -22,21 +22,14 @@ "type": "object", "additionalProperties": true, "required": [ - "short_channel_id", - "direction", + "short_channel_id_dir", "amount_msat" ], "properties": { - "short_channel_id": { - "type": "short_channel_id", + "short_channel_id_dir": { + "type": "short_channel_id_dir", "description": [ - "The channel joining these nodes." - ] - }, - "direction": { - "type": "u32", - "description": [ - "0 if this channel is traversed from lesser to greater **id**, otherwise 1." + "The channel and direction joining these nodes." ] }, "amount_msat": { diff --git a/doc/schemas/lightning-getroutes.json b/doc/schemas/lightning-getroutes.json index 5b09bda28..aeaeb2216 100644 --- a/doc/schemas/lightning-getroutes.json +++ b/doc/schemas/lightning-getroutes.json @@ -121,23 +121,16 @@ "type": "object", "additionalProperties": false, "required": [ - "short_channel_id", - "direction", + "short_channel_id_dir", "next_node_id", "amount_msat", "delay" ], "properties": { - "short_channel_id": { - "type": "short_channel_id", + "short_channel_id_dir": { + "type": "short_channel_id_dir", "description": [ - "The channel joining these nodes." - ] - }, - "direction": { - "type": "u32", - "description": [ - "0 if this channel is traversed from lesser to greater **id**, otherwise 1." + "The channel and direction joining these nodes." ] }, "amount_msat": { diff --git a/plugins/askrene/askrene.c b/plugins/askrene/askrene.c index ade22c2f6..97d1060d0 100644 --- a/plugins/askrene/askrene.c +++ b/plugins/askrene/askrene.c @@ -102,20 +102,6 @@ static struct command_result *param_known_layer(struct command *cmd, return NULL; } -static struct command_result *param_zero_or_one(struct command *cmd, - const char *name, - const char *buffer, - const jsmntok_t *tok, - int **num) -{ - *num = tal(cmd, int); - if (json_to_zero_or_one(buffer, tok, *num)) - return NULL; - - return command_fail_badparam(cmd, name, buffer, tok, - "should be 0 or 1"); -} - struct reserve_path { struct short_channel_id_dir *scidds; struct amount_msat *amounts; @@ -130,9 +116,8 @@ static struct command_result *parse_reserve_path(struct command *cmd, { const char *err; - err = json_scan(tmpctx, buffer, tok, "{short_channel_id:%,direction:%,amount_msat:%}", - JSON_SCAN(json_to_short_channel_id, &scidd->scid), - JSON_SCAN(json_to_zero_or_one, &scidd->dir), + err = json_scan(tmpctx, buffer, tok, "{short_channel_id_dir:%,amount_msat:%}", + JSON_SCAN(json_to_short_channel_id_dir, scidd), JSON_SCAN(json_to_msat, amount)); if (err) return command_fail_badparam(cmd, name, buffer, tok, err); @@ -553,10 +538,12 @@ static struct command_result *do_getroutes(struct command *cmd, json_add_u32(response, "final_cltv", *info->finalcltv); json_array_start(response, "path"); for (size_t j = 0; j < tal_count(routes[i]->hops); j++) { + struct short_channel_id_dir scidd; const struct route_hop *r = &routes[i]->hops[j]; json_object_start(response, NULL); - json_add_short_channel_id(response, "short_channel_id", r->scid); - json_add_u32(response, "direction", r->direction); + scidd.scid = r->scid; + scidd.dir = r->direction; + json_add_short_channel_id_dir(response, "short_channel_id_dir", scidd); json_add_node_id(response, "next_node_id", &r->node_id); json_add_amount_msat(response, "amount_msat", r->amount); json_add_u32(response, "delay", r->delay); @@ -825,18 +812,15 @@ static struct command_result *json_askrene_inform_channel(struct command *cmd, { struct layer *layer; const char *layername; - struct short_channel_id *scid; - int *direction; + struct short_channel_id_dir *scidd; struct json_stream *response; struct amount_msat *max, *min; const struct constraint *c; - struct short_channel_id_dir scidd; struct askrene *askrene = get_askrene(cmd->plugin); if (!param_check(cmd, buffer, params, p_req("layer", param_layername, &layername), - p_req("short_channel_id", param_short_channel_id, &scid), - p_req("direction", param_zero_or_one, &direction), + p_req("short_channel_id_dir", param_short_channel_id_dir, &scidd), p_opt("minimum_msat", param_msat, &min), p_opt("maximum_msat", param_msat, &max), NULL)) @@ -854,15 +838,11 @@ static struct command_result *json_askrene_inform_channel(struct command *cmd, if (!layer) layer = new_layer(askrene, layername); - /* Calls expect a convenient short_channel_id_dir struct */ - scidd.scid = *scid; - scidd.dir = *direction; - if (min) { - c = layer_update_constraint(layer, &scidd, CONSTRAINT_MIN, + c = layer_update_constraint(layer, scidd, CONSTRAINT_MIN, time_now().ts.tv_sec, *min); } else { - c = layer_update_constraint(layer, &scidd, CONSTRAINT_MAX, + c = layer_update_constraint(layer, scidd, CONSTRAINT_MAX, time_now().ts.tv_sec, *max); } response = jsonrpc_stream_success(cmd); diff --git a/plugins/askrene/layer.c b/plugins/askrene/layer.c index 9e8efe54c..b2dd00bea 100644 --- a/plugins/askrene/layer.c +++ b/plugins/askrene/layer.c @@ -419,8 +419,7 @@ void json_add_constraint(struct json_stream *js, json_object_start(js, fieldname); if (layer) json_add_string(js, "layer", layer->name); - json_add_short_channel_id(js, "short_channel_id", c->key.scidd.scid); - json_add_u32(js, "direction", c->key.scidd.dir); + json_add_short_channel_id_dir(js, "short_channel_id_dir", c->key.scidd); json_add_u64(js, "timestamp", c->timestamp); switch (c->key.type) { case CONSTRAINT_MIN: diff --git a/tests/test_askrene.py b/tests/test_askrene.py index 2af1834f4..e7380fe04 100644 --- a/tests/test_askrene.py +++ b/tests/test_askrene.py @@ -8,6 +8,13 @@ import pytest import time +def direction(src, dst): + """BOLT 7 direction: 0 means from lesser encoded id""" + if src < dst: + return 0 + return 1 + + def test_layers(node_factory): """Test manipulating information in layers""" l1, l2, l3 = node_factory.line_graph(3, wait_for_announce=True) @@ -52,12 +59,10 @@ def test_layers(node_factory): # We can tell it about made up channels... first_timestamp = int(time.time()) l2.rpc.askrene_inform_channel('test_layers', - '0x0x1', - 1, + '0x0x1/1', 100000) last_timestamp = int(time.time()) + 1 - expect['constraints'].append({'short_channel_id': '0x0x1', - 'direction': 1, + expect['constraints'].append({'short_channel_id_dir': '0x0x1/1', 'minimum_msat': 100000}) # Check timestamp first. listlayers = l2.rpc.askrene_listlayers('test_layers') @@ -72,25 +77,23 @@ def test_layers(node_factory): # We can tell it about existing channels... scid12 = first_scid(l1, l2) first_timestamp = int(time.time()) + scid12dir = f"{scid12}/{direction(l2.info['id'], l1.info['id'])}" l2.rpc.askrene_inform_channel(layer='test_layers', - short_channel_id=scid12, - # This is l2 -> l1 - direction=0, + short_channel_id_dir=scid12dir, maximum_msat=12341234) last_timestamp = int(time.time()) + 1 - expect['constraints'].append({'short_channel_id': scid12, - 'direction': 0, + expect['constraints'].append({'short_channel_id_dir': scid12dir, 'timestamp': first_timestamp, 'maximum_msat': 12341234}) # Check timestamp first. listlayers = l2.rpc.askrene_listlayers('test_layers') - ts2 = only_one([c['timestamp'] for c in only_one(listlayers['layers'])['constraints'] if c['short_channel_id'] == scid12]) + ts2 = only_one([c['timestamp'] for c in only_one(listlayers['layers'])['constraints'] if c['short_channel_id_dir'] == scid12dir]) assert first_timestamp <= ts2 <= last_timestamp expect['constraints'][1]['timestamp'] = ts2 # Could be either order! actual = expect.copy() - if only_one(listlayers['layers'])['constraints'][0]['short_channel_id'] == scid12: + if only_one(listlayers['layers'])['constraints'][0]['short_channel_id_dir'] == scid12dir: actual['constraints'] = [expect['constraints'][1], expect['constraints'][0]] assert listlayers == {'layers': [actual]} @@ -169,13 +172,8 @@ def test_getroutes(node_factory): # Set up l1 with this as the gossip_store l1 = node_factory.get_node(gossip_store_file=gsfile.name) - def direction(nodemap, src, dst): - if nodemap[src] < nodemap[dst]: - return 0 - return 1 - # Disabling channels makes getroutes fail - l1.rpc.askrene_disable_channel("chans_disabled", f"0x1x0/{direction(nodemap, 0, 1)}") + l1.rpc.askrene_disable_channel("chans_disabled", '0x1x0/1') with pytest.raises(RpcError, match="Could not find route"): l1.rpc.getroutes(source=nodemap[0], destination=nodemap[1], @@ -193,8 +191,7 @@ def test_getroutes(node_factory): 'routes': [{'probability_ppm': 999999, 'final_cltv': 99, 'amount_msat': 1000, - 'path': [{'short_channel_id': '0x1x0', - 'direction': 1, + 'path': [{'short_channel_id_dir': '0x1x0/1', 'next_node_id': nodemap[1], 'amount_msat': 1010, 'delay': 99 + 6}]}]} @@ -208,13 +205,11 @@ def test_getroutes(node_factory): 'routes': [{'probability_ppm': 999798, 'final_cltv': 99, 'amount_msat': 100000, - 'path': [{'short_channel_id': '0x1x0', - 'direction': 1, + 'path': [{'short_channel_id_dir': '0x1x0/1', 'next_node_id': nodemap[1], 'amount_msat': 103020, 'delay': 99 + 6 + 6}, - {'short_channel_id': '1x3x2', - 'direction': 1, + {'short_channel_id_dir': '1x3x2/1', 'next_node_id': nodemap[3], 'amount_msat': 102000, 'delay': 99 + 6} @@ -254,8 +249,7 @@ def test_getroutes(node_factory): 'routes': [{'probability_ppm': 900000, 'final_cltv': 99, 'amount_msat': 1000000, - 'path': [{'short_channel_id': '0x2x3', - 'direction': 1, + 'path': [{'short_channel_id_dir': '0x2x3/1', 'next_node_id': nodemap[2], 'amount_msat': 1000001, 'delay': 99 + 6}]}]} @@ -265,11 +259,11 @@ def test_getroutes(node_factory): nodemap[0], nodemap[2], 10000000, - [[{'short_channel_id': '0x2x1', + [[{'short_channel_id_dir': '0x2x1/1', 'next_node_id': nodemap[2], 'amount_msat': 500000, 'delay': 99 + 6}], - [{'short_channel_id': '0x2x3', + [{'short_channel_id_dir': '0x2x3/1', 'next_node_id': nodemap[2], 'amount_msat': 9500009, 'delay': 99 + 6}]]) @@ -299,8 +293,8 @@ def test_getroutes_fee_fallback(node_factory): nodemap[3], 10000, maxfee_msat=201, - paths=[[{'short_channel_id': '0x1x0'}, - {'short_channel_id': '1x3x2'}]]) + paths=[[{'short_channel_id_dir': '0x1x0/1'}, + {'short_channel_id_dir': '1x3x2/1'}]]) # maxfee exceeded? lower prob path. check_getroute_paths(l1, @@ -308,8 +302,8 @@ def test_getroutes_fee_fallback(node_factory): nodemap[3], 10000, maxfee_msat=200, - paths=[[{'short_channel_id': '0x2x1'}, - {'short_channel_id': '2x3x3'}]]) + paths=[[{'short_channel_id_dir': '0x2x1/1'}, + {'short_channel_id_dir': '2x3x3/0'}]]) def test_getroutes_auto_sourcefree(node_factory): @@ -333,8 +327,7 @@ def test_getroutes_auto_sourcefree(node_factory): 'routes': [{'probability_ppm': 999999, 'final_cltv': 99, 'amount_msat': 1000, - 'path': [{'short_channel_id': '0x1x0', - 'direction': 1, + 'path': [{'short_channel_id_dir': '0x1x0/1', 'next_node_id': nodemap[1], 'amount_msat': 1000, 'delay': 99}]}]} @@ -348,13 +341,11 @@ def test_getroutes_auto_sourcefree(node_factory): 'routes': [{'probability_ppm': 999798, 'final_cltv': 99, 'amount_msat': 100000, - 'path': [{'short_channel_id': '0x1x0', - 'direction': 1, + 'path': [{'short_channel_id_dir': '0x1x0/1', 'next_node_id': nodemap[1], 'amount_msat': 102000, 'delay': 99 + 6}, - {'short_channel_id': '1x3x2', - 'direction': 1, + {'short_channel_id_dir': '1x3x2/1', 'next_node_id': nodemap[3], 'amount_msat': 102000, 'delay': 99 + 6} @@ -408,15 +399,16 @@ def test_getroutes_auto_localchans(node_factory): final_cltv=99) # This should work + scid21dir = f"{scid12}/{direction(l2.info['id'], l1.info['id'])}" check_getroute_paths(l2, l2.info['id'], nodemap[2], 100000, maxfee_msat=100000, layers=['auto.localchans'], - paths=[[{'short_channel_id': scid12, 'amount_msat': 102012, 'delay': 99 + 6 + 6 + 6}, - {'short_channel_id': '0x1x0', 'amount_msat': 102010, 'delay': 99 + 6 + 6}, - {'short_channel_id': '1x2x1', 'amount_msat': 101000, 'delay': 99 + 6}]]) + paths=[[{'short_channel_id_dir': scid21dir, 'amount_msat': 102012, 'delay': 99 + 6 + 6 + 6}, + {'short_channel_id_dir': '0x1x0/0', 'amount_msat': 102010, 'delay': 99 + 6 + 6}, + {'short_channel_id_dir': '1x2x1/1', 'amount_msat': 101000, 'delay': 99 + 6}]]) # This should get self-discount correct check_getroute_paths(l2, @@ -425,9 +417,9 @@ def test_getroutes_auto_localchans(node_factory): 100000, maxfee_msat=100000, layers=['auto.localchans', 'auto.sourcefree'], - paths=[[{'short_channel_id': scid12, 'amount_msat': 102010, 'delay': 99 + 6 + 6}, - {'short_channel_id': '0x1x0', 'amount_msat': 102010, 'delay': 99 + 6 + 6}, - {'short_channel_id': '1x2x1', 'amount_msat': 101000, 'delay': 99 + 6}]]) + paths=[[{'short_channel_id_dir': scid21dir, 'amount_msat': 102010, 'delay': 99 + 6 + 6}, + {'short_channel_id_dir': '0x1x0/0', 'amount_msat': 102010, 'delay': 99 + 6 + 6}, + {'short_channel_id_dir': '1x2x1/1', 'amount_msat': 101000, 'delay': 99 + 6}]]) def test_fees_dont_exceed_constraints(node_factory): @@ -444,8 +436,7 @@ def test_fees_dont_exceed_constraints(node_factory): chan = only_one([c for c in l1.rpc.listchannels(source=nodemap[0])['channels'] if c['destination'] == nodemap[1]]) l1.rpc.askrene_inform_channel(layer='test_layers', - short_channel_id=chan['short_channel_id'], - direction=chan['direction'], + short_channel_id_dir=f"{chan['short_channel_id']}/{chan['direction']}", maximum_msat=max_msat) routes = l1.rpc.getroutes(source=nodemap[0], @@ -456,7 +447,7 @@ def test_fees_dont_exceed_constraints(node_factory): final_cltv=99)['routes'] assert len(routes) == 2 for hop in routes[0]['path'] + routes[1]['path']: - if hop['short_channel_id'] == chan['short_channel_id']: + if hop['short_channel_id_dir'] == f"{chan['short_channel_id']}/{chan['direction']}": amount = hop['amount_msat'] assert amount <= max_msat @@ -483,7 +474,7 @@ def test_sourcefree_on_mods(node_factory, bitcoind): maxfee_msat=100000, final_cltv=99)['routes'] # Expect no fee. - check_route_as_expected(routes, [[{'short_channel_id': '0x3x3', + check_route_as_expected(routes, [[{'short_channel_id_dir': '0x3x3/1', 'amount_msat': 1000000, 'delay': 99}]]) # Same if we specify layers in the other order! @@ -494,7 +485,7 @@ def test_sourcefree_on_mods(node_factory, bitcoind): maxfee_msat=100000, final_cltv=99)['routes'] # Expect no fee. - check_route_as_expected(routes, [[{'short_channel_id': '0x3x3', + check_route_as_expected(routes, [[{'short_channel_id_dir': '0x3x3/1', 'amount_msat': 1000000, 'delay': 99}]]) @@ -536,9 +527,7 @@ def test_live_spendable(node_factory, bitcoind): path_total = {} num_htlcs = {} for r in routes["routes"]: - key = "{}/{}".format( - r["path"][0]["short_channel_id"], r["path"][0]["direction"] - ) + key = r["path"][0]["short_channel_id_dir"] path_total[key] = path_total.get(key, 0) + r["path"][0]["amount_msat"] num_htlcs[key] = num_htlcs.get(key, 0) + 1 @@ -557,9 +546,9 @@ def test_live_spendable(node_factory, bitcoind): # No duplicate paths! for i in range(0, len(routes["routes"])): - path_i = [(p['short_channel_id'], p['direction']) for p in routes["routes"][i]['path']] + path_i = [p['short_channel_id_dir'] for p in routes["routes"][i]['path']] for j in range(i + 1, len(routes["routes"])): - path_j = [(p['short_channel_id'], p['direction']) for p in routes["routes"][j]['path']] + path_j = [p['short_channel_id_dir'] for p in routes["routes"][j]['path']] assert path_i != path_j # Must deliver exact amount. @@ -592,12 +581,11 @@ def test_limits_fake_gossmap(node_factory, bitcoind): assert scidd in [f"{c['short_channel_id']}/{c['direction']}" for c in l1.rpc.listchannels(source=nodemap[0])['channels']] for scidd, amount in spendable.items(): - chan, direction = scidd.split('/') l1.rpc.askrene_inform_channel(layer='localchans', - short_channel_id=chan, direction=int(direction), + short_channel_id_dir=scidd, minimum_msat=amount) l1.rpc.askrene_inform_channel(layer='localchans', - short_channel_id=chan, direction=int(direction), + short_channel_id_dir=scidd, maximum_msat=amount) routes = l1.rpc.getroutes( @@ -611,9 +599,7 @@ def test_limits_fake_gossmap(node_factory, bitcoind): path_total = {} for r in routes["routes"]: - key = "{}/{}".format( - r["path"][0]["short_channel_id"], r["path"][0]["direction"] - ) + key = r["path"][0]["short_channel_id_dir"] path_total[key] = path_total.get(key, 0) + r["path"][0]["amount_msat"] exceeded = {} @@ -626,9 +612,9 @@ def test_limits_fake_gossmap(node_factory, bitcoind): # No duplicate paths! for i in range(0, len(routes["routes"])): - path_i = [(p['short_channel_id'], p['direction']) for p in routes["routes"][i]['path']] + path_i = [p['short_channel_id_dir'] for p in routes["routes"][i]['path']] for j in range(i + 1, len(routes["routes"])): - path_j = [(p['short_channel_id'], p['direction']) for p in routes["routes"][j]['path']] + path_j = [p['short_channel_id_dir'] for p in routes["routes"][j]['path']] assert path_i != path_j # Must deliver exact amount. @@ -650,12 +636,12 @@ def test_max_htlc(node_factory, bitcoind): final_cltv=10) check_route_as_expected(routes['routes'], - [[{'short_channel_id': '0x1x0', 'amount_msat': 1_000_001, 'delay': 10 + 6}], - [{'short_channel_id': '0x1x1', 'amount_msat': 19_000_019, 'delay': 10 + 6}]]) + [[{'short_channel_id_dir': '0x1x0/1', 'amount_msat': 1_000_001, 'delay': 10 + 6}], + [{'short_channel_id_dir': '0x1x1/1', 'amount_msat': 19_000_019, 'delay': 10 + 6}]]) # If we can't use channel 2, we fail. l1.rpc.askrene_inform_channel(layer='removechan2', - short_channel_id='0x1x1', direction=1, + short_channel_id_dir='0x1x1/1', maximum_msat=0) # FIXME: Better diag!