dual-funding: update fee_step to be a feerate

Using a 'feestep' is more restrictive than you'd want, instead we
enforce that the next feerate must be at least 1/64th more than the
last, but put no upper limit on it

Includes update to lnprototest changes

Contributed-By: Vincenzo Palazzo <vincenzopalazzodev@gmail.com>
Changelog-EXPERIMENTAL: Protocol: Replaces init_rbf's `fee_step` for RBF of v2 opens with `funding_feerate_perkw`, breaking change
This commit is contained in:
niftynei
2021-07-09 14:13:20 -05:00
committed by neil saitug
parent 04b6ad06cb
commit 376e6f8bd1
20 changed files with 181 additions and 174 deletions

View File

@@ -1039,12 +1039,13 @@ class LightningRpc(UnixDomainSocketRpc):
} }
return self.call("openchannel_update", payload) return self.call("openchannel_update", payload)
def openchannel_bump(self, channel_id, amount, initialpsbt): def openchannel_bump(self, channel_id, amount, initialpsbt, funding_feerate=None):
""" Initiate an RBF for an in-progress open """ """ Initiate an RBF for an in-progress open """
payload = { payload = {
"channel_id": channel_id, "channel_id": channel_id,
"amount": amount, "amount": amount,
"initialpsbt": initialpsbt, "initialpsbt": initialpsbt,
"funding_feerate": funding_feerate,
} }
return self.call("openchannel_bump", payload) return self.call("openchannel_bump", payload)

View File

@@ -273,8 +273,6 @@ If \fBinflight\fR is present:
\fBlast_feerate\fR (string): The feerate for the latest funding transaction in per-1000-weight, with "kpw" appended \fBlast_feerate\fR (string): The feerate for the latest funding transaction in per-1000-weight, with "kpw" appended
.IP \[bu] .IP \[bu]
\fBnext_feerate\fR (string): The minimum feerate for the next funding transaction in per-1000-weight, with "kpw" appended \fBnext_feerate\fR (string): The minimum feerate for the next funding transaction in per-1000-weight, with "kpw" appended
.IP \[bu]
\fBnext_fee_step\fR (u32): The number of fee steps so far, plus one
.RE .RE
@@ -646,4 +644,4 @@ Main web site: \fIhttps://github.com/ElementsProject/lightning\fR Lightning
RFC site (BOLT #9): RFC site (BOLT #9):
\fIhttps://github.com/lightningnetwork/lightning-rfc/blob/master/09-features.md\fR \fIhttps://github.com/lightningnetwork/lightning-rfc/blob/master/09-features.md\fR
\" SHA256STAMP:0eee52605e08ff184fa052d51ada7eb5da26149c6bc3d2a553c8e6518a27818b \" SHA256STAMP:16d808a5a346bb7dbffc263846617d33c74fdc6e0d5165f462d634ed8409f882

View File

@@ -132,7 +132,6 @@ On success, an object containing **peers** is returned. It is an array of objec
- **initial_feerate** (string): The feerate for the initial funding transaction in per-1000-weight, with "kpw" appended - **initial_feerate** (string): The feerate for the initial funding transaction in per-1000-weight, with "kpw" appended
- **last_feerate** (string): The feerate for the latest funding transaction in per-1000-weight, with "kpw" appended - **last_feerate** (string): The feerate for the latest funding transaction in per-1000-weight, with "kpw" appended
- **next_feerate** (string): The minimum feerate for the next funding transaction in per-1000-weight, with "kpw" appended - **next_feerate** (string): The minimum feerate for the next funding transaction in per-1000-weight, with "kpw" appended
- **next_fee_step** (u32): The number of fee steps so far, plus one
- **log** (array of objects, optional): if *level* is specified, logs for this peer: - **log** (array of objects, optional): if *level* is specified, logs for this peer:
- **type** (string) (one of "SKIPPED", "BROKEN", "UNUSUAL", "INFO", "DEBUG", "IO_IN", "IO_OUT") - **type** (string) (one of "SKIPPED", "BROKEN", "UNUSUAL", "INFO", "DEBUG", "IO_IN", "IO_OUT")
@@ -376,4 +375,4 @@ Main web site: <https://github.com/ElementsProject/lightning> Lightning
RFC site (BOLT \#9): RFC site (BOLT \#9):
<https://github.com/lightningnetwork/lightning-rfc/blob/master/09-features.md> <https://github.com/lightningnetwork/lightning-rfc/blob/master/09-features.md>
[comment]: # ( SHA256STAMP:6db6eb853f6c1953f05160cd9026ad6a8ccb97a016b15bc76242adc8026fa4ca) [comment]: # ( SHA256STAMP:91d30768a795456c75c72cf499df529ae8dbcc8088d06d1ed27150272425ab37)

View File

@@ -3,7 +3,7 @@
lightning-openchannel_bump - Command to initiate a channel RBF lightning-openchannel_bump - Command to initiate a channel RBF
.SH SYNOPSIS .SH SYNOPSIS
\fBopenchannel_bump\fR \fIchannel_id\fR \fIamount\fR \fIinitalpsbt\fR \fBopenchannel_bump\fR \fIchannel_id\fR \fIamount\fR \fIinitalpsbt\fR [\fIfunding_feerate\fR]
.SH DESCRIPTION .SH DESCRIPTION
@@ -27,6 +27,11 @@ 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 every input\. An error (code 309) will be returned if this requirement
is not met\. is not met\.
\fIfunding_feerate\fR is an optional field\. Sets the feerate for the
funding transaction\. Defaults to 1/64th greater than the last
feerate used for this channel\.
.SH RETURN VALUE .SH RETURN VALUE
On success, an object is returned, containing: On success, an object is returned, containing:
@@ -89,4 +94,4 @@ lightning-fundchannel_\fBstart\fR(7), lightning-fundchannel_\fBcomplete\fR(7),
Main web site: \fIhttps://github.com/ElementsProject/lightning\fR Main web site: \fIhttps://github.com/ElementsProject/lightning\fR
\" SHA256STAMP:53b3a3b647564ae97a249226271642dc775985dce376065dd95d332d9f60dd95 \" SHA256STAMP:357923fcd85b832cc52f77858c0744cae6c06d7612aaebb87e65f2ef0a42f367

View File

@@ -4,7 +4,7 @@ lightning-openchannel\_bump -- Command to initiate a channel RBF
SYNOPSIS SYNOPSIS
-------- --------
**openchannel_bump** *channel_id* *amount* *initalpsbt* **openchannel_bump** *channel_id* *amount* *initalpsbt* \[*funding_feerate*\]
DESCRIPTION DESCRIPTION
----------- -----------
@@ -26,6 +26,10 @@ 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 every input. An error (code 309) will be returned if this requirement
is not met. is not met.
*funding_feerate* is an optional field. Sets the feerate for the
funding transaction. Defaults to 1/64th greater than the last
feerate used for this channel.
RETURN VALUE RETURN VALUE
------------ ------------

View File

@@ -579,7 +579,6 @@
"short_channel_id": { }, "short_channel_id": { },
"channel_id": { }, "channel_id": { },
"funding_txid": { }, "funding_txid": { },
"inflight": { },
"close_to": { }, "close_to": { },
"private": { }, "private": { },
"opener": { }, "opener": { },
@@ -635,7 +634,6 @@
"initial_feerate": { }, "initial_feerate": { },
"last_feerate": { }, "last_feerate": { },
"next_feerate": { }, "next_feerate": { },
"next_fee_step": { },
"inflight": { }, "inflight": { },
"last_tx_fee": { }, "last_tx_fee": { },
"last_tx_fee_msat": { }, "last_tx_fee_msat": { },
@@ -715,12 +713,13 @@
"out_fulfilled_msat": { }, "out_fulfilled_msat": { },
"out_msatoshi_fulfilled": { }, "out_msatoshi_fulfilled": { },
"htlcs": { }, "htlcs": { },
"inflight": { }, "initial_feerate": { },
"last_feerate": { },
"next_feerate": { },
"close_to_addr": { }, "close_to_addr": { },
"initial_feerate": { }, "initial_feerate": { },
"last_feerate": { }, "last_feerate": { },
"next_feerate": { }, "next_feerate": { },
"next_fee_step": { },
"direction": { }, "direction": { },
"last_tx_fee": { "last_tx_fee": {
"deprecated": true "deprecated": true
@@ -800,13 +799,14 @@
"out_fulfilled_msat": { }, "out_fulfilled_msat": { },
"out_msatoshi_fulfilled": { }, "out_msatoshi_fulfilled": { },
"htlcs": { }, "htlcs": { },
"inflight": { }, "initial_feerate": { },
"last_feerate": { },
"next_feerate": { },
"last_tx_fee": { }, "last_tx_fee": { },
"close_to_addr": { }, "close_to_addr": { },
"initial_feerate": { }, "initial_feerate": { },
"last_feerate": { }, "last_feerate": { },
"next_feerate": { }, "next_feerate": { },
"next_fee_step": { },
"last_tx_fee": { }, "last_tx_fee": { },
"last_tx_fee_msat": { }, "last_tx_fee_msat": { },
"direction": { "direction": {
@@ -822,7 +822,7 @@
}, },
"then": { "then": {
"additionalProperties": false, "additionalProperties": false,
"required": [ "initial_feerate", "last_feerate", "next_feerate", "next_fee_step" ], "required": [ "initial_feerate", "last_feerate", "next_feerate" ],
"properties": { "properties": {
"state": { }, "state": { },
"scratch_txid": { }, "scratch_txid": { },
@@ -831,7 +831,6 @@
"short_channel_id": { }, "short_channel_id": { },
"channel_id": { }, "channel_id": { },
"funding_txid": { }, "funding_txid": { },
"inflight": { },
"close_to": { }, "close_to": { },
"private": { }, "private": { },
"opener": { }, "opener": { },
@@ -901,10 +900,6 @@
"next_feerate": { "next_feerate": {
"type": "string", "type": "string",
"description": "The minimum feerate for the next funding transaction in per-1000-weight, with \"kpw\" appended" "description": "The minimum feerate for the next funding transaction in per-1000-weight, with \"kpw\" appended"
},
"next_fee_step": {
"type": "u32",
"description": "The number of fee steps so far, plus one"
} }
} }
} }

View File

@@ -1986,12 +1986,15 @@ json_openchannel_bump(struct command *cmd,
struct channel *channel; struct channel *channel;
struct amount_sat *amount, psbt_val; struct amount_sat *amount, psbt_val;
struct wally_psbt *psbt; struct wally_psbt *psbt;
u32 last_feerate_perkw, next_feerate_min, *feerate_per_kw_funding;
struct open_attempt *oa; struct open_attempt *oa;
if (!param(cmd, buffer, params, if (!param(cmd, buffer, params,
p_req("channel_id", param_channel_id, &cid), p_req("channel_id", param_channel_id, &cid),
p_req("amount", param_sat, &amount), p_req("amount", param_sat, &amount),
p_req("initialpsbt", param_psbt, &psbt), p_req("initialpsbt", param_psbt, &psbt),
p_opt("funding_feerate", param_feerate,
&feerate_per_kw_funding),
NULL)) NULL))
return command_param_failed(); return command_param_failed();
@@ -2033,6 +2036,20 @@ json_openchannel_bump(struct command *cmd,
type_to_string(tmpctx, struct channel_id, type_to_string(tmpctx, struct channel_id,
cid)); cid));
last_feerate_perkw = channel_last_funding_feerate(channel);
next_feerate_min = last_feerate_perkw * 65 / 64;
assert(next_feerate_min > last_feerate_perkw);
if (!feerate_per_kw_funding) {
feerate_per_kw_funding = tal(cmd, u32);
*feerate_per_kw_funding = next_feerate_min;
} else if (*feerate_per_kw_funding < next_feerate_min)
return command_fail(cmd, JSONRPC2_INVALID_PARAMS,
"Next feerate must be at least 1/64th"
" greater than the last. Min req %u,"
" you proposed %u",
next_feerate_min,
*feerate_per_kw_funding);
/* BOLT #2: /* BOLT #2:
* - if both nodes advertised `option_support_large_channel`: * - if both nodes advertised `option_support_large_channel`:
* - MAY set `funding_satoshis` greater than or equal to 2^24 satoshi. * - MAY set `funding_satoshis` greater than or equal to 2^24 satoshi.
@@ -2092,7 +2109,9 @@ json_openchannel_bump(struct command *cmd,
psbt)); psbt));
subd_send_msg(channel->owner, subd_send_msg(channel->owner,
take(towire_dualopend_rbf_init(NULL, *amount, psbt))); take(towire_dualopend_rbf_init(NULL, *amount,
*feerate_per_kw_funding,
psbt)));
return command_still_pending(cmd); return command_still_pending(cmd);
} }
@@ -2876,7 +2895,7 @@ void peer_restart_dualopend(struct peer *peer,
u32 max_to_self_delay; u32 max_to_self_delay;
struct amount_msat min_effective_htlc_capacity; struct amount_msat min_effective_htlc_capacity;
struct channel_config unused_config; struct channel_config unused_config;
struct channel_inflight *inflight, *first_inflight; struct channel_inflight *inflight;
int hsmfd; int hsmfd;
u8 *msg; u8 *msg;
@@ -2917,12 +2936,6 @@ void peer_restart_dualopend(struct peer *peer,
inflight = channel_current_inflight(channel); inflight = channel_current_inflight(channel);
assert(inflight); assert(inflight);
/* Get the first inflight to figure out the original feerate
* for this channel. It's fine if it's the same as the current */
first_inflight = list_top(&channel->inflights,
struct channel_inflight,
list);
assert(first_inflight);
msg = towire_dualopend_reinit(NULL, msg = towire_dualopend_reinit(NULL,
chainparams, chainparams,
peer->ld->our_features, peer->ld->our_features,
@@ -2939,7 +2952,6 @@ void peer_restart_dualopend(struct peer *peer,
channel->minimum_depth, channel->minimum_depth,
&inflight->funding->txid, &inflight->funding->txid,
inflight->funding->outnum, inflight->funding->outnum,
first_inflight->funding->feerate,
inflight->funding->feerate, inflight->funding->feerate,
channel->funding, channel->funding,
channel->our_msat, channel->our_msat,

View File

@@ -774,32 +774,32 @@ static void json_add_channel(struct lightningd *ld,
if (!list_empty(&channel->inflights)) { if (!list_empty(&channel->inflights)) {
struct channel_inflight *initial, *inflight; struct channel_inflight *initial, *inflight;
u32 last_feerate, next_feerate, feerate; u32 last_feerate, next_feerate;
u8 feestep;
last_feerate = channel_last_funding_feerate(channel);
assert(last_feerate > 0);
next_feerate = last_feerate + last_feerate / 4;
initial = list_top(&channel->inflights, initial = list_top(&channel->inflights,
struct channel_inflight, list); struct channel_inflight, list);
feerate = initial->funding->feerate;
json_add_string(response, "initial_feerate", json_add_string(response, "initial_feerate",
tal_fmt(tmpctx, "%d%s", feerate, tal_fmt(tmpctx, "%d%s",
initial->funding->feerate,
feerate_style_name(FEERATE_PER_KSIPA))); feerate_style_name(FEERATE_PER_KSIPA)));
last_feerate = channel_last_funding_feerate(channel);
assert(last_feerate > 0);
json_add_string(response, "last_feerate", json_add_string(response, "last_feerate",
tal_fmt(tmpctx, "%d%s", last_feerate, tal_fmt(tmpctx, "%d%s", last_feerate,
feerate_style_name(FEERATE_PER_KSIPA))); feerate_style_name(FEERATE_PER_KSIPA)));
/* BOLT-9e7723387c8859b511e178485605a0b9133b9869 #2:
* - MUST set `funding_feerate_perkw` greater than or equal to
* 65/64 times the last sent `funding_feerate_perkw`
* rounded down.
*/
next_feerate = last_feerate * 65 / 64;
assert(next_feerate > last_feerate);
json_add_string(response, "next_feerate", json_add_string(response, "next_feerate",
tal_fmt(tmpctx, "%d%s", next_feerate, tal_fmt(tmpctx, "%d%s", next_feerate,
feerate_style_name(FEERATE_PER_KSIPA))); feerate_style_name(FEERATE_PER_KSIPA)));
/* Now we derive the feestep */
for (feestep = 0; feerate < next_feerate; feestep++)
feerate += feerate / 4;
json_add_num(response, "next_fee_step", feestep);
/* List the inflights */ /* List the inflights */
json_array_start(response, "inflight"); json_array_start(response, "inflight");
list_for_each(&channel->inflights, inflight, list) { list_for_each(&channel->inflights, inflight, list) {

View File

@@ -165,7 +165,6 @@ struct state {
enum tx_role our_role; enum tx_role our_role;
u32 feerate_per_kw_funding;
u32 feerate_per_kw_commitment; u32 feerate_per_kw_commitment;
/* If non-NULL, this is the scriptpubkey we/they *must* close with */ /* If non-NULL, this is the scriptpubkey we/they *must* close with */
@@ -1957,9 +1956,6 @@ static void accepter_start(struct state *state, const u8 *oc2_msg)
type_to_string(tmpctx, struct channel_id, type_to_string(tmpctx, struct channel_id,
&cid)); &cid));
/* Save feerate on the state as well */
state->feerate_per_kw_funding = tx_state->feerate_per_kw_funding;
/* BOLT #2: /* BOLT #2:
* *
* The receiving node MUST fail the channel if: * The receiving node MUST fail the channel if:
@@ -2002,7 +1998,7 @@ static void accepter_start(struct state *state, const u8 *oc2_msg)
tx_state->remoteconf.dust_limit, tx_state->remoteconf.dust_limit,
tx_state->remoteconf.max_htlc_value_in_flight, tx_state->remoteconf.max_htlc_value_in_flight,
tx_state->remoteconf.htlc_minimum, tx_state->remoteconf.htlc_minimum,
state->feerate_per_kw_funding, tx_state->feerate_per_kw_funding,
state->feerate_per_kw_commitment, state->feerate_per_kw_commitment,
tx_state->remoteconf.to_self_delay, tx_state->remoteconf.to_self_delay,
tx_state->remoteconf.max_accepted_htlcs, tx_state->remoteconf.max_accepted_htlcs,
@@ -2410,13 +2406,12 @@ static void opener_start(struct state *state, u8 *msg)
&tx_state->opener_funding, &tx_state->opener_funding,
&state->upfront_shutdown_script[LOCAL], &state->upfront_shutdown_script[LOCAL],
&state->feerate_per_kw_commitment, &state->feerate_per_kw_commitment,
&state->feerate_per_kw_funding, &tx_state->feerate_per_kw_funding,
&state->channel_flags)) &state->channel_flags))
master_badmsg(WIRE_DUALOPEND_OPENER_INIT, msg); master_badmsg(WIRE_DUALOPEND_OPENER_INIT, msg);
state->our_role = TX_INITIATOR; state->our_role = TX_INITIATOR;
tx_state->tx_locktime = tx_state->psbt->tx->locktime; tx_state->tx_locktime = tx_state->psbt->tx->locktime;
tx_state->feerate_per_kw_funding = state->feerate_per_kw_funding;
open_tlv = tlv_opening_tlvs_new(tmpctx); open_tlv = tlv_opening_tlvs_new(tmpctx);
/* BOLT-* #2 /* BOLT-* #2
@@ -2444,7 +2439,7 @@ static void opener_start(struct state *state, u8 *msg)
msg = towire_open_channel2(NULL, msg = towire_open_channel2(NULL,
&chainparams->genesis_blockhash, &chainparams->genesis_blockhash,
&state->channel_id, &state->channel_id,
state->feerate_per_kw_funding, tx_state->feerate_per_kw_funding,
state->feerate_per_kw_commitment, state->feerate_per_kw_commitment,
tx_state->opener_funding, tx_state->opener_funding,
tx_state->localconf.dust_limit, tx_state->localconf.dust_limit,
@@ -2600,52 +2595,29 @@ static void opener_start(struct state *state, u8 *msg)
wire_sync_write(REQ_FD, take(msg)); wire_sync_write(REQ_FD, take(msg));
} }
static bool update_feerate(struct tx_state *tx_state, static bool check_funding_feerate(u32 proposed_next_feerate,
u32 feerate_funding, u32 last_feerate)
u32 last_feerate,
u8 fee_step)
{ {
u32 feerate = feerate_funding;
/* /*
* BOLT-f53ca2301232db780843e894f55d95d512f297f9 #2: * BOLT-9e7723387c8859b511e178485605a0b9133b9869 #2:
* *
* `fee_step` is an integer value, which specifies the * The recipient: ...
* `feerate` for this funding transaction, as a rate of * - MUST fail the negotiation if:
* increase above the `open_channel2`. `funding_feerate_perkw`. * - the `funding_feerate_perkw` is not greater than 65/64 times
* * `funding_feerate_perkw` of the last successfully negotiated
* The effective `funding_feerate_perkw` for this RBF attempt * open attempt
* if calculated as 1.25^`fee_step` * `funding_feerate_perkw`.
* E.g. if `feerate_per_kw_funding` is 512 and the `fee_step` is 1,
* the effective `feerate` for this RBF attempt is 512 + 512 / 4
* or 640 sat/kw. A `fee_step` 2 would be `1.25^2 * 512`
* (or 640 + 640 / 4), 800 sat/kw.
*/ */
for (; fee_step > 0; fee_step--) u32 next_min = last_feerate * 65 / 64;
feerate += feerate / 4;
/* It's possible they sent us a 'bad' feerate step, if (next_min < last_feerate) {
* i.e. less than the last one. */ status_broken("Overflow calculating next feerate. last %u",
if (feerate <= last_feerate) last_feerate);
return false;
}
if (last_feerate > proposed_next_feerate)
return false; return false;
tx_state->feerate_per_kw_funding = feerate; return next_min <= proposed_next_feerate;
return true;
}
static u8 find_next_feestep(u32 last_feerate, u32 feerate_funding,
u32 *next_feerate)
{
u8 feestep;
u32 feerate = feerate_funding;
assert(last_feerate != 0 && feerate != 0);
for (feestep = 0; feerate <= last_feerate; feestep++)
feerate = feerate + feerate / 4;
if (next_feerate)
*next_feerate = feerate;
return feestep;
} }
static void rbf_wrap_up(struct state *state, static void rbf_wrap_up(struct state *state,
@@ -2739,7 +2711,6 @@ static void rbf_local_start(struct state *state, u8 *msg)
struct channel_id cid; struct channel_id cid;
struct amount_sat total; struct amount_sat total;
char *err_reason; char *err_reason;
u8 fee_step;
/* We need a new tx_state! */ /* We need a new tx_state! */
tx_state = new_tx_state(state); tx_state = new_tx_state(state);
@@ -2752,14 +2723,18 @@ static void rbf_local_start(struct state *state, u8 *msg)
state->our_role == TX_INITIATOR ? state->our_role == TX_INITIATOR ?
&tx_state->opener_funding : &tx_state->opener_funding :
&tx_state->accepter_funding, &tx_state->accepter_funding,
&tx_state->feerate_per_kw_funding,
&tx_state->psbt)) &tx_state->psbt))
master_badmsg(WIRE_DUALOPEND_RBF_INIT, msg); master_badmsg(WIRE_DUALOPEND_RBF_INIT, msg);
peer_billboard(false, "channel rbf: init received from master"); peer_billboard(false, "channel rbf: init received from master");
fee_step = find_next_feestep(state->tx_state->feerate_per_kw_funding, if (!check_funding_feerate(tx_state->feerate_per_kw_funding,
state->feerate_per_kw_funding, state->tx_state->feerate_per_kw_funding)) {
&tx_state->feerate_per_kw_funding); open_err_warn(state, "Proposed funding feerate (%u) invalid",
tx_state->feerate_per_kw_funding);
return;
}
/* Have you sent us everything we need yet ? */ /* Have you sent us everything we need yet ? */
if (!state->tx_state->remote_funding_sigs_rcvd) { if (!state->tx_state->remote_funding_sigs_rcvd) {
@@ -2778,7 +2753,7 @@ static void rbf_local_start(struct state *state, u8 *msg)
tx_state->opener_funding : tx_state->opener_funding :
tx_state->accepter_funding, tx_state->accepter_funding,
tx_state->tx_locktime, tx_state->tx_locktime,
fee_step); tx_state->feerate_per_kw_funding);
sync_crypto_write(state->pps, take(msg)); sync_crypto_write(state->pps, take(msg));
@@ -2859,7 +2834,7 @@ static void rbf_remote_start(struct state *state, const u8 *rbf_msg)
char *err_reason; char *err_reason;
struct amount_sat total; struct amount_sat total;
enum dualopend_wire msg_type; enum dualopend_wire msg_type;
u8 fee_step, *msg; u8 *msg;
/* We need a new tx_state! */ /* We need a new tx_state! */
tx_state = new_tx_state(state); tx_state = new_tx_state(state);
@@ -2869,7 +2844,7 @@ static void rbf_remote_start(struct state *state, const u8 *rbf_msg)
&tx_state->accepter_funding : &tx_state->accepter_funding :
&tx_state->opener_funding, &tx_state->opener_funding,
&tx_state->tx_locktime, &tx_state->tx_locktime,
&fee_step)) &tx_state->feerate_per_kw_funding))
open_err_fatal(state, "Parsing init_rbf %s", open_err_fatal(state, "Parsing init_rbf %s",
tal_hex(tmpctx, rbf_msg)); tal_hex(tmpctx, rbf_msg));
@@ -2895,13 +2870,11 @@ static void rbf_remote_start(struct state *state, const u8 *rbf_msg)
tx_state->localconf = state->tx_state->localconf; tx_state->localconf = state->tx_state->localconf;
tx_state->remoteconf = state->tx_state->remoteconf; tx_state->remoteconf = state->tx_state->remoteconf;
if (!update_feerate(tx_state, if (!check_funding_feerate(tx_state->feerate_per_kw_funding,
state->feerate_per_kw_funding, state->tx_state->feerate_per_kw_funding)) {
state->tx_state->feerate_per_kw_funding, open_err_warn(state, "Funding feerate not greater than last."
fee_step)) { "Proposed %u, last feerate %u",
open_err_warn(state, "Fee step not greater than last." tx_state->feerate_per_kw_funding,
" Fee step %d, last feerate %d",
fee_step,
state->tx_state->feerate_per_kw_funding); state->tx_state->feerate_per_kw_funding);
tal_free(tx_state); tal_free(tx_state);
return; return;
@@ -3499,7 +3472,6 @@ int main(int argc, char *argv[])
&state->minimum_depth, &state->minimum_depth,
&state->tx_state->funding_txid, &state->tx_state->funding_txid,
&state->tx_state->funding_txout, &state->tx_state->funding_txout,
&state->feerate_per_kw_funding,
&state->tx_state->feerate_per_kw_funding, &state->tx_state->feerate_per_kw_funding,
&total_funding, &total_funding,
&our_msat, &our_msat,

View File

@@ -45,7 +45,6 @@ msgdata,dualopend_reinit,their_funding_pubkey,pubkey,
msgdata,dualopend_reinit,minimum_depth,u32, msgdata,dualopend_reinit,minimum_depth,u32,
msgdata,dualopend_reinit,funding_txid,bitcoin_txid, msgdata,dualopend_reinit,funding_txid,bitcoin_txid,
msgdata,dualopend_reinit,funding_txout,u16, msgdata,dualopend_reinit,funding_txout,u16,
msgdata,dualopend_reinit,orignal_feerate_per_kw_funding,u32,
msgdata,dualopend_reinit,most_recent_feerate_per_kw_funding,u32, msgdata,dualopend_reinit,most_recent_feerate_per_kw_funding,u32,
msgdata,dualopend_reinit,funding_satoshi,amount_sat, msgdata,dualopend_reinit,funding_satoshi,amount_sat,
msgdata,dualopend_reinit,our_funding,amount_msat, msgdata,dualopend_reinit,our_funding,amount_msat,
@@ -110,6 +109,7 @@ msgtype,dualopend_rbf_valid,7507
# master->dualopend: attempt an RBF # master->dualopend: attempt an RBF
msgtype,dualopend_rbf_init,7509 msgtype,dualopend_rbf_init,7509
msgdata,dualopend_rbf_init,our_funding,amount_sat, msgdata,dualopend_rbf_init,our_funding,amount_sat,
msgdata,dualopend_rbf_init,funding_feerate_perkw,u32,
msgdata,dualopend_rbf_init,psbt,wally_psbt, msgdata,dualopend_rbf_init,psbt,wally_psbt,
# dualopend->master: ready to commit channel open to database and # dualopend->master: ready to commit channel open to database and
Can't render this file because it has a wrong number of fields in line 13.

View File

@@ -146,7 +146,7 @@ bool fromwire_dualopend_init(const tal_t *ctx, const void *p, const struct chain
/* WIRE: DUALOPEND_REINIT */ /* WIRE: DUALOPEND_REINIT */
/* master-dualopend: peer has reconnected */ /* master-dualopend: peer has reconnected */
u8 *towire_dualopend_reinit(const tal_t *ctx, const struct chainparams *chainparams, const struct feature_set *our_feature_set, const u8 *their_init_features, const struct channel_config *our_config, const struct channel_config *their_config, const struct channel_id *channel_id, u32 max_to_self_delay, struct amount_msat min_effective_htlc_capacity_msat, const struct per_peer_state *pps, const struct basepoints *our_basepoints, const struct pubkey *our_funding_pubkey, const struct pubkey *their_funding_pubkey, u32 minimum_depth, const struct bitcoin_txid *funding_txid, u16 funding_txout, u32 orignal_feerate_per_kw_funding, u32 most_recent_feerate_per_kw_funding, struct amount_sat funding_satoshi, struct amount_msat our_funding, const struct basepoints *their_basepoints, const struct pubkey *remote_per_commit, const struct wally_psbt *funding_psbt, enum side opener, bool local_funding_locked, bool remote_funding_locked, bool send_shutdown, bool remote_shutdown_received, const u8 *local_shutdown_scriptpubkey, const u8 *remote_shutdown_scriptpubkey, bool remote_funding_sigs_received, const struct fee_states *fee_states, u8 channel_flags) u8 *towire_dualopend_reinit(const tal_t *ctx, const struct chainparams *chainparams, const struct feature_set *our_feature_set, const u8 *their_init_features, const struct channel_config *our_config, const struct channel_config *their_config, const struct channel_id *channel_id, u32 max_to_self_delay, struct amount_msat min_effective_htlc_capacity_msat, const struct per_peer_state *pps, const struct basepoints *our_basepoints, const struct pubkey *our_funding_pubkey, const struct pubkey *their_funding_pubkey, u32 minimum_depth, const struct bitcoin_txid *funding_txid, u16 funding_txout, u32 most_recent_feerate_per_kw_funding, struct amount_sat funding_satoshi, struct amount_msat our_funding, const struct basepoints *their_basepoints, const struct pubkey *remote_per_commit, const struct wally_psbt *funding_psbt, enum side opener, bool local_funding_locked, bool remote_funding_locked, bool send_shutdown, bool remote_shutdown_received, const u8 *local_shutdown_scriptpubkey, const u8 *remote_shutdown_scriptpubkey, bool remote_funding_sigs_received, const struct fee_states *fee_states, u8 channel_flags)
{ {
u16 their_init_features_len = tal_count(their_init_features); u16 their_init_features_len = tal_count(their_init_features);
u16 local_shutdown_len = tal_count(local_shutdown_scriptpubkey); u16 local_shutdown_len = tal_count(local_shutdown_scriptpubkey);
@@ -170,7 +170,6 @@ u8 *towire_dualopend_reinit(const tal_t *ctx, const struct chainparams *chainpar
towire_u32(&p, minimum_depth); towire_u32(&p, minimum_depth);
towire_bitcoin_txid(&p, funding_txid); towire_bitcoin_txid(&p, funding_txid);
towire_u16(&p, funding_txout); towire_u16(&p, funding_txout);
towire_u32(&p, orignal_feerate_per_kw_funding);
towire_u32(&p, most_recent_feerate_per_kw_funding); towire_u32(&p, most_recent_feerate_per_kw_funding);
towire_amount_sat(&p, funding_satoshi); towire_amount_sat(&p, funding_satoshi);
towire_amount_msat(&p, our_funding); towire_amount_msat(&p, our_funding);
@@ -192,7 +191,7 @@ u8 *towire_dualopend_reinit(const tal_t *ctx, const struct chainparams *chainpar
return memcheck(p, tal_count(p)); return memcheck(p, tal_count(p));
} }
bool fromwire_dualopend_reinit(const tal_t *ctx, const void *p, const struct chainparams **chainparams, struct feature_set **our_feature_set, u8 **their_init_features, struct channel_config *our_config, struct channel_config *their_config, struct channel_id *channel_id, u32 *max_to_self_delay, struct amount_msat *min_effective_htlc_capacity_msat, struct per_peer_state **pps, struct basepoints *our_basepoints, struct pubkey *our_funding_pubkey, struct pubkey *their_funding_pubkey, u32 *minimum_depth, struct bitcoin_txid *funding_txid, u16 *funding_txout, u32 *orignal_feerate_per_kw_funding, u32 *most_recent_feerate_per_kw_funding, struct amount_sat *funding_satoshi, struct amount_msat *our_funding, struct basepoints *their_basepoints, struct pubkey *remote_per_commit, struct wally_psbt **funding_psbt, enum side *opener, bool *local_funding_locked, bool *remote_funding_locked, bool *send_shutdown, bool *remote_shutdown_received, u8 **local_shutdown_scriptpubkey, u8 **remote_shutdown_scriptpubkey, bool *remote_funding_sigs_received, struct fee_states **fee_states, u8 *channel_flags) bool fromwire_dualopend_reinit(const tal_t *ctx, const void *p, const struct chainparams **chainparams, struct feature_set **our_feature_set, u8 **their_init_features, struct channel_config *our_config, struct channel_config *their_config, struct channel_id *channel_id, u32 *max_to_self_delay, struct amount_msat *min_effective_htlc_capacity_msat, struct per_peer_state **pps, struct basepoints *our_basepoints, struct pubkey *our_funding_pubkey, struct pubkey *their_funding_pubkey, u32 *minimum_depth, struct bitcoin_txid *funding_txid, u16 *funding_txout, u32 *most_recent_feerate_per_kw_funding, struct amount_sat *funding_satoshi, struct amount_msat *our_funding, struct basepoints *their_basepoints, struct pubkey *remote_per_commit, struct wally_psbt **funding_psbt, enum side *opener, bool *local_funding_locked, bool *remote_funding_locked, bool *send_shutdown, bool *remote_shutdown_received, u8 **local_shutdown_scriptpubkey, u8 **remote_shutdown_scriptpubkey, bool *remote_funding_sigs_received, struct fee_states **fee_states, u8 *channel_flags)
{ {
u16 their_init_features_len; u16 their_init_features_len;
u16 local_shutdown_len; u16 local_shutdown_len;
@@ -221,7 +220,6 @@ bool fromwire_dualopend_reinit(const tal_t *ctx, const void *p, const struct cha
*minimum_depth = fromwire_u32(&cursor, &plen); *minimum_depth = fromwire_u32(&cursor, &plen);
fromwire_bitcoin_txid(&cursor, &plen, funding_txid); fromwire_bitcoin_txid(&cursor, &plen, funding_txid);
*funding_txout = fromwire_u16(&cursor, &plen); *funding_txout = fromwire_u16(&cursor, &plen);
*orignal_feerate_per_kw_funding = fromwire_u32(&cursor, &plen);
*most_recent_feerate_per_kw_funding = fromwire_u32(&cursor, &plen); *most_recent_feerate_per_kw_funding = fromwire_u32(&cursor, &plen);
*funding_satoshi = fromwire_amount_sat(&cursor, &plen); *funding_satoshi = fromwire_amount_sat(&cursor, &plen);
*our_funding = fromwire_amount_msat(&cursor, &plen); *our_funding = fromwire_amount_msat(&cursor, &plen);
@@ -427,17 +425,18 @@ bool fromwire_dualopend_rbf_valid(const void *p)
/* WIRE: DUALOPEND_RBF_INIT */ /* WIRE: DUALOPEND_RBF_INIT */
/* master->dualopend: attempt an RBF */ /* master->dualopend: attempt an RBF */
u8 *towire_dualopend_rbf_init(const tal_t *ctx, struct amount_sat our_funding, const struct wally_psbt *psbt) u8 *towire_dualopend_rbf_init(const tal_t *ctx, struct amount_sat our_funding, u32 funding_feerate_perkw, const struct wally_psbt *psbt)
{ {
u8 *p = tal_arr(ctx, u8, 0); u8 *p = tal_arr(ctx, u8, 0);
towire_u16(&p, WIRE_DUALOPEND_RBF_INIT); towire_u16(&p, WIRE_DUALOPEND_RBF_INIT);
towire_amount_sat(&p, our_funding); towire_amount_sat(&p, our_funding);
towire_u32(&p, funding_feerate_perkw);
towire_wally_psbt(&p, psbt); towire_wally_psbt(&p, psbt);
return memcheck(p, tal_count(p)); return memcheck(p, tal_count(p));
} }
bool fromwire_dualopend_rbf_init(const tal_t *ctx, const void *p, struct amount_sat *our_funding, struct wally_psbt **psbt) bool fromwire_dualopend_rbf_init(const tal_t *ctx, const void *p, struct amount_sat *our_funding, u32 *funding_feerate_perkw, struct wally_psbt **psbt)
{ {
const u8 *cursor = p; const u8 *cursor = p;
size_t plen = tal_count(p); size_t plen = tal_count(p);
@@ -445,6 +444,7 @@ bool fromwire_dualopend_rbf_init(const tal_t *ctx, const void *p, struct amount_
if (fromwire_u16(&cursor, &plen) != WIRE_DUALOPEND_RBF_INIT) if (fromwire_u16(&cursor, &plen) != WIRE_DUALOPEND_RBF_INIT)
return false; return false;
*our_funding = fromwire_amount_sat(&cursor, &plen); *our_funding = fromwire_amount_sat(&cursor, &plen);
*funding_feerate_perkw = fromwire_u32(&cursor, &plen);
*psbt = fromwire_wally_psbt(ctx, &cursor, &plen); *psbt = fromwire_wally_psbt(ctx, &cursor, &plen);
return cursor != NULL; return cursor != NULL;
} }
@@ -912,4 +912,4 @@ bool fromwire_dualopend_dev_memleak_reply(const void *p, bool *leak)
*leak = fromwire_bool(&cursor, &plen); *leak = fromwire_bool(&cursor, &plen);
return cursor != NULL; return cursor != NULL;
} }
// SHA256STAMP:a4678b6938e46bd8ab7c6076312789d0cdfa06076d745fd28fd65f3febc4c3a0 // SHA256STAMP:2aa38c967abfcd0110b6c65f62b13aa77cefacaf5f036a9217bb5d63220f1e1f

View File

@@ -91,8 +91,8 @@ bool fromwire_dualopend_init(const tal_t *ctx, const void *p, const struct chain
/* WIRE: DUALOPEND_REINIT */ /* WIRE: DUALOPEND_REINIT */
/* master-dualopend: peer has reconnected */ /* master-dualopend: peer has reconnected */
u8 *towire_dualopend_reinit(const tal_t *ctx, const struct chainparams *chainparams, const struct feature_set *our_feature_set, const u8 *their_init_features, const struct channel_config *our_config, const struct channel_config *their_config, const struct channel_id *channel_id, u32 max_to_self_delay, struct amount_msat min_effective_htlc_capacity_msat, const struct per_peer_state *pps, const struct basepoints *our_basepoints, const struct pubkey *our_funding_pubkey, const struct pubkey *their_funding_pubkey, u32 minimum_depth, const struct bitcoin_txid *funding_txid, u16 funding_txout, u32 orignal_feerate_per_kw_funding, u32 most_recent_feerate_per_kw_funding, struct amount_sat funding_satoshi, struct amount_msat our_funding, const struct basepoints *their_basepoints, const struct pubkey *remote_per_commit, const struct wally_psbt *funding_psbt, enum side opener, bool local_funding_locked, bool remote_funding_locked, bool send_shutdown, bool remote_shutdown_received, const u8 *local_shutdown_scriptpubkey, const u8 *remote_shutdown_scriptpubkey, bool remote_funding_sigs_received, const struct fee_states *fee_states, u8 channel_flags); u8 *towire_dualopend_reinit(const tal_t *ctx, const struct chainparams *chainparams, const struct feature_set *our_feature_set, const u8 *their_init_features, const struct channel_config *our_config, const struct channel_config *their_config, const struct channel_id *channel_id, u32 max_to_self_delay, struct amount_msat min_effective_htlc_capacity_msat, const struct per_peer_state *pps, const struct basepoints *our_basepoints, const struct pubkey *our_funding_pubkey, const struct pubkey *their_funding_pubkey, u32 minimum_depth, const struct bitcoin_txid *funding_txid, u16 funding_txout, u32 most_recent_feerate_per_kw_funding, struct amount_sat funding_satoshi, struct amount_msat our_funding, const struct basepoints *their_basepoints, const struct pubkey *remote_per_commit, const struct wally_psbt *funding_psbt, enum side opener, bool local_funding_locked, bool remote_funding_locked, bool send_shutdown, bool remote_shutdown_received, const u8 *local_shutdown_scriptpubkey, const u8 *remote_shutdown_scriptpubkey, bool remote_funding_sigs_received, const struct fee_states *fee_states, u8 channel_flags);
bool fromwire_dualopend_reinit(const tal_t *ctx, const void *p, const struct chainparams **chainparams, struct feature_set **our_feature_set, u8 **their_init_features, struct channel_config *our_config, struct channel_config *their_config, struct channel_id *channel_id, u32 *max_to_self_delay, struct amount_msat *min_effective_htlc_capacity_msat, struct per_peer_state **pps, struct basepoints *our_basepoints, struct pubkey *our_funding_pubkey, struct pubkey *their_funding_pubkey, u32 *minimum_depth, struct bitcoin_txid *funding_txid, u16 *funding_txout, u32 *orignal_feerate_per_kw_funding, u32 *most_recent_feerate_per_kw_funding, struct amount_sat *funding_satoshi, struct amount_msat *our_funding, struct basepoints *their_basepoints, struct pubkey *remote_per_commit, struct wally_psbt **funding_psbt, enum side *opener, bool *local_funding_locked, bool *remote_funding_locked, bool *send_shutdown, bool *remote_shutdown_received, u8 **local_shutdown_scriptpubkey, u8 **remote_shutdown_scriptpubkey, bool *remote_funding_sigs_received, struct fee_states **fee_states, u8 *channel_flags); bool fromwire_dualopend_reinit(const tal_t *ctx, const void *p, const struct chainparams **chainparams, struct feature_set **our_feature_set, u8 **their_init_features, struct channel_config *our_config, struct channel_config *their_config, struct channel_id *channel_id, u32 *max_to_self_delay, struct amount_msat *min_effective_htlc_capacity_msat, struct per_peer_state **pps, struct basepoints *our_basepoints, struct pubkey *our_funding_pubkey, struct pubkey *their_funding_pubkey, u32 *minimum_depth, struct bitcoin_txid *funding_txid, u16 *funding_txout, u32 *most_recent_feerate_per_kw_funding, struct amount_sat *funding_satoshi, struct amount_msat *our_funding, struct basepoints *their_basepoints, struct pubkey *remote_per_commit, struct wally_psbt **funding_psbt, enum side *opener, bool *local_funding_locked, bool *remote_funding_locked, bool *send_shutdown, bool *remote_shutdown_received, u8 **local_shutdown_scriptpubkey, u8 **remote_shutdown_scriptpubkey, bool *remote_funding_sigs_received, struct fee_states **fee_states, u8 *channel_flags);
/* WIRE: DUALOPEND_GOT_OFFER */ /* WIRE: DUALOPEND_GOT_OFFER */
/* dualopend->master: they offered channel */ /* dualopend->master: they offered channel */
@@ -126,8 +126,8 @@ bool fromwire_dualopend_rbf_valid(const void *p);
/* WIRE: DUALOPEND_RBF_INIT */ /* WIRE: DUALOPEND_RBF_INIT */
/* master->dualopend: attempt an RBF */ /* master->dualopend: attempt an RBF */
u8 *towire_dualopend_rbf_init(const tal_t *ctx, struct amount_sat our_funding, const struct wally_psbt *psbt); u8 *towire_dualopend_rbf_init(const tal_t *ctx, struct amount_sat our_funding, u32 funding_feerate_perkw, const struct wally_psbt *psbt);
bool fromwire_dualopend_rbf_init(const tal_t *ctx, const void *p, struct amount_sat *our_funding, struct wally_psbt **psbt); bool fromwire_dualopend_rbf_init(const tal_t *ctx, const void *p, struct amount_sat *our_funding, u32 *funding_feerate_perkw, struct wally_psbt **psbt);
/* WIRE: DUALOPEND_COMMIT_RCVD */ /* WIRE: DUALOPEND_COMMIT_RCVD */
/* dualopend->master: ready to commit channel open to database and */ /* dualopend->master: ready to commit channel open to database and */
@@ -216,4 +216,4 @@ bool fromwire_dualopend_dev_memleak_reply(const void *p, bool *leak);
#endif /* LIGHTNING_OPENINGD_DUALOPEND_WIREGEN_H */ #endif /* LIGHTNING_OPENINGD_DUALOPEND_WIREGEN_H */
// SHA256STAMP:a4678b6938e46bd8ab7c6076312789d0cdfa06076d745fd28fd65f3febc4c3a0 // SHA256STAMP:2aa38c967abfcd0110b6c65f62b13aa77cefacaf5f036a9217bb5d63220f1e1f

View File

@@ -201,7 +201,7 @@ def test_v2_open_sigs_restart_while_dead(node_factory, bitcoind):
@unittest.skipIf(TEST_NETWORK != 'regtest', 'elementsd doesnt yet support PSBT features we need') @unittest.skipIf(TEST_NETWORK != 'regtest', 'elementsd doesnt yet support PSBT features we need')
@pytest.mark.openchannel('v2') @pytest.mark.openchannel('v2')
def test_v2_rbf(node_factory, bitcoind, chainparams): def test_v2_rbf_single(node_factory, bitcoind, chainparams):
l1, l2 = node_factory.get_nodes(2, opts={'wumbo': None}) l1, l2 = node_factory.get_nodes(2, opts={'wumbo': None})
l1.rpc.connect(l2.info['id'], 'localhost', l2.port) l1.rpc.connect(l2.info['id'], 'localhost', l2.port)
@@ -227,8 +227,7 @@ def test_v2_rbf(node_factory, bitcoind, chainparams):
info_1 = only_one(only_one(l1.rpc.listpeers(l2.info['id'])['peers'])['channels']) info_1 = only_one(only_one(l1.rpc.listpeers(l2.info['id'])['peers'])['channels'])
assert info_1['initial_feerate'] == info_1['last_feerate'] assert info_1['initial_feerate'] == info_1['last_feerate']
rate = int(info_1['last_feerate'][:-5]) rate = int(info_1['last_feerate'][:-5])
assert int(info_1['next_feerate'][:-5]) == rate + rate // 4 assert int(info_1['next_feerate'][:-5]) == rate * 65 // 64
assert info_1['next_fee_step'] == 1
# Initiate an RBF # Initiate an RBF
startweight = 42 + 172 # base weight, funding output startweight = 42 + 172 # base weight, funding output
@@ -249,11 +248,36 @@ def test_v2_rbf(node_factory, bitcoind, chainparams):
assert info_1['next_feerate'] == info_2['last_feerate'] assert info_1['next_feerate'] == info_2['last_feerate']
rate = int(info_2['last_feerate'][:-5]) rate = int(info_2['last_feerate'][:-5])
assert int(info_2['next_feerate'][:-5]) == rate + rate // 4 assert int(info_2['next_feerate'][:-5]) == rate * 65 // 64
assert info_2['next_fee_step'] == 2
# Sign our inputs, and continue # Sign our inputs, and continue
signed_psbt = l1.rpc.signpsbt(update['psbt'])['signed_psbt'] signed_psbt = l1.rpc.signpsbt(update['psbt'])['signed_psbt']
# Fails because we didn't put enough feerate in.
with pytest.raises(RpcError, match=r'insufficient fee'):
l1.rpc.openchannel_signed(chan_id, signed_psbt)
# Do it again, with a higher feerate
info_2 = only_one(only_one(l1.rpc.listpeers(l2.info['id'])['peers'])['channels'])
assert info_1['initial_feerate'] == info_2['initial_feerate']
assert info_1['next_feerate'] == info_2['last_feerate']
rate = int(info_2['last_feerate'][:-5])
assert int(info_2['next_feerate'][:-5]) == rate * 65 // 64
# We 4x the feerate to beat the min-relay fee
next_rate = '{}perkw'.format(rate * 65 // 64 * 4)
# Gotta unreserve the psbt and re-reserve with higher feerate
l1.rpc.unreserveinputs(initpsbt['psbt'])
initpsbt = l1.rpc.utxopsbt(chan_amount, next_rate, startweight,
prev_utxos, reservedok=True,
min_witness_weight=110,
excess_as_change=True)
# Do the bump+sign
bump = l1.rpc.openchannel_bump(chan_id, chan_amount, initpsbt['psbt'],
funding_feerate=next_rate)
update = l1.rpc.openchannel_update(chan_id, bump['psbt'])
assert update['commitments_secured']
signed_psbt = l1.rpc.signpsbt(update['psbt'])['signed_psbt']
l1.rpc.openchannel_signed(chan_id, signed_psbt) l1.rpc.openchannel_signed(chan_id, signed_psbt)
bitcoind.generate_block(1) bitcoind.generate_block(1)
@@ -265,7 +289,6 @@ def test_v2_rbf(node_factory, bitcoind, chainparams):
assert 'initial_feerate' not in info_1 assert 'initial_feerate' not in info_1
assert 'last_feerate' not in info_1 assert 'last_feerate' not in info_1
assert 'next_feerate' not in info_1 assert 'next_feerate' not in info_1
assert 'next_fee_step' not in info_1
# Shut l2 down, force close the channel. # Shut l2 down, force close the channel.
l2.stop() l2.stop()
@@ -304,7 +327,9 @@ def test_v2_rbf_multi(node_factory, bitcoind, chainparams):
with pytest.raises(RpcError): with pytest.raises(RpcError):
l1.rpc.openchannel_abort(chan_id) l1.rpc.openchannel_abort(chan_id)
next_feerate = find_next_feerate(l1, l2) rate = int(find_next_feerate(l1, l2)[:-5])
# We 4x the feerate to beat the min-relay fee
next_feerate = '{}perkw'.format(rate * 4)
# Initiate an RBF # Initiate an RBF
startweight = 42 + 172 # base weight, funding output startweight = 42 + 172 # base weight, funding output
@@ -314,15 +339,19 @@ def test_v2_rbf_multi(node_factory, bitcoind, chainparams):
excess_as_change=True) excess_as_change=True)
# Do the bump # Do the bump
bump = l1.rpc.openchannel_bump(chan_id, chan_amount, initpsbt['psbt']) bump = l1.rpc.openchannel_bump(chan_id, chan_amount,
initpsbt['psbt'],
funding_feerate=next_feerate)
# Abort this open attempt! We will re-try # Abort this open attempt! We will re-try
aborted = l1.rpc.openchannel_abort(chan_id) aborted = l1.rpc.openchannel_abort(chan_id)
assert not aborted['channel_canceled'] assert not aborted['channel_canceled']
# Do the bump, again # Do the bump, again, same feerate
l1.rpc.connect(l2.info['id'], 'localhost', l2.port) l1.rpc.connect(l2.info['id'], 'localhost', l2.port)
bump = l1.rpc.openchannel_bump(chan_id, chan_amount, initpsbt['psbt']) bump = l1.rpc.openchannel_bump(chan_id, chan_amount,
initpsbt['psbt'],
funding_feerate=next_feerate)
update = l1.rpc.openchannel_update(chan_id, bump['psbt']) update = l1.rpc.openchannel_update(chan_id, bump['psbt'])
assert update['commitments_secured'] assert update['commitments_secured']
@@ -331,9 +360,11 @@ def test_v2_rbf_multi(node_factory, bitcoind, chainparams):
signed_psbt = l1.rpc.signpsbt(update['psbt'])['signed_psbt'] signed_psbt = l1.rpc.signpsbt(update['psbt'])['signed_psbt']
l1.rpc.openchannel_signed(chan_id, signed_psbt) l1.rpc.openchannel_signed(chan_id, signed_psbt)
next_feerate = find_next_feerate(l1, l2) # We 2x the feerate to beat the min-relay fee
rate = int(find_next_feerate(l1, l2)[:-5])
next_feerate = '{}perkw'.format(rate * 2)
# Initiate an RBF, double the channel amount this time # Initiate another RBF, double the channel amount this time
startweight = 42 + 172 # base weight, funding output startweight = 42 + 172 # base weight, funding output
initpsbt = l1.rpc.utxopsbt(chan_amount * 2, next_feerate, startweight, initpsbt = l1.rpc.utxopsbt(chan_amount * 2, next_feerate, startweight,
prev_utxos, reservedok=True, prev_utxos, reservedok=True,
@@ -341,7 +372,9 @@ def test_v2_rbf_multi(node_factory, bitcoind, chainparams):
excess_as_change=True) excess_as_change=True)
# Do the bump # Do the bump
bump = l1.rpc.openchannel_bump(chan_id, chan_amount * 2, initpsbt['psbt']) bump = l1.rpc.openchannel_bump(chan_id, chan_amount * 2,
initpsbt['psbt'],
funding_feerate=next_feerate)
update = l1.rpc.openchannel_update(chan_id, bump['psbt']) update = l1.rpc.openchannel_update(chan_id, bump['psbt'])
assert update['commitments_secured'] assert update['commitments_secured']
@@ -724,14 +757,18 @@ def test_rbf_fails_to_broadcast(node_factory, bitcoind, chainparams):
def run_retry(): def run_retry():
startweight = 42 + 173 startweight = 42 + 173
next_feerate = find_next_feerate(l1, l2) rate = int(find_next_feerate(l1, l2)[:-5])
# We 2x the feerate to beat the min-relay fee
next_feerate = '{}perkw'.format(rate * 2)
initpsbt = l1.rpc.utxopsbt(chan_amount, next_feerate, startweight, initpsbt = l1.rpc.utxopsbt(chan_amount, next_feerate, startweight,
prev_utxos, reservedok=True, prev_utxos, reservedok=True,
min_witness_weight=110, min_witness_weight=110,
excess_as_change=True) excess_as_change=True)
l1.rpc.connect(l2.info['id'], 'localhost', l2.port) l1.rpc.connect(l2.info['id'], 'localhost', l2.port)
bump = l1.rpc.openchannel_bump(chan_id, chan_amount, initpsbt['psbt']) bump = l1.rpc.openchannel_bump(chan_id, chan_amount,
initpsbt['psbt'],
funding_feerate=next_feerate)
# We should be able to call this with while an open is progress # We should be able to call this with while an open is progress
# but not yet committed # but not yet committed
l1.rpc.dev_sign_last_tx(l2.info['id']) l1.rpc.dev_sign_last_tx(l2.info['id'])
@@ -741,37 +778,19 @@ def test_rbf_fails_to_broadcast(node_factory, bitcoind, chainparams):
return l1.rpc.signpsbt(update['psbt'])['signed_psbt'] return l1.rpc.signpsbt(update['psbt'])['signed_psbt']
signed_psbt = run_retry() signed_psbt = run_retry()
with pytest.raises(RpcError, match=r'insufficient fee, rejecting replacement'):
l1.rpc.openchannel_signed(chan_id, signed_psbt) l1.rpc.openchannel_signed(chan_id, signed_psbt)
inflights = only_one(only_one(l1.rpc.listpeers()['peers'])['channels'])['inflight'] inflights = only_one(only_one(l1.rpc.listpeers()['peers'])['channels'])['inflight']
assert inflights[-1]['funding_txid'] not in bitcoind.rpc.getrawmempool() assert inflights[-1]['funding_txid'] in bitcoind.rpc.getrawmempool()
# If we restart and listpeers, it will crash # Restart and listpeers, used to crash
l1.restart() l1.restart()
l1.rpc.listpeers() l1.rpc.listpeers()
# We've restarted. Let's RBF until we successfully get a # We've restarted. Let's RBF
# new funding transaction for this channel
# do it again
signed_psbt = run_retry()
with pytest.raises(RpcError, match=r'insufficient fee, rejecting replacement'):
l1.rpc.openchannel_signed(chan_id, signed_psbt)
inflights = only_one(only_one(l1.rpc.listpeers()['peers'])['channels'])['inflight']
assert inflights[-1]['funding_txid'] not in bitcoind.rpc.getrawmempool()
# and again
signed_psbt = run_retry()
with pytest.raises(RpcError, match=r'insufficient fee, rejecting replacement'):
l1.rpc.openchannel_signed(chan_id, signed_psbt)
inflights = only_one(only_one(l1.rpc.listpeers()['peers'])['channels'])['inflight']
assert inflights[-1]['funding_txid'] not in bitcoind.rpc.getrawmempool()
# now we should be ok
signed_psbt = run_retry() signed_psbt = run_retry()
l1.rpc.openchannel_signed(chan_id, signed_psbt) l1.rpc.openchannel_signed(chan_id, signed_psbt)
inflights = only_one(only_one(l1.rpc.listpeers()['peers'])['channels'])['inflight'] inflights = only_one(only_one(l1.rpc.listpeers()['peers'])['channels'])['inflight']
assert len(inflights) == 5 assert len(inflights) == 3
assert inflights[-1]['funding_txid'] in bitcoind.rpc.getrawmempool() assert inflights[-1]['funding_txid'] in bitcoind.rpc.getrawmempool()
l1.restart() l1.restart()
@@ -896,7 +915,9 @@ def test_rbf_non_last_mined(node_factory, bitcoind, chainparams):
def run_retry(): def run_retry():
startweight = 42 + 173 startweight = 42 + 173
next_feerate = find_next_feerate(l1, l2) rate = int(find_next_feerate(l1, l2)[:-5])
# We 2x the feerate to beat the min-relay fee
next_feerate = '{}perkw'.format(rate * 2)
initpsbt = l1.rpc.utxopsbt(chan_amount, next_feerate, startweight, initpsbt = l1.rpc.utxopsbt(chan_amount, next_feerate, startweight,
prev_utxos, reservedok=True, prev_utxos, reservedok=True,
min_witness_weight=110, min_witness_weight=110,

View File

@@ -91,7 +91,7 @@
+msgdata,init_rbf,channel_id,channel_id, +msgdata,init_rbf,channel_id,channel_id,
+msgdata,init_rbf,funding_satoshis,u64, +msgdata,init_rbf,funding_satoshis,u64,
+msgdata,init_rbf,locktime,u32, +msgdata,init_rbf,locktime,u32,
+msgdata,init_rbf,fee_step,byte, +msgdata,init_rbf,funding_feerate_perkw,u32,
+msgtype,ack_rbf,73 +msgtype,ack_rbf,73
+msgdata,ack_rbf,channel_id,channel_id, +msgdata,ack_rbf,channel_id,channel_id,
+msgdata,ack_rbf,funding_satoshis,u64, +msgdata,ack_rbf,funding_satoshis,u64,

8
wire/peer_printgen.c generated
View File

@@ -1808,10 +1808,10 @@ void printwire_init_rbf(const char *fieldname, const u8 *cursor)
printf("**TRUNCATED**\n"); printf("**TRUNCATED**\n");
return; return;
} }
printf("fee_step="); printf("funding_feerate_perkw=");
u8 fee_step = fromwire_u8(&cursor, &plen); u32 funding_feerate_perkw = fromwire_u32(&cursor, &plen);
printwire_u8(tal_fmt(NULL, "%s.fee_step", fieldname), &fee_step); printwire_u32(tal_fmt(NULL, "%s.funding_feerate_perkw", fieldname), &funding_feerate_perkw);
if (!cursor) { if (!cursor) {
printf("**TRUNCATED**\n"); printf("**TRUNCATED**\n");
return; return;
@@ -2935,4 +2935,4 @@ void printpeer_wire_tlv_message(const char *tlv_name, const u8 *msg) {
printwire_tlvs(tlv_name, &msg, &plen, print_tlvs_onion_message_tlvs, ARRAY_SIZE(print_tlvs_onion_message_tlvs)); printwire_tlvs(tlv_name, &msg, &plen, print_tlvs_onion_message_tlvs, ARRAY_SIZE(print_tlvs_onion_message_tlvs));
} }
} }
// SHA256STAMP:aeea1df56a4d408e222ac2c9f2deb201fda3cd2062f3c65f1b3ca52e11600acd // SHA256STAMP:a3a508935b99ff0b985d0774432ae9d98f3ec7660bf4edf64095a3d0a37ba0e8

2
wire/peer_printgen.h generated
View File

@@ -96,4 +96,4 @@ void printwire_channel_update_checksums(const char *fieldname, const u8 **cursor
void printwire_channel_update_timestamps(const char *fieldname, const u8 **cursor, size_t *plen); void printwire_channel_update_timestamps(const char *fieldname, const u8 **cursor, size_t *plen);
void printwire_witness_stack(const char *fieldname, const u8 **cursor, size_t *plen); void printwire_witness_stack(const char *fieldname, const u8 **cursor, size_t *plen);
#endif /* LIGHTNING_WIRE_PEER_PRINTGEN_H */ #endif /* LIGHTNING_WIRE_PEER_PRINTGEN_H */
// SHA256STAMP:aeea1df56a4d408e222ac2c9f2deb201fda3cd2062f3c65f1b3ca52e11600acd // SHA256STAMP:a3a508935b99ff0b985d0774432ae9d98f3ec7660bf4edf64095a3d0a37ba0e8

View File

@@ -166,7 +166,7 @@ msgtype,init_rbf,72
msgdata,init_rbf,channel_id,channel_id, msgdata,init_rbf,channel_id,channel_id,
msgdata,init_rbf,funding_satoshis,u64, msgdata,init_rbf,funding_satoshis,u64,
msgdata,init_rbf,locktime,u32, msgdata,init_rbf,locktime,u32,
msgdata,init_rbf,fee_step,byte, msgdata,init_rbf,funding_feerate_perkw,u32,
msgtype,ack_rbf,73 msgtype,ack_rbf,73
msgdata,ack_rbf,channel_id,channel_id, msgdata,ack_rbf,channel_id,channel_id,
msgdata,ack_rbf,funding_satoshis,u64, msgdata,ack_rbf,funding_satoshis,u64,
1 msgtype,init,16
166 msgdata,init_rbf,channel_id,channel_id,
167 msgdata,init_rbf,funding_satoshis,u64,
168 msgdata,init_rbf,locktime,u32,
169 msgdata,init_rbf,fee_step,byte, msgdata,init_rbf,funding_feerate_perkw,u32,
170 msgtype,ack_rbf,73
171 msgdata,ack_rbf,channel_id,channel_id,
172 msgdata,ack_rbf,funding_satoshis,u64,

10
wire/peer_wiregen.c generated
View File

@@ -1623,7 +1623,7 @@ bool fromwire_accept_channel2(const void *p, struct channel_id *channel_id, stru
} }
/* WIRE: INIT_RBF */ /* WIRE: INIT_RBF */
u8 *towire_init_rbf(const tal_t *ctx, const struct channel_id *channel_id, struct amount_sat funding_satoshis, u32 locktime, u8 fee_step) u8 *towire_init_rbf(const tal_t *ctx, const struct channel_id *channel_id, struct amount_sat funding_satoshis, u32 locktime, u32 funding_feerate_perkw)
{ {
u8 *p = tal_arr(ctx, u8, 0); u8 *p = tal_arr(ctx, u8, 0);
@@ -1631,11 +1631,11 @@ u8 *towire_init_rbf(const tal_t *ctx, const struct channel_id *channel_id, struc
towire_channel_id(&p, channel_id); towire_channel_id(&p, channel_id);
towire_amount_sat(&p, funding_satoshis); towire_amount_sat(&p, funding_satoshis);
towire_u32(&p, locktime); towire_u32(&p, locktime);
towire_u8(&p, fee_step); towire_u32(&p, funding_feerate_perkw);
return memcheck(p, tal_count(p)); return memcheck(p, tal_count(p));
} }
bool fromwire_init_rbf(const void *p, struct channel_id *channel_id, struct amount_sat *funding_satoshis, u32 *locktime, u8 *fee_step) bool fromwire_init_rbf(const void *p, struct channel_id *channel_id, struct amount_sat *funding_satoshis, u32 *locktime, u32 *funding_feerate_perkw)
{ {
const u8 *cursor = p; const u8 *cursor = p;
size_t plen = tal_count(p); size_t plen = tal_count(p);
@@ -1645,7 +1645,7 @@ bool fromwire_init_rbf(const void *p, struct channel_id *channel_id, struct amou
fromwire_channel_id(&cursor, &plen, channel_id); fromwire_channel_id(&cursor, &plen, channel_id);
*funding_satoshis = fromwire_amount_sat(&cursor, &plen); *funding_satoshis = fromwire_amount_sat(&cursor, &plen);
*locktime = fromwire_u32(&cursor, &plen); *locktime = fromwire_u32(&cursor, &plen);
*fee_step = fromwire_u8(&cursor, &plen); *funding_feerate_perkw = fromwire_u32(&cursor, &plen);
return cursor != NULL; return cursor != NULL;
} }
@@ -2330,4 +2330,4 @@ bool fromwire_channel_update_option_channel_htlc_max(const void *p, secp256k1_ec
*htlc_maximum_msat = fromwire_amount_msat(&cursor, &plen); *htlc_maximum_msat = fromwire_amount_msat(&cursor, &plen);
return cursor != NULL; return cursor != NULL;
} }
// SHA256STAMP:aeea1df56a4d408e222ac2c9f2deb201fda3cd2062f3c65f1b3ca52e11600acd // SHA256STAMP:a3a508935b99ff0b985d0774432ae9d98f3ec7660bf4edf64095a3d0a37ba0e8

6
wire/peer_wiregen.h generated
View File

@@ -766,8 +766,8 @@ u8 *towire_accept_channel2(const tal_t *ctx, const struct channel_id *channel_id
bool fromwire_accept_channel2(const void *p, struct channel_id *channel_id, struct amount_sat *funding_satoshis, struct amount_sat *dust_limit_satoshis, struct amount_msat *max_htlc_value_in_flight_msat, struct amount_msat *htlc_minimum_msat, u32 *minimum_depth, u16 *to_self_delay, u16 *max_accepted_htlcs, struct pubkey *funding_pubkey, struct pubkey *revocation_basepoint, struct pubkey *payment_basepoint, struct pubkey *delayed_payment_basepoint, struct pubkey *htlc_basepoint, struct pubkey *first_per_commitment_point, struct tlv_accept_tlvs *tlvs); bool fromwire_accept_channel2(const void *p, struct channel_id *channel_id, struct amount_sat *funding_satoshis, struct amount_sat *dust_limit_satoshis, struct amount_msat *max_htlc_value_in_flight_msat, struct amount_msat *htlc_minimum_msat, u32 *minimum_depth, u16 *to_self_delay, u16 *max_accepted_htlcs, struct pubkey *funding_pubkey, struct pubkey *revocation_basepoint, struct pubkey *payment_basepoint, struct pubkey *delayed_payment_basepoint, struct pubkey *htlc_basepoint, struct pubkey *first_per_commitment_point, struct tlv_accept_tlvs *tlvs);
/* WIRE: INIT_RBF */ /* WIRE: INIT_RBF */
u8 *towire_init_rbf(const tal_t *ctx, const struct channel_id *channel_id, struct amount_sat funding_satoshis, u32 locktime, u8 fee_step); u8 *towire_init_rbf(const tal_t *ctx, const struct channel_id *channel_id, struct amount_sat funding_satoshis, u32 locktime, u32 funding_feerate_perkw);
bool fromwire_init_rbf(const void *p, struct channel_id *channel_id, struct amount_sat *funding_satoshis, u32 *locktime, u8 *fee_step); bool fromwire_init_rbf(const void *p, struct channel_id *channel_id, struct amount_sat *funding_satoshis, u32 *locktime, u32 *funding_feerate_perkw);
/* WIRE: ACK_RBF */ /* WIRE: ACK_RBF */
u8 *towire_ack_rbf(const tal_t *ctx, const struct channel_id *channel_id, struct amount_sat funding_satoshis); u8 *towire_ack_rbf(const tal_t *ctx, const struct channel_id *channel_id, struct amount_sat funding_satoshis);
@@ -859,4 +859,4 @@ bool fromwire_channel_update_option_channel_htlc_max(const void *p, secp256k1_ec
#endif /* LIGHTNING_WIRE_PEER_WIREGEN_H */ #endif /* LIGHTNING_WIRE_PEER_WIREGEN_H */
// SHA256STAMP:aeea1df56a4d408e222ac2c9f2deb201fda3cd2062f3c65f1b3ca52e11600acd // SHA256STAMP:a3a508935b99ff0b985d0774432ae9d98f3ec7660bf4edf64095a3d0a37ba0e8