Introduce splice-compatible commitment update monitor variants#3855
Conversation
|
👋 Thanks for assigning @tankyleo as a reviewer! |
| let htlcs_for_commitment = |commitment: &CommitmentTransaction| { | ||
| let mut nondust_htlcs = commitment.nondust_htlcs().clone().into_iter(); | ||
| let mut sources = htlc_data.nondust_htlc_sources.clone().into_iter(); |
There was a problem hiding this comment.
I'm not too happy with this, but trying to not duplicatively track the HTLC sources across FundingScopes is a good bit of non-trivial work. At least they'll only exist in the current and previous counterparty commitments, but those are still per FundingScope. The simplest thing we could do for now is Arc them to reduce memory bandwidth (unfortunately on disk we'll still have duplicates), but I chose not to pursue that unless we're sure of it.
There was a problem hiding this comment.
Given its just for the latest and prev commitment txn I feel like its okay. It also gives us room to relax the restriction on multiple splices having the same dust/non-dust HTLC sets in the future.
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #3855 +/- ##
==========================================
- Coverage 89.65% 88.80% -0.86%
==========================================
Files 164 165 +1
Lines 134658 119288 -15370
Branches 134658 119288 -15370
==========================================
- Hits 120734 105937 -14797
+ Misses 11246 11020 -226
+ Partials 2678 2331 -347 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
tankyleo
left a comment
There was a problem hiding this comment.
Thanks dude, just went through the first commit, will continue tomorrow. I have a big-picture question in commitment_signed_batch take a look at that first.
| let msg = messages | ||
| .get(&funding_txid) | ||
| .ok_or_else(|| ChannelError::close(format!("Peer did not send a commitment_signed for pending splice transaction: {}", funding_txid)))?; | ||
| let (commitment_tx, htlcs_included) = self.context.validate_commitment_signed( |
There was a problem hiding this comment.
It might not be worth the pain let me know:
Can we avoid doing the work of populating and sorting this table for all the pending scopes in build_commitment_transaction ? We only need it for the current scope here.
(In validate_commitment_signed, let's read the HTLCs from the commitment transaction instead of the HTLC-source table).
Also wondering if we can make the state and dust-vs-nondust HTLC sorting only once for all scopes.
There was a problem hiding this comment.
Hm yeah this would be nice, this code was mostly written before we made the change to populate the source table separately. I wouldn't consider it a blocker to this PR, unless @TheBlueMatt feels strongly.
tankyleo
left a comment
There was a problem hiding this comment.
Went through the second commit, some similar questions, some new ones.
| self.counterparty_hash_commitment_number.insert(htlc.payment_hash, commitment_number); | ||
| } | ||
|
|
||
| log_trace!(logger, "Tracking new counterparty commitment transaction with txid {} at commitment number {} with {} HTLC outputs", txid, commitment_number, htlc_outputs.len()); |
There was a problem hiding this comment.
You find this log not necessary ?
There was a problem hiding this comment.
@wpaulino just want to confirm here - i think the worry is hey these could be used to cheat so make sure we are tracking them ?
|
🔔 1st Reminder Hey @TheBlueMatt! This PR has been waiting for your review. |
|
🔔 2nd Reminder Hey @TheBlueMatt! This PR has been waiting for your review. |
| let htlcs_for_commitment = |commitment: &CommitmentTransaction| { | ||
| let mut nondust_htlcs = commitment.nondust_htlcs().clone().into_iter(); | ||
| let mut sources = htlc_data.nondust_htlc_sources.clone().into_iter(); |
There was a problem hiding this comment.
Given its just for the latest and prev commitment txn I feel like its okay. It also gives us room to relax the restriction on multiple splices having the same dust/non-dust HTLC sets in the future.
7f942f4 to
fedd0ff
Compare
fedd0ff to
0e88cdf
Compare
tankyleo
left a comment
There was a problem hiding this comment.
Another pass on the first commit, will continue first thing tomorrow...
tankyleo
left a comment
There was a problem hiding this comment.
Done with the two other commits
|
🔔 1st Reminder Hey @TheBlueMatt! This PR has been waiting for your review. |
|
Mind addressing @tankyleo's feedback? |
This new variant is a backwards-incompatible successor to `LatestHolderCommitmentTXInfo` that is capable of handling holder commitment updates while a splice is pending. Since all holder commitment candidates share the same set of non-dust and dust HTLCs (though each non-dust HTLC can have differing output indices), we can share the same set of HTLC source data across all candidates.
This new variant is a backwards-incompatible successor to `LatestCounterpartyCommitmentTXInfo` that is capable of handling counterparty commitment updates while a splice is pending. Since all counterparty commitment candidates share the same set of non-dust and dust HTLCs (though each non-dust HTLC can have differing output indices), we can share the same set of HTLC source data across all candidates. Unfortunately, each `FundingScope` tracks its own set of `counterparty_claimable_outpoints`, which includes the HTLC source data (though only for the current and previous counterparty commitments), so we end up duplicating it (both in memory and on disk) temporarily.
They don't need to be tracked as we can recompute them easily, though we still write them in the `ChannelMonitor` for the current `FundingScope` for backwards compatibility. The serialization implementation for `FundingScope` can now use the `impl_writeable_tlv_based` macro as a result.
0e88cdf to
4dc47f9
Compare
| fn update_counterparty_commitment_data( | ||
| &mut self, commitment_txs: &[CommitmentTransaction], htlc_data: &CommitmentHTLCData, | ||
| ) -> Result<(), &'static str> { | ||
| self.verify_matching_commitment_transactions(commitment_txs.iter())?; |
There was a problem hiding this comment.
The function verify_matching_commitment_transactions returns a Result, but the error case isn't being handled here. Consider propagating the error back to the caller by changing this to:
self.verify_matching_commitment_transactions(commitment_txs.iter())?;This matches the pattern used in update_holder_commitment_data and ensures errors aren't silently ignored.
Spotted by Diamond
Is this helpful? React 👍 or 👎 to let us know.
|
🔔 1st Reminder Hey @TheBlueMatt @tankyleo! This PR has been waiting for your review. |
1 similar comment
|
🔔 1st Reminder Hey @TheBlueMatt @tankyleo! This PR has been waiting for your review. |
|
|
||
| let current_funding_commitment_tx = commitment_txs.first().unwrap(); | ||
| self.current_holder_commitment_number = current_funding_commitment_tx.commitment_number(); | ||
| self.onchain_tx_handler.provide_latest_holder_tx(current_funding_commitment_tx.clone()); |
There was a problem hiding this comment.
Mind leaving a comment here on why OnchainTxHandler doesn't need to know about other commitments?
| let source = (!htlc.offered).then(|| { | ||
| let source = sources | ||
| .next() | ||
| .expect("Every inbound non-dust HTLC should have a corresponding source") |
There was a problem hiding this comment.
We generally call these "outbound" HTLCs, since they're outbound, just !offered on the commitment tx.
There was a problem hiding this comment.
Ah yes my bad should be every outbound :)
tankyleo
left a comment
There was a problem hiding this comment.
Nothing blocking, just have a pending question further above about why we delete
log_trace!(logger, "Tracking new counterparty commitment transaction with txid {} at commitment number {} with {} HTLC outputs", txid, commitment_number, htlc_outputs.len());
|
Landing this, we can figure out the logging and comments in a followup. |
No description provided.