mirror of
https://github.com/aljazceru/lightning.git
synced 2025-12-19 23:24:27 +01:00
dual-fund: rework where we send our tx-sigs message, allow peers in
Prior to this patch update, we expected a client to call `openchannel_signed` before checking for peer's tx-sigs messages on the wire. When moving to a 'multifundchannel' approach, we'll need to be able to collect sigs from our peers before sending our tx_sigs message. There's no strict ordering on when tx-sigs messages are sent/received, so this is fine. To do this, we go ahead and start up channeld as soon as commitment_sigs are secured, so that we process incoming tx-sigs from our peers as soon as we get them.
This commit is contained in:
@@ -151,10 +151,6 @@ struct channel {
|
||||
|
||||
/* PSBT, for v2 channels. Saved until it's sent */
|
||||
struct wally_psbt *psbt;
|
||||
|
||||
/* Stashed pps, saved until channeld is started.
|
||||
* Needed only for v2 channel open flow */
|
||||
struct per_peer_state *pps;
|
||||
};
|
||||
|
||||
struct channel *new_channel(struct peer *peer, u64 dbid,
|
||||
|
||||
@@ -11,7 +11,9 @@
|
||||
#include <common/jsonrpc_errors.h>
|
||||
#include <common/memleak.h>
|
||||
#include <common/per_peer_state.h>
|
||||
#include <common/psbt_open.h>
|
||||
#include <common/timeout.h>
|
||||
#include <common/tx_roles.h>
|
||||
#include <common/utils.h>
|
||||
#include <common/wire_error.h>
|
||||
#include <errno.h>
|
||||
@@ -316,7 +318,7 @@ static void handle_error_channel(struct channel *channel,
|
||||
}
|
||||
|
||||
struct channel_send {
|
||||
struct wally_tx *wtx;
|
||||
const struct wally_tx *wtx;
|
||||
struct channel *channel;
|
||||
};
|
||||
|
||||
@@ -326,7 +328,7 @@ static void sendfunding_done(struct bitcoind *bitcoind UNUSED,
|
||||
{
|
||||
struct lightningd *ld = cs->channel->peer->ld;
|
||||
struct channel *channel = cs->channel;
|
||||
struct wally_tx *wtx = cs->wtx;
|
||||
const struct wally_tx *wtx = cs->wtx;
|
||||
struct json_stream *response;
|
||||
struct bitcoin_txid txid;
|
||||
struct open_command *oc;
|
||||
@@ -386,20 +388,22 @@ static void sendfunding_done(struct bitcoind *bitcoind UNUSED,
|
||||
tal_free(cs);
|
||||
}
|
||||
|
||||
static void handle_funding_tx(struct channel *channel,
|
||||
const u8 *msg)
|
||||
static void send_funding_tx(struct channel *channel,
|
||||
const struct wally_tx *wtx TAKES)
|
||||
{
|
||||
struct channel_send *cs;
|
||||
struct lightningd *ld = channel->peer->ld;
|
||||
struct channel_send *cs;
|
||||
|
||||
cs = tal(channel, struct channel_send);
|
||||
cs->channel = channel;
|
||||
|
||||
if (!fromwire_channeld_funding_tx(tmpctx, msg, &cs->wtx)) {
|
||||
channel_internal_error(channel,
|
||||
"bad channeld_funding_tx: %s",
|
||||
tal_hex(tmpctx, msg));
|
||||
return;
|
||||
if (taken(wtx))
|
||||
cs->wtx = tal_steal(cs, wtx);
|
||||
else {
|
||||
tal_wally_start();
|
||||
wally_tx_clone_alloc(wtx, 0,
|
||||
cast_const2(struct wally_tx **,
|
||||
&cs->wtx));
|
||||
tal_wally_end(tal_steal(cs, cs->wtx));
|
||||
}
|
||||
|
||||
log_debug(channel->log,
|
||||
@@ -412,6 +416,41 @@ static void handle_funding_tx(struct channel *channel,
|
||||
sendfunding_done, cs);
|
||||
}
|
||||
|
||||
static void peer_tx_sigs_msg(struct channel *channel, const u8 *msg)
|
||||
{
|
||||
struct wally_psbt *psbt;
|
||||
const struct wally_tx *wtx;
|
||||
struct lightningd *ld = channel->peer->ld;
|
||||
|
||||
if (!fromwire_channeld_funding_sigs(tmpctx, msg, &psbt)) {
|
||||
channel_internal_error(channel,
|
||||
"bad channeld_funding_sigs: %s",
|
||||
tal_hex(tmpctx, msg));
|
||||
return;
|
||||
}
|
||||
|
||||
tal_wally_start();
|
||||
if (wally_psbt_combine(channel->psbt, psbt) != WALLY_OK) {
|
||||
channel_internal_error(channel,
|
||||
"Unable to combine PSBTs: %s, %s",
|
||||
type_to_string(tmpctx,
|
||||
struct wally_psbt,
|
||||
channel->psbt),
|
||||
type_to_string(tmpctx,
|
||||
struct wally_psbt,
|
||||
psbt));
|
||||
}
|
||||
tal_wally_end(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));
|
||||
}
|
||||
|
||||
wallet_channel_save(ld->wallet, channel);
|
||||
}
|
||||
|
||||
void forget_channel(struct channel *channel, const char *why)
|
||||
{
|
||||
channel->error = towire_errorfmt(channel, &channel->cid, "%s", why);
|
||||
@@ -436,6 +475,9 @@ static unsigned channel_msg(struct subd *sd, const u8 *msg, const int *fds)
|
||||
case WIRE_CHANNELD_GOT_COMMITSIG:
|
||||
peer_got_commitsig(sd->channel, msg);
|
||||
break;
|
||||
case WIRE_CHANNELD_FUNDING_SIGS:
|
||||
peer_tx_sigs_msg(sd->channel, msg);
|
||||
break;
|
||||
case WIRE_CHANNELD_GOT_REVOKE:
|
||||
peer_got_revoke(sd->channel, msg);
|
||||
break;
|
||||
@@ -460,9 +502,6 @@ static unsigned channel_msg(struct subd *sd, const u8 *msg, const int *fds)
|
||||
case WIRE_CHANNELD_SEND_ERROR_REPLY:
|
||||
handle_error_channel(sd->channel, msg);
|
||||
break;
|
||||
case WIRE_CHANNELD_FUNDING_TX:
|
||||
handle_funding_tx(sd->channel, msg);
|
||||
break;
|
||||
#if EXPERIMENTAL_FEATURES
|
||||
case WIRE_GOT_ONIONMSG_TO_US:
|
||||
handle_onionmsg_to_us(sd->channel, msg);
|
||||
@@ -476,6 +515,7 @@ static unsigned channel_msg(struct subd *sd, const u8 *msg, const int *fds)
|
||||
#endif
|
||||
/* And we never get these from channeld. */
|
||||
case WIRE_CHANNELD_INIT:
|
||||
case WIRE_CHANNELD_SEND_TX_SIGS:
|
||||
case WIRE_CHANNELD_FUNDING_DEPTH:
|
||||
case WIRE_CHANNELD_OFFER_HTLC:
|
||||
case WIRE_CHANNELD_FULFILL_HTLC:
|
||||
@@ -931,6 +971,97 @@ struct command_result *cancel_channel_before_broadcast(struct command *cmd,
|
||||
return command_still_pending(cmd);
|
||||
}
|
||||
|
||||
static struct command_result *json_open_channel_signed(struct command *cmd,
|
||||
const char *buffer,
|
||||
const jsmntok_t *obj UNNEEDED,
|
||||
const jsmntok_t *params)
|
||||
{
|
||||
struct wally_psbt *psbt;
|
||||
const struct wally_tx *wtx;
|
||||
struct uncommitted_channel *uc;
|
||||
struct channel_id *cid;
|
||||
struct channel *channel;
|
||||
struct bitcoin_txid txid;
|
||||
|
||||
if (!param(cmd, buffer, params,
|
||||
p_req("channel_id", param_channel_id, &cid),
|
||||
p_req("signed_psbt", param_psbt, &psbt),
|
||||
NULL))
|
||||
return command_param_failed();
|
||||
|
||||
channel = channel_by_cid(cmd->ld, cid, &uc);
|
||||
if (uc)
|
||||
return command_fail(cmd, LIGHTNINGD,
|
||||
"Commitments for this channel not "
|
||||
"yet secured, see `openchannl_update`");
|
||||
if (!channel)
|
||||
return command_fail(cmd, FUNDING_UNKNOWN_CHANNEL,
|
||||
"Unknown channel");
|
||||
if (channel->psbt && psbt_is_finalized(channel->psbt))
|
||||
return command_fail(cmd, LIGHTNINGD,
|
||||
"Already have a finalized PSBT for "
|
||||
"this channel");
|
||||
|
||||
/* Verify that the psbt's txid matches that of the
|
||||
* funding txid for this channel */
|
||||
psbt_txid(NULL, psbt, &txid, NULL);
|
||||
if (!bitcoin_txid_eq(&txid, &channel->funding_txid))
|
||||
return command_fail(cmd, FUNDING_PSBT_INVALID,
|
||||
"Txid for passed in PSBT does not match"
|
||||
" funding txid for channel. Expected %s, "
|
||||
"received %s",
|
||||
type_to_string(tmpctx, struct bitcoin_txid,
|
||||
&channel->funding_txid),
|
||||
type_to_string(tmpctx, struct bitcoin_txid,
|
||||
&txid));
|
||||
|
||||
/* Go ahead and try to finalize things, or what we can */
|
||||
psbt_finalize(psbt);
|
||||
|
||||
/* Check that all of *our* outputs are finalized */
|
||||
if (!psbt_side_finalized(psbt, TX_INITIATOR))
|
||||
return command_fail(cmd, FUNDING_PSBT_INVALID,
|
||||
"Local PSBT input(s) not finalized");
|
||||
|
||||
/* Now that we've got the signed PSBT, save it */
|
||||
tal_wally_start();
|
||||
if (wally_psbt_combine(cast_const(struct wally_psbt *,
|
||||
channel->psbt),
|
||||
psbt) != WALLY_OK) {
|
||||
tal_wally_end(tal_free(channel->psbt));
|
||||
return command_fail(cmd, FUNDING_PSBT_INVALID,
|
||||
"Failed adding sigs");
|
||||
}
|
||||
tal_wally_end(tal_steal(channel, channel->psbt));
|
||||
|
||||
wallet_channel_save(cmd->ld->wallet, channel);
|
||||
channel_watch_funding(cmd->ld, channel);
|
||||
|
||||
/* Return when the transaction is broadcast */
|
||||
register_open_command(cmd->ld, cmd, channel);
|
||||
|
||||
/* Send our tx_sigs to the peer */
|
||||
subd_send_msg(channel->owner,
|
||||
take(towire_channeld_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));
|
||||
}
|
||||
|
||||
return command_still_pending(cmd);
|
||||
}
|
||||
|
||||
static const struct json_command open_channel_signed_command = {
|
||||
"openchannel_signed",
|
||||
"channels",
|
||||
json_open_channel_signed,
|
||||
"Send our {signed_psbt}'s tx sigs for {channel_id}."
|
||||
};
|
||||
AUTODATA(json_command, &open_channel_signed_command);
|
||||
|
||||
#if DEVELOPER
|
||||
static struct command_result *json_dev_feerate(struct command *cmd,
|
||||
const char *buffer,
|
||||
|
||||
@@ -879,7 +879,6 @@ static void opener_commit_received(struct subd *dualopend,
|
||||
goto failed;
|
||||
}
|
||||
|
||||
channel->pps = tal_steal(channel, pps);
|
||||
if (pbase)
|
||||
wallet_penalty_base_add(ld->wallet, channel->dbid, pbase);
|
||||
|
||||
@@ -890,14 +889,18 @@ static void opener_commit_received(struct subd *dualopend,
|
||||
json_add_bool(response, "commitments_secured", true);
|
||||
was_pending(command_success(uc->fc->cmd, response));
|
||||
|
||||
subd_release_channel(dualopend, uc);
|
||||
uc->open_daemon = NULL;
|
||||
tal_free(uc);
|
||||
return;
|
||||
/* Now that we've got the final PSBT, save it */
|
||||
channel->psbt = tal_steal(channel, psbt);
|
||||
wallet_channel_save(uc->fc->cmd->ld->wallet, channel);
|
||||
|
||||
peer_start_channeld(channel, pps,
|
||||
NULL, psbt, false);
|
||||
goto cleanup;
|
||||
|
||||
failed:
|
||||
was_pending(command_fail(uc->fc->cmd, LIGHTNINGD,
|
||||
"%s", err_reason));
|
||||
cleanup:
|
||||
subd_release_channel(dualopend, uc);
|
||||
uc->open_daemon = NULL;
|
||||
tal_free(uc);
|
||||
@@ -968,71 +971,6 @@ static void accepter_got_offer(struct subd *dualopend,
|
||||
plugin_hook_call_openchannel2(dualopend->ld, payload);
|
||||
}
|
||||
|
||||
static struct command_result *json_open_channel_signed(struct command *cmd,
|
||||
const char *buffer,
|
||||
const jsmntok_t *obj UNNEEDED,
|
||||
const jsmntok_t *params)
|
||||
{
|
||||
struct wally_psbt *psbt;
|
||||
struct channel_id *cid;
|
||||
struct channel *channel;
|
||||
struct bitcoin_txid txid;
|
||||
|
||||
if (!param(cmd, buffer, params,
|
||||
p_req("channel_id", param_channel_id, &cid),
|
||||
p_req("signed_psbt", param_psbt, &psbt),
|
||||
NULL))
|
||||
return command_param_failed();
|
||||
|
||||
channel = channel_by_cid(cmd->ld, cid, NULL);
|
||||
if (!channel)
|
||||
return command_fail(cmd, FUNDING_UNKNOWN_CHANNEL,
|
||||
"Unknown channel");
|
||||
if (!channel->pps)
|
||||
return command_fail(cmd, LIGHTNINGD,
|
||||
"Missing per-peer-state for channel, "
|
||||
"are you in the right state to call "
|
||||
"this method?");
|
||||
if (channel->psbt)
|
||||
return command_fail(cmd, LIGHTNINGD,
|
||||
"Already have a finalized PSBT for "
|
||||
"this channel");
|
||||
|
||||
/* Verify that the psbt's txid matches that of the
|
||||
* funding txid for this channel */
|
||||
psbt_txid(NULL, psbt, &txid, NULL);
|
||||
if (!bitcoin_txid_eq(&txid, &channel->funding_txid))
|
||||
return command_fail(cmd, FUNDING_PSBT_INVALID,
|
||||
"Txid for passed in PSBT does not match"
|
||||
" funding txid for channel. Expected %s, "
|
||||
"received %s",
|
||||
type_to_string(tmpctx, struct bitcoin_txid,
|
||||
&channel->funding_txid),
|
||||
type_to_string(tmpctx, struct bitcoin_txid,
|
||||
&txid));
|
||||
|
||||
/* Go ahead and try to finalize things, or what we can */
|
||||
psbt_finalize(psbt);
|
||||
|
||||
/* Check that all of *our* outputs are finalized */
|
||||
if (!psbt_side_finalized(psbt, TX_INITIATOR))
|
||||
return command_fail(cmd, FUNDING_PSBT_INVALID,
|
||||
"Local PSBT input(s) not finalized");
|
||||
|
||||
/* Now that we've got the signed PSBT, save it */
|
||||
channel->psbt = tal_steal(channel, psbt);
|
||||
wallet_channel_save(cmd->ld->wallet, channel);
|
||||
|
||||
channel_watch_funding(cmd->ld, channel);
|
||||
|
||||
register_open_command(cmd->ld, cmd, channel);
|
||||
peer_start_channeld(channel, channel->pps,
|
||||
NULL, psbt, false);
|
||||
channel->pps = tal_free(channel->pps);
|
||||
|
||||
return command_still_pending(cmd);
|
||||
}
|
||||
|
||||
static struct command_result *json_open_channel_update(struct command *cmd,
|
||||
const char *buffer,
|
||||
const jsmntok_t *obj UNNEEDED,
|
||||
@@ -1086,7 +1024,6 @@ static struct command_result *json_open_channel_update(struct command *cmd,
|
||||
return command_still_pending(cmd);
|
||||
}
|
||||
|
||||
|
||||
static struct command_result *json_open_channel_init(struct command *cmd,
|
||||
const char *buffer,
|
||||
const jsmntok_t *obj UNNEEDED,
|
||||
@@ -1325,17 +1262,9 @@ static const struct json_command open_channel_update_command = {
|
||||
"If {commitments_secured} is true, next call should be to openchannel_signed"
|
||||
};
|
||||
|
||||
static const struct json_command open_channel_signed_command = {
|
||||
"openchannel_signed",
|
||||
"channels",
|
||||
json_open_channel_signed,
|
||||
"Finish opening {channel_id} with {signed_psbt}. "
|
||||
};
|
||||
|
||||
#if EXPERIMENTAL_FEATURES
|
||||
AUTODATA(json_command, &open_channel_init_command);
|
||||
AUTODATA(json_command, &open_channel_update_command);
|
||||
AUTODATA(json_command, &open_channel_signed_command);
|
||||
#endif /* EXPERIMENTAL_FEATURES */
|
||||
|
||||
void peer_start_dualopend(struct peer *peer,
|
||||
|
||||
Reference in New Issue
Block a user