Skip to content

Commit 4c5459e

Browse files
committed
refactor(dash): unify cycle-already-verified check via is_cycle_fully_verified
`store_cycle_if_fully_verified` and `try_load_previous_cycle_entries` both decide whether to skip work based on what is already in `rotated_quorums_per_cycle`, but the predicates had drifted. The storage gate required a non-empty cycle with every entry `Verified`, while the previous-cycle loader only checked `contains_key`. The two now share a single `is_cycle_fully_verified` helper so the previous-cycle path also refuses to short-circuit on a partial entry.
1 parent 1b742e1 commit 4c5459e

1 file changed

Lines changed: 16 additions & 9 deletions

File tree

  • dash/src/sml/masternode_list_engine

dash/src/sml/masternode_list_engine/mod.rs

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -552,7 +552,7 @@ impl MasternodeListEngine {
552552
.values()
553553
.find(|q| q.quorum_entry.quorum_index == Some(0))
554554
.map(|q| q.quorum_entry.quorum_hash)?;
555-
if self.rotated_quorums_per_cycle.contains_key(&cycle_hash) {
555+
if self.is_cycle_fully_verified(&cycle_hash) {
556556
return None;
557557
}
558558
let entries: Vec<QualifiedQuorumEntry> = quorums_of_type
@@ -707,6 +707,20 @@ impl MasternodeListEngine {
707707
hashes
708708
}
709709

710+
/// `true` iff `rotated_quorums_per_cycle` already holds a non-empty cycle
711+
/// for `cycle_hash` whose every entry is `Verified`. Used by the storage
712+
/// gate to refuse downgrading a cycle and by the previous-cycle revalidation
713+
/// path to skip work that would not improve trust.
714+
#[cfg(feature = "quorum_validation")]
715+
fn is_cycle_fully_verified(&self, cycle_hash: &BlockHash) -> bool {
716+
self.rotated_quorums_per_cycle.get(cycle_hash).is_some_and(|existing| {
717+
!existing.is_empty()
718+
&& existing
719+
.values()
720+
.all(|q| matches!(q.verified, LLMQEntryVerificationStatus::Verified))
721+
})
722+
}
723+
710724
/// `rotated_quorums_per_cycle` is the authoritative map for IS lock
711725
/// verification, so only store a cycle when every entry is `Verified`.
712726
/// Skipped entries (e.g. from incomplete CL sigs or missing context) cannot
@@ -725,17 +739,10 @@ impl MasternodeListEngine {
725739
qualified_last_commitment_per_index: Vec<QualifiedQuorumEntry>,
726740
rotation_quorum_type: LLMQType,
727741
) -> Result<Option<CoreBlockHeight>, QuorumValidationError> {
728-
let already_fully_verified =
729-
self.rotated_quorums_per_cycle.get(&cycle_key).is_some_and(|existing| {
730-
!existing.is_empty()
731-
&& existing
732-
.values()
733-
.all(|q| matches!(q.verified, LLMQEntryVerificationStatus::Verified))
734-
});
735742
let all_entries_verified = qualified_last_commitment_per_index
736743
.iter()
737744
.all(|q| matches!(q.verified, LLMQEntryVerificationStatus::Verified));
738-
if !all_entries_verified || already_fully_verified {
745+
if !all_entries_verified || self.is_cycle_fully_verified(&cycle_key) {
739746
return Ok(None);
740747
}
741748
let cycle_map =

0 commit comments

Comments
 (0)