-
Notifications
You must be signed in to change notification settings - Fork 38.8k
test: wallet rescan with reorged parent + IsFromMe child in mempool #29179
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
Conversation
|
The following sections might be updated with supplementary metadata relevant to reviewers and maintainers. Code CoverageFor detailed information about the code coverage, see the test coverage report. ReviewsSee the guideline for information on the review process.
If your review is incorrectly listed, please react with 👎 to this comment and the bot will ignore it on the next update. ConflictsReviewers, this pull request conflicts with the following ones:
If you consider this pull request important, please also help to review the conflicting pull requests. Ideally, start with the one that should be merged first. |
|
Huh, looks like this behavior has been broken since it was introduced in #15652 |
|
ACK 1a52ca7619eeb1baafa5a32b364381126862b29d |
stickies-v
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.
Approach ACK, nice one finding this test case! 1a52ca7619eeb1baafa5a32b364381126862b29d looks good to me but not super familiar with this part of the code. Left some suggestions about maintainability and can be ignored.
I verified that the tests fail on #29019 as well as on 453b481~1, as is necessary.
1a52ca7 to
aa7eda3
Compare
furszy
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.
Pre-review note: have you considered that wallet_import_rescan.py is a legacy wallet only test?
If it's placed here due to a lack of alternatives, I think this could be moved to a separate wallet_mempool.py file, where we could continue adding more cases related to the wallet-mempool interaction (or.. we could upgrade this file to run on a descriptors wallet).
Ah good point. |
b4eafa3 to
aa7eda3
Compare
|
I'm working on adding a descriptors version of this test so we can have both. |
aa7eda3 to
86f5cc8
Compare
|
I've added another commit which has pretty much the same test but using descriptor wallets i.e. a rescan through |
86f5cc8 to
1b18ac4
Compare
1b18ac4 to
fa2b8d0
Compare
stickies-v
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.
Hooray for adding descriptor wallet support. Is there a reason both legacy and descriptor wallet tests aren't in the new wallet_rescan_unconfirmed test, though? That seems like a more logical grouping with less duplication? If there are technical objections, I think it would be good to add some extra documentation to both tests stating that the other wallet type is tested in file xxx.py, making it easier to clean up these tests e.g. when we drop legacy wallets or make other significant changes?
They use different RPCs. I think it's more readable for them to be separate (having most the test as |
fa2b8d0 to
d9df438
Compare
|
Tested ACK d9df438 Ran the tests locally and got |
stickies-v
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.
ACK d9df438c6e581dae0c818a4c2f5fe95627ae26bc
I think it's much easier to delete legacy without touching the descriptor one if they're in different files.
Thanks, you're right. There's less overlap than I thought there would be.
…empool Test that wallet rescans process transactions topologically, even if a parent's entry into the mempool is later than that of its child. This behavior is important because IsFromMe requires the ability to look up a transaction's inputs.
d9df438 to
c39e829
Compare
stickies-v
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.
re-ACK c39e829
|
CI failure is unrelated, #29234 |
furszy
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.
Code reviewed, looking good. Left few comments, mostly testing time improvements. Nothing blocking.
As the scenario being covered does not require verifying p2p mempool relay, you could speed up the new wallet_rescan_unconfirmed.py test by ~2.5x (tested locally, ~3 secs versus ~8 secs) by using a single node instead of creating three of them. See commit f827351 (feel free to pull it).
c39e829 to
9db0d42
Compare
stickies-v
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.
re-ACK 9db0d42509e0e223b45238fd8087fc98ef32c091
9db0d42 to
4d09fd0
Compare
…in mempool Test that wallet rescans process transactions topologically, even if a parent's entry into the mempool is later than that of its child. This behavior is important because IsFromMe requires the ability to look up a transaction's inputs. Co-authored-by: furszy <[email protected]>
4d09fd0 to
df30247
Compare
Sorry I hadn't seen this. Thanks, taken with a couple of edits. |
furszy
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.
Code review ACK df30247, nits can be disregarded.
| # inputs of the transaction to detect it, so the parent must be processed before the child. | ||
| w0_utxos = w0.listunspent() | ||
|
|
||
| self.log.info("Create a child tx and wait for it to propagate to all mempools") |
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:
leftover
| self.log.info("Create a child tx and wait for it to propagate to all mempools") | |
| self.log.info("Create a child tx and wait until all wallets are notified") |
| node.invalidateblock(block_to_reorg) | ||
| assert tx_parent_to_reorg["txid"] in node.getrawmempool() | ||
|
|
||
| self.log.info("Import descriptor wallet on another node") |
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:
leftover; should be "import descriptor on another wallet"
|
ACK df30247 |
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.
Post-merge re-ACK df30247, I was still investigating the non-deterministic behaviour in wallet_import_rescan but I've now found the issue and it doesn't seem problematic enough to revert or immediately fix.
When rebasing these tests on top of e.g. #29019 as well as on 453b4813ebc74859864803e9972b58e4be76a4d6~1, the mempool variant tests should fail for every variant where expect_rescan == True because in each case, only the parent is re-imported in the mempool (after re-org). However, when running the test multiple times one can observe this is not the case, and it sometimes takes 2 or even more rescan variants before the test fails.
log outputs
Expected failure logs:
...
2024-01-18T13:20:15.028000Z TestFramework (INFO): Test that the mempool is rescanned as well if the rescan parameter is set to true
2024-01-18T13:20:30.271000Z TestFramework (INFO): Run import for mempool variant Variant(call=<Call.single: 1>, data=<Data.address: 1>, address_type=<AddressType.bech32: 'bech32'>, rescan=<Rescan.no: 1>, prune=False)
2024-01-18T13:20:30.317000Z TestFramework (INFO): Run import for mempool variant Variant(call=<Call.single: 1>, data=<Data.address: 1>, address_type=<AddressType.bech32: 'bech32'>, rescan=<Rescan.yes: 2>, prune=False)
2024-01-18T13:20:30.388000Z TestFramework (ERROR): JSONRPC error
...
Actual failure logs, sometimes:
...
2024-01-18T13:25:50.799000Z TestFramework (INFO): Test that the mempool is rescanned as well if the rescan parameter is set to true
2024-01-18T13:26:06.108000Z TestFramework (INFO): Run import for mempool variant Variant(call=<Call.single: 1>, data=<Data.address: 1>, address_type=<AddressType.bech32: 'bech32'>, rescan=<Rescan.no: 1>, prune=False)
2024-01-18T13:26:06.164000Z TestFramework (INFO): Run import for mempool variant Variant(call=<Call.single: 1>, data=<Data.address: 1>, address_type=<AddressType.bech32: 'bech32'>, rescan=<Rescan.yes: 2>, prune=False)
2024-01-18T13:26:06.235000Z TestFramework (INFO): Run import for mempool variant Variant(call=<Call.single: 1>, data=<Data.address: 1>, address_type=<AddressType.p2sh_segwit: 'p2sh-segwit'>, rescan=<Rescan.no: 1>, prune=False)
2024-01-18T13:26:06.268000Z TestFramework (INFO): Run import for mempool variant Variant(call=<Call.single: 1>, data=<Data.address: 1>, address_type=<AddressType.p2sh_segwit: 'p2sh-segwit'>, rescan=<Rescan.yes: 2>, prune=False)
2024-01-18T13:26:06.341000Z TestFramework (INFO): Run import for mempool variant Variant(call=<Call.single: 1>, data=<Data.address: 1>, address_type=<AddressType.legacy: 'legacy'>, rescan=<Rescan.no: 1>, prune=False)
2024-01-18T13:26:06.374000Z TestFramework (INFO): Run import for mempool variant Variant(call=<Call.single: 1>, data=<Data.address: 1>, address_type=<AddressType.legacy: 'legacy'>, rescan=<Rescan.yes: 2>, prune=False)
2024-01-18T13:26:06.449000Z TestFramework (INFO): Run import for mempool variant Variant(call=<Call.single: 1>, data=<Data.pub: 2>, address_type=<AddressType.bech32: 'bech32'>, rescan=<Rescan.no: 1>, prune=False)
2024-01-18T13:26:06.494000Z TestFramework (INFO): Run import for mempool variant Variant(call=<Call.single: 1>, data=<Data.pub: 2>, address_type=<AddressType.bech32: 'bech32'>, rescan=<Rescan.yes: 2>, prune=False)
2024-01-18T13:26:06.578000Z TestFramework (ERROR): JSONRPC error
...
This happens because a chain of transactions can be formed, where variant_a.child_tx == variant_b.initial_txid, causing variant_a's child tx to be re-imported into the mempool when variant b's initial tx is re-orged.
I don't think this needs to be fixed or reverted, because if such a chain is formed, the last variant in the chain is still guaranteed to fail. The descriptor test is unaffected because we create only a single parent/child combo.
|
Reviewers might be interested in #29283, fixing a rare intermittency issue |
…empool Test that wallet rescans process transactions topologically, even if a parent's entry into the mempool is later than that of its child. This behavior is important because IsFromMe requires the ability to look up a transaction's inputs. Github-Pull: bitcoin#29179 Rebased-From: c3d02be
…in mempool Test that wallet rescans process transactions topologically, even if a parent's entry into the mempool is later than that of its child. This behavior is important because IsFromMe requires the ability to look up a transaction's inputs. Co-authored-by: furszy <[email protected]> Github-Pull: bitcoin#29179 Rebased-From: df30247
11f3a7e Use hardened runtime on macOS release builds. (Mark Friedenbach) ac1b9a5 [test] import descriptor wallet with reorged parent + IsFromMe child in mempool (glozow) ecb8ebc [test] rescan legacy wallet with reorged parent + IsFromMe child in mempool (Gloria Zhao) 438ac29 snapshots: don't core dump when running -checkblockindex after `loadtxoutset` (Mark Friedenbach) 7ec3455 [log] mempool loading (glozow) fe0f8fe net: create I2P sessions with both ECIES-X25519 and ElGamal encryption (Jon Atack) fc62271 [refactor] Add helper for iterating through mempool entries (stickies-v) Pull request description: Backports for 26.x. Includes: - 453b481 from #28391 - #29179 - #29200 - #29227 - #28791 - #29127 ACKs for top commit: stickies-v: ACK 11f3a7e Tree-SHA512: 20ef871ec768f2328056d83f958e595b36ae9b8baa8a6e8b0e1f02c3df4b16965a8e05dcb4323afbcc9ecc4bdde10931232512022c39ee7e12baf9795bf25bf1
Originally motivated by #29019, which reverts back to having
requestMempoolTransactionsemittransactionAddedToMempoolinmapTxdefault order instead ofGetSortedDepthAndScoreorder.It's important that these notifications happen in topological order, otherwise the wallet rescan may miss transactions that belong to it. Notably, checking whether a transaction
IsFromMerequires knowing its inputs, which may be from a mempool parent.When using
mapTxorder, a parent may come later than its child if it was added from a block disconnected in a reorg.This PR adds a test for this case.