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