|
@ -22,6 +22,7 @@ |
|
|
#include <lightningd/channel_control.h> |
|
|
#include <lightningd/channel_control.h> |
|
|
#include <lightningd/dual_open_control.h> |
|
|
#include <lightningd/dual_open_control.h> |
|
|
#include <lightningd/hsm_control.h> |
|
|
#include <lightningd/hsm_control.h> |
|
|
|
|
|
#include <lightningd/notification.h> |
|
|
#include <lightningd/opening_common.h> |
|
|
#include <lightningd/opening_common.h> |
|
|
#include <lightningd/peer_control.h> |
|
|
#include <lightningd/peer_control.h> |
|
|
#include <lightningd/plugin_hook.h> |
|
|
#include <lightningd/plugin_hook.h> |
|
@ -1032,6 +1033,231 @@ static void accepter_got_offer(struct subd *dualopend, |
|
|
plugin_hook_call_openchannel2(dualopend->ld, payload); |
|
|
plugin_hook_call_openchannel2(dualopend->ld, payload); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
struct channel_send { |
|
|
|
|
|
const struct wally_tx *wtx; |
|
|
|
|
|
struct channel *channel; |
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
static void sendfunding_done(struct bitcoind *bitcoind UNUSED, |
|
|
|
|
|
bool success, const char *msg, |
|
|
|
|
|
struct channel_send *cs) |
|
|
|
|
|
{ |
|
|
|
|
|
struct lightningd *ld = cs->channel->peer->ld; |
|
|
|
|
|
struct channel *channel = cs->channel; |
|
|
|
|
|
const struct wally_tx *wtx = cs->wtx; |
|
|
|
|
|
struct json_stream *response; |
|
|
|
|
|
struct bitcoin_txid txid; |
|
|
|
|
|
struct open_command *oc; |
|
|
|
|
|
struct amount_sat unused; |
|
|
|
|
|
int num_utxos; |
|
|
|
|
|
|
|
|
|
|
|
oc = find_open_command(ld, channel); |
|
|
|
|
|
if (!oc && channel->opener == LOCAL) { |
|
|
|
|
|
log_broken(channel->log, |
|
|
|
|
|
"No outstanding command for channel %s," |
|
|
|
|
|
" funding sent was success? %d", |
|
|
|
|
|
type_to_string(tmpctx, struct channel_id, |
|
|
|
|
|
&channel->cid), |
|
|
|
|
|
success); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (!success) { |
|
|
|
|
|
if (oc) |
|
|
|
|
|
was_pending(command_fail(oc->cmd, |
|
|
|
|
|
FUNDING_BROADCAST_FAIL, |
|
|
|
|
|
"Error broadcasting funding " |
|
|
|
|
|
"tx: %s. Unsent tx discarded " |
|
|
|
|
|
"%s.", |
|
|
|
|
|
msg, |
|
|
|
|
|
type_to_string(tmpctx, |
|
|
|
|
|
struct wally_tx, |
|
|
|
|
|
wtx))); |
|
|
|
|
|
log_unusual(channel->log, |
|
|
|
|
|
"Error broadcasting funding " |
|
|
|
|
|
"tx: %s. Unsent tx discarded " |
|
|
|
|
|
"%s.", |
|
|
|
|
|
msg, |
|
|
|
|
|
type_to_string(tmpctx, struct wally_tx, wtx)); |
|
|
|
|
|
tal_free(cs); |
|
|
|
|
|
return; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/* This might have spent UTXOs from our wallet */ |
|
|
|
|
|
num_utxos = wallet_extract_owned_outputs(ld->wallet, |
|
|
|
|
|
wtx, NULL, |
|
|
|
|
|
&unused); |
|
|
|
|
|
if (num_utxos) { |
|
|
|
|
|
wallet_transaction_add(ld->wallet, wtx, 0, 0); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (oc) { |
|
|
|
|
|
response = json_stream_success(oc->cmd); |
|
|
|
|
|
wally_txid(wtx, &txid); |
|
|
|
|
|
json_add_hex_talarr(response, "tx", linearize_wtx(tmpctx, wtx)); |
|
|
|
|
|
json_add_txid(response, "txid", &txid); |
|
|
|
|
|
json_add_string(response, "channel_id", |
|
|
|
|
|
type_to_string(tmpctx, struct channel_id, |
|
|
|
|
|
&channel->cid)); |
|
|
|
|
|
was_pending(command_success(oc->cmd, response)); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
tal_free(cs); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static void send_funding_tx(struct channel *channel, |
|
|
|
|
|
const struct wally_tx *wtx TAKES) |
|
|
|
|
|
{ |
|
|
|
|
|
struct lightningd *ld = channel->peer->ld; |
|
|
|
|
|
struct channel_send *cs; |
|
|
|
|
|
|
|
|
|
|
|
cs = tal(channel, struct channel_send); |
|
|
|
|
|
cs->channel = channel; |
|
|
|
|
|
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, |
|
|
|
|
|
"Broadcasting funding tx for channel %s. %s", |
|
|
|
|
|
type_to_string(tmpctx, struct channel_id, &channel->cid), |
|
|
|
|
|
type_to_string(tmpctx, struct wally_tx, cs->wtx)); |
|
|
|
|
|
|
|
|
|
|
|
bitcoind_sendrawtx(ld->topology->bitcoind, |
|
|
|
|
|
tal_hex(tmpctx, linearize_wtx(tmpctx, cs->wtx)), |
|
|
|
|
|
sendfunding_done, cs); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static void peer_tx_sigs_msg(struct subd *dualopend, |
|
|
|
|
|
const u8 *msg) |
|
|
|
|
|
{ |
|
|
|
|
|
struct wally_psbt *psbt; |
|
|
|
|
|
const struct wally_tx *wtx; |
|
|
|
|
|
struct lightningd *ld = dualopend->ld; |
|
|
|
|
|
struct channel *channel = dualopend->channel; |
|
|
|
|
|
|
|
|
|
|
|
if (!fromwire_dualopend_funding_sigs(tmpctx, msg, &psbt)) { |
|
|
|
|
|
channel_internal_error(channel, |
|
|
|
|
|
"bad dualopend_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)); |
|
|
|
|
|
return; |
|
|
|
|
|
} |
|
|
|
|
|
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); |
|
|
|
|
|
|
|
|
|
|
|
/* Send notification with peer's signed PSBT */ |
|
|
|
|
|
notify_openchannel_peer_sigs(ld, &channel->cid, |
|
|
|
|
|
channel->psbt); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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_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)); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
return command_still_pending(cmd); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static struct command_result *json_open_channel_update(struct command *cmd, |
|
|
static struct command_result *json_open_channel_update(struct command *cmd, |
|
|
const char *buffer, |
|
|
const char *buffer, |
|
|
const jsmntok_t *obj UNNEEDED, |
|
|
const jsmntok_t *obj UNNEEDED, |
|
@ -1238,6 +1464,8 @@ static unsigned int dual_opend_msg(struct subd *dualopend, |
|
|
const u8 *msg, const int *fds) |
|
|
const u8 *msg, const int *fds) |
|
|
{ |
|
|
{ |
|
|
enum dualopend_wire t = fromwire_peektype(msg); |
|
|
enum dualopend_wire t = fromwire_peektype(msg); |
|
|
|
|
|
|
|
|
|
|
|
/* FIXME: might be channel? */ |
|
|
struct uncommitted_channel *uc = dualopend->channel; |
|
|
struct uncommitted_channel *uc = dualopend->channel; |
|
|
|
|
|
|
|
|
switch (t) { |
|
|
switch (t) { |
|
@ -1274,6 +1502,9 @@ static unsigned int dual_opend_msg(struct subd *dualopend, |
|
|
accepter_commit_received(dualopend, |
|
|
accepter_commit_received(dualopend, |
|
|
uc, fds, msg); |
|
|
uc, fds, msg); |
|
|
return 0; |
|
|
return 0; |
|
|
|
|
|
case WIRE_DUALOPEND_FUNDING_SIGS: |
|
|
|
|
|
peer_tx_sigs_msg(dualopend, msg); |
|
|
|
|
|
return 0; |
|
|
case WIRE_DUALOPEND_FAILED: |
|
|
case WIRE_DUALOPEND_FAILED: |
|
|
case WIRE_DUALOPEND_DEV_MEMLEAK_REPLY: |
|
|
case WIRE_DUALOPEND_DEV_MEMLEAK_REPLY: |
|
|
|
|
|
|
|
@ -1283,6 +1514,7 @@ static unsigned int dual_opend_msg(struct subd *dualopend, |
|
|
case WIRE_DUALOPEND_GOT_OFFER_REPLY: |
|
|
case WIRE_DUALOPEND_GOT_OFFER_REPLY: |
|
|
case WIRE_DUALOPEND_FAIL: |
|
|
case WIRE_DUALOPEND_FAIL: |
|
|
case WIRE_DUALOPEND_PSBT_UPDATED: |
|
|
case WIRE_DUALOPEND_PSBT_UPDATED: |
|
|
|
|
|
case WIRE_DUALOPEND_SEND_TX_SIGS: |
|
|
case WIRE_DUALOPEND_DEV_MEMLEAK: |
|
|
case WIRE_DUALOPEND_DEV_MEMLEAK: |
|
|
break; |
|
|
break; |
|
|
} |
|
|
} |
|
@ -1323,9 +1555,17 @@ static const struct json_command open_channel_update_command = { |
|
|
"If {commitments_secured} is true, next call should be to openchannel_signed" |
|
|
"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, |
|
|
|
|
|
"Send our {signed_psbt}'s tx sigs for {channel_id}." |
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
#if EXPERIMENTAL_FEATURES |
|
|
#if EXPERIMENTAL_FEATURES |
|
|
AUTODATA(json_command, &open_channel_init_command); |
|
|
AUTODATA(json_command, &open_channel_init_command); |
|
|
AUTODATA(json_command, &open_channel_update_command); |
|
|
AUTODATA(json_command, &open_channel_update_command); |
|
|
|
|
|
AUTODATA(json_command, &open_channel_signed_command); |
|
|
#endif /* EXPERIMENTAL_FEATURES */ |
|
|
#endif /* EXPERIMENTAL_FEATURES */ |
|
|
|
|
|
|
|
|
void peer_start_dualopend(struct peer *peer, |
|
|
void peer_start_dualopend(struct peer *peer, |
|
|