diff --git a/lightningd/channel.c b/lightningd/channel.c index af5dae06e..1ea3693cd 100644 --- a/lightningd/channel.c +++ b/lightningd/channel.c @@ -310,6 +310,8 @@ struct channel *new_unsaved_channel(struct peer *peer, channel->ignore_fee_limits = ld->config.ignore_fee_limits; channel->last_stable_connection = 0; channel->stable_conn_timer = NULL; + /* Nothing happened yet */ + memset(&channel->stats, 0, sizeof(channel->stats)); /* No shachain yet */ channel->their_shachain.id = 0; @@ -445,7 +447,8 @@ struct channel *new_channel(struct peer *peer, u64 dbid, bool ignore_fee_limits, /* NULL or stolen */ struct peer_update *peer_update STEALS, - u64 last_stable_connection) + u64 last_stable_connection, + const struct channel_stats *stats) { struct channel *channel = tal(peer->ld, struct channel); struct amount_msat htlc_min, htlc_max; @@ -602,6 +605,7 @@ struct channel *new_channel(struct peer *peer, u64 dbid, channel->ignore_fee_limits = ignore_fee_limits; channel->last_stable_connection = last_stable_connection; channel->stable_conn_timer = NULL; + channel->stats = *stats; /* Populate channel->channel_gossip */ channel_gossip_init(channel, take(peer_update)); diff --git a/lightningd/channel.h b/lightningd/channel.h index b04e68d84..cdb6cc15f 100644 --- a/lightningd/channel.h +++ b/lightningd/channel.h @@ -314,6 +314,9 @@ struct channel { /* Last time we had a stable connection, if any (0 = none) */ u64 last_stable_connection; struct oneshot *stable_conn_timer; + + /* Our stats */ + struct channel_stats stats; }; /* Is channel owned (and should be talking to peer) */ @@ -395,7 +398,8 @@ struct channel *new_channel(struct peer *peer, u64 dbid, bool ignore_fee_limits, /* NULL or stolen */ struct peer_update *peer_update STEALS, - u64 last_stable_connection); + u64 last_stable_connection, + const struct channel_stats *stats); /* new_inflight - Create a new channel_inflight for a channel */ struct channel_inflight *new_inflight(struct channel *channel, diff --git a/lightningd/opening_control.c b/lightningd/opening_control.c index a1066eb16..197316615 100644 --- a/lightningd/opening_control.c +++ b/lightningd/opening_control.c @@ -109,6 +109,10 @@ wallet_commit_channel(struct lightningd *ld, u32 lease_start_blockheight = 0; /* No leases on v1 */ struct timeabs timestamp; bool any_active = peer_any_channel(uc->peer, channel_state_wants_peercomms, NULL); + struct channel_stats zero_channel_stats; + + /* We can't have any payments yet */ + memset(&zero_channel_stats, 0, sizeof(zero_channel_stats)); /* We cannot both be the fundee *and* have a `fundchannel_start` * command running! @@ -215,7 +219,8 @@ wallet_commit_channel(struct lightningd *ld, ld->config.htlc_maximum_msat, ld->config.ignore_fee_limits, NULL, - 0); + 0, + &zero_channel_stats); /* Now we finally put it in the database. */ wallet_channel_insert(ld->wallet, channel); @@ -1456,6 +1461,7 @@ static struct channel *stub_chan(struct command *cmd, struct short_channel_id *scid; u32 blockht; u32 feerate; + struct channel_stats zero_channel_stats; u8 *dummy_sig = tal_hexdata(cmd, "30450221009b2e0eef267b94c3899fb0dc73750" "12e2cee4c10348a068fe78d1b82b4b1403602207" @@ -1530,6 +1536,8 @@ static struct channel *stub_chan(struct command *cmd, if (!mk_short_channel_id(scid, 1, 1, 1)) fatal("Failed to make short channel 1x1x1!"); + memset(&zero_channel_stats, 0, sizeof(zero_channel_stats)); + /* Channel Shell with Dummy data(mostly) */ channel = new_channel(peer, id, NULL, /* No shachain yet */ @@ -1589,7 +1597,8 @@ static struct channel *stub_chan(struct command *cmd, ld->config.htlc_maximum_msat, false, NULL, - 0); + 0, + &zero_channel_stats); /* We don't want to gossip about this, ever. */ channel->channel_gossip = tal_free(channel->channel_gossip); diff --git a/lightningd/peer_htlcs.c b/lightningd/peer_htlcs.c index 97bb11b03..a9af74260 100644 --- a/lightningd/peer_htlcs.c +++ b/lightningd/peer_htlcs.c @@ -93,6 +93,48 @@ static bool htlc_out_update_state(struct channel *channel, return true; } +static void cstat_accumulate(struct channel *c, + struct amount_msat *val, + struct amount_msat msat) +{ + if (!amount_msat_add(val, *val, msat)) + log_broken(c->log, "Adding %s to stat %s overflowed!", + fmt_amount_msat(tmpctx, *val), + fmt_amount_msat(tmpctx, msat)); +} + +static void channel_stats_incr_in_fulfilled(struct channel *c, + struct amount_msat msat) +{ + c->stats.in_payments_fulfilled++; + cstat_accumulate(c, &c->stats.in_msatoshi_fulfilled, msat); + wallet_channel_stats_incr_in_fulfilled(c->peer->ld->wallet, c->dbid, msat); +} + +static void channel_stats_incr_out_fulfilled(struct channel *c, + struct amount_msat msat) +{ + c->stats.out_payments_fulfilled++; + cstat_accumulate(c, &c->stats.out_msatoshi_fulfilled, msat); + wallet_channel_stats_incr_out_fulfilled(c->peer->ld->wallet, c->dbid, msat); +} + +static void channel_stats_incr_in_offered(struct channel *c, + struct amount_msat msat) +{ + c->stats.in_payments_offered++; + cstat_accumulate(c, &c->stats.in_msatoshi_offered, msat); + wallet_channel_stats_incr_in_offered(c->peer->ld->wallet, c->dbid, msat); +} + +static void channel_stats_incr_out_offered(struct channel *c, + struct amount_msat msat) +{ + c->stats.out_payments_offered++; + cstat_accumulate(c, &c->stats.out_msatoshi_offered, msat); + wallet_channel_stats_incr_out_offered(c->peer->ld->wallet, c->dbid, msat); +} + /* BOLT #4: * - if `blinding_point` is set in the incoming `update_add_htlc`: * - MUST return an `invalid_onion_blinding` error. @@ -332,7 +374,6 @@ void fulfill_htlc(struct htlc_in *hin, const struct preimage *preimage) { u8 *msg; struct channel *channel = hin->key.channel; - struct wallet *wallet = channel->peer->ld->wallet; if (hin->hstate != RCVD_ADD_ACK_REVOCATION) { log_debug(channel->log, @@ -349,9 +390,7 @@ void fulfill_htlc(struct htlc_in *hin, const struct preimage *preimage) htlc_in_check(hin, __func__); /* Update channel stats */ - wallet_channel_stats_incr_in_fulfilled(wallet, - channel->dbid, - hin->msat); + channel_stats_incr_in_fulfilled(channel, hin->msat); /* No owner? We'll either send to channeld in peer_htlcs, or * onchaind in onchaind_tell_fulfill. */ @@ -1417,9 +1456,7 @@ static void fulfill_our_htlc_out(struct channel *channel, struct htlc_out *hout, 0, hout->failonion, hout->failmsg, &we_filled); /* Update channel stats */ - wallet_channel_stats_incr_out_fulfilled(ld->wallet, - channel->dbid, - hout->msat); + channel_stats_incr_out_fulfilled(channel, hout->msat); if (hout->am_origin) payment_succeeded(ld, &hout->payment_hash, hout->partid, hout->groupid, preimage); @@ -1892,9 +1929,7 @@ static bool update_out_htlc(struct channel *channel, if (!hout->dbid) { wallet_htlc_save_out(ld->wallet, channel, hout); /* Update channel stats */ - wallet_channel_stats_incr_out_offered(ld->wallet, - channel->dbid, - hout->msat); + channel_stats_incr_out_offered(channel, hout->msat); if (hout->in) { struct short_channel_id scid; @@ -2131,8 +2166,7 @@ static bool channel_added_their_htlc(struct channel *channel, /* Save an incoming htlc to the wallet */ wallet_htlc_save_in(ld->wallet, channel, hin); /* Update channel stats */ - wallet_channel_stats_incr_in_offered(ld->wallet, channel->dbid, - added->amount); + channel_stats_incr_in_offered(channel, added->amount); log_debug(channel->log, "Adding their HTLC %"PRIu64, added->id); connect_htlc_in(channel->peer->ld->htlcs_in, hin); diff --git a/wallet/test/run-db.c b/wallet/test/run-db.c index fc73479c2..4af4988e7 100644 --- a/wallet/test/run-db.c +++ b/wallet/test/run-db.c @@ -191,7 +191,8 @@ struct channel *new_channel(struct peer *peer UNNEEDED, u64 dbid UNNEEDED, bool ignore_fee_limits UNNEEDED, /* NULL or stolen */ struct peer_update *peer_update STEALS UNNEEDED, - u64 last_stable_connection UNNEEDED) + u64 last_stable_connection UNNEEDED, + const struct channel_stats *stats UNNEEDED) { fprintf(stderr, "new_channel called!\n"); abort(); } /* Generated stub for new_coin_wallet_deposit */ struct chain_coin_mvt *new_coin_wallet_deposit(const tal_t *ctx UNNEEDED, diff --git a/wallet/test/run-wallet.c b/wallet/test/run-wallet.c index b6f0791a9..68c961fc3 100644 --- a/wallet/test/run-wallet.c +++ b/wallet/test/run-wallet.c @@ -1918,6 +1918,7 @@ static bool test_channel_inflight_crud(struct lightningd *ld, const tal_t *ctx) secp256k1_ecdsa_signature *lease_commit_sig; u32 feerate, lease_blockheight_start; u64 dbid; + struct channel_stats *stats = talz(w, struct channel_stats); pubkey_from_der(tal_hexdata(w, "02a1633cafcc01ebfb6d78e39f687a1f0995c62fc95f51ead10a02ee0be551b5dc", 66), 33, &pk); node_id_from_pubkey(&id, &pk); @@ -1995,7 +1996,8 @@ static bool test_channel_inflight_crud(struct lightningd *ld, const tal_t *ctx) AMOUNT_MSAT(-1ULL), false, NULL, - 0); + 0, + stats); db_begin_transaction(w->db); CHECK(!wallet_err); wallet_channel_insert(w, chan); diff --git a/wallet/wallet.c b/wallet/wallet.c index 6d0ee76a9..831ae4880 100644 --- a/wallet/wallet.c +++ b/wallet/wallet.c @@ -1536,6 +1536,7 @@ static struct channel *wallet_stmt2channel(struct wallet *w, struct db_stmt *stm u16 lease_chan_max_ppt; bool ignore_fee_limits; struct peer_update *remote_update; + struct channel_stats stats; peer_dbid = db_col_u64(stmt, "peer_id"); peer = find_peer_by_dbid(w->ld, peer_dbid); @@ -1718,6 +1719,8 @@ static struct channel *wallet_stmt2channel(struct wallet *w, struct db_stmt *stm db_col_ignore(stmt, "remote_htlc_maximum_msat"); } + wallet_channel_stats_load(w, db_col_u64(stmt, "id"), &stats); + chan = new_channel(peer, db_col_u64(stmt, "id"), &wshachain, channel_state_in_db(db_col_int(stmt, "state")), @@ -1779,7 +1782,8 @@ static struct channel *wallet_stmt2channel(struct wallet *w, struct db_stmt *stm htlc_maximum_msat, ignore_fee_limits, remote_update, - db_col_u64(stmt, "last_stable_connection")); + db_col_u64(stmt, "last_stable_connection"), + &stats); if (!wallet_channel_load_inflights(w, chan)) { tal_free(chan);