From 2c2df5a607d9a391c4d9512a870f0ae4238b6e34 Mon Sep 17 00:00:00 2001 From: Uncle Stinky Date: Wed, 4 Jun 2025 15:44:53 +0300 Subject: [PATCH] ability to do self applause if claps received Signed-off-by: Uncle Stinky --- Cargo.lock | 6 +-- pallets/slow-clap/Cargo.toml | 2 +- pallets/slow-clap/src/benchmarking.rs | 49 +++++++++++++++++++++- pallets/slow-clap/src/lib.rs | 56 ++++++++++++++++++++++++-- pallets/slow-clap/src/tests.rs | 58 +++++++++++++++++++++++++++ pallets/slow-clap/src/weights.rs | 4 +- 6 files changed, 163 insertions(+), 12 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 7c353a8..11d358b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3648,7 +3648,7 @@ dependencies = [ [[package]] name = "ghost-networks" -version = "0.1.4" +version = "0.1.5" dependencies = [ "frame-benchmarking", "frame-support", @@ -3834,7 +3834,7 @@ dependencies = [ [[package]] name = "ghost-slow-clap" -version = "0.3.19" +version = "0.3.20" dependencies = [ "frame-benchmarking", "frame-support", @@ -3870,7 +3870,7 @@ dependencies = [ [[package]] name = "ghost-traits" -version = "0.3.20" +version = "0.3.21" dependencies = [ "frame-support", "sp-runtime 31.0.1", diff --git a/pallets/slow-clap/Cargo.toml b/pallets/slow-clap/Cargo.toml index e9675ac..be4301f 100644 --- a/pallets/slow-clap/Cargo.toml +++ b/pallets/slow-clap/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "ghost-slow-clap" -version = "0.3.19" +version = "0.3.20" description = "Applause protocol for the EVM bridge" license.workspace = true authors.workspace = true diff --git a/pallets/slow-clap/src/benchmarking.rs b/pallets/slow-clap/src/benchmarking.rs index 15e04a7..b547876 100644 --- a/pallets/slow-clap/src/benchmarking.rs +++ b/pallets/slow-clap/src/benchmarking.rs @@ -20,8 +20,7 @@ benchmarks! { let network_id = NetworkIdOf::::default(); let authorities = vec![T::AuthorityId::generate_pair(None)]; - let bounded_authorities = - WeakBoundedVec::<_, T::MaxAuthorities>::try_from(authorities.clone()) + let bounded_authorities = WeakBoundedVec::<_, T::MaxAuthorities>::try_from(authorities.clone()) .map_err(|()| "more than the maximum number of keys provided")?; Authorities::::put(bounded_authorities); @@ -48,6 +47,52 @@ benchmarks! { assert_eq!(<::Currency>::total_balance(&receiver), amount); } + self_applause { + let authority = T::AuthorityId::generate_pair(Some(vec![69u8])); + let bounded_authorities = WeakBoundedVec::<_, T::MaxAuthorities>::try_from(vec![authority.clone()]) + .map_err(|()| "more than the maximum number of keys provided")?; + Authorities::::put(bounded_authorities); + + let minimum_balance = <::Currency>::minimum_balance(); + let receiver = create_account::(); + let receiver_clone = receiver.clone(); + let amount = minimum_balance + minimum_balance; + let network_id = NetworkIdOf::::default(); + let session_index = Default::default(); + let transaction_hash = H256::repeat_byte(1u8); + + let unique_transaction_hash = >::generate_unique_hash( + &receiver, + &amount, + &network_id, + ); + let storage_key = (session_index, &transaction_hash, &unique_transaction_hash); + + >::trigger_nullification_for_benchmark(); + let clap = Clap { + session_index, + authority_index: 0, + transaction_hash, + block_number: 69, + removed: false, + network_id, + receiver: receiver.clone(), + amount, + }; + + let encoded_clap = clap.encode(); + let signature = authority.sign(&encoded_clap).unwrap(); + >::slow_clap(RawOrigin::None.into(), clap, signature)?; + >::trigger_nullification_for_benchmark(); + + assert_eq!(<::Currency>::total_balance(&receiver), Default::default()); + assert_eq!(ApplausesForTransaction::::get(&storage_key), false); + }: _(RawOrigin::Signed(receiver_clone), network_id, session_index, transaction_hash, receiver_clone.clone(), amount) + verify { + assert_eq!(<::Currency>::total_balance(&receiver), amount); + assert_eq!(ApplausesForTransaction::::get(&storage_key), true); + } + impl_benchmark_test_suite!( Pallet, crate::mock::new_test_ext(), diff --git a/pallets/slow-clap/src/lib.rs b/pallets/slow-clap/src/lib.rs index c56263e..01b8111 100644 --- a/pallets/slow-clap/src/lib.rs +++ b/pallets/slow-clap/src/lib.rs @@ -323,6 +323,7 @@ pub mod pallet { #[pallet::error] pub enum Error { + NotEnoughClaps, NotAnAuthority, ClapForWrongSession, CurrentValidatorIsDisabled, @@ -404,13 +405,23 @@ pub mod pallet { } #[pallet::call_index(1)] - #[pallet::weight(T::WeightInfo::applause())] - pub fn applause( + #[pallet::weight(T::WeightInfo::self_applause())] + pub fn self_applause( origin: OriginFor, - _clap: Clap, BalanceOf>, + network_id: NetworkIdOf, + session_index: SessionIndex, + transaction_hash: H256, + receiver: T::AccountId, + amount: BalanceOf, ) -> DispatchResult { let _ = ensure_signed(origin)?; - Ok(()) + Self::applause_if_posible( + network_id, + session_index, + transaction_hash, + receiver, + amount, + ) } } @@ -598,6 +609,38 @@ impl Pallet { }) } + fn applause_if_posible( + network_id: NetworkIdOf, + session_index: SessionIndex, + transaction_hash: H256, + receiver: T::AccountId, + amount: BalanceOf, + ) -> DispatchResult{ + let clap_unique_hash = Self::generate_unique_hash(&receiver, &amount, &network_id); + let received_claps_key = (session_index, &transaction_hash, &clap_unique_hash); + + let clap = Clap { + authority_index: Default::default(), + block_number: Default::default(), + removed: false, + session_index, + network_id, + receiver, + amount, + transaction_hash, + }; + + let enough_authorities = Perbill::from_rational( + ReceivedClaps::::get(&received_claps_key).len() as u32, + Authorities::::get().len() as u32, + ) > Perbill::from_percent(T::ApplauseThreshold::get()); + + ensure!(enough_authorities, Error::::NotEnoughClaps); + Self::try_applause(&clap, &received_claps_key)?; + + Ok(()) + } + fn start_slow_clapping( block_number: BlockNumberFor, networks_len: usize, @@ -914,6 +957,11 @@ impl Pallet { .expect("more than the maximum number of authorities"); Authorities::::put(bounded_authorities); } + + #[cfg(feature = "runtime-benchmarks")] + fn trigger_nullification_for_benchmark() { + T::NetworkDataHandler::trigger_nullification(); + } } impl sp_runtime::BoundToRuntimeAppPublic for Pallet { diff --git a/pallets/slow-clap/src/tests.rs b/pallets/slow-clap/src/tests.rs index 204eef4..a39b5a5 100644 --- a/pallets/slow-clap/src/tests.rs +++ b/pallets/slow-clap/src/tests.rs @@ -602,6 +602,64 @@ fn should_avoid_applause_during_nullification_period() { }); } +#[test] +fn should_self_applause_if_enough_received_claps() { + let (network_id, transaction_hash, unique_transaction_hash) = + generate_unique_hash(None, None, None, None); + let (_, receiver, amount) = get_mocked_metadata(); + + new_test_ext().execute_with(|| { + let _ = prepare_evm_network(Some(network_id), Some(0)); + let session_index = advance_session_and_get_index(); + let storage_key = (session_index, transaction_hash, unique_transaction_hash); + + assert_err!(SlowClap::self_applause( + RuntimeOrigin::signed(receiver), + network_id, + session_index, + transaction_hash, + receiver, + amount, + ), Error::::NotEnoughClaps); + + assert_eq!(pallet::ApplausesForTransaction::::get(&storage_key), false); + assert_eq!(Balances::balance(&receiver), 0); + assert_eq!(BridgedInflationCurve::::era_payout( + 0, 0, 0), (0, 0)); + + assert_ok!(do_clap_from(session_index, network_id, 0, false)); + assert_ok!(do_clap_from(session_index, network_id, 1, false)); + assert_ok!(do_clap_from(session_index, network_id, 2, false)); + + assert_eq!(pallet::ApplausesForTransaction::::get(&storage_key), false); + assert_eq!(Balances::balance(&receiver), 0); + + assert_ok!(SlowClap::self_applause( + RuntimeOrigin::signed(receiver), + network_id, + session_index, + transaction_hash, + receiver, + amount, + )); + assert_eq!(pallet::ApplausesForTransaction::::get(&storage_key), false); + assert_eq!(Balances::balance(&receiver), 0); + + Networks::on_finalize(System::block_number()); + + assert_ok!(SlowClap::self_applause( + RuntimeOrigin::signed(receiver), + network_id, + session_index, + transaction_hash, + receiver, + amount, + )); + assert_eq!(pallet::ApplausesForTransaction::::get(&storage_key), true); + assert_eq!(Balances::balance(&receiver), amount); + }); +} + // TODO: check event // TODO: multiple logs will create multiple records // TODO: errors should be checked as much as possible diff --git a/pallets/slow-clap/src/weights.rs b/pallets/slow-clap/src/weights.rs index b479cbe..3e14088 100644 --- a/pallets/slow-clap/src/weights.rs +++ b/pallets/slow-clap/src/weights.rs @@ -2,10 +2,10 @@ use frame_support::weights::Weight; pub trait WeightInfo { fn slow_clap() -> Weight; - fn applause()-> Weight; + fn self_applause()-> Weight; } impl WeightInfo for () { fn slow_clap()-> Weight { Weight::zero() } - fn applause()-> Weight { Weight::zero() } + fn self_applause()-> Weight { Weight::zero() } }