diff --git a/wallet/walletrpc.c b/wallet/walletrpc.c index 6ec384873a58..af33d905a330 100644 --- a/wallet/walletrpc.c +++ b/wallet/walletrpc.c @@ -1,10 +1,12 @@ #include #include #include +#include #include #include #include #include +#include #include #include #include @@ -21,6 +23,7 @@ #include #include #include +#include #include #include #include @@ -33,6 +36,78 @@ #include #include +static struct amount_sat compute_fee(const struct bitcoin_tx *tx, + struct unreleased_tx *utx) +{ + size_t i; + bool ok; + struct amount_sat input_sum = AMOUNT_SAT(0); + + /* ok so, the easiest thing to do is to add up all the inputs, + * separately, and then compute the fee from the outputs. + * 'normally' we'd just pass in the tx to `bitcoin_compute_fee` + * but due to how serialization works, the input amounts aren't + * preserved here */ + /* FIXME: use `bitcoin_compute_fee` once input amounts + * are preserved across the wire */ + for (i = 0; i < tal_count(utx->wtx->utxos); i++) { + ok = amount_sat_add(&input_sum, input_sum, + utx->wtx->utxos[i]->amount); + assert(ok); + } + + return bitcoin_tx_compute_fee_w_inputs(tx, input_sum); +} + +static void record_coin_moves(struct lightningd *ld, + struct unreleased_tx *utx) +{ + struct amount_sat fees; + struct chain_coin_mvt *mvt; + size_t i; + + /* record each of the outputs as a withdrawal */ + for (i = 0; i < utx->tx->wtx->num_outputs; i++) { + struct amount_asset asset; + struct amount_sat sats; + asset = bitcoin_tx_output_get_amount(utx->tx, i); + if (elements_tx_output_is_fee(utx->tx, i) || + !amount_asset_is_main(&asset)) { + /* FIXME: handle non-btc withdrawals */ + continue; + } + sats = amount_asset_to_sat(&asset); + mvt = new_chain_coin_mvt_sat(utx, "wallet", &utx->txid, + &utx->txid, i, NULL, + WITHDRAWAL, sats, + false, BTC); + if (!mvt) + fatal("unable to convert %s to msat", + type_to_string(tmpctx, struct amount_sat, + &sats)); + notify_chain_mvt(ld, mvt); + } + + /* we can't use bitcoin_tx_compute_fee because the input + * amounts aren't set... */ + fees = compute_fee(utx->tx, utx); + + /* Note that to figure out the *total* 'onchain' + * cost of a channel, you'll want to also include + * fees logged here, to the 'wallet' account (for funding tx). + * You can do this in post by accounting for any 'chain_fees' logged for + * the funding txid when looking at a channel. */ + mvt = new_chain_coin_mvt_sat(utx, "wallet", &utx->txid, + NULL, 0, NULL, CHAIN_FEES, + fees, false, BTC); + + if (!mvt) + fatal("unable to convert %s to msat", + type_to_string(tmpctx, struct amount_sat, &fees)); + + notify_chain_mvt(ld, mvt); +} + /** * wallet_withdrawal_broadcast - The tx has been broadcast (or it failed) * @@ -56,6 +131,7 @@ static void wallet_withdrawal_broadcast(struct bitcoind *bitcoind UNUSED, if (success) { /* Mark used outputs as spent */ wallet_confirm_utxos(ld->wallet, utx->wtx->utxos); + record_coin_moves(ld, utx); /* Extract the change output and add it to the DB */ wallet_extract_owned_outputs(ld->wallet, utx->tx, NULL, &change);