Skip to content

Commit 6a8eb06

Browse files
committed
withdraw: refactor change output handling
We're not using the change_outnum for withdraw tx's (and the way we were calculating it was broken as of the addition of 'multiple outputs'). This removes the change output knowhow from withdraw_tx entirely, and pushes the responsibility up to the caller to include the change output in the output set if desired. Consequently, we also remove the change output knowhow from hsmd.
1 parent c0f2828 commit 6a8eb06

File tree

8 files changed

+60
-60
lines changed

8 files changed

+60
-60
lines changed

bitcoin/tx.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,16 @@
1414

1515
#define SEGREGATED_WITNESS_FLAG 0x1
1616

17+
struct bitcoin_tx_output *new_tx_output(const tal_t *ctx,
18+
struct amount_sat amount,
19+
const u8 *script)
20+
{
21+
struct bitcoin_tx_output *output = tal(ctx, struct bitcoin_tx_output);
22+
output->amount = amount;
23+
output->script = tal_dup_arr(output, u8, script, tal_count(script), 0);
24+
return output;
25+
}
26+
1727
int bitcoin_tx_add_output(struct bitcoin_tx *tx, const u8 *script,
1828
struct amount_sat amount)
1929
{

bitcoin/tx.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,9 @@ struct bitcoin_tx_input {
4343
u8 **witness;
4444
};
4545

46+
struct bitcoin_tx_output *new_tx_output(const tal_t *ctx,
47+
struct amount_sat amount,
48+
const u8 *script);
4649

4750
/* SHA256^2 the tx: simpler than sha256_tx */
4851
void bitcoin_txid(const struct bitcoin_tx *tx, struct bitcoin_txid *txid);

common/withdraw_tx.c

Lines changed: 25 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
#include <bitcoin/pubkey.h>
44
#include <bitcoin/script.h>
55
#include <ccan/ptrint/ptrint.h>
6+
#include <common/key_derive.h>
67
#include <common/permute_tx.h>
78
#include <common/utils.h>
89
#include <common/utxo.h>
@@ -13,30 +14,36 @@ struct bitcoin_tx *withdraw_tx(const tal_t *ctx,
1314
const struct chainparams *chainparams,
1415
const struct utxo **utxos,
1516
struct bitcoin_tx_output **outputs,
16-
const struct pubkey *changekey,
17-
struct amount_sat change,
18-
const struct ext_key *bip32_base,
19-
int *change_outnum)
17+
const struct ext_key *bip32_base)
2018
{
2119
struct bitcoin_tx *tx;
20+
struct pubkey key;
21+
u8 *script;
22+
size_t i;
2223

23-
tx = tx_spending_utxos(ctx, chainparams, utxos, bip32_base,
24-
!amount_sat_eq(change, AMOUNT_SAT(0)),
25-
tal_count(outputs));
24+
assert(tal_count(utxos) > 0 && tal_count(outputs) > 0);
25+
26+
tx = bitcoin_tx(ctx, chainparams,
27+
tal_count(utxos),
28+
tal_count(outputs));
29+
30+
/* Add our utxo's */
31+
for (i = 0; i < tal_count(utxos); i++) {
32+
if (utxos[i]->is_p2sh && bip32_base) {
33+
bip32_pubkey(bip32_base, &key, utxos[i]->keyindex);
34+
script = bitcoin_scriptsig_p2sh_p2wpkh(tmpctx, &key);
35+
} else {
36+
script = NULL;
37+
}
38+
39+
bitcoin_tx_add_input(tx, &utxos[i]->txid, utxos[i]->outnum,
40+
BITCOIN_TX_DEFAULT_SEQUENCE,
41+
utxos[i]->amount, script);
42+
}
2643

2744
bitcoin_tx_add_multi_outputs(tx, outputs);
45+
permute_outputs(tx, NULL, (const void **)outputs);
2846

29-
if (!amount_sat_eq(change, AMOUNT_SAT(0))) {
30-
const void *map[2];
31-
map[0] = int2ptr(0);
32-
map[1] = int2ptr(1);
33-
bitcoin_tx_add_output(tx, scriptpubkey_p2wpkh(tmpctx, changekey),
34-
change);
35-
permute_outputs(tx, NULL, map);
36-
if (change_outnum)
37-
*change_outnum = ptr2int(map[1]);
38-
} else if (change_outnum)
39-
*change_outnum = -1;
4047
permute_inputs(tx, (const void **)utxos);
4148
elements_tx_add_fee_output(tx);
4249
assert(bitcoin_tx_check(tx));

common/withdraw_tx.h

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -21,18 +21,12 @@ struct utxo;
2121
* @chainparams: (in) the params for the created transaction.
2222
* @utxos: (in/out) tal_arr of UTXO pointers to spend (permuted to match)
2323
* @outputs: (in) tal_arr of bitcoin_tx_output, scriptPubKeys with amount to send to.
24-
* @changekey: (in) key to send change to (only used if change_satoshis != 0).
25-
* @change: (in) amount to send as change.
2624
* @bip32_base: (in) bip32 base for key derivation, or NULL.
27-
* @change_outnum: (out) set to output index of change output or -1 if none, unless NULL.
2825
*/
2926
struct bitcoin_tx *withdraw_tx(const tal_t *ctx,
3027
const struct chainparams *chainparams,
3128
const struct utxo **utxos,
3229
struct bitcoin_tx_output **outputs,
33-
const struct pubkey *changekey,
34-
struct amount_sat change,
35-
const struct ext_key *bip32_base,
36-
int *change_outnum);
30+
const struct ext_key *bip32_base);
3731

3832
#endif /* LIGHTNING_COMMON_WITHDRAW_TX_H */

hsmd/hsm_wire.csv

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -67,9 +67,6 @@ msgdata,hsm_node_announcement_sig_reply,signature,secp256k1_ecdsa_signature,
6767

6868
# Sign a withdrawal request
6969
msgtype,hsm_sign_withdrawal,7
70-
msgdata,hsm_sign_withdrawal,satoshi_out,amount_sat,
71-
msgdata,hsm_sign_withdrawal,change_out,amount_sat,
72-
msgdata,hsm_sign_withdrawal,change_keyindex,u32,
7370
msgdata,hsm_sign_withdrawal,num_outputs,u16,
7471
msgdata,hsm_sign_withdrawal,outputs,bitcoin_tx_output,num_outputs
7572
msgdata,hsm_sign_withdrawal,num_inputs,u16,

hsmd/hsmd.c

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1640,25 +1640,17 @@ static struct io_plan *handle_sign_withdrawal_tx(struct io_conn *conn,
16401640
struct client *c,
16411641
const u8 *msg_in)
16421642
{
1643-
struct amount_sat satoshi_out, change_out;
1644-
u32 change_keyindex;
16451643
struct utxo **utxos;
16461644
struct bitcoin_tx *tx;
1647-
struct pubkey changekey;
16481645
struct bitcoin_tx_output **outputs;
16491646

1650-
if (!fromwire_hsm_sign_withdrawal(tmpctx, msg_in, &satoshi_out,
1651-
&change_out, &change_keyindex,
1647+
if (!fromwire_hsm_sign_withdrawal(tmpctx, msg_in,
16521648
&outputs, &utxos))
16531649
return bad_req(conn, c, msg_in);
16541650

1655-
if (!bip32_pubkey(&secretstuff.bip32, &changekey, change_keyindex))
1656-
return bad_req_fmt(conn, c, msg_in,
1657-
"Failed to get key %u", change_keyindex);
1658-
16591651
tx = withdraw_tx(tmpctx, c->chainparams,
1660-
cast_const2(const struct utxo **, utxos), outputs,
1661-
&changekey, change_out, NULL, NULL);
1652+
cast_const2(const struct utxo **, utxos),
1653+
outputs, NULL);
16621654

16631655
sign_all_inputs(tx, utxos);
16641656

wallet/wallet.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,8 +63,6 @@ struct unreleased_tx {
6363
/* The tx itself (unsigned initially) */
6464
struct bitcoin_tx *tx;
6565
struct bitcoin_txid txid;
66-
/* Index of change output, or -1 if none. */
67-
int change_outnum;
6866
};
6967

7068
/* Possible states for tracked outputs in the database. Not sure yet

wallet/walletrpc.c

Lines changed: 18 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -84,9 +84,6 @@ static struct command_result *broadcast_and_wait(struct command *cmd,
8484
/* FIXME: hsm will sign almost anything, but it should really
8585
* fail cleanly (not abort!) and let us report the error here. */
8686
u8 *msg = towire_hsm_sign_withdrawal(cmd,
87-
utx->wtx->amount,
88-
utx->wtx->change,
89-
utx->wtx->change_key_index,
9087
cast_const2(const struct bitcoin_tx_output **,
9188
utx->outputs),
9289
utx->wtx->utxos);
@@ -293,10 +290,8 @@ static struct command_result *json_prepare_tx(struct command *cmd,
293290
* Support only one output. */
294291
if (destination) {
295292
outputs = tal_arr(tmpctx, struct bitcoin_tx_output *, 1);
296-
outputs[0] = tal(outputs, struct bitcoin_tx_output);
297-
outputs[0]->script = tal_steal(outputs[0],
298-
cast_const(u8 *, destination));
299-
outputs[0]->amount = (*utx)->wtx->amount;
293+
outputs[0] = new_tx_output(outputs, (*utx)->wtx->amount,
294+
destination);
300295
out_len = tal_count(outputs[0]->script);
301296

302297
goto create_tx;
@@ -338,11 +333,9 @@ static struct command_result *json_prepare_tx(struct command *cmd,
338333
"'%.*s' is a invalid satoshi amount",
339334
t[2].end - t[2].start, buffer + t[2].start);
340335

336+
outputs[i] = new_tx_output(outputs, *amount,
337+
cast_const(u8 *, destination));
341338
out_len += tal_count(destination);
342-
outputs[i] = tal(outputs, struct bitcoin_tx_output);
343-
outputs[i]->amount = *amount;
344-
outputs[i]->script = tal_steal(outputs[i],
345-
cast_const(u8 *, destination));
346339

347340
/* In fact, the maximum amount of bitcoin satoshi is 2.1e15.
348341
* It can't be equal to/bigger than 2^64.
@@ -368,8 +361,6 @@ static struct command_result *json_prepare_tx(struct command *cmd,
368361
}
369362

370363
create_tx:
371-
(*utx)->outputs = tal_steal(*utx, outputs);
372-
373364
if (chosen_utxos)
374365
result = wtx_from_utxos((*utx)->wtx, *feerate_per_kw,
375366
out_len, maxheight,
@@ -386,18 +377,26 @@ static struct command_result *json_prepare_tx(struct command *cmd,
386377
if ((*utx)->wtx->all_funds)
387378
outputs[0]->amount = (*utx)->wtx->amount;
388379

380+
/* Add the change as the last output */
389381
if (!amount_sat_eq((*utx)->wtx->change, AMOUNT_SAT(0))) {
382+
struct bitcoin_tx_output *change_output;
383+
390384
changekey = tal(tmpctx, struct pubkey);
391385
if (!bip32_pubkey(cmd->ld->wallet->bip32_base, changekey,
392386
(*utx)->wtx->change_key_index))
393387
return command_fail(cmd, LIGHTNINGD, "Keys generation failure");
394-
} else
395-
changekey = NULL;
388+
389+
change_output = new_tx_output(outputs, (*utx)->wtx->change,
390+
scriptpubkey_p2wpkh(tmpctx, changekey));
391+
tal_arr_expand(outputs, *change_output);
392+
}
393+
394+
(*utx)->outputs = tal_steal(*utx, outputs);
396395
(*utx)->tx = withdraw_tx(*utx, get_chainparams(cmd->ld),
397-
(*utx)->wtx->utxos, (*utx)->outputs,
398-
changekey, (*utx)->wtx->change,
399-
cmd->ld->wallet->bip32_base,
400-
&(*utx)->change_outnum);
396+
(*utx)->wtx->utxos,
397+
(*utx)->outputs,
398+
cmd->ld->wallet->bip32_base);
399+
401400
bitcoin_txid((*utx)->tx, &(*utx)->txid);
402401

403402
return NULL;

0 commit comments

Comments
 (0)