zmq|validationinterface|llmq: Implement recovered signature notifications (#3803)

* zmq: Add notifier for recovered signatures

* validationinterface: Add and connect NotifyRecoveredSig signal

* llmq: Notify about recovered signatures

* zmq: Reverse byte order of msgHash in NotifyRecoveredSig

* doc: Add hashrecoveredsig and rawrecoveredsig in zmq.md

* init: Add recovered sig options in "ZeroMQ notification" section

* init: LLMQ's -> LLMQs

Co-authored-by: PastaPastaPasta <6443210+PastaPastaPasta@users.noreply.github.com>

Co-authored-by: PastaPastaPasta <6443210+PastaPastaPasta@users.noreply.github.com>
This commit is contained in:
dustinface 2020-11-17 20:41:30 +01:00 committed by GitHub
parent e7c91558d3
commit 7884b62f28
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 74 additions and 2 deletions

View File

@ -63,6 +63,7 @@ Currently, the following notifications are supported:
-zmqpubhashgovernancevote=address
-zmqpubhashgovernanceobject=address
-zmqpubhashinstantsenddoublespend=address
-zmqpubhashrecoveredsig=address
-zmqpubrawblock=address
-zmqpubrawchainlock=address
-zmqpubrawchainlocksig=address
@ -72,6 +73,7 @@ Currently, the following notifications are supported:
-zmqpubrawgovernancevote=address
-zmqpubrawgovernanceobject=address
-zmqpubrawinstantsenddoublespend=address
-zmqpubrawrecoveredsig=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.

View File

@ -553,10 +553,12 @@ std::string HelpMessage(HelpMessageMode mode)
strUsage += HelpMessageOpt("-zmqpubhashgovernanceobject=<address>", _("Enable publish hash of governance objects (like proposals) in <address>"));
strUsage += HelpMessageOpt("-zmqpubhashgovernancevote=<address>", _("Enable publish hash of governance votes in <address>"));
strUsage += HelpMessageOpt("-zmqpubhashinstantsenddoublespend=<address>", _("Enable publish transaction hashes of attempted InstantSend double spend in <address>"));
strUsage += HelpMessageOpt("-zmqpubhashrecoveredsig=<address>", _("Enable publish message hash of recovered signatures (recovered by LLMQs) 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("-zmqpubrawinstantsenddoublespend=<address>", _("Enable publish raw transactions of attempted InstantSend double spend in <address>"));
strUsage += HelpMessageOpt("-zmqpubrawrecoveredsig=<address>", _("Enable publish raw recovered signatures (recovered by LLMQs) 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

View File

@ -737,6 +737,8 @@ void CSigningManager::ProcessRecoveredSig(NodeId nodeId, const CRecoveredSig& re
for (auto& l : listeners) {
l->HandleNewRecoveredSig(recoveredSig);
}
GetMainSignals().NotifyRecoveredSig(recoveredSig);
}
void CSigningManager::PushReconstructedRecoveredSig(const llmq::CRecoveredSig& recoveredSig, const llmq::CQuorumCPtr& quorum)

View File

@ -38,6 +38,7 @@ struct MainSignalsInstance {
boost::signals2::signal<void (const CGovernanceObject &object)>NotifyGovernanceObject;
boost::signals2::signal<void (const CTransaction &currentTx, const CTransaction &previousTx)>NotifyInstantSendDoubleSpendAttempt;
boost::signals2::signal<void (bool undo, const CDeterministicMNList& oldMNList, const CDeterministicMNListDiff& diff)>NotifyMasternodeListChanged;
boost::signals2::signal<void (const llmq::CRecoveredSig& sig)>NotifyRecoveredSig;
// We are not allowed to assume the scheduler only runs in one thread,
// but must ensure all callbacks happen in-order, so we end up creating
// our own queue here :(
@ -99,6 +100,7 @@ void RegisterValidationInterface(CValidationInterface* pwalletIn) {
g_signals.m_internals->NotifyGovernanceObject.connect(boost::bind(&CValidationInterface::NotifyGovernanceObject, pwalletIn, _1));
g_signals.m_internals->NotifyGovernanceVote.connect(boost::bind(&CValidationInterface::NotifyGovernanceVote, pwalletIn, _1));
g_signals.m_internals->NotifyInstantSendDoubleSpendAttempt.connect(boost::bind(&CValidationInterface::NotifyInstantSendDoubleSpendAttempt, pwalletIn, _1, _2));
g_signals.m_internals->NotifyRecoveredSig.connect(boost::bind(&CValidationInterface::NotifyRecoveredSig, pwalletIn, _1));
g_signals.m_internals->NotifyMasternodeListChanged.connect(boost::bind(&CValidationInterface::NotifyMasternodeListChanged, pwalletIn, _1, _2, _3));
}
@ -120,6 +122,7 @@ void UnregisterValidationInterface(CValidationInterface* pwalletIn) {
g_signals.m_internals->NotifyGovernanceObject.disconnect(boost::bind(&CValidationInterface::NotifyGovernanceObject, pwalletIn, _1));
g_signals.m_internals->NotifyGovernanceVote.disconnect(boost::bind(&CValidationInterface::NotifyGovernanceVote, pwalletIn, _1));
g_signals.m_internals->NotifyInstantSendDoubleSpendAttempt.disconnect(boost::bind(&CValidationInterface::NotifyInstantSendDoubleSpendAttempt, pwalletIn, _1, _2));
g_signals.m_internals->NotifyRecoveredSig.disconnect(boost::bind(&CValidationInterface::NotifyRecoveredSig, pwalletIn, _1));
g_signals.m_internals->NotifyMasternodeListChanged.disconnect(boost::bind(&CValidationInterface::NotifyMasternodeListChanged, pwalletIn, _1, _2, _3));
}
@ -144,6 +147,7 @@ void UnregisterAllValidationInterfaces() {
g_signals.m_internals->NotifyGovernanceObject.disconnect_all_slots();
g_signals.m_internals->NotifyGovernanceVote.disconnect_all_slots();
g_signals.m_internals->NotifyInstantSendDoubleSpendAttempt.disconnect_all_slots();
g_signals.m_internals->NotifyRecoveredSig.disconnect_all_slots();
g_signals.m_internals->NotifyMasternodeListChanged.disconnect_all_slots();
}
@ -247,6 +251,10 @@ void CMainSignals::NotifyInstantSendDoubleSpendAttempt(const CTransaction &curre
m_internals->NotifyInstantSendDoubleSpendAttempt(currentTx, previousTx);
}
void CMainSignals::NotifyRecoveredSig(const llmq::CRecoveredSig& sig) {
m_internals->NotifyRecoveredSig(sig);
}
void CMainSignals::NotifyMasternodeListChanged(bool undo, const CDeterministicMNList& oldMNList, const CDeterministicMNListDiff& diff) {
m_internals->NotifyMasternodeListChanged(undo, oldMNList, diff);
}

View File

@ -30,6 +30,7 @@ enum class MemPoolRemovalReason;
namespace llmq {
class CChainLockSig;
class CInstantSendLock;
class CRecoveredSig;
} // namespace llmq
// These functions dispatch to one or all registered wallets
@ -125,6 +126,7 @@ protected:
virtual void NotifyGovernanceVote(const CGovernanceVote &vote) {}
virtual void NotifyGovernanceObject(const CGovernanceObject &object) {}
virtual void NotifyInstantSendDoubleSpendAttempt(const CTransaction &currentTx, const CTransaction &previousTx) {}
virtual void NotifyRecoveredSig(const llmq::CRecoveredSig& sig) {}
virtual void NotifyMasternodeListChanged(bool undo, const CDeterministicMNList& oldMNList, const CDeterministicMNListDiff& diff) {}
/**
* Notifies listeners of the new active block chain on-disk.
@ -189,6 +191,7 @@ public:
void NotifyGovernanceVote(const CGovernanceVote &vote);
void NotifyGovernanceObject(const CGovernanceObject &object);
void NotifyInstantSendDoubleSpendAttempt(const CTransaction &currentTx, const CTransaction &previousTx);
void NotifyRecoveredSig(const llmq::CRecoveredSig &sig);
void NotifyMasternodeListChanged(bool undo, const CDeterministicMNList& oldMNList, const CDeterministicMNListDiff& diff);
void SetBestChain(const CBlockLocator &);
void Broadcast(int64_t nBestBlockTime, CConnman* connman);

View File

@ -45,3 +45,8 @@ bool CZMQAbstractNotifier::NotifyInstantSendDoubleSpendAttempt(const CTransactio
{
return true;
}
bool CZMQAbstractNotifier::NotifyRecoveredSig(const llmq::CRecoveredSig& /*sig*/)
{
return true;
}

View File

@ -15,6 +15,7 @@ class CZMQAbstractNotifier;
namespace llmq {
class CChainLockSig;
class CInstantSendLock;
class CRecoveredSig;
} // namespace llmq
typedef CZMQAbstractNotifier* (*CZMQNotifierFactory)();
@ -46,7 +47,7 @@ public:
virtual bool NotifyGovernanceVote(const CGovernanceVote &vote);
virtual bool NotifyGovernanceObject(const CGovernanceObject &object);
virtual bool NotifyInstantSendDoubleSpendAttempt(const CTransaction &currentTx, const CTransaction &previousTx);
virtual bool NotifyRecoveredSig(const llmq::CRecoveredSig& sig);
protected:
void *psocket;

View File

@ -24,6 +24,7 @@
#include <llmq/quorums_chainlocks.h>
#include <llmq/quorums_instantsend.h>
#include <llmq/quorums_signing.h>
void zmqError(const char *str);

View File

@ -51,6 +51,7 @@ CZMQNotificationInterface* CZMQNotificationInterface::Create()
factories["pubhashgovernancevote"] = CZMQAbstractNotifier::Create<CZMQPublishHashGovernanceVoteNotifier>;
factories["pubhashgovernanceobject"] = CZMQAbstractNotifier::Create<CZMQPublishHashGovernanceObjectNotifier>;
factories["pubhashinstantsenddoublespend"] = CZMQAbstractNotifier::Create<CZMQPublishHashInstantSendDoubleSpendNotifier>;
factories["pubhashrecoveredsig"] = CZMQAbstractNotifier::Create<CZMQPublishHashRecoveredSigNotifier>;
factories["pubrawblock"] = CZMQAbstractNotifier::Create<CZMQPublishRawBlockNotifier>;
factories["pubrawchainlock"] = CZMQAbstractNotifier::Create<CZMQPublishRawChainLockNotifier>;
factories["pubrawchainlocksig"] = CZMQAbstractNotifier::Create<CZMQPublishRawChainLockSigNotifier>;
@ -60,6 +61,7 @@ CZMQNotificationInterface* CZMQNotificationInterface::Create()
factories["pubrawgovernancevote"] = CZMQAbstractNotifier::Create<CZMQPublishRawGovernanceVoteNotifier>;
factories["pubrawgovernanceobject"] = CZMQAbstractNotifier::Create<CZMQPublishRawGovernanceObjectNotifier>;
factories["pubrawinstantsenddoublespend"] = CZMQAbstractNotifier::Create<CZMQPublishRawInstantSendDoubleSpendNotifier>;
factories["pubrawrecoveredsig"] = CZMQAbstractNotifier::Create<CZMQPublishRawRecoveredSigNotifier>;
for (const auto& entry : factories)
{
@ -283,4 +285,17 @@ void CZMQNotificationInterface::NotifyInstantSendDoubleSpendAttempt(const CTrans
}
}
void CZMQNotificationInterface::NotifyRecoveredSig(const llmq::CRecoveredSig& sig)
{
for (auto it = notifiers.begin(); it != notifiers.end();) {
CZMQAbstractNotifier *notifier = *it;
if (notifier->NotifyRecoveredSig(sig)) {
++it;
} else {
notifier->Shutdown();
it = notifiers.erase(it);
}
}
}
CZMQNotificationInterface* g_zmq_notification_interface = nullptr;

View File

@ -36,7 +36,7 @@ protected:
void NotifyGovernanceVote(const CGovernanceVote& vote) override;
void NotifyGovernanceObject(const CGovernanceObject& object) override;
void NotifyInstantSendDoubleSpendAttempt(const CTransaction &currentTx, const CTransaction &previousTx) override;
void NotifyRecoveredSig(const llmq::CRecoveredSig& sig) override;
private:
CZMQNotificationInterface();

View File

@ -18,6 +18,7 @@ static const char *MSG_HASHTXLOCK = "hashtxlock";
static const char *MSG_HASHGVOTE = "hashgovernancevote";
static const char *MSG_HASHGOBJ = "hashgovernanceobject";
static const char *MSG_HASHISCON = "hashinstantsenddoublespend";
static const char *MSG_HASHRECSIG = "hashrecoveredsig";
static const char *MSG_RAWBLOCK = "rawblock";
static const char *MSG_RAWCHAINLOCK = "rawchainlock";
static const char *MSG_RAWCLSIG = "rawchainlocksig";
@ -27,6 +28,7 @@ static const char *MSG_RAWTXLOCKSIG = "rawtxlocksig";
static const char *MSG_RAWGVOTE = "rawgovernancevote";
static const char *MSG_RAWGOBJ = "rawgovernanceobject";
static const char *MSG_RAWISCON = "rawinstantsenddoublespend";
static const char *MSG_RAWRECSIG = "rawrecoveredsig";
// Internal function to send multipart message
static int zmq_send_multipart(void *sock, const void* data, size_t size, ...)
@ -230,6 +232,14 @@ bool CZMQPublishHashInstantSendDoubleSpendNotifier::NotifyInstantSendDoubleSpend
&& SendMessage(MSG_HASHISCON, dataPreviousHash, 32);
}
bool CZMQPublishHashRecoveredSigNotifier::NotifyRecoveredSig(const llmq::CRecoveredSig &sig)
{
LogPrint(BCLog::ZMQ, "zmq: Publish hashrecoveredsig %s\n", sig.msgHash.ToString());
char data[32];
for (unsigned int i = 0; i < 32; i++)
data[31 - i] = sig.msgHash.begin()[i];
return SendMessage(MSG_HASHRECSIG, data, 32);
}
bool CZMQPublishRawBlockNotifier::NotifyBlock(const CBlockIndex *pindex)
{
@ -350,3 +360,14 @@ bool CZMQPublishRawInstantSendDoubleSpendNotifier::NotifyInstantSendDoubleSpendA
return SendMessage(MSG_RAWISCON, &(*ssCurrent.begin()), ssCurrent.size())
&& SendMessage(MSG_RAWISCON, &(*ssPrevious.begin()), ssPrevious.size());
}
bool CZMQPublishRawRecoveredSigNotifier::NotifyRecoveredSig(const llmq::CRecoveredSig& sig)
{
LogPrint(BCLog::ZMQ, "zmq: Publish rawrecoveredsig %s\n", sig.msgHash.ToString());
CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
ss << sig;
return SendMessage(MSG_RAWRECSIG, &(*ss.begin()), ss.size());
}

View File

@ -72,6 +72,12 @@ public:
bool NotifyInstantSendDoubleSpendAttempt(const CTransaction &currentTx, const CTransaction &previousTx) override;
};
class CZMQPublishHashRecoveredSigNotifier : public CZMQAbstractPublishNotifier
{
public:
bool NotifyRecoveredSig(const llmq::CRecoveredSig&) override;
};
class CZMQPublishRawBlockNotifier : public CZMQAbstractPublishNotifier
{
public:
@ -125,4 +131,10 @@ class CZMQPublishRawInstantSendDoubleSpendNotifier : public CZMQAbstractPublishN
public:
bool NotifyInstantSendDoubleSpendAttempt(const CTransaction &currentTx, const CTransaction &previousTx) override;
};
class CZMQPublishRawRecoveredSigNotifier : public CZMQAbstractPublishNotifier
{
public:
bool NotifyRecoveredSig(const llmq::CRecoveredSig &sig) override;
};
#endif // BITCOIN_ZMQ_ZMQPUBLISHNOTIFIER_H