-
Notifications
You must be signed in to change notification settings - Fork 421
Minimize reads to counterparty_claimable_outpoints #3057
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
Minimize reads to counterparty_claimable_outpoints #3057
Conversation
0ee0080 to
2081c15
Compare
Codecov ReportAll modified and coverable lines are covered by tests ✅
❗ Your organization needs to install the Codecov GitHub app to enable full functionality. Additional details and impacted files@@ Coverage Diff @@
## main #3057 +/- ##
==========================================
- Coverage 89.82% 89.76% -0.07%
==========================================
Files 116 116
Lines 96466 96466
Branches 96466 96466
==========================================
- Hits 86655 86591 -64
- Misses 7264 7311 +47
- Partials 2547 2564 +17 ☔ View full report in Codecov by Sentry. |
78fd449 to
3aea5ef
Compare
|
Now this PR should be ready for review. |
| let mut commitment_tx_to_counterparty_output = None; | ||
| if (tx.input[0].sequence.0 >> 8*3) as u8 == 0x80 && (tx.lock_time.to_consensus_u32() >> 8*3) as u8 == 0x20 { | ||
| let per_commitment_option = self.counterparty_claimable_outpoints.get(&tx.txid()).map(|x| x.iter() | ||
| .map(|&(ref a, ref b)| (a.clone(), b.clone())).collect::<Vec<_>>()); |
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.
Had to clone here because calling self.check_spend_counterparty_transaction needs a mut ref to self and without clone self.counterparty_claimable_outpoints.get will need a immut ref to self.
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.
Its not really a huge deal, but maybe that's an indication we're building the wrong API here - if we're passing a copy of some internal state to a method probably we should....not be doing that :). Instead, maybe we pass an override value (ie "i have this, dont look it up" and check_spend_counterparty_transaction can do a lookup if no override is provided.
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.
removed per_commitment_option from check_spend signature
|
This PR is ready for review and merging. |
| ($txid: expr, $commitment_tx: expr) => { | ||
| if let Some(ref latest_outpoints) = $self.counterparty_claimable_outpoints.get($txid) { | ||
| ($txid: expr, $commitment_tx: expr, $per_commitment_outpoints: expr) => { | ||
| if let Some(ref latest_outpoints) = $per_commitment_outpoints { |
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.
While you're here, mind seeing if you can make this a function instead of a macro?
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.
ok, i tried this.
Both check_htlc_fails and fail_unbroadcast_htlcs need mut refernce to self they push/delete from onchain_events_awaiting_threshold_conf.
and per_commitment_option uses a immut reference. so i don't think we can do it easily unless i use clone everywhere. (otherwise we somehow have to revamp onchain_events_awaiting_threshold_conf into return of fn or something.)
| /// transaction. | ||
| fn check_spend_counterparty_transaction<L: Deref>(&mut self, tx: &Transaction, height: u32, block_hash: &BlockHash, logger: &L) | ||
| -> (Vec<PackageTemplate>, TransactionOutputs, CommitmentTxCounterpartyOutputInfo) | ||
| fn check_spend_counterparty_transaction<L: Deref>(&mut self, tx: &Transaction, height: u32, block_hash: &BlockHash, per_commitment_option: Option<&Vec<(HTLCOutputInCommitment, Option<Box<HTLCSource>>)>>, logger: &L) |
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.
Do you want to go ahead and define a type for this? Doesn't really matter but might leave things cleaner in this 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.
i reverted this change to fn signature, since we are no longer re-using per_commitment_option b/w this and cancel_prev_claims.
We will need some more changes once we implement provide_claim_info, will see if need a new request type here then.
| let mut commitment_tx_to_counterparty_output = None; | ||
| if (tx.input[0].sequence.0 >> 8*3) as u8 == 0x80 && (tx.lock_time.to_consensus_u32() >> 8*3) as u8 == 0x20 { | ||
| let per_commitment_option = self.counterparty_claimable_outpoints.get(&tx.txid()).map(|x| x.iter() | ||
| .map(|&(ref a, ref b)| (a.clone(), b.clone())).collect::<Vec<_>>()); |
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.
Its not really a huge deal, but maybe that's an indication we're building the wrong API here - if we're passing a copy of some internal state to a method probably we should....not be doing that :). Instead, maybe we pass an override value (ie "i have this, dont look it up" and check_spend_counterparty_transaction can do a lookup if no override is provided.
| ($counterparty_txid: expr, $htlc_output: expr) => { | ||
| if let Some(txid) = $counterparty_txid { | ||
| for &(ref pending_htlc, ref pending_source) in self.counterparty_claimable_outpoints.get(&txid).unwrap() { | ||
| ($htlc_output: expr, $per_commitment_data: expr) => { |
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.
Same here, can this be an fn instead?
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 one should be doable,
but it is getting messy really quick, as args/vars for check_htlc_valid_counterparty/log_claim/sca_commitment are intertwined.
I can do this is separate PR.
its current signature as it is extracted to function looks like
fn check_htlc_valid_counterparty<L: Deref>(
&self, htlc_output: &HTLCOutputInCommitment, per_commitment_data: &[(HTLCOutputInCommitment, Option<Box<HTLCSource>>)],
htlc_claim: &Option<HTLCClaim>, input: &TxIn, txid: &Txid, logger: &WithChannelMonitor<L>,
) -> Option<(HTLCSource, PaymentHash, u64)> where L::Target: Logger {
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.
Part of #3076
59eb80e to
ea5f999
Compare
tnull
left a comment
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.
One question, one nit, otherwise LGTM.
3435f18 to
39900bb
Compare
| /// data in counterparty_claimable_outpoints. Will directly claim any HTLC outputs which expire at a | ||
| /// height > height + CLTV_SHARED_CLAIM_BUFFER. In any case, will install monitoring for | ||
| /// HTLC-Success/HTLC-Timeout transactions. | ||
| /// HTLC-Success/HTLC-Timeout transactions. This function should only be called when claimable HTLC |
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 really convinced pushing this on the caller makes sense either? Rather, ISTM it would make sense for this function to just be retryable - we call it whenever we think we have a transaction for it, it tries to use the transaction and if it finds it needs some per_commitment data that it doesn't have it just returns and expects to be called again later.
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.
after everything related to 3049 is done,
we will call this function directly when tx is current/prev commitment tx.
otherwise we will call it once ClaimInfo is provided to us by the user.
So this function should always have per_commitment_data. This updated docs doesn't change anything, it was already working with such presumption.
why add the complexity which might never be 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.
Then I'm quite confused what we're building to - in your first version of the patch you wanted to pass the the counterparty_claimable_outpoints lookup result to this method which resulted in a double-self-mut-reference, so I suggested that that is probably not the right API. This implies we shouldn't be doing the counterparty_claimable_outpoints lookup at the callsite at all (as it would then be duplicated in check_spend_counterparty_transaction), but rather that we should consider handling the "can I do something or do I need to ask for ClaimInfo" decision inside of check_spend_counterparty_transaction.
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.
in your first version of the patch you wanted to pass the the counterparty_claimable_outpoints lookup result to this method
Yes earlier i was re-using counterparty_claimable_outpoints b/w check_spend and cancel_prev_commitment_claims, but i had to revert that change, i was using it incorrectly.
now, since that re-using is no longer required, check_spend can do a lookup internally. There won't be any duplicate lookup for counterparty_claimable_outpoints.
we will publish ClaimInfoRequest once and after receiving ClaimInfo, we will call check_spend and update_claims_view_from_requests
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 can remove this comment if that unblock this PR and we can tackle this when we are actually going to use ClaimInfo.
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.
now, since that re-using is no longer required, check_spend can do a lookup internally. There won't be any duplicate lookup for counterparty_claimable_outpoints. we will publish ClaimInfoRequest once and after receiving ClaimInfo, we will call check_spend and update_claims_view_from_requests
Okay, then I'm very confused why you added this comment here - it seems like we're on the same page that we can call check_spend_counterparty_transaction no matter if we have claim info available or not, and we'll simply let it fail in cases where counterparty_claimable_outpoints doesn't have anything and no ClaimInfo is available?
I can remove this comment if that unblock this PR and we can tackle this when we are actually going to use ClaimInfo.
That's fine, but I'd very much like to make sure we're on the same page in terms of how this is going to work.
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.
but I'd very much like to make sure we're on the same page in terms of how this is going to work.
Yes i will sync with you offline.
I think you are right, i missed the part where we need to check if we should publish ClaimInfoRequest, we will have to access counterparty_claimable_outpoints there.
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.
Removed the comment.
Reads related to current/previous commitment_tx should be explicit and reads related to older commitment_txs should be minimized.
39900bb to
1690c66
Compare
| if counterparty_commitment_txid == confirmed_commitment_txid { | ||
| continue; | ||
| } | ||
| // If we have generated claims for counterparty_commitment_txid earlier, we can rely on always |
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 is fine but we'll need to make sure we explicitly skip any pruning step when we receive a new revocation secret if we've seen the channel close already.
|
The only change from @tnull's previous ACK is the following, so gonna merge: diff --git a/lightning/src/chain/channelmonitor.rs b/lightning/src/chain/channelmonitor.rs
index 0dda18629..7a6551bab 100644
--- a/lightning/src/chain/channelmonitor.rs
+++ b/lightning/src/chain/channelmonitor.rs
@@ -3232,4 +3232,3 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
/// height > height + CLTV_SHARED_CLAIM_BUFFER. In any case, will install monitoring for
- /// HTLC-Success/HTLC-Timeout transactions. This function should only be called when claimable HTLC
- /// data is available in `counterparty_claimable_outpoints`.
+ /// HTLC-Success/HTLC-Timeout transactions.
/// |
As part of #3049