diff --git a/bitcoin/psbt.c b/bitcoin/psbt.c
index 13692c50b..f73c0aef4 100644
--- a/bitcoin/psbt.c
+++ b/bitcoin/psbt.c
@@ -24,36 +24,26 @@ static struct wally_psbt *init_psbt(const tal_t *ctx, size_t num_inputs, size_t
tal_wally_start();
if (is_elements(chainparams))
- wally_err = wally_psbt_elements_init_alloc(0, num_inputs, num_outputs, 0, &psbt);
+ wally_err = wally_psbt_init_alloc(2, num_inputs, num_outputs, 0, WALLY_PSBT_INIT_PSET, &psbt);
else
- wally_err = wally_psbt_init_alloc(0, num_inputs, num_outputs, 0, &psbt);
+ wally_err = wally_psbt_init_alloc(2, num_inputs, num_outputs, 0, 0, &psbt);
assert(wally_err == WALLY_OK);
+ /* By default we are modifying them internally; allow it */
+ wally_psbt_set_tx_modifiable_flags(psbt, WALLY_PSBT_TXMOD_INPUTS | WALLY_PSBT_TXMOD_OUTPUTS);
tal_add_destructor(psbt, psbt_destroy);
tal_wally_end_onto(ctx, psbt, struct wally_psbt);
return psbt;
}
+/* FIXME extremely thin wrapper; remove? */
struct wally_psbt *create_psbt(const tal_t *ctx, size_t num_inputs, size_t num_outputs, u32 locktime)
{
- int wally_err;
- struct wally_tx *wtx;
struct wally_psbt *psbt;
- tal_wally_start();
- if (wally_tx_init_alloc(WALLY_TX_VERSION_2, locktime, num_inputs, num_outputs, &wtx) != WALLY_OK)
- abort();
- /* wtx is freed below */
- tal_wally_end(NULL);
-
psbt = init_psbt(ctx, num_inputs, num_outputs);
+ wally_psbt_set_fallback_locktime(psbt, locktime);
- tal_wally_start();
- wally_err = wally_psbt_set_global_tx(psbt, wtx);
- assert(wally_err == WALLY_OK);
- tal_wally_end(psbt);
-
- wally_tx_free(wtx);
return psbt;
}
@@ -72,17 +62,18 @@ struct wally_psbt *new_psbt(const tal_t *ctx, const struct wally_tx *wtx)
struct wally_psbt *psbt;
int wally_err;
- psbt = init_psbt(ctx, wtx->num_inputs, wtx->num_outputs);
+ psbt = create_psbt(ctx, wtx->num_inputs, wtx->num_outputs, wtx->locktime);
tal_wally_start();
- /* Set directly: avoids psbt checks for non-NULL scripts/witnesses */
- wally_err = wally_tx_clone_alloc(wtx, 0, &psbt->tx);
- assert(wally_err == WALLY_OK);
- /* Inputs/outs are pre-allocated above, 'add' them as empty dummies */
- psbt->num_inputs = wtx->num_inputs;
- psbt->num_outputs = wtx->num_outputs;
+
+ /* locktime set in create_psbt for now */
+ wally_psbt_set_tx_version(psbt, wtx->version);
+ wally_psbt_set_tx_modifiable_flags(psbt, WALLY_PSBT_TXMOD_INPUTS | WALLY_PSBT_TXMOD_OUTPUTS);
for (size_t i = 0; i < wtx->num_inputs; i++) {
+ wally_err = wally_psbt_add_tx_input_at(psbt, i, 0, &wtx->inputs[i]);
+ assert(wally_err == WALLY_OK);
+
/* add these scripts + witnesses to the psbt */
if (wtx->inputs[i].script) {
wally_err =
@@ -90,24 +81,19 @@ struct wally_psbt *new_psbt(const tal_t *ctx, const struct wally_tx *wtx)
wtx->inputs[i].script,
wtx->inputs[i].script_len);
assert(wally_err == WALLY_OK);
-
- /* Clear out script sig data */
- psbt->tx->inputs[i].script_len = 0;
- tal_free(psbt->tx->inputs[i].script);
- psbt->tx->inputs[i].script = NULL;
}
if (wtx->inputs[i].witness) {
wally_err =
wally_psbt_input_set_final_witness(&psbt->inputs[i],
wtx->inputs[i].witness);
assert(wally_err == WALLY_OK);
-
- /* Delete the witness data */
- wally_tx_witness_stack_free(psbt->tx->inputs[i].witness);
- psbt->tx->inputs[i].witness = NULL;
}
}
+ for (size_t i = 0; i < wtx->num_outputs; i++) {
+ wally_psbt_add_tx_output_at(psbt, i, 0, &wtx->outputs[i]);
+ }
+
tal_wally_end(psbt);
return psbt;
}
@@ -128,7 +114,7 @@ struct wally_psbt_input *psbt_add_input(struct wally_psbt *psbt,
int wally_err;
tal_wally_start();
- wally_err = wally_psbt_add_input_at(psbt, insert_at, flags, input);
+ wally_err = wally_psbt_add_tx_input_at(psbt, insert_at, flags, input);
assert(wally_err == WALLY_OK);
tal_wally_end(psbt);
return &psbt->inputs[insert_at];
@@ -168,7 +154,7 @@ struct wally_psbt_input *psbt_append_input(struct wally_psbt *psbt,
abort();
}
- wally_err = wally_psbt_add_input_at(psbt, input_num, flags, tx_in);
+ wally_err = wally_psbt_add_tx_input_at(psbt, input_num, flags, tx_in);
assert(wally_err == WALLY_OK);
wally_tx_input_free(tx_in);
tal_wally_end(psbt);
@@ -204,7 +190,7 @@ struct wally_psbt_output *psbt_add_output(struct wally_psbt *psbt,
int wally_err;
tal_wally_start();
- wally_err = wally_psbt_add_output_at(psbt, insert_at, 0, output);
+ wally_err = wally_psbt_add_tx_output_at(psbt, insert_at, 0, output);
assert(wally_err == WALLY_OK);
tal_wally_end(psbt);
return &psbt->outputs[insert_at];
@@ -217,7 +203,7 @@ struct wally_psbt_output *psbt_append_output(struct wally_psbt *psbt,
struct wally_psbt_output *out;
struct wally_tx_output *tx_out = wally_tx_output(NULL, script, amount);
- out = psbt_add_output(psbt, tx_out, psbt->tx->num_outputs);
+ out = psbt_add_output(psbt, tx_out, psbt->num_outputs);
wally_tx_output_free(tx_out);
return out;
}
@@ -264,7 +250,7 @@ void psbt_input_add_pubkey(struct wally_psbt *psbt, size_t in,
pubkey_to_der(pk_der, pubkey);
tal_wally_start();
- wally_err = wally_psbt_input_add_keypath_item(&psbt->inputs[in],
+ wally_err = wally_psbt_input_keypath_add(&psbt->inputs[in],
pk_der, sizeof(pk_der),
fingerprint, sizeof(fingerprint),
empty_path, ARRAY_SIZE(empty_path));
@@ -361,7 +347,7 @@ void psbt_elements_input_set_asset(struct wally_psbt *psbt, size_t in,
tal_wally_start();
if (asset->value > 0)
- if (wally_psbt_input_set_value(&psbt->inputs[in],
+ if (wally_psbt_input_set_amount(&psbt->inputs[in],
asset->value) != WALLY_OK)
abort();
@@ -375,7 +361,6 @@ void psbt_elements_input_set_asset(struct wally_psbt *psbt, size_t in,
void psbt_elements_normalize_fees(struct wally_psbt *psbt)
{
- struct amount_asset asset;
size_t fee_output_idx = psbt->num_outputs;
if (!is_elements(chainparams))
@@ -383,15 +368,15 @@ void psbt_elements_normalize_fees(struct wally_psbt *psbt)
/* Elements requires that every input value is accounted for,
* including the fees */
- struct amount_sat total_in = AMOUNT_SAT(0), val;
+ struct amount_sat total_fee = AMOUNT_SAT(0), val;
for (size_t i = 0; i < psbt->num_inputs; i++) {
val = psbt_input_get_amount(psbt, i);
- if (!amount_sat_add(&total_in, total_in, val))
+ if (!amount_sat_add(&total_fee, total_fee, val))
return;
}
for (size_t i = 0; i < psbt->num_outputs; i++) {
- asset = wally_tx_output_get_amount(&psbt->tx->outputs[i]);
- if (elements_wtx_output_is_fee(psbt->tx, i)) {
+ struct amount_asset output_amount = wally_psbt_output_get_amount(&psbt->outputs[i]);
+ if (elements_psbt_output_is_fee(psbt, i)) {
if (fee_output_idx == psbt->num_outputs) {
fee_output_idx = i;
continue;
@@ -401,40 +386,47 @@ void psbt_elements_normalize_fees(struct wally_psbt *psbt)
psbt_rm_output(psbt, i--);
continue;
}
- if (!amount_asset_is_main(&asset))
+ if (!amount_asset_is_main(&output_amount))
continue;
- if (!amount_sat_sub(&total_in, total_in,
- amount_asset_to_sat(&asset)))
+ if (!amount_sat_sub(&total_fee, total_fee,
+ amount_asset_to_sat(&output_amount)))
return;
}
- if (amount_sat_eq(total_in, AMOUNT_SAT(0)))
+ if (amount_sat_eq(total_fee, AMOUNT_SAT(0)))
return;
/* We need to add a fee output */
if (fee_output_idx == psbt->num_outputs) {
- psbt_append_output(psbt, NULL, total_in);
+ psbt_append_output(psbt, NULL, total_fee);
} else {
- u64 sats = total_in.satoshis; /* Raw: wally API */
- struct wally_tx_output *out = &psbt->tx->outputs[fee_output_idx];
- if (wally_tx_confidential_value_from_satoshi(
- sats, out->value, out->value_len) != WALLY_OK)
- return;
+ int ret;
+ u64 sats = total_fee.satoshis; /* Raw: wally API */
+ struct wally_psbt_output *out = &psbt->outputs[fee_output_idx];
+ ret = wally_psbt_output_set_amount(out, sats);
+ assert(ret == WALLY_OK);
}
}
+void wally_psbt_input_get_txid(const struct wally_psbt_input *in,
+ struct bitcoin_txid *txid)
+{
+ BUILD_ASSERT(sizeof(struct bitcoin_txid) == sizeof(in->txhash));
+ memcpy(txid, in->txhash, sizeof(struct bitcoin_txid));
+}
+
bool psbt_has_input(const struct wally_psbt *psbt,
const struct bitcoin_outpoint *outpoint)
{
for (size_t i = 0; i < psbt->num_inputs; i++) {
struct bitcoin_txid in_txid;
- struct wally_tx_input *in = &psbt->tx->inputs[i];
+ const struct wally_psbt_input *in = &psbt->inputs[i];
if (outpoint->n != in->index)
continue;
- wally_tx_input_get_txid(in, &in_txid);
+ wally_psbt_input_get_txid(in, &in_txid);
if (bitcoin_txid_eq(&outpoint->txid, &in_txid))
return true;
}
@@ -452,7 +444,7 @@ struct amount_sat psbt_input_get_amount(const struct wally_psbt *psbt,
assert(amount_asset_is_main(&amt_asset));
val = amount_asset_to_sat(&amt_asset);
} else if (psbt->inputs[in].utxo) {
- int idx = psbt->tx->inputs[in].index;
+ int idx = psbt->inputs[in].index;
struct wally_tx *prev_tx = psbt->inputs[in].utxo;
val = amount_sat(prev_tx->outputs[idx].satoshi);
} else
@@ -466,7 +458,7 @@ struct amount_sat psbt_output_get_amount(const struct wally_psbt *psbt,
{
struct amount_asset asset;
assert(out < psbt->num_outputs);
- asset = wally_tx_output_get_amount(&psbt->tx->outputs[out]);
+ asset = wally_psbt_output_get_amount(&psbt->outputs[out]);
assert(amount_asset_is_main(&asset));
return amount_asset_to_sat(&asset);
}
@@ -505,7 +497,7 @@ u8 *psbt_make_key(const tal_t *ctx, u8 key_subtype, const u8 *key_data)
***
*/
u8 *key = tal_arr(ctx, u8, 0);
- add_type(&key, PSBT_PROPRIETARY_TYPE);
+ add_type(&key, WALLY_PSBT_PROPRIETARY_TYPE);
add_varint(&key, strlen(LIGHTNING_PROPRIETARY_PREFIX));
add(&key, LIGHTNING_PROPRIETARY_PREFIX,
strlen(LIGHTNING_PROPRIETARY_PREFIX));
@@ -616,9 +608,11 @@ bool psbt_finalize(struct wally_psbt *psbt)
for (size_t i = 0; i < psbt->num_inputs; i++) {
struct wally_psbt_input *input = &psbt->inputs[i];
struct wally_tx_witness_stack *stack;
+ const struct wally_map_item *iws;
- if (!is_anchor_witness_script(input->witness_script,
- input->witness_script_len))
+ iws = wally_map_get_integer(&input->psbt_fields, /* PSBT_IN_WITNESS_SCRIPT */ 0x05);
+ if (!iws || !is_anchor_witness_script(iws->value,
+ iws->value_len))
continue;
if (input->signatures.num_items != 1)
@@ -643,8 +637,8 @@ bool psbt_finalize(struct wally_psbt *psbt)
input->signatures.items[0].value,
input->signatures.items[0].value_len);
wally_tx_witness_stack_add(stack,
- input->witness_script,
- input->witness_script_len);
+ iws->value,
+ iws->value_len);
wally_psbt_input_set_final_witness(input, stack);
}
@@ -662,7 +656,7 @@ struct wally_tx *psbt_final_tx(const tal_t *ctx, const struct wally_psbt *psbt)
return NULL;
tal_wally_start();
- if (wally_psbt_extract(psbt, &wtx) == WALLY_OK)
+ if (wally_psbt_extract(psbt, /* flags */ 0, &wtx) == WALLY_OK)
tal_add_destructor(wtx, wally_tx_destroy);
else
wtx = NULL;
@@ -679,7 +673,7 @@ struct wally_psbt *psbt_from_b64(const tal_t *ctx,
char *str = tal_strndup(tmpctx, b64, b64len);
tal_wally_start();
- if (wally_psbt_from_base64(str, &psbt) == WALLY_OK)
+ if (wally_psbt_from_base64(str, /* flags */ 0, &psbt) == WALLY_OK)
tal_add_destructor(psbt, psbt_destroy);
else
psbt = NULL;
@@ -713,7 +707,9 @@ const u8 *psbt_get_bytes(const tal_t *ctx, const struct wally_psbt *psbt,
return NULL;
}
- wally_psbt_get_length(psbt, 0, &len);
+ if (wally_psbt_get_length(psbt, 0, &len) != WALLY_OK) {
+ abort();
+ }
bytes = tal_arr(ctx, u8, len);
if (wally_psbt_to_bytes(psbt, 0, bytes, len, bytes_written) != WALLY_OK ||
@@ -730,7 +726,7 @@ struct wally_psbt *psbt_from_bytes(const tal_t *ctx, const u8 *bytes,
struct wally_psbt *psbt;
tal_wally_start();
- if (wally_psbt_from_bytes(bytes, byte_len, &psbt) == WALLY_OK)
+ if (wally_psbt_from_bytes(bytes, byte_len, /* flags */ 0, &psbt) == WALLY_OK)
tal_add_destructor(psbt, psbt_destroy);
else
psbt = NULL;
@@ -780,38 +776,23 @@ struct wally_psbt *fromwire_wally_psbt(const tal_t *ctx,
return psbt;
}
-/* This only works on a non-final psbt because we're ALL SEGWIT! */
void psbt_txid(const tal_t *ctx,
- const struct wally_psbt *psbt, struct bitcoin_txid *txid,
+ const struct wally_psbt *psbt,
+ struct bitcoin_txid *txid,
struct wally_tx **wtx)
{
struct wally_tx *tx;
+ int wally_err;
+ assert(psbt->version == 2);
- /* You can *almost* take txid of global tx. But @niftynei thought
- * about this far more than me and pointed out that P2SH
- * inputs would not be represented, so here we go. */
+ /* We rely on wally extractor to fill out all txid-related fields including scriptSigs */
tal_wally_start();
- wally_tx_clone_alloc(psbt->tx, 0, &tx);
+ wally_err = wally_psbt_extract(psbt, WALLY_PSBT_EXTRACT_NON_FINAL, &tx);
+ assert(wally_err == WALLY_OK);
+ wally_err = wally_tx_get_txid(tx, txid->shad.sha.u.u8, sizeof(txid->shad.sha.u.u8));
+ assert(wally_err == WALLY_OK);
+ tal_wally_end(ctx);
- for (size_t i = 0; i < tx->num_inputs; i++) {
- if (psbt->inputs[i].final_scriptsig) {
- wally_tx_set_input_script(tx, i,
- psbt->inputs[i].final_scriptsig,
- psbt->inputs[i].final_scriptsig_len);
- } else if (psbt->inputs[i].redeem_script) {
- u8 *script;
-
- /* P2SH requires push of the redeemscript, from libwally src */
- script = tal_arr(tmpctx, u8, 0);
- script_push_bytes(&script,
- psbt->inputs[i].redeem_script,
- psbt->inputs[i].redeem_script_len);
- wally_tx_set_input_script(tx, i, script, tal_bytelen(script));
- }
- }
- tal_wally_end_onto(ctx, tx, struct wally_tx);
-
- wally_txid(tx, txid);
if (wtx)
*wtx = tx;
else
@@ -832,9 +813,9 @@ struct amount_sat psbt_compute_fee(const struct wally_psbt *psbt)
}
for (size_t i = 0; i < psbt->num_outputs; i++) {
- asset = wally_tx_output_get_amount(&psbt->tx->outputs[i]);
+ asset = wally_psbt_output_get_amount(&psbt->outputs[i]);
if (!amount_asset_is_main(&asset)
- || elements_wtx_output_is_fee(psbt->tx, i))
+ || elements_psbt_output_is_fee(psbt, i))
continue;
ok = amount_sat_sub(&fee, fee, amount_asset_to_sat(&asset));
@@ -844,3 +825,93 @@ struct amount_sat psbt_compute_fee(const struct wally_psbt *psbt)
return fee;
}
+
+bool wally_psbt_input_spends(const struct wally_psbt_input *input,
+ const struct bitcoin_outpoint *outpoint)
+{
+ /* Useful, as tx_part can have some NULL inputs */
+ if (!input)
+ return false;
+ BUILD_ASSERT(sizeof(outpoint->txid) == sizeof(input->txhash));
+ if (input->index != outpoint->n)
+ return false;
+ if (memcmp(&outpoint->txid, input->txhash, sizeof(outpoint->txid)) != 0)
+ return false;
+ return true;
+}
+
+void wally_psbt_input_get_outpoint(const struct wally_psbt_input *in,
+ struct bitcoin_outpoint *outpoint)
+{
+ BUILD_ASSERT(sizeof(struct bitcoin_txid) == sizeof(in->txhash));
+ memcpy(&outpoint->txid, in->txhash, sizeof(struct bitcoin_txid));
+ outpoint->n = in->index;
+}
+
+const u8 *wally_psbt_output_get_script(const tal_t *ctx,
+ const struct wally_psbt_output *output)
+{
+ if (output->script == NULL) {
+ /* This can happen for coinbase transactions, pegin
+ * transactions, and elements fee outputs */
+ return NULL;
+ }
+
+ return tal_dup_arr(ctx, u8, output->script, output->script_len, 0);
+}
+
+/* FIXME(cdecker) Make the caller pass in a reference to amount_asset, and
+ * return false if unintelligible/encrypted. (WARN UNUSED). */
+struct amount_asset
+wally_psbt_output_get_amount(const struct wally_psbt_output *output)
+{
+ struct amount_asset amount;
+ size_t asset_out;
+
+ if (chainparams->is_elements) {
+ if (wally_psbt_output_get_asset(output, amount.asset + 1, sizeof(amount.asset) - 1, &asset_out) != WALLY_OK) {
+ amount.value = 0;
+ return amount;
+ }
+ assert(asset_out == 32);
+ amount.asset[0] = 0x01; /* explicit */
+ /* We currently only support explicit value
+ * asset tags, others are confidential, so
+ * don't even try to assign a value to it. */
+ if (output->has_amount == true) {
+ amount.value = output->amount;
+ } else {
+ amount.value = 0;
+ }
+ } else {
+ /* Do not assign amount.asset, we should never touch it in
+ * non-elements scenarios. */
+ if (output->has_amount) {
+ amount.value = output->amount;
+ } else {
+ abort();
+ }
+ }
+
+ return amount;
+}
+
+bool elements_psbt_output_is_fee(const struct wally_psbt *psbt, size_t outnum)
+{
+ assert(outnum < psbt->num_outputs);
+ return chainparams->is_elements &&
+ psbt->outputs[outnum].script_len == 0;
+}
+
+bool psbt_set_version(struct wally_psbt *psbt, u32 version)
+{
+ bool ok;
+
+ tal_wally_start();
+ ok = wally_psbt_set_version(psbt, 0, version) == WALLY_OK;
+ if (ok && version == 2) {
+ ok &= wally_psbt_set_tx_modifiable_flags(psbt, WALLY_PSBT_TXMOD_INPUTS | WALLY_PSBT_TXMOD_OUTPUTS) == WALLY_OK;
+ }
+ tal_wally_end(psbt);
+ return ok;
+}
diff --git a/bitcoin/psbt.h b/bitcoin/psbt.h
index 53ff1c4ce..18b0351da 100644
--- a/bitcoin/psbt.h
+++ b/bitcoin/psbt.h
@@ -29,7 +29,7 @@ struct wally_psbt *create_psbt(const tal_t *ctx, size_t num_inputs, size_t num_o
/*
* new_psbt - Create a PSBT, using the passed in tx
- * as the global_tx
+ * as the locktime/inputs/output psbt fields
*
* @ctx - allocation context
* @wtx - global_tx starter kit
@@ -228,6 +228,33 @@ struct amount_sat psbt_compute_fee(const struct wally_psbt *psbt);
bool psbt_has_input(const struct wally_psbt *psbt,
const struct bitcoin_outpoint *outpoint);
+/* wally_psbt_input_spends - Returns true if PSBT input spends given outpoint
+ *
+ * @input - psbt input
+ * @outpoint - outpoint
+ */
+bool wally_psbt_input_spends(const struct wally_psbt_input *input,
+ const struct bitcoin_outpoint *outpoint);
+
+void wally_psbt_input_get_outpoint(const struct wally_psbt_input *in,
+ struct bitcoin_outpoint *outpoint);
+
+const u8 *wally_psbt_output_get_script(const tal_t *ctx,
+ const struct wally_psbt_output *output);
+
+void wally_psbt_input_get_txid(const struct wally_psbt_input *in,
+ struct bitcoin_txid *txid);
+
+struct amount_asset
+wally_psbt_output_get_amount(const struct wally_psbt_output *output);
+
+/* psbt_set_version - Returns false if there was any issue with the PSBT.
+ * Returns true if it was a well-formed PSET and treats it as a no-op
+ */
+bool psbt_set_version(struct wally_psbt *psbt, u32 version);
+
+bool elements_psbt_output_is_fee(const struct wally_psbt *psbt, size_t outnum);
+
struct wally_psbt *psbt_from_b64(const tal_t *ctx,
const char *b64,
size_t b64len);
diff --git a/bitcoin/test/run-bitcoin_block_from_hex.c b/bitcoin/test/run-bitcoin_block_from_hex.c
index 4c910f8b8..0e2eefa95 100644
--- a/bitcoin/test/run-bitcoin_block_from_hex.c
+++ b/bitcoin/test/run-bitcoin_block_from_hex.c
@@ -72,9 +72,6 @@ void pubkey_to_der(u8 der[PUBKEY_CMPR_LEN] UNNEEDED, const struct pubkey *key UN
/* Generated stub for pubkey_to_hash160 */
void pubkey_to_hash160(const struct pubkey *pk UNNEEDED, struct ripemd160 *hash UNNEEDED)
{ fprintf(stderr, "pubkey_to_hash160 called!\n"); abort(); }
-/* Generated stub for script_push_bytes */
-void script_push_bytes(u8 **scriptp UNNEEDED, const void *mem UNNEEDED, size_t len UNNEEDED)
-{ fprintf(stderr, "script_push_bytes called!\n"); abort(); }
/* Generated stub for scriptpubkey_p2wsh */
u8 *scriptpubkey_p2wsh(const tal_t *ctx UNNEEDED, const u8 *witnessscript UNNEEDED)
{ fprintf(stderr, "scriptpubkey_p2wsh called!\n"); abort(); }
diff --git a/bitcoin/test/run-psbt-from-tx.c b/bitcoin/test/run-psbt-from-tx.c
index 5aefcb9ed..f05809728 100644
--- a/bitcoin/test/run-psbt-from-tx.c
+++ b/bitcoin/test/run-psbt-from-tx.c
@@ -53,9 +53,6 @@ void pubkey_to_der(u8 der[PUBKEY_CMPR_LEN] UNNEEDED, const struct pubkey *key UN
/* Generated stub for pubkey_to_hash160 */
void pubkey_to_hash160(const struct pubkey *pk UNNEEDED, struct ripemd160 *hash UNNEEDED)
{ fprintf(stderr, "pubkey_to_hash160 called!\n"); abort(); }
-/* Generated stub for script_push_bytes */
-void script_push_bytes(u8 **scriptp UNNEEDED, const void *mem UNNEEDED, size_t len UNNEEDED)
-{ fprintf(stderr, "script_push_bytes called!\n"); abort(); }
/* Generated stub for scriptpubkey_p2wsh */
u8 *scriptpubkey_p2wsh(const tal_t *ctx UNNEEDED, const u8 *witnessscript UNNEEDED)
{ fprintf(stderr, "scriptpubkey_p2wsh called!\n"); abort(); }
@@ -105,7 +102,8 @@ int main(int argc, char *argv[])
/* Witness/scriptsig data is saved down into psbt */
assert(tx2->psbt->num_inputs == 1);
- assert(tx2->psbt->inputs[0].final_scriptsig_len > 0);
+ const struct wally_map_item *final_scriptsig = wally_map_get_integer(&tx2->psbt->inputs[0].psbt_fields, /* PSBT_IN_FINAL_SCRIPTSIG */ 0x07);
+ assert(final_scriptsig->value_len > 0);
assert(tx2->psbt->inputs[0].final_witness != NULL);
common_shutdown();
diff --git a/bitcoin/test/run-tx-bitcoin_tx_2of2_input_witness_weight.c b/bitcoin/test/run-tx-bitcoin_tx_2of2_input_witness_weight.c
index b387279c2..05892c964 100644
--- a/bitcoin/test/run-tx-bitcoin_tx_2of2_input_witness_weight.c
+++ b/bitcoin/test/run-tx-bitcoin_tx_2of2_input_witness_weight.c
@@ -81,10 +81,6 @@ struct wally_psbt_input *psbt_append_input(struct wally_psbt *psbt UNNEEDED,
const u8 *input_wscript UNNEEDED,
const u8 *redeemscript UNNEEDED)
{ fprintf(stderr, "psbt_append_input called!\n"); abort(); }
-/* Generated stub for psbt_elements_input_set_asset */
-void psbt_elements_input_set_asset(struct wally_psbt *psbt UNNEEDED, size_t in UNNEEDED,
- struct amount_asset *asset UNNEEDED)
-{ fprintf(stderr, "psbt_elements_input_set_asset called!\n"); abort(); }
/* Generated stub for psbt_final_tx */
struct wally_tx *psbt_final_tx(const tal_t *ctx UNNEEDED, const struct wally_psbt *psbt UNNEEDED)
{ fprintf(stderr, "psbt_final_tx called!\n"); abort(); }
diff --git a/bitcoin/test/run-tx-encode.c b/bitcoin/test/run-tx-encode.c
index e84b4e5a0..aecd28ab2 100644
--- a/bitcoin/test/run-tx-encode.c
+++ b/bitcoin/test/run-tx-encode.c
@@ -73,9 +73,6 @@ void pubkey_to_der(u8 der[PUBKEY_CMPR_LEN] UNNEEDED, const struct pubkey *key UN
/* Generated stub for pubkey_to_hash160 */
void pubkey_to_hash160(const struct pubkey *pk UNNEEDED, struct ripemd160 *hash UNNEEDED)
{ fprintf(stderr, "pubkey_to_hash160 called!\n"); abort(); }
-/* Generated stub for script_push_bytes */
-void script_push_bytes(u8 **scriptp UNNEEDED, const void *mem UNNEEDED, size_t len UNNEEDED)
-{ fprintf(stderr, "script_push_bytes called!\n"); abort(); }
/* Generated stub for scriptpubkey_p2wsh */
u8 *scriptpubkey_p2wsh(const tal_t *ctx UNNEEDED, const u8 *witnessscript UNNEEDED)
{ fprintf(stderr, "scriptpubkey_p2wsh called!\n"); abort(); }
diff --git a/bitcoin/tx.c b/bitcoin/tx.c
index 7d575196c..951798234 100644
--- a/bitcoin/tx.c
+++ b/bitcoin/tx.c
@@ -180,7 +180,36 @@ static int elements_tx_add_fee_output(struct bitcoin_tx *tx)
void bitcoin_tx_set_locktime(struct bitcoin_tx *tx, u32 locktime)
{
tx->wtx->locktime = locktime;
- tx->psbt->tx->locktime = locktime;
+ tx->psbt->fallback_locktime = locktime;
+ tx->psbt->has_fallback_locktime = true;
+}
+
+/* FIXME Stolen from psbt_append_input; export? */
+static struct wally_tx_input *wally_tx_input_from_outpoint_sequence(const struct bitcoin_outpoint *outpoint,
+ u32 sequence)
+{
+ struct wally_tx_input *tx_in;
+ if (chainparams->is_elements) {
+ if (wally_tx_elements_input_init_alloc(outpoint->txid.shad.sha.u.u8,
+ sizeof(outpoint->txid.shad.sha.u.u8),
+ outpoint->n,
+ sequence, NULL, 0,
+ NULL,
+ NULL, 0,
+ NULL, 0, NULL, 0,
+ NULL, 0, NULL, 0,
+ NULL, 0, NULL,
+ &tx_in) != WALLY_OK)
+ abort();
+ } else {
+ if (wally_tx_input_init_alloc(outpoint->txid.shad.sha.u.u8,
+ sizeof(outpoint->txid.shad.sha.u.u8),
+ outpoint->n,
+ sequence, NULL, 0, NULL,
+ &tx_in) != WALLY_OK)
+ abort();
+ }
+ return tx_in;
}
int bitcoin_tx_add_input(struct bitcoin_tx *tx,
@@ -191,6 +220,7 @@ int bitcoin_tx_add_input(struct bitcoin_tx *tx,
{
int wally_err;
int input_num = tx->wtx->num_inputs;
+ struct wally_tx_input *tx_input;
psbt_append_input(tx->psbt, outpoint,
sequence, scriptSig,
@@ -205,9 +235,11 @@ int bitcoin_tx_add_input(struct bitcoin_tx *tx,
scriptPubkey, amount);
tal_wally_start();
+ tx_input = wally_tx_input_from_outpoint_sequence(outpoint, sequence);
wally_err = wally_tx_add_input(tx->wtx,
- &tx->psbt->tx->inputs[input_num]);
+ tx_input);
assert(wally_err == WALLY_OK);
+ wally_tx_input_free(tx_input);
/* scriptsig isn't actually stored in psbt input, so add that now */
wally_tx_set_input_script(tx->wtx, input_num,
@@ -215,12 +247,10 @@ int bitcoin_tx_add_input(struct bitcoin_tx *tx,
tal_wally_end(tx->wtx);
if (is_elements(chainparams)) {
- struct amount_asset asset;
/* FIXME: persist asset tags */
- asset = amount_sat_to_asset(&amount,
+ 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;
}
@@ -258,10 +288,6 @@ void bitcoin_tx_output_set_amount(struct bitcoin_tx *tx, int outnum,
assert(ret == WALLY_OK);
} else {
output->satoshi = satoshis;
-
- /* update the global tx for the psbt also */
- output = &tx->psbt->tx->outputs[outnum];
- output->satoshi = satoshis;
}
}
@@ -291,14 +317,16 @@ u8 *bitcoin_tx_output_get_witscript(const tal_t *ctx, const struct bitcoin_tx *t
int outnum)
{
struct wally_psbt_output *out;
+ const struct wally_map_item *output_witness_script;
assert(outnum < tx->psbt->num_outputs);
out = &tx->psbt->outputs[outnum];
- if (out->witness_script_len == 0)
+ output_witness_script = wally_map_get_integer(&out->psbt_fields, /* PSBT_OUT_WITNESS_SCRIPT */ 0x01);
+ if (output_witness_script->value_len == 0)
return NULL;
- return tal_dup_arr(ctx, u8, out->witness_script, out->witness_script_len, 0);
+ return tal_dup_arr(ctx, u8, output_witness_script->value, output_witness_script->value_len, 0);
}
struct amount_asset bitcoin_tx_output_get_amount(const struct bitcoin_tx *tx,
@@ -536,18 +564,21 @@ void bitcoin_tx_finalize(struct bitcoin_tx *tx)
struct bitcoin_tx *bitcoin_tx_with_psbt(const tal_t *ctx, struct wally_psbt *psbt STEALS)
{
+ size_t locktime;
+ wally_psbt_get_locktime(psbt, &locktime);
struct bitcoin_tx *tx = bitcoin_tx(ctx, chainparams,
- psbt->tx->num_inputs,
- psbt->tx->num_outputs,
- psbt->tx->locktime);
+ psbt->num_inputs,
+ psbt->num_outputs,
+ locktime);
wally_tx_free(tx->wtx);
psbt_finalize(psbt);
tx->wtx = psbt_final_tx(tx, psbt);
if (!tx->wtx) {
tal_wally_start();
- if (wally_tx_clone_alloc(psbt->tx, 0, &tx->wtx) != WALLY_OK)
+ if (wally_psbt_extract(psbt, WALLY_PSBT_EXTRACT_NON_FINAL, &tx->wtx) != WALLY_OK) {
tx->wtx = NULL;
+ }
tal_wally_end_onto(tx, tx->wtx, struct wally_tx);
if (!tx->wtx)
return tal_free(tx);
diff --git a/common/permute_tx.c b/common/permute_tx.c
index 75fdf6140..ab76e3106 100644
--- a/common/permute_tx.c
+++ b/common/permute_tx.c
@@ -3,7 +3,6 @@
#include
static void swap_wally_outputs(struct wally_tx_output *outputs,
- struct wally_tx_output *psbt_global_outs,
struct wally_psbt_output *psbt_outs,
const void **map, u32 *cltvs,
size_t i1, size_t i2)
@@ -18,12 +17,6 @@ static void swap_wally_outputs(struct wally_tx_output *outputs,
outputs[i1] = outputs[i2];
outputs[i2] = tmpoutput;
- /* For the PSBT, we swap the psbt outputs and
- * the global tx's outputs */
- tmpoutput = psbt_global_outs[i1];
- psbt_global_outs[i1] = psbt_global_outs[i2];
- psbt_global_outs[i2] = tmpoutput;
-
tmppsbtout = psbt_outs[i1];
psbt_outs[i1] = psbt_outs[i2];
psbt_outs[i2] = tmppsbtout;
@@ -106,7 +99,6 @@ void permute_outputs(struct bitcoin_tx *tx, u32 *cltvs, const void **map)
/* Swap best into first place. */
swap_wally_outputs(tx->wtx->outputs,
- tx->psbt->tx->outputs,
tx->psbt->outputs,
map, cltvs, i, best_pos);
}
diff --git a/common/psbt_internal.c b/common/psbt_internal.c
index bc7ca0a9c..475b4cabc 100644
--- a/common/psbt_internal.c
+++ b/common/psbt_internal.c
@@ -26,6 +26,7 @@ void psbt_finalize_input(const tal_t *ctx,
struct wally_psbt_input *in,
const struct witness_element **elements)
{
+ const struct wally_map_item *redeem_script;
psbt_input_set_final_witness_stack(ctx, in, elements);
/* There's this horrible edgecase where we set the final_witnesses
@@ -35,18 +36,16 @@ void psbt_finalize_input(const tal_t *ctx,
* on these just .. ignores it!? Murder. Anyway, here we do a final
* scriptsig check -- if there's a redeemscript field still around we
* just go ahead and mush it into the final_scriptsig field. */
- if (in->redeem_script) {
+ redeem_script = wally_map_get_integer(&in->psbt_fields, /* PSBT_IN_REDEEM_SCRIPT */ 0x04);
+ if (redeem_script) {
u8 *redeemscript = tal_dup_arr(NULL, u8,
- in->redeem_script,
- in->redeem_script_len, 0);
- in->final_scriptsig =
+ redeem_script->value,
+ redeem_script->value_len, 0);
+ u8 *final_scriptsig =
bitcoin_scriptsig_redeem(NULL,
take(redeemscript));
- in->final_scriptsig_len =
- tal_bytelen(in->final_scriptsig);
-
- in->redeem_script = tal_free(in->redeem_script);
- in->redeem_script_len = 0;
+ wally_psbt_input_set_final_scriptsig(in, final_scriptsig, tal_bytelen(final_scriptsig));
+ wally_psbt_input_set_redeem_script(in, tal_arr(NULL, u8, 0), 0);
}
}
diff --git a/common/psbt_keypath.c b/common/psbt_keypath.c
index 5037a0a40..f163614e4 100644
--- a/common/psbt_keypath.c
+++ b/common/psbt_keypath.c
@@ -14,7 +14,7 @@ void psbt_set_keypath(u32 index, const struct ext_key *ext, struct wally_map *ma
u32 path[1];
path[0] = index;
- if (wally_map_add_keypath_item(map_in,
+ if (wally_map_keypath_add(map_in,
ext->pub_key, sizeof(ext->pub_key),
fingerprint, sizeof(fingerprint),
path, 1) != WALLY_OK)
diff --git a/common/psbt_open.c b/common/psbt_open.c
index 646b4ea02..80cbe7fb4 100644
--- a/common/psbt_open.c
+++ b/common/psbt_open.c
@@ -58,17 +58,11 @@ static int compare_outputs_at(const struct output_set *a,
}
static const u8 *linearize_input(const tal_t *ctx,
- const struct wally_psbt_input *in,
- const struct wally_tx_input *tx_in)
+ const struct wally_psbt_input *in)
{
struct wally_psbt *psbt = create_psbt(NULL, 1, 0, 0);
size_t byte_len;
- tal_wally_start();
- if (wally_tx_add_input(psbt->tx, tx_in) != WALLY_OK)
- abort();
- tal_wally_end(psbt->tx);
-
psbt->inputs[0] = *in;
psbt->num_inputs++;
@@ -77,11 +71,10 @@ static const u8 *linearize_input(const tal_t *ctx,
wally_map_sort(&psbt->inputs[0].unknowns, 0);
/* signatures, keypaths, etc - we dont care if they change */
- psbt->inputs[0].final_witness = NULL;
- psbt->inputs[0].final_scriptsig_len = 0;
- psbt->inputs[0].witness_script = NULL;
- psbt->inputs[0].witness_script_len = 0;
- psbt->inputs[0].redeem_script_len = 0;
+ wally_psbt_input_set_final_witness(&psbt->inputs[0], NULL);
+ wally_psbt_input_set_final_scriptsig(&psbt->inputs[0], NULL, 0);
+ wally_psbt_input_set_witness_script(&psbt->inputs[0], NULL, 0);
+ wally_psbt_input_set_redeem_script(&psbt->inputs[0], NULL, 0);
psbt->inputs[0].keypaths.num_items = 0;
psbt->inputs[0].signatures.num_items = 0;
@@ -94,22 +87,16 @@ static const u8 *linearize_input(const tal_t *ctx,
}
static const u8 *linearize_output(const tal_t *ctx,
- const struct wally_psbt_output *out,
- const struct wally_tx_output *tx_out)
+ const struct wally_psbt_output *out)
{
struct wally_psbt *psbt = create_psbt(NULL, 1, 1, 0);
size_t byte_len;
struct bitcoin_outpoint outpoint;
- /* Add a 'fake' input so this will linearize the tx */
- memset(&outpoint, 0, sizeof(outpoint));
+ /* Add a 'fake' non-zero input so libwally will agree to linearize the tx */
+ memset(&outpoint, 1, sizeof(outpoint));
psbt_append_input(psbt, &outpoint, 0, NULL, NULL, NULL);
- tal_wally_start();
- if (wally_tx_add_output(psbt->tx, tx_out) != WALLY_OK)
- abort();
- tal_wally_end(psbt->tx);
-
psbt->outputs[0] = *out;
psbt->num_outputs++;
/* Sort the outputs, so serializing them is ok */
@@ -118,8 +105,8 @@ static const u8 *linearize_output(const tal_t *ctx,
/* We don't care if the keypaths change */
psbt->outputs[0].keypaths.num_items = 0;
/* And you can add scripts, no problem */
- psbt->outputs[0].witness_script_len = 0;
- psbt->outputs[0].redeem_script_len = 0;
+ wally_psbt_output_set_witness_script(&psbt->outputs[0], NULL, 0);
+ wally_psbt_output_set_redeem_script(&psbt->outputs[0], NULL, 0);
const u8 *bytes = psbt_get_bytes(ctx, psbt, &byte_len);
@@ -135,11 +122,9 @@ static bool input_identical(const struct wally_psbt *a,
size_t b_index)
{
const u8 *a_in = linearize_input(tmpctx,
- &a->inputs[a_index],
- &a->tx->inputs[a_index]);
+ &a->inputs[a_index]);
const u8 *b_in = linearize_input(tmpctx,
- &b->inputs[b_index],
- &b->tx->inputs[b_index]);
+ &b->inputs[b_index]);
return memeq(a_in, tal_bytelen(a_in),
b_in, tal_bytelen(b_in));
@@ -151,11 +136,9 @@ static bool output_identical(const struct wally_psbt *a,
size_t b_index)
{
const u8 *a_out = linearize_output(tmpctx,
- &a->outputs[a_index],
- &a->tx->outputs[a_index]);
+ &a->outputs[a_index]);
const u8 *b_out = linearize_output(tmpctx,
- &b->outputs[b_index],
- &b->tx->outputs[b_index]);
+ &b->outputs[b_index]);
return memeq(a_out, tal_bytelen(a_out),
b_out, tal_bytelen(b_out));
}
@@ -168,7 +151,6 @@ static void sort_inputs(struct wally_psbt *psbt)
psbt->num_inputs);
for (size_t i = 0; i < tal_count(set); i++) {
- set[i].tx_input = psbt->tx->inputs[i];
set[i].input = psbt->inputs[i];
}
@@ -178,7 +160,6 @@ static void sort_inputs(struct wally_psbt *psbt)
/* Put PSBT parts into place */
for (size_t i = 0; i < tal_count(set); i++) {
psbt->inputs[i] = set[i].input;
- psbt->tx->inputs[i] = set[i].tx_input;
}
tal_free(set);
@@ -191,7 +172,6 @@ static void sort_outputs(struct wally_psbt *psbt)
struct output_set,
psbt->num_outputs);
for (size_t i = 0; i < tal_count(set); i++) {
- set[i].tx_output = psbt->tx->outputs[i];
set[i].output = psbt->outputs[i];
}
@@ -201,7 +181,6 @@ static void sort_outputs(struct wally_psbt *psbt)
/* Put PSBT parts into place */
for (size_t i = 0; i < tal_count(set); i++) {
psbt->outputs[i] = set[i].output;
- psbt->tx->outputs[i] = set[i].tx_output;
}
tal_free(set);
@@ -217,7 +196,6 @@ void psbt_sort_by_serial_id(struct wally_psbt *psbt)
do { \
struct type##_set a; \
a.type = from->type##s[index]; \
- a.tx_##type = from->tx->type##s[index]; \
a.idx = index; \
tal_arr_expand(&add_to, a); \
} while (0)
@@ -398,6 +376,7 @@ bool psbt_has_required_fields(struct wally_psbt *psbt)
{
u64 serial_id;
for (size_t i = 0; i < psbt->num_inputs; i++) {
+ const struct wally_map_item *redeem_script;
struct wally_psbt_input *input = &psbt->inputs[i];
if (!psbt_get_serial_id(&input->unknowns, &serial_id))
@@ -408,13 +387,13 @@ bool psbt_has_required_fields(struct wally_psbt *psbt)
return false;
/* If is P2SH, redeemscript must be present */
- assert(psbt->tx->inputs[i].index < input->utxo->num_outputs);
+ assert(psbt->inputs[i].index < input->utxo->num_outputs);
const u8 *outscript =
wally_tx_output_get_script(tmpctx,
- &input->utxo->outputs[psbt->tx->inputs[i].index]);
- if (is_p2sh(outscript, NULL) && input->redeem_script_len == 0)
+ &input->utxo->outputs[psbt->inputs[i].index]);
+ redeem_script = wally_map_get_integer(&psbt->inputs[i].psbt_fields, /* PSBT_IN_REDEEM_SCRIPT */ 0x04);
+ if (is_p2sh(outscript, NULL) && (!redeem_script || redeem_script->value_len == 0))
return false;
-
}
for (size_t i = 0; i < psbt->num_outputs; i++) {
@@ -511,6 +490,8 @@ bool psbt_output_to_external(const struct wally_psbt_output *output)
bool psbt_contribs_changed(struct wally_psbt *orig,
struct wally_psbt *new)
{
+ assert(orig->version == 2 && new->version == 2);
+
struct psbt_changeset *cs;
bool ok;
cs = psbt_get_changeset(NULL, orig, new);
diff --git a/common/psbt_open.h b/common/psbt_open.h
index 134a5da65..be3c4995b 100644
--- a/common/psbt_open.h
+++ b/common/psbt_open.h
@@ -15,14 +15,12 @@ struct wally_psbt_output;
struct wally_map;
struct input_set {
- struct wally_tx_input tx_input;
struct wally_psbt_input input;
/* index on PSBT of this input */
size_t idx;
};
struct output_set {
- struct wally_tx_output tx_output;
struct wally_psbt_output output;
/* index on PSBT of this output */
size_t idx;
diff --git a/common/test/run-psbt_diff.c b/common/test/run-psbt_diff.c
index 4c8ff0587..37f4fdf49 100644
--- a/common/test/run-psbt_diff.c
+++ b/common/test/run-psbt_diff.c
@@ -132,6 +132,19 @@ static void check_psbt_comparison(void)
struct wally_psbt *newpsbt = psbt_from_b64(tmpctx, "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", strlen("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"));
+ /* Round-trip versioning of both PSBTs as belt and suspender check */
+ tal_wally_start();
+ wally_psbt_set_version(oldpsbt, 0 /* flags */, 2);
+ wally_psbt_set_version(oldpsbt, 0 /* flags */, 0);
+ wally_psbt_set_version(oldpsbt, 0 /* flags */, 2);
+ tal_wally_end(oldpsbt);
+
+ tal_wally_start();
+ wally_psbt_set_version(newpsbt, 0 /* flags */, 2);
+ wally_psbt_set_version(newpsbt, 0 /* flags */, 0);
+ wally_psbt_set_version(newpsbt, 0 /* flags */, 2);
+ tal_wally_end(newpsbt);
+
assert(!psbt_contribs_changed(oldpsbt, newpsbt));
}
diff --git a/external/libwally-core b/external/libwally-core
index d839dbab4..23e6b626c 160000
--- a/external/libwally-core
+++ b/external/libwally-core
@@ -1 +1 @@
-Subproject commit d839dbab4279e1d3d1ece4e52d4766f523b3f7ee
+Subproject commit 23e6b626c8906bce2e3179409b938c9ef9bca463
diff --git a/hsmd/libhsmd.c b/hsmd/libhsmd.c
index 0ba4c87ec..557fb414f 100644
--- a/hsmd/libhsmd.c
+++ b/hsmd/libhsmd.c
@@ -466,7 +466,7 @@ static void sign_our_inputs(struct utxo **utxos, struct wally_psbt *psbt)
struct privkey privkey;
struct pubkey pubkey;
- if (!wally_tx_input_spends(&psbt->tx->inputs[j],
+ if (!wally_psbt_input_spends(&psbt->inputs[j],
&utxo->outpoint))
continue;
diff --git a/lightningd/dual_open_control.c b/lightningd/dual_open_control.c
index d38a3f9c9..faebf7b33 100644
--- a/lightningd/dual_open_control.c
+++ b/lightningd/dual_open_control.c
@@ -2180,11 +2180,11 @@ static void handle_validate_rbf(struct subd *dualopend,
list_for_each(&channel->inflights, inflight, list) {
/* Remove every non-matching input from set */
for (size_t i = 0; i < candidate_psbt->num_inputs; i++) {
- struct wally_tx_input *input =
- &candidate_psbt->tx->inputs[i];
+ const struct wally_psbt_input *input =
+ &candidate_psbt->inputs[i];
struct bitcoin_outpoint outpoint;
- wally_tx_input_get_outpoint(input, &outpoint);
+ wally_psbt_input_get_outpoint(input, &outpoint);
if (!psbt_has_input(inflight->funding_psbt,
&outpoint))
@@ -2793,6 +2793,11 @@ static struct command_result *json_openchannel_init(struct command *cmd,
NULL))
return command_param_failed();
+ /* We only deal in v2 */
+ if (!psbt_set_version(psbt, 2)) {
+ return command_fail(cmd, LIGHTNINGD, "Could not set PSBT version.");
+ }
+
/* Gotta expect some rates ! */
if (!amount_sat_zero(*request_amt) && !rates)
return command_fail(cmd, JSONRPC2_INVALID_PARAMS,
diff --git a/lightningd/opening_control.c b/lightningd/opening_control.c
index 68a3b3037..7156d5f62 100644
--- a/lightningd/opening_control.c
+++ b/lightningd/opening_control.c
@@ -1009,10 +1009,15 @@ static struct command_result *json_fundchannel_complete(struct command *cmd,
fc = peer->uncommitted_channel->fc;
+ /* We only deal with V2 internally */
+ if (!psbt_set_version(funding_psbt, 2)) {
+ return command_fail(cmd, LIGHTNINGD, "Could not set PSBT version.");
+ }
+
/* Figure out the correct output, and perform sanity checks. */
- for (size_t i = 0; i < funding_psbt->tx->num_outputs; i++) {
- if (memeq(funding_psbt->tx->outputs[i].script,
- funding_psbt->tx->outputs[i].script_len,
+ for (size_t i = 0; i < funding_psbt->num_outputs; i++) {
+ if (memeq(funding_psbt->outputs[i].script,
+ funding_psbt->outputs[i].script_len,
fc->funding_scriptpubkey,
tal_bytelen(fc->funding_scriptpubkey))) {
if (funding_txout_num)
@@ -1028,14 +1033,14 @@ static struct command_result *json_fundchannel_complete(struct command *cmd,
/* Can't really check amounts for elements. */
if (!chainparams->is_elements
- && !amount_sat_eq(amount_sat(funding_psbt->tx->outputs
- [*funding_txout_num].satoshi),
+ && !amount_sat_eq(amount_sat(funding_psbt->outputs
+ [*funding_txout_num].amount),
fc->funding_sats))
return command_fail(cmd, FUNDING_PSBT_INVALID,
"Output to open channel is %"PRIu64"sat,"
" should be %s",
- funding_psbt->tx->outputs
- [*funding_txout_num].satoshi,
+ funding_psbt->outputs
+ [*funding_txout_num].amount,
type_to_string(tmpctx, struct amount_sat,
&fc->funding_sats));
diff --git a/lightningd/peer_control.c b/lightningd/peer_control.c
index 7ab13ba3f..71c15a8f2 100644
--- a/lightningd/peer_control.c
+++ b/lightningd/peer_control.c
@@ -1891,6 +1891,8 @@ void channel_watch_wrong_funding(struct lightningd *ld, struct channel *channel)
void channel_watch_funding(struct lightningd *ld, struct channel *channel)
{
/* FIXME: Remove arg from cb? */
+ log_debug(channel->log, "Watching for funding txid: %s",
+ type_to_string(tmpctx, struct bitcoin_txid, &channel->funding.txid));
watch_txid(channel, ld->topology, channel,
&channel->funding.txid, funding_depth_cb);
watch_txo(channel, ld->topology, channel,
diff --git a/openingd/dualopend.c b/openingd/dualopend.c
index 4f46b6d02..5375331aa 100644
--- a/openingd/dualopend.c
+++ b/openingd/dualopend.c
@@ -250,8 +250,8 @@ static u8 *psbt_changeset_get_next(const tal_t *ctx,
in->input.utxo);
msg = towire_tx_add_input(ctx, cid, serial_id,
- prevtx, in->tx_input.index,
- in->tx_input.sequence);
+ prevtx, in->input.index,
+ in->input.sequence);
tal_arr_remove(&set->added_ins, 0);
return msg;
@@ -274,10 +274,11 @@ static u8 *psbt_changeset_get_next(const tal_t *ctx,
if (!psbt_get_serial_id(&out->output.unknowns, &serial_id))
abort();
- asset_amt = wally_tx_output_get_amount(&out->tx_output);
+ asset_amt = wally_psbt_output_get_amount(&out->output);
sats = amount_asset_to_sat(&asset_amt);
- const u8 *script = wally_tx_output_get_script(ctx,
- &out->tx_output);
+ const u8 *script = wally_psbt_output_get_script(ctx,
+ &out->output);
+
msg = towire_tx_add_output(ctx, cid, serial_id,
sats.satoshis, /* Raw: wire interface */
@@ -596,12 +597,20 @@ static size_t psbt_input_weight(struct wally_psbt *psbt,
size_t in)
{
size_t weight;
+ const struct wally_map_item *redeem_script;
+
+ redeem_script = wally_map_get_integer(&psbt->inputs[in].psbt_fields, /* PSBT_IN_REDEEM_SCRIPT */ 0x04);
/* txid + txout + sequence */
weight = (32 + 4 + 4) * 4;
- weight +=
- (psbt->inputs[in].redeem_script_len +
- (varint_t) varint_size(psbt->inputs[in].redeem_script_len)) * 4;
+ if (redeem_script) {
+ weight +=
+ (redeem_script->value_len +
+ (varint_t) varint_size(redeem_script->value_len)) * 4;
+ } else {
+ /* zero scriptSig length */
+ weight += (varint_t) varint_size(0) * 4;
+ }
return weight;
}
@@ -609,15 +618,15 @@ static size_t psbt_input_weight(struct wally_psbt *psbt,
static size_t psbt_output_weight(struct wally_psbt *psbt,
size_t outnum)
{
- return (8 + psbt->tx->outputs[outnum].script_len +
- varint_size(psbt->tx->outputs[outnum].script_len)) * 4;
+ return (8 + psbt->outputs[outnum].script_len +
+ varint_size(psbt->outputs[outnum].script_len)) * 4;
}
static bool find_txout(struct wally_psbt *psbt, const u8 *wscript, u32 *funding_txout)
{
for (size_t i = 0; i < psbt->num_outputs; i++) {
- if (memeq(wscript, tal_bytelen(wscript), psbt->tx->outputs[i].script,
- psbt->tx->outputs[i].script_len)) {
+ if (memeq(wscript, tal_bytelen(wscript), psbt->outputs[i].script,
+ psbt->outputs[i].script_len)) {
*funding_txout = i;
return true;
}
@@ -2382,9 +2391,17 @@ static void accepter_start(struct state *state, const u8 *oc2_msg)
if (!tx_state->psbt)
tx_state->psbt = create_psbt(tx_state, 0, 0,
tx_state->tx_locktime);
- else
+ else {
/* Locktimes must match! */
- tx_state->psbt->tx->locktime = tx_state->tx_locktime;
+ tx_state->psbt->fallback_locktime = tx_state->tx_locktime;
+ if (!psbt_set_version(tx_state->psbt, 2)) {
+ status_failed(STATUS_FAIL_INTERNAL_ERROR,
+ "Could not set PSBT version: %s",
+ type_to_string(tmpctx,
+ struct wally_psbt,
+ tx_state->psbt));
+ }
+ }
/* BOLT- #2:
*
@@ -2914,6 +2931,7 @@ static void opener_start(struct state *state, u8 *msg)
struct lease_rates *expected_rates;
struct tx_state *tx_state = state->tx_state;
struct amount_sat *requested_lease;
+ size_t locktime;
if (!fromwire_dualopend_opener_init(state, msg,
&tx_state->psbt,
@@ -2930,8 +2948,8 @@ static void opener_start(struct state *state, u8 *msg)
master_badmsg(WIRE_DUALOPEND_OPENER_INIT, msg);
state->our_role = TX_INITIATOR;
- tx_state->tx_locktime = tx_state->psbt->tx->locktime;
-
+ wally_psbt_get_locktime(tx_state->psbt, &locktime);
+ tx_state->tx_locktime = locktime;
open_tlv = tlv_opening_tlvs_new(tmpctx);
/* BOLT #2:
@@ -3456,6 +3474,7 @@ static void rbf_local_start(struct state *state, u8 *msg)
/* tmpctx gets cleaned midway, so we have a context for this fn */
char *rbf_ctx = notleak_with_children(tal(state, char));
+ size_t locktime;
/* We need a new tx_state! */
tx_state = new_tx_state(rbf_ctx);
@@ -3490,8 +3509,8 @@ static void rbf_local_start(struct state *state, u8 *msg)
return;
}
- tx_state->tx_locktime = tx_state->psbt->tx->locktime;
-
+ wally_psbt_get_locktime(tx_state->psbt, &locktime);
+ tx_state->tx_locktime = locktime;
/* For now, we always just echo/send the funding amount */
init_rbf_tlvs->funding_output_contribution
= tal(init_rbf_tlvs, u64);
diff --git a/plugins/funder.c b/plugins/funder.c
index 877c5a08e..dc09e310f 100644
--- a/plugins/funder.c
+++ b/plugins/funder.c
@@ -5,6 +5,7 @@
*/
#include "config.h"
#include
+#include
#include
#include
#include
@@ -212,14 +213,14 @@ remember_channel_utxos(struct command *cmd,
signed_psbt);
utxos_bin = tal_arr(cmd, u8, 0);
- for (size_t i = 0; i < signed_psbt->tx->num_inputs; i++) {
+ for (size_t i = 0; i < signed_psbt->num_inputs; i++) {
struct bitcoin_outpoint outpoint;
/* Don't save peer's UTXOS */
if (!psbt_input_is_ours(&signed_psbt->inputs[i]))
continue;
- wally_tx_input_get_outpoint(&signed_psbt->tx->inputs[i],
+ wally_psbt_input_get_outpoint(&signed_psbt->inputs[i],
&outpoint);
towire_bitcoin_outpoint(&utxos_bin, &outpoint);
}
diff --git a/plugins/spender/multifundchannel.c b/plugins/spender/multifundchannel.c
index 28a578c07..38c836f53 100644
--- a/plugins/spender/multifundchannel.c
+++ b/plugins/spender/multifundchannel.c
@@ -572,6 +572,14 @@ after_signpsbt(struct command *cmd,
json_tok_full_len(field),
json_tok_full(buf, field));
+ if (!psbt_set_version(psbt, 2)) {
+ /* It should be well-formed? */
+ plugin_err(mfc->cmd->plugin,
+ "mfc: could not set PSBT version: %s",
+ type_to_string(tmpctx, struct wally_psbt,
+ mfc->psbt));
+ }
+
if (!psbt_finalize(psbt))
plugin_err(mfc->cmd->plugin,
"mfc %"PRIu64": Signed PSBT won't finalize"
@@ -831,11 +839,21 @@ perform_funding_tx_finalize(struct multifundchannel_command *mfc)
size_t v1_dest_count = dest_count(mfc, FUND_CHANNEL);
size_t v2_dest_count = dest_count(mfc, OPEN_CHANNEL);
size_t i, deck_i;
+ u32 psbt_version = mfc->psbt->version;
plugin_log(mfc->cmd->plugin, LOG_DBG,
"mfc %"PRIu64": Creating funding tx.",
mfc->id);
+ /* We operate over PSBTv2 only */
+ if (!psbt_set_version(mfc->psbt, 2)) {
+ /* It should be well-formed? */
+ plugin_err(mfc->cmd->plugin,
+ "mfc: could not set PSBT version: %s",
+ type_to_string(tmpctx, struct wally_psbt,
+ mfc->psbt));
+ }
+
/* Construct a deck of destinations. */
deck = tal_arr(tmpctx, struct multifundchannel_destination *,
v1_dest_count + mfc->change_needed);
@@ -929,6 +947,14 @@ perform_funding_tx_finalize(struct multifundchannel_command *mfc)
mfc->txid),
content);
+ if (!psbt_set_version(mfc->psbt, psbt_version)) {
+ /* It should be well-formed? */
+ plugin_err(mfc->cmd->plugin,
+ "mfc: could not set PSBT version: %s",
+ type_to_string(tmpctx, struct wally_psbt,
+ mfc->psbt));
+ }
+
/* Now we can feed the TXID and outnums to the peer. */
return perform_fundchannel_complete(mfc);
}
@@ -1343,6 +1369,9 @@ after_fundpsbt(struct command *cmd,
if (!mfc->psbt)
goto fail;
+ if (!psbt_set_version(mfc->psbt, 2))
+ goto fail;
+
field = json_get_member(buf, result, "feerate_per_kw");
if (!field || !json_to_u32(buf, field, &mfc->feerate_per_kw))
goto fail;
diff --git a/plugins/spender/multiwithdraw.c b/plugins/spender/multiwithdraw.c
index 9eb93c30e..d0f864077 100644
--- a/plugins/spender/multiwithdraw.c
+++ b/plugins/spender/multiwithdraw.c
@@ -421,6 +421,8 @@ mw_after_fundpsbt(struct command *cmd,
field->end - field->start) : NULL;
ok = ok && mw->psbt;
+ ok = ok && psbt_set_version(mw->psbt, 2);
+
field = ok ? json_get_member(buf, result, "feerate_per_kw") : NULL;
ok = ok && field;
ok = ok && json_to_number(buf, field, &feerate_per_kw);
diff --git a/plugins/spender/openchannel.c b/plugins/spender/openchannel.c
index 41a5bc804..74cd90839 100644
--- a/plugins/spender/openchannel.c
+++ b/plugins/spender/openchannel.c
@@ -112,9 +112,16 @@ static bool update_parent_psbt(const tal_t *ctx,
if (s_idx != -1)
goto fail;
- psbt_add_input(clone,
- &changes->added_ins[i].tx_input,
- idx);
+ const struct wally_psbt_input *input = &changes->added_ins[i].input;
+ struct bitcoin_outpoint outpoint;
+ wally_psbt_input_get_outpoint(input, &outpoint);
+ psbt_append_input(clone,
+ &outpoint,
+ input->sequence,
+ NULL /* scriptSig */,
+ NULL /* input_wscript */,
+ NULL /* redeemscript */);
+
/* Move the input over */
clone->inputs[idx] = *in;
@@ -172,9 +179,9 @@ static bool update_parent_psbt(const tal_t *ctx,
if (s_idx != -1)
goto fail;
- psbt_add_output(clone,
- &changes->added_outs[i].tx_output,
- idx);
+ const struct wally_psbt_output *output = &changes->added_outs[i].output;
+ psbt_append_output(clone, output->script, amount_sat(output->amount));
+
/* Move output over */
clone->outputs[idx] = *out;
@@ -638,8 +645,8 @@ funding_transaction_established(struct multifundchannel_command *mfc)
for (size_t j = 0; j < mfc->psbt->num_outputs; j++) {
if (memeq(dest->funding_script,
tal_bytelen(dest->funding_script),
- mfc->psbt->tx->outputs[j].script,
- mfc->psbt->tx->outputs[j].script_len))
+ mfc->psbt->outputs[j].script,
+ mfc->psbt->outputs[j].script_len))
dest->outnum = j;
}
if (dest->outnum == mfc->psbt->num_outputs)
diff --git a/plugins/txprepare.c b/plugins/txprepare.c
index 5b668043f..a80376813 100644
--- a/plugins/txprepare.c
+++ b/plugins/txprepare.c
@@ -216,7 +216,7 @@ static struct command_result *finish_txprepare(struct command *cmd,
utx = tal(NULL, struct unreleased_tx);
utx->is_upgrade = txp->is_upgrade;
utx->psbt = tal_steal(utx, txp->psbt);
- psbt_txid(utx, txp->psbt, &utx->txid, &utx->tx);
+ psbt_txid(utx, utx->psbt, &utx->txid, &utx->tx);
/* If this is a withdraw, we sign and send immediately. */
if (txp->is_withdraw) {
@@ -301,6 +301,11 @@ static struct command_result *psbt_created(struct command *cmd,
psbttok->end - psbttok->start,
buf + psbttok->start);
+ if (!psbt_set_version(txp->psbt, 2)) {
+ return command_fail(cmd, LIGHTNINGD,
+ "Unable to convert PSBT to version 2.");
+ }
+
if (!json_to_number(buf, json_get_member(buf, result, "feerate_per_kw"),
&txp->feerate))
return command_fail(cmd, LIGHTNINGD,
diff --git a/tests/test_db.py b/tests/test_db.py
index 8c8b7dea8..5229b6611 100644
--- a/tests/test_db.py
+++ b/tests/test_db.py
@@ -1,8 +1,7 @@
-from decimal import Decimal
from fixtures import * # noqa: F401,F403
from fixtures import TEST_NETWORK
from pyln.client import RpcError
-from utils import wait_for, sync_blockheight, COMPAT, VALGRIND, DEVELOPER, TIMEOUT, only_one, scid_to_int
+from utils import wait_for, sync_blockheight, COMPAT, VALGRIND, DEVELOPER, TIMEOUT, scid_to_int
import base64
import os
@@ -171,21 +170,16 @@ def test_scid_upgrade(node_factory, bitcoind):
def test_last_tx_inflight_psbt_upgrade(node_factory, bitcoind):
bitcoind.generate_block(12)
- prior_txs = ['02000000019CCCA2E59D863B00B5BD835BF7BA93CC257932D2C7CDBE51EFE2EE4A9D29DFCB01000000009DB0E280024A01000000000000220020BE7935A77CA9AB70A4B8B1906825637767FED3C00824AA90C988983587D68488F0820100000000002200209F4684DDB28ACDC73959BC194D1A25DF906F61ED030F52D163E6F1E247D32CBB9A3ED620', '020000000122F9EBE38F54208545B681AD7F73A7AE3504A09C8201F502673D34E28424687C01000000009DB0E280024A01000000000000220020BE7935A77CA9AB70A4B8B1906825637767FED3C00824AA90C988983587D68488F0820100000000002200209F4684DDB28ACDC73959BC194D1A25DF906F61ED030F52D163E6F1E247D32CBB9A3ED620']
+ # FIXME: Re-add dynamic checks once PSBTv2 support is in both Core/Elements, or get python support
+ # These PSBTs were manually checked for 0.001 BTC multisig witness utxos in a single input
+ upgraded_psbts = ['cHNidP8BAgQCAAAAAQMEmj7WIAEEAQEBBQECAQYBAwH7BAIAAAAAAQEroIYBAAAAAAAiACBbjNO5FM9nzdj6YnPJMDU902R2c0+9liECwt9TuQiAzSICAuO9OACYZsnajsSqmcxOqcbA3UbfFcYe8M4fJxKRcU5XRjBDAiBgFZ+8xOkvxfBoC9QdAhBuX6zhpvKsqWw8QeN2gK1b4wIfQdSIq+vNMfnFZqLyv3Un4s7i2MzHUiTs2morB/t/SwEBAwQBAAAAAQVHUiECMkJm3oQDs6sVegnx94TVh69hgxyZjBUbzCG7dMKyMUshAuO9OACYZsnajsSqmcxOqcbA3UbfFcYe8M4fJxKRcU5XUq4iBgIyQmbehAOzqxV6CfH3hNWHr2GDHJmMFRvMIbt0wrIxSwhK0xNpAAAAACIGAuO9OACYZsnajsSqmcxOqcbA3UbfFcYe8M4fJxKRcU5XCBq8wdAAAAAAAQ4gnMyi5Z2GOwC1vYNb97qTzCV5MtLHzb5R7+LuSp0p38sBDwQBAAAAARAEnbDigAABAwhKAQAAAAAAAAEEIgAgvnk1p3ypq3CkuLGQaCVjd2f+08AIJKqQyYiYNYfWhIgAAQMI8IIBAAAAAAABBCIAIJ9GhN2yis3HOVm8GU0aJd+Qb2HtAw9S0WPm8eJH0yy7AA==', 'cHNidP8BAgQCAAAAAQMEmj7WIAEEAQEBBQECAQYBAwH7BAIAAAAAAQEroIYBAAAAAAAiACBbjNO5FM9nzdj6YnPJMDU902R2c0+9liECwt9TuQiAzSICAuO9OACYZsnajsSqmcxOqcbA3UbfFcYe8M4fJxKRcU5XRzBEAiBWXvsSYMpD69abqr7X9XurE6B6GkhyI5JeGuKYByBukAIgUmk9q/g3PIS9HjTVJ4OmRoSZAMKLFdsowq15Sl9OAD8BAQMEAQAAAAEFR1IhAjJCZt6EA7OrFXoJ8feE1YevYYMcmYwVG8whu3TCsjFLIQLjvTgAmGbJ2o7EqpnMTqnGwN1G3xXGHvDOHycSkXFOV1KuIgYCMkJm3oQDs6sVegnx94TVh69hgxyZjBUbzCG7dMKyMUsIStMTaQAAAAAiBgLjvTgAmGbJ2o7EqpnMTqnGwN1G3xXGHvDOHycSkXFOVwgavMHQAAAAAAEOICL56+OPVCCFRbaBrX9zp641BKCcggH1Amc9NOKEJGh8AQ8EAQAAAAEQBJ2w4oAAAQMISgEAAAAAAAABBCIAIL55Nad8qatwpLixkGglY3dn/tPACCSqkMmImDWH1oSIAAEDCPCCAQAAAAAAAQQiACCfRoTdsorNxzlZvBlNGiXfkG9h7QMPUtFj5vHiR9MsuwA=']
l1 = node_factory.get_node(dbfile='upgrade_inflight.sqlite3.xz',
options={'database-upgrade': True})
b64_last_txs = [base64.b64encode(x['last_tx']).decode('utf-8') for x in l1.db_query('SELECT last_tx FROM channel_funding_inflights ORDER BY channel_id, funding_feerate;')]
for i in range(len(b64_last_txs)):
- bpsbt = b64_last_txs[i]
- psbt = bitcoind.rpc.decodepsbt(bpsbt)
- tx = prior_txs[i]
- assert psbt['tx']['txid'] == bitcoind.rpc.decoderawtransaction(tx)['txid']
- funding_input = only_one(psbt['inputs'])
- assert funding_input['witness_utxo']['amount'] == Decimal('0.001')
- assert funding_input['witness_utxo']['scriptPubKey']['type'] == 'witness_v0_scripthash'
- assert funding_input['witness_script']['type'] == 'multisig'
+ assert b64_last_txs[i] == upgraded_psbts[i]
@unittest.skipIf(not COMPAT, "needs COMPAT to convert obsolete db")
@@ -194,22 +188,16 @@ def test_last_tx_inflight_psbt_upgrade(node_factory, bitcoind):
def test_last_tx_psbt_upgrade(node_factory, bitcoind):
bitcoind.generate_block(12)
- prior_txs = ['02000000018DD699861B00061E50937A233DB584BF8ED4C0BF50B44C0411F71B031A06455000000000000EF7A9800350C300000000000022002073356CFF7E1588F14935EF138E142ABEFB5F7E3D51DE942758DCD5A179449B6250A90600000000002200202DF545EA882889846C52FC5E111AC07CE07E0C09418AC15743A6F6284C2A4FA720A1070000000000160014E89954FAC8F7A2DCE51E095D7BEB5271C3F7DA56EF81DC20', '02000000018A0AE4C63BCDF9D78B07EB4501BB23404FDDBC73973C592793F047BE1495074B010000000074D99980010A2D0F00000000002200203B8CB644781CBECA96BE8B2BF1827AFD908B3CFB5569AC74DAB9395E8DDA39E4C9555420', '020000000135DAB2996E57762E3EC158C0D57D39F43CA657E882D93FC24F5FEBAA8F36ED9A0100000000566D1D800350C30000000000002200205679A7D06E1BD276AA25F56E9E4DF7E07D9837EFB0C5F63604F10CD9F766A03ED4DD0600000000001600147E5B5C8F4FC1A9484E259F92CA4CBB7FA2814EA49A6C070000000000220020AB6226DEBFFEFF4A741C01367FA3C875172483CFB3E327D0F8C7AA4C51EDECAA27AA4720']
+ # FIXME: Re-add dynamic checks once PSBTv2 support is in both Core/Elements, or get python support
+ # These PSBTs were manually checked for 0.01 BTC multisig witness utxos in a single input
+ upgraded_psbts = ['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']
l1 = node_factory.get_node(dbfile='last_tx_upgrade.sqlite3.xz',
options={'database-upgrade': True})
b64_last_txs = [base64.b64encode(x['last_tx']).decode('utf-8') for x in l1.db_query('SELECT last_tx FROM channels ORDER BY id;')]
for i in range(len(b64_last_txs)):
- bpsbt = b64_last_txs[i]
- psbt = bitcoind.rpc.decodepsbt(bpsbt)
- tx = prior_txs[i]
- assert psbt['tx']['txid'] == bitcoind.rpc.decoderawtransaction(tx)['txid']
- funding_input = only_one(psbt['inputs'])
- # Every opened channel was funded with the same amount: 1M sats
- assert funding_input['witness_utxo']['amount'] == Decimal('0.01')
- assert funding_input['witness_utxo']['scriptPubKey']['type'] == 'witness_v0_scripthash'
- assert funding_input['witness_script']['type'] == 'multisig'
+ assert b64_last_txs[i] == upgraded_psbts[i]
l1.stop()
# Test again, but this time with a database with a closed channel + forgotten peer
@@ -222,8 +210,9 @@ def test_last_tx_psbt_upgrade(node_factory, bitcoind):
options={'database-upgrade': True})
last_txs = [x['last_tx'] for x in l2.db_query('SELECT last_tx FROM channels ORDER BY id;')]
- # The first tx should be psbt, the second should still be hex
- bitcoind.rpc.decodepsbt(base64.b64encode(last_txs[0]).decode('utf-8'))
+ # The first tx should be psbt, the second should still be hex (Newer Core version required for better error message)
+ assert last_txs[0][:4] == b'psbt'
+
bitcoind.rpc.decoderawtransaction(last_txs[1].hex())
diff --git a/tests/test_misc.py b/tests/test_misc.py
index 02c7e17ee..c040c76c4 100644
--- a/tests/test_misc.py
+++ b/tests/test_misc.py
@@ -461,6 +461,7 @@ def test_bech32_funding(node_factory, chainparams):
assert only_one(fundingtx['vin'])['txid'] == res['wallettxid']
+@unittest.skipIf(not TEST_NETWORK == 'regtest', 'no support for PSETv0')
def test_withdraw_misc(node_factory, bitcoind, chainparams):
def dont_spend_outputs(n, txid):
"""Reserve both outputs (we assume there are two!) in case any our ours, so we don't spend change: wrecks accounting checks"""
diff --git a/tests/test_wallet.py b/tests/test_wallet.py
index 6d4ccac3c..20090b0c4 100644
--- a/tests/test_wallet.py
+++ b/tests/test_wallet.py
@@ -441,6 +441,7 @@ def test_txprepare(node_factory, bitcoind, chainparams):
assert decode['vout'][changenum]['scriptPubKey']['type'] == 'witness_v0_keyhash'
+@unittest.skipIf(TEST_NETWORK == 'liquid-regtest', '')
def test_reserveinputs(node_factory, bitcoind, chainparams):
amount = 1000000
total_outs = 12
@@ -494,6 +495,7 @@ def test_reserveinputs(node_factory, bitcoind, chainparams):
assert not any('reserved_to_block' in o for o in l1.rpc.listfunds()['outputs'])
+@unittest.skipIf(TEST_NETWORK == 'liquid-regtest', '')
def test_fundpsbt(node_factory, bitcoind, chainparams):
amount = 1000000
total_outs = 4
@@ -577,6 +579,7 @@ def test_fundpsbt(node_factory, bitcoind, chainparams):
l1.rpc.fundpsbt(amount // 2, feerate, 0)
+@unittest.skipIf(TEST_NETWORK == 'liquid-regtest', '')
def test_utxopsbt(node_factory, bitcoind, chainparams):
amount = 1000000
l1 = node_factory.get_node()
@@ -691,6 +694,7 @@ def test_utxopsbt(node_factory, bitcoind, chainparams):
reservedok=True)
+@unittest.skipIf(TEST_NETWORK == 'liquid-regtest', '')
def test_sign_external_psbt(node_factory, bitcoind, chainparams):
"""
A PSBT w/ one of our inputs should be signable (we can fill
@@ -719,6 +723,7 @@ def test_sign_external_psbt(node_factory, bitcoind, chainparams):
l1.rpc.signpsbt(psbt)
+@unittest.skipIf(TEST_NETWORK == 'liquid-regtest', '')
def test_sign_and_send_psbt(node_factory, bitcoind, chainparams):
"""
Tests for the sign + send psbt RPCs
diff --git a/wallet/reservation.c b/wallet/reservation.c
index da1e27454..d131aa375 100644
--- a/wallet/reservation.c
+++ b/wallet/reservation.c
@@ -97,12 +97,21 @@ static struct command_result *json_reserveinputs(struct command *cmd,
NULL))
return command_param_failed();
+ /* We only deal with V2 internally */
+ if (!psbt_set_version(psbt, 2)) {
+ return command_fail(cmd, LIGHTNINGD,
+ "Failed to set version for PSBT: %s",
+ type_to_string(tmpctx,
+ struct wally_psbt,
+ psbt));
+ }
+
current_height = get_block_height(cmd->ld->topology);
- for (size_t i = 0; i < psbt->tx->num_inputs; i++) {
+ for (size_t i = 0; i < psbt->num_inputs; i++) {
struct bitcoin_outpoint outpoint;
struct utxo *utxo;
- wally_tx_input_get_outpoint(&psbt->tx->inputs[i], &outpoint);
+ wally_psbt_input_get_outpoint(&psbt->inputs[i], &outpoint);
utxo = wallet_utxo_get(cmd, cmd->ld->wallet, &outpoint);
if (!utxo)
continue;
@@ -152,6 +161,14 @@ static struct command_result *json_unreserveinputs(struct command *cmd,
NULL))
return command_param_failed();
+ /* We only deal with V2 internally */
+ if (!psbt_set_version(psbt, 2)) {
+ log_broken(cmd->ld->log,
+ "Unable to set version for PSBT: %s",
+ type_to_string(tmpctx, struct wally_psbt,
+ psbt));
+ }
+
/* We should also add the utxo info for these inputs!
* (absolutely required for using this psbt in a dual-funded
* round) */
@@ -159,7 +176,7 @@ static struct command_result *json_unreserveinputs(struct command *cmd,
struct bitcoin_tx *utxo_tx;
struct bitcoin_txid txid;
- wally_tx_input_get_txid(&psbt->tx->inputs[i], &txid);
+ wally_psbt_input_get_txid(&psbt->inputs[i], &txid);
utxo_tx = wallet_transaction_get(psbt, cmd->ld->wallet,
&txid);
if (utxo_tx) {
@@ -176,13 +193,13 @@ static struct command_result *json_unreserveinputs(struct command *cmd,
response = json_stream_success(cmd);
json_array_start(response, "reservations");
- for (size_t i = 0; i < psbt->tx->num_inputs; i++) {
+ for (size_t i = 0; i < psbt->num_inputs; i++) {
struct bitcoin_outpoint outpoint;
struct utxo *utxo;
enum output_status oldstatus;
u32 old_res;
- wally_tx_input_get_outpoint(&psbt->tx->inputs[i], &outpoint);
+ wally_psbt_input_get_outpoint(&psbt->inputs[i], &outpoint);
utxo = wallet_utxo_get(cmd, cmd->ld->wallet, &outpoint);
if (!utxo || utxo->status != OUTPUT_STATE_RESERVED)
continue;
@@ -295,14 +312,10 @@ static struct wally_psbt *psbt_using_utxos(const tal_t *ctx,
psbt_input_set_wit_utxo(psbt, i, scriptPubkey, utxos[i]->amount);
if (is_elements(chainparams)) {
- struct amount_asset asset;
/* FIXME: persist asset tags */
- asset = amount_sat_to_asset(&utxos[i]->amount,
+ amount_sat_to_asset(&utxos[i]->amount,
chainparams->fee_asset_tag);
/* FIXME: persist nonces */
- psbt_elements_input_set_asset(psbt,
- psbt->num_inputs - 1,
- &asset);
}
/* FIXME: as of 17 sept 2020, elementsd is *at most* at par
@@ -358,7 +371,7 @@ static struct command_result *finish_psbt(struct command *cmd,
psbt = psbt_using_utxos(cmd, cmd->ld->wallet, utxos,
*locktime, BITCOIN_TX_RBF_SEQUENCE);
-
+ assert(psbt->version == 2);
/* Should we add a change output for the excess? */
if (excess_as_change) {
struct amount_sat change;
@@ -401,7 +414,14 @@ fee_calc:
psbt_append_output(psbt, NULL, est_fee);
/* Add additional weight of fee output */
weight += bitcoin_tx_output_weight(0);
+ } else {
+ /* PSETv0 doesn't exist */
+ if (!psbt_set_version(psbt, 0)) {
+ return command_fail(cmd, LIGHTNINGD,
+ "Failed to set PSBT version number back to 0.");
+ }
}
+
response = json_stream_success(cmd);
json_add_psbt(response, "psbt", psbt);
json_add_num(response, "feerate_per_kw", feerate_per_kw);
diff --git a/wallet/walletrpc.c b/wallet/walletrpc.c
index aa3e2ea7e..0f6ccab73 100644
--- a/wallet/walletrpc.c
+++ b/wallet/walletrpc.c
@@ -614,14 +614,14 @@ static struct command_result *match_psbt_inputs_to_utxos(struct command *cmd,
struct utxo ***utxos)
{
*utxos = tal_arr(cmd, struct utxo *, 0);
- for (size_t i = 0; i < psbt->tx->num_inputs; i++) {
+ for (size_t i = 0; i < psbt->num_inputs; i++) {
struct utxo *utxo;
struct bitcoin_outpoint outpoint;
if (only_inputs && !in_only_inputs(only_inputs, i))
continue;
- wally_tx_input_get_outpoint(&psbt->tx->inputs[i], &outpoint);
+ wally_psbt_input_get_outpoint(&psbt->inputs[i], &outpoint);
utxo = wallet_utxo_get(*utxos, cmd->ld->wallet, &outpoint);
if (!utxo) {
if (only_inputs)
@@ -673,7 +673,6 @@ static struct command_result *match_psbt_inputs_to_utxos(struct command *cmd,
static void match_psbt_outputs_to_wallet(struct wally_psbt *psbt,
struct wallet *w)
{
- assert(psbt->tx->num_outputs == psbt->num_outputs);
tal_wally_start();
for (size_t outndx = 0; outndx < psbt->num_outputs; ++outndx) {
u32 index;
@@ -681,8 +680,8 @@ static void match_psbt_outputs_to_wallet(struct wally_psbt *psbt,
const u8 *script;
struct ext_key ext;
- script = wally_tx_output_get_script(tmpctx,
- &psbt->tx->outputs[outndx]);
+ script = wally_psbt_output_get_script(tmpctx,
+ &psbt->outputs[outndx]);
if (!script)
continue;
@@ -735,6 +734,7 @@ static struct command_result *json_signpsbt(struct command *cmd,
struct wally_psbt *psbt, *signed_psbt;
struct utxo **utxos;
u32 *input_nums;
+ u32 psbt_version;
if (!param(cmd, buffer, params,
p_req("psbt", param_psbt, &psbt),
@@ -742,6 +742,15 @@ static struct command_result *json_signpsbt(struct command *cmd,
NULL))
return command_param_failed();
+ /* We internally deal with v2 only but we want to return V2 if given */
+ psbt_version = psbt->version;
+ if (!psbt_set_version(psbt, 2)) {
+ return command_fail(cmd, LIGHTNINGD,
+ "Could not set PSBT version: %s",
+ type_to_string(tmpctx, struct wally_psbt,
+ psbt));
+ }
+
/* Sanity check! */
for (size_t i = 0; i < tal_count(input_nums); i++) {
if (input_nums[i] >= psbt->num_inputs)
@@ -782,6 +791,13 @@ static struct command_result *json_signpsbt(struct command *cmd,
"HSM gave bad sign_withdrawal_reply %s",
tal_hex(tmpctx, msg));
+ if (!psbt_set_version(signed_psbt, psbt_version)) {
+ return command_fail(cmd, LIGHTNINGD,
+ "Signed PSBT unable to have version set: %s",
+ type_to_string(tmpctx, struct wally_psbt,
+ psbt));
+ }
+
response = json_stream_success(cmd);
json_add_psbt(response, "signed_psbt", signed_psbt);
return command_success(cmd, response);
@@ -824,8 +840,8 @@ static void maybe_notify_new_external_send(struct lightningd *ld,
return;
/* If it's going to our wallet, ignore */
- script = wally_tx_output_get_script(tmpctx,
- &psbt->tx->outputs[outnum]);
+ script = wally_psbt_output_get_script(tmpctx,
+ &psbt->outputs[outnum]);
if (wallet_can_spend(ld->wallet, script, &index, &is_p2sh))
return;
@@ -870,6 +886,11 @@ static void sendpsbt_done(struct bitcoind *bitcoind UNUSED,
return;
}
+ /* Internal-only after, set to v2 */
+ if (!psbt_set_version(sending->psbt, 2)) {
+ abort(); // Send succeeded but later calls may fail
+ }
+
wallet_transaction_add(ld->wallet, sending->wtx, 0, 0);
/* Extract the change output and add it to the DB */