diff --git a/lightningd/channel_control.c b/lightningd/channel_control.c index b743b70ba..c4bd758c3 100644 --- a/lightningd/channel_control.c +++ b/lightningd/channel_control.c @@ -631,7 +631,11 @@ bool channel_tell_depth(struct lightningd *ld, return true; } - // FIXME: pass to dualopend here! +#if EXPERIMENTAL_FEATURES + dualopen_tell_depth(channel->owner, channel, depth); + // FIXME: lockin complete? + return true; +#endif /* EXPERIMENTAL_FEATURES */ } else if (channel->state != CHANNELD_AWAITING_LOCKIN && channel->state != CHANNELD_NORMAL) { /* If not awaiting lockin/announce, it doesn't diff --git a/lightningd/dual_open_control.c b/lightningd/dual_open_control.c index 646a49731..460d2f329 100644 --- a/lightningd/dual_open_control.c +++ b/lightningd/dual_open_control.c @@ -26,7 +26,6 @@ #include #include #include -#include #include #include #include @@ -34,12 +33,11 @@ struct commit_rcvd { struct channel *channel; struct channel_id cid; - struct per_peer_state *pps; - u8 *commitment_msg; struct uncommitted_channel *uc; }; static void handle_signed_psbt(struct lightningd *ld, + struct subd *dualopend, const struct wally_psbt *psbt, struct commit_rcvd *rcvd) { @@ -51,10 +49,9 @@ static void handle_signed_psbt(struct lightningd *ld, channel_watch_funding(ld, rcvd->channel); - peer_start_channeld(rcvd->channel, - rcvd->pps, - rcvd->commitment_msg, - false); + /* Send peer our signatures */ + subd_send_msg(dualopend, + take(towire_dualopend_send_tx_sigs(NULL, psbt))); } /* ~Map of the Territory~ @@ -534,6 +531,7 @@ openchannel2_signed_deserialize(struct openchannel2_psbt_payload *payload, if (payload->psbt) tal_free(payload->psbt); + payload->psbt = tal_steal(payload, psbt); return true; } @@ -541,9 +539,19 @@ openchannel2_signed_deserialize(struct openchannel2_psbt_payload *payload, static void openchannel2_sign_hook_cb(struct openchannel2_psbt_payload *payload STEALS) { - /* Free payload regardless of what happens next */ + /* Whatever happens, we free the payload */ tal_steal(tmpctx, payload); + if (!payload->dualopend) { + log_broken(payload->ld->log, "dualopend daemon died" + " before signed PSBT returned"); + channel_internal_error(payload->rcvd->channel, "daemon died"); + return; + } + tal_del_destructor2(payload->dualopend, + openchannel2_psbt_remove_dualopend, + payload); + /* Finalize it, if not already. It shouldn't work entirely */ psbt_finalize(payload->psbt); @@ -552,7 +560,8 @@ openchannel2_sign_hook_cb(struct openchannel2_psbt_payload *payload STEALS) "for their inputs %s", type_to_string(tmpctx, struct wally_psbt, payload->psbt)); - handle_signed_psbt(payload->ld, payload->psbt, payload->rcvd); + handle_signed_psbt(payload->ld, payload->dualopend, + payload->psbt, payload->rcvd); } REGISTER_PLUGIN_HOOK(openchannel2, @@ -620,7 +629,7 @@ wallet_commit_channel(struct lightningd *ld, channel = new_channel(uc->peer, uc->dbid, NULL, /* No shachain yet */ - CHANNELD_AWAITING_LOCKIN, + DUALOPEND_OPEN_INIT, opener, uc->log, take(uc->transient_billboard), @@ -1040,6 +1049,110 @@ static void send_funding_tx(struct channel *channel, sendfunding_done, cs); } +static void handle_peer_tx_sigs_sent(struct subd *dualopend, + const int *fds, + const u8 *msg) +{ + struct channel *channel = dualopend->channel; + const struct wally_tx *wtx; + + if (!fromwire_dualopend_tx_sigs_sent(msg)) { + channel_internal_error(channel, + "bad WIRE_DUALOPEND_TX_SIGS_SENT %s", + tal_hex(tmpctx, msg)); + return; + } + + if (psbt_finalize(cast_const(struct wally_psbt *, channel->psbt))) { + wtx = psbt_final_tx(NULL, channel->psbt); + if (!wtx) { + channel_internal_error(channel, + "Unable to extract final tx" + " from PSBT %s", + type_to_string(tmpctx, + struct wally_psbt, + channel->psbt)); + return; + } + + send_funding_tx(channel, take(wtx)); + + channel_set_state(channel, DUALOPEND_OPEN_INIT, + DUALOPEND_AWAITING_LOCKIN, + REASON_UNKNOWN, + "Sigs exchanged, waiting for lock-in"); + } +} + +static void handle_channel_locked(struct subd *dualopend, + const int *fds, + const u8 *msg) +{ + struct channel *channel = dualopend->channel; + struct pubkey remote_per_commit; + struct per_peer_state *pps; + + if (!fromwire_dualopend_channel_locked(tmpctx, msg, &pps, + &remote_per_commit)) { + log_broken(dualopend->log, + "bad WIRE_DUALOPEND_CHANNEL_LOCKED %s", + tal_hex(msg, msg)); + close(fds[0]); + close(fds[1]); + close(fds[2]); + goto cleanup; + } + per_peer_state_set_fds_arr(pps, fds); + + /* Updates channel with the next per-commit point etc */ + if (!channel_on_funding_locked(channel, &remote_per_commit)) + goto cleanup; + + assert(channel->scid); + assert(channel->remote_funding_locked); + + if (channel->state != DUALOPEND_AWAITING_LOCKIN) { + log_debug(channel->log, "Lockin complete, but state %s", + channel_state_name(channel)); + } else { + channel_set_state(channel, + DUALOPEND_AWAITING_LOCKIN, + CHANNELD_NORMAL, + REASON_UNKNOWN, + "Lockin complete"); + channel_record_open(channel); + } + + /* FIXME: LND sigs/update_fee msgs? */ + peer_start_channeld(channel, pps, NULL, false); + return; + +cleanup: + subd_release_channel(dualopend, channel); +} + +void dualopen_tell_depth(struct subd *dualopend, + struct channel *channel, + u32 depth) +{ + const u8 *msg; + u32 to_go; + + if (depth < channel->minimum_depth) + to_go = channel->minimum_depth - depth; + else + to_go = 0; + + /* Are we there yet? */ + if (to_go == 0) { + assert(channel->scid); + msg = towire_dualopend_depth_reached(NULL, depth); + subd_send_msg(dualopend, take(msg)); + } + + // FIXME: update billboard. needs to_go counter! +} + static void accepter_psbt_changed(struct subd *dualopend, const u8 *msg) { @@ -1118,8 +1231,8 @@ static void accepter_got_offer(struct subd *dualopend, plugin_hook_call_openchannel2(dualopend->ld, payload); } -static void peer_tx_sigs_msg(struct subd *dualopend, - const u8 *msg) +static void handle_peer_tx_sigs_msg(struct subd *dualopend, + const u8 *msg) { struct wally_psbt *psbt; const struct wally_tx *wtx; @@ -1150,8 +1263,21 @@ static void peer_tx_sigs_msg(struct subd *dualopend, if (psbt_finalize(cast_const(struct wally_psbt *, channel->psbt))) { wtx = psbt_final_tx(NULL, channel->psbt); - if (wtx) - send_funding_tx(channel, take(wtx)); + if (!wtx) { + channel_internal_error(channel, + "Unable to extract final tx" + " from PSBT %s", + type_to_string(tmpctx, + struct wally_psbt, + channel->psbt)); + return; + } + send_funding_tx(channel, take(wtx)); + + channel_set_state(channel, DUALOPEND_OPEN_INIT, + DUALOPEND_AWAITING_LOCKIN, + REASON_UNKNOWN, + "Sigs exchanged, waiting for lock-in"); } wallet_channel_save(ld->wallet, channel); @@ -1169,7 +1295,6 @@ json_openchannel_signed(struct command *cmd, const jsmntok_t *params) { struct wally_psbt *psbt; - const struct wally_tx *wtx; struct uncommitted_channel *uc; struct channel_id *cid; struct channel *channel; @@ -1237,12 +1362,6 @@ json_openchannel_signed(struct command *cmd, subd_send_msg(channel->owner, take(towire_dualopend_send_tx_sigs(NULL, channel->psbt))); - if (psbt_finalize(cast_const(struct wally_psbt *, channel->psbt))) { - wtx = psbt_final_tx(NULL, channel->psbt); - if (wtx) - send_funding_tx(channel, take(wtx)); - } - channel->openchannel_signed_cmd = tal_steal(channel, cmd); return command_still_pending(cmd); } @@ -1491,7 +1610,15 @@ static unsigned int dual_opend_msg(struct subd *dualopend, uc, fds, msg); return 0; case WIRE_DUALOPEND_FUNDING_SIGS: - peer_tx_sigs_msg(dualopend, msg); + handle_peer_tx_sigs_msg(dualopend, msg); + return 0; + case WIRE_DUALOPEND_TX_SIGS_SENT: + handle_peer_tx_sigs_sent(dualopend, fds, msg); + return 0; + case WIRE_DUALOPEND_CHANNEL_LOCKED: + if (tal_count(fds) != 3) + return 3; + handle_channel_locked(dualopend, fds, msg); return 0; case WIRE_DUALOPEND_FAILED: case WIRE_DUALOPEND_DEV_MEMLEAK_REPLY: @@ -1503,6 +1630,7 @@ static unsigned int dual_opend_msg(struct subd *dualopend, case WIRE_DUALOPEND_FAIL: case WIRE_DUALOPEND_PSBT_UPDATED: case WIRE_DUALOPEND_SEND_TX_SIGS: + case WIRE_DUALOPEND_DEPTH_REACHED: case WIRE_DUALOPEND_DEV_MEMLEAK: break; } diff --git a/lightningd/dual_open_control.h b/lightningd/dual_open_control.h index 072f273d8..32e4d65cc 100644 --- a/lightningd/dual_open_control.h +++ b/lightningd/dual_open_control.h @@ -2,10 +2,15 @@ #define LIGHTNING_LIGHTNINGD_DUAL_OPEN_CONTROL_H #include "config.h" +#include struct per_peer_state; void peer_start_dualopend(struct peer *peer, struct per_peer_state *pps, const u8 *send_msg); + +void dualopen_tell_depth(struct subd *dualopend, + struct channel *channel, + u32 depth); #endif /* LIGHTNING_LIGHTNINGD_DUAL_OPEN_CONTROL_H */ diff --git a/openingd/dualopend.c b/openingd/dualopend.c index 80c90441d..0f632c358 100644 --- a/openingd/dualopend.c +++ b/openingd/dualopend.c @@ -144,10 +144,17 @@ struct state { /* Track how many of each tx collab msg we receive */ u16 tx_msg_count[NUM_TX_MSGS]; + /* Tally of which sides are locked, or not */ bool funding_locked[NUM_SIDES]; /* PSBT of the funding tx */ struct wally_psbt *psbt; + + /* Peer sends this to us in the funding_locked msg */ + struct pubkey remote_per_commit; + + /* Are we shutting this channel down? */ + bool shutting_down; }; /* psbt_changeset_get_next - Get next message to send @@ -750,7 +757,7 @@ static void handle_tx_sigs(struct state *state, const u8 *msg) take(towire_dualopend_funding_sigs(NULL, state->psbt))); } -static u8 *handle_send_tx_sigs(struct state *state, const u8 *msg) +static void handle_send_tx_sigs(struct state *state, const u8 *msg) { struct wally_psbt *psbt; struct bitcoin_txid txid; @@ -774,10 +781,21 @@ static u8 *handle_send_tx_sigs(struct state *state, const u8 *msg) if (wally_psbt_combine(state->psbt, psbt) != WALLY_OK) { tal_wally_end(tal_free(state->psbt)); status_failed(STATUS_FAIL_INTERNAL_ERROR, - "Unable to combine PSBTs"); + "Unable to combine PSBTs. received %s\n" + "local %s", + type_to_string(tmpctx, struct wally_psbt, + psbt), + type_to_string(tmpctx, struct wally_psbt, + state->psbt)); } - tal_wally_end(tal_steal(state, state->psbt)); - return psbt_to_tx_sigs_msg(tmpctx, state, psbt); + tal_wally_end(state->psbt); + + /* Send our sigs to peer */ + msg = psbt_to_tx_sigs_msg(tmpctx, state, state->psbt); + sync_crypto_write(state->pps, take(msg)); + + /* Notify lightningd that we've sent sigs */ + wire_sync_write(REQ_FD, take(towire_dualopend_tx_sigs_sent(NULL))); } static struct wally_psbt * @@ -2151,6 +2169,81 @@ static void opener_start(struct state *state, u8 *msg) wire_sync_write(REQ_FD, take(msg)); } +static u8 *handle_funding_locked(struct state *state, u8 *msg) +{ + struct channel_id cid; + + if (!fromwire_funding_locked(msg, &cid, + &state->remote_per_commit)) + peer_failed(state->pps, &state->channel_id, + "Bad funding_locked %s", tal_hex(msg, msg)); + + if (!channel_id_eq(&cid, &state->channel_id)) + peer_failed(state->pps, &state->channel_id, + "funding_locked ids don't match: " + "expected %s, got %s", + type_to_string(msg, struct channel_id, + &state->channel_id), + type_to_string(msg, struct channel_id, &cid)); + + state->funding_locked[REMOTE] = true; + // FIXME: update billboard! + if (state->funding_locked[LOCAL]) + return towire_dualopend_channel_locked(state, state->pps, + &state->remote_per_commit); + + return NULL; +} + +static void hsm_per_commitment_point(u64 index, struct pubkey *point) +{ + struct secret *s; + const u8 *msg; + + msg = towire_hsmd_get_per_commitment_point(NULL, index); + wire_sync_write(HSM_FD, take(msg)); + msg = wire_sync_read(tmpctx, HSM_FD); + + if (!fromwire_hsmd_get_per_commitment_point_reply(tmpctx, msg, + point, &s)) + status_failed(STATUS_FAIL_HSM_IO, + "Bad per_commitment_point reply %s", + tal_hex(tmpctx, msg)); +} + +static u8 *handle_funding_depth(struct state *state, u8 *msg) +{ + u32 depth; + struct pubkey next_local_per_commit; + + if (!fromwire_dualopend_depth_reached(msg, &depth)) + master_badmsg(WIRE_DUALOPEND_DEPTH_REACHED, msg); + + /* Too late, shutting down already */ + if (state->shutting_down) + return NULL; + + /* We check this before we arrive here, but for sanity */ + assert(state->minimum_depth <= depth); + + /* Figure out the next local commit */ + hsm_per_commitment_point(1, &next_local_per_commit); + + msg = towire_funding_locked(NULL, + &state->channel_id, + &next_local_per_commit); + sync_crypto_write(state->pps, take(msg)); + + state->funding_locked[LOCAL] = true; + // FIXME: update billboard! + if (state->funding_locked[REMOTE]) + return towire_dualopend_channel_locked(state, + state->pps, + &state->remote_per_commit); + + return NULL; +} + /*~ 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) @@ -2209,7 +2302,11 @@ static u8 *handle_master_in(struct state *state) case WIRE_DUALOPEND_SEND_TX_SIGS: handle_send_tx_sigs(state, msg); return NULL; + case WIRE_DUALOPEND_DEPTH_REACHED: + return handle_funding_depth(state, msg); /* mostly handled inline */ + case WIRE_DUALOPEND_TX_SIGS_SENT: + case WIRE_DUALOPEND_CHANNEL_LOCKED: case WIRE_DUALOPEND_INIT: case WIRE_DUALOPEND_FUNDING_SIGS: case WIRE_DUALOPEND_DEV_MEMLEAK_REPLY: @@ -2256,6 +2353,8 @@ static u8 *handle_peer_in(struct state *state) } else if (t == WIRE_TX_SIGNATURES) { handle_tx_sigs(state, msg); return NULL; + } else if (t == WIRE_FUNDING_LOCKED) { + return handle_funding_locked(state, msg); } #if DEVELOPER @@ -2338,6 +2437,9 @@ int main(int argc, char *argv[]) * handle_peer_gossip_or_error compares this. */ memset(&state->channel_id, 0, sizeof(state->channel_id)); state->channel = NULL; + state->funding_locked[LOCAL] = state->funding_locked[REMOTE] = false; + state->shutting_down = false; + for (size_t i = 0; i < NUM_TX_MSGS; i++) state->tx_msg_count[i] = 0; diff --git a/openingd/dualopend_wire.csv b/openingd/dualopend_wire.csv index aaf660ab6..7a0f9c713 100644 --- a/openingd/dualopend_wire.csv +++ b/openingd/dualopend_wire.csv @@ -118,6 +118,18 @@ msgdata,dualopend_funding_sigs,signed_psbt,wally_psbt, msgtype,dualopend_send_tx_sigs,7011 msgdata,dualopend_send_tx_sigs,signed_psbt,wally_psbt, +# dualopend->master tx sigs transmitted to peer +msgtype,dualopend_tx_sigs_sent,7012 + +# dualopend->master this channel has been locked +msgtype,dualopend_channel_locked,7019 +msgdata,dualopend_channel_locked,pps,per_peer_state, +msgdata,dualopend_channel_locked,remote_per_commit,pubkey, + +# master->dualopend funding reached depth; tell peer +msgtype,dualopend_depth_reached,7020 +msgdata,dualopend_depth_reached,depth,u32, + # master -> dualopend: do you have a memleak? msgtype,dualopend_dev_memleak,7033 diff --git a/openingd/dualopend_wiregen.c b/openingd/dualopend_wiregen.c index 49861b41d..4520d2c7a 100644 --- a/openingd/dualopend_wiregen.c +++ b/openingd/dualopend_wiregen.c @@ -31,6 +31,9 @@ const char *dualopend_wire_name(int e) case WIRE_DUALOPEND_OPENER_INIT: return "WIRE_DUALOPEND_OPENER_INIT"; case WIRE_DUALOPEND_FUNDING_SIGS: return "WIRE_DUALOPEND_FUNDING_SIGS"; case WIRE_DUALOPEND_SEND_TX_SIGS: return "WIRE_DUALOPEND_SEND_TX_SIGS"; + case WIRE_DUALOPEND_TX_SIGS_SENT: return "WIRE_DUALOPEND_TX_SIGS_SENT"; + case WIRE_DUALOPEND_CHANNEL_LOCKED: return "WIRE_DUALOPEND_CHANNEL_LOCKED"; + case WIRE_DUALOPEND_DEPTH_REACHED: return "WIRE_DUALOPEND_DEPTH_REACHED"; case WIRE_DUALOPEND_DEV_MEMLEAK: return "WIRE_DUALOPEND_DEV_MEMLEAK"; case WIRE_DUALOPEND_DEV_MEMLEAK_REPLY: return "WIRE_DUALOPEND_DEV_MEMLEAK_REPLY"; } @@ -53,6 +56,9 @@ bool dualopend_wire_is_defined(u16 type) case WIRE_DUALOPEND_OPENER_INIT:; case WIRE_DUALOPEND_FUNDING_SIGS:; case WIRE_DUALOPEND_SEND_TX_SIGS:; + case WIRE_DUALOPEND_TX_SIGS_SENT:; + case WIRE_DUALOPEND_CHANNEL_LOCKED:; + case WIRE_DUALOPEND_DEPTH_REACHED:; case WIRE_DUALOPEND_DEV_MEMLEAK:; case WIRE_DUALOPEND_DEV_MEMLEAK_REPLY:; return true; @@ -481,6 +487,72 @@ bool fromwire_dualopend_send_tx_sigs(const tal_t *ctx, const void *p, struct wal return cursor != NULL; } +/* WIRE: DUALOPEND_TX_SIGS_SENT */ +/* dualopend->master tx sigs transmitted to peer */ +u8 *towire_dualopend_tx_sigs_sent(const tal_t *ctx) +{ + u8 *p = tal_arr(ctx, u8, 0); + + towire_u16(&p, WIRE_DUALOPEND_TX_SIGS_SENT); + + return memcheck(p, tal_count(p)); +} +bool fromwire_dualopend_tx_sigs_sent(const void *p) +{ + const u8 *cursor = p; + size_t plen = tal_count(p); + + if (fromwire_u16(&cursor, &plen) != WIRE_DUALOPEND_TX_SIGS_SENT) + return false; + return cursor != NULL; +} + +/* WIRE: DUALOPEND_CHANNEL_LOCKED */ +/* dualopend->master this channel has been locked */ +u8 *towire_dualopend_channel_locked(const tal_t *ctx, const struct per_peer_state *pps, const struct pubkey *remote_per_commit) +{ + u8 *p = tal_arr(ctx, u8, 0); + + towire_u16(&p, WIRE_DUALOPEND_CHANNEL_LOCKED); + towire_per_peer_state(&p, pps); + towire_pubkey(&p, remote_per_commit); + + return memcheck(p, tal_count(p)); +} +bool fromwire_dualopend_channel_locked(const tal_t *ctx, const void *p, struct per_peer_state **pps, struct pubkey *remote_per_commit) +{ + const u8 *cursor = p; + size_t plen = tal_count(p); + + if (fromwire_u16(&cursor, &plen) != WIRE_DUALOPEND_CHANNEL_LOCKED) + return false; + *pps = fromwire_per_peer_state(ctx, &cursor, &plen); + fromwire_pubkey(&cursor, &plen, remote_per_commit); + return cursor != NULL; +} + +/* WIRE: DUALOPEND_DEPTH_REACHED */ +/* master->dualopend funding reached depth; tell peer */ +u8 *towire_dualopend_depth_reached(const tal_t *ctx, u32 depth) +{ + u8 *p = tal_arr(ctx, u8, 0); + + towire_u16(&p, WIRE_DUALOPEND_DEPTH_REACHED); + towire_u32(&p, depth); + + return memcheck(p, tal_count(p)); +} +bool fromwire_dualopend_depth_reached(const void *p, u32 *depth) +{ + const u8 *cursor = p; + size_t plen = tal_count(p); + + if (fromwire_u16(&cursor, &plen) != WIRE_DUALOPEND_DEPTH_REACHED) + return false; + *depth = fromwire_u32(&cursor, &plen); + return cursor != NULL; +} + /* WIRE: DUALOPEND_DEV_MEMLEAK */ /* master -> dualopend: do you have a memleak? */ u8 *towire_dualopend_dev_memleak(const tal_t *ctx) @@ -521,4 +593,4 @@ bool fromwire_dualopend_dev_memleak_reply(const void *p, bool *leak) *leak = fromwire_bool(&cursor, &plen); return cursor != NULL; } -// SHA256STAMP:b209a8683f1e9cbdc9f64302b70b86b2d66ac8fa917e3f1e482fda64f92c20a2 +// SHA256STAMP:420b9d30d0ecd89f962dee16c410c54f9ac7852dd5ab02c05730ab07ebc6bece diff --git a/openingd/dualopend_wiregen.h b/openingd/dualopend_wiregen.h index c19bd708c..cb6cbd17a 100644 --- a/openingd/dualopend_wiregen.h +++ b/openingd/dualopend_wiregen.h @@ -40,6 +40,12 @@ enum dualopend_wire { WIRE_DUALOPEND_FUNDING_SIGS = 7010, /* master->dualopend send our tx_sigs to peer */ WIRE_DUALOPEND_SEND_TX_SIGS = 7011, + /* dualopend->master tx sigs transmitted to peer */ + WIRE_DUALOPEND_TX_SIGS_SENT = 7012, + /* dualopend->master this channel has been locked */ + WIRE_DUALOPEND_CHANNEL_LOCKED = 7019, + /* master->dualopend funding reached depth; tell peer */ + WIRE_DUALOPEND_DEPTH_REACHED = 7020, /* master -> dualopend: do you have a memleak? */ WIRE_DUALOPEND_DEV_MEMLEAK = 7033, WIRE_DUALOPEND_DEV_MEMLEAK_REPLY = 7133, @@ -112,6 +118,21 @@ bool fromwire_dualopend_funding_sigs(const tal_t *ctx, const void *p, struct wal u8 *towire_dualopend_send_tx_sigs(const tal_t *ctx, const struct wally_psbt *signed_psbt); bool fromwire_dualopend_send_tx_sigs(const tal_t *ctx, const void *p, struct wally_psbt **signed_psbt); +/* WIRE: DUALOPEND_TX_SIGS_SENT */ +/* dualopend->master tx sigs transmitted to peer */ +u8 *towire_dualopend_tx_sigs_sent(const tal_t *ctx); +bool fromwire_dualopend_tx_sigs_sent(const void *p); + +/* WIRE: DUALOPEND_CHANNEL_LOCKED */ +/* dualopend->master this channel has been locked */ +u8 *towire_dualopend_channel_locked(const tal_t *ctx, const struct per_peer_state *pps, const struct pubkey *remote_per_commit); +bool fromwire_dualopend_channel_locked(const tal_t *ctx, const void *p, struct per_peer_state **pps, struct pubkey *remote_per_commit); + +/* WIRE: DUALOPEND_DEPTH_REACHED */ +/* master->dualopend funding reached depth; tell peer */ +u8 *towire_dualopend_depth_reached(const tal_t *ctx, u32 depth); +bool fromwire_dualopend_depth_reached(const void *p, u32 *depth); + /* WIRE: DUALOPEND_DEV_MEMLEAK */ /* master -> dualopend: do you have a memleak? */ u8 *towire_dualopend_dev_memleak(const tal_t *ctx); @@ -123,4 +144,4 @@ bool fromwire_dualopend_dev_memleak_reply(const void *p, bool *leak); #endif /* LIGHTNING_OPENINGD_DUALOPEND_WIREGEN_H */ -// SHA256STAMP:b209a8683f1e9cbdc9f64302b70b86b2d66ac8fa917e3f1e482fda64f92c20a2 +// SHA256STAMP:420b9d30d0ecd89f962dee16c410c54f9ac7852dd5ab02c05730ab07ebc6bece