Skip to content

Conversation

instagibbs
Copy link
Member

@instagibbs instagibbs commented Jul 7, 2020

Currently the only zmq notifications that exist for transactions are for:

  1. Entry into mempool
  2. Appearance in blocks
  3. Disconnect from block

For mempool-tracking purposes, it's useful to know when transactions are being dropped from the local mempool without relying on a tight polling loop. This notification publishes anytime a transaction is removed from the mempool, aside from the case where it is confirmed in the new incoming block(already published in 2 above).

Based on #19507

Additional test cases that could be added:

  1. block conflict
  2. mempool timeout
  3. mempool trim to size

@andrewtoth
Copy link
Contributor

Concept ACK.

Definitely useful since there's no easy way to currently track replacement for systems listening to bitcoind.

@DrahtBot
Copy link
Contributor

DrahtBot commented Jul 7, 2020

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

Conflicts

Reviewers, this pull request conflicts with the following ones:

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.

Copy link
Contributor

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

Concept ACK.

@instagibbs
Copy link
Member Author

Pushed some fixes, and documentation.

@instagibbs
Copy link
Member Author

Single run failure unrelated:

  File "/home/travis/build/bitcoin/bitcoin/ci/scratch/build/bitcoin-x86_64-pc-linux-gnu/test/functional/feature_backwards_compatibility.py", line 106, in run_test
    self.nodes[1].abandontransaction(tx3_id)

restarted

@maflcko maflcko removed the Tests label Jul 8, 2020
@laanwj
Copy link
Member

laanwj commented Jul 9, 2020

Concept ACK

@shuckc
Copy link

shuckc commented Jul 9, 2020

At the moment, the way that I synchronise with mempool contents is to poll getrawmempool and listen out for hashtx notifications, with the caveat that evictions are only detected by the poll. Since you are looking to address that here, Concept Ack from me.

One consideration is that it's not currently possible to perfectly synchronise the poll of getrawmempool with the zmq announcements, as they share no common sequence number. This can cause you to interpret an addition as a removal and visa-versa when checking for a tx hash in your local mempool transaction set. This get slightly worse with each additional zmq notifier you have to listen to, since they are typically (see lnd) configured on separate TCP connections, so TCP packet loss (causing delays on one stream) and reconnections can cause ordering issues. The configuration on separate connections seems to be an (now unnecessary) piece of inherited wisdom from before the publishing buffer size was tuneable with the High Water Mark value.

Since this implementation adds another new zmq notifier, it might be worthwhile to take this opportunity to design the notifier such that it can be used exclusively to maintain mempool synchronisation, then you would only need to query getrawmempool at startup and after seeing a gap on the zmq channel sequence number. This would require a message format that is something slightly more complex.

Could I suggest adding a new notifier called mempoolsync where the messages are:

C <block hash>              connect block hash
D <block hash>              disconnect block hash
A <txn hash>                add new transaction into mempool (ie. via rpc)
R <txn hash> <txn hash>     replace transaction hash with another
X <txn hash>                mempool eviction

Since this new notifier has all the relevant events for mempool synchonisation strongly sequenced by a single notifier sequence number, you could then (when zmq is compiled in) add an additional field in the return value for getrawmempool that is the last published notification value at the time the result was prepared. Of course to actually maintain mempool synchronisation, several of these events require calls to be made to bitcoind to decode various things depending on your use case, but that is relatively straightforward.

@luke-jr
Copy link
Member

luke-jr commented Jul 9, 2020

Couldn't this just be a new message for the existing endpoints?

@instagibbs
Copy link
Member Author

instagibbs commented Jul 9, 2020

@luke-jr I thought I'd break someone's integration perhaps if I did so since there's no "options" or anything in current messages, just txids AFAICT. (maybe I'm wrong!)

@instagibbs
Copy link
Member Author

pushed fixups

Copy link
Contributor

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

@@ -177,6 +179,25 @@ void CZMQNotificationInterface::TransactionAddedToMempool(const CTransactionRef&
}
}

void CZMQNotificationInterface::TransactionRemovedFromMempool(const CTransactionRef& ptx, MemPoolRemovalReason reason)
Copy link
Contributor

Choose a reason for hiding this comment

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

Also a some code duplication here with the two functions above.

@@ -178,6 +180,16 @@ bool CZMQPublishHashTransactionNotifier::NotifyTransaction(const CTransaction &t
return SendMessage(MSG_HASHTX, data, 32);
}

bool CZMQPublishHashTransactionEvictionNotifier::NotifyTransactionEviction(const CTransaction &transaction, MemPoolRemovalReason reason)
Copy link
Contributor

Choose a reason for hiding this comment

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

Code between this function and NotifyTransaction is almost identical, could be de-dublicated, maybe also together with NotifyBlock but it's not blocking IMO

Copy link
Member Author

Choose a reason for hiding this comment

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

Deduplicated the txn publishing portion, left block stuff alone for now.

@instagibbs instagibbs force-pushed the notify_eviction branch 2 times, most recently from ee86391 to 0686a96 Compare July 13, 2020 14:28
@instagibbs
Copy link
Member Author

Oddly enough I'm going to concept NACK my own PR.

After spending some time trying to write a "mempool tracker" via ZMQ with mempool sequence numbers, this plus legacy zmq notifications are insufficient.

  1. The hashtx feed really isn't a mempool feed, it's a feed of "transactions I saw somewhere", which is pretty obnoxious and hard to reason about and be very useful, especially in the presence of reorgs.
  2. The "eviction" feed here doesn't get told about transactions removed via block inclusion. This means relying on the hashtx feed, but there are no mempool sequence numbers attached to those because chainstate has no clue what a mempool is.

In my estimation, these transaction feeds can be subsumed by a single feed that is mempooltx, which includes both inclusion and exclusion from the mempool for any reason, with the appropriate label on the report. This way we don't have to touch older notifications at all instead of adding a bunch of options here and there to achieve the goal.

mempooltx allows you to track exactly what is in the mempool(assuming no dropped messages), and blockhash is used to trigger block transaction fetching(to show inclusion, exclusion via reog, etc).

@instagibbs instagibbs closed this Jul 14, 2020
laanwj added a commit that referenced this pull request Sep 23, 2020
…empool tracking

759d94e Update zmq notification documentation and sample consumer (Gregory Sanders)
68c3c7e Add functional tests for zmq sequence topic and mempool sequence logic (Gregory Sanders)
e76fc2b Add 'sequence' zmq publisher to track all block (dis)connects, mempool deltas (Gregory Sanders)
1b615e6 zmq test: Actually make reorg occur (Gregory Sanders)

Pull request description:

  This PR creates a new ZMQ notifier that gives a "total hash history" of block (dis)connection, mempool addition/substraction, all in one pipeline. It also exposes a "mempool sequence number" to both this notifier and `getrawmempool` results, which allows the consumer to use the results together without confusion about ordering of results and without excessive `getrawmempool` polling.

  See the functional test `interfaces_zmq.py::test_mempool_sync` which shows the proposed user flow for the client-side tracking of mempool contents and confirmations.

  Inspired by #19462 (comment)
  Alternative to #19462 due to noted deficiencies in current zmq notification streams.

  Also fixes a legacy zmq test that didn't actually trigger a reorg because of identical blocks being generated on each side of the split(oops)

ACKs for top commit:
  laanwj:
    Code review ACK 759d94e

Tree-SHA512: 9daf0d7d996190f3a68ff40340a687519323d7a6c51dcb26be457fbc013217ea7b62fbd0700b74b654433d2e370704feb61e5584399290692464fcfcb72ce3b7
sidhujag pushed a commit to syscoin/syscoin that referenced this pull request Sep 23, 2020
…-side mempool tracking

759d94e Update zmq notification documentation and sample consumer (Gregory Sanders)
68c3c7e Add functional tests for zmq sequence topic and mempool sequence logic (Gregory Sanders)
e76fc2b Add 'sequence' zmq publisher to track all block (dis)connects, mempool deltas (Gregory Sanders)
1b615e6 zmq test: Actually make reorg occur (Gregory Sanders)

Pull request description:

  This PR creates a new ZMQ notifier that gives a "total hash history" of block (dis)connection, mempool addition/substraction, all in one pipeline. It also exposes a "mempool sequence number" to both this notifier and `getrawmempool` results, which allows the consumer to use the results together without confusion about ordering of results and without excessive `getrawmempool` polling.

  See the functional test `interfaces_zmq.py::test_mempool_sync` which shows the proposed user flow for the client-side tracking of mempool contents and confirmations.

  Inspired by bitcoin#19462 (comment)
  Alternative to bitcoin#19462 due to noted deficiencies in current zmq notification streams.

  Also fixes a legacy zmq test that didn't actually trigger a reorg because of identical blocks being generated on each side of the split(oops)

ACKs for top commit:
  laanwj:
    Code review ACK 759d94e

Tree-SHA512: 9daf0d7d996190f3a68ff40340a687519323d7a6c51dcb26be457fbc013217ea7b62fbd0700b74b654433d2e370704feb61e5584399290692464fcfcb72ce3b7
@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.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

9 participants