-
Notifications
You must be signed in to change notification settings - Fork 403
Fix min relay fee to be 1s/vB #3457
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
b8f4153
to
7d6b1f3
Compare
Codecov ReportAll modified and coverable lines are covered by tests ✅
Additional details and impacted files@@ Coverage Diff @@
## main #3457 +/- ##
==========================================
+ Coverage 88.43% 89.04% +0.60%
==========================================
Files 149 149
Lines 113302 118322 +5020
Branches 113302 118322 +5020
==========================================
+ Hits 100203 105362 +5159
+ Misses 10631 10511 -120
+ Partials 2468 2449 -19 ☔ View full report in Codecov by Sentry. |
@@ -176,7 +176,7 @@ pub trait FeeEstimator { | |||
} | |||
|
|||
/// Minimum relay fee as required by bitcoin network mempool policy. | |||
pub const MIN_RELAY_FEE_SAT_PER_1000_WEIGHT: u64 = 4000; | |||
pub const MIN_RELAY_FEE_SAT_PER_1000_WEIGHT: u64 = 253; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could we delete this in favor of FEERATE_FLOOR_SATS_PER_KW
below ? Different types, but same number.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think we can, because one is the regular broadcast fee rate, and the other is the eviction/incremental fee rate per RBF rule 4 (https://gist.github.com/glozow/25d9662c52453bd08b4b4b1d3783b9ff)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
that said, looking at these values
"mempoolminfee": 0.00001373,
"minrelaytxfee": 0.00001000,
"incrementalrelayfee": 0.00001000
I don't know when minrelaytxfee and incrementalrelayfee wouldn't align short of an explicit config change.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you where did you find them ? I've been grepping the bitcoin repo, can't see them.
I agree these are two different settings - I suggest we clarify one of them is the incremental fee rate, the other is the broadcast fee rate, as you've described - "MIN_RELAY_FEE" and "FEERATE_FLOOR" is a little too similar.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
oh I just called getmempoolinfo
on my node's RPC lol
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fair point, honestly both names suck
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
could use the names from bitcoin core, minrelaytxfee
and incrementalrelayfee
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
let's start with renaming minrelaytxfee to incrementalrelayfee for now, and we can get more ambitious with the other one in a separate PR
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It would be good to add some unit tests for feerate_bump
.
lightning/src/ln/functional_tests.rs
Outdated
@@ -1312,18 +1312,21 @@ fn test_duplicate_htlc_different_direction_onchain() { | |||
|
|||
let chan_1 = create_announced_chan_between_nodes(&nodes, 0, 1); | |||
|
|||
let payment_value_sats = 546; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why was the value changed to 546?
Also the naming is bound to cause confusion: payment_value_sats
sounds like it should correspond to the same payment as the payment_preimage
and payment_hash
variables, but it actually is a different payment.
Also, we should define the variables closer to where they are used.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I added a comment explaining the reasoning, and revised the variable once again. The fee bumping was succeeding much more often with the lower minrelayfee, resulting in indeterminism depending on whether the block connection style skipped intermediates or not. Now the value is fine-tuned to accommodate a single 25% fee bump.
lightning/src/ln/functional_tests.rs
Outdated
assert!(claim_txn.len() >= 3); | ||
assert!(claim_txn.len() <= 5); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't the claim transactions be deterministic? Why are we accepting a range of transactions now?
It would be good to add a comment explaining the transactions expected to be broadcast.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Funnily enough, with intermediate blocks being skipped, it is theoretically fine to have non-determinism, but I adjusted the values such that it can only happen once.
lightning/src/ln/functional_tests.rs
Outdated
let htlc_value_a_msats = 847_000; | ||
let htlc_value_b_msats = 546_000; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why are the payment values changed?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I added a comment explaining these. In principle they don't even have to differ, but both 842 and 843 only allow one bump. I could make one of them the necessary satoshi amount for two bumps - 1 if you like?
lightning/src/ln/functional_tests.rs
Outdated
assert_eq!(remote_txn[0].input[0].previous_output.txid, chan.3.compute_txid()); | ||
let chan = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1000000, 59000000); | ||
let (payment_preimage, payment_hash, ..) = route_payment(&nodes[0], &[&nodes[1]], htlc_value_a_msats); | ||
route_payment(&nodes[1], &vec!(&nodes[0])[..], htlc_value_b_msats).0; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Return value is unused.
route_payment(&nodes[1], &vec!(&nodes[0])[..], htlc_value_b_msats).0; | |
route_payment(&nodes[1], &vec!(&nodes[0])[..], htlc_value_b_msats); |
lightning/src/ln/functional_tests.rs
Outdated
assert_eq!(node_txn.len(), 3); | ||
// plus, depending on the block connection style, two further bumps | ||
assert!(node_txn.len() >= 3); | ||
assert!(node_txn.len() <= 6); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If additional bumps can occur, we should verify all of them below (not just the first bump).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
They no longer should be able to.
lightning/src/ln/functional_tests.rs
Outdated
// preimage and timeout sweeps from remote commitment + preimage sweep bump | ||
assert_eq!(node_txn.len(), 3); | ||
// plus, depending on the block connection style, two further bumps |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So the bumping strategy can vary depending on how the user calls the block connection APIs?
How specifically is bumping affected, and could this lead to transactions not confirming in time?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So technically it's not the bumping strategy as the block connection strategy. The bumping strategy is technically the same, but in one case there's a time jump and it lacks the opportunity to attempt intermediate bumps.
cd4c50f
to
1634965
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I still think it would be good to have unit tests specifically for feerate_bump
.
The CI incremental-mutants failure provides further evidence that such unit tests would be beneficial.
lightning/src/chain/package.rs
Outdated
} | ||
|
||
let new_feerate = new_fee * 1000 / predicted_weight; | ||
log_trace!(logger, "Fee rate bumped by {}s from {} s/KWU ({} s) to {} s/KWU ({} s) (naive: {} s/KWU ({} s))", new_fee - previous_fee, previous_feerate, previous_fee, new_feerate, new_fee, naive_new_feerate, naive_new_fee); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This naive feerate/fee logging is a little confusing. IMO we could just remove it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I felt it was quite valuable for debugging purposes seeing whether the bump would be failing simply due to the 25% increment or due to the incremental relay fee. Do you think perhaps a different phrasing might help?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the log message you added above clarifies things. We can remove the "(naive: ..)" logging from this log line now.
1634965
to
6aca2d3
Compare
You're right, I was just tinkering with some values for the test. The potential list of confirmation target / fee strategy combinations would be rather exhaustive, so I focused on the main scenario that was not previously being caught, but let me know if there are others you think I should add to the test. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Did the unit tests pass for you locally? At least one of them looks incorrect to me.
Also, I'm not sure we should be relying so heavily on pattern matching the logs. feerate_bump
is a pure function that we should be able to test by verifying outputs alone.
lightning/src/chain/package.rs
Outdated
} | ||
|
||
let new_feerate = new_fee * 1000 / predicted_weight; | ||
log_trace!(logger, "Fee rate bumped by {}s from {} s/KWU ({} s) to {} s/KWU ({} s) (naive: {} s/KWU ({} s))", new_fee - previous_fee, previous_feerate, previous_fee, new_feerate, new_fee, naive_new_feerate, naive_new_fee); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the log message you added above clarifies things. We can remove the "(naive: ..)" logging from this log line now.
lightning/src/chain/package.rs
Outdated
|
||
let remaining_output_amount = input_amounts - new_fee; | ||
if remaining_output_amount < dust_limit_sats { | ||
log_warn!(logger, "Can't new-estimation bump new claiming tx, output amount {} would end up below dust threshold {}", remaining_output_amount, dust_limit_sats); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: "new-estimation bump" seems confusing.
log_warn!(logger, "Can't new-estimation bump new claiming tx, output amount {} would end up below dust threshold {}", remaining_output_amount, dust_limit_sats); | |
log_warn!(logger, "Can't bump new claiming tx, output amount {} would end up below dust threshold {}", remaining_output_amount, dust_limit_sats); |
lightning/src/chain/package.rs
Outdated
|
||
let remaining_output_amount = input_amounts - bumped_fee; | ||
if remaining_output_amount < dust_limit_sats { | ||
log_warn!(logger, "Can't new-estimation bump new claiming tx, output amount {} would end up below dust threshold {}", remaining_output_amount, dust_limit_sats); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: "new-estimation bump" seems confusing.
log_warn!(logger, "Can't new-estimation bump new claiming tx, output amount {} would end up below dust threshold {}", remaining_output_amount, dust_limit_sats); | |
log_warn!(logger, "Can't bump new claiming tx, output amount {} would end up below dust threshold {}", remaining_output_amount, dust_limit_sats); |
lightning/src/chain/package.rs
Outdated
|
||
let bumped_fee_rate = feerate_bump(predicted_weight_units, input_satoshis, 546, 253, &fee_rate_strategy, confirmation_target, &fee_estimator, &logger); | ||
assert!(bumped_fee_rate.is_none()); | ||
logger.assert_log_regex("lightning::chain::package", regex::Regex::new(r"Can't new-estimation bump new claiming tx, output amount 545 would end up below dust threshold 546").unwrap(), 1); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This doesn't seem right...
- Weight: 1000
- Input amount: 861
- Previous feerate: 253
new_fee = max(1.25 * 253, 253 + 253) = 506
remaining_output_amount = 861 - 506 = 355
Yet test test expects output amount of 545.
What am I missing?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here it notices that the remaining amount is insufficient even before applying the min relay fee, which only happens at the end of feerate_bump. It's an early termination path.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Got it, thanks for explaining. By the way, it looks like that early termination path can be removed since the dust check is repeated here as well.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, I was wondering myself if I should add that. The reason I did was because there were a bunch of "amount too small" terminations specifically within the 25% bump clause, which I guess might be a helpful hint for users, but those checks would technically also be preëmpted by a single final check ensuring the remaining amount was at or above the dust threshold.
Technically this method could be cleaned up quite significantly, but at the potential expense of logic traceability. You figure that's a non-issue?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Or rather, because there was a 25%-bump-specific amount-too-small-check and one in the else clause, as opposed to a singular one that would come after the bump strategy processing.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My intuition is that during debugging most of the path can be inferred by the amount of the fee bump (e.g., is it 25% or the incremental relay fee), especially for a short, fairly simple function like this one. In cases where something unexpected could happen, that's when logging is more helpful.
For instance, I'm not sure it's super helpful to have logs like this:
... Initiating fee rate bump from X to Y.
... Attempting forced 25% fee rate bump from X to (X*1.25)
... Naive fee bump of (X*.25) does not meet min relay fee of 253
... Fee rate bumped by 253 from X to (X+253)
when something like this communicates almost as much:
... Fee rate bumped from X to X+253
So both the modified unit tests pass highly consistently for me; in fact, I haven't been able to get them to fail once, and I tried hard-coding the block connection strategies to ensure it worked for every single one. Can you elaborate on what looks wrong to you? The unit tests are now performing the same checks as they had been originally. |
6aca2d3
to
9db6c88
Compare
I was referring to the unit test that had a remaining output amount I didn't expect, which you clarified for me. The unit tests look correct to me, though I would prefer if they didn't rely so heavily on whitebox testing with the log pattern matching. It would also be good to add a short description to each test case explaining what it's testing. |
Ah gotcha. Yeah, I can remove the log output checks, and will add some comments |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Test changes lgtm, obv need squashed into the commit that broke the tests.
lightning/src/chain/package.rs
Outdated
// If old feerate inferior to actual one given back by Fee Estimator, use it to compute new fee... | ||
let (new_fee, new_feerate) = if let Some((new_fee, new_feerate)) = | ||
compute_fee_from_spent_amounts(input_amounts, predicted_weight, conf_target, fee_estimator, logger) | ||
{ | ||
log_trace!(logger, "Initiating fee rate bump from {} s/kWU ({} s) to {} s/kWU ({} s)", previous_feerate, previous_fee, new_feerate, new_fee); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since we're doing this on a timer for a rare event, we don't need to log as trace
and should log more at debug
or info
.
lightning/src/chain/package.rs
Outdated
@@ -1297,6 +1300,8 @@ where | |||
// ...else just increase the previous feerate by 25% (because that's a nice number) | |||
let bumped_feerate = previous_feerate + (previous_feerate / 4); | |||
let bumped_fee = bumped_feerate * predicted_weight / 1000; | |||
log_trace!(logger, "Attempting forced 25% fee rate bump from {} s/kWU ({} s) to {} s/kWU ({} s)", previous_feerate, previous_fee, bumped_feerate, bumped_fee); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Having two separate logs isn't communicating any additional new info that couln't be communicated in one log line if we included the FeerateStrategy
that was used in the first.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we don't get the post-25%-bump value in the first, which would just show something like "bump from 300 to 300"
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The last log communicates the ultimate bump calculation. The inclusion of a FeerateStategy
will provide anyone reading the code side-by-side with the log enough information to figure out which code path was taken.
lightning/src/chain/package.rs
Outdated
@@ -1306,6 +1307,13 @@ where | |||
log_warn!(logger, "Can't 25% bump new claiming tx, amount {} is too small", input_amounts); | |||
return None; | |||
} | |||
|
|||
let remaining_output_amount = input_amounts - bumped_fee; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure I understand the point of this commit (and the commit has no description in it to explain why). The logic is called from compute_package_output
which already does the appropriate max
before returning, so this just returns early and avoids bumping if we'll hit the dust limit, which I'm not sure accomplishes anything?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
compute_package_output does not update the returned fee rate if the dust threshold is violated, which resulted in bumping attempts growing ever more insane despite nothing happening, and the corresponding unit test failures. I can move this logic up into the calling function, but feerate_bump seems like the more appropriate place to enforce this invariant
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Doing the dust check in feerate_bump
sounds good to me. But we should also remove the now redundant max
from compute_package_output
.
9db6c88
to
5f60e51
Compare
lightning/src/chain/package.rs
Outdated
log_debug!(logger, "Naive fee bump of {}s does not meet min relay fee requirements of {}s", naive_new_fee - previous_fee, min_relay_fee); | ||
} | ||
|
||
let remaining_output_amount = input_amounts - new_fee; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yikes! The input_amounts <= bumped_fee
short-circuit was removed from the ForceBump
case above, so now we can get an unsigned underflow here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We actually still cannot, but you're right, this should be a saturating_sub.
622fe55
to
d93516b
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks pretty good to me.
I'll approve after the max
is removed from compute_package_output
and commits are squashed and cleaned up.
lightning/src/chain/package.rs
Outdated
@@ -1306,6 +1307,13 @@ where | |||
log_warn!(logger, "Can't 25% bump new claiming tx, amount {} is too small", input_amounts); | |||
return None; | |||
} | |||
|
|||
let remaining_output_amount = input_amounts - bumped_fee; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Doing the dust check in feerate_bump
sounds good to me. But we should also remove the now redundant max
from compute_package_output
.
Thanks! I'm also thinking of squishing commits "log fee bump process" into "enforce dust threshold" as well as reordering "test fee rate bumping" and "fix min relay" to ensure test integrity. |
d93516b
to
92fa97b
Compare
33f2880
to
02775fa
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
@morehouse you figure it would make sense to also add a fuzz test for feerate_bump? |
It couldn't hurt, I suppose. A fuzz test could assert that the dust limit is never violated and that the incremental fee rate is always satisfied when a fee bump occurs. It would also detect if the If you want to write the test, I'm happy to review it. |
Previously, the `feerate_bump` method did not enforce the dust threshold, which could result in us thinking we had raised the fee rate without actually having done so. Instead, `compute_package_output` blindly accepted the updated fee rate while enforcing a non-dust output value, resulting in repeated broadcast attempts of an identical transaction.
Bitcoin Core relay policy does not require 16s/vB, which it was previously set to.
Create some tests for various `feerate_bump` scenarios and ensure among other thigns that there are no underflows.
02775fa
to
8fd2dee
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Landing since @morehouse also said it looks good (and recently reviewed all this code).
@@ -1243,7 +1243,7 @@ impl Readable for PackageTemplate { | |||
/// fee and the corresponding updated feerate. If fee is under [`FEERATE_FLOOR_SATS_PER_KW`], we | |||
/// return nothing. | |||
/// | |||
/// [`FEERATE_FLOOR_SATS_PER_KW`]: crate::chain::chaininterface::MIN_RELAY_FEE_SAT_PER_1000_WEIGHT | |||
/// [`FEERATE_FLOOR_SATS_PER_KW`]: crate::chain::chaininterface::INCREMENTAL_RELAY_FEE_SAT_PER_1000_WEIGHT |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: update the text that's linking too, cause its weird to reference the name of a variable from two names ago :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This got merged without the fix, so I opened a trivial followup: #3565
Backported in #3567 |
v0.1.1 - Jan 28, 2025 - "Onchain Matters" API Updates =========== * A `ChannelManager::send_payment_with_route` was (re-)added, with semantics similar to `ChannelManager::send_payment` (rather than like the pre-0.1 `send_payent_with_route`, lightningdevkit#3534). * `RawBolt11Invoice::{to,from}_raw` were added (lightningdevkit#3549). Bug Fixes ========= * HTLCs which were forwarded where the inbound edge times out within the next three blocks will have the inbound HTLC failed backwards irrespective of the status of the outbound HTLC. This avoids the peer force-closing the channel (and claiming the inbound edge HTLC on-chain) even if we have not yet managed to claim the outbound edge on chain (lightningdevkit#3556). * On restart, replay of `Event::SpendableOutput`s could have caused `OutputSweeper` to generate double-spending transactions, making it unable to claim any delayed claims. This was resolved by retaining old claims for more than four weeks after they are claimed on-chain to detect replays (lightningdevkit#3559). * Fixed the additional feerate we will pay each time we RBF on-chain claims to match the Bitcoin Core policy (1 sat/vB) instead of 16 sats/vB (lightningdevkit#3457). * Fixed a cased where a custom `Router` which returns an invalid `Route`, provided to `ChannelManager`, can result in an outbound payment remaining pending forever despite no HTLCs being pending (lightningdevkit#3531). Security ======== 0.1.1 fixes a denial-of-service vulnerability allowing channel counterparties to cause force-closure of unrelated channels. * If a malicious channel counterparty force-closes a channel, broadcasting a revoked commitment transaction while the channel at closure time included multiple non-dust forwarded outbound HTLCs with identical payment hashes and amounts, failure to fail the HTLCs backwards could cause the channels on which we recieved the corresponding inbound HTLCs to be force-closed. Note that we'll receive, at a minimum, the malicious counterparty's reserve value when they broadcast the stale commitment (lightningdevkit#3556). Thanks to Matt Morehouse for reporting this issue.
Bitcoin Core relay policy does not require 16s/vB, which it was
previously set to.
This should address #3438.