Skip to content

Conversation

@domob1812
Copy link
Contributor

The new clearmempool RPC method removes all transactions in the mempool. This can be useful for testing, and might be useful also in some other situations.

@domob1812
Copy link
Contributor Author

I don't know if adding this new method is desired. I would have found it useful from time to time, but mostly related to testing (and not production use). For instance, it can be useful in combination with invalidateblock to prevent the transactions from invalidated blocks from getting remined (if that is desired).

Feel free to close if you think this is not useful to have.

Copy link
Member

Choose a reason for hiding this comment

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

If it is only for testing, it shoulnd't be mentioned in the release notes?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I don't know about the exact policy and included it here to have them "complete". But of course I'm happy to remove the mention if it is common to not include changes that are not meant (mainly) for end users.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Removed.

Copy link
Contributor

Choose a reason for hiding this comment

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

Could return the number of evicted txns to be more useful.

Copy link
Contributor

Choose a reason for hiding this comment

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

Then return an object which can have more keys in the future.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, that makes sense. If you generally think having this method is useful, I'll add a useful return value to it (e.g. starting with the number of evicated tx).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Changed the RPC to return a JSON object, with nTx holding the number of evicted transactions.

Copy link
Contributor

Choose a reason for hiding this comment

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

Are we missing some lock acquisitions here (e.g. mempool.cs)?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I thought so first myself, but CTxMempool::clear explicitly locks for you.

Copy link
Contributor

Choose a reason for hiding this comment

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

Oh right, my mistake.

@jonasschnelli
Copy link
Contributor

Yes. Why not.
Concept ACK

Copy link
Contributor

Choose a reason for hiding this comment

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

Use same key as?

" \"size\": xxxxx, (numeric) Current tx count\n"

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah, that makes sense. (nTx was based on getblock, but getmempoolinfo is of course more relevant in this context.) Will update the commit accordingly.

Copy link
Contributor

@skeees skeees 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

I'd note that this is the first time CTxMempool::clear() will be called during normal operation (apart from startup / shutdown), so I think this requires extensive testing to make sure it leaves the mempool in a consistent state (suitable for re-use and with no cruft around).

For example, just a cursory look at that implementation suggests it might not be doing a full clear of every data structure (mapDeltas for example).

Copy link
Contributor

Choose a reason for hiding this comment

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

maybe call this transactions_removed or something more informative

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Changed. size is consistent with getmempoolinfo, but in that context "size" is clearly more descriptive than for clearmempool. I agree that here transactions_removed is a better name.

Copy link
Contributor

Choose a reason for hiding this comment

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

is there a future safety benefit to calling the toplevel mempool.clear() here?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Why not - changed to clear. (Especially since _clear does not AssertLockHeld(cs).)

@maflcko
Copy link
Member

maflcko commented Aug 2, 2018

Should probably run a CTxMemPool::check after the clean and throw if the check fails?

@domob1812
Copy link
Contributor Author

domob1812 commented Aug 2, 2018

@MarcoFalke: If we are worried that CTxMemPool::clean might leave the mempool in an inconsistent state, then we should add the check to clean (not the RPC invocation of it), right? I don't think this is particularly necessary, but I can surely add it "just in case". (But as I said, I think the proper place would be in CTxMemPool::clean and not the new RPC call.)

EDIT: That said, it seems to have benefits to add the check call in the RPC - we should probably lock cs_main for that (since it also depends on pcoinsTip), and that should probably not be done in the clear function itself to avoid overlocking.

@domob1812
Copy link
Contributor Author

I've now added a call to check to the RPC (see my previous comment - while I think the check belongs semantically into clear, it requires to lock cs_main and I think it is better to do that in the RPC than in clear).

mapDeltas is a good observation - this seems to not be caught by check, either. I'll add a test for consistently between mapDeltas and mapTx there separately.

CTxMemPool::clear() was missing mapDeltas, which should also be cleared
as part of the overall mempool state.  This change fixes that, and adds
a consistency check between mapDeltas and mapTx to CTxMemPool::check.
@promag
Copy link
Contributor

promag commented Aug 3, 2018

@skeees made an excellent observation. Maybe add tests involving unconfirmed wallet transactions after clearing the mempool? Also try to include other RPC's related to the mempool, like sendrawtransaction, abandontransaction and testmempoolaccept?

The new 'clearmempool' RPC method removes all transactions in the
mempool.  This can be useful for testing, and might be useful also
in some other situations.
@domob1812
Copy link
Contributor Author

I've now split out the test into a new mempool_clear.py file, which I think fits better (especially if we want to have more extensive tests). The test already has an unconfirmed wallet transaction that gets cleared from the mempool and then verifies that it is still unconfirmed after mining a block.

I'm not sure what exactly you are thinking about with other mempool-related functions. In my opinion, the test strategy should look like this:

  1. Create some "non-trivial" mempool; e.g. as now with a wallet transactions and a fee delta.
  2. Call clearmempool.
  3. Rely on CTxMemPool::check to verify that no inconsistencies are left (which might include extending the checker, as I did for mapDeltas).

I don't think that sendrawtransaction or testmempoolaccept add anything to this. The main things to consider are that the mempool created through 1) is "complicated enough" and that check for step 3) is complete enough.

Do you have any concrete suggestions of what else we should do for step 1) and what might be missing for check?

@promag
Copy link
Contributor

promag commented Aug 12, 2018

I'm not sure what exactly you are thinking about with other mempool-related functions

Just a way to say that their functionality is preserved after clearmempool. For instance, sendrawtransaction tx -> clearmempool -> sendrawtransaction tx should work?

@sipa
Copy link
Member

sipa commented Aug 12, 2018

What would this RPC be useful for? It seems pretty ill advised to expose it for production use, and for testing it can always be accomplished by restarting the node (and wiping mempool.dat).

@DrahtBot
Copy link
Contributor

DrahtBot commented Aug 12, 2018

No more conflicts as of last run.

@domob1812
Copy link
Contributor Author

@sipa: The situation where I would have found it useful from time to time is certainly testing (not production). You are right that restarting with wiping mempool.dat can reproduce the same effect, but especially the latter is at least some hassle to do. (And honestly, when I last wanted to do it, I played around with -nopersistmempool but wasn't able to get it working - I didn't think about removing mempool.dat manually, as that seemed a bit like digging around in implementation details that shouldn't concern me as a tester.)

But if you think we should rather not expose this, then we can of course close this PR. (And I'll just move the fix for mapDeltas to a separate PR without the new RPC.)

@promag
Copy link
Contributor

promag commented Aug 18, 2018

@sipa correct me if I'm wrong (can't test ATM) but a new wallet transaction could be rejected and this would allow to add it?

@sipa
Copy link
Member

sipa commented Aug 18, 2018

@promag Yes, but other nodes will still reject it. Permitting is locally seems a bad idea in that case (and at the least a privacy leak).

mapLinks.clear();
mapTx.clear();
mapNextTx.clear();
mapDeltas.clear();
Copy link
Member

Choose a reason for hiding this comment

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

mapDeltas probably shouldn't be cleared...?

assert(&tx == it->second);
}
for (const auto& entry : mapDeltas) {
assert(mapTx.count(entry.first) > 0);
Copy link
Member

Choose a reason for hiding this comment

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

Deltas aren't necessarily in the pool (needed to prioritise ones that would be rejected otherwise).

@laanwj
Copy link
Member

laanwj commented Sep 11, 2018

What would this RPC be useful for? It seems pretty ill advised to expose it for production use, and for testing it can always be accomplished by restarting the node (and wiping mempool.dat).

I agree with @sipa here. This has much foot-shooting potential and, besides for a few developer corner cases, doesn't seem worth the maintenance and testing hassle.

(in practice, methods such as this are going to be suggested for any common ailment, "oh have you tried 'clearmempool')

@laanwj laanwj closed this Sep 11, 2018
@domob1812
Copy link
Contributor Author

Agreed - I also don't see much use besides testing, so perhaps it is safer not to add this generally.

@domob1812 domob1812 deleted the clear-mempool branch September 24, 2018 19:21
@bitcoin bitcoin locked as resolved and limited conversation to collaborators Sep 8, 2021
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.