Skip to content

Expose new BumpChannelClose event for channels with anchor outputs #1689

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

Merged

Conversation

wpaulino
Copy link
Contributor

@wpaulino wpaulino commented Aug 31, 2022

This PR introduces a new BumpChannelClose event to be consumed by users indicating that they should craft a proper child anchor transaction with a sufficient feerate to increase the commitment transaction's (its parent) feerate and help get it confirmed.

Future work will also feature a similar event to bump the fees of HTLC success and timeout transactions.

@wpaulino wpaulino force-pushed the anchors-bump-channel-close-event branch from ab79496 to 0e079cd Compare August 31, 2022 22:58
@codecov-commenter
Copy link

codecov-commenter commented Aug 31, 2022

Codecov Report

Base: 90.79% // Head: 90.49% // Decreases project coverage by -0.29% ⚠️

Coverage data is based on head (5478ef6) compared to base (6738fd5).
Patch coverage: 58.70% of modified lines in pull request are covered.

❗ Current head 5478ef6 differs from pull request most recent head e159214. Consider uploading reports for the commit e159214 to get more accurate results

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #1689      +/-   ##
==========================================
- Coverage   90.79%   90.49%   -0.30%     
==========================================
  Files          87       87              
  Lines       46969    46863     -106     
  Branches    46969    46863     -106     
==========================================
- Hits        42646    42410     -236     
- Misses       4323     4453     +130     
Impacted Files Coverage Δ
lightning/src/chain/keysinterface.rs 90.89% <0.00%> (-1.65%) ⬇️
lightning/src/util/events.rs 36.95% <0.00%> (-1.19%) ⬇️
lightning/src/ln/chan_utils.rs 93.99% <14.28%> (-0.56%) ⬇️
lightning/src/chain/channelmonitor.rs 89.77% <52.08%> (-1.44%) ⬇️
lightning/src/chain/onchaintx.rs 88.16% <54.16%> (-7.47%) ⬇️
lightning/src/chain/package.rs 91.59% <80.80%> (-1.46%) ⬇️
lightning/src/util/wakers.rs 86.70% <0.00%> (-4.86%) ⬇️
lightning/src/chain/mod.rs 63.63% <0.00%> (-4.55%) ⬇️
lightning/src/routing/gossip.rs 91.44% <0.00%> (-0.72%) ⬇️
... and 11 more

Help us with your feedback. Take ten seconds to tell us how you rate us. Have a feature suggestion? Share it here.

☔ View full report at Codecov.
📢 Do you have feedback about the report comment? Let us know in this issue.

Copy link
Collaborator

@TheBlueMatt TheBlueMatt left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Didn't really dig into anything, just looking at the high-level.

@wpaulino wpaulino force-pushed the anchors-bump-channel-close-event branch from 0e079cd to 937017e Compare September 14, 2022 23:23
@wpaulino
Copy link
Contributor Author

Rebased on latest main and addressed pending comments.

Copy link

@ariard ariard left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm Approach ACK on both the BumpTransaction enum, the data scope returned back to the user and the event itself. To be looked more, the callsites where we're triggering the event, to see if there is way to simplify or clean paths.

log_debug!(logger, "Finalized transaction {} ready to broadcast", bumped_tx.txid());
Some(bumped_tx)
}
pub(crate) fn finalize_untractable_package<L: Deref, Signer: Sign>(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think "intractable" is the more common form

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"untractable" is already used quite a bit across the codebase, I'd prefer having a separate PR to only do the rename.

@wpaulino wpaulino force-pushed the anchors-bump-channel-close-event branch from 937017e to 21ad8f4 Compare September 19, 2022 23:24
Copy link
Collaborator

@TheBlueMatt TheBlueMatt left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some quick comments, will take a further look later.

let package_feerate = Self::compute_feerate(previous_package_feerate, fee_estimator, conf_target);
// With the new package feerate obtained, compute the feerate the child transaction must
// meet such that the package feerate is met.
(package_feerate as u64).checked_mul(2).map(|f| f.checked_sub(parent_feerate)).flatten()
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmmmm, how do we handle the 1-sat/vb initial fee requirement? If our target ends up being, eg, 1sat/vb can we end up returning something lower here? Also, can we just subtract here? Don't we have to weigh it by the weight of the two transactions?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The issue here is that we don't know the weight of the child transaction yet as it will be created by the event consumer.

After dwelling on #1689 (comment), it may be better to expose a ConfirmationTarget instead of a feerate to indicate the confirmation urgency. The yet to be developed middleware can then handle mapping it to an appropriate feerate as it will have all the context required to do so properly.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, yea....somehow the consumer has to be able to track the specific transaction, though. We generally try to avoid assuming the fee estimator is correct, or that it responds quickly if the mempool is actively filling up (because some explicitly don't). Thus, we really need to make sure it's easy to track what feerate was used on the previous transaction not just what the target is.

I guess we could just expose the target feerate and let the user do the averaging?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah that should work. We can then expose a helper method that does the averaging for the user.

@wpaulino wpaulino force-pushed the anchors-bump-channel-close-event branch 2 times, most recently from 4aff3e2 to 974c96f Compare September 23, 2022 21:51
#[derive(PartialEq, Eq, PartialOrd, Ord)]
pub(crate) enum ClaimEvent {
BumpCommitment {
target_feerate_sat_per_1000_weight: u32,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: Just grepping around and see we have this identifier but with plural sats.

Suggested change
target_feerate_sat_per_1000_weight: u32,
target_feerate_sats_per_1000_weight: u32,

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like we just use both interchangeably across the codebase. Would prefer deferring a consistent rename change to a distinct PR.

Copy link

@ariard ariard left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Still have to review some of the changes in package.rs, looks good overall.

Thanks for dealing with the rather murky package API, my apologies for the lack of documentation there.

@wpaulino wpaulino force-pushed the anchors-bump-channel-close-event branch from 974c96f to 5748ec9 Compare September 29, 2022 19:27
Copy link
Collaborator

@TheBlueMatt TheBlueMatt left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Basically LGTM.

@wpaulino wpaulino force-pushed the anchors-bump-channel-close-event branch 3 times, most recently from 0a0216b to 5478ef6 Compare October 6, 2022 19:38
Copy link

@ariard ariard left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we're good though I'm blocking a bit as using #[cfg(test)] TODO: remove-on-anchors-release to feature gate anchor output support. I can't remember we have gradually release sophisticated feature in the past, so sounds a first time. While I think it's worthy to do so in the present case I don't know if it's the best approach, see comment.

let commitment_package = PackageTemplate::build_package(
self.funding_info.0.txid.clone(), self.funding_info.0.index as u32,
PackageSolvingData::HolderFundingOutput(funding_output),
best_block_height, false, best_block_height,
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For builders/helpers in safety-critical parts, we could start to document the boolean argument at the caller call-site, i.e "/* aggregable */ false". It sounds a code style sophistication, though we already do that on the Core-side. As the codebase keeps growing I think this could be a good practice as a argument misusage could introduce a logical bug. E.g, aggregating a PackageMalleability::Untractable and a PackageMalleability::Malleable together triggering a panic!(). Already seen that type of bug sticking for years in Core.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will address this as a separate PR.

// attempt to broadcast the transaction with its current fee rate and hope
// it confirms. This is essentially the same behavior as a commitment
// transaction without anchor outputs.
None => Some((None, 0, OnchainClaim::Tx(tx.clone()))),
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IIRC, the case where we don't find a second anchor output for the channel is when we have no fund at stakes in the channel (no-htlc, no-balance) output. We could consider the channel early closed and return a OnchainEvent::ChannelClosed, to allow consumer to react in consequence.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like the idea, but seems out of scope for this PR.

@@ -2299,6 +2321,39 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
pub fn get_and_clear_pending_events(&mut self) -> Vec<Event> {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should update ChainMonitor::process_pending_events in consequence, noticing the user that this call is from now on important for the funds safety and call frequence should at least match every block ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done. I wonder if the ChainMonitor should just do this itself if any anchor channels are present. Would it be considered a violation of the events API?

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah we can do in a follow-up.

@wpaulino wpaulino force-pushed the anchors-bump-channel-close-event branch 2 times, most recently from 46f35c0 to e159214 Compare October 11, 2022 20:25
@wpaulino
Copy link
Contributor Author

Had to rebase on main to address a conflict. The previous push includes changes addressing latest round of feedback.

arik-so
arik-so previously approved these changes Oct 11, 2022
Copy link

@ariard ariard left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ACK e159214

Copy link

@ariard ariard left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ACK c963d3a

TheBlueMatt
TheBlueMatt previously approved these changes Oct 17, 2022
Copy link
Collaborator

@TheBlueMatt TheBlueMatt left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. There's a few followups but ideally let's just land this and we can do them later.

Some((idx, _)) => {
// Our target feerate will depend on whether we have any HTLCs present
// within our commitment.
let conf_target = if self.holder_commitment.trust().htlcs().is_empty() {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We may have a unrevoked counterparty commitment that does contain HTLCs, I think, so we should check for that or just always use highpriority. Happy to see it as a followup so we can land this.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since the counterparty commitment isn't exposed to the OnchainTxHandler, I reverted to always using HighPriority and added a todo.

&Event::BumpTransaction(ref event)=> {
27u8.write(writer)?;
match event {
// We never write the ChannelClose events as they'll be replayed upon restarting
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm a little dubious of the never-write here. While we should generate a new bump eventually, we may take a few blocks to do so, and dropping the event may waste a few blocks' time, which seems bad?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was thinking it would be fine as long as we always use a soonest_conf_deadline of our best known height (which is currently the case). get_height_timer will then force a retry at the next block.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yea, we should reconsider that at some point, though, IIUC that will do an RBF bump at every block, which may mean bumping the fee by 25% every block, which seems like a lot? Not something for this PR, though.

@TheBlueMatt
Copy link
Collaborator

Oops, needs rebase now, sorry about that. Feel free to tackle some of the above when you do so.

arik-so
arik-so previously approved these changes Oct 18, 2022
As we integrate the support of anchor outputs, we'll want to know if
each input we're working with came from an anchor outputs channel.
Instead of threading through a `opt_anchors` boolean across several
methods on `PackageSolvingData` and `PackageTemplate`, we decide to
store a reference in each `PackageSolvingData` variant instead that
features a change in behavior between channels with and without anchor
outputs.
This will be useful later on when determining the appropriate fee rate
to use on the anchor transaction to bump its commitment transaction.
@wpaulino wpaulino dismissed stale reviews from arik-so and TheBlueMatt via abe85a1 October 18, 2022 19:27
@wpaulino wpaulino force-pushed the anchors-bump-channel-close-event branch from c963d3a to abe85a1 Compare October 18, 2022 19:27
@TheBlueMatt TheBlueMatt merged commit 95bb27a into lightningdevkit:main Oct 19, 2022
@wpaulino wpaulino deleted the anchors-bump-channel-close-event branch October 19, 2022 00:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants