Inside Bitcoin
Opening the selected file…
Inside Bitcoin
Opening the selected file…
The code behind the network, with room to understand it.
Release published 2026-10-28 · Snapshot fetched 2026-11-01. Latest stable release at fetch time; development branches and Git history are excluded. Only the selected code window and visible folders load here.
1// Copyright (c) 2015-present The Bitcoin Core developers2// Distributed under the MIT software license, see the accompanying3// file COPYING or http://www.opensource.org/licenses/mit-license.php.5#include <zmq/zmqnotificationinterface.h>7#include <common/args.h>8#include <kernel/mempool_entry.h>9#include <kernel/types.h>10#include <netbase.h>11#include <primitives/block.h>12#include <primitives/transaction.h>13#include <util/check.h>14#include <util/log.h>15#include <zmq/zmqabstractnotifier.h>16#include <zmq/zmqpublishnotifier.h>17#include <zmq/zmqutil.h>19#include <zmq.h>21#include <map>22#include <string>23#include <utility>24#include <vector>26using kernel::ChainstateRole;28CZMQNotificationInterface::CZMQNotificationInterface() = default;30CZMQNotificationInterface::~CZMQNotificationInterface()31{32Shutdown();33}35std::list<const CZMQAbstractNotifier*> CZMQNotificationInterface::GetActiveNotifiers() const36{37std::list<const CZMQAbstractNotifier*> result;38for (const auto& n : notifiers) {39result.push_back(n.get());40}41return result;42}44std::unique_ptr<CZMQNotificationInterface> CZMQNotificationInterface::Create(std::function<bool(std::vector<std::byte>&, const CBlockIndex&)> get_block_by_index)45{46std::map<std::string, CZMQNotifierFactory> factories;47factories["pubhashblock"] = CZMQAbstractNotifier::Create<CZMQPublishHashBlockNotifier>;48factories["pubhashtx"] = CZMQAbstractNotifier::Create<CZMQPublishHashTransactionNotifier>;49factories["pubrawblock"] = [&get_block_by_index]() -> std::unique_ptr<CZMQAbstractNotifier> {50return std::make_unique<CZMQPublishRawBlockNotifier>(get_block_by_index);51};52factories["pubrawtx"] = CZMQAbstractNotifier::Create<CZMQPublishRawTransactionNotifier>;53factories["pubsequence"] = CZMQAbstractNotifier::Create<CZMQPublishSequenceNotifier>;55std::list<std::unique_ptr<CZMQAbstractNotifier>> notifiers;56for (const auto& entry : factories)57{58std::string arg("-zmq" + entry.first);59const auto& factory = entry.second;60for (std::string& address : gArgs.GetArgs(arg)) {61// libzmq uses prefix "ipc://" for UNIX domain sockets62if (address.starts_with(ADDR_PREFIX_UNIX)) {63address.replace(0, ADDR_PREFIX_UNIX.length(), ADDR_PREFIX_IPC);64}66std::unique_ptr<CZMQAbstractNotifier> notifier = factory();67notifier->SetType(entry.first);68notifier->SetAddress(address);69notifier->SetOutboundMessageHighWaterMark(static_cast<int>(gArgs.GetIntArg(arg + "hwm", CZMQAbstractNotifier::DEFAULT_ZMQ_SNDHWM)));70notifiers.push_back(std::move(notifier));71}72}74if (!notifiers.empty())75{76std::unique_ptr<CZMQNotificationInterface> notificationInterface(new CZMQNotificationInterface());77notificationInterface->notifiers = std::move(notifiers);79if (notificationInterface->Initialize()) {80return notificationInterface;81}82}84return nullptr;85}87// Called at startup to conditionally set up ZMQ socket(s)88bool CZMQNotificationInterface::Initialize()89{90int major = 0, minor = 0, patch = 0;91zmq_version(&major, &minor, &patch);92LogDebug(BCLog::ZMQ, "version %d.%d.%d\n", major, minor, patch);94LogDebug(BCLog::ZMQ, "Initialize notification interface\n");95assert(!pcontext);97pcontext = zmq_ctx_new();99if (!pcontext)100{101zmqError("Unable to initialize context");102return false;103}105for (auto& notifier : notifiers) {106if (notifier->Initialize(pcontext)) {107LogDebug(BCLog::ZMQ, "Notifier %s ready (address = %s)\n", notifier->GetType(), notifier->GetAddress());108} else {109LogDebug(BCLog::ZMQ, "Notifier %s failed (address = %s)\n", notifier->GetType(), notifier->GetAddress());110return false;111}112}114return true;115}117// Called during shutdown sequence118void CZMQNotificationInterface::Shutdown()119{120LogDebug(BCLog::ZMQ, "Shutdown notification interface\n");121if (pcontext)122{123for (auto& notifier : notifiers) {124LogDebug(BCLog::ZMQ, "Shutdown notifier %s at %s\n", notifier->GetType(), notifier->GetAddress());125notifier->Shutdown();126}127zmq_ctx_term(pcontext);129pcontext = nullptr;130}131}133namespace {135template <typename Function>136void TryForEachAndRemoveFailed(std::list<std::unique_ptr<CZMQAbstractNotifier>>& notifiers, const Function& func)137{138for (auto i = notifiers.begin(); i != notifiers.end(); ) {139CZMQAbstractNotifier* notifier = i->get();140if (func(notifier)) {141++i;142} else {143notifier->Shutdown();144i = notifiers.erase(i);145}146}147}149} // anonymous namespace151void CZMQNotificationInterface::UpdatedBlockTip(const CBlockIndex *pindexNew, const CBlockIndex *pindexFork, bool fInitialDownload)152{153if (fInitialDownload || pindexNew == pindexFork) // In IBD or blocks were disconnected without any new ones154return;156TryForEachAndRemoveFailed(notifiers, [pindexNew](CZMQAbstractNotifier* notifier) {157return notifier->NotifyBlock(pindexNew);158});159}161void CZMQNotificationInterface::TransactionAddedToMempool(const NewMempoolTransactionInfo& ptx, uint64_t mempool_sequence)162{163const CTransaction& tx = *(ptx.info.m_tx);165TryForEachAndRemoveFailed(notifiers, [&tx, mempool_sequence](CZMQAbstractNotifier* notifier) {166return notifier->NotifyTransaction(tx) && notifier->NotifyTransactionAcceptance(tx, mempool_sequence);167});168}170void CZMQNotificationInterface::TransactionRemovedFromMempool(const CTransactionRef& ptx, MemPoolRemovalReason reason, uint64_t mempool_sequence)171{172// Called for all non-block inclusion reasons173const CTransaction& tx = *ptx;175TryForEachAndRemoveFailed(notifiers, [&tx, mempool_sequence](CZMQAbstractNotifier* notifier) {176return notifier->NotifyTransactionRemoval(tx, mempool_sequence);177});178}180void CZMQNotificationInterface::BlockConnected(const ChainstateRole& role, const std::shared_ptr<const CBlock>& pblock, const CBlockIndex* pindexConnected)181{182if (role.historical) {183return;184}185for (const CTransactionRef& ptx : pblock->vtx) {186const CTransaction& tx = *ptx;187TryForEachAndRemoveFailed(notifiers, [&tx](CZMQAbstractNotifier* notifier) {188return notifier->NotifyTransaction(tx);189});190}192// Next we notify BlockConnect listeners for *all* blocks193TryForEachAndRemoveFailed(notifiers, [pindexConnected](CZMQAbstractNotifier* notifier) {194return notifier->NotifyBlockConnect(pindexConnected);195});196}198void CZMQNotificationInterface::BlockDisconnected(const std::shared_ptr<const CBlock>& pblock, const CBlockIndex* pindexDisconnected)199{200for (const CTransactionRef& ptx : pblock->vtx) {201const CTransaction& tx = *ptx;202TryForEachAndRemoveFailed(notifiers, [&tx](CZMQAbstractNotifier* notifier) {203return notifier->NotifyTransaction(tx);204});205}207// Next we notify BlockDisconnect listeners for *all* blocks208TryForEachAndRemoveFailed(notifiers, [pindexDisconnected](CZMQAbstractNotifier* notifier) {209return notifier->NotifyBlockDisconnect(pindexDisconnected);210});211}213std::unique_ptr<CZMQNotificationInterface> g_zmq_notification_interface;
Independent explanations by MyBitcoinExplorer. Not affiliated with or endorsed by Bitcoin Core. Guides are educational and do not replace the source or its tests.
Bitcoin Core source © its contributors, distributed under the MIT license. Original notices and bundled third-party licenses are retained in the source tree.