-
Notifications
You must be signed in to change notification settings - Fork 1.2k
fix: handle null pprev in IsQuorumTypeEnabled instead of terminating #7520
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
base: develop
Are you sure you want to change the base?
Changes from all commits
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 |
|---|---|---|
|
|
@@ -5,7 +5,9 @@ | |
| #include <test/util/setup_common.h> | ||
|
|
||
| #include <chainparams.h> | ||
| #include <llmq/context.h> | ||
| #include <llmq/options.h> | ||
| #include <llmq/utils.h> | ||
| #include <validation.h> | ||
|
|
||
| #include <boost/test/unit_test.hpp> | ||
|
|
@@ -68,4 +70,37 @@ BOOST_FIXTURE_TEST_CASE(utils_IsQuorumTypeEnabled_tests_mainnet, TestingSetup) | |
| Test(m_node); | ||
| } | ||
|
|
||
| // Regression: a genesis quorum base has pprev == nullptr. | ||
| // Pre-fix that pointer was fed to IsQuorumTypeEnabled's gsl::not_null parameter, | ||
| // whose converting constructor calls Expects() and so std::terminate()s the | ||
| // process. That is [[noreturn]] noexcept, not an exception, so no try/catch in | ||
| // the validation or net-processing stack could contain it. | ||
| // | ||
| // Note the two guards below are not equivalent. Passing a literal nullptr was a | ||
| // *compile* error pre-fix (not_null(std::nullptr_t) is deleted), so that line | ||
| // only pins the relaxed signature. The GetAllQuorumMembers() call is the one | ||
| // that reproduced the abort, since the null arrives through a runtime pointer. | ||
| // The end-to-end consensus path is covered by | ||
| // llmq_commitment_tests/commitment_genesis_quorum_hash_rejected_test. | ||
| BOOST_FIXTURE_TEST_CASE(genesis_quorum_base_null_pprev_safe, RegTestingSetup) | ||
| { | ||
| const CBlockIndex* genesis = WITH_LOCK(::cs_main, return m_node.chainman->ActiveTip()); | ||
| BOOST_REQUIRE(genesis != nullptr); | ||
| BOOST_REQUIRE_EQUAL(genesis->nHeight, 0); | ||
| BOOST_REQUIRE(genesis->pprev == nullptr); | ||
|
|
||
| const auto llmq_type = Params().GetConsensus().llmqTypeChainLocks; | ||
|
|
||
| // IsQuorumTypeEnabled sink pattern (NetDKG passes pQuorumBaseBlockIndex->pprev). | ||
| BOOST_CHECK(!m_node.chainman->IsQuorumTypeEnabled(llmq_type, nullptr)); | ||
|
|
||
|
Comment on lines
+95
to
+96
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. 🔴 Blocking: Rewrite the non-buildable regression-test commit Commit source: ['codex'] 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. Correction — Rewrite the non-buildable regression-test commit remains STILL VALID at The rebase preserved the same patch: commit 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. Resolved in this update — Rewrite the non-buildable regression-test commit no longer present. Auto-resolved by the review system based on the latest commit diff. If you believe this was closed in error, reopen the thread. |
||
| // GetAllQuorumMembers with m_base_index == genesis. | ||
| const llmq::UtilParameters util_params{*Assert(m_node.dmnman), | ||
| *Assert(m_node.llmq_ctx)->qsnapman, | ||
| *Assert(m_node.chainman), | ||
| genesis}; | ||
| const auto members = llmq::utils::GetAllQuorumMembers(llmq_type, util_params); | ||
| BOOST_CHECK(members.empty()); | ||
| } | ||
|
|
||
| BOOST_AUTO_TEST_SUITE_END() | ||
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.
When an empty member set reaches block verification, this new
return falsedoes not reject the block becauseCQuorumBlockProcessor::ProcessBlockignoresVerifySignatureAsync's return value and then treats an empty check queue as successful. This is reachable with the accepted zero-threshold regtest/devnet quorum overrides: the count checks accept all-false member bitsets, while a genesis quorum base produces no members, so the commitment can be processed without either BLS signature being verified. Have the queued caller reject a false return (and cover that caller in the regression test) rather than relying solely on the return here.AGENTS.md reference: AGENTS.md:L164-L164
Useful? React with 👍 / 👎.