Dash Core Source Documentation (0.16.0.1)

Find detailed information regarding the Dash Core source code.

zmqnotificationinterface.cpp
Go to the documentation of this file.
1 // Copyright (c) 2015 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 
33 {
34  CZMQNotificationInterface* notificationInterface = nullptr;
35  std::map<std::string, CZMQNotifierFactory> factories;
36  std::list<CZMQAbstractNotifier*> notifiers;
37 
38  factories["pubhashblock"] = CZMQAbstractNotifier::Create<CZMQPublishHashBlockNotifier>;
39  factories["pubhashchainlock"] = CZMQAbstractNotifier::Create<CZMQPublishHashChainLockNotifier>;
40  factories["pubhashtx"] = CZMQAbstractNotifier::Create<CZMQPublishHashTransactionNotifier>;
41  factories["pubhashtxlock"] = CZMQAbstractNotifier::Create<CZMQPublishHashTransactionLockNotifier>;
42  factories["pubhashgovernancevote"] = CZMQAbstractNotifier::Create<CZMQPublishHashGovernanceVoteNotifier>;
43  factories["pubhashgovernanceobject"] = CZMQAbstractNotifier::Create<CZMQPublishHashGovernanceObjectNotifier>;
44  factories["pubhashinstantsenddoublespend"] = CZMQAbstractNotifier::Create<CZMQPublishHashInstantSendDoubleSpendNotifier>;
45  factories["pubrawblock"] = CZMQAbstractNotifier::Create<CZMQPublishRawBlockNotifier>;
46  factories["pubrawchainlock"] = CZMQAbstractNotifier::Create<CZMQPublishRawChainLockNotifier>;
47  factories["pubrawchainlocksig"] = CZMQAbstractNotifier::Create<CZMQPublishRawChainLockSigNotifier>;
48  factories["pubrawtx"] = CZMQAbstractNotifier::Create<CZMQPublishRawTransactionNotifier>;
49  factories["pubrawtxlock"] = CZMQAbstractNotifier::Create<CZMQPublishRawTransactionLockNotifier>;
50  factories["pubrawtxlocksig"] = CZMQAbstractNotifier::Create<CZMQPublishRawTransactionLockSigNotifier>;
51  factories["pubrawgovernancevote"] = CZMQAbstractNotifier::Create<CZMQPublishRawGovernanceVoteNotifier>;
52  factories["pubrawgovernanceobject"] = CZMQAbstractNotifier::Create<CZMQPublishRawGovernanceObjectNotifier>;
53  factories["pubrawinstantsenddoublespend"] = CZMQAbstractNotifier::Create<CZMQPublishRawInstantSendDoubleSpendNotifier>;
54 
55  for (const auto& entry : factories)
56  {
57  std::string arg("-zmq" + entry.first);
58  if (gArgs.IsArgSet(arg))
59  {
60  CZMQNotifierFactory factory = entry.second;
61  std::string address = gArgs.GetArg(arg, "");
62  CZMQAbstractNotifier *notifier = factory();
63  notifier->SetType(entry.first);
64  notifier->SetAddress(address);
65  notifiers.push_back(notifier);
66  }
67  }
68 
69  if (!notifiers.empty())
70  {
71  notificationInterface = new CZMQNotificationInterface();
72  notificationInterface->notifiers = notifiers;
73 
74  if (!notificationInterface->Initialize())
75  {
76  delete notificationInterface;
77  notificationInterface = nullptr;
78  }
79  }
80 
81  return notificationInterface;
82 }
83 
84 // Called at startup to conditionally set up ZMQ socket(s)
86 {
87  LogPrint(BCLog::ZMQ, "zmq: Initialize notification interface\n");
88  assert(!pcontext);
89 
90  pcontext = zmq_init(1);
91 
92  if (!pcontext)
93  {
94  zmqError("Unable to initialize context");
95  return false;
96  }
97 
98  std::list<CZMQAbstractNotifier*>::iterator i=notifiers.begin();
99  for (; i!=notifiers.end(); ++i)
100  {
101  CZMQAbstractNotifier *notifier = *i;
102  if (notifier->Initialize(pcontext))
103  {
104  LogPrint(BCLog::ZMQ, " Notifier %s ready (address = %s)\n", notifier->GetType(), notifier->GetAddress());
105  }
106  else
107  {
108  LogPrint(BCLog::ZMQ, " Notifier %s failed (address = %s)\n", notifier->GetType(), notifier->GetAddress());
109  break;
110  }
111  }
112 
113  if (i!=notifiers.end())
114  {
115  return false;
116  }
117 
118  return true;
119 }
120 
121 // Called during shutdown sequence
123 {
124  LogPrint(BCLog::ZMQ, "zmq: Shutdown notification interface\n");
125  if (pcontext)
126  {
127  for (std::list<CZMQAbstractNotifier*>::iterator i=notifiers.begin(); i!=notifiers.end(); ++i)
128  {
129  CZMQAbstractNotifier *notifier = *i;
130  LogPrint(BCLog::ZMQ, " Shutdown notifier %s at %s\n", notifier->GetType(), notifier->GetAddress());
131  notifier->Shutdown();
132  }
133  zmq_ctx_destroy(pcontext);
134 
135  pcontext = nullptr;
136  }
137 }
138 
139 void CZMQNotificationInterface::UpdatedBlockTip(const CBlockIndex *pindexNew, const CBlockIndex *pindexFork, bool fInitialDownload)
140 {
141  if (fInitialDownload || pindexNew == pindexFork) // In IBD or blocks were disconnected without any new ones
142  return;
143 
144  for (std::list<CZMQAbstractNotifier*>::iterator i = notifiers.begin(); i!=notifiers.end(); )
145  {
146  CZMQAbstractNotifier *notifier = *i;
147  if (notifier->NotifyBlock(pindexNew))
148  {
149  i++;
150  }
151  else
152  {
153  notifier->Shutdown();
154  i = notifiers.erase(i);
155  }
156  }
157 }
158 
160 {
161  for (std::list<CZMQAbstractNotifier*>::iterator i = notifiers.begin(); i!=notifiers.end(); )
162  {
163  CZMQAbstractNotifier *notifier = *i;
164  if (notifier->NotifyChainLock(pindex, clsig))
165  {
166  i++;
167  }
168  else
169  {
170  notifier->Shutdown();
171  i = notifiers.erase(i);
172  }
173  }
174 }
175 
177 {
178  // Used by BlockConnected and BlockDisconnected as well, because they're
179  // all the same external callback.
180  const CTransaction& tx = *ptx;
181 
182  for (std::list<CZMQAbstractNotifier*>::iterator i = notifiers.begin(); i!=notifiers.end(); )
183  {
184  CZMQAbstractNotifier *notifier = *i;
185  if (notifier->NotifyTransaction(tx))
186  {
187  i++;
188  }
189  else
190  {
191  notifier->Shutdown();
192  i = notifiers.erase(i);
193  }
194  }
195 }
196 
197 void CZMQNotificationInterface::BlockConnected(const std::shared_ptr<const CBlock>& pblock, const CBlockIndex* pindexConnected, const std::vector<CTransactionRef>& vtxConflicted)
198 {
199  for (const CTransactionRef& ptx : pblock->vtx) {
200  // Do a normal notify for each transaction added in the block
202  }
203 }
204 
205 void CZMQNotificationInterface::BlockDisconnected(const std::shared_ptr<const CBlock>& pblock, const CBlockIndex* pindexDisconnected)
206 {
207  for (const CTransactionRef& ptx : pblock->vtx) {
208  // Do a normal notify for each transaction removed in block disconnection
210  }
211 }
212 
214 {
215  for (std::list<CZMQAbstractNotifier*>::iterator i = notifiers.begin(); i!=notifiers.end(); )
216  {
217  CZMQAbstractNotifier *notifier = *i;
218  if (notifier->NotifyTransactionLock(tx, islock))
219  {
220  i++;
221  }
222  else
223  {
224  notifier->Shutdown();
225  i = notifiers.erase(i);
226  }
227  }
228 }
229 
231 {
232  for (std::list<CZMQAbstractNotifier*>::iterator i = notifiers.begin(); i != notifiers.end(); )
233  {
234  CZMQAbstractNotifier *notifier = *i;
235  if (notifier->NotifyGovernanceVote(vote))
236  {
237  i++;
238  }
239  else
240  {
241  notifier->Shutdown();
242  i = notifiers.erase(i);
243  }
244  }
245 }
246 
248 {
249  for (std::list<CZMQAbstractNotifier*>::iterator i = notifiers.begin(); i != notifiers.end(); )
250  {
251  CZMQAbstractNotifier *notifier = *i;
252  if (notifier->NotifyGovernanceObject(object))
253  {
254  i++;
255  }
256  else
257  {
258  notifier->Shutdown();
259  i = notifiers.erase(i);
260  }
261  }
262 }
263 
265 {
266  for (auto it = notifiers.begin(); it != notifiers.end();) {
267  CZMQAbstractNotifier *notifier = *it;
268  if (notifier->NotifyInstantSendDoubleSpendAttempt(currentTx, previousTx)) {
269  ++it;
270  } else {
271  notifier->Shutdown();
272  it = notifiers.erase(it);
273  }
274  }
275 }
void BlockDisconnected(const std::shared_ptr< const CBlock > &pblock, const CBlockIndex *pindexDisconnected) override
Notifies listeners of a block being disconnected.
virtual bool NotifyTransactionLock(const CTransaction &transaction, const llmq::CInstantSendLock &islock)
bool IsArgSet(const std::string &strArg) const
Return true if the given argument has been manually set.
Definition: util.cpp:784
Governance Object.
virtual bool NotifyGovernanceObject(const CGovernanceObject &object)
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:345
virtual bool NotifyInstantSendDoubleSpendAttempt(const CTransaction &currentTx, const CTransaction &previousTx)
static CZMQNotificationInterface * Create()
virtual bool NotifyTransaction(const CTransaction &transaction)
void NotifyGovernanceVote(const CGovernanceVote &vote) override
void SetAddress(const std::string &a)
virtual void Shutdown()=0
#define LogPrint(category,...)
Definition: util.h:214
void UpdatedBlockTip(const CBlockIndex *pindexNew, const CBlockIndex *pindexFork, bool fInitialDownload) override
Notifies listeners of updated block chain tip.
void NotifyTransactionLock(const CTransaction &tx, const llmq::CInstantSendLock &islock) override
std::list< CZMQAbstractNotifier * > notifiers
ArgsManager gArgs
Definition: util.cpp:108
void NotifyGovernanceObject(const CGovernanceObject &object) override
void NotifyInstantSendDoubleSpendAttempt(const CTransaction &currentTx, const CTransaction &previousTx) override
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:808
CZMQAbstractNotifier *(* CZMQNotifierFactory)()
virtual bool Initialize(void *pcontext)=0
void NotifyChainLock(const CBlockIndex *pindex, const llmq::CChainLockSig &clsig) override
The basic transaction that is broadcasted on the network and contained in blocks. ...
Definition: transaction.h:198
virtual bool NotifyChainLock(const CBlockIndex *pindex, const llmq::CChainLockSig &clsig)
void SetType(const std::string &t)
std::string GetType() const
virtual bool NotifyGovernanceVote(const CGovernanceVote &vote)
void TransactionAddedToMempool(const CTransactionRef &tx, int64_t nAcceptTime) override
Notifies listeners of a transaction having been added to mempool.
Released under the MIT license