ZMQ: Create “sequence” notifier, enabling client-side mempool tracking #19572

pull instagibbs wants to merge 4 commits into bitcoin:master from instagibbs:zmq_sequence_all changing 22 files +552 −63
  1. instagibbs commented at 3:06 pm on July 23, 2020: member

    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)

  2. instagibbs force-pushed on Jul 23, 2020
  3. instagibbs commented at 3:57 pm on July 23, 2020: member

    fixed bug(was pushing to verbose list of transactions)

    looking at another racey looking failure:

    0    assert_equal((payment_txid_2, "A", seq_num), seq.receive_sequence())
    1  File "/home/travis/build/bitcoin/bitcoin/ci/scratch/build/bitcoin-arm-linux-gnueabihf/test/functional/test_framework/util.py", line 49, in assert_equal
    2    raise AssertionError("not(%s)" % " == ".join(str(arg) for arg in (thing1, thing2) + args))
    3AssertionError: not(('1ac086d8f16212a6bab2bceee95742ff09e9477928c2e09e931a57c382d7b09b', 'A', 4) == ('1ac086d8f16212a6bab2bceee95742ff09e9477928c2e09e931a57c382d7b09b', 'A', 5))
    

    edit: Pushed fix(I hope) for that.

  4. DrahtBot commented at 4:57 pm on July 23, 2020: member

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

    Conflicts

    Reviewers, this pull request conflicts with the following ones:

    • #19967 (test: Replace (dis)?connect_nodes globals with TestFramework methods by robot-dreams)
    • #19652 (Avoid locking CTxMemPool::cs recursively in Mempool{Info}ToJSON() by hebasto)
    • #19532 (test: Mypy next steps by Ghorbanian)
    • #18531 (rpc: Assert that RPCArg names are equal to CRPCCommand ones by MarcoFalke)
    • #18309 (zmq: Add support to listen on multiple interfaces by n-thumann)

    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.

  5. DrahtBot added the label Mempool on Jul 23, 2020
  6. DrahtBot added the label RPC/REST/ZMQ on Jul 23, 2020
  7. DrahtBot added the label Tests on Jul 23, 2020
  8. DrahtBot added the label Validation on Jul 23, 2020
  9. DrahtBot added the label Wallet on Jul 23, 2020
  10. instagibbs force-pushed on Jul 23, 2020
  11. in test/functional/interface_zmq.py:170 in 951507c4d1 outdated
    146@@ -147,8 +147,8 @@ def test_reorg(self):
    147         self.nodes[0].generatetoaddress(1, ADDRESS_BCRT1_UNSPENDABLE)
    148         assert_equal(self.nodes[0].getbestblockhash(), hashblock.receive().hex())
    149 
    150-        # Generate 2 blocks in nodes[1]
    151-        self.nodes[1].generatetoaddress(2, ADDRESS_BCRT1_UNSPENDABLE)
    152+        # Generate 2 blocks in nodes[1] to a different address to ensure split
    153+        self.nodes[1].generatetoaddress(2, ADDRESS_BCRT1_P2WSH_OP_TRUE)
    


    promag commented at 10:23 pm on July 23, 2020:

    951507c4d1152ceab2a930fb16fdac05504f0056

    oops 😅 good catch.

  12. in src/txmempool.h:735 in dc413fbd8d outdated
    730@@ -725,6 +731,17 @@ class CTxMemPool
    731         return (m_unbroadcast_txids.count(txid) != 0);
    732     }
    733 
    734+    /** Guards this internal counter for external reporting */
    735+    uint32_t GetAndIncrementSequence() const {
    


    promag commented at 10:29 pm on July 23, 2020:
    EXCLUSIVE_LOCKS_REQUIRED(cs) instead?

    instagibbs commented at 1:39 am on August 4, 2020:
    done
  13. promag commented at 10:37 pm on July 23, 2020: member

    I still think #19476 makes life easier for the client in regards to fault tolerance and simplicity. With this PR, the client still has to bake its state from RPC and ZMQ.

    I think you could extract CValidationInterface changes to a different PR.

  14. instagibbs commented at 10:57 pm on July 23, 2020: member

    From conversations with people who use the notifications already they seemed more keen to a solution like this that doesn’t require long polling support. Also it makes wumpus less upset to just improve a current notification system 🤯

    That’s said they’re not necessarily in competition.

    On Thu, Jul 23, 2020, 6:37 PM João Barbosa notifications@github.com wrote:

    @promag commented on this pull request.

    I still think #19476 https://github.com/bitcoin/bitcoin/pull/19476 makes life easier for the client in regards to fault tolerance and simplicity. With this PR, the client still has to bake its state from RPC and ZMQ.

    I think you could extract CValidationInterface changes to a different PR.

    In test/functional/interface_zmq.py https://github.com/bitcoin/bitcoin/pull/19572#discussion_r459761022:

    @@ -147,8 +147,8 @@ def test_reorg(self):

         self.nodes[0].generatetoaddress(1, ADDRESS_BCRT1_UNSPENDABLE)
    
         assert_equal(self.nodes[0].getbestblockhash(), hashblock.receive().hex())
    
    •    # Generate 2 blocks in nodes[1]
      
    •    self.nodes[1].generatetoaddress(2, ADDRESS_BCRT1_UNSPENDABLE)
      
    •    # Generate 2 blocks in nodes[1] to a different address to ensure split
      
    •    self.nodes[1].generatetoaddress(2, ADDRESS_BCRT1_P2WSH_OP_TRUE)
      

    951507c https://github.com/bitcoin/bitcoin/commit/951507c4d1152ceab2a930fb16fdac05504f0056

    oops 😅 good catch.

    In src/txmempool.h https://github.com/bitcoin/bitcoin/pull/19572#discussion_r459763375:

    @@ -725,6 +731,17 @@ class CTxMemPool

         return (m_unbroadcast_txids.count(txid) != 0);
    
     }
    
    • /** Guards this internal counter for external reporting */

    • uint32_t GetAndIncrementSequence() const {

    EXCLUSIVE_LOCKS_REQUIRED(cs) instead?

    — You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/bitcoin/bitcoin/pull/19572#pullrequestreview-454535546, or unsubscribe https://github.com/notifications/unsubscribe-auth/ABMAFU6BN2AS2HWUGITFY7LR5C3UFANCNFSM4PF2HZKQ .

  15. promag commented at 10:53 am on July 26, 2020: member

    That’s said they’re not necessarily in competition.

    I wasn’t suggesting otherwise 👍

  16. jonasschnelli commented at 7:50 am on July 27, 2020: contributor
    Concept ACK
  17. instagibbs commented at 12:52 pm on July 27, 2020: member
    I’m running some extensive testing of this PR against testnet and mainnet nodes, tracking expected mempool for a couple weeks using a modified test harness. Once I’m satisfied I’ll be updating the test for this PR with the updated logic(if any) and maybe the consumer tool itself.
  18. instagibbs commented at 3:14 pm on July 27, 2020: member
    added test showing conflicted tx from block announcement(“R” shows up before “C”)
  19. instagibbs commented at 4:12 pm on July 27, 2020: member

    Was able to replicate a seeming gap in mempool_sequence values being reported. Pushed a possibly controversial fix(touching mempool logic) showing that it fixes the test case written.

    While that is a very minimal change I can understand it might rub people the wrong way.

    The alternatives are: 0) Ignore the gaps(print a warning when you see a gap maybe), it doesn’t seem to meaningfully interact with using the features as-is. Consumer will be tracking zmq sequence value, and any getrawmempool results will report an “expected” value.

    1. “Just” account for these gaps. When hitting an “R” mempool_sequence gap, sum up those gaps, then make sure that value + the number of found mempool transactions being removed normally equals the mempool_sequence reported in the next mempool report.
    2. Add another removal reporting hook which just announces all txhashes being removed.

    (2) seems like way overkill. (0) is fine for mempool view tracking, (1) just allows the consumer to do more asserting I guess, you can take it or leave it.

    Thoughts on last commit?

    edit: I’ve decided to just keep behavior as-is to avoid touching mempool code, and update the sample usage test to reflect that check.

  20. instagibbs force-pushed on Jul 27, 2020
  21. DrahtBot added the label Needs rebase on Jul 30, 2020
  22. in src/init.cpp:486 in b5de7c116a outdated
    482@@ -483,10 +483,12 @@ void SetupServerArgs(NodeContext& node)
    483     gArgs.AddArg("-zmqpubhashtx=<address>", "Enable publish hash transaction in <address>", ArgsManager::ALLOW_ANY, OptionsCategory::ZMQ);
    484     gArgs.AddArg("-zmqpubrawblock=<address>", "Enable publish raw block in <address>", ArgsManager::ALLOW_ANY, OptionsCategory::ZMQ);
    485     gArgs.AddArg("-zmqpubrawtx=<address>", "Enable publish raw transaction in <address>", ArgsManager::ALLOW_ANY, OptionsCategory::ZMQ);
    486+    gArgs.AddArg("-zmqpubsequence=<address>", "Enable publish hash block and tx sequence in <address>", ArgsManager::ALLOW_ANY, OptionsCategory::ZMQ);
    


    luke-jr commented at 0:32 am on July 31, 2020:
    “sequence” doesn’t really express what this does. Maybe “zmqpubmempool”?
  23. instagibbs commented at 0:36 am on July 31, 2020: member

    Point taken but it also publishes a sequence of block hashes for connects and disconnects.

    On Thu, Jul 30, 2020, 8:32 PM Luke Dashjr notifications@github.com wrote:

    @luke-jr commented on this pull request.

    In src/init.cpp https://github.com/bitcoin/bitcoin/pull/19572#discussion_r463343776:

    @@ -483,10 +483,12 @@ void SetupServerArgs(NodeContext& node) gArgs.AddArg("-zmqpubhashtx=", “Enable publish hash transaction in ”, ArgsManager::ALLOW_ANY, OptionsCategory::ZMQ); gArgs.AddArg("-zmqpubrawblock=", “Enable publish raw block in ”, ArgsManager::ALLOW_ANY, OptionsCategory::ZMQ); gArgs.AddArg("-zmqpubrawtx=", “Enable publish raw transaction in ”, ArgsManager::ALLOW_ANY, OptionsCategory::ZMQ);

    • gArgs.AddArg("-zmqpubsequence=", “Enable publish hash block and tx sequence in ”, ArgsManager::ALLOW_ANY, OptionsCategory::ZMQ);

    “sequence” doesn’t really express what this does. Maybe “zmqpubmempool”?

    — You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/bitcoin/bitcoin/pull/19572#pullrequestreview-458848709, or unsubscribe https://github.com/notifications/unsubscribe-auth/ABMAFU4SHWAGULPMYAO77NLR6IGKNANCNFSM4PF2HZKQ .

  24. instagibbs force-pushed on Aug 4, 2020
  25. instagibbs commented at 1:39 am on August 4, 2020: member

    rebased on master.

    Improved mempool sync test with code I’ve been running on mainnet/testnet for a few weeks now, last week with no issues. Added exclusive locks annotation.

  26. instagibbs force-pushed on Aug 4, 2020
  27. instagibbs force-pushed on Aug 4, 2020
  28. instagibbs force-pushed on Aug 4, 2020
  29. DrahtBot removed the label Needs rebase on Aug 4, 2020
  30. in src/init.cpp:504 in e98f4b36be outdated
    500@@ -499,6 +501,7 @@ void SetupServerArgs(NodeContext& node)
    501     hidden_args.emplace_back("-zmqpubhashtxhwm=<n>");
    502     hidden_args.emplace_back("-zmqpubrawblockhwm=<n>");
    503     hidden_args.emplace_back("-zmqpubrawtxhwm=<n>");
    504+    hidden_args.emplace_back("-zmqpubseqhwm=<n>");
    


    luke-jr commented at 6:28 pm on August 8, 2020:
    Shouldn’t this be spelled out?

    instagibbs commented at 5:51 pm on August 18, 2020:
    done
  31. in src/init.cpp:504 in e98f4b36be outdated
    500@@ -499,6 +501,7 @@ void SetupServerArgs(NodeContext& node)
    501     hidden_args.emplace_back("-zmqpubhashtxhwm=<n>");
    


    luke-jr commented at 6:28 pm on August 8, 2020:
    Think you need zmqpubsequence in here too

    instagibbs commented at 5:50 pm on August 18, 2020:
    done
  32. in src/rpc/blockchain.cpp:502 in e98f4b36be outdated
    498@@ -499,14 +499,25 @@ UniValue MempoolToJSON(const CTxMemPool& pool, bool verbose)
    499         }
    500         return o;
    501     } else {
    502+        uint32_t mempool_sequence = 0;
    


    luke-jr commented at 1:47 am on August 9, 2020:
    This shouldn’t be initialised here

    instagibbs commented at 5:50 pm on August 18, 2020:
    done
  33. in src/rpc/blockchain.cpp:505 in e98f4b36be outdated
    482@@ -483,7 +483,7 @@ static void entryToJSON(const CTxMemPool& pool, UniValue& info, const CTxMemPool
    483     info.pushKV("unbroadcast", pool.IsUnbroadcastTx(tx.GetHash()));
    484 }
    485 
    486-UniValue MempoolToJSON(const CTxMemPool& pool, bool verbose)
    487+UniValue MempoolToJSON(const CTxMemPool& pool, bool verbose, bool include_mempool_sequence)
    488 {
    489     if (verbose) {
    


    luke-jr commented at 1:50 am on August 9, 2020:
    Should throw an exception if include_mempool_sequence is true here. (Or support it)

    instagibbs commented at 5:50 pm on August 18, 2020:
    done, throws error + test
  34. in src/txmempool.h:480 in e98f4b36be outdated
    473@@ -474,6 +474,12 @@ class CTxMemPool
    474     mutable uint64_t m_epoch;
    475     mutable bool m_has_epoch_guard;
    476 
    477+    // In-memory counter for external mempool tracking purposes.
    478+    // This number is incremented once every time a transaction
    479+    // is added or removed from the mempool(except when removed
    480+    // for block inclusion).
    


    luke-jr commented at 1:54 am on August 9, 2020:
    The code increments it for block inclusion removals too…

    instagibbs commented at 3:27 pm on August 10, 2020:
    Right, stale comment. Will update.

    instagibbs commented at 5:50 pm on August 18, 2020:
    done
  35. in src/txmempool.h:481 in e98f4b36be outdated
    473@@ -474,6 +474,12 @@ class CTxMemPool
    474     mutable uint64_t m_epoch;
    475     mutable bool m_has_epoch_guard;
    476 
    477+    // In-memory counter for external mempool tracking purposes.
    478+    // This number is incremented once every time a transaction
    479+    // is added or removed from the mempool(except when removed
    480+    // for block inclusion).
    481+    mutable uint32_t sequence_number{1};
    


    luke-jr commented at 1:54 am on August 9, 2020:
    m_sequence_number

    luke-jr commented at 1:57 am on August 9, 2020:

    Maybe uint64_t would be better?

    Possibly even a sequence_number_t typedef in case it were to ever change.


    instagibbs commented at 3:29 pm on August 10, 2020:
    I believe my original theory was that the zmq sequence values themselves were also 32 bit, so I figured not much to be gained since any consumer has to handle this wrap around anyways?

    instagibbs commented at 1:36 pm on August 18, 2020:
    Offline someone noted that the ZMQ sequence numbers(probably) reset if the connection itself is reset, but the mempool sequence numbers will continue. I think this is a good argument to expand to uint64_t. Will do that soon.

    instagibbs commented at 5:50 pm on August 18, 2020:
    done

    instagibbs commented at 5:50 pm on August 18, 2020:
    done
  36. in src/validationinterface.h:106 in e98f4b36be outdated
     97@@ -98,6 +98,17 @@ class CValidationInterface {
     98      * Called on a background thread.
     99      */
    100     virtual void TransactionAddedToMempool(const CTransactionRef& tx) {}
    101+    /**
    102+     * Notifies listeners of a transaction having been added to mempool.
    103+     *
    104+     * Required because of legacy ZMQ notifications including block
    105+     * transactions when using TransactionAddedToMempool. See:
    106+     * CZMQNotificationInterface::TransactionAddedToMempool
    


    luke-jr commented at 2:01 am on August 9, 2020:
    Ugly hack. Just change CZMQNotificationInterface

    instagibbs commented at 3:30 pm on August 10, 2020:
    Sorry, change it how specifically? If you mean I should change the legacy notifications too, I disagree? Might be misunderstanding.

    instagibbs commented at 7:04 pm on August 18, 2020:
    Figured out what you meant. Done in follow-on commit.
  37. luke-jr changes_requested
  38. instagibbs force-pushed on Aug 18, 2020
  39. instagibbs force-pushed on Aug 18, 2020
  40. instagibbs commented at 7:07 pm on August 18, 2020: member

    Updated PR with fixes/cleanups, and changed sequence number to 8 bytes.

    Dogfooding consumer still running strong after 2+ weeks on testnet/mainnet, no mempool inconsistencies or dropped messages.

  41. jonatack commented at 7:25 pm on August 18, 2020: member

    Concept ACK

    (You had me at “dogfooding”)

  42. instagibbs commented at 3:41 pm on August 20, 2020: member

    Looks like the consumer logic failed during the recent mainnet reorg of one block https://twitter.com/BitMEXResearch/status/1296431817592057857

    A->D->A occurred and the mempool sequence number jumped by a couple hundred between the two As which is unexpected based on my assumptions of Core locking. Investigating more. (Note that this worst case means you have to take an additional getrawmempool snapshot) If this ends up being too messy I may change the format to notifying for each removal by mining as well.

  43. MarcoFalke removed the label Tests on Aug 23, 2020
  44. MarcoFalke removed the label Wallet on Aug 23, 2020
  45. instagibbs commented at 5:06 pm on August 25, 2020: member

    After some consideration of the failure detected above, I’m going to stick with the current format, and eat the cost of a single getrawmempool call every time an unexpected mempool sequence value is encountered. If all evictions are announced for block inclusion we get dangerously close to blowing out zmq buffers, and in practice is creating more traffic for little gain.

    In other words, please continue review :)

  46. DrahtBot added the label Needs rebase on Aug 31, 2020
  47. instagibbs force-pushed on Sep 1, 2020
  48. instagibbs commented at 2:44 am on September 1, 2020: member
    rebased
  49. DrahtBot removed the label Needs rebase on Sep 1, 2020
  50. n-thumann commented at 6:25 pm on September 1, 2020: contributor
    Tested ACK, works as expected on macOS 10.15.6. Just two minor hints: I think this should also be added to doc/zmq.md and explicitly explain the difference between the already existing sequence number and this new mempool sequence number to prevent confusion. Maybe also add these new notifications to contrib/zmq_sub.py with unpacking of message type (Tx addition/removal, Block connect/disconnect) and mempool sequence number ✌️
  51. instagibbs commented at 6:28 pm on September 1, 2020: member
    @n-thumann good points, I was unfamiliar with those docs. Will update with an additional commit
  52. instagibbs commented at 7:19 pm on September 1, 2020: member

    @n-thumann can you actually get contrib/zmq/zmq_sub.py to work? I updated what I think it should look like, but I had trouble running it even with legacy notifications. Try it out?

     0Task exception was never retrieved
     1future: <Task finished coro=<ZMQHandler.handle() done, defined at contrib/zmq/zmq_sub.py:54> exception=ValueError('Invalid file object: <zmq.asyncio.Socket object at 0x7f62f0138e88>',)>
     2Traceback (most recent call last):
     3  File "contrib/zmq/zmq_sub.py", line 55, in handle
     4    topic, body, seq = await self.zmqSubSocket.recv_multipart()
     5  File "/usr/lib/python3/dist-packages/zmq/eventloop/future.py", line 170, in recv_multipart
     6    dict(flags=flags, copy=copy, track=track)
     7  File "/usr/lib/python3/dist-packages/zmq/eventloop/future.py", line 321, in _add_recv_event
     8    self._add_io_state(self._READ)
     9  File "/usr/lib/python3/dist-packages/zmq/asyncio/__init__.py", line 294, in _add_io_state
    10    self.io_loop.add_reader(self, self._handle_recv)
    11  File "/usr/lib/python3.6/asyncio/selector_events.py", line 326, in add_reader
    12    return self._add_reader(fd, callback, *args)
    13  File "/usr/lib/python3.6/asyncio/selector_events.py", line 253, in _add_reader
    14    key = self._selector.get_key(fd)
    15  File "/usr/lib/python3.6/selectors.py", line 189, in get_key
    16    return mapping[fileobj]
    17  File "/usr/lib/python3.6/selectors.py", line 70, in __getitem__
    18    fd = self._selector._fileobj_lookup(fileobj)
    19  File "/usr/lib/python3.6/selectors.py", line 224, in _fileobj_lookup
    20    return _fileobj_to_fd(fileobj)
    21  File "/usr/lib/python3.6/selectors.py", line 39, in _fileobj_to_fd
    22    "{!r}".format(fileobj)) from None
    23ValueError: Invalid file object: <zmq.asyncio.Socket object at 0x7f62f0138e88>
    
  53. instagibbs force-pushed on Sep 1, 2020
  54. in doc/zmq.md:125 in 6bc7b33008 outdated
    120@@ -119,3 +121,8 @@ There are several possibilities that ZMQ notification can get lost
    121 during transmission depending on the communication type you are
    122 using. Bitcoind appends an up-counting sequence number to each
    123 notification which allows listeners to detect lost notifications.
    124+
    125+The "sequence" publisher refers specifically to the mempool sequence
    


    n-thumann commented at 10:21 pm on September 1, 2020:

    slightly more consistent wording 😊

    0The `sequence` topic refers specifically to the mempool sequence
    
  55. in contrib/zmq/zmq_sub.py:72 in 6bc7b33008 outdated
    67@@ -69,6 +68,12 @@ async def handle(self) :
    68         elif topic == b"rawtx":
    69             print('- RAW TX ('+sequence+') -')
    70             print(binascii.hexlify(body))
    71+        elif topic == b"sequence":
    72+            hash = body[:32].hex()
    


    n-thumann commented at 11:08 pm on September 1, 2020:

    Use bytes instead of string

    0            hash = binascii.hexlify(body[:32])
    
  56. in contrib/zmq/zmq_sub.py:76 in 6bc7b33008 outdated
    67@@ -69,6 +68,12 @@ async def handle(self) :
    68         elif topic == b"rawtx":
    69             print('- RAW TX ('+sequence+') -')
    70             print(binascii.hexlify(body))
    71+        elif topic == b"sequence":
    72+            hash = body[:32].hex()
    73+            label = chr(body[32])
    74+            mempool_sequence = None if len(body) != 32+1+8 else struct.unpack("<Q", body[32+1:])[0]
    75+            print('- SEQUENCE ('+sequence+') -')
    76+            print("{} {} {}".format(hash, label, mempool_sequence))
    


    n-thumann commented at 11:16 pm on September 1, 2020:

    Format looks unnecessary here :)

    0            print(hash, label, mempool_sequence)
    
  57. n-thumann commented at 11:17 pm on September 1, 2020: contributor

    @n-thumann can you actually get contrib/zmq/zmq_sub.py to work?

    Your updated script runs perfectly fine! Another doc related idea: Should these lines be changed? This only applies when using hashblock or rawblock and can be circumvented by using sequence topic. I think it´s also useful to briefly mention here that the body of sequence notifications differs from the others, so basically what you´ve already written here ✌️. Oh, and in case you have a little bit of spare time I would you mind having a look at my (also zmq-related) PR #18309? 😊

  58. instagibbs force-pushed on Sep 2, 2020
  59. instagibbs commented at 2:05 am on September 2, 2020: member
    took your suggestions @n-thumann , added some more information to docs as well as suggested
  60. n-thumann approved
  61. instagibbs requested review from promag on Sep 2, 2020
  62. in test/functional/interface_zmq.py:237 in 103207ba2e outdated
    232+        <32-byte hash>D :                 Blockhash disconnected
    233+        <32-byte hash>R<8-byte LE uint> : Transactionhash removed from mempool for non-block inclusion reason
    234+        <32-byte hash>A<8-byte LE uint> : Transactionhash added mempool
    235+        """
    236+        self.log.info("Testing 'sequence' publisher")
    237+        import zmq
    


    jonatack commented at 2:24 pm on September 3, 2020:

    Perhaps import zmq once at the top rather than 4 times in the tests, e.g.:

     0diff --git a/test/functional/interface_zmq.py b/test/functional/interface_zmq.py
     1index ef4780cacb..3afab07dbf 100755
     2--- a/test/functional/interface_zmq.py
     3+++ b/test/functional/interface_zmq.py
     4@@ -4,6 +4,7 @@
     5 # file COPYING or http://www.opensource.org/licenses/mit-license.php.
     6 """Test the ZMQ notification interface."""
     7 import struct
     8+import zmq
     9 
    10 from test_framework.address import ADDRESS_BCRT1_UNSPENDABLE
    11 from test_framework.test_framework import BitcoinTestFramework
    12@@ -21,7 +22,6 @@ class ZMQSubscriber:
    13         self.socket = socket
    14         self.topic = topic
    15 
    16-        import zmq
    17         self.socket.setsockopt(zmq.SUBSCRIBE, self.topic)
    18 
    19     def receive(self):
    20@@ -43,7 +43,6 @@ class ZMQTest (BitcoinTestFramework):
    21         self.skip_if_no_bitcoind_zmq()
    22 
    23     def run_test(self):
    24-        import zmq
    25         self.ctx = zmq.Context()
    26         try:
    27             self.test_basic()
    28@@ -54,8 +53,6 @@ class ZMQTest (BitcoinTestFramework):
    29             self.ctx.destroy(linger=None)
    30 
    31     def test_basic(self):
    32-        import zmq
    33-
    34         # Invalid zmq arguments don't take down the node, see [#17185](/bitcoin-bitcoin/17185/).
    35         self.restart_node(0, ["-zmqpubrawtx=foo", "-zmqpubhashtx=bar"])
    36 
    37@@ -146,7 +143,6 @@ class ZMQTest (BitcoinTestFramework):
    38             self.log.info("Skipping reorg test because wallet is disabled")
    39             return
    40 
    41-        import zmq
    42         address = 'tcp://127.0.0.1:28333'
    43 
    44         services = [b"hashblock", b"hashtx"]
    

    instagibbs commented at 4:12 pm on September 4, 2020:
    done

    instagibbs commented at 7:06 pm on September 4, 2020:
    found out why: zmq-less functional test builds. Stuck it inside a pass-through try/except block.
  63. in src/zmq/zmqnotificationinterface.cpp:208 in 103207ba2e outdated
    205+        for (std::list<CZMQAbstractNotifier*>::iterator i = notifiers.begin(); i!=notifiers.end(); )
    206+        {
    207+            CZMQAbstractNotifier *notifier = *i;
    208+            if (notifier->NotifyTransaction(*ptx))
    209+            {
    210+                i++;
    


    jonatack commented at 2:56 pm on September 3, 2020:

    here and four other places below in the new code

    0                ++i;
    

    instagibbs commented at 7:19 pm on September 3, 2020:
    is this in the style guide? :P

    jonatack commented at 7:42 pm on September 3, 2020:
    yeah, ++i is preferred over i++

    instagibbs commented at 4:12 pm on September 4, 2020:
    done
  64. in contrib/zmq/zmq_sub.py:55 in 103207ba2e outdated
    53 
    54     async def handle(self) :
    55-        msg = await self.zmqSubSocket.recv_multipart()
    56-        topic = msg[0]
    57-        body = msg[1]
    58+        topic, body, seq = await self.zmqSubSocket.recv_multipart()
    


    jonatack commented at 5:18 pm on September 3, 2020:
    Nice cleanup here.
  65. in contrib/zmq/zmq_sub.py:58 in 103207ba2e outdated
    59         sequence = "Unknown"
    60-        if len(msg[-1]) == 4:
    61-          msgSequence = struct.unpack('<I', msg[-1])[-1]
    62-          sequence = str(msgSequence)
    63+        if len(seq) == 4:
    64+          sequence = str(struct.unpack('<I', seq)[-1])
    


    jonatack commented at 5:18 pm on September 3, 2020:

    indentation

    0            sequence = str(struct.unpack('<I', seq)[-1])
    

    instagibbs commented at 4:11 pm on September 4, 2020:
    done
  66. in test/functional/interface_zmq.py:12 in 103207ba2e outdated
    10+from test_framework.blocktools import create_block, create_coinbase, add_witness_commitment
    11 from test_framework.test_framework import BitcoinTestFramework
    12-from test_framework.messages import CTransaction, hash256
    13-from test_framework.util import assert_equal, connect_nodes
    14+from test_framework.messages import CTransaction, hash256, FromHex
    15+from test_framework.util import assert_equal, connect_nodes, assert_raises_rpc_error
    


    jonatack commented at 5:21 pm on September 3, 2020:

    nit, sort

    0from test_framework.util import (
    1    assert_equal,
    2    assert_raises_rpc_error,
    3    connect_nodes,
    4)
    

    instagibbs commented at 4:11 pm on September 4, 2020:
    done
  67. in test/functional/interface_zmq.py:341 in 103207ba2e outdated
    336+            self.log.info("Evict mempool transaction by block conflict")
    337+            orig_txid = self.nodes[0].sendtoaddress(address=self.nodes[0].getnewaddress(), amount=1.0, replaceable=True)
    338+
    339+            # More to be simply mined
    340+            more_tx = []
    341+            for i in range(5):
    


    jonatack commented at 6:08 pm on September 3, 2020:
    0            for _ in range(5):
    

    instagibbs commented at 4:11 pm on September 4, 2020:
    done
  68. in test/functional/interface_zmq.py:417 in 103207ba2e outdated
    412+
    413+        # Some transactions have been happening but we aren't consuming zmq notifications yet
    414+        # or we lost a ZMQ message somehow and want to start over
    415+        txids = []
    416+        num_txs = 5
    417+        for i in range(num_txs):
    


    jonatack commented at 6:09 pm on September 3, 2020:
    0        for _ in range(num_txs):
    

    instagibbs commented at 4:11 pm on September 4, 2020:
    done
  69. in test/functional/interface_zmq.py:443 in 103207ba2e outdated
    438+            mempool_view = set(mempool_snapshot["txids"])
    439+            get_raw_seq = mempool_snapshot["mempool_sequence"]
    440+
    441+        # Things continue to happen in the "interim" while waiting for snapshot results
    442+        # We have node 0 do all these to avoid p2p races with RBF announcements
    443+        for i in range(num_txs):
    


    jonatack commented at 6:09 pm on September 3, 2020:
    0        for _ in range(num_txs):
    

    instagibbs commented at 4:11 pm on September 4, 2020:
    done
  70. in test/functional/interface_zmq.py:464 in 103207ba2e outdated
    459+
    460+        # 4) Moving forward, we apply the delta to our local view
    461+        #    remaining txs(5) + 1 rbf(A+R) + 1 block connect + 1 final tx
    462+        expected_sequence = get_raw_seq
    463+        r_gap = 0
    464+        for i in range(num_txs+2+1+1):
    


    jonatack commented at 6:10 pm on September 3, 2020:
    0        for _ in range(num_txs + 2 + 1 + 1):
    

    instagibbs commented at 4:11 pm on September 4, 2020:
    done
  71. jonatack commented at 7:05 pm on September 3, 2020: member

    Checkpoint review feedback so far:

    • the debug build is clean and tests green
    • the contrib script seems to work well and without issues after a day of doing it’s thing, though I needed to chmod it to change permissions to run it (EDIT: fixed in #19870)
    • the new c++ code could definitely do with some clang formatting :heart:
    • now or for later, there is a fair amount of duplicate-looking code, nothing blocking tho
    • so far the test interface_zmq.py fails in 38fbf2d8f5 at line 103
    • in 9b5daf74f the test fails as well; best if each commit has passing tests
    • EDIT: the test passes for me in commits d353bd19b, a976c97c9, and 92ca0fca0

    A few minor comments follow to take or leave.

  72. in doc/zmq.md:127 in 103207ba2e outdated
    127+Note that for `*block` topics when the block chain tip changes,
    128+a reorganisation may occur and just the tip will be notified.
    129+It is up to the subscriber to retrieve the chain from the last known
    130+block to the new tip. Also note that no notification occurs if the tip
    131+was in the active chain - this is the case after calling invalidateblock RPC.
    132+In contrast the `sequence` topic publishes all block connects and disconnects.
    


    jonatack commented at 11:07 am on September 4, 2020:

    nit proposals, feel free to take or ignore

     0-Note that for `*block` topics when the block chain tip changes,
     1-a reorganisation may occur and just the tip will be notified.
     2+Note that for `*block` topics, when the block chain tip changes,
     3+a reorganisation may occur and only the tip will be notified.
     4 It is up to the subscriber to retrieve the chain from the last known
     5-block to the new tip. Also note that no notification occurs if the tip
     6-was in the active chain - this is the case after calling invalidateblock RPC.
     7-In contrast the `sequence` topic publishes all block connects and disconnects.
     8+block to the new tip. Also note that no notification will occur if the tip
     9+was in the active chain--as would be the case after calling the invalidateblock
    10+RPC. In contrast, the `sequence` topic publishes all block connections and
    11+disconnections.
    

    instagibbs commented at 4:11 pm on September 4, 2020:
    took most of this
  73. in doc/zmq.md:153 in 103207ba2e outdated
    137 notification which allows listeners to detect lost notifications.
    138+
    139+The `sequence` topic refers specifically to the mempool sequence
    140+number which is also published along with all mempool events. This
    141+is a different sequence value than in ZMQ itself to allow a total
    142+ordering of mempool events to be constructed.
    


    jonatack commented at 11:08 am on September 4, 2020:

    nit suggestions

    0 The `sequence` topic refers specifically to the mempool sequence
    1-number which is also published along with all mempool events. This
    2-is a different sequence value than in ZMQ itself to allow a total
    3+number, which is also published along with all mempool events. This
    4+is a different sequence value than in ZMQ itself in order to allow a total
    5 ordering of mempool events to be constructed.
    

    instagibbs commented at 4:11 pm on September 4, 2020:
    done
  74. jonatack commented at 11:18 am on September 4, 2020: member
    Approach ACK on this useful feature for bitcoind mempool management that has the bonus of you and others dogfooding it. Thanks for the tests and updated contrib script and doc. It seems pretty close apart from the nits mentioned above and clean organisation of the commits wrt the test changes. I’m not sure if it’s helpful for 92ca0fca04cdb6 to be a separate commit, as it partially undoes some of the changes in the previous commits, unless you wanted to document the design in some way. Otherwise LGTM, will re-review after the next update.
  75. in src/rpc/blockchain.cpp:490 in 103207ba2e outdated
    482@@ -483,9 +483,12 @@ static void entryToJSON(const CTxMemPool& pool, UniValue& info, const CTxMemPool
    483     info.pushKV("unbroadcast", pool.IsUnbroadcastTx(tx.GetHash()));
    484 }
    485 
    486-UniValue MempoolToJSON(const CTxMemPool& pool, bool verbose)
    487+UniValue MempoolToJSON(const CTxMemPool& pool, bool verbose, bool include_mempool_sequence)
    488 {
    489     if (verbose) {
    490+        if (include_mempool_sequence) {
    491+            throw JSONRPCError(RPC_INVALID_PARAMETER, "Verbose results can not contain mempool sequence values.");
    


    jonatack commented at 12:29 pm on September 4, 2020:
    s/can not/cannot/

    instagibbs commented at 4:11 pm on September 4, 2020:
    done

    instagibbs commented at 4:15 pm on September 4, 2020:
    my string change broke the test of this. See!?!

    jonatack commented at 4:31 pm on September 4, 2020:
    Proof of test! 😄
  76. in src/rpc/blockchain.cpp:538 in 103207ba2e outdated
    519+        if (!include_mempool_sequence) {
    520+            return a;
    521+        } else {
    522+            UniValue o(UniValue::VOBJ);
    523+            o.pushKV("txids", a);
    524+            o.pushKV("mempool_sequence", mempool_sequence);
    


    jonatack commented at 12:31 pm on September 4, 2020:
    The behavior of getrawmempool with the additional param and its interaction with verbose should be covered in a functional test, unless I missed the added assertion somewhere.

    instagibbs commented at 3:42 pm on September 4, 2020:
    There is a test line for it: assert_raises_rpc_error(-8, "Verbose results can not contain mempool sequence values.", self.nodes[0].getrawmempool, True, True)

    jonatack commented at 4:01 pm on September 4, 2020:
    Oops, I even tested it manually as well. More like an assert("mempool_sequence" in getrawmempool.keys()) or even checking the value too.

    jonatack commented at 4:02 pm on September 4, 2020:
    Never mind, it looks like you covered that.
  77. jonatack commented at 12:31 pm on September 4, 2020: member
    A couple items with the RPC changes.
  78. instagibbs force-pushed on Sep 4, 2020
  79. instagibbs commented at 4:12 pm on September 4, 2020: member

    @jonatack I’m keeping https://github.com/bitcoin/bitcoin/pull/19572/commits/003767e7a92e8ae41f5c561a69d7be23e4753f63 in for now out of a real reason(it’s changing how the legacy zmq notifications work under the hood) and laziness.

    Should have addessed everything. Did some history cleanup as well.

  80. instagibbs force-pushed on Sep 4, 2020
  81. instagibbs force-pushed on Sep 4, 2020
  82. instagibbs commented at 7:47 pm on September 4, 2020: member
    @mruddy in case you’re interested(I don’t know if you’re on IRC)
  83. DrahtBot added the label Needs rebase on Sep 5, 2020
  84. instagibbs force-pushed on Sep 5, 2020
  85. instagibbs commented at 4:17 pm on September 5, 2020: member
    rebased, looks like appveyor and one of the cirrus builds is having the sads
  86. DrahtBot removed the label Needs rebase on Sep 5, 2020
  87. MarcoFalke commented at 5:48 pm on September 5, 2020: member
    You might have to add a suppression, not sure if the tsan failue is a false positive
  88. instagibbs commented at 9:01 pm on September 6, 2020: member
    Can’t seem to replicate locally with tsan.
  89. instagibbs requested review from jonatack on Sep 8, 2020
  90. instagibbs commented at 12:55 pm on September 8, 2020: member
    @n-thumann (can’t seem to re-request with your stale review, thanks github)
  91. n-thumann commented at 5:21 pm on September 8, 2020: contributor

    @n-thumann (can’t seem to re-request with your stale review, thanks github)

    re-ACK c2f03fd7b9090ac17299190f118511326483f23c ✌️

  92. in src/zmq/zmqnotificationinterface.cpp:167 in c2f03fd7b9 outdated
    166 
    167     for (std::list<CZMQAbstractNotifier*>::iterator i = notifiers.begin(); i!=notifiers.end(); )
    168     {
    169         CZMQAbstractNotifier *notifier = *i;
    170-        if (notifier->NotifyTransaction(tx))
    171+        if (notifier->NotifyTransaction(tx) && notifier->NotifyTransactionAcceptance(tx, mempool_sequence))
    


    jonatack commented at 7:57 pm on September 8, 2020:

    error here while building 712f214

    0zmq/zmqnotificationinterface.cpp: In member function virtual void CZMQNotificationInterface::TransactionAddedToMempool(const CTransactionRef&, uint64_t):
    1zmq/zmqnotificationinterface.cpp:167:106: error: no matching function for call to CZMQAbstractNotifier::NotifyTransactionAcceptance(const CTransaction&, uint64_t&)
    2  167 |         if (notifier->NotifyTransaction(tx) && notifier->NotifyTransactionAcceptance(tx, mempool_sequence))
    3      |                                                                                                          ^
    4In file included from ./zmq/zmqpublishnotifier.h:8,
    5                 from zmq/zmqnotificationinterface.cpp:6:
    6./zmq/zmqabstractnotifier.h:50:18: note: candidate: virtual bool CZMQAbstractNotifier::NotifyTransactionAcceptance(const CTransaction&)
    7   50 |     virtual bool NotifyTransactionAcceptance(const CTransaction &transaction);
    8      |                  ^~~~~~~~~~~~~~~~~~~~~~~~~~~
    9./zmq/zmqabstractnotifier.h:50:18: note:   candidate expects 1 argument, 2 provided
    
  93. in src/validation.cpp:1061 in c2f03fd7b9 outdated
    1051@@ -1052,7 +1052,7 @@ bool MemPoolAccept::AcceptSingleTransaction(const CTransactionRef& ptx, ATMPArgs
    1052 
    1053     if (!Finalize(args, workspace)) return false;
    1054 
    1055-    GetMainSignals().TransactionAddedToMempool(ptx);
    1056+    GetMainSignals().TransactionAddedToMempool(ptx, m_pool.GetAndIncrementSequence());
    


    jonatack commented at 7:59 pm on September 8, 2020:

    error here while building 712f214

    0validation.cpp: In member function bool {anonymous}::MemPoolAccept::AcceptSingleTransaction(const CTransactionRef&, {anonymous}::MemPoolAccept::ATMPArgs&):
    1validation.cpp:1055:60: error: class CTxMemPool has no member named GetAndIncrementSequence
    2 1055 |     GetMainSignals().TransactionAddedToMempool(ptx, m_pool.GetAndIncrementSequence());
    3      |                                                            ^~~~~~~~~~~~~~~~~~~~~~~
    4make[2]: *** [Makefile:12086: libbitcoin_server_a-validation.o] Error 1
    5make[2]: *** Waiting for unfinished jobs....
    6make[2]: Leaving directory '/home/jon/projects/bitcoin/bitcoin/src'
    7make[1]: *** [Makefile:18955: all-recursive] Error 1
    8make[1]: Leaving directory '/home/jon/projects/bitcoin/bitcoin/src'
    9make: *** [Makefile:799: all-recursive] Error 1
    
  94. jonatack commented at 8:01 pm on September 8, 2020: member
    A couple of errors while building 712f214.
  95. instagibbs force-pushed on Sep 8, 2020
  96. instagibbs commented at 8:53 pm on September 8, 2020: member
    collapsed the two logic commits since it’s not that much code and lots of lines changed twice in a row
  97. in test/functional/interface_zmq.py:8 in 4e1cc1d888 outdated
    4@@ -5,13 +5,24 @@
    5 """Test the ZMQ notification interface."""
    6 import struct
    7 
    8-from test_framework.address import ADDRESS_BCRT1_UNSPENDABLE
    9+from test_framework.address import ADDRESS_BCRT1_UNSPENDABLE, ADDRESS_BCRT1_P2WSH_OP_TRUE
    


    jonatack commented at 7:50 am on September 9, 2020:

    bb5e3a34 nit sort

    0from test_framework.address import ADDRESS_BCRT1_P2WSH_OP_TRUE, ADDRESS_BCRT1_UNSPENDABLE
    
  98. in src/rpc/blockchain.cpp:567 in 4e1cc1d888 outdated
    543@@ -529,6 +544,15 @@ static UniValue getrawmempool(const JSONRPCRequest& request)
    544                         {
    545                             {RPCResult::Type::OBJ, "transactionid", "", MempoolEntryDescription()},
    546                         }},
    547+                    RPCResult{"for verbose = false and mempool_sequence = true",
    548+                        RPCResult::Type::OBJ, "", "",
    549+                        {
    550+                            {RPCResult::Type::NUM, "mempool_sequence", "The mempool sequence value."},
    551+                            {RPCResult::Type::ARR, "txids", "",
    


    jonatack commented at 8:06 am on September 9, 2020:

    885212e could you please inverse the order of txids and mempool_sequence fields here in the help to be the same as the rpc output

    0                         {
    1-                            {RPCResult::Type::NUM, "mempool_sequence", "The mempool sequence value."},
    2                             {RPCResult::Type::ARR, "txids", "",
    3                             {
    4                                 {RPCResult::Type::STR_HEX, "", "The transaction id"},
    5                             }},
    6+                            {RPCResult::Type::NUM, "mempool_sequence", "The mempool sequence value."},
    7                         }},
    

    instagibbs commented at 2:17 pm on September 9, 2020:
    done
  99. in test/functional/interface_zmq.py:9 in 4e1cc1d888 outdated
     4@@ -5,13 +5,24 @@
     5 """Test the ZMQ notification interface."""
     6 import struct
     7 
     8-from test_framework.address import ADDRESS_BCRT1_UNSPENDABLE
     9+from test_framework.address import ADDRESS_BCRT1_UNSPENDABLE, ADDRESS_BCRT1_P2WSH_OP_TRUE
    10+from test_framework.blocktools import create_block, create_coinbase, add_witness_commitment
    


    jonatack commented at 8:10 am on September 9, 2020:

    99a94fe

    0from test_framework.blocktools import add_witness_commitment, create_block, create_coinbase
    
  100. in test/functional/interface_zmq.py:15 in 4e1cc1d888 outdated
    13-from test_framework.util import assert_equal, connect_nodes
    14+from test_framework.messages import CTransaction, hash256, FromHex
    15+from test_framework.util import (
    16+    assert_equal,
    17+    connect_nodes,
    18+    assert_raises_rpc_error,
    


    jonatack commented at 8:11 am on September 9, 2020:
    99a94fe nit sort
  101. jonatack commented at 8:24 am on September 9, 2020: member

    Tested ACK 4e1cc1d88889784e962e4393091c445b6561df9d

    Aligning the rpc output and help would be good. Feel free to ignore the test import order nits.

  102. instagibbs force-pushed on Sep 9, 2020
  103. jonatack commented at 2:15 pm on September 10, 2020: member

    re-ACK 4baaa89d29057e524a38e120512664ffacce413d per git range-diff 564e1ab 4e1cc1d 4baaa89, manually re-ran getrawmempool and its help for the fun

    new help section

    0$ bitcoin-cli -regtest help getrawmempool
    1
    2Result (for verbose = false and mempool_sequence = true):
    3{                            (json object)
    4  "txids" : [                (json array)
    5    "hex",                   (string) The transaction id
    6    ...
    7  ],
    8  "mempool_sequence" : n     (numeric) The mempool sequence value.
    9}
    

    getrawmempool with mempool_sequence

    0$ bitcoin-cli -regtest getrawmempool false true
    1{
    2  "txids": [
    3  ],
    4  "mempool_sequence": 1
    5}
    

    getrawmempool with bad params combination

    0$ bitcoin-cli -regtest getrawmempool true true
    1error code: -8
    2error message:
    3Verbose results cannot contain mempool sequence values.
    
  104. fanquake referenced this in commit dffefda21d on Sep 11, 2020
  105. sidhujag referenced this in commit 27c6cdde45 on Sep 11, 2020
  106. in src/wallet/wallet.cpp:1237 in 4baaa89d29 outdated
    1226@@ -1227,7 +1227,7 @@ void CWallet::blockConnected(const CBlock& block, int height)
    1227     m_last_block_processed = block_hash;
    1228     for (size_t index = 0; index < block.vtx.size(); index++) {
    1229         SyncTransaction(block.vtx[index], {CWalletTx::Status::CONFIRMED, height, block_hash, (int)index});
    1230-        transactionRemovedFromMempool(block.vtx[index], MemPoolRemovalReason::BLOCK);
    1231+        transactionRemovedFromMempool(block.vtx[index], MemPoolRemovalReason::BLOCK, 0 /* mempool_sequence */);
    


    0xB10C commented at 6:35 am on September 14, 2020:
    Why is mempool_sequence == 0 here?

    instagibbs commented at 1:55 pm on September 14, 2020:
    it’s a required chain interface argument, but the wallet doesn’t care/have access to about the mempool sequence value.
  107. 0xB10C commented at 7:20 am on September 14, 2020: member

    Concept ACK for using a ZMQ feed for tracking mempool and chain changes. The sequence number allows to order and detect missing mempool changes. This seems helpful.

    This change allows Bitcoin Core users to keep track of their mempool in an external service connected via ZMQ. It makes the external detection of reorgs easier as every block connection is notified (not only changes to the block tip as its the case with the other *block topics).

    On the approach: IMO the sequence notifier could use proper ZMQ multipart messages instead of in-lining a new protocol. https://github.com/bitcoin/bitcoin/pull/19572/files#diff-d8e6fe13399f13c42a93ec8326c60614R94-R97

    0now:
    1| topic | <32-byte hash>R<8-byte LE uint> | zmq sequence num |
    2
    3multipart:
    4| topic | 32-byte-hash | char | (optional) mempool sequence | zmq sequence | 
    

    I mentioned something like this in #17878 (review) as a concept alternative as well. However, I think adding proper ZMQ multipart message support to CZMQAbstractPublishNotifier::SendMessage could be a change in its own. This could, for example, look like this SendMessage with this zmq_send_multipart. Let me know what you think.

  108. 0xB10C commented at 9:38 am on September 14, 2020: member

    Had a quick look at the Bitcoin Core is restarted and transactions are added to the mempool from mempool.dat case. These are correctly notified, but don’t necessary have the same mempool_sequence (that’s expected). With a mempool.dat containing multiple thousand transactions the ZMQ buffer could fill up when using the DEFAULT_ZMQ_SNDHWM of 1000 resulting in ZMQ messages being dropped. This is, however, nothing new and can happen with the existing *tx ZMQ publishers as well.

    Here, the ZMQ buffers could fill up when multiple thousand transactions are removed from the mempool (this excludes confirmations). This would result in some removal notifications not reaching the external service. But I believe these events to be rare. It’s more something a user of the new ZMQ sequence endpoint should keep in mind. Not really specific to this PR.

  109. instagibbs commented at 1:53 pm on September 14, 2020: member

    @0xB10C thanks for the review!

    Discussion about dropped messages

    Yes, this is a general problem that can be mostly avoided, and if not the endpoint logic should basically toss what it thinks it knows and restart its tracking.

    Multipart messages

    I’m not sure if the change alone is worth it for current messages. I think it really shines when there are optional messages, of which we currently have none. Is this a fair assessment? A potential application would be for example we publish optional mempool eviction reasons. I’ll review/pocket https://github.com/0xB10C/bitcoin/commit/a06f5c7db6c0e491f150fe5dafb864c15326bb71# for now but if we decide to break format again, I think it’s worth inclusion.

  110. DrahtBot added the label Needs rebase on Sep 19, 2020
  111. instagibbs force-pushed on Sep 21, 2020
  112. instagibbs commented at 4:01 pm on September 21, 2020: member
    rebased. No functional changes.
  113. DrahtBot removed the label Needs rebase on Sep 21, 2020
  114. in src/zmq/zmqnotificationinterface.cpp:144 in 877f511d7f outdated
    140@@ -140,31 +141,53 @@ void CZMQNotificationInterface::UpdatedBlockTip(const CBlockIndex *pindexNew, co
    141     });
    142 }
    143 
    144-void CZMQNotificationInterface::TransactionAddedToMempool(const CTransactionRef& ptx)
    145+void CZMQNotificationInterface::TransactionAddedToMempool(const CTransactionRef& ptx,  uint64_t mempool_sequence)
    


    jonatack commented at 8:15 pm on September 21, 2020:
    pico-nit 68b1e612 extra space in last rebase, ignore unless you have to retouch again

    instagibbs commented at 3:21 pm on September 22, 2020:
    you’re in luck, rebasing again. done.
  115. jonatack commented at 8:16 pm on September 21, 2020: member
    Code review re-ACK 877f511d7f1f3c37a86c421e21fc0694c387e69f per git range-diff c0c409d 4baaa89 877f511, looked at the new function TryForEachAndRemoveFailed() that caused most of the rebase, verified debug build is clean and the changed test interface_zmq.py passes.
  116. instagibbs requested review from luke-jr on Sep 21, 2020
  117. n-thumann commented at 9:29 pm on September 21, 2020: contributor
  118. zmq test: Actually make reorg occur 1b615e61bf
  119. instagibbs force-pushed on Sep 22, 2020
  120. Add 'sequence' zmq publisher to track all block (dis)connects, mempool deltas
    Using the zmq notifications to avoid excessive mempool polling can be difficult
    given the current notifications available. It announces all transactions
    being added to mempool or included in blocks, but announces no evictions
    and gives no indication if the transaction is in the mempool or a block.
    
    Block notifications for zmq are also substandard, in that it only announces
    block tips, while all block transactions are still announced.
    
    This commit adds a unified stream which can be used to closely track mempool:
    
    1) getrawmempool to fill out mempool knowledge
    2) if txhash is announced, add or remove from set
    based on add/remove flag
    3) if blockhash is announced, get block txn list,
    remove from those transactions local view of mempool
    4) if we drop a sequence number, go to (1)
    
    The mempool sequence number starts at the value 1, and
    increments each time a transaction enters the mempool,
    or is evicted from the mempool for any reason, including
    block inclusion. The mempool sequence number is published
    via ZMQ for any transaction-related notification.
    
    These features allow for ZMQ/RPC consumer to track mempool
    state in a more exacting way, without unnecesarily polling
    getrawmempool. See interface_zmq.py::test_mempool_sync for
    example usage.
    e76fc2b84d
  121. Add functional tests for zmq sequence topic and mempool sequence logic 68c3c7e1bd
  122. Update zmq notification documentation and sample consumer 759d94e70f
  123. instagibbs force-pushed on Sep 22, 2020
  124. instagibbs commented at 3:36 pm on September 22, 2020: member
    rebased again
  125. laanwj commented at 11:53 am on September 23, 2020: member

    Code review ACK 759d94e70f6844443106404882c7b105f3a4dba7

    I see a potential confusion between sequence numbers of the individual packets and the “mempool sequence” but this is a matter of documentation, I don’t have a suggestion for better naming.

  126. laanwj merged this on Sep 23, 2020
  127. laanwj closed this on Sep 23, 2020

  128. instagibbs commented at 11:58 am on September 23, 2020: member

    I see a potential confusion between sequence numbers of the individual packets and the “mempool sequence” but this is a matter of documentation, I don’t have a suggestion for better naming.

    Willing to entertain any renaming if people think of something better!

  129. jonatack commented at 2:02 pm on September 23, 2020: member
    re-ACK 759d94e70f6844443106404882c7b105f3a4dba7
  130. shuckc commented at 2:34 pm on September 23, 2020: none
    Lovely! Very much look forward to using this.
  131. sidhujag referenced this in commit e38523bda0 on Sep 23, 2020
  132. domob1812 referenced this in commit c8d0274012 on Sep 28, 2020
  133. PastaPastaPasta referenced this in commit bc18d5d458 on Jun 27, 2021
  134. PastaPastaPasta referenced this in commit 9762ada89e on Jun 28, 2021
  135. PastaPastaPasta referenced this in commit 36237fe794 on Jun 29, 2021
  136. PastaPastaPasta referenced this in commit 66c1ad151a on Jul 1, 2021
  137. PastaPastaPasta referenced this in commit b17d32b26f on Jul 1, 2021
  138. PastaPastaPasta referenced this in commit 6ef9992a26 on Jul 15, 2021
  139. PastaPastaPasta referenced this in commit 788e3d31b4 on Jul 16, 2021
  140. Fabcien referenced this in commit 3cf2c996d8 on Oct 14, 2021
  141. Fabcien referenced this in commit 18db6565c0 on Oct 14, 2021
  142. Fabcien referenced this in commit 5ec80435a5 on Oct 14, 2021
  143. Fabcien referenced this in commit 0f144de39f on Oct 14, 2021
  144. DrahtBot locked this on Feb 15, 2022

github-metadata-mirror

This is a metadata mirror of the GitHub repository bitcoin/bitcoin. This site is not affiliated with GitHub. Content is generated from a GitHub metadata backup.
generated: 2024-06-29 10:13 UTC

This site is hosted by @0xB10C
More mirrored repositories can be found on mirror.b10c.me