Browse Source

dualfund: rearrange things so that the wire-dependent calls are separate

There's a few structs/wire calls that only exist under experimental features.
These were in a common file that was shared/used a bunch of places but
this causes problems. Here we move one of the problematic methods back
into `openingd`, as it's only used locally and then isolate the
references to the `witness_stack` in a new `common/psbt_internal` file.

This lets us remove the iff EXP_FEATURES inclusion switches in most of
the Makefiles.
travis-experimental
niftynei 4 years ago
committed by Rusty Russell
parent
commit
4508584b21
  1. 3
      channeld/Makefile
  2. 3
      channeld/channeld.c
  3. 5
      closingd/Makefile
  4. 3
      common/Makefile
  5. 76
      common/psbt_internal.c
  6. 36
      common/psbt_internal.h
  7. 144
      common/psbt_open.c
  8. 35
      common/psbt_open.h
  9. 12
      common/test/exp-run-psbt_diff.c
  10. 5
      connectd/Makefile
  11. 5
      devtools/Makefile
  12. 5
      gossipd/Makefile
  13. 7
      hsmd/Makefile
  14. 5
      lightningd/Makefile
  15. 7
      onchaind/Makefile
  16. 6
      openingd/Makefile
  17. 88
      openingd/dualopend.c

3
channeld/Makefile

@ -70,6 +70,7 @@ CHANNELD_COMMON_OBJS := \
common/per_peer_state.o \
common/permute_tx.o \
common/ping.o \
common/psbt_open.o \
common/pseudorand.o \
common/read_peer_msg.o \
common/setup.o \
@ -90,7 +91,7 @@ CHANNELD_COMMON_OBJS := \
wire/towire.o
ifeq ($(EXPERIMENTAL_FEATURES),1)
CHANNELD_COMMON_OBJS += common/psbt_open.o
CHANNELD_COMMON_OBJS += common/psbt_internal.o
endif
channeld/gen_full_channel_error_names.h: channeld/full_channel_error.h ccan/ccan/cdump/tools/cdump-enumstr

3
channeld/channeld.c

@ -47,6 +47,7 @@
#include <common/peer_billboard.h>
#include <common/peer_failed.h>
#include <common/ping.h>
#include <common/psbt_internal.h>
#include <common/psbt_open.h>
#include <common/read_peer_msg.h>
#include <common/sphinx.h>
@ -2054,7 +2055,7 @@ static void handle_tx_sigs(struct peer *peer, const u8 *msg)
elem = cast_const2(const struct witness_element **,
ws[j++]->witness_element);
psbt_input_set_final_witness_stack(in, elem);
psbt_input_set_final_witness_stack(peer->psbt, in, elem);
}
/* Then we broadcast it, and let the command know we did it */

5
closingd/Makefile

@ -46,6 +46,7 @@ CLOSINGD_COMMON_OBJS := \
common/peer_failed.o \
common/per_peer_state.o \
common/permute_tx.o \
common/psbt_open.o \
common/pseudorand.o \
common/read_peer_msg.o \
common/setup.o \
@ -61,10 +62,6 @@ CLOSINGD_COMMON_OBJS := \
common/wireaddr.o \
gossipd/gossipd_peerd_wiregen.o
ifeq ($(EXPERIMENTAL_FEATURES),1)
CLOSINGD_COMMON_OBJS += common/psbt_open.o
endif
lightningd/lightning_closingd: $(CLOSINGD_OBJS) $(WIRE_ONION_OBJS) $(CLOSINGD_COMMON_OBJS) $(WIRE_OBJS) $(BITCOIN_OBJS) $(HSMD_CLIENT_OBJS)
-include closingd/test/Makefile

3
common/Makefile

@ -56,6 +56,7 @@ COMMON_SRC_NOGEN := \
common/peer_failed.c \
common/permute_tx.c \
common/ping.c \
common/psbt_open.c \
common/pseudorand.c \
common/random_select.c \
common/read_peer_msg.c \
@ -77,7 +78,7 @@ COMMON_SRC_NOGEN := \
ifeq ($(EXPERIMENTAL_FEATURES),1)
COMMON_SRC_NOGEN += common/psbt_open.c
COMMON_SRC_NOGEN += common/psbt_internal.c
endif
COMMON_SRC_GEN := common/status_wiregen.c common/peer_status_wiregen.c

76
common/psbt_internal.c

@ -0,0 +1,76 @@
#include "common/psbt_internal.h"
#include <common/psbt_open.h>
#include <wally_psbt.h>
#include <wire/peer_wire.h>
#if EXPERIMENTAL_FEATURES
void psbt_input_set_final_witness_stack(const tal_t *ctx,
struct wally_psbt_input *in,
const struct witness_element **elements)
{
tal_wally_start();
wally_tx_witness_stack_init_alloc(tal_count(elements),
&in->final_witness);
for (size_t i = 0; i < tal_count(elements); i++)
wally_tx_witness_stack_add(in->final_witness,
elements[i]->witness,
tal_bytelen(elements[i]->witness));
tal_wally_end(ctx);
}
const struct witness_stack **
psbt_to_witness_stacks(const tal_t *ctx,
const struct wally_psbt *psbt,
enum tx_role side_to_stack)
{
size_t stack_index;
u16 serial_id;
const struct witness_stack **stacks
= tal_arr(ctx, const struct witness_stack *, psbt->num_inputs);
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;
/* BOLT-78de9a79b491ae9fb84b1fdb4546bacf642dce87 #2:
* - if is the `initiator`:
* - MUST send even `serial_id`s
*/
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_element =
tal_arr(stack, struct witness_element *,
wtx_s->num_items);
for (size_t j = 0; j < tal_count(stack->witness_element); j++) {
stack->witness_element[j] = tal(stack,
struct witness_element);
stack->witness_element[j]->witness =
tal_dup_arr(stack, u8,
wtx_s->items[j].witness,
wtx_s->items[j].witness_len,
0);
}
stacks[stack_index++] = stack;
}
}
if (stack_index == 0)
return tal_free(stacks);
tal_resize(&stacks, stack_index);
return stacks;
}
#endif /* EXPERIMENTAL_FEATURES */

36
common/psbt_internal.h

@ -0,0 +1,36 @@
#ifndef LIGHTNING_COMMON_PSBT_INTERNAL_H
#define LIGHTNING_COMMON_PSBT_INTERNAL_H
#include "config.h"
#include <ccan/tal/tal.h>
#include <common/tx_roles.h>
struct wally_psbt;
struct wally_psbt_input;
#if EXPERIMENTAL_FEATURES
struct witness_element;
#endif /* EXPERIMENTAL_FEATURES */
#if EXPERIMENTAL_FEATURES
/* psbt_input_set_final_witness_stack - Set the witness stack for PSBT input
*
* @ctx - the context to allocate onto
* @in - input to set final_witness for
* @witness_element - elements to add to witness stack
*/
void psbt_input_set_final_witness_stack(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
*
* @ctx - allocation context
* @psbt - PSBT to copy sigs from
* @opener - which side initiated this tx
*/
const struct witness_stack **
psbt_to_witness_stacks(const tal_t *ctx,
const struct wally_psbt *psbt,
enum tx_role side_to_stack);
#endif /* EXPERIMENTAL_FEATURES */
#endif /* LIGHTNING_COMMON_PSBT_INTERNAL_H */

144
common/psbt_open.c

@ -6,10 +6,8 @@
#include <ccan/asort/asort.h>
#include <ccan/ccan/endian/endian.h>
#include <ccan/ccan/mem/mem.h>
#include <common/channel_id.h>
#include <common/pseudorand.h>
#include <common/utils.h>
#include <wire/peer_wire.h>
bool psbt_get_serial_id(const struct wally_map *map, u16 *serial_id)
{
@ -427,148 +425,6 @@ bool psbt_has_required_fields(struct wally_psbt *psbt)
return true;
}
u8 *psbt_changeset_get_next(const tal_t *ctx, struct channel_id *cid,
struct psbt_changeset *set)
{
u16 serial_id;
u8 *msg;
if (tal_count(set->added_ins) != 0) {
const struct input_set *in = &set->added_ins[0];
u8 *script;
if (!psbt_get_serial_id(&in->input.unknowns, &serial_id))
abort();
const u8 *prevtx = linearize_wtx(ctx,
in->input.utxo);
if (in->input.redeem_script_len)
script = tal_dup_arr(ctx, u8,
in->input.redeem_script,
in->input.redeem_script_len, 0);
else
script = NULL;
msg = towire_tx_add_input(ctx, cid, serial_id,
prevtx, in->tx_input.index,
in->tx_input.sequence,
script,
NULL);
tal_arr_remove(&set->added_ins, 0);
return msg;
}
if (tal_count(set->rm_ins) != 0) {
if (!psbt_get_serial_id(&set->rm_ins[0].input.unknowns,
&serial_id))
abort();
msg = towire_tx_remove_input(ctx, cid, serial_id);
tal_arr_remove(&set->rm_ins, 0);
return msg;
}
if (tal_count(set->added_outs) != 0) {
struct amount_sat sats;
struct amount_asset asset_amt;
const struct output_set *out = &set->added_outs[0];
if (!psbt_get_serial_id(&out->output.unknowns, &serial_id))
abort();
asset_amt = wally_tx_output_get_amount(&out->tx_output);
sats = amount_asset_to_sat(&asset_amt);
const u8 *script = wally_tx_output_get_script(ctx,
&out->tx_output);
msg = towire_tx_add_output(ctx, cid, serial_id,
sats.satoshis, /* Raw: wire interface */
script);
tal_arr_remove(&set->added_outs, 0);
return msg;
}
if (tal_count(set->rm_outs) != 0) {
if (!psbt_get_serial_id(&set->rm_outs[0].output.unknowns,
&serial_id))
abort();
msg = towire_tx_remove_output(ctx, cid, serial_id);
/* Is this a kosher way to move the list forward? */
tal_arr_remove(&set->rm_outs, 0);
return msg;
}
return NULL;
}
void psbt_input_set_final_witness_stack(struct wally_psbt_input *in,
const struct witness_element **elements)
{
wally_tx_witness_stack_init_alloc(tal_count(elements),
&in->final_witness);
for (size_t i = 0; i < tal_count(elements); i++)
wally_tx_witness_stack_add(in->final_witness,
elements[i]->witness,
tal_bytelen(elements[i]->witness));
}
const struct witness_stack **
psbt_to_witness_stacks(const tal_t *ctx,
const struct wally_psbt *psbt,
enum tx_role side_to_stack)
{
size_t stack_index;
u16 serial_id;
const struct witness_stack **stacks
= tal_arr(ctx, const struct witness_stack *, psbt->num_inputs);
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;
/* BOLT-78de9a79b491ae9fb84b1fdb4546bacf642dce87 #2:
* - if is the `initiator`:
* - MUST send even `serial_id`s
*/
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_element =
tal_arr(stack, struct witness_element *,
wtx_s->num_items);
for (size_t j = 0; j < tal_count(stack->witness_element); j++) {
stack->witness_element[j] = tal(stack,
struct witness_element);
stack->witness_element[j]->witness =
tal_dup_arr(stack, u8,
wtx_s->items[j].witness,
wtx_s->items[j].witness_len,
0);
}
stacks[stack_index++] = stack;
}
}
if (stack_index == 0)
return tal_free(stacks);
tal_resize(&stacks, stack_index);
return stacks;
}
bool psbt_side_finalized(const struct wally_psbt *psbt, enum tx_role role)
{
u16 serial_id;

35
common/psbt_open.h

@ -15,7 +15,6 @@ struct wally_psbt;
struct wally_psbt_input;
struct wally_psbt_output;
struct wally_map;
struct witness_element;
struct input_set {
struct wally_tx_input tx_input;
@ -71,20 +70,6 @@ struct psbt_changeset *psbt_get_changeset(const tal_t *ctx,
struct wally_psbt *orig,
struct wally_psbt *new);
/* psbt_changeset_get_next - Get next message to send
*
* This generates the next message to send from a changeset for the
* interactive transaction protocol.
*
* @ctx - allocation context of returned msg
* @cid - channel_id for the message
* @set - changeset to get next update from
*
* Returns a wire message or NULL if no changes.
*/
u8 *psbt_changeset_get_next(const tal_t *ctx, struct channel_id *cid,
struct psbt_changeset *set);
/* psbt_input_set_serial_id - Sets a serial id on given input
*
* @ctx - tal context for allocations
@ -160,26 +145,6 @@ u16 psbt_new_output_serial(struct wally_psbt *psbt, enum tx_role role);
*/
bool psbt_has_required_fields(struct wally_psbt *psbt);
/* psbt_input_set_final_witness_stack - Set the witness stack for PSBT input
*
* @in - input to set final_witness for
* @witness_element - elements to add to witness stack
*/
void psbt_input_set_final_witness_stack(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
*
* @ctx - allocation context
* @psbt - PSBT to copy sigs from
* @opener - which side initiated this tx
*/
const struct witness_stack **
psbt_to_witness_stacks(const tal_t *ctx,
const struct wally_psbt *psbt,
enum tx_role side_to_stack);
/* psbt_side_finalized - True if designated role has all signature data */
bool psbt_side_finalized(const struct wally_psbt *psbt,
enum tx_role role);

12
common/test/exp-run-psbt_diff.c

@ -58,18 +58,6 @@ void towire_secp256k1_ecdsa_signature(u8 **pptr UNNEEDED,
/* Generated stub for towire_sha256 */
void towire_sha256(u8 **pptr UNNEEDED, const struct sha256 *sha256 UNNEEDED)
{ fprintf(stderr, "towire_sha256 called!\n"); abort(); }
/* Generated stub for towire_tx_add_input */
u8 *towire_tx_add_input(const tal_t *ctx UNNEEDED, const struct channel_id *channel_id UNNEEDED, u16 serial_id UNNEEDED, const u8 *prevtx UNNEEDED, u32 prevtx_vout UNNEEDED, u32 sequence UNNEEDED, const u8 *script UNNEEDED, const struct tlv_tx_add_input_tlvs *tlvs UNNEEDED)
{ fprintf(stderr, "towire_tx_add_input called!\n"); abort(); }
/* Generated stub for towire_tx_add_output */
u8 *towire_tx_add_output(const tal_t *ctx UNNEEDED, const struct channel_id *channel_id UNNEEDED, u16 serial_id UNNEEDED, u64 sats UNNEEDED, const u8 *script UNNEEDED)
{ fprintf(stderr, "towire_tx_add_output called!\n"); abort(); }
/* Generated stub for towire_tx_remove_input */
u8 *towire_tx_remove_input(const tal_t *ctx UNNEEDED, const struct channel_id *channel_id UNNEEDED, u16 serial_id UNNEEDED)
{ fprintf(stderr, "towire_tx_remove_input called!\n"); abort(); }
/* Generated stub for towire_tx_remove_output */
u8 *towire_tx_remove_output(const tal_t *ctx UNNEEDED, const struct channel_id *channel_id UNNEEDED, u16 serial_id UNNEEDED)
{ fprintf(stderr, "towire_tx_remove_output called!\n"); abort(); }
/* Generated stub for towire_u16 */
void towire_u16(u8 **pptr UNNEEDED, u16 v UNNEEDED)
{ fprintf(stderr, "towire_u16 called!\n"); abort(); }

5
connectd/Makefile

@ -49,6 +49,7 @@ CONNECTD_COMMON_OBJS := \
common/node_id.o \
common/onionreply.o \
common/per_peer_state.o \
common/psbt_open.o \
common/pseudorand.o \
common/setup.o \
common/status.o \
@ -65,10 +66,6 @@ CONNECTD_COMMON_OBJS := \
lightningd/gossip_msg.o \
wire/onion$(EXP)_wiregen.o
ifeq ($(EXPERIMENTAL_FEATURES),1)
CONNECTD_COMMON_OBJS += common/psbt_open.o
endif
lightningd/lightning_connectd: $(CONNECTD_OBJS) $(CONNECTD_COMMON_OBJS) $(BITCOIN_OBJS) $(WIRE_OBJS) $(HSMD_CLIENT_OBJS)
include connectd/test/Makefile

5
devtools/Makefile

@ -33,6 +33,7 @@ DEVTOOLS_COMMON_OBJS := \
common/memleak.o \
common/node_id.o \
common/per_peer_state.o \
common/psbt_open.o \
common/pseudorand.o \
common/json.o \
common/json_helpers.o \
@ -44,10 +45,6 @@ DEVTOOLS_COMMON_OBJS := \
wire/onion$(EXP)_wiregen.o \
wire/peer$(EXP)_wiregen.o
ifeq ($(EXPERIMENTAL_FEATURES),1)
DEVTOOLS_COMMON_OBJS += common/psbt_open.o
endif
devtools/bolt11-cli: $(DEVTOOLS_COMMON_OBJS) $(JSMN_OBJS) $(CCAN_OBJS) $(BITCOIN_OBJS) wire/fromwire.o wire/towire.o devtools/bolt11-cli.o
devtools/decodemsg: $(DEVTOOLS_COMMON_OBJS) $(JSMN_OBJS) $(CCAN_OBJS) $(BITCOIN_OBJS) $(WIRE_PRINT_OBJS) wire/fromwire.o wire/towire.o devtools/print_wire.o devtools/decodemsg.o

5
gossipd/Makefile

@ -51,6 +51,7 @@ GOSSIPD_COMMON_OBJS := \
common/onionreply.o \
common/per_peer_state.o \
common/ping.o \
common/psbt_open.o \
common/pseudorand.o \
common/random_select.o \
common/setup.o \
@ -68,10 +69,6 @@ GOSSIPD_COMMON_OBJS := \
lightningd/gossip_msg.o \
wire/onion$(EXP)_wiregen.o
ifeq ($(EXPERIMENTAL_FEATURES),1)
GOSSIPD_COMMON_OBJS += common/psbt_open.o
endif
lightningd/lightning_gossipd: $(GOSSIPD_OBJS) $(GOSSIPD_COMMON_OBJS) $(BITCOIN_OBJS) $(WIRE_OBJS) $(HSMD_CLIENT_OBJS)
include gossipd/test/Makefile

7
hsmd/Makefile

@ -31,6 +31,8 @@ HSMD_COMMON_OBJS := \
common/msg_queue.o \
common/node_id.o \
common/permute_tx.o \
common/psbt_open.o \
common/pseudorand.o \
common/setup.o \
common/status.o \
common/status_wire.o \
@ -40,11 +42,6 @@ HSMD_COMMON_OBJS := \
common/utxo.o \
common/version.o
ifeq ($(EXPERIMENTAL_FEATURES),1)
HSMD_COMMON_OBJS += common/psbt_open.o \
common/pseudorand.o
endif
lightningd/lightning_hsmd: $(HSMD_OBJS) $(HSMD_COMMON_OBJS) $(BITCOIN_OBJS) $(WIRE_OBJS)
-include hsmd/test/Makefile

5
lightningd/Makefile

@ -106,6 +106,7 @@ LIGHTNINGD_COMMON_OBJS := \
common/penalty_base.o \
common/per_peer_state.o \
common/permute_tx.o \
common/psbt_open.o \
common/pseudorand.o \
common/random_select.o \
common/setup.o \
@ -120,10 +121,6 @@ LIGHTNINGD_COMMON_OBJS := \
common/wire_error.o \
common/wireaddr.o \
ifeq ($(EXPERIMENTAL_FEATURES),1)
LIGHTNINGD_COMMON_OBJS += common/psbt_open.o
endif
include wallet/Makefile
# All together in one convenient var

7
onchaind/Makefile

@ -53,6 +53,8 @@ ONCHAIND_COMMON_OBJS := \
common/onionreply.o \
common/peer_billboard.o \
common/permute_tx.o \
common/psbt_open.o \
common/pseudorand.o \
common/setup.o \
common/status.o \
common/status_wire.o \
@ -63,11 +65,6 @@ ONCHAIND_COMMON_OBJS := \
common/version.o \
common/wallet.o
ifeq ($(EXPERIMENTAL_FEATURES),1)
ONCHAIND_COMMON_OBJS += common/psbt_open.o \
common/pseudorand.o
endif
lightningd/lightning_onchaind: $(ONCHAIND_OBJS) $(WIRE_ONION_OBJS) $(ONCHAIND_COMMON_OBJS) $(WIRE_OBJS) $(BITCOIN_OBJS) $(HSMD_CLIENT_OBJS)
include onchaind/test/Makefile

6
openingd/Makefile

@ -70,6 +70,7 @@ OPENINGD_COMMON_OBJS := \
common/peer_billboard.o \
common/peer_failed.o \
common/permute_tx.o \
common/psbt_open.o \
common/pseudorand.o \
common/read_peer_msg.o \
common/setup.o \
@ -85,11 +86,6 @@ OPENINGD_COMMON_OBJS := \
gossipd/gossipd_peerd_wiregen.o \
lightningd/gossip_msg.o
ifeq ($(EXPERIMENTAL_FEATURES),1)
OPENINGD_COMMON_OBJS += common/psbt_open.o \
common/pseudorand.o
endif
lightningd/lightning_openingd: $(OPENINGD_OBJS) $(OPENINGD_COMMON_OBJS) $(WIRE_OBJS) $(BITCOIN_OBJS) $(HSMD_CLIENT_OBJS)
lightningd/lightning_dualopend: $(DUALOPEND_OBJS) $(OPENINGD_COMMON_OBJS) $(WIRE_OBJS) $(BITCOIN_OBJS) $(HSMD_CLIENT_OBJS)

88
openingd/dualopend.c

@ -124,6 +124,94 @@ struct state {
};
#if EXPERIMENTAL_FEATURES
/* psbt_changeset_get_next - Get next message to send
*
* This generates the next message to send from a changeset for the
* interactive transaction protocol.
*
* @ctx - allocation context of returned msg
* @cid - channel_id for the message
* @set - changeset to get next update from
*
* Returns a wire message or NULL if no changes.
*/
static u8 *psbt_changeset_get_next(const tal_t *ctx,
struct channel_id *cid,
struct psbt_changeset *set)
{
u16 serial_id;
u8 *msg;
if (tal_count(set->added_ins) != 0) {
const struct input_set *in = &set->added_ins[0];
u8 *script;
if (!psbt_get_serial_id(&in->input.unknowns, &serial_id))
abort();
const u8 *prevtx = linearize_wtx(ctx,
in->input.utxo);
if (in->input.redeem_script_len)
script = tal_dup_arr(ctx, u8,
in->input.redeem_script,
in->input.redeem_script_len, 0);
else
script = NULL;
msg = towire_tx_add_input(ctx, cid, serial_id,
prevtx, in->tx_input.index,
in->tx_input.sequence,
script,
NULL);
tal_arr_remove(&set->added_ins, 0);
return msg;
}
if (tal_count(set->rm_ins) != 0) {
if (!psbt_get_serial_id(&set->rm_ins[0].input.unknowns,
&serial_id))
abort();
msg = towire_tx_remove_input(ctx, cid, serial_id);
tal_arr_remove(&set->rm_ins, 0);
return msg;
}
if (tal_count(set->added_outs) != 0) {
struct amount_sat sats;
struct amount_asset asset_amt;
const struct output_set *out = &set->added_outs[0];
if (!psbt_get_serial_id(&out->output.unknowns, &serial_id))
abort();
asset_amt = wally_tx_output_get_amount(&out->tx_output);
sats = amount_asset_to_sat(&asset_amt);
const u8 *script = wally_tx_output_get_script(ctx,
&out->tx_output);
msg = towire_tx_add_output(ctx, cid, serial_id,
sats.satoshis, /* Raw: wire interface */
script);
tal_arr_remove(&set->added_outs, 0);
return msg;
}
if (tal_count(set->rm_outs) != 0) {
if (!psbt_get_serial_id(&set->rm_outs[0].output.unknowns,
&serial_id))
abort();
msg = towire_tx_remove_output(ctx, cid, serial_id);
/* Is this a kosher way to move the list forward? */
tal_arr_remove(&set->rm_outs, 0);
return msg;
}
return NULL;
}
/*~ If we can't agree on parameters, we fail to open the channel. If we're
* the opener, we need to tell lightningd, otherwise it never really notices. */

Loading…
Cancel
Save