From 99988cb0e18b3301cf3cee0205638b218e31f37e Mon Sep 17 00:00:00 2001 From: Christian Decker Date: Thu, 9 May 2019 18:49:46 +0200 Subject: [PATCH] elements: Fix up existing fee output instead of adding a new one Especially when we grind fees we may end up setting the fees several times, so instead of always adding a new fee output look for an existing one and set its value. Signed-off-by: Christian Decker --- bitcoin/tx.c | 29 +++++++++++++++++++++++++---- bitcoin/tx.h | 3 +-- 2 files changed, 26 insertions(+), 6 deletions(-) diff --git a/bitcoin/tx.c b/bitcoin/tx.c index 9fe7613b7..d1a7aea48 100644 --- a/bitcoin/tx.c +++ b/bitcoin/tx.c @@ -68,6 +68,12 @@ int bitcoin_tx_add_multi_outputs(struct bitcoin_tx *tx, return tx->wtx->num_outputs; } +static bool bitcoin_tx_output_is_fee(const struct bitcoin_tx *tx, int outnum) +{ + assert(outnum < tx->wtx->num_outputs); + return is_elements && tx->wtx->outputs[outnum].script_len == 0; +} + /** * Compute how much fee we are actually sending with this transaction. */ @@ -79,6 +85,9 @@ static u64 bitcoin_tx_compute_fee(const struct bitcoin_tx *tx) fee += tx->input_amounts[i]->satoshis; /* Raw: fee computation */ for (size_t i=0; iwtx->num_outputs; i++) { + if (bitcoin_tx_output_is_fee(tx, i)) + continue; + if (!is_elements) { fee -= tx->wtx->outputs[i].satoshi; /* Raw: low-level helper */ } else { @@ -95,13 +104,28 @@ static u64 bitcoin_tx_compute_fee(const struct bitcoin_tx *tx) int bitcoin_tx_add_fee_output(struct bitcoin_tx *tx) { struct amount_sat fee; + int pos = -1; u64 rawsats = bitcoin_tx_compute_fee(tx); /* Raw: pedantic much? */ fee.satoshis = rawsats; /* Raw: need amounts later */ /* If we aren't using elements, we don't add explicit fee outputs */ if (!is_elements || rawsats == 0) return -1; - return bitcoin_tx_add_output(tx, NULL, fee); + + /* Try to find any existing fee output */ + for (int i=0; iwtx->num_outputs; i++) { + if (bitcoin_tx_output_is_fee(tx, i)) { + assert(pos == -1); + pos = i; + } + } + + if (pos == -1) { + return bitcoin_tx_add_output(tx, NULL, fee); + } else { + bitcoin_tx_output_set_amount(tx, pos, fee); + return pos; + } } int bitcoin_tx_add_input(struct bitcoin_tx *tx, const struct bitcoin_txid *txid, @@ -139,9 +163,6 @@ bool bitcoin_tx_check(const struct bitcoin_tx *tx) if (is_elements) { flags |= WALLY_TX_FLAG_USE_ELEMENTS; - /* Elements transactions must have an explicit fee */ - if (bitcoin_tx_compute_fee(tx) != 0) - return false; } newtx = tal_arr(tmpctx, u8, written); diff --git a/bitcoin/tx.h b/bitcoin/tx.h index 6ad41f607..030be9d3e 100644 --- a/bitcoin/tx.h +++ b/bitcoin/tx.h @@ -153,8 +153,7 @@ bool bitcoin_tx_check(const struct bitcoin_tx *tx); * * An explicit fee output is only necessary if we are using an elements * transaction, and we have a non-zero fee. This method may be called multiple - * times if input and output values do not change, however it may result in - * multiple change outputs if the fee is changed. + * times. * * Returns the position of the fee output, or -1 in the case of non-elements * transactions.