Skip to content

Commit 648bba9

Browse files
committed
lightningd: db infrastructure for network events.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
1 parent bbf8529 commit 648bba9

File tree

5 files changed

+231
-0
lines changed

5 files changed

+231
-0
lines changed

lightningd/wait.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ const char *wait_subsystem_name(enum wait_subsystem subsystem);
4646
* Increase index, write to db, wake any waiters, give them any name/value pairs.
4747
* If the value is NULL, omit that name.
4848
* If the name starts with '=', the value is a JSON literal (and skip over the =)
49+
* If the value is "", use the resulting index value.
4950
*
5051
* Returns the updated index value (always > 0).
5152
*/

wallet/db.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1093,6 +1093,15 @@ static struct migration dbmigrations[] = {
10931093
/* We do a lookup before each append, to avoid duplicates */
10941094
{SQL("CREATE INDEX chain_moves_utxo_idx ON chain_moves (utxo)"), NULL},
10951095
{NULL, migrate_from_account_db},
1096+
{SQL("CREATE TABLE network_events ("
1097+
" id BIGSERIAL,"
1098+
" peer_id BLOB NOT NULL,"
1099+
" type INTEGER NOT NULL,"
1100+
" timestamp BIGINT,"
1101+
" reason TEXT,"
1102+
" duration_nsec BIGINT,"
1103+
" PRIMARY KEY (id)"
1104+
")"), NULL},
10961105
};
10971106

10981107
/**

wallet/test/run-db.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -430,6 +430,13 @@ u8 *towire_temporary_node_failure(const tal_t *ctx UNNEEDED)
430430
/* Generated stub for txfilter_add_scriptpubkey */
431431
void txfilter_add_scriptpubkey(struct txfilter *filter UNNEEDED, const u8 *script TAKES UNNEEDED)
432432
{ fprintf(stderr, "txfilter_add_scriptpubkey called!\n"); abort(); }
433+
/* Generated stub for wait_index_increment */
434+
u64 wait_index_increment(struct lightningd *ld UNNEEDED,
435+
struct db *db UNNEEDED,
436+
enum wait_subsystem subsystem UNNEEDED,
437+
enum wait_index index UNNEEDED,
438+
...)
439+
{ fprintf(stderr, "wait_index_increment called!\n"); abort(); }
433440
/* Generated stub for wait_index_name */
434441
const char *wait_index_name(enum wait_index index UNNEEDED)
435442
{ fprintf(stderr, "wait_index_name called!\n"); abort(); }

wallet/wallet.c

Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7408,6 +7408,148 @@ struct db_stmt *wallet_channel_moves_next(struct wallet *wallet, struct db_stmt
74087408
return stmt;
74097409
}
74107410

7411+
struct db_stmt *wallet_network_events_first(struct wallet *w,
7412+
const struct node_id *specific_id,
7413+
u64 liststart,
7414+
u32 *listlimit)
7415+
{
7416+
struct db_stmt *stmt;
7417+
7418+
if (specific_id) {
7419+
stmt = db_prepare_v2(w->db,
7420+
SQL("SELECT"
7421+
" id"
7422+
", peer_id"
7423+
", type"
7424+
", reason"
7425+
", timestamp"
7426+
", duration_nsec"
7427+
" FROM network_events"
7428+
" WHERE peer_id = ? AND id >= ?"
7429+
" ORDER BY id"
7430+
" LIMIT ?;"));
7431+
db_bind_node_id(stmt, specific_id);
7432+
} else {
7433+
stmt = db_prepare_v2(w->db,
7434+
SQL("SELECT"
7435+
" id"
7436+
", peer_id"
7437+
", type"
7438+
", reason"
7439+
", timestamp"
7440+
", duration_nsec"
7441+
" FROM network_events"
7442+
" WHERE id >= ?"
7443+
" ORDER BY id"
7444+
" LIMIT ?;"));
7445+
}
7446+
db_bind_u64(stmt, liststart);
7447+
if (listlimit)
7448+
db_bind_int(stmt, *listlimit);
7449+
else
7450+
db_bind_int(stmt, INT_MAX);
7451+
db_query_prepared(stmt);
7452+
return wallet_channel_moves_next(w, stmt);
7453+
}
7454+
7455+
const char *network_event_name(enum network_event n)
7456+
{
7457+
switch (n) {
7458+
case NETWORK_EVENT_CONNECT:
7459+
return "connect";
7460+
case NETWORK_EVENT_CONNECTFAIL:
7461+
return "connect_fail";
7462+
case NETWORK_EVENT_PING:
7463+
return "ping";
7464+
case NETWORK_EVENT_DISCONNECT:
7465+
return "disconnect";
7466+
}
7467+
fatal("%s: %u is invalid", __func__, n);
7468+
}
7469+
7470+
struct db_stmt *wallet_network_events_next(struct wallet *w,
7471+
struct db_stmt *stmt)
7472+
{
7473+
if (!db_step(stmt))
7474+
return tal_free(stmt);
7475+
7476+
return stmt;
7477+
}
7478+
7479+
void wallet_network_events_extract(const tal_t *ctx,
7480+
struct db_stmt *stmt,
7481+
u64 *id,
7482+
struct node_id *peer_id,
7483+
u64 *timestamp,
7484+
enum network_event *etype,
7485+
const char **reason,
7486+
u64 *duration_nsec)
7487+
{
7488+
*id = db_col_u64(stmt, "id");
7489+
db_col_node_id(stmt, "peer_id", peer_id);
7490+
*etype = network_event_in_db(db_col_int(stmt, "type"));
7491+
*timestamp = db_col_u64(stmt, "timestamp");
7492+
*reason = db_col_strdup_optional(ctx, stmt, "reason");
7493+
*duration_nsec = db_col_u64(stmt, "duration_nsec");
7494+
}
7495+
7496+
static u64 network_event_index_inc(struct lightningd *ld,
7497+
/* NULL means it's being created */
7498+
const u64 *created_index,
7499+
const enum network_event *etype,
7500+
const struct node_id *peer_id,
7501+
enum wait_index idx)
7502+
{
7503+
return wait_index_increment(ld, ld->wallet->db,
7504+
WAIT_SUBSYSTEM_NETWORKEVENTS, idx,
7505+
/* "" is a magic value meaning 'current val' */
7506+
"=created_index", created_index ? tal_fmt(tmpctx, "%"PRIu64, *created_index) : "",
7507+
"type", etype ? network_event_name(*etype) : NULL,
7508+
"peer_id", peer_id ? fmt_node_id(tmpctx, peer_id) : NULL,
7509+
NULL);
7510+
}
7511+
7512+
static u64 network_event_index_created(struct lightningd *ld,
7513+
enum network_event etype,
7514+
const struct node_id *peer_id)
7515+
{
7516+
return network_event_index_inc(ld, NULL,
7517+
&etype, peer_id,
7518+
WAIT_INDEX_CREATED);
7519+
}
7520+
7521+
/* Put the next network event into the db */
7522+
void wallet_save_network_event(struct lightningd *ld,
7523+
const struct node_id *peer_id,
7524+
enum network_event etype,
7525+
const char *reason,
7526+
u64 duration_nsec)
7527+
{
7528+
u64 id;
7529+
struct db_stmt *stmt;
7530+
7531+
stmt = db_prepare_v2(ld->wallet->db,
7532+
SQL("INSERT INTO network_events ("
7533+
" id,"
7534+
" peer_id,"
7535+
" type, "
7536+
" timestamp,"
7537+
" reason,"
7538+
" duration_nsec) VALUES "
7539+
"(?, ?, ?, ?, ?, ?);"));
7540+
id = network_event_index_created(ld, etype, peer_id);
7541+
db_bind_u64(stmt, id);
7542+
db_bind_node_id(stmt, peer_id);
7543+
db_bind_int(stmt, network_event_in_db(etype));
7544+
db_bind_u64(stmt, time_now().ts.tv_sec);
7545+
if (reason)
7546+
db_bind_text(stmt, reason);
7547+
else
7548+
db_bind_null(stmt);
7549+
db_bind_u64(stmt, duration_nsec);
7550+
db_exec_prepared_v2(take(stmt));
7551+
}
7552+
74117553
struct missing {
74127554
size_t num_found;
74137555
struct missing_addr *addrs;

wallet/wallet.h

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1866,6 +1866,78 @@ struct issued_address_type *wallet_list_addresses(const tal_t *ctx, struct walle
18661866
u64 liststart, const u32 *listlimit);
18671867

18681868

1869+
enum network_event {
1870+
NETWORK_EVENT_CONNECT = 1,
1871+
NETWORK_EVENT_CONNECTFAIL = 2,
1872+
NETWORK_EVENT_PING = 3,
1873+
NETWORK_EVENT_DISCONNECT = 4,
1874+
};
1875+
1876+
static inline enum network_event network_event_in_db(enum network_event n)
1877+
{
1878+
switch (n) {
1879+
case NETWORK_EVENT_CONNECT:
1880+
BUILD_ASSERT(NETWORK_EVENT_CONNECT == 1);
1881+
return n;
1882+
case NETWORK_EVENT_CONNECTFAIL:
1883+
BUILD_ASSERT(NETWORK_EVENT_CONNECTFAIL == 2);
1884+
return n;
1885+
case NETWORK_EVENT_PING:
1886+
BUILD_ASSERT(NETWORK_EVENT_PING == 3);
1887+
return n;
1888+
case NETWORK_EVENT_DISCONNECT:
1889+
BUILD_ASSERT(NETWORK_EVENT_DISCONNECT == 4);
1890+
return n;
1891+
}
1892+
fatal("%s: %u is invalid", __func__, n);
1893+
}
1894+
1895+
const char *network_event_name(enum network_event n);
1896+
1897+
/**
1898+
* Iterate through the network events.
1899+
* @w: the wallet
1900+
* @specific_id: filter by peer_id if non-NULL.
1901+
* @liststart: first index to return (0 == all).
1902+
* @listlimit: limit on number of entries to return (NULL == no limit).
1903+
*
1904+
* Returns pointer to hand as @stmt to wallet_network_events_next(), or NULL.
1905+
* If you choose not to call wallet_network_events_next() you must free it!
1906+
*/
1907+
struct db_stmt *wallet_network_events_first(struct wallet *w,
1908+
const struct node_id *specific_id,
1909+
u64 liststart,
1910+
u32 *listlimit);
1911+
struct db_stmt *wallet_network_events_next(struct wallet *w,
1912+
struct db_stmt *stmt);
1913+
1914+
/**
1915+
* Extract a network event from the db.
1916+
* @ctx: the tal ctx to allocate off
1917+
* @stmt: the db_stmt from wallet_network_events_first/next
1918+
* @id: the creation key
1919+
* @peer_id: the peer we're talking to
1920+
* @timestamp: the time the event was recorded
1921+
* @etype: the network_event type
1922+
* @reason: the optional reason (or set to NULL)
1923+
* @duration_nsec: the time it took (if applicable).
1924+
*/
1925+
void wallet_network_events_extract(const tal_t *ctx,
1926+
struct db_stmt *stmt,
1927+
u64 *id,
1928+
struct node_id *peer_id,
1929+
u64 *timestamp,
1930+
enum network_event *etype,
1931+
const char **reason,
1932+
u64 *duration_nsec);
1933+
1934+
/* Put the next network event into the db */
1935+
void wallet_save_network_event(struct lightningd *ld,
1936+
const struct node_id *peer_id,
1937+
enum network_event etype,
1938+
const char *reason,
1939+
u64 duration_nsec);
1940+
18691941
/**
18701942
* wallet_begin_old_close_rescan: rescan for missing mutual close p2wpkh outputs.
18711943
*

0 commit comments

Comments
 (0)