-
Notifications
You must be signed in to change notification settings - Fork 1.2k
perf: using asynchronous worker to validate BLS signatures in quorum commitments #6692
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 all commits
76e4e72
0f3a8e4
7a86e19
8530c92
2d4fe1b
43ed80d
7733740
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 | ||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -12,6 +12,7 @@ | |||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| #include <chain.h> | ||||||||||||||||||||||||||||||||||||||
| #include <chainparams.h> | ||||||||||||||||||||||||||||||||||||||
| #include <checkqueue.h> | ||||||||||||||||||||||||||||||||||||||
| #include <consensus/params.h> | ||||||||||||||||||||||||||||||||||||||
| #include <consensus/validation.h> | ||||||||||||||||||||||||||||||||||||||
| #include <deploymentstatus.h> | ||||||||||||||||||||||||||||||||||||||
|
|
@@ -52,8 +53,25 @@ CQuorumBlockProcessor::CQuorumBlockProcessor(CChainState& chainstate, CDetermini | |||||||||||||||||||||||||||||||||||||
| m_qsnapman(qsnapman) | ||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||
| utils::InitQuorumsCache(mapHasMinedCommitmentCache); | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| int bls_threads = gArgs.GetIntArg("-parbls", DEFAULT_BLSCHECK_THREADS); | ||||||||||||||||||||||||||||||||||||||
| if (bls_threads <= 0) { | ||||||||||||||||||||||||||||||||||||||
| // -parbls=0 means autodetect (number of cores - 1 validator threads) | ||||||||||||||||||||||||||||||||||||||
| // -parbls=-n means "leave n cores free" (number of cores - n - 1 validator threads) | ||||||||||||||||||||||||||||||||||||||
| bls_threads += GetNumCores(); | ||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
| // Subtract 1 because the main thread counts towards the par threads | ||||||||||||||||||||||||||||||||||||||
| bls_threads = std::max(bls_threads - 1, 0); | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| // Number of script-checking threads <= MAX_BLSCHECK_THREADS | ||||||||||||||||||||||||||||||||||||||
| bls_threads = std::min(bls_threads, MAX_BLSCHECK_THREADS); | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| LogPrintf("BLS verification uses %d additional threads\n", bls_threads); | ||||||||||||||||||||||||||||||||||||||
| m_bls_queue.StartWorkerThreads(bls_threads); | ||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| CQuorumBlockProcessor::~CQuorumBlockProcessor() { m_bls_queue.StopWorkerThreads(); } | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| MessageProcessingResult CQuorumBlockProcessor::ProcessMessage(const CNode& peer, std::string_view msg_type, | ||||||||||||||||||||||||||||||||||||||
| CDataStream& vRecv) | ||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||
|
|
@@ -196,8 +214,21 @@ bool CQuorumBlockProcessor::ProcessBlock(const CBlock& block, gsl::not_null<cons | |||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| if (fBLSChecks) { | ||||||||||||||||||||||||||||||||||||||
| CCheckQueueControl<utils::BlsCheck> queue_control(&m_bls_queue); | ||||||||||||||||||||||||||||||||||||||
| for (const auto& [_, qc] : qcs) { | ||||||||||||||||||||||||||||||||||||||
| if (qc.IsNull()) continue; | ||||||||||||||||||||||||||||||||||||||
| const auto* pQuorumBaseBlockIndex = m_chainstate.m_blockman.LookupBlockIndex(qc.quorumHash); | ||||||||||||||||||||||||||||||||||||||
| qc.VerifySignatureAsync(m_dmnman, m_qsnapman, pQuorumBaseBlockIndex, &queue_control); | ||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
|
Comment on lines
217
to
224
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. Potential null dereference: LookupBlockIndex may return nullptr but is passed to gsl::not_null In ProcessBlock() you call VerifySignatureAsync with pQuorumBaseBlockIndex constructed from LookupBlockIndex(qc.quorumHash). If LookupBlockIndex returns nullptr, constructing gsl::not_null inside VerifySignatureAsync is UB/assert-failing. This can happen before structural verification when processing untrusted blocks. Skip queueing the check when the index isn’t found (it will be rejected later in ProcessCommitment), or invalidate the block immediately. - for (const auto& [_, qc] : qcs) {
+ for (const auto& [_, qc] : qcs) {
if (qc.IsNull()) continue;
const auto* pQuorumBaseBlockIndex = m_chainstate.m_blockman.LookupBlockIndex(qc.quorumHash);
- qc.VerifySignatureAsync(m_dmnman, m_qsnapman, pQuorumBaseBlockIndex, &queue_control);
+ if (!pQuorumBaseBlockIndex) {
+ // Defer to ProcessCommitment() for full validation; avoid passing nullptr to gsl::not_null
+ continue;
+ }
+ qc.VerifySignatureAsync(m_dmnman, m_qsnapman, pQuorumBaseBlockIndex, &queue_control);
}Alternatively (stricter): return state.Invalid(BlockValidationResult::BLOCK_CONSENSUS, "bad-qc-quorum-hash") here. 📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents
Collaborator
Author
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. addressed in follow-up #6789, it's copy-paste code and out-of-scope to fix 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. @knst, thank you for the quick response and for being proactive in creating PR #6789 to address this issue. I understand that keeping the current PR focused on the BLS signature validation performance improvements makes sense to avoid scope creep, especially when dealing with existing code patterns. Your approach of handling this in a separate follow-up PR is consistent with good engineering practices for maintaining focused changes. ✏️ Learnings added
🧠 Learnings used |
||||||||||||||||||||||||||||||||||||||
| if (!queue_control.Wait()) { | ||||||||||||||||||||||||||||||||||||||
| // at least one check failed | ||||||||||||||||||||||||||||||||||||||
| return state.Invalid(BlockValidationResult::BLOCK_CONSENSUS, "bad-qc-invalid"); | ||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
|
Comment on lines
225
to
228
Member
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.
Suggested change
Collaborator
Author
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. duplicated log, see: https://github.com/dashpay/dash/pull/6692/files#diff-cf3d9716cca5e57a6033574399f5be8a184f017da2c02c414ae2771c101a2339R952
Member
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. What is that log? Seems very non-clear / non-detailed
Collaborator
Author
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. See a caller, which create an object of BlsCheck: So, there will be |
||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
| for (const auto& [_, qc] : qcs) { | ||||||||||||||||||||||||||||||||||||||
| if (!ProcessCommitment(pindex->nHeight, blockHash, qc, state, fJustCheck, fBLSChecks)) { | ||||||||||||||||||||||||||||||||||||||
| if (!ProcessCommitment(pindex->nHeight, blockHash, qc, state, fJustCheck)) { | ||||||||||||||||||||||||||||||||||||||
| LogPrintf("[ProcessBlock] failed h[%d] llmqType[%d] version[%d] quorumIndex[%d] quorumHash[%s]\n", pindex->nHeight, ToUnderlying(qc.llmqType), qc.nVersion, qc.quorumIndex, qc.quorumHash.ToString()); | ||||||||||||||||||||||||||||||||||||||
| return false; | ||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
|
|
@@ -237,7 +268,8 @@ static bool IsMiningPhase(const Consensus::LLMQParams& llmqParams, const CChain& | |||||||||||||||||||||||||||||||||||||
| return nHeight >= quorumCycleMiningStartHeight && nHeight <= quorumCycleMiningEndHeight; | ||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| bool CQuorumBlockProcessor::ProcessCommitment(int nHeight, const uint256& blockHash, const CFinalCommitment& qc, BlockValidationState& state, bool fJustCheck, bool fBLSChecks) | ||||||||||||||||||||||||||||||||||||||
| bool CQuorumBlockProcessor::ProcessCommitment(int nHeight, const uint256& blockHash, const CFinalCommitment& qc, | ||||||||||||||||||||||||||||||||||||||
| BlockValidationState& state, bool fJustCheck) | ||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||
| AssertLockHeld(::cs_main); | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
|
|
@@ -303,7 +335,8 @@ bool CQuorumBlockProcessor::ProcessCommitment(int nHeight, const uint256& blockH | |||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| const auto* pQuorumBaseBlockIndex = m_chainstate.m_blockman.LookupBlockIndex(qc.quorumHash); | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| if (!qc.Verify(m_dmnman, m_qsnapman, pQuorumBaseBlockIndex, /*checkSigs=*/fBLSChecks)) { | ||||||||||||||||||||||||||||||||||||||
| // we don't validate signatures here; they already validated on previous step | ||||||||||||||||||||||||||||||||||||||
| if (!qc.Verify(m_dmnman, m_qsnapman, pQuorumBaseBlockIndex, /*checksigs=*/false)) { | ||||||||||||||||||||||||||||||||||||||
| LogPrint(BCLog::LLMQ, /* Continued */ | ||||||||||||||||||||||||||||||||||||||
| "%s -- height=%d, type=%d, quorumIndex=%d, quorumHash=%s, signers=%s, validMembers=%d, " | ||||||||||||||||||||||||||||||||||||||
| "quorumPublicKey=%s qc verify failed.\n", | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -8,13 +8,14 @@ | |||||||||||||||||||||||||||||||||||
| #include <evo/specialtx.h> | ||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
| #include <chainparams.h> | ||||||||||||||||||||||||||||||||||||
| #include <checkqueue.h> | ||||||||||||||||||||||||||||||||||||
| #include <consensus/validation.h> | ||||||||||||||||||||||||||||||||||||
| #include <deploymentstatus.h> | ||||||||||||||||||||||||||||||||||||
| #include <llmq/options.h> | ||||||||||||||||||||||||||||||||||||
| #include <llmq/utils.h> | ||||||||||||||||||||||||||||||||||||
| #include <logging.h> | ||||||||||||||||||||||||||||||||||||
| #include <validation.h> | ||||||||||||||||||||||||||||||||||||
| #include <util/underlying.h> | ||||||||||||||||||||||||||||||||||||
| #include <validation.h> | ||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
| namespace llmq | ||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||
|
|
@@ -27,6 +28,73 @@ CFinalCommitment::CFinalCommitment(const Consensus::LLMQParams& params, const ui | |||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
| bool CFinalCommitment::VerifySignatureAsync(CDeterministicMNManager& dmnman, CQuorumSnapshotManager& qsnapman, | ||||||||||||||||||||||||||||||||||||
| gsl::not_null<const CBlockIndex*> pQuorumBaseBlockIndex, | ||||||||||||||||||||||||||||||||||||
| CCheckQueueControl<utils::BlsCheck>* queue_control) const | ||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||
| auto members = utils::GetAllQuorumMembers(llmqType, dmnman, qsnapman, pQuorumBaseBlockIndex); | ||||||||||||||||||||||||||||||||||||
| const auto& llmq_params_opt = Params().GetLLMQ(llmqType); | ||||||||||||||||||||||||||||||||||||
| if (!llmq_params_opt.has_value()) { | ||||||||||||||||||||||||||||||||||||
| LogPrint(BCLog::LLMQ, "CFinalCommitment -- q[%s] invalid llmqType=%d\n", quorumHash.ToString(), | ||||||||||||||||||||||||||||||||||||
| ToUnderlying(llmqType)); | ||||||||||||||||||||||||||||||||||||
| return false; | ||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||
| const auto& llmq_params = llmq_params_opt.value(); | ||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
| uint256 commitmentHash = BuildCommitmentHash(llmq_params.type, quorumHash, validMembers, quorumPublicKey, | ||||||||||||||||||||||||||||||||||||
| quorumVvecHash); | ||||||||||||||||||||||||||||||||||||
| if (LogAcceptDebug(BCLog::LLMQ)) { | ||||||||||||||||||||||||||||||||||||
| std::stringstream ss3; | ||||||||||||||||||||||||||||||||||||
| for (const auto& mn : members) { | ||||||||||||||||||||||||||||||||||||
| ss3 << mn->proTxHash.ToString().substr(0, 4) << " | "; | ||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||
| LogPrint(BCLog::LLMQ, "CFinalCommitment::%s members[%s] quorumPublicKey[%s] commitmentHash[%s]\n", __func__, | ||||||||||||||||||||||||||||||||||||
| ss3.str(), quorumPublicKey.ToString(), commitmentHash.ToString()); | ||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||
| if (llmq_params.size == 1) { | ||||||||||||||||||||||||||||||||||||
| LogPrintf("pubkey operator: %s\n", members[0]->pdmnState->pubKeyOperator.Get().ToString()); | ||||||||||||||||||||||||||||||||||||
| if (!membersSig.VerifyInsecure(members[0]->pdmnState->pubKeyOperator.Get(), commitmentHash)) { | ||||||||||||||||||||||||||||||||||||
| LogPrint(BCLog::LLMQ, "CFinalCommitment -- q[%s] invalid member signature\n", quorumHash.ToString()); | ||||||||||||||||||||||||||||||||||||
| return false; | ||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||
| } else { | ||||||||||||||||||||||||||||||||||||
|
Comment on lines
54
to
60
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 Guard against out-of-bounds access and remove noisy log
Apply this diff to make the path safe and quiet: - if (llmq_params.size == 1) {
- LogPrintf("pubkey operator: %s\n", members[0]->pdmnState->pubKeyOperator.Get().ToString());
- if (!membersSig.VerifyInsecure(members[0]->pdmnState->pubKeyOperator.Get(), commitmentHash)) {
+ if (llmq_params.size == 1) {
+ if (members.empty()) {
+ LogPrint(BCLog::LLMQ, "CFinalCommitment -- q[%s] missing quorum members for size=1\n", quorumHash.ToString());
+ return false;
+ }
+ if (!membersSig.VerifyInsecure(members[0]->pdmnState->pubKeyOperator.Get(), commitmentHash)) {
LogPrint(BCLog::LLMQ, "CFinalCommitment -- q[%s] invalid member signature\n", quorumHash.ToString());
return false;
}
} else {📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents
Collaborator
Author
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. I can't think of case when members.empty(). Anyway, llmq_params.size == 1 is used for regtest only, won't cause any public-net failure 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. @knst, thank you for the context! You're absolutely right that if Given your domain expertise, I trust your assessment about when However, what about the I understand if you prefer to keep the scope focused on the main performance improvements rather than these edge cases. 🐰💭 Contemplating the balance between defensive programming and practical risk assessment... ✏️ Learnings added
🧠 Learnings used |
||||||||||||||||||||||||||||||||||||
| std::vector<CBLSPublicKey> memberPubKeys; | ||||||||||||||||||||||||||||||||||||
| for (const auto i : irange::range(members.size())) { | ||||||||||||||||||||||||||||||||||||
| if (!signers[i]) { | ||||||||||||||||||||||||||||||||||||
| continue; | ||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||
| memberPubKeys.emplace_back(members[i]->pdmnState->pubKeyOperator.Get()); | ||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||
|
Comment on lines
61
to
67
Member
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. we should probably reserve here; we know that for a qc to be valid, we need at least 80% (llmq_50_60 has minsize 40). As such, we can pretty safely reserve the entire size. For the LLMQ_400 this may reduce the number of allocations from ~10-ish reallocations to just a single one.
Collaborator
Author
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. Please notice, that this code is not new,but moved in commit 219f223e983bb50d4e39e771c35a6625544cfb6b I may implement this optimization in follow-up PR |
||||||||||||||||||||||||||||||||||||
| std::string members_id_string{ | ||||||||||||||||||||||||||||||||||||
| strprintf("CFinalCommitment -- q[%s] invalid aggregated members signature", quorumHash.ToString())}; | ||||||||||||||||||||||||||||||||||||
| if (queue_control) { | ||||||||||||||||||||||||||||||||||||
| std::vector<utils::BlsCheck> vChecks; | ||||||||||||||||||||||||||||||||||||
| vChecks.emplace_back(membersSig, memberPubKeys, commitmentHash, members_id_string); | ||||||||||||||||||||||||||||||||||||
| queue_control->Add(vChecks); | ||||||||||||||||||||||||||||||||||||
| } else { | ||||||||||||||||||||||||||||||||||||
| if (!membersSig.VerifySecureAggregated(memberPubKeys, commitmentHash)) { | ||||||||||||||||||||||||||||||||||||
| LogPrint(BCLog::LLMQ, "%s\n", members_id_string); | ||||||||||||||||||||||||||||||||||||
| return false; | ||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||
| std::string qsig_id_string{strprintf("CFinalCommitment -- q[%s] invalid quorum signature", quorumHash.ToString())}; | ||||||||||||||||||||||||||||||||||||
| if (queue_control) { | ||||||||||||||||||||||||||||||||||||
| std::vector<utils::BlsCheck> vChecks; | ||||||||||||||||||||||||||||||||||||
| std::vector<CBLSPublicKey> public_keys; | ||||||||||||||||||||||||||||||||||||
| public_keys.push_back(quorumPublicKey); | ||||||||||||||||||||||||||||||||||||
| vChecks.emplace_back(quorumSig, public_keys, commitmentHash, qsig_id_string); | ||||||||||||||||||||||||||||||||||||
| queue_control->Add(vChecks); | ||||||||||||||||||||||||||||||||||||
| } else { | ||||||||||||||||||||||||||||||||||||
| if (!quorumSig.VerifyInsecure(quorumPublicKey, commitmentHash)) { | ||||||||||||||||||||||||||||||||||||
| LogPrint(BCLog::LLMQ, "%s\n", qsig_id_string); | ||||||||||||||||||||||||||||||||||||
| return false; | ||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||
| return true; | ||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
| bool CFinalCommitment::Verify(CDeterministicMNManager& dmnman, CQuorumSnapshotManager& qsnapman, | ||||||||||||||||||||||||||||||||||||
| gsl::not_null<const CBlockIndex*> pQuorumBaseBlockIndex, bool checkSigs) const | ||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||
|
|
@@ -106,38 +174,7 @@ bool CFinalCommitment::Verify(CDeterministicMNManager& dmnman, CQuorumSnapshotMa | |||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
| // sigs are only checked when the block is processed | ||||||||||||||||||||||||||||||||||||
| if (checkSigs) { | ||||||||||||||||||||||||||||||||||||
| uint256 commitmentHash = BuildCommitmentHash(llmq_params.type, quorumHash, validMembers, quorumPublicKey, quorumVvecHash); | ||||||||||||||||||||||||||||||||||||
| if (LogAcceptDebug(BCLog::LLMQ)) { | ||||||||||||||||||||||||||||||||||||
| std::stringstream ss3; | ||||||||||||||||||||||||||||||||||||
| for (const auto &mn: members) { | ||||||||||||||||||||||||||||||||||||
| ss3 << mn->proTxHash.ToString().substr(0, 4) << " | "; | ||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||
| LogPrint(BCLog::LLMQ, "CFinalCommitment::%s members[%s] quorumPublicKey[%s] commitmentHash[%s]\n", | ||||||||||||||||||||||||||||||||||||
| __func__, ss3.str(), quorumPublicKey.ToString(), commitmentHash.ToString()); | ||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||
| if (llmq_params.size == 1) { | ||||||||||||||||||||||||||||||||||||
| LogPrintf("pubkey operator: %s\n", members[0]->pdmnState->pubKeyOperator.Get().ToString()); | ||||||||||||||||||||||||||||||||||||
| if (!membersSig.VerifyInsecure(members[0]->pdmnState->pubKeyOperator.Get(), commitmentHash)) { | ||||||||||||||||||||||||||||||||||||
| LogPrint(BCLog::LLMQ, "CFinalCommitment -- q[%s] invalid member signature\n", quorumHash.ToString()); | ||||||||||||||||||||||||||||||||||||
| return false; | ||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||
| } else { | ||||||||||||||||||||||||||||||||||||
| std::vector<CBLSPublicKey> memberPubKeys; | ||||||||||||||||||||||||||||||||||||
| for (const auto i : irange::range(members.size())) { | ||||||||||||||||||||||||||||||||||||
| if (!signers[i]) { | ||||||||||||||||||||||||||||||||||||
| continue; | ||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||
| memberPubKeys.emplace_back(members[i]->pdmnState->pubKeyOperator.Get()); | ||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
| if (!membersSig.VerifySecureAggregated(memberPubKeys, commitmentHash)) { | ||||||||||||||||||||||||||||||||||||
| LogPrint(BCLog::LLMQ, "CFinalCommitment -- q[%s] invalid aggregated members signature\n", | ||||||||||||||||||||||||||||||||||||
| quorumHash.ToString()); | ||||||||||||||||||||||||||||||||||||
| return false; | ||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||
| if (!quorumSig.VerifyInsecure(quorumPublicKey, commitmentHash)) { | ||||||||||||||||||||||||||||||||||||
| LogPrint(BCLog::LLMQ, "CFinalCommitment -- q[%s] invalid quorum signature\n", quorumHash.ToString()); | ||||||||||||||||||||||||||||||||||||
| if (!VerifySignatureAsync(dmnman, qsnapman, pQuorumBaseBlockIndex, nullptr)) { | ||||||||||||||||||||||||||||||||||||
| return false; | ||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
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.
I think I recall in the early days of testing and benchmarking BLS, we found it to be more efficient to aggregate then verify, rather than verify asynchronously or something like that. Did you investigate if this was possible?
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.
it maybe faster, but I can't be 100% sure that I won't introduce security issue and my solution will be safe enough