psbt: finalize to-remote with option_anchor_outputs.

Until it gains miniscript support, wally doesn't know how to
finalize P2WSH.  This happens with `option_anchor_outputs` for
to-remote, which requires a 1 block delay to force use of
anchor outputs for CPFP.

So we finalize this ourselves.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
Rusty Russell 2020-08-14 11:00:42 +09:30
parent 754765c139
commit 591e8f9663
5 changed files with 63 additions and 0 deletions

View File

@ -343,6 +343,44 @@ struct wally_tx *psbt_finalize(struct wally_psbt *psbt, bool finalize_in_place)
} else
tmppsbt = cast_const(struct wally_psbt *, psbt);
/* Wally doesn't know how to finalize P2WSH; this happens with
* option_anchor_outputs, and finalizing is trivial. */
/* FIXME: miniscript! miniscript! miniscript! */
for (size_t i = 0; i < tmppsbt->num_inputs; i++) {
struct wally_psbt_input *input = &tmppsbt->inputs[i];
struct wally_tx_witness_stack *stack;
if (!is_anchor_witness_script(input->witness_script,
input->witness_script_len))
continue;
if (input->signatures.num_items != 1)
continue;
/* BOLT-a12da24dd0102c170365124782b46d9710950ac1 #3:
* #### `to_remote` Output
*...
*
* If `option_anchor_outputs` applies to the commitment
* transaction, the `to_remote` output is encumbered by a one
* block csv lock.
*
* <remote_pubkey> OP_CHECKSIGVERIFY 1 OP_CHECKSEQUENCEVERIFY
*
* The output is spent by a transaction with `nSequence` field set to `1` and witness:
*
* <remote_sig>
*/
wally_tx_witness_stack_init_alloc(2, &stack);
wally_tx_witness_stack_add(stack,
input->signatures.items[0].value,
input->signatures.items[0].value_len);
wally_tx_witness_stack_add(stack,
input->witness_script,
input->witness_script_len);
input->final_witness = stack;
}
if (wally_psbt_finalize(tmppsbt) != WALLY_OK) {
if (!finalize_in_place)
wally_psbt_free(tmppsbt);

View File

@ -340,9 +340,25 @@ u8 *anchor_to_remote_redeem(const tal_t *ctx,
add_number(&script, 1);
add_op(&script, OP_CHECKSEQUENCEVERIFY);
assert(is_anchor_witness_script(script, tal_bytelen(script)));
return script;
}
bool is_anchor_witness_script(const u8 *script, size_t script_len)
{
if (script_len != 34 + 1 + 1 + 1)
return false;
if (script[0] != OP_PUSHBYTES(33))
return false;
if (script[34] != OP_CHECKSIGVERIFY)
return false;
if (script[35] != 0x51)
return false;
if (script[36] != OP_CHECKSEQUENCEVERIFY)
return false;
return true;
}
/* Create a witness which spends the 2of2. */
u8 **bitcoin_witness_2of2(const tal_t *ctx,
const struct bitcoin_signature *sig1,

View File

@ -149,6 +149,9 @@ bool is_p2wpkh(const u8 *script, struct bitcoin_address *addr);
/* Is this one of the four above script types? */
bool is_known_scripttype(const u8 *script);
/* Is this an anchor witness script? */
bool is_anchor_witness_script(const u8 *script, size_t script_len);
/* Are these two scripts equal? */
bool scripteq(const u8 *s1, const u8 *s2);

View File

@ -63,6 +63,9 @@ u16 fromwire_u16(const u8 **cursor UNNEEDED, size_t *max UNNEEDED)
/* Generated stub for fromwire_u32 */
u32 fromwire_u32(const u8 **cursor UNNEEDED, size_t *max UNNEEDED)
{ fprintf(stderr, "fromwire_u32 called!\n"); abort(); }
/* 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(); }

View File

@ -64,6 +64,9 @@ u16 fromwire_u16(const u8 **cursor UNNEEDED, size_t *max UNNEEDED)
/* Generated stub for fromwire_u32 */
u32 fromwire_u32(const u8 **cursor UNNEEDED, size_t *max UNNEEDED)
{ fprintf(stderr, "fromwire_u32 called!\n"); abort(); }
/* 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(); }