lightningd: add option dev-strict-forwarding

Changelog-Add: add option dev-strict-forwarding
This commit is contained in:
Lagrang3 2024-08-24 10:54:26 +01:00 committed by Vincenzo Palazzo
parent fcdbbd8534
commit bc419b41a8
5 changed files with 122 additions and 1 deletions

View File

@ -151,6 +151,7 @@ static struct lightningd *new_lightningd(const tal_t *ctx)
ld->dev_hsmd_no_preapprove_check = false;
ld->dev_hsmd_fail_preapprove = false;
ld->dev_handshake_no_reply = false;
ld->dev_strict_forwarding = false;
/*~ We try to ensure enough fds for twice the number of channels
* we start with. We have a developer option to change that factor

View File

@ -362,6 +362,10 @@ struct lightningd {
/* Tell connectd not to talk after handshake */
bool dev_handshake_no_reply;
/* Remove the freedom to choose select between parallel channels to
* forward a payment. */
bool dev_strict_forwarding;
/* tor support */
struct wireaddr *proxyaddr;
bool always_use_proxy;

View File

@ -956,6 +956,10 @@ static void dev_register_opts(struct lightningd *ld)
opt_set_bool,
&ld->dev_handshake_no_reply,
"Don't send or read init message after connection");
clnopt_noarg("--dev-strict-forwarding", OPT_DEV,
opt_set_bool,
&ld->dev_strict_forwarding,
"Forward HTLCs along the channel specified");
clnopt_noarg("--dev-throttle-gossip", OPT_DEV,
opt_set_bool,
&ld->dev_throttle_gossip,

View File

@ -1288,7 +1288,11 @@ static struct channel_id *calc_forwarding_channel(struct lightningd *ld,
c = NULL;
}
best = best_channel(ld, peer, p->amt_to_forward, c);
if (!ld->dev_strict_forwarding)
best = best_channel(ld, peer, p->amt_to_forward, c);
else
best = c;
if (!c) {
if (!best)
return NULL;

View File

@ -6588,3 +6588,111 @@ def test_injectpaymentonion_failures(node_factory, executor):
# PAY_INJECTPAYMENTONION_FAILED
assert err.value.error['code'] == 218
assert 'onionreply' in err.value.error['data']
def test_parallel_channels_reserve(node_factory, bitcoind):
"""Tests wether we are able to pay through parallel channels concurrently.
To do that we need to enable strict-forwarding."""
def direction(node1, node2):
return 0 if node1.info["id"] < node2.info["id"] else 1
def get_local_channel_by_id(node, chanid):
peerchannels = node.rpc.listpeerchannels()["channels"]
if not peerchannels:
return None
for c in peerchannels:
if c["channel_id"] == chanid:
return c
return None
opts = {
"fee-base": 0,
"fee-per-satoshi": 0,
"cltv-delta": 6,
"dev-strict-forwarding": None,
}
l1, l2, l3 = node_factory.get_nodes(3, opts=opts)
l1.fundwallet(10**7)
l2.fundwallet(10**7)
scids = []
l1.rpc.connect(l2.info["id"], "localhost", l2.port)
l2.rpc.connect(l3.info["id"], "localhost", l3.port)
c12 = l1.rpc.fundchannel(l2.info["id"], 3000_000, minconf=0)["channel_id"]
c23 = []
c23.append(l2.rpc.fundchannel(l3.info["id"], 1000_000, minconf=0)["channel_id"])
c23.append(l2.rpc.fundchannel(l3.info["id"], 2000_000, minconf=0)["channel_id"])
bitcoind.generate_block(6)
sync_blockheight(bitcoind, [l1, l2, l3])
scids.append(get_local_channel_by_id(l1, c12)["short_channel_id"])
scids.append(get_local_channel_by_id(l2, c23[0])["short_channel_id"])
scids.append(get_local_channel_by_id(l2, c23[1])["short_channel_id"])
for l in [l1, l2, l3]:
for c in scids:
l.wait_channel_active(c)
# we should be able to send these two parts:
nparts = 2
route_amounts = ["750000sat", "1750000sat"]
total_msat = sum([Millisatoshi(a) for a in route_amounts[:nparts]])
# Test succeeds if we are able to pay this invoice
inv = l3.rpc.call(
"invoice",
{"amount_msat": total_msat, "label": "inv", "description": "inv", "cltv": 10},
)
# Share data by every route we will construct: l1->l2->l3
route = [
{
"id": l2.info["id"],
"direction": direction(l1, l2),
"delay": 16,
"style": "tlv",
},
{
"id": l3.info["id"],
"direction": direction(l2, l3),
"delay": 10,
"style": "tlv",
},
]
# Send every part with sendpay
for part in range(nparts):
this_part_msat = Millisatoshi(route_amounts[part])
chan1 = get_local_channel_by_id(l1, c12)
chan2 = get_local_channel_by_id(l2, c23[part])
route[0]["channel"] = chan1["short_channel_id"]
route[1]["channel"] = chan2["short_channel_id"]
route[0]["amount_msat"] = route[1]["amount_msat"] = this_part_msat
assert chan1["spendable_msat"] >= this_part_msat
assert chan2["spendable_msat"] >= this_part_msat
l1.rpc.call(
"sendpay",
{
"route": route,
"payment_hash": inv["payment_hash"],
"payment_secret": inv["payment_secret"],
"amount_msat": total_msat,
"groupid": 1,
"partid": part + 1,
},
)
l1.wait_for_htlcs()
# Are we happy?
receipt = only_one(l3.rpc.listinvoices("inv")["invoices"])
assert receipt["status"] == "paid"
assert receipt["amount_received_msat"] == total_msat