Skip to content

Commit

Permalink
psbt: clean up interface for setting metadata on PSBT inputs
Browse files Browse the repository at this point in the history
it's just neater if it's not all wrapped up together, simplifies the
interface a smidge
  • Loading branch information
niftynei authored and rustyrussell committed Sep 9, 2020
1 parent 169b781 commit 303263d
Show file tree
Hide file tree
Showing 31 changed files with 92 additions and 280 deletions.
193 changes: 20 additions & 173 deletions bitcoin/psbt.c
Original file line number Diff line number Diff line change
Expand Up @@ -110,8 +110,6 @@ struct wally_psbt_input *psbt_append_input(struct wally_psbt *psbt,
const struct bitcoin_txid *txid,
u32 outnum, u32 sequence,
const u8 *scriptSig,
struct amount_sat amount,
const u8 *scriptPubkey,
const u8 *input_wscript,
const u8 *redeemscript)
{
Expand Down Expand Up @@ -145,52 +143,7 @@ struct wally_psbt_input *psbt_append_input(struct wally_psbt *psbt,

if (input_wscript) {
/* Add the prev output's data into the PSBT struct */
if (is_elements(chainparams)) {
struct amount_asset asset;
/*FIXME: persist asset tags */
asset = amount_sat_to_asset(
&amount,
chainparams->fee_asset_tag);
psbt_elements_input_init_witness(psbt, input_num,
input_wscript,
&asset, NULL);
} else
psbt_input_set_prev_utxo_wscript(psbt, input_num,
input_wscript,
amount);
} else if (scriptPubkey) {
if (is_p2wsh(scriptPubkey, NULL) ||
is_p2wpkh(scriptPubkey, NULL) ||
/* FIXME: assert that p2sh inputs are
* witness/are accompanied by a
* redeemscript+witnessscript */
is_p2sh(scriptPubkey, NULL)) {
/* the only way to get here currently with
* a p2sh script is via a p2sh-p2wpkh script
* that we've created ...*/
/* BIP0174:
* ** Value: The entire transaction output in
* network serialization which the
* current input spends from.
* This should only be present for
* inputs which spend segwit outputs,
* including P2SH embedded ones.
*/
if (is_elements(chainparams)) {
struct amount_asset asset;
/*FIXME: persist asset tags */
asset = amount_sat_to_asset(
&amount,
chainparams->fee_asset_tag);
/* FIXME: persist nonces */
psbt_elements_input_init(psbt, input_num,
scriptPubkey,
&asset, NULL);
} else
psbt_input_set_prev_utxo(psbt, input_num,
scriptPubkey,
amount);
}
psbt_input_set_witscript(psbt, input_num, input_wscript);
}

if (redeemscript) {
Expand Down Expand Up @@ -284,149 +237,43 @@ bool psbt_input_set_signature(struct wally_psbt *psbt, size_t in,
sizeof(sig->s.data)) == WALLY_OK;
}

static void psbt_input_set_witness_utxo(struct wally_psbt *psbt, size_t in,
const struct wally_tx_output *txout)
void psbt_input_set_wit_utxo(struct wally_psbt *psbt, size_t in,
const u8 *scriptPubkey, struct amount_sat amt)
{
struct wally_tx_output tx_out;
int wally_err;
assert(psbt->num_inputs > in);
wally_err = wally_psbt_input_set_witness_utxo(&psbt->inputs[in],
txout);
assert(wally_err == WALLY_OK);
}

void psbt_input_set_prev_utxo(struct wally_psbt *psbt, size_t in,
const u8 *scriptPubkey, struct amount_sat amt)
{
struct wally_tx_output prev_out;
int wally_err;
u8 *scriptpk;

if (scriptPubkey) {
assert(is_p2wsh(scriptPubkey, NULL) || is_p2wpkh(scriptPubkey, NULL)
|| is_p2sh(scriptPubkey, NULL));
scriptpk = cast_const(u8 *, scriptPubkey);
} else {
/* Adding a NULL scriptpubkey is an error, *however* there is the
* possiblity we're spending a UTXO that we didn't save the
* scriptpubkey data for. in this case we set it to an 'empty'
* or zero-len script */
scriptpk = tal_arr(psbt, u8, 1);
scriptpk[0] = 0x00;
}

assert(in < psbt->num_inputs);
assert(tal_bytelen(scriptPubkey) > 0);
wally_err = wally_tx_output_init(amt.satoshis, /* Raw: type conv */
scriptpk,
tal_bytelen(scriptpk),
&prev_out);
scriptPubkey,
tal_bytelen(scriptPubkey),
&tx_out);
assert(wally_err == WALLY_OK);
psbt_input_set_witness_utxo(psbt, in, &prev_out);
}

static void psbt_input_set_elements_prev_utxo(struct wally_psbt *psbt,
size_t in,
const u8 *scriptPubkey,
struct amount_asset *asset,
const u8 *nonce)
{
struct wally_tx_output prev_out;
int wally_err;

u8 *prefixed_value = amount_asset_extract_value(psbt, asset);

wally_err =
wally_tx_elements_output_init(scriptPubkey,
tal_bytelen(scriptPubkey),
asset->asset,
sizeof(asset->asset),
prefixed_value,
tal_bytelen(prefixed_value),
nonce,
tal_bytelen(nonce),
NULL, 0,
NULL, 0,
&prev_out);
wally_err = wally_psbt_input_set_witness_utxo(&psbt->inputs[in],
&tx_out);
assert(wally_err == WALLY_OK);
psbt_input_set_witness_utxo(psbt, in, &prev_out);
}

void psbt_input_set_prev_utxo_wscript(struct wally_psbt *psbt, size_t in,
const u8 *wscript, struct amount_sat amt)
{
int wally_err;
const u8 *scriptPubkey;

if (wscript) {
scriptPubkey = scriptpubkey_p2wsh(psbt, wscript);
wally_err = wally_psbt_input_set_witness_script(&psbt->inputs[in],
wscript,
tal_bytelen(wscript));
assert(wally_err == WALLY_OK);
} else
scriptPubkey = NULL;
psbt_input_set_prev_utxo(psbt, in, scriptPubkey, amt);
}

static void
psbt_input_set_elements_prev_utxo_wscript(struct wally_psbt *psbt,
size_t in,
const u8 *wscript,
struct amount_asset *asset,
const u8 *nonce)
void psbt_input_set_witscript(struct wally_psbt *psbt, size_t in, const u8 *wscript)
{
int wally_err;
const u8 *scriptPubkey;

if (wscript) {
scriptPubkey = scriptpubkey_p2wsh(psbt, wscript);
wally_err = wally_psbt_input_set_witness_script(
&psbt->inputs[in],
wscript, tal_bytelen(wscript));
assert(wally_err == WALLY_OK);
} else
scriptPubkey = NULL;

psbt_input_set_elements_prev_utxo(psbt, in, scriptPubkey,
asset, nonce);
wally_err = wally_psbt_input_set_witness_script(&psbt->inputs[in],
wscript,
tal_bytelen(wscript));
assert(wally_err == WALLY_OK);
}

void psbt_elements_input_init_witness(struct wally_psbt *psbt, size_t in,
const u8 *witscript,
struct amount_asset *asset,
const u8 *nonce)
void psbt_elements_input_set_asset(struct wally_psbt *psbt, size_t in,
struct amount_asset *asset)
{
psbt_input_set_elements_prev_utxo_wscript(
psbt, in, witscript,
asset, nonce);

if (asset->value > 0)
wally_psbt_input_set_value(&psbt->inputs[in], asset->value);

/* PSET expects an asset tag without the prefix */
if (wally_psbt_input_set_asset(&psbt->inputs[in],
asset->asset + 1,
ELEMENTS_ASSET_LEN - 1) != WALLY_OK)
abort();
}

void psbt_elements_input_init(struct wally_psbt *psbt, size_t in,
const u8 *scriptPubkey,
struct amount_asset *asset,
const u8 *nonce)
{
psbt_input_set_elements_prev_utxo(psbt, in,
scriptPubkey,
asset, nonce);

if (asset->value > 0) {
if (wally_psbt_input_set_value(
&psbt->inputs[in],
asset->value) != WALLY_OK)
if (wally_psbt_input_set_value(&psbt->inputs[in],
asset->value) != WALLY_OK)
abort();

}

/* PSET expects an asset tag without the prefix */
/* FIXME: Verify that we're sending unblinded asset tag */
if (wally_psbt_input_set_asset(&psbt->inputs[in],
asset->asset + 1,
ELEMENTS_ASSET_LEN - 1) != WALLY_OK)
Expand Down
19 changes: 10 additions & 9 deletions bitcoin/psbt.h
Original file line number Diff line number Diff line change
Expand Up @@ -90,11 +90,18 @@ struct wally_psbt_input *psbt_append_input(struct wally_psbt *psbt,
const struct bitcoin_txid *txid,
u32 outnum, u32 sequence,
const u8 *scriptSig,
struct amount_sat amount,
const u8 *scriptPubkey,
const u8 *input_wscript,
const u8 *redeemscript);

/* psbt_input_set_wit_utxo - Set the witness_utxo field for this PSBT */
void psbt_input_set_wit_utxo(struct wally_psbt *psbt, size_t in,
const u8 *scriptPubkey, struct amount_sat amt);

/* psbt_elements_input_set_asset - Set the asset/value fields for an
* Elements PSBT (PSET, technically */
void psbt_elements_input_set_asset(struct wally_psbt *psbt, size_t in,
struct amount_asset *asset);

void psbt_rm_input(struct wally_psbt *psbt,
size_t remove_at);

Expand Down Expand Up @@ -123,13 +130,7 @@ WARN_UNUSED_RESULT bool psbt_input_set_signature(struct wally_psbt *psbt, size_t
const struct pubkey *pubkey,
const struct bitcoin_signature *sig);

void psbt_input_set_prev_utxo(struct wally_psbt *psbt,
size_t in,
const u8 *wscript,
struct amount_sat amt);
void psbt_input_set_prev_utxo_wscript(struct wally_psbt *psbt, size_t in,
const u8 *wscript,
struct amount_sat amt);
void psbt_input_set_witscript(struct wally_psbt *psbt, size_t in, const u8 *wscript);
void psbt_elements_input_init(struct wally_psbt *psbt, size_t in,
const u8 *scriptPubkey,
struct amount_asset *asset,
Expand Down
12 changes: 0 additions & 12 deletions bitcoin/test/run-bitcoin_block_from_hex.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,6 @@
#include <common/setup.h>

/* AUTOGENERATED MOCKS START */
/* Generated stub for amount_asset_extract_value */
u8 *amount_asset_extract_value(const tal_t *ctx UNNEEDED, struct amount_asset *asset UNNEEDED)
{ fprintf(stderr, "amount_asset_extract_value called!\n"); abort(); }
/* Generated stub for amount_asset_is_main */
bool amount_asset_is_main(struct amount_asset *asset UNNEEDED)
{ fprintf(stderr, "amount_asset_is_main called!\n"); abort(); }
Expand Down Expand Up @@ -66,15 +63,6 @@ u32 fromwire_u32(const u8 **cursor UNNEEDED, size_t *max UNNEEDED)
/* Generated stub for is_anchor_witness_script */
bool is_anchor_witness_script(const u8 *script UNNEEDED, size_t script_len UNNEEDED)
{ fprintf(stderr, "is_anchor_witness_script called!\n"); abort(); }
/* Generated stub for is_p2sh */
bool is_p2sh(const u8 *script UNNEEDED, struct ripemd160 *addr UNNEEDED)
{ fprintf(stderr, "is_p2sh called!\n"); abort(); }
/* Generated stub for is_p2wpkh */
bool is_p2wpkh(const u8 *script UNNEEDED, struct bitcoin_address *addr UNNEEDED)
{ fprintf(stderr, "is_p2wpkh called!\n"); abort(); }
/* Generated stub for is_p2wsh */
bool is_p2wsh(const u8 *script UNNEEDED, struct sha256 *addr UNNEEDED)
{ fprintf(stderr, "is_p2wsh called!\n"); abort(); }
/* Generated stub for pubkey_to_der */
void pubkey_to_der(u8 der[PUBKEY_CMPR_LEN] UNNEEDED, const struct pubkey *key UNNEEDED)
{ fprintf(stderr, "pubkey_to_der called!\n"); abort(); }
Expand Down
12 changes: 0 additions & 12 deletions bitcoin/test/run-tx-encode.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,6 @@
#include <common/utils.h>

/* AUTOGENERATED MOCKS START */
/* Generated stub for amount_asset_extract_value */
u8 *amount_asset_extract_value(const tal_t *ctx UNNEEDED, struct amount_asset *asset UNNEEDED)
{ fprintf(stderr, "amount_asset_extract_value called!\n"); abort(); }
/* Generated stub for amount_asset_is_main */
bool amount_asset_is_main(struct amount_asset *asset UNNEEDED)
{ fprintf(stderr, "amount_asset_is_main called!\n"); abort(); }
Expand Down Expand Up @@ -67,15 +64,6 @@ u32 fromwire_u32(const u8 **cursor UNNEEDED, size_t *max UNNEEDED)
/* Generated stub for is_anchor_witness_script */
bool is_anchor_witness_script(const u8 *script UNNEEDED, size_t script_len UNNEEDED)
{ fprintf(stderr, "is_anchor_witness_script called!\n"); abort(); }
/* Generated stub for is_p2sh */
bool is_p2sh(const u8 *script UNNEEDED, struct ripemd160 *addr UNNEEDED)
{ fprintf(stderr, "is_p2sh called!\n"); abort(); }
/* Generated stub for is_p2wpkh */
bool is_p2wpkh(const u8 *script UNNEEDED, struct bitcoin_address *addr UNNEEDED)
{ fprintf(stderr, "is_p2wpkh called!\n"); abort(); }
/* Generated stub for is_p2wsh */
bool is_p2wsh(const u8 *script UNNEEDED, struct sha256 *addr UNNEEDED)
{ fprintf(stderr, "is_p2wsh called!\n"); abort(); }
/* Generated stub for pubkey_to_der */
void pubkey_to_der(u8 der[PUBKEY_CMPR_LEN] UNNEEDED, const struct pubkey *key UNNEEDED)
{ fprintf(stderr, "pubkey_to_der called!\n"); abort(); }
Expand Down
21 changes: 19 additions & 2 deletions bitcoin/tx.c
Original file line number Diff line number Diff line change
Expand Up @@ -191,14 +191,31 @@ int bitcoin_tx_add_input(struct bitcoin_tx *tx, const struct bitcoin_txid *txid,
int input_num = tx->wtx->num_inputs;

psbt_append_input(tx->psbt, txid, outnum, sequence, scriptSig,
amount, scriptPubkey, input_wscript, NULL);
input_wscript, NULL);

if (input_wscript) {
scriptPubkey = scriptpubkey_p2wsh(tx->psbt, input_wscript);
}

assert(scriptPubkey);
psbt_input_set_wit_utxo(tx->psbt, input_num,
scriptPubkey, amount);
wally_err = wally_tx_add_input(tx->wtx,
&tx->psbt->tx->inputs[input_num]);
assert(wally_err == WALLY_OK);
/* scriptsig isn't actually store in psbt input, so add that now */

/* scriptsig isn't actually stored in psbt input, so add that now */
wally_tx_set_input_script(tx->wtx, input_num,
scriptSig, tal_bytelen(scriptSig));

if (is_elements(chainparams)) {
struct amount_asset asset;
/* FIXME: persist asset tags */
asset = amount_sat_to_asset(&amount,
chainparams->fee_asset_tag);
/* FIXME: persist nonces */
psbt_elements_input_set_asset(tx->psbt, input_num, &asset);
}
return input_num;
}

Expand Down
3 changes: 0 additions & 3 deletions cli/test/run-large-input.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,6 @@ int test_chdir(const char *path);
#undef main

/* AUTOGENERATED MOCKS START */
/* Generated stub for amount_asset_extract_value */
u8 *amount_asset_extract_value(const tal_t *ctx UNNEEDED, struct amount_asset *asset UNNEEDED)
{ fprintf(stderr, "amount_asset_extract_value called!\n"); abort(); }
/* Generated stub for amount_asset_is_main */
bool amount_asset_is_main(struct amount_asset *asset UNNEEDED)
{ fprintf(stderr, "amount_asset_is_main called!\n"); abort(); }
Expand Down
3 changes: 0 additions & 3 deletions cli/test/run-remove-hint.c
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,6 @@ int test_chdir(const char *path);
#undef main

/* AUTOGENERATED MOCKS START */
/* Generated stub for amount_asset_extract_value */
u8 *amount_asset_extract_value(const tal_t *ctx UNNEEDED, struct amount_asset *asset UNNEEDED)
{ fprintf(stderr, "amount_asset_extract_value called!\n"); abort(); }
/* Generated stub for amount_asset_is_main */
bool amount_asset_is_main(struct amount_asset *asset UNNEEDED)
{ fprintf(stderr, "amount_asset_is_main called!\n"); abort(); }
Expand Down
2 changes: 1 addition & 1 deletion common/psbt_open.c
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ static const u8 *linearize_output(const tal_t *ctx,

/* Add a 'fake' input so this will linearize the tx */
memset(&txid, 0, sizeof(txid));
psbt_append_input(psbt, &txid, 0, 0, NULL, AMOUNT_SAT(0), NULL, NULL, NULL);
psbt_append_input(psbt, &txid, 0, 0, NULL, NULL, NULL);

if (wally_tx_add_output(psbt->tx, tx_out) != WALLY_OK)
abort();
Expand Down
3 changes: 0 additions & 3 deletions common/test/run-bigsize.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,6 @@ static const char *reason;
#include <common/bigsize.c>

/* AUTOGENERATED MOCKS START */
/* Generated stub for amount_asset_extract_value */
u8 *amount_asset_extract_value(const tal_t *ctx UNNEEDED, struct amount_asset *asset UNNEEDED)
{ fprintf(stderr, "amount_asset_extract_value called!\n"); abort(); }
/* Generated stub for amount_asset_is_main */
bool amount_asset_is_main(struct amount_asset *asset UNNEEDED)
{ fprintf(stderr, "amount_asset_is_main called!\n"); abort(); }
Expand Down
Loading

0 comments on commit 303263d

Please sign in to comment.