-
Notifications
You must be signed in to change notification settings - Fork 407
Do not test any block-contents-rescan cases #715
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
Do not test any block-contents-rescan cases #715
Conversation
We'd previously largely not turned on derive(Debug) on any of our structs, but not for good reason. Especially for Events objects, Debug can be a very useful for users to quickly print what they received from us without having to write out a large match.
Add a few comments to make it clear whats going on a bit more and don't test/confirm a bogus transaction.
Note that this does not update any docs (though that is absolutely necessary for release), its presumed that 649 will rewrite most of the docs anyway, so no need to update them here. |
Codecov Report
@@ Coverage Diff @@
## main #715 +/- ##
==========================================
+ Coverage 91.91% 92.00% +0.08%
==========================================
Files 36 36
Lines 20161 20200 +39
==========================================
+ Hits 18531 18585 +54
+ Misses 1630 1615 -15
Continue to review full report at Codecov.
|
Add a few comments to make it clear whats going on a bit more and don't test/confirm a double-spend transaction.
b8d0a7f
to
b63ab7d
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'm leaning about pushing this PR further and remove bogus transactions generation. We may have a helper running before OnchainTxHandler::block_connected
sanitizing disjunctive outpoints, like sanitize_outpoints(txn_matched, claimable_outpoints)
assert_eq!(node_txn[0].input[0].previous_output, revoked_htlc_txn[0].input[0].previous_output); | ||
assert_eq!(node_txn[1].input[0].previous_output, revoked_htlc_txn[1].input[0].previous_output); | ||
|
||
// node_txn[3] is the local commitment tx broadcast just because (and somewhat in case of |
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.
"Just because of remote force-closing". But I think this local broadcast isn't really worthy as this transaction is double-spending a already confirmed and will never propagate.
I think that future work should remove this behavior and we should only broadcast holder commitment when a) a off-chain condition is detected, or b) holder request, or c) HTLC to claim on-chain. But not in reaction to confirmation of counterparty commitment.
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.
Right, sure, there's definitely room to improve things, but at least for the local-commitment copy we'd need to store it somewhere for broadcast-on-reorg, which we don't currently do.
@@ -377,10 +377,19 @@ impl ChainWatchInterface for ChainWatchInterfaceUtil { | |||
|
|||
fn filter_block(&self, block: &Block) -> Vec<usize> { | |||
let mut matched_index = Vec::new(); | |||
let mut match_set = HashSet::new(); |
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 know how long this function will live but in the meanwhile IMO it's clearer if we call this variable descendants_matched
as it underscores better that those transactions are captured in reason of their parents succeeding does_match_tx_unguarded
.
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 depend on the context. That naming would apply to inserting into the set, but with membership checks "ancestor" rather than "descendant" would be an accurate naming.
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.
Lets not bikeshed a name that will be removed asap.
if self.does_match_tx_unguarded(transaction, &watched) { | ||
let mut matched = self.does_match_tx_unguarded(transaction, &watched); | ||
for input in transaction.input.iter() { | ||
if matched || match_set.contains(&input.previous_output.txid) { |
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 you want to break early from iteration on a already-matched transaction, scope code in a conditional if !matched {}
, it would make code clearer.
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, hopefully that's clear, but its also nice to break when we hit the contains case too :)
assert_eq!(node_txn[0].input.len(), 2); | ||
check_spends!(node_txn[0], revoked_local_txn[0]); | ||
assert_eq!(node_txn[0].input.len(), 3); | ||
check_spends!(node_txn[0], revoked_local_txn[0], revoked_htlc_txn[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.
I observed the logs and here the new behavior:
- detection of revoked commitment and revoked htlc-timeout by ChannelMonitor
- aggregation of revoked outputs in one claim tx by OnchainTxHandler, broadcast of node_txn[0]
- detection of revoked htlc-timeout which double-spend a registered claim by OnchainTxHandler, broadcast of node_txn[1]
- feerate of node_txn[1] is wrongly bumped as we don't dissociate clearly the reschedule source either double-spend or internal block timer expiration
I think either ChannelMonitor or OnchainTxHandler should sanitize claimable outpoints and ensure there is no disjunctive ones.
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.
Is there something you think should be changed here? I agree eventually we should be more careful about the txn we generate, but we should be pretty confident when we do that - I'd rather air on the side of over-broadcasting invalid crap than ever miss a claim, of course, and this PR is a bit more time-critical as its blocking 649.
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.
There is currently an overpaid fee bug due to this behavior which should be fixed. But I'm also thinking we should rework our aggregation logic to avoid exploitation. Let's address this further.
Hmm, that's a lot of work (and, as you pointed out on IRC, in many cases not practical at all), and seems somewhat orthogonal to fixing tests. There is some generation that is obviously a double-spend, but for the most part we just generate a lot of transactions which are theoretically valid in a reorg case. |
Add a few comments to make it clear whats going on a bit more and assert the basic structure of more transactions. Further, point out where transactions are double-spends and don't confirm double-spends.
In anticipation for removing support for users calling block_connected multiple times for the same block to include all relevant transactions in the next PR, this commit stops testing such cases. Specifically, users who filter blocks for relevant transactions before calling block_connected will need to filter by including any transactions which spend a previously-matched transaction in the same block (and we now do so in our own filtering logic, which is also used in our testing).
b63ab7d
to
38dacf1
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.
Overall LGTM
if node_txn[0].input[0].previous_output == revoked_htlc_txn[0].input[0].previous_output { | ||
assert_eq!(node_txn[1].input[0].previous_output, revoked_htlc_txn[1].input[0].previous_output); | ||
} else { | ||
assert_eq!(node_txn[0].input[0].previous_output, revoked_htlc_txn[1].input[0].previous_output); | ||
assert_eq!(node_txn[1].input[0].previous_output, revoked_htlc_txn[0].input[0].previous_output); | ||
} |
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 my own understanding, is there some non-determinism that can't be eliminated from how transactions are broadcast? Given these are accumulated in a vector (at least in TestBroadcaster
), could they be sorted in some manner prior to making these asserts?
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.
Honestly, I didn't dig too far into it, just noted that it broke the test non-deterministically and fixed it up.
Code Review ACK 38dacf1 |
This is in preparation for #649 removing support for block rescan wholesale, fixing the tests which rely on it and are overly-specific. It doesn't really address the fact that the tests are over-specific (though does address a few cases where we're confirming double-spends in blocks in tests), but should at least make it so that #649 can make progress.