From f24bbac8d93a4de9880d96b001b3b009a7a47205 Mon Sep 17 00:00:00 2001 From: niftynei Date: Fri, 2 Jul 2021 16:19:47 -0500 Subject: [PATCH] channel leases: pass expected lease rates around in compat form We need to know what the lease we're expecting is. To do this we pass around the hex encoded portion of the wire format. We can use this passed in expected lease rates to confirm that the peer is, in fact, using the same rates as what we have currently. Changelog-Added: JSON-RPC: fundchannel, multifundchannel, and openchannel_init now accept a 'compact_lease' for any requested funds --- contrib/pyln-client/pyln/client/lightning.py | 3 +- doc/lightning-fundchannel.7 | 11 +++++-- doc/lightning-fundchannel.7.md | 9 ++++-- doc/lightning-multifundchannel.7 | 8 +++-- doc/lightning-multifundchannel.7.md | 7 +++-- doc/lightning-openchannel_init.7 | 11 +++++-- doc/lightning-openchannel_init.7.md | 8 +++-- lightningd/dual_open_control.c | 19 ++++++++++-- lightningd/gossip_control.c | 1 + openingd/dualopend.c | 31 +++++++++++++++++++- openingd/dualopend_wire.csv | 4 +++ openingd/dualopend_wiregen.c | 28 ++++++++++++++---- openingd/dualopend_wiregen.h | 6 ++-- plugins/funder.c | 5 +++- plugins/spender/fundchannel.c | 11 ++++++- plugins/spender/multifundchannel.c | 11 +++++++ plugins/spender/multifundchannel.h | 3 ++ plugins/spender/openchannel.c | 5 +++- plugins/topology.c | 5 ++++ 19 files changed, 156 insertions(+), 30 deletions(-) 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); } }