From 251cde3514047a0d4f3a32d4e9b4ec2a38bea392 Mon Sep 17 00:00:00 2001 From: niftynei Date: Wed, 22 Jul 2020 21:03:59 -0500 Subject: [PATCH] psbt: add helpers for creating + adding input/outputs --- bitcoin/psbt.c | 91 ++++++++++++++++++++++++++++++++++++++++++++++++++ bitcoin/psbt.h | 58 ++++++++++++++++++++++++++++++-- 2 files changed, 147 insertions(+), 2 deletions(-) diff --git a/bitcoin/psbt.c b/bitcoin/psbt.c index 1b4740f03..81c973977 100644 --- a/bitcoin/psbt.c +++ b/bitcoin/psbt.c @@ -21,6 +21,36 @@ void psbt_destroy(struct wally_psbt *psbt) wally_psbt_free(psbt); } +static struct wally_psbt *init_psbt(const tal_t *ctx, size_t num_inputs, size_t num_outputs) +{ + int wally_err; + struct wally_psbt *psbt; + + if (is_elements(chainparams)) + wally_err = wally_psbt_elements_init_alloc(0, num_inputs, num_outputs, 0, &psbt); + else + wally_err = wally_psbt_init_alloc(0, num_inputs, num_outputs, 0, &psbt); + assert(wally_err == WALLY_OK); + tal_add_destructor(psbt, psbt_destroy); + return tal_steal(ctx, psbt); +} + +struct wally_psbt *create_psbt(const tal_t *ctx, size_t num_inputs, size_t num_outputs) +{ + int wally_err; + struct wally_tx *wtx; + struct wally_psbt *psbt; + + if (wally_tx_init_alloc(WALLY_TX_VERSION_2, 0, num_inputs, num_outputs, &wtx) != WALLY_OK) + abort(); + + psbt = init_psbt(ctx, num_inputs, num_outputs); + + wally_err = wally_psbt_set_global_tx(psbt, wtx); + assert(wally_err == WALLY_OK); + return psbt; +} + struct wally_psbt *new_psbt(const tal_t *ctx, const struct wally_tx *wtx) { struct wally_psbt *psbt; @@ -80,6 +110,28 @@ struct wally_psbt_input *psbt_add_input(struct wally_psbt *psbt, return &psbt->inputs[insert_at]; } +struct wally_psbt_input *psbt_append_input(struct wally_psbt *psbt, + const struct bitcoin_txid *txid, + u32 outnum, u32 sequence) +{ + struct wally_tx_input *tx_in; + struct wally_psbt_input *input; + size_t insert_at; + + insert_at = psbt->num_inputs; + + if (wally_tx_input_init_alloc(txid->shad.sha.u.u8, + sizeof(struct bitcoin_txid), + outnum, sequence, NULL, 0, NULL, + &tx_in) != WALLY_OK) + abort(); + + tx_in->features = chainparams->is_elements ? WALLY_TX_IS_ELEMENTS : 0; + input = psbt_add_input(psbt, tx_in, insert_at); + wally_tx_input_free(tx_in); + return input; +} + void psbt_rm_input(struct wally_psbt *psbt, size_t remove_at) { @@ -96,6 +148,18 @@ struct wally_psbt_output *psbt_add_output(struct wally_psbt *psbt, return &psbt->outputs[insert_at]; } +struct wally_psbt_output *psbt_append_out(struct wally_psbt *psbt, + const u8 *script, + struct amount_sat amount) +{ + struct wally_psbt_output *out; + struct wally_tx_output *tx_out = wally_tx_output(script, amount); + + out = psbt_add_output(psbt, tx_out, psbt->tx->num_outputs); + wally_tx_output_free(tx_out); + return out; +} + void psbt_rm_output(struct wally_psbt *psbt, size_t remove_at) { @@ -298,6 +362,24 @@ void psbt_elements_input_init(struct wally_psbt *psbt, size_t in, abort(); } +bool psbt_has_input(struct wally_psbt *psbt, + struct bitcoin_txid *txid, + u32 outnum) +{ + for (size_t i = 0; i < psbt->num_inputs; i++) { + struct bitcoin_txid in_txid; + struct wally_tx_input *in = &psbt->tx->inputs[i]; + + if (outnum != in->index) + continue; + + wally_tx_input_get_txid(in, &in_txid); + if (bitcoin_txid_eq(txid, &in_txid)) + return true; + } + return false; +} + bool psbt_input_set_redeemscript(struct wally_psbt *psbt, size_t in, const u8 *redeemscript) { @@ -329,6 +411,15 @@ struct amount_sat psbt_input_get_amount(struct wally_psbt *psbt, return val; } +struct amount_sat psbt_output_get_amount(struct wally_psbt *psbt, + size_t out) +{ + struct amount_asset asset; + assert(out < psbt->num_outputs); + asset = wally_tx_output_get_amount(&psbt->tx->outputs[out]); + assert(amount_asset_is_main(&asset)); + return amount_asset_to_sat(&asset); +} struct wally_tx *psbt_finalize(struct wally_psbt *psbt, bool finalize_in_place) { struct wally_psbt *tmppsbt; diff --git a/bitcoin/psbt.h b/bitcoin/psbt.h index ff154d985..40e572296 100644 --- a/bitcoin/psbt.h +++ b/bitcoin/psbt.h @@ -5,11 +5,11 @@ #include #include -struct wally_tx_input; -struct wally_tx_output; struct wally_psbt; struct wally_psbt_input; struct wally_tx; +struct wally_tx_input; +struct wally_tx_output; struct amount_asset; struct amount_sat; struct bitcoin_signature; @@ -18,6 +18,22 @@ struct pubkey; void psbt_destroy(struct wally_psbt *psbt); +/** + * create_psbt - Create a new psbt object + * + * @ctx - allocation context + * @num_inputs - number of inputs to allocate + * @num_outputs - number of outputs to allocate + */ +struct wally_psbt *create_psbt(const tal_t *ctx, size_t num_inputs, size_t num_outputs); + +/* + * new_psbt - Create a PSBT, using the passed in tx + * as the global_tx + * + * @ctx - allocation context + * @wtx - global_tx starter kit + */ struct wally_psbt *new_psbt(const tal_t *ctx, const struct wally_tx *wtx); @@ -47,6 +63,10 @@ struct wally_psbt_input *psbt_add_input(struct wally_psbt *psbt, struct wally_tx_input *input, size_t insert_at); +struct wally_psbt_input *psbt_append_input(struct wally_psbt *psbt, + const struct bitcoin_txid *txid, + u32 outnum, u32 sequence); + void psbt_rm_input(struct wally_psbt *psbt, size_t remove_at); @@ -54,6 +74,17 @@ struct wally_psbt_output *psbt_add_output(struct wally_psbt *psbt, struct wally_tx_output *output, size_t insert_at); +/** + * wally_psbt_output - Append a new output to the PSBT + * + * @psbt - PSBT to append output to + * @script - scriptPubKey of the output + * @amount - value of the output + */ +struct wally_psbt_output *psbt_append_out(struct wally_psbt *psbt, + const u8 *script, + struct amount_sat amount); + void psbt_rm_output(struct wally_psbt *psbt, size_t remove_at); @@ -81,9 +112,32 @@ void psbt_elements_input_init_witness(struct wally_psbt *psbt, size_t in, const u8 *nonce); bool psbt_input_set_redeemscript(struct wally_psbt *psbt, size_t in, const u8 *redeemscript); +/* psbt_input_get_amount - Returns the value of this input + * + * @psbt - psbt + * @in - index of input whose value you're returning + * */ struct amount_sat psbt_input_get_amount(struct wally_psbt *psbt, size_t in); +/* psbt_output_get_amount - Returns the value of this output + * + * @psbt - psbt + * @out -index of output whose value you're returning + */ +struct amount_sat psbt_output_get_amount(struct wally_psbt *psbt, + size_t out); + +/* psbt_has_input - Is this input present on this psbt + * + * @psbt - psbt + * @txid - txid of input + * @outnum - output index of input + */ +bool psbt_has_input(struct wally_psbt *psbt, + struct bitcoin_txid *txid, + u32 outnum); + struct wally_psbt *psbt_from_b64(const tal_t *ctx, const char *b64, size_t b64len);