From 0cd7fe50893117ace12d26fb2d00b097a1e59091 Mon Sep 17 00:00:00 2001 From: niftynei Date: Thu, 29 Jun 2023 15:03:50 -0500 Subject: [PATCH] spec: update to latest dual-funding wire changes the witnesses are maddeningly weird now (you concat everything together) we also changed some things to be s64's (it's a teeny tiny change) --- channeld/channeld.c | 4 +- common/psbt_internal.c | 139 +++++++++++++----- common/psbt_internal.h | 21 +-- openingd/dualopend.c | 32 ++-- ...racted_peer_11_openchannelv2_updates.patch | 43 ++++++ wire/peer_wire.csv | 17 +-- 6 files changed, 177 insertions(+), 79 deletions(-) create mode 100644 wire/extracted_peer_11_openchannelv2_updates.patch diff --git a/channeld/channeld.c b/channeld/channeld.c index c48d1ea6f..439b55b33 100644 --- a/channeld/channeld.c +++ b/channeld/channeld.c @@ -2091,7 +2091,7 @@ static void handle_peer_shutdown(struct peer *peer, const u8 *shutdown) static void handle_unexpected_tx_sigs(struct peer *peer, const u8 *msg) { - const struct witness_stack **ws; + const struct witness **witnesses; struct channel_id cid; struct bitcoin_txid txid; @@ -2099,7 +2099,7 @@ static void handle_unexpected_tx_sigs(struct peer *peer, const u8 *msg) * This happens when they've/we've exchanged channel_ready, * but they did not receive our channel_ready. */ if (!fromwire_tx_signatures(tmpctx, msg, &cid, &txid, - cast_const3(struct witness_stack ***, &ws))) + cast_const3(struct witness ***, &witnesses))) peer_failed_warn(peer->pps, &peer->channel_id, "Bad tx_signatures %s", tal_hex(msg, msg)); diff --git a/common/psbt_internal.c b/common/psbt_internal.c index 475b4cabc..454e824fb 100644 --- a/common/psbt_internal.c +++ b/common/psbt_internal.c @@ -1,33 +1,97 @@ #include "config.h" +#include +#include #include +#include #include #include #include + +static bool next_size(const u8 **cursor, size_t *max, size_t *size) +{ + size_t len; + varint_t varint; + + if (*max < 1) + return false; + + len = varint_get(*cursor, *max, &varint); + + if (len < 1) + return false; + + if (*max < len) { + *max = 0; + return false; + } + + *cursor += len; + *max -= len; + *size = varint; + return true; +} + +static u8 *next_script(const tal_t *ctx, const u8 **cursor, size_t *max) +{ + const u8 *p; + size_t size; + u8 *ret; + + if (!next_size(cursor, max, &size)) + return NULL; + + if (*max < size) { + *max = 0; + return NULL; + } + + p = *cursor; + *max -= size; + *cursor += size; + + ret = tal_arr(ctx, u8, size); + memcpy(ret, p, size); + return ret; +} + static void psbt_input_set_final_witness_stack(const tal_t *ctx, struct wally_psbt_input *in, - const struct witness_element **elements) + const struct witness *witness) { + u8 *script, *sctx; + const u8 *data = witness->witness_data; + size_t size, max = tal_count(data); + bool ok; + wally_tx_witness_stack_free(in->final_witness); - tal_wally_start(); - wally_tx_witness_stack_init_alloc(tal_count(elements), - &in->final_witness); + /* FIXME: return an error?? */ + if (!next_size(&data, &max, &size)) + return; + + tal_wally_start(); + sctx = tal(NULL, u8); + + wally_tx_witness_stack_init_alloc(size, &in->final_witness); + + while ((script = next_script(sctx, &data, &max)) && script != NULL) { + ok = (wally_tx_witness_stack_add(in->final_witness, + script, tal_count(script)) == WALLY_OK); + assert(ok); + } - for (size_t i = 0; i < tal_count(elements); i++) - wally_tx_witness_stack_add(in->final_witness, - elements[i]->witness_data, - tal_bytelen(elements[i]->witness_data)); tal_wally_end(ctx); + tal_free(sctx); } void psbt_finalize_input(const tal_t *ctx, struct wally_psbt_input *in, - const struct witness_element **elements) + const struct witness *witness) { const struct wally_map_item *redeem_script; - psbt_input_set_final_witness_stack(ctx, in, elements); + psbt_input_set_final_witness_stack(ctx, in, witness); /* There's this horrible edgecase where we set the final_witnesses * directly onto the PSBT, but the input is a P2SH-wrapped input @@ -49,22 +113,20 @@ void psbt_finalize_input(const tal_t *ctx, } } -const struct witness_stack ** -psbt_to_witness_stacks(const tal_t *ctx, - const struct wally_psbt *psbt, - enum tx_role side_to_stack) +const struct witness ** +psbt_to_witnesses(const tal_t *ctx, + const struct wally_psbt *psbt, + enum tx_role side_to_stack) { - size_t stack_index; u64 serial_id; - const struct witness_stack **stacks - = tal_arr(ctx, const struct witness_stack *, psbt->num_inputs); + const struct witness **witnesses = + tal_arr(ctx, const struct witness *, 0); - stack_index = 0; for (size_t i = 0; i < psbt->num_inputs; i++) { if (!psbt_get_serial_id(&psbt->inputs[i].unknowns, &serial_id)) /* FIXME: throw an error ? */ - return NULL; + return tal_free(witnesses); /* BOLT-f53ca2301232db780843e894f55d95d512f297f9 #2: * - if is the *initiator*: @@ -73,32 +135,29 @@ psbt_to_witness_stacks(const tal_t *ctx, if (serial_id % 2 == side_to_stack) { struct wally_tx_witness_stack *wtx_s = psbt->inputs[i].final_witness; - struct witness_stack *stack = - tal(stacks, struct witness_stack); - /* Convert the wally_tx_witness_stack to - * a witness_stack entry */ - stack->witness_elements = - tal_arr(stack, struct witness_element *, - wtx_s->num_items); - for (size_t j = 0; j < tal_count(stack->witness_elements); j++) { - stack->witness_elements[j] = tal(stack, - struct witness_element); - stack->witness_elements[j]->witness_data = - tal_dup_arr(stack, u8, - wtx_s->items[j].witness, - wtx_s->items[j].witness_len, - 0); + /* BOLT-e299850cb5ebd8bd9c55763bbc498fcdf94a9567 #2: + * + * The `witness_data` is encoded as per bitcoin's + * wire protocol (a CompactSize number of elements, + * with each element a CompactSize length and that + * many bytes following. Each `witness_data` field + * contains all of the witness elements for a single input, + * including the leading counter of elements. + */ + struct witness *wit = tal(witnesses, struct witness); + wit->witness_data = tal_arr(wit, u8, 0); + add_varint(&wit->witness_data, wtx_s->num_items); + for (size_t j = 0; j < wtx_s->num_items; j++) { + add_varint(&wit->witness_data, wtx_s->items[j].witness_len); + tal_expand(&wit->witness_data, wtx_s->items[j].witness, + wtx_s->items[j].witness_len); } - stacks[stack_index++] = stack; + tal_arr_expand(&witnesses, wit); } } - if (stack_index == 0) - return tal_free(stacks); - - tal_resize(&stacks, stack_index); - return stacks; + return witnesses; } diff --git a/common/psbt_internal.h b/common/psbt_internal.h index b0f0e5ba5..166c7a91f 100644 --- a/common/psbt_internal.h +++ b/common/psbt_internal.h @@ -7,7 +7,7 @@ struct wally_psbt; struct wally_psbt_input; -struct witness_element; +struct witness; /* psbt_finalize_input - Finalize an input with a given witness stack * @@ -15,21 +15,22 @@ struct witness_element; * the redeem_script, if any. * @ctx - the context to allocate onto * @in - input to set final_witness for - * @witness_element - elements to add to witness stack + * @witness - witness data to add to witness stack */ void psbt_finalize_input(const tal_t *ctx, struct wally_psbt_input *in, - const struct witness_element **elements); -/* psbt_to_witness_stacks - Take all sigs on a PSBT and copy to a - * witness_stack + const struct witness *witness); + +/* psbt_to_witness_stacks - Take a side's sigs from a PSBT and copy to a + * wire witness * * @ctx - allocation context * @psbt - PSBT to copy sigs from - * @opener - which side initiated this tx + * @side_to_stack - which side to stack witnesses of */ -const struct witness_stack ** -psbt_to_witness_stacks(const tal_t *ctx, - const struct wally_psbt *psbt, - enum tx_role side_to_stack); +const struct witness ** +psbt_to_witnesses(const tal_t *ctx, + const struct wally_psbt *psbt, + enum tx_role side_to_stack); #endif /* LIGHTNING_COMMON_PSBT_INTERNAL_H */ diff --git a/openingd/dualopend.c b/openingd/dualopend.c index bc17fecdf..fc20d7d3d 100644 --- a/openingd/dualopend.c +++ b/openingd/dualopend.c @@ -1021,9 +1021,8 @@ static u8 *psbt_to_tx_sigs_msg(const tal_t *ctx, struct state *state, const struct wally_psbt *psbt) { - const struct witness_stack **ws = - psbt_to_witness_stacks(tmpctx, psbt, - state->our_role); + const struct witness **ws = + psbt_to_witnesses(tmpctx, psbt, state->our_role); return towire_tx_signatures(ctx, &state->channel_id, &state->tx_state->funding.txid, @@ -1034,16 +1033,15 @@ static void handle_tx_sigs(struct state *state, const u8 *msg) { struct channel_id cid; struct bitcoin_txid txid; - const struct witness_stack **ws; - size_t j = 0; + const struct witness **witnesses; struct tx_state *tx_state = state->tx_state; enum tx_role their_role = state->our_role == TX_INITIATOR ? TX_ACCEPTER : TX_INITIATOR; if (!fromwire_tx_signatures(tmpctx, msg, &cid, &txid, cast_const3( - struct witness_stack ***, - &ws))) + struct witness ***, + &witnesses))) open_err_fatal(state, "Bad tx_signatures %s", tal_hex(msg, msg)); @@ -1085,11 +1083,10 @@ static void handle_tx_sigs(struct state *state, const u8 *msg) &tx_state->funding.txid)); /* We put the PSBT + sigs all together */ - for (size_t i = 0; i < tx_state->psbt->num_inputs; i++) { + for (size_t i = 0, j = 0; i < tx_state->psbt->num_inputs; i++) { struct wally_psbt_input *in = &tx_state->psbt->inputs[i]; u64 in_serial; - const struct witness_element **elem; if (!psbt_get_serial_id(&in->unknowns, &in_serial)) { status_broken("PSBT input %zu missing serial_id %s", @@ -1101,13 +1098,12 @@ static void handle_tx_sigs(struct state *state, const u8 *msg) if (in_serial % 2 != their_role) continue; - if (j == tal_count(ws)) - open_err_warn(state, "Mismatch witness stack count %s", + if (j == tal_count(witnesses)) + open_err_warn(state, "Mismatched witness stack count %s", tal_hex(msg, msg)); - elem = cast_const2(const struct witness_element **, - ws[j++]->witness_elements); - psbt_finalize_input(tx_state->psbt, in, elem); + psbt_finalize_input(tx_state->psbt, in, witnesses[j]); + j++; } tx_state->remote_funding_sigs_rcvd = true; @@ -3526,9 +3522,9 @@ static void rbf_local_start(struct state *state, u8 *msg) 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); + = tal(init_rbf_tlvs, s64); *init_rbf_tlvs->funding_output_contribution - = tx_state->opener_funding.satoshis; /* Raw: wire conversion */ + = (s64)tx_state->opener_funding.satoshis; /* Raw: wire conversion */ msg = towire_tx_init_rbf(tmpctx, &state->channel_id, tx_state->tx_locktime, @@ -3795,9 +3791,9 @@ static void rbf_remote_start(struct state *state, const u8 *rbf_msg) /* We always send the funding amount */ ack_rbf_tlvs->funding_output_contribution - = tal(ack_rbf_tlvs, u64); + = tal(ack_rbf_tlvs, s64); *ack_rbf_tlvs->funding_output_contribution - = tx_state->accepter_funding.satoshis; /* Raw: wire conversion */ + = (s64)tx_state->accepter_funding.satoshis; /* Raw: wire conversion */ msg = towire_tx_ack_rbf(tmpctx, &state->channel_id, ack_rbf_tlvs); peer_write(state->pps, msg); diff --git a/wire/extracted_peer_11_openchannelv2_updates.patch b/wire/extracted_peer_11_openchannelv2_updates.patch new file mode 100644 index 000000000..8c715127f --- /dev/null +++ b/wire/extracted_peer_11_openchannelv2_updates.patch @@ -0,0 +1,43 @@ +--- wire/peer_wire.csv 2023-06-29 14:36:10.986268579 -0500 ++++ - 2023-06-29 14:37:45.737004393 -0500 +@@ -62,25 +62,22 @@ + msgdata,tx_signatures,channel_id,channel_id, + msgdata,tx_signatures,txid,sha256, + msgdata,tx_signatures,num_witnesses,u16, +-msgdata,tx_signatures,witnesses,witness_stack,num_witnesses +-subtype,witness_stack +-subtypedata,witness_stack,num_witness_elements,u16, +-subtypedata,witness_stack,witness_elements,witness_element,num_witness_elements +-subtype,witness_element +-subtypedata,witness_element,len,u16, +-subtypedata,witness_element,witness_data,byte,len ++msgdata,tx_signatures,witnesses,witness,num_witnesses ++subtype,witness ++subtypedata,witness,len,u16, ++subtypedata,witness,witness_data,byte,len + msgtype,tx_init_rbf,72 + msgdata,tx_init_rbf,channel_id,channel_id, + msgdata,tx_init_rbf,locktime,u32, + msgdata,tx_init_rbf,feerate,u32, + msgdata,tx_init_rbf,tlvs,tx_init_rbf_tlvs, + tlvtype,tx_init_rbf_tlvs,funding_output_contribution,0 +-tlvdata,tx_init_rbf_tlvs,funding_output_contribution,satoshis,tu64, ++tlvdata,tx_init_rbf_tlvs,funding_output_contribution,satoshis,s64, + msgtype,tx_ack_rbf,73 + msgdata,tx_ack_rbf,channel_id,channel_id, + msgdata,tx_ack_rbf,tlvs,tx_ack_rbf_tlvs, + tlvtype,tx_ack_rbf_tlvs,funding_output_contribution,0 +-tlvdata,tx_ack_rbf_tlvs,funding_output_contribution,satoshis,tu64, ++tlvdata,tx_ack_rbf_tlvs,funding_output_contribution,satoshis,s64, + msgtype,tx_abort,74 + msgdata,tx_abort,channel_id,channel_id, + msgdata,tx_abort,len,u16, +@@ -257,6 +235,8 @@ + msgdata,channel_reestablish,your_last_per_commitment_secret,byte,32 + msgdata,channel_reestablish,my_current_per_commitment_point,point, + msgdata,channel_reestablish,tlvs,channel_reestablish_tlvs, ++tlvtype,channel_reestablish_tlvs,next_funding,0 ++tlvdata,channel_reestablish_tlvs,next_funding,next_funding_txid,sha256, + tlvtype,channel_reestablish_tlvs,next_to_send,1 + tlvdata,channel_reestablish_tlvs,next_to_send,commitment_number,tu64, + tlvtype,channel_reestablish_tlvs,desired_channel_type,3 diff --git a/wire/peer_wire.csv b/wire/peer_wire.csv index 3cfeb632c..32f8617b5 100644 --- a/wire/peer_wire.csv +++ b/wire/peer_wire.csv @@ -62,25 +62,22 @@ msgtype,tx_signatures,71 msgdata,tx_signatures,channel_id,channel_id, msgdata,tx_signatures,txid,sha256, msgdata,tx_signatures,num_witnesses,u16, -msgdata,tx_signatures,witnesses,witness_stack,num_witnesses -subtype,witness_stack -subtypedata,witness_stack,num_witness_elements,u16, -subtypedata,witness_stack,witness_elements,witness_element,num_witness_elements -subtype,witness_element -subtypedata,witness_element,len,u16, -subtypedata,witness_element,witness_data,byte,len +msgdata,tx_signatures,witnesses,witness,num_witnesses +subtype,witness +subtypedata,witness,len,u16, +subtypedata,witness,witness_data,byte,len msgtype,tx_init_rbf,72 msgdata,tx_init_rbf,channel_id,channel_id, msgdata,tx_init_rbf,locktime,u32, msgdata,tx_init_rbf,feerate,u32, msgdata,tx_init_rbf,tlvs,tx_init_rbf_tlvs, tlvtype,tx_init_rbf_tlvs,funding_output_contribution,0 -tlvdata,tx_init_rbf_tlvs,funding_output_contribution,satoshis,tu64, +tlvdata,tx_init_rbf_tlvs,funding_output_contribution,satoshis,s64, msgtype,tx_ack_rbf,73 msgdata,tx_ack_rbf,channel_id,channel_id, msgdata,tx_ack_rbf,tlvs,tx_ack_rbf_tlvs, tlvtype,tx_ack_rbf_tlvs,funding_output_contribution,0 -tlvdata,tx_ack_rbf_tlvs,funding_output_contribution,satoshis,tu64, +tlvdata,tx_ack_rbf_tlvs,funding_output_contribution,satoshis,s64, msgtype,tx_abort,74 msgdata,tx_abort,channel_id,channel_id, msgdata,tx_abort,len,u16, @@ -267,6 +264,8 @@ msgdata,channel_reestablish,next_revocation_number,u64, msgdata,channel_reestablish,your_last_per_commitment_secret,byte,32 msgdata,channel_reestablish,my_current_per_commitment_point,point, msgdata,channel_reestablish,tlvs,channel_reestablish_tlvs, +tlvtype,channel_reestablish_tlvs,next_funding,0 +tlvdata,channel_reestablish_tlvs,next_funding,next_funding_txid,sha256, tlvtype,channel_reestablish_tlvs,next_to_send,1 tlvdata,channel_reestablish_tlvs,next_to_send,commitment_number,tu64, tlvtype,channel_reestablish_tlvs,desired_channel_type,3