mirror of
https://github.com/aljazceru/lightning.git
synced 2026-02-03 05:04:21 +01:00
wallet: add buildtime and runtime assertions on db enums.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
committed by
Christian Decker
parent
1dde233a48
commit
7c856470e2
@@ -7,7 +7,6 @@
|
||||
#include <common/wireaddr.h>
|
||||
#include <inttypes.h>
|
||||
#include <lightningd/lightningd.h>
|
||||
#include <lightningd/log.h>
|
||||
#include <lightningd/peer_control.h>
|
||||
#include <lightningd/peer_htlcs.h>
|
||||
#include <onchaind/gen_onchain_wire.h>
|
||||
@@ -83,7 +82,7 @@ bool wallet_add_utxo(struct wallet *w, struct utxo *utxo,
|
||||
sqlite3_bind_blob(stmt, 1, &utxo->txid, sizeof(utxo->txid), SQLITE_TRANSIENT);
|
||||
sqlite3_bind_int(stmt, 2, utxo->outnum);
|
||||
sqlite3_bind_int64(stmt, 3, utxo->amount);
|
||||
sqlite3_bind_int(stmt, 4, type);
|
||||
sqlite3_bind_int(stmt, 4, wallet_output_type_in_db(type));
|
||||
sqlite3_bind_int(stmt, 5, output_state_available);
|
||||
sqlite3_bind_int(stmt, 6, utxo->keyindex);
|
||||
if (utxo->close_info) {
|
||||
@@ -161,14 +160,14 @@ bool wallet_update_output_status(struct wallet *w,
|
||||
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, newstatus);
|
||||
sqlite3_bind_int(stmt, 2, oldstatus);
|
||||
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);
|
||||
} else {
|
||||
stmt = db_prepare(
|
||||
w->db, "UPDATE outputs SET status=? WHERE prev_out_tx=? AND prev_out_index=?");
|
||||
sqlite3_bind_int(stmt, 1, newstatus);
|
||||
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);
|
||||
}
|
||||
@@ -176,18 +175,26 @@ bool wallet_update_output_status(struct wallet *w,
|
||||
return sqlite3_changes(w->db->sql) > 0;
|
||||
}
|
||||
|
||||
#define UTXO_FIELDS \
|
||||
"prev_out_tx, prev_out_index, value, type, status, keyindex, " \
|
||||
"channel_id, peer_id, commitment_point, confirmation_height, " \
|
||||
"spend_height"
|
||||
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;
|
||||
|
||||
sqlite3_stmt *stmt = db_prepare(
|
||||
w->db, "SELECT prev_out_tx, prev_out_index, value, type, status, keyindex, "
|
||||
"channel_id, peer_id, commitment_point, confirmation_height, spend_height "
|
||||
"FROM outputs WHERE status=?1 OR ?1=255");
|
||||
sqlite3_bind_int(stmt, 1, state);
|
||||
if (state == output_state_any)
|
||||
stmt = db_prepare(w->db, "SELECT "UTXO_FIELDS
|
||||
" FROM outputs");
|
||||
else {
|
||||
stmt = db_prepare(w->db, "SELECT "UTXO_FIELDS
|
||||
" FROM outputs WHERE status=?1");
|
||||
sqlite3_bind_int(stmt, 1, output_status_in_db(state));
|
||||
}
|
||||
|
||||
results = tal_arr(ctx, struct utxo*, 0);
|
||||
results = tal_arr(ctx, struct utxo*, 0);
|
||||
for (i=0; sqlite3_step(stmt) == SQLITE_ROW; i++) {
|
||||
tal_resize(&results, i+1);
|
||||
results[i] = tal(results, struct utxo);
|
||||
@@ -1211,6 +1218,7 @@ void wallet_htlc_update(struct wallet *wallet, const u64 htlc_dbid,
|
||||
wallet->db,
|
||||
"UPDATE channel_htlcs SET hstate=?, payment_key=? WHERE id=?");
|
||||
|
||||
/* FIXME: htlc_state_in_db */
|
||||
sqlite3_bind_int(stmt, 1, new_state);
|
||||
sqlite3_bind_int64(stmt, 3, htlc_dbid);
|
||||
|
||||
@@ -1727,7 +1735,7 @@ void wallet_payment_set_status(struct wallet *wallet,
|
||||
"UPDATE payments SET status=? "
|
||||
"WHERE payment_hash=?");
|
||||
|
||||
sqlite3_bind_int(stmt, 1, newstatus);
|
||||
sqlite3_bind_int(stmt, 1, wallet_payment_status_in_db(newstatus));
|
||||
sqlite3_bind_sha256(stmt, 2, payment_hash);
|
||||
db_exec_prepared(wallet->db, stmt);
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include "db.h"
|
||||
#include <bitcoin/chainparams.h>
|
||||
#include <bitcoin/tx.h>
|
||||
#include <ccan/build_assert/build_assert.h>
|
||||
#include <ccan/crypto/shachain/shachain.h>
|
||||
#include <ccan/list/list.h>
|
||||
#include <ccan/tal/tal.h>
|
||||
@@ -13,6 +14,7 @@
|
||||
#include <lightningd/chaintopology.h>
|
||||
#include <lightningd/htlc_end.h>
|
||||
#include <lightningd/invoice.h>
|
||||
#include <lightningd/log.h>
|
||||
#include <onchaind/onchain_wire.h>
|
||||
#include <wally_bip32.h>
|
||||
|
||||
@@ -46,6 +48,8 @@ struct wallet {
|
||||
/* Possible states for tracked outputs in the database. Not sure yet
|
||||
* whether we really want to have reservations reflected in the
|
||||
* database, it would simplify queries at the cost of some IO ops */
|
||||
/* /!\ This is a DB ENUM, please do not change the numbering of any
|
||||
* already defined elements (adding is ok) /!\ */
|
||||
enum output_status {
|
||||
output_state_available= 0,
|
||||
output_state_reserved = 1,
|
||||
@@ -55,10 +59,31 @@ enum output_status {
|
||||
output_state_any = 255
|
||||
};
|
||||
|
||||
static inline enum output_status output_status_in_db(enum output_status s)
|
||||
{
|
||||
switch (s) {
|
||||
case output_state_available:
|
||||
BUILD_ASSERT(output_state_available == 0);
|
||||
return s;
|
||||
case output_state_reserved:
|
||||
BUILD_ASSERT(output_state_reserved == 1);
|
||||
return s;
|
||||
case output_state_spent:
|
||||
BUILD_ASSERT(output_state_spent == 2);
|
||||
return s;
|
||||
/* This one doesn't go into db */
|
||||
case output_state_any:
|
||||
break;
|
||||
}
|
||||
fatal("%s: %u is invalid", __func__, s);
|
||||
}
|
||||
|
||||
/* Enumeration of all known output types. These include all types that
|
||||
* could ever end up on-chain and we may need to react upon. Notice
|
||||
* that `to_local`, `htlc_offer`, and `htlc_recv` may need immediate
|
||||
* action since they are encumbered with a CSV. */
|
||||
/* /!\ This is a DB ENUM, please do not change the numbering of any
|
||||
* already defined elements (adding is ok) /!\ */
|
||||
enum wallet_output_type {
|
||||
p2sh_wpkh = 0,
|
||||
to_local = 1,
|
||||
@@ -68,6 +93,31 @@ enum wallet_output_type {
|
||||
p2wpkh = 6
|
||||
};
|
||||
|
||||
static inline enum wallet_output_type wallet_output_type_in_db(enum wallet_output_type w)
|
||||
{
|
||||
switch (w) {
|
||||
case p2sh_wpkh:
|
||||
BUILD_ASSERT(p2sh_wpkh == 0);
|
||||
return w;
|
||||
case to_local:
|
||||
BUILD_ASSERT(to_local == 1);
|
||||
return w;
|
||||
case htlc_offer:
|
||||
BUILD_ASSERT(htlc_offer == 3);
|
||||
return w;
|
||||
case htlc_recv:
|
||||
BUILD_ASSERT(htlc_recv == 4);
|
||||
return w;
|
||||
case our_change:
|
||||
BUILD_ASSERT(our_change == 5);
|
||||
return w;
|
||||
case p2wpkh:
|
||||
BUILD_ASSERT(p2wpkh == 6);
|
||||
return w;
|
||||
}
|
||||
fatal("%s: %u is invalid", __func__, w);
|
||||
}
|
||||
|
||||
/* A database backed shachain struct. The datastructure is
|
||||
* writethrough, reads are performed from an in-memory version, all
|
||||
* writes are passed through to the DB. */
|
||||
@@ -89,6 +139,22 @@ enum wallet_payment_status {
|
||||
PAYMENT_FAILED = 2
|
||||
};
|
||||
|
||||
static inline enum wallet_payment_status wallet_payment_status_in_db(enum wallet_payment_status w)
|
||||
{
|
||||
switch (w) {
|
||||
case PAYMENT_PENDING:
|
||||
BUILD_ASSERT(PAYMENT_PENDING == 0);
|
||||
return w;
|
||||
case PAYMENT_COMPLETE:
|
||||
BUILD_ASSERT(PAYMENT_COMPLETE == 1);
|
||||
return w;
|
||||
case PAYMENT_FAILED:
|
||||
BUILD_ASSERT(PAYMENT_FAILED == 2);
|
||||
return w;
|
||||
}
|
||||
fatal("%s: %u is invalid", __func__, w);
|
||||
}
|
||||
|
||||
/* Outgoing payments. A simple persisted representation
|
||||
* of a payment we initiated. This can be used by
|
||||
* a UI (alongside invoices) to display the balance history.
|
||||
@@ -424,6 +490,22 @@ enum invoice_status {
|
||||
EXPIRED,
|
||||
};
|
||||
|
||||
static inline enum invoice_status invoice_status_in_db(enum invoice_status s)
|
||||
{
|
||||
switch (s) {
|
||||
case UNPAID:
|
||||
BUILD_ASSERT(UNPAID == 0);
|
||||
return s;
|
||||
case PAID:
|
||||
BUILD_ASSERT(PAID == 1);
|
||||
return s;
|
||||
case EXPIRED:
|
||||
BUILD_ASSERT(EXPIRED == 2);
|
||||
return s;
|
||||
}
|
||||
fatal("%s: %u is invalid", __func__, s);
|
||||
}
|
||||
|
||||
/* The information about an invoice */
|
||||
struct invoice_details {
|
||||
/* Current invoice state */
|
||||
|
||||
Reference in New Issue
Block a user