mirror of
https://github.com/ElementsProject/lightning.git
synced 2025-01-17 19:03:42 +01:00
wallet: Adding primitives to save/load invoices to wallet
Signed-off-by: Christian Decker <decker.christian@gmail.com>
This commit is contained in:
parent
048680d0f2
commit
a005bce155
@ -1096,12 +1096,99 @@ bool wallet_htlcs_reconnect(struct wallet *wallet,
|
||||
if (!hout->in) {
|
||||
log_broken(
|
||||
wallet->log,
|
||||
"Unable to find corresponding htlc_in %" PRIu64
|
||||
" for htlc_out %" PRIu64,
|
||||
"Unable to find corresponding htlc_in %"PRIu64" for htlc_out %"PRIu64,
|
||||
hout->origin_htlc_id, hout->dbid);
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool wallet_invoice_save(struct wallet *wallet, struct invoice *inv)
|
||||
{
|
||||
/* Need to use the lower level API of sqlite3 to bind
|
||||
* label. Otherwise we'd need to implement sanitization of
|
||||
* that string for sql injections... */
|
||||
sqlite3_stmt *stmt;
|
||||
if (!inv->id) {
|
||||
stmt = db_prepare(wallet->db,
|
||||
"INSERT INTO invoices (payment_hash, payment_key, state, msatoshi, label) VALUES (?, ?, ?, ?, ?);");
|
||||
if (!stmt) {
|
||||
log_broken(wallet->log, "Could not prepare statement: %s", wallet->db->err);
|
||||
return false;
|
||||
}
|
||||
|
||||
sqlite3_bind_blob(stmt, 1, &inv->rhash, sizeof(inv->rhash), SQLITE_TRANSIENT);
|
||||
sqlite3_bind_blob(stmt, 2, &inv->r, sizeof(inv->r), SQLITE_TRANSIENT);
|
||||
sqlite3_bind_int(stmt, 3, inv->state);
|
||||
sqlite3_bind_int64(stmt, 4, inv->msatoshi);
|
||||
sqlite3_bind_text(stmt, 5, inv->label, strlen(inv->label), SQLITE_TRANSIENT);
|
||||
|
||||
if (!db_exec_prepared(wallet->db, stmt)) {
|
||||
log_broken(wallet->log, "Could not exec prepared statement: %s", wallet->db->err);
|
||||
return false;
|
||||
}
|
||||
|
||||
inv->id = sqlite3_last_insert_rowid(wallet->db->sql);
|
||||
return true;
|
||||
} else {
|
||||
stmt = db_prepare(wallet->db, "UPDATE invoices SET state=? WHERE id=?;");
|
||||
|
||||
if (!stmt) {
|
||||
log_broken(wallet->log, "Could not prepare statement: %s", wallet->db->err);
|
||||
return false;
|
||||
}
|
||||
|
||||
sqlite3_bind_int(stmt, 1, inv->state);
|
||||
sqlite3_bind_int64(stmt, 2, inv->id);
|
||||
|
||||
if (!db_exec_prepared(wallet->db, stmt)) {
|
||||
log_broken(wallet->log, "Could not exec prepared statement: %s", wallet->db->err);
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static bool wallet_stmt2invoice(sqlite3_stmt *stmt, struct invoice *inv)
|
||||
{
|
||||
inv->id = sqlite3_column_int64(stmt, 0);
|
||||
inv->state = sqlite3_column_int(stmt, 1);
|
||||
|
||||
assert(sqlite3_column_bytes(stmt, 2) == sizeof(struct preimage));
|
||||
memcpy(&inv->r, sqlite3_column_blob(stmt, 2), sqlite3_column_bytes(stmt, 2));
|
||||
|
||||
assert(sqlite3_column_bytes(stmt, 3) == sizeof(struct sha256));
|
||||
memcpy(&inv->rhash, sqlite3_column_blob(stmt, 3), sqlite3_column_bytes(stmt, 3));
|
||||
|
||||
inv->label = tal_strndup(inv, sqlite3_column_blob(stmt, 4), sqlite3_column_bytes(stmt, 4));
|
||||
inv->msatoshi = sqlite3_column_int64(stmt, 5);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool wallet_invoices_load(struct wallet *wallet, struct invoices *invs)
|
||||
{
|
||||
struct invoice *i;
|
||||
int count = 0;
|
||||
sqlite3_stmt *stmt = db_query(__func__, wallet->db,
|
||||
"SELECT id, state, payment_key, payment_hash, "
|
||||
"label, msatoshi FROM invoices;");
|
||||
if (!stmt) {
|
||||
log_broken(wallet->log, "Could not load invoices: %s", wallet->db->err);
|
||||
return false;
|
||||
}
|
||||
|
||||
while (sqlite3_step(stmt) == SQLITE_ROW) {
|
||||
i = tal(invs, struct invoice);
|
||||
if (!wallet_stmt2invoice(stmt, i)) {
|
||||
log_broken(wallet->log, "Error deserializing invoice");
|
||||
return false;
|
||||
}
|
||||
invoice_add(invs, i);
|
||||
count++;
|
||||
}
|
||||
|
||||
log_debug(wallet->log, "Loaded %d invoices from DB", count);
|
||||
return true;
|
||||
}
|
||||
|
@ -10,6 +10,7 @@
|
||||
#include <common/channel_config.h>
|
||||
#include <common/utxo.h>
|
||||
#include <lightningd/htlc_end.h>
|
||||
#include <lightningd/invoice.h>
|
||||
#include <wally_bip32.h>
|
||||
|
||||
struct lightningd;
|
||||
@ -300,4 +301,26 @@ bool wallet_htlcs_reconnect(struct wallet *wallet,
|
||||
struct htlc_in_map *htlcs_in,
|
||||
struct htlc_out_map *htlcs_out);
|
||||
|
||||
/**
|
||||
* wallet_invoice_save -- Save/update an invoice to the wallet
|
||||
*
|
||||
* Save or update the invoice in the wallet. If `inv->id` is 0 this
|
||||
* invoice will be considered a new invoice and result in an intert
|
||||
* into the database, otherwise it'll be updated.
|
||||
*
|
||||
* @wallet: Wallet to store in
|
||||
* @inv: Invoice to save
|
||||
*/
|
||||
bool wallet_invoice_save(struct wallet *wallet, struct invoice *inv);
|
||||
|
||||
/**
|
||||
* wallet_invoices_load -- Load all invoices into memory
|
||||
*
|
||||
* Load all invoices into the given `invoices` struct.
|
||||
*
|
||||
* @wallet: Wallet to load invoices from
|
||||
* @invs: invoices container to load into
|
||||
*/
|
||||
bool wallet_invoices_load(struct wallet *wallet, struct invoices *invs);
|
||||
|
||||
#endif /* WALLET_WALLET_H */
|
||||
|
@ -8,6 +8,9 @@
|
||||
#include <unistd.h>
|
||||
#include <wallet/test_utils.h>
|
||||
|
||||
void invoice_add(struct invoices *invs,
|
||||
struct invoice *inv){}
|
||||
|
||||
static struct wallet *create_test_wallet(const tal_t *ctx)
|
||||
{
|
||||
char filename[] = "/tmp/ldb-XXXXXX";
|
||||
|
Loading…
Reference in New Issue
Block a user