Skip to content

Conversation

markblundeberg
Copy link

Only return confirmed (not from mempool) outpoints in pvNoSpendsRemaining,
as is the intended behaviour.

With the previous code, removed chains of tx would have all internally-spent outpoints
included in this vector, which is not the intended result. It seems to have been
incorrectly coded from the very start (#6872)
but the bug is benign as this result is only used to uncache coins.

As a bonus, no copying of CTransaction is needed now.

An existing test case is modified to test this behaviour (the modified test fails
under prior behaviour).

(this is an upstreaming of https://gitlab.com/bitcoin-cash-node/bitcoin-cash-node/-/merge_requests/761 )

@markblundeberg
Copy link
Author

@TheBlueMatt can you confirm on the original intent here?

…emaining

Only return confirmed (not from mempool) outpoints in `pvNoSpendsRemaining`,
as is the intended behaviour.

With the previous code, removed chains of tx would have all internally-spent outpoints
included in this vector, which is not the intended result. It seems to have been
incorrectly coded from the very start (bitcoin#6872)
but the bug is benign as this result is only used to uncache coins.

As a bonus, no copying of CTransaction is needed now.

An existing test case is modified to test this behaviour (the modified test fails
under prior behaviour).
for (const CTransaction& tx : txn) {
for (const CTxIn& txin : tx.vin) {
if (exists(txin.prevout.hash)) continue;
for (txiter iter : stage) {
Copy link

Choose a reason for hiding this comment

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

If I understand this correctly, the change allows for removal of txn vector (for optimization), but behaviour should be the same (as I don't see RemoveStaged having access to txn vector in the old code, thus not modifying it anywhere)?

Copy link
Author

Choose a reason for hiding this comment

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

Not sure I understand your question... the behaviour is indeed altered since RemoveStaged removes stuff from mempool and thus alters the result of exists().

Oh, I guess also worth mentioning: the reason txn had to be created in the prior version is that the contents of stage become invalid after RemoveStaged. Now that RemoveStaged is the final step of the loop, this is no longer a concern so txn doesn't need to exist now.

Copy link
Member

Choose a reason for hiding this comment

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

Correct me if I'm wrong: an example you’re imagining is A and B are being removed from the mempool. B spends an output of A, but since we’ve already called RemoveStaged at this point, exists(A) will return false, and we incorrectly place that outpoint into pvNoSpendsRemaining. There is no behavior change because Uncache will just skip the outpoint if it’s not in the coins cache.

@DrahtBot
Copy link
Contributor

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

Conflicts

Reviewers, this pull request conflicts with the following ones:

  • #23325 (mempool: delete exists(uint256) function by glozow)

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.

@DrahtBot
Copy link
Contributor

🐙 This pull request conflicts with the target branch and needs rebase.

Want to unsubscribe from rebase notifications on this pull request? Just convert this pull request to a "draft".

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.

Concept ACK, there are two changes here that are kind of intermingled (I'd recommend splitting them into different commits):

  • Refactor TrimToSize to not create a vector of CTransaction copies for the entries
  • Call RemoveStaged() at the very end to remove ambiguity of !exists meaning confirmed UTXO or no-longer-in-mempool UTXO.

The background for why we generate the vector of outpoints is: If you remove a transaction from the mempool and it spends a UTXO that’s sitting in your coins cache, you should also uncache that coin, since you no longer expect to look up that coin in the near future.

for (const CTransaction& tx : txn) {
for (const CTxIn& txin : tx.vin) {
if (exists(txin.prevout.hash)) continue;
for (txiter iter : stage) {
Copy link
Member

Choose a reason for hiding this comment

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

Correct me if I'm wrong: an example you’re imagining is A and B are being removed from the mempool. B spends an output of A, but since we’ve already called RemoveStaged at this point, exists(A) will return false, and we incorrectly place that outpoint into pvNoSpendsRemaining. There is no behavior change because Uncache will just skip the outpoint if it’s not in the coins cache.

BOOST_CHECK(!pool.exists(tx1.GetHash()));
BOOST_CHECK(!pool.exists(tx2.GetHash()));
BOOST_CHECK(!pool.exists(tx3.GetHash()));
// This vector should only contain 'root' (not unconfirmed) outpoints
Copy link
Member

Choose a reason for hiding this comment

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

I don't think we use "root" anywhere else to refer to confirmed outpoints

Suggested change
// This vector should only contain 'root' (not unconfirmed) outpoints
// This vector should only contain confirmed outpoints

@DrahtBot
Copy link
Contributor

There hasn't been much activity lately and the patch still needs rebase. What is the status here?
  • Is it still relevant? ➡️ Please solve the conflicts to make it ready for review and to ensure the CI passes.
  • Is it no longer relevant? ➡️ Please close.
  • Did the author lose interest or time to work on this? ➡️ Please close it and mark it 'Up for grabs' with the label, so that it can be picked up in the future.

@glozow
Copy link
Member

glozow commented Feb 25, 2022

@markblundeberg are you still working on this?

@fanquake
Copy link
Member

markblundeberg are you still working on this?

Closing for now. Feel free to reopen if you want to pick this back up.

@fanquake fanquake closed this May 12, 2022
@bitcoin bitcoin locked and limited conversation to collaborators May 12, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants