bkpr: separate the invoice_fees from the invoice paid

For income events, break out the amount paid in routing fees vs the
total amount of the *invoice* that is paid.

Also printout these fees, when available, on listaccountevents
This commit is contained in:
niftynei 2022-07-19 17:04:38 +09:30 committed by Rusty Russell
parent aa7ffb78bd
commit e7ed196f87
5 changed files with 48 additions and 2 deletions

View file

@ -7,6 +7,7 @@
static const char *tags[] = {
"journal_entry",
"penalty_adj",
"invoice_fee",
};
const char *account_entry_tag_str(enum account_entry_tag tag)

View file

@ -2,10 +2,11 @@
#define LIGHTNING_PLUGINS_BKPR_ACCOUNT_ENTRY_H
#include "config.h"
#define NUM_ACCOUNT_ENTRY_TAGS (JOURNAL_ENTRY + 1)
#define NUM_ACCOUNT_ENTRY_TAGS (INVOICEFEE + 1)
enum account_entry_tag {
JOURNAL_ENTRY = 0,
PENALTY_ADJ = 1,
INVOICEFEE = 2,
};
/* Convert an enum into a string */

View file

@ -39,6 +39,8 @@ void json_add_channel_event(struct json_stream *out,
json_add_string(out, "tag", ev->tag);
json_add_amount_msat_only(out, "credit", ev->credit);
json_add_amount_msat_only(out, "debit", ev->debit);
if (!amount_msat_zero(ev->fees))
json_add_amount_msat_only(out, "fees", ev->fees);
json_add_string(out, "currency", ev->currency);
if (ev->payment_id)
json_add_sha256(out, "payment_id", ev->payment_id);

View file

@ -190,6 +190,16 @@ static struct income_event *maybe_chain_income(const tal_t *ctx,
return NULL;
}
static struct income_event *paid_invoice_fee(const tal_t *ctx,
struct channel_event *ev)
{
struct income_event *iev;
iev = channel_to_income(ctx, ev, AMOUNT_MSAT(0), ev->fees);
iev->tag = tal_free(ev->tag);
iev->tag = (char *)account_entry_tag_str(INVOICEFEE);
return iev;
}
static struct income_event *maybe_channel_income(const tal_t *ctx,
struct channel_event *ev)
{
@ -203,7 +213,17 @@ static struct income_event *maybe_channel_income(const tal_t *ctx,
}
if (streq(ev->tag, "invoice")) {
/* FIXME: add a sub-category for fees paid */
/* If it's a payment, we note fees separately */
if (!amount_msat_zero(ev->debit)) {
struct amount_msat paid;
bool ok;
ok = amount_msat_sub(&paid, ev->debit, ev->fees);
assert(ok);
return channel_to_income(ctx, ev,
ev->credit,
paid);
}
return channel_to_income(ctx, ev,
ev->credit,
ev->debit);
@ -338,6 +358,13 @@ struct income_event **list_income_events(const tal_t *ctx,
if (ev)
tal_arr_expand(&evs, ev);
/* Breakout fees on sent payments */
if (streq(chan->tag, "invoice")
&& !amount_msat_zero(chan->debit)) {
ev = paid_invoice_fee(evs, chan);
tal_arr_expand(&evs, ev);
}
j++;
continue;
}

View file

@ -1303,6 +1303,21 @@ def test_forward_pad_fees_and_cltv(node_factory, bitcoind):
l1.rpc.waitsendpay(rhash)
assert only_one(l3.rpc.listinvoices('test_forward_pad_fees_and_cltv')['invoices'])['status'] == 'paid'
# Do some checks of the bookkeeper's records
def _income_tagset(node, tagset):
incomes = node.rpc.listincome()['income_events']
return [e for e in incomes if e['tag'] in tagset]
tags = ['invoice', 'invoice_fee']
wait_for(lambda: len(_income_tagset(l1, tags)) == 2)
incomes = _income_tagset(l1, tags)
# the balance on l3 should equal the invoice
bal = only_one(only_one(l3.rpc.listbalances()['accounts'])['balances'])['balance']
assert incomes[0]['tag'] == 'invoice'
assert bal == incomes[0]['debit']
inve = only_one([e for e in l1.rpc.listaccountevents()['events'] if e['tag'] == 'invoice'])
assert Millisatoshi(inve['debit']) == Millisatoshi(incomes[0]['debit']) + Millisatoshi(incomes[1]['debit'])
@pytest.mark.developer("needs DEVELOPER=1 for dev_ignore_htlcs")
def test_forward_stats(node_factory, bitcoind):