Skip to content

Conversation

TheCharlatan
Copy link
Contributor

Current call sites of entryAll do not require the entries to be sorted, so iterate through mapTx directly to retrieve the entries instead of using SortedDepthAndScore.

This is a follow up to #28391 and was noted here #28391 (comment).

@DrahtBot
Copy link
Contributor

DrahtBot commented Dec 7, 2023

The following sections might be updated with supplementary metadata relevant to reviewers and maintainers.

Code Coverage

For detailed information about the code coverage, see the test coverage report.

Reviews

See the guideline for information on the review process.

Type Reviewers
ACK stickies-v, dergoegge, glozow
Stale ACK maflcko

If your review is incorrectly listed, please react with 👎 to this comment and the bot will ignore it on the next update.

Conflicts

No conflicts as of last run.

@maflcko
Copy link
Member

maflcko commented Dec 7, 2023

lgtm ACK 87fa444

Though, if the function will be removed either way, I wonder if this is worth it. Maybe wait for an OK by @sdaftuar to avoid a merge conflict with #28676 ?

@stickies-v
Copy link
Contributor

Current call sites of entryAll do not require the entries to be sorted

Will this PR not cause issues here? In CWallet::transactionAddedToMempool, we eventually call CWallet::AddToWalletIfInvolvingMe where we have a dependency on CWallet::GetDebit which tries to find the input tx in mapWallet. If this happens in a random order, and not sorted by depth, I think we'd incorrectly miss transactions that are actually "mine" but just aren't in mapWallet yet?

@maflcko
Copy link
Member

maflcko commented Dec 7, 2023

Well, if it is needed, then 453b481 should not have been tagged "refactor", but "bugfix" and should be backported, along with a regression test?

@stickies-v
Copy link
Contributor

That is a good point, I'd missed that this just reverts back to the behaviour pre-entryAll(). It seems that when iterating over a boost::multi_index_container without specifying an index, we default to the insertion order, so i think that would be sufficient guarantees that the CWallet::transactionAddedToMempool calls happen in a safe order too.

@sdaftuar
Copy link
Member

sdaftuar commented Dec 7, 2023

Though, if the function will be removed either way, I wonder if this is worth it. Maybe wait for an OK by @sdaftuar to avoid a merge conflict with #28676 ?

I'm not necessarily planning to remove entryAll(), but I am planning to replace GetSortedDepthAndScore() with a different function that will iterate the mempool topologically based on cluster sort (ie a valid topological order in which the mempool is sorted by descending feerate chunks).

I think if the sorted order is not needed, probably best to remove it now so that we don't take the performance hit needlessly in the next release...? I mostly just wanted to know if I needed to replace it with the new topological sort I'm implementing or if it's fine to just revert back to the mapTx order.

Copy link
Contributor

@stickies-v stickies-v left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ACK 87fa444

@DrahtBot DrahtBot mentioned this pull request Dec 7, 2023
8 tasks
@@ -832,8 +832,8 @@ std::vector<CTxMemPoolEntryRef> CTxMemPool::entryAll() const

std::vector<CTxMemPoolEntryRef> ret;
ret.reserve(mapTx.size());
Copy link
Contributor

@martinus martinus Dec 8, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: you could just write

AssertLockHeld(cs);
return {mapTx.begin(), mapTx.end()};

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, seems easy enough to re-ACK, so will push this.

Current call sites of entryAll do not require the entries to be sorted,
so iterate through mapTx directly to retrieve the entries instead of
using SortedDepthAndScore.
@TheCharlatan
Copy link
Contributor Author

Updated 87fa444 -> f761f03 (entryAllNoOrder_0 -> entryAllNoOrder_1, compare)

Copy link
Contributor

@stickies-v stickies-v left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

re-ACK f761f03, very nice

@DrahtBot DrahtBot requested a review from maflcko December 11, 2023 12:50
Copy link
Member

@dergoegge dergoegge left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

utACK f761f03

Copy link
Member

@glozow glozow left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ACK f761f03 given this brings us back to what we had before

It seems correct that none of the callsites need GetSortedDepthAndScore, though maybe topological is needed in wallet? I had the same question. I guess insertion order doesn't imply topological if a parent was inserted later than a child, i.e. if it's from a reorg?

@glozow
Copy link
Member

glozow commented Jan 4, 2024

Will this PR not cause issues here? In CWallet::transactionAddedToMempool, we eventually call CWallet::AddToWalletIfInvolvingMe where we have a dependency on CWallet::GetDebit which tries to find the input tx in mapWallet. If this happens in a random order, and not sorted by depth, I think we'd incorrectly miss transactions that are actually "mine" but just aren't in mapWallet yet?

Well, if it is needed, then 453b481 should not have been tagged "refactor", but "bugfix" and should be backported, along with a regression test?

I wrote a test and I think we actually do need a topological sort here. See #29179. Cherry-picking this on top, it fails with

Traceback (most recent call last):
  File "/home/gloria/bitcoin/test/functional/test_framework/test_framework.py", line 131, in main
    self.run_test()
  File "/home/gloria/bitcoin/test/functional/wallet_import_rescan.py", line 323, in run_test
    assert_equal(variant.node.gettransaction(variant.child_txid)['confirmations'], 0)
  File "/home/gloria/bitcoin/test/functional/test_framework/coverage.py", line 50, in __call__
    return_val = self.auth_service_proxy_instance.__call__(*args, **kwargs)
  File "/home/gloria/bitcoin/test/functional/test_framework/authproxy.py", line 129, in __call__
    raise JSONRPCException(response['error'], status)
test_framework.authproxy.JSONRPCException: Invalid or non-wallet transaction id (-5)

which indicates that the child wasn't identified as IsFromMe in the wallet (i.e. couldn't see the inputs because the parent hadn't been seen yet). Assuming I didn't write a bad test, it makes me wonder why this wasn't a problem before? I guess this is very unlikely?

@TheCharlatan
Copy link
Contributor Author

Seems like the new behavior incidentally fixed a bug, so closing this again in favor of #29179. Could do a follow-up eventually to make the entryAll call when processing the getrawmempool RPC call more efficient by skipping the sorting.

achow101 added a commit that referenced this pull request Jan 16, 2024
…d in mempool

df30247 [test] import descriptor wallet with reorged parent + IsFromMe child in mempool (glozow)
c3d02be [test] rescan legacy wallet with reorged parent + IsFromMe child in mempool (Gloria Zhao)

Pull request description:

  Originally motivated by #29019, which reverts back to having `requestMempoolTransactions` emit `transactionAddedToMempool` in `mapTx` default order instead of `GetSortedDepthAndScore` order.

  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 `IsFromMe` requires knowing its inputs, which may be from a mempool parent.

  When using `mapTx` order, 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.

ACKs for top commit:
  achow101:
    ACK df30247
  furszy:
    Code review ACK df30247, nits can be disregarded.

Tree-SHA512: 2f1d9ef92313228adbbef94e634e5f7a9ec6e6a2c88e16aa343bdc95ffc9b9f9c82a569b412c9a3841db9d789e52f9283e8b9385731668d59355903e26e58a5d
@bitcoin bitcoin locked and limited conversation to collaborators Jan 4, 2025
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants