Skip to content

Commit 87b2e47

Browse files
UdjinM6claude
authored andcommitted
refactor: extract validation logic and add proper unit tests
Extract the pure validation logic from PreVerifyBatchedSigShares into a new ValidateBatchedSigSharesStructure function that can be properly unit tested without external dependencies. Changes: - Add ValidateBatchedSigSharesStructure() - validates duplicates, bounds, and member validity without requiring IsQuorumActive, IsMember, or HasVerificationVector - Refactor PreVerifyBatchedSigShares() to use the extracted function - Rewrite unit tests to actually test the extracted function instead of reimplementing the logic manually Test coverage (14 tests, all passing): - Result structure tests (3): success, ban errors, non-ban errors - Validation logic tests (11): success case, empty batch, duplicate detection, bounds checking, member validity, error priority These tests provide real value by exercising the actual validation code and will catch regressions. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
1 parent 5defa8d commit 87b2e47

File tree

3 files changed

+232
-252
lines changed

3 files changed

+232
-252
lines changed

src/llmq/signing_shares.cpp

Lines changed: 23 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -551,6 +551,28 @@ void CSigSharesManager::ProcessMessageSigShare(NodeId fromId, const CSigShare& s
551551
signHash.ToString(), sigShare.getId().ToString(), sigShare.getMsgHash().ToString(), sigShare.getQuorumMember(), fromId);
552552
}
553553

554+
PreVerifyBatchedResult CSigSharesManager::ValidateBatchedSigSharesStructure(const CQuorum& quorum,
555+
const CBatchedSigShares& batchedSigShares)
556+
{
557+
std::unordered_set<uint16_t> dupMembers;
558+
559+
for (const auto& [quorumMember, _] : batchedSigShares.sigShares) {
560+
if (!dupMembers.emplace(quorumMember).second) {
561+
return {PreVerifyResult::DuplicateMember, true};
562+
}
563+
564+
if (quorumMember >= quorum.members.size()) {
565+
LogPrint(BCLog::LLMQ_SIGS, "CSigSharesManager::%s -- quorumMember out of bounds\n", __func__);
566+
return {PreVerifyResult::QuorumMemberOutOfBounds, true};
567+
}
568+
if (!quorum.qc->validMembers[quorumMember]) {
569+
LogPrint(BCLog::LLMQ_SIGS, "CSigSharesManager::%s -- quorumMember not valid\n", __func__);
570+
return {PreVerifyResult::QuorumMemberNotValid, true};
571+
}
572+
}
573+
return {PreVerifyResult::Success, false};
574+
}
575+
554576
PreVerifyBatchedResult CSigSharesManager::PreVerifyBatchedSigShares(const CActiveMasternodeManager& mn_activeman,
555577
const CQuorumManager& quorum_manager,
556578
const CSigSharesNodeState::SessionInfo& session,
@@ -571,23 +593,7 @@ PreVerifyBatchedResult CSigSharesManager::PreVerifyBatchedSigShares(const CActiv
571593
return {PreVerifyResult::MissingVerificationVector, false};
572594
}
573595

574-
std::unordered_set<uint16_t> dupMembers;
575-
576-
for (const auto& [quorumMember, _] : batchedSigShares.sigShares) {
577-
if (!dupMembers.emplace(quorumMember).second) {
578-
return {PreVerifyResult::DuplicateMember, true};
579-
}
580-
581-
if (quorumMember >= session.quorum->members.size()) {
582-
LogPrint(BCLog::LLMQ_SIGS, "CSigSharesManager::%s -- quorumMember out of bounds\n", __func__);
583-
return {PreVerifyResult::QuorumMemberOutOfBounds, true};
584-
}
585-
if (!session.quorum->qc->validMembers[quorumMember]) {
586-
LogPrint(BCLog::LLMQ_SIGS, "CSigSharesManager::%s -- quorumMember not valid\n", __func__);
587-
return {PreVerifyResult::QuorumMemberNotValid, true};
588-
}
589-
}
590-
return {PreVerifyResult::Success, false};
596+
return ValidateBatchedSigSharesStructure(*session.quorum, batchedSigShares);
591597
}
592598

593599
bool CSigSharesManager::CollectPendingSigSharesToVerify(

src/llmq/signing_shares.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -478,6 +478,11 @@ class CSigSharesManager : public llmq::CRecoveredSigsListener
478478
const CSigSharesNodeState::SessionInfo& session,
479479
const CBatchedSigShares& batchedSigShares);
480480

481+
// Validates the structure of batched sig shares (duplicates, bounds, member validity)
482+
// This is extracted for testability - it's the pure validation logic without external dependencies
483+
static PreVerifyBatchedResult ValidateBatchedSigSharesStructure(const CQuorum& quorum,
484+
const CBatchedSigShares& batchedSigShares);
485+
481486
private:
482487
std::optional<CSigShare> CreateSigShareForSingleMember(const CQuorum& quorum, const uint256& id, const uint256& msgHash) const;
483488

0 commit comments

Comments
 (0)