Skip to content

Commit 821f1ff

Browse files
committed
Add grouped targets for pallet-rate-limiting
1 parent f717d4d commit 821f1ff

File tree

7 files changed

+1525
-694
lines changed

7 files changed

+1525
-694
lines changed

pallets/rate-limiting/src/benchmarking.rs

Lines changed: 123 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
use codec::Decode;
66
use frame_benchmarking::v2::*;
77
use frame_system::{RawOrigin, pallet_prelude::BlockNumberFor};
8-
use sp_runtime::traits::DispatchOriginOf;
8+
use sp_runtime::traits::{One, Saturating};
99

1010
use super::*;
1111

@@ -29,59 +29,144 @@ where
2929
Box::new(T::BenchmarkHelper::sample_call())
3030
}
3131

32+
fn seed_group<T: Config>(name: &[u8], sharing: GroupSharing) -> <T as Config>::GroupId {
33+
Pallet::<T, ()>::create_group(RawOrigin::Root.into(), name.to_vec(), sharing)
34+
.expect("group created");
35+
Pallet::<T, ()>::next_group_id().saturating_sub(<T as Config>::GroupId::one())
36+
}
37+
38+
fn register_call_with_group<T: Config>(
39+
group: Option<<T as Config>::GroupId>,
40+
) -> TransactionIdentifier {
41+
let call = sample_call::<T>();
42+
let identifier = TransactionIdentifier::from_call::<T, ()>(call.as_ref()).expect("id");
43+
Pallet::<T, ()>::register_call(RawOrigin::Root.into(), call, group).expect("registered");
44+
identifier
45+
}
46+
3247
#[benchmarks]
3348
mod benchmarks {
3449
use super::*;
50+
use sp_std::vec::Vec;
3551

3652
#[benchmark]
37-
fn set_rate_limit() {
53+
fn register_call() {
3854
let call = sample_call::<T>();
39-
let limit = RateLimitKind::<BlockNumberFor<T>>::Exact(BlockNumberFor::<T>::from(10u32));
40-
let origin = T::RuntimeOrigin::from(RawOrigin::Root);
41-
let resolver_origin: DispatchOriginOf<<T as Config>::RuntimeCall> =
42-
Into::<DispatchOriginOf<<T as Config>::RuntimeCall>>::into(origin.clone());
43-
let scope = <T as Config>::LimitScopeResolver::context(&resolver_origin, call.as_ref());
44-
let identifier =
45-
TransactionIdentifier::from_call::<T, ()>(call.as_ref()).expect("identifier");
55+
let identifier = TransactionIdentifier::from_call::<T, ()>(call.as_ref()).expect("id");
56+
let target = RateLimitTarget::Transaction(identifier);
4657

4758
#[extrinsic_call]
48-
_(RawOrigin::Root, call, limit.clone());
49-
50-
let stored = Limits::<T, ()>::get(&identifier).expect("limit stored");
51-
match (scope, &stored) {
52-
(Some(ref sc), RateLimit::Scoped(map)) => {
53-
assert_eq!(map.get(sc), Some(&limit));
54-
}
55-
(None, RateLimit::Global(kind)) | (Some(_), RateLimit::Global(kind)) => {
56-
assert_eq!(kind, &limit);
57-
}
58-
(None, RateLimit::Scoped(map)) => {
59-
assert!(map.values().any(|k| k == &limit));
60-
}
61-
}
59+
_(RawOrigin::Root, call, None);
60+
61+
assert!(Limits::<T, ()>::contains_key(target));
6262
}
6363

6464
#[benchmark]
65-
fn clear_rate_limit() {
65+
fn set_rate_limit() {
6666
let call = sample_call::<T>();
67+
let identifier = TransactionIdentifier::from_call::<T, ()>(call.as_ref()).expect("id");
68+
let target = RateLimitTarget::Transaction(identifier);
69+
Limits::<T, ()>::insert(target, RateLimit::global(RateLimitKind::Default));
70+
6771
let limit = RateLimitKind::<BlockNumberFor<T>>::Exact(BlockNumberFor::<T>::from(10u32));
68-
let origin = T::RuntimeOrigin::from(RawOrigin::Root);
69-
let resolver_origin: DispatchOriginOf<<T as Config>::RuntimeCall> =
70-
Into::<DispatchOriginOf<<T as Config>::RuntimeCall>>::into(origin.clone());
71-
let scope = <T as Config>::LimitScopeResolver::context(&resolver_origin, call.as_ref());
72-
73-
// Pre-populate limit for benchmark call
74-
let identifier =
75-
TransactionIdentifier::from_call::<T, ()>(call.as_ref()).expect("identifier");
76-
match scope.clone() {
77-
Some(sc) => Limits::<T, ()>::insert(identifier, RateLimit::scoped_single(sc, limit)),
78-
None => Limits::<T, ()>::insert(identifier, RateLimit::global(limit)),
79-
}
8072

8173
#[extrinsic_call]
82-
_(RawOrigin::Root, call);
74+
_(RawOrigin::Root, target, None, limit);
75+
76+
let stored = Limits::<T, ()>::get(target).expect("limit stored");
77+
assert!(
78+
matches!(stored, RateLimit::Global(RateLimitKind::Exact(span)) if span == BlockNumberFor::<T>::from(10u32))
79+
);
80+
}
81+
82+
#[benchmark]
83+
fn assign_call_to_group() {
84+
let group = seed_group::<T>(b"grp", GroupSharing::UsageOnly);
85+
let identifier = register_call_with_group::<T>(None);
86+
87+
#[extrinsic_call]
88+
_(RawOrigin::Root, identifier, group);
89+
90+
assert_eq!(CallGroups::<T, ()>::get(identifier), Some(group));
91+
assert!(GroupMembers::<T, ()>::get(group).contains(&identifier));
92+
}
93+
94+
#[benchmark]
95+
fn remove_call_from_group() {
96+
let group = seed_group::<T>(b"team", GroupSharing::ConfigOnly);
97+
let identifier = register_call_with_group::<T>(Some(group));
98+
99+
#[extrinsic_call]
100+
_(RawOrigin::Root, identifier);
101+
102+
assert!(CallGroups::<T, ()>::get(identifier).is_none());
103+
assert!(!GroupMembers::<T, ()>::get(group).contains(&identifier));
104+
}
105+
106+
#[benchmark]
107+
fn create_group() {
108+
let name = b"bench".to_vec();
109+
let sharing = GroupSharing::ConfigAndUsage;
110+
111+
#[extrinsic_call]
112+
_(RawOrigin::Root, name.clone(), sharing);
113+
114+
let group = Pallet::<T, ()>::next_group_id().saturating_sub(<T as Config>::GroupId::one());
115+
let details = Groups::<T, ()>::get(group).expect("group stored");
116+
let stored: Vec<u8> = details.name.into();
117+
assert_eq!(stored, name);
118+
assert_eq!(details.sharing, sharing);
119+
}
120+
121+
#[benchmark]
122+
fn update_group() {
123+
let group = seed_group::<T>(b"old", GroupSharing::UsageOnly);
124+
let new_name = b"new".to_vec();
125+
let new_sharing = GroupSharing::ConfigAndUsage;
126+
127+
#[extrinsic_call]
128+
_(
129+
RawOrigin::Root,
130+
group,
131+
Some(new_name.clone()),
132+
Some(new_sharing),
133+
);
134+
135+
let details = Groups::<T, ()>::get(group).expect("group exists");
136+
let stored: Vec<u8> = details.name.into();
137+
assert_eq!(stored, new_name);
138+
assert_eq!(details.sharing, new_sharing);
139+
}
140+
141+
#[benchmark]
142+
fn delete_group() {
143+
let group = seed_group::<T>(b"delete", GroupSharing::UsageOnly);
144+
145+
#[extrinsic_call]
146+
_(RawOrigin::Root, group);
147+
148+
assert!(Groups::<T, ()>::get(group).is_none());
149+
}
150+
151+
#[benchmark]
152+
fn deregister_call() {
153+
let group = seed_group::<T>(b"dreg", GroupSharing::ConfigAndUsage);
154+
let identifier = register_call_with_group::<T>(Some(group));
155+
let target = RateLimitTarget::Transaction(identifier);
156+
let usage_target = Pallet::<T, ()>::usage_target(&identifier).expect("usage target");
157+
LastSeen::<T, ()>::insert(
158+
usage_target,
159+
None::<T::UsageKey>,
160+
BlockNumberFor::<T>::from(1u32),
161+
);
162+
163+
#[extrinsic_call]
164+
_(RawOrigin::Root, identifier, None, true);
83165

84-
assert!(Limits::<T, ()>::get(identifier).is_none());
166+
assert!(Limits::<T, ()>::get(target).is_none());
167+
assert!(LastSeen::<T, ()>::get(usage_target, None::<T::UsageKey>).is_none());
168+
assert!(CallGroups::<T, ()>::get(identifier).is_none());
169+
assert!(!GroupMembers::<T, ()>::get(group).contains(&identifier));
85170
}
86171

87172
#[benchmark]

0 commit comments

Comments
 (0)