Browse Source

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 <decker.christian@gmail.com>
travis-debug
Christian Decker 6 years ago
committed by Rusty Russell
parent
commit
99988cb0e1
  1. 29
      bitcoin/tx.c
  2. 3
      bitcoin/tx.h

29
bitcoin/tx.c

@ -68,6 +68,12 @@ int bitcoin_tx_add_multi_outputs(struct bitcoin_tx *tx,
return tx->wtx->num_outputs; 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. * 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 */ fee += tx->input_amounts[i]->satoshis; /* Raw: fee computation */
for (size_t i=0; i<tx->wtx->num_outputs; i++) { for (size_t i=0; i<tx->wtx->num_outputs; i++) {
if (bitcoin_tx_output_is_fee(tx, i))
continue;
if (!is_elements) { if (!is_elements) {
fee -= tx->wtx->outputs[i].satoshi; /* Raw: low-level helper */ fee -= tx->wtx->outputs[i].satoshi; /* Raw: low-level helper */
} else { } 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) int bitcoin_tx_add_fee_output(struct bitcoin_tx *tx)
{ {
struct amount_sat fee; struct amount_sat fee;
int pos = -1;
u64 rawsats = bitcoin_tx_compute_fee(tx); /* Raw: pedantic much? */ u64 rawsats = bitcoin_tx_compute_fee(tx); /* Raw: pedantic much? */
fee.satoshis = rawsats; /* Raw: need amounts later */ fee.satoshis = rawsats; /* Raw: need amounts later */
/* If we aren't using elements, we don't add explicit fee outputs */ /* If we aren't using elements, we don't add explicit fee outputs */
if (!is_elements || rawsats == 0) if (!is_elements || rawsats == 0)
return -1; return -1;
return bitcoin_tx_add_output(tx, NULL, fee);
/* Try to find any existing fee output */
for (int i=0; i<tx->wtx->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, 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) { if (is_elements) {
flags |= WALLY_TX_FLAG_USE_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); newtx = tal_arr(tmpctx, u8, written);

3
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 * 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 * 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 * times.
* multiple change outputs if the fee is changed.
* *
* Returns the position of the fee output, or -1 in the case of non-elements * Returns the position of the fee output, or -1 in the case of non-elements
* transactions. * transactions.

Loading…
Cancel
Save