invoices: Remove persistent in-memory invoice structures.

This commit is contained in:
ZmnSCPxj 2018-02-23 01:04:47 +00:00 committed by Christian Decker
parent f05c86618c
commit 978e5c67d8
7 changed files with 240 additions and 255 deletions

View File

@ -62,7 +62,7 @@ static void tell_waiter(struct command *cmd, const struct invoice *inv)
struct json_result *response = new_json_result(cmd);
struct invoice_details details;
wallet_invoice_details(cmd, cmd->ld->wallet, inv, &details);
wallet_invoice_details(cmd, cmd->ld->wallet, *inv, &details);
json_add_invoice(response, &details, true);
if (details.state == PAID)
command_success(cmd, response);
@ -104,7 +104,7 @@ static bool hsm_sign_b11(const u5 *u5bytes,
static void json_invoice(struct command *cmd,
const char *buffer, const jsmntok_t *params)
{
const struct invoice *invoice;
struct invoice invoice;
struct invoice_details details;
jsmntok_t *msatoshi, *label, *desc, *exp, *fallback;
u64 *msatoshi_val;
@ -117,6 +117,7 @@ static void json_invoice(struct command *cmd,
char *b11enc;
const u8 *fallback_script;
u64 expiry = 3600;
bool result;
if (!json_get_params(cmd, buffer, params,
"msatoshi", &msatoshi,
@ -146,7 +147,7 @@ static void json_invoice(struct command *cmd,
/* label */
label_val = tal_strndup(cmd, buffer + label->start,
label->end - label->start);
if (wallet_invoice_find_by_label(wallet, label_val)) {
if (wallet_invoice_find_by_label(wallet, &invoice, label_val)) {
command_fail(cmd, "Duplicate label '%s'", label_val);
return;
}
@ -193,11 +194,12 @@ static void json_invoice(struct command *cmd,
}
invoice = wallet_invoice_create(cmd->ld->wallet,
take(msatoshi_val),
take(label_val),
expiry);
if (!invoice) {
result = wallet_invoice_create(cmd->ld->wallet,
&invoice,
take(msatoshi_val),
take(label_val),
expiry);
if (!result) {
command_fail(cmd, "Failed to create invoice on database");
return;
}
@ -318,7 +320,7 @@ AUTODATA(json_command, &listinvoices_command);
static void json_delinvoice(struct command *cmd,
const char *buffer, const jsmntok_t *params)
{
const struct invoice *i;
struct invoice i;
struct invoice_details details;
jsmntok_t *labeltok, *statustok;
struct json_result *response = new_json_result(cmd);
@ -334,8 +336,7 @@ static void json_delinvoice(struct command *cmd,
label = tal_strndup(cmd, buffer + labeltok->start,
labeltok->end - labeltok->start);
i = wallet_invoice_find_by_label(wallet, label);
if (!i) {
if (!wallet_invoice_find_by_label(wallet, &i, label)) {
command_fail(cmd, "Unknown invoice");
return;
}
@ -359,7 +360,7 @@ static void json_delinvoice(struct command *cmd,
if (!wallet_invoice_delete(wallet, i)) {
log_broken(cmd->ld->log,
"Error attempting to remove invoice %"PRIu64,
i->id);
i.id);
command_fail(cmd, "Database error");
return;
}
@ -424,7 +425,7 @@ AUTODATA(json_command, &waitanyinvoice_command);
static void json_waitinvoice(struct command *cmd,
const char *buffer, const jsmntok_t *params)
{
const struct invoice *i;
struct invoice i;
struct invoice_details details;
struct wallet *wallet = cmd->ld->wallet;
jsmntok_t *labeltok;
@ -434,18 +435,17 @@ static void json_waitinvoice(struct command *cmd,
return;
}
/* Search in paid invoices, if found return immediately */
/* Search for invoice */
label = tal_strndup(cmd, buffer + labeltok->start, labeltok->end - labeltok->start);
i = wallet_invoice_find_by_label(wallet, label);
if (!i) {
if (!wallet_invoice_find_by_label(wallet, &i, label)) {
command_fail(cmd, "Label not found");
return;
}
wallet_invoice_details(cmd, cmd->ld->wallet, i, &details);
/* If paid or expired return immediately */
if (details.state == PAID || details.state == EXPIRED) {
tell_waiter(cmd, i);
tell_waiter(cmd, &i);
return;
} else {
/* There is an unpaid one matching, let's wait... */

View File

@ -229,7 +229,7 @@ static void handle_localpay(struct htlc_in *hin,
u32 outgoing_cltv_value)
{
enum onion_type failcode;
const struct invoice *invoice;
struct invoice invoice;
struct invoice_details details;
struct lightningd *ld = hin->key.channel->peer->ld;
const tal_t *tmpctx = tal_tmpctx(ld);
@ -262,8 +262,7 @@ static void handle_localpay(struct htlc_in *hin,
goto fail;
}
invoice = wallet_invoice_find_unpaid(ld->wallet, payment_hash);
if (!invoice) {
if (!wallet_invoice_find_unpaid(ld->wallet, &invoice, payment_hash)) {
failcode = WIRE_UNKNOWN_PAYMENT_HASH;
goto fail;
}

View File

@ -37,8 +37,6 @@ struct invoices {
struct log *log;
/* The timers object to use for expirations. */
struct timers *timers;
/* The invoice list. */
struct list_head invlist;
/* Waiters waiting for invoices to be paid, expired, or deleted. */
struct list_head waiters;
/* Earliest time for some invoice to expire */
@ -92,37 +90,36 @@ trigger_invoice_waiter_expire_or_delete(struct invoices *invoices,
tal_free(tmpctx);
}
static bool wallet_stmt2invoice_details(sqlite3_stmt *stmt,
struct invoice *invoice,
static void wallet_stmt2invoice_details(const tal_t *ctx,
sqlite3_stmt *stmt,
struct invoice_details *dtl)
{
invoice->id = sqlite3_column_int64(stmt, 0);
dtl->state = sqlite3_column_int(stmt, 1);
dtl->state = sqlite3_column_int(stmt, 0);
assert(sqlite3_column_bytes(stmt, 2) == sizeof(struct preimage));
memcpy(&dtl->r, sqlite3_column_blob(stmt, 2), sqlite3_column_bytes(stmt, 2));
assert(sqlite3_column_bytes(stmt, 1) == sizeof(struct preimage));
memcpy(&dtl->r, sqlite3_column_blob(stmt, 1), sqlite3_column_bytes(stmt, 1));
assert(sqlite3_column_bytes(stmt, 3) == sizeof(struct sha256));
memcpy(&dtl->rhash, sqlite3_column_blob(stmt, 3), sqlite3_column_bytes(stmt, 3));
assert(sqlite3_column_bytes(stmt, 2) == sizeof(struct sha256));
memcpy(&dtl->rhash, sqlite3_column_blob(stmt, 2), sqlite3_column_bytes(stmt, 2));
dtl->label = tal_strndup(dtl, sqlite3_column_blob(stmt, 4), sqlite3_column_bytes(stmt, 4));
dtl->label = tal_strndup(ctx, sqlite3_column_blob(stmt, 3), sqlite3_column_bytes(stmt, 3));
if (sqlite3_column_type(stmt, 5) != SQLITE_NULL) {
dtl->msatoshi = tal(dtl, u64);
*dtl->msatoshi = sqlite3_column_int64(stmt, 5);
if (sqlite3_column_type(stmt, 4) != SQLITE_NULL) {
dtl->msatoshi = tal(ctx, u64);
*dtl->msatoshi = sqlite3_column_int64(stmt, 4);
} else {
dtl->msatoshi = NULL;
}
dtl->expiry_time = sqlite3_column_int64(stmt, 6);
dtl->expiry_time = sqlite3_column_int64(stmt, 5);
if (dtl->state == PAID) {
dtl->pay_index = sqlite3_column_int64(stmt, 7);
dtl->msatoshi_received = sqlite3_column_int64(stmt, 8);
dtl->paid_timestamp = sqlite3_column_int64(stmt, 9);
dtl->pay_index = sqlite3_column_int64(stmt, 6);
dtl->msatoshi_received = sqlite3_column_int64(stmt, 7);
dtl->paid_timestamp = sqlite3_column_int64(stmt, 8);
}
return true;
return;
}
struct invoices *invoices_new(const tal_t *ctx,
@ -136,7 +133,6 @@ struct invoices *invoices_new(const tal_t *ctx,
invs->log = log;
invs->timers = timers;
list_head_init(&invs->invlist);
list_head_init(&invs->waiters);
invs->expiration_timer = NULL;
@ -159,19 +155,6 @@ static void update_db_expirations(struct invoices *invoices, u64 now)
db_exec_prepared(invoices->db, stmt);
}
static struct invoice *invoices_find_by_id(struct invoices *invoices,
u64 id)
{
struct invoice *i;
/* FIXME: Use something better than a linear scan. */
list_for_each(&invoices->invlist, i, list) {
if (i->id == id)
return i;
}
return NULL;
}
struct invoice_id_node {
struct list_node list;
u64 id;
@ -185,7 +168,7 @@ static void trigger_expiration(struct invoices *invoices)
struct invoice_id_node *idn;
u64 now = time_now().ts.tv_sec;
sqlite3_stmt *stmt;
struct invoice *i;
struct invoice i;
/* Free current expiration timer */
invoices->expiration_timer = tal_free(invoices->expiration_timer);
@ -211,13 +194,11 @@ static void trigger_expiration(struct invoices *invoices)
/* Trigger expirations */
list_for_each(&idlist, idn, list) {
/* Update in-memory structure */
i = invoices_find_by_id(invoices, idn->id);
i->details->state = EXPIRED;
/* Trigger expiration */
i.id = idn->id;
trigger_invoice_waiter_expire_or_delete(invoices,
idn->id,
i);
&i);
}
install_expiration_timer(invoices);
@ -271,63 +252,34 @@ static void install_expiration_timer(struct invoices *invoices)
bool invoices_load(struct invoices *invoices)
{
int count = 0;
u64 now = time_now().ts.tv_sec;
struct invoice *i;
sqlite3_stmt *stmt;
update_db_expirations(invoices, now);
/* Load invoices from db. */
stmt = db_query(__func__, invoices->db,
"SELECT id, state, payment_key, payment_hash"
" , label, msatoshi, expiry_time, pay_index"
" , msatoshi_received, paid_timestamp"
" FROM invoices;");
if (!stmt) {
log_broken(invoices->log, "Could not load invoices");
return false;
}
while (sqlite3_step(stmt) == SQLITE_ROW) {
i = tal(invoices, struct invoice);
i->owner = invoices;
i->details = tal(i, struct invoice_details);
if (!wallet_stmt2invoice_details(stmt, i, i->details)) {
log_broken(invoices->log, "Error deserializing invoice");
sqlite3_finalize(stmt);
return false;
}
list_add_tail(&invoices->invlist, &i->list);
count++;
}
log_debug(invoices->log, "Loaded %d invoices from DB", count);
sqlite3_finalize(stmt);
install_expiration_timer(invoices);
return true;
}
const struct invoice *invoices_create(struct invoices *invoices,
u64 *msatoshi TAKES,
const char *label TAKES,
u64 expiry)
bool invoices_create(struct invoices *invoices,
struct invoice *pinvoice,
u64 *msatoshi TAKES,
const char *label TAKES,
u64 expiry)
{
sqlite3_stmt *stmt;
struct invoice *invoice;
struct invoice dummy;
struct preimage r;
struct sha256 rhash;
u64 expiry_time;
u64 now = time_now().ts.tv_sec;
if (invoices_find_by_label(invoices, label)) {
if (invoices_find_by_label(invoices, &dummy, label)) {
if (taken(msatoshi))
tal_free(msatoshi);
if (taken(label))
tal_free(label);
return NULL;
return false;
}
/* Compute expiration. */
@ -363,21 +315,7 @@ const struct invoice *invoices_create(struct invoices *invoices,
db_exec_prepared(invoices->db, stmt);
/* Create and load in-memory structure. */
invoice = tal(invoices, struct invoice);
invoice->owner = invoices;
invoice->id = sqlite3_last_insert_rowid(invoices->db->sql);
invoice->details = tal(invoice, struct invoice_details);
invoice->details->state = UNPAID;
invoice->details->label = tal_strdup(invoice->details, label);
invoice->details->msatoshi = tal_dup(invoice->details, u64, msatoshi); /* Works even if msatoshi == NULL. */
memcpy(&invoice->details->r, &r, sizeof(invoice->details->r));
memcpy(&invoice->details->rhash, &rhash, sizeof(invoice->details->rhash));
invoice->details->expiry_time = expiry_time;
/* Add to invoices object. */
list_add_tail(&invoices->invlist, &invoice->list);
pinvoice->id = sqlite3_last_insert_rowid(invoices->db->sql);
/* Install expiration trigger. */
if (!invoices->expiration_timer ||
@ -387,80 +325,109 @@ const struct invoice *invoices_create(struct invoices *invoices,
install_expiration_timer(invoices);
}
return invoice;
if (taken(msatoshi))
tal_free(msatoshi);
if (taken(label))
tal_free(label);
return true;
}
const struct invoice *invoices_find_by_label(struct invoices *invoices,
const char *label)
bool invoices_find_by_label(struct invoices *invoices,
struct invoice *pinvoice,
const char *label)
{
struct invoice *i;
sqlite3_stmt *stmt;
/* FIXME: Use something better than a linear scan. */
list_for_each(&invoices->invlist, i, list) {
if (streq(i->details->label, label))
return i;
stmt = db_prepare(invoices->db,
"SELECT id"
" FROM invoices"
" WHERE label = ?;");
sqlite3_bind_text(stmt, 1, label, strlen(label), SQLITE_TRANSIENT);
if (sqlite3_step(stmt) == SQLITE_ROW) {
pinvoice->id = sqlite3_column_int64(stmt, 0);
sqlite3_finalize(stmt);
return true;
} else {
sqlite3_finalize(stmt);
return false;
}
return NULL;
}
const struct invoice *invoices_find_unpaid(struct invoices *invoices,
const struct sha256 *rhash)
bool invoices_find_unpaid(struct invoices *invoices,
struct invoice *pinvoice,
const struct sha256 *rhash)
{
struct invoice *i;
sqlite3_stmt *stmt;
list_for_each(&invoices->invlist, i, list) {
if (structeq(rhash, &i->details->rhash) &&
i->details->state == UNPAID) {
if (time_now().ts.tv_sec > i->details->expiry_time)
break;
return i;
}
stmt = db_prepare(invoices->db,
"SELECT id"
" FROM invoices"
" WHERE payment_hash = ?"
" AND state = ?;");
sqlite3_bind_blob(stmt, 1, rhash, sizeof(*rhash), SQLITE_TRANSIENT);
sqlite3_bind_int(stmt, 2, UNPAID);
if (sqlite3_step(stmt) == SQLITE_ROW) {
pinvoice->id = sqlite3_column_int64(stmt, 0);
sqlite3_finalize(stmt);
return true;
} else {
sqlite3_finalize(stmt);
return false;
}
return NULL;
}
bool invoices_delete(struct invoices *invoices,
const struct invoice *cinvoice)
struct invoice invoice)
{
sqlite3_stmt *stmt;
struct invoice *invoice = (struct invoice *) cinvoice;
/* Delete from database. */
stmt = db_prepare(invoices->db, "DELETE FROM invoices WHERE id=?;");
sqlite3_bind_int64(stmt, 1, invoice->id);
sqlite3_bind_int64(stmt, 1, invoice.id);
db_exec_prepared(invoices->db, stmt);
if (sqlite3_changes(invoices->db->sql) != 1)
return false;
/* Delete from invoices object. */
list_del_from(&invoices->invlist, &invoice->list);
/* Tell all the waiters about the fact that it was deleted. */
trigger_invoice_waiter_expire_or_delete(invoices,
invoice->id, NULL);
/* Free all watchers and the invoice. */
tal_free(invoice);
invoice.id, NULL);
return true;
}
bool invoices_iterate(struct invoices *invoices,
struct invoice_iterator *it)
{
if (it->curr)
it->curr = list_next(&invoices->invlist, it->curr, list);
else
it->curr = list_top(&invoices->invlist, struct invoice, list);
return it->curr != NULL;
sqlite3_stmt *stmt;
int res;
if (!it->p) {
stmt = db_prepare(invoices->db,
"SELECT state, payment_key, payment_hash"
" , label, msatoshi, expiry_time, pay_index"
" , msatoshi_received, paid_timestamp"
" FROM invoices;");
it->p = stmt;
} else
stmt = it->p;
res = sqlite3_step(stmt);
if (res == SQLITE_DONE) {
sqlite3_finalize(stmt);
it->p = NULL;
return false;
} else {
assert(res == SQLITE_ROW);
return true;
}
}
void invoices_iterator_deref(const tal_t *ctx,
struct invoices *invoices,
const struct invoice_iterator *it,
struct invoice_details *details)
{
invoices_get_details(ctx, invoices, it->curr, details);
assert(it->p);
wallet_stmt2invoice_details(ctx, (sqlite3_stmt*) it->p, details);
}
static s64 get_next_pay_index(struct db *db)
@ -476,11 +443,10 @@ static s64 get_next_pay_index(struct db *db)
void invoices_resolve(struct invoices *invoices,
const struct invoice *cinvoice,
struct invoice invoice,
u64 msatoshi_received)
{
sqlite3_stmt *stmt;
struct invoice *invoice = (struct invoice *)cinvoice;
s64 pay_index;
u64 paid_timestamp;
const tal_t *tmpctx = tal_tmpctx(NULL);
@ -501,17 +467,11 @@ void invoices_resolve(struct invoices *invoices,
sqlite3_bind_int64(stmt, 2, pay_index);
sqlite3_bind_int64(stmt, 3, msatoshi_received);
sqlite3_bind_int64(stmt, 4, paid_timestamp);
sqlite3_bind_int64(stmt, 5, invoice->id);
sqlite3_bind_int64(stmt, 5, invoice.id);
db_exec_prepared(invoices->db, stmt);
/* Update in-memory structure. */
invoice->details->state = PAID;
invoice->details->pay_index = pay_index;
invoice->details->msatoshi_received = msatoshi_received;
invoice->details->paid_timestamp = paid_timestamp;
/* Tell all the waiters about the paid invoice. */
trigger_invoice_waiter_resolve(invoices, invoice->id, invoice);
trigger_invoice_waiter_resolve(invoices, invoice.id, &invoice);
/* Free all watchers. */
tal_free(tmpctx);
@ -552,13 +512,12 @@ void invoices_waitany(const tal_t *ctx,
void *cbarg)
{
sqlite3_stmt *stmt;
const struct invoice *invoice;
struct invoice invoice;
int res;
char const* label;
/* Look for an already-paid invoice. */
stmt = db_prepare(invoices->db,
"SELECT label"
"SELECT id"
" FROM invoices"
" WHERE pay_index NOT NULL"
" AND pay_index > ?"
@ -567,16 +526,10 @@ void invoices_waitany(const tal_t *ctx,
res = sqlite3_step(stmt);
if (res == SQLITE_ROW) {
/* Invoice found. Look up the invoice object. */
label = tal_strndup(ctx, sqlite3_column_blob(stmt, 0), sqlite3_column_bytes(stmt, 0));
invoice.id = sqlite3_column_int64(stmt, 0);
sqlite3_finalize(stmt);
/* The invoice should definitely exist in-memory. */
invoice = invoices_find_by_label(invoices, label);
assert(invoice);
tal_free(label);
cb(invoice, cbarg);
cb(&invoice, cbarg);
return;
}
@ -590,38 +543,53 @@ void invoices_waitany(const tal_t *ctx,
void invoices_waitone(const tal_t *ctx,
struct invoices *invoices UNUSED,
struct invoice const *cinvoice,
struct invoice invoice,
void (*cb)(const struct invoice *, void*),
void *cbarg)
{
struct invoice *invoice = (struct invoice*) cinvoice;
if (invoice->details->state == PAID || invoice->details->state == EXPIRED) {
cb(invoice, cbarg);
sqlite3_stmt *stmt;
int res;
enum invoice_status state;
stmt = db_prepare(invoices->db,
"SELECT state"
" FROM invoices"
" WHERE id = ?;");
sqlite3_bind_int64(stmt, 1, invoice.id);
res = sqlite3_step(stmt);
assert(res == SQLITE_ROW);
state = sqlite3_column_int(stmt, 0);
sqlite3_finalize(stmt);
if (state == PAID || state == EXPIRED) {
cb(&invoice, cbarg);
return;
}
/* Not yet paid. */
add_invoice_waiter(ctx, &invoices->waiters,
false, invoice->id, cb, cbarg);
false, invoice.id, cb, cbarg);
}
void invoices_get_details(const tal_t *ctx,
struct invoices *invoices,
const struct invoice *invoice,
struct invoice invoice,
struct invoice_details *dtl)
{
dtl->state = invoice->details->state;
dtl->r = invoice->details->r;
dtl->rhash = invoice->details->rhash;
dtl->label = tal_strdup(ctx, invoice->details->label);
dtl->msatoshi =
invoice->details->msatoshi ?
tal_dup(ctx, u64, invoice->details->msatoshi) :
/*otherwise*/ NULL ;
dtl->expiry_time = invoice->details->expiry_time;
if (dtl->state == PAID) {
dtl->pay_index = invoice->details->pay_index;
dtl->msatoshi_received = invoice->details->msatoshi_received;
dtl->paid_timestamp = invoice->details->paid_timestamp;
}
sqlite3_stmt *stmt;
int result;
stmt = db_prepare(invoices->db,
"SELECT state, payment_key, payment_hash"
" , label, msatoshi, expiry_time, pay_index"
" , msatoshi_received, paid_timestamp"
" FROM invoices"
" WHERE id = ?;");
sqlite3_bind_int64(stmt, 1, invoice.id);
result = sqlite3_step(stmt);
assert(result == SQLITE_ROW);
wallet_stmt2invoice_details(ctx, stmt, dtl);
sqlite3_finalize(stmt);
}

View File

@ -39,6 +39,7 @@ bool invoices_load(struct invoices *invoices);
* invoices_create - Create a new invoice.
*
* @invoices - the invoice handler.
* @pinvoice - pointer to location to load new invoice in.
* @msatoshi - the amount the invoice should have, or
* NULL for any-amount invoices.
* @label - the unique label for this invoice. Must be
@ -46,36 +47,44 @@ bool invoices_load(struct invoices *invoices);
* @expiry - the number of seconds before the invoice
* expires
*
* Returns NULL if label already exists or expiry is 0.
* Returns false if label already exists or expiry is 0.
* Returns true if created invoice.
* FIXME: Fallback addresses
*/
const struct invoice *invoices_create(struct invoices *invoices,
u64 *msatoshi TAKES,
const char *label TAKES,
u64 expiry);
bool invoices_create(struct invoices *invoices,
struct invoice *pinvoice,
u64 *msatoshi TAKES,
const char *label TAKES,
u64 expiry);
/**
* invoices_find_by_label - Search for an invoice by label
*
* @invoices - the invoice handler.
* @pinvoice - pointer to location to load found invoice in.
* @label - the label to search for. Must be null-terminated.
*
* Returns NULL if no invoice with that label exists.
* Returns false if no invoice with that label exists.
* Returns true if found.
*/
const struct invoice *invoices_find_by_label(struct invoices *invoices,
const char *label);
bool invoices_find_by_label(struct invoices *invoices,
struct invoice *pinvoice,
const char *label);
/**
* invoices_find_unpaid - Search for an unpaid, unexpired invoice by
* payment_hash
*
* @invoices - the invoice handler.
* @pinvoice - pointer to location to load found invoice in.
* @rhash - the payment_hash to search for.
*
* Returns NULL if no invoice with that payment hash exists.
* Returns false if no unpaid invoice with that rhash exists.
* Returns true if found.
*/
const struct invoice *invoices_find_unpaid(struct invoices *invoices,
const struct sha256 *rhash);
bool invoices_find_unpaid(struct invoices *invoices,
struct invoice *pinvoice,
const struct sha256 *rhash);
/**
* invoices_delete - Delete an invoice
@ -86,7 +95,7 @@ const struct invoice *invoices_find_unpaid(struct invoices *invoices,
* Return false on failure.
*/
bool invoices_delete(struct invoices *invoices,
const struct invoice *invoice);
struct invoice invoice);
/**
* invoices_iterate - Iterate over all existing invoices
@ -132,7 +141,7 @@ void invoices_iterator_deref(const tal_t *ctx,
* does not check).
*/
void invoices_resolve(struct invoices *invoices,
const struct invoice *invoice,
struct invoice invoice,
u64 msatoshi_received);
/**
@ -173,7 +182,7 @@ void invoices_waitany(const tal_t *ctx,
*/
void invoices_waitone(const tal_t *ctx,
struct invoices *invoices,
struct invoice const *invoice,
struct invoice invoice,
void (*cb)(const struct invoice *, void*),
void *cbarg);
@ -187,7 +196,7 @@ void invoices_waitone(const tal_t *ctx,
*/
void invoices_get_details(const tal_t *ctx,
struct invoices *invoices,
const struct invoice *invoice,
struct invoice invoice,
struct invoice_details *details);
#endif /* LIGHTNING_WALLET_INVOICES_H */

View File

@ -95,27 +95,30 @@ u8 *get_supported_global_features(const tal_t *ctx UNNEEDED)
u8 *get_supported_local_features(const tal_t *ctx UNNEEDED)
{ fprintf(stderr, "get_supported_local_features called!\n"); abort(); }
/* Generated stub for invoices_create */
const struct invoice *invoices_create(struct invoices *invoices UNNEEDED,
u64 *msatoshi TAKES UNNEEDED,
const char *label TAKES UNNEEDED,
u64 expiry UNNEEDED)
bool invoices_create(struct invoices *invoices UNNEEDED,
struct invoice *pinvoice UNNEEDED,
u64 *msatoshi TAKES UNNEEDED,
const char *label TAKES UNNEEDED,
u64 expiry UNNEEDED)
{ fprintf(stderr, "invoices_create called!\n"); abort(); }
/* Generated stub for invoices_delete */
bool invoices_delete(struct invoices *invoices UNNEEDED,
const struct invoice *invoice UNNEEDED)
struct invoice invoice UNNEEDED)
{ fprintf(stderr, "invoices_delete called!\n"); abort(); }
/* Generated stub for invoices_find_by_label */
const struct invoice *invoices_find_by_label(struct invoices *invoices UNNEEDED,
const char *label UNNEEDED)
bool invoices_find_by_label(struct invoices *invoices UNNEEDED,
struct invoice *pinvoice UNNEEDED,
const char *label UNNEEDED)
{ fprintf(stderr, "invoices_find_by_label called!\n"); abort(); }
/* Generated stub for invoices_find_unpaid */
const struct invoice *invoices_find_unpaid(struct invoices *invoices UNNEEDED,
const struct sha256 *rhash UNNEEDED)
bool invoices_find_unpaid(struct invoices *invoices UNNEEDED,
struct invoice *pinvoice UNNEEDED,
const struct sha256 *rhash UNNEEDED)
{ fprintf(stderr, "invoices_find_unpaid called!\n"); abort(); }
/* Generated stub for invoices_get_details */
void invoices_get_details(const tal_t *ctx UNNEEDED,
struct invoices *invoices UNNEEDED,
const struct invoice *invoice UNNEEDED,
struct invoice invoice UNNEEDED,
struct invoice_details *details UNNEEDED)
{ fprintf(stderr, "invoices_get_details called!\n"); abort(); }
/* Generated stub for invoices_iterate */
@ -139,7 +142,7 @@ struct invoices *invoices_new(const tal_t *ctx UNNEEDED,
{ fprintf(stderr, "invoices_new called!\n"); abort(); }
/* Generated stub for invoices_resolve */
void invoices_resolve(struct invoices *invoices UNNEEDED,
const struct invoice *invoice UNNEEDED,
struct invoice invoice UNNEEDED,
u64 msatoshi_received UNNEEDED)
{ fprintf(stderr, "invoices_resolve called!\n"); abort(); }
/* Generated stub for invoices_waitany */
@ -152,7 +155,7 @@ void invoices_waitany(const tal_t *ctx UNNEEDED,
/* Generated stub for invoices_waitone */
void invoices_waitone(const tal_t *ctx UNNEEDED,
struct invoices *invoices UNNEEDED,
struct invoice const *invoice UNNEEDED,
struct invoice invoice UNNEEDED,
void (*cb)(const struct invoice * UNNEEDED, void*) UNNEEDED,
void *cbarg UNNEEDED)
{ fprintf(stderr, "invoices_waitone called!\n"); abort(); }

View File

@ -1266,24 +1266,27 @@ bool wallet_invoice_load(struct wallet *wallet)
{
return invoices_load(wallet->invoices);
}
const struct invoice *wallet_invoice_create(struct wallet *wallet,
u64 *msatoshi TAKES,
const char *label TAKES,
u64 expiry) {
return invoices_create(wallet->invoices, msatoshi, label, expiry);
bool wallet_invoice_create(struct wallet *wallet,
struct invoice *pinvoice,
u64 *msatoshi TAKES,
const char *label TAKES,
u64 expiry) {
return invoices_create(wallet->invoices, pinvoice, msatoshi, label, expiry);
}
const struct invoice *wallet_invoice_find_by_label(struct wallet *wallet,
const char *label)
bool wallet_invoice_find_by_label(struct wallet *wallet,
struct invoice *pinvoice,
const char *label)
{
return invoices_find_by_label(wallet->invoices, label);
return invoices_find_by_label(wallet->invoices, pinvoice, label);
}
const struct invoice *wallet_invoice_find_unpaid(struct wallet *wallet,
const struct sha256 *rhash)
bool wallet_invoice_find_unpaid(struct wallet *wallet,
struct invoice *pinvoice,
const struct sha256 *rhash)
{
return invoices_find_unpaid(wallet->invoices, rhash);
return invoices_find_unpaid(wallet->invoices, pinvoice, rhash);
}
bool wallet_invoice_delete(struct wallet *wallet,
const struct invoice *invoice)
struct invoice invoice)
{
return invoices_delete(wallet->invoices, invoice);
}
@ -1300,7 +1303,7 @@ void wallet_invoice_iterator_deref(const tal_t *ctx,
return invoices_iterator_deref(ctx, wallet->invoices, it, details);
}
void wallet_invoice_resolve(struct wallet *wallet,
const struct invoice *invoice,
struct invoice invoice,
u64 msatoshi_received)
{
invoices_resolve(wallet->invoices, invoice, msatoshi_received);
@ -1315,7 +1318,7 @@ void wallet_invoice_waitany(const tal_t *ctx,
}
void wallet_invoice_waitone(const tal_t *ctx,
struct wallet *wallet,
struct invoice const *invoice,
struct invoice invoice,
void (*cb)(const struct invoice *, void*),
void *cbarg)
{
@ -1323,7 +1326,7 @@ void wallet_invoice_waitone(const tal_t *ctx,
}
void wallet_invoice_details(const tal_t *ctx,
struct wallet *wallet,
const struct invoice *invoice,
struct invoice invoice,
struct invoice_details *details)
{
invoices_get_details(ctx, wallet->invoices, invoice, details);

View File

@ -394,20 +394,13 @@ struct invoice_details {
struct invoice_iterator {
/* The contents of this object is subject to change
* and should not be depended upon */
const struct invoice *curr;
void *p;
};
struct invoice {
/* Internal, rest of lightningd should not use */
/* List off ld->wallet->invoices. Must be first or else
* dev-memleak is driven insane. */
struct list_node list;
/* Database ID */
u64 id;
/* The owning invoices object. */
struct invoices *owner;
/* Loaded details. */
struct invoice_details *details;
};
#define INVOICE_MAX_LABEL_LEN 128
@ -430,6 +423,7 @@ bool wallet_invoice_load(struct wallet *wallet);
* wallet_invoice_create - Create a new invoice.
*
* @wallet - the wallet to create the invoice in.
* @pinvoice - pointer to location to load new invoice in.
* @msatoshi - the amount the invoice should have, or
* NULL for any-amount invoices.
* @label - the unique label for this invoice. Must be
@ -437,36 +431,44 @@ bool wallet_invoice_load(struct wallet *wallet);
* @expiry - the number of seconds before the invoice
* expires
*
* Returns NULL if label already exists or expiry is 0.
* Returns false if label already exists or expiry is 0.
* Returns true if created invoice.
* FIXME: Fallback addresses
*/
const struct invoice *wallet_invoice_create(struct wallet *wallet,
u64 *msatoshi TAKES,
const char *label TAKES,
u64 expiry);
bool wallet_invoice_create(struct wallet *wallet,
struct invoice *pinvoice,
u64 *msatoshi TAKES,
const char *label TAKES,
u64 expiry);
/**
* wallet_invoice_find_by_label - Search for an invoice by label
*
* @wallet - the wallet to search.
* @pinvoice - pointer to location to load found invoice in.
* @label - the label to search for. Must be null-terminated.
*
* Returns NULL if no invoice with that label exists.
* Returns false if no invoice with that label exists.
* Returns true if found.
*/
const struct invoice *wallet_invoice_find_by_label(struct wallet *wallet,
const char *label);
bool wallet_invoice_find_by_label(struct wallet *wallet,
struct invoice *pinvoice,
const char *label);
/**
* wallet_invoice_find_unpaid - Search for an unpaid, unexpired invoice by
* payment_hash
*
* @wallet - the wallet to search.
* @pinvoice - pointer to location to load found invoice in.
* @rhash - the payment_hash to search for.
*
* Returns NULL if no invoice with that payment hash exists.
* Returns false if no unpaid invoice with that rhash exists.
* Returns true if found.
*/
const struct invoice *wallet_invoice_find_unpaid(struct wallet *wallet,
const struct sha256 *rhash);
bool wallet_invoice_find_unpaid(struct wallet *wallet,
struct invoice *pinvoice,
const struct sha256 *rhash);
/**
* wallet_invoice_delete - Delete an invoice
@ -477,7 +479,7 @@ const struct invoice *wallet_invoice_find_unpaid(struct wallet *wallet,
* Return false on failure.
*/
bool wallet_invoice_delete(struct wallet *wallet,
const struct invoice *invoice);
struct invoice invoice);
/**
* wallet_invoice_iterate - Iterate over all existing invoices
@ -520,10 +522,10 @@ void wallet_invoice_iterator_deref(const tal_t *ctx,
* @msatoshi_received - the actual amount received.
*
* Precondition: the invoice must not yet be expired (wallet
* does not check).
* does not check!).
*/
void wallet_invoice_resolve(struct wallet *wallet,
const struct invoice *invoice,
struct invoice invoice,
u64 msatoshi_received);
/**
@ -537,7 +539,8 @@ void wallet_invoice_resolve(struct wallet *wallet,
* @cb - the callback to invoke. If an invoice is already
* paid with pay_index greater than lastpay_index, this
* is called immediately, otherwise it is called during
* an invoices_resolve call.
* an invoices_resolve call. Will never be given a NULL
* pointer-to-invoice.
* @cbarg - the callback data.
*/
void wallet_invoice_waitany(const tal_t *ctx,
@ -564,7 +567,7 @@ void wallet_invoice_waitany(const tal_t *ctx,
*/
void wallet_invoice_waitone(const tal_t *ctx,
struct wallet *wallet,
struct invoice const *invoice,
struct invoice invoice,
void (*cb)(const struct invoice *, void*),
void *cbarg);
@ -578,7 +581,7 @@ void wallet_invoice_waitone(const tal_t *ctx,
*/
void wallet_invoice_details(const tal_t *ctx,
struct wallet *wallet,
const struct invoice *invoice,
struct invoice invoice,
struct invoice_details *details);
/**