Skip to content
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

Merged
merged 1 commit into from Oct 18, 2017

Conversation

kallewoof
Copy link
Member

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).

Copy link
Member

@promag promag left a 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?

// 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())) {
Copy link
Member

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 {
    ...
}

Copy link
Member

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?

Copy link
Member

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.

Copy link
Member

Choose a reason for hiding this comment

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

What about #10503?

Copy link
Member

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") {

Copy link
Member Author

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.

Copy link
Member

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.

Copy link
Member Author

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.

Copy link
Member

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)?

Copy link
Member Author

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.

@@ -4274,6 +4274,7 @@ bool LoadMempool(void)
int64_t count = 0;
int64_t skipped = 0;
int64_t failed = 0;
int64_t alreadythere = 0;
Copy link
Member

Choose a reason for hiding this comment

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

Maybe just increment skipped?

Copy link
Member Author

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.

Copy link
Member

@promag promag Aug 18, 2017

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.. 🙄

Copy link
Member Author

Choose a reason for hiding this comment

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

Good point. Done.

@sipa
Copy link
Member

sipa commented Aug 17, 2017

Yes, what about it?

@kallewoof kallewoof force-pushed the mempool-alreadythere branch 2 times, most recently from d2eba62 to 08b7e22 Compare August 18, 2017 00:34
@sipa
Copy link
Member

sipa commented Aug 18, 2017

utACK

@TheBlueMatt
Copy link
Contributor

utACK 8c8ef83edc8724f2dc7e363e9c412c5df564e08f

@maflcko
Copy link
Member

maflcko commented Sep 1, 2017

utACK 8c8ef83

Copy link
Contributor

@jnewbery jnewbery left a 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.

int64_t failed = 0;
int64_t alreadythere = 0;
Copy link
Contributor

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

Copy link
Member

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.

Copy link
Member Author

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.

// 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'
Copy link
Contributor

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.
@kallewoof
Copy link
Member Author

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

@jnewbery
Copy link
Contributor

jnewbery commented Sep 4, 2017

already_there seems fine to me. Will retest later.

@kallewoof
Copy link
Member Author

Didn't realize test failed. Restarting as it's obviously unrelated.

@jnewbery
Copy link
Contributor

jnewbery commented Sep 6, 2017

Tested ACK 258d33b

@maflcko
Copy link
Member

maflcko commented Sep 6, 2017

re-utACK 258d33b

@promag
Copy link
Member

promag commented Sep 6, 2017

utACK 258d33b.

@sipa sipa merged commit 258d33b into bitcoin:master Oct 18, 2017
sipa added a commit that referenced this pull request Oct 18, 2017
…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
@kallewoof kallewoof deleted the mempool-alreadythere branch October 18, 2017 09:40
ptschip pushed a commit to ptschip/BitcoinUnlimited that referenced this pull request Oct 22, 2019
…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
PastaPastaPasta pushed a commit to PastaPastaPasta/dash that referenced this pull request Dec 22, 2019
…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
jonspock pushed a commit to jonspock/devault that referenced this pull request Dec 27, 2019
…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
jonspock pushed a commit to devaultcrypto/devault that referenced this pull request Dec 29, 2019
…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
PastaPastaPasta pushed a commit to PastaPastaPasta/dash that referenced this pull request Jan 2, 2020
…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
PastaPastaPasta pushed a commit to PastaPastaPasta/dash that referenced this pull request Jan 4, 2020
…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
PastaPastaPasta pushed a commit to PastaPastaPasta/dash that referenced this pull request Jan 12, 2020
…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
PastaPastaPasta pushed a commit to PastaPastaPasta/dash that referenced this pull request Jan 12, 2020
…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
PastaPastaPasta pushed a commit to PastaPastaPasta/dash that referenced this pull request Jan 12, 2020
…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
PastaPastaPasta pushed a commit to PastaPastaPasta/dash that referenced this pull request Jan 12, 2020
…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
PastaPastaPasta pushed a commit to PastaPastaPasta/dash that referenced this pull request Jan 12, 2020
…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
PastaPastaPasta pushed a commit to PastaPastaPasta/dash that referenced this pull request Jan 12, 2020
…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
PastaPastaPasta pushed a commit to PastaPastaPasta/dash that referenced this pull request Jan 16, 2020
…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
jonspock pushed a commit to jonspock/devault that referenced this pull request Oct 1, 2020
…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
jonspock pushed a commit to jonspock/devault that referenced this pull request Oct 1, 2020
…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
jonspock pushed a commit to jonspock/devault that referenced this pull request Oct 5, 2020
…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
jonspock pushed a commit to devaultcrypto/devault that referenced this pull request Oct 10, 2020
…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
@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.
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

7 participants