Browse Source

db: Migrate invoices.c to new abstraction layer

Signed-off-by: Christian Decker <decker.christian@gmail.com>
pull/2803/head
Christian Decker 6 years ago
committed by Rusty Russell
parent
commit
f19dc2ecc1
  1. 316
      wallet/invoices.c
  2. 49
      wallet/wallet.c

316
wallet/invoices.c

@ -12,7 +12,6 @@
#include <lightningd/invoice.h> #include <lightningd/invoice.h>
#include <lightningd/log.h> #include <lightningd/log.h>
#include <sodium/randombytes.h> #include <sodium/randombytes.h>
#include <sqlite3.h>
#include <string.h> #include <string.h>
struct invoice_waiter { struct invoice_waiter {
@ -85,38 +84,38 @@ trigger_invoice_waiter_expire_or_delete(struct invoices *invoices,
} }
static struct invoice_details *wallet_stmt2invoice_details(const tal_t *ctx, static struct invoice_details *wallet_stmt2invoice_details(const tal_t *ctx,
sqlite3_stmt *stmt) struct db_stmt *stmt)
{ {
struct invoice_details *dtl = tal(ctx, struct invoice_details); struct invoice_details *dtl = tal(ctx, struct invoice_details);
dtl->state = sqlite3_column_int(stmt, 0); dtl->state = db_column_int(stmt, 0);
sqlite3_column_preimage(stmt, 1, &dtl->r); db_column_preimage(stmt, 1, &dtl->r);
sqlite3_column_sha256(stmt, 2, &dtl->rhash); db_column_sha256(stmt, 2, &dtl->rhash);
dtl->label = sqlite3_column_json_escape(dtl, stmt, 3); dtl->label = db_column_json_escape(dtl, stmt, 3);
if (sqlite3_column_type(stmt, 4) != SQLITE_NULL) { if (!db_column_is_null(stmt, 4)) {
dtl->msat = tal(dtl, struct amount_msat); dtl->msat = tal(dtl, struct amount_msat);
*dtl->msat = sqlite3_column_amount_msat(stmt, 4); db_column_amount_msat(stmt, 4, dtl->msat);
} else { } else {
dtl->msat = NULL; dtl->msat = NULL;
} }
dtl->expiry_time = sqlite3_column_int64(stmt, 5); dtl->expiry_time = db_column_u64(stmt, 5);
if (dtl->state == PAID) { if (dtl->state == PAID) {
dtl->pay_index = sqlite3_column_int64(stmt, 6); dtl->pay_index = db_column_u64(stmt, 6);
dtl->received = sqlite3_column_amount_msat(stmt, 7); db_column_amount_msat(stmt, 7, &dtl->received);
dtl->paid_timestamp = sqlite3_column_int64(stmt, 8); dtl->paid_timestamp = db_column_u64(stmt, 8);
} }
dtl->bolt11 = tal_strndup(dtl, sqlite3_column_blob(stmt, 9), dtl->bolt11 = tal_strndup(dtl, db_column_blob(stmt, 9),
sqlite3_column_bytes(stmt, 9)); db_column_bytes(stmt, 9));
if (sqlite3_column_type(stmt, 10) != SQLITE_NULL) if (!db_column_is_null(stmt, 10))
dtl->description = tal_strdup( dtl->description = tal_strdup(
dtl, (const char *)sqlite3_column_text(stmt, 10)); dtl, (const char *)db_column_text(stmt, 10));
else else
dtl->description = NULL; dtl->description = NULL;
@ -126,16 +125,15 @@ static struct invoice_details *wallet_stmt2invoice_details(const tal_t *ctx,
/* Update expirations. */ /* Update expirations. */
static void update_db_expirations(struct invoices *invoices, u64 now) static void update_db_expirations(struct invoices *invoices, u64 now)
{ {
sqlite3_stmt *stmt; struct db_stmt *stmt;
stmt = db_prepare(invoices->db, stmt = db_prepare_v2(invoices->db, SQL("UPDATE invoices"
"UPDATE invoices"
" SET state = ?" " SET state = ?"
" WHERE state = ?" " WHERE state = ?"
" AND expiry_time <= ?;"); " AND expiry_time <= ?;"));
sqlite3_bind_int(stmt, 1, EXPIRED); db_bind_int(stmt, 0, EXPIRED);
sqlite3_bind_int(stmt, 2, UNPAID); db_bind_int(stmt, 1, UNPAID);
sqlite3_bind_int64(stmt, 3, now); db_bind_u64(stmt, 2, now);
db_exec_prepared(invoices->db, stmt); db_exec_prepared_v2(take(stmt));
} }
static void install_expiration_timer(struct invoices *invoices); static void install_expiration_timer(struct invoices *invoices);
@ -170,7 +168,7 @@ static void trigger_expiration(struct invoices *invoices)
struct list_head idlist; struct list_head idlist;
struct invoice_id_node *idn; struct invoice_id_node *idn;
u64 now = time_now().ts.tv_sec; u64 now = time_now().ts.tv_sec;
sqlite3_stmt *stmt; struct db_stmt *stmt;
struct invoice i; struct invoice i;
/* Free current expiration timer */ /* Free current expiration timer */
@ -178,18 +176,20 @@ static void trigger_expiration(struct invoices *invoices)
/* Acquire all expired invoices and save them in a list */ /* Acquire all expired invoices and save them in a list */
list_head_init(&idlist); list_head_init(&idlist);
stmt = db_select_prepare(invoices->db, stmt = db_prepare_v2(invoices->db, SQL("SELECT id"
"SELECT id"
" FROM invoices" " FROM invoices"
" WHERE state = ?" " WHERE state = ?"
" AND expiry_time <= ?;"); " AND expiry_time <= ?"));
sqlite3_bind_int(stmt, 1, UNPAID); db_bind_int(stmt, 0, UNPAID);
sqlite3_bind_int64(stmt, 2, now); db_bind_u64(stmt, 1, now);
while (db_select_step(invoices->db, stmt)) { db_query_prepared(stmt);
while (db_step(stmt)) {
idn = tal(tmpctx, struct invoice_id_node); idn = tal(tmpctx, struct invoice_id_node);
list_add_tail(&idlist, &idn->list); list_add_tail(&idlist, &idn->list);
idn->id = sqlite3_column_int64(stmt, 0); idn->id = db_column_u64(stmt, 0);
} }
tal_free(stmt);
/* Expire all those invoices */ /* Expire all those invoices */
update_db_expirations(invoices, now); update_db_expirations(invoices, now);
@ -198,9 +198,7 @@ static void trigger_expiration(struct invoices *invoices)
list_for_each(&idlist, idn, list) { list_for_each(&idlist, idn, list) {
/* Trigger expiration */ /* Trigger expiration */
i.id = idn->id; i.id = idn->id;
trigger_invoice_waiter_expire_or_delete(invoices, trigger_invoice_waiter_expire_or_delete(invoices, idn->id, &i);
idn->id,
&i);
} }
install_expiration_timer(invoices); install_expiration_timer(invoices);
@ -209,7 +207,7 @@ static void trigger_expiration(struct invoices *invoices)
static void install_expiration_timer(struct invoices *invoices) static void install_expiration_timer(struct invoices *invoices)
{ {
bool res; bool res;
sqlite3_stmt *stmt; struct db_stmt *stmt;
struct timerel rel; struct timerel rel;
struct timeabs expiry; struct timeabs expiry;
struct timeabs now = time_now(); struct timeabs now = time_now();
@ -217,20 +215,21 @@ static void install_expiration_timer(struct invoices *invoices)
assert(!invoices->expiration_timer); assert(!invoices->expiration_timer);
/* Find unpaid invoice with nearest expiry time */ /* Find unpaid invoice with nearest expiry time */
stmt = db_select_prepare(invoices->db, stmt = db_prepare_v2(invoices->db, SQL("SELECT MIN(expiry_time)"
"SELECT MIN(expiry_time)"
" FROM invoices" " FROM invoices"
" WHERE state = ?;"); " WHERE state = ?;"));
sqlite3_bind_int(stmt, 1, UNPAID); db_bind_int(stmt, 0, UNPAID);
res = db_select_step(invoices->db, stmt);
db_query_prepared(stmt);
res = db_step(stmt);
assert(res); assert(res);
if (sqlite3_column_type(stmt, 0) == SQLITE_NULL) {
if (db_column_is_null(stmt, 0))
/* Nothing to install */ /* Nothing to install */
db_stmt_done(stmt); goto done;
return;
} else invoices->min_expiry_time = db_column_u64(stmt, 0);
invoices->min_expiry_time = sqlite3_column_int64(stmt, 0);
db_stmt_done(stmt);
memset(&expiry, 0, sizeof(expiry)); memset(&expiry, 0, sizeof(expiry));
expiry.ts.tv_sec = invoices->min_expiry_time; expiry.ts.tv_sec = invoices->min_expiry_time;
@ -248,6 +247,8 @@ static void install_expiration_timer(struct invoices *invoices)
rel, rel,
&trigger_expiration, &trigger_expiration,
invoices); invoices);
done:
tal_free(stmt);
} }
bool invoices_create(struct invoices *invoices, bool invoices_create(struct invoices *invoices,
@ -260,7 +261,7 @@ bool invoices_create(struct invoices *invoices,
const struct preimage *r, const struct preimage *r,
const struct sha256 *rhash) const struct sha256 *rhash)
{ {
sqlite3_stmt *stmt; struct db_stmt *stmt;
struct invoice dummy; struct invoice dummy;
u64 expiry_time; u64 expiry_time;
u64 now = time_now().ts.tv_sec; u64 now = time_now().ts.tv_sec;
@ -277,11 +278,9 @@ bool invoices_create(struct invoices *invoices,
expiry_time = now + expiry; expiry_time = now + expiry;
/* Save to database. */ /* Save to database. */
/* Need to use the lower level API of sqlite3 to bind stmt = db_prepare_v2(
* label. Otherwise we'd need to implement sanitization of invoices->db,
* that string for sql injections... */ SQL("INSERT INTO invoices"
stmt = db_prepare(invoices->db,
"INSERT INTO invoices"
" ( payment_hash, payment_key, state" " ( payment_hash, payment_key, state"
" , msatoshi, label, expiry_time" " , msatoshi, label, expiry_time"
" , pay_index, msatoshi_received" " , pay_index, msatoshi_received"
@ -289,23 +288,24 @@ bool invoices_create(struct invoices *invoices,
" VALUES ( ?, ?, ?" " VALUES ( ?, ?, ?"
" , ?, ?, ?" " , ?, ?, ?"
" , NULL, NULL" " , NULL, NULL"
" , NULL, ?, ?);"); " , NULL, ?, ?);"));
sqlite3_bind_blob(stmt, 1, rhash, sizeof(struct sha256), SQLITE_TRANSIENT); db_bind_sha256(stmt, 0, rhash);
sqlite3_bind_blob(stmt, 2, r, sizeof(struct preimage), SQLITE_TRANSIENT); db_bind_preimage(stmt, 1, r);
sqlite3_bind_int(stmt, 3, UNPAID); db_bind_int(stmt, 2, UNPAID);
if (msat) if (msat)
sqlite3_bind_amount_msat(stmt, 4, *msat); db_bind_amount_msat(stmt, 3, msat);
else else
sqlite3_bind_null(stmt, 4); db_bind_null(stmt, 3);
sqlite3_bind_json_escape(stmt, 5, label); db_bind_json_escape(stmt, 4, label);
sqlite3_bind_int64(stmt, 6, expiry_time); db_bind_u64(stmt, 5, expiry_time);
sqlite3_bind_text(stmt, 7, b11enc, strlen(b11enc), SQLITE_TRANSIENT); db_bind_text(stmt, 6, b11enc);
sqlite3_bind_text(stmt, 8, description, strlen(description), SQLITE_TRANSIENT); db_bind_text(stmt, 7, description);
db_exec_prepared(invoices->db, stmt); db_exec_prepared_v2(stmt);
pinvoice->id = db_last_insert_id(invoices->db); pinvoice->id = db_last_insert_id(invoices->db);
tal_free(stmt);
/* Install expiration trigger. */ /* Install expiration trigger. */
if (!invoices->expiration_timer || if (!invoices->expiration_timer ||
@ -327,18 +327,20 @@ bool invoices_find_by_label(struct invoices *invoices,
struct invoice *pinvoice, struct invoice *pinvoice,
const struct json_escape *label) const struct json_escape *label)
{ {
sqlite3_stmt *stmt; struct db_stmt *stmt;
stmt = db_prepare_v2(invoices->db, SQL("SELECT id"
stmt = db_select_prepare(invoices->db,
"SELECT id"
" FROM invoices" " FROM invoices"
" WHERE label = ?;"); " WHERE label = ?;"));
sqlite3_bind_json_escape(stmt, 1, label); db_bind_json_escape(stmt, 0, label);
if (!db_select_step(invoices->db, stmt)) db_query_prepared(stmt);
if (!db_step(stmt)) {
tal_free(stmt);
return false; return false;
}
pinvoice->id = sqlite3_column_int64(stmt, 0); pinvoice->id = db_column_u64(stmt, 0);
db_stmt_done(stmt); tal_free(stmt);
return true; return true;
} }
@ -346,82 +348,88 @@ bool invoices_find_by_rhash(struct invoices *invoices,
struct invoice *pinvoice, struct invoice *pinvoice,
const struct sha256 *rhash) const struct sha256 *rhash)
{ {
sqlite3_stmt *stmt; struct db_stmt *stmt;
stmt = db_select_prepare(invoices->db, stmt = db_prepare_v2(invoices->db, SQL("SELECT id"
"SELECT id"
" FROM invoices" " FROM invoices"
" WHERE payment_hash = ?;"); " WHERE payment_hash = ?;"));
sqlite3_bind_blob(stmt, 1, rhash, sizeof(*rhash), SQLITE_TRANSIENT); db_bind_sha256(stmt, 0, rhash);
if (!db_select_step(invoices->db, stmt)) db_query_prepared(stmt);
return false;
pinvoice->id = sqlite3_column_int64(stmt, 0); if (!db_step(stmt)) {
db_stmt_done(stmt); tal_free(stmt);
return false;
} else {
pinvoice->id = db_column_u64(stmt, 0);
tal_free(stmt);
return true; return true;
} }
}
bool invoices_find_unpaid(struct invoices *invoices, bool invoices_find_unpaid(struct invoices *invoices,
struct invoice *pinvoice, struct invoice *pinvoice,
const struct sha256 *rhash) const struct sha256 *rhash)
{ {
sqlite3_stmt *stmt; struct db_stmt *stmt;
stmt = db_prepare_v2(invoices->db, SQL("SELECT id"
stmt = db_select_prepare(invoices->db,
"SELECT id"
" FROM invoices" " FROM invoices"
" WHERE payment_hash = ?" " WHERE payment_hash = ?"
" AND state = ?;"); " AND state = ?;"));
sqlite3_bind_blob(stmt, 1, rhash, sizeof(*rhash), SQLITE_TRANSIENT); db_bind_sha256(stmt, 0, rhash);
sqlite3_bind_int(stmt, 2, UNPAID); db_bind_int(stmt, 1, UNPAID);
if (!db_select_step(invoices->db, stmt)) db_query_prepared(stmt);
return false;
pinvoice->id = sqlite3_column_int64(stmt, 0); if (!db_step(stmt)) {
db_stmt_done(stmt); tal_free(stmt);
return false;
} else {
pinvoice->id = db_column_u64(stmt, 0);
tal_free(stmt);
return true; return true;
} }
}
bool invoices_delete(struct invoices *invoices, bool invoices_delete(struct invoices *invoices, struct invoice invoice)
struct invoice invoice)
{ {
sqlite3_stmt *stmt; struct db_stmt *stmt;
int changes;
/* Delete from database. */ /* Delete from database. */
stmt = db_prepare(invoices->db, "DELETE FROM invoices WHERE id=?;"); stmt = db_prepare_v2(invoices->db,
sqlite3_bind_int64(stmt, 1, invoice.id); SQL("DELETE FROM invoices WHERE id=?;"));
db_exec_prepared(invoices->db, stmt); db_bind_u64(stmt, 0, invoice.id);
db_exec_prepared_v2(stmt);
if (db_changes(invoices->db) != 1) changes = db_count_changes(stmt);
return false; tal_free(stmt);
if (changes != 1) {
return false;
}
/* Tell all the waiters about the fact that it was deleted. */ /* Tell all the waiters about the fact that it was deleted. */
trigger_invoice_waiter_expire_or_delete(invoices, trigger_invoice_waiter_expire_or_delete(invoices, invoice.id, NULL);
invoice.id, NULL);
return true; return true;
} }
void invoices_delete_expired(struct invoices *invoices, void invoices_delete_expired(struct invoices *invoices,
u64 max_expiry_time) u64 max_expiry_time)
{ {
sqlite3_stmt *stmt; struct db_stmt *stmt;
stmt = db_prepare(invoices->db, stmt = db_prepare_v2(invoices->db, SQL(
"DELETE FROM invoices" "DELETE FROM invoices"
" WHERE state = ?" " WHERE state = ?"
" AND expiry_time <= ?;"); " AND expiry_time <= ?;"));
sqlite3_bind_int(stmt, 1, EXPIRED); db_bind_int(stmt, 0, EXPIRED);
sqlite3_bind_int64(stmt, 2, max_expiry_time); db_bind_u64(stmt, 1, max_expiry_time);
db_exec_prepared(invoices->db, stmt); db_exec_prepared_v2(take(stmt));
} }
bool invoices_iterate(struct invoices *invoices, bool invoices_iterate(struct invoices *invoices,
struct invoice_iterator *it) struct invoice_iterator *it)
{ {
sqlite3_stmt *stmt; struct db_stmt *stmt;
if (!it->p) { if (!it->p) {
stmt = db_select_prepare(invoices->db, stmt = db_prepare_v2(invoices->db, SQL("SELECT"
"SELECT"
" state" " state"
", payment_key" ", payment_key"
", payment_hash" ", payment_hash"
@ -433,14 +441,19 @@ bool invoices_iterate(struct invoices *invoices,
", paid_timestamp" ", paid_timestamp"
", bolt11" ", bolt11"
", description" ", description"
" FROM invoices;"); " FROM invoices;"));
db_query_prepared(stmt);
it->p = stmt; it->p = stmt;
} else } else
stmt = it->p; stmt = it->p;
if (db_select_step(invoices->db, stmt))
if (db_step(stmt))
/* stmt doesn't need to be freed since we expect to be called
* again, and stmt will be freed on the last iteration. */
return true; return true;
tal_free(stmt);
it->p = NULL; it->p = NULL;
return false; return false;
} }
@ -450,7 +463,7 @@ invoices_iterator_deref(const tal_t *ctx, struct invoices *invoices UNUSED,
const struct invoice_iterator *it) const struct invoice_iterator *it)
{ {
assert(it->p); assert(it->p);
return wallet_stmt2invoice_details(ctx, (sqlite3_stmt*) it->p); return wallet_stmt2invoice_details(ctx, (struct db_stmt*) it->p);
} }
static s64 get_next_pay_index(struct db *db) static s64 get_next_pay_index(struct db *db)
@ -466,17 +479,19 @@ static s64 get_next_pay_index(struct db *db)
static enum invoice_status invoice_get_status(struct invoices *invoices, struct invoice invoice) static enum invoice_status invoice_get_status(struct invoices *invoices, struct invoice invoice)
{ {
sqlite3_stmt *stmt; struct db_stmt *stmt;
enum invoice_status state; enum invoice_status state;
bool res; bool res;
stmt = db_select_prepare(invoices->db, stmt = db_prepare_v2(
"SELECT state FROM invoices WHERE id = ?;"); invoices->db, SQL("SELECT state FROM invoices WHERE id = ?;"));
sqlite3_bind_int64(stmt, 1, invoice.id); db_bind_u64(stmt, 0, invoice.id);
res = db_select_step(invoices->db, stmt); db_query_prepared(stmt);
res = db_step(stmt);
assert(res); assert(res);
state = sqlite3_column_int(stmt, 0); state = db_column_int(stmt, 0);
db_stmt_done(stmt); tal_free(stmt);
return state; return state;
} }
@ -484,7 +499,7 @@ void invoices_resolve(struct invoices *invoices,
struct invoice invoice, struct invoice invoice,
struct amount_msat received) struct amount_msat received)
{ {
sqlite3_stmt *stmt; struct db_stmt *stmt;
s64 pay_index; s64 pay_index;
u64 paid_timestamp; u64 paid_timestamp;
enum invoice_status state = invoice_get_status(invoices, invoice); enum invoice_status state = invoice_get_status(invoices, invoice);
@ -496,19 +511,18 @@ void invoices_resolve(struct invoices *invoices,
paid_timestamp = time_now().ts.tv_sec; paid_timestamp = time_now().ts.tv_sec;
/* Update database. */ /* Update database. */
stmt = db_prepare(invoices->db, stmt = db_prepare_v2(invoices->db, SQL("UPDATE invoices"
"UPDATE invoices"
" SET state=?" " SET state=?"
" , pay_index=?" " , pay_index=?"
" , msatoshi_received=?" " , msatoshi_received=?"
" , paid_timestamp=?" " , paid_timestamp=?"
" WHERE id=?;"); " WHERE id=?;"));
sqlite3_bind_int(stmt, 1, PAID); db_bind_int(stmt, 0, PAID);
sqlite3_bind_int64(stmt, 2, pay_index); db_bind_u64(stmt, 1, pay_index);
sqlite3_bind_amount_msat(stmt, 3, received); db_bind_amount_msat(stmt, 2, &received);
sqlite3_bind_int64(stmt, 4, paid_timestamp); db_bind_u64(stmt, 3, paid_timestamp);
sqlite3_bind_int64(stmt, 5, invoice.id); db_bind_u64(stmt, 4, invoice.id);
db_exec_prepared(invoices->db, stmt); db_exec_prepared_v2(take(stmt));
/* Tell all the waiters about the paid invoice. */ /* Tell all the waiters about the paid invoice. */
trigger_invoice_waiter_resolve(invoices, invoice.id, &invoice); trigger_invoice_waiter_resolve(invoices, invoice.id, &invoice);
@ -548,30 +562,30 @@ void invoices_waitany(const tal_t *ctx,
void (*cb)(const struct invoice *, void*), void (*cb)(const struct invoice *, void*),
void *cbarg) void *cbarg)
{ {
sqlite3_stmt *stmt; struct db_stmt *stmt;
struct invoice invoice; struct invoice invoice;
/* Look for an already-paid invoice. */ /* Look for an already-paid invoice. */
stmt = db_select_prepare(invoices->db, stmt = db_prepare_v2(invoices->db,
"SELECT id" SQL("SELECT id"
" FROM invoices" " FROM invoices"
" WHERE pay_index NOT NULL" " WHERE pay_index NOT NULL"
" AND pay_index > ?" " AND pay_index > ?"
" ORDER BY pay_index ASC LIMIT 1;"); " ORDER BY pay_index ASC LIMIT 1;"));
sqlite3_bind_int64(stmt, 1, lastpay_index); db_bind_u64(stmt, 0, lastpay_index);
db_query_prepared(stmt);
if (db_select_step(invoices->db, stmt)) { if (db_step(stmt)) {
invoice.id = sqlite3_column_int64(stmt, 0); invoice.id = db_column_u64(stmt, 0);
db_stmt_done(stmt);
cb(&invoice, cbarg); cb(&invoice, cbarg);
return; } else {
}
/* None found. */ /* None found. */
add_invoice_waiter(ctx, &invoices->waiters, add_invoice_waiter(ctx, &invoices->waiters,
true, 0, cb, cbarg); true, 0, cb, cbarg);
} }
tal_free(stmt);
}
void invoices_waitone(const tal_t *ctx, void invoices_waitone(const tal_t *ctx,
@ -598,12 +612,11 @@ const struct invoice_details *invoices_get_details(const tal_t *ctx,
struct invoices *invoices, struct invoices *invoices,
struct invoice invoice) struct invoice invoice)
{ {
sqlite3_stmt *stmt; struct db_stmt *stmt;
bool res; bool res;
struct invoice_details *details; struct invoice_details *details;
stmt = db_select_prepare(invoices->db, stmt = db_prepare_v2(invoices->db, SQL("SELECT"
"SELECT"
" state" " state"
", payment_key" ", payment_key"
", payment_hash" ", payment_hash"
@ -616,12 +629,13 @@ const struct invoice_details *invoices_get_details(const tal_t *ctx,
", bolt11" ", bolt11"
", description" ", description"
" FROM invoices" " FROM invoices"
" WHERE id = ?;"); " WHERE id = ?;"));
sqlite3_bind_int64(stmt, 1, invoice.id); db_bind_u64(stmt, 0, invoice.id);
res = db_select_step(invoices->db, stmt); db_query_prepared(stmt);
res = db_step(stmt);
assert(res); assert(res);
details = wallet_stmt2invoice_details(ctx, stmt); details = wallet_stmt2invoice_details(ctx, stmt);
db_stmt_done(stmt); tal_free(stmt);
return details; return details;
} }

49
wallet/wallet.c

@ -68,7 +68,7 @@ struct wallet *wallet_new(struct lightningd *ld,
bool wallet_add_utxo(struct wallet *w, struct utxo *utxo, bool wallet_add_utxo(struct wallet *w, struct utxo *utxo,
enum wallet_output_type type) enum wallet_output_type type)
{ {
sqlite3_stmt *stmt; struct db_stmt *stmt;
stmt = db_select_prepare(w->db, stmt = db_select_prepare(w->db,
"SELECT * from outputs WHERE prev_out_tx=? AND prev_out_index=?"); "SELECT * from outputs WHERE prev_out_tx=? AND prev_out_index=?");
@ -81,8 +81,8 @@ bool wallet_add_utxo(struct wallet *w, struct utxo *utxo,
return false; return false;
} }
stmt = db_prepare(w->db, stmt = db_prepare_v2(
"INSERT INTO outputs (" w->db, SQL("INSERT INTO outputs ("
" prev_out_tx" " prev_out_tx"
", prev_out_index" ", prev_out_index"
", value" ", value"
@ -95,41 +95,40 @@ bool wallet_add_utxo(struct wallet *w, struct utxo *utxo,
", confirmation_height" ", confirmation_height"
", spend_height" ", spend_height"
", scriptpubkey" ", scriptpubkey"
") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);"); ") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);"));
sqlite3_bind_blob(stmt, 1, &utxo->txid, sizeof(utxo->txid), SQLITE_TRANSIENT); db_bind_txid(stmt, 0, &utxo->txid);
sqlite3_bind_int(stmt, 2, utxo->outnum); db_bind_int(stmt, 1, utxo->outnum);
sqlite3_bind_amount_sat(stmt, 3, utxo->amount); db_bind_amount_sat(stmt, 2, &utxo->amount);
sqlite3_bind_int(stmt, 4, wallet_output_type_in_db(type)); db_bind_int(stmt, 3, wallet_output_type_in_db(type));
sqlite3_bind_int(stmt, 5, output_state_available); db_bind_int(stmt, 4, output_state_available);
sqlite3_bind_int(stmt, 6, utxo->keyindex); db_bind_int(stmt, 5, utxo->keyindex);
if (utxo->close_info) { if (utxo->close_info) {
sqlite3_bind_int64(stmt, 7, utxo->close_info->channel_id); db_bind_u64(stmt, 6, utxo->close_info->channel_id);
sqlite3_bind_node_id(stmt, 8, &utxo->close_info->peer_id); db_bind_node_id(stmt, 7, &utxo->close_info->peer_id);
sqlite3_bind_pubkey(stmt, 9, &utxo->close_info->commitment_point); db_bind_pubkey(stmt, 8, &utxo->close_info->commitment_point);
} else { } else {
sqlite3_bind_null(stmt, 7); db_bind_null(stmt, 6);
sqlite3_bind_null(stmt, 8); db_bind_null(stmt, 7);
sqlite3_bind_null(stmt, 9); db_bind_null(stmt, 8);
} }
if (utxo->blockheight) { if (utxo->blockheight) {
sqlite3_bind_int(stmt, 10, *utxo->blockheight); db_bind_int(stmt, 9, *utxo->blockheight);
} else } else
sqlite3_bind_null(stmt, 10); db_bind_null(stmt, 9);
if (utxo->spendheight) if (utxo->spendheight)
sqlite3_bind_int(stmt, 11, *utxo->spendheight); db_bind_int(stmt, 10, *utxo->spendheight);
else else
sqlite3_bind_null(stmt, 11); db_bind_null(stmt, 10);
if (utxo->scriptPubkey) if (utxo->scriptPubkey)
sqlite3_bind_blob(stmt, 12, utxo->scriptPubkey, db_bind_blob(stmt, 11, utxo->scriptPubkey,
tal_bytelen(utxo->scriptPubkey), tal_bytelen(utxo->scriptPubkey));
SQLITE_TRANSIENT);
else else
sqlite3_bind_null(stmt, 12); db_bind_null(stmt, 11);
db_exec_prepared(w->db, stmt); db_exec_prepared_v2(take(stmt));
return true; return true;
} }

Loading…
Cancel
Save