diff --git a/plugins/libplugin-pay.c b/plugins/libplugin-pay.c index cb212236bd7e..2792bc1b136b 100644 --- a/plugins/libplugin-pay.c +++ b/plugins/libplugin-pay.c @@ -3479,6 +3479,15 @@ static struct command_result *direct_pay_override(struct payment *p) hint = channel_hint_set_find(root->hints, d->chan); if (hint && hint->enabled && amount_msat_greater(hint->estimated_capacity, p->our_amount)) { + if (p->getroute->cltv > p->constraints.cltv_budget) { + paymod_log(p, LOG_DBG, + "Direct channel (%s) skipped: " + "CLTV delay %u exceeds budget %u.", + fmt_short_channel_id_dir(tmpctx, &hint->scid), + p->getroute->cltv, p->constraints.cltv_budget); + return payment_continue(p); + } + /* Now build a route that consists only of this single hop */ p->route = tal_arr(p, struct route_hop, 1); p->route[0].amount = p->our_amount; diff --git a/tests/test_pay.py b/tests/test_pay.py index 442e35d73756..f159689b1cce 100644 --- a/tests/test_pay.py +++ b/tests/test_pay.py @@ -150,6 +150,17 @@ def test_pay_limits(node_factory): assert status[0]['strategy'] == "Initial attempt" +def test_pay_maxdelay_direct_channel(node_factory): + """Test that maxdelay is enforced even for direct channel payments""" + l1, l2 = node_factory.line_graph(2, wait_for_announce=True) + + inv = l2.rpc.invoice('10000msat', 'test_pay_maxdelay_direct', 'description')['bolt11'] + + # Delay too low for direct channel. + with pytest.raises(RpcError, match=r'CLTV delay exceeds our CLTV budget'): + l1.rpc.call('pay', {'bolt11': inv, 'maxdelay': 1}) + + def test_pay_exclude_node(node_factory, bitcoind): """Test excluding the node if there's the NODE-level error in the failure_code """