RPC: Add new “getzmqnotifications” method #13570

pull domob1812 wants to merge 2 commits into bitcoin:master from domob1812:zmq changing 9 files +141 −15
  1. domob1812 commented at 2:17 pm on June 29, 2018: contributor

    This adds a new RPC method getzmqnotifications, which returns information about all active ZMQ notification endpoints. This is useful for software that layers on top of bitcoind, so it can verify that ZeroMQ is enabled and also figure out where it should listen.

    See #13526.

  2. Make ZMQ notification interface instance global.
    This moves the used instance of CZMQNotificationInterface from a static
    variable in init.cpp to a globally-accessible one declared in
    zmq/zmqnotificationinterface.h.  The variable is also renamed to
    g_zmq_notification_interface, to be consistent with other globals.
    
    We need this to implement a new RPC method "getzmqnotifications" (see
    https://github.com/bitcoin/bitcoin/issues/13526) in a follow up.
    caac39b0ac
  3. domob1812 commented at 2:17 pm on June 29, 2018: contributor
    I’ve created two commits, because the first is a trivial and “unrelated” refactor - I think it makes sense for the review and version history to have it separate. But I’m happy to squash them if you think that’s better.
  4. fanquake added the label RPC/REST/ZMQ on Jun 29, 2018
  5. in src/zmq/zmqnotificationinterface.cpp:41 in dd140e345a outdated
    32@@ -29,6 +33,15 @@ CZMQNotificationInterface::~CZMQNotificationInterface()
    33     }
    34 }
    35 
    36+void CZMQNotificationInterface::AddJSONNotifiers(UniValue& publish) const
    37+{
    38+    for (const auto* n : notifiers) {
    39+        const std::string& type = n->GetType();
    40+        assert(type.substr(0, 3) == "pub");
    41+        publish.pushKV (type.substr(3), n->GetAddress());
    


    Empact commented at 4:42 pm on June 29, 2018:
    Whitespace - maybe run clang-format.

    domob1812 commented at 7:33 am on June 30, 2018:
    Good catch, fixed.
  6. in src/zmq/zmqnotificationinterface.cpp:36 in dd140e345a outdated
    32@@ -29,6 +33,15 @@ CZMQNotificationInterface::~CZMQNotificationInterface()
    33     }
    34 }
    35 
    36+void CZMQNotificationInterface::AddJSONNotifiers(UniValue& publish) const
    


    promag commented at 11:36 pm on June 29, 2018:
    IMO should not use UniValue here. Return a list instead?

    domob1812 commented at 7:33 am on June 30, 2018:
    I thought about this - returning a list means (because I think we should not return a list of non-const notifiers) that we have to create a new std::list<const CZMQAbstractNotifier*> and cannot return the existing notifiers. But on second thought, that seems not too bad - and decoupling from UniValue makes sense. I’ve changed that accordingly.
  7. in src/zmq/zmqnotificationinterface.cpp:40 in dd140e345a outdated
    32@@ -29,6 +33,15 @@ CZMQNotificationInterface::~CZMQNotificationInterface()
    33     }
    34 }
    35 
    36+void CZMQNotificationInterface::AddJSONNotifiers(UniValue& publish) const
    37+{
    38+    for (const auto* n : notifiers) {
    39+        const std::string& type = n->GetType();
    40+        assert(type.substr(0, 3) == "pub");
    


    promag commented at 11:37 pm on June 29, 2018:
    Why assert?

    domob1812 commented at 7:33 am on June 30, 2018:

    Because the current code is meant to only add types that start with "pub" - if that is not the case, it is a bug with the code (or at least means the code here has to be updated as well).

    But if you prefer, we could just ignore those that don’t start with "pub" and print a warning to debug.log instead. Or we could just keep the "pub" prefix in the output - whatever you think is best.

  8. promag commented at 11:40 pm on June 29, 2018: member
    Concept ACK. Please update code format.
  9. domob1812 force-pushed on Jun 30, 2018
  10. in test/functional/rpc_zmq.py:13 in 25e27531cc outdated
     8+from test_framework.util import *
     9+
    10+
    11+class RPCZMQTest(BitcoinTestFramework):
    12+    def set_test_params(self):
    13+        self.num_nodes = 2
    


    promag commented at 9:26 am on June 30, 2018:
    Use 1 node and below restart_node with the options options you want to test.

    domob1812 commented at 2:06 pm on June 30, 2018:
    Done - besides reducing the number of nodes, this also puts the args right next to the corresponding test; so indeed a good suggestion!
  11. promag commented at 9:27 am on June 30, 2018: member

    Maybe just return as follow:

    0[
    1    { "type": "pubhashtx", "address": "tcp://127.0.0.1:28332" }
    2]
    

    And this supports multiple notifications of the same type.

  12. DrahtBot commented at 11:35 am on June 30, 2018: member
    • #13008 (rpc: Rename size to vsize in mempool related calls by IPGlider)

    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.

  13. domob1812 force-pushed on Jun 30, 2018
  14. domob1812 commented at 2:07 pm on June 30, 2018: contributor
    The latest update also changed the format as suggested to an array. We now also return just the literal type without removing the "pub" prefix - so there’s no more assert.
  15. in src/zmq/zmqnotificationinterface.cpp:34 in fcc652960c outdated
    28@@ -29,6 +29,14 @@ CZMQNotificationInterface::~CZMQNotificationInterface()
    29     }
    30 }
    31 
    32+std::list<const CZMQAbstractNotifier*> CZMQNotificationInterface::GetActiveNotifiers() const
    33+{
    34+    std::list<const CZMQAbstractNotifier*> result;
    


    promag commented at 3:05 pm on July 1, 2018:
    Could just return notifiers?

    domob1812 commented at 5:48 am on July 2, 2018:
    No because notifiers is a list of non-const CZMQAbstractNotifier, and I’d rather not return the mutable objects. That’s the reason why I originally had this “add to JSON” method - but I think that the additional copy done here is probably not relevant in practice.
  16. in src/zmq/zmqrpc.cpp:36 in fcc652960c outdated
    32+            + HelpExampleCli("getzmqnotifications", "")
    33+            + HelpExampleRpc("getzmqnotifications", "")
    34+        );
    35+
    36+    UniValue publish(UniValue::VARR);
    37+    if (g_zmq_notification_interface != nullptr) {
    


    promag commented at 3:11 pm on July 1, 2018:

    An alternative is to make these RPC available (registered) if g_zmq_notification_interface != nullptr so this check could be removed.

    Not sure what others think.


    domob1812 commented at 5:46 am on July 2, 2018:

    I was thinking about this, and my opinion is that we should have them always available (if ZMQ is compiled in at least) - as in the current code. The reason is that if a wallet frontend or such uses this RPC, then checking whether any notification is registered at all (which is equivalent to checking for non-nullness of g_zmq_notification_interface) is part of the reason for having this RPC in the first place. And while it may then catch the “method not found” error, this makes things more complicated. Having the RPC and returning an empty response seems more useful for this case to me.

    But of course I’m happy to change that if others disagree.


    promag commented at 6:28 am on July 2, 2018:

    Consider an hypothetical zmqaddnotification, shouldn’t it raise an error if g_zmq_notification_interface == nullptr?

    this makes things more complicated

    Why? Also, if your “frontend” is calling these RPC then it would be bad configuration if these are not present.


    domob1812 commented at 6:55 am on July 2, 2018:

    But g_zmq_notification_interface being null just means that we have no notifications enabled through the command-line. So with zmqaddnotification, I would imagine that it actually is able to add a notification also in that case (in fact, that could be the primary usage - do not configure any notifications through the CLI and instead add them later by RPC). I. e., zmqaddnotification would either initialise g_zmq_notification_interface if it was null, or we would always initialise it (even if no notifications are specified) on startup.

    (We then might want to have a separate argument to turn off ZMQ completely - but that would be something new and is not what we have today!)

    Of course, a frontend would have to handle the case of the method failing just in case. But I think if the daemon has ZMQ support but was just started without notifications, then the method should simply return that information (empty array), rather than not be present. Especially with a hypothetical addzmqnotification in the future, this behaviour makes more sense for me.


    promag commented at 5:49 pm on July 2, 2018:

    But g_zmq_notification_interface being null just means that we have no notifications enabled through the command-line.

    Indeed, forgot about that.

  17. in src/zmq/zmqnotificationinterface.cpp:35 in fcc652960c outdated
    28@@ -29,6 +29,14 @@ CZMQNotificationInterface::~CZMQNotificationInterface()
    29     }
    30 }
    31 
    32+std::list<const CZMQAbstractNotifier*> CZMQNotificationInterface::GetActiveNotifiers() const
    33+{
    34+    std::list<const CZMQAbstractNotifier*> result;
    35+    for (const auto* n : notifiers)
    


    promag commented at 8:51 pm on July 4, 2018:
    Missing {}.

    domob1812 commented at 6:02 am on July 5, 2018:
    Done. I’ve seen single-line blocks without it (even in this file), but the style guide is indeed pretty clear that this should be avoided going forward.
  18. in src/zmq/zmqrpc.cpp:63 in fcc652960c outdated
    58+
    59+} // anonymous namespace
    60+
    61+void RegisterZMQRPCCommands(CRPCTable& t)
    62+{
    63+    for (const auto& c : commands)
    


    promag commented at 8:51 pm on July 4, 2018:
    Missing {}.

    domob1812 commented at 6:02 am on July 5, 2018:
    Done. I’ve also added {} for the if body that throws the help message - while it seems none of these use them, they are required by the style guide there as well.
  19. in src/zmq/zmqrpc.cpp:48 in fcc652960c outdated
    43+            publish.push_back(obj);
    44+        }
    45+    }
    46+
    47+    UniValue result(UniValue::VOBJ);
    48+    result.pushKV("publish", publish);
    


    promag commented at 8:53 pm on July 4, 2018:

    Now that each notification has the type, could just return the array:

    0[
    1    { "type": "...", "address": "..." },
    2    ...
    3]
    

    domob1812 commented at 6:02 am on July 5, 2018:
    Makes sense, changed.
  20. in src/zmq/zmqrpc.cpp:39 in fcc652960c outdated
    34+        );
    35+
    36+    UniValue publish(UniValue::VARR);
    37+    if (g_zmq_notification_interface != nullptr) {
    38+        const std::list<const CZMQAbstractNotifier*> notifiers = g_zmq_notification_interface->GetActiveNotifiers();
    39+        for (const auto* n : notifiers) {
    


    promag commented at 8:55 pm on July 4, 2018:

    Could avoid above line:

    0for (auto n : g_zmq_notification_interface->GetActiveNotifiers()) {
    

    domob1812 commented at 6:03 am on July 5, 2018:
    Done.
  21. in test/functional/rpc_zmq.py:8 in fcc652960c outdated
    0@@ -0,0 +1,35 @@
    1+#!/usr/bin/env python3
    2+# Copyright (c) 2018 The Bitcoin Core developers
    3+# Distributed under the MIT software license, see the accompanying
    4+# file COPYING or http://www.opensource.org/licenses/mit-license.php.
    5+"""Test for the ZMQ RPC methods."""
    6+
    7+from test_framework.test_framework import BitcoinTestFramework
    8+from test_framework.util import *
    


    promag commented at 8:56 pm on July 4, 2018:
    Could specify import symbols.

    domob1812 commented at 6:03 am on July 5, 2018:
    Done (only assert_equal, so this certainly makes sense).
  22. in test/functional/rpc_zmq.py:13 in fcc652960c outdated
     8+from test_framework.util import *
     9+
    10+
    11+class RPCZMQTest(BitcoinTestFramework):
    12+
    13+    address = "tcp://127.0.0.1:28332"
    


    promag commented at 8:58 pm on July 4, 2018:
    nit, inline this (only 2 times)?

    domob1812 commented at 6:04 am on July 5, 2018:

    I actually like it better like this, even if it is only used in two places for now. And if we add a addzmqnotification later, it will be used in more.

    But if you strongly prefer this to be inlined, I can of course do it.


    promag commented at 6:11 am on July 5, 2018:
    No strong opinion.
  23. RPC: Add new getzmqnotifications method.
    This adds a new RPC method "getzmqnotifications", which returns
    information about all active ZMQ notification endpoints.  This is useful
    for software that layers on top of bitcoind, so it can verify that
    ZeroMQ is enabled and also figure out where it should listen.
    
    See https://github.com/bitcoin/bitcoin/issues/13526.
    161e8d40a4
  24. domob1812 force-pushed on Jul 5, 2018
  25. laanwj commented at 3:41 pm on July 5, 2018: member

    I vaguely remember I also started work on something like this a few years ago, with a zmq refactor that was never eventually merged, but I still think it’s a good idea.

    What I needed at the time was a way to ask a bitcoind instance whether it was listening on zmq, and if so, on that endpoints. This prevents having to pass in zmq configuration to the client application separately as well.

    Tested ACK caac39b0ace38aa088d88c1a5a9a9dbb4d2e893f.

  26. laanwj merged this on Jul 9, 2018
  27. laanwj closed this on Jul 9, 2018

  28. laanwj referenced this in commit a247594e75 on Jul 9, 2018
  29. domob1812 deleted the branch on Jul 9, 2018
  30. in test/functional/rpc_zmq.py:20 in 161e8d40a4
    15+    def set_test_params(self):
    16+        self.num_nodes = 1
    17+        self.setup_clean_chain = True
    18+
    19+    def run_test(self):
    20+        self._test_getzmqnotifications()
    


    MarcoFalke commented at 2:39 pm on July 11, 2018:
    The test should be skipped similar to interface_zmq.py. Otherwise it will fail.

    domob1812 commented at 4:19 pm on July 11, 2018:
    That is indeed a good point! Since this was already merged, should I create a new PR with this fix?

    domob1812 commented at 3:01 pm on July 12, 2018:
    I’ll work on a fix and send in a PR with it as soon as I’m ready. Thanks again for spotting this!

    domob1812 commented at 3:55 pm on July 12, 2018:
    Created #13646.
  31. domob1812 referenced this in commit 8fe3994145 on Jul 12, 2018
  32. luke-jr referenced this in commit e953e65cd2 on Jul 30, 2018
  33. luke-jr referenced this in commit b87d341b40 on Jul 30, 2018
  34. PastaPastaPasta referenced this in commit 9d25593ba7 on Jul 17, 2020
  35. PastaPastaPasta referenced this in commit 87cf14727a on Jul 17, 2020
  36. MarcoFalke locked this on Sep 8, 2021

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-12-18 18:12 UTC

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