From cafdbbcd2d43650e0a0d94436401d3a8d9bbb087 Mon Sep 17 00:00:00 2001 From: niftynei Date: Wed, 9 Sep 2020 19:40:25 +0930 Subject: [PATCH] dualopend: new `dualopend` daemon, containing most of accepter side oof. needs validation. --- Makefile | 3 +- lightningd/.gitignore | 5 +- openingd/Makefile | 25 +- openingd/dual_fund_roles.h | 10 + openingd/dualopend.c | 1609 ++++++++++++++++++++++++++++++++++ openingd/dualopend_wire.csv | 105 +++ openingd/dualopend_wiregen.c | 418 +++++++++ openingd/dualopend_wiregen.h | 100 +++ 8 files changed, 2266 insertions(+), 9 deletions(-) create mode 100644 openingd/dual_fund_roles.h create mode 100644 openingd/dualopend.c create mode 100644 openingd/dualopend_wire.csv create mode 100644 openingd/dualopend_wiregen.c create mode 100644 openingd/dualopend_wiregen.h diff --git a/Makefile b/Makefile index 7bdbc0119..bcd6b68d2 100644 --- a/Makefile +++ b/Makefile @@ -580,7 +580,8 @@ PKGLIBEXEC_PROGRAMS = \ lightningd/lightning_gossipd \ lightningd/lightning_hsmd \ lightningd/lightning_onchaind \ - lightningd/lightning_openingd + lightningd/lightning_openingd \ + lightningd/lightning_dualopend # $(PLUGINS) is defined in plugins/Makefile. diff --git a/lightningd/.gitignore b/lightningd/.gitignore index e7deac2b7..85094969a 100644 --- a/lightningd/.gitignore +++ b/lightningd/.gitignore @@ -1,8 +1,9 @@ lightningd lightning_channeld +lightning_closingd lightning_connectd +lightning_dualopend lightning_gossipd lightning_hsmd -lightning_openingd -lightning_closingd lightning_onchaind +lightning_openingd diff --git a/openingd/Makefile b/openingd/Makefile index b31b55239..2632c4c16 100644 --- a/openingd/Makefile +++ b/openingd/Makefile @@ -4,20 +4,30 @@ OPENINGD_HEADERS := \ openingd/common.h \ openingd/openingd_wiregen.h -OPENINGD_SRC := openingd/openingd.c \ +DUALOPEND_HEADERS := \ + openingd/common.h \ + openingd/dualopend_wiregen.h + +OPENINGD_SRC := openingd/openingd.c \ $(OPENINGD_HEADERS:.h=.c) +DUALOPEND_SRC := openingd/dualopend.c \ + $(DUALOPEND_HEADERS:.h=.c) + OPENINGD_OBJS := $(OPENINGD_SRC:.c=.o) $(OPENINGD_OBJS): $(OPENINGD_HEADERS) +DUALOPEND_OBJS := $(DUALOPEND_SRC:.c=.o) +$(DUALOPEND_OBJS): $(DUALOPEND_HEADERS) + # Make sure these depend on everything. -ALL_C_SOURCES += $(OPENINGD_SRC) -ALL_C_HEADERS += $(OPENINGD_HEADERS) -ALL_PROGRAMS += lightningd/lightning_openingd +ALL_C_SOURCES += $(OPENINGD_SRC) $(DUALOPEND_SRC) +ALL_C_HEADERS += $(OPENINGD_HEADERS) $(DUALOPEND_HEADERS) +ALL_PROGRAMS += lightningd/lightning_openingd lightningd/lightning_dualopend # Here's what lightningd depends on -LIGHTNINGD_CONTROL_HEADERS += openingd/openingd_wiregen.h -LIGHTNINGD_CONTROL_OBJS += openingd/openingd_wiregen.o +LIGHTNINGD_CONTROL_HEADERS += openingd/openingd_wiregen.h openingd/dualopend_wiregen.h +LIGHTNINGD_CONTROL_OBJS += openingd/openingd_wiregen.o openingd/dualopend_wiregen.o # Common source we use. OPENINGD_COMMON_OBJS := \ @@ -55,6 +65,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 \ @@ -72,4 +83,6 @@ OPENINGD_COMMON_OBJS := \ 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) + -include openingd/test/Makefile diff --git a/openingd/dual_fund_roles.h b/openingd/dual_fund_roles.h new file mode 100644 index 000000000..f2e3b7a30 --- /dev/null +++ b/openingd/dual_fund_roles.h @@ -0,0 +1,10 @@ +#ifndef LIGHTNING_OPENINGD_DUAL_FUND_ROLES_H +#define LIGHTNING_OPENINGD_DUAL_FUND_ROLES_H + +#define NUM_DF_RULES (OPENER + 1) +enum dual_fund_roles { + ACCEPTER, + OPENER, +}; + +#endif /* LIGHTNING_OPENINGD_DUAL_FUND_ROLES_H */ diff --git a/openingd/dualopend.c b/openingd/dualopend.c new file mode 100644 index 000000000..864852f38 --- /dev/null +++ b/openingd/dualopend.c @@ -0,0 +1,1609 @@ +/*~ Welcome to the ~nifty~ dual-opening daemon: the other gateway to channels! + * + * This daemon handles a single peer. It's happy to trade gossip with the + * peer until either lightningd asks it to fund a channel, or the peer itself + * asks to fund a channel. Then it goes through with the channel opening + * negotiations. It's important to note that until this negotiation is complete, + * there's nothing permanent about the channel: lightningd will only have to + * commit to the database once dualopend succeeds. + * + * Much like the original opening daemon, openingd, dualopend implements the + * new and improved, two-party opening protocol, which allows bother peers to + * contribute inputs to the transaction + */ +#include "dual_fund_roles.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* stdin == lightningd, 3 == peer, 4 == gossipd, 5 = gossip_store, 6 = hsmd */ +#define REQ_FD STDIN_FILENO +#define HSM_FD 6 + +struct psbt_changeset { + struct input_set *added_ins; + struct input_set *rm_ins; + struct output_set *added_outs; + struct output_set *rm_outs; +}; + +/* Global state structure. This is only for the one specific peer and channel */ +struct state { + struct per_peer_state *pps; + + /* Features they offered */ + u8 *their_features; + + /* Constraints on a channel they open. */ + u32 minimum_depth; + u32 min_feerate, max_feerate; + struct amount_msat min_effective_htlc_capacity; + + /* Limits on what remote config we accept. */ + u32 max_to_self_delay; + + /* These are the points lightningd told us to use when accepting or + * opening a channel. */ + struct basepoints our_points; + struct pubkey our_funding_pubkey; + struct pubkey their_funding_pubkey; + + /* Information we need between funding_start and funding_complete */ + struct basepoints their_points; + + /* hsmd gives us our first per-commitment point, and peer tells us + * theirs */ + struct pubkey first_per_commitment_point[NUM_SIDES]; + + struct channel_id channel_id; + + /* Funding and feerate: set by opening peer. */ + struct amount_sat opener_funding; + struct amount_sat accepter_funding; + u32 tx_locktime; + + struct sha256 opening_podle_h2; + enum dual_fund_roles our_role; + + u32 feerate_per_kw_funding; + u32 feerate_per_kw; + + struct bitcoin_txid funding_txid; + u16 funding_txout; + + /* If non-NULL, this is the scriptpubkey we/they *must* close with */ + u8 *upfront_shutdown_script[NUM_SIDES]; + + /* This is a cluster of fields in open_channel and accept_channel which + * indicate the restrictions each side places on the channel. */ + struct channel_config localconf, remoteconf; + + /* The channel structure, as defined in common/initial_channel.h. While + * the structure has room for HTLCs, those routines are channeld-specific + * as initial channels never have HTLCs. */ + struct channel *channel; + + struct feature_set *our_features; + bool option_anchor_outputs; + + /* Set of pending changes to send to peer */ + struct psbt_changeset *changeset; +}; + +static struct psbt_changeset *new_changeset(const tal_t *ctx) +{ + struct psbt_changeset *set = tal(ctx, struct psbt_changeset); + + set->added_ins = tal_arr(set, struct input_set, 0); + set->rm_ins = tal_arr(set, struct input_set, 0); + set->added_outs = tal_arr(set, struct output_set, 0); + set->rm_outs = tal_arr(set, struct output_set, 0); + + return set; +} + +#if EXPERIMENTAL_FEATURES +static u8 *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]; + u16 max_witness_len; + u8 *script; + + if (!psbt_get_serial_id(&in->input.unknowns, &serial_id)) + abort(); + + const u8 *prevtx = linearize_wtx(ctx, + in->input.utxo); + + if (!psbt_input_get_max_witness_len(&in->input, + &max_witness_len)) + abort(); + + 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, + max_witness_len, + 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. */ +static void negotiation_aborted(struct state *state, bool am_opener, + const char *why) +{ + status_debug("aborted opening negotiation: %s", why); + /*~ The "billboard" (exposed as "status" in the JSON listpeers RPC + * call) is a transient per-channel area which indicates important + * information about what is happening. It has a "permanent" area for + * each state, which can be used to indicate what went wrong in that + * state (such as here), and a single transient area for current + * status. */ + peer_billboard(true, why); + + /* If necessary, tell master that funding failed. */ + if (am_opener) { + u8 *msg = towire_dual_open_failed(NULL, why); + wire_sync_write(REQ_FD, take(msg)); + } + + /* Default is no shutdown_scriptpubkey: free any leftover ones. */ + state->upfront_shutdown_script[LOCAL] + = tal_free(state->upfront_shutdown_script[LOCAL]); + state->upfront_shutdown_script[REMOTE] + = tal_free(state->upfront_shutdown_script[REMOTE]); + + /*~ Reset state. We keep gossipping with them, even though this open + * failed. */ + memset(&state->channel_id, 0, sizeof(state->channel_id)); + state->channel = tal_free(state->channel); +} + +/*~ For negotiation failures: we tell them the parameter we didn't like. */ +static void negotiation_failed(struct state *state, bool am_opener, + const char *fmt, ...) +{ + va_list ap; + const char *errmsg; + u8 *msg; + + va_start(ap, fmt); + errmsg = tal_vfmt(tmpctx, fmt, ap); + va_end(ap); + + msg = towire_errorfmt(NULL, &state->channel_id, + "You gave bad parameters: %s", errmsg); + sync_crypto_write(state->pps, take(msg)); + + negotiation_aborted(state, am_opener, errmsg); +} + +static void check_channel_id(struct state *state, + struct channel_id *id_in, + struct channel_id *orig_id) +{ + /* BOLT #2: + * + * The `temporary_channel_id` MUST be the same as + * the `temporary_channel_id` in the `open_channel` message. + */ + if (!channel_id_eq(id_in, orig_id)) + peer_failed(state->pps, id_in, + "channel ids don't match. expected %s, got %s", + type_to_string(tmpctx, struct channel_id, orig_id), + type_to_string(tmpctx, struct channel_id, id_in)); +} + +static void set_reserve(struct state *state, struct amount_sat funding_total) +{ + struct amount_sat reserve; + + /* BOLT-fe0351ca2cea3105c4f2eb18c571afca9d21c85b #2 + * + * The channel reserve is fixed at 1% of the total channel balance + * rounded down (sum of `funding_satoshis` from `open_channel2` and `accept_channel2`) + * or the `dust_limit_satoshis`, whichever is greater. + */ + reserve = amount_sat_div(funding_total, 100); + + if (amount_sat_greater(state->remoteconf.dust_limit, reserve)) + state->remoteconf.channel_reserve = state->remoteconf.dust_limit; + else + state->remoteconf.channel_reserve = reserve; + + if (amount_sat_greater(state->localconf.dust_limit, reserve)) + state->localconf.channel_reserve = state->localconf.dust_limit; + else + state->localconf.channel_reserve = reserve; +} + +static bool is_openers(const struct wally_map *unknowns) +{ + /* BOLT-fe0351ca2cea3105c4f2eb18c571afca9d21c85b #2 + * The sending node: + * ... + * - if is the `initiator`: + * - MUST send even `serial_id`s + * - if is the `contributor`: + * ... + * - MUST send odd `serial_id`s + */ + u16 serial_id; + if (!psbt_get_serial_id(unknowns, &serial_id)) + status_failed(STATUS_FAIL_INTERNAL_ERROR, + "PSBTs must have serial_ids set"); + + return serial_id % 2 == 0; +} + +static size_t psbt_input_weight(struct wally_psbt *psbt, + size_t in) +{ + size_t weight; + u16 max_witness_len; + bool ok; + + /* BOLT-fe0351ca2cea3105c4f2eb18c571afca9d21c85b #2 + * `max_witness_len` is the total serialized length of the + * witness data that will be supplied (e.g. sizeof(varint) + + * sizeof(witness) for each) in `funding_signed2`. + */ + + /* 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; + + ok = psbt_input_get_max_witness_len(&psbt->inputs[in], + &max_witness_len); + assert(ok); + weight += max_witness_len; + return weight; +} + +static bool find_txout(struct wally_psbt *psbt, const u8 *wscript, u16 *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)) { + *funding_txout = i; + return true; + } + } + return false; +} + +static bool check_balances(struct state *state, + struct wally_psbt *psbt, + bool check_opener_balance, + bool do_full_tx_check, + u32 feerate_per_kw_funding) +{ + struct amount_sat side_input_amt, side_output_amt, + input_amt, output_amt, fee, diff; + size_t weight, input_count = 0, output_count = 0; + bool ok; + u16 funding_outnum = psbt->num_outputs; + + if (check_opener_balance) { + u8 *funding_wscript; + + weight = common_weight(psbt->num_inputs, psbt->num_outputs); + funding_wscript = bitcoin_redeem_2of2(tmpctx, + &state->our_funding_pubkey, + &state->their_funding_pubkey); + find_txout(psbt, scriptpubkey_p2wsh(tmpctx, funding_wscript), &funding_outnum); + } else + weight = 0; + + /* Find the total input and output sums for this participant */ + input_amt = AMOUNT_SAT(0); + side_input_amt = AMOUNT_SAT(0); + for (size_t i = 0; i < psbt->num_inputs; i++) { + struct amount_sat amt = psbt_input_get_amount(psbt, i); + + /* Add to total balance check */ + if (!amount_sat_add(&input_amt, input_amt, amt)) + return false; + + if (is_openers(&psbt->inputs[i].unknowns) == check_opener_balance) { + /* If the above additon passed, this should also */ + ok = amount_sat_add(&side_input_amt, side_input_amt, amt); + assert(ok); + + weight += psbt_input_weight(psbt, i); + input_count++; + } + } + output_amt = AMOUNT_SAT(0); + side_output_amt = AMOUNT_SAT(0); + for (size_t i = 0; i < psbt->num_outputs; i++) { + struct amount_sat amt = psbt_output_get_amount(psbt, i); + /* Add to total balance check */ + if (!amount_sat_add(&output_amt, output_amt, amt)) + return false; + + if (is_openers(&psbt->outputs[i].unknowns) == check_opener_balance) { + /* Don't add the total funding balance to the amount */ + if (i != funding_outnum) { + /* If the above additon passed, this should also */ + ok = amount_sat_add(&side_output_amt, side_output_amt, amt); + assert(ok); + } + + weight += (8 + psbt->tx->outputs[i].script_len + + varint_size(psbt->tx->outputs[i].script_len)) * 4; + output_count++; + } + } + + /* Inputs must exceed outputs */ + if (do_full_tx_check && !amount_sat_greater(input_amt, output_amt)) + return false; + + /* No inputs, no outputs. Nothing to see here */ + if (input_count + output_count == 0) + return true; + + /* We need to add the 'funding' amount of the side's total, to check + * that they can cover what they've promised */ + struct amount_sat promised_funding; + if (check_opener_balance) + promised_funding = state->opener_funding; + else + promised_funding = state->accepter_funding; + + /* This shouldn't happen !? */ + if (!amount_sat_add(&side_output_amt, side_output_amt, promised_funding)) + return false; + + /* Find difference, or fail if too small */ + if (!amount_sat_sub(&diff, side_input_amt, side_output_amt)) + return false; + + /* Figure out the fee for their side */ + fee = amount_tx_fee(feerate_per_kw_funding, weight); + + /* Can they cover their fee? */ + return amount_sat_greater_eq(diff, fee); +} + +static bool is_segwit_output(struct wally_tx_output *output, + const u8 *redeemscript) +{ + const u8 *wit_prog; + if (tal_bytelen(redeemscript) > 0) + wit_prog = redeemscript; + else + wit_prog = wally_tx_output_get_script(tmpctx, output); + + return is_p2wsh(wit_prog, NULL) || is_p2wpkh(wit_prog, NULL); +} + +static struct wally_psbt * +fetch_psbt_changes(struct state *state, const struct wally_psbt *psbt) +{ + u8 *msg; + char *err; + struct channel_id unused; + struct wally_psbt *updated_psbt; + + /* Go ask lightningd what other changes we've got */ + msg = towire_dual_open_psbt_changed(NULL, &state->channel_id, psbt); + + wire_sync_write(REQ_FD, take(msg)); + msg = wire_sync_read(tmpctx, REQ_FD); + + if (fromwire_dual_open_fail(msg, msg, &err)) + peer_failed(state->pps, &state->channel_id, "%s", err); + else if (fromwire_dual_open_psbt_changed(state, msg, &unused, &updated_psbt)) { + /* Does our PSBT meet requirements? */ + if (!check_balances(state, updated_psbt, + state->our_role == OPENER, + false, /* peers input/outputs not complete */ + state->feerate_per_kw_funding)) + peer_failed(state->pps, &state->channel_id, + "Peer error updating tx state. " + "Local funds insufficient."); + + return updated_psbt; + } else + master_badmsg(fromwire_peektype(msg), msg); + + return NULL; +} + +static bool send_next(struct state *state, struct wally_psbt **psbt) +{ + u8 *msg; + bool finished = false; + struct wally_psbt *updated_psbt; + struct psbt_changeset *cs = state->changeset; + + /* First we check our cached changes */ + msg = changeset_get_next(tmpctx, &state->channel_id, cs); + if (msg) + goto sendmsg; + + /* If we don't have any changes cached, go ask Alice for + * what changes they've got for us */ + updated_psbt = fetch_psbt_changes(state, *psbt); + + /* We should always get a updated psbt back */ + if (!updated_psbt) + peer_failed(state->pps, &state->channel_id, + "Unable to determine next tx update"); + + if (psbt_has_diff(cs, *psbt, updated_psbt, + &cs->added_ins, &cs->rm_ins, + &cs->added_outs, &cs->rm_outs)) { + + *psbt = tal_steal(state, updated_psbt); + msg = changeset_get_next(tmpctx, &state->channel_id, + state->changeset); + assert(msg); + goto sendmsg; + } + + /* + * If there's no more moves, we send tx_complete + * and reply that we're finished */ + msg = towire_tx_complete(tmpctx, &state->channel_id); + finished = true; + +sendmsg: + sync_crypto_write(state->pps, msg); + + return finished; +} + +static void init_changeset(struct state *state, struct wally_psbt *psbt) +{ + struct psbt_changeset *cs = state->changeset; + /* We need an empty to compare to */ + struct wally_psbt *empty_psbt = create_psbt(tmpctx, 0, 0, 0); + + psbt_has_diff(cs, empty_psbt, psbt, + &cs->added_ins, &cs->rm_ins, + &cs->added_outs, &cs->rm_outs); +} + +/*~ Handle random messages we might get during opening negotiation, (eg. gossip) + * returning the first non-handled one, or NULL if we aborted negotiation. */ +static u8 *opening_negotiate_msg(const tal_t *ctx, struct state *state, + bool am_opener) +{ + /* This is an event loop of its own. That's generally considered poor + * form, but we use it in a very limited way. */ + for (;;) { + u8 *msg; + bool from_gossipd; + char *err; + bool all_channels; + struct channel_id actual; + + /* The event loop is responsible for freeing tmpctx, so our + * temporary allocations don't grow unbounded. */ + clean_tmpctx(); + + /* This helper routine polls both the peer and gossipd. */ + msg = peer_or_gossip_sync_read(ctx, state->pps, &from_gossipd); + + /* Use standard helper for gossip msgs (forwards, if it's an + * error, exits). */ + if (from_gossipd) { + handle_gossip_msg(state->pps, take(msg)); + continue; + } + + /* Some messages go straight to gossipd. */ + if (is_msg_for_gossipd(msg)) { + gossip_rcvd_filter_add(state->pps->grf, msg); + wire_sync_write(state->pps->gossip_fd, take(msg)); + continue; + } + + /* BOLT #1: + * + * A receiving node: + * - upon receiving a message of _odd_, unknown type: + * - MUST ignore the received message. + */ + if (is_unknown_msg_discardable(msg)) + continue; + + /* Might be a timestamp filter request: handle. */ + if (handle_timestamp_filter(state->pps, msg)) + continue; + + /* A helper which decodes an error. */ + if (is_peer_error(tmpctx, msg, &state->channel_id, + &err, &all_channels)) { + /* BOLT #1: + * + * - if no existing channel is referred to by the + * message: + * - MUST ignore the message. + */ + /* In this case, is_peer_error returns true, but sets + * err to NULL */ + if (!err) { + tal_free(msg); + continue; + } + /* Close connection on all_channels error. */ + if (all_channels) { + if (am_opener) { + msg = towire_dual_open_failed(NULL, err); + wire_sync_write(REQ_FD, take(msg)); + } + peer_failed_received_errmsg(state->pps, err, + NULL, false); + } + negotiation_aborted(state, am_opener, + tal_fmt(tmpctx, "They sent error %s", + err)); + /* Return NULL so caller knows to stop negotiating. */ + return NULL; + } + + /*~ We do not support multiple "live" channels, though the + * protocol has a "channel_id" field in all non-gossip messages + * so it's possible. Our one-process-one-channel mechanism + * keeps things simple: if we wanted to change this, we would + * probably be best with another daemon to de-multiplex them; + * this could be connectd itself, in fact. */ + if (is_wrong_channel(msg, &state->channel_id, &actual)) { + status_debug("Rejecting %s for unknown channel_id %s", + peer_wire_name(fromwire_peektype(msg)), + type_to_string(tmpctx, struct channel_id, + &actual)); + sync_crypto_write(state->pps, + take(towire_errorfmt(NULL, &actual, + "Multiple channels" + " unsupported"))); + tal_free(msg); + continue; + } + + /* If we get here, it's an interesting message. */ + return msg; + } +} + +static bool run_tx_interactive(struct state *state, struct wally_psbt **orig_psbt) +{ + /* Opener always sends the first utxo info */ + bool we_complete = false, they_complete = false; + u8 *msg; + struct wally_psbt *psbt = *orig_psbt; + + while (!(we_complete && they_complete)) { + struct channel_id cid; + enum peer_wire t; + u16 serial_id; + + /* Reset their_complete to false every round, + * they have to re-affirm every time */ + they_complete = false; + + msg = opening_negotiate_msg(tmpctx, state, false); + if (!msg) + return false; + t = fromwire_peektype(msg); + switch (t) { + case WIRE_TX_ADD_INPUT: { + const u8 *tx_bytes, *redeemscript; + u16 max_witness_len; + u32 outnum, sequence; + size_t len; + struct bitcoin_tx *tx; + struct bitcoin_txid txid; + struct amount_sat amt; + struct tlv_tx_add_input_tlvs *add_tlvs = + tlv_tx_add_input_tlvs_new(tmpctx); + + if (!fromwire_tx_add_input(tmpctx, msg, &cid, + &serial_id, + cast_const2(u8 **, &tx_bytes), + &outnum, &sequence, + &max_witness_len, + cast_const2(u8 **, &redeemscript), + add_tlvs)) + peer_failed(state->pps, &state->channel_id, + "Parsing tx_add_input %s", + tal_hex(tmpctx, msg)); + + check_channel_id(state, &cid, &state->channel_id); + /* + * BOLT-fe0351ca2cea3105c4f2eb18c571afca9d21c85b #2: + * - if is the `initiator`: + * - MUST send even `serial_id`s + * - MUST fail the transaction collaboration if: + * ... + * - it receives a `serial_id` from the peer + * with the incorrect parity + */ + if (serial_id % 2 != 0) + peer_failed(state->pps, &state->channel_id, + "Invalid serial_id rcvd. %u", serial_id); + /* + * BOLT-fe0351ca2cea3105c4f2eb18c571afca9d21c85b #2: + * - MUST fail the transaction collaboration if: + * ... + * - it recieves a duplicate `serial_id` + */ + if (psbt_has_serial_input(psbt, serial_id)) + peer_failed(state->pps, &state->channel_id, + "Duplicate serial_id rcvd. %u", serial_id); + + /* Convert tx_bytes to a tx! */ + len = tal_bytelen(tx_bytes); + tx = pull_bitcoin_tx(state, &tx_bytes, &len); + if (!tx || len != 0) + peer_failed(state->pps, &state->channel_id, + "Invalid tx sent."); + + if (outnum >= tx->wtx->num_outputs) + peer_failed(state->pps, &state->channel_id, + "Invalid tx outnum sent. %u", outnum); + /* + * BOLT-fe0351ca2cea3105c4f2eb18c571afca9d21c85b #2: + * - MUST fail the transaction collaboration if: + * ... + * - it receives an input that would create a + * malleable transaction id (e.g. pre-Segwit) + */ + if (!is_segwit_output(&tx->wtx->outputs[outnum], redeemscript)) + peer_failed(state->pps, &state->channel_id, + "Invalid tx sent. Not SegWit %s", + type_to_string(tmpctx, struct bitcoin_tx, tx)); + + /* + * BOLT-fe0351ca2cea3105c4f2eb18c571afca9d21c85b #2: + * - MUST NOT re-transmit inputs it has already received from the peer + * ... + * - MUST fail the transaction collaboration if: + * ... + * - it receives a duplicate input to one it sent previously + */ + bitcoin_txid(tx, &txid); + if (psbt_has_input(psbt, &txid, outnum)) + peer_failed(state->pps, &state->channel_id, + "Unable to add input"); + + /* + * BOLT-fe0351ca2cea3105c4f2eb18c571afca9d21c85b #2: + * The receiving node: + * - MUST add all received inputs to the funding transaction + */ + /* FIXME: elements! */ + bitcoin_tx_output_get_amount_sat(tx, outnum, &amt); + + struct wally_psbt_input *in = + psbt_append_input(psbt, &txid, outnum, + sequence, NULL, + amt, + bitcoin_tx_output_get_script(tmpctx, + tx, outnum), + NULL, + redeemscript); + if (!in) + peer_failed(state->pps, &state->channel_id, + "Unable to add input"); + + wally_psbt_input_set_utxo(in, tx->wtx); + psbt_input_add_serial_id(in, serial_id); + psbt_input_add_max_witness_len(in, max_witness_len); + + /* FIXME: what's in the tlv? */ + break; + } + case WIRE_TX_REMOVE_INPUT: { + bool input_found = false; + + if (!fromwire_tx_remove_input(msg, &cid, &serial_id)) + peer_failed(state->pps, &state->channel_id, + "Parsing tx_remove_input %s", + tal_hex(tmpctx, msg)); + + check_channel_id(state, &cid, &state->channel_id); + + for (size_t i = 0; i < psbt->num_inputs; i++) { + u16 input_serial; + if (!psbt_get_serial_id(&psbt->inputs[i].unknowns, + &input_serial)) { + peer_failed(state->pps, &state->channel_id, + "No input added with serial_id %u", + serial_id); + } + if (input_serial == serial_id) { + psbt_rm_input(psbt, i); + input_found = true; + break; + } + } + if (!input_found) + peer_failed(state->pps, &state->channel_id, + "No input added with serial_id %u", + serial_id); + break; + } + case WIRE_TX_ADD_OUTPUT: { + u64 value; + u8 *scriptpubkey; + struct wally_psbt_output *out; + struct amount_sat amt; + if (!fromwire_tx_add_output(tmpctx, msg, &cid, + &serial_id, &value, + &scriptpubkey)) + peer_failed(state->pps, &state->channel_id, + "Parsing tx_add_output %s", + tal_hex(tmpctx, msg)); + check_channel_id(state, &cid, &state->channel_id); + + if (psbt_has_serial_output(psbt, serial_id)) + peer_failed(state->pps, &state->channel_id, + "Duplicate serial_id rcvd. %u", serial_id); + amt = amount_sat(value); + out = psbt_append_output(psbt, scriptpubkey, amt); + psbt_output_add_serial_id(out, serial_id); + break; + } + case WIRE_TX_REMOVE_OUTPUT: { + bool out_found = false; + + if (!fromwire_tx_remove_output(msg, &cid, &serial_id)) + peer_failed(state->pps, &state->channel_id, + "Parsing tx_remove_output %s", + tal_hex(tmpctx, msg)); + + check_channel_id(state, &cid, &state->channel_id); + + for (size_t i = 0; i < psbt->num_outputs; i++) { + u16 output_serial; + if (!psbt_get_serial_id(&psbt->outputs[i].unknowns, + &output_serial)) { + peer_failed(state->pps, &state->channel_id, + "No output added with serial_id %u", + serial_id); + } + if (output_serial == serial_id) { + psbt_rm_output(psbt, i); + out_found = true; + break; + } + } + if (!out_found) + peer_failed(state->pps, &state->channel_id, + "No output added with serial_id %u", + serial_id); + break; + } + case WIRE_TX_COMPLETE: + if (!fromwire_tx_complete(msg, &cid)) + peer_failed(state->pps, &state->channel_id, + "Parsing tx_complete %s", + tal_hex(tmpctx, msg)); + check_channel_id(state, &cid, &state->channel_id); + they_complete = true; + break; + case WIRE_INIT: + case WIRE_ERROR: + case WIRE_OPEN_CHANNEL: + case WIRE_ACCEPT_CHANNEL: + case WIRE_FUNDING_CREATED: + case WIRE_FUNDING_SIGNED: + case WIRE_FUNDING_LOCKED: + case WIRE_SHUTDOWN: + case WIRE_CLOSING_SIGNED: + case WIRE_UPDATE_ADD_HTLC: + case WIRE_UPDATE_FULFILL_HTLC: + case WIRE_UPDATE_FAIL_HTLC: + case WIRE_UPDATE_FAIL_MALFORMED_HTLC: + case WIRE_COMMITMENT_SIGNED: + case WIRE_REVOKE_AND_ACK: + case WIRE_UPDATE_FEE: + case WIRE_CHANNEL_REESTABLISH: + case WIRE_ANNOUNCEMENT_SIGNATURES: + case WIRE_GOSSIP_TIMESTAMP_FILTER: + case WIRE_ONION_MESSAGE: + case WIRE_TX_SIGNATURES: + case WIRE_OPEN_CHANNEL2: + case WIRE_ACCEPT_CHANNEL2: + case WIRE_INIT_RBF: + case WIRE_BLACKLIST_PODLE: + case WIRE_CHANNEL_ANNOUNCEMENT: + case WIRE_CHANNEL_UPDATE: + case WIRE_NODE_ANNOUNCEMENT: + case WIRE_QUERY_CHANNEL_RANGE: + case WIRE_REPLY_CHANNEL_RANGE: + case WIRE_QUERY_SHORT_CHANNEL_IDS: + case WIRE_REPLY_SHORT_CHANNEL_IDS_END: + case WIRE_PING: + case WIRE_PONG: + peer_failed(state->pps, &state->channel_id, + "Unexpected wire message %s", + tal_hex(tmpctx, msg)); + return false; + } + + if (!(we_complete && they_complete)) + we_complete = send_next(state, &psbt); + } + + /* Sort psbt! */ + psbt_sort_by_serial_id(psbt); + + /* Return the 'finished' psbt */ + *orig_psbt = psbt; + return true; +} + +static u8 *accepter_start(struct state *state, const u8 *oc2_msg) +{ + struct bitcoin_blkid chain_hash; + struct tlv_opening_tlvs *open_tlv; + u8 channel_flags; + struct wally_psbt *psbt; + char *err_reason; + const u8 *wscript; + struct channel_id cid; + struct bitcoin_tx *remote_commit, *local_commit; + struct bitcoin_signature remote_sig, local_sig; + struct wally_tx_output *direct_outputs[NUM_SIDES]; + secp256k1_ecdsa_signature *htlc_sigs; + u8 *msg; + struct penalty_base *pbase; + struct amount_msat our_msats; + struct amount_sat total; + u8 msg_type; + + state->our_role = ACCEPTER; + open_tlv = tlv_opening_tlvs_new(tmpctx); + + if (!fromwire_open_channel2(oc2_msg, &chain_hash, + &state->opening_podle_h2, + &state->feerate_per_kw_funding, + &state->opener_funding, + &state->remoteconf.dust_limit, + &state->remoteconf.max_htlc_value_in_flight, + &state->remoteconf.htlc_minimum, + &state->feerate_per_kw, + &state->remoteconf.to_self_delay, + &state->remoteconf.max_accepted_htlcs, + &state->tx_locktime, + &state->their_funding_pubkey, + &state->their_points.revocation, + &state->their_points.payment, + &state->their_points.delayed_payment, + &state->their_points.htlc, + &state->first_per_commitment_point[REMOTE], + &channel_flags, + open_tlv)) + peer_failed(state->pps, &state->channel_id, + "Parsing open_channel2 %s", + tal_hex(tmpctx, oc2_msg)); + + if (open_tlv->option_upfront_shutdown_script) { + state->upfront_shutdown_script[REMOTE] = tal_steal(state, + open_tlv->option_upfront_shutdown_script->shutdown_scriptpubkey); + } else + state->upfront_shutdown_script[REMOTE] = NULL; + + /* BOLT #2: + * + * The receiving node MUST fail the channel if: + * - the `chain_hash` value is set to a hash of a chain + * that is unknown to the receiver. + */ + if (!bitcoin_blkid_eq(&chain_hash, &chainparams->genesis_blockhash)) { + negotiation_failed(state, false, + "Unknown chain-hash %s", + type_to_string(tmpctx, + struct bitcoin_blkid, + &chain_hash)); + return NULL; + } + + /* BOLT #2: + * + * The receiving node MUST fail the channel if: + *... + * - `funding_satoshis` is greater than or equal to 2^24 and the receiver does not support + * `option_support_large_channel`. */ + /* We choose to require *negotiation*, not just support! */ + if (!feature_negotiated(state->our_features, state->their_features, + OPT_LARGE_CHANNELS) + && amount_sat_greater(state->opener_funding, chainparams->max_funding)) { + negotiation_failed(state, false, + "opener's funding_satoshis %s too large", + type_to_string(tmpctx, struct amount_sat, + &state->opener_funding)); + return NULL; + } + + /* BOLT #2: + * + * The receiving node MUST fail the channel if: + *... + * - it considers `feerate_per_kw` too small for timely processing or + * unreasonably large. + */ + if (state->feerate_per_kw_funding < state->min_feerate) { + negotiation_failed(state, false, + "feerate_per_kw_funding %u below minimum %u", + state->feerate_per_kw_funding, state->min_feerate); + return NULL; + } + + /* We can figure out the channel id now */ + derive_channel_id_v2(&state->channel_id, + &state->our_points.revocation, + &state->their_points.revocation); + + /* FIXME: pass the podle back also */ + msg = towire_dual_open_got_offer(NULL, + state->opener_funding, + state->remoteconf.dust_limit, + state->remoteconf.max_htlc_value_in_flight, + state->remoteconf.htlc_minimum, + state->feerate_per_kw_funding, + state->feerate_per_kw, + state->remoteconf.to_self_delay, + state->remoteconf.max_accepted_htlcs, + channel_flags, + state->tx_locktime, + state->upfront_shutdown_script[REMOTE]); + + wire_sync_write(REQ_FD, take(msg)); + msg = wire_sync_read(tmpctx, REQ_FD); + + if ((msg_type = fromwire_peektype(msg)) == WIRE_DUAL_OPEN_FAIL) { + if (!fromwire_dual_open_fail(msg, msg, &err_reason)) + master_badmsg(msg_type, msg); + + u8 *errmsg = towire_errorfmt(tmpctx, &state->channel_id, + "%s", err_reason); + sync_crypto_write(state->pps, take(errmsg)); + return NULL; + } + if (!fromwire_dual_open_got_offer_reply(state, msg, + &state->accepter_funding, &psbt, + &state->upfront_shutdown_script[LOCAL])) + master_badmsg(WIRE_DUAL_OPEN_GOT_OFFER_REPLY, msg); + + if (!psbt) + psbt = create_psbt(state, 0, 0, state->tx_locktime); + + /* Check that total funding doesn't overflow */ + if (!amount_sat_add(&total, state->opener_funding, + state->accepter_funding)) + peer_failed(state->pps, &state->channel_id, + "Amount overflow. Local sats %s. " + "Remote sats %s", + type_to_string(tmpctx, struct amount_sat, + &state->accepter_funding), + type_to_string(tmpctx, struct amount_sat, + &state->opener_funding)); + + + /* Add all of our inputs/outputs to the changeset */ + init_changeset(state, psbt); + + /* Now that we know the total of the channel, we can set the reserve */ + set_reserve(state, total); + + if (!check_config_bounds(tmpctx, total, state->feerate_per_kw, + state->max_to_self_delay, + state->min_effective_htlc_capacity, + &state->remoteconf, + &state->localconf, + false, + true, /* v2 means we use anchor outputs */ + &err_reason)) { + negotiation_failed(state, false, "%s", err_reason); + return NULL; + } + + /* If we have an upfront shutdown script, send it to our peer */ + struct tlv_accept_tlvs *a_tlv = tlv_accept_tlvs_new(state); + if (state->upfront_shutdown_script[LOCAL]) { + a_tlv->option_upfront_shutdown_script = tal(a_tlv, + struct tlv_accept_tlvs_option_upfront_shutdown_script); + a_tlv->option_upfront_shutdown_script->shutdown_scriptpubkey = + tal_dup_arr(a_tlv, u8, state->upfront_shutdown_script[LOCAL], + tal_count(state->upfront_shutdown_script[LOCAL]), 0); + } + + msg = towire_accept_channel2(tmpctx, &state->channel_id, + state->accepter_funding, + state->localconf.dust_limit, + state->localconf.max_htlc_value_in_flight, + state->localconf.htlc_minimum, + state->minimum_depth, + state->localconf.to_self_delay, + state->localconf.max_accepted_htlcs, + &state->our_funding_pubkey, + &state->our_points.revocation, + &state->our_points.payment, + &state->our_points.delayed_payment, + &state->our_points.htlc, + &state->first_per_commitment_point[LOCAL], + a_tlv); + + sync_crypto_write(state->pps, msg); + peer_billboard(false, "Channel Opening: accept sent, waiting for reply"); + + /* Figure out what the funding transaction looks like! */ + if (!run_tx_interactive(state, &psbt)) + return NULL; + + /* Find the funding transaction txid */ + struct wally_tx *funding_tx; + psbt_txid(psbt, &state->funding_txid, &funding_tx); + + wscript = bitcoin_redeem_2of2(state, + &state->our_funding_pubkey, + &state->their_funding_pubkey); + + /* Figure out the txout */ + if (!find_txout(psbt, scriptpubkey_p2wsh(tmpctx, wscript), &state->funding_txout)) + peer_failed(state->pps, &state->channel_id, + "Expected output %s not found on funding tx %s", + tal_hex(tmpctx, scriptpubkey_p2wsh(tmpctx, wscript)), + type_to_string(tmpctx, struct wally_psbt, psbt)); + + /* Check that their amounts are sane */ + if (!check_balances(state, psbt, true, true, + state->feerate_per_kw_funding)) + peer_failed(state->pps, &state->channel_id, + "Insufficient funds"); + + /* Wait for the peer to send us our commitment tx signature */ + msg = opening_negotiate_msg(tmpctx, state, false); + if (!msg) + return NULL; + + remote_sig.sighash_type = SIGHASH_ALL; + if (!fromwire_commitment_signed(tmpctx, msg, &cid, + &remote_sig.s, + &htlc_sigs)) + peer_failed(state->pps, &state->channel_id, + "Parsing commitment signed %s", + tal_hex(tmpctx, msg)); + + check_channel_id(state, &cid, &state->channel_id); + + if (htlc_sigs != NULL) + peer_failed(state->pps, &state->channel_id, + "Must not send HTLCs with first" + " commitment. %s", + tal_hex(tmpctx, msg)); + + if (!amount_sat_to_msat(&our_msats, state->accepter_funding)) + peer_failed(state->pps, &state->channel_id, + "Rounding error on client."); + + state->channel = new_initial_channel(state, + &state->channel_id, + &state->funding_txid, + state->funding_txout, + state->minimum_depth, + total, + our_msats, + take(new_fee_states( + NULL, REMOTE, + &state->feerate_per_kw)), + &state->localconf, + &state->remoteconf, + &state->our_points, &state->their_points, + &state->our_funding_pubkey, + &state->their_funding_pubkey, + true, + state->option_anchor_outputs, + REMOTE); + + local_commit = initial_channel_tx(state, &wscript, state->channel, + &state->first_per_commitment_point[LOCAL], + LOCAL, NULL, &err_reason); + + /* This shouldn't happen either, AFAICT. */ + if (!local_commit) { + negotiation_failed(state, false, + "Could not meet our fees and reserve: %s", + err_reason); + return NULL; + } + + /* BOLT #2: + * + * The recipient: + * - if `signature` is incorrect: + * - MUST fail the channel. + */ + if (!check_tx_sig(local_commit, 0, NULL, wscript, &state->their_funding_pubkey, + &remote_sig)) { + /* BOLT #1: + * + * ### The `error` Message + *... + * - when failure was caused by an invalid signature check: + * - SHOULD include the raw, hex-encoded transaction in reply + * to a `funding_created`, `funding_signed`, + * `closing_signed`, or `commitment_signed` message. + */ + /*~ This verbosity is not only useful for our own testing, but + * a courtesy to other implementaters whose brains may be so + * twisted by coding in Go, Scala and Rust that they can no + * longer read C code. */ + peer_failed(state->pps, + &state->channel_id, + "Bad signature %s on tx %s using key %s (funding txid %s, psbt %s)", + type_to_string(tmpctx, struct bitcoin_signature, + &remote_sig), + type_to_string(tmpctx, struct bitcoin_tx, local_commit), + type_to_string(tmpctx, struct pubkey, + &state->their_funding_pubkey), + /* This is the first place we'd discover the funding tx + * doesn't match up */ + type_to_string(tmpctx, struct bitcoin_txid, + &state->funding_txid), + type_to_string(tmpctx, struct wally_psbt, + psbt)); + } + + /* Create commitment tx signatures for remote */ + remote_commit = initial_channel_tx(state, &wscript, state->channel, + &state->first_per_commitment_point[REMOTE], + REMOTE, direct_outputs, &err_reason); + + if (!remote_commit) { + negotiation_failed(state, false, + "Could not meet their fees and reserve: %s", err_reason); + return NULL; + } + + /* Make HSM sign it */ + msg = towire_hsmd_sign_remote_commitment_tx(NULL, + remote_commit, + &state->channel->funding_pubkey[REMOTE], + &state->first_per_commitment_point[REMOTE], + true); + wire_sync_write(HSM_FD, take(msg)); + msg = wire_sync_read(tmpctx, HSM_FD); + if (!fromwire_hsmd_sign_tx_reply(msg, &local_sig)) + status_failed(STATUS_FAIL_HSM_IO, + "Bad sign_tx_reply %s", tal_hex(tmpctx, msg)); + + assert(local_sig.sighash_type == SIGHASH_ALL); + msg = towire_commitment_signed(tmpctx, &state->channel_id, + &local_sig.s, + NULL); + + if (direct_outputs[LOCAL]) + pbase = penalty_base_new(tmpctx, 0, remote_commit, + direct_outputs[LOCAL]); + else + pbase = NULL; + + /* Send the commitment_signed controller; will save to db + * and pass messages along to channeld to send along! */ + return towire_dual_open_commit_rcvd(state, + &state->remoteconf, + remote_commit, + pbase, + &remote_sig, + psbt, + &state->channel_id, + state->pps, + &state->their_points.revocation, + &state->their_points.payment, + &state->their_points.htlc, + &state->their_points.delayed_payment, + &state->first_per_commitment_point[REMOTE], + &state->their_funding_pubkey, + &state->funding_txid, + state->funding_txout, + total, + state->accepter_funding, + channel_flags, + state->feerate_per_kw, + msg, + state->localconf.channel_reserve, + state->upfront_shutdown_script[LOCAL], + state->upfront_shutdown_script[REMOTE]); +} +#endif /* EXPERIMENTAL_FEATURES */ + +/* Memory leak detection is DEVELOPER-only because we go to great lengths to + * record the backtrace when allocations occur: without that, the leak + * detection tends to be useless for diagnosing where the leak came from, but + * it has significant overhead. */ +#if DEVELOPER +static void handle_dev_memleak(struct state *state, const u8 *msg) +{ + struct htable *memtable; + bool found_leak; + + /* Populate a hash table with all our allocations (except msg, which + * is in use right now). */ + memtable = memleak_enter_allocations(tmpctx, msg, msg); + + /* Now delete state and things it has pointers to. */ + memleak_remove_referenced(memtable, state); + + /* If there's anything left, dump it to logs, and return true. */ + found_leak = dump_memleak(memtable); + wire_sync_write(REQ_FD, + take(towire_dual_open_dev_memleak_reply(NULL, + found_leak))); +} + +/* We were told to send a custommsg to the peer by `lightningd`. All the + * verification is done on the side of `lightningd` so we should be good to + * just forward it here. */ +static void dualopend_send_custommsg(struct state *state, const u8 *msg) +{ + sync_crypto_write(state->pps, take(msg)); +} +#endif + +/*~ If we see the gossip_fd readable, we read a whole message. Sure, we might + * block, but we trust gossipd. */ +static void handle_gossip_in(struct state *state) +{ + u8 *msg = wire_sync_read(NULL, state->pps->gossip_fd); + + if (!msg) + status_failed(STATUS_FAIL_GOSSIP_IO, + "Reading gossip: %s", strerror(errno)); + + handle_gossip_msg(state->pps, take(msg)); +} + +static void try_read_gossip_store(struct state *state) +{ + u8 *msg = gossip_store_next(tmpctx, state->pps); + + if (msg) + sync_crypto_write(state->pps, take(msg)); +} + +/*~ Is this message of type `error` with the special zero-id + * "fail-everything"? If lightningd asked us to send such a thing, we're + * done. */ +static void fail_if_all_error(const u8 *inner) +{ + struct channel_id channel_id; + u8 *data; + + if (!fromwire_error(tmpctx, inner, &channel_id, &data) + || !channel_id_is_all(&channel_id)) { + return; + } + + status_info("Master said send err: %s", + sanitize_error(tmpctx, inner, NULL)); + exit(0); +} + +/* Standard lightningd-fd-is-ready-to-read demux code. Again, we could hang + * here, but if we can't trust our parent, who can we trust? */ +static u8 *handle_master_in(struct state *state) +{ + u8 *msg = wire_sync_read(tmpctx, REQ_FD); + enum dualopend_wire t = fromwire_peektype(msg); + + switch (t) { + case WIRE_DUAL_OPEN_DEV_MEMLEAK: +#if DEVELOPER + handle_dev_memleak(state, msg); + return NULL; +#endif + /* mostly handled inline */ + case WIRE_DUAL_OPEN_DEV_MEMLEAK_REPLY: + case WIRE_DUAL_OPEN_INIT: + case WIRE_DUAL_OPEN_FAILED: + case WIRE_DUAL_OPEN_FAIL: + case WIRE_DUAL_OPEN_GOT_OFFER: + case WIRE_DUAL_OPEN_GOT_OFFER_REPLY: + case WIRE_DUAL_OPEN_COMMIT_RCVD: + case WIRE_DUAL_OPEN_PSBT_CHANGED: + break; + } + + /* Now handle common messages. */ + switch ((enum common_wire)t) { +#if DEVELOPER + case WIRE_CUSTOMMSG_OUT: + dualopend_send_custommsg(state, msg); + return NULL; +#else + case WIRE_CUSTOMMSG_OUT: +#endif + /* We send these. */ + case WIRE_CUSTOMMSG_IN: + break; + } + + status_failed(STATUS_FAIL_MASTER_IO, + "Unknown msg %s", tal_hex(tmpctx, msg)); +} + +/*~ Standard "peer sent a message, handle it" demuxer. Though it really only + * handles one message, we use the standard form as principle of least + * surprise. */ +static u8 *handle_peer_in(struct state *state) +{ + u8 *msg = sync_crypto_read(tmpctx, state->pps); + enum peer_wire t = fromwire_peektype(msg); + struct channel_id channel_id; + +#if EXPERIMENTAL_FEATURES + if (t == WIRE_OPEN_CHANNEL2) + return accepter_start(state, msg); +#endif + +#if DEVELOPER + /* Handle custommsgs */ + enum peer_wire type = fromwire_peektype(msg); + if (type % 2 == 1 && !peer_wire_is_defined(type)) { + /* The message is not part of the messages we know how to + * handle. Assuming this is a custommsg, we just forward it to the + * master. */ + wire_sync_write(REQ_FD, take(towire_custommsg_in(NULL, msg))); + return NULL; + } +#endif + + /* Handles standard cases, and legal unknown ones. */ + if (handle_peer_gossip_or_error(state->pps, + &state->channel_id, false, msg)) + return NULL; + + sync_crypto_write(state->pps, + take(towire_errorfmt(NULL, + extract_channel_id(msg, &channel_id) ? &channel_id : NULL, + "Unexpected message %s: %s", + peer_wire_name(t), + tal_hex(tmpctx, msg)))); + + /* FIXME: We don't actually want master to try to send an + * error, since peer is transient. This is a hack. + */ + status_broken("Unexpected message %s", peer_wire_name(t)); + peer_failed_connection_lost(); +} + +int main(int argc, char *argv[]) +{ + common_setup(argv[0]); + + struct pollfd pollfd[3]; + struct state *state = tal(NULL, struct state); + struct secret *none; + u8 *msg, *inner; + + subdaemon_setup(argc, argv); + + /*~ This makes status_failed, status_debug etc work synchronously by + * writing to REQ_FD */ + status_setup_sync(REQ_FD); + + /*~ The very first thing we read from lightningd is our init msg */ + msg = wire_sync_read(tmpctx, REQ_FD); + if (!fromwire_dual_open_init(state, msg, + &chainparams, + &state->our_features, + &state->their_features, + &state->localconf, + &state->max_to_self_delay, + &state->min_effective_htlc_capacity, + &state->pps, + &state->our_points, + &state->our_funding_pubkey, + &state->minimum_depth, + &state->min_feerate, &state->max_feerate, + &state->option_anchor_outputs, + &inner)) + master_badmsg(WIRE_DUAL_OPEN_INIT, msg); + + /* 3 == peer, 4 == gossipd, 5 = gossip_store, 6 = hsmd */ + per_peer_state_set_fds(state->pps, 3, 4, 5); + + /*~ If lightningd wanted us to send a msg, do so before we waste time + * doing work. If it's a global error, we'll close immediately. */ + if (inner != NULL) { + sync_crypto_write(state->pps, inner); + fail_if_all_error(inner); + tal_free(inner); + } + + /*~ Initially we're not associated with a channel, but + * handle_peer_gossip_or_error compares this. */ + memset(&state->channel_id, 0, sizeof(state->channel_id)); + state->channel = NULL; + state->changeset = new_changeset(state); + + /*~ We set these to NULL, meaning no requirements on shutdown */ + state->upfront_shutdown_script[LOCAL] + = state->upfront_shutdown_script[REMOTE] + = NULL; + + /*~ We need an initial per-commitment point whether we're funding or + * they are, and lightningd has reserved a unique dbid for us already, + * so we might as well get the hsm daemon to generate it now. */ + wire_sync_write(HSM_FD, + take(towire_hsmd_get_per_commitment_point(NULL, 0))); + msg = wire_sync_read(tmpctx, HSM_FD); + if (!fromwire_hsmd_get_per_commitment_point_reply(tmpctx, msg, + &state->first_per_commitment_point[LOCAL], + &none)) + status_failed(STATUS_FAIL_HSM_IO, + "Bad get_per_commitment_point_reply %s", + tal_hex(tmpctx, msg)); + /*~ The HSM gives us the N-2'th per-commitment secret when we get the + * N'th per-commitment point. But since N=0, it won't give us one. */ + assert(none == NULL); + + /*~ Turns out this is useful for testing, to make sure we're ready. */ + status_debug("Handed peer, entering loop"); + + /*~ We manually run a little poll() loop here. With only three fds */ + pollfd[0].fd = REQ_FD; + pollfd[0].events = POLLIN; + pollfd[1].fd = state->pps->gossip_fd; + pollfd[1].events = POLLIN; + pollfd[2].fd = state->pps->peer_fd; + pollfd[2].events = POLLIN; + + /* We exit when we get a conclusion to write to lightningd: either + * opening_funder_reply or opening_fundee. */ + msg = NULL; + while (!msg) { + int t; + struct timerel trel; + if (time_to_next_gossip(state->pps, &trel)) + t = time_to_msec(trel); + else + t = -1; + + /*~ If we get a signal which aborts the poll() call, valgrind + * complains about revents being uninitialized. I'm not sure + * that's correct, but it's easy to be sure. */ + pollfd[0].revents = pollfd[1].revents = pollfd[2].revents = 0; + + poll(pollfd, ARRAY_SIZE(pollfd), t); + /* Subtle: handle_master_in can do its own poll loop, so + * don't try to service more than one fd per loop. */ + /* First priority: messages from lightningd. */ + if (pollfd[0].revents & POLLIN) + msg = handle_master_in(state); + /* Second priority: messages from peer. */ + else if (pollfd[2].revents & POLLIN) + msg = handle_peer_in(state); + /* Last priority: chit-chat from gossipd. */ + else if (pollfd[1].revents & POLLIN) + handle_gossip_in(state); + else + try_read_gossip_store(state); + + /* Since we're the top-level event loop, we clean up */ + clean_tmpctx(); + } + + /*~ Write message and hand back the peer fd and gossipd fd. This also + * means that if the peer or gossipd wrote us any messages we didn't + * read yet, it will simply be read by the next daemon. */ + wire_sync_write(REQ_FD, msg); + per_peer_state_fdpass_send(REQ_FD, state->pps); + status_debug("Sent %s with fds", + dualopend_wire_name(fromwire_peektype(msg))); + + /* This frees the entire tal tree. */ + tal_free(state); + common_shutdown(); + daemon_shutdown(); + return 0; +} diff --git a/openingd/dualopend_wire.csv b/openingd/dualopend_wire.csv new file mode 100644 index 000000000..984acc47e --- /dev/null +++ b/openingd/dualopend_wire.csv @@ -0,0 +1,105 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +msgtype,dual_open_init,7000 +# Which network are we configured for? +msgdata,dual_open_init,chainparams,chainparams, +msgdata,dual_open_init,our_feature_set,feature_set, +msgdata,dual_open_init,their_init_features_len,u16, +msgdata,dual_open_init,their_init_features,u8,their_init_features_len +# Base configuration we'll offer +msgdata,dual_open_init,our_config,channel_config, +# Minimum/maximum configuration values we'll accept +msgdata,dual_open_init,max_to_self_delay,u32, +msgdata,dual_open_init,min_effective_htlc_capacity_msat,amount_msat, +msgdata,dual_open_init,pps,per_peer_state, +msgdata,dual_open_init,our_basepoints,basepoints, +msgdata,dual_open_init,our_funding_pubkey,pubkey, +# Constraints in case the other end tries to open a channel. +msgdata,dual_open_init,minimum_depth,u32, +msgdata,dual_open_init,min_feerate,u32, +msgdata,dual_open_init,max_feerate,u32, +msgdata,dual_open_init,option_anchor_outputs,bool, +# Optional msg to send. +msgdata,dual_open_init,len,u16, +msgdata,dual_open_init,msg,u8,len + +# dualopend->master: they offered channel, should we continue? +msgtype,dual_open_got_offer,7005 +msgdata,dual_open_got_offer,opener_funding,amount_sat, +msgdata,dual_open_got_offer,dust_limit_satoshis,amount_sat, +msgdata,dual_open_got_offer,max_htlc_value_in_flight_msat,amount_msat, +msgdata,dual_open_got_offer,htlc_minimum_msat,amount_msat, +msgdata,dual_open_got_offer,feerate_per_kw_funding,u32, +msgdata,dual_open_got_offer,feerate_per_kw,u32, +msgdata,dual_open_got_offer,to_self_delay,u16, +msgdata,dual_open_got_offer,max_accepted_htlcs,u16, +msgdata,dual_open_got_offer,channel_flags,u8, +msgdata,dual_open_got_offer,locktime,u32, +msgdata,dual_open_got_offer,shutdown_len,u16, +msgdata,dual_open_got_offer,shutdown_scriptpubkey,u8,shutdown_len + +# master->dualopend: reply back with our first funding info/contribs +msgtype,dual_open_got_offer_reply,7105 +msgdata,dual_open_got_offer_reply,accepter_funding,amount_sat, +msgdata,dual_open_got_offer_reply,psbt,wally_psbt, +msgdata,dual_open_got_offer_reply,shutdown_len,u16, +msgdata,dual_open_got_offer_reply,our_shutdown_scriptpubkey,?u8,shutdown_len + +# dualopend->master: ready to commit channel open to database and +# get some signatures for the funding_tx. +msgtype,dual_open_commit_rcvd,7007 +msgdata,dual_open_commit_rcvd,their_config,channel_config, +msgdata,dual_open_commit_rcvd,remote_first_commit,bitcoin_tx, +msgdata,dual_open_commit_rcvd,pbase,?penalty_base, +msgdata,dual_open_commit_rcvd,first_commit_sig,bitcoin_signature, +msgdata,dual_open_commit_rcvd,psbt,wally_psbt, +msgdata,dual_open_commit_rcvd,channel_id,channel_id, +msgdata,dual_open_commit_rcvd,pps,per_peer_state, +msgdata,dual_open_commit_rcvd,revocation_basepoint,pubkey, +msgdata,dual_open_commit_rcvd,payment_basepoint,pubkey, +msgdata,dual_open_commit_rcvd,htlc_basepoint,pubkey, +msgdata,dual_open_commit_rcvd,delayed_payment_basepoint,pubkey, +msgdata,dual_open_commit_rcvd,their_per_commit_point,pubkey, +msgdata,dual_open_commit_rcvd,remote_fundingkey,pubkey, +msgdata,dual_open_commit_rcvd,funding_txid,bitcoin_txid, +msgdata,dual_open_commit_rcvd,funding_txout,u16, +msgdata,dual_open_commit_rcvd,funding_satoshis,amount_sat, +msgdata,dual_open_commit_rcvd,our_funding_sats,amount_sat, +msgdata,dual_open_commit_rcvd,channel_flags,u8, +msgdata,dual_open_commit_rcvd,feerate_per_kw,u32, +# our commitment signatures, for the peer +msgdata,dual_open_commit_rcvd,msglen,u16, +msgdata,dual_open_commit_rcvd,commitment_msg,u8,msglen +msgdata,dual_open_commit_rcvd,our_channel_reserve_satoshis,amount_sat, +msgdata,dual_open_commit_rcvd,local_shutdown_len,u16, +msgdata,dual_open_commit_rcvd,local_shutdown_scriptpubkey,u8,local_shutdown_len +msgdata,dual_open_commit_rcvd,remote_shutdown_len,u16, +msgdata,dual_open_commit_rcvd,remote_shutdown_scriptpubkey,u8,remote_shutdown_len + +# dualopend->master: peer updated the psbt +# master->dualopend: response from hook when asking for next moves +msgtype,dual_open_psbt_changed,7107 +msgdata,dual_open_psbt_changed,channel_id,channel_id, +msgdata,dual_open_psbt_changed,psbt,wally_psbt, + +# master->dualopend: fail this channel open +msgtype,dual_open_fail,7003 +msgdata,dual_open_fail,reason,wirestring, + +# dualopend->master: we failed to negotiation channel +msgtype,dual_open_failed,7004 +msgdata,dual_open_failed,reason,wirestring, + +# master -> dualopend: do you have a memleak? +msgtype,dual_open_dev_memleak,7033 + +msgtype,dual_open_dev_memleak_reply,7133 +msgdata,dual_open_dev_memleak_reply,leak,bool, diff --git a/openingd/dualopend_wiregen.c b/openingd/dualopend_wiregen.c new file mode 100644 index 000000000..3a520ea92 --- /dev/null +++ b/openingd/dualopend_wiregen.c @@ -0,0 +1,418 @@ +/* This file was generated by generate-wire.py */ +/* Do not modify this file! Modify the .csv file it was generated from. */ +/* Original template can be found at tools/gen/impl_template */ + +#include +#include +#include +#include +#include +#include +#include + +#ifndef SUPERVERBOSE +#define SUPERVERBOSE(...) +#endif + + +const char *dualopend_wire_name(int e) +{ + static char invalidbuf[sizeof("INVALID ") + STR_MAX_CHARS(e)]; + + switch ((enum dualopend_wire)e) { + case WIRE_DUAL_OPEN_INIT: return "WIRE_DUAL_OPEN_INIT"; + case WIRE_DUAL_OPEN_GOT_OFFER: return "WIRE_DUAL_OPEN_GOT_OFFER"; + case WIRE_DUAL_OPEN_GOT_OFFER_REPLY: return "WIRE_DUAL_OPEN_GOT_OFFER_REPLY"; + case WIRE_DUAL_OPEN_COMMIT_RCVD: return "WIRE_DUAL_OPEN_COMMIT_RCVD"; + case WIRE_DUAL_OPEN_PSBT_CHANGED: return "WIRE_DUAL_OPEN_PSBT_CHANGED"; + case WIRE_DUAL_OPEN_FAIL: return "WIRE_DUAL_OPEN_FAIL"; + case WIRE_DUAL_OPEN_FAILED: return "WIRE_DUAL_OPEN_FAILED"; + case WIRE_DUAL_OPEN_DEV_MEMLEAK: return "WIRE_DUAL_OPEN_DEV_MEMLEAK"; + case WIRE_DUAL_OPEN_DEV_MEMLEAK_REPLY: return "WIRE_DUAL_OPEN_DEV_MEMLEAK_REPLY"; + } + + snprintf(invalidbuf, sizeof(invalidbuf), "INVALID %i", e); + return invalidbuf; +} + +bool dualopend_wire_is_defined(u16 type) +{ + switch ((enum dualopend_wire)type) { + case WIRE_DUAL_OPEN_INIT:; + case WIRE_DUAL_OPEN_GOT_OFFER:; + case WIRE_DUAL_OPEN_GOT_OFFER_REPLY:; + case WIRE_DUAL_OPEN_COMMIT_RCVD:; + case WIRE_DUAL_OPEN_PSBT_CHANGED:; + case WIRE_DUAL_OPEN_FAIL:; + case WIRE_DUAL_OPEN_FAILED:; + case WIRE_DUAL_OPEN_DEV_MEMLEAK:; + case WIRE_DUAL_OPEN_DEV_MEMLEAK_REPLY:; + return true; + } + return false; +} + + + + + +/* WIRE: DUAL_OPEN_INIT */ +u8 *towire_dual_open_init(const tal_t *ctx, const struct chainparams *chainparams, const struct feature_set *our_feature_set, const u8 *their_init_features, const struct channel_config *our_config, u32 max_to_self_delay, struct amount_msat min_effective_htlc_capacity_msat, const struct per_peer_state *pps, const struct basepoints *our_basepoints, const struct pubkey *our_funding_pubkey, u32 minimum_depth, u32 min_feerate, u32 max_feerate, bool option_anchor_outputs, const u8 *msg) +{ + u16 their_init_features_len = tal_count(their_init_features); + u16 len = tal_count(msg); + u8 *p = tal_arr(ctx, u8, 0); + + towire_u16(&p, WIRE_DUAL_OPEN_INIT); + /* Which network are we configured for? */ + towire_chainparams(&p, chainparams); + towire_feature_set(&p, our_feature_set); + towire_u16(&p, their_init_features_len); + towire_u8_array(&p, their_init_features, their_init_features_len); + /* Base configuration we'll offer */ + towire_channel_config(&p, our_config); + /* Minimum/maximum configuration values we'll accept */ + towire_u32(&p, max_to_self_delay); + towire_amount_msat(&p, min_effective_htlc_capacity_msat); + towire_per_peer_state(&p, pps); + towire_basepoints(&p, our_basepoints); + towire_pubkey(&p, our_funding_pubkey); + /* Constraints in case the other end tries to open a channel. */ + towire_u32(&p, minimum_depth); + towire_u32(&p, min_feerate); + towire_u32(&p, max_feerate); + towire_bool(&p, option_anchor_outputs); + /* Optional msg to send. */ + towire_u16(&p, len); + towire_u8_array(&p, msg, len); + + return memcheck(p, tal_count(p)); +} +bool fromwire_dual_open_init(const tal_t *ctx, const void *p, const struct chainparams **chainparams, struct feature_set **our_feature_set, u8 **their_init_features, struct channel_config *our_config, u32 *max_to_self_delay, struct amount_msat *min_effective_htlc_capacity_msat, struct per_peer_state **pps, struct basepoints *our_basepoints, struct pubkey *our_funding_pubkey, u32 *minimum_depth, u32 *min_feerate, u32 *max_feerate, bool *option_anchor_outputs, u8 **msg) +{ + u16 their_init_features_len; + u16 len; + + const u8 *cursor = p; + size_t plen = tal_count(p); + + if (fromwire_u16(&cursor, &plen) != WIRE_DUAL_OPEN_INIT) + return false; + /* Which network are we configured for? */ + fromwire_chainparams(&cursor, &plen, chainparams); + *our_feature_set = fromwire_feature_set(ctx, &cursor, &plen); + their_init_features_len = fromwire_u16(&cursor, &plen); + // 2nd case their_init_features + *their_init_features = their_init_features_len ? tal_arr(ctx, u8, their_init_features_len) : NULL; + fromwire_u8_array(&cursor, &plen, *their_init_features, their_init_features_len); + /* Base configuration we'll offer */ + fromwire_channel_config(&cursor, &plen, our_config); + /* Minimum/maximum configuration values we'll accept */ + *max_to_self_delay = fromwire_u32(&cursor, &plen); + *min_effective_htlc_capacity_msat = fromwire_amount_msat(&cursor, &plen); + *pps = fromwire_per_peer_state(ctx, &cursor, &plen); + fromwire_basepoints(&cursor, &plen, our_basepoints); + fromwire_pubkey(&cursor, &plen, our_funding_pubkey); + /* Constraints in case the other end tries to open a channel. */ + *minimum_depth = fromwire_u32(&cursor, &plen); + *min_feerate = fromwire_u32(&cursor, &plen); + *max_feerate = fromwire_u32(&cursor, &plen); + *option_anchor_outputs = fromwire_bool(&cursor, &plen); + /* Optional msg to send. */ + len = fromwire_u16(&cursor, &plen); + // 2nd case msg + *msg = len ? tal_arr(ctx, u8, len) : NULL; + fromwire_u8_array(&cursor, &plen, *msg, len); + return cursor != NULL; +} + +/* WIRE: DUAL_OPEN_GOT_OFFER */ +/* dualopend->master: they offered channel */ +u8 *towire_dual_open_got_offer(const tal_t *ctx, struct amount_sat opener_funding, struct amount_sat dust_limit_satoshis, struct amount_msat max_htlc_value_in_flight_msat, struct amount_msat htlc_minimum_msat, u32 feerate_per_kw_funding, u32 feerate_per_kw, u16 to_self_delay, u16 max_accepted_htlcs, u8 channel_flags, u32 locktime, const u8 *shutdown_scriptpubkey) +{ + u16 shutdown_len = tal_count(shutdown_scriptpubkey); + u8 *p = tal_arr(ctx, u8, 0); + + towire_u16(&p, WIRE_DUAL_OPEN_GOT_OFFER); + towire_amount_sat(&p, opener_funding); + towire_amount_sat(&p, dust_limit_satoshis); + towire_amount_msat(&p, max_htlc_value_in_flight_msat); + towire_amount_msat(&p, htlc_minimum_msat); + towire_u32(&p, feerate_per_kw_funding); + towire_u32(&p, feerate_per_kw); + towire_u16(&p, to_self_delay); + towire_u16(&p, max_accepted_htlcs); + towire_u8(&p, channel_flags); + towire_u32(&p, locktime); + towire_u16(&p, shutdown_len); + towire_u8_array(&p, shutdown_scriptpubkey, shutdown_len); + + return memcheck(p, tal_count(p)); +} +bool fromwire_dual_open_got_offer(const tal_t *ctx, const void *p, struct amount_sat *opener_funding, struct amount_sat *dust_limit_satoshis, struct amount_msat *max_htlc_value_in_flight_msat, struct amount_msat *htlc_minimum_msat, u32 *feerate_per_kw_funding, u32 *feerate_per_kw, u16 *to_self_delay, u16 *max_accepted_htlcs, u8 *channel_flags, u32 *locktime, u8 **shutdown_scriptpubkey) +{ + u16 shutdown_len; + + const u8 *cursor = p; + size_t plen = tal_count(p); + + if (fromwire_u16(&cursor, &plen) != WIRE_DUAL_OPEN_GOT_OFFER) + return false; + *opener_funding = fromwire_amount_sat(&cursor, &plen); + *dust_limit_satoshis = fromwire_amount_sat(&cursor, &plen); + *max_htlc_value_in_flight_msat = fromwire_amount_msat(&cursor, &plen); + *htlc_minimum_msat = fromwire_amount_msat(&cursor, &plen); + *feerate_per_kw_funding = fromwire_u32(&cursor, &plen); + *feerate_per_kw = fromwire_u32(&cursor, &plen); + *to_self_delay = fromwire_u16(&cursor, &plen); + *max_accepted_htlcs = fromwire_u16(&cursor, &plen); + *channel_flags = fromwire_u8(&cursor, &plen); + *locktime = fromwire_u32(&cursor, &plen); + shutdown_len = fromwire_u16(&cursor, &plen); + // 2nd case shutdown_scriptpubkey + *shutdown_scriptpubkey = shutdown_len ? tal_arr(ctx, u8, shutdown_len) : NULL; + fromwire_u8_array(&cursor, &plen, *shutdown_scriptpubkey, shutdown_len); + return cursor != NULL; +} + +/* WIRE: DUAL_OPEN_GOT_OFFER_REPLY */ +/* master->dualopend: reply back with our first funding info/contribs */ +u8 *towire_dual_open_got_offer_reply(const tal_t *ctx, struct amount_sat accepter_funding, const struct wally_psbt *psbt, const u8 *our_shutdown_scriptpubkey) +{ + u16 shutdown_len = tal_count(our_shutdown_scriptpubkey); + u8 *p = tal_arr(ctx, u8, 0); + + towire_u16(&p, WIRE_DUAL_OPEN_GOT_OFFER_REPLY); + towire_amount_sat(&p, accepter_funding); + towire_wally_psbt(&p, psbt); + towire_u16(&p, shutdown_len); + towire_u8_array(&p, our_shutdown_scriptpubkey, shutdown_len); + + return memcheck(p, tal_count(p)); +} +bool fromwire_dual_open_got_offer_reply(const tal_t *ctx, const void *p, struct amount_sat *accepter_funding, struct wally_psbt **psbt, u8 **our_shutdown_scriptpubkey) +{ + u16 shutdown_len; + + const u8 *cursor = p; + size_t plen = tal_count(p); + + if (fromwire_u16(&cursor, &plen) != WIRE_DUAL_OPEN_GOT_OFFER_REPLY) + return false; + *accepter_funding = fromwire_amount_sat(&cursor, &plen); + *psbt = fromwire_wally_psbt(ctx, &cursor, &plen); + shutdown_len = fromwire_u16(&cursor, &plen); + // 2nd case our_shutdown_scriptpubkey + *our_shutdown_scriptpubkey = shutdown_len ? tal_arr(ctx, u8, shutdown_len) : NULL; + fromwire_u8_array(&cursor, &plen, *our_shutdown_scriptpubkey, shutdown_len); + return cursor != NULL; +} + +/* WIRE: DUAL_OPEN_COMMIT_RCVD */ +/* dualopend->master: ready to commit channel open to database and */ +/* get some signatures for the funding_tx. */ +u8 *towire_dual_open_commit_rcvd(const tal_t *ctx, const struct channel_config *their_config, const struct bitcoin_tx *remote_first_commit, const struct penalty_base *pbase, const struct bitcoin_signature *first_commit_sig, const struct wally_psbt *psbt, const struct channel_id *channel_id, const struct per_peer_state *pps, const struct pubkey *revocation_basepoint, const struct pubkey *payment_basepoint, const struct pubkey *htlc_basepoint, const struct pubkey *delayed_payment_basepoint, const struct pubkey *their_per_commit_point, const struct pubkey *remote_fundingkey, const struct bitcoin_txid *funding_txid, u16 funding_txout, struct amount_sat funding_satoshis, struct amount_sat our_funding_sats, u8 channel_flags, u32 feerate_per_kw, const u8 *commitment_msg, struct amount_sat our_channel_reserve_satoshis, const u8 *local_shutdown_scriptpubkey, const u8 *remote_shutdown_scriptpubkey) +{ + u16 msglen = tal_count(commitment_msg); + u16 local_shutdown_len = tal_count(local_shutdown_scriptpubkey); + u16 remote_shutdown_len = tal_count(remote_shutdown_scriptpubkey); + u8 *p = tal_arr(ctx, u8, 0); + + towire_u16(&p, WIRE_DUAL_OPEN_COMMIT_RCVD); + towire_channel_config(&p, their_config); + towire_bitcoin_tx(&p, remote_first_commit); + if (!pbase) + towire_bool(&p, false); + else { + towire_bool(&p, true); + towire_penalty_base(&p, pbase); + } + towire_bitcoin_signature(&p, first_commit_sig); + towire_wally_psbt(&p, psbt); + towire_channel_id(&p, channel_id); + towire_per_peer_state(&p, pps); + towire_pubkey(&p, revocation_basepoint); + towire_pubkey(&p, payment_basepoint); + towire_pubkey(&p, htlc_basepoint); + towire_pubkey(&p, delayed_payment_basepoint); + towire_pubkey(&p, their_per_commit_point); + towire_pubkey(&p, remote_fundingkey); + towire_bitcoin_txid(&p, funding_txid); + towire_u16(&p, funding_txout); + towire_amount_sat(&p, funding_satoshis); + towire_amount_sat(&p, our_funding_sats); + towire_u8(&p, channel_flags); + towire_u32(&p, feerate_per_kw); + /* our commitment signatures */ + towire_u16(&p, msglen); + towire_u8_array(&p, commitment_msg, msglen); + towire_amount_sat(&p, our_channel_reserve_satoshis); + towire_u16(&p, local_shutdown_len); + towire_u8_array(&p, local_shutdown_scriptpubkey, local_shutdown_len); + towire_u16(&p, remote_shutdown_len); + towire_u8_array(&p, remote_shutdown_scriptpubkey, remote_shutdown_len); + + return memcheck(p, tal_count(p)); +} +bool fromwire_dual_open_commit_rcvd(const tal_t *ctx, const void *p, struct channel_config *their_config, struct bitcoin_tx **remote_first_commit, struct penalty_base **pbase, struct bitcoin_signature *first_commit_sig, struct wally_psbt **psbt, struct channel_id *channel_id, struct per_peer_state **pps, struct pubkey *revocation_basepoint, struct pubkey *payment_basepoint, struct pubkey *htlc_basepoint, struct pubkey *delayed_payment_basepoint, struct pubkey *their_per_commit_point, struct pubkey *remote_fundingkey, struct bitcoin_txid *funding_txid, u16 *funding_txout, struct amount_sat *funding_satoshis, struct amount_sat *our_funding_sats, u8 *channel_flags, u32 *feerate_per_kw, u8 **commitment_msg, struct amount_sat *our_channel_reserve_satoshis, u8 **local_shutdown_scriptpubkey, u8 **remote_shutdown_scriptpubkey) +{ + u16 msglen; + u16 local_shutdown_len; + u16 remote_shutdown_len; + + const u8 *cursor = p; + size_t plen = tal_count(p); + + if (fromwire_u16(&cursor, &plen) != WIRE_DUAL_OPEN_COMMIT_RCVD) + return false; + fromwire_channel_config(&cursor, &plen, their_config); + *remote_first_commit = fromwire_bitcoin_tx(ctx, &cursor, &plen); + if (!fromwire_bool(&cursor, &plen)) + *pbase = NULL; + else { + *pbase = tal(ctx, struct penalty_base); + fromwire_penalty_base(&cursor, &plen, *pbase); + } + fromwire_bitcoin_signature(&cursor, &plen, first_commit_sig); + *psbt = fromwire_wally_psbt(ctx, &cursor, &plen); + fromwire_channel_id(&cursor, &plen, channel_id); + *pps = fromwire_per_peer_state(ctx, &cursor, &plen); + fromwire_pubkey(&cursor, &plen, revocation_basepoint); + fromwire_pubkey(&cursor, &plen, payment_basepoint); + fromwire_pubkey(&cursor, &plen, htlc_basepoint); + fromwire_pubkey(&cursor, &plen, delayed_payment_basepoint); + fromwire_pubkey(&cursor, &plen, their_per_commit_point); + fromwire_pubkey(&cursor, &plen, remote_fundingkey); + fromwire_bitcoin_txid(&cursor, &plen, funding_txid); + *funding_txout = fromwire_u16(&cursor, &plen); + *funding_satoshis = fromwire_amount_sat(&cursor, &plen); + *our_funding_sats = fromwire_amount_sat(&cursor, &plen); + *channel_flags = fromwire_u8(&cursor, &plen); + *feerate_per_kw = fromwire_u32(&cursor, &plen); + /* our commitment signatures */ + msglen = fromwire_u16(&cursor, &plen); + // 2nd case commitment_msg + *commitment_msg = msglen ? tal_arr(ctx, u8, msglen) : NULL; + fromwire_u8_array(&cursor, &plen, *commitment_msg, msglen); + *our_channel_reserve_satoshis = fromwire_amount_sat(&cursor, &plen); + local_shutdown_len = fromwire_u16(&cursor, &plen); + // 2nd case local_shutdown_scriptpubkey + *local_shutdown_scriptpubkey = local_shutdown_len ? tal_arr(ctx, u8, local_shutdown_len) : NULL; + fromwire_u8_array(&cursor, &plen, *local_shutdown_scriptpubkey, local_shutdown_len); + remote_shutdown_len = fromwire_u16(&cursor, &plen); + // 2nd case remote_shutdown_scriptpubkey + *remote_shutdown_scriptpubkey = remote_shutdown_len ? tal_arr(ctx, u8, remote_shutdown_len) : NULL; + fromwire_u8_array(&cursor, &plen, *remote_shutdown_scriptpubkey, remote_shutdown_len); + return cursor != NULL; +} + +/* WIRE: DUAL_OPEN_PSBT_CHANGED */ +/* dualopend->master: peer updated the psbt */ +/* master->dualopend: response from hook when asking for next moves */ +u8 *towire_dual_open_psbt_changed(const tal_t *ctx, const struct channel_id *channel_id, const struct wally_psbt *psbt) +{ + u8 *p = tal_arr(ctx, u8, 0); + + towire_u16(&p, WIRE_DUAL_OPEN_PSBT_CHANGED); + towire_channel_id(&p, channel_id); + towire_wally_psbt(&p, psbt); + + return memcheck(p, tal_count(p)); +} +bool fromwire_dual_open_psbt_changed(const tal_t *ctx, const void *p, struct channel_id *channel_id, struct wally_psbt **psbt) +{ + const u8 *cursor = p; + size_t plen = tal_count(p); + + if (fromwire_u16(&cursor, &plen) != WIRE_DUAL_OPEN_PSBT_CHANGED) + return false; + fromwire_channel_id(&cursor, &plen, channel_id); + *psbt = fromwire_wally_psbt(ctx, &cursor, &plen); + return cursor != NULL; +} + +/* WIRE: DUAL_OPEN_FAIL */ +/* master->dualopend: fail this channel open */ +u8 *towire_dual_open_fail(const tal_t *ctx, const wirestring *reason) +{ + u8 *p = tal_arr(ctx, u8, 0); + + towire_u16(&p, WIRE_DUAL_OPEN_FAIL); + towire_wirestring(&p, reason); + + return memcheck(p, tal_count(p)); +} +bool fromwire_dual_open_fail(const tal_t *ctx, const void *p, wirestring **reason) +{ + const u8 *cursor = p; + size_t plen = tal_count(p); + + if (fromwire_u16(&cursor, &plen) != WIRE_DUAL_OPEN_FAIL) + return false; + *reason = fromwire_wirestring(ctx, &cursor, &plen); + return cursor != NULL; +} + +/* WIRE: DUAL_OPEN_FAILED */ +/* dualopend->master: we failed to negotiation channel */ +u8 *towire_dual_open_failed(const tal_t *ctx, const wirestring *reason) +{ + u8 *p = tal_arr(ctx, u8, 0); + + towire_u16(&p, WIRE_DUAL_OPEN_FAILED); + towire_wirestring(&p, reason); + + return memcheck(p, tal_count(p)); +} +bool fromwire_dual_open_failed(const tal_t *ctx, const void *p, wirestring **reason) +{ + const u8 *cursor = p; + size_t plen = tal_count(p); + + if (fromwire_u16(&cursor, &plen) != WIRE_DUAL_OPEN_FAILED) + return false; + *reason = fromwire_wirestring(ctx, &cursor, &plen); + return cursor != NULL; +} + +/* WIRE: DUAL_OPEN_DEV_MEMLEAK */ +/* master -> dualopend: do you have a memleak? */ +u8 *towire_dual_open_dev_memleak(const tal_t *ctx) +{ + u8 *p = tal_arr(ctx, u8, 0); + + towire_u16(&p, WIRE_DUAL_OPEN_DEV_MEMLEAK); + + return memcheck(p, tal_count(p)); +} +bool fromwire_dual_open_dev_memleak(const void *p) +{ + const u8 *cursor = p; + size_t plen = tal_count(p); + + if (fromwire_u16(&cursor, &plen) != WIRE_DUAL_OPEN_DEV_MEMLEAK) + return false; + return cursor != NULL; +} + +/* WIRE: DUAL_OPEN_DEV_MEMLEAK_REPLY */ +u8 *towire_dual_open_dev_memleak_reply(const tal_t *ctx, bool leak) +{ + u8 *p = tal_arr(ctx, u8, 0); + + towire_u16(&p, WIRE_DUAL_OPEN_DEV_MEMLEAK_REPLY); + towire_bool(&p, leak); + + return memcheck(p, tal_count(p)); +} +bool fromwire_dual_open_dev_memleak_reply(const void *p, bool *leak) +{ + const u8 *cursor = p; + size_t plen = tal_count(p); + + if (fromwire_u16(&cursor, &plen) != WIRE_DUAL_OPEN_DEV_MEMLEAK_REPLY) + return false; + *leak = fromwire_bool(&cursor, &plen); + return cursor != NULL; +} +// SHA256STAMP:1c4ae8e18ade1c0dcf975d8573e82c491a52fcda35d193b7302abda8d35dee8e diff --git a/openingd/dualopend_wiregen.h b/openingd/dualopend_wiregen.h new file mode 100644 index 000000000..9bb1122f1 --- /dev/null +++ b/openingd/dualopend_wiregen.h @@ -0,0 +1,100 @@ +/* This file was generated by generate-wire.py */ +/* Do not modify this file! Modify the _csv file it was generated from. */ +/* Original template can be found at tools/gen/header_template */ + +#ifndef LIGHTNING_OPENINGD_DUALOPEND_WIREGEN_H +#define LIGHTNING_OPENINGD_DUALOPEND_WIREGEN_H +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +enum dualopend_wire { + WIRE_DUAL_OPEN_INIT = 7000, + /* dualopend->master: they offered channel */ + WIRE_DUAL_OPEN_GOT_OFFER = 7005, + /* master->dualopend: reply back with our first funding info/contribs */ + WIRE_DUAL_OPEN_GOT_OFFER_REPLY = 7105, + /* dualopend->master: ready to commit channel open to database and */ + /* get some signatures for the funding_tx. */ + WIRE_DUAL_OPEN_COMMIT_RCVD = 7007, + /* dualopend->master: peer updated the psbt */ + /* master->dualopend: response from hook when asking for next moves */ + WIRE_DUAL_OPEN_PSBT_CHANGED = 7107, + /* master->dualopend: fail this channel open */ + WIRE_DUAL_OPEN_FAIL = 7003, + /* dualopend->master: we failed to negotiation channel */ + WIRE_DUAL_OPEN_FAILED = 7004, + /* master -> dualopend: do you have a memleak? */ + WIRE_DUAL_OPEN_DEV_MEMLEAK = 7033, + WIRE_DUAL_OPEN_DEV_MEMLEAK_REPLY = 7133, +}; + +const char *dualopend_wire_name(int e); + +/** + * Determine whether a given message type is defined as a message. + * + * Returns true if the message type is part of the message definitions we have + * generated parsers for, false if it is a custom message that cannot be + * handled internally. + */ +bool dualopend_wire_is_defined(u16 type); + + +/* WIRE: DUAL_OPEN_INIT */ +u8 *towire_dual_open_init(const tal_t *ctx, const struct chainparams *chainparams, const struct feature_set *our_feature_set, const u8 *their_init_features, const struct channel_config *our_config, u32 max_to_self_delay, struct amount_msat min_effective_htlc_capacity_msat, const struct per_peer_state *pps, const struct basepoints *our_basepoints, const struct pubkey *our_funding_pubkey, u32 minimum_depth, u32 min_feerate, u32 max_feerate, bool option_anchor_outputs, const u8 *msg); +bool fromwire_dual_open_init(const tal_t *ctx, const void *p, const struct chainparams **chainparams, struct feature_set **our_feature_set, u8 **their_init_features, struct channel_config *our_config, u32 *max_to_self_delay, struct amount_msat *min_effective_htlc_capacity_msat, struct per_peer_state **pps, struct basepoints *our_basepoints, struct pubkey *our_funding_pubkey, u32 *minimum_depth, u32 *min_feerate, u32 *max_feerate, bool *option_anchor_outputs, u8 **msg); + +/* WIRE: DUAL_OPEN_GOT_OFFER */ +/* dualopend->master: they offered channel */ +u8 *towire_dual_open_got_offer(const tal_t *ctx, struct amount_sat opener_funding, struct amount_sat dust_limit_satoshis, struct amount_msat max_htlc_value_in_flight_msat, struct amount_msat htlc_minimum_msat, u32 feerate_per_kw_funding, u32 feerate_per_kw, u16 to_self_delay, u16 max_accepted_htlcs, u8 channel_flags, u32 locktime, const u8 *shutdown_scriptpubkey); +bool fromwire_dual_open_got_offer(const tal_t *ctx, const void *p, struct amount_sat *opener_funding, struct amount_sat *dust_limit_satoshis, struct amount_msat *max_htlc_value_in_flight_msat, struct amount_msat *htlc_minimum_msat, u32 *feerate_per_kw_funding, u32 *feerate_per_kw, u16 *to_self_delay, u16 *max_accepted_htlcs, u8 *channel_flags, u32 *locktime, u8 **shutdown_scriptpubkey); + +/* WIRE: DUAL_OPEN_GOT_OFFER_REPLY */ +/* master->dualopend: reply back with our first funding info/contribs */ +u8 *towire_dual_open_got_offer_reply(const tal_t *ctx, struct amount_sat accepter_funding, const struct wally_psbt *psbt, const u8 *our_shutdown_scriptpubkey); +bool fromwire_dual_open_got_offer_reply(const tal_t *ctx, const void *p, struct amount_sat *accepter_funding, struct wally_psbt **psbt, u8 **our_shutdown_scriptpubkey); + +/* WIRE: DUAL_OPEN_COMMIT_RCVD */ +/* dualopend->master: ready to commit channel open to database and */ +/* get some signatures for the funding_tx. */ +u8 *towire_dual_open_commit_rcvd(const tal_t *ctx, const struct channel_config *their_config, const struct bitcoin_tx *remote_first_commit, const struct penalty_base *pbase, const struct bitcoin_signature *first_commit_sig, const struct wally_psbt *psbt, const struct channel_id *channel_id, const struct per_peer_state *pps, const struct pubkey *revocation_basepoint, const struct pubkey *payment_basepoint, const struct pubkey *htlc_basepoint, const struct pubkey *delayed_payment_basepoint, const struct pubkey *their_per_commit_point, const struct pubkey *remote_fundingkey, const struct bitcoin_txid *funding_txid, u16 funding_txout, struct amount_sat funding_satoshis, struct amount_sat our_funding_sats, u8 channel_flags, u32 feerate_per_kw, const u8 *commitment_msg, struct amount_sat our_channel_reserve_satoshis, const u8 *local_shutdown_scriptpubkey, const u8 *remote_shutdown_scriptpubkey); +bool fromwire_dual_open_commit_rcvd(const tal_t *ctx, const void *p, struct channel_config *their_config, struct bitcoin_tx **remote_first_commit, struct penalty_base **pbase, struct bitcoin_signature *first_commit_sig, struct wally_psbt **psbt, struct channel_id *channel_id, struct per_peer_state **pps, struct pubkey *revocation_basepoint, struct pubkey *payment_basepoint, struct pubkey *htlc_basepoint, struct pubkey *delayed_payment_basepoint, struct pubkey *their_per_commit_point, struct pubkey *remote_fundingkey, struct bitcoin_txid *funding_txid, u16 *funding_txout, struct amount_sat *funding_satoshis, struct amount_sat *our_funding_sats, u8 *channel_flags, u32 *feerate_per_kw, u8 **commitment_msg, struct amount_sat *our_channel_reserve_satoshis, u8 **local_shutdown_scriptpubkey, u8 **remote_shutdown_scriptpubkey); + +/* WIRE: DUAL_OPEN_PSBT_CHANGED */ +/* dualopend->master: peer updated the psbt */ +/* master->dualopend: response from hook when asking for next moves */ +u8 *towire_dual_open_psbt_changed(const tal_t *ctx, const struct channel_id *channel_id, const struct wally_psbt *psbt); +bool fromwire_dual_open_psbt_changed(const tal_t *ctx, const void *p, struct channel_id *channel_id, struct wally_psbt **psbt); + +/* WIRE: DUAL_OPEN_FAIL */ +/* master->dualopend: fail this channel open */ +u8 *towire_dual_open_fail(const tal_t *ctx, const wirestring *reason); +bool fromwire_dual_open_fail(const tal_t *ctx, const void *p, wirestring **reason); + +/* WIRE: DUAL_OPEN_FAILED */ +/* dualopend->master: we failed to negotiation channel */ +u8 *towire_dual_open_failed(const tal_t *ctx, const wirestring *reason); +bool fromwire_dual_open_failed(const tal_t *ctx, const void *p, wirestring **reason); + +/* WIRE: DUAL_OPEN_DEV_MEMLEAK */ +/* master -> dualopend: do you have a memleak? */ +u8 *towire_dual_open_dev_memleak(const tal_t *ctx); +bool fromwire_dual_open_dev_memleak(const void *p); + +/* WIRE: DUAL_OPEN_DEV_MEMLEAK_REPLY */ +u8 *towire_dual_open_dev_memleak_reply(const tal_t *ctx, bool leak); +bool fromwire_dual_open_dev_memleak_reply(const void *p, bool *leak); + + +#endif /* LIGHTNING_OPENINGD_DUALOPEND_WIREGEN_H */ +// SHA256STAMP:1c4ae8e18ade1c0dcf975d8573e82c491a52fcda35d193b7302abda8d35dee8e