diff --git a/Cargo.lock b/Cargo.lock index f22ae99..b71dace 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3837,7 +3837,7 @@ dependencies = [ [[package]] name = "ghost-slow-clap" -version = "0.4.7" +version = "0.4.8" dependencies = [ "frame-benchmarking", "frame-support", diff --git a/pallets/slow-clap/Cargo.toml b/pallets/slow-clap/Cargo.toml index 51157de..ba48845 100644 --- a/pallets/slow-clap/Cargo.toml +++ b/pallets/slow-clap/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "ghost-slow-clap" -version = "0.4.8" +version = "0.4.9" description = "Applause protocol for the EVM bridge" license.workspace = true authors.workspace = true diff --git a/pallets/slow-clap/src/lib.rs b/pallets/slow-clap/src/lib.rs index 2e40665..7a73ca8 100644 --- a/pallets/slow-clap/src/lib.rs +++ b/pallets/slow-clap/src/lib.rs @@ -455,13 +455,11 @@ pub mod pallet { #[pallet::hooks] impl Hooks> for Pallet { fn offchain_worker(now: BlockNumberFor) { - if let Err(e) = Self::start_slow_clapping(now) { - log::info!( - target: LOG_TARGET, - "👻 Skipping slow clap at {:?}: {:?}", - now, - e, - ) + match Self::start_slow_clapping(now) { + Ok(_) => { + log::info!(target: LOG_TARGET, "👻 Slow Clap #{:?} finished gracefully", now) + } + Err(e) => log::info!(target: LOG_TARGET, "👻 Slow Clap #{:?} failed: {:?}", now, e), } } } @@ -812,9 +810,9 @@ impl Pallet { log::info!( target: LOG_TARGET, - "👻 Offchain worker started for network #{:?} at block #{:?}", - network_in_use.0, + "👻 Slow Clap #{:?} started for network #{:?}", block_number, + network_in_use.0, ); let network_id_encoded = network_in_use.0.encode(); @@ -826,11 +824,17 @@ impl Pallet { .try_lock() .map_err(|_| OffchainErr::OffchainTimeoutPeriod(network_in_use.0))?; - Self::do_evm_claps_or_save_block(session_index, network_in_use.0, &network_in_use.1) + Self::do_evm_claps_or_save_block( + session_index, + block_number, + network_in_use.0, + &network_in_use.1, + ) } fn do_evm_claps_or_save_block( session_index: SessionIndex, + block_number: BlockNumberFor, network_id: NetworkIdOf, network_data: &NetworkData, ) -> OffchainResult { @@ -907,7 +911,8 @@ impl Pallet { log::info!( target: LOG_TARGET, - "👻 Stored from_block is #{:?} for network {:?}", + "👻 Slow Clap #{:?} stored block #{:?} for network {:?}", + block_number, new_block_range.0, network_id, ); @@ -1220,8 +1225,9 @@ impl Pallet { }) .collect::>>(); + let disabled_or_offence_bitmap = disabled_bitmap.bitor(offence_bitmap); let not_enough_validators_left = validator_set_count - .saturating_sub(disabled_bitmap.bitor(offence_bitmap).count_ones()) + .saturating_sub(disabled_or_offence_bitmap.count_ones()) .lt(&T::MinAuthoritiesNumber::get()); if not_enough_validators_left && offenders.len() > 0 { @@ -1256,7 +1262,17 @@ impl Pallet { offence_type, }; - if let Err(e) = T::ReportUnresponsiveness::report_offence(vec![], offence) { + let reporters = validators + .into_iter() + .enumerate() + .filter_map(|(index, _)| { + (!disabled_or_offence_bitmap.exists(&(index as AuthIndex))) + .then(|| T::ExposureListener::get_account_by_index(index)) + .flatten() + }) + .collect(); + + if let Err(e) = T::ReportUnresponsiveness::report_offence(reporters, offence) { sp_runtime::print(e); } } diff --git a/pallets/slow-clap/src/tests.rs b/pallets/slow-clap/src/tests.rs index 0dc1d1a..97b7ce5 100644 --- a/pallets/slow-clap/src/tests.rs +++ b/pallets/slow-clap/src/tests.rs @@ -1295,6 +1295,61 @@ fn should_not_nullify_on_incorrect_block_commitment() { }); } +#[test] +fn should_split_commit_slash_between_active_validators() { + let (network_id, _, _) = generate_unique_hash(None, None, None, None, None); + + new_test_ext().execute_with(|| { + let session_index = advance_session_and_get_index(); + prepare_evm_network(None, None); + + let timestamp = SystemTime::now() + .duration_since(UNIX_EPOCH) + .expect("Time went backwards") + .as_millis() as u64; + + let mut block_commitment = CommitmentDetails { + last_stored_block: 9_500_000, + commits: 420, + last_updated: timestamp, + }; + + for extra_time in 1..=3 { + if extra_time < 3 { + let offences = Offences::get(); + assert_eq!(offences.len(), 0); + } + + block_commitment.last_updated += COMMITMENT_DELAY_MILLIS + extra_time; + for i in 0..3 { + assert_ok!(do_block_commitment( + session_index, + network_id, + i, + &block_commitment + )); + } + } + + System::assert_has_event(RuntimeEvent::SlowClap( + crate::Event::SomeAuthoritiesDelayed { + delayed: vec![(3, 3)], + }, + )); + + let offences = Offences::get(); + assert_eq!(offences.len(), 3); + for offence in offences { + assert_eq!(offence.0, vec![0, 1, 2]); + assert_eq!(offence.1.session_index, session_index); + assert_eq!(offence.1.validator_set_count, 4); + assert_eq!(offence.1.offenders, vec![(3, 3)]); + assert_eq!(offence.1.validator_set_count, 4); + assert_eq!(offence.1.offence_type, OffenceType::CommitmentOffence); + } + }); +} + fn assert_clapped_amount( session_index: &SessionIndex, unique_hash: &H256,