Skip to content

Conversation

maflcko
Copy link
Member

@maflcko maflcko commented Sep 7, 2020

Seems odd to have code in Bitcoin Core that is unused.

Moreover the function was broken (see #24145) and is brittle, as there is nothing that prevents similar bugs from re-appearing.

Fix both issues by replacing it with C++11 member initializers.

@maflcko maflcko force-pushed the 2009-noTxpoolClear branch 2 times, most recently from fa8af69 to fa0fbb3 Compare September 7, 2020 15:05
@hebasto
Copy link
Member

hebasto commented Sep 7, 2020

Concept ACK. Mind elaborating "useless calls" in fa947cc "validation: Remove useless call to mempool->clear()"?

@maflcko
Copy link
Member Author

maflcko commented Sep 7, 2020

The mempool.clear() in UnloadBlockIndex has been added in commit 51598b2 to clear global state between unit tests. Now that there is no global mempool anymore, this it not needed anymore. Also, I couldn't find it to be useful for anything else.

@laanwj
Copy link
Member

laanwj commented Sep 8, 2020

Concept ACK

@hebasto
Copy link
Member

hebasto commented Sep 8, 2020

Wrt to preserving recursive locking of CTxMemPool::cs mind considering the following patch:

--- a/src/test/txvalidationcache_tests.cpp
+++ b/src/test/txvalidationcache_tests.cpp
@@ -73,7 +73,7 @@ BOOST_FIXTURE_TEST_CASE(tx_mempool_block_doublespend, TestChain100Setup)
         LOCK(cs_main);
         BOOST_CHECK(::ChainActive().Tip()->GetBlockHash() != block.GetHash());
     }
-    tx_pool.clearTxs();
+    WITH_LOCK(tx_pool.cs, tx_pool.clearTxs());
 
     // Test 3: ... and should be rejected if spend2 is in the memory pool
     BOOST_CHECK(ToMemPool(spends[1]));
@@ -82,7 +82,7 @@ BOOST_FIXTURE_TEST_CASE(tx_mempool_block_doublespend, TestChain100Setup)
         LOCK(cs_main);
         BOOST_CHECK(::ChainActive().Tip()->GetBlockHash() != block.GetHash());
     }
-    tx_pool.clearTxs();
+    WITH_LOCK(tx_pool.cs, tx_pool.clearTxs());
 
     // Final sanity test: first spend in tx_pool, second in block, that's OK:
     std::vector<CMutableTransaction> oneSpend;
diff --git a/src/test/util/txmempool.h b/src/test/util/txmempool.h
index 7edc6d607..db52377b0 100644
--- a/src/test/util/txmempool.h
+++ b/src/test/util/txmempool.h
@@ -9,9 +9,9 @@
 
 struct TxMemPoolClearable : public CTxMemPool {
     /** Clear added transactions */
-    void clearTxs()
+    void clearTxs() EXCLUSIVE_LOCKS_REQUIRED(cs)
     {
-        LOCK(cs);
+        AssertLockHeld(cs);
         mapTx.clear();
         mapNextTx.clear();
         totalTxSize = 0;

?

@maflcko
Copy link
Member Author

maflcko commented Sep 9, 2020

@hebasto It hasn't been decided for the project whether to switch the mempool.cs to non-recursive mutex, nor in what way to do it, so I'll leave that test patch for later.

@maflcko maflcko force-pushed the 2009-noTxpoolClear branch 2 times, most recently from fa16d78 to fa13890 Compare September 9, 2020 14:06
@dongcarl
Copy link
Contributor

dongcarl commented Sep 10, 2020

I'm not very familiar with these tests, so I may be completely off the mark here. However, it seems to me like the purpose of clearTxs is to reset the mempool without re-instantiating it. I wonder if we shouldn't consider just re-instantiating the mempool every time we want to clear it, as:

  1. If there were a performance penalty, it wouldn't matter too much as it's in the test code
  2. We wouldn't have to have the burden of keeping TxMemPoolClearable::clearTxs() and CTxMemPool in sync.

@laanwj
Copy link
Member

laanwj commented Sep 10, 2020

@dongcarl This was also my idea in the discussion here, but there wasn't really a decision: #19909 (comment)

@dongcarl
Copy link
Contributor

The mempool.clear() in UnloadBlockIndex has been added in commit 51598b2 to clear global state between unit tests. Now that there is no global mempool anymore, this it not needed anymore. Also, I couldn't find it to be useful for anything else.

Does the call to UnloadBlockIndex here:

UnloadBlockIndex(node.mempool.get());

Make any difference to the mempool that we should keep in mind?

@sdaftuar
Copy link
Member

Is this refactor important to other work? Having the ability to clear the mempool seems useful to me; even though we've never exposed it, I could imagine some situations where invoking the clear() function somehow (say via rpc) might be useful.

Alternatively -- and even more speculatively -- in thinking about how we update the mempool after a reorg, I've wondered if there might be solutions where clearing the mempool and re-adding things back might be better in some scenarios.

I don't think either of those is pressing though so if there's some good reason to get rid of it to help with other work in progress, then that's fine with me, we can always revisit the right design if the functionality I suggest might actually be useful. Just not sure if this might be wasted effort, if there's no important reason or followup work motivating this change?

@laanwj
Copy link
Member

laanwj commented Sep 11, 2020

I think you have a point there @sdaftuar. I'm not sure in how far it's here the case (there is no standard definition of the expectation for a "mempool interface"), but in some cases some methods just belong in an API (say, add/lookup/delete in a table) even if they're temporarily not used, and going over the top to clean APIs to the minimum set can make future changes harder.

@DrahtBot
Copy link
Contributor

DrahtBot commented Sep 19, 2020

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

Reviews

See the guideline for information on the review process.

Type Reviewers
ACK glozow
Concept ACK hebasto, laanwj, jnewbery, practicalswift, fanquake

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

Conflicts

Reviewers, this pull request conflicts with the following ones:

  • #26614 (Accurately account for mempool index memory by hebasto)

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.

@maflcko
Copy link
Member Author

maflcko commented Sep 19, 2020

The clear method as currently implemented doesn't help with implementing a RPC that clears the mempool, because it also clears the fee estimates. If the method is kept, it should be renamed to ReInit (or similar), because all it does is (re-)initialize the member variables of the mempool.

Though, according to our release notes, member variables should be initialized inline via C++11 initializers to avoid uninitialized values. (This is what is being done in this pull)

Also, I can not imagine a single use case where clearing the whole mempool over RPC is useful. At most sniping a single tx might be useful. Though even that has been rejected at least twice in the past. Please refer to #15873 and #16523.

@sdaftuar
Copy link
Member

If you’re a miner, I could imagine it is possible that clearing the mempool could be helpful in the event of a dos-attack where pathological transaction chains (for example) cause block template creation to be very slow. So a use case could be to empty it and use other rpcs to manually refill it.

That’s just an example, and I don’t know if it is likely we’d support that anytime soon, but I could imagine the use case.

(Your point about fee estimation is a reasonable one, but I believe there is work happening elsewhere to decouple that from the mempool? )

At any rate I don’t feel strongly about this, if removing this function is helpful for other work I am not opposed either.

@jnewbery
Copy link
Contributor

I wonder if we shouldn't consider just re-instantiating the mempool every time we want to clear it, as:

@dongcarl This was also my idea in the discussion here, but there wasn't really a decision: #19909 (comment)

@MarcoFalke did you consider this approach? On the face of it, it seems better to reinstantiate a mempool every time you want to clear it rather than having custom test code to reach into the object's members.

@maflcko
Copy link
Member Author

maflcko commented Apr 29, 2022

Yeah, I'll look into this. First part of that is #25024

@maflcko
Copy link
Member Author

maflcko commented Apr 29, 2022

In reply to Suhas point that the clear method could be used to wipe the txs for example during a reorg or by a miner to speed up block template creation: I am still doubtful that this method can actually achieve this goal, as it also resets other members of mempool. I think it would be sufficient and clearer to just use the existing removeRecursive functionality of the mempool to wipe all txs?

fanquake added a commit to bitcoin-core/gui that referenced this pull request Oct 10, 2022
faa1552 test: Use dedicated mempool in TestBasicMining (MacroFake)
fafab38 test: Use dedicated mempool in TestPackageSelection (MacroFake)
fa4055d test: Use dedicated mempool in TestPrioritisedMining (MacroFake)
fa29218 test: Pass mempool reference to AssemblerForTest (MacroFake)

Pull request description:

  This cleans up the miner tests:

  * Removes duplicate/redundant and thus confusing chainparams object.
  * Uses a fresh mempool for each subtest instead of using the "global" one from the testing setup. This makes it easier to follow the tests in smaller scopes. Also it makes sure the mempool is truly cleared by reconstructing it. Finally, this removes calls to `clear`, see bitcoin/bitcoin#19909

ACKs for top commit:
  glozow:
    utACK faa1552

Tree-SHA512: ced1260f6ab70fba74b0fac7ff4fc7adfddcd2f3bee785249d2a4a9055ac253eff9090edbda7a17e72a71a81b56ff708d5ff64e1f57ebc7b7747d6c88fec51e3
@maflcko maflcko force-pushed the 2009-noTxpoolClear branch from bf50db6 to fa299b3 Compare October 10, 2022 13:07
@fanquake
Copy link
Member

Concept ACK

@maflcko maflcko changed the title txmempool: Remove unused clear() member function refactor: Remove unused CTxMemPool::clear() helper Oct 10, 2022
sidhujag pushed a commit to syscoin/syscoin that referenced this pull request Oct 10, 2022
faa1552 test: Use dedicated mempool in TestBasicMining (MacroFake)
fafab38 test: Use dedicated mempool in TestPackageSelection (MacroFake)
fa4055d test: Use dedicated mempool in TestPrioritisedMining (MacroFake)
fa29218 test: Pass mempool reference to AssemblerForTest (MacroFake)

Pull request description:

  This cleans up the miner tests:

  * Removes duplicate/redundant and thus confusing chainparams object.
  * Uses a fresh mempool for each subtest instead of using the "global" one from the testing setup. This makes it easier to follow the tests in smaller scopes. Also it makes sure the mempool is truly cleared by reconstructing it. Finally, this removes calls to `clear`, see bitcoin#19909

ACKs for top commit:
  glozow:
    utACK faa1552

Tree-SHA512: ced1260f6ab70fba74b0fac7ff4fc7adfddcd2f3bee785249d2a4a9055ac253eff9090edbda7a17e72a71a81b56ff708d5ff64e1f57ebc7b7747d6c88fec51e3
@fanquake fanquake requested a review from glozow November 30, 2022 10:59
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 to removing a function that is not used. I agree that, if manually removing individual or all transactions from mempool is a valid use case we want to implement, this function would not be sufficient.

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 fa818e1

@glozow glozow merged commit 03254c2 into bitcoin:master Jan 4, 2023
@maflcko maflcko deleted the 2009-noTxpoolClear branch January 4, 2023 10:30
sidhujag pushed a commit to syscoin/syscoin that referenced this pull request Jan 4, 2023
@bitcoin bitcoin locked and limited conversation to collaborators Jan 4, 2024
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.