From 159e736fc15d3ce847973b6526dd264308550fa1 Mon Sep 17 00:00:00 2001 From: ZmnSCPxj Date: Sat, 17 Mar 2018 15:12:37 +0000 Subject: [PATCH] invoices: Implement autocleaninvoice. --- doc/Makefile | 1 + doc/lightning-autocleaninvoice.7 | 0 doc/lightning-autocleaninvoice.7.txt | 42 ++++++++++++++++++++++ doc/lightning-delexpiredinvoice.7 | 51 +++++++++++++++++++++++++++ doc/lightning-delexpiredinvoice.7.txt | 4 +-- doc/lightning-delinvoice.7 | 6 ++-- doc/lightning-delinvoice.7.txt | 2 +- lightningd/invoice.c | 50 ++++++++++++++++++++++++++ wallet/invoices.c | 41 +++++++++++++++++++++ wallet/invoices.h | 16 +++++++++ wallet/test/run-wallet.c | 5 +++ wallet/wallet.c | 4 +++ wallet/wallet.h | 11 ++++++ 13 files changed, 227 insertions(+), 6 deletions(-) create mode 100644 doc/lightning-autocleaninvoice.7 create mode 100644 doc/lightning-autocleaninvoice.7.txt diff --git a/doc/Makefile b/doc/Makefile index c09c340f2..788793e0b 100644 --- a/doc/Makefile +++ b/doc/Makefile @@ -5,6 +5,7 @@ doc-wrongdir: $(MAKE) -C .. doc-all MANPAGES := doc/lightning-cli.1 \ + doc/lightning-autocleaninvoice.7 \ doc/lightning-decodepay.7 \ doc/lightning-delexpiredinvoice.7 \ doc/lightning-delinvoice.7 \ diff --git a/doc/lightning-autocleaninvoice.7 b/doc/lightning-autocleaninvoice.7 new file mode 100644 index 000000000..e69de29bb diff --git a/doc/lightning-autocleaninvoice.7.txt b/doc/lightning-autocleaninvoice.7.txt new file mode 100644 index 000000000..c413d48d6 --- /dev/null +++ b/doc/lightning-autocleaninvoice.7.txt @@ -0,0 +1,42 @@ +LIGHTNING-AUTOCLEANINVOICE(7) +============================= +:doctype: manpage + +NAME +---- +lightning-autocleaninvoice - Set up auto-delete of expired invoice + +SYNOPSIS +-------- +*autocleaninvoice* ['cycle_seconds'] ['expired_by'] + +DESCRIPTION +----------- +The *autocleaninvoice* RPC command sets up automatic cleaning of +expired invoices. + +Autoclean will be done every 'cycle_seconds' seconds. +Setting 'cycle_seconds' to 0 disables autoclean. +If not specified, this defaults to 3600 (one hour). + +Every autoclean cycle, expired invoices, which have already +been expired for at least 'expired_by' seconds, will be deleted. +If 'expired_by' is not specified, this defaults to 86400 (one day). + +On startup of the daemon, no autoclean is set up. + +RETURN VALUE +------------ +On success, an empty object is returned. + +AUTHOR +------ +ZmnSCPxj is mainly responsible. + +SEE ALSO +-------- +lightning-delexpiredinvoice(7), lightning-delinvoice(7) + +RESOURCES +--------- +Main web site: https://github.com/ElementsProject/lightning diff --git a/doc/lightning-delexpiredinvoice.7 b/doc/lightning-delexpiredinvoice.7 index e69de29bb..d5f99e6c1 100644 --- a/doc/lightning-delexpiredinvoice.7 +++ b/doc/lightning-delexpiredinvoice.7 @@ -0,0 +1,51 @@ +'\" t +.\" Title: lightning-delexpiredinvoice +.\" Author: [see the "AUTHOR" section] +.\" Generator: DocBook XSL Stylesheets v1.79.1 +.\" Date: 03/17/2018 +.\" Manual: \ \& +.\" Source: \ \& +.\" Language: English +.\" +.TH "LIGHTNING\-DELEXPIRE" "7" "03/17/2018" "\ \&" "\ \&" +.\" ----------------------------------------------------------------- +.\" * Define some portability stuff +.\" ----------------------------------------------------------------- +.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +.\" http://bugs.debian.org/507673 +.\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html +.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.\" ----------------------------------------------------------------- +.\" * set default formatting +.\" ----------------------------------------------------------------- +.\" disable hyphenation +.nh +.\" disable justification (adjust text to left margin only) +.ad l +.\" ----------------------------------------------------------------- +.\" * MAIN CONTENT STARTS HERE * +.\" ----------------------------------------------------------------- +.SH "NAME" +lightning-delexpiredinvoice \- Protocol for removing expired invoices\&. +.SH "SYNOPSIS" +.sp +\fBdelexpiredinvoice\fR [\fImaxexpirytime\fR] +.SH "DESCRIPTION" +.sp +The \fBdelexpiredinvoice\fR RPC command removes all invoices that have expired on or before the given \fImaxexpirytime\fR\&. +.sp +If \fImaxexpirytime\fR is not specified then all expired invoices are deleted\&. +.SH "RETURN VALUE" +.sp +On success, an empty object is returned\&. +.SH "AUTHOR" +.sp +ZmnSCPxj is mainly responsible\&. +.SH "SEE ALSO" +.sp +lightning\-delinvoice(7), lightning\-autocleaninvoice(7) +.SH "RESOURCES" +.sp +Main web site: https://github\&.com/ElementsProject/lightning diff --git a/doc/lightning-delexpiredinvoice.7.txt b/doc/lightning-delexpiredinvoice.7.txt index c11610b19..521e77b58 100644 --- a/doc/lightning-delexpiredinvoice.7.txt +++ b/doc/lightning-delexpiredinvoice.7.txt @@ -20,7 +20,7 @@ deleted. RETURN VALUE ------------ -On success, does nothing. +On success, an empty object is returned. AUTHOR ------ @@ -28,7 +28,7 @@ ZmnSCPxj is mainly responsible. SEE ALSO -------- -lightning-delinvoice(7) +lightning-delinvoice(7), lightning-autocleaninvoice(7) RESOURCES --------- diff --git a/doc/lightning-delinvoice.7 b/doc/lightning-delinvoice.7 index c9baf3ed1..775e47527 100644 --- a/doc/lightning-delinvoice.7 +++ b/doc/lightning-delinvoice.7 @@ -2,12 +2,12 @@ .\" Title: lightning-delinvoice .\" Author: [see the "AUTHOR" section] .\" Generator: DocBook XSL Stylesheets v1.79.1 -.\" Date: 02/26/2018 +.\" Date: 03/17/2018 .\" Manual: \ \& .\" Source: \ \& .\" Language: English .\" -.TH "LIGHTNING\-DELINVOIC" "7" "02/26/2018" "\ \&" "\ \&" +.TH "LIGHTNING\-DELINVOIC" "7" "03/17/2018" "\ \&" "\ \&" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- @@ -45,7 +45,7 @@ On success, an invoice description will be returned as per lightning\-listinvoic Rusty Russell is mainly responsible\&. .SH "SEE ALSO" .sp -lightning\-listinvoice(7), lightning\-waitinvoice(7), lightning\-invoice(7), lightning\-delexpiredinvoice(7) +lightning\-listinvoice(7), lightning\-waitinvoice(7), lightning\-invoice(7), lightning\-delexpiredinvoice(7), lightning\-autocleaninvoice(7) .SH "RESOURCES" .sp Main web site: https://github\&.com/ElementsProject/lightning diff --git a/doc/lightning-delinvoice.7.txt b/doc/lightning-delinvoice.7.txt index 1e72a01b9..50dca972d 100644 --- a/doc/lightning-delinvoice.7.txt +++ b/doc/lightning-delinvoice.7.txt @@ -31,7 +31,7 @@ Rusty Russell is mainly responsible. SEE ALSO -------- lightning-listinvoice(7), lightning-waitinvoice(7), lightning-invoice(7), -lightning-delexpiredinvoice(7) +lightning-delexpiredinvoice(7), lightning-autocleaninvoice(7) RESOURCES --------- diff --git a/lightningd/invoice.c b/lightningd/invoice.c index d399029a0..90fb6775d 100644 --- a/lightningd/invoice.c +++ b/lightningd/invoice.c @@ -423,6 +423,56 @@ static const struct json_command delexpiredinvoice_command = { }; AUTODATA(json_command, &delexpiredinvoice_command); +static void json_autocleaninvoice(struct command *cmd, + const char *buffer, + const jsmntok_t *params) +{ + jsmntok_t *cycletok; + jsmntok_t *exbytok; + u64 cycle = 3600; + u64 exby = 86400; + struct json_result *result; + + if (!json_get_params(cmd, buffer, params, + "?cycle_seconds", &cycletok, + "?expired_by", &exbytok, + NULL)) { + return; + } + + if (cycletok) { + if (!json_tok_u64(buffer, cycletok, &cycle)) { + command_fail(cmd, "'%.*s' is not a valid number", + cycletok->end - cycletok->start, + buffer + cycletok->start); + return; + } + } + if (exbytok) { + if (!json_tok_u64(buffer, exbytok, &exby)) { + command_fail(cmd, "'%.*s' is not a valid number", + exbytok->end - exbytok->start, + buffer + exbytok->start); + return; + } + } + + wallet_invoice_autoclean(cmd->ld->wallet, cycle, exby); + + result = new_json_result(cmd); + json_object_start(result, NULL); + json_object_end(result); + command_success(cmd, result); +} +static const struct json_command autocleaninvoice_command = { + "autocleaninvoice", + json_autocleaninvoice, + "Set up autoclean of expired invoices. " + "Perform cleanup every {cycle_seconds} (default 3600), or disable autoclean if 0. " + "Clean up expired invoices that have expired for {expired_by} seconds (default 86400). " +}; +AUTODATA(json_command, &autocleaninvoice_command); + static void json_waitanyinvoice(struct command *cmd, const char *buffer, const jsmntok_t *params) { diff --git a/wallet/invoices.c b/wallet/invoices.c index 67bcc7520..de631bd88 100644 --- a/wallet/invoices.c +++ b/wallet/invoices.c @@ -43,6 +43,10 @@ struct invoices { u64 min_expiry_time; /* Expiration timer */ struct oneshot *expiration_timer; + /* Autoclean timer */ + struct oneshot *autoclean_timer; + u64 autoclean_cycle_seconds; + u64 autoclean_expired_by; }; static void trigger_invoice_waiter(struct invoice_waiter *w, @@ -128,6 +132,7 @@ struct invoices *invoices_new(const tal_t *ctx, list_head_init(&invs->waiters); invs->expiration_timer = NULL; + invs->autoclean_timer = NULL; return invs; } @@ -397,6 +402,42 @@ void invoices_delete_expired(struct invoices *invoices, db_exec_prepared(invoices->db, stmt); } +static void refresh_autoclean(struct invoices *invoices); +static void trigger_autoclean(struct invoices *invoices) +{ + u64 now = time_now().ts.tv_sec; + + invoices_delete_expired(invoices, + now - invoices->autoclean_expired_by); + + refresh_autoclean(invoices); +} +static void refresh_autoclean(struct invoices *invoices) +{ + struct timerel rel = time_from_sec(invoices->autoclean_cycle_seconds); + invoices->autoclean_timer = tal_free(invoices->autoclean_timer); + invoices->autoclean_timer = new_reltimer(invoices->timers, + invoices, + rel, + &trigger_autoclean, + invoices); +} + +void invoices_autoclean_set(struct invoices *invoices, + u64 cycle_seconds, + u64 expired_by) +{ + /* If not perform autoclean, just clear */ + if (cycle_seconds == 0) { + invoices->autoclean_timer = tal_free(invoices->autoclean_timer); + return; + } + + invoices->autoclean_cycle_seconds = cycle_seconds; + invoices->autoclean_expired_by = expired_by; + refresh_autoclean(invoices); +} + bool invoices_iterate(struct invoices *invoices, struct invoice_iterator *it) { diff --git a/wallet/invoices.h b/wallet/invoices.h index db898ccc3..68fd3b6f5 100644 --- a/wallet/invoices.h +++ b/wallet/invoices.h @@ -111,6 +111,22 @@ bool invoices_delete(struct invoices *invoices, void invoices_delete_expired(struct invoices *invoices, u64 max_expiry_time); +/** + * invoices_autoclean_set - Set up automatic deletion of + * expired invoices. + * + * @invoices - the invoice handler. + * @cycle_seconds - The number of seconds to repeat the + * automatic deletion. If 0, do not perform automatic + * deletion. + * @expiry_by - Each cycle, delete invoices that + * have been expired for at least `expiry_by` + * seconds. + */ +void invoices_autoclean_set(struct invoices *invoices, + u64 cycle_seconds, + u64 expired_by); + /** * invoices_iterate - Iterate over all existing invoices * diff --git a/wallet/test/run-wallet.c b/wallet/test/run-wallet.c index 60a201c9b..31f7010bf 100644 --- a/wallet/test/run-wallet.c +++ b/wallet/test/run-wallet.c @@ -99,6 +99,11 @@ u8 *get_offered_global_features(const tal_t *ctx UNNEEDED) /* Generated stub for get_offered_local_features */ u8 *get_offered_local_features(const tal_t *ctx UNNEEDED) { fprintf(stderr, "get_offered_local_features called!\n"); abort(); } +/* Generated stub for invoices_autoclean_set */ +void invoices_autoclean_set(struct invoices *invoices UNNEEDED, + u64 cycle_seconds UNNEEDED, + u64 expired_by UNNEEDED) +{ fprintf(stderr, "invoices_autoclean_set called!\n"); abort(); } /* Generated stub for invoices_create */ bool invoices_create(struct invoices *invoices UNNEEDED, struct invoice *pinvoice UNNEEDED, diff --git a/wallet/wallet.c b/wallet/wallet.c index 9045f3afa..ff469acce 100644 --- a/wallet/wallet.c +++ b/wallet/wallet.c @@ -1399,6 +1399,10 @@ void wallet_invoice_delete_expired(struct wallet *wallet, u64 e) { invoices_delete_expired(wallet->invoices, e); } +void wallet_invoice_autoclean(struct wallet *wallet, u64 c, u64 e) +{ + invoices_autoclean_set(wallet->invoices, c, e); +} bool wallet_invoice_iterate(struct wallet *wallet, struct invoice_iterator *it) { diff --git a/wallet/wallet.h b/wallet/wallet.h index 23a9450b1..46a4c3554 100644 --- a/wallet/wallet.h +++ b/wallet/wallet.h @@ -516,6 +516,17 @@ bool wallet_invoice_delete(struct wallet *wallet, void wallet_invoice_delete_expired(struct wallet *wallet, u64 max_expiry_time); +/** + * wallet_invoice_autoclean - Set up a repeating autoclean of + * expired invoices. + * Cleans (deletes) expired invoices every @cycle_seconds. + * Clean only those invoices that have been expired for at + * least @expired_by seconds or more. + */ +void wallet_invoice_autoclean(struct wallet * wallet, + u64 cycle_seconds, + u64 expired_by); + /** * wallet_invoice_iterate - Iterate over all existing invoices *