-
Notifications
You must be signed in to change notification settings - Fork 411
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
Expose new BumpChannelClose event for channels with anchor outputs #1689
Conversation
ab79496
to
0e079cd
Compare
Codecov ReportBase: 90.79% // Head: 90.49% // Decreases project coverage by
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
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. |
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.
Didn't really dig into anything, just looking at the high-level.
0e079cd
to
937017e
Compare
Rebased on latest main and addressed pending 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.
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>( |
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 "intractable" is the more common form
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.
"untractable" is already used quite a bit across the codebase, I'd prefer having a separate PR to only do the rename.
937017e
to
21ad8f4
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.
Some quick comments, will take a further look later.
lightning/src/chain/package.rs
Outdated
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() |
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.
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?
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 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.
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.
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?
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 that should work. We can then expose a helper method that does the averaging for the user.
4aff3e2
to
974c96f
Compare
lightning/src/chain/onchaintx.rs
Outdated
#[derive(PartialEq, Eq, PartialOrd, Ord)] | ||
pub(crate) enum ClaimEvent { | ||
BumpCommitment { | ||
target_feerate_sat_per_1000_weight: u32, |
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: Just grepping around and see we have this identifier but with plural sats
.
target_feerate_sat_per_1000_weight: u32, | |
target_feerate_sats_per_1000_weight: u32, |
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 like we just use both interchangeably across the codebase. Would prefer deferring a consistent rename change to a distinct 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.
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.
974c96f
to
5748ec9
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.
Basically LGTM.
0a0216b
to
5478ef6
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 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, |
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.
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.
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.
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()))), |
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.
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.
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 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> { |
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 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 ?
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.
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?
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 we can do in a follow-up.
46f35c0
to
e159214
Compare
Had to rebase on main to address a conflict. The previous push includes changes addressing latest round of feedback. |
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.
ACK e159214
e159214
to
c963d3a
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.
ACK c963d3a
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. There's a few followups but ideally let's just land this and we can do them later.
lightning/src/chain/onchaintx.rs
Outdated
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() { |
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 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.
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 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 |
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 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?
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 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.
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.
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.
Oops, needs rebase now, sorry about that. Feel free to tackle some of the above when you do so. |
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.
c963d3a
to
abe85a1
Compare
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.