Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Zero fee htlc: Finally add support (experimental!) #6137

Closed
Closed
26 changes: 23 additions & 3 deletions bitcoin/psbt.c
Original file line number Diff line number Diff line change
Expand Up @@ -603,18 +603,24 @@ bool psbt_finalize(struct wally_psbt *psbt)
tal_wally_start();

/* Wally doesn't know how to finalize P2WSH; this happens with
* option_anchor_outputs, and finalizing is trivial. */
* option_anchor_outputs, and finalizing those two cases is trivial. */
/* FIXME: miniscript! miniscript! miniscript! */
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;

iws = wally_map_get_integer(&input->psbt_fields, /* PSBT_IN_WITNESS_SCRIPT */ 0x05);
if (!iws || !is_to_remote_anchored_witness_script(iws->value,
iws->value_len))
if (!iws)
continue;

if (!is_to_remote_anchored_witness_script(iws->value,
iws->value_len)
&& !is_anchor_witness_script(iws->value,
iws->value_len)) {
continue;
}

if (input->signatures.num_items != 1)
continue;

Expand All @@ -632,6 +638,19 @@ bool psbt_finalize(struct wally_psbt *psbt)
*
* <remote_sig>
*/
/* BOLT #3:
* #### `to_local_anchor` and `to_remote_anchor` Output (option_anchors)
*...
* <local_funding_pubkey/remote_funding_pubkey> OP_CHECKSIG OP_IFDUP
* OP_NOTIF
* OP_16 OP_CHECKSEQUENCEVERIFY
* OP_ENDIF
*...
* Spending of the output requires the following witness:
* <local_sig/remote_sig>
*/

/* i.e. in both cases, this is the same thing */
wally_tx_witness_stack_init_alloc(2, &stack);
wally_tx_witness_stack_add(stack,
input->signatures.items[0].value,
Expand All @@ -640,6 +659,7 @@ bool psbt_finalize(struct wally_psbt *psbt)
iws->value,
iws->value_len);
wally_psbt_input_set_final_witness(input, stack);
wally_tx_witness_stack_free(stack);
}

ok = (wally_psbt_finalize(psbt) == WALLY_OK);
Expand Down
22 changes: 22 additions & 0 deletions bitcoin/script.c
Original file line number Diff line number Diff line change
Expand Up @@ -874,9 +874,31 @@ u8 *bitcoin_wscript_anchor(const tal_t *ctx,
add_op(&script, OP_CHECKSEQUENCEVERIFY);
add_op(&script, OP_ENDIF);

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 + 1 + 1 + 1)
return false;
if (script[0] != OP_PUSHBYTES(33))
return false;
if (script[34] != OP_CHECKSIG)
return false;
if (script[35] != OP_IFDUP)
return false;
if (script[36] != OP_NOTIF)
return false;
if (script[37] != 0x50 + 16)
return false;
if (script[38] != OP_CHECKSEQUENCEVERIFY)
return false;
if (script[39] != OP_ENDIF)
return false;
return true;
Comment on lines +889 to +905
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A template comparison system would be nice here, but probably overkill 🤔

}

bool scripteq(const u8 *s1, const u8 *s2)
{
memcheck(s1, tal_count(s1));
Expand Down
3 changes: 3 additions & 0 deletions bitcoin/script.h
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,9 @@ bool is_known_scripttype(const u8 *script);
/* Is this a to-remote witness script (used for option_anchor_outputs)? */
bool is_to_remote_anchored_witness_script(const u8 *script, size_t script_len);

/* 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);

Expand Down
3 changes: 3 additions & 0 deletions bitcoin/test/run-bitcoin_block_from_hex.c
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,9 @@ u8 fromwire_u8(const u8 **cursor UNNEEDED, size_t *max UNNEEDED)
/* Generated stub for fromwire_u8_array */
void fromwire_u8_array(const u8 **cursor UNNEEDED, size_t *max UNNEEDED, u8 *arr UNNEEDED, size_t num UNNEEDED)
{ fprintf(stderr, "fromwire_u8_array 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_to_remote_anchored_witness_script */
bool is_to_remote_anchored_witness_script(const u8 *script UNNEEDED, size_t script_len UNNEEDED)
{ fprintf(stderr, "is_to_remote_anchored_witness_script called!\n"); abort(); }
Expand Down
3 changes: 3 additions & 0 deletions bitcoin/test/run-psbt-from-tx.c
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,9 @@ struct amount_sat amount_tx_fee(u32 fee_per_kw UNNEEDED, size_t weight UNNEEDED)
void fromwire_sha256_double(const u8 **cursor UNNEEDED, size_t *max UNNEEDED,
struct sha256_double *sha256d UNNEEDED)
{ fprintf(stderr, "fromwire_sha256_double 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_to_remote_anchored_witness_script */
bool is_to_remote_anchored_witness_script(const u8 *script UNNEEDED, size_t script_len UNNEEDED)
{ fprintf(stderr, "is_to_remote_anchored_witness_script called!\n"); abort(); }
Expand Down
3 changes: 3 additions & 0 deletions bitcoin/test/run-tx-encode.c
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,9 @@ u8 fromwire_u8(const u8 **cursor UNNEEDED, size_t *max UNNEEDED)
/* Generated stub for fromwire_u8_array */
void fromwire_u8_array(const u8 **cursor UNNEEDED, size_t *max UNNEEDED, u8 *arr UNNEEDED, size_t num UNNEEDED)
{ fprintf(stderr, "fromwire_u8_array 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_to_remote_anchored_witness_script */
bool is_to_remote_anchored_witness_script(const u8 *script UNNEEDED, size_t script_len UNNEEDED)
{ fprintf(stderr, "is_to_remote_anchored_witness_script called!\n"); abort(); }
Expand Down