Commit Graph

55 Commits

Author SHA1 Message Date
niftynei
c1cef773ca bkpr: make sure there's always at least on difference in blockheights
We can't divide by zero, so make sure it's always 1 (with a small loss
of precision for other cases, ce la vie)
2022-07-28 12:08:18 +09:30
niftynei
0c2b43b6b2 bkpr: add more data to listaccountevents printout 2022-07-28 12:08:18 +09:30
niftynei
d72033882f bkpr: check for channel resolution for any "originated" event
We were failing to mark channels as resolved b/c we weren't using later
events to external (but originated from this account) events as signals
to run the channel resolution check.

This fixes that, and adds a test.
2022-07-28 12:08:18 +09:30
niftynei
cf8b30d2e8 bkpr: print more info in bkpr-listbalances 2022-07-28 12:08:18 +09:30
niftynei
3dcfd2d0e4 bkpr: account name is required for bkpr-inspect 2022-07-28 12:08:18 +09:30
niftynei
563910e667 bkpr: add docs, change names to 'bkpr-*'
Adds schema definitions and manpages for bkpr- commands; also renames
the commands to all start with 'bkpr-', so they're easier to identify/
make runes about.
2022-07-28 12:08:18 +09:30
niftynei
e2ef44c043 bkpr: add 'msat' suffix to all msat denominated fields
Makes our json schema parsing work as expected.
2022-07-28 12:08:18 +09:30
niftynei
2b3ef37590 bkpr: don't use a minus in a sql stmt
Avoid rounding errors in sql by doing it in code.
2022-07-28 12:08:18 +09:30
niftynei
a45da63280 bkpr: pass the node_id over for channel_opens, add to account
it's nice to know what node your channel was opened with. in theory we
could use listpeers to merge the data after the fact, except that
channels disappear after they've been closed for a bit. it's better to
just save the info.

we print it out in `listbalances`, as that's a great place account level
information
2022-07-28 12:08:18 +09:30
niftynei
a3d82d5a01 bkpr: exclude non-wallet events in the balance snapshot
Anchor outputs are ignored by the clightning wallet, but we keep track
of them in the bookkeeper. This causes problems when we do the balance
checks on restart w/ the balance_snapshot -- it results in us printing
out a journal_entry to 'get rid of' the anchors that the clightning node
doesnt know about.

Instead, we mark some outputs as 'ignored' and exclude these from our
account balance sums when we're comparing to the clightning snapshot.
2022-07-28 12:08:18 +09:30
niftynei
fec8186413 bkpr: get rid of crash in listincome
Our consolidate fees had a crash bug (and was pretty convoluted). This
makes it less convoluted and resolves the crash.

The only kinda meh thing is that we have to look up the most recent
timestamp data for the onchain fee entry separately, because of the way
SQL sums work.
2022-07-28 12:08:18 +09:30
niftynei
10e58a3788 nit,bkpr: add a note about what the tag was to this printout
Makes it much easier to debug when something goes wrong!
2022-07-28 12:08:18 +09:30
niftynei
e7ed196f87 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
2022-07-28 12:08:18 +09:30
niftynei
91ebddeb78 bkpr: actually fill in the current blockheight for channelsapy
I had hardcoded something for the tests, but really we want this to be
dynamically fetched from lightningd via `getinfo`.

This does the trick!
2022-07-28 12:08:18 +09:30
niftynei
ee47715a1b bkpr: command to calculate some APYs/stats on channel routing fees
Computes some stats from the net routed fees etc

```
{
   "channel_apys": [
      {
         "account": "7de277250f8003c35378c1eb20aacf8fa6a69dd4bb22077266329a9ad812cd5d",
         "routed_out": "2000msat",
         "routed_in": "125100101msat",
         "lease_fee_paid": "0msat",
         "lease_fee_earned": "670000msat",
         "pushed_out": "0msat",
         "pushed_in": "0msat",
         "our_start_balance": "100670000msat",
         "channel_start_balance": "1100670000msat",
         "fees_out": "0msat",
         "fees_in": "10100101msat",
         "utilization_out": "0.0002%",
         "utilization_out_initial": "0.0020%",
         "utilization_in": "11.3658%",
         "utilization_in_initial": "12.5100%",
         "apy_out": "0.0000%",
         "apy_out_initial": "0.0000%",
         "apy_in": "3203.3924%",
         "apy_in_initial": "3525.8779%",
         "apy_total": "3203.3924%",
         "apy_total_initial": "3203.3924%",
         "apy_lease": "8.7014%"
      },
      {
         "account": "b71937a02eb7694d946c311297ca2da454057c5c3e97ac67500739cc2afbc0c5",
         "routed_out": "110000000msat",
         "routed_in": "0msat",
         "lease_fee_paid": "670000msat",
         "lease_fee_earned": "0msat",
         "pushed_out": "0msat",
         "pushed_in": "0msat",
         "our_start_balance": "4000000000msat",
         "channel_start_balance": "4100670000msat",
         "fees_out": "10100101msat",
         "fees_in": "0msat",
         "utilization_out": "2.6825%",
         "utilization_out_initial": "2.7500%",
         "utilization_in": "0.0000%",
         "utilization_in_initial": "0.0000%",
         "apy_out": "2579.4892%",
         "apy_out_initial": "2644.4084%",
         "apy_in": "0.0000%",
         "apy_in_initial": "0.0000%",
         "apy_total": "2579.4892%",
         "apy_total_initial": "2579.4892%"
      },
      {
         "account": "net",
         "routed_out": "110002000msat",
         "routed_in": "125100101msat",
         "lease_fee_paid": "670000msat",
         "lease_fee_earned": "670000msat",
         "pushed_out": "0msat",
         "pushed_in": "0msat",
         "our_start_balance": "4100670000msat",
         "channel_start_balance": "5201340000msat",
         "fees_out": "10100101msat",
         "fees_in": "10100101msat",
         "utilization_out": "2.1149%",
         "utilization_out_initial": "2.6825%",
         "utilization_in": "2.4052%",
         "utilization_in_initial": "11.3658%",
         "apy_out": "677.8788%",
         "apy_out_initial": "859.8297%",
         "apy_in": "677.8788%",
         "apy_in_initial": "3203.3924%",
         "apy_total": "1355.7575%",
         "apy_total_initial": "1355.7575%",
         "apy_lease": "0.2122%"
      }
   ]
}
```
2022-07-28 12:08:18 +09:30
niftynei
c05900c676 bkpr: add option --bookkeeper-dir
Allow setting custom directory for bookkeeper's database
and default directory for any csv file creation
2022-07-28 12:08:18 +09:30
niftynei
12b5c06219 bkpr: add 'start_time' and 'end_time' to listincome
Add ability to filter results by timestamp.

Note that "start_time" is everything *after* that timestamp; and
"end_time" is everything *up to and including* that timestamp.
2022-07-28 12:08:18 +09:30
niftynei
a0b34066e0 bkpr: add dumpincomecsv command
Prints out the `listincome` events as a CSV formatted file

Current csv_format options:

- koinly
- cointracker
- harmony (https://github.com/harmony-csv/harmony)
- quickbooks*

*Quickbooks expects values in 'USD', whereas we print values out
in <currency> (will be noted in the Description field). This won't work
how you'd expect -> you might need to do some conversion etc before
uploading it.

All amounts emitted as 'btc' w/ *11* decimals.
2022-07-28 12:08:18 +09:30
niftynei
a7b7ea5d49 bkpr: add a 'consolidate-fees' flag to the income stmt
Defaults to true. This is actually what you want to see -- the fees for
an account's txid collapsed into a single entry.
2022-07-28 12:08:18 +09:30
niftynei
83c6cf25d2 bkpr: 'to_miner' spends are considered terminal
This is a rare case where we RBF the output of a penalty until it no
longer has an output value we can reclaim. We ignore the txid for these
events when closing a channel.
2022-07-28 12:08:18 +09:30
niftynei
1dd52ba003 bkpr: mark external deposits (withdraws) via blockheight when confirmed
We issue events for external deposits (withdrawals) before the tx is
confirmed in a block. To avoid double counting these, we don't count
them as confirmed/included until after they're confirmed. We do this
by keeping the blockheight as zero until the withdraw for the input for
them comes through.

Note that since we don't have any way to note when RBF'd withdraws
aren't eligible for block inclusion anymore, we don't really have a good
heuristic to trim them. Which is fine, they *will* show up in account
events however.
2022-07-28 12:08:18 +09:30
niftynei
593f1e7365 bkpr: add a 'listincome' event
list the income/expense events for a node.
2022-07-28 12:08:18 +09:30
niftynei
595c52f611 bkpr: add timestamp filters to event lists 2022-07-28 12:08:18 +09:30
niftynei
462fa20c17 bkpr: move json_to functions to respective type files 2022-07-28 12:08:18 +09:30
niftynei
5f41d9247e bkpr: properly account for onchain fees for channel closes
onchain fees are weird at channel close because:

- you may be missing an trimmed htlc (which went to fees)
- the balance from close may have been rounded (msats cant land on
chain)
- the close might have been a past state and you've actually
  ended up with more money onchain than you had in the channel. wut

This commit accounts for all of this appropriately, with some tests.

channel_close.debit should equal onchain_fee.credit (for that txid)
plus sum(chain_event.credit [wallet/channel_acct]).

In the penalty case, channel_close.debit becomes channel_close.debit +
penalty_adj.debit, i.e.

	channel-close.debit + (penalty_adj.debit) =
		onchain_fee.credit
	      + sum(chain_event.credit [wallet/channel_acct])
2022-07-28 12:08:18 +09:30
niftynei
8f869ade3c bkpr: use chain_closed count to do mark account closed
More robust than inspecting the returned utxo treeset -- if the tree is
complete but missing outputs we'll get the wrong result
2022-07-28 12:08:18 +09:30
niftynei
7d5a0988db bkpr: save closed_count for account, when known
When the closing channel event tells you how many outputs to expect,
save it to the account so we can verify the account is fully closed/onchain.
2022-07-28 12:08:18 +09:30
niftynei
7b6956e4f9 bkpr: annotate an account with the block at which it's been resolved
Due to the way that onchain channel closes work, there is often a delay
between when the funding output is spent and the channel is considered
'closed'.

Once *every* downstream utxo of a channel has landed on chain, we
annotate the account with the resolving blockheight.

This gives us some insight into whether or not the chain fees etc of a
channel are going to update further and allows for a natural marker to
prune data (at a later date)
2022-07-28 12:08:18 +09:30
niftynei
b33bd05524 bkpr: add an 'inspect' command to the bookkeeper
Pass in an account id, get out a utxo chain of the channel open and
close (and any other related htlc txs etc).

Note that this prints all wallet deposits that occurred in any of the
tx's that touched this channel.

This is fine and expected for any tx that's not the open; when
considerig the tx open event, the wallet deposit that's present is
typically the change. If there were other channels opened in the same tx
then the change won't match up exactly...
2022-07-28 12:08:18 +09:30
niftynei
fea33221d4 bkpr: once we get channel_opens, we might need to update the fee records
Also note that we might have ignored/missed fees for the channel
closed's spending txid, so we attempt to update those as well.

Backfilling for missed events is a beast.
2022-07-28 12:08:18 +09:30
niftynei
8827423556 bkpr: account for pushed amounts and record the output_value
We need the total output_value, and we can figure this out if we look at
the remote amount also.

We also need to account for the pushed/leased amount, as for leased
channels this really messes with onchain fee calculations.

We copy basically the events that lightningd emits for leased channels:
an open event with the 'lease fee' (pushed?) amount credited to the side
that made the lease/push; then an in-channel event to effectively push
the pushed/leased amount over to the peer it was paid to.

We run the journal entry info after this, so the journal snapshot will
take the pushed amount into account when figuring out what the further
missed in-channel payments were (if any)
2022-07-28 12:08:18 +09:30
niftynei
2385d8d613 bkpr: listbalances, rename 'account_id' => 'account' 2022-07-28 12:08:18 +09:30
niftynei
f767e41755 bkpr: listbalances, skip the external account
it's essentialy meaningless
2022-07-28 12:08:18 +09:30
niftynei
791c1a7526 bkpr: cleanup wallet fee entries if decide they belong to a channel
Because we update the onchain_fee table every time a new event comes in,
it's possible (and in fact happens) that we get a wallet
withdraw/deposit event and then the channel open output event.

What we'd expect in this case is that the fees for the tx were credited
to the channel's account, not the wallet. But since we got the two
in/out events first, the fees were accumulated there first.

Our existing logic will add the channel's fees correctly, but we weren't
zeroing out the wallet's balance once it'd been determined that they
were 'ineligble' so to speak, for being included in the fees that round.
2022-07-28 12:08:18 +09:30
niftynei
08d8de8e45 bkpr: don't try to add fees if this tx didn't touch any accts
Dividing by zero causes problems.
2022-07-28 12:08:18 +09:30
niftynei
8c3347d129 bkpr: dont count fees for channel closes if we're not the opener
The opener pays fees on close, so if we're not the opener we should
ignore any fees on the closing tx.
2022-07-28 12:08:18 +09:30
niftynei
ee8c04a63a bkpr: update tests for wallet/external onchain fees
Working as intended; had a bool switched etc
2022-07-28 12:08:18 +09:30
niftynei
2a3875204a bkpr: parse the 'originating_account' field, save to event
It's useful to know which account an 'external' event impacted, so we
save this data now
2022-07-28 12:08:18 +09:30
niftynei
307ea93592 bkpr: invert channel + chain event printouts
We now add chain events for starting channel balances, so print these
out with chain first then channel events.

Makes it less confusing for channel lease fee events.
2022-07-28 12:08:18 +09:30
niftynei
8089f246c1 bkpr: use tags not str for tag originations 2022-07-28 12:08:18 +09:30
niftynei
a1d72cef06 bkpr: add a new command listaccountevents
Prints all the events for the requested account. If no account
requested, prints out all the events. Ordered by timestamp.

Changelog-Added: bookkeeper: new command `listaccountevents`
2022-07-28 12:08:18 +09:30
niftynei
8039fde5ab bkpr: if we're missing info about an account, add in journal entry
There's two situations where we're missing info.

One is we get a 'channel_closed' event (but there's no 'channel_open')

The other is a balance_snapshot arrives with information about accounts
that doesn't match what's already on disk. (For some of these cases, we
may be missing 'channel_open' events..)

In the easy case (no channel_open missing), we just figure out what the
2022-07-28 12:08:18 +09:30
niftynei
ccffac8208 bkpr: put the account name on the event
When we print events out, we need to know the account name. This makes
our lookup a lot easier, since we just pull it out from the database
every time we query for these.
2022-07-28 12:08:18 +09:30
niftynei
d943e5e85c bkpr: use pointer for payment_id for channel events
sometimes these are null!
2022-07-28 12:08:18 +09:30
niftynei
8ec35b7eb1 bkpr: turns out these fields are optional
pushes and channel leases don't provide fees or payment_id info
2022-07-28 12:08:18 +09:30
niftynei
899d54edd0 bkpr: have onchain_fee records be write-only, don't update in place
One really rough thing about how we did onchain fees is that the records update
every time a new event comes in.

The better way to do this is to create new entries for every adjustment,
so that reconciliation between printouts isn't a misery.

We add a timestamp and `update_count` to these records, so you can
roughly order them now (and have a good idea of the last time an event
that updated an onchain_fee occurred).
2022-07-28 12:08:18 +09:30
niftynei
29c6884468 bkpr: add journal entry for offset account balances; report listbalances
When the node starts up, it records missing/updated account balances
to the 'channel' events... which is kinda fucked for wallet + external
events now that i think about it but these are all treated the same
anyway so it's fine.

This is the magic piece that lets your bookkeeping data startup ok on an
already running/established node.
2022-07-28 12:08:18 +09:30
niftynei
b7d85f1d0b bkpr: wire up our chain fee accting to chain event reception
When we get a chain event, check to see if this updates any onchain fee
records that we have.
2022-07-28 12:08:18 +09:30
Rusty Russell
721ceb7519 patch db-fatal-plugin_err.patch 2022-07-28 12:08:18 +09:30
niftynei
351dc17e46 bkpr: add bookkeeper to PLUGINS list
This makes it start up automatically
2022-07-28 12:08:18 +09:30