Skip to content

Conversation

morcos
Copy link
Contributor

@morcos morcos commented Dec 16, 2016

Fixes #9479

This is my alternative to reverting #9240

@sipa
@laanwj

I think we have to decide which one of these 3 choices we like best:

  • walletnotify, zmq notification and UI notification on all transactions evicted from the mempool for any reason => merge this PR or something similar
  • walletnotify, zmq notification and UI notification on only transactions evicted from the mempool due to conflicts (prior behavior) => revert Remove txConflicted #9240
  • No walletnotify, zmq notification and UI notification on any transactions evicted from the mempool including due to conflicts => do nothing

I'm not sure this PR is the perfect solution, but I found txConflicted confusing, and I'm hoping this is at least a bit of a clearer overall picture.

Feedback welcome.

if (trackRemovalsCount == 0) {
std::vector<CTransactionRef> temp(std::move(removedTxs));
removedTxs.clear();
return std::move(temp);
Copy link
Member

Choose a reason for hiding this comment

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

It's better to have a single return statement that returns a local variable over using std::move:

    ...
    std::vector<CTransactionRef> temp;
    if (trackRemovalsCount == 0) {
        temp.emplace_back(std::move(removedTxs));
        removedTxs.clear();
    }
    return temp;
}

This allows the compiler to use NVRO (named return value optimization) - the temp variable essentially becomes an alias for the returned object.

Copy link
Contributor

@ryanofsky ryanofsky Dec 16, 2016

Choose a reason for hiding this comment

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

Using swap in the middle could be a nice way to simplify this:

    std::vector<CTransactionRef> temp;
    if (trackRemovalsCount == 0)
        temp.swap(removedTxs);
    return temp;

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 like @ryanofsky's suggestion. Will do.

// If there are ever intentionally removals that are not
// meant to be tracked (so they can be notified on), then
// this log message can be removed.
LogPrint("mempool", "MemPoolRemovalTracker not tracking removed transaction %s\n",hash.ToString());
Copy link
Contributor

Choose a reason for hiding this comment

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

Is this the only notification, or is the GUI notified also?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

about the error? this is the only log of the fact that a removal happened without notification.

@dcousens
Copy link
Contributor

dcousens commented Dec 19, 2016

Is there a way to isolate these changes to the wallet code only?
I understand it is to fix a problem there, but ideally I'd rather see just a primitive mechanism in the mempool for removal events, and the wallet then handle that with a "mempool removal tracker" and such.

AFAIK, non-wallet users don't need this or #9240 reverted.

@laanwj
Copy link
Member

laanwj commented Dec 19, 2016

I'd rather see just a primitive mechanism in the mempool for removal events, and the wallet then handle that with a "mempool removal tracker" and such.

In #8549 I had added a specific signal on the mempool to be notified of removed transactions, even with a reason field.
I think this was slightly more elegant than having a stateful StartTracking/StopTracking in the mempool itself and keeping a vector there (which means there can only be one client at a time). A client could easily handle the part of accumulating notifications into a vector itself, if that is desired.

@jonasschnelli
Copy link
Contributor

Agree with @laanwj: the reason enum is really what we should have for mempool removal notifications: https://github.com/bitcoin/bitcoin/pull/8549/files#diff-d8e6fe13399f13c42a93ec8326c60614R150

@dcousens
Copy link
Contributor

Agree with @laanwj, I actually thought that was merged and was wondering why this wasn't using it.

@morcos
Copy link
Contributor Author

morcos commented Dec 19, 2016

@laanwj ah, sorry I hadn't seen #8549. The reason I did it this way instead of trying to do notifications from the mempool directly was because we had just gone to such much effort to remove other notifications from happening within cs_main during the block connection logic.

It would be very easy to add to this PR the ability to distinguish between: "added", "removed", "appeared in a disconnected block", but slightly more involved to distinguish between the various "removed" reasons. (EDIT: I suppose the approach used in #8549 would work just as easily, we could just save the reason state in the vector.)

Whichever approach we take, I think it's a step in the right direction towards cleaning up the notification design and we should keep going. Note for example that even after #8549, I think "rawtx" and "hashtx" notifications are also happening on transactions in disconnected blocks (and before #9240 in transactions removed due to conflict), which doesn't seem to be the intent.

@morcos
Copy link
Contributor Author

morcos commented Jan 4, 2017

rebased

@morcos
Copy link
Contributor Author

morcos commented Jan 4, 2017

.. and added @ryanofsky's suggested cleanup

@sipa
Copy link
Member

sipa commented Jan 9, 2017

It seems strange to have a constraint that the mempool is either in a tracking or non-tracking state... the mempool object itself shouldn't need to know or care that there is at most one entity interested in seeing its removals.

Would it be possible to instead have a callback installed from the mempool to notify whatever is interested of removed transactions?

@morcos
Copy link
Contributor Author

morcos commented Jan 9, 2017

Yes @laanwj had a similar comment.
What I wanted to accomplish was that the notifications (or at least some of the potentially time consuming ones) happened outside of the critical path. The same as the change we recently made with transactions in connected blocks. But perhaps there is a better way to design that where the mempool just fires off its notifications immediately, but there can be a helper class that subscribes and appropriately batches them before passing them on? It's a bit tricky to imagine how some removals caused by limiting inside ATMP should be fired immediately and some shouldn't, but there ought to be a way.

In any case I'm open to a suggestion on redesigning that aspect of it.

@sipa
Copy link
Member

sipa commented Jan 9, 2017

The receiver of the mempool-removal event notifications can also still add things to a queue for later processing, i mean. It doesn't need to be the mempool that does the batching - as that inherently only works for a single consumer of event.

@morcos morcos force-pushed the notifyOnRemoval branch 2 times, most recently from 370061b to f0574d6 Compare January 18, 2017 19:08
@morcos
Copy link
Contributor Author

morcos commented Jan 18, 2017

OK I've redone this in a way that is hopefully more appealing.

The first commit is stolen (and slightly tweaked) from #8549 and will lay the ground work for a more flexible notification system on mempool actions.

Then I introduce a minimal MemPoolConflictRemovalTracker which should exactly mimic the behavior of txConflicted that was removed in #9240. I wouldn't argue that we want to keep this class in the long run, but as a regression fix for 0.14, I think this most clearly accomplishes the goal while moving us in a forward direction.

In the future we will want to rethink exactly what notifications need to fire on mempool removals and when. Most of the wallet functionality that is called by SyncTransaction is a no-op on mempool removals except for downstream notifications. This is documented.

~MemPoolConflictRemovalTracker() {
pool.NotifyEntryRemoved.disconnect(boost::bind(&MemPoolConflictRemovalTracker::NotifyEntryRemoved, this, _1, _2));
for (const auto& tx : conflictedTxs) {
GetMainSignals().SyncTransaction(*tx, NULL, CMainSignals::SYNC_TRANSACTION_NOT_IN_BLOCK);
Copy link
Member

Choose a reason for hiding this comment

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

Seems like a good time to split up SyncTransaction.

How about dropping the SYNC_TRANSACTION_NOT_IN_BLOCK kludge, and adding a new signal for mempool removals? I suspect @TheBlueMatt's recent-removed-tx-cache could benefit from that as well.

// notification of a connected conflict might cause an outside process
// to abandon a transaction and then have it inadvertantly cleared by
// the notification that the conflicted transaction was evicted.
MemPoolConflictRemovalTracker mrt(mempool);
Copy link
Contributor

Choose a reason for hiding this comment

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

I believe you need some lock held here so that no two threads could be calling mempool.NotifyEntryRemoved.connect at the same time, however I agree you dont want to SyncTransaction with cs_main held. You could add a static mutex here, or you could create the object with cs_main, then std::move it to a dummy which will be destroyed without cs_main.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Hmm I guess you're right.. Perhaps I need to go back to reference counting these things..

@TheBlueMatt
Copy link
Contributor

TheBlueMatt commented Jan 18, 2017

I believe this breaks #9570. Even if its rebased on #9570 (so that SyncTransaction becomes SyncTransactions and they're all batched together), the multiple per-block SyncTransactions calls will still expose wallet state as of mid-block to RPC clients. I'm not sure how exactly we should go about fixing this, but one way might be to take @theuni's suggestion for 0.14 and split SyncTransaction to SyncTransactionsFromBlock(vTxnConnected, vTxnConflicted) and TransactionAddedToMemPool(tx) so that we can hold the cs_wallet lock the whole time in SyncTransactionsFromBlock.

Of course, as noted in #9240, the only visible state from the SyncTransaction calls from CONFLICTED transaction removals is to un-abandon some transactions and update the UI/call walletnotify, both of which I think maybe are OK.

@morcos
Copy link
Contributor Author

morcos commented Jan 18, 2017

Yeah .... frustrating... Ideally we wouldn't actually be calling the wallet part of SyncTransaction for these transactions anyway. But I suspect that for 0.14 we should just be fine with wallet state being inspectable between these. As you point out it should have basically no effect... (it really shouldn't be unabandoning anything, that would imply some other logic was broken)

@morcos
Copy link
Contributor Author

morcos commented Jan 19, 2017

OK this has been rebased on #9583 which automagically fixes the lesser synchronization issues here if these notifications are also moved inside cs_main.

The ugly scope hack to have removals notified before connections I think should be removed after we tidy up abandoned logic in some future PR. I believe the natural order of notifications should be chainstate changes before mempool changes...

laanwj and others added 3 commits January 23, 2017 15:43
Add notification signals to make it possible to subscribe to mempool
changes:

- NotifyEntryAdded(CTransactionRef)>
- NotifyEntryRemoved(CTransactionRef, MemPoolRemovalReason)>

Also add a mempool removal reason enumeration, which is passed to the
removed notification based on why the transaction was removed from
the mempool.
Analogue to ConnectTrace that tracks transactions that have been removed from the mempool due to conflicts and then passes them through SyncTransaction at the end of its scope.
@TheBlueMatt
Copy link
Contributor

utACK 094e4b3

@@ -3597,7 +3642,7 @@ bool CVerifyDB::VerifyDB(const CChainParams& chainparams, CCoinsView *coinsview,
return error("VerifyDB(): *** ReadBlockFromDisk failed at %d, hash=%s", pindex->nHeight, pindex->GetBlockHash().ToString());
// check level 1: verify block validity
if (nCheckLevel >= 1 && !CheckBlock(block, state, chainparams.GetConsensus()))
return error("%s: *** found bad block at %d, hash=%s (%s)\n", __func__,
return error("%s: *** found bad block at %d, hash=%s (%s)\n", __func__,
Copy link
Member

Choose a reason for hiding this comment

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

μ-nit: please don't include space changes in otherwise unchanged lines/functions

Copy link
Contributor Author

Choose a reason for hiding this comment

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

heh. sure. i'll pass that on to the commit author. :)

@laanwj
Copy link
Member

laanwj commented Jan 24, 2017

Looks good to me now. utACK 094e4b3

@laanwj laanwj merged commit 094e4b3 into bitcoin:master Jan 24, 2017
laanwj added a commit that referenced this pull request Jan 24, 2017
094e4b3 Better document usage of SyncTransaction (Alex Morcos)
4afbde6 Introduce MemPoolConflictRemovalTracker (Alex Morcos)
ff25c32 mempool: add notification for added/removed entries (Wladimir J. van der Laan)
codablock pushed a commit to codablock/dash that referenced this pull request Jan 21, 2018
094e4b3 Better document usage of SyncTransaction (Alex Morcos)
4afbde6 Introduce MemPoolConflictRemovalTracker (Alex Morcos)
ff25c32 mempool: add notification for added/removed entries (Wladimir J. van der Laan)
andvgal pushed a commit to energicryptocurrency/gen2-energi that referenced this pull request Jan 6, 2019
094e4b3 Better document usage of SyncTransaction (Alex Morcos)
4afbde6 Introduce MemPoolConflictRemovalTracker (Alex Morcos)
ff25c32 mempool: add notification for added/removed entries (Wladimir J. van der Laan)
CryptoCentric pushed a commit to absolute-community/absolute that referenced this pull request Feb 27, 2019
@ryanofsky
Copy link
Contributor

@jnewbery pointed out the PR description here became out of date and doesn't reflect the change that was actually merged

re: #9371 (comment)

I think we have to decide which one of these 3 choices we like best:

  • walletnotify, zmq notification and UI notification on all transactions evicted from the mempool for any reason => merge this PR or something similar
  • walletnotify, zmq notification and UI notification on only transactions evicted from the mempool due to conflicts (prior behavior) => revert Remove txConflicted #9240
  • No walletnotify, zmq notification and UI notification on any transactions evicted from the mempool including due to conflicts => do nothing

Initially this PR implemented the first choice behavior (commits), but it was changed in #9371 (comment) to implement second choice behavior instead. That behavior got broken again in 7e89994 from #16624 and we are currently discussing how to restore it in #18325

laanwj added a commit that referenced this pull request Mar 19, 2020
…moved signals

e57980b [mempool] Remove NotifyEntryAdded and NotifyEntryRemoved callbacks (John Newbery)
2dd561f [validation] Remove pool member from ConnectTrace (John Newbery)
969b65f [validation] Remove NotifyEntryRemoved callback from ConnectTrace (John Newbery)
5613f98 [validation] Remove conflictedTxs from PerBlockConnectTrace (John Newbery)
cdb8934 [validation interface] Remove vtxConflicted from BlockConnected (John Newbery)
1168394 [wallet] Notify conflicted transactions in TransactionRemovedFromMempool (John Newbery)

Pull request description:

  These boost signals were added in #9371, before we had a `TransactionRemovedFromMempool` method in the validation interface. The `NotifyEntryAdded` callback was used by validation to build a vector of conflicted transactions when connecting a block, which the wallet was notified of in the `BlockConnected` CValidationInterface callback.

  Now that we have a `TransactionRemovedFromMempool` callback, we can fire that signal directly from the mempool for conflicted transactions.

  Note that #9371 was implemented to ensure `-walletnotify` events were fired for these conflicted transaction. We inadvertently stopped sending these notifications in #16624 (Sep 2019 commit 7e89994). We should probably fix that, but in a different PR.

ACKs for top commit:
  jonatack:
    Re-ACK e57980b
  ryanofsky:
    Code review ACK e57980b, no code changes since previous review, but helpful new code comments have been added and the PR description is now more clear about where the old code came from

Tree-SHA512: 3bdbaf1ef2731e788462d4756e69c42a1efdcf168691ce1bbfdaa4b7b55ac3c5b1fd4ab7b90bcdec653703600501b4224d252cfc086aef28f9ce0da3b0563a69
ryanofsky added a commit to ryanofsky/bitcoin that referenced this pull request May 5, 2020
Add test coverage for conflicted wallet transaction notifications so we improve
current behavior and avoid future regressions

bitcoin#9240 - accidental break
bitcoin#9479 - bug report
bitcoin#9371 - fix
bitcoin#16624 - accidental break
bitcoin#18325 - bug report
bitcoin#18600 - potential fix
ryanofsky added a commit to ryanofsky/bitcoin that referenced this pull request May 13, 2020
Add test coverage for conflicted wallet transaction notifications so we improve
current behavior and avoid future regressions

bitcoin#9240 - accidental break
bitcoin#9479 - bug report
bitcoin#9371 - fix
bitcoin#16624 - accidental break
bitcoin#18325 - bug report
bitcoin#18600 - potential fix
laanwj added a commit that referenced this pull request May 13, 2020
f963a68 test: Add test for conflicted wallet tx notifications (Russell Yanofsky)

Pull request description:

  Add test coverage for conflicted wallet transaction notifications so we can improve current behavior and avoid future regressions

  #9240 - accidental break
  #9479 - bug report
  #9371 - fix
  #16624 - accidental break
  #18325 - bug report
  #18600 - potential fix

ACKs for top commit:
  laanwj:
    ACK f963a68
  jonatack:
    re-ACK f963a68
  MarcoFalke:
    ACK f963a68

Tree-SHA512: d3a7952a2d3dc2ff0800ef857575ea4ef9759c0917d58a7fc91e2db0ca3cc3baf0dd0cf9af61683f691e5fefb11afe8120bb5810c7037ed9ecedee385dd4aa07
sidhujag pushed a commit to syscoin/syscoin that referenced this pull request May 14, 2020
…tions

f963a68 test: Add test for conflicted wallet tx notifications (Russell Yanofsky)

Pull request description:

  Add test coverage for conflicted wallet transaction notifications so we can improve current behavior and avoid future regressions

  bitcoin#9240 - accidental break
  bitcoin#9479 - bug report
  bitcoin#9371 - fix
  bitcoin#16624 - accidental break
  bitcoin#18325 - bug report
  bitcoin#18600 - potential fix

ACKs for top commit:
  laanwj:
    ACK f963a68
  jonatack:
    re-ACK f963a68
  MarcoFalke:
    ACK f963a68

Tree-SHA512: d3a7952a2d3dc2ff0800ef857575ea4ef9759c0917d58a7fc91e2db0ca3cc3baf0dd0cf9af61683f691e5fefb11afe8120bb5810c7037ed9ecedee385dd4aa07
fanquake pushed a commit to fanquake/bitcoin that referenced this pull request May 14, 2020
Add test coverage for conflicted wallet transaction notifications so we improve
current behavior and avoid future regressions

bitcoin#9240 - accidental break
bitcoin#9479 - bug report
bitcoin#9371 - fix
bitcoin#16624 - accidental break
bitcoin#18325 - bug report
bitcoin#18600 - potential fix

Github-Pull: bitcoin#18878
Rebased-From: f963a68
fanquake pushed a commit to fanquake/bitcoin that referenced this pull request May 15, 2020
Add test coverage for conflicted wallet transaction notifications so we improve
current behavior and avoid future regressions

bitcoin#9240 - accidental break
bitcoin#9479 - bug report
bitcoin#9371 - fix
bitcoin#16624 - accidental break
bitcoin#18325 - bug report
bitcoin#18600 - potential fix

Github-Pull: bitcoin#18878
Rebased-From: f963a68
janus pushed a commit to janus/bitgesell that referenced this pull request Nov 15, 2020
Add test coverage for conflicted wallet transaction notifications so we improve
current behavior and avoid future regressions

bitcoin/bitcoin#9240 - accidental break
bitcoin/bitcoin#9479 - bug report
bitcoin/bitcoin#9371 - fix
bitcoin/bitcoin#16624 - accidental break
bitcoin/bitcoin#18325 - bug report
bitcoin/bitcoin#18600 - potential fix
furszy added a commit to PIVX-Project/PIVX that referenced this pull request Jan 30, 2021
…llet

98d770f CScheduler boost->std::function, use millisecs for times, not secs (Matt Corallo)
67e068c Remove now unneeded ChainTip signal (furszy)
bcdd3e9 Move ChainTip sapling update witnesses and nullifiers to BlockConnected/BlockDisconnected. (furszy)
b799070 Take a CTransactionRef in AddToWalletIfInvolvingMe to avoid a copy (Matt Corallo)
d77244c Remove dead-code tracking of requests for blocks we generated (Matt Corallo)
10ccbbf Hold cs_wallet for whole block [dis]connection processing (Matt Corallo)
1a45036 fix compiler warning member functions not marked as 'override' (furszy)
d3867a7 An adaptation of Corallo's btc@461e49fee2935b1eb4d4ea7bae3023e655c0a6d8 (Matt Corallo)
f5ac648 [Refactor] Move Sapling ChainTip signal notification loop to use the latest connectTrace class structure (furszy)
8704d9d Handle SyncTransaction in ActivateBestChain instead of ConnectTrace (Matt Corallo)
6dcb6b0 Keep conflictedTxs in ConnectTrace per-block (Matt Corallo)
50d3e0e Handle conflicted transactions directly in ConnectTrace (furszy)
27fb897 Make ConnectTrace::blocksConnected private, hide behind accessors (Matt Corallo)
60329da Add pblock to connectTrace at the end of ConnectTip, not start (Matt Corallo)
e7c2789 Include missing #include in zmqnotificationinterface.h (Matt Corallo)
1b396b8 Move `NotifyEntryRemoved` to use the general interfaces::MakeHandler (furszy)
4cb5820 Better document usage of SyncTransaction (Alex Morcos)
21be4e2 Introduce MemPoolConflictRemovalTracker (Alex Morcos)
7326acb mempool: add notification for added/removed entries (Wladimir J. van der Laan)
a8605d2 Clean up tx prioritization when conflict mined (Casey Rodarmor)
e7db9ff remove internal tracking of mempool conflicts for reporting to wallet (Alex Morcos)
76c72c6 remove external usage of mempool conflict tracking (Alex Morcos)
ef429af tests: Stop node before removing the notification file (furszy)
15a21c2 tests: write the notification to different files to avoid race condition (Chun Kuan Lee)
466e97a [Wallet] Simplify InMempool (furszy)
85e18f0 Rename FlushWalletDB -> CompactWalletDB, add function description (Matt Corallo)
00f36ea Use CScheduler for wallet flushing, remove ThreadFlushWalletDB (Matt Corallo)

Pull request description:

  Revamped the validation interface interaction with the wallet, encapsulating and improving the mempool and block signaling and each of the wallet signals handler.
  Restructured the Sapling witnesses and nullifiers update under the new signals.
  Solved several bugs that found on the way as well (Check each commit description).

  This PR concludes with #1726 long road :). Pushing our repository around 2 years ahead in btc time in the mempool and validation interface areas (without including RBF).
  The new validation -> wallet interaction architecture will enable further, and much more user facing important, improvements for the syncing process, overall software responsiveness and multithreading locking issues.

  Adapted backports:
  dashpay#6464 --> Always clean up manual transaction prioritization (mempool)
  bitcoin#9240 --> Remove txConflicted (mempool)
  bitcoin#9371 --> Notify on removal (mempool)
  bitcoin#9605 --> Use CScheduler for wallet flushing, remove ThreadFlushWalletDB (walletdb)
  bitcoin#9725 --> CValidationInterface Cleanups (wallet, validation and validation interface)

ACKs for top commit:
  random-zebra:
    utACK 98d770f
  Fuzzbawls:
    utACK 98d770f

Tree-SHA512: 84c86567c2bff36b859b2ae73c558956a70dff0fffb4f73208708d92165b851bf42d35246410238c66c7a4b77e5bf51ec93885234a75fa48901fd182d2f70a28
backpacker69 pushed a commit to peercoin/peercoin that referenced this pull request Mar 28, 2021
Add test coverage for conflicted wallet transaction notifications so we improve
current behavior and avoid future regressions

bitcoin/bitcoin#9240 - accidental break
bitcoin/bitcoin#9479 - bug report
bitcoin/bitcoin#9371 - fix
bitcoin/bitcoin#16624 - accidental break
bitcoin/bitcoin#18325 - bug report
bitcoin/bitcoin#18600 - potential fix

Github-Pull: #18878
Rebased-From: f963a68
@bitcoin bitcoin locked as resolved and limited conversation to collaborators Feb 15, 2022
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.

-walletnotify isn't fired on transactions that were in the mempool and then evicted due to a tx in a new block conflicting them.
10 participants