Merge #903: Implement transaction lock zmq notifications
15a6a16 Implement transaction lock zmq notifications 3bc86a6 always push zmqpubhashtxlock even if tx is not from/to our wallet 568315b fix typo b6d41d2 fix data size for notification name 339be11 implement zmqpubrawtxlock 70f44f9 update zmq_sub.py with hashtxlock and rawtxlock
This commit is contained in:
parent
175508d6b7
commit
90adb89233
@ -10,8 +10,10 @@ zmqContext = zmq.Context()
|
|||||||
zmqSubSocket = zmqContext.socket(zmq.SUB)
|
zmqSubSocket = zmqContext.socket(zmq.SUB)
|
||||||
zmqSubSocket.setsockopt(zmq.SUBSCRIBE, "hashblock")
|
zmqSubSocket.setsockopt(zmq.SUBSCRIBE, "hashblock")
|
||||||
zmqSubSocket.setsockopt(zmq.SUBSCRIBE, "hashtx")
|
zmqSubSocket.setsockopt(zmq.SUBSCRIBE, "hashtx")
|
||||||
|
zmqSubSocket.setsockopt(zmq.SUBSCRIBE, "hashtxlock")
|
||||||
zmqSubSocket.setsockopt(zmq.SUBSCRIBE, "rawblock")
|
zmqSubSocket.setsockopt(zmq.SUBSCRIBE, "rawblock")
|
||||||
zmqSubSocket.setsockopt(zmq.SUBSCRIBE, "rawtx")
|
zmqSubSocket.setsockopt(zmq.SUBSCRIBE, "rawtx")
|
||||||
|
zmqSubSocket.setsockopt(zmq.SUBSCRIBE, "rawtxlock")
|
||||||
zmqSubSocket.connect("tcp://127.0.0.1:%i" % port)
|
zmqSubSocket.connect("tcp://127.0.0.1:%i" % port)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@ -26,12 +28,18 @@ try:
|
|||||||
elif topic == "hashtx":
|
elif topic == "hashtx":
|
||||||
print '- HASH TX -'
|
print '- HASH TX -'
|
||||||
print binascii.hexlify(body)
|
print binascii.hexlify(body)
|
||||||
|
elif topic == "hashtxlock":
|
||||||
|
print '- HASH TX LOCK -'
|
||||||
|
print binascii.hexlify(body)
|
||||||
elif topic == "rawblock":
|
elif topic == "rawblock":
|
||||||
print "- RAW BLOCK HEADER -"
|
print "- RAW BLOCK HEADER -"
|
||||||
print binascii.hexlify(body[:80])
|
print binascii.hexlify(body[:80])
|
||||||
elif topic == "rawtx":
|
elif topic == "rawtx":
|
||||||
print '- RAW TX -'
|
print '- RAW TX -'
|
||||||
print binascii.hexlify(body)
|
print binascii.hexlify(body)
|
||||||
|
elif topic == "rawtxlock":
|
||||||
|
print '- RAW TX LOCK -'
|
||||||
|
print binascii.hexlify(body)
|
||||||
|
|
||||||
except KeyboardInterrupt:
|
except KeyboardInterrupt:
|
||||||
zmqContext.destroy()
|
zmqContext.destroy()
|
||||||
|
@ -57,9 +57,11 @@ the commandline or in the configuration file.
|
|||||||
Currently, the following notifications are supported:
|
Currently, the following notifications are supported:
|
||||||
|
|
||||||
-zmqpubhashtx=address
|
-zmqpubhashtx=address
|
||||||
|
-zmqpubhashtxlock=address
|
||||||
-zmqpubhashblock=address
|
-zmqpubhashblock=address
|
||||||
-zmqpubrawblock=address
|
-zmqpubrawblock=address
|
||||||
-zmqpubrawtx=address
|
-zmqpubrawtx=address
|
||||||
|
-zmqpubrawtxlock=address
|
||||||
|
|
||||||
The socket type is PUB and the address must be a valid ZeroMQ socket
|
The socket type is PUB and the address must be a valid ZeroMQ socket
|
||||||
address. The same address can be used in more than one notification.
|
address. The same address can be used in more than one notification.
|
||||||
|
@ -481,8 +481,10 @@ std::string HelpMessage(HelpMessageMode mode)
|
|||||||
strUsage += HelpMessageGroup(_("ZeroMQ notification options:"));
|
strUsage += HelpMessageGroup(_("ZeroMQ notification options:"));
|
||||||
strUsage += HelpMessageOpt("-zmqpubhashblock=<address>", _("Enable publish hash block in <address>"));
|
strUsage += HelpMessageOpt("-zmqpubhashblock=<address>", _("Enable publish hash block in <address>"));
|
||||||
strUsage += HelpMessageOpt("-zmqpubhashtx=<address>", _("Enable publish hash transaction in <address>"));
|
strUsage += HelpMessageOpt("-zmqpubhashtx=<address>", _("Enable publish hash transaction in <address>"));
|
||||||
|
strUsage += HelpMessageOpt("-zmqpubhashtxlock=<address>", _("Enable publish hash transaction (locked via InstantSend) in <address>"));
|
||||||
strUsage += HelpMessageOpt("-zmqpubrawblock=<address>", _("Enable publish raw block in <address>"));
|
strUsage += HelpMessageOpt("-zmqpubrawblock=<address>", _("Enable publish raw block in <address>"));
|
||||||
strUsage += HelpMessageOpt("-zmqpubrawtx=<address>", _("Enable publish raw transaction in <address>"));
|
strUsage += HelpMessageOpt("-zmqpubrawtx=<address>", _("Enable publish raw transaction in <address>"));
|
||||||
|
strUsage += HelpMessageOpt("-zmqpubrawtxlock=<address>", _("Enable publish raw transaction (locked via InstantSend) in <address>"));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
strUsage += HelpMessageGroup(_("Debugging/Testing options:"));
|
strUsage += HelpMessageGroup(_("Debugging/Testing options:"));
|
||||||
|
@ -386,11 +386,12 @@ void UpdateLockedTransaction(CTransaction& tx, bool fForceNotification) {
|
|||||||
// there must be a successfully verified lock request
|
// there must be a successfully verified lock request
|
||||||
if (!mapTxLockReq.count(txHash)) return;
|
if (!mapTxLockReq.count(txHash)) return;
|
||||||
|
|
||||||
|
int nSignatures = GetTransactionLockSignatures(txHash);
|
||||||
|
|
||||||
#ifdef ENABLE_WALLET
|
#ifdef ENABLE_WALLET
|
||||||
if(pwalletMain && pwalletMain->UpdatedTransaction(txHash)){
|
if(pwalletMain && pwalletMain->UpdatedTransaction(txHash)){
|
||||||
// bumping this to update UI
|
// bumping this to update UI
|
||||||
nCompleteTXLocks++;
|
nCompleteTXLocks++;
|
||||||
int nSignatures = GetTransactionLockSignatures(txHash);
|
|
||||||
// a transaction lock must have enough signatures to trigger this notification
|
// a transaction lock must have enough signatures to trigger this notification
|
||||||
if(nSignatures == INSTANTX_SIGNATURES_REQUIRED || (fForceNotification && nSignatures > INSTANTX_SIGNATURES_REQUIRED)) {
|
if(nSignatures == INSTANTX_SIGNATURES_REQUIRED || (fForceNotification && nSignatures > INSTANTX_SIGNATURES_REQUIRED)) {
|
||||||
// notify an external script once threshold is reached
|
// notify an external script once threshold is reached
|
||||||
@ -403,6 +404,10 @@ void UpdateLockedTransaction(CTransaction& tx, bool fForceNotification) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
if(nSignatures == INSTANTX_SIGNATURES_REQUIRED || (fForceNotification && nSignatures > INSTANTX_SIGNATURES_REQUIRED)) {
|
||||||
|
GetMainSignals().NotifyTransactionLock(tx);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void LockTransactionInputs(CTransaction& tx) {
|
void LockTransactionInputs(CTransaction& tx) {
|
||||||
|
@ -15,6 +15,7 @@ CMainSignals& GetMainSignals()
|
|||||||
void RegisterValidationInterface(CValidationInterface* pwalletIn) {
|
void RegisterValidationInterface(CValidationInterface* pwalletIn) {
|
||||||
g_signals.UpdatedBlockTip.connect(boost::bind(&CValidationInterface::UpdatedBlockTip, pwalletIn, _1));
|
g_signals.UpdatedBlockTip.connect(boost::bind(&CValidationInterface::UpdatedBlockTip, pwalletIn, _1));
|
||||||
g_signals.SyncTransaction.connect(boost::bind(&CValidationInterface::SyncTransaction, pwalletIn, _1, _2));
|
g_signals.SyncTransaction.connect(boost::bind(&CValidationInterface::SyncTransaction, pwalletIn, _1, _2));
|
||||||
|
g_signals.NotifyTransactionLock.connect(boost::bind(&CValidationInterface::NotifyTransactionLock, pwalletIn, _1));
|
||||||
g_signals.UpdatedTransaction.connect(boost::bind(&CValidationInterface::UpdatedTransaction, pwalletIn, _1));
|
g_signals.UpdatedTransaction.connect(boost::bind(&CValidationInterface::UpdatedTransaction, pwalletIn, _1));
|
||||||
g_signals.SetBestChain.connect(boost::bind(&CValidationInterface::SetBestChain, pwalletIn, _1));
|
g_signals.SetBestChain.connect(boost::bind(&CValidationInterface::SetBestChain, pwalletIn, _1));
|
||||||
g_signals.Inventory.connect(boost::bind(&CValidationInterface::Inventory, pwalletIn, _1));
|
g_signals.Inventory.connect(boost::bind(&CValidationInterface::Inventory, pwalletIn, _1));
|
||||||
@ -32,6 +33,7 @@ void UnregisterValidationInterface(CValidationInterface* pwalletIn) {
|
|||||||
g_signals.Inventory.disconnect(boost::bind(&CValidationInterface::Inventory, pwalletIn, _1));
|
g_signals.Inventory.disconnect(boost::bind(&CValidationInterface::Inventory, pwalletIn, _1));
|
||||||
g_signals.SetBestChain.disconnect(boost::bind(&CValidationInterface::SetBestChain, pwalletIn, _1));
|
g_signals.SetBestChain.disconnect(boost::bind(&CValidationInterface::SetBestChain, pwalletIn, _1));
|
||||||
g_signals.UpdatedTransaction.disconnect(boost::bind(&CValidationInterface::UpdatedTransaction, pwalletIn, _1));
|
g_signals.UpdatedTransaction.disconnect(boost::bind(&CValidationInterface::UpdatedTransaction, pwalletIn, _1));
|
||||||
|
g_signals.NotifyTransactionLock.disconnect(boost::bind(&CValidationInterface::NotifyTransactionLock, pwalletIn, _1));
|
||||||
g_signals.SyncTransaction.disconnect(boost::bind(&CValidationInterface::SyncTransaction, pwalletIn, _1, _2));
|
g_signals.SyncTransaction.disconnect(boost::bind(&CValidationInterface::SyncTransaction, pwalletIn, _1, _2));
|
||||||
g_signals.UpdatedBlockTip.disconnect(boost::bind(&CValidationInterface::UpdatedBlockTip, pwalletIn, _1));
|
g_signals.UpdatedBlockTip.disconnect(boost::bind(&CValidationInterface::UpdatedBlockTip, pwalletIn, _1));
|
||||||
}
|
}
|
||||||
@ -44,6 +46,7 @@ void UnregisterAllValidationInterfaces() {
|
|||||||
g_signals.Inventory.disconnect_all_slots();
|
g_signals.Inventory.disconnect_all_slots();
|
||||||
g_signals.SetBestChain.disconnect_all_slots();
|
g_signals.SetBestChain.disconnect_all_slots();
|
||||||
g_signals.UpdatedTransaction.disconnect_all_slots();
|
g_signals.UpdatedTransaction.disconnect_all_slots();
|
||||||
|
g_signals.NotifyTransactionLock.disconnect_all_slots();
|
||||||
g_signals.SyncTransaction.disconnect_all_slots();
|
g_signals.SyncTransaction.disconnect_all_slots();
|
||||||
g_signals.UpdatedBlockTip.disconnect_all_slots();
|
g_signals.UpdatedBlockTip.disconnect_all_slots();
|
||||||
}
|
}
|
||||||
|
@ -33,6 +33,7 @@ class CValidationInterface {
|
|||||||
protected:
|
protected:
|
||||||
virtual void UpdatedBlockTip(const CBlockIndex *pindex) {}
|
virtual void UpdatedBlockTip(const CBlockIndex *pindex) {}
|
||||||
virtual void SyncTransaction(const CTransaction &tx, const CBlock *pblock) {}
|
virtual void SyncTransaction(const CTransaction &tx, const CBlock *pblock) {}
|
||||||
|
virtual void NotifyTransactionLock(const CTransaction &tx) {}
|
||||||
virtual void SetBestChain(const CBlockLocator &locator) {}
|
virtual void SetBestChain(const CBlockLocator &locator) {}
|
||||||
virtual bool UpdatedTransaction(const uint256 &hash) { return false;}
|
virtual bool UpdatedTransaction(const uint256 &hash) { return false;}
|
||||||
virtual void Inventory(const uint256 &hash) {}
|
virtual void Inventory(const uint256 &hash) {}
|
||||||
@ -50,6 +51,8 @@ struct CMainSignals {
|
|||||||
boost::signals2::signal<void (const CBlockIndex *)> UpdatedBlockTip;
|
boost::signals2::signal<void (const CBlockIndex *)> UpdatedBlockTip;
|
||||||
/** Notifies listeners of updated transaction data (transaction, and optionally the block it is found in. */
|
/** Notifies listeners of updated transaction data (transaction, and optionally the block it is found in. */
|
||||||
boost::signals2::signal<void (const CTransaction &, const CBlock *)> SyncTransaction;
|
boost::signals2::signal<void (const CTransaction &, const CBlock *)> SyncTransaction;
|
||||||
|
/** Notifies listeners of an updated transaction lock without new data. */
|
||||||
|
boost::signals2::signal<void (const CTransaction &)> NotifyTransactionLock;
|
||||||
/** Notifies listeners of an updated transaction without new data (for now: a coinbase potentially becoming visible). */
|
/** Notifies listeners of an updated transaction without new data (for now: a coinbase potentially becoming visible). */
|
||||||
boost::signals2::signal<bool (const uint256 &)> UpdatedTransaction;
|
boost::signals2::signal<bool (const uint256 &)> UpdatedTransaction;
|
||||||
/** Notifies listeners of a new active block chain. */
|
/** Notifies listeners of a new active block chain. */
|
||||||
|
@ -20,3 +20,8 @@ bool CZMQAbstractNotifier::NotifyTransaction(const CTransaction &/*transaction*/
|
|||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CZMQAbstractNotifier::NotifyTransactionLock(const CTransaction &/*transaction*/)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
@ -34,6 +34,7 @@ public:
|
|||||||
|
|
||||||
virtual bool NotifyBlock(const CBlockIndex *pindex);
|
virtual bool NotifyBlock(const CBlockIndex *pindex);
|
||||||
virtual bool NotifyTransaction(const CTransaction &transaction);
|
virtual bool NotifyTransaction(const CTransaction &transaction);
|
||||||
|
virtual bool NotifyTransactionLock(const CTransaction &transaction);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void *psocket;
|
void *psocket;
|
||||||
|
@ -37,8 +37,10 @@ CZMQNotificationInterface* CZMQNotificationInterface::CreateWithArguments(const
|
|||||||
|
|
||||||
factories["pubhashblock"] = CZMQAbstractNotifier::Create<CZMQPublishHashBlockNotifier>;
|
factories["pubhashblock"] = CZMQAbstractNotifier::Create<CZMQPublishHashBlockNotifier>;
|
||||||
factories["pubhashtx"] = CZMQAbstractNotifier::Create<CZMQPublishHashTransactionNotifier>;
|
factories["pubhashtx"] = CZMQAbstractNotifier::Create<CZMQPublishHashTransactionNotifier>;
|
||||||
|
factories["pubhashtxlock"] = CZMQAbstractNotifier::Create<CZMQPublishHashTransactionLockNotifier>;
|
||||||
factories["pubrawblock"] = CZMQAbstractNotifier::Create<CZMQPublishRawBlockNotifier>;
|
factories["pubrawblock"] = CZMQAbstractNotifier::Create<CZMQPublishRawBlockNotifier>;
|
||||||
factories["pubrawtx"] = CZMQAbstractNotifier::Create<CZMQPublishRawTransactionNotifier>;
|
factories["pubrawtx"] = CZMQAbstractNotifier::Create<CZMQPublishRawTransactionNotifier>;
|
||||||
|
factories["pubrawtxlock"] = CZMQAbstractNotifier::Create<CZMQPublishRawTransactionLockNotifier>;
|
||||||
|
|
||||||
for (std::map<std::string, CZMQNotifierFactory>::const_iterator i=factories.begin(); i!=factories.end(); ++i)
|
for (std::map<std::string, CZMQNotifierFactory>::const_iterator i=factories.begin(); i!=factories.end(); ++i)
|
||||||
{
|
{
|
||||||
@ -158,3 +160,20 @@ void CZMQNotificationInterface::SyncTransaction(const CTransaction &tx, const CB
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CZMQNotificationInterface::NotifyTransactionLock(const CTransaction &tx)
|
||||||
|
{
|
||||||
|
for (std::list<CZMQAbstractNotifier*>::iterator i = notifiers.begin(); i!=notifiers.end(); )
|
||||||
|
{
|
||||||
|
CZMQAbstractNotifier *notifier = *i;
|
||||||
|
if (notifier->NotifyTransactionLock(tx))
|
||||||
|
{
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
notifier->Shutdown();
|
||||||
|
i = notifiers.erase(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -26,6 +26,7 @@ protected:
|
|||||||
// CValidationInterface
|
// CValidationInterface
|
||||||
void SyncTransaction(const CTransaction &tx, const CBlock *pblock);
|
void SyncTransaction(const CTransaction &tx, const CBlock *pblock);
|
||||||
void UpdatedBlockTip(const CBlockIndex *pindex);
|
void UpdatedBlockTip(const CBlockIndex *pindex);
|
||||||
|
void NotifyTransactionLock(const CTransaction &tx);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
CZMQNotificationInterface();
|
CZMQNotificationInterface();
|
||||||
|
@ -139,6 +139,17 @@ bool CZMQPublishHashTransactionNotifier::NotifyTransaction(const CTransaction &t
|
|||||||
return rc == 0;
|
return rc == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CZMQPublishHashTransactionLockNotifier::NotifyTransactionLock(const CTransaction &transaction)
|
||||||
|
{
|
||||||
|
uint256 hash = transaction.GetHash();
|
||||||
|
LogPrint("zmq", "zmq: Publish hashtxlock %s\n", hash.GetHex());
|
||||||
|
char data[32];
|
||||||
|
for (unsigned int i = 0; i < 32; i++)
|
||||||
|
data[31 - i] = hash.begin()[i];
|
||||||
|
int rc = zmq_send_multipart(psocket, "hashtxlock", 10, data, 32, 0);
|
||||||
|
return rc == 0;
|
||||||
|
}
|
||||||
|
|
||||||
bool CZMQPublishRawBlockNotifier::NotifyBlock(const CBlockIndex *pindex)
|
bool CZMQPublishRawBlockNotifier::NotifyBlock(const CBlockIndex *pindex)
|
||||||
{
|
{
|
||||||
LogPrint("zmq", "zmq: Publish rawblock %s\n", pindex->GetBlockHash().GetHex());
|
LogPrint("zmq", "zmq: Publish rawblock %s\n", pindex->GetBlockHash().GetHex());
|
||||||
@ -170,3 +181,13 @@ bool CZMQPublishRawTransactionNotifier::NotifyTransaction(const CTransaction &tr
|
|||||||
int rc = zmq_send_multipart(psocket, "rawtx", 5, &(*ss.begin()), ss.size(), 0);
|
int rc = zmq_send_multipart(psocket, "rawtx", 5, &(*ss.begin()), ss.size(), 0);
|
||||||
return rc == 0;
|
return rc == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CZMQPublishRawTransactionLockNotifier::NotifyTransactionLock(const CTransaction &transaction)
|
||||||
|
{
|
||||||
|
uint256 hash = transaction.GetHash();
|
||||||
|
LogPrint("zmq", "zmq: Publish rawtxlock %s\n", hash.GetHex());
|
||||||
|
CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
|
||||||
|
ss << transaction;
|
||||||
|
int rc = zmq_send_multipart(psocket, "rawtxlock", 9, &(*ss.begin()), ss.size(), 0);
|
||||||
|
return rc == 0;
|
||||||
|
}
|
||||||
|
@ -28,6 +28,12 @@ public:
|
|||||||
bool NotifyTransaction(const CTransaction &transaction);
|
bool NotifyTransaction(const CTransaction &transaction);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class CZMQPublishHashTransactionLockNotifier : public CZMQAbstractPublishNotifier
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
bool NotifyTransactionLock(const CTransaction &transaction);
|
||||||
|
};
|
||||||
|
|
||||||
class CZMQPublishRawBlockNotifier : public CZMQAbstractPublishNotifier
|
class CZMQPublishRawBlockNotifier : public CZMQAbstractPublishNotifier
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -40,4 +46,10 @@ public:
|
|||||||
bool NotifyTransaction(const CTransaction &transaction);
|
bool NotifyTransaction(const CTransaction &transaction);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class CZMQPublishRawTransactionLockNotifier : public CZMQAbstractPublishNotifier
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
bool NotifyTransactionLock(const CTransaction &transaction);
|
||||||
|
};
|
||||||
|
|
||||||
#endif // BITCOIN_ZMQ_ZMQPUBLISHNOTIFIER_H
|
#endif // BITCOIN_ZMQ_ZMQPUBLISHNOTIFIER_H
|
||||||
|
Loading…
Reference in New Issue
Block a user