BSHA3  0.17.99
P2P Blockchain, based on Bitcoin
zmqnotificationinterface.cpp
Go to the documentation of this file.
1 // Copyright (c) 2015-2018 The Bitcoin Core developers
2 // Distributed under the MIT software license, see the accompanying
3 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
4 
7 
8 #include <version.h>
9 #include <validation.h>
10 #include <streams.h>
11 #include <util.h>
12 
13 void zmqError(const char *str)
14 {
15  LogPrint(BCLog::ZMQ, "zmq: Error: %s, errno=%s\n", str, zmq_strerror(errno));
16 }
17 
19 {
20 }
21 
23 {
24  Shutdown();
25 
26  for (std::list<CZMQAbstractNotifier*>::iterator i=notifiers.begin(); i!=notifiers.end(); ++i)
27  {
28  delete *i;
29  }
30 }
31 
32 std::list<const CZMQAbstractNotifier*> CZMQNotificationInterface::GetActiveNotifiers() const
33 {
34  std::list<const CZMQAbstractNotifier*> result;
35  for (const auto* n : notifiers) {
36  result.push_back(n);
37  }
38  return result;
39 }
40 
42 {
43  CZMQNotificationInterface* notificationInterface = nullptr;
44  std::map<std::string, CZMQNotifierFactory> factories;
45  std::list<CZMQAbstractNotifier*> notifiers;
46 
47  factories["pubhashblock"] = CZMQAbstractNotifier::Create<CZMQPublishHashBlockNotifier>;
48  factories["pubhashtx"] = CZMQAbstractNotifier::Create<CZMQPublishHashTransactionNotifier>;
49  factories["pubrawblock"] = CZMQAbstractNotifier::Create<CZMQPublishRawBlockNotifier>;
50  factories["pubrawtx"] = CZMQAbstractNotifier::Create<CZMQPublishRawTransactionNotifier>;
51 
52  for (const auto& entry : factories)
53  {
54  std::string arg("-zmq" + entry.first);
55  if (gArgs.IsArgSet(arg))
56  {
57  CZMQNotifierFactory factory = entry.second;
58  std::string address = gArgs.GetArg(arg, "");
59  CZMQAbstractNotifier *notifier = factory();
60  notifier->SetType(entry.first);
61  notifier->SetAddress(address);
62  notifiers.push_back(notifier);
63  }
64  }
65 
66  if (!notifiers.empty())
67  {
68  notificationInterface = new CZMQNotificationInterface();
69  notificationInterface->notifiers = notifiers;
70 
71  if (!notificationInterface->Initialize())
72  {
73  delete notificationInterface;
74  notificationInterface = nullptr;
75  }
76  }
77 
78  return notificationInterface;
79 }
80 
81 // Called at startup to conditionally set up ZMQ socket(s)
83 {
84  int major = 0, minor = 0, patch = 0;
85  zmq_version(&major, &minor, &patch);
86  LogPrint(BCLog::ZMQ, "zmq: version %d.%d.%d\n", major, minor, patch);
87 
88  LogPrint(BCLog::ZMQ, "zmq: Initialize notification interface\n");
89  assert(!pcontext);
90 
91  pcontext = zmq_ctx_new();
92 
93  if (!pcontext)
94  {
95  zmqError("Unable to initialize context");
96  return false;
97  }
98 
99  std::list<CZMQAbstractNotifier*>::iterator i=notifiers.begin();
100  for (; i!=notifiers.end(); ++i)
101  {
102  CZMQAbstractNotifier *notifier = *i;
103  if (notifier->Initialize(pcontext))
104  {
105  LogPrint(BCLog::ZMQ, " Notifier %s ready (address = %s)\n", notifier->GetType(), notifier->GetAddress());
106  }
107  else
108  {
109  LogPrint(BCLog::ZMQ, " Notifier %s failed (address = %s)\n", notifier->GetType(), notifier->GetAddress());
110  break;
111  }
112  }
113 
114  if (i!=notifiers.end())
115  {
116  return false;
117  }
118 
119  return true;
120 }
121 
122 // Called during shutdown sequence
124 {
125  LogPrint(BCLog::ZMQ, "zmq: Shutdown notification interface\n");
126  if (pcontext)
127  {
128  for (std::list<CZMQAbstractNotifier*>::iterator i=notifiers.begin(); i!=notifiers.end(); ++i)
129  {
130  CZMQAbstractNotifier *notifier = *i;
131  LogPrint(BCLog::ZMQ, " Shutdown notifier %s at %s\n", notifier->GetType(), notifier->GetAddress());
132  notifier->Shutdown();
133  }
134  zmq_ctx_term(pcontext);
135 
136  pcontext = nullptr;
137  }
138 }
139 
140 void CZMQNotificationInterface::UpdatedBlockTip(const CBlockIndex *pindexNew, const CBlockIndex *pindexFork, bool fInitialDownload)
141 {
142  if (fInitialDownload || pindexNew == pindexFork) // In IBD or blocks were disconnected without any new ones
143  return;
144 
145  for (std::list<CZMQAbstractNotifier*>::iterator i = notifiers.begin(); i!=notifiers.end(); )
146  {
147  CZMQAbstractNotifier *notifier = *i;
148  if (notifier->NotifyBlock(pindexNew))
149  {
150  i++;
151  }
152  else
153  {
154  notifier->Shutdown();
155  i = notifiers.erase(i);
156  }
157  }
158 }
159 
161 {
162  // Used by BlockConnected and BlockDisconnected as well, because they're
163  // all the same external callback.
164  const CTransaction& tx = *ptx;
165 
166  for (std::list<CZMQAbstractNotifier*>::iterator i = notifiers.begin(); i!=notifiers.end(); )
167  {
168  CZMQAbstractNotifier *notifier = *i;
169  if (notifier->NotifyTransaction(tx))
170  {
171  i++;
172  }
173  else
174  {
175  notifier->Shutdown();
176  i = notifiers.erase(i);
177  }
178  }
179 }
180 
181 void CZMQNotificationInterface::BlockConnected(const std::shared_ptr<const CBlock>& pblock, const CBlockIndex* pindexConnected, const std::vector<CTransactionRef>& vtxConflicted)
182 {
183  for (const CTransactionRef& ptx : pblock->vtx) {
184  // Do a normal notify for each transaction added in the block
186  }
187 }
188 
189 void CZMQNotificationInterface::BlockDisconnected(const std::shared_ptr<const CBlock>& pblock)
190 {
191  for (const CTransactionRef& ptx : pblock->vtx) {
192  // Do a normal notify for each transaction removed in block disconnection
194  }
195 }
196 
bool IsArgSet(const std::string &strArg) const
Return true if the given argument has been manually set.
Definition: util.cpp:502
void TransactionAddedToMempool(const CTransactionRef &tx) override
Notifies listeners of a transaction having been added to mempool.
virtual bool NotifyBlock(const CBlockIndex *pindex)
std::string GetAddress() const
void BlockConnected(const std::shared_ptr< const CBlock > &pblock, const CBlockIndex *pindexConnected, const std::vector< CTransactionRef > &vtxConflicted) override
Notifies listeners of a block being connected.
std::shared_ptr< const CTransaction > CTransactionRef
Definition: transaction.h:402
static CZMQNotificationInterface * Create()
virtual bool NotifyTransaction(const CTransaction &transaction)
void BlockDisconnected(const std::shared_ptr< const CBlock > &pblock) override
Notifies listeners of a block being disconnected.
void SetAddress(const std::string &a)
virtual void Shutdown()=0
void UpdatedBlockTip(const CBlockIndex *pindexNew, const CBlockIndex *pindexFork, bool fInitialDownload) override
Notifies listeners when the block chain tip advances.
std::list< CZMQAbstractNotifier * > notifiers
ArgsManager gArgs
Definition: util.cpp:88
void zmqError(const char *str)
The block chain is a tree shaped structure starting with the genesis block at the root...
Definition: chain.h:170
std::string GetArg(const std::string &strArg, const std::string &strDefault) const
Return string argument or default value.
Definition: util.cpp:526
CZMQAbstractNotifier *(* CZMQNotifierFactory)()
virtual bool Initialize(void *pcontext)=0
std::list< const CZMQAbstractNotifier * > GetActiveNotifiers() const
The basic transaction that is broadcasted on the network and contained in blocks. ...
Definition: transaction.h:264
void SetType(const std::string &t)
std::string GetType() const
CZMQNotificationInterface * g_zmq_notification_interface