polkadot_runtime_common/claims/
benchmarking.rs1#[cfg(feature = "runtime-benchmarks")]
20use super::*;
21use crate::claims::Call;
22use frame_benchmarking::v2::*;
23use frame_support::{
24 dispatch::{DispatchInfo, GetDispatchInfo},
25 traits::UnfilteredDispatchable,
26};
27use frame_system::RawOrigin;
28use secp_utils::*;
29use sp_runtime::{traits::DispatchTransaction, DispatchResult};
30
31const SEED: u32 = 0;
32
33const MAX_CLAIMS: u32 = 10_000;
34const VALUE: u32 = 1_000_000;
35
36fn create_claim<T: Config>(input: u32) -> DispatchResult {
37 let secret_key = libsecp256k1::SecretKey::parse(&keccak_256(&input.encode())).unwrap();
38 let eth_address = eth(&secret_key);
39 let vesting = Some((100_000u32.into(), 1_000u32.into(), 100u32.into()));
40 super::Pallet::<T>::mint_claim(
41 RawOrigin::Root.into(),
42 eth_address,
43 VALUE.into(),
44 vesting,
45 None,
46 )?;
47 Ok(())
48}
49
50fn create_claim_attest<T: Config>(input: u32) -> DispatchResult {
51 let secret_key = libsecp256k1::SecretKey::parse(&keccak_256(&input.encode())).unwrap();
52 let eth_address = eth(&secret_key);
53 let vesting = Some((100_000u32.into(), 1_000u32.into(), 100u32.into()));
54 super::Pallet::<T>::mint_claim(
55 RawOrigin::Root.into(),
56 eth_address,
57 VALUE.into(),
58 vesting,
59 Some(Default::default()),
60 )?;
61 Ok(())
62}
63
64#[benchmarks(
65 where
66 <T as frame_system::Config>::RuntimeCall: IsSubType<Call<T>> + From<Call<T>>,
67 <T as frame_system::Config>::RuntimeCall: Dispatchable<Info = DispatchInfo> + GetDispatchInfo,
68 <<T as frame_system::Config>::RuntimeCall as Dispatchable>::RuntimeOrigin: AsSystemOriginSigner<T::AccountId> + AsTransactionAuthorizedOrigin + Clone,
69 <<T as frame_system::Config>::RuntimeCall as Dispatchable>::PostInfo: Default,
70 )]
71mod benchmarks {
72 use super::*;
73
74 #[allow(deprecated)]
75 use sp_runtime::traits::ValidateUnsigned;
76
77 #[benchmark]
79 fn claim() -> Result<(), BenchmarkError> {
80 let c = MAX_CLAIMS;
81 for _ in 0..c / 2 {
82 create_claim::<T>(c)?;
83 create_claim_attest::<T>(u32::MAX - c)?;
84 }
85 let secret_key = libsecp256k1::SecretKey::parse(&keccak_256(&c.encode())).unwrap();
86 let eth_address = eth(&secret_key);
87 let account: T::AccountId = account("user", c, SEED);
88 let vesting = Some((100_000u32.into(), 1_000u32.into(), 100u32.into()));
89 let signature = sig::<T>(&secret_key, &account.encode(), &[][..]);
90 super::Pallet::<T>::mint_claim(
91 RawOrigin::Root.into(),
92 eth_address,
93 VALUE.into(),
94 vesting,
95 None,
96 )?;
97 assert_eq!(Claims::<T>::get(eth_address), Some(VALUE.into()));
98 let source = sp_runtime::transaction_validity::TransactionSource::External;
99 let call_enc =
100 Call::<T>::claim { dest: account.clone(), ethereum_signature: signature.clone() }
101 .encode();
102
103 #[block]
104 {
105 let call = <Call<T> as Decode>::decode(&mut &*call_enc)
106 .expect("call is encoded above, encoding must be correct");
107 #[allow(deprecated)]
108 super::Pallet::<T>::validate_unsigned(source, &call)
109 .map_err(|e| -> &'static str { e.into() })?;
110 call.dispatch_bypass_filter(RawOrigin::None.into())?;
111 }
112
113 assert_eq!(Claims::<T>::get(eth_address), None);
114 Ok(())
115 }
116
117 #[benchmark]
119 fn mint_claim() -> Result<(), BenchmarkError> {
120 let c = MAX_CLAIMS;
121 for _ in 0..c / 2 {
122 create_claim::<T>(c)?;
123 create_claim_attest::<T>(u32::MAX - c)?;
124 }
125 let eth_address = account("eth_address", 0, SEED);
126 let vesting = Some((100_000u32.into(), 1_000u32.into(), 100u32.into()));
127 let statement = StatementKind::Regular;
128
129 #[extrinsic_call]
130 _(RawOrigin::Root, eth_address, VALUE.into(), vesting, Some(statement));
131
132 assert_eq!(Claims::<T>::get(eth_address), Some(VALUE.into()));
133 Ok(())
134 }
135
136 #[benchmark]
138 fn claim_attest() -> Result<(), BenchmarkError> {
139 let c = MAX_CLAIMS;
140 for _ in 0..c / 2 {
141 create_claim::<T>(c)?;
142 create_claim_attest::<T>(u32::MAX - c)?;
143 }
144 let attest_c = u32::MAX - c;
146 let secret_key = libsecp256k1::SecretKey::parse(&keccak_256(&attest_c.encode())).unwrap();
147 let eth_address = eth(&secret_key);
148 let account: T::AccountId = account("user", c, SEED);
149 let vesting = Some((100_000u32.into(), 1_000u32.into(), 100u32.into()));
150 let statement = StatementKind::Regular;
151 let signature = sig::<T>(&secret_key, &account.encode(), statement.to_text());
152 super::Pallet::<T>::mint_claim(
153 RawOrigin::Root.into(),
154 eth_address,
155 VALUE.into(),
156 vesting,
157 Some(statement),
158 )?;
159 assert_eq!(Claims::<T>::get(eth_address), Some(VALUE.into()));
160 let call_enc = Call::<T>::claim_attest {
161 dest: account.clone(),
162 ethereum_signature: signature.clone(),
163 statement: StatementKind::Regular.to_text().to_vec(),
164 }
165 .encode();
166 let source = sp_runtime::transaction_validity::TransactionSource::External;
167
168 #[block]
169 {
170 let call = <Call<T> as Decode>::decode(&mut &*call_enc)
171 .expect("call is encoded above, encoding must be correct");
172 #[allow(deprecated)]
173 super::Pallet::<T>::validate_unsigned(source, &call)
174 .map_err(|e| -> &'static str { e.into() })?;
175 call.dispatch_bypass_filter(RawOrigin::None.into())?;
176 }
177
178 assert_eq!(Claims::<T>::get(eth_address), None);
179 Ok(())
180 }
181
182 #[benchmark]
184 fn attest() -> Result<(), BenchmarkError> {
185 let c = MAX_CLAIMS;
186 for _ in 0..c / 2 {
187 create_claim::<T>(c)?;
188 create_claim_attest::<T>(u32::MAX - c)?;
189 }
190 let attest_c = u32::MAX - c;
191 let secret_key = libsecp256k1::SecretKey::parse(&keccak_256(&attest_c.encode())).unwrap();
192 let eth_address = eth(&secret_key);
193 let account: T::AccountId = account("user", c, SEED);
194 let vesting = Some((100_000u32.into(), 1_000u32.into(), 100u32.into()));
195 let statement = StatementKind::Regular;
196 super::Pallet::<T>::mint_claim(
197 RawOrigin::Root.into(),
198 eth_address,
199 VALUE.into(),
200 vesting,
201 Some(statement),
202 )?;
203 Preclaims::<T>::insert(&account, eth_address);
204 assert_eq!(Claims::<T>::get(eth_address), Some(VALUE.into()));
205
206 let stmt = StatementKind::Regular.to_text().to_vec();
207
208 #[extrinsic_call]
209 _(RawOrigin::Signed(account), stmt);
210
211 assert_eq!(Claims::<T>::get(eth_address), None);
212 Ok(())
213 }
214
215 #[benchmark]
216 fn move_claim() -> Result<(), BenchmarkError> {
217 let c = MAX_CLAIMS;
218 for _ in 0..c / 2 {
219 create_claim::<T>(c)?;
220 create_claim_attest::<T>(u32::MAX - c)?;
221 }
222 let attest_c = u32::MAX - c;
223 let secret_key = libsecp256k1::SecretKey::parse(&keccak_256(&attest_c.encode())).unwrap();
224 let eth_address = eth(&secret_key);
225
226 let new_secret_key =
227 libsecp256k1::SecretKey::parse(&keccak_256(&(u32::MAX / 2).encode())).unwrap();
228 let new_eth_address = eth(&new_secret_key);
229
230 let account: T::AccountId = account("user", c, SEED);
231 Preclaims::<T>::insert(&account, eth_address);
232
233 assert!(Claims::<T>::contains_key(eth_address));
234 assert!(!Claims::<T>::contains_key(new_eth_address));
235
236 #[extrinsic_call]
237 _(RawOrigin::Root, eth_address, new_eth_address, Some(account));
238
239 assert!(!Claims::<T>::contains_key(eth_address));
240 assert!(Claims::<T>::contains_key(new_eth_address));
241 Ok(())
242 }
243
244 #[benchmark(extra)]
246 fn keccak256(i: Linear<0, 10_000>) {
247 let bytes = (i).encode();
248
249 #[block]
250 {
251 for _ in 0..i {
252 let _hash = keccak_256(&bytes);
253 }
254 }
255 }
256
257 #[benchmark(extra)]
259 fn eth_recover(i: Linear<0, 1_000>) {
260 let secret_key = libsecp256k1::SecretKey::parse(&keccak_256(&i.encode())).unwrap();
262 let account: T::AccountId = account("user", i, SEED);
263 let signature = sig::<T>(&secret_key, &account.encode(), &[][..]);
264 let data = account.using_encoded(to_ascii_hex);
265 let extra = StatementKind::default().to_text();
266
267 #[block]
268 {
269 for _ in 0..i {
270 assert!(super::Pallet::<T>::eth_recover(&signature, &data, extra).is_some());
271 }
272 }
273 }
274
275 #[benchmark]
276 fn prevalidate_attests() -> Result<(), BenchmarkError> {
277 let c = MAX_CLAIMS;
278 for _ in 0..c / 2 {
279 create_claim::<T>(c)?;
280 create_claim_attest::<T>(u32::MAX - c)?;
281 }
282 let ext = PrevalidateAttests::<T>::new();
283 let call = super::Call::attest { statement: StatementKind::Regular.to_text().to_vec() };
284 let call: <T as frame_system::Config>::RuntimeCall = call.into();
285 let info = call.get_dispatch_info();
286 let attest_c = u32::MAX - c;
287 let secret_key = libsecp256k1::SecretKey::parse(&keccak_256(&attest_c.encode())).unwrap();
288 let eth_address = eth(&secret_key);
289 let account: T::AccountId = account("user", c, SEED);
290 let vesting = Some((100_000u32.into(), 1_000u32.into(), 100u32.into()));
291 let statement = StatementKind::Regular;
292 super::Pallet::<T>::mint_claim(
293 RawOrigin::Root.into(),
294 eth_address,
295 VALUE.into(),
296 vesting,
297 Some(statement),
298 )?;
299 Preclaims::<T>::insert(&account, eth_address);
300 assert_eq!(Claims::<T>::get(eth_address), Some(VALUE.into()));
301
302 #[block]
303 {
304 assert!(ext
305 .test_run(RawOrigin::Signed(account).into(), &call, &info, 0, 0, |_| {
306 Ok(Default::default())
307 })
308 .unwrap()
309 .is_ok());
310 }
311
312 Ok(())
313 }
314
315 impl_benchmark_test_suite!(
316 Pallet,
317 crate::claims::mock::new_test_ext(),
318 crate::claims::mock::Test,
319 );
320}