From 824e8fa72bd2180ac080934b719174aa0851b10f Mon Sep 17 00:00:00 2001 From: lisa neigut Date: Wed, 1 Apr 2020 20:35:04 -0500 Subject: [PATCH] tx: split 'compute fee' into two, with one that takes an input value Transactions that we 'get' from bitciond don't have the input values available on the transaction; for these cases we'll sum up the inputs amounts using a different data source than the transaction's `input_amounts`. So we need to expose it here. --- bitcoin/tx.c | 39 +++++++++++++++++++++++++-------------- bitcoin/tx.h | 14 ++++++++++++++ 2 files changed, 39 insertions(+), 14 deletions(-) diff --git a/bitcoin/tx.c b/bitcoin/tx.c index 0aa6d1d90..2bffd7677 100644 --- a/bitcoin/tx.c +++ b/bitcoin/tx.c @@ -70,35 +70,46 @@ bool elements_tx_output_is_fee(const struct bitcoin_tx *tx, int outnum) tx->wtx->outputs[outnum].script_len == 0; } -/** - * Compute how much fee we are actually sending with this transaction. - */ -static struct amount_sat bitcoin_tx_compute_fee(const struct bitcoin_tx *tx) +struct amount_sat bitcoin_tx_compute_fee_w_inputs(const struct bitcoin_tx *tx, + struct amount_sat input_val) { - struct amount_sat fee = AMOUNT_SAT(0), value; struct amount_asset asset; bool ok; - for (size_t i = 0; i < tal_count(tx->input_amounts); i++) { - value.satoshis = tx->input_amounts[i]->satoshis; /* Raw: fee computation */ - ok = amount_sat_add(&fee, fee, value); - assert(ok); - } - for (size_t i = 0; i < tx->wtx->num_outputs; i++) { asset = bitcoin_tx_output_get_amount(tx, i); if (elements_tx_output_is_fee(tx, i) || !amount_asset_is_main(&asset)) continue; - value = amount_asset_to_sat(&asset); - ok = amount_sat_sub(&fee, fee, value); + ok = amount_sat_sub(&input_val, input_val, + amount_asset_to_sat(&asset)); assert(ok); } - return fee; + return input_val; } /** + * Compute how much fee we are actually sending with this transaction. + * Note that using this with a transaction without the input_amounts + * initialized/populated is an error. + */ +struct amount_sat bitcoin_tx_compute_fee(const struct bitcoin_tx *tx) +{ + struct amount_sat input_total = AMOUNT_SAT(0); + bool ok; + + for (size_t i = 0; i < tal_count(tx->input_amounts); i++) { + assert(tx->input_amounts[i]); + ok = amount_sat_add(&input_total, input_total, + *tx->input_amounts[i]); + assert(ok); + } + + return bitcoin_tx_compute_fee_w_inputs(tx, input_total); +} + +/* * Add an explicit fee output if necessary. * * An explicit fee output is only necessary if we are using an elements diff --git a/bitcoin/tx.h b/bitcoin/tx.h index 59e2395ab..50c414970 100644 --- a/bitcoin/tx.h +++ b/bitcoin/tx.h @@ -177,4 +177,18 @@ void bitcoin_tx_finalize(struct bitcoin_tx *tx); */ bool elements_tx_output_is_fee(const struct bitcoin_tx *tx, int outnum); +/** + * Calculate the fees for this transaction + */ +struct amount_sat bitcoin_tx_compute_fee(const struct bitcoin_tx *tx); + +/* + * Calculate the fees for this transaction, given a pre-computed input balance. + * + * This is needed for cases where the input_amounts aren't properly initialized, + * typically due to being passed across the wire. + */ +struct amount_sat bitcoin_tx_compute_fee_w_inputs(const struct bitcoin_tx *tx, + struct amount_sat input_val); + #endif /* LIGHTNING_BITCOIN_TX_H */