From 4c28e7b362aa2ead6ffa6fe80726dff3c1e1dd9d Mon Sep 17 00:00:00 2001 From: niftynei Date: Wed, 9 Sep 2020 17:38:12 -0500 Subject: [PATCH] txprepare: elements requires inclusion of an accurate fee output so we add an accurate one --- bitcoin/psbt.c | 45 +++++++++++++++++++++++++++++++++++++++++++++ bitcoin/psbt.h | 8 ++++++++ plugins/txprepare.c | 4 ++++ 3 files changed, 57 insertions(+) diff --git a/bitcoin/psbt.c b/bitcoin/psbt.c index f6c88d0c6..970e67a53 100644 --- a/bitcoin/psbt.c +++ b/bitcoin/psbt.c @@ -308,6 +308,51 @@ void psbt_elements_input_set_asset(struct wally_psbt *psbt, size_t in, abort(); } +void psbt_elements_normalize_fees(struct wally_psbt *psbt) +{ + struct amount_asset asset; + size_t fee_output_idx = psbt->num_outputs; + + if (!is_elements(chainparams)) + return; + + /* Elements requires that every input value is accounted for, + * including the fees */ + struct amount_sat total_in = AMOUNT_SAT(0), val; + for (size_t i = 0; i < psbt->num_inputs; i++) { + val = psbt_input_get_amount(psbt, i); + if (!amount_sat_add(&total_in, total_in, val)) + return; + } + for (size_t i = 0; i < psbt->num_outputs; i++) { + asset = wally_tx_output_get_amount(&psbt->tx->outputs[i]); + if (elements_wtx_output_is_fee(psbt->tx, i)) { + fee_output_idx = i; + continue; + } + if (!amount_asset_is_main(&asset)) + continue; + + if (!amount_sat_sub(&total_in, total_in, + amount_asset_to_sat(&asset))) + return; + } + + if (amount_sat_eq(total_in, AMOUNT_SAT(0))) + return; + + /* We need to add a fee output */ + if (fee_output_idx == psbt->num_outputs) { + psbt_append_output(psbt, NULL, total_in); + } else { + u64 sats = total_in.satoshis; /* Raw: wally API */ + struct wally_tx_output *out = &psbt->tx->outputs[fee_output_idx]; + if (wally_tx_confidential_value_from_satoshi( + sats, out->value, out->value_len) != WALLY_OK) + return; + } +} + bool psbt_has_input(struct wally_psbt *psbt, struct bitcoin_txid *txid, u32 outnum) diff --git a/bitcoin/psbt.h b/bitcoin/psbt.h index 1fc8482d6..312dcf22e 100644 --- a/bitcoin/psbt.h +++ b/bitcoin/psbt.h @@ -69,6 +69,14 @@ bool psbt_is_finalized(const struct wally_psbt *psbt); void psbt_txid(const struct wally_psbt *psbt, struct bitcoin_txid *txid, struct wally_tx **wtx); +/* psbt_elements_normalize_fees - Figure out the fee output for a PSET + * + * Adds a fee output if not present, or updates it to include the diff + * between inputs - outputs. Unlike bitcoin, elements requires every + * satoshi to be accounted for in an output. + */ +void psbt_elements_normalize_fees(struct wally_psbt *psbt); + struct wally_tx *psbt_finalize(struct wally_psbt *psbt, bool finalize_in_place); /* psbt_make_key - Create a new, proprietary c-lightning key diff --git a/plugins/txprepare.c b/plugins/txprepare.c index 7ce05cb48..bd579c827 100644 --- a/plugins/txprepare.c +++ b/plugins/txprepare.c @@ -191,6 +191,10 @@ static struct command_result *finish_txprepare(struct command *cmd, psbt_add_output(txp->psbt, out, i); } + /* If this is elements, we should normalize + * the PSBT fee output */ + psbt_elements_normalize_fees(txp->psbt); + utx = tal(NULL, struct unreleased_tx); utx->psbt = tal_steal(utx, txp->psbt); psbt_txid(txp->psbt, &utx->txid, &utx->tx);