From ec991e3af7ee23988c02131460d61eb2610371aa Mon Sep 17 00:00:00 2001 From: niftynei Date: Mon, 13 Dec 2021 16:44:32 -0600 Subject: [PATCH] balance snap: first pass --- common/coin_mvt.c | 1 - common/coin_mvt.h | 1 + lightningd/chaintopology.c | 4 +++ lightningd/coin_mvts.c | 56 ++++++++++++++++++++++++++++++++++++++ lightningd/coin_mvts.h | 15 ++++++++++ lightningd/notification.c | 38 ++++++++++++++++++++++++++ lightningd/notification.h | 4 +++ 7 files changed, 118 insertions(+), 1 deletion(-) diff --git a/common/coin_mvt.c b/common/coin_mvt.c index 8292991f6..9133c166b 100644 --- a/common/coin_mvt.c +++ b/common/coin_mvt.c @@ -7,7 +7,6 @@ #include #include -#define WALLET "wallet" #define EXTERNAL "external" static const char *mvt_types[] = { "chain_mvt", "channel_mvt" }; diff --git a/common/coin_mvt.h b/common/coin_mvt.h index 026aead82..84fedaff1 100644 --- a/common/coin_mvt.h +++ b/common/coin_mvt.h @@ -7,6 +7,7 @@ #include #define COIN_MVT_VERSION 2 +#define WALLET "wallet" enum mvt_type { CHAIN_MVT = 0, diff --git a/lightningd/chaintopology.c b/lightningd/chaintopology.c index ed0e184d5..9dcdc0124 100644 --- a/lightningd/chaintopology.c +++ b/lightningd/chaintopology.c @@ -629,6 +629,10 @@ static void updates_complete(struct chain_topology *topo) "last_processed_block", topo->tip->height); topo->prev_tip = topo->tip->blkid; + + /* Send out an account balance snapshot */ + /* FIXME: only issue on first updates_complete call */ + send_account_balance_snapshot(topo->ld, topo->tip->height); } /* If bitcoind is synced, we're now synced. */ diff --git a/lightningd/coin_mvts.c b/lightningd/coin_mvts.c index 20c2eccac..529360db1 100644 --- a/lightningd/coin_mvts.c +++ b/lightningd/coin_mvts.c @@ -1,8 +1,12 @@ #include "config.h" +#include #include +#include #include #include #include +#include + void notify_channel_mvt(struct lightningd *ld, const struct channel_coin_mvt *mvt) { @@ -76,3 +80,55 @@ struct channel_coin_mvt *new_channel_mvt_routed_hout(const tal_t *ctx, false, hout->fees); } + +void send_account_balance_snapshot(struct lightningd *ld, u32 blockheight) +{ + struct balance_snapshot *snap = tal(NULL, struct balance_snapshot); + struct account_balance *bal; + struct utxo **utxos; + struct channel *chan; + struct peer *p; + /* Available + reserved utxos are A+, as reserved things have not yet + * been spent */ + enum output_status utxo_states[] = {OUTPUT_STATE_AVAILABLE, + OUTPUT_STATE_RESERVED}; + + snap->blockheight = blockheight; + snap->timestamp = time_now().ts.tv_sec; + snap->node_id = &ld->id; + + /* Add the 'wallet' account balance */ + snap->accts = tal_arr(snap, struct account_balance *, 1); + bal = tal(snap, struct account_balance); + bal->acct_id = WALLET; + bal->bip173_name = chainparams->lightning_hrp; + + for (size_t i = 0; i < ARRAY_SIZE(utxo_states); i++) { + utxos = wallet_get_utxos(NULL, ld->wallet, utxo_states[i]); + for (size_t j = 0; j < tal_count(utxos); j++) { + if (!amount_msat_add_sat(&bal->balance, + bal->balance, utxos[j]->amount)) + fatal("Overflow adding node balance"); + } + tal_free(utxos); + } + snap->accts[0] = bal; + + /* Add channel balances */ + list_for_each(&ld->peers, p, list) { + list_for_each(&p->channels, chan, list) { + if (channel_active(chan)) { + bal = tal(snap, struct account_balance); + bal->bip173_name = chainparams->lightning_hrp; + bal->acct_id = type_to_string(bal, + struct channel_id, + &chan->cid); + bal->balance = chan->our_msat; + tal_arr_expand(&snap->accts, bal); + } + } + } + + notify_balance_snapshot(ld, snap); + tal_free(snap); +} diff --git a/lightningd/coin_mvts.h b/lightningd/coin_mvts.h index 0ebce3d7d..ac70f4096 100644 --- a/lightningd/coin_mvts.h +++ b/lightningd/coin_mvts.h @@ -5,6 +5,20 @@ #include #include +struct account_balance { + const char *acct_id; + const char *bip173_name; + struct amount_msat balance; +}; + +struct balance_snapshot { + struct node_id *node_id; + u32 blockheight; + u32 timestamp; + + struct account_balance **accts; +}; + void notify_channel_mvt(struct lightningd *ld, const struct channel_coin_mvt *mvt); void notify_chain_mvt(struct lightningd *ld, const struct chain_coin_mvt *mvt); @@ -21,4 +35,5 @@ struct channel_coin_mvt *new_channel_mvt_routed_hout(const tal_t *ctx, struct htlc_out *hout, struct channel *channel); +void send_account_balance_snapshot(struct lightningd *ld, u32 blockheight); #endif /* LIGHTNING_LIGHTNINGD_COIN_MVTS_H */ diff --git a/lightningd/notification.c b/lightningd/notification.c index 239fbfabf..8161aa83f 100644 --- a/lightningd/notification.c +++ b/lightningd/notification.c @@ -2,6 +2,7 @@ #include #include #include +#include #include static struct notification *find_notification_by_topic(const char* topic) @@ -513,6 +514,43 @@ void notify_coin_mvt(struct lightningd *ld, plugins_notify(ld->plugins, take(n)); } +static void balance_snapshot_notification_serialize(struct json_stream *stream, struct balance_snapshot *snap) +{ + json_object_start(stream, "balance_snapshot"); + json_add_node_id(stream, "node_id", snap->node_id); + json_add_u32(stream, "blockheight", snap->blockheight); + json_add_u32(stream, "timestamp", snap->timestamp); + + json_array_start(stream, "accounts"); + for (size_t i = 0; i < tal_count(snap->accts); i++) { + json_object_start(stream, NULL); + json_add_string(stream, "account_id", + snap->accts[i]->acct_id); + json_add_amount_msat_only(stream, "balance", + snap->accts[i]->balance); + json_add_string(stream, "coin_type", snap->accts[i]->bip173_name); + json_object_end(stream); + } + json_array_end(stream); + json_object_end(stream); +} + +REGISTER_NOTIFICATION(balance_snapshot, + balance_snapshot_notification_serialize); + +void notify_balance_snapshot(struct lightningd *ld, + const struct balance_snapshot *snap) +{ + void (*serialize)(struct json_stream *, + const struct balance_snapshot *) = balance_snapshot_notification_gen.serialize; + + struct jsonrpc_notification *n = + jsonrpc_notification_start(NULL, "balance_snapshot"); + serialize(n->stream, snap); + jsonrpc_notification_end(n); + plugins_notify(ld->plugins, take(n)); +} + static void openchannel_peer_sigs_serialize(struct json_stream *stream, const struct channel_id *cid, const struct wally_psbt *psbt) diff --git a/lightningd/notification.h b/lightningd/notification.h index 931357276..87234ca2d 100644 --- a/lightningd/notification.h +++ b/lightningd/notification.h @@ -5,6 +5,7 @@ #include #include +struct balance_snapshot; struct onionreply; struct wally_psbt; @@ -81,6 +82,9 @@ void notify_sendpay_failure(struct lightningd *ld, void notify_coin_mvt(struct lightningd *ld, const struct coin_mvt *mvt); +void notify_balance_snapshot(struct lightningd *ld, + const struct balance_snapshot *snap); + void notify_openchannel_peer_sigs(struct lightningd *ld, const struct channel_id *cid, const struct wally_psbt *psbt);