-
Notifications
You must be signed in to change notification settings - Fork 1.2k
refactor: introduce SignHash type for improved type safety in LLMQ signing #6826
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
Changes from 2 commits
0465463
f446223
ac9e5b7
b34fd1b
fd6ad86
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -9,6 +9,7 @@ | |||||
| #include <evo/specialtx.h> | ||||||
| #include <llmq/commitment.h> | ||||||
| #include <llmq/quorums.h> | ||||||
| #include <llmq/signhash.h> | ||||||
| #include <llmq/signing.h> | ||||||
| #include <node/blockstorage.h> | ||||||
|
|
||||||
|
|
@@ -102,8 +103,8 @@ bool MNHFTx::Verify(const llmq::CQuorumManager& qman, const uint256& quorumHash, | |||||
| return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-mnhf-missing-quorum"); | ||||||
| } | ||||||
|
|
||||||
| const uint256 signHash = llmq::BuildSignHash(llmqType, quorum->qc->quorumHash, requestId, msgHash); | ||||||
| if (!sig.VerifyInsecure(quorum->qc->quorumPublicKey, signHash)) { | ||||||
| const llmq::SignHash signHash(llmqType, quorum->qc->quorumHash, requestId, msgHash); | ||||||
|
||||||
| const llmq::SignHash signHash(llmqType, quorum->qc->quorumHash, requestId, msgHash); | |
| const llmq::SignHash signHash{llmqType, quorum->qc->quorumHash, requestId, msgHash}; |
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -17,6 +17,7 @@ | |||||
| #include <instantsend/signing.h> | ||||||
| #include <llmq/commitment.h> | ||||||
| #include <llmq/quorums.h> | ||||||
| #include <llmq/signhash.h> | ||||||
| #include <masternode/sync.h> | ||||||
| #include <spork.h> | ||||||
| #include <stats/client.h> | ||||||
|
|
@@ -285,7 +286,7 @@ std::unordered_set<uint256, StaticSaltedHasher> CInstantSendManager::ProcessPend | |||||
| // should not happen, but if one fails to select, all others will also fail to select | ||||||
| return {}; | ||||||
| } | ||||||
| uint256 signHash = BuildSignHash(llmq_params.type, quorum->qc->quorumHash, id, islock->txid); | ||||||
| uint256 signHash = llmq::SignHash(llmq_params.type, quorum->qc->quorumHash, id, islock->txid).Get(); | ||||||
|
||||||
| uint256 signHash = llmq::SignHash(llmq_params.type, quorum->qc->quorumHash, id, islock->txid).Get(); | |
| uint256 signHash = llmq::SignHash{llmq_params.type, quorum->qc->quorumHash, id, islock->txid}.Get(); |
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -8,6 +8,7 @@ | |||||
| #include <llmq/dkgsessionmgr.h> | ||||||
| #include <llmq/options.h> | ||||||
| #include <llmq/params.h> | ||||||
| #include <llmq/signhash.h> | ||||||
| #include <llmq/utils.h> | ||||||
|
|
||||||
| #include <bls/bls.h> | ||||||
|
|
@@ -36,8 +37,6 @@ static const std::string DB_QUORUM_QUORUM_VVEC = "q_Qqvvec"; | |||||
| RecursiveMutex cs_data_requests; | ||||||
| static std::unordered_map<CQuorumDataRequestKey, CQuorumDataRequest, StaticSaltedHasher> mapQuorumDataRequests GUARDED_BY(cs_data_requests); | ||||||
|
|
||||||
| // forward declaration to avoid circular dependency | ||||||
| uint256 BuildSignHash(Consensus::LLMQType llmqType, const uint256& quorumHash, const uint256& id, const uint256& msgHash); | ||||||
|
|
||||||
| static uint256 MakeQuorumKey(const CQuorum& q) | ||||||
| { | ||||||
|
|
@@ -1279,8 +1278,8 @@ VerifyRecSigStatus VerifyRecoveredSig(Consensus::LLMQType llmqType, const CChain | |||||
| return VerifyRecSigStatus::NoQuorum; | ||||||
| } | ||||||
|
|
||||||
| uint256 signHash = BuildSignHash(llmqType, quorum->qc->quorumHash, id, msgHash); | ||||||
| const bool ret = sig.VerifyInsecure(quorum->qc->quorumPublicKey, signHash); | ||||||
| SignHash signHash(llmqType, quorum->qc->quorumHash, id, msgHash); | ||||||
|
||||||
| SignHash signHash(llmqType, quorum->qc->quorumHash, id, msgHash); | |
| SignHash signHash{llmqType, quorum->qc->quorumHash, id, msgHash}; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,25 @@ | ||
| // Copyright (c) 2025 The Dash Core developers | ||
| // Distributed under the MIT software license, see the accompanying | ||
| // file COPYING or http://www.opensource.org/licenses/mit-license.php. | ||
|
|
||
| #include <llmq/signhash.h> | ||
|
|
||
| #include <hash.h> | ||
| #include <serialize.h> | ||
|
|
||
| #include <vector> | ||
|
|
||
| namespace llmq | ||
| { | ||
|
|
||
| SignHash::SignHash(Consensus::LLMQType llmqType, const uint256& quorumHash, const uint256& id, const uint256& msgHash) | ||
| { | ||
| CHashWriter h(SER_GETHASH, 0); | ||
| h << llmqType; | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Ensure deterministic encoding of enum; drop unused include.
Apply: -#include <vector>
@@
- h << llmqType;
+ h << static_cast<uint8_t>(llmqType);Also applies to: 10-10 🤖 Prompt for AI Agents |
||
| h << quorumHash; | ||
| h << id; | ||
| h << msgHash; | ||
| m_hash = h.GetHash(); | ||
| } | ||
|
|
||
| } // namespace llmq | ||
|
||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,67 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Copyright (c) 2025 The Dash Core developers | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Distributed under the MIT software license, see the accompanying | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // file COPYING or http://www.opensource.org/licenses/mit-license.php. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| #ifndef BITCOIN_LLMQ_SIGNHASH_H | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| #define BITCOIN_LLMQ_SIGNHASH_H | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| #include <llmq/params.h> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| #include <uint256.h> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| #include <cstring> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| #include <vector> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| #include <util/hash_type.h> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| namespace llmq | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /** | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * SignHash is a strongly-typed wrapper for the hash used in LLMQ signing operations. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * It encapsulates the hash calculation for quorum signatures, replacing the need for | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * BuildSignHash function and avoiding circular dependencies. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| */ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| class SignHash : public BaseHash<uint256> { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| public: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| SignHash() = default; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /** | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * Constructs a SignHash from the given parameters. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * This replaces the previous BuildSignHash function. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| */ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| SignHash(Consensus::LLMQType llmqType, const uint256& quorumHash, const uint256& id, const uint256& msgHash); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /** | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * Get the underlying uint256 hash value. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| */ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const uint256& Get() const { return m_hash; } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| class SignHash : public BaseHash<uint256> { | |
| public: | |
| SignHash() = default; | |
| /** | |
| * Constructs a SignHash from the given parameters. | |
| * This replaces the previous BuildSignHash function. | |
| */ | |
| SignHash(Consensus::LLMQType llmqType, const uint256& quorumHash, const uint256& id, const uint256& msgHash); | |
| /** | |
| * Get the underlying uint256 hash value. | |
| */ | |
| const uint256& Get() const { return m_hash; } | |
| #include <consensus/llmq_types.h> | |
| #include <uint256.h> | |
| #include <cstring> | |
| #include <cstdint> | |
| #include <functional> | |
| #include <util/hash_type.h> | |
| namespace llmq { | |
| class SignHash : public BaseHash<SignHash> { | |
| public: | |
| SignHash() = default; | |
| /** | |
| * Constructs a SignHash from the given parameters. | |
| * This replaces the previous BuildSignHash function. | |
| */ | |
| explicit SignHash(Consensus::LLMQType llmqType, const uint256& quorumHash, const uint256& id, const uint256& msgHash); | |
| /** | |
| * Get the underlying uint256 hash value. | |
| */ | |
| const uint256& Get() const { return m_hash; } |
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: \n here too
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -6,6 +6,7 @@ | |
|
|
||
| #include <llmq/commitment.h> | ||
| #include <llmq/quorums.h> | ||
| #include <llmq/signhash.h> | ||
| #include <llmq/signing_shares.h> | ||
|
|
||
| #include <bls/bls_batchverifier.h> | ||
|
|
@@ -161,7 +162,7 @@ void CRecoveredSigsDb::WriteRecoveredSig(const llmq::CRecoveredSig& recSig) | |
|
|
||
| // store by signHash | ||
| auto signHash = recSig.buildSignHash(); | ||
| auto k4 = std::make_tuple(std::string("rs_s"), signHash); | ||
| auto k4 = std::make_tuple(std::string("rs_s"), signHash.Get()); | ||
| batch.Write(k4, (uint8_t)1); | ||
|
|
||
| // store by current time. Allows fast cleanup of old recSigs | ||
|
|
@@ -173,7 +174,7 @@ void CRecoveredSigsDb::WriteRecoveredSig(const llmq::CRecoveredSig& recSig) | |
| { | ||
| LOCK(cs_cache); | ||
| hasSigForIdCache.insert(std::make_pair(recSig.getLlmqType(), recSig.getId()), true); | ||
| hasSigForSessionCache.insert(signHash, true); | ||
| hasSigForSessionCache.insert(signHash.Get(), true); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. consider further refactoring by using |
||
| hasSigForHashCache.insert(recSig.GetHash(), true); | ||
| } | ||
| } | ||
|
|
@@ -211,7 +212,7 @@ void CRecoveredSigsDb::RemoveRecoveredSig(CDBBatch& batch, Consensus::LLMQType l | |
|
|
||
| LOCK(cs_cache); | ||
| hasSigForIdCache.erase(std::make_pair(recSig.getLlmqType(), recSig.getId())); | ||
| hasSigForSessionCache.erase(signHash); | ||
| hasSigForSessionCache.erase(signHash.Get()); | ||
| if (deleteHashKey) { | ||
| hasSigForHashCache.erase(recSig.GetHash()); | ||
| } | ||
|
|
@@ -469,7 +470,7 @@ void CSigningManager::CollectPendingRecoveredSigsToVerify( | |
|
|
||
| bool alreadyHave = db.HasRecoveredSigForHash(recSig->GetHash()); | ||
| if (!alreadyHave) { | ||
| uniqueSignHashes.emplace(nodeId, recSig->buildSignHash()); | ||
| uniqueSignHashes.emplace(nodeId, recSig->buildSignHash().Get()); | ||
| retSigShares[nodeId].emplace_back(recSig); | ||
| } | ||
| ns.erase(ns.begin()); | ||
|
|
@@ -553,7 +554,7 @@ bool CSigningManager::ProcessPendingRecoveredSigs(PeerManager& peerman) | |
| } | ||
|
|
||
| const auto& quorum = quorums.at(std::make_pair(recSig->getLlmqType(), recSig->getQuorumHash())); | ||
| batchVerifier.PushMessage(nodeId, recSig->GetHash(), recSig->buildSignHash(), recSig->sig.Get(), quorum->qc->quorumPublicKey); | ||
| batchVerifier.PushMessage(nodeId, recSig->GetHash(), recSig->buildSignHash().Get(), recSig->sig.Get(), quorum->qc->quorumPublicKey); | ||
| verifyCount++; | ||
| } | ||
| } | ||
|
|
@@ -605,7 +606,7 @@ void CSigningManager::ProcessRecoveredSig(const std::shared_ptr<const CRecovered | |
| CRecoveredSig otherRecoveredSig; | ||
| if (db.GetRecoveredSigById(llmqType, recoveredSig->getId(), otherRecoveredSig)) { | ||
| auto otherSignHash = otherRecoveredSig.buildSignHash(); | ||
| if (signHash != otherSignHash) { | ||
| if (signHash.Get() != otherSignHash.Get()) { | ||
| // this should really not happen, as each masternode is participating in only one vote, | ||
| // even if it's a member of multiple quorums. so a majority is only possible on one quorum and one msgHash per id | ||
| LogPrintf("CSigningManager::%s -- conflicting recoveredSig for signHash=%s, id=%s, msgHash=%s, otherSignHash=%s\n", __func__, | ||
|
|
@@ -836,20 +837,11 @@ void CSigningManager::WorkThreadMain(PeerManager& peerman) | |
| } | ||
| } | ||
|
|
||
| uint256 CSigBase::buildSignHash() const | ||
| SignHash CSigBase::buildSignHash() const | ||
| { | ||
| return BuildSignHash(llmqType, quorumHash, id, msgHash); | ||
| return SignHash(llmqType, quorumHash, id, msgHash); | ||
| } | ||
|
|
||
| uint256 BuildSignHash(Consensus::LLMQType llmqType, const uint256& quorumHash, const uint256& id, const uint256& msgHash) | ||
| { | ||
| CHashWriter h(SER_GETHASH, 0); | ||
| h << llmqType; | ||
| h << quorumHash; | ||
| h << id; | ||
| h << msgHash; | ||
| return h.GetHash(); | ||
| } | ||
|
|
||
| bool IsQuorumActive(Consensus::LLMQType llmqType, const CQuorumManager& qman, const uint256& quorumHash) | ||
| { | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.