From 014ed7d5dce750a414ec3ff13e1c21e64536939b Mon Sep 17 00:00:00 2001 From: Uncle Stinky Date: Fri, 30 Oct 2026 18:29:38 +0300 Subject: [PATCH] resolve infinite loop in phase switching and block drift Signed-off-by: Uncle Stinky --- pallets/exodus/Cargo.toml | 2 +- pallets/exodus/src/lib.rs | 12 +++++------- pallets/exodus/src/tests.rs | 35 ++++------------------------------- runtime/casper/Cargo.toml | 2 +- runtime/casper/src/lib.rs | 2 +- 5 files changed, 12 insertions(+), 41 deletions(-) diff --git a/pallets/exodus/Cargo.toml b/pallets/exodus/Cargo.toml index cc058d0..7345551 100644 --- a/pallets/exodus/Cargo.toml +++ b/pallets/exodus/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "ghost-exodus" -version = "0.1.6" +version = "0.1.7" description = "Threshold signature generation with DKG included" license.workspace = true authors.workspace = true diff --git a/pallets/exodus/src/lib.rs b/pallets/exodus/src/lib.rs index 9acd79d..f56d9bd 100644 --- a/pallets/exodus/src/lib.rs +++ b/pallets/exodus/src/lib.rs @@ -1866,19 +1866,17 @@ pub mod pallet { let threshold_reached = min_threshold <= dkg_qualification.count_ones::(); let is_dkg_phase_vacant = dkg_qualification.is_dkg_vacant(); - if threshold_reached || is_dkg_phase_vacant { + let blocks_delay = if threshold_reached || is_dkg_phase_vacant { dkg_qualification.next_phase(); - } else { - dkg_qualification.restart_dkg(); - } - - let blocks_delay = if threshold_reached && !is_dkg_phase_vacant { T::DkgRoundPeriod::get().unique_saturated_into() } else { + dkg_qualification.restart_dkg(); BLOCKS_FOR_DKG_RESET.unique_saturated_into() }; - let next_release_block = release_block.saturating_add(blocks_delay); + let next_release_block = current_block + .max(release_block) + .saturating_add(blocks_delay); dkg_qualification.set_release_block(next_release_block); QualificationDkgState::::insert(&network_curve, dkg_qualification); diff --git a/pallets/exodus/src/tests.rs b/pallets/exodus/src/tests.rs index fcec66b..e487289 100644 --- a/pallets/exodus/src/tests.rs +++ b/pallets/exodus/src/tests.rs @@ -507,22 +507,12 @@ fn run_succesfull_dkg_session_partially( tx_pool_state: &std::sync::Arc>, raw_authorities: &[u64], curve: NetworkCurve, -) -> (u64, u64) { +) { let authorities: Vec = raw_authorities.iter().map(|&id| id.into()).collect(); let prev_dkg_index = ext.execute_with(|| QualificationDkgState::::get(curve).get_dkg_index()); ext.execute_with(|| Exodus::start_dkg_qualification(authorities, NetworkCurve::iter())); let dkg_index = ext.execute_with(|| QualificationDkgState::::get(curve).get_dkg_index()); - let (start_block, round_delay) = ext.execute_with(|| { - let round_delay = <::DkgRoundPeriod as frame_support::traits::Get< - frame_system::pallet_prelude::BlockNumberFor - >>::get(); - - let start_block = System::block_number(); - - (start_block, round_delay) - }); - assert_eq!(prev_dkg_index + 1, dkg_index); ext.execute_with(|| { @@ -530,18 +520,6 @@ fn run_succesfull_dkg_session_partially( let max_authority_index = raw_authorities.iter().max().cloned().unwrap_or_default() as usize; let padded_participants = max_authority_index.saturating_add(1); - let bitmask_len = padded_participants.div_ceil(8); - - let mut key_members_raw = vec![0u8; bitmask_len]; - - for &authority in raw_authorities.iter() { - let global_index = authority as usize; - let byte_index = global_index >> 3; - let bit_index = global_index & 7; - if let Some(byte) = key_members_raw.get_mut(byte_index) { - *byte |= 1 << bit_index; - } - } let dummy_key_members = ParticipantsBitmap::::empty(padded_participants); let dummy_oversized_bitmap = ParticipantsBitmap::::all_ones(max_authorities_len); @@ -594,8 +572,6 @@ fn run_succesfull_dkg_session_partially( } run_to_next_round(ext, curve); - - (start_block, round_delay) } fn run_initial_dkg_session(raw_authorities: &[u64], curve: NetworkCurve) -> ( @@ -607,8 +583,7 @@ fn run_initial_dkg_session(raw_authorities: &[u64], curve: NetworkCurve) -> ( let prev_verifying_key = ext.execute_with(|| ActiveVerifyingKey::::get(curve)); assert!(prev_verifying_key.is_empty()); - let (start_block, round_delay) = - run_succesfull_dkg_session_partially(&mut ext, &tx_pool_state, &raw_authorities, curve); + let _ = run_succesfull_dkg_session_partially(&mut ext, &tx_pool_state, &raw_authorities, curve); run_to_next_round(&mut ext, curve); @@ -623,7 +598,6 @@ fn run_initial_dkg_session(raw_authorities: &[u64], curve: NetworkCurve) -> ( assert!(state.contains_index(member)); } - assert_eq!(state.get_release_block(), start_block + round_delay * 8 + 2 * BLOCKS_FOR_DKG_RESET); assert_eq!(state.get_dkg_index(), 1); assert_eq!(state.get_phase(), DkgPhase::Finalized); @@ -657,8 +631,7 @@ fn run_dkg_session( }); let next_dkg_index = dkg_index.saturating_add(1); - let (start_block, round_delay) = - run_succesfull_dkg_session_partially(ext, tx_pool_state, &raw_authorities, curve); + run_succesfull_dkg_session_partially(ext, tx_pool_state, &raw_authorities, curve); let total_validators = prev_authorities.len(); let threshold = get_byzantium_quorum_threshold(total_validators); @@ -743,7 +716,7 @@ fn run_dkg_session( let member = authority as AuthIndex; assert!(state.contains_index(member)); } - assert_eq!(state.get_release_block(), start_block + round_delay * 8 + 2 * BLOCKS_FOR_DKG_RESET); + assert_eq!(state.get_dkg_index(), next_dkg_index); assert_eq!(state.get_phase(), DkgPhase::Finalized); diff --git a/runtime/casper/Cargo.toml b/runtime/casper/Cargo.toml index 629a95a..b436f1f 100644 --- a/runtime/casper/Cargo.toml +++ b/runtime/casper/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "casper-runtime" -version = "4.0.16" +version = "4.0.17" build = "build.rs" description = "Runtime of the Casper Network" edition.workspace = true diff --git a/runtime/casper/src/lib.rs b/runtime/casper/src/lib.rs index fac8f53..e5ac63c 100644 --- a/runtime/casper/src/lib.rs +++ b/runtime/casper/src/lib.rs @@ -124,7 +124,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { spec_name: create_runtime_str!("casper"), impl_name: create_runtime_str!("casper-svengali"), authoring_version: 0, - spec_version: 8, + spec_version: 9, impl_version: 0, apis: RUNTIME_API_VERSIONS, transaction_version: 1,