coin_mvt: wire up notifications for in-channel htlcs

HTLCs trigger a coin movement only when their final form (state) is
reached. This prevents us from needing to concern ourselves with
retries, as well as being the absolutely most correct in terms of
answering the question 'when has the money irrevocably changed hands'.

All coin movements should pass this bar, for ultimate accounting
correctness
This commit is contained in:
lisa neigut 2020-03-18 18:40:32 -05:00 committed by Rusty Russell
parent 9bb9e69bf3
commit ce8bdfcc45
2 changed files with 41 additions and 0 deletions

View File

@ -7,6 +7,7 @@
#include <ccan/tal/str/str.h>
#include <channeld/gen_channel_wire.h>
#include <common/blinding.h>
#include <common/coin_mvt.h>
#include <common/ecdh.h>
#include <common/json_command.h>
#include <common/jsonrpc_errors.h>
@ -20,6 +21,7 @@
#include <gossipd/gen_gossip_wire.h>
#include <hsmd/gen_hsm_wire.h>
#include <lightningd/chaintopology.h>
#include <lightningd/coin_mvts.h>
#include <lightningd/htlc_end.h>
#include <lightningd/htlc_set.h>
#include <lightningd/json.h>
@ -1453,6 +1455,8 @@ static void remove_htlc_in(struct channel *channel, struct htlc_in *hin)
/* If we fulfilled their HTLC, credit us. */
if (hin->preimage) {
struct amount_msat oldamt = channel->our_msat;
const struct channel_coin_mvt *mvt;
if (!amount_msat_add(&channel->our_msat, channel->our_msat,
hin->msat)) {
channel_internal_error(channel,
@ -1471,6 +1475,15 @@ static void remove_htlc_in(struct channel *channel, struct htlc_in *hin)
if (amount_msat_greater(channel->our_msat,
channel->msat_to_us_max))
channel->msat_to_us_max = channel->our_msat;
/* Coins have definitively moved, log a movement */
mvt = new_channel_coin_mvt(hin, &channel->funding_txid,
channel->funding_outnum,
hin->payment_hash, 0, hin->msat,
hin->we_filled ? INVOICE : ROUTED,
/* FIXME: variable unit ? */
true, BTC);
notify_channel_mvt(channel->peer->ld, mvt);
}
tal_free(hin);
@ -1490,6 +1503,7 @@ static void remove_htlc_out(struct channel *channel, struct htlc_out *hout)
if (!hout->preimage) {
fail_out_htlc(hout, NULL, NULL);
} else {
const struct channel_coin_mvt *mvt;
struct amount_msat oldamt = channel->our_msat;
/* We paid for this HTLC, so deduct balance. */
if (!amount_msat_sub(&channel->our_msat, channel->our_msat,
@ -1510,6 +1524,18 @@ static void remove_htlc_out(struct channel *channel, struct htlc_out *hout)
&channel->our_msat));
if (amount_msat_less(channel->our_msat, channel->msat_to_us_min))
channel->msat_to_us_min = channel->our_msat;
/* Coins have definitively moved, log a movement */
mvt = new_channel_coin_mvt(hout, &channel->funding_txid,
channel->funding_outnum,
hout->payment_hash, hout->partid,
hout->msat,
/* routed payments flow through... */
hout->am_origin ? INVOICE : ROUTED,
/* FIXME: variable unit ? */
false, BTC);
notify_channel_mvt(channel->peer->ld, mvt);
}
tal_free(hout);
@ -2585,4 +2611,5 @@ static const struct json_command listforwards_command = {
"List all forwarded payments and their information", false,
"List all forwarded payments and their information"
};
AUTODATA(json_command, &listforwards_command);

View File

@ -384,6 +384,20 @@ bool json_tok_streq(const char *buffer UNNEEDED, const jsmntok_t *tok UNNEEDED,
void kill_uncommitted_channel(struct uncommitted_channel *uc UNNEEDED,
const char *why UNNEEDED)
{ fprintf(stderr, "kill_uncommitted_channel called!\n"); abort(); }
/* Generated stub for new_channel_coin_mvt */
struct channel_coin_mvt *new_channel_coin_mvt(const tal_t *ctx UNNEEDED,
struct bitcoin_txid *funding_txid UNNEEDED,
u32 funding_outnum UNNEEDED,
struct sha256 payment_hash UNNEEDED,
u32 part_id UNNEEDED,
struct amount_msat amount UNNEEDED,
enum mvt_tag tag UNNEEDED,
bool is_credit UNNEEDED,
enum mvt_unit_type unit UNNEEDED)
{ fprintf(stderr, "new_channel_coin_mvt called!\n"); abort(); }
/* Generated stub for notify_channel_mvt */
void notify_channel_mvt(struct lightningd *ld UNNEEDED, const struct channel_coin_mvt *mvt UNNEEDED)
{ fprintf(stderr, "notify_channel_mvt called!\n"); abort(); }
/* Generated stub for notify_connect */
void notify_connect(struct lightningd *ld UNNEEDED, struct node_id *nodeid UNNEEDED,
struct wireaddr_internal *addr UNNEEDED)