diff --git a/contrib/pyln-client/pyln/client/lightning.py b/contrib/pyln-client/pyln/client/lightning.py index 4f3a4549f..8dc39f611 100644 --- a/contrib/pyln-client/pyln/client/lightning.py +++ b/contrib/pyln-client/pyln/client/lightning.py @@ -699,7 +699,7 @@ class LightningRpc(UnixDomainSocketRpc): } return self.call("feerates", payload) - def fundchannel(self, node_id, amount, feerate=None, announce=True, minconf=None, utxos=None, push_msat=None, close_to=None, request_amt=None): + def fundchannel(self, node_id, amount, feerate=None, announce=True, minconf=None, utxos=None, push_msat=None, close_to=None, request_amt=None, compact_lease=None): """ Fund channel with {id} using {amount} satoshis with feerate of {feerate} (uses default feerate if unset). @@ -723,6 +723,7 @@ class LightningRpc(UnixDomainSocketRpc): "push_msat": push_msat, "close_to": close_to, "request_amt": request_amt, + "compact_lease": compact_lease, } return self.call("fundchannel", payload) diff --git a/doc/lightning-fundchannel.7 b/doc/lightning-fundchannel.7 index 3180e88b8..d6177b742 100644 --- a/doc/lightning-fundchannel.7 +++ b/doc/lightning-fundchannel.7 @@ -4,7 +4,7 @@ lightning-fundchannel - Command for establishing a lightning channel .SH SYNOPSIS \fBfundchannel\fR \fIid\fR \fIamount\fR [\fIfeerate\fR] [\fIannounce\fR] [\fIminconf\fR] -[\fIutxos\fR] [\fIpush_msat\fR] [\fIclose_to\fR] +[\fIutxos\fR] [\fIpush_msat\fR] [\fIclose_to\fR] [\fIrequest_amt\fR] [\fIcompact_lease\fR] .SH DESCRIPTION @@ -74,7 +74,12 @@ Returns \fBclose_to\fR set to closing script iff is negotiated\. \fIrequest_amt\fR is an amount of liquidity you'd like to lease from the peer\. If peer supports \fBoption_will_fund\fR, indicates to them to include this -much liquidity into the channel\. +much liquidity into the channel\. Must also pass in \fIcompact_lease\fR\. + + +\fIcompact_lease\fR is a compact represenation of the peer's expected +channel lease terms\. If the peer's terms don't match this set, we will +fail to open the channel\. This example shows how to use lightning-cli to open new channel with peer 03f\.\.\.fc1 from one whole utxo bcc1\.\.\.39c:0 @@ -134,4 +139,4 @@ channel parameters (funding limits, channel reserves, fees, etc\.)\. Main web site: \fIhttps://github.com/ElementsProject/lightning\fR -\" SHA256STAMP:c7cd9291a08e66e41b24d0045c313ac1e3dabcb4579ab5fe132aad8d1ecbb640 +\" SHA256STAMP:73f87ce2618c7be8bce775de6e879f88a26e7b2cc48bedb077c29dba725d24eb diff --git a/doc/lightning-fundchannel.7.md b/doc/lightning-fundchannel.7.md index 125fc9204..30039a88f 100644 --- a/doc/lightning-fundchannel.7.md +++ b/doc/lightning-fundchannel.7.md @@ -5,7 +5,7 @@ SYNOPSIS -------- **fundchannel** *id* *amount* \[*feerate*\] \[*announce*\] \[*minconf*\] -\[*utxos*\] \[*push_msat*\] \[*close_to*\] +\[*utxos*\] \[*push_msat*\] \[*close_to*\] \[*request_amt*\] \[*compact_lease*\] DESCRIPTION ----------- @@ -66,7 +66,12 @@ Returns `close_to` set to closing script iff is negotiated. *request_amt* is an amount of liquidity you'd like to lease from the peer. If peer supports `option_will_fund`, indicates to them to include this -much liquidity into the channel. +much liquidity into the channel. Must also pass in *compact_lease*. + +*compact_lease* is a compact represenation of the peer's expected +channel lease terms. If the peer's terms don't match this set, we will +fail to open the channel. + This example shows how to use lightning-cli to open new channel with peer 03f...fc1 from one whole utxo bcc1...39c:0 diff --git a/doc/lightning-multifundchannel.7 b/doc/lightning-multifundchannel.7 index c86e9ea55..361d874ac 100644 --- a/doc/lightning-multifundchannel.7 +++ b/doc/lightning-multifundchannel.7 @@ -61,7 +61,11 @@ closing script iff is negotiated\. .IP \[bu] \fIrequest_amt\fR is the amount of liquidity you'd like to lease from peer\. If peer supports \fBoption_will_fund\fR, indicates to them to include this -much liquidity into the channel\. +much liquidity into the channel\. Must also pass in \fIcompact_lease\fR\. +.IP \[bu] +\fIcompact_lease\fR is a compact represenation of the peer's expected +channel lease terms\. If the peer's terms don't match this set, we will +fail to open the channel to this destination\. .RE @@ -208,4 +212,4 @@ ZmnSCPxj \fI is mainly responsible\. Main web site: \fIhttps://github.com/ElementsProject/lightning\fR -\" SHA256STAMP:fa55ac01a568d6b816641ddbfa3c9cccf437dea06df5ec84747f7ef02db6d47e +\" SHA256STAMP:a01cd5e8fa80e29fac6a23bc2907207a59714455b15435d4152b999f82da173b diff --git a/doc/lightning-multifundchannel.7.md b/doc/lightning-multifundchannel.7.md index a0472f9d4..d99e3e0fd 100644 --- a/doc/lightning-multifundchannel.7.md +++ b/doc/lightning-multifundchannel.7.md @@ -52,8 +52,11 @@ Readiness is indicated by **listpeers** reporting a *state* of `option_upfront_shutdown_script`. Returns `close_to` set to closing script iff is negotiated. * *request_amt* is the amount of liquidity you'd like to lease from peer. -If peer supports `option_will_fund`, indicates to them to include this -much liquidity into the channel. + If peer supports `option_will_fund`, indicates to them to include this + much liquidity into the channel. Must also pass in *compact_lease*. +* *compact_lease* is a compact represenation of the peer's expected + channel lease terms. If the peer's terms don't match this set, we will + fail to open the channel to this destination. There must be at least one entry in *destinations*; it cannot be an empty array. diff --git a/doc/lightning-openchannel_init.7 b/doc/lightning-openchannel_init.7 index 3c449a822..9ffdef476 100644 --- a/doc/lightning-openchannel_init.7 +++ b/doc/lightning-openchannel_init.7 @@ -3,7 +3,7 @@ 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] [\fIrequest_amt\fR] +\fBopenchannel_init\fR \fIid\fR \fIamount\fR \fIinitalpsbt\fR [\fIcommitment_feerate\fR] [\fIfunding_feerate\fR] [\fIannounce\fR] [\fIclose_to\fR] [\fIrequest_amt\fR] [\fIcompact_lease\fR] .SH DESCRIPTION @@ -46,7 +46,12 @@ sent on close\. Only valid if both peers have negotiated \fIrequest_amt\fR is an amount of liquidity you'd like to lease from the peer\. If peer supports \fBoption_will_fund\fR, indicates to them to include this -much liquidity into the channel\. +much liquidity into the channel\. Must also pass in \fIcompact_lease\fR\. + + +\fIcompact_lease\fR is a compact represenation of the peer's expected +channel lease terms\. If the peer's terms don't match this set, we will +fail to open the channel\. .SH RETURN VALUE @@ -119,4 +124,4 @@ lightning-fundchannel_\fBcomplete\fR(7), \fBlightning-fundchannel\fR(7), Main web site: \fIhttps://github.com/ElementsProject/lightning\fR -\" SHA256STAMP:13023bb80ee4a7f6a94a168399a01e05c6c5ab68e9eec5795ebd5f49207a03ac +\" SHA256STAMP:a5532a84325f6807aa370bd34a12828dba2fd87bd348bdeaac4217518882d90c diff --git a/doc/lightning-openchannel_init.7.md b/doc/lightning-openchannel_init.7.md index b3493557f..0b7ae285c 100644 --- a/doc/lightning-openchannel_init.7.md +++ b/doc/lightning-openchannel_init.7.md @@ -4,7 +4,7 @@ lightning-openchannel\_init -- Command to initiate a channel to a peer SYNOPSIS -------- -**openchannel_init** *id* *amount* *initalpsbt* \[*commitment_feerate*\] \[*funding_feerate*\] \[*announce*\] \[*close_to*\] \[*request_amt*\] +**openchannel_init** *id* *amount* *initalpsbt* \[*commitment_feerate*\] \[*funding_feerate*\] \[*announce*\] \[*close_to*\] \[*request_amt*\] \[*compact_lease*\] DESCRIPTION ----------- @@ -40,7 +40,11 @@ sent on close. Only valid if both peers have negotiated *request_amt* is an amount of liquidity you'd like to lease from the peer. If peer supports `option_will_fund`, indicates to them to include this -much liquidity into the channel. +much liquidity into the channel. Must also pass in *compact_lease*. + +*compact_lease* is a compact represenation of the peer's expected +channel lease terms. If the peer's terms don't match this set, we will +fail to open the channel. RETURN VALUE diff --git a/lightningd/dual_open_control.c b/lightningd/dual_open_control.c index 34fd7d5ba..44f7e7fcd 100644 --- a/lightningd/dual_open_control.c +++ b/lightningd/dual_open_control.c @@ -1617,8 +1617,12 @@ static void handle_dry_run_finished(struct subd *dualopend, const u8 *msg) json_add_amount_sat_only(response, "our_funding_msat", our_funding); json_add_amount_sat_only(response, "their_funding_msat", their_funding); - if (rates) + if (rates) { json_add_lease_rates(response, rates); + /* As a convenience, add a hexstring version of this data */ + json_add_string(response, "compact_lease", + lease_rates_tohex(tmpctx, rates)); + } was_pending(command_success(cmd, response)); } @@ -2597,7 +2601,8 @@ static struct command_result *json_queryrates(struct command *cmd, channel->channel_flags, *request_amt, get_block_height(cmd->ld->topology), - true); + true, + NULL); subd_send_msg(channel->owner, take(msg)); return command_still_pending(cmd); @@ -2619,6 +2624,7 @@ static struct command_result *json_openchannel_init(struct command *cmd, struct wally_psbt *psbt; const u8 *our_upfront_shutdown_script; struct open_attempt *oa; + struct lease_rates *rates; struct command_result *res; u8 *msg; @@ -2631,9 +2637,15 @@ static struct command_result *json_openchannel_init(struct command *cmd, p_opt_def("announce", param_bool, &announce_channel, true), p_opt("close_to", param_bitcoin_address, &our_upfront_shutdown_script), p_opt_def("request_amt", param_sat, &request_amt, AMOUNT_SAT(0)), + p_opt("compact_lease", param_lease_hex, &rates), NULL)) return command_param_failed(); + /* Gotta expect some rates ! */ + if (!amount_sat_zero(*request_amt) && !rates) + return command_fail(cmd, JSONRPC2_INVALID_PARAMS, + "Must pass in 'compact_lease' if requesting" + " funds from peer"); 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); @@ -2754,7 +2766,8 @@ static struct command_result *json_openchannel_init(struct command *cmd, channel->channel_flags, *request_amt, get_block_height(cmd->ld->topology), - false); + false, + rates); subd_send_msg(channel->owner, take(msg)); return command_still_pending(cmd); diff --git a/lightningd/gossip_control.c b/lightningd/gossip_control.c index acb0e851c..b783621d0 100644 --- a/lightningd/gossip_control.c +++ b/lightningd/gossip_control.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include diff --git a/openingd/dualopend.c b/openingd/dualopend.c index 4bf1dee01..cf7492ea7 100644 --- a/openingd/dualopend.c +++ b/openingd/dualopend.c @@ -2598,6 +2598,7 @@ static void opener_start(struct state *state, u8 *msg) char *err_reason; struct amount_sat total, requested_sats, lease_fee; bool dry_run; + struct lease_rates *expected_rates; struct tx_state *tx_state = state->tx_state; if (!fromwire_dualopend_opener_init(state, msg, @@ -2609,7 +2610,8 @@ static void opener_start(struct state *state, u8 *msg) &state->channel_flags, &requested_sats, &tx_state->blockheight, - &dry_run)) + &dry_run, + &expected_rates)) master_badmsg(WIRE_DUALOPEND_OPENER_INIT, msg); state->our_role = TX_INITIATOR; @@ -2747,6 +2749,23 @@ static void opener_start(struct state *state, u8 *msg) open_err_warn(state, "%s", "Abort requested"); } + /* If we've requested funds and they've failed to provide + * to lease us (or give them to us for free?!) then we fail. + * This isn't spec'd but it makes the UX predictable */ + if (open_tlv->request_funds + && amount_sat_less(tx_state->accepter_funding, requested_sats)) + negotiation_failed(state, + "We requested %s, which is more" + " than they've offered to provide" + " (%s)", + type_to_string(tmpctx, + struct amount_sat, + &requested_sats), + type_to_string(tmpctx, + struct amount_sat, + &tx_state->accepter_funding)); + + /* BOLT- #2: * The accepting node: ... * - if they decide to accept the offer: @@ -2756,6 +2775,16 @@ static void opener_start(struct state *state, u8 *msg) char *err_msg; struct lease_rates *rates = &a_tlv->will_fund->lease_rates; + if (!lease_rates_eq(rates, expected_rates)) + negotiation_failed(state, + "Expected lease rates (%s)," + " their returned lease rates (%s)", + lease_rates_fmt(tmpctx, + expected_rates), + lease_rates_fmt(tmpctx, + rates)); + + tx_state->lease_expiry = tx_state->blockheight + LEASE_RATE_DURATION; msg = towire_dualopend_validate_lease(NULL, diff --git a/openingd/dualopend_wire.csv b/openingd/dualopend_wire.csv index 823b790ef..8dffaef93 100644 --- a/openingd/dualopend_wire.csv +++ b/openingd/dualopend_wire.csv @@ -95,6 +95,7 @@ msgdata,dualopend_got_offer_reply,accepter_funding,amount_sat, msgdata,dualopend_got_offer_reply,psbt,wally_psbt, msgdata,dualopend_got_offer_reply,shutdown_len,u16, msgdata,dualopend_got_offer_reply,our_shutdown_scriptpubkey,?u8,shutdown_len +# must go last because of embedded tu32 msgdata,dualopend_got_offer_reply,lease_rates,?lease_rates, # dualopend->master: they offered a RBF, should we continue? @@ -179,6 +180,8 @@ msgdata,dualopend_opener_init,channel_flags,u8, msgdata,dualopend_opener_init,requested_sats,amount_sat, msgdata,dualopend_opener_init,blockheight,u32, msgdata,dualopend_opener_init,dry_run,bool, +# must go last because embedded tu32 +msgdata,dualopend_opener_init,expected_rates,?lease_rates, # dualopend->master received tx_sigs from peer msgtype,dualopend_funding_sigs,7010 @@ -231,6 +234,7 @@ msgtype,dualopend_dry_run,7026 msgdata,dualopend_dry_run,channel_id,channel_id, msgdata,dualopend_dry_run,our_funding,amount_sat, msgdata,dualopend_dry_run,their_funding,amount_sat, +# must go last because of embedded tu32 msgdata,dualopend_dry_run,lease_rates,?lease_rates, # dualopend -> master: validate liqudity offer sig diff --git a/openingd/dualopend_wiregen.c b/openingd/dualopend_wiregen.c index 54083001c..605e51e2c 100644 --- a/openingd/dualopend_wiregen.c +++ b/openingd/dualopend_wiregen.c @@ -338,6 +338,7 @@ u8 *towire_dualopend_got_offer_reply(const tal_t *ctx, struct amount_sat accepte towire_wally_psbt(&p, psbt); towire_u16(&p, shutdown_len); towire_u8_array(&p, our_shutdown_scriptpubkey, shutdown_len); + /* must go last because of embedded tu32 */ if (!lease_rates) towire_bool(&p, false); else { @@ -362,7 +363,8 @@ bool fromwire_dualopend_got_offer_reply(const tal_t *ctx, const void *p, struct // 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); - if (!fromwire_bool(&cursor, &plen)) + /* must go last because of embedded tu32 */ + if (!fromwire_bool(&cursor, &plen)) *lease_rates = NULL; else { *lease_rates = tal(ctx, struct lease_rates); @@ -667,7 +669,7 @@ bool fromwire_dualopend_fail(const tal_t *ctx, const void *p, wirestring **reaso /* WIRE: DUALOPEND_OPENER_INIT */ /* master->dualopend: hello */ -u8 *towire_dualopend_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, struct amount_sat requested_sats, u32 blockheight, bool dry_run) +u8 *towire_dualopend_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, struct amount_sat requested_sats, u32 blockheight, bool dry_run, const struct lease_rates *expected_rates) { u16 local_shutdown_len = tal_count(local_shutdown_scriptpubkey); u8 *p = tal_arr(ctx, u8, 0); @@ -683,10 +685,17 @@ u8 *towire_dualopend_opener_init(const tal_t *ctx, const struct wally_psbt *psbt towire_amount_sat(&p, requested_sats); towire_u32(&p, blockheight); towire_bool(&p, dry_run); + /* must go last because embedded tu32 */ + if (!expected_rates) + towire_bool(&p, false); + else { + towire_bool(&p, true); + towire_lease_rates(&p, expected_rates); + } return memcheck(p, tal_count(p)); } -bool fromwire_dualopend_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, struct amount_sat *requested_sats, u32 *blockheight, bool *dry_run) +bool fromwire_dualopend_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, struct amount_sat *requested_sats, u32 *blockheight, bool *dry_run, struct lease_rates **expected_rates) { u16 local_shutdown_len; @@ -707,6 +716,13 @@ bool fromwire_dualopend_opener_init(const tal_t *ctx, const void *p, struct wall *requested_sats = fromwire_amount_sat(&cursor, &plen); *blockheight = fromwire_u32(&cursor, &plen); *dry_run = fromwire_bool(&cursor, &plen); + /* must go last because embedded tu32 */ + if (!fromwire_bool(&cursor, &plen)) + *expected_rates = NULL; + else { + *expected_rates = tal(ctx, struct lease_rates); + fromwire_lease_rates(&cursor, &plen, *expected_rates); + } return cursor != NULL; } @@ -991,6 +1007,7 @@ u8 *towire_dualopend_dry_run(const tal_t *ctx, const struct channel_id *channel_ towire_channel_id(&p, channel_id); towire_amount_sat(&p, our_funding); towire_amount_sat(&p, their_funding); + /* must go last because of embedded tu32 */ if (!lease_rates) towire_bool(&p, false); else { @@ -1010,7 +1027,8 @@ bool fromwire_dualopend_dry_run(const tal_t *ctx, const void *p, struct channel_ fromwire_channel_id(&cursor, &plen, channel_id); *our_funding = fromwire_amount_sat(&cursor, &plen); *their_funding = fromwire_amount_sat(&cursor, &plen); - if (!fromwire_bool(&cursor, &plen)) + /* must go last because of embedded tu32 */ + if (!fromwire_bool(&cursor, &plen)) *lease_rates = NULL; else { *lease_rates = tal(ctx, struct lease_rates); @@ -1078,4 +1096,4 @@ bool fromwire_dualopend_validate_lease_reply(const tal_t *ctx, const void *p, wi } return cursor != NULL; } -// SHA256STAMP:65d1bedd1e05436c5474d298811fbb9c3fc96ac4e84bef8081c4eee55de286ad +// SHA256STAMP:893f2d8e99ee42b814c293ee5fc24c6234b4198c87eaa9ec55e83c8085b5045f diff --git a/openingd/dualopend_wiregen.h b/openingd/dualopend_wiregen.h index efbfb40d2..c4f693f21 100644 --- a/openingd/dualopend_wiregen.h +++ b/openingd/dualopend_wiregen.h @@ -159,8 +159,8 @@ bool fromwire_dualopend_fail(const tal_t *ctx, const void *p, wirestring **reaso /* WIRE: DUALOPEND_OPENER_INIT */ /* master->dualopend: hello */ -u8 *towire_dualopend_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, struct amount_sat requested_sats, u32 blockheight, bool dry_run); -bool fromwire_dualopend_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, struct amount_sat *requested_sats, u32 *blockheight, bool *dry_run); +u8 *towire_dualopend_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, struct amount_sat requested_sats, u32 blockheight, bool dry_run, const struct lease_rates *expected_rates); +bool fromwire_dualopend_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, struct amount_sat *requested_sats, u32 *blockheight, bool *dry_run, struct lease_rates **expected_rates); /* WIRE: DUALOPEND_FUNDING_SIGS */ /* dualopend->master received tx_sigs from peer */ @@ -237,4 +237,4 @@ bool fromwire_dualopend_validate_lease_reply(const tal_t *ctx, const void *p, wi #endif /* LIGHTNING_OPENINGD_DUALOPEND_WIREGEN_H */ -// SHA256STAMP:65d1bedd1e05436c5474d298811fbb9c3fc96ac4e84bef8081c4eee55de286ad +// SHA256STAMP:893f2d8e99ee42b814c293ee5fc24c6234b4198c87eaa9ec55e83c8085b5045f diff --git a/plugins/funder.c b/plugins/funder.c index e2e5997cc..b44fdb80b 100644 --- a/plugins/funder.c +++ b/plugins/funder.c @@ -761,8 +761,11 @@ static void json_add_policy(struct json_stream *stream, json_add_num(stream, "fuzz_percent", policy->fuzz_factor); json_add_num(stream, "fund_probability", policy->fund_probability); - if (policy->rates) + if (policy->rates) { json_add_lease_rates(stream, policy->rates); + json_add_string(stream, "compact_lease", + lease_rates_tohex(tmpctx, policy->rates)); + } } static struct command_result * diff --git a/plugins/spender/fundchannel.c b/plugins/spender/fundchannel.c index e4b75756d..1423b191c 100644 --- a/plugins/spender/fundchannel.c +++ b/plugins/spender/fundchannel.c @@ -43,6 +43,7 @@ json_fundchannel(struct command *cmd, const jsmntok_t *push_msat; const jsmntok_t *close_to; const jsmntok_t *request_amt; + const jsmntok_t *compact_lease; struct out_req *req; @@ -56,9 +57,15 @@ json_fundchannel(struct command *cmd, p_opt("push_msat", param_tok, &push_msat), p_opt("close_to", param_tok, &close_to), p_opt("request_amt", param_tok, &request_amt), + p_opt("compact_lease", param_tok, &compact_lease), NULL)) return command_param_failed(); + if (request_amt && !compact_lease) + return command_fail(cmd, JSONRPC2_INVALID_PARAMS, + "Must pass in 'compact_lease' if requesting" + " funds from peer"); + req = jsonrpc_request_start(cmd->plugin, cmd, "multifundchannel", &fundchannel_get_result, &forward_error, NULL); @@ -73,8 +80,10 @@ json_fundchannel(struct command *cmd, json_add_tok(req->js, "push_msat", push_msat, buf); if (close_to) json_add_tok(req->js, "close_to", close_to, buf); - if (request_amt) + if (request_amt) { json_add_tok(req->js, "request_amt", request_amt, buf); + json_add_tok(req->js, "compact_lease", compact_lease, buf); + } json_object_end(req->js); json_array_end(req->js); if (feerate) diff --git a/plugins/spender/multifundchannel.c b/plugins/spender/multifundchannel.c index 6df6931b6..e2de18446 100644 --- a/plugins/spender/multifundchannel.c +++ b/plugins/spender/multifundchannel.c @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -16,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -1816,6 +1818,7 @@ param_destinations_array(struct command *cmd, const char *name, struct amount_sat *amount, *request_amt; bool *announce; struct amount_msat *push_msat; + struct lease_rates *rates; dest = &(*dests)[i]; @@ -1832,6 +1835,7 @@ param_destinations_array(struct command *cmd, const char *name, &dest->close_to_str), p_opt_def("request_amt", param_sat, &request_amt, AMOUNT_SAT(0)), + p_opt("compact_lease", param_lease_hex, &rates), NULL)) return command_param_failed(); @@ -1854,6 +1858,12 @@ param_destinations_array(struct command *cmd, const char *name, json_dest, "output would be dust"); + if (!amount_sat_zero(*request_amt) && !rates) + return command_fail_badparam(cmd, name, buffer, + json_dest, + "Must pass in 'compact_" + "lease' if requesting" + " funds from peer"); dest->index = i; dest->addrhint = addrhint; dest->their_features = NULL; @@ -1867,6 +1877,7 @@ param_destinations_array(struct command *cmd, const char *name, dest->updated_psbt = NULL; dest->protocol = FUND_CHANNEL; dest->request_amt = *request_amt; + dest->rates = tal_steal(*dests, rates); /* Only one destination can have "all" indicator. */ if (dest->all) { diff --git a/plugins/spender/multifundchannel.h b/plugins/spender/multifundchannel.h index 0a1614ce4..e9cfe5d46 100644 --- a/plugins/spender/multifundchannel.h +++ b/plugins/spender/multifundchannel.h @@ -146,6 +146,9 @@ struct multifundchannel_destination { /* amount to request peer to lease (OPEN_CHANNEL) */ struct amount_sat request_amt; + + /* Channel lease rates that we expect the peer to respond with */ + struct lease_rates *rates; }; diff --git a/plugins/spender/openchannel.c b/plugins/spender/openchannel.c index 9f274aad7..22cbb171f 100644 --- a/plugins/spender/openchannel.c +++ b/plugins/spender/openchannel.c @@ -1026,9 +1026,12 @@ openchannel_init_dest(struct multifundchannel_destination *dest) &dest->push_msat)); /* Request some sats from the peer! */ - if (amount_sat_greater(dest->request_amt, AMOUNT_SAT(0))) + if (!amount_sat_zero(dest->request_amt)) { json_add_string(req->js, "request_amt", fmt_amount_sat(tmpctx, dest->request_amt)); + json_add_string(req->js, "compact_lease", + lease_rates_tohex(tmpctx, dest->rates)); + } return send_outreq(cmd->plugin, req); } diff --git a/plugins/topology.c b/plugins/topology.c index 9a263df64..c58dfb219 100644 --- a/plugins/topology.c +++ b/plugins/topology.c @@ -561,6 +561,11 @@ static void json_add_node(struct json_stream *js, if (na_tlvs->option_will_fund) { json_object_start(js, "option_will_fund"); json_add_lease_rates(js, na_tlvs->option_will_fund); + /* As a convenience, add a hexstring version + * of this info */ + json_add_string(js, "compact_lease", + lease_rates_tohex(tmpctx, + na_tlvs->option_will_fund)); json_object_end(js); } }