Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement transaction lock zmq notifications #903

Merged
merged 6 commits into from
Jul 15, 2016
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
8 changes: 8 additions & 0 deletions contrib/zmq/zmq_sub.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,10 @@
zmqSubSocket = zmqContext.socket(zmq.SUB)
zmqSubSocket.setsockopt(zmq.SUBSCRIBE, "hashblock")
zmqSubSocket.setsockopt(zmq.SUBSCRIBE, "hashtx")
zmqSubSocket.setsockopt(zmq.SUBSCRIBE, "hashtxlock")
zmqSubSocket.setsockopt(zmq.SUBSCRIBE, "rawblock")
zmqSubSocket.setsockopt(zmq.SUBSCRIBE, "rawtx")
zmqSubSocket.setsockopt(zmq.SUBSCRIBE, "rawtxlock")
zmqSubSocket.connect("tcp://127.0.0.1:%i" % port)

try:
Expand All @@ -26,12 +28,18 @@
elif topic == "hashtx":
print '- HASH TX -'
print binascii.hexlify(body)
elif topic == "hashtxlock":
print '- HASH TX LOCK -'
print binascii.hexlify(body)
elif topic == "rawblock":
print "- RAW BLOCK HEADER -"
print binascii.hexlify(body[:80])
elif topic == "rawtx":
print '- RAW TX -'
print binascii.hexlify(body)
elif topic == "rawtxlock":
print '- RAW TX LOCK -'
print binascii.hexlify(body)

except KeyboardInterrupt:
zmqContext.destroy()
2 changes: 2 additions & 0 deletions doc/zmq.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,9 +57,11 @@ the commandline or in the configuration file.
Currently, the following notifications are supported:

-zmqpubhashtx=address
-zmqpubhashtxlock=address
-zmqpubhashblock=address
-zmqpubrawblock=address
-zmqpubrawtx=address
-zmqpubrawtxlock=address

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.
Expand Down
2 changes: 2 additions & 0 deletions src/init.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -481,8 +481,10 @@ std::string HelpMessage(HelpMessageMode mode)
strUsage += HelpMessageGroup(_("ZeroMQ notification options:"));
strUsage += HelpMessageOpt("-zmqpubhashblock=<address>", _("Enable publish hash block 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("-zmqpubrawtx=<address>", _("Enable publish raw transaction in <address>"));
strUsage += HelpMessageOpt("-zmqpubrawtxlock=<address>", _("Enable publish raw transaction (locked via InstantSend) in <address>"));
#endif

strUsage += HelpMessageGroup(_("Debugging/Testing options:"));
Expand Down
7 changes: 6 additions & 1 deletion src/instantx.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -386,11 +386,12 @@ void UpdateLockedTransaction(CTransaction& tx, bool fForceNotification) {
// there must be a successfully verified lock request
if (!mapTxLockReq.count(txHash)) return;

int nSignatures = GetTransactionLockSignatures(txHash);

#ifdef ENABLE_WALLET
if(pwalletMain && pwalletMain->UpdatedTransaction(txHash)){
// bumping this to update UI
nCompleteTXLocks++;
int nSignatures = GetTransactionLockSignatures(txHash);
// a transaction lock must have enough signatures to trigger this notification
if(nSignatures == INSTANTX_SIGNATURES_REQUIRED || (fForceNotification && nSignatures > INSTANTX_SIGNATURES_REQUIRED)) {
// notify an external script once threshold is reached
Expand All @@ -403,6 +404,10 @@ void UpdateLockedTransaction(CTransaction& tx, bool fForceNotification) {
}
}
#endif

if(nSignatures == INSTANTX_SIGNATURES_REQUIRED || (fForceNotification && nSignatures > INSTANTX_SIGNATURES_REQUIRED)) {
GetMainSignals().NotifyTransactionLock(tx);
}
}

void LockTransactionInputs(CTransaction& tx) {
Expand Down
3 changes: 3 additions & 0 deletions src/validationinterface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ CMainSignals& GetMainSignals()
void RegisterValidationInterface(CValidationInterface* pwalletIn) {
g_signals.UpdatedBlockTip.connect(boost::bind(&CValidationInterface::UpdatedBlockTip, pwalletIn, _1));
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.SetBestChain.connect(boost::bind(&CValidationInterface::SetBestChain, pwalletIn, _1));
g_signals.Inventory.connect(boost::bind(&CValidationInterface::Inventory, pwalletIn, _1));
Expand All @@ -32,6 +33,7 @@ void UnregisterValidationInterface(CValidationInterface* pwalletIn) {
g_signals.Inventory.disconnect(boost::bind(&CValidationInterface::Inventory, pwalletIn, _1));
g_signals.SetBestChain.disconnect(boost::bind(&CValidationInterface::SetBestChain, 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.UpdatedBlockTip.disconnect(boost::bind(&CValidationInterface::UpdatedBlockTip, pwalletIn, _1));
}
Expand All @@ -44,6 +46,7 @@ void UnregisterAllValidationInterfaces() {
g_signals.Inventory.disconnect_all_slots();
g_signals.SetBestChain.disconnect_all_slots();
g_signals.UpdatedTransaction.disconnect_all_slots();
g_signals.NotifyTransactionLock.disconnect_all_slots();
g_signals.SyncTransaction.disconnect_all_slots();
g_signals.UpdatedBlockTip.disconnect_all_slots();
}
Expand Down
3 changes: 3 additions & 0 deletions src/validationinterface.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ class CValidationInterface {
protected:
virtual void UpdatedBlockTip(const CBlockIndex *pindex) {}
virtual void SyncTransaction(const CTransaction &tx, const CBlock *pblock) {}
virtual void NotifyTransactionLock(const CTransaction &tx) {}
virtual void SetBestChain(const CBlockLocator &locator) {}
virtual bool UpdatedTransaction(const uint256 &hash) { return false;}
virtual void Inventory(const uint256 &hash) {}
Expand All @@ -50,6 +51,8 @@ struct CMainSignals {
boost::signals2::signal<void (const CBlockIndex *)> UpdatedBlockTip;
/** Notifies listeners of updated transaction data (transaction, and optionally the block it is found in. */
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). */
boost::signals2::signal<bool (const uint256 &)> UpdatedTransaction;
/** Notifies listeners of a new active block chain. */
Expand Down
5 changes: 5 additions & 0 deletions src/zmq/zmqabstractnotifier.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,8 @@ bool CZMQAbstractNotifier::NotifyTransaction(const CTransaction &/*transaction*/
{
return true;
}

bool CZMQAbstractNotifier::NotifyTransactionLock(const CTransaction &/*transaction*/)
{
return true;
}
1 change: 1 addition & 0 deletions src/zmq/zmqabstractnotifier.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ class CZMQAbstractNotifier

virtual bool NotifyBlock(const CBlockIndex *pindex);
virtual bool NotifyTransaction(const CTransaction &transaction);
virtual bool NotifyTransactionLock(const CTransaction &transaction);

protected:
void *psocket;
Expand Down
19 changes: 19 additions & 0 deletions src/zmq/zmqnotificationinterface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,10 @@ CZMQNotificationInterface* CZMQNotificationInterface::CreateWithArguments(const

factories["pubhashblock"] = CZMQAbstractNotifier::Create<CZMQPublishHashBlockNotifier>;
factories["pubhashtx"] = CZMQAbstractNotifier::Create<CZMQPublishHashTransactionNotifier>;
factories["pubhashtxlock"] = CZMQAbstractNotifier::Create<CZMQPublishHashTransactionLockNotifier>;
factories["pubrawblock"] = CZMQAbstractNotifier::Create<CZMQPublishRawBlockNotifier>;
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)
{
Expand Down Expand Up @@ -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);
}
}
}
1 change: 1 addition & 0 deletions src/zmq/zmqnotificationinterface.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ class CZMQNotificationInterface : public CValidationInterface
// CValidationInterface
void SyncTransaction(const CTransaction &tx, const CBlock *pblock);
void UpdatedBlockTip(const CBlockIndex *pindex);
void NotifyTransactionLock(const CTransaction &tx);

private:
CZMQNotificationInterface();
Expand Down
21 changes: 21 additions & 0 deletions src/zmq/zmqpublishnotifier.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,17 @@ bool CZMQPublishHashTransactionNotifier::NotifyTransaction(const CTransaction &t
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)
{
LogPrint("zmq", "zmq: Publish rawblock %s\n", pindex->GetBlockHash().GetHex());
Expand Down Expand Up @@ -170,3 +181,13 @@ bool CZMQPublishRawTransactionNotifier::NotifyTransaction(const CTransaction &tr
int rc = zmq_send_multipart(psocket, "rawtx", 5, &(*ss.begin()), ss.size(), 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;
}
12 changes: 12 additions & 0 deletions src/zmq/zmqpublishnotifier.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,12 @@ class CZMQPublishHashTransactionNotifier : public CZMQAbstractPublishNotifier
bool NotifyTransaction(const CTransaction &transaction);
};

class CZMQPublishHashTransactionLockNotifier : public CZMQAbstractPublishNotifier
{
public:
bool NotifyTransactionLock(const CTransaction &transaction);
};

class CZMQPublishRawBlockNotifier : public CZMQAbstractPublishNotifier
{
public:
Expand All @@ -40,4 +46,10 @@ class CZMQPublishRawTransactionNotifier : public CZMQAbstractPublishNotifier
bool NotifyTransaction(const CTransaction &transaction);
};

class CZMQPublishRawTransactionLockNotifier : public CZMQAbstractPublishNotifier
{
public:
bool NotifyTransactionLock(const CTransaction &transaction);
};

#endif // BITCOIN_ZMQ_ZMQPUBLISHNOTIFIER_H