Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions doc/release-notes.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
---------------------
Expand Down
6 changes: 4 additions & 2 deletions src/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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


Expand Down
22 changes: 11 additions & 11 deletions src/init.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@

#if ENABLE_ZMQ
#include <zmq/zmqnotificationinterface.h>
#include <zmq/zmqrpc.h>
#endif

bool fFeeEstimatesInitialized = false;
Expand Down Expand Up @@ -99,10 +100,6 @@ void DummyWalletInit::AddWalletOptions() const
const WalletInitInterface& g_wallet_init_interface = DummyWalletInit();
#endif

#if ENABLE_ZMQ
static CZMQNotificationInterface* pzmqNotificationInterface = nullptr;
#endif

#ifdef WIN32
// Win32 LevelDB doesn't use filedescriptors, and the ones used for
// accessing block files don't count towards the fd_set size limit
Expand Down Expand Up @@ -279,10 +276,10 @@ void Shutdown()
g_wallet_init_interface.Stop();

#if ENABLE_ZMQ
if (pzmqNotificationInterface) {
UnregisterValidationInterface(pzmqNotificationInterface);
delete pzmqNotificationInterface;
pzmqNotificationInterface = nullptr;
if (g_zmq_notification_interface) {
UnregisterValidationInterface(g_zmq_notification_interface);
delete g_zmq_notification_interface;
g_zmq_notification_interface = nullptr;
}
#endif

Expand Down Expand Up @@ -1291,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
Expand Down Expand Up @@ -1409,10 +1409,10 @@ bool AppInitMain()
}

#if ENABLE_ZMQ
pzmqNotificationInterface = CZMQNotificationInterface::Create();
g_zmq_notification_interface = CZMQNotificationInterface::Create();

if (pzmqNotificationInterface) {
RegisterValidationInterface(pzmqNotificationInterface);
if (g_zmq_notification_interface) {
RegisterValidationInterface(g_zmq_notification_interface);
}
#endif
uint64_t nMaxOutboundLimit = 0; //unlimited unless -maxuploadtarget is set
Expand Down
13 changes: 12 additions & 1 deletion src/zmq/zmqnotificationinterface.cpp
Original file line number Diff line number Diff line change
@@ -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.

Expand Down Expand Up @@ -29,6 +29,15 @@ CZMQNotificationInterface::~CZMQNotificationInterface()
}
}

std::list<const CZMQAbstractNotifier*> CZMQNotificationInterface::GetActiveNotifiers() const
{
std::list<const CZMQAbstractNotifier*> result;
Copy link
Contributor

Choose a reason for hiding this comment

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

Could just return notifiers?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

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.

for (const auto* n : notifiers) {
result.push_back(n);
}
return result;
}

CZMQNotificationInterface* CZMQNotificationInterface::Create()
{
CZMQNotificationInterface* notificationInterface = nullptr;
Expand Down Expand Up @@ -180,3 +189,5 @@ void CZMQNotificationInterface::BlockDisconnected(const std::shared_ptr<const CB
TransactionAddedToMempool(ptx);
}
}

CZMQNotificationInterface* g_zmq_notification_interface = nullptr;
6 changes: 5 additions & 1 deletion src/zmq/zmqnotificationinterface.h
Original file line number Diff line number Diff line change
@@ -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.

Expand All @@ -18,6 +18,8 @@ class CZMQNotificationInterface final : public CValidationInterface
public:
virtual ~CZMQNotificationInterface();

std::list<const CZMQAbstractNotifier*> GetActiveNotifiers() const;

static CZMQNotificationInterface* Create();

protected:
Expand All @@ -37,4 +39,6 @@ class CZMQNotificationInterface final : public CValidationInterface
std::list<CZMQAbstractNotifier*> notifiers;
};

extern CZMQNotificationInterface* g_zmq_notification_interface;

#endif // BITCOIN_ZMQ_ZMQNOTIFICATIONINTERFACE_H
61 changes: 61 additions & 0 deletions src/zmq/zmqrpc.cpp
Original file line number Diff line number Diff line change
@@ -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 changes: 12 additions & 0 deletions src/zmq/zmqrpc.h
Original file line number Diff line number Diff line change
@@ -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 changes: 33 additions & 0 deletions test/functional/rpc_zmq.py
Original file line number Diff line number Diff line change
@@ -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"
Copy link
Contributor

Choose a reason for hiding this comment

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

nit, inline this (only 2 times)?

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

Copy link
Contributor

Choose a reason for hiding this comment

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

No strong opinion.


def set_test_params(self):
self.num_nodes = 1
self.setup_clean_chain = True

def run_test(self):
self._test_getzmqnotifications()
Copy link
Member

Choose a reason for hiding this comment

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

The test should be skipped similar to interface_zmq.py. Otherwise it will fail.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

That is indeed a good point! Since this was already merged, should I create a new PR with this fix?

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'll work on a fix and send in a PR with it as soon as I'm ready. Thanks again for spotting this!

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Created #13646.


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()
1 change: 1 addition & 0 deletions test/functional/test_runner.py
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@
'feature_versionbits_warning.py',
'rpc_preciousblock.py',
'wallet_importprunedfunds.py',
'rpc_zmq.py',
'rpc_signmessage.py',
'feature_nulldummy.py',
'mempool_accept.py',
Expand Down