ability to do self applause if claps received

Signed-off-by: Uncle Stinky <uncle.stinky@ghostchain.io>
This commit is contained in:
Uncle Stinky 2025-06-04 15:44:53 +03:00
parent 186fb58367
commit 2c2df5a607
Signed by: st1nky
GPG Key ID: 016064BD97603B40
6 changed files with 163 additions and 12 deletions

6
Cargo.lock generated
View File

@ -3648,7 +3648,7 @@ dependencies = [
[[package]] [[package]]
name = "ghost-networks" name = "ghost-networks"
version = "0.1.4" version = "0.1.5"
dependencies = [ dependencies = [
"frame-benchmarking", "frame-benchmarking",
"frame-support", "frame-support",
@ -3834,7 +3834,7 @@ dependencies = [
[[package]] [[package]]
name = "ghost-slow-clap" name = "ghost-slow-clap"
version = "0.3.19" version = "0.3.20"
dependencies = [ dependencies = [
"frame-benchmarking", "frame-benchmarking",
"frame-support", "frame-support",
@ -3870,7 +3870,7 @@ dependencies = [
[[package]] [[package]]
name = "ghost-traits" name = "ghost-traits"
version = "0.3.20" version = "0.3.21"
dependencies = [ dependencies = [
"frame-support", "frame-support",
"sp-runtime 31.0.1", "sp-runtime 31.0.1",

View File

@ -1,6 +1,6 @@
[package] [package]
name = "ghost-slow-clap" name = "ghost-slow-clap"
version = "0.3.19" version = "0.3.20"
description = "Applause protocol for the EVM bridge" description = "Applause protocol for the EVM bridge"
license.workspace = true license.workspace = true
authors.workspace = true authors.workspace = true

View File

@ -20,8 +20,7 @@ benchmarks! {
let network_id = NetworkIdOf::<T>::default(); let network_id = NetworkIdOf::<T>::default();
let authorities = vec![T::AuthorityId::generate_pair(None)]; let authorities = vec![T::AuthorityId::generate_pair(None)];
let bounded_authorities = let bounded_authorities = WeakBoundedVec::<_, T::MaxAuthorities>::try_from(authorities.clone())
WeakBoundedVec::<_, T::MaxAuthorities>::try_from(authorities.clone())
.map_err(|()| "more than the maximum number of keys provided")?; .map_err(|()| "more than the maximum number of keys provided")?;
Authorities::<T>::put(bounded_authorities); Authorities::<T>::put(bounded_authorities);
@ -48,6 +47,52 @@ benchmarks! {
assert_eq!(<<T as pallet::Config>::Currency>::total_balance(&receiver), amount); assert_eq!(<<T as pallet::Config>::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::<T>::put(bounded_authorities);
let minimum_balance = <<T as pallet::Config>::Currency>::minimum_balance();
let receiver = create_account::<T>();
let receiver_clone = receiver.clone();
let amount = minimum_balance + minimum_balance;
let network_id = NetworkIdOf::<T>::default();
let session_index = Default::default();
let transaction_hash = H256::repeat_byte(1u8);
let unique_transaction_hash = <Pallet<T>>::generate_unique_hash(
&receiver,
&amount,
&network_id,
);
let storage_key = (session_index, &transaction_hash, &unique_transaction_hash);
<Pallet::<T>>::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();
<Pallet<T>>::slow_clap(RawOrigin::None.into(), clap, signature)?;
<Pallet::<T>>::trigger_nullification_for_benchmark();
assert_eq!(<<T as pallet::Config>::Currency>::total_balance(&receiver), Default::default());
assert_eq!(ApplausesForTransaction::<T>::get(&storage_key), false);
}: _(RawOrigin::Signed(receiver_clone), network_id, session_index, transaction_hash, receiver_clone.clone(), amount)
verify {
assert_eq!(<<T as pallet::Config>::Currency>::total_balance(&receiver), amount);
assert_eq!(ApplausesForTransaction::<T>::get(&storage_key), true);
}
impl_benchmark_test_suite!( impl_benchmark_test_suite!(
Pallet, Pallet,
crate::mock::new_test_ext(), crate::mock::new_test_ext(),

View File

@ -323,6 +323,7 @@ pub mod pallet {
#[pallet::error] #[pallet::error]
pub enum Error<T> { pub enum Error<T> {
NotEnoughClaps,
NotAnAuthority, NotAnAuthority,
ClapForWrongSession, ClapForWrongSession,
CurrentValidatorIsDisabled, CurrentValidatorIsDisabled,
@ -404,13 +405,23 @@ pub mod pallet {
} }
#[pallet::call_index(1)] #[pallet::call_index(1)]
#[pallet::weight(T::WeightInfo::applause())] #[pallet::weight(T::WeightInfo::self_applause())]
pub fn applause( pub fn self_applause(
origin: OriginFor<T>, origin: OriginFor<T>,
_clap: Clap<T::AccountId, NetworkIdOf<T>, BalanceOf<T>>, network_id: NetworkIdOf<T>,
session_index: SessionIndex,
transaction_hash: H256,
receiver: T::AccountId,
amount: BalanceOf<T>,
) -> DispatchResult { ) -> DispatchResult {
let _ = ensure_signed(origin)?; let _ = ensure_signed(origin)?;
Ok(()) Self::applause_if_posible(
network_id,
session_index,
transaction_hash,
receiver,
amount,
)
} }
} }
@ -598,6 +609,38 @@ impl<T: Config> Pallet<T> {
}) })
} }
fn applause_if_posible(
network_id: NetworkIdOf<T>,
session_index: SessionIndex,
transaction_hash: H256,
receiver: T::AccountId,
amount: BalanceOf<T>,
) -> 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::<T>::get(&received_claps_key).len() as u32,
Authorities::<T>::get().len() as u32,
) > Perbill::from_percent(T::ApplauseThreshold::get());
ensure!(enough_authorities, Error::<T>::NotEnoughClaps);
Self::try_applause(&clap, &received_claps_key)?;
Ok(())
}
fn start_slow_clapping( fn start_slow_clapping(
block_number: BlockNumberFor<T>, block_number: BlockNumberFor<T>,
networks_len: usize, networks_len: usize,
@ -914,6 +957,11 @@ impl<T: Config> Pallet<T> {
.expect("more than the maximum number of authorities"); .expect("more than the maximum number of authorities");
Authorities::<T>::put(bounded_authorities); Authorities::<T>::put(bounded_authorities);
} }
#[cfg(feature = "runtime-benchmarks")]
fn trigger_nullification_for_benchmark() {
T::NetworkDataHandler::trigger_nullification();
}
} }
impl<T: Config> sp_runtime::BoundToRuntimeAppPublic for Pallet<T> { impl<T: Config> sp_runtime::BoundToRuntimeAppPublic for Pallet<T> {

View File

@ -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::<Runtime>::NotEnoughClaps);
assert_eq!(pallet::ApplausesForTransaction::<Runtime>::get(&storage_key), false);
assert_eq!(Balances::balance(&receiver), 0);
assert_eq!(BridgedInflationCurve::<RewardCurve, Runtime>::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::<Runtime>::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::<Runtime>::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::<Runtime>::get(&storage_key), true);
assert_eq!(Balances::balance(&receiver), amount);
});
}
// TODO: check event // TODO: check event
// TODO: multiple logs will create multiple records // TODO: multiple logs will create multiple records
// TODO: errors should be checked as much as possible // TODO: errors should be checked as much as possible

View File

@ -2,10 +2,10 @@ use frame_support::weights::Weight;
pub trait WeightInfo { pub trait WeightInfo {
fn slow_clap() -> Weight; fn slow_clap() -> Weight;
fn applause()-> Weight; fn self_applause()-> Weight;
} }
impl WeightInfo for () { impl WeightInfo for () {
fn slow_clap()-> Weight { Weight::zero() } fn slow_clap()-> Weight { Weight::zero() }
fn applause()-> Weight { Weight::zero() } fn self_applause()-> Weight { Weight::zero() }
} }