Skip to content

Commit

Permalink
psbt: move witness script storage into the psbt
Browse files Browse the repository at this point in the history
we can now keep associated witness data with the output in the psbt
struct, so we do that.
  • Loading branch information
niftynei authored and rustyrussell committed May 21, 2020
1 parent 2d5c61d commit b076f40
Show file tree
Hide file tree
Showing 18 changed files with 148 additions and 125 deletions.
5 changes: 5 additions & 0 deletions bitcoin/test/run-bitcoin_block_from_hex.c
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,11 @@ u8 *fromwire_tal_arrn(const tal_t *ctx UNNEEDED,
/* Generated stub for fromwire_u16 */
u16 fromwire_u16(const u8 **cursor UNNEEDED, size_t *max UNNEEDED)
{ fprintf(stderr, "fromwire_u16 called!\n"); abort(); }
/* Generated stub for psbt_add_output */
struct wally_psbt_output *psbt_add_output(struct wally_psbt *psbt UNNEEDED,
struct wally_tx_output *output UNNEEDED,
size_t insert_at UNNEEDED)
{ fprintf(stderr, "psbt_add_output called!\n"); abort(); }
/* Generated stub for towire_amount_sat */
void towire_amount_sat(u8 **pptr UNNEEDED, const struct amount_sat sat UNNEEDED)
{ fprintf(stderr, "towire_amount_sat called!\n"); abort(); }
Expand Down
5 changes: 5 additions & 0 deletions bitcoin/test/run-tx-encode.c
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,11 @@ u8 *fromwire_tal_arrn(const tal_t *ctx UNNEEDED,
/* Generated stub for fromwire_u16 */
u16 fromwire_u16(const u8 **cursor UNNEEDED, size_t *max UNNEEDED)
{ fprintf(stderr, "fromwire_u16 called!\n"); abort(); }
/* Generated stub for psbt_add_output */
struct wally_psbt_output *psbt_add_output(struct wally_psbt *psbt UNNEEDED,
struct wally_tx_output *output UNNEEDED,
size_t insert_at UNNEEDED)
{ fprintf(stderr, "psbt_add_output called!\n"); abort(); }
/* Generated stub for towire_amount_sat */
void towire_amount_sat(u8 **pptr UNNEEDED, const struct amount_sat sat UNNEEDED)
{ fprintf(stderr, "towire_amount_sat called!\n"); abort(); }
Expand Down
74 changes: 49 additions & 25 deletions bitcoin/tx.c
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#include <assert.h>
#include <bitcoin/block.h>
#include <bitcoin/chainparams.h>
#include <bitcoin/psbt.h>
#include <bitcoin/pullpush.h>
#include <bitcoin/tx.h>
#include <ccan/cast/cast.h>
Expand All @@ -16,10 +17,11 @@
#define SEGREGATED_WITNESS_FLAG 0x1

int bitcoin_tx_add_output(struct bitcoin_tx *tx, const u8 *script,
struct amount_sat amount)
u8 *wscript, struct amount_sat amount)
{
size_t i = tx->wtx->num_outputs;
struct wally_tx_output *output;
struct wally_psbt_output *psbt_out;
int ret;
u64 satoshis = amount.satoshis; /* Raw: low-level helper */
const struct chainparams *chainparams = tx->chainparams;
Expand Down Expand Up @@ -48,6 +50,14 @@ int bitcoin_tx_add_output(struct bitcoin_tx *tx, const u8 *script,
ret = wally_tx_add_output(tx->wtx, output);
assert(ret == WALLY_OK);

psbt_out = psbt_add_output(tx->psbt, output, i);
if (wscript) {
ret = wally_psbt_output_set_witness_script(psbt_out,
wscript,
tal_bytelen(wscript));
assert(ret == WALLY_OK);
}

wally_tx_output_free(output);
bitcoin_tx_output_set_amount(tx, i, amount);

Expand All @@ -59,7 +69,7 @@ int bitcoin_tx_add_multi_outputs(struct bitcoin_tx *tx,
{
for (size_t j = 0; j < tal_count(outputs); j++)
bitcoin_tx_add_output(tx, outputs[j]->script,
outputs[j]->amount);
NULL, outputs[j]->amount);

return tx->wtx->num_outputs;
}
Expand Down Expand Up @@ -124,7 +134,6 @@ static int elements_tx_add_fee_output(struct bitcoin_tx *tx)
{
struct amount_sat fee = bitcoin_tx_compute_fee(tx);
int pos;
struct witscript *w;

/* If we aren't using elements, we don't add explicit fee outputs */
if (!chainparams->is_elements || amount_sat_eq(fee, AMOUNT_SAT(0)))
Expand All @@ -136,18 +145,9 @@ static int elements_tx_add_fee_output(struct bitcoin_tx *tx)
break;
}

if (pos == tx->wtx->num_outputs) {
w = tal(tx->output_witscripts, struct witscript);
w->ptr = tal_arr(w, u8, 0);

/* Make sure we have a place to stash the witness script in. */
if (tal_count(tx->output_witscripts) < pos + 1) {
tal_resize(&tx->output_witscripts, pos + 1);
}
tx->output_witscripts[pos] = w;

return bitcoin_tx_add_output(tx, NULL, fee);
} else {
if (pos == tx->wtx->num_outputs)
return bitcoin_tx_add_output(tx, NULL, NULL, fee);
else {
bitcoin_tx_output_set_amount(tx, pos, fee);
return pos;
}
Expand Down Expand Up @@ -177,6 +177,7 @@ int bitcoin_tx_add_input(struct bitcoin_tx *tx, const struct bitcoin_txid *txid,
tx->input_amounts[i] = tal_free(tx->input_amounts[i]);
tx->input_amounts[i] = tal_dup(tx, struct amount_sat, &amount);


return i;
}

Expand All @@ -189,9 +190,6 @@ bool bitcoin_tx_check(const struct bitcoin_tx *tx)
if (tal_count(tx->input_amounts) != tx->wtx->num_inputs)
return false;

if (tal_count(tx->output_witscripts) != tx->wtx->num_outputs)
return false;

if (wally_tx_get_length(tx->wtx, flags, &written) != WALLY_OK)
return false;

Expand Down Expand Up @@ -240,6 +238,38 @@ const u8 *bitcoin_tx_output_get_script(const tal_t *ctx,
return res;
}

struct witscript *bitcoin_tx_output_get_witscript(const tal_t *ctx,
const struct bitcoin_tx *tx,
int outnum)
{
struct witscript *wit;
struct wally_psbt_output *out;
assert(outnum < tx->psbt->num_outputs);
out = &tx->psbt->outputs[outnum];

if (out->witness_script_len == 0)
return NULL;

wit = tal(ctx, struct witscript);
wit->ptr = tal_dup_arr(ctx, u8, out->witness_script, out->witness_script_len, 0);

return wit;
}

const struct witscript **bitcoin_tx_get_witscripts(const tal_t *ctx,
const struct bitcoin_tx *tx)
{
size_t i;
struct witscript **witscripts;
witscripts = tal_arr(ctx, struct witscript *, tx->wtx->num_outputs);

for (i = 0; i < tx->wtx->num_outputs; i++)
witscripts[i] = bitcoin_tx_output_get_witscript(witscripts, tx, i);

return cast_const2(const struct witscript **, witscripts);
}


/* FIXME(cdecker) Make the caller pass in a reference to amount_asset, and
* return false if unintelligible/encrypted. (WARN UNUSED). */
struct amount_asset bitcoin_tx_output_get_amount(const struct bitcoin_tx *tx,
Expand Down Expand Up @@ -446,7 +476,6 @@ struct bitcoin_tx *bitcoin_tx(const tal_t *ctx,
tx->input_amounts = tal_arrz(tx, struct amount_sat*, input_count);
tx->wtx->locktime = nlocktime;
tx->wtx->version = 2;
tx->output_witscripts = tal_arrz(tx, struct witscript*, output_count);
tx->chainparams = chainparams;

ret = wally_psbt_init_alloc(input_count, output_count,
Expand All @@ -459,12 +488,9 @@ struct bitcoin_tx *bitcoin_tx(const tal_t *ctx,

void bitcoin_tx_finalize(struct bitcoin_tx *tx)
{
size_t num_outputs, num_inputs;
size_t num_inputs;
elements_tx_add_fee_output(tx);

num_outputs = tx->wtx->num_outputs;
tal_resize(&(tx->output_witscripts), num_outputs);

num_inputs = tx->wtx->num_inputs;
tal_resize(&tx->input_amounts, num_inputs);
assert(bitcoin_tx_check(tx));
Expand Down Expand Up @@ -539,8 +565,6 @@ struct bitcoin_tx *bitcoin_tx_from_hex(const tal_t *ctx, const char *hex,

tal_free(linear_tx);

tx->output_witscripts =
tal_arrz(tx, struct witscript *, tx->wtx->num_outputs);
tx->input_amounts =
tal_arrz(tx, struct amount_sat *, tx->wtx->num_inputs);

Expand Down
13 changes: 10 additions & 3 deletions bitcoin/tx.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,6 @@ struct bitcoin_tx {
struct amount_sat **input_amounts;
struct wally_tx *wtx;

/* Need the output wscripts in the HSM to validate transaction */
struct witscript **output_witscripts;

/* Keep a reference to the ruleset we have to abide by */
const struct chainparams *chainparams;

Expand Down Expand Up @@ -78,6 +75,7 @@ struct bitcoin_tx *pull_bitcoin_tx(const tal_t *ctx,
const u8 **cursor, size_t *max);
/* Add one output to tx. */
int bitcoin_tx_add_output(struct bitcoin_tx *tx, const u8 *script,
u8 *wscript,
struct amount_sat amount);

/* Add mutiple output to tx. */
Expand Down Expand Up @@ -109,6 +107,15 @@ void bitcoin_tx_output_set_amount(struct bitcoin_tx *tx, int outnum,
*/
const u8 *bitcoin_tx_output_get_script(const tal_t *ctx, const struct bitcoin_tx *tx, int outnum);

/**
* Helper to get a witness script for an output.
*/
struct witscript *bitcoin_tx_output_get_witscript(const tal_t *ctx, const struct bitcoin_tx *tx, int outnum);

/**
* Helper to get all witness scripts for a transaction.
*/
const struct witscript **bitcoin_tx_get_witscripts(const tal_t *ctx, const struct bitcoin_tx *tx);
/** bitcoin_tx_output_get_amount_sat - Helper to get transaction output's amount
*
* Internally we use a `wally_tx` to represent the transaction. The
Expand Down
25 changes: 16 additions & 9 deletions channeld/channeld.c
Original file line number Diff line number Diff line change
Expand Up @@ -837,13 +837,14 @@ static secp256k1_ecdsa_signature *calc_commitsigs(const tal_t *ctx,
size_t i;
struct pubkey local_htlckey;
const u8 *msg;
const struct witscript **ws;
secp256k1_ecdsa_signature *htlc_sigs;

ws = bitcoin_tx_get_witscripts(tmpctx, txs[0]);
msg = towire_hsm_sign_remote_commitment_tx(NULL, txs[0],
&peer->channel->funding_pubkey[REMOTE],
*txs[0]->input_amounts[0],
(const struct witscript **) txs[0]->output_witscripts,
&peer->remote_per_commit,
ws, &peer->remote_per_commit,
peer->channel->option_static_remotekey);

msg = hsm_req(tmpctx, take(msg));
Expand Down Expand Up @@ -879,8 +880,11 @@ static secp256k1_ecdsa_signature *calc_commitsigs(const tal_t *ctx,

for (i = 0; i < tal_count(htlc_sigs); i++) {
struct bitcoin_signature sig;
msg = towire_hsm_sign_remote_htlc_tx(NULL, txs[i + 1],
txs[i+1]->output_witscripts[0]->ptr,
struct witscript *w;

w = bitcoin_tx_output_get_witscript(tmpctx, txs[0],
txs[i+1]->wtx->inputs[0].index);
msg = towire_hsm_sign_remote_htlc_tx(NULL, txs[i + 1], w->ptr,
*txs[i+1]->input_amounts[0],
&peer->remote_per_commit);

Expand All @@ -895,11 +899,10 @@ static secp256k1_ecdsa_signature *calc_commitsigs(const tal_t *ctx,
type_to_string(tmpctx, struct bitcoin_signature,
&sig),
type_to_string(tmpctx, struct bitcoin_tx, txs[1+i]),
tal_hex(tmpctx, txs[i+1]->output_witscripts[0]->ptr),
tal_hex(tmpctx, w->ptr),
type_to_string(tmpctx, struct pubkey,
&local_htlckey));
assert(check_tx_sig(txs[1+i], 0, NULL,
txs[i+1]->output_witscripts[0]->ptr,
assert(check_tx_sig(txs[1+i], 0, NULL, w->ptr,
&local_htlckey,
&sig));
}
Expand Down Expand Up @@ -1346,19 +1349,23 @@ static void handle_peer_commit_sig(struct peer *peer, const u8 *msg)
*/
for (i = 0; i < tal_count(htlc_sigs); i++) {
struct bitcoin_signature sig;
struct witscript *w;

w = bitcoin_tx_output_get_witscript(tmpctx, txs[0],
txs[i+1]->wtx->inputs[0].index);

/* SIGHASH_ALL is implied. */
sig.s = htlc_sigs[i];
sig.sighash_type = SIGHASH_ALL;

if (!check_tx_sig(txs[1+i], 0, NULL, txs[1+i]->output_witscripts[0]->ptr,
if (!check_tx_sig(txs[1+i], 0, NULL, w->ptr,
&remote_htlckey, &sig))
peer_failed(peer->pps,
&peer->channel_id,
"Bad commit_sig signature %s for htlc %s wscript %s key %s",
type_to_string(msg, struct bitcoin_signature, &sig),
type_to_string(msg, struct bitcoin_tx, txs[1+i]),
tal_hex(msg, txs[1+i]->output_witscripts[0]->ptr),
tal_hex(msg, w->ptr),
type_to_string(msg, struct pubkey,
&remote_htlckey));
}
Expand Down
33 changes: 8 additions & 25 deletions channeld/commit_tx.c
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,7 @@ size_t commit_tx_num_untrimmed(const struct htlc **htlcs,

static void add_offered_htlc_out(struct bitcoin_tx *tx, size_t n,
const struct htlc *htlc,
const struct keyset *keyset,
struct witscript *o_wscript)
const struct keyset *keyset)
{
struct ripemd160 ripemd;
u8 *wscript, *p2wsh;
Expand All @@ -46,19 +45,16 @@ static void add_offered_htlc_out(struct bitcoin_tx *tx, size_t n,
ripemd160(&ripemd, htlc->rhash.u.u8, sizeof(htlc->rhash.u.u8));
wscript = htlc_offered_wscript(tx, &ripemd, keyset);
p2wsh = scriptpubkey_p2wsh(tx, wscript);
bitcoin_tx_add_output(tx, p2wsh, amount);
bitcoin_tx_add_output(tx, p2wsh, wscript, amount);
SUPERVERBOSE("# HTLC %" PRIu64 " offered %s wscript %s\n", htlc->id,
type_to_string(tmpctx, struct amount_sat, &amount),
tal_hex(wscript, wscript));
o_wscript->ptr = tal_dup_arr(o_wscript, u8, wscript,
tal_count(wscript), 0);
tal_free(wscript);
}

static void add_received_htlc_out(struct bitcoin_tx *tx, size_t n,
const struct htlc *htlc,
const struct keyset *keyset,
struct witscript *o_wscript)
const struct keyset *keyset)
{
struct ripemd160 ripemd;
u8 *wscript, *p2wsh;
Expand All @@ -69,15 +65,13 @@ static void add_received_htlc_out(struct bitcoin_tx *tx, size_t n,
p2wsh = scriptpubkey_p2wsh(tx, wscript);
amount = amount_msat_to_sat_round_down(htlc->amount);

bitcoin_tx_add_output(tx, p2wsh, amount);
bitcoin_tx_add_output(tx, p2wsh, wscript, amount);

SUPERVERBOSE("# HTLC %"PRIu64" received %s wscript %s\n",
htlc->id,
type_to_string(tmpctx, struct amount_sat,
&amount),
tal_hex(wscript, wscript));
o_wscript->ptr = tal_dup_arr(o_wscript, u8,
wscript, tal_count(wscript), 0);
tal_free(wscript);
}

Expand Down Expand Up @@ -177,10 +171,7 @@ struct bitcoin_tx *commit_tx(const tal_t *ctx,
continue;
if (trim(htlcs[i], feerate_per_kw, dust_limit, side))
continue;
tx->output_witscripts[n] =
tal(tx->output_witscripts, struct witscript);
add_offered_htlc_out(tx, n, htlcs[i],
keyset, tx->output_witscripts[n]);
add_offered_htlc_out(tx, n, htlcs[i], keyset);
(*htlcmap)[n] = htlcs[i];
cltvs[n] = abs_locktime_to_blocks(&htlcs[i]->expiry);
n++;
Expand All @@ -196,10 +187,7 @@ struct bitcoin_tx *commit_tx(const tal_t *ctx,
continue;
if (trim(htlcs[i], feerate_per_kw, dust_limit, side))
continue;
tx->output_witscripts[n] =
tal(tx->output_witscripts, struct witscript);
add_received_htlc_out(tx, n, htlcs[i], keyset,
tx->output_witscripts[n]);
add_received_htlc_out(tx, n, htlcs[i], keyset);
(*htlcmap)[n] = htlcs[i];
cltvs[n] = abs_locktime_to_blocks(&htlcs[i]->expiry);
n++;
Expand All @@ -216,19 +204,14 @@ struct bitcoin_tx *commit_tx(const tal_t *ctx,
u8 *p2wsh = scriptpubkey_p2wsh(tx, wscript);
struct amount_sat amount = amount_msat_to_sat_round_down(self_pay);

bitcoin_tx_add_output(tx, p2wsh, amount);
bitcoin_tx_add_output(tx, p2wsh, wscript, amount);
/* Add a dummy entry to the htlcmap so we can recognize it later */
(*htlcmap)[n] = direct_outputs ? dummy_to_local : NULL;
/* We don't assign cltvs[n]: if we use it, order doesn't matter.
* However, valgrind will warn us something wierd is happening */
SUPERVERBOSE("# to-local amount %s wscript %s\n",
type_to_string(tmpctx, struct amount_sat, &amount),
tal_hex(tmpctx, wscript));
tx->output_witscripts[n] =
tal(tx->output_witscripts, struct witscript);
tx->output_witscripts[n]->ptr =
tal_dup_arr(tx->output_witscripts[n], u8,
wscript, tal_count(wscript), 0);
n++;
}

Expand All @@ -249,7 +232,7 @@ struct bitcoin_tx *commit_tx(const tal_t *ctx,
* This output sends funds to the other peer and thus is a simple
* P2WPKH to `remotepubkey`.
*/
int pos = bitcoin_tx_add_output(tx, p2wpkh, amount);
int pos = bitcoin_tx_add_output(tx, p2wpkh, NULL, amount);
assert(pos == n);
(*htlcmap)[n] = direct_outputs ? dummy_to_remote : NULL;
/* We don't assign cltvs[n]: if we use it, order doesn't matter.
Expand Down
Loading

0 comments on commit b076f40

Please sign in to comment.