Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

pay: Prevent duplicate preapproveinvoice calls #7121

Merged
merged 1 commit into from
Mar 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 35 additions & 2 deletions plugins/libplugin-pay.c
Original file line number Diff line number Diff line change
Expand Up @@ -3818,6 +3818,11 @@ check_preapproveinvoice_allow(struct command *cmd,
struct payment *p)
{
/* On success, an empty object is returned. */
// struct preapproveinvoice_data *d

struct preapproveinvoice_data *d = payment_mod_check_preapproveinvoice_get_data(payment_root(p));
d->approved = true;
paymod_log(p, LOG_DBG, "Result from preapproveinvoice: allow");
payment_continue(p);
return command_still_pending(cmd);
}
Expand All @@ -3833,8 +3838,20 @@ static struct command_result *preapproveinvoice_rpc_failure(struct command *cmd,
return command_still_pending(cmd);
}

static void check_preapproveinvoice_start(void *d UNUSED, struct payment *p)
static void check_preapproveinvoice_start(struct preapproveinvoice_data *d UNUSED, struct payment *p)
{
struct payment *root = payment_root(p);

struct preapproveinvoice_data *data =
payment_mod_check_preapproveinvoice_get_data(root);
/* If the root payment was used to send the
* `preapproveinvoice` message to the signer, we don't need to
* do that again. */
if (data->approved) {
return payment_continue(p);
}

paymod_log(p, LOG_DBG, "Calling preapproveinvoice on signer for payment=%"PRIu64, root->id);
/* Ask the HSM if the invoice is OK to pay */
struct out_req *req;
req = jsonrpc_request_start(p->plugin, NULL, "preapproveinvoice",
Expand All @@ -3845,7 +3862,23 @@ static void check_preapproveinvoice_start(void *d UNUSED, struct payment *p)
(void) send_outreq(p->plugin, req);
}

REGISTER_PAYMENT_MODIFIER(check_preapproveinvoice, void *, NULL,
static struct preapproveinvoice_data* preapproveinvoice_data_init(struct payment *p)
{
struct preapproveinvoice_data *d;
/* Only keep state on the root. We will use the root's flag
* for all payments. */
if (p == payment_root(p)) {
d = tal(p, struct preapproveinvoice_data);
d->approved = false;
return d;
} else {
return NULL;
}
}

REGISTER_PAYMENT_MODIFIER(check_preapproveinvoice,
struct preapproveinvoice_data *,
preapproveinvoice_data_init,
check_preapproveinvoice_start);

static struct route_exclusions_data *
Expand Down
6 changes: 5 additions & 1 deletion plugins/libplugin-pay.h
Original file line number Diff line number Diff line change
Expand Up @@ -432,6 +432,10 @@ struct route_exclusions_data {
struct route_exclusion **exclusions;
};

struct preapproveinvoice_data {
bool approved;
};

/* List of globally available payment modifiers. */
REGISTER_PAYMENT_MODIFIER_HEADER(retry, struct retry_mod_data);
REGISTER_PAYMENT_MODIFIER_HEADER(routehints, struct routehints_data);
Expand All @@ -453,7 +457,7 @@ REGISTER_PAYMENT_MODIFIER_HEADER(local_channel_hints, void);
* each of those channels can bear. */
REGISTER_PAYMENT_MODIFIER_HEADER(payee_incoming_limit, void);
REGISTER_PAYMENT_MODIFIER_HEADER(route_exclusions, struct route_exclusions_data);
REGISTER_PAYMENT_MODIFIER_HEADER(check_preapproveinvoice, void);
REGISTER_PAYMENT_MODIFIER_HEADER(check_preapproveinvoice, struct preapproveinvoice_data);


struct payment *payment_new(tal_t *ctx, struct command *cmd,
Expand Down
Loading