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
[mempool] Mark mempool import fails that were found in mempool as 'already there' #11062
Conversation
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.
Switch commit order? Commit messages are a bit long, maybe reduce?
src/validation.cpp
Outdated
// wallet(s) having loaded it while we were processing | ||
// mempool transactions; consider these as valid, instead of | ||
// failed, but mark them as 'already existed' | ||
if (mempool.exists(tx->GetHash())) { |
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.
Check state.GetRejectCode() == REJECT_DUPLICATE
? See this.
Also, IMO this is prettier:
if (state.IsValid()) {
...
} else if (state.GetRejectCode() == REJECT_DUPLICATE) {
...
} else {
...
}
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.
There is more than one reason forREJECT_DUPLICATE
, don't know if that matters here. @sipa?
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.
REJECT_DUPLICATE is used to indicate double spends, so that wouldn't be correct.
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.
What about #10503?
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.
But REJECT_DUPLICATE is set if it's in the mempool which happens to be what's tested here. So it should be?
} else if (state.GetRejectCode() == REJECT_DUPLICATE && state.GetRejectReason() == "txn-already-in-mempool") {
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.
As @sipa noted, REJECT_DUPLICATE
is ambiguous. I don't want to say it was already there, when a conflicted different transaction was there instead. The safest course would seem to simply check if it is there after a failure, as I am doing now.
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.
Understood, can't use REJECT_DUPLICATE.
Still, the way it's now is like catching the error, whereas testing before it's like expecting that behaviour.
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.
Yes. There's a race condition going on here, which makes this better than the alternative (i.e. checking if exists and then trying to accept).
Thread A is doing wallet mempool insertions.
Thread B is calling LoadMempool().
Case 1:
- Thread A imports tx X
- Thread B tests for presence of tx X. Found. Marks already there and moves on.
Case 2:
- Thread B tests for presence of tx X. Not found.
- Thread A imports tx X.
- Thread B attempts to import tx X and fails.
Both cases should result in 'already there', but by checking presence before attempt to accept, the second case will result in a failure.
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.
Doesn't the above LOCK(cs_main)
prevents that case (and the current implementation for all that matters)?
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.
Hm, you're right, it does. I think.
src/validation.cpp
Outdated
@@ -4274,6 +4274,7 @@ bool LoadMempool(void) | |||
int64_t count = 0; | |||
int64_t skipped = 0; | |||
int64_t failed = 0; | |||
int64_t alreadythere = 0; |
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.
Maybe just increment skipped
?
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.
But it wasn't skipped. It was already there.
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.
Rigth, maybe rename skipped to expired.
Edit: the message on the bottom already prints expired.. 🙄
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.
Good point. Done.
Yes, what about it? |
d2eba62
to
08b7e22
Compare
utACK |
utACK 8c8ef83edc8724f2dc7e363e9c412c5df564e08f |
utACK 8c8ef83 |
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.
Seems reasonable. utACK 8c8ef83edc8724f2dc7e363e9c412c5df564e08f , although I think the commits can be squashed down into one commit for merge. I have a couple of supernits on variable names and comments which you can take or leave.
Shame there aren't any LoadMempool unit tests that you could add to. I think adding them from scratch is beyond the scope of this PR.
src/validation.cpp
Outdated
int64_t failed = 0; | ||
int64_t alreadythere = 0; |
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: snake case already_there
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.
IMO consider renaming to one of already_imported
, already_loaded
, already_in_mempool
.
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.
Personally feel the current name is fine as is, but will change if people want it.
src/validation.cpp
Outdated
// mempool may contain the transaction already, e.g. from | ||
// wallet(s) having loaded it while we were processing | ||
// mempool transactions; consider these as valid, instead of | ||
// failed, but mark them as 'already existed' |
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: mark them as 'already there'
On startup, the wallets will start pumping wallet transactions into the mempool in a different thread while LoadMempool() is running. This will sometimes result in transactions "failing" to be accepted into mempool, but only for the reason that they were already put there by a wallet. The log message for mempool load would note this as a 'failure' to import, which was misleading; it should instead mark it as the transaction already being in the mempool.
8c8ef83
to
258d33b
Compare
@jnewbery Thanks for the review! You're right, I think I was overthinking things when I tried to split commits. I've squashed into one commit and addressed your nits. |
|
Didn't realize test failed. Restarting as it's obviously unrelated. |
Tested ACK 258d33b |
re-utACK 258d33b |
utACK 258d33b. |
…mempool as 'already there' 258d33b [mempool] Mark unaccepted txs present in mempool as 'already there'. (Karl-Johan Alm) Pull request description: I was investigating the reasons for failed imports in mempool and noticed that `LoadMempool()` and `pwallet->postInitProcess()` (for all wallets) are executed concurrently. The wallet will end up importing transactions that `LoadMempool()` later tries to import; the latter will fail due to the tx already being in the mempool. This PR changes the log message, adding an additional "already there" entry. For transactions not accepted into mempool, a check if they are in the mempool is done first, and if found, they are counted as 'already there', otherwise counted as 'failed'. Also slight rewording for consistency (successes, failed, expired, ... -> succeeded, failed, expired). Tree-SHA512: 1a6134a25260917f2768365e0dfd8b278fe3f8287cab38bb028b7de3d517718a2d37696186dc7a23ceab338cc755fbbe7d45358ee94e573610fddd2a0620d6e5
…ready there' Summary: I was investigating the reasons for failed imports in mempool and noticed that `LoadMempool()` and `pwallet->postInitProcess()` (for all wallets) are executed concurrently. The wallet will end up importing transactions that `LoadMempool()` later tries to import; the latter will fail due to the tx already being in the mempool. Backport of Bitcoin Core PR11062 bitcoin/bitcoin#11062 Test Plan: ``` make check-all ``` Reviewers: Fabien, #bitcoin_abc, deadalnix Reviewed By: Fabien, #bitcoin_abc Differential Revision: https://reviews.bitcoinabc.org/D4266
…und in mempool as 'already there' 258d33b [mempool] Mark unaccepted txs present in mempool as 'already there'. (Karl-Johan Alm) Pull request description: I was investigating the reasons for failed imports in mempool and noticed that `LoadMempool()` and `pwallet->postInitProcess()` (for all wallets) are executed concurrently. The wallet will end up importing transactions that `LoadMempool()` later tries to import; the latter will fail due to the tx already being in the mempool. This PR changes the log message, adding an additional "already there" entry. For transactions not accepted into mempool, a check if they are in the mempool is done first, and if found, they are counted as 'already there', otherwise counted as 'failed'. Also slight rewording for consistency (successes, failed, expired, ... -> succeeded, failed, expired). Tree-SHA512: 1a6134a25260917f2768365e0dfd8b278fe3f8287cab38bb028b7de3d517718a2d37696186dc7a23ceab338cc755fbbe7d45358ee94e573610fddd2a0620d6e5
…ready there' Summary: I was investigating the reasons for failed imports in mempool and noticed that `LoadMempool()` and `pwallet->postInitProcess()` (for all wallets) are executed concurrently. The wallet will end up importing transactions that `LoadMempool()` later tries to import; the latter will fail due to the tx already being in the mempool. Backport of Bitcoin Core PR11062 bitcoin/bitcoin#11062 Test Plan: ``` make check-all ``` Reviewers: Fabien, #bitcoin_abc, deadalnix Reviewed By: Fabien, #bitcoin_abc Differential Revision: https://reviews.bitcoinabc.org/D4266
…ready there' Summary: I was investigating the reasons for failed imports in mempool and noticed that `LoadMempool()` and `pwallet->postInitProcess()` (for all wallets) are executed concurrently. The wallet will end up importing transactions that `LoadMempool()` later tries to import; the latter will fail due to the tx already being in the mempool. Backport of Bitcoin Core PR11062 bitcoin/bitcoin#11062 Test Plan: ``` make check-all ``` Reviewers: Fabien, #bitcoin_abc, deadalnix Reviewed By: Fabien, #bitcoin_abc Differential Revision: https://reviews.bitcoinabc.org/D4266
…und in mempool as 'already there' 258d33b [mempool] Mark unaccepted txs present in mempool as 'already there'. (Karl-Johan Alm) Pull request description: I was investigating the reasons for failed imports in mempool and noticed that `LoadMempool()` and `pwallet->postInitProcess()` (for all wallets) are executed concurrently. The wallet will end up importing transactions that `LoadMempool()` later tries to import; the latter will fail due to the tx already being in the mempool. This PR changes the log message, adding an additional "already there" entry. For transactions not accepted into mempool, a check if they are in the mempool is done first, and if found, they are counted as 'already there', otherwise counted as 'failed'. Also slight rewording for consistency (successes, failed, expired, ... -> succeeded, failed, expired). Tree-SHA512: 1a6134a25260917f2768365e0dfd8b278fe3f8287cab38bb028b7de3d517718a2d37696186dc7a23ceab338cc755fbbe7d45358ee94e573610fddd2a0620d6e5
…und in mempool as 'already there' 258d33b [mempool] Mark unaccepted txs present in mempool as 'already there'. (Karl-Johan Alm) Pull request description: I was investigating the reasons for failed imports in mempool and noticed that `LoadMempool()` and `pwallet->postInitProcess()` (for all wallets) are executed concurrently. The wallet will end up importing transactions that `LoadMempool()` later tries to import; the latter will fail due to the tx already being in the mempool. This PR changes the log message, adding an additional "already there" entry. For transactions not accepted into mempool, a check if they are in the mempool is done first, and if found, they are counted as 'already there', otherwise counted as 'failed'. Also slight rewording for consistency (successes, failed, expired, ... -> succeeded, failed, expired). Tree-SHA512: 1a6134a25260917f2768365e0dfd8b278fe3f8287cab38bb028b7de3d517718a2d37696186dc7a23ceab338cc755fbbe7d45358ee94e573610fddd2a0620d6e5
…und in mempool as 'already there' 258d33b [mempool] Mark unaccepted txs present in mempool as 'already there'. (Karl-Johan Alm) Pull request description: I was investigating the reasons for failed imports in mempool and noticed that `LoadMempool()` and `pwallet->postInitProcess()` (for all wallets) are executed concurrently. The wallet will end up importing transactions that `LoadMempool()` later tries to import; the latter will fail due to the tx already being in the mempool. This PR changes the log message, adding an additional "already there" entry. For transactions not accepted into mempool, a check if they are in the mempool is done first, and if found, they are counted as 'already there', otherwise counted as 'failed'. Also slight rewording for consistency (successes, failed, expired, ... -> succeeded, failed, expired). Tree-SHA512: 1a6134a25260917f2768365e0dfd8b278fe3f8287cab38bb028b7de3d517718a2d37696186dc7a23ceab338cc755fbbe7d45358ee94e573610fddd2a0620d6e5
…und in mempool as 'already there' 258d33b [mempool] Mark unaccepted txs present in mempool as 'already there'. (Karl-Johan Alm) Pull request description: I was investigating the reasons for failed imports in mempool and noticed that `LoadMempool()` and `pwallet->postInitProcess()` (for all wallets) are executed concurrently. The wallet will end up importing transactions that `LoadMempool()` later tries to import; the latter will fail due to the tx already being in the mempool. This PR changes the log message, adding an additional "already there" entry. For transactions not accepted into mempool, a check if they are in the mempool is done first, and if found, they are counted as 'already there', otherwise counted as 'failed'. Also slight rewording for consistency (successes, failed, expired, ... -> succeeded, failed, expired). Tree-SHA512: 1a6134a25260917f2768365e0dfd8b278fe3f8287cab38bb028b7de3d517718a2d37696186dc7a23ceab338cc755fbbe7d45358ee94e573610fddd2a0620d6e5
…und in mempool as 'already there' 258d33b [mempool] Mark unaccepted txs present in mempool as 'already there'. (Karl-Johan Alm) Pull request description: I was investigating the reasons for failed imports in mempool and noticed that `LoadMempool()` and `pwallet->postInitProcess()` (for all wallets) are executed concurrently. The wallet will end up importing transactions that `LoadMempool()` later tries to import; the latter will fail due to the tx already being in the mempool. This PR changes the log message, adding an additional "already there" entry. For transactions not accepted into mempool, a check if they are in the mempool is done first, and if found, they are counted as 'already there', otherwise counted as 'failed'. Also slight rewording for consistency (successes, failed, expired, ... -> succeeded, failed, expired). Tree-SHA512: 1a6134a25260917f2768365e0dfd8b278fe3f8287cab38bb028b7de3d517718a2d37696186dc7a23ceab338cc755fbbe7d45358ee94e573610fddd2a0620d6e5
…und in mempool as 'already there' 258d33b [mempool] Mark unaccepted txs present in mempool as 'already there'. (Karl-Johan Alm) Pull request description: I was investigating the reasons for failed imports in mempool and noticed that `LoadMempool()` and `pwallet->postInitProcess()` (for all wallets) are executed concurrently. The wallet will end up importing transactions that `LoadMempool()` later tries to import; the latter will fail due to the tx already being in the mempool. This PR changes the log message, adding an additional "already there" entry. For transactions not accepted into mempool, a check if they are in the mempool is done first, and if found, they are counted as 'already there', otherwise counted as 'failed'. Also slight rewording for consistency (successes, failed, expired, ... -> succeeded, failed, expired). Tree-SHA512: 1a6134a25260917f2768365e0dfd8b278fe3f8287cab38bb028b7de3d517718a2d37696186dc7a23ceab338cc755fbbe7d45358ee94e573610fddd2a0620d6e5
…und in mempool as 'already there' 258d33b [mempool] Mark unaccepted txs present in mempool as 'already there'. (Karl-Johan Alm) Pull request description: I was investigating the reasons for failed imports in mempool and noticed that `LoadMempool()` and `pwallet->postInitProcess()` (for all wallets) are executed concurrently. The wallet will end up importing transactions that `LoadMempool()` later tries to import; the latter will fail due to the tx already being in the mempool. This PR changes the log message, adding an additional "already there" entry. For transactions not accepted into mempool, a check if they are in the mempool is done first, and if found, they are counted as 'already there', otherwise counted as 'failed'. Also slight rewording for consistency (successes, failed, expired, ... -> succeeded, failed, expired). Tree-SHA512: 1a6134a25260917f2768365e0dfd8b278fe3f8287cab38bb028b7de3d517718a2d37696186dc7a23ceab338cc755fbbe7d45358ee94e573610fddd2a0620d6e5
…und in mempool as 'already there' 258d33b [mempool] Mark unaccepted txs present in mempool as 'already there'. (Karl-Johan Alm) Pull request description: I was investigating the reasons for failed imports in mempool and noticed that `LoadMempool()` and `pwallet->postInitProcess()` (for all wallets) are executed concurrently. The wallet will end up importing transactions that `LoadMempool()` later tries to import; the latter will fail due to the tx already being in the mempool. This PR changes the log message, adding an additional "already there" entry. For transactions not accepted into mempool, a check if they are in the mempool is done first, and if found, they are counted as 'already there', otherwise counted as 'failed'. Also slight rewording for consistency (successes, failed, expired, ... -> succeeded, failed, expired). Tree-SHA512: 1a6134a25260917f2768365e0dfd8b278fe3f8287cab38bb028b7de3d517718a2d37696186dc7a23ceab338cc755fbbe7d45358ee94e573610fddd2a0620d6e5
…und in mempool as 'already there' 258d33b [mempool] Mark unaccepted txs present in mempool as 'already there'. (Karl-Johan Alm) Pull request description: I was investigating the reasons for failed imports in mempool and noticed that `LoadMempool()` and `pwallet->postInitProcess()` (for all wallets) are executed concurrently. The wallet will end up importing transactions that `LoadMempool()` later tries to import; the latter will fail due to the tx already being in the mempool. This PR changes the log message, adding an additional "already there" entry. For transactions not accepted into mempool, a check if they are in the mempool is done first, and if found, they are counted as 'already there', otherwise counted as 'failed'. Also slight rewording for consistency (successes, failed, expired, ... -> succeeded, failed, expired). Tree-SHA512: 1a6134a25260917f2768365e0dfd8b278fe3f8287cab38bb028b7de3d517718a2d37696186dc7a23ceab338cc755fbbe7d45358ee94e573610fddd2a0620d6e5
…ready there' Summary: I was investigating the reasons for failed imports in mempool and noticed that `LoadMempool()` and `pwallet->postInitProcess()` (for all wallets) are executed concurrently. The wallet will end up importing transactions that `LoadMempool()` later tries to import; the latter will fail due to the tx already being in the mempool. Backport of Bitcoin Core PR11062 bitcoin/bitcoin#11062 Test Plan: ``` make check-all ``` Reviewers: Fabien, #bitcoin_abc, deadalnix Reviewed By: Fabien, #bitcoin_abc Differential Revision: https://reviews.bitcoinabc.org/D4266
…ready there' Summary: I was investigating the reasons for failed imports in mempool and noticed that `LoadMempool()` and `pwallet->postInitProcess()` (for all wallets) are executed concurrently. The wallet will end up importing transactions that `LoadMempool()` later tries to import; the latter will fail due to the tx already being in the mempool. Backport of Bitcoin Core PR11062 bitcoin/bitcoin#11062 Test Plan: ``` make check-all ``` Reviewers: Fabien, #bitcoin_abc, deadalnix Reviewed By: Fabien, #bitcoin_abc Differential Revision: https://reviews.bitcoinabc.org/D4266
…ready there' Summary: I was investigating the reasons for failed imports in mempool and noticed that `LoadMempool()` and `pwallet->postInitProcess()` (for all wallets) are executed concurrently. The wallet will end up importing transactions that `LoadMempool()` later tries to import; the latter will fail due to the tx already being in the mempool. Backport of Bitcoin Core PR11062 bitcoin/bitcoin#11062 Test Plan: ``` make check-all ``` Reviewers: Fabien, #bitcoin_abc, deadalnix Reviewed By: Fabien, #bitcoin_abc Differential Revision: https://reviews.bitcoinabc.org/D4266
…ready there' Summary: I was investigating the reasons for failed imports in mempool and noticed that `LoadMempool()` and `pwallet->postInitProcess()` (for all wallets) are executed concurrently. The wallet will end up importing transactions that `LoadMempool()` later tries to import; the latter will fail due to the tx already being in the mempool. Backport of Bitcoin Core PR11062 bitcoin/bitcoin#11062 Test Plan: ``` make check-all ``` Reviewers: Fabien, #bitcoin_abc, deadalnix Reviewed By: Fabien, #bitcoin_abc Differential Revision: https://reviews.bitcoinabc.org/D4266
I was investigating the reasons for failed imports in mempool and noticed that
LoadMempool()
andpwallet->postInitProcess()
(for all wallets) are executed concurrently. The wallet will end up importing transactions thatLoadMempool()
later tries to import; the latter will fail due to the tx already being in the mempool.This PR changes the log message, adding an additional "already there" entry. For transactions not accepted into mempool, a check if they are in the mempool is done first, and if found, they are counted as 'already there', otherwise counted as 'failed'.
Also slight rewording for consistency (successes, failed, expired, ... -> succeeded, failed, expired).