2018-03-22 11:36:25 +01:00
|
|
|
#ifndef LIGHTNING_WALLET_DB_H
|
|
|
|
#define LIGHTNING_WALLET_DB_H
|
2017-05-12 20:24:18 +02:00
|
|
|
#include "config.h"
|
2018-03-07 01:06:07 +01:00
|
|
|
|
2017-10-30 19:21:41 +01:00
|
|
|
#include <bitcoin/preimage.h>
|
2018-03-07 01:06:07 +01:00
|
|
|
#include <bitcoin/pubkey.h>
|
2017-10-30 19:21:41 +01:00
|
|
|
#include <bitcoin/short_channel_id.h>
|
|
|
|
#include <bitcoin/tx.h>
|
2019-08-28 23:04:05 +02:00
|
|
|
#include <ccan/json_escape/json_escape.h>
|
2019-04-10 17:08:57 +02:00
|
|
|
#include <ccan/time/time.h>
|
2017-05-12 20:24:18 +02:00
|
|
|
|
2020-09-09 09:20:53 +02:00
|
|
|
struct channel_id;
|
2020-07-29 03:20:30 +02:00
|
|
|
struct ext_key;
|
2019-02-24 06:12:09 +01:00
|
|
|
struct lightningd;
|
2018-01-02 05:03:42 +01:00
|
|
|
struct log;
|
common/node_id: new type.
Node ids are pubkeys, but we only use them as pubkeys for routing and checking
gossip messages. So we're packing and unpacking them constantly, and wasting
some space and time.
This introduces a new type, explicitly the SEC1 compressed encoding
(33 bytes). We ensure its validity when we load from the db, or get it
from JSON. We still use 'struct pubkey' for peer messages, which checks
validity.
Results from 5 runs, min-max(mean +/- stddev):
store_load_msec,vsz_kb,store_rewrite_sec,listnodes_sec,listchannels_sec,routing_sec,peer_write_all_sec
39475-39572(39518+/-36),2880732,41.150000-41.390000(41.298+/-0.085),2.260000-2.550000(2.336+/-0.11),44.390000-65.150000(58.648+/-7.5),32.740000-33.020000(32.89+/-0.093),44.130000-45.090000(44.566+/-0.32)
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2019-04-08 08:34:06 +02:00
|
|
|
struct node_id;
|
2020-01-22 07:28:25 +01:00
|
|
|
struct onionreply;
|
2019-07-25 22:45:02 +02:00
|
|
|
struct db_stmt;
|
2019-07-23 20:45:06 +02:00
|
|
|
struct db;
|
2020-05-22 05:18:33 +02:00
|
|
|
struct wally_psbt;
|
2020-09-11 22:33:41 +02:00
|
|
|
struct wally_tx;
|
2017-05-12 20:24:18 +02:00
|
|
|
|
2019-07-17 18:11:19 +02:00
|
|
|
/**
|
|
|
|
* Macro to annotate a named SQL query.
|
|
|
|
*
|
|
|
|
* This macro is used to annotate SQL queries that might need rewriting for
|
|
|
|
* different SQL dialects. It is used both as a marker for the query
|
|
|
|
* extraction logic in devtools/sql-rewrite.py to identify queries, as well as
|
|
|
|
* a way to swap out the query text with it's name so that the query execution
|
|
|
|
* engine can then look up the rewritten query using its name.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
#define NAMED_SQL(name,x) x
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Simple annotation macro that auto-generates names for NAMED_SQL
|
|
|
|
*
|
|
|
|
* If this macro is changed it is likely that the extraction logic in
|
|
|
|
* devtools/sql-rewrite.py needs to change as well, since they need to
|
|
|
|
* generate identical names to work correctly.
|
|
|
|
*/
|
2019-09-05 16:08:54 +02:00
|
|
|
#define SQL(x) NAMED_SQL( __FILE__ ":" stringify(__COUNTER__), x)
|
2019-07-17 18:11:19 +02:00
|
|
|
|
|
|
|
|
2017-05-12 20:24:18 +02:00
|
|
|
/**
|
|
|
|
* db_setup - Open a the lightningd database and update the schema
|
|
|
|
*
|
|
|
|
* Opens the database, creating it if necessary, and applying
|
|
|
|
* migrations until the schema is updated to the current state.
|
2017-11-01 02:21:56 +01:00
|
|
|
* Calls fatal() on error.
|
2017-05-12 20:24:18 +02:00
|
|
|
*
|
|
|
|
* Params:
|
|
|
|
* @ctx: the tal_t context to allocate from
|
2019-03-01 23:18:40 +01:00
|
|
|
* @ld: the lightningd context to hand to upgrade functions.
|
2020-07-29 03:20:30 +02:00
|
|
|
* @bip32_base: the base all of our pubkeys are constructed on
|
2017-05-12 20:24:18 +02:00
|
|
|
*/
|
2020-07-29 03:20:30 +02:00
|
|
|
struct db *db_setup(const tal_t *ctx, struct lightningd *ld,
|
|
|
|
const struct ext_key *bip32_base);
|
2017-05-12 20:24:18 +02:00
|
|
|
|
2017-05-31 15:50:36 +02:00
|
|
|
/**
|
|
|
|
* db_begin_transaction - Begin a transaction
|
|
|
|
*
|
2017-11-01 02:21:56 +01:00
|
|
|
* Begin a new DB transaction. fatal() on database error.
|
2017-05-31 15:50:36 +02:00
|
|
|
*/
|
2017-11-01 02:21:56 +01:00
|
|
|
#define db_begin_transaction(db) \
|
|
|
|
db_begin_transaction_((db), __FILE__ ":" stringify(__LINE__))
|
|
|
|
void db_begin_transaction_(struct db *db, const char *location);
|
2017-05-31 15:50:36 +02:00
|
|
|
|
2019-07-23 20:45:06 +02:00
|
|
|
bool db_in_transaction(struct db *db);
|
|
|
|
|
2017-05-31 15:50:36 +02:00
|
|
|
/**
|
|
|
|
* db_commit_transaction - Commit a running transaction
|
|
|
|
*
|
2017-11-01 02:21:56 +01:00
|
|
|
* Requires that we are currently in a transaction. fatal() if we
|
|
|
|
* fail to commit.
|
2017-05-31 15:50:36 +02:00
|
|
|
*/
|
2017-11-01 02:21:56 +01:00
|
|
|
void db_commit_transaction(struct db *db);
|
2017-05-31 15:50:36 +02:00
|
|
|
|
2017-06-01 16:10:40 +02:00
|
|
|
/**
|
|
|
|
* db_set_intvar - Set an integer variable in the database
|
|
|
|
*
|
|
|
|
* Utility function to store generic integer values in the
|
|
|
|
* database.
|
|
|
|
*/
|
2017-11-01 02:21:56 +01:00
|
|
|
void db_set_intvar(struct db *db, char *varname, s64 val);
|
2017-06-01 16:10:40 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* db_get_intvar - Retrieve an integer variable from the database
|
|
|
|
*
|
|
|
|
* Either returns the value in the database, or @defval if
|
|
|
|
* the query failed or no such variable exists.
|
|
|
|
*/
|
|
|
|
s64 db_get_intvar(struct db *db, char *varname, s64 defval);
|
|
|
|
|
2019-07-25 22:45:02 +02:00
|
|
|
void db_bind_null(struct db_stmt *stmt, int pos);
|
|
|
|
void db_bind_int(struct db_stmt *stmt, int pos, int val);
|
|
|
|
void db_bind_u64(struct db_stmt *stmt, int pos, u64 val);
|
2019-08-15 22:16:19 +02:00
|
|
|
void db_bind_blob(struct db_stmt *stmt, int pos, const u8 *val, size_t len);
|
2019-07-25 22:45:02 +02:00
|
|
|
void db_bind_text(struct db_stmt *stmt, int pos, const char *val);
|
2019-08-15 22:16:19 +02:00
|
|
|
void db_bind_preimage(struct db_stmt *stmt, int pos, const struct preimage *p);
|
|
|
|
void db_bind_sha256(struct db_stmt *stmt, int pos, const struct sha256 *s);
|
|
|
|
void db_bind_sha256d(struct db_stmt *stmt, int pos, const struct sha256_double *s);
|
|
|
|
void db_bind_secret(struct db_stmt *stmt, int pos, const struct secret *s);
|
|
|
|
void db_bind_secret_arr(struct db_stmt *stmt, int col, const struct secret *s);
|
|
|
|
void db_bind_txid(struct db_stmt *stmt, int pos, const struct bitcoin_txid *t);
|
2020-09-09 09:20:53 +02:00
|
|
|
void db_bind_channel_id(struct db_stmt *stmt, int pos, const struct channel_id *id);
|
2019-08-15 22:16:19 +02:00
|
|
|
void db_bind_node_id(struct db_stmt *stmt, int pos, const struct node_id *ni);
|
|
|
|
void db_bind_node_id_arr(struct db_stmt *stmt, int col,
|
|
|
|
const struct node_id *ids);
|
|
|
|
void db_bind_pubkey(struct db_stmt *stmt, int pos, const struct pubkey *p);
|
|
|
|
void db_bind_short_channel_id(struct db_stmt *stmt, int col,
|
|
|
|
const struct short_channel_id *id);
|
|
|
|
void db_bind_short_channel_id_arr(struct db_stmt *stmt, int col,
|
|
|
|
const struct short_channel_id *id);
|
|
|
|
void db_bind_signature(struct db_stmt *stmt, int col,
|
|
|
|
const secp256k1_ecdsa_signature *sig);
|
|
|
|
void db_bind_timeabs(struct db_stmt *stmt, int col, struct timeabs t);
|
2020-08-07 03:30:47 +02:00
|
|
|
void db_bind_tx(struct db_stmt *stmt, int col, const struct wally_tx *tx);
|
2020-05-22 05:18:33 +02:00
|
|
|
void db_bind_psbt(struct db_stmt *stmt, int col, const struct wally_psbt *psbt);
|
2019-08-15 22:16:19 +02:00
|
|
|
void db_bind_amount_msat(struct db_stmt *stmt, int pos,
|
|
|
|
const struct amount_msat *msat);
|
|
|
|
void db_bind_amount_sat(struct db_stmt *stmt, int pos,
|
|
|
|
const struct amount_sat *sat);
|
|
|
|
void db_bind_json_escape(struct db_stmt *stmt, int pos,
|
|
|
|
const struct json_escape *esc);
|
2020-01-22 07:28:25 +01:00
|
|
|
void db_bind_onionreply(struct db_stmt *stmt, int col,
|
|
|
|
const struct onionreply *r);
|
2020-08-25 23:20:52 +02:00
|
|
|
void db_bind_talarr(struct db_stmt *stmt, int col, const u8 *arr);
|
2019-07-25 22:45:02 +02:00
|
|
|
|
2019-08-03 16:34:03 +02:00
|
|
|
bool db_step(struct db_stmt *stmt);
|
2021-11-14 18:54:46 +01:00
|
|
|
|
|
|
|
/* Modern variants: get columns by name from SELECT */
|
|
|
|
/* Bridge function to get column number from SELECT
|
|
|
|
(must exist) */
|
2021-11-14 19:00:46 +01:00
|
|
|
size_t db_query_colnum(const struct db_stmt *stmt, const char *colname);
|
2021-11-14 18:54:46 +01:00
|
|
|
|
|
|
|
u64 db_col_u64(struct db_stmt *stmt, const char *colname);
|
|
|
|
int db_col_int(struct db_stmt *stmt, const char *colname);
|
|
|
|
size_t db_col_bytes(struct db_stmt *stmt, const char *colname);
|
|
|
|
int db_col_is_null(struct db_stmt *stmt, const char *colname);
|
|
|
|
const void* db_col_blob(struct db_stmt *stmt, const char *colname);
|
2021-11-14 18:55:46 +01:00
|
|
|
char *db_col_strdup(const tal_t *ctx,
|
|
|
|
struct db_stmt *stmt,
|
|
|
|
const char *colname);
|
2021-11-14 18:54:46 +01:00
|
|
|
void db_col_preimage(struct db_stmt *stmt, const char *colname, struct preimage *preimage);
|
|
|
|
void db_col_amount_msat(struct db_stmt *stmt, const char *colname, struct amount_msat *msat);
|
|
|
|
void db_col_amount_sat(struct db_stmt *stmt, const char *colname, struct amount_sat *sat);
|
|
|
|
struct json_escape *db_col_json_escape(const tal_t *ctx, struct db_stmt *stmt, const char *colname);
|
|
|
|
void db_col_sha256(struct db_stmt *stmt, const char *colname, struct sha256 *sha);
|
|
|
|
void db_col_sha256d(struct db_stmt *stmt, const char *colname, struct sha256_double *shad);
|
|
|
|
void db_col_secret(struct db_stmt *stmt, const char *colname, struct secret *s);
|
|
|
|
struct secret *db_col_secret_arr(const tal_t *ctx, struct db_stmt *stmt,
|
|
|
|
const char *colname);
|
|
|
|
void db_col_txid(struct db_stmt *stmt, const char *colname, struct bitcoin_txid *t);
|
|
|
|
void db_col_channel_id(struct db_stmt *stmt, const char *colname, struct channel_id *dest);
|
|
|
|
void db_col_node_id(struct db_stmt *stmt, const char *colname, struct node_id *ni);
|
|
|
|
struct node_id *db_col_node_id_arr(const tal_t *ctx, struct db_stmt *stmt,
|
|
|
|
const char *colname);
|
|
|
|
void db_col_pubkey(struct db_stmt *stmt, const char *colname,
|
|
|
|
struct pubkey *p);
|
2021-11-14 18:55:46 +01:00
|
|
|
bool db_col_short_channel_id_str(struct db_stmt *stmt, const char *colname,
|
2021-11-14 18:54:46 +01:00
|
|
|
struct short_channel_id *dest);
|
|
|
|
struct short_channel_id *
|
|
|
|
db_col_short_channel_id_arr(const tal_t *ctx, struct db_stmt *stmt, const char *colname);
|
|
|
|
bool db_col_signature(struct db_stmt *stmt, const char *colname,
|
|
|
|
secp256k1_ecdsa_signature *sig);
|
|
|
|
struct timeabs db_col_timeabs(struct db_stmt *stmt, const char *colname);
|
|
|
|
struct bitcoin_tx *db_col_tx(const tal_t *ctx, struct db_stmt *stmt, const char *colname);
|
|
|
|
struct wally_psbt *db_col_psbt(const tal_t *ctx, struct db_stmt *stmt, const char *colname);
|
|
|
|
struct bitcoin_tx *db_col_psbt_to_tx(const tal_t *ctx, struct db_stmt *stmt, const char *colname);
|
|
|
|
|
|
|
|
struct onionreply *db_col_onionreply(const tal_t *ctx,
|
|
|
|
struct db_stmt *stmt, const char *colname);
|
|
|
|
|
|
|
|
#define db_col_arr(ctx, stmt, colname, type) \
|
|
|
|
((type *)db_col_arr_((ctx), (stmt), (colname), \
|
|
|
|
sizeof(type), TAL_LABEL(type, "[]"), \
|
|
|
|
__func__))
|
|
|
|
void *db_col_arr_(const tal_t *ctx, struct db_stmt *stmt, const char *colname,
|
|
|
|
size_t bytes, const char *label, const char *caller);
|
|
|
|
|
|
|
|
|
|
|
|
/* Some useful default variants */
|
|
|
|
int db_col_int_or_default(struct db_stmt *stmt, const char *colname, int def);
|
|
|
|
void db_col_amount_msat_or_default(struct db_stmt *stmt, const char *colname,
|
|
|
|
struct amount_msat *msat,
|
|
|
|
struct amount_msat def);
|
|
|
|
|
|
|
|
|
2021-11-14 19:00:46 +01:00
|
|
|
/* Explicitly ignore a column (so we don't complain you didn't use it!) */
|
|
|
|
void db_col_ignore(struct db_stmt *stmt, const char *colname);
|
|
|
|
|
2019-08-28 23:04:05 +02:00
|
|
|
/**
|
|
|
|
* db_exec_prepared -- Execute a prepared statement
|
|
|
|
*
|
|
|
|
* After preparing a statement using `db_prepare`, and after binding all
|
|
|
|
* non-null variables using the `db_bind_*` functions, it can be executed with
|
|
|
|
* this function. It is a small, transaction-aware, wrapper around `db_step`,
|
|
|
|
* that calls fatal() if the execution fails. This may take ownership of
|
|
|
|
* `stmt` if annotated with `take()`and will free it before returning.
|
|
|
|
*
|
|
|
|
* If you'd like to issue a query and access the rows returned by the query
|
|
|
|
* please use `db_query_prepared` instead, since this function will not expose
|
|
|
|
* returned results, and the `stmt` can only be used for calls to
|
|
|
|
* `db_count_changes` and `db_last_insert_id` after executing.
|
|
|
|
*
|
|
|
|
* @stmt: The prepared statement to execute
|
|
|
|
*/
|
2019-08-15 22:16:19 +02:00
|
|
|
bool db_exec_prepared_v2(struct db_stmt *stmt TAKES);
|
2019-08-28 23:04:05 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* db_query_prepared -- Execute a prepared query
|
|
|
|
*
|
|
|
|
* After preparing a query using `db_prepare`, and after binding all non-null
|
|
|
|
* variables using the `db_bind_*` functions, it can be executed with this
|
|
|
|
* function. This function must be called before calling `db_step` or any of
|
2021-11-14 18:54:46 +01:00
|
|
|
* the `db_col_*` column access functions.
|
2019-08-28 23:04:05 +02:00
|
|
|
*
|
|
|
|
* If you are not executing a read-only statement, please use
|
|
|
|
* `db_exec_prepared` instead.
|
|
|
|
*
|
|
|
|
* @stmt: The prepared statement to execute
|
|
|
|
*/
|
2019-08-03 16:34:03 +02:00
|
|
|
bool db_query_prepared(struct db_stmt *stmt);
|
2019-08-03 18:13:31 +02:00
|
|
|
size_t db_count_changes(struct db_stmt *stmt);
|
2019-08-20 19:38:09 +02:00
|
|
|
u64 db_last_insert_id_v2(struct db_stmt *stmt);
|
2019-08-28 23:04:05 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* db_prepare -- Prepare a DB query/command
|
|
|
|
*
|
|
|
|
* Create an instance of `struct db_stmt` that encapsulates a SQL query or command.
|
|
|
|
*
|
|
|
|
* @query MUST be wrapped in a `SQL()` macro call, since that allows the
|
|
|
|
* extraction and translation of the query into the target SQL dialect.
|
|
|
|
*
|
|
|
|
* It does not execute the query and does not check its validity, but
|
|
|
|
* allocates the placeholders detected in the query. The placeholders in the
|
|
|
|
* `stmt` can then be bound using the `db_bind_*` functions, and executed
|
|
|
|
* using `db_exec_prepared` for write-only statements and `db_query_prepared`
|
|
|
|
* for read-only statements.
|
|
|
|
*
|
|
|
|
* @db: Database to query/exec
|
|
|
|
* @query: The SQL statement to compile
|
|
|
|
*/
|
2019-07-25 22:45:02 +02:00
|
|
|
struct db_stmt *db_prepare_v2_(const char *location, struct db *db,
|
|
|
|
const char *query_id);
|
2019-08-28 23:04:05 +02:00
|
|
|
|
|
|
|
/* TODO(cdecker) Remove the v2 suffix after finishing the migration */
|
|
|
|
#define db_prepare_v2(db,query) \
|
2019-07-25 22:45:02 +02:00
|
|
|
db_prepare_v2_(__FILE__ ":" stringify(__LINE__), db, query)
|
|
|
|
|
lightningd: shutdown plugins after subdaemons and assert no write access to db
because:
- shutdown_subdaemons can trigger db write, comments in that function say so at least
- resurrecting the main event loop with subdaemons still running is counter productive
in shutting down activity (such as htlc's, hook_calls etc.)
- custom behavior injected by plugins via hooks should be consistent, see test
in previous commmit
IDEA:
in shutdown_plugins, when starting new io_loop:
- A plugin that is still running can return a jsonrpc_request response, this triggers
response_cb, which cannot be handled because subdaemons are gone -> so any response_cb should be blocked/aborted
- jsonrpc is still there, so users (such as plugins) can make new jsonrpc_request's which
cannot be handled because subdaemons are gone -> so new rpc_request should also be blocked
- But we do want to send/receive notifications and log messages (handled in jsonrpc as jsonrpc_notification)
as these do not trigger subdaemon calls or db_write's
Log messages and notifications do not have "id" field, where jsonrpc_request *do* have an "id" field
PLAN (hypothesis):
- hack into plugin_read_json_one OR plugin_response_handle to filter-out json with
an "id" field, this should
block/abandon any jsonrpc_request responses (and new jsonrpc_requests for plugins?)
Q. Can internal (so not via plugin) jsonrpc_requests called in the main io_loop return/revive in
the shutdown io_loop?
A. No. All code under lightningd/ returning command_still_pending depends on either a subdaemon, timer or
plugin. In shutdown loop the subdaemons are dead, timer struct cleared and plugins will be taken
care of (in next commits).
fixup: we can only io_break the main io_loop once
2021-11-10 10:39:02 +01:00
|
|
|
/* Check that plugins are not shutting down when calling db_write hook */
|
|
|
|
void db_check_plugins_not_shutdown(struct db *db);
|
|
|
|
|
2019-12-18 11:06:09 +01:00
|
|
|
/**
|
|
|
|
* Access pending changes that have been added to the current transaction.
|
|
|
|
*/
|
|
|
|
const char **db_changes(struct db *db);
|
|
|
|
|
2019-12-18 19:45:24 +01:00
|
|
|
/* Get the current data version. */
|
|
|
|
u32 db_data_version_get(struct db *db);
|
|
|
|
|
2018-03-22 11:36:25 +01:00
|
|
|
#endif /* LIGHTNING_WALLET_DB_H */
|