mirror of
https://github.com/ElementsProject/lightning.git
synced 2025-02-20 13:54:36 +01:00
dualfund: opener, openchannel_init command (1/3)
There are 3 commands for opening a channel with dualfunding. `openchannel_init` is the first of these. It initializes the open-channel dialog, and stops once we've run out of updates (input/outputs) to send to the peer.
This commit is contained in:
parent
2618ef10c3
commit
06c41a0547
10 changed files with 629 additions and 8 deletions
|
@ -52,6 +52,8 @@ static const errcode_t FUNDING_PEER_NOT_CONNECTED = 305;
|
|||
static const errcode_t FUNDING_UNKNOWN_PEER = 306;
|
||||
static const errcode_t FUNDING_NOTHING_TO_CANCEL = 307;
|
||||
static const errcode_t FUNDING_CANCEL_NOT_SAFE = 308;
|
||||
static const errcode_t FUNDING_PSBT_INVALID = 309;
|
||||
static const errcode_t FUNDING_V2_NOT_SUPPORTED = 310;
|
||||
|
||||
/* `connect` errors */
|
||||
static const errcode_t CONNECT_NO_KNOWN_ADDRESS = 400;
|
||||
|
|
|
@ -40,6 +40,7 @@ MANPAGES := doc/lightning-cli.1 \
|
|||
doc/lightning-multifundchannel.7 \
|
||||
doc/lightning-multiwithdraw.7 \
|
||||
doc/lightning-newaddr.7 \
|
||||
doc/lightning-openchannel_init.7 \
|
||||
doc/lightning-pay.7 \
|
||||
doc/lightning-plugin.7 \
|
||||
doc/lightning-reserveinputs.7 \
|
||||
|
|
|
@ -68,6 +68,7 @@ c-lightning Documentation
|
|||
lightning-multifundchannel <lightning-multifundchannel.7.md>
|
||||
lightning-multiwithdraw <lightning-multiwithdraw.7.md>
|
||||
lightning-newaddr <lightning-newaddr.7.md>
|
||||
lightning-openchannel_init <lightning-openchannel_init.7.md>
|
||||
lightning-pay <lightning-pay.7.md>
|
||||
lightning-ping <lightning-ping.7.md>
|
||||
lightning-plugin <lightning-plugin.7.md>
|
||||
|
|
97
doc/lightning-openchannel_init.7
generated
Normal file
97
doc/lightning-openchannel_init.7
generated
Normal file
|
@ -0,0 +1,97 @@
|
|||
.TH "LIGHTNING-OPENCHANNEL_INIT" "7" "" "" "lightning-openchannel_init"
|
||||
.SH NAME
|
||||
lightning-openchannel_init - Command to initiate a channel to a peer
|
||||
.SH SYNOPSIS
|
||||
|
||||
\fBopenchannel_init\fR \fIid\fR \fIamount\fR \fIinitalpsbt\fR [\fIcommitment_feerate\fR] [\fIfunding_feerate\fR] [\fIannounce\fR] [\fIclose_to\fR]
|
||||
|
||||
.SH DESCRIPTION
|
||||
|
||||
\fBopenchannel_init\fR is a low level RPC command which initiates a channel
|
||||
open with a specified peer\. It uses the openchannel protocol
|
||||
which allows for interactive transaction construction\.
|
||||
|
||||
|
||||
\fIid\fR is the node id of the remote peer\.
|
||||
|
||||
|
||||
\fIamount\fR is the satoshi value that we will contribute to the channel\.
|
||||
This value will be \fIadded\fR to the provided PSBT in the output which is
|
||||
encumbered by the 2-of-2 script for this channel\.
|
||||
|
||||
|
||||
\fIinitialpsbt\fR is the funded, incomplete PSBT that specifies the UTXOs and
|
||||
change output for our channel contribution\. It can be updated,
|
||||
see \fBopenchannel_update\fR; \fIinitialpsbt\fR must have at least one input to
|
||||
provide a PoDLE to the peer\. Must have the Non-Witness UTXO
|
||||
(PSBT_IN_NON_WITNESS_UTXO) set for every input\. An error
|
||||
(code 309) will be returned if this requirement is not met\.
|
||||
|
||||
|
||||
\fIcommitment_feerate\fR is an optional field\. Sets the feerate for
|
||||
commitment transactions: see \fBfundchannel\fR\.
|
||||
|
||||
|
||||
\fIfunding_feerate\fR is an optional field\. Sets the feerate for the
|
||||
funding transaction\. Defaults to 'opening' feerate\.
|
||||
|
||||
|
||||
\fIannounce\fR is an optional field\. Whether or not to announce this channel\.
|
||||
|
||||
|
||||
\fIclose_to\fR is a Bitcoin address to which the channel funds should be
|
||||
sent on close\. Only valid if both peers have negotiated
|
||||
\fBoption_upfront_shutdown_script\fR\.
|
||||
|
||||
.SH RETURN VALUE
|
||||
|
||||
On success, returns the \fIchannel_id\fR for this channel; an updated
|
||||
incomplete \fIinitialpsbt\fR for this funding transaction; and the flag
|
||||
\fIcommitments_secured\fR, which indiciates the completeness of the
|
||||
passed back \fIpsbt\fR\. (Will always be false)\.
|
||||
|
||||
|
||||
If the peer does not support \fBoption_dual_fund\fR, this command
|
||||
will return an error\.
|
||||
|
||||
|
||||
On error the returned object will contain \fBcode\fR and \fBmessage\fR properties,
|
||||
with \fBcode\fR being one of the following:
|
||||
|
||||
.RS
|
||||
.IP \[bu]
|
||||
-32602: If the given parameters are wrong\.
|
||||
.IP \[bu]
|
||||
-1: Catchall nonspecific error\.
|
||||
.IP \[bu]
|
||||
300: The amount exceeded the maximum configured funding amount\.
|
||||
.IP \[bu]
|
||||
301: The provided PSBT cannot afford the funding amount\.
|
||||
.IP \[bu]
|
||||
304: Still syncing with bitcoin network
|
||||
.IP \[bu]
|
||||
305: Peer is not connected\.
|
||||
.IP \[bu]
|
||||
306: Unknown peer id\.
|
||||
.IP \[bu]
|
||||
309: PSBT missing required fields
|
||||
.IP \[bu]
|
||||
310: v2 channel open protocol not supported by peer
|
||||
|
||||
.RE
|
||||
.SH SEE ALSO
|
||||
|
||||
lightning-openchannel_\fBupdate\fR(7), lightning-openchannel_\fBsigned\fR(7),
|
||||
lightning-fundchannel_\fBstart\fR(7), lightning-fundchannel_\fBcomplete\fR(7),
|
||||
\fBlightning-fundchannel\fR(7), \fBlightning-fundpsbt\fR(7), \fBlightning-utxopsbt\fR(7),
|
||||
\fBlightning-multifundchannel\fR(7)
|
||||
|
||||
.SH AUTHOR
|
||||
|
||||
@niftynei \fI<niftynei@gmail.com\fR> is mainly responsible\.
|
||||
|
||||
.SH RESOURCES
|
||||
|
||||
Main web site: \fIhttps://github.com/ElementsProject/lightning\fR
|
||||
|
||||
\" SHA256STAMP:a06dc67176c3c9863e4fc3048de7d0172eb79d091479415eb639335b3d096860
|
82
doc/lightning-openchannel_init.7.md
Normal file
82
doc/lightning-openchannel_init.7.md
Normal file
|
@ -0,0 +1,82 @@
|
|||
lightning-openchannel\_init -- Command to initiate a channel to a peer
|
||||
=====================================================================
|
||||
|
||||
SYNOPSIS
|
||||
--------
|
||||
|
||||
**openchannel_init** *id* *amount* *initalpsbt* \[*commitment_feerate*\] \[*funding_feerate*\] \[*announce*\] \[*close_to*\]
|
||||
|
||||
DESCRIPTION
|
||||
-----------
|
||||
|
||||
`openchannel_init` is a low level RPC command which initiates a channel
|
||||
open with a specified peer. It uses the openchannel protocol
|
||||
which allows for interactive transaction construction.
|
||||
|
||||
*id* is the node id of the remote peer.
|
||||
|
||||
*amount* is the satoshi value that we will contribute to the channel.
|
||||
This value will be _added_ to the provided PSBT in the output which is
|
||||
encumbered by the 2-of-2 script for this channel.
|
||||
|
||||
*initialpsbt* is the funded, incomplete PSBT that specifies the UTXOs and
|
||||
change output for our channel contribution. It can be updated,
|
||||
see `openchannel_update`; *initialpsbt* must have at least one input to
|
||||
provide a PoDLE to the peer. Must have the Non-Witness UTXO
|
||||
(PSBT\_IN\_NON\_WITNESS\_UTXO) set for every input. An error
|
||||
(code 309) will be returned if this requirement is not met.
|
||||
|
||||
*commitment_feerate* is an optional field. Sets the feerate for
|
||||
commitment transactions: see **fundchannel**.
|
||||
|
||||
*funding_feerate* is an optional field. Sets the feerate for the
|
||||
funding transaction. Defaults to 'opening' feerate.
|
||||
|
||||
*announce* is an optional field. Whether or not to announce this channel.
|
||||
|
||||
*close_to* is a Bitcoin address to which the channel funds should be
|
||||
sent on close. Only valid if both peers have negotiated
|
||||
`option_upfront_shutdown_script`.
|
||||
|
||||
|
||||
RETURN VALUE
|
||||
------------
|
||||
|
||||
On success, returns the *channel_id* for this channel; an updated
|
||||
incomplete *initialpsbt* for this funding transaction; and the flag
|
||||
*commitments_secured*, which indiciates the completeness of the
|
||||
passed back *psbt*. (Will always be false).
|
||||
|
||||
If the peer does not support `option_dual_fund`, this command
|
||||
will return an error.
|
||||
|
||||
On error the returned object will contain `code` and `message` properties,
|
||||
with `code` being one of the following:
|
||||
|
||||
- -32602: If the given parameters are wrong.
|
||||
- -1: Catchall nonspecific error.
|
||||
- 300: The amount exceeded the maximum configured funding amount.
|
||||
- 301: The provided PSBT cannot afford the funding amount.
|
||||
- 304: Still syncing with bitcoin network
|
||||
- 305: Peer is not connected.
|
||||
- 306: Unknown peer id.
|
||||
- 309: PSBT missing required fields
|
||||
- 310: v2 channel open protocol not supported by peer
|
||||
|
||||
SEE ALSO
|
||||
--------
|
||||
|
||||
lightning-openchannel\_update(7), lightning-openchannel\_signed(7),
|
||||
lightning-fundchannel\_start(7), lightning-fundchannel\_complete(7),
|
||||
lightning-fundchannel(7), lightning-fundpsbt(7), lightning-utxopsbt(7),
|
||||
lightning-multifundchannel(7)
|
||||
|
||||
AUTHOR
|
||||
------
|
||||
|
||||
@niftynei <<niftynei@gmail.com>> is mainly responsible.
|
||||
|
||||
RESOURCES
|
||||
---------
|
||||
|
||||
Main web site: <https://github.com/ElementsProject/lightning>
|
|
@ -741,6 +741,35 @@ wallet_commit_channel(struct lightningd *ld,
|
|||
return channel;
|
||||
}
|
||||
|
||||
static void opener_psbt_changed(struct subd *dualopend,
|
||||
struct uncommitted_channel *uc,
|
||||
const u8 *msg)
|
||||
{
|
||||
struct channel_id cid;
|
||||
struct wally_psbt *psbt;
|
||||
struct json_stream *response;
|
||||
struct command *cmd = uc->fc->cmd;
|
||||
|
||||
if (!fromwire_dual_open_psbt_changed(cmd, msg,
|
||||
&cid,
|
||||
&psbt)) {
|
||||
log_broken(dualopend->log,
|
||||
"Malformed dual_open_psbt_changed %s",
|
||||
tal_hex(tmpctx, msg));
|
||||
tal_free(dualopend);
|
||||
return;
|
||||
}
|
||||
|
||||
response = json_stream_success(cmd);
|
||||
json_add_string(response, "channel_id",
|
||||
type_to_string(tmpctx, struct channel_id, &cid));
|
||||
json_add_psbt(response, "psbt", psbt);
|
||||
json_add_bool(response, "commitments_secured", false);
|
||||
|
||||
uc->fc->inflight = true;
|
||||
was_pending(command_success(cmd, response));
|
||||
}
|
||||
|
||||
static void accepter_commit_received(struct subd *dualopend,
|
||||
struct uncommitted_channel *uc,
|
||||
const int *fds,
|
||||
|
@ -923,6 +952,155 @@ static void accepter_got_offer(struct subd *dualopend,
|
|||
plugin_hook_call_openchannel2(dualopend->ld, payload);
|
||||
}
|
||||
|
||||
static struct command_result *json_open_channel_init(struct command *cmd,
|
||||
const char *buffer,
|
||||
const jsmntok_t *obj UNNEEDED,
|
||||
const jsmntok_t *params)
|
||||
{
|
||||
struct funding_channel *fc = tal(cmd, struct funding_channel);
|
||||
struct node_id *id;
|
||||
struct peer *peer;
|
||||
struct channel *channel;
|
||||
bool *announce_channel;
|
||||
u32 *feerate_per_kw_funding;
|
||||
u32 *feerate_per_kw;
|
||||
struct amount_sat *amount, psbt_val;
|
||||
struct wally_psbt *psbt;
|
||||
|
||||
u8 *msg = NULL;
|
||||
|
||||
fc->cmd = cmd;
|
||||
fc->cancels = tal_arr(fc, struct command *, 0);
|
||||
fc->uc = NULL;
|
||||
fc->inflight = false;
|
||||
|
||||
if (!param(fc->cmd, buffer, params,
|
||||
p_req("id", param_node_id, &id),
|
||||
p_req("amount", param_sat, &amount),
|
||||
p_req("initialpsbt", param_psbt, &psbt),
|
||||
p_opt("commitment_feerate", param_feerate, &feerate_per_kw),
|
||||
p_opt("funding_feerate", param_feerate, &feerate_per_kw_funding),
|
||||
p_opt_def("announce", param_bool, &announce_channel, true),
|
||||
p_opt("close_to", param_bitcoin_address, &fc->our_upfront_shutdown_script),
|
||||
NULL))
|
||||
return command_param_failed();
|
||||
|
||||
psbt_val = AMOUNT_SAT(0);
|
||||
for (size_t i = 0; i < psbt->num_inputs; i++) {
|
||||
struct amount_sat in_amt = psbt_input_get_amount(psbt, i);
|
||||
if (!amount_sat_add(&psbt_val, psbt_val, in_amt))
|
||||
return command_fail(cmd, JSONRPC2_INVALID_PARAMS,
|
||||
"Overflow in adding PSBT input values. %s",
|
||||
type_to_string(tmpctx, struct wally_psbt, psbt));
|
||||
}
|
||||
|
||||
/* If they don't pass in at least enough in the PSBT to cover
|
||||
* their amount, nope */
|
||||
if (!amount_sat_greater(psbt_val, *amount))
|
||||
return command_fail(cmd, FUND_CANNOT_AFFORD,
|
||||
"Provided PSBT cannot afford funding of "
|
||||
"amount %s. %s",
|
||||
type_to_string(tmpctx, struct amount_sat, amount),
|
||||
type_to_string(tmpctx, struct wally_psbt, psbt));
|
||||
|
||||
fc->funding = *amount;
|
||||
if (!feerate_per_kw) {
|
||||
feerate_per_kw = tal(cmd, u32);
|
||||
/* Anchors exist, set the commitment feerate to min */
|
||||
*feerate_per_kw = feerate_min(cmd->ld, NULL);
|
||||
}
|
||||
if (!feerate_per_kw_funding) {
|
||||
feerate_per_kw_funding = tal(cmd, u32);
|
||||
*feerate_per_kw_funding = opening_feerate(cmd->ld->topology);
|
||||
if (!*feerate_per_kw_funding)
|
||||
return command_fail(cmd, LIGHTNINGD,
|
||||
"`funding_feerate` not specified and fee "
|
||||
"estimation failed");
|
||||
}
|
||||
|
||||
if (!topology_synced(cmd->ld->topology)) {
|
||||
return command_fail(cmd, FUNDING_STILL_SYNCING_BITCOIN,
|
||||
"Still syncing with bitcoin network");
|
||||
}
|
||||
|
||||
peer = peer_by_id(cmd->ld, id);
|
||||
if (!peer) {
|
||||
return command_fail(cmd, FUNDING_UNKNOWN_PEER, "Unknown peer");
|
||||
}
|
||||
|
||||
channel = peer_active_channel(peer);
|
||||
if (channel) {
|
||||
return command_fail(cmd, LIGHTNINGD, "Peer already %s",
|
||||
channel_state_name(channel));
|
||||
}
|
||||
|
||||
if (!peer->uncommitted_channel) {
|
||||
return command_fail(cmd, FUNDING_PEER_NOT_CONNECTED,
|
||||
"Peer not connected");
|
||||
}
|
||||
|
||||
if (peer->uncommitted_channel->fc) {
|
||||
return command_fail(cmd, LIGHTNINGD, "Already funding channel");
|
||||
}
|
||||
|
||||
#if EXPERIMENTAL_FEATURES
|
||||
if (!feature_negotiated(cmd->ld->our_features,
|
||||
peer->their_features,
|
||||
OPT_DUAL_FUND)) {
|
||||
return command_fail(cmd, FUNDING_V2_NOT_SUPPORTED,
|
||||
"v2 openchannel not supported "
|
||||
"by peer");
|
||||
}
|
||||
#endif /* EXPERIMENTAL_FEATURES */
|
||||
|
||||
/* BOLT #2:
|
||||
* - if both nodes advertised `option_support_large_channel`:
|
||||
* - MAY set `funding_satoshis` greater than or equal to 2^24 satoshi.
|
||||
* - otherwise:
|
||||
* - MUST set `funding_satoshis` to less than 2^24 satoshi.
|
||||
*/
|
||||
if (!feature_negotiated(cmd->ld->our_features,
|
||||
peer->their_features, OPT_LARGE_CHANNELS)
|
||||
&& amount_sat_greater(*amount, chainparams->max_funding))
|
||||
return command_fail(cmd, FUND_MAX_EXCEEDED,
|
||||
"Amount exceeded %s",
|
||||
type_to_string(tmpctx, struct amount_sat,
|
||||
&chainparams->max_funding));
|
||||
|
||||
fc->channel_flags = OUR_CHANNEL_FLAGS;
|
||||
if (!*announce_channel) {
|
||||
fc->channel_flags &= ~CHANNEL_FLAGS_ANNOUNCE_CHANNEL;
|
||||
log_info(peer->ld->log, "Will open private channel with node %s",
|
||||
type_to_string(fc, struct node_id, id));
|
||||
}
|
||||
|
||||
/* Add serials to any input that's missing them */
|
||||
psbt_add_serials(psbt, LOCAL);
|
||||
if (!psbt_has_required_fields(psbt))
|
||||
return command_fail(cmd, FUNDING_PSBT_INVALID,
|
||||
"PSBT is missing required fields %s",
|
||||
type_to_string(tmpctx, struct wally_psbt,
|
||||
psbt));
|
||||
|
||||
peer->uncommitted_channel->fc = tal_steal(peer->uncommitted_channel, fc);
|
||||
fc->uc = peer->uncommitted_channel;
|
||||
|
||||
/* Needs to be stolen away from cmd */
|
||||
if (fc->our_upfront_shutdown_script)
|
||||
fc->our_upfront_shutdown_script
|
||||
= tal_steal(fc, fc->our_upfront_shutdown_script);
|
||||
|
||||
msg = towire_dual_open_opener_init(NULL,
|
||||
psbt, *amount,
|
||||
fc->our_upfront_shutdown_script,
|
||||
*feerate_per_kw,
|
||||
*feerate_per_kw_funding,
|
||||
fc->channel_flags);
|
||||
|
||||
subd_send_msg(peer->uncommitted_channel->open_daemon, take(msg));
|
||||
return command_still_pending(cmd);
|
||||
}
|
||||
|
||||
static unsigned int dual_opend_msg(struct subd *dualopend,
|
||||
const u8 *msg, const int *fds)
|
||||
{
|
||||
|
@ -934,7 +1112,17 @@ static unsigned int dual_opend_msg(struct subd *dualopend,
|
|||
accepter_got_offer(dualopend, uc, msg);
|
||||
return 0;
|
||||
case WIRE_DUAL_OPEN_PSBT_CHANGED:
|
||||
accepter_psbt_changed(dualopend, msg);
|
||||
if (uc->fc) {
|
||||
if (!uc->fc->cmd) {
|
||||
log_unusual(dualopend->log,
|
||||
"Unexpected PSBT_CHANGED %s",
|
||||
tal_hex(tmpctx, msg));
|
||||
tal_free(dualopend);
|
||||
return 0;
|
||||
}
|
||||
opener_psbt_changed(dualopend, uc, msg);
|
||||
} else
|
||||
accepter_psbt_changed(dualopend, msg);
|
||||
return 0;
|
||||
case WIRE_DUAL_OPEN_COMMIT_RCVD:
|
||||
if (tal_count(fds) != 3)
|
||||
|
@ -946,6 +1134,7 @@ static unsigned int dual_opend_msg(struct subd *dualopend,
|
|||
|
||||
/* Messages we send */
|
||||
case WIRE_DUAL_OPEN_INIT:
|
||||
case WIRE_DUAL_OPEN_OPENER_INIT:
|
||||
case WIRE_DUAL_OPEN_GOT_OFFER_REPLY:
|
||||
case WIRE_DUAL_OPEN_FAIL:
|
||||
case WIRE_DUAL_OPEN_DEV_MEMLEAK:
|
||||
|
@ -971,6 +1160,15 @@ static unsigned int dual_opend_msg(struct subd *dualopend,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static const struct json_command open_channel_init_command = {
|
||||
"openchannel_init",
|
||||
"channels",
|
||||
json_open_channel_init,
|
||||
"Init an open channel to {id} with {initialpsbt} for {amount} satoshis. "
|
||||
"Returns updated {psbt} with (partial) contributions from peer"
|
||||
};
|
||||
AUTODATA(json_command, &open_channel_init_command);
|
||||
|
||||
void peer_start_dualopend(struct peer *peer,
|
||||
struct per_peer_state *pps,
|
||||
const u8 *send_msg)
|
||||
|
|
|
@ -1236,6 +1236,186 @@ static u8 *accepter_start(struct state *state, const u8 *oc2_msg)
|
|||
}
|
||||
#endif /* EXPERIMENTAL_FEATURES */
|
||||
|
||||
static u8 *opener_start(struct state *state, u8 *msg)
|
||||
{
|
||||
struct tlv_opening_tlvs *open_tlv;
|
||||
struct tlv_accept_tlvs *a_tlv;
|
||||
struct channel_id cid;
|
||||
char *err_reason;
|
||||
struct amount_sat total;
|
||||
struct wally_psbt *psbt;
|
||||
struct wally_psbt_output *funding_out;
|
||||
u8 channel_flags;
|
||||
const u8 *wscript;
|
||||
u16 serial_id;
|
||||
struct sha256 podle;
|
||||
|
||||
if (!fromwire_dual_open_opener_init(state, msg,
|
||||
&psbt,
|
||||
&state->opener_funding,
|
||||
&state->upfront_shutdown_script[LOCAL],
|
||||
&state->feerate_per_kw,
|
||||
&state->feerate_per_kw_funding,
|
||||
&channel_flags))
|
||||
master_badmsg(WIRE_DUAL_OPEN_OPENER_INIT, msg);
|
||||
|
||||
state->our_role = TX_INITIATOR;
|
||||
state->tx_locktime = psbt->tx->locktime;
|
||||
open_tlv = tlv_opening_tlvs_new(tmpctx);
|
||||
|
||||
if (state->upfront_shutdown_script[LOCAL]) {
|
||||
open_tlv->option_upfront_shutdown_script =
|
||||
tal(open_tlv,
|
||||
struct tlv_opening_tlvs_option_upfront_shutdown_script);
|
||||
open_tlv->option_upfront_shutdown_script->shutdown_scriptpubkey =
|
||||
state->upfront_shutdown_script[LOCAL];
|
||||
}
|
||||
|
||||
/* FIXME: actually set the podle */
|
||||
memset(&podle, 0, sizeof(podle));
|
||||
msg = towire_open_channel2(NULL,
|
||||
&chainparams->genesis_blockhash,
|
||||
&podle, /* FIXME: podle H2! */
|
||||
state->feerate_per_kw_funding,
|
||||
state->opener_funding,
|
||||
state->localconf.dust_limit,
|
||||
state->localconf.max_htlc_value_in_flight,
|
||||
state->localconf.htlc_minimum,
|
||||
state->feerate_per_kw,
|
||||
state->localconf.to_self_delay,
|
||||
state->localconf.max_accepted_htlcs,
|
||||
state->tx_locktime,
|
||||
&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],
|
||||
channel_flags,
|
||||
open_tlv);
|
||||
|
||||
sync_crypto_write(state->pps, take(msg));
|
||||
|
||||
/* This is usually a very transient state... */
|
||||
peer_billboard(false, "channel open: offered, waiting for accept_channel2");
|
||||
|
||||
/* ... since their reply should be immediate. */
|
||||
msg = opening_negotiate_msg(tmpctx, state, true);
|
||||
if (!msg)
|
||||
return NULL;
|
||||
|
||||
/* Set a cid default value, so on failure it's populated */
|
||||
memset(&cid, 0xFF, sizeof(cid));
|
||||
|
||||
a_tlv = tlv_accept_tlvs_new(state);
|
||||
if (!fromwire_accept_channel2(msg, &cid,
|
||||
&state->accepter_funding,
|
||||
&state->remoteconf.dust_limit,
|
||||
&state->remoteconf.max_htlc_value_in_flight,
|
||||
&state->remoteconf.htlc_minimum,
|
||||
&state->minimum_depth,
|
||||
&state->remoteconf.to_self_delay,
|
||||
&state->remoteconf.max_accepted_htlcs,
|
||||
&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],
|
||||
a_tlv))
|
||||
peer_failed(state->pps, &cid,
|
||||
"Parsing accept_channel2 %s", tal_hex(msg, msg));
|
||||
|
||||
if (a_tlv->option_upfront_shutdown_script) {
|
||||
state->upfront_shutdown_script[REMOTE] = tal_steal(state,
|
||||
a_tlv->option_upfront_shutdown_script->shutdown_scriptpubkey);
|
||||
} else
|
||||
state->upfront_shutdown_script[REMOTE] = NULL;
|
||||
|
||||
derive_channel_id_v2(&state->channel_id,
|
||||
&state->our_points.revocation,
|
||||
&state->their_points.revocation);
|
||||
|
||||
if (!channel_id_eq(&cid, &state->channel_id))
|
||||
peer_failed(state->pps, &state->channel_id,
|
||||
"accept_channel2 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));
|
||||
|
||||
/* 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->opener_funding),
|
||||
type_to_string(tmpctx, struct amount_sat,
|
||||
&state->accepter_funding));
|
||||
|
||||
/* Check that total funding doesn't exceed allowed channel capacity */
|
||||
/* 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(total, chainparams->max_funding)) {
|
||||
negotiation_failed(state, false,
|
||||
"total funding_satoshis %s too large",
|
||||
type_to_string(tmpctx, struct amount_sat,
|
||||
&total));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* BOLT-78de9a79b491ae9fb84b1fdb4546bacf642dce87 #2:
|
||||
* The sending node:
|
||||
* - if is the `opener`:
|
||||
* - MUST send at least one `tx_add_output`, the channel funding output.
|
||||
*/
|
||||
wscript = bitcoin_redeem_2of2(state,
|
||||
&state->our_funding_pubkey,
|
||||
&state->their_funding_pubkey);
|
||||
funding_out = psbt_append_output(psbt,
|
||||
scriptpubkey_p2wsh(tmpctx, wscript),
|
||||
total);
|
||||
/* Add a serial_id for this output */
|
||||
serial_id = 0; /* FIXME: generate new serial */
|
||||
psbt_output_add_serial_id(psbt, funding_out, serial_id);
|
||||
|
||||
/* 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,
|
||||
true, true, /* v2 means we use anchor outputs */
|
||||
&err_reason)) {
|
||||
negotiation_failed(state, false, "%s", err_reason);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Send our first message, we're opener we initiate here */
|
||||
if (send_next(state, &psbt))
|
||||
status_failed(STATUS_FAIL_INTERNAL_ERROR,
|
||||
"Must have at least one update to send");
|
||||
|
||||
/* Figure out what the funding transaction looks like! */
|
||||
if (!run_tx_interactive(state, &psbt))
|
||||
return NULL;
|
||||
|
||||
/* FIXME! */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* 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
|
||||
|
@ -1321,9 +1501,11 @@ static u8 *handle_master_in(struct state *state)
|
|||
handle_dev_memleak(state, msg);
|
||||
return NULL;
|
||||
#endif
|
||||
case WIRE_DUAL_OPEN_OPENER_INIT:
|
||||
return opener_start(state, msg);
|
||||
/* mostly handled inline */
|
||||
case WIRE_DUAL_OPEN_DEV_MEMLEAK_REPLY:
|
||||
case WIRE_DUAL_OPEN_INIT:
|
||||
case WIRE_DUAL_OPEN_DEV_MEMLEAK_REPLY:
|
||||
case WIRE_DUAL_OPEN_FAILED:
|
||||
case WIRE_DUAL_OPEN_FAIL:
|
||||
case WIRE_DUAL_OPEN_GOT_OFFER:
|
||||
|
|
|
@ -93,10 +93,20 @@ msgdata,dual_open_psbt_changed,psbt,wally_psbt,
|
|||
msgtype,dual_open_fail,7003
|
||||
msgdata,dual_open_fail,reason,wirestring,
|
||||
|
||||
# dualopend->master: we failed to negotiation channel
|
||||
# dualopend->master: we failed to negotiate channel
|
||||
msgtype,dual_open_failed,7004
|
||||
msgdata,dual_open_failed,reason,wirestring,
|
||||
|
||||
# master->dualopend: hello, I'd like to start a channel open
|
||||
msgtype,dual_open_opener_init,7200
|
||||
msgdata,dual_open_opener_init,psbt,wally_psbt,
|
||||
msgdata,dual_open_opener_init,funding_amount,amount_sat,
|
||||
msgdata,dual_open_opener_init,local_shutdown_len,u16,
|
||||
msgdata,dual_open_opener_init,local_shutdown_scriptpubkey,u8,local_shutdown_len
|
||||
msgdata,dual_open_opener_init,feerate_per_kw,u32,
|
||||
msgdata,dual_open_opener_init,feerate_per_kw_funding,u32,
|
||||
msgdata,dual_open_opener_init,channel_flags,u8,
|
||||
|
||||
# master -> dualopend: do you have a memleak?
|
||||
msgtype,dual_open_dev_memleak,7033
|
||||
|
||||
|
|
Can't render this file because it has a wrong number of fields in line 11.
|
45
openingd/dualopend_wiregen.c
generated
45
openingd/dualopend_wiregen.c
generated
|
@ -27,6 +27,7 @@ const char *dualopend_wire_name(int e)
|
|||
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_OPENER_INIT: return "WIRE_DUAL_OPEN_OPENER_INIT";
|
||||
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";
|
||||
}
|
||||
|
@ -45,6 +46,7 @@ bool dualopend_wire_is_defined(u16 type)
|
|||
case WIRE_DUAL_OPEN_PSBT_CHANGED:;
|
||||
case WIRE_DUAL_OPEN_FAIL:;
|
||||
case WIRE_DUAL_OPEN_FAILED:;
|
||||
case WIRE_DUAL_OPEN_OPENER_INIT:;
|
||||
case WIRE_DUAL_OPEN_DEV_MEMLEAK:;
|
||||
case WIRE_DUAL_OPEN_DEV_MEMLEAK_REPLY:;
|
||||
return true;
|
||||
|
@ -352,7 +354,7 @@ bool fromwire_dual_open_fail(const tal_t *ctx, const void *p, wirestring **reaso
|
|||
}
|
||||
|
||||
/* WIRE: DUAL_OPEN_FAILED */
|
||||
/* dualopend->master: we failed to negotiation channel */
|
||||
/* dualopend->master: we failed to negotiate channel */
|
||||
u8 *towire_dual_open_failed(const tal_t *ctx, const wirestring *reason)
|
||||
{
|
||||
u8 *p = tal_arr(ctx, u8, 0);
|
||||
|
@ -373,6 +375,45 @@ bool fromwire_dual_open_failed(const tal_t *ctx, const void *p, wirestring **rea
|
|||
return cursor != NULL;
|
||||
}
|
||||
|
||||
/* WIRE: DUAL_OPEN_OPENER_INIT */
|
||||
/* master->dualopend: hello */
|
||||
u8 *towire_dual_open_opener_init(const tal_t *ctx, const struct wally_psbt *psbt, struct amount_sat funding_amount, const u8 *local_shutdown_scriptpubkey, u32 feerate_per_kw, u32 feerate_per_kw_funding, u8 channel_flags)
|
||||
{
|
||||
u16 local_shutdown_len = tal_count(local_shutdown_scriptpubkey);
|
||||
u8 *p = tal_arr(ctx, u8, 0);
|
||||
|
||||
towire_u16(&p, WIRE_DUAL_OPEN_OPENER_INIT);
|
||||
towire_wally_psbt(&p, psbt);
|
||||
towire_amount_sat(&p, funding_amount);
|
||||
towire_u16(&p, local_shutdown_len);
|
||||
towire_u8_array(&p, local_shutdown_scriptpubkey, local_shutdown_len);
|
||||
towire_u32(&p, feerate_per_kw);
|
||||
towire_u32(&p, feerate_per_kw_funding);
|
||||
towire_u8(&p, channel_flags);
|
||||
|
||||
return memcheck(p, tal_count(p));
|
||||
}
|
||||
bool fromwire_dual_open_opener_init(const tal_t *ctx, const void *p, struct wally_psbt **psbt, struct amount_sat *funding_amount, u8 **local_shutdown_scriptpubkey, u32 *feerate_per_kw, u32 *feerate_per_kw_funding, u8 *channel_flags)
|
||||
{
|
||||
u16 local_shutdown_len;
|
||||
|
||||
const u8 *cursor = p;
|
||||
size_t plen = tal_count(p);
|
||||
|
||||
if (fromwire_u16(&cursor, &plen) != WIRE_DUAL_OPEN_OPENER_INIT)
|
||||
return false;
|
||||
*psbt = fromwire_wally_psbt(ctx, &cursor, &plen);
|
||||
*funding_amount = 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);
|
||||
*feerate_per_kw = fromwire_u32(&cursor, &plen);
|
||||
*feerate_per_kw_funding = fromwire_u32(&cursor, &plen);
|
||||
*channel_flags = fromwire_u8(&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)
|
||||
|
@ -413,4 +454,4 @@ bool fromwire_dual_open_dev_memleak_reply(const void *p, bool *leak)
|
|||
*leak = fromwire_bool(&cursor, &plen);
|
||||
return cursor != NULL;
|
||||
}
|
||||
// SHA256STAMP:45ac65939acab987dfb71715f3a03db62863aa2048923666845e2adf45387eba
|
||||
// SHA256STAMP:4d357681ca9bea1ad36f3fe4d3482a0a12f808dfe20b71f0b9bee78beed0950e
|
||||
|
|
13
openingd/dualopend_wiregen.h
generated
13
openingd/dualopend_wiregen.h
generated
|
@ -31,8 +31,10 @@ enum dualopend_wire {
|
|||
WIRE_DUAL_OPEN_PSBT_CHANGED = 7107,
|
||||
/* master->dualopend: fail this channel open */
|
||||
WIRE_DUAL_OPEN_FAIL = 7003,
|
||||
/* dualopend->master: we failed to negotiation channel */
|
||||
/* dualopend->master: we failed to negotiate channel */
|
||||
WIRE_DUAL_OPEN_FAILED = 7004,
|
||||
/* master->dualopend: hello */
|
||||
WIRE_DUAL_OPEN_OPENER_INIT = 7200,
|
||||
/* master -> dualopend: do you have a memleak? */
|
||||
WIRE_DUAL_OPEN_DEV_MEMLEAK = 7033,
|
||||
WIRE_DUAL_OPEN_DEV_MEMLEAK_REPLY = 7133,
|
||||
|
@ -82,10 +84,15 @@ 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 */
|
||||
/* dualopend->master: we failed to negotiate 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_OPENER_INIT */
|
||||
/* master->dualopend: hello */
|
||||
u8 *towire_dual_open_opener_init(const tal_t *ctx, const struct wally_psbt *psbt, struct amount_sat funding_amount, const u8 *local_shutdown_scriptpubkey, u32 feerate_per_kw, u32 feerate_per_kw_funding, u8 channel_flags);
|
||||
bool fromwire_dual_open_opener_init(const tal_t *ctx, const void *p, struct wally_psbt **psbt, struct amount_sat *funding_amount, u8 **local_shutdown_scriptpubkey, u32 *feerate_per_kw, u32 *feerate_per_kw_funding, u8 *channel_flags);
|
||||
|
||||
/* WIRE: DUAL_OPEN_DEV_MEMLEAK */
|
||||
/* master -> dualopend: do you have a memleak? */
|
||||
u8 *towire_dual_open_dev_memleak(const tal_t *ctx);
|
||||
|
@ -97,4 +104,4 @@ bool fromwire_dual_open_dev_memleak_reply(const void *p, bool *leak);
|
|||
|
||||
|
||||
#endif /* LIGHTNING_OPENINGD_DUALOPEND_WIREGEN_H */
|
||||
// SHA256STAMP:45ac65939acab987dfb71715f3a03db62863aa2048923666845e2adf45387eba
|
||||
// SHA256STAMP:4d357681ca9bea1ad36f3fe4d3482a0a12f808dfe20b71f0b9bee78beed0950e
|
||||
|
|
Loading…
Add table
Reference in a new issue