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.
This commit is contained in:
Daniel Kraft 2018-06-29 16:10:01 +02:00
parent caac39b0ac
commit 161e8d40a4
9 changed files with 130 additions and 4 deletions

View File

@ -79,6 +79,8 @@ RPC changes
`getmempoolentry` when verbosity is set to `true` with sub-fields `ancestor`, `base`, `modified`
and `descendant` denominated in BTC. This new field deprecates previous fee fields, such as
`fee`, `modifiedfee`, `ancestorfee` and `descendantfee`.
- The new RPC `getzmqnotifications` returns information about active ZMQ
notifications.
External wallet files
---------------------

View File

@ -193,7 +193,8 @@ BITCOIN_CORE_H = \
zmq/zmqabstractnotifier.h \
zmq/zmqconfig.h\
zmq/zmqnotificationinterface.h \
zmq/zmqpublishnotifier.h
zmq/zmqpublishnotifier.h \
zmq/zmqrpc.h
obj/build.h: FORCE
@ -253,7 +254,8 @@ libbitcoin_zmq_a_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
libbitcoin_zmq_a_SOURCES = \
zmq/zmqabstractnotifier.cpp \
zmq/zmqnotificationinterface.cpp \
zmq/zmqpublishnotifier.cpp
zmq/zmqpublishnotifier.cpp \
zmq/zmqrpc.cpp
endif

View File

@ -62,6 +62,7 @@
#if ENABLE_ZMQ
#include <zmq/zmqnotificationinterface.h>
#include <zmq/zmqrpc.h>
#endif
bool fFeeEstimatesInitialized = false;
@ -1287,6 +1288,9 @@ bool AppInitMain()
*/
RegisterAllCoreRPCCommands(tableRPC);
g_wallet_init_interface.RegisterRPC(tableRPC);
#if ENABLE_ZMQ
RegisterZMQRPCCommands(tableRPC);
#endif
/* Start the RPC server already. It will be started in "warmup" mode
* and not really process calls already (but it will signify connections

View File

@ -1,4 +1,4 @@
// Copyright (c) 2015-2017 The Bitcoin Core developers
// Copyright (c) 2015-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@ -29,6 +29,15 @@ CZMQNotificationInterface::~CZMQNotificationInterface()
}
}
std::list<const CZMQAbstractNotifier*> CZMQNotificationInterface::GetActiveNotifiers() const
{
std::list<const CZMQAbstractNotifier*> result;
for (const auto* n : notifiers) {
result.push_back(n);
}
return result;
}
CZMQNotificationInterface* CZMQNotificationInterface::Create()
{
CZMQNotificationInterface* notificationInterface = nullptr;

View File

@ -1,4 +1,4 @@
// Copyright (c) 2015-2017 The Bitcoin Core developers
// Copyright (c) 2015-2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@ -18,6 +18,8 @@ class CZMQNotificationInterface final : public CValidationInterface
public:
virtual ~CZMQNotificationInterface();
std::list<const CZMQAbstractNotifier*> GetActiveNotifiers() const;
static CZMQNotificationInterface* Create();
protected:

61
src/zmq/zmqrpc.cpp Normal file
View File

@ -0,0 +1,61 @@
// Copyright (c) 2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <zmq/zmqrpc.h>
#include <rpc/server.h>
#include <zmq/zmqabstractnotifier.h>
#include <zmq/zmqnotificationinterface.h>
#include <univalue.h>
namespace {
UniValue getzmqnotifications(const JSONRPCRequest& request)
{
if (request.fHelp || request.params.size() != 0) {
throw std::runtime_error(
"getzmqnotifications\n"
"\nReturns information about the active ZeroMQ notifications.\n"
"\nResult:\n"
"[\n"
" { (json object)\n"
" \"type\": \"pubhashtx\", (string) Type of notification\n"
" \"address\": \"...\" (string) Address of the publisher\n"
" },\n"
" ...\n"
"]\n"
"\nExamples:\n"
+ HelpExampleCli("getzmqnotifications", "")
+ HelpExampleRpc("getzmqnotifications", "")
);
}
UniValue result(UniValue::VARR);
if (g_zmq_notification_interface != nullptr) {
for (const auto* n : g_zmq_notification_interface->GetActiveNotifiers()) {
UniValue obj(UniValue::VOBJ);
obj.pushKV("type", n->GetType());
obj.pushKV("address", n->GetAddress());
result.push_back(obj);
}
}
return result;
}
const CRPCCommand commands[] =
{ // category name actor (function) argNames
// ----------------- ------------------------ ----------------------- ----------
{ "zmq", "getzmqnotifications", &getzmqnotifications, {} },
};
} // anonymous namespace
void RegisterZMQRPCCommands(CRPCTable& t)
{
for (const auto& c : commands) {
t.appendCommand(c.name, &c);
}
}

12
src/zmq/zmqrpc.h Normal file
View File

@ -0,0 +1,12 @@
// Copyright (c) 2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#ifndef BITCOIN_ZMQ_ZMQRPC_H
#define BITCOIN_ZMQ_ZMQRPC_H
class CRPCTable;
void RegisterZMQRPCCommands(CRPCTable& t);
#endif // BITCOIN_ZMQ_ZMRRPC_H

33
test/functional/rpc_zmq.py Executable file
View File

@ -0,0 +1,33 @@
#!/usr/bin/env python3
# Copyright (c) 2018 The Bitcoin Core developers
# Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
"""Test for the ZMQ RPC methods."""
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import assert_equal
class RPCZMQTest(BitcoinTestFramework):
address = "tcp://127.0.0.1:28332"
def set_test_params(self):
self.num_nodes = 1
self.setup_clean_chain = True
def run_test(self):
self._test_getzmqnotifications()
def _test_getzmqnotifications(self):
self.restart_node(0, extra_args=[])
assert_equal(self.nodes[0].getzmqnotifications(), [])
self.restart_node(0, extra_args=["-zmqpubhashtx=%s" % self.address])
assert_equal(self.nodes[0].getzmqnotifications(), [
{"type": "pubhashtx", "address": self.address},
])
if __name__ == '__main__':
RPCZMQTest().main()

View File

@ -116,6 +116,7 @@ BASE_SCRIPTS = [
'feature_versionbits_warning.py',
'rpc_preciousblock.py',
'wallet_importprunedfunds.py',
'rpc_zmq.py',
'rpc_signmessage.py',
'feature_nulldummy.py',
'mempool_accept.py',