Skip to content

Commit

Permalink
xpay: give an additional block "slack" for CLTV values.
Browse files Browse the repository at this point in the history
pay does this, xpay does not.  Which means if a block comes in (or you're behind),
you get gratuitous failures:

```
    def test_xpay_simple(node_factory):
        l1, l2, l3, l4 = node_factory.get_nodes(4, opts={'may_reconnect': True})
        node_factory.join_nodes([l1, l2, l3], wait_for_announce=True)
        node_factory.join_nodes([l3, l4], announce_channels=False)

        # BOLT 11, direct peer
        b11 = l2.rpc.invoice('10000msat', 'test_xpay_simple', 'test_xpay_simple bolt11')['bolt11']
>       ret = l1.rpc.xpay(b11)

tests/test_xpay.py:148:
...
        if not isinstance(resp, dict):
            raise TypeError("Malformed response, response is not a dictionary %s." % resp)
        elif "error" in resp:
>           raise RpcError(method, payload, resp['error'])
E           pyln.client.lightning.RpcError: RPC call failed: method: xpay, payload: ('lnbcrt100n1pn5qu7csp53rp0mfwtfsyyy8gzsggepnxgslyalwvz3jkg9ptmqq452ln2nmgqpp58ak9nmfz9l93r0fpm266ewyjrhurhatrs05nda0r03p82cykp0vsdp9w3jhxazl0pcxz72lwd5k6urvv5sxymmvwscnzxqyjw5qcqp99qxpqysgqa798258yppu2tlfj8herr3zuz0zgux79zvtx6z57cmfzs2wdesmr4nvnkcmyssyu6k64ud54eg0v45c3mcw342jj6uy7tu202p6klrcp6ljc9w',), error: {'code': 203, 'message': "Destination said it doesn't know invoice: incorrect_or_unknown_payment_details"}
```

Signed-off-by: Rusty Russell <[email protected]>
Changelog-None: xpay is new this release.
  • Loading branch information
rustyrussell committed Nov 22, 2024
1 parent 4186591 commit 90ab932
Showing 1 changed file with 13 additions and 8 deletions.
21 changes: 13 additions & 8 deletions plugins/xpay/xpay.c
Original file line number Diff line number Diff line change
Expand Up @@ -777,11 +777,11 @@ static struct command_result *injectpaymentonion_succeeded(struct command *aux_c

static void append_blinded_payloads(struct sphinx_path *sp,
const struct attempt *attempt,
u32 effective_bheight,
size_t path_num)
{
const struct blinded_path *path = attempt->payment->paths[path_num];
struct xpay *xpay = xpay_of(attempt->payment->plugin);
u32 final_cltv = attempt->payment->final_cltv + xpay->blockheight;
u32 final_cltv = attempt->payment->final_cltv + effective_bheight;

for (size_t i = 0; i < tal_count(path->path); i++) {
bool first = (i == 0);
Expand Down Expand Up @@ -813,7 +813,9 @@ static void append_blinded_payloads(struct sphinx_path *sp,
}
}

static const u8 *create_onion(const tal_t *ctx, struct attempt *attempt)
static const u8 *create_onion(const tal_t *ctx,
struct attempt *attempt,
u32 effective_bheight)
{
struct xpay *xpay = xpay_of(attempt->payment->plugin);
bool blinded_path = false;
Expand All @@ -834,15 +836,16 @@ static const u8 *create_onion(const tal_t *ctx, struct attempt *attempt)
if (pubkey_eq(&hop->next_node, &xpay->fakenode)
&& hop->scidd.scid.u64 < tal_count(attempt->payment->paths)) {
blinded_path = true;
append_blinded_payloads(sp, attempt, hop->scidd.scid.u64);
append_blinded_payloads(sp, attempt, effective_bheight,
hop->scidd.scid.u64);
/* This must be at the end, unless they put the fake nodeid
* in a layer, in which case it doesn't matter what we put
* in the rest of the onion. */
break;
}
/* We tell it how much to send *out* */
payload = onion_nonfinal_hop(NULL, &hop->scidd.scid, hop->amount_out,
hop->cltv_value_out + xpay->blockheight);
hop->cltv_value_out + effective_bheight);
sphinx_add_hop_has_length(sp, node, take(payload));
node = &hop->next_node;
}
Expand All @@ -853,7 +856,7 @@ static const u8 *create_onion(const tal_t *ctx, struct attempt *attempt)
sphinx_add_hop_has_length(sp, node,
take(onion_final_hop(NULL,
attempt->delivers,
attempt->payment->final_cltv + xpay->blockheight,
attempt->payment->final_cltv + effective_bheight,
attempt->payment->full_amount,
attempt->payment->payment_secret,
attempt->payment->payment_metadata)));
Expand All @@ -876,8 +879,10 @@ static struct command_result *do_inject(struct command *aux_cmd,
struct out_req *req;
const u8 *onion;
struct xpay *xpay = xpay_of(attempt->payment->plugin);
/* In case a block comes in, we give CLTVs an extra 1. */
u32 effective_bheight = xpay->blockheight + 1;

onion = create_onion(tmpctx, attempt);
onion = create_onion(tmpctx, attempt, effective_bheight);
/* FIXME: Handle this better! */
if (!onion) {
payment_failed(aux_cmd, attempt->payment, PAY_UNSPECIFIED_ERROR,
Expand All @@ -894,7 +899,7 @@ static struct command_result *do_inject(struct command *aux_cmd,
json_add_sha256(req->js, "payment_hash", &attempt->payment->payment_hash);
/* If no route, its the same as delivery (self-pay) */
json_add_amount_msat(req->js, "amount_msat", initial_sent(attempt));
json_add_u32(req->js, "cltv_expiry", initial_cltv_delta(attempt) + xpay->blockheight);
json_add_u32(req->js, "cltv_expiry", initial_cltv_delta(attempt) + effective_bheight);
json_add_u64(req->js, "partid", attempt->partid);
json_add_u64(req->js, "groupid", attempt->payment->group_id);
json_add_string(req->js, "invstring", attempt->payment->invstring);
Expand Down

0 comments on commit 90ab932

Please sign in to comment.