Skip to content

Commit 3eaa7a5

Browse files
committed
tx: Strengthen transaction construction checks
We roll the `elements_add_fee_output` function and the cropping of overallocated arrays into the `bitcoin_tx_finalize` function. This is supposed to be the final cleanup and compaction step before a tx can be sent to bitcoin or passed off to other daemons. This is the cleanup promised in ElementsProject#3491
1 parent b5a41f9 commit 3eaa7a5

File tree

8 files changed

+56
-17
lines changed

8 files changed

+56
-17
lines changed

bitcoin/tx.c

Lines changed: 37 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -101,25 +101,29 @@ static struct amount_sat bitcoin_tx_compute_fee(const struct bitcoin_tx *tx)
101101
int elements_tx_add_fee_output(struct bitcoin_tx *tx)
102102
{
103103
struct amount_sat fee = bitcoin_tx_compute_fee(tx);
104-
int pos = -1;
104+
int pos;
105105
struct witscript *w;
106106

107107
/* If we aren't using elements, we don't add explicit fee outputs */
108108
if (!chainparams->is_elements || amount_sat_eq(fee, AMOUNT_SAT(0)))
109109
return -1;
110110

111111
/* Try to find any existing fee output */
112-
for (int i=0; i<tx->wtx->num_outputs; i++) {
113-
if (elements_tx_output_is_fee(tx, i)) {
114-
assert(pos == -1);
115-
pos = i;
116-
}
112+
for (pos = 0; pos < tx->wtx->num_outputs; pos++) {
113+
if (elements_tx_output_is_fee(tx, pos))
114+
break;
117115
}
118116

119-
if (pos == -1) {
117+
if (pos == tx->wtx->num_outputs) {
120118
w = tal(tx->output_witscripts, struct witscript);
121119
w->ptr = tal_arr(w, u8, 0);
122-
tx->output_witscripts[tx->wtx->num_outputs] = w;
120+
121+
/* Make sure we have a place to stash the witness script in. */
122+
if (tal_count(tx->output_witscripts) < pos + 1) {
123+
tal_resize(&tx->output_witscripts, pos + 1);
124+
}
125+
tx->output_witscripts[pos] = w;
126+
123127
return bitcoin_tx_add_output(tx, NULL, fee);
124128
} else {
125129
bitcoin_tx_output_set_amount(tx, pos, fee);
@@ -160,6 +164,12 @@ bool bitcoin_tx_check(const struct bitcoin_tx *tx)
160164
size_t written;
161165
int flags = WALLY_TX_FLAG_USE_WITNESS;
162166

167+
if (tal_count(tx->input_amounts) != tx->wtx->num_inputs)
168+
return false;
169+
170+
if (tal_count(tx->output_witscripts) != tx->wtx->num_outputs)
171+
return false;
172+
163173
if (wally_tx_get_length(tx->wtx, flags, &written) != WALLY_OK)
164174
return false;
165175

@@ -408,6 +418,19 @@ struct bitcoin_tx *bitcoin_tx(const tal_t *ctx,
408418
return tx;
409419
}
410420

421+
void bitcoin_tx_finalize(struct bitcoin_tx *tx)
422+
{
423+
size_t num_outputs, num_inputs;
424+
elements_tx_add_fee_output(tx);
425+
426+
num_outputs = tx->wtx->num_outputs;
427+
tal_resize(&(tx->output_witscripts), num_outputs);
428+
429+
num_inputs = tx->wtx->num_inputs;
430+
tal_resize(&tx->input_amounts, num_inputs);
431+
assert(bitcoin_tx_check(tx));
432+
}
433+
411434
struct bitcoin_tx *pull_bitcoin_tx(const tal_t *ctx, const u8 **cursor,
412435
size_t *max)
413436
{
@@ -470,6 +493,12 @@ struct bitcoin_tx *bitcoin_tx_from_hex(const tal_t *ctx, const char *hex,
470493
goto fail_free_tx;
471494

472495
tal_free(linear_tx);
496+
497+
tx->output_witscripts =
498+
tal_arrz(tx, struct witscript *, tx->wtx->num_outputs);
499+
tx->input_amounts =
500+
tal_arrz(tx, struct amount_sat *, tx->wtx->num_inputs);
501+
473502
return tx;
474503

475504
fail_free_tx:

bitcoin/tx.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,15 @@ void bitcoin_tx_input_get_txid(const struct bitcoin_tx *tx, int innum,
156156
*/
157157
bool bitcoin_tx_check(const struct bitcoin_tx *tx);
158158

159+
160+
/**
161+
* Finalize a transaction by truncating overallocated and temporary
162+
* fields. This includes adding a fee output for elements transactions or
163+
* adjusting an existing fee output, and resizing metadata arrays for inputs
164+
* and outputs.
165+
*/
166+
void bitcoin_tx_finalize(struct bitcoin_tx *tx);
167+
159168
/**
160169
* Add an explicit fee output if necessary.
161170
*

channeld/commit_tx.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -305,8 +305,8 @@ struct bitcoin_tx *commit_tx(const tal_t *ctx,
305305
u32 sequence = (0x80000000 | ((obscured_commitment_number>>24) & 0xFFFFFF));
306306
bitcoin_tx_add_input(tx, funding_txid, funding_txout, sequence, funding, NULL);
307307

308-
elements_tx_add_fee_output(tx);
309-
tal_resize(&(tx->output_witscripts), tx->wtx->num_outputs);
308+
bitcoin_tx_finalize(tx);
309+
assert(bitcoin_tx_check(tx));
310310

311311
return tx;
312312
}

common/close_tx.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,8 +60,8 @@ struct bitcoin_tx *create_close_tx(const tal_t *ctx,
6060
return tal_free(tx);
6161

6262
permute_outputs(tx, NULL, NULL);
63-
elements_tx_add_fee_output(tx);
6463

64+
bitcoin_tx_finalize(tx);
6565
assert(bitcoin_tx_check(tx));
6666
return tx;
6767
}

common/funding_tx.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ struct bitcoin_tx *funding_tx(const tal_t *ctx,
5050

5151
permute_inputs(tx, (const void **)utxomap);
5252

53-
elements_tx_add_fee_output(tx);
53+
bitcoin_tx_finalize(tx);
5454
assert(bitcoin_tx_check(tx));
5555
return tx;
5656
}

common/htlc_tx.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,9 @@ static struct bitcoin_tx *htlc_tx(const tal_t *ctx,
6161
wscript = bitcoin_wscript_htlc_tx(tx, to_self_delay, revocation_pubkey,
6262
local_delayedkey);
6363
bitcoin_tx_add_output(tx, scriptpubkey_p2wsh(tx, wscript), amount);
64-
elements_tx_add_fee_output(tx);
64+
65+
bitcoin_tx_finalize(tx);
66+
assert(bitcoin_tx_check(tx));
6567

6668
tal_free(wscript);
6769

common/initial_commit_tx.c

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -241,9 +241,7 @@ struct bitcoin_tx *initial_commit_tx(const tal_t *ctx,
241241
sequence = (0x80000000 | ((obscured_commitment_number>>24) & 0xFFFFFF));
242242
bitcoin_tx_add_input(tx, funding_txid, funding_txout, sequence, funding, NULL);
243243

244-
elements_tx_add_fee_output(tx);
245-
tal_resize(&(tx->output_witscripts), tx->wtx->num_outputs);
246-
244+
bitcoin_tx_finalize(tx);
247245
assert(bitcoin_tx_check(tx));
248246

249247
return tx;

common/withdraw_tx.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,8 @@ struct bitcoin_tx *withdraw_tx(const tal_t *ctx,
5252
*change_outnum = -1;
5353

5454
permute_inputs(tx, (const void **)utxos);
55-
elements_tx_add_fee_output(tx);
55+
56+
bitcoin_tx_finalize(tx);
5657
assert(bitcoin_tx_check(tx));
5758
return tx;
5859
}

0 commit comments

Comments
 (0)