From b06cb68330ce3029982e19652ce3db83f60e8bf7 Mon Sep 17 00:00:00 2001 From: Christian Decker Date: Tue, 20 Aug 2019 09:54:38 +0200 Subject: [PATCH] db: Migrate wallet.c to the new abstraction layer Signed-off-by: Christian Decker --- wallet/wallet.c | 2574 +++++++++++++++++++++++++---------------------- wallet/wallet.h | 2 +- 2 files changed, 1348 insertions(+), 1228 deletions(-) diff --git a/wallet/wallet.c b/wallet/wallet.c index eed173954..263eb00e9 100644 --- a/wallet/wallet.c +++ b/wallet/wallet.c @@ -25,7 +25,7 @@ static void outpointfilters_init(struct wallet *w) { - sqlite3_stmt *stmt; + struct db_stmt *stmt; struct utxo **utxos = wallet_get_utxos(NULL, w, output_state_any); struct bitcoin_txid txid; u32 outnum; @@ -37,13 +37,17 @@ static void outpointfilters_init(struct wallet *w) tal_free(utxos); w->utxoset_outpoints = outpointfilter_new(w); - stmt = db_select_prepare(w->db, "SELECT txid, outnum FROM utxoset WHERE spendheight is NULL"); + stmt = db_prepare_v2( + w->db, + SQL("SELECT txid, outnum FROM utxoset WHERE spendheight is NULL")); + db_query_prepared(stmt); - while (db_select_step(w->db, stmt)) { - sqlite3_column_sha256_double(stmt, 0, &txid.shad); - outnum = sqlite3_column_int(stmt, 1); + while (db_step(stmt)) { + db_column_sha256d(stmt, 0, &txid.shad); + outnum = db_column_int(stmt, 1); outpointfilter_add(w->utxoset_outpoints, &txid, outnum); } + tal_free(stmt); } struct wallet *wallet_new(struct lightningd *ld, @@ -70,16 +74,18 @@ bool wallet_add_utxo(struct wallet *w, struct utxo *utxo, { struct db_stmt *stmt; - stmt = db_select_prepare(w->db, - "SELECT * from outputs WHERE prev_out_tx=? AND prev_out_index=?"); - sqlite3_bind_blob(stmt, 1, &utxo->txid, sizeof(utxo->txid), SQLITE_TRANSIENT); - sqlite3_bind_int(stmt, 2, utxo->outnum); + stmt = db_prepare_v2(w->db, SQL("SELECT * from outputs WHERE " + "prev_out_tx=? AND prev_out_index=?")); + db_bind_txid(stmt, 0, &utxo->txid); + db_bind_int(stmt, 1, utxo->outnum); + db_query_prepared(stmt); /* If we get a result, that means a clash. */ - if (db_select_step(w->db, stmt)) { - db_stmt_done(stmt); + if (db_step(stmt)) { + tal_free(stmt); return false; } + tal_free(stmt); stmt = db_prepare_v2( w->db, SQL("INSERT INTO outputs (" @@ -135,21 +141,21 @@ bool wallet_add_utxo(struct wallet *w, struct utxo *utxo, /** * wallet_stmt2output - Extract data from stmt and fill an UTXO */ -static struct utxo *wallet_stmt2output(const tal_t *ctx, sqlite3_stmt *stmt) +static struct utxo *wallet_stmt2output(const tal_t *ctx, struct db_stmt *stmt) { struct utxo *utxo = tal(ctx, struct utxo); u32 *blockheight, *spendheight; - sqlite3_column_sha256_double(stmt, 0, &utxo->txid.shad); - utxo->outnum = sqlite3_column_int(stmt, 1); - utxo->amount = sqlite3_column_amount_sat(stmt, 2); - utxo->is_p2sh = sqlite3_column_int(stmt, 3) == p2sh_wpkh; - utxo->status = sqlite3_column_int(stmt, 4); - utxo->keyindex = sqlite3_column_int(stmt, 5); - if (sqlite3_column_type(stmt, 6) != SQLITE_NULL) { + db_column_txid(stmt, 0, &utxo->txid); + utxo->outnum = db_column_int(stmt, 1); + db_column_amount_sat(stmt, 2, &utxo->amount); + utxo->is_p2sh = db_column_int(stmt, 3) == p2sh_wpkh; + utxo->status = db_column_int(stmt, 4); + utxo->keyindex = db_column_int(stmt, 5); + if (!db_column_is_null(stmt, 6)) { utxo->close_info = tal(utxo, struct unilateral_close_info); - utxo->close_info->channel_id = sqlite3_column_int64(stmt, 6); - sqlite3_column_node_id(stmt, 7, &utxo->close_info->peer_id); - sqlite3_column_pubkey(stmt, 8, &utxo->close_info->commitment_point); + utxo->close_info->channel_id = db_column_u64(stmt, 6); + db_column_node_id(stmt, 7, &utxo->close_info->peer_id); + db_column_pubkey(stmt, 8, &utxo->close_info->commitment_point); } else { utxo->close_info = NULL; } @@ -158,22 +164,22 @@ static struct utxo *wallet_stmt2output(const tal_t *ctx, sqlite3_stmt *stmt) utxo->spendheight = NULL; utxo->scriptPubkey = NULL; - if (sqlite3_column_type(stmt, 9) != SQLITE_NULL) { + if (!db_column_is_null(stmt, 9)) { blockheight = tal(utxo, u32); - *blockheight = sqlite3_column_int(stmt, 9); + *blockheight = db_column_int(stmt, 9); utxo->blockheight = blockheight; } - if (sqlite3_column_type(stmt, 10) != SQLITE_NULL) { + if (!db_column_is_null(stmt, 10)) { spendheight = tal(utxo, u32); - *spendheight = sqlite3_column_int(stmt, 10); + *spendheight = db_column_int(stmt, 10); utxo->spendheight = spendheight; } - if (sqlite3_column_type(stmt, 11) != SQLITE_NULL) { + if (!db_column_is_null(stmt, 11)) { utxo->scriptPubkey = - tal_dup_arr(utxo, u8, sqlite3_column_blob(stmt, 11), - sqlite3_column_bytes(stmt, 11), 0); + tal_dup_arr(utxo, u8, db_column_blob(stmt, 11), + db_column_bytes(stmt, 11), 0); } return utxo; @@ -184,103 +190,112 @@ bool wallet_update_output_status(struct wallet *w, const u32 outnum, enum output_status oldstatus, enum output_status newstatus) { - sqlite3_stmt *stmt; + struct db_stmt *stmt; + size_t changes; if (oldstatus != output_state_any) { - stmt = db_prepare( - w->db, "UPDATE outputs SET status=? WHERE status=? AND prev_out_tx=? AND prev_out_index=?"); - sqlite3_bind_int(stmt, 1, output_status_in_db(newstatus)); - sqlite3_bind_int(stmt, 2, output_status_in_db(oldstatus)); - sqlite3_bind_blob(stmt, 3, txid, sizeof(*txid), SQLITE_TRANSIENT); - sqlite3_bind_int(stmt, 4, outnum); + stmt = db_prepare_v2( + w->db, SQL("UPDATE outputs SET status=? WHERE status=? AND " + "prev_out_tx=? AND prev_out_index=?")); + db_bind_int(stmt, 0, output_status_in_db(newstatus)); + db_bind_int(stmt, 1, output_status_in_db(oldstatus)); + db_bind_txid(stmt, 2, txid); + db_bind_int(stmt, 3, outnum); } else { - stmt = db_prepare( - w->db, "UPDATE outputs SET status=? WHERE prev_out_tx=? AND prev_out_index=?"); - sqlite3_bind_int(stmt, 1, output_status_in_db(newstatus)); - sqlite3_bind_blob(stmt, 2, txid, sizeof(*txid), SQLITE_TRANSIENT); - sqlite3_bind_int(stmt, 3, outnum); + stmt = db_prepare_v2(w->db, + SQL("UPDATE outputs SET status=? WHERE " + "prev_out_tx=? AND prev_out_index=?")); + db_bind_int(stmt, 0, output_status_in_db(newstatus)); + db_bind_txid(stmt, 1, txid); + db_bind_int(stmt, 2, outnum); } - db_exec_prepared(w->db, stmt); - return db_changes(w->db) > 0; + db_exec_prepared_v2(stmt); + changes = db_count_changes(stmt); + tal_free(stmt); + return changes > 0; } struct utxo **wallet_get_utxos(const tal_t *ctx, struct wallet *w, const enum output_status state) { struct utxo **results; int i; - sqlite3_stmt *stmt; - - if (state == output_state_any) - stmt = db_select_prepare(w->db, - "SELECT" - " prev_out_tx" - ", prev_out_index" - ", value" - ", type" - ", status" - ", keyindex" - ", channel_id" - ", peer_id" - ", commitment_point" - ", confirmation_height" - ", spend_height" - ", scriptpubkey " - "FROM outputs"); - else { - stmt = db_select_prepare(w->db, - "SELECT" - " prev_out_tx" - ", prev_out_index" - ", value" - ", type" - ", status" - ", keyindex" - ", channel_id" - ", peer_id" - ", commitment_point" - ", confirmation_height" - ", spend_height" - ", scriptpubkey " - "FROM outputs " - "WHERE status=?1"); - sqlite3_bind_int(stmt, 1, output_status_in_db(state)); - } + struct db_stmt *stmt; + + if (state == output_state_any) { + stmt = db_prepare_v2(w->db, SQL("SELECT" + " prev_out_tx" + ", prev_out_index" + ", value" + ", type" + ", status" + ", keyindex" + ", channel_id" + ", peer_id" + ", commitment_point" + ", confirmation_height" + ", spend_height" + ", scriptpubkey " + "FROM outputs")); + } else { + stmt = db_prepare_v2(w->db, SQL("SELECT" + " prev_out_tx" + ", prev_out_index" + ", value" + ", type" + ", status" + ", keyindex" + ", channel_id" + ", peer_id" + ", commitment_point" + ", confirmation_height" + ", spend_height" + ", scriptpubkey " + "FROM outputs " + "WHERE status= ? ")); + db_bind_int(stmt, 0, output_status_in_db(state)); + } + db_query_prepared(stmt); results = tal_arr(ctx, struct utxo*, 0); - for (i=0; db_select_step(w->db, stmt); i++) { + for (i=0; db_step(stmt); i++) { struct utxo *u = wallet_stmt2output(results, stmt); tal_arr_expand(&results, u); } + tal_free(stmt); return results; } -struct utxo **wallet_get_unconfirmed_closeinfo_utxos(const tal_t *ctx, struct wallet *w) +struct utxo **wallet_get_unconfirmed_closeinfo_utxos(const tal_t *ctx, + struct wallet *w) { + struct db_stmt *stmt; struct utxo **results; int i; - sqlite3_stmt *stmt = db_select_prepare(w->db, - "SELECT" - " prev_out_tx" - ", prev_out_index" - ", value" - ", type" - ", status" - ", keyindex" - ", channel_id" - ", peer_id" - ", commitment_point" - ", confirmation_height" - ", spend_height" - ", scriptpubkey" - " FROM outputs" - " WHERE channel_id IS NOT NULL AND confirmation_height IS NULL"); - - results = tal_arr(ctx, struct utxo*, 0); - for (i=0; db_select_step(w->db, stmt); i++) { + stmt = db_prepare_v2(w->db, SQL("SELECT" + " prev_out_tx" + ", prev_out_index" + ", value" + ", type" + ", status" + ", keyindex" + ", channel_id" + ", peer_id" + ", commitment_point" + ", confirmation_height" + ", spend_height" + ", scriptpubkey" + " FROM outputs" + " WHERE channel_id IS NOT NULL AND " + "confirmation_height IS NULL")); + db_query_prepared(stmt); + + results = tal_arr(ctx, struct utxo *, 0); + for (i = 0; db_step(stmt); i++) { struct utxo *u = wallet_stmt2output(results, stmt); tal_arr_expand(&results, u); } + tal_free(stmt); return results; } @@ -536,17 +551,20 @@ s64 wallet_get_newindex(struct lightningd *ld) static void wallet_shachain_init(struct wallet *wallet, struct wallet_shachain *chain) { - sqlite3_stmt *stmt; + struct db_stmt *stmt; assert(chain->id == 0); /* Create shachain */ shachain_init(&chain->chain); - stmt = db_prepare(wallet->db, "INSERT INTO shachains (min_index, num_valid) VALUES (?, 0);"); - sqlite3_bind_int64(stmt, 1, chain->chain.min_index); - db_exec_prepared(wallet->db, stmt); + stmt = db_prepare_v2( + wallet->db, + SQL("INSERT INTO shachains (min_index, num_valid) VALUES (?, 0);")); + db_bind_u64(stmt, 0, chain->chain.min_index); + db_exec_prepared_v2(stmt); - chain->id = db_last_insert_id(wallet->db); + chain->id = db_last_insert_id_v2(stmt); + tal_free(stmt); } /* TODO(cdecker) Stolen from shachain, move to some appropriate location */ @@ -570,7 +588,7 @@ bool wallet_shachain_add_hash(struct wallet *wallet, uint64_t index, const struct secret *hash) { - sqlite3_stmt *stmt; + struct db_stmt *stmt; u32 pos = count_trailing_zeroes(index); struct sha256 s; @@ -582,20 +600,22 @@ bool wallet_shachain_add_hash(struct wallet *wallet, return false; } - stmt = db_prepare(wallet->db, "UPDATE shachains SET num_valid=?, min_index=? WHERE id=?"); - sqlite3_bind_int(stmt, 1, chain->chain.num_valid); - sqlite3_bind_int64(stmt, 2, index); - sqlite3_bind_int64(stmt, 3, chain->id); - db_exec_prepared(wallet->db, stmt); + stmt = db_prepare_v2( + wallet->db, + SQL("UPDATE shachains SET num_valid=?, min_index=? WHERE id=?")); + db_bind_int(stmt, 0, chain->chain.num_valid); + db_bind_u64(stmt, 1, index); + db_bind_u64(stmt, 2, chain->id); + db_exec_prepared_v2(take(stmt)); - stmt = db_prepare( - wallet->db, - "REPLACE INTO shachain_known (shachain_id, pos, idx, hash) VALUES (?, ?, ?, ?);"); - sqlite3_bind_int64(stmt, 1, chain->id); - sqlite3_bind_int(stmt, 2, pos); - sqlite3_bind_int64(stmt, 3, index); - sqlite3_bind_blob(stmt, 4, hash, sizeof(*hash), SQLITE_TRANSIENT); - db_exec_prepared(wallet->db, stmt); + stmt = db_prepare_v2(wallet->db, + SQL("REPLACE INTO shachain_known (shachain_id, " + "pos, idx, hash) VALUES (?, ?, ?, ?);")); + db_bind_u64(stmt, 0, chain->id); + db_bind_int(stmt, 1, pos); + db_bind_u64(stmt, 2, index); + db_bind_secret(stmt, 3, hash); + db_exec_prepared_v2(take(stmt)); return true; } @@ -603,76 +623,91 @@ bool wallet_shachain_add_hash(struct wallet *wallet, bool wallet_shachain_load(struct wallet *wallet, u64 id, struct wallet_shachain *chain) { - sqlite3_stmt *stmt; + struct db_stmt *stmt; chain->id = id; shachain_init(&chain->chain); /* Load shachain metadata */ - stmt = db_select_prepare(wallet->db, "SELECT min_index, num_valid FROM shachains WHERE id=?"); - sqlite3_bind_int64(stmt, 1, id); + stmt = db_prepare_v2( + wallet->db, + SQL("SELECT min_index, num_valid FROM shachains WHERE id=?")); + db_bind_u64(stmt, 0, id); + db_query_prepared(stmt); - if (!db_select_step(wallet->db, stmt)) + if (!db_step(stmt)) { + tal_free(stmt); return false; + } - chain->chain.min_index = sqlite3_column_int64(stmt, 0); - chain->chain.num_valid = sqlite3_column_int64(stmt, 1); - db_stmt_done(stmt); + chain->chain.min_index = db_column_u64(stmt, 0); + chain->chain.num_valid = db_column_u64(stmt, 1); + tal_free(stmt); /* Load shachain known entries */ - stmt = db_select_prepare(wallet->db, "SELECT idx, hash, pos FROM shachain_known WHERE shachain_id=?"); - sqlite3_bind_int64(stmt, 1, id); - - while (db_select_step(wallet->db, stmt)) { - int pos = sqlite3_column_int(stmt, 2); - chain->chain.known[pos].index = sqlite3_column_int64(stmt, 0); - memcpy(&chain->chain.known[pos].hash, sqlite3_column_blob(stmt, 1), sqlite3_column_bytes(stmt, 1)); - } + stmt = db_prepare_v2(wallet->db, + SQL("SELECT idx, hash, pos FROM shachain_known " + "WHERE shachain_id=?")); + db_bind_u64(stmt, 0, id); + db_query_prepared(stmt); + + while (db_step(stmt)) { + int pos = db_column_int(stmt, 2); + chain->chain.known[pos].index = db_column_u64(stmt, 0); + db_column_sha256(stmt, 1, &chain->chain.known[pos].hash); + } + tal_free(stmt); return true; } static struct peer *wallet_peer_load(struct wallet *w, const u64 dbid) { const unsigned char *addrstr; - struct peer *peer; + struct peer *peer = NULL; struct node_id id; struct wireaddr_internal addr; + struct db_stmt *stmt; - sqlite3_stmt *stmt = db_select_prepare( - w->db, "SELECT id, node_id, address FROM peers WHERE id=?;"); - sqlite3_bind_int64(stmt, 1, dbid); + stmt = db_prepare_v2( + w->db, SQL("SELECT id, node_id, address FROM peers WHERE id=?;")); + db_bind_u64(stmt, 0, dbid); + db_query_prepared(stmt); - if (!db_select_step(w->db, stmt)) - return NULL; + if (!db_step(stmt)) + goto done; - if (!sqlite3_column_node_id(stmt, 1, &id)) { - db_stmt_done(stmt); - return NULL; - } - addrstr = sqlite3_column_text(stmt, 2); - if (!parse_wireaddr_internal((const char*)addrstr, &addr, DEFAULT_PORT, false, false, true, NULL)) { - db_stmt_done(stmt); - return NULL; - } + if (db_column_is_null(stmt, 1)) + goto done; + + db_column_node_id(stmt, 1, &id); + + addrstr = db_column_text(stmt, 2); + if (!parse_wireaddr_internal((const char*)addrstr, &addr, DEFAULT_PORT, false, false, true, NULL)) + goto done; - peer = new_peer(w->ld, sqlite3_column_int64(stmt, 0), - &id, &addr); - db_stmt_done(stmt); + peer = new_peer(w->ld, db_column_u64(stmt, 0), &id, &addr); +done: + tal_free(stmt); return peer; } static secp256k1_ecdsa_signature * wallet_htlc_sigs_load(const tal_t *ctx, struct wallet *w, u64 channelid) { - sqlite3_stmt *stmt = db_select_prepare(w->db, "SELECT signature FROM htlc_sigs WHERE channelid = ?"); + struct db_stmt *stmt; + + stmt = db_prepare_v2( + w->db, SQL("SELECT signature FROM htlc_sigs WHERE channelid = ?")); secp256k1_ecdsa_signature *htlc_sigs = tal_arr(ctx, secp256k1_ecdsa_signature, 0); - sqlite3_bind_int64(stmt, 1, channelid); + db_bind_u64(stmt, 0, channelid); + db_query_prepared(stmt); - while (db_select_step(w->db, stmt)) { + while (db_step(stmt)) { secp256k1_ecdsa_signature sig; - sqlite3_column_signature(stmt, 0, &sig); + db_column_signature(stmt, 0, &sig); tal_arr_expand(&htlc_sigs, sig); } + tal_free(stmt); log_debug(w->log, "Loaded %zu HTLC signatures from DB", tal_count(htlc_sigs)); @@ -683,23 +718,23 @@ bool wallet_remote_ann_sigs_load(const tal_t *ctx, struct wallet *w, u64 id, secp256k1_ecdsa_signature **remote_ann_node_sig, secp256k1_ecdsa_signature **remote_ann_bitcoin_sig) { - sqlite3_stmt *stmt; - int res; - stmt = db_select_prepare(w->db, - "SELECT remote_ann_node_sig, remote_ann_bitcoin_sig" - " FROM channels WHERE id = ?"); - sqlite3_bind_int64(stmt, 1, id); + struct db_stmt *stmt; + bool res; + stmt = db_prepare_v2( + w->db, SQL("SELECT remote_ann_node_sig, remote_ann_bitcoin_sig" + " FROM channels WHERE id = ?")); + db_bind_u64(stmt, 0, id); + db_query_prepared(stmt); - res = sqlite3_step(stmt); + res = db_step(stmt); /* This must succeed, since we know the channel exists */ - assert(res == SQLITE_ROW); + assert(res); /* if only one sig exists, forget the sig and hope peer send new ones*/ - if(sqlite3_column_type(stmt, 0) == SQLITE_NULL || - sqlite3_column_type(stmt, 1) == SQLITE_NULL) { + if (db_column_is_null(stmt, 0) || db_column_is_null(stmt, 1)) { *remote_ann_node_sig = *remote_ann_bitcoin_sig = NULL; - db_stmt_done(stmt); + tal_free(stmt); return true; } @@ -707,26 +742,26 @@ bool wallet_remote_ann_sigs_load(const tal_t *ctx, struct wallet *w, u64 id, *remote_ann_node_sig = tal(ctx, secp256k1_ecdsa_signature); *remote_ann_bitcoin_sig = tal(ctx, secp256k1_ecdsa_signature); - if (!sqlite3_column_signature(stmt, 0, *remote_ann_node_sig)) + if (!db_column_signature(stmt, 0, *remote_ann_node_sig)) goto fail; - if (!sqlite3_column_signature(stmt, 1, *remote_ann_bitcoin_sig)) + if (!db_column_signature(stmt, 1, *remote_ann_bitcoin_sig)) goto fail; - db_stmt_done(stmt); + tal_free(stmt); return true; fail: *remote_ann_node_sig = tal_free(*remote_ann_node_sig); *remote_ann_bitcoin_sig = tal_free(*remote_ann_bitcoin_sig); - db_stmt_done(stmt); + tal_free(stmt); return false; } /** - * wallet_stmt2channel - Helper to populate a wallet_channel from a sqlite3_stmt + * wallet_stmt2channel - Helper to populate a wallet_channel from a `db_stmt` */ -static struct channel *wallet_stmt2channel(struct wallet *w, sqlite3_stmt *stmt) +static struct channel *wallet_stmt2channel(struct wallet *w, struct db_stmt *stmt) { bool ok = true; struct channel_info channel_info; @@ -740,12 +775,14 @@ static struct channel *wallet_stmt2channel(struct wallet *w, sqlite3_stmt *stmt) struct bitcoin_signature last_sig; u8 *remote_shutdown_scriptpubkey; struct changed_htlc *last_sent_commit; - s64 final_key_idx; + s64 final_key_idx, channel_config_id; struct basepoints local_basepoints; struct pubkey local_funding_pubkey; struct pubkey *future_per_commitment_point; + struct amount_sat funding_sat; + struct amount_msat push_msat, our_msat, msat_to_us_min, msat_to_us_max; - peer_dbid = sqlite3_column_int64(stmt, 1); + peer_dbid = db_column_u64(stmt, 1); peer = find_peer_by_dbid(w->ld, peer_dbid); if (!peer) { peer = wallet_peer_load(w, peer_dbid); @@ -754,23 +791,22 @@ static struct channel *wallet_stmt2channel(struct wallet *w, sqlite3_stmt *stmt) } } - if (sqlite3_column_type(stmt, 2) != SQLITE_NULL) { + if (!db_column_is_null(stmt, 2)) { scid = tal(tmpctx, struct short_channel_id); - if (!sqlite3_column_short_channel_id(stmt, 2, scid)) + if (!db_column_short_channel_id(stmt, 2, scid)) return NULL; } else { scid = NULL; } - ok &= wallet_shachain_load(w, sqlite3_column_int64(stmt, 27), - &wshachain); + ok &= wallet_shachain_load(w, db_column_u64(stmt, 27), &wshachain); - remote_shutdown_scriptpubkey = sqlite3_column_arr(tmpctx, stmt, 28, u8); + remote_shutdown_scriptpubkey = db_column_arr(tmpctx, stmt, 28, u8); /* Do we have a last_sent_commit, if yes, populate */ - if (sqlite3_column_type(stmt, 41) != SQLITE_NULL) { - const u8 *cursor = sqlite3_column_blob(stmt, 41); - size_t len = sqlite3_column_bytes(stmt, 41); + if (!db_column_is_null(stmt, 41)) { + const u8 *cursor = db_column_blob(stmt, 41); + size_t len = db_column_bytes(stmt, 41); size_t n = 0; last_sent_commit = tal_arr(tmpctx, struct changed_htlc, n); while (len) { @@ -782,178 +818,182 @@ static struct channel *wallet_stmt2channel(struct wallet *w, sqlite3_stmt *stmt) last_sent_commit = NULL; #ifdef COMPAT_V060 - if (!last_sent_commit && sqlite3_column_type(stmt, 30) != SQLITE_NULL) { + if (!last_sent_commit && !db_column_is_null(stmt, 30)) { last_sent_commit = tal(tmpctx, struct changed_htlc); - last_sent_commit->newstate = sqlite3_column_int64(stmt, 30); - last_sent_commit->id = sqlite3_column_int64(stmt, 31); + last_sent_commit->newstate = db_column_u64(stmt, 30); + last_sent_commit->id = db_column_u64(stmt, 31); } #endif - if (sqlite3_column_type(stmt, 40) != SQLITE_NULL) { + if (!db_column_is_null(stmt, 40)) { future_per_commitment_point = tal(tmpctx, struct pubkey); - ok &= sqlite3_column_pubkey(stmt, 40, - future_per_commitment_point); + db_column_pubkey(stmt, 40, future_per_commitment_point); } else future_per_commitment_point = NULL; - ok &= wallet_channel_config_load(w, sqlite3_column_int64(stmt, 3), - &our_config); - ok &= sqlite3_column_sha256_double(stmt, 12, &funding_txid.shad); - - ok &= sqlite3_column_signature(stmt, 33, &last_sig.s); + channel_config_id = db_column_u64(stmt, 3); + ok &= wallet_channel_config_load(w, channel_config_id, &our_config); + db_column_sha256d(stmt, 12, &funding_txid.shad); + ok &= db_column_signature(stmt, 33, &last_sig.s); last_sig.sighash_type = SIGHASH_ALL; /* Populate channel_info */ - ok &= sqlite3_column_pubkey(stmt, 18, &channel_info.remote_fundingkey); - ok &= sqlite3_column_pubkey(stmt, 19, &channel_info.theirbase.revocation); - ok &= sqlite3_column_pubkey(stmt, 20, &channel_info.theirbase.payment); - ok &= sqlite3_column_pubkey(stmt, 21, &channel_info.theirbase.htlc); - ok &= sqlite3_column_pubkey(stmt, 22, &channel_info.theirbase.delayed_payment); - ok &= sqlite3_column_pubkey(stmt, 23, &channel_info.remote_per_commit); - ok &= sqlite3_column_pubkey(stmt, 24, &channel_info.old_remote_per_commit); - channel_info.feerate_per_kw[LOCAL] = sqlite3_column_int(stmt, 25); - channel_info.feerate_per_kw[REMOTE] = sqlite3_column_int(stmt, 26); - - wallet_channel_config_load(w, sqlite3_column_int64(stmt, 4), + db_column_pubkey(stmt, 18, &channel_info.remote_fundingkey); + db_column_pubkey(stmt, 19, &channel_info.theirbase.revocation); + db_column_pubkey(stmt, 20, &channel_info.theirbase.payment); + db_column_pubkey(stmt, 21, &channel_info.theirbase.htlc); + db_column_pubkey(stmt, 22, &channel_info.theirbase.delayed_payment); + db_column_pubkey(stmt, 23, &channel_info.remote_per_commit); + db_column_pubkey(stmt, 24, &channel_info.old_remote_per_commit); + channel_info.feerate_per_kw[LOCAL] = db_column_int(stmt, 25); + channel_info.feerate_per_kw[REMOTE] = db_column_int(stmt, 26); + + wallet_channel_config_load(w, db_column_u64(stmt, 4), &channel_info.their_config); if (!ok) { return NULL; } - final_key_idx = sqlite3_column_int64(stmt, 29); + final_key_idx = db_column_u64(stmt, 29); if (final_key_idx < 0) { log_broken(w->log, "%s: Final key < 0", __func__); return NULL; } - get_channel_basepoints(w->ld, &peer->id, sqlite3_column_int64(stmt, 0), + get_channel_basepoints(w->ld, &peer->id, db_column_u64(stmt, 0), &local_basepoints, &local_funding_pubkey); - chan = new_channel(peer, sqlite3_column_int64(stmt, 0), + + db_column_amount_sat(stmt, 14, &funding_sat); + db_column_amount_msat(stmt, 16, &push_msat); + db_column_amount_msat(stmt, 17, &our_msat); + db_column_amount_msat(stmt, 38, &msat_to_us_min); + db_column_amount_msat(stmt, 39, &msat_to_us_max); + + chan = new_channel(peer, db_column_u64(stmt, 0), &wshachain, - sqlite3_column_int(stmt, 5), - sqlite3_column_int(stmt, 6), + db_column_int(stmt, 5), + db_column_int(stmt, 6), NULL, /* Set up fresh log */ "Loaded from database", - sqlite3_column_int(stmt, 7), + db_column_int(stmt, 7), &our_config, - sqlite3_column_int(stmt, 8), - sqlite3_column_int64(stmt, 9), - sqlite3_column_int64(stmt, 10), - sqlite3_column_int64(stmt, 11), + db_column_int(stmt, 8), + db_column_u64(stmt, 9), + db_column_u64(stmt, 10), + db_column_u64(stmt, 11), &funding_txid, - sqlite3_column_int(stmt, 13), - sqlite3_column_amount_sat(stmt, 14), - sqlite3_column_amount_msat(stmt, 16), - sqlite3_column_int(stmt, 15) != 0, + db_column_int(stmt, 13), + funding_sat, + push_msat, + db_column_int(stmt, 15) != 0, scid, - sqlite3_column_amount_msat(stmt, 17), - sqlite3_column_amount_msat(stmt, 38), /* msatoshi_to_us_min */ - sqlite3_column_amount_msat(stmt, 39), /* msatoshi_to_us_max */ - sqlite3_column_tx(tmpctx, stmt, 32), + our_msat, + msat_to_us_min, /* msatoshi_to_us_min */ + msat_to_us_max, /* msatoshi_to_us_max */ + db_column_tx(tmpctx, stmt, 32), &last_sig, wallet_htlc_sigs_load(tmpctx, w, - sqlite3_column_int64(stmt, 0)), + db_column_u64(stmt, 0)), &channel_info, remote_shutdown_scriptpubkey, final_key_idx, - sqlite3_column_int(stmt, 34) != 0, + db_column_int(stmt, 34) != 0, last_sent_commit, - sqlite3_column_int64(stmt, 35), - sqlite3_column_int(stmt, 36), - sqlite3_column_int(stmt, 37), + db_column_u64(stmt, 35), + db_column_int(stmt, 36), + db_column_int(stmt, 37), /* Not connected */ false, &local_basepoints, &local_funding_pubkey, future_per_commitment_point, - sqlite3_column_int(stmt, 42), - sqlite3_column_int(stmt, 43), - sqlite3_column_arr(tmpctx, stmt, 44, u8)); + db_column_int(stmt, 42), + db_column_int(stmt, 43), + db_column_arr(tmpctx, stmt, 44, u8)); return chan; } static void set_max_channel_dbid(struct wallet *w) { - sqlite3_stmt *stmt; - int result; + struct db_stmt *stmt; - stmt = db_select(w->db, "SELECT id FROM channels ORDER BY id DESC LIMIT 1;"); + stmt = db_prepare_v2(w->db, SQL("SELECT id FROM channels ORDER BY id DESC LIMIT 1;")); + db_query_prepared(stmt); w->max_channel_dbid = 0; - result = sqlite3_step(stmt); - if (result == SQLITE_ROW) - w->max_channel_dbid = sqlite3_column_int64(stmt, 0); + if (db_step(stmt)) + w->max_channel_dbid = db_column_u64(stmt, 0); - db_stmt_done(stmt); + tal_free(stmt); } static bool wallet_channels_load_active(struct wallet *w) { bool ok = true; - sqlite3_stmt *stmt; + struct db_stmt *stmt; int count = 0; /* We load all channels */ - stmt = db_select(w->db, "SELECT" - " id" - ", peer_id" - ", short_channel_id" - ", channel_config_local" - ", channel_config_remote" - ", state" - ", funder" - ", channel_flags" - ", minimum_depth" - ", next_index_local" - ", next_index_remote" - ", next_htlc_id" - ", funding_tx_id" - ", funding_tx_outnum" - ", funding_satoshi" - ", funding_locked_remote" - ", push_msatoshi" - ", msatoshi_local" - ", fundingkey_remote" - ", revocation_basepoint_remote" - ", payment_basepoint_remote" - ", htlc_basepoint_remote" - ", delayed_payment_basepoint_remote" - ", per_commit_remote" - ", old_per_commit_remote" - ", local_feerate_per_kw" - ", remote_feerate_per_kw" - ", shachain_remote_id" - ", shutdown_scriptpubkey_remote" - ", shutdown_keyidx_local" - ", last_sent_commit_state" - ", last_sent_commit_id" - ", last_tx" - ", last_sig" - ", last_was_revoke" - ", first_blocknum" - ", min_possible_feerate" - ", max_possible_feerate" - ", msatoshi_to_us_min" - ", msatoshi_to_us_max" - ", future_per_commitment_point" - ", last_sent_commit" - ", feerate_base" - ", feerate_ppm" - ", remote_upfront_shutdown_script" - " FROM channels WHERE state < ?;"); - sqlite3_bind_int(stmt, 1, CLOSED); - - while (db_select_step(w->db, stmt)) { + stmt = db_prepare_v2(w->db, SQL("SELECT" + " id" + ", peer_id" + ", short_channel_id" + ", channel_config_local" + ", channel_config_remote" + ", state" + ", funder" + ", channel_flags" + ", minimum_depth" + ", next_index_local" + ", next_index_remote" + ", next_htlc_id" + ", funding_tx_id" + ", funding_tx_outnum" + ", funding_satoshi" + ", funding_locked_remote" + ", push_msatoshi" + ", msatoshi_local" + ", fundingkey_remote" + ", revocation_basepoint_remote" + ", payment_basepoint_remote" + ", htlc_basepoint_remote" + ", delayed_payment_basepoint_remote" + ", per_commit_remote" + ", old_per_commit_remote" + ", local_feerate_per_kw" + ", remote_feerate_per_kw" + ", shachain_remote_id" + ", shutdown_scriptpubkey_remote" + ", shutdown_keyidx_local" + ", last_sent_commit_state" + ", last_sent_commit_id" + ", last_tx" + ", last_sig" + ", last_was_revoke" + ", first_blocknum" + ", min_possible_feerate" + ", max_possible_feerate" + ", msatoshi_to_us_min" + ", msatoshi_to_us_max" + ", future_per_commitment_point" + ", last_sent_commit" + ", feerate_base" + ", feerate_ppm" + ", remote_upfront_shutdown_script" + " FROM channels WHERE state < ?;")); + db_bind_int(stmt, 0, CLOSED); + db_query_prepared(stmt); + + while (db_step(stmt)) { struct channel *c = wallet_stmt2channel(w, stmt); if (!c) { ok = false; - db_stmt_done(stmt); break; } count++; } log_debug(w->log, "Loaded %d channels from DB", count); - + tal_free(stmt); return ok; } @@ -972,20 +1012,39 @@ void wallet_channel_stats_incr_x(struct wallet *w, u64 cdbid, struct amount_msat msat) { - char const *payments_stat = tal_fmt(tmpctx, "%s_payments_%s", - dir, typ); - char const *msatoshi_stat = tal_fmt(tmpctx, "%s_msatoshi_%s", - dir, typ); - char const *qry = tal_fmt(tmpctx, - "UPDATE channels" - " SET %s = COALESCE(%s, 0) + 1" - " , %s = COALESCE(%s, 0) + %"PRIu64"" - " WHERE id = %"PRIu64";", - payments_stat, payments_stat, - msatoshi_stat, msatoshi_stat, msat.millisatoshis, /* Raw: db access */ - cdbid); - sqlite3_stmt *stmt = db_prepare(w->db, qry); - db_exec_prepared(w->db, stmt); + struct db_stmt *stmt; + const char *query; + /* TODO These would be much better as a switch statement, leaving + * these here for now in order to keep the commit clean. */ + if (streq(dir, "in") && streq(typ, "offered")) { + query = SQL("UPDATE channels" + " SET in_payments_offered = COALESCE(in_payments_offered, 0) + 1" + " , in_msatoshi_offered = COALESCE(in_msatoshi_offered, 0) + ?" + " WHERE id = ?;"); + } else if (streq(dir, "in") && streq(typ, "fulfilled")) { + query = SQL("UPDATE channels" + " SET in_payments_fulfilled = COALESCE(in_payments_fulfilled, 0) + 1" + " , in_msatoshi_fulfilled = COALESCE(in_msatoshi_fulfilled, 0) + ?" + " WHERE id = ?;"); + } else if (streq(dir, "out") && streq(typ, "offered")) { + query = SQL("UPDATE channels" + " SET out_payments_offered = COALESCE(out_payments_offered, 0) + 1" + " , out_msatoshi_offered = COALESCE(out_msatoshi_offered, 0) + ?" + " WHERE id = ?;"); + } else if (streq(dir, "out") && streq(typ, "fulfilled")) { + query = SQL("UPDATE channels" + " SET out_payments_fulfilled = COALESCE(out_payments_fulfilled, 0) + 1" + " , out_msatoshi_fulfilled = COALESCE(out_msatoshi_fulfilled, 0) + ?" + " WHERE id = ?;"); + } else { + fatal("Unknown stats key %s %s", dir, typ); + } + + stmt = db_prepare_v2(w->db, query); + db_bind_amount_msat(stmt, 0, &msat); + db_bind_u64(stmt, 1, cdbid); + + db_exec_prepared_v2(take(stmt)); } void wallet_channel_stats_incr_in_offered(struct wallet *w, u64 id, struct amount_msat m) @@ -1012,86 +1071,88 @@ void wallet_channel_stats_load(struct wallet *w, u64 id, struct channel_stats *stats) { - sqlite3_stmt *stmt; + struct db_stmt *stmt; int res; - stmt = db_select_prepare(w->db, - "SELECT" - " in_payments_offered, in_payments_fulfilled" - ", in_msatoshi_offered, in_msatoshi_fulfilled" - ", out_payments_offered, out_payments_fulfilled" - ", out_msatoshi_offered, out_msatoshi_fulfilled" - " FROM channels" - " WHERE id = ?"); - sqlite3_bind_int64(stmt, 1, id); - - res = sqlite3_step(stmt); + stmt = db_prepare_v2(w->db, SQL( + "SELECT" + " in_payments_offered, in_payments_fulfilled" + ", in_msatoshi_offered, in_msatoshi_fulfilled" + ", out_payments_offered, out_payments_fulfilled" + ", out_msatoshi_offered, out_msatoshi_fulfilled" + " FROM channels" + " WHERE id = ?")); + db_bind_u64(stmt, 0, id); + db_query_prepared(stmt); + + res = db_step(stmt); /* This must succeed, since we know the channel exists */ - assert(res == SQLITE_ROW); + assert(res); - stats->in_payments_offered = sqlite3_column_int64(stmt, 0); - stats->in_payments_fulfilled = sqlite3_column_int64(stmt, 1); - stats->in_msatoshi_offered = sqlite3_column_amount_msat(stmt, 2); - stats->in_msatoshi_fulfilled = sqlite3_column_amount_msat(stmt, 3); - stats->out_payments_offered = sqlite3_column_int64(stmt, 4); - stats->out_payments_fulfilled = sqlite3_column_int64(stmt, 5); - stats->out_msatoshi_offered = sqlite3_column_amount_msat(stmt, 6); - stats->out_msatoshi_fulfilled = sqlite3_column_amount_msat(stmt, 7); - db_stmt_done(stmt); + stats->in_payments_offered = db_column_u64(stmt, 0); + stats->in_payments_fulfilled = db_column_u64(stmt, 1); + db_column_amount_msat(stmt, 2, &stats->in_msatoshi_offered); + db_column_amount_msat(stmt, 3, &stats->in_msatoshi_fulfilled); + stats->out_payments_offered = db_column_u64(stmt, 4); + stats->out_payments_fulfilled = db_column_u64(stmt, 5); + db_column_amount_msat(stmt, 6, &stats->out_msatoshi_offered); + db_column_amount_msat(stmt, 7, &stats->out_msatoshi_fulfilled); + tal_free(stmt); } void wallet_blocks_heights(struct wallet *w, u32 def, u32 *min, u32 *max) { assert(min != NULL && max != NULL); - sqlite3_stmt *stmt = db_select_prepare(w->db, "SELECT MIN(height), MAX(height) FROM blocks;"); - + struct db_stmt *stmt = db_prepare_v2(w->db, SQL("SELECT MIN(height), MAX(height) FROM blocks;")); + db_query_prepared(stmt); *min = def; *max = def; /* If we ever processed a block we'll get the latest block in the chain */ - if (db_select_step(w->db, stmt)) { - if (sqlite3_column_type(stmt, 0) != SQLITE_NULL) { - *min = sqlite3_column_int(stmt, 0); - *max = sqlite3_column_int(stmt, 1); + if (db_step(stmt)) { + if (!db_column_is_null(stmt, 0)) { + *min = db_column_int(stmt, 0); + *max = db_column_int(stmt, 1); } - db_stmt_done(stmt); } + tal_free(stmt); } static void wallet_channel_config_insert(struct wallet *w, struct channel_config *cc) { - sqlite3_stmt *stmt; + struct db_stmt *stmt; assert(cc->id == 0); - stmt = db_prepare(w->db, "INSERT INTO channel_configs DEFAULT VALUES;"); - db_exec_prepared(w->db, stmt); - cc->id = db_last_insert_id(w->db); + stmt = db_prepare_v2(w->db, SQL("INSERT INTO channel_configs DEFAULT VALUES;")); + db_exec_prepared_v2(stmt); + cc->id = db_last_insert_id_v2(stmt); + tal_free(stmt); } static void wallet_channel_config_save(struct wallet *w, const struct channel_config *cc) { - sqlite3_stmt *stmt; + struct db_stmt *stmt; assert(cc->id != 0); - stmt = db_prepare(w->db, "UPDATE channel_configs SET" - " dust_limit_satoshis=?," - " max_htlc_value_in_flight_msat=?," - " channel_reserve_satoshis=?," - " htlc_minimum_msat=?," - " to_self_delay=?," - " max_accepted_htlcs=?" - " WHERE id=?;"); - sqlite3_bind_amount_sat(stmt, 1, cc->dust_limit); - sqlite3_bind_amount_msat(stmt, 2, cc->max_htlc_value_in_flight); - sqlite3_bind_amount_sat(stmt, 3, cc->channel_reserve); - sqlite3_bind_amount_msat(stmt, 4, cc->htlc_minimum); - sqlite3_bind_int(stmt, 5, cc->to_self_delay); - sqlite3_bind_int(stmt, 6, cc->max_accepted_htlcs); - sqlite3_bind_int64(stmt, 7, cc->id); - db_exec_prepared(w->db, stmt); + stmt = db_prepare_v2(w->db, SQL("UPDATE channel_configs SET" + " dust_limit_satoshis=?," + " max_htlc_value_in_flight_msat=?," + " channel_reserve_satoshis=?," + " htlc_minimum_msat=?," + " to_self_delay=?," + " max_accepted_htlcs=?" + " WHERE id=?;")); + db_bind_amount_sat(stmt, 0, &cc->dust_limit); + db_bind_amount_msat(stmt, 1, &cc->max_htlc_value_in_flight); + db_bind_amount_sat(stmt, 2, &cc->channel_reserve); + db_bind_amount_msat(stmt, 3, &cc->htlc_minimum); + db_bind_int(stmt, 4, cc->to_self_delay); + db_bind_int(stmt, 5, cc->max_accepted_htlcs); + db_bind_u64(stmt, 6, cc->id); + db_exec_prepared_v2(take(stmt)); } bool wallet_channel_config_load(struct wallet *w, const u64 id, @@ -1099,25 +1160,26 @@ bool wallet_channel_config_load(struct wallet *w, const u64 id, { bool ok = true; int col = 1; - const char *query = + const char *query = SQL( "SELECT id, dust_limit_satoshis, max_htlc_value_in_flight_msat, " "channel_reserve_satoshis, htlc_minimum_msat, to_self_delay, " - "max_accepted_htlcs FROM channel_configs WHERE id= ? ;"; - sqlite3_stmt *stmt = db_select_prepare(w->db, query); - sqlite3_bind_int64(stmt, 1, id); + "max_accepted_htlcs FROM channel_configs WHERE id= ? ;"); + struct db_stmt *stmt = db_prepare_v2(w->db, query); + db_bind_u64(stmt, 0, id); + db_query_prepared(stmt); - if (!db_select_step(w->db, stmt)) + if (!db_step(stmt)) return false; cc->id = id; - cc->dust_limit = sqlite3_column_amount_sat(stmt, col++); - cc->max_htlc_value_in_flight = sqlite3_column_amount_msat(stmt, col++); - cc->channel_reserve = sqlite3_column_amount_sat(stmt, col++); - cc->htlc_minimum = sqlite3_column_amount_msat(stmt, col++); - cc->to_self_delay = sqlite3_column_int(stmt, col++); - cc->max_accepted_htlcs = sqlite3_column_int(stmt, col++); + db_column_amount_sat(stmt, col++, &cc->dust_limit); + db_column_amount_msat(stmt, col++, &cc->max_htlc_value_in_flight); + db_column_amount_sat(stmt, col++, &cc->channel_reserve); + db_column_amount_msat(stmt, col++, &cc->htlc_minimum); + cc->to_self_delay = db_column_int(stmt, col++); + cc->max_accepted_htlcs = db_column_int(stmt, col++); assert(col == 7); - db_stmt_done(stmt); + tal_free(stmt); return ok; } @@ -1131,135 +1193,134 @@ void wallet_announcement_save(struct wallet *w, u64 id, secp256k1_ecdsa_signature *remote_ann_node_sig, secp256k1_ecdsa_signature *remote_ann_bitcoin_sig) { - sqlite3_stmt *stmt; + struct db_stmt *stmt; - stmt = db_prepare(w->db, "UPDATE channels SET" - " remote_ann_node_sig=?," - " remote_ann_bitcoin_sig=?" - " WHERE id=?"); + stmt = db_prepare_v2(w->db, SQL("UPDATE channels SET" + " remote_ann_node_sig=?," + " remote_ann_bitcoin_sig=?" + " WHERE id=?")); - sqlite3_bind_signature(stmt, 1, remote_ann_node_sig); - sqlite3_bind_signature(stmt, 2, remote_ann_bitcoin_sig); - sqlite3_bind_int64(stmt, 3, id); - db_exec_prepared(w->db, stmt); + db_bind_signature(stmt, 0, remote_ann_node_sig); + db_bind_signature(stmt, 1, remote_ann_bitcoin_sig); + db_bind_u64(stmt, 2, id); + db_exec_prepared_v2(take(stmt)); } void wallet_channel_save(struct wallet *w, struct channel *chan) { - sqlite3_stmt *stmt; + struct db_stmt *stmt; u8 *last_sent_commit; assert(chan->first_blocknum); wallet_channel_config_save(w, &chan->our_config); - stmt = db_prepare(w->db, "UPDATE channels SET" - " shachain_remote_id=?," - " short_channel_id=?," - " state=?," - " funder=?," - " channel_flags=?," - " minimum_depth=?," - " next_index_local=?," - " next_index_remote=?," - " next_htlc_id=?," - " funding_tx_id=?," - " funding_tx_outnum=?," - " funding_satoshi=?," - " funding_locked_remote=?," - " push_msatoshi=?," - " msatoshi_local=?," - " shutdown_scriptpubkey_remote=?," - " shutdown_keyidx_local=?," - " channel_config_local=?," - " last_tx=?, last_sig=?," - " last_was_revoke=?," - " min_possible_feerate=?," - " max_possible_feerate=?," - " msatoshi_to_us_min=?," - " msatoshi_to_us_max=?," - " feerate_base=?," - " feerate_ppm=?," - " remote_upfront_shutdown_script=?" - " WHERE id=?"); - sqlite3_bind_int64(stmt, 1, chan->their_shachain.id); + stmt = db_prepare_v2(w->db, SQL("UPDATE channels SET" + " shachain_remote_id=?," + " short_channel_id=?," + " state=?," + " funder=?," + " channel_flags=?," + " minimum_depth=?," + " next_index_local=?," + " next_index_remote=?," + " next_htlc_id=?," + " funding_tx_id=?," + " funding_tx_outnum=?," + " funding_satoshi=?," + " funding_locked_remote=?," + " push_msatoshi=?," + " msatoshi_local=?," + " shutdown_scriptpubkey_remote=?," + " shutdown_keyidx_local=?," + " channel_config_local=?," + " last_tx=?, last_sig=?," + " last_was_revoke=?," + " min_possible_feerate=?," + " max_possible_feerate=?," + " msatoshi_to_us_min=?," + " msatoshi_to_us_max=?," + " feerate_base=?," + " feerate_ppm=?," + " remote_upfront_shutdown_script=?" + " WHERE id=?")); + db_bind_u64(stmt, 0, chan->their_shachain.id); if (chan->scid) - sqlite3_bind_short_channel_id(stmt, 2, chan->scid); + db_bind_short_channel_id(stmt, 1, chan->scid); else - sqlite3_bind_null(stmt, 2); - sqlite3_bind_int(stmt, 3, chan->state); - sqlite3_bind_int(stmt, 4, chan->funder); - sqlite3_bind_int(stmt, 5, chan->channel_flags); - sqlite3_bind_int(stmt, 6, chan->minimum_depth); + db_bind_null(stmt, 1); + db_bind_int(stmt, 2, chan->state); + db_bind_int(stmt, 3, chan->funder); + db_bind_int(stmt, 4, chan->channel_flags); + db_bind_int(stmt, 5, chan->minimum_depth); - sqlite3_bind_int64(stmt, 7, chan->next_index[LOCAL]); - sqlite3_bind_int64(stmt, 8, chan->next_index[REMOTE]); - sqlite3_bind_int64(stmt, 9, chan->next_htlc_id); + db_bind_u64(stmt, 6, chan->next_index[LOCAL]); + db_bind_u64(stmt, 7, chan->next_index[REMOTE]); + db_bind_u64(stmt, 8, chan->next_htlc_id); - sqlite3_bind_sha256_double(stmt, 10, &chan->funding_txid.shad); + db_bind_sha256d(stmt, 9, &chan->funding_txid.shad); - sqlite3_bind_int(stmt, 11, chan->funding_outnum); - sqlite3_bind_amount_sat(stmt, 12, chan->funding); - sqlite3_bind_int(stmt, 13, chan->remote_funding_locked); - sqlite3_bind_amount_msat(stmt, 14, chan->push); - sqlite3_bind_amount_msat(stmt, 15, chan->our_msat); + db_bind_int(stmt, 10, chan->funding_outnum); + db_bind_amount_sat(stmt, 11, &chan->funding); + db_bind_int(stmt, 12, chan->remote_funding_locked); + db_bind_amount_msat(stmt, 13, &chan->push); + db_bind_amount_msat(stmt, 14, &chan->our_msat); if (chan->remote_shutdown_scriptpubkey) - sqlite3_bind_blob(stmt, 16, chan->remote_shutdown_scriptpubkey, - tal_count(chan->remote_shutdown_scriptpubkey), - SQLITE_TRANSIENT); + db_bind_blob(stmt, 15, chan->remote_shutdown_scriptpubkey, + tal_count(chan->remote_shutdown_scriptpubkey)); else - sqlite3_bind_null(stmt, 16); - - sqlite3_bind_int64(stmt, 17, chan->final_key_idx); - sqlite3_bind_int64(stmt, 18, chan->our_config.id); - sqlite3_bind_tx(stmt, 19, chan->last_tx); - sqlite3_bind_signature(stmt, 20, &chan->last_sig.s); - sqlite3_bind_int(stmt, 21, chan->last_was_revoke); - sqlite3_bind_int(stmt, 22, chan->min_possible_feerate); - sqlite3_bind_int(stmt, 23, chan->max_possible_feerate); - sqlite3_bind_amount_msat(stmt, 24, chan->msat_to_us_min); - sqlite3_bind_amount_msat(stmt, 25, chan->msat_to_us_max); - sqlite3_bind_int(stmt, 26, chan->feerate_base); - sqlite3_bind_int(stmt, 27, chan->feerate_ppm); + db_bind_null(stmt, 15); + + db_bind_u64(stmt, 16, chan->final_key_idx); + db_bind_u64(stmt, 17, chan->our_config.id); + db_bind_tx(stmt, 18, chan->last_tx); + db_bind_signature(stmt, 19, &chan->last_sig.s); + db_bind_int(stmt, 20, chan->last_was_revoke); + db_bind_int(stmt, 21, chan->min_possible_feerate); + db_bind_int(stmt, 22, chan->max_possible_feerate); + db_bind_amount_msat(stmt, 23, &chan->msat_to_us_min); + db_bind_amount_msat(stmt, 24, &chan->msat_to_us_max); + db_bind_int(stmt, 25, chan->feerate_base); + db_bind_int(stmt, 26, chan->feerate_ppm); if (chan->remote_upfront_shutdown_script) - sqlite3_bind_blob(stmt, 28, chan->remote_upfront_shutdown_script, - tal_count(chan->remote_upfront_shutdown_script), - SQLITE_TRANSIENT); + db_bind_blob( + stmt, 27, chan->remote_upfront_shutdown_script, + tal_count(chan->remote_upfront_shutdown_script)); else - sqlite3_bind_null(stmt, 28); - sqlite3_bind_int64(stmt, 29, chan->dbid); - db_exec_prepared(w->db, stmt); + db_bind_null(stmt, 27); + db_bind_u64(stmt, 28, chan->dbid); + db_exec_prepared_v2(take(stmt)); wallet_channel_config_save(w, &chan->channel_info.their_config); - stmt = db_prepare(w->db, "UPDATE channels SET" - " fundingkey_remote=?," - " revocation_basepoint_remote=?," - " payment_basepoint_remote=?," - " htlc_basepoint_remote=?," - " delayed_payment_basepoint_remote=?," - " per_commit_remote=?," - " old_per_commit_remote=?," - " local_feerate_per_kw=?," - " remote_feerate_per_kw=?," - " channel_config_remote=?," - " future_per_commitment_point=?" - " WHERE id=?"); - sqlite3_bind_pubkey(stmt, 1, &chan->channel_info.remote_fundingkey); - sqlite3_bind_pubkey(stmt, 2, &chan->channel_info.theirbase.revocation); - sqlite3_bind_pubkey(stmt, 3, &chan->channel_info.theirbase.payment); - sqlite3_bind_pubkey(stmt, 4, &chan->channel_info.theirbase.htlc); - sqlite3_bind_pubkey(stmt, 5, &chan->channel_info.theirbase.delayed_payment); - sqlite3_bind_pubkey(stmt, 6, &chan->channel_info.remote_per_commit); - sqlite3_bind_pubkey(stmt, 7, &chan->channel_info.old_remote_per_commit); - sqlite3_bind_int(stmt, 8, chan->channel_info.feerate_per_kw[LOCAL]); - sqlite3_bind_int(stmt, 9, chan->channel_info.feerate_per_kw[REMOTE]); - sqlite3_bind_int64(stmt, 10, chan->channel_info.their_config.id); + stmt = db_prepare_v2(w->db, SQL("UPDATE channels SET" + " fundingkey_remote=?," + " revocation_basepoint_remote=?," + " payment_basepoint_remote=?," + " htlc_basepoint_remote=?," + " delayed_payment_basepoint_remote=?," + " per_commit_remote=?," + " old_per_commit_remote=?," + " local_feerate_per_kw=?," + " remote_feerate_per_kw=?," + " channel_config_remote=?," + " future_per_commitment_point=?" + " WHERE id=?")); + db_bind_pubkey(stmt, 0, &chan->channel_info.remote_fundingkey); + db_bind_pubkey(stmt, 1, &chan->channel_info.theirbase.revocation); + db_bind_pubkey(stmt, 2, &chan->channel_info.theirbase.payment); + db_bind_pubkey(stmt, 3, &chan->channel_info.theirbase.htlc); + db_bind_pubkey(stmt, 4, &chan->channel_info.theirbase.delayed_payment); + db_bind_pubkey(stmt, 5, &chan->channel_info.remote_per_commit); + db_bind_pubkey(stmt, 6, &chan->channel_info.old_remote_per_commit); + db_bind_int(stmt, 7, chan->channel_info.feerate_per_kw[LOCAL]); + db_bind_int(stmt, 8, chan->channel_info.feerate_per_kw[REMOTE]); + db_bind_u64(stmt, 9, chan->channel_info.their_config.id); if (chan->future_per_commitment_point) - sqlite3_bind_pubkey(stmt, 11, chan->future_per_commitment_point); + db_bind_pubkey(stmt, 10, chan->future_per_commitment_point); else - sqlite3_bind_null(stmt, 11); - sqlite3_bind_int64(stmt, 12, chan->dbid); - db_exec_prepared(w->db, stmt); + db_bind_null(stmt, 10); + db_bind_u64(stmt, 11, chan->dbid); + db_exec_prepared_v2(take(stmt)); /* If we have a last_sent_commit, store it */ last_sent_commit = tal_arr(tmpctx, u8, 0); @@ -1267,42 +1328,43 @@ void wallet_channel_save(struct wallet *w, struct channel *chan) towire_changed_htlc(&last_sent_commit, &chan->last_sent_commit[i]); - stmt = db_prepare(w->db, - "UPDATE channels SET" - " last_sent_commit=?" - " WHERE id=?"); + stmt = db_prepare_v2(w->db, SQL("UPDATE channels SET" + " last_sent_commit=?" + " WHERE id=?")); if (tal_count(last_sent_commit)) - sqlite3_bind_blob(stmt, 1, - last_sent_commit, tal_count(last_sent_commit), - SQLITE_TRANSIENT); + db_bind_blob(stmt, 0, last_sent_commit, + tal_count(last_sent_commit)); else - sqlite3_bind_null(stmt, 1); - sqlite3_bind_int64(stmt, 2, chan->dbid); - db_exec_prepared(w->db, stmt); + db_bind_null(stmt, 0); + db_bind_u64(stmt, 1, chan->dbid); + db_exec_prepared_v2(take(stmt)); } void wallet_channel_insert(struct wallet *w, struct channel *chan) { - sqlite3_stmt *stmt; + struct db_stmt *stmt; if (chan->peer->dbid == 0) { /* Need to create the peer first */ - stmt = db_prepare(w->db, "INSERT INTO peers (node_id, address) VALUES (?, ?);"); - sqlite3_bind_node_id(stmt, 1, &chan->peer->id); - sqlite3_bind_text(stmt, 2, - type_to_string(tmpctx, struct wireaddr_internal, &chan->peer->addr), - -1, SQLITE_TRANSIENT); - db_exec_prepared(w->db, stmt); + stmt = db_prepare_v2(w->db, + SQL("INSERT INTO peers (node_id, address) VALUES (?, ?);") + ); + db_bind_node_id(stmt, 0, &chan->peer->id); + db_bind_text(stmt, 1, + type_to_string(tmpctx, struct wireaddr_internal, + &chan->peer->addr)); + db_exec_prepared_v2(take(stmt)); chan->peer->dbid = db_last_insert_id(w->db); } /* Insert a stub, that we update, unifies INSERT and UPDATE paths */ - stmt = db_prepare(w->db, "INSERT INTO channels (" - "peer_id, first_blocknum, id) VALUES (?, ?, ?);"); - sqlite3_bind_int64(stmt, 1, chan->peer->dbid); - sqlite3_bind_int(stmt, 2, chan->first_blocknum); - sqlite3_bind_int(stmt, 3, chan->dbid); - db_exec_prepared(w->db, stmt); + stmt = db_prepare_v2( + w->db, SQL("INSERT INTO channels (" + "peer_id, first_blocknum, id) VALUES (?, ?, ?);")); + db_bind_u64(stmt, 0, chan->peer->dbid); + db_bind_int(stmt, 1, chan->first_blocknum); + db_bind_int(stmt, 2, chan->dbid); + db_exec_prepared_v2(take(stmt)); wallet_channel_config_insert(w, &chan->our_config); wallet_channel_config_insert(w, &chan->channel_info.their_config); @@ -1320,81 +1382,77 @@ void wallet_channel_close(struct wallet *w, u64 wallet_id) * considerably and that are of limited use after channel closure will * be pruned as well. */ - sqlite3_stmt *stmt; + struct db_stmt *stmt; /* Delete entries from `channel_htlcs` */ - stmt = db_prepare(w->db, - "DELETE FROM channel_htlcs " - "WHERE channel_id=?"); - sqlite3_bind_int64(stmt, 1, wallet_id); - db_exec_prepared(w->db, stmt); + stmt = db_prepare_v2(w->db, SQL("DELETE FROM channel_htlcs " + "WHERE channel_id=?")); + db_bind_u64(stmt, 0, wallet_id); + db_exec_prepared_v2(take(stmt)); /* Delete entries from `htlc_sigs` */ - stmt = db_prepare(w->db, - "DELETE FROM htlc_sigs " - "WHERE channelid=?"); - sqlite3_bind_int64(stmt, 1, wallet_id); - db_exec_prepared(w->db, stmt); + stmt = db_prepare_v2(w->db, SQL("DELETE FROM htlc_sigs " + "WHERE channelid=?")); + db_bind_u64(stmt, 0, wallet_id); + db_exec_prepared_v2(take(stmt)); /* Delete entries from `htlc_sigs` */ - stmt = db_prepare(w->db, - "DELETE FROM channeltxs " - "WHERE channel_id=?"); - sqlite3_bind_int64(stmt, 1, wallet_id); - db_exec_prepared(w->db, stmt); + stmt = db_prepare_v2(w->db, SQL("DELETE FROM channeltxs " + "WHERE channel_id=?")); + db_bind_u64(stmt, 0, wallet_id); + db_exec_prepared_v2(take(stmt)); /* Delete shachains */ - stmt = db_prepare(w->db, - "DELETE FROM shachains " - "WHERE id IN (" - " SELECT shachain_remote_id " - " FROM channels " - " WHERE channels.id=?" - ")"); - sqlite3_bind_int64(stmt, 1, wallet_id); - db_exec_prepared(w->db, stmt); + stmt = db_prepare_v2(w->db, SQL("DELETE FROM shachains " + "WHERE id IN (" + " SELECT shachain_remote_id " + " FROM channels " + " WHERE channels.id=?" + ")")); + db_bind_u64(stmt, 0, wallet_id); + db_exec_prepared_v2(take(stmt)); /* Set the channel to closed and disassociate with peer */ - stmt = db_prepare(w->db, - "UPDATE channels " - "SET state=?, peer_id=?" - "WHERE channels.id=?"); - sqlite3_bind_int64(stmt, 1, CLOSED); - sqlite3_bind_null(stmt, 2); - sqlite3_bind_int64(stmt, 3, wallet_id); - db_exec_prepared(w->db, stmt); + stmt = db_prepare_v2(w->db, SQL("UPDATE channels " + "SET state=?, peer_id=?" + "WHERE channels.id=?")); + db_bind_u64(stmt, 0, CLOSED); + db_bind_null(stmt, 1); + db_bind_u64(stmt, 2, wallet_id); + db_exec_prepared_v2(take(stmt)); } void wallet_peer_delete(struct wallet *w, u64 peer_dbid) { - sqlite3_stmt *stmt; + struct db_stmt *stmt; /* Must not have any channels still using this peer */ - stmt = db_select_prepare(w->db, "SELECT * FROM channels WHERE peer_id = ?;"); - sqlite3_bind_int64(stmt, 1, peer_dbid); + stmt = db_prepare_v2(w->db, SQL("SELECT * FROM channels WHERE peer_id = ?;")); + db_bind_u64(stmt, 0, peer_dbid); + db_query_prepared(stmt); - if (db_select_step(w->db, stmt)) + if (db_step(stmt)) fatal("We have channels using peer %"PRIu64, peer_dbid); + tal_free(stmt); - stmt = db_prepare(w->db, "DELETE FROM peers WHERE id=?"); - sqlite3_bind_int64(stmt, 1, peer_dbid); - db_exec_prepared(w->db, stmt); + stmt = db_prepare_v2(w->db, SQL("DELETE FROM peers WHERE id=?")); + db_bind_u64(stmt, 0, peer_dbid); + db_exec_prepared_v2(take(stmt)); } void wallet_confirm_tx(struct wallet *w, const struct bitcoin_txid *txid, const u32 confirmation_height) { - sqlite3_stmt *stmt; + struct db_stmt *stmt; assert(confirmation_height > 0); - stmt = db_prepare(w->db, - "UPDATE outputs " - "SET confirmation_height = ? " - "WHERE prev_out_tx = ?"); - sqlite3_bind_int(stmt, 1, confirmation_height); - sqlite3_bind_sha256_double(stmt, 2, &txid->shad); + stmt = db_prepare_v2(w->db, SQL("UPDATE outputs " + "SET confirmation_height = ? " + "WHERE prev_out_tx = ?")); + db_bind_int(stmt, 0, confirmation_height); + db_bind_sha256d(stmt, 1, &txid->shad); - db_exec_prepared(w->db, stmt); + db_exec_prepared_v2(take(stmt)); } int wallet_extract_owned_outputs(struct wallet *w, const struct bitcoin_tx *tx, @@ -1469,49 +1527,47 @@ int wallet_extract_owned_outputs(struct wallet *w, const struct bitcoin_tx *tx, void wallet_htlc_save_in(struct wallet *wallet, const struct channel *chan, struct htlc_in *in) { - sqlite3_stmt *stmt; + struct db_stmt *stmt; - stmt = db_prepare( - wallet->db, - "INSERT INTO channel_htlcs (" - " channel_id," - " channel_htlc_id, " - " direction," - " msatoshi," - " cltv_expiry," - " payment_hash, " - " payment_key," - " hstate," - " shared_secret," - " routing_onion," - " received_time) VALUES " - "(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);"); - - sqlite3_bind_int64(stmt, 1, chan->dbid); - sqlite3_bind_int64(stmt, 2, in->key.id); - sqlite3_bind_int(stmt, 3, DIRECTION_INCOMING); - sqlite3_bind_amount_msat(stmt, 4, in->msat); - sqlite3_bind_int(stmt, 5, in->cltv_expiry); - sqlite3_bind_sha256(stmt, 6, &in->payment_hash); + stmt = db_prepare_v2(wallet->db, + SQL("INSERT INTO channel_htlcs (" + " channel_id," + " channel_htlc_id, " + " direction," + " msatoshi," + " cltv_expiry," + " payment_hash, " + " payment_key," + " hstate," + " shared_secret," + " routing_onion," + " received_time) VALUES " + "(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);")); + + db_bind_u64(stmt, 0, chan->dbid); + db_bind_u64(stmt, 1, in->key.id); + db_bind_int(stmt, 2, DIRECTION_INCOMING); + db_bind_amount_msat(stmt, 3, &in->msat); + db_bind_int(stmt, 4, in->cltv_expiry); + db_bind_sha256(stmt, 5, &in->payment_hash); if (in->preimage) - sqlite3_bind_preimage(stmt, 7, in->preimage); + db_bind_preimage(stmt, 6, in->preimage); else - sqlite3_bind_null(stmt, 7); - sqlite3_bind_int(stmt, 8, in->hstate); + db_bind_null(stmt, 6); + db_bind_int(stmt, 7, in->hstate); if (!in->shared_secret) - sqlite3_bind_null(stmt, 9); + db_bind_null(stmt, 8); else - sqlite3_bind_blob(stmt, 9, in->shared_secret, - sizeof(*in->shared_secret), SQLITE_TRANSIENT); + db_bind_secret(stmt, 8, in->shared_secret); - sqlite3_bind_blob(stmt, 10, &in->onion_routing_packet, - sizeof(in->onion_routing_packet), SQLITE_TRANSIENT); + db_bind_blob(stmt, 9, in->onion_routing_packet, + sizeof(in->onion_routing_packet)); - sqlite3_bind_timeabs(stmt, 11, in->received_time); + db_bind_timeabs(stmt, 10, in->received_time); - db_exec_prepared(wallet->db, stmt); + db_exec_prepared_v2(take(stmt)); in->dbid = db_last_insert_id(wallet->db); } @@ -1519,50 +1575,50 @@ void wallet_htlc_save_out(struct wallet *wallet, const struct channel *chan, struct htlc_out *out) { - sqlite3_stmt *stmt; + struct db_stmt *stmt; /* We absolutely need the incoming HTLC to be persisted before * we can persist it's dependent */ assert(out->in == NULL || out->in->dbid != 0); out->origin_htlc_id = out->in?out->in->dbid:0; - stmt = db_prepare( + stmt = db_prepare_v2( wallet->db, - "INSERT INTO channel_htlcs (" - " channel_id," - " channel_htlc_id," - " direction," - " origin_htlc," - " msatoshi," - " cltv_expiry," - " payment_hash," - " payment_key," - " hstate," - " routing_onion) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?);"); - - sqlite3_bind_int64(stmt, 1, chan->dbid); - sqlite3_bind_int64(stmt, 2, out->key.id); - sqlite3_bind_int(stmt, 3, DIRECTION_OUTGOING); + SQL("INSERT INTO channel_htlcs (" + " channel_id," + " channel_htlc_id," + " direction," + " origin_htlc," + " msatoshi," + " cltv_expiry," + " payment_hash," + " payment_key," + " hstate," + " routing_onion) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?);")); + + db_bind_u64(stmt, 0, chan->dbid); + db_bind_u64(stmt, 1, out->key.id); + db_bind_int(stmt, 2, DIRECTION_OUTGOING); if (out->in) - sqlite3_bind_int64(stmt, 4, out->in->dbid); + db_bind_u64(stmt, 3, out->in->dbid); else - sqlite3_bind_null(stmt, 4); - sqlite3_bind_amount_msat(stmt, 5, out->msat); - sqlite3_bind_int(stmt, 6, out->cltv_expiry); - sqlite3_bind_sha256(stmt, 7, &out->payment_hash); + db_bind_null(stmt, 3); + db_bind_amount_msat(stmt, 4, &out->msat); + db_bind_int(stmt, 5, out->cltv_expiry); + db_bind_sha256(stmt, 6, &out->payment_hash); if (out->preimage) - sqlite3_bind_preimage(stmt, 8,out->preimage); + db_bind_preimage(stmt, 7, out->preimage); else - sqlite3_bind_null(stmt, 8); - sqlite3_bind_int(stmt, 9, out->hstate); - - sqlite3_bind_blob(stmt, 10, &out->onion_routing_packet, - sizeof(out->onion_routing_packet), SQLITE_TRANSIENT); + db_bind_null(stmt, 7); + db_bind_int(stmt, 8, out->hstate); - db_exec_prepared(wallet->db, stmt); + db_bind_blob(stmt, 9, out->onion_routing_packet, + sizeof(out->onion_routing_packet)); - out->dbid = db_last_insert_id(wallet->db); + db_exec_prepared_v2(stmt); + out->dbid = db_last_insert_id_v2(stmt); + tal_free(stmt); } void wallet_htlc_update(struct wallet *wallet, const u64 htlc_dbid, @@ -1570,68 +1626,66 @@ void wallet_htlc_update(struct wallet *wallet, const u64 htlc_dbid, const struct preimage *payment_key, enum onion_type failcode, const u8 *failuremsg) { - sqlite3_stmt *stmt; + struct db_stmt *stmt; /* The database ID must be set by a previous call to * `wallet_htlc_save_*` */ assert(htlc_dbid); - stmt = db_prepare( - wallet->db, - "UPDATE channel_htlcs SET hstate=?, payment_key=?, malformed_onion=?, failuremsg=? WHERE id=?"); + stmt = db_prepare_v2( + wallet->db, SQL("UPDATE channel_htlcs SET hstate=?, payment_key=?, " + "malformed_onion=?, failuremsg=? WHERE id=?")); /* FIXME: htlc_state_in_db */ - sqlite3_bind_int(stmt, 1, new_state); - sqlite3_bind_int64(stmt, 5, htlc_dbid); + db_bind_int(stmt, 0, new_state); + db_bind_u64(stmt, 4, htlc_dbid); if (payment_key) - sqlite3_bind_preimage(stmt, 2, payment_key); + db_bind_preimage(stmt, 1, payment_key); else - sqlite3_bind_null(stmt, 2); + db_bind_null(stmt, 1); - sqlite3_bind_int(stmt, 3, failcode); + db_bind_int(stmt, 2, failcode); if (failuremsg) - sqlite3_bind_blob(stmt, 4, - failuremsg, tal_bytelen(failuremsg), - SQLITE_TRANSIENT); + db_bind_blob(stmt, 3, failuremsg, tal_bytelen(failuremsg)); else - sqlite3_bind_null(stmt, 4); + db_bind_null(stmt, 3); - db_exec_prepared(wallet->db, stmt); + db_exec_prepared_v2(take(stmt)); } static bool wallet_stmt2htlc_in(struct channel *channel, - sqlite3_stmt *stmt, struct htlc_in *in) + struct db_stmt *stmt, struct htlc_in *in) { bool ok = true; - in->dbid = sqlite3_column_int64(stmt, 0); - in->key.id = sqlite3_column_int64(stmt, 1); + in->dbid = db_column_u64(stmt, 0); + in->key.id = db_column_u64(stmt, 1); in->key.channel = channel; - in->msat = sqlite3_column_amount_msat(stmt, 2); - in->cltv_expiry = sqlite3_column_int(stmt, 3); - in->hstate = sqlite3_column_int(stmt, 4); + db_column_amount_msat(stmt, 2, &in->msat); + in->cltv_expiry = db_column_int(stmt, 3); + in->hstate = db_column_int(stmt, 4); - sqlite3_column_sha256(stmt, 5, &in->payment_hash); + db_column_sha256(stmt, 5, &in->payment_hash); - if (sqlite3_column_type(stmt, 6) != SQLITE_NULL) { + if (!db_column_is_null(stmt, 6)) { in->preimage = tal(in, struct preimage); - sqlite3_column_preimage(stmt, 6, in->preimage); + db_column_preimage(stmt, 6, in->preimage); } else { in->preimage = NULL; } - assert(sqlite3_column_bytes(stmt, 7) == sizeof(in->onion_routing_packet)); - memcpy(&in->onion_routing_packet, sqlite3_column_blob(stmt, 7), + assert(db_column_bytes(stmt, 7) == sizeof(in->onion_routing_packet)); + memcpy(&in->onion_routing_packet, db_column_blob(stmt, 7), sizeof(in->onion_routing_packet)); - in->failuremsg = sqlite3_column_arr(in, stmt, 8, u8); - in->failcode = sqlite3_column_int(stmt, 9); + in->failuremsg = db_column_arr(in, stmt, 8, u8); + in->failcode = db_column_int(stmt, 9); - if (sqlite3_column_type(stmt, 11) == SQLITE_NULL) { + if (db_column_is_null(stmt, 11)) { in->shared_secret = NULL; } else { - assert(sqlite3_column_bytes(stmt, 11) == sizeof(struct secret)); + assert(db_column_bytes(stmt, 11) == sizeof(struct secret)); in->shared_secret = tal(in, struct secret); - memcpy(in->shared_secret, sqlite3_column_blob(stmt, 11), + memcpy(in->shared_secret, db_column_blob(stmt, 11), sizeof(struct secret)); #ifdef COMPAT_V062 if (memeqzero(in->shared_secret, sizeof(*in->shared_secret))) @@ -1639,39 +1693,39 @@ static bool wallet_stmt2htlc_in(struct channel *channel, #endif } - in->received_time = sqlite3_column_timeabs(stmt, 12); + in->received_time = db_column_timeabs(stmt, 12); return ok; } static bool wallet_stmt2htlc_out(struct channel *channel, - sqlite3_stmt *stmt, struct htlc_out *out) + struct db_stmt *stmt, struct htlc_out *out) { bool ok = true; - out->dbid = sqlite3_column_int64(stmt, 0); - out->key.id = sqlite3_column_int64(stmt, 1); + out->dbid = db_column_u64(stmt, 0); + out->key.id = db_column_u64(stmt, 1); out->key.channel = channel; - out->msat = sqlite3_column_amount_msat(stmt, 2); - out->cltv_expiry = sqlite3_column_int(stmt, 3); - out->hstate = sqlite3_column_int(stmt, 4); - sqlite3_column_sha256(stmt, 5, &out->payment_hash); + db_column_amount_msat(stmt, 2, &out->msat); + out->cltv_expiry = db_column_int(stmt, 3); + out->hstate = db_column_int(stmt, 4); + db_column_sha256(stmt, 5, &out->payment_hash); - if (sqlite3_column_type(stmt, 6) != SQLITE_NULL) { + if (!db_column_is_null(stmt, 6)) { out->preimage = tal(out, struct preimage); - sqlite3_column_preimage(stmt, 6, out->preimage); + db_column_preimage(stmt, 6, out->preimage); } else { out->preimage = NULL; } - assert(sqlite3_column_bytes(stmt, 7) == sizeof(out->onion_routing_packet)); - memcpy(&out->onion_routing_packet, sqlite3_column_blob(stmt, 7), + assert(db_column_bytes(stmt, 7) == sizeof(out->onion_routing_packet)); + memcpy(&out->onion_routing_packet, db_column_blob(stmt, 7), sizeof(out->onion_routing_packet)); - out->failuremsg = sqlite3_column_arr(out, stmt, 8, u8); - out->failcode = sqlite3_column_int(stmt, 9); + out->failuremsg = db_column_arr(out, stmt, 8, u8); + out->failcode = db_column_int(stmt, 9); - if (sqlite3_column_type(stmt, 10) != SQLITE_NULL) { - out->origin_htlc_id = sqlite3_column_int64(stmt, 10); + if (!db_column_is_null(stmt, 10)) { + out->origin_htlc_id = db_column_u64(stmt, 10); out->am_origin = false; } else { out->origin_htlc_id = 0; @@ -1727,33 +1781,35 @@ bool wallet_htlcs_load_for_channel(struct wallet *wallet, struct htlc_in_map *htlcs_in, struct htlc_out_map *htlcs_out) { + struct db_stmt *stmt; bool ok = true; int incount = 0, outcount = 0; log_debug(wallet->log, "Loading HTLCs for channel %"PRIu64, chan->dbid); - sqlite3_stmt *stmt = db_select_prepare(wallet->db, "SELECT" - " id" - ", channel_htlc_id" - ", msatoshi" - ", cltv_expiry" - ", hstate" - ", payment_hash" - ", payment_key" - ", routing_onion" - ", failuremsg" - ", malformed_onion" - ", origin_htlc" - ", shared_secret" - ", received_time" - " FROM channel_htlcs" - " WHERE direction= ?" - " AND channel_id= ?" - " AND hstate != ?"); - sqlite3_bind_int(stmt, 1, DIRECTION_INCOMING); - sqlite3_bind_int64(stmt, 2, chan->dbid); - sqlite3_bind_int(stmt, 3, SENT_REMOVE_ACK_REVOCATION); - - while (db_select_step(wallet->db, stmt)) { + stmt = db_prepare_v2(wallet->db, SQL("SELECT" + " id" + ", channel_htlc_id" + ", msatoshi" + ", cltv_expiry" + ", hstate" + ", payment_hash" + ", payment_key" + ", routing_onion" + ", failuremsg" + ", malformed_onion" + ", origin_htlc" + ", shared_secret" + ", received_time" + " FROM channel_htlcs" + " WHERE direction= ?" + " AND channel_id= ?" + " AND hstate != ?")); + db_bind_int(stmt, 0, DIRECTION_INCOMING); + db_bind_u64(stmt, 1, chan->dbid); + db_bind_int(stmt, 2, SENT_REMOVE_ACK_REVOCATION); + db_query_prepared(stmt); + + while (db_step(stmt)) { struct htlc_in *in = tal(chan, struct htlc_in); ok &= wallet_stmt2htlc_in(chan, stmt, in); connect_htlc_in(htlcs_in, in); @@ -1761,8 +1817,9 @@ bool wallet_htlcs_load_for_channel(struct wallet *wallet, ok &= htlc_in_check(in, NULL) != NULL; incount++; } + tal_free(stmt); - stmt = db_select_prepare(wallet->db, "SELECT" + stmt = db_prepare_v2(wallet->db, SQL("SELECT" " id" ", channel_htlc_id" ", msatoshi" @@ -1779,12 +1836,13 @@ bool wallet_htlcs_load_for_channel(struct wallet *wallet, " FROM channel_htlcs" " WHERE direction = ?" " AND channel_id = ?" - " AND hstate != ?"); - sqlite3_bind_int(stmt, 1, DIRECTION_OUTGOING); - sqlite3_bind_int64(stmt, 2, chan->dbid); - sqlite3_bind_int(stmt, 3, RCVD_REMOVE_ACK_REVOCATION); + " AND hstate != ?")); + db_bind_int(stmt, 0, DIRECTION_OUTGOING); + db_bind_u64(stmt, 1, chan->dbid); + db_bind_int(stmt, 2, RCVD_REMOVE_ACK_REVOCATION); + db_query_prepared(stmt); - while (db_select_step(wallet->db, stmt)) { + while (db_step(stmt)) { struct htlc_out *out = tal(chan, struct htlc_out); ok &= wallet_stmt2htlc_out(chan, stmt, out); connect_htlc_out(htlcs_out, out); @@ -1792,6 +1850,7 @@ bool wallet_htlcs_load_for_channel(struct wallet *wallet, * dependencies in yet */ outcount++; } + tal_free(stmt); log_debug(wallet->log, "Restored %d incoming and %d outgoing HTLCS", incount, outcount); @@ -1883,28 +1942,33 @@ struct htlc_stub *wallet_htlc_stubs(const tal_t *ctx, struct wallet *wallet, { struct htlc_stub *stubs; struct sha256 payment_hash; - sqlite3_stmt *stmt = db_select_prepare(wallet->db, - "SELECT channel_id, direction, cltv_expiry, channel_htlc_id, payment_hash " - "FROM channel_htlcs WHERE channel_id = ?;"); + struct db_stmt *stmt; - sqlite3_bind_int64(stmt, 1, chan->dbid); + stmt = db_prepare_v2(wallet->db, + SQL("SELECT channel_id, direction, cltv_expiry, " + "channel_htlc_id, payment_hash " + "FROM channel_htlcs WHERE channel_id = ?;")); + + db_bind_u64(stmt, 0, chan->dbid); + db_query_prepared(stmt); stubs = tal_arr(ctx, struct htlc_stub, 0); - while (db_select_step(wallet->db, stmt)) { + while (db_step(stmt)) { struct htlc_stub stub; - assert(sqlite3_column_int64(stmt, 0) == chan->dbid); + assert(db_column_u64(stmt, 0) == chan->dbid); /* FIXME: merge these two enums */ - stub.owner = sqlite3_column_int(stmt, 1)==DIRECTION_INCOMING?REMOTE:LOCAL; - stub.cltv_expiry = sqlite3_column_int(stmt, 2); - stub.id = sqlite3_column_int(stmt, 3); + stub.owner = db_column_int(stmt, 1)==DIRECTION_INCOMING?REMOTE:LOCAL; + stub.cltv_expiry = db_column_int(stmt, 2); + stub.id = db_column_int(stmt, 3); - sqlite3_column_sha256(stmt, 4, &payment_hash); + db_column_sha256(stmt, 4, &payment_hash); ripemd160(&stub.ripemd, payment_hash.u.u8, sizeof(payment_hash.u)); tal_arr_expand(&stubs, stub); } + tal_free(stmt); return stubs; } @@ -1912,18 +1976,17 @@ void wallet_local_htlc_out_delete(struct wallet *wallet, struct channel *chan, const struct sha256 *payment_hash) { - sqlite3_stmt *stmt; + struct db_stmt *stmt; - stmt = db_prepare(wallet->db, - "DELETE FROM channel_htlcs" - " WHERE direction = ?" - " AND origin_htlc = ?" - " AND payment_hash = ?"); - sqlite3_bind_int(stmt, 1, DIRECTION_OUTGOING); - sqlite3_bind_int(stmt, 2, 0); - sqlite3_bind_sha256(stmt, 3, payment_hash); + stmt = db_prepare_v2(wallet->db, SQL("DELETE FROM channel_htlcs" + " WHERE direction = ?" + " AND origin_htlc = ?" + " AND payment_hash = ?")); + db_bind_int(stmt, 0, DIRECTION_OUTGOING); + db_bind_int(stmt, 1, 0); + db_bind_sha256(stmt, 2, payment_hash); - db_exec_prepared(wallet->db, stmt); + db_exec_prepared_v2(take(stmt)); } static struct wallet_payment * @@ -1954,7 +2017,7 @@ void wallet_payment_setup(struct wallet *wallet, struct wallet_payment *payment) void wallet_payment_store(struct wallet *wallet, const struct sha256 *payment_hash) { - sqlite3_stmt *stmt; + struct db_stmt *stmt; struct wallet_payment *payment; payment = find_unstored_payment(wallet, payment_hash); @@ -1965,13 +2028,14 @@ void wallet_payment_store(struct wallet *wallet, * (catch bug, where we call this on a payment_hash * we never paid to) */ bool res; - stmt = db_select_prepare(wallet->db, - "SELECT status FROM payments" - " WHERE payment_hash=?;"); - sqlite3_bind_sha256(stmt, 1, payment_hash); - res = db_select_step(wallet->db, stmt); + stmt = + db_prepare_v2(wallet->db, SQL("SELECT status FROM payments" + " WHERE payment_hash=?;")); + db_bind_sha256(stmt, 0, payment_hash); + db_query_prepared(stmt); + res = db_step(stmt); assert(res); - db_stmt_done(stmt); + tal_free(stmt); #endif return; } @@ -1979,9 +2043,9 @@ void wallet_payment_store(struct wallet *wallet, /* Don't attempt to add the same payment twice */ assert(!payment->id); - stmt = db_prepare( + stmt = db_prepare_v2( wallet->db, - "INSERT INTO payments (" + SQL("INSERT INTO payments (" " status," " payment_hash," " destination," @@ -1993,44 +2057,47 @@ void wallet_payment_store(struct wallet *wallet, " msatoshi_sent," " description," " bolt11" - ") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);"); - - sqlite3_bind_int(stmt, 1, payment->status); - sqlite3_bind_sha256(stmt, 2, &payment->payment_hash); - sqlite3_bind_node_id(stmt, 3, &payment->destination); - sqlite3_bind_amount_msat(stmt, 4, payment->msatoshi); - sqlite3_bind_int(stmt, 5, payment->timestamp); - sqlite3_bind_blob(stmt, 6, payment->path_secrets, - tal_bytelen(payment->path_secrets), - SQLITE_TRANSIENT); - sqlite3_bind_node_id_array(stmt, 7, payment->route_nodes); - sqlite3_bind_short_channel_id_array(stmt, 8, - payment->route_channels); - sqlite3_bind_amount_msat(stmt, 9, payment->msatoshi_sent); + ") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);")); + + db_bind_int(stmt, 0, payment->status); + db_bind_sha256(stmt, 1, &payment->payment_hash); + db_bind_node_id(stmt, 2, &payment->destination); + db_bind_amount_msat(stmt, 3, &payment->msatoshi); + db_bind_int(stmt, 4, payment->timestamp); + + if (payment->route_nodes) { + assert(payment->path_secrets); + assert(payment->route_nodes); + assert(payment->route_channels); + db_bind_secret_arr(stmt, 5, payment->path_secrets); + db_bind_node_id_arr(stmt, 6, payment->route_nodes); + db_bind_short_channel_id_arr(stmt, 7, payment->route_channels); + } else { + db_bind_null(stmt, 5); + db_bind_null(stmt, 6); + db_bind_null(stmt, 7); + } + + db_bind_amount_msat(stmt, 8, &payment->msatoshi_sent); if (payment->label != NULL) - sqlite3_bind_text(stmt, 10, payment->label, - strlen(payment->label), - SQLITE_TRANSIENT); + db_bind_text(stmt, 9, payment->label); else - sqlite3_bind_null(stmt, 10); + db_bind_null(stmt, 9); if (payment->bolt11 != NULL) - sqlite3_bind_text(stmt, 11, payment->bolt11, - strlen(payment->bolt11), - SQLITE_TRANSIENT); + db_bind_text(stmt, 10, payment->bolt11); else - sqlite3_bind_null(stmt, 11); - - db_exec_prepared(wallet->db, stmt); + db_bind_null(stmt, 10); + db_exec_prepared_v2(take(stmt)); tal_free(payment); } void wallet_payment_delete(struct wallet *wallet, const struct sha256 *payment_hash) { - sqlite3_stmt *stmt; + struct db_stmt *stmt; struct wallet_payment *payment; payment = find_unstored_payment(wallet, payment_hash); @@ -2039,51 +2106,54 @@ void wallet_payment_delete(struct wallet *wallet, return; } - stmt = db_prepare( - wallet->db, - "DELETE FROM payments WHERE payment_hash = ?"); + stmt = db_prepare_v2( + wallet->db, SQL("DELETE FROM payments WHERE payment_hash = ?")); - sqlite3_bind_sha256(stmt, 1, payment_hash); + db_bind_sha256(stmt, 0, payment_hash); - db_exec_prepared(wallet->db, stmt); + db_exec_prepared_v2(take(stmt)); } static struct wallet_payment *wallet_stmt2payment(const tal_t *ctx, - sqlite3_stmt *stmt) + struct db_stmt *stmt) { struct wallet_payment *payment = tal(ctx, struct wallet_payment); - payment->id = sqlite3_column_int64(stmt, 0); - payment->status = sqlite3_column_int(stmt, 1); + payment->id = db_column_u64(stmt, 0); + payment->status = db_column_int(stmt, 1); - sqlite3_column_node_id(stmt, 2, &payment->destination); - payment->msatoshi = sqlite3_column_amount_msat(stmt, 3); - sqlite3_column_sha256(stmt, 4, &payment->payment_hash); + db_column_node_id(stmt, 2, &payment->destination); + db_column_amount_msat(stmt, 3, &payment->msatoshi); + db_column_sha256(stmt, 4, &payment->payment_hash); - payment->timestamp = sqlite3_column_int(stmt, 5); - if (sqlite3_column_type(stmt, 6) != SQLITE_NULL) { + payment->timestamp = db_column_int(stmt, 5); + if (!db_column_is_null(stmt, 6)) { payment->payment_preimage = tal(payment, struct preimage); - sqlite3_column_preimage(stmt, 6, payment->payment_preimage); + db_column_preimage(stmt, 6, payment->payment_preimage); } else payment->payment_preimage = NULL; /* Can be NULL for old db! */ - payment->path_secrets = sqlite3_column_secrets(payment, stmt, 7); + if (!db_column_is_null(stmt, 7)) { + assert(!db_column_is_null(stmt, 8)); + assert(!db_column_is_null(stmt, 9)); + payment->path_secrets = db_column_secret_arr(payment, stmt, 7); - payment->route_nodes = sqlite3_column_node_id_array(payment, stmt, 8); - payment->route_channels - = sqlite3_column_short_channel_id_array(payment, stmt, 9); + payment->route_nodes = db_column_node_id_arr(payment, stmt, 8); + payment->route_channels = + db_column_short_channel_id_arr(payment, stmt, 9); + } - payment->msatoshi_sent = sqlite3_column_amount_msat(stmt, 10); + db_column_amount_msat(stmt, 10, &payment->msatoshi_sent); - if (sqlite3_column_type(stmt, 11) != SQLITE_NULL) - payment->label = tal_strdup( - payment, (const char *)sqlite3_column_text(stmt, 11)); + if (!db_column_is_null(stmt, 11)) + payment->label = + tal_strdup(payment, (const char *)db_column_text(stmt, 11)); else payment->label = NULL; - if (sqlite3_column_type(stmt, 12) != SQLITE_NULL) - payment->bolt11 = tal_strdup(payment, - (const char *)sqlite3_column_text(stmt, 12)); + if (!db_column_is_null(stmt, 12)) + payment->bolt11 = tal_strdup( + payment, (const char *)db_column_text(stmt, 12)); else payment->bolt11 = NULL; @@ -2094,7 +2164,7 @@ struct wallet_payment * wallet_payment_by_hash(const tal_t *ctx, struct wallet *wallet, const struct sha256 *payment_hash) { - sqlite3_stmt *stmt; + struct db_stmt *stmt; struct wallet_payment *payment; /* Present the illusion that it's in the db... */ @@ -2102,29 +2172,29 @@ wallet_payment_by_hash(const tal_t *ctx, struct wallet *wallet, if (payment) return payment; - stmt = db_select_prepare(wallet->db, - "SELECT" - " id" - ", status" - ", destination" - ", msatoshi" - ", payment_hash" - ", timestamp" - ", payment_preimage" - ", path_secrets" - ", route_nodes" - ", route_channels" - ", msatoshi_sent" - ", description" - ", bolt11" - " FROM payments" - " WHERE payment_hash = ?"); - - sqlite3_bind_sha256(stmt, 1, payment_hash); - if (db_select_step(wallet->db, stmt)) { + stmt = db_prepare_v2(wallet->db, SQL("SELECT" + " id" + ", status" + ", destination" + ", msatoshi" + ", payment_hash" + ", timestamp" + ", payment_preimage" + ", path_secrets" + ", route_nodes" + ", route_channels" + ", msatoshi_sent" + ", description" + ", bolt11" + " FROM payments" + " WHERE payment_hash = ?")); + + db_bind_sha256(stmt, 0, payment_hash); + db_query_prepared(stmt); + if (db_step(stmt)) { payment = wallet_stmt2payment(ctx, stmt); - db_stmt_done(stmt); } + tal_free(stmt); return payment; } @@ -2133,7 +2203,7 @@ void wallet_payment_set_status(struct wallet *wallet, const enum wallet_payment_status newstatus, const struct preimage *preimage) { - sqlite3_stmt *stmt; + struct db_stmt *stmt; struct wallet_payment *payment; /* We can only fail an unstored payment! */ @@ -2144,32 +2214,32 @@ void wallet_payment_set_status(struct wallet *wallet, return; } - stmt = db_prepare(wallet->db, - "UPDATE payments SET status=? " - "WHERE payment_hash=?"); + stmt = db_prepare_v2(wallet->db, + SQL("UPDATE payments SET status=? " + "WHERE payment_hash=?")); - sqlite3_bind_int(stmt, 1, wallet_payment_status_in_db(newstatus)); - sqlite3_bind_sha256(stmt, 2, payment_hash); - db_exec_prepared(wallet->db, stmt); + db_bind_int(stmt, 0, wallet_payment_status_in_db(newstatus)); + db_bind_sha256(stmt, 1, payment_hash); + db_exec_prepared_v2(take(stmt)); if (preimage) { - stmt = db_prepare(wallet->db, - "UPDATE payments SET payment_preimage=? " - "WHERE payment_hash=?"); + stmt = db_prepare_v2(wallet->db, + SQL("UPDATE payments SET payment_preimage=? " + "WHERE payment_hash=?")); - sqlite3_bind_preimage(stmt, 1, preimage); - sqlite3_bind_sha256(stmt, 2, payment_hash); - db_exec_prepared(wallet->db, stmt); + db_bind_preimage(stmt, 0, preimage); + db_bind_sha256(stmt, 1, payment_hash); + db_exec_prepared_v2(take(stmt)); } if (newstatus != PAYMENT_PENDING) { - stmt = db_prepare(wallet->db, - "UPDATE payments" - " SET path_secrets = NULL" - " , route_nodes = NULL" - " , route_channels = NULL" - " WHERE payment_hash = ?;"); - sqlite3_bind_sha256(stmt, 1, payment_hash); - db_exec_prepared(wallet->db, stmt); + stmt = + db_prepare_v2(wallet->db, SQL("UPDATE payments" + " SET path_secrets = NULL" + " , route_nodes = NULL" + " , route_channels = NULL" + " WHERE payment_hash = ?;")); + db_bind_sha256(stmt, 0, payment_hash); + db_exec_prepared_v2(take(stmt)); } } @@ -2187,58 +2257,59 @@ void wallet_payment_get_failinfo(const tal_t *ctx, char **faildetail, int *faildirection) { - sqlite3_stmt *stmt; + struct db_stmt *stmt; bool resb; size_t len; - stmt = db_select_prepare(wallet->db, - "SELECT failonionreply, faildestperm" + stmt = db_prepare_v2(wallet->db, + SQL("SELECT failonionreply, faildestperm" ", failindex, failcode" ", failnode, failchannel" ", failupdate, faildetail, faildirection" " FROM payments" - " WHERE payment_hash=?;"); - sqlite3_bind_sha256(stmt, 1, payment_hash); - resb = db_select_step(wallet->db, stmt); + " WHERE payment_hash=?;")); + db_bind_sha256(stmt, 0, payment_hash); + db_query_prepared(stmt); + resb = db_step(stmt); assert(resb); - if (sqlite3_column_type(stmt, 0) == SQLITE_NULL) + + if (db_column_is_null(stmt, 0)) *failonionreply = NULL; else { - len = sqlite3_column_bytes(stmt, 0); + len = db_column_bytes(stmt, 0); *failonionreply = tal_arr(ctx, u8, len); - memcpy(*failonionreply, sqlite3_column_blob(stmt, 0), len); + memcpy(*failonionreply, db_column_blob(stmt, 0), len); } - *faildestperm = sqlite3_column_int(stmt, 1) != 0; - *failindex = sqlite3_column_int(stmt, 2); - *failcode = (enum onion_type) sqlite3_column_int(stmt, 3); - if (sqlite3_column_type(stmt, 4) == SQLITE_NULL) + *faildestperm = db_column_int(stmt, 1) != 0; + *failindex = db_column_int(stmt, 2); + *failcode = (enum onion_type) db_column_int(stmt, 3); + if (db_column_is_null(stmt, 4)) *failnode = NULL; else { *failnode = tal(ctx, struct node_id); - resb = sqlite3_column_node_id(stmt, 4, *failnode); - assert(resb); + db_column_node_id(stmt, 4, *failnode); } - if (sqlite3_column_type(stmt, 5) == SQLITE_NULL) + if (db_column_is_null(stmt, 5)) *failchannel = NULL; else { *failchannel = tal(ctx, struct short_channel_id); - resb = sqlite3_column_short_channel_id(stmt, 5, *failchannel); + resb = db_column_short_channel_id(stmt, 5, *failchannel); assert(resb); /* For pre-0.6.2 dbs, direction will be 0 */ - *faildirection = sqlite3_column_int(stmt, 8); + *faildirection = db_column_int(stmt, 8); } - if (sqlite3_column_type(stmt, 6) == SQLITE_NULL) + if (db_column_is_null(stmt, 6)) *failupdate = NULL; else { - len = sqlite3_column_bytes(stmt, 6); + len = db_column_bytes(stmt, 6); *failupdate = tal_arr(ctx, u8, len); - memcpy(*failupdate, sqlite3_column_blob(stmt, 6), len); + memcpy(*failupdate, db_column_blob(stmt, 6), len); } - *faildetail = tal_strndup(ctx, sqlite3_column_blob(stmt, 7), - sqlite3_column_bytes(stmt, 7)); + *faildetail = + tal_strndup(ctx, db_column_blob(stmt, 7), db_column_bytes(stmt, 7)); - db_stmt_done(stmt); + tal_free(stmt); } void wallet_payment_set_failinfo(struct wallet *wallet, @@ -2253,57 +2324,55 @@ void wallet_payment_set_failinfo(struct wallet *wallet, const char *faildetail, int faildirection) { - sqlite3_stmt *stmt; - - stmt = db_prepare(wallet->db, - "UPDATE payments" - " SET failonionreply=?" - " , faildestperm=?" - " , failindex=?" - " , failcode=?" - " , failnode=?" - " , failchannel=?" - " , failupdate=?" - " , faildetail=?" - " , faildirection=?" - " WHERE payment_hash=?;"); + struct db_stmt *stmt; + + stmt = db_prepare_v2(wallet->db, SQL("UPDATE payments" + " SET failonionreply=?" + " , faildestperm=?" + " , failindex=?" + " , failcode=?" + " , failnode=?" + " , failchannel=?" + " , failupdate=?" + " , faildetail=?" + " , faildirection=?" + " WHERE payment_hash=?;")); if (failonionreply) - sqlite3_bind_blob(stmt, 1, - failonionreply, tal_count(failonionreply), - SQLITE_TRANSIENT); + db_bind_blob(stmt, 0, failonionreply, + tal_count(failonionreply)); else - sqlite3_bind_null(stmt, 1); - sqlite3_bind_int(stmt, 2, faildestperm ? 1 : 0); - sqlite3_bind_int(stmt, 3, failindex); - sqlite3_bind_int(stmt, 4, (int) failcode); + db_bind_null(stmt, 0); + + db_bind_int(stmt, 1, faildestperm ? 1 : 0); + db_bind_int(stmt, 2, failindex); + db_bind_int(stmt, 3, (int) failcode); + if (failnode) - sqlite3_bind_node_id(stmt, 5, failnode); + db_bind_node_id(stmt, 4, failnode); else - sqlite3_bind_null(stmt, 5); + db_bind_null(stmt, 4); + if (failchannel) { - /* sqlite3_bind_short_channel_id requires the input + /* db_bind_short_channel_id requires the input * channel to be tal-allocated... */ struct short_channel_id *scid = tal(tmpctx, struct short_channel_id); *scid = *failchannel; - sqlite3_bind_short_channel_id(stmt, 6, scid); - sqlite3_bind_int(stmt, 9, faildirection); + db_bind_short_channel_id(stmt, 5, scid); + db_bind_int(stmt, 8, faildirection); } else { - sqlite3_bind_null(stmt, 6); - sqlite3_bind_null(stmt, 9); + db_bind_null(stmt, 5); + db_bind_null(stmt, 8); } + if (failupdate) - sqlite3_bind_blob(stmt, 7, - failupdate, tal_count(failupdate), - SQLITE_TRANSIENT); + db_bind_blob(stmt, 6, failupdate, tal_count(failupdate)); else - sqlite3_bind_null(stmt, 7); - sqlite3_bind_blob(stmt, 8, - faildetail, strlen(faildetail), - SQLITE_TRANSIENT); + db_bind_null(stmt, 6); - sqlite3_bind_sha256(stmt, 10, payment_hash); + db_bind_text(stmt, 7, faildetail); + db_bind_sha256(stmt, 9, payment_hash); - db_exec_prepared(wallet->db, stmt); + db_exec_prepared_v2(take(stmt)); } const struct wallet_payment ** @@ -2312,53 +2381,54 @@ wallet_payment_list(const tal_t *ctx, const struct sha256 *payment_hash) { const struct wallet_payment **payments; - sqlite3_stmt *stmt; + struct db_stmt *stmt; struct wallet_payment *p; size_t i; payments = tal_arr(ctx, const struct wallet_payment *, 0); if (payment_hash) { - stmt = db_select_prepare(wallet->db, - "SELECT" - " id" - ", status" - ", destination" - ", msatoshi" - ", payment_hash" - ", timestamp" - ", payment_preimage" - ", path_secrets" - ", route_nodes" - ", route_channels" - ", msatoshi_sent" - ", description" - ", bolt11" - " FROM payments" - " WHERE payment_hash = ?;"); - sqlite3_bind_sha256(stmt, 1, payment_hash); + stmt = + db_prepare_v2(wallet->db, SQL("SELECT" + " id" + ", status" + ", destination" + ", msatoshi" + ", payment_hash" + ", timestamp" + ", payment_preimage" + ", path_secrets" + ", route_nodes" + ", route_channels" + ", msatoshi_sent" + ", description" + ", bolt11" + " FROM payments" + " WHERE payment_hash = ?;")); + db_bind_sha256(stmt, 0, payment_hash); } else { - stmt = db_select_prepare(wallet->db, - "SELECT" - " id" - ", status" - ", destination" - ", msatoshi" - ", payment_hash" - ", timestamp" - ", payment_preimage" - ", path_secrets" - ", route_nodes" - ", route_channels" - ", msatoshi_sent" - ", description" - ", bolt11" - " FROM payments;"); - } - - for (i = 0; db_select_step(wallet->db, stmt); i++) { + stmt = db_prepare_v2(wallet->db, SQL("SELECT" + " id" + ", status" + ", destination" + ", msatoshi" + ", payment_hash" + ", timestamp" + ", payment_preimage" + ", path_secrets" + ", route_nodes" + ", route_channels" + ", msatoshi_sent" + ", description" + ", bolt11" + " FROM payments;")); + } + db_query_prepared(stmt); + + for (i = 0; db_step(stmt); i++) { tal_resize(&payments, i+1); payments[i] = wallet_stmt2payment(payments, stmt); } + tal_free(stmt); /* Now attach payments not yet in db. */ list_for_each(&wallet->unstored_payments, p, list) { @@ -2375,30 +2445,33 @@ void wallet_htlc_sigs_save(struct wallet *w, u64 channel_id, secp256k1_ecdsa_signature *htlc_sigs) { /* Clear any existing HTLC sigs for this channel */ - sqlite3_stmt *stmt = - db_prepare(w->db, "DELETE FROM htlc_sigs WHERE channelid = ?"); - sqlite3_bind_int64(stmt, 1, channel_id); - db_exec_prepared(w->db, stmt); + struct db_stmt *stmt = db_prepare_v2( + w->db, SQL("DELETE FROM htlc_sigs WHERE channelid = ?")); + db_bind_u64(stmt, 0, channel_id); + db_exec_prepared_v2(take(stmt)); /* Now insert the new ones */ for (size_t i=0; idb, "INSERT INTO htlc_sigs (channelid, signature) VALUES (?, ?)"); - sqlite3_bind_int64(stmt, 1, channel_id); - sqlite3_bind_signature(stmt, 2, &htlc_sigs[i]); - db_exec_prepared(w->db, stmt); + stmt = db_prepare_v2(w->db, + SQL("INSERT INTO htlc_sigs (channelid, " + "signature) VALUES (?, ?)")); + db_bind_u64(stmt, 0, channel_id); + db_bind_signature(stmt, 1, &htlc_sigs[i]); + db_exec_prepared_v2(take(stmt)); } } bool wallet_network_check(struct wallet *w, const struct chainparams *chainparams) { - sqlite3_stmt *stmt = db_select(w->db, - "SELECT val FROM vars WHERE name='genesis_hash'"); struct bitcoin_blkid chainhash; + struct db_stmt *stmt = db_prepare_v2( + w->db, SQL("SELECT val FROM vars WHERE name='genesis_hash'")); + db_query_prepared(stmt); - if (db_select_step(w->db, stmt)) { - sqlite3_column_sha256_double(stmt, 0, &chainhash.shad); - db_stmt_done(stmt); + if (db_step(stmt)) { + db_column_sha256d(stmt, 0, &chainhash.shad); + tal_free(stmt); if (!bitcoin_blkid_eq(&chainhash, &chainparams->genesis_blockhash)) { log_broken(w->log, "Wallet blockchain hash does not " @@ -2414,11 +2487,13 @@ bool wallet_network_check(struct wallet *w, return false; } } else { + tal_free(stmt); /* Still a pristine wallet, claim it for the chain * that we are running */ - stmt = db_prepare(w->db, "INSERT INTO vars (name, val) VALUES ('genesis_hash', ?);"); - sqlite3_bind_sha256_double(stmt, 1, &chainparams->genesis_blockhash.shad); - db_exec_prepared(w->db, stmt); + stmt = db_prepare_v2(w->db, SQL("INSERT INTO vars (name, val) " + "VALUES ('genesis_hash', ?);")); + db_bind_sha256d(stmt, 0, &chainparams->genesis_blockhash.shad); + db_exec_prepared_v2(take(stmt)); } return true; } @@ -2428,36 +2503,42 @@ bool wallet_network_check(struct wallet *w, */ static void wallet_utxoset_prune(struct wallet *w, const u32 blockheight) { - sqlite3_stmt *stmt; + struct db_stmt *stmt; struct bitcoin_txid txid; - stmt = db_select_prepare(w->db, "SELECT txid, outnum FROM utxoset WHERE spendheight < ?"); - sqlite3_bind_int(stmt, 1, blockheight - UTXO_PRUNE_DEPTH); + stmt = db_prepare_v2( + w->db, + SQL("SELECT txid, outnum FROM utxoset WHERE spendheight < ?")); + db_bind_int(stmt, 0, blockheight - UTXO_PRUNE_DEPTH); + db_query_prepared(stmt); - while (db_select_step(w->db, stmt)) { - sqlite3_column_sha256_double(stmt, 0, &txid.shad); - outpointfilter_remove(w->utxoset_outpoints, &txid, sqlite3_column_int(stmt, 1)); + while (db_step(stmt)) { + db_column_sha256d(stmt, 0, &txid.shad); + outpointfilter_remove(w->utxoset_outpoints, &txid, + db_column_int(stmt, 1)); } + tal_free(stmt); - stmt = db_prepare(w->db, "DELETE FROM utxoset WHERE spendheight < ?"); - sqlite3_bind_int(stmt, 1, blockheight - UTXO_PRUNE_DEPTH); - db_exec_prepared(w->db, stmt); + stmt = db_prepare_v2(w->db, + SQL("DELETE FROM utxoset WHERE spendheight < ?")); + db_bind_int(stmt, 0, blockheight - UTXO_PRUNE_DEPTH); + db_exec_prepared_v2(take(stmt)); } void wallet_block_add(struct wallet *w, struct block *b) { - sqlite3_stmt *stmt = db_prepare(w->db, - "INSERT INTO blocks " - "(height, hash, prev_hash) " - "VALUES (?, ?, ?);"); - sqlite3_bind_int(stmt, 1, b->height); - sqlite3_bind_sha256_double(stmt, 2, &b->blkid.shad); + struct db_stmt *stmt = + db_prepare_v2(w->db, SQL("INSERT INTO blocks " + "(height, hash, prev_hash) " + "VALUES (?, ?, ?);")); + db_bind_int(stmt, 0, b->height); + db_bind_sha256d(stmt, 1, &b->blkid.shad); if (b->prev) { - sqlite3_bind_sha256_double(stmt, 3, &b->prev->blkid.shad); + db_bind_sha256d(stmt, 2, &b->prev->blkid.shad); }else { - sqlite3_bind_null(stmt, 3); + db_bind_null(stmt, 2); } - db_exec_prepared(w->db, stmt); + db_exec_prepared_v2(take(stmt)); /* Now cleanup UTXOs that we don't care about anymore */ wallet_utxoset_prune(w, b->height); @@ -2465,23 +2546,26 @@ void wallet_block_add(struct wallet *w, struct block *b) void wallet_block_remove(struct wallet *w, struct block *b) { - sqlite3_stmt *stmt = db_prepare(w->db, - "DELETE FROM blocks WHERE hash = ?"); - sqlite3_bind_sha256_double(stmt, 1, &b->blkid.shad); - db_exec_prepared(w->db, stmt); + struct db_stmt *stmt = + db_prepare_v2(w->db, SQL("DELETE FROM blocks WHERE hash = ?")); + db_bind_sha256d(stmt, 0, &b->blkid.shad); + db_exec_prepared_v2(take(stmt)); /* Make sure that all descendants of the block are also deleted */ - stmt = db_select_prepare(w->db, "SELECT * FROM blocks WHERE height >= ?;"); - sqlite3_bind_int(stmt, 1, b->height); - assert(!db_select_step(w->db, stmt)); + stmt = db_prepare_v2(w->db, + SQL("SELECT * FROM blocks WHERE height >= ?;")); + db_bind_int(stmt, 0, b->height); + db_query_prepared(stmt); + assert(!db_step(stmt)); + tal_free(stmt); } void wallet_blocks_rollback(struct wallet *w, u32 height) { - sqlite3_stmt *stmt = db_prepare(w->db, "DELETE FROM blocks " - "WHERE height > ?"); - sqlite3_bind_int(stmt, 1, height); - db_exec_prepared(w->db, stmt); + struct db_stmt *stmt = db_prepare_v2(w->db, SQL("DELETE FROM blocks " + "WHERE height > ?")); + db_bind_int(stmt, 0, height); + db_exec_prepared_v2(take(stmt)); } const struct short_channel_id * @@ -2489,58 +2573,60 @@ wallet_outpoint_spend(struct wallet *w, const tal_t *ctx, const u32 blockheight, const struct bitcoin_txid *txid, const u32 outnum) { struct short_channel_id *scid; - sqlite3_stmt *stmt; + struct db_stmt *stmt; bool res; + int changes; if (outpointfilter_matches(w->owned_outpoints, txid, outnum)) { - stmt = db_prepare(w->db, - "UPDATE outputs " - "SET spend_height = ? " - "WHERE prev_out_tx = ?" - " AND prev_out_index = ?"); + stmt = db_prepare_v2(w->db, SQL("UPDATE outputs " + "SET spend_height = ? " + "WHERE prev_out_tx = ?" + " AND prev_out_index = ?")); - sqlite3_bind_int(stmt, 1, blockheight); - sqlite3_bind_sha256_double(stmt, 2, &txid->shad); - sqlite3_bind_int(stmt, 3, outnum); + db_bind_int(stmt, 0, blockheight); + db_bind_sha256d(stmt, 1, &txid->shad); + db_bind_int(stmt, 2, outnum); - db_exec_prepared(w->db, stmt); + db_exec_prepared_v2(take(stmt)); } if (outpointfilter_matches(w->utxoset_outpoints, txid, outnum)) { - stmt = db_prepare(w->db, - "UPDATE utxoset " - "SET spendheight = ? " - "WHERE txid = ?" - " AND outnum = ?"); + stmt = db_prepare_v2(w->db, SQL("UPDATE utxoset " + "SET spendheight = ? " + "WHERE txid = ?" + " AND outnum = ?")); - sqlite3_bind_int(stmt, 1, blockheight); - sqlite3_bind_sha256_double(stmt, 2, &txid->shad); - sqlite3_bind_int(stmt, 3, outnum); + db_bind_int(stmt, 0, blockheight); + db_bind_sha256d(stmt, 1, &txid->shad); + db_bind_int(stmt, 2, outnum); - db_exec_prepared(w->db, stmt); + db_exec_prepared_v2(stmt); + changes = db_count_changes(stmt); + tal_free(stmt); - if (db_changes(w->db) == 0) { + if (changes == 0) { return NULL; } /* Now look for the outpoint's short_channel_id */ - stmt = db_select_prepare(w->db, - "SELECT " - "blockheight, txindex " - "FROM utxoset " - "WHERE txid = ? AND outnum = ?"); - sqlite3_bind_sha256_double(stmt, 1, &txid->shad); - sqlite3_bind_int(stmt, 2, outnum); - - res = db_select_step(w->db, stmt); + stmt = + db_prepare_v2(w->db, SQL("SELECT " + "blockheight, txindex " + "FROM utxoset " + "WHERE txid = ? AND outnum = ?")); + db_bind_sha256d(stmt, 0, &txid->shad); + db_bind_int(stmt, 1, outnum); + db_query_prepared(stmt); + + res = db_step(stmt); assert(res); scid = tal(ctx, struct short_channel_id); - if (!mk_short_channel_id(scid, sqlite3_column_int(stmt, 0), - sqlite3_column_int(stmt, 1), outnum)) + if (!mk_short_channel_id(scid, db_column_int(stmt, 0), + db_column_int(stmt, 1), outnum)) fatal("wallet_outpoint_spend: invalid scid %u:%u:%u", - sqlite3_column_int(stmt, 0), - sqlite3_column_int(stmt, 1), outnum); - db_stmt_done(stmt); + db_column_int(stmt, 0), + db_column_int(stmt, 1), outnum); + tal_free(stmt); return scid; } return NULL; @@ -2551,63 +2637,65 @@ void wallet_utxoset_add(struct wallet *w, const struct bitcoin_tx *tx, const u32 txindex, const u8 *scriptpubkey, struct amount_sat sat) { - sqlite3_stmt *stmt; + struct db_stmt *stmt; struct bitcoin_txid txid; bitcoin_txid(tx, &txid); - stmt = db_prepare(w->db, "INSERT INTO utxoset (" - " txid," - " outnum," - " blockheight," - " spendheight," - " txindex," - " scriptpubkey," - " satoshis" - ") VALUES(?, ?, ?, ?, ?, ?, ?);"); - sqlite3_bind_sha256_double(stmt, 1, &txid.shad); - sqlite3_bind_int(stmt, 2, outnum); - sqlite3_bind_int(stmt, 3, blockheight); - sqlite3_bind_null(stmt, 4); - sqlite3_bind_int(stmt, 5, txindex); - sqlite3_bind_blob(stmt, 6, scriptpubkey, tal_count(scriptpubkey), SQLITE_TRANSIENT); - sqlite3_bind_amount_sat(stmt, 7, sat); - db_exec_prepared(w->db, stmt); + stmt = db_prepare_v2(w->db, SQL("INSERT INTO utxoset (" + " txid," + " outnum," + " blockheight," + " spendheight," + " txindex," + " scriptpubkey," + " satoshis" + ") VALUES(?, ?, ?, ?, ?, ?, ?);")); + db_bind_sha256d(stmt, 0, &txid.shad); + db_bind_int(stmt, 1, outnum); + db_bind_int(stmt, 2, blockheight); + db_bind_null(stmt, 3); + db_bind_int(stmt, 4, txindex); + db_bind_blob(stmt, 5, scriptpubkey, tal_count(scriptpubkey)); + db_bind_amount_sat(stmt, 6, &sat); + db_exec_prepared_v2(take(stmt)); outpointfilter_add(w->utxoset_outpoints, &txid, outnum); } void wallet_filteredblock_add(struct wallet *w, const struct filteredblock *fb) { + struct db_stmt *stmt; if (wallet_have_block(w, fb->height)) return; - sqlite3_stmt *stmt = db_prepare(w->db, "INSERT OR IGNORE INTO blocks " - "(height, hash, prev_hash) " - "VALUES (?, ?, ?);"); - sqlite3_bind_int(stmt, 1, fb->height); - sqlite3_bind_sha256_double(stmt, 2, &fb->id.shad); - sqlite3_bind_sha256_double(stmt, 3, &fb->prev_hash.shad); - db_exec_prepared(w->db, stmt); + stmt = db_prepare_v2(w->db, SQL("INSERT OR IGNORE INTO blocks " + "(height, hash, prev_hash) " + "VALUES (?, ?, ?);")); + db_bind_int(stmt, 0, fb->height); + db_bind_sha256d(stmt, 1, &fb->id.shad); + db_bind_sha256d(stmt, 2, &fb->prev_hash.shad); + db_exec_prepared_v2(take(stmt)); for (size_t i = 0; i < tal_count(fb->outpoints); i++) { struct filteredblock_outpoint *o = fb->outpoints[i]; - stmt = db_prepare(w->db, "INSERT INTO utxoset (" - " txid," - " outnum," - " blockheight," - " spendheight," - " txindex," - " scriptpubkey," - " satoshis" - ") VALUES(?, ?, ?, ?, ?, ?, ?);"); - sqlite3_bind_sha256_double(stmt, 1, &o->txid.shad); - sqlite3_bind_int(stmt, 2, o->outnum); - sqlite3_bind_int(stmt, 3, fb->height); - sqlite3_bind_null(stmt, 4); - sqlite3_bind_int(stmt, 5, o->txindex); - sqlite3_bind_blob(stmt, 6, o->scriptPubKey, - tal_count(o->scriptPubKey), SQLITE_TRANSIENT); - sqlite3_bind_amount_sat(stmt, 7, o->amount); - db_exec_prepared(w->db, stmt); + stmt = + db_prepare_v2(w->db, SQL("INSERT INTO utxoset (" + " txid," + " outnum," + " blockheight," + " spendheight," + " txindex," + " scriptpubkey," + " satoshis" + ") VALUES(?, ?, ?, ?, ?, ?, ?);")); + db_bind_sha256d(stmt, 0, &o->txid.shad); + db_bind_int(stmt, 1, o->outnum); + db_bind_int(stmt, 2, fb->height); + db_bind_null(stmt, 3); + db_bind_int(stmt, 4, o->txindex); + db_bind_blob(stmt, 5, o->scriptPubKey, + tal_count(o->scriptPubKey)); + db_bind_amount_sat(stmt, 6, &o->amount); + db_exec_prepared_v2(take(stmt)); outpointfilter_add(w->utxoset_outpoints, &o->txid, o->outnum); } @@ -2616,19 +2704,21 @@ void wallet_filteredblock_add(struct wallet *w, const struct filteredblock *fb) bool wallet_have_block(struct wallet *w, u32 blockheight) { bool result; - sqlite3_stmt *stmt = db_select_prepare(w->db, "SELECT height FROM blocks WHERE height = ?"); - sqlite3_bind_int(stmt, 1, blockheight); - result = sqlite3_step(stmt) == SQLITE_ROW; - db_stmt_done(stmt); + struct db_stmt *stmt = db_prepare_v2( + w->db, SQL("SELECT height FROM blocks WHERE height = ?")); + db_bind_int(stmt, 0, blockheight); + db_query_prepared(stmt); + result = db_step(stmt); + tal_free(stmt); return result; } struct outpoint *wallet_outpoint_for_scid(struct wallet *w, tal_t *ctx, const struct short_channel_id *scid) { - sqlite3_stmt *stmt; + struct db_stmt *stmt; struct outpoint *op; - stmt = db_select_prepare(w->db, "SELECT" + stmt = db_prepare_v2(w->db, SQL("SELECT" " txid," " spendheight," " scriptpubkey," @@ -2637,25 +2727,27 @@ struct outpoint *wallet_outpoint_for_scid(struct wallet *w, tal_t *ctx, "WHERE blockheight = ?" " AND txindex = ?" " AND outnum = ?" - " AND spendheight IS NULL"); - sqlite3_bind_int(stmt, 1, short_channel_id_blocknum(scid)); - sqlite3_bind_int(stmt, 2, short_channel_id_txnum(scid)); - sqlite3_bind_int(stmt, 3, short_channel_id_outnum(scid)); - - - if (!db_select_step(w->db, stmt)) + " AND spendheight IS NULL")); + db_bind_int(stmt, 0, short_channel_id_blocknum(scid)); + db_bind_int(stmt, 1, short_channel_id_txnum(scid)); + db_bind_int(stmt, 2, short_channel_id_outnum(scid)); + db_query_prepared(stmt); + + if (!db_step(stmt)) { + tal_free(stmt); return NULL; + } op = tal(ctx, struct outpoint); op->blockheight = short_channel_id_blocknum(scid); op->txindex = short_channel_id_txnum(scid); op->outnum = short_channel_id_outnum(scid); - sqlite3_column_sha256_double(stmt, 0, &op->txid.shad); - op->spendheight = sqlite3_column_int(stmt, 1); - op->scriptpubkey = tal_arr(op, u8, sqlite3_column_bytes(stmt, 2)); - memcpy(op->scriptpubkey, sqlite3_column_blob(stmt, 2), sqlite3_column_bytes(stmt, 2)); - op->sat = sqlite3_column_amount_sat(stmt, 3); - db_stmt_done(stmt); + db_column_sha256d(stmt, 0, &op->txid.shad); + op->spendheight = db_column_int(stmt, 1); + op->scriptpubkey = tal_arr(op, u8, db_column_bytes(stmt, 2)); + memcpy(op->scriptpubkey, db_column_blob(stmt, 2), db_column_bytes(stmt, 2)); + db_column_amount_sat(stmt, 3, &op->sat); + tal_free(stmt); return op; } @@ -2664,41 +2756,45 @@ void wallet_transaction_add(struct wallet *w, const struct bitcoin_tx *tx, const u32 blockheight, const u32 txindex) { struct bitcoin_txid txid; - sqlite3_stmt *stmt = db_select_prepare(w->db, "SELECT blockheight FROM transactions WHERE id=?"); + struct db_stmt *stmt = db_prepare_v2( + w->db, SQL("SELECT blockheight FROM transactions WHERE id=?")); bitcoin_txid(tx, &txid); - sqlite3_bind_sha256(stmt, 1, &txid.shad.sha); - if (!db_select_step(w->db, stmt)) { + db_bind_txid(stmt, 0, &txid); + db_query_prepared(stmt); + + if (!db_step(stmt)) { + tal_free(stmt); /* This transaction is still unknown, insert */ - stmt = db_prepare(w->db, - "INSERT INTO transactions (" + stmt = db_prepare_v2(w->db, + SQL("INSERT INTO transactions (" " id" ", blockheight" ", txindex" - ", rawtx) VALUES (?, ?, ?, ?);"); - sqlite3_bind_sha256(stmt, 1, &txid.shad.sha); + ", rawtx) VALUES (?, ?, ?, ?);")); + db_bind_txid(stmt, 0, &txid); if (blockheight) { - sqlite3_bind_int(stmt, 2, blockheight); - sqlite3_bind_int(stmt, 3, txindex); + db_bind_int(stmt, 1, blockheight); + db_bind_int(stmt, 2, txindex); } else { - sqlite3_bind_null(stmt, 2); - sqlite3_bind_null(stmt, 3); + db_bind_null(stmt, 1); + db_bind_null(stmt, 2); } - sqlite3_bind_tx(stmt, 4, tx); - db_exec_prepared(w->db, stmt); + db_bind_tx(stmt, 3, tx); + db_exec_prepared_v2(take(stmt)); } else { - db_stmt_done(stmt); + tal_free(stmt); if (blockheight) { /* We know about the transaction, update */ - stmt = db_prepare(w->db, - "UPDATE transactions " - "SET blockheight = ?, txindex = ? " - "WHERE id = ?"); - sqlite3_bind_int(stmt, 1, blockheight); - sqlite3_bind_int(stmt, 2, txindex); - sqlite3_bind_sha256(stmt, 3, &txid.shad.sha); - db_exec_prepared(w->db, stmt); + stmt = db_prepare_v2(w->db, + SQL("UPDATE transactions " + "SET blockheight = ?, txindex = ? " + "WHERE id = ?")); + db_bind_int(stmt, 0, blockheight); + db_bind_int(stmt, 1, txindex); + db_bind_txid(stmt, 2, &txid); + db_exec_prepared_v2(take(stmt)); } } } @@ -2707,43 +2803,52 @@ void wallet_transaction_annotate(struct wallet *w, const struct bitcoin_txid *txid, enum wallet_tx_type type, u64 channel_id) { - sqlite3_stmt *stmt = db_select_prepare(w->db, "SELECT type, channel_id FROM transactions WHERE id=?"); - sqlite3_bind_sha256(stmt, 1, &txid->shad.sha); - if (!db_select_step(w->db, stmt)) + struct db_stmt *stmt = db_prepare_v2( + w->db, SQL("SELECT type, channel_id FROM transactions WHERE id=?")); + db_bind_txid(stmt, 0, txid); + db_query_prepared(stmt); + + if (!db_step(stmt)) fatal("Attempting to annotate a transaction we don't have: %s", type_to_string(tmpctx, struct bitcoin_txid, txid)); - type |= sqlite3_column_int(stmt, 0); + + type |= db_column_int(stmt, 0); if (channel_id == 0) - channel_id = sqlite3_column_int64(stmt, 1); + channel_id = db_column_u64(stmt, 1); - db_stmt_done(stmt); + tal_free(stmt); - stmt = db_prepare(w->db, "UPDATE transactions " - "SET type = ?" - ", channel_id = ? " - "WHERE id = ?"); + stmt = db_prepare_v2(w->db, SQL("UPDATE transactions " + "SET type = ?" + ", channel_id = ? " + "WHERE id = ?")); + + db_bind_int(stmt, 0, type); - sqlite3_bind_int(stmt, 1, type); if (channel_id) - sqlite3_bind_int(stmt, 2, channel_id); + db_bind_int(stmt, 1, channel_id); else - sqlite3_bind_null(stmt, 2); - sqlite3_bind_sha256(stmt, 3, &txid->shad.sha); - db_exec_prepared(w->db, stmt); + db_bind_null(stmt, 1); + + db_bind_txid(stmt, 2, txid); + db_exec_prepared_v2(take(stmt)); } u32 wallet_transaction_height(struct wallet *w, const struct bitcoin_txid *txid) { u32 blockheight; - sqlite3_stmt *stmt = db_select_prepare( - w->db, "SELECT blockheight FROM transactions WHERE id=?"); - sqlite3_bind_sha256(stmt, 1, &txid->shad.sha); + struct db_stmt *stmt = db_prepare_v2( + w->db, SQL("SELECT blockheight FROM transactions WHERE id=?")); + db_bind_txid(stmt, 0, txid); + db_query_prepared(stmt); - if (!db_select_step(w->db, stmt)) + if (!db_step(stmt)) { + tal_free(stmt); return 0; + } - blockheight = sqlite3_column_int(stmt, 0); - db_stmt_done(stmt); + blockheight = db_column_int(stmt, 0); + tal_free(stmt); return blockheight; } @@ -2751,23 +2856,26 @@ struct txlocator *wallet_transaction_locate(const tal_t *ctx, struct wallet *w, const struct bitcoin_txid *txid) { struct txlocator *loc; - sqlite3_stmt *stmt; + struct db_stmt *stmt; - stmt = db_select_prepare( - w->db, "SELECT blockheight, txindex FROM transactions WHERE id=?"); - sqlite3_bind_sha256(stmt, 1, &txid->shad.sha); + stmt = db_prepare_v2( + w->db, SQL("SELECT blockheight, txindex FROM transactions WHERE id=?")); + db_bind_txid(stmt, 0, txid); + db_query_prepared(stmt); - if (!db_select_step(w->db, stmt)) + if (!db_step(stmt)) { + tal_free(stmt); return NULL; + } - if (sqlite3_column_type(stmt, 0) == SQLITE_NULL) + if (db_column_is_null(stmt, 0)) loc = NULL; else { loc = tal(ctx, struct txlocator); - loc->blkheight = sqlite3_column_int(stmt, 0); - loc->index = sqlite3_column_int(stmt, 1); + loc->blkheight = db_column_int(stmt, 0); + loc->index = db_column_int(stmt, 1); } - db_stmt_done(stmt); + tal_free(stmt); return loc; } @@ -2775,18 +2883,20 @@ struct bitcoin_txid *wallet_transactions_by_height(const tal_t *ctx, struct wallet *w, const u32 blockheight) { - sqlite3_stmt *stmt; + struct db_stmt *stmt; struct bitcoin_txid *txids = tal_arr(ctx, struct bitcoin_txid, 0); int count = 0; - stmt = db_select_prepare( - w->db, "SELECT id FROM transactions WHERE blockheight=?"); - sqlite3_bind_int(stmt, 1, blockheight); + stmt = db_prepare_v2( + w->db, SQL("SELECT id FROM transactions WHERE blockheight=?")); + db_bind_int(stmt, 0, blockheight); + db_query_prepared(stmt); - while (db_select_step(w->db, stmt)) { + while (db_step(stmt)) { count++; tal_resize(&txids, count); - sqlite3_column_sha256(stmt, 0, &txids[count-1].shad.sha); + db_column_txid(stmt, 0, &txids[count-1]); } + tal_free(stmt); return txids; } @@ -2795,37 +2905,41 @@ void wallet_channeltxs_add(struct wallet *w, struct channel *chan, const int type, const struct bitcoin_txid *txid, const u32 input_num, const u32 blockheight) { - sqlite3_stmt *stmt; - stmt = db_prepare(w->db, "INSERT INTO channeltxs (" - " channel_id" - ", type" - ", transaction_id" - ", input_num" - ", blockheight" - ") VALUES (?, ?, ?, ?, ?);"); - sqlite3_bind_int(stmt, 1, chan->dbid); - sqlite3_bind_int(stmt, 2, type); - sqlite3_bind_sha256(stmt, 3, &txid->shad.sha); - sqlite3_bind_int(stmt, 4, input_num); - sqlite3_bind_int(stmt, 5, blockheight); + struct db_stmt *stmt; + stmt = db_prepare_v2(w->db, SQL("INSERT INTO channeltxs (" + " channel_id" + ", type" + ", transaction_id" + ", input_num" + ", blockheight" + ") VALUES (?, ?, ?, ?, ?);")); + db_bind_int(stmt, 0, chan->dbid); + db_bind_int(stmt, 1, type); + db_bind_sha256(stmt, 2, &txid->shad.sha); + db_bind_int(stmt, 3, input_num); + db_bind_int(stmt, 4, blockheight); - db_exec_prepared(w->db, stmt); + db_exec_prepared_v2(take(stmt)); } u32 *wallet_onchaind_channels(struct wallet *w, const tal_t *ctx) { - sqlite3_stmt *stmt; + struct db_stmt *stmt; size_t count = 0; u32 *channel_ids = tal_arr(ctx, u32, 0); - stmt = db_select_prepare(w->db, "SELECT DISTINCT(channel_id) FROM channeltxs WHERE type = ?;"); - sqlite3_bind_int(stmt, 1, WIRE_ONCHAIN_INIT); + stmt = db_prepare_v2( + w->db, + SQL("SELECT DISTINCT(channel_id) FROM channeltxs WHERE type = ?;")); + db_bind_int(stmt, 0, WIRE_ONCHAIN_INIT); + db_query_prepared(stmt); - while (db_select_step(w->db, stmt)) { + while (db_step(stmt)) { count++; tal_resize(&channel_ids, count); - channel_ids[count-1] = sqlite3_column_int64(stmt, 0); + channel_ids[count-1] = db_column_u64(stmt, 0); } + tal_free(stmt); return channel_ids; } @@ -2833,35 +2947,37 @@ u32 *wallet_onchaind_channels(struct wallet *w, struct channeltx *wallet_channeltxs_get(struct wallet *w, const tal_t *ctx, u32 channel_id) { - sqlite3_stmt *stmt; + struct db_stmt *stmt; size_t count = 0; struct channeltx *res = tal_arr(ctx, struct channeltx, 0); - stmt = db_select_prepare( - w->db, "SELECT" - " c.type" - ", c.blockheight" - ", t.rawtx" - ", c.input_num" - ", c.blockheight - t.blockheight + 1 AS depth" - ", t.id as txid " - "FROM channeltxs c " - "JOIN transactions t ON t.id == c.transaction_id " - "WHERE c.channel_id = ? " - "ORDER BY c.id ASC;"); - sqlite3_bind_int(stmt, 1, channel_id); - - while (db_select_step(w->db, stmt)) { + stmt = db_prepare_v2( + w->db, SQL("SELECT" + " c.type" + ", c.blockheight" + ", t.rawtx" + ", c.input_num" + ", c.blockheight - t.blockheight + 1 AS depth" + ", t.id as txid " + "FROM channeltxs c " + "JOIN transactions t ON t.id == c.transaction_id " + "WHERE c.channel_id = ? " + "ORDER BY c.id ASC;")); + db_bind_int(stmt, 0, channel_id); + db_query_prepared(stmt); + + while (db_step(stmt)) { count++; tal_resize(&res, count); res[count-1].channel_id = channel_id; - res[count-1].type = sqlite3_column_int(stmt, 0); - res[count-1].blockheight = sqlite3_column_int(stmt, 1); - res[count-1].tx = sqlite3_column_tx(ctx, stmt, 2); - res[count-1].input_num = sqlite3_column_int(stmt, 3); - res[count-1].depth = sqlite3_column_int(stmt, 4); - sqlite3_column_sha256(stmt, 5, &res[count-1].txid.shad.sha); - } + res[count-1].type = db_column_int(stmt, 0); + res[count-1].blockheight = db_column_int(stmt, 1); + res[count-1].tx = db_column_tx(ctx, stmt, 2); + res[count-1].input_num = db_column_int(stmt, 3); + res[count-1].depth = db_column_int(stmt, 4); + db_column_txid(stmt, 5, &res[count-1].txid); + } + tal_free(stmt); return res; } @@ -2870,83 +2986,82 @@ void wallet_forwarded_payment_add(struct wallet *w, const struct htlc_in *in, enum forward_status state, enum onion_type failcode) { - sqlite3_stmt *stmt; + struct db_stmt *stmt; struct timeabs *resolved_time; - stmt = db_prepare( - w->db, - "INSERT OR REPLACE INTO forwarded_payments (" - " in_htlc_id" - ", out_htlc_id" - ", in_channel_scid" - ", out_channel_scid" - ", in_msatoshi" - ", out_msatoshi" - ", state" - ", received_time" - ", resolved_time" - ", failcode" - ") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?);"); - sqlite3_bind_int64(stmt, 1, in->dbid); + stmt = db_prepare_v2(w->db, + SQL("INSERT OR REPLACE INTO forwarded_payments (" + " in_htlc_id" + ", out_htlc_id" + ", in_channel_scid" + ", out_channel_scid" + ", in_msatoshi" + ", out_msatoshi" + ", state" + ", received_time" + ", resolved_time" + ", failcode" + ") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?);")); + db_bind_u64(stmt, 0, in->dbid); if(out) { - sqlite3_bind_int64(stmt, 2, out->dbid); - sqlite3_bind_int64(stmt, 4, out->key.channel->scid->u64); - sqlite3_bind_amount_msat(stmt, 6, out->msat); + db_bind_u64(stmt, 1, out->dbid); + db_bind_u64(stmt, 3, out->key.channel->scid->u64); + db_bind_amount_msat(stmt, 5, &out->msat); } else { /* FORWARD_LOCAL_FAILED may occur before we get htlc_out */ assert(failcode != 0); assert(state == FORWARD_LOCAL_FAILED); - sqlite3_bind_null(stmt, 2); - sqlite3_bind_null(stmt, 4); - sqlite3_bind_null(stmt, 6); + db_bind_null(stmt, 1); + db_bind_null(stmt, 3); + db_bind_null(stmt, 5); } - sqlite3_bind_int64(stmt, 3, in->key.channel->scid->u64); + db_bind_u64(stmt, 2, in->key.channel->scid->u64); - sqlite3_bind_amount_msat(stmt, 5, in->msat); + db_bind_amount_msat(stmt, 4, &in->msat); - sqlite3_bind_int(stmt, 7, wallet_forward_status_in_db(state)); - sqlite3_bind_timeabs(stmt, 8, in->received_time); + db_bind_int(stmt, 6, wallet_forward_status_in_db(state)); + db_bind_timeabs(stmt, 7, in->received_time); if (state == FORWARD_SETTLED || state == FORWARD_FAILED) { resolved_time = tal(tmpctx, struct timeabs); *resolved_time = time_now(); - sqlite3_bind_timeabs(stmt, 9, *resolved_time); + db_bind_timeabs(stmt, 8, *resolved_time); } else { resolved_time = NULL; - sqlite3_bind_null(stmt, 9); + db_bind_null(stmt, 8); } if(failcode != 0) { assert(state == FORWARD_FAILED || state == FORWARD_LOCAL_FAILED); - sqlite3_bind_int(stmt, 10, (int)failcode); + db_bind_int(stmt, 9, (int)failcode); } else { - sqlite3_bind_null(stmt, 10); + db_bind_null(stmt, 9); } - db_exec_prepared(w->db, stmt); + db_exec_prepared_v2(take(stmt)); notify_forward_event(w->ld, in, out, state, failcode, resolved_time); } struct amount_msat wallet_total_forward_fees(struct wallet *w) { - sqlite3_stmt *stmt; + struct db_stmt *stmt; struct amount_msat total; bool res; - stmt = db_select_prepare(w->db, "SELECT" + stmt = db_prepare_v2(w->db, SQL("SELECT" " SUM(in_msatoshi - out_msatoshi) " "FROM forwarded_payments " - "WHERE state = ?;"); - - sqlite3_bind_int(stmt, 1, wallet_forward_status_in_db(FORWARD_SETTLED)); + "WHERE state = ?;")); + db_bind_int(stmt, 0, wallet_forward_status_in_db(FORWARD_SETTLED)); + db_query_prepared(stmt); - res = db_select_step(w->db, stmt); + res = db_step(stmt); assert(res); - total = sqlite3_column_amount_msat(stmt, 0); - db_stmt_done(stmt); + db_column_amount_msat(stmt, 0, &total); + tal_free(stmt); return total; } @@ -2956,29 +3071,31 @@ const struct forwarding *wallet_forwarded_payments_get(struct wallet *w, { struct forwarding *results = tal_arr(ctx, struct forwarding, 0); size_t count = 0; - sqlite3_stmt *stmt; - stmt = db_select_prepare( - w->db, "SELECT" - " f.state" - ", in_msatoshi" - ", out_msatoshi" - ", hin.payment_hash as payment_hash" - ", in_channel_scid" - ", out_channel_scid" - ", f.received_time" - ", f.resolved_time" - ", f.failcode " - "FROM forwarded_payments f " - "LEFT JOIN channel_htlcs hin ON (f.in_htlc_id == hin.id)"); - - for (count=0; db_select_step(w->db, stmt); count++) { + struct db_stmt *stmt; + stmt = db_prepare_v2( + w->db, + SQL("SELECT" + " f.state" + ", in_msatoshi" + ", out_msatoshi" + ", hin.payment_hash as payment_hash" + ", in_channel_scid" + ", out_channel_scid" + ", f.received_time" + ", f.resolved_time" + ", f.failcode " + "FROM forwarded_payments f " + "LEFT JOIN channel_htlcs hin ON (f.in_htlc_id == hin.id)")); + db_query_prepared(stmt); + + for (count=0; db_step(stmt); count++) { tal_resize(&results, count+1); struct forwarding *cur = &results[count]; - cur->status = sqlite3_column_int(stmt, 0); - cur->msat_in = sqlite3_column_amount_msat(stmt, 1); + cur->status = db_column_int(stmt, 0); + db_column_amount_msat(stmt, 1, &cur->msat_in); - if (sqlite3_column_type(stmt, 2) != SQLITE_NULL) { - cur->msat_out = sqlite3_column_amount_msat(stmt, 2); + if (!db_column_is_null(stmt, 2)) { + db_column_amount_msat(stmt, 2, &cur->msat_out); if (!amount_msat_sub(&cur->fee, cur->msat_in, cur->msat_out)) { log_broken(w->log, "Forwarded in %s less than out %s!", type_to_string(tmpctx, struct amount_msat, @@ -2996,40 +3113,40 @@ const struct forwarding *wallet_forwarded_payments_get(struct wallet *w, cur->fee = AMOUNT_MSAT(0); } - if (sqlite3_column_type(stmt, 3) != SQLITE_NULL) { + if (!db_column_is_null(stmt, 3)) { cur->payment_hash = tal(ctx, struct sha256); - sqlite3_column_sha256(stmt, 3, cur->payment_hash); + db_column_sha256(stmt, 3, cur->payment_hash); } else { cur->payment_hash = NULL; } - cur->channel_in.u64 = sqlite3_column_int64(stmt, 4); + cur->channel_in.u64 = db_column_u64(stmt, 4); - if (sqlite3_column_type(stmt, 5) != SQLITE_NULL) { - cur->channel_out.u64 = sqlite3_column_int64(stmt, 5); + if (!db_column_is_null(stmt, 5)) { + cur->channel_out.u64 = db_column_u64(stmt, 5); } else { assert(cur->status == FORWARD_LOCAL_FAILED); cur->channel_out.u64 = 0; } - cur->received_time = sqlite3_column_timeabs(stmt, 6); + cur->received_time = db_column_timeabs(stmt, 6); - if (sqlite3_column_type(stmt, 7) != SQLITE_NULL) { + if (!db_column_is_null(stmt, 7)) { cur->resolved_time = tal(ctx, struct timeabs); - *cur->resolved_time = sqlite3_column_timeabs(stmt, 7); + *cur->resolved_time = db_column_timeabs(stmt, 7); } else { cur->resolved_time = NULL; } - if (sqlite3_column_type(stmt, 8) != SQLITE_NULL) { + if (!db_column_is_null(stmt, 8)) { assert(cur->status == FORWARD_FAILED || cur->status == FORWARD_LOCAL_FAILED); - cur->failcode = sqlite3_column_int(stmt, 8); + cur->failcode = db_column_int(stmt, 8); } else { cur->failcode = 0; } } - + tal_free(stmt); return results; } @@ -3110,24 +3227,27 @@ void wallet_clean_utxos(struct wallet *w, struct bitcoind *bitcoind) struct wallet_transaction *wallet_transactions_get(struct wallet *w, const tal_t *ctx) { - sqlite3_stmt *stmt; + struct db_stmt *stmt; size_t count; struct wallet_transaction *cur, *txs = tal_arr(ctx, struct wallet_transaction, 0); - stmt = db_select_prepare(w->db, - "SELECT id, id, rawtx, blockheight, txindex, type, channel_id " - "FROM transactions"); - for (count = 0; db_select_step(w->db, stmt); count++) { + stmt = db_prepare_v2( + w->db, + SQL("SELECT id, id, rawtx, blockheight, txindex, type, channel_id " + "FROM transactions")); + db_query_prepared(stmt); + + for (count = 0; db_step(stmt); count++) { tal_resize(&txs, count + 1); cur = &txs[count]; - sqlite3_column_sha256_double(stmt, 1, &cur->id.shad); - cur->rawtx = tal_dup_arr(txs, u8, sqlite3_column_blob(stmt, 2), - sqlite3_column_bytes(stmt, 2), 0); - cur->blockheight = sqlite3_column_int(stmt, 3); - cur->txindex = sqlite3_column_int(stmt, 4); - cur->type = sqlite3_column_int(stmt, 5); - cur->channel_id = sqlite3_column_int(stmt, 6); - } - + db_column_txid(stmt, 1, &cur->id); + cur->rawtx = tal_dup_arr(txs, u8, db_column_blob(stmt, 2), + db_column_bytes(stmt, 2), 0); + cur->blockheight = db_column_int(stmt, 3); + cur->txindex = db_column_int(stmt, 4); + cur->type = db_column_int(stmt, 5); + cur->channel_id = db_column_int(stmt, 6); + } + tal_free(stmt); return txs; } diff --git a/wallet/wallet.h b/wallet/wallet.h index 4c67cfb69..3437b4633 100644 --- a/wallet/wallet.h +++ b/wallet/wallet.h @@ -300,7 +300,7 @@ struct wallet_transaction { }; /** - * wallet_new - Constructor for a new sqlite3 based wallet + * wallet_new - Constructor for a new DB based wallet * * This is guaranteed to either return a valid wallet, or abort with * `fatal` if it cannot be initialized.