Skip to content

Commit 9df2569

Browse files
Neopalliumadamdossa
authored andcommitted
Include permmisions complexity in extrinsic weight. (#1192)
1 parent bdc670b commit 9df2569

File tree

5 files changed

+174
-8
lines changed

5 files changed

+174
-8
lines changed

pallets/common/src/traits/identity.rs

Lines changed: 46 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,8 @@ use frame_support::{
3333
Parameter,
3434
};
3535
use polymesh_primitives::{
36-
secondary_key::api::SecondaryKey, AuthorizationData, IdentityClaim, IdentityId, InvestorUid,
37-
Permissions, Signatory, Ticker,
36+
secondary_key::api::{LegacyPermissions, SecondaryKey},
37+
AuthorizationData, IdentityClaim, IdentityId, InvestorUid, Permissions, Signatory, Ticker,
3838
};
3939
use sp_core::H512;
4040
use sp_runtime::traits::{Dispatchable, IdentifyAccount, Member, Verify};
@@ -87,6 +87,12 @@ pub trait WeightInfo {
8787
fn add_claim() -> Weight;
8888
fn revoke_claim() -> Weight;
8989
fn set_permission_to_signer() -> Weight;
90+
/// Complexity Parameters:
91+
/// `a` = Number of (A)ssets
92+
/// `p` = Number of (P)ortfolios
93+
/// `l` = Number of pa(L)lets
94+
/// `e` = Number of (E)xtrinsics
95+
fn permissions_cost(a: u32, p: u32, l: u32, e: u32) -> Weight;
9096
fn freeze_secondary_keys() -> Weight;
9197
fn unfreeze_secondary_keys() -> Weight;
9298
fn add_authorization() -> Weight;
@@ -95,6 +101,44 @@ pub trait WeightInfo {
95101
fn add_investor_uniqueness_claim() -> Weight;
96102
fn add_investor_uniqueness_claim_v2() -> Weight;
97103
fn revoke_claim_by_index() -> Weight;
104+
105+
// Helpers for extrinsics with Permissions.
106+
fn add_secondary_keys_full<AccountId>(
107+
additional_keys: &[SecondaryKeyWithAuth<AccountId>],
108+
) -> Weight {
109+
let perm_cost = additional_keys.iter().fold(0u64, |cost, key_with_auth| {
110+
let (assets, portfolios, pallets, extrinsics) =
111+
key_with_auth.secondary_key.permissions.get_weights();
112+
let perm_cost = Self::permissions_cost(assets, portfolios, pallets, extrinsics);
113+
cost.saturating_add(perm_cost)
114+
});
115+
perm_cost.saturating_add(Self::add_secondary_keys_with_authorization(
116+
additional_keys.len() as u32,
117+
))
118+
}
119+
120+
fn add_authorization_full<AccountId>(data: &AuthorizationData<AccountId>) -> Weight {
121+
let perm_cost = match data {
122+
AuthorizationData::JoinIdentity(perms) => {
123+
let (assets, portfolios, pallets, extrinsics) = perms.get_weights();
124+
Self::permissions_cost(assets, portfolios, pallets, extrinsics)
125+
}
126+
_ => 0,
127+
};
128+
129+
perm_cost.saturating_add(Self::add_authorization())
130+
}
131+
132+
fn set_permission_to_signer_full(perms: &Permissions) -> Weight {
133+
let (assets, portfolios, pallets, extrinsics) = perms.get_weights();
134+
Self::permissions_cost(assets, portfolios, pallets, extrinsics)
135+
.saturating_add(Self::set_permission_to_signer())
136+
}
137+
fn legacy_set_permission_to_signer_full(perms: &LegacyPermissions) -> Weight {
138+
let (assets, portfolios, pallets, extrinsics) = perms.get_weights();
139+
Self::permissions_cost(assets, portfolios, pallets, extrinsics)
140+
.saturating_add(Self::set_permission_to_signer())
141+
}
98142
}
99143

100144
/// The module's configuration trait.

pallets/identity/src/benchmarking.rs

Lines changed: 56 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,10 @@ use polymesh_common_utilities::{
2525
};
2626
use polymesh_primitives::{
2727
investor_zkproof_data::{v1, v2},
28-
AuthorizationData, Claim, CountryCode, IdentityId, InvestorUid, Permissions, Scope, ScopeId,
29-
SecondaryKey, Signatory,
28+
secondary_key::DispatchableNames,
29+
AssetPermissions, AuthorizationData, Claim, CountryCode, DispatchableName,
30+
ExtrinsicPermissions, IdentityId, InvestorUid, PalletName, PalletPermissions, Permissions,
31+
PortfolioId, PortfolioNumber, PortfolioPermissions, Scope, ScopeId, SecondaryKey, Signatory,
3032
};
3133
use sp_core::H512;
3234
use sp_std::prelude::*;
@@ -132,11 +134,19 @@ pub fn generate_secondary_keys<T: Config>(n: usize) -> Vec<SecondaryKey<T::Accou
132134
#[cfg(feature = "running-ci")]
133135
mod limits {
134136
pub const MAX_SECONDARY_KEYS: u32 = 2;
137+
pub const MAX_ASSETS: u32 = 4;
138+
pub const MAX_PORTFOLIOS: u32 = 4;
139+
pub const MAX_PALLETS: u32 = 4;
140+
pub const MAX_EXTRINSICS: u32 = 4;
135141
}
136142

137143
#[cfg(not(feature = "running-ci"))]
138144
mod limits {
139145
pub const MAX_SECONDARY_KEYS: u32 = 100;
146+
pub const MAX_ASSETS: u32 = 100;
147+
pub const MAX_PORTFOLIOS: u32 = 100;
148+
pub const MAX_PALLETS: u32 = 100;
149+
pub const MAX_EXTRINSICS: u32 = 100;
140150
}
141151

142152
use limits::*;
@@ -295,6 +305,50 @@ benchmarks! {
295305
Module::<T>::unsafe_join_identity(target.did(), Permissions::empty(), key.account());
296306
}: _(target.origin, signatory, Permissions::default().into())
297307

308+
permissions_cost {
309+
// Number of assets/portfolios/pallets/extrinsics.
310+
let a in 0 .. MAX_ASSETS; // a=(A)ssets
311+
let p in 0 .. MAX_PORTFOLIOS; // p=(P)ortfolios
312+
let l in 0 .. MAX_PALLETS; // l=pa(L)lets
313+
let e in 0 .. MAX_EXTRINSICS; // e=(E)xtrinsics
314+
315+
let asset = AssetPermissions::elems(
316+
(0..a as u64).map(Ticker::generate_into)
317+
);
318+
let portfolio = PortfolioPermissions::elems(
319+
(0..p as u128).map(|did| {
320+
PortfolioId::user_portfolio(did.into(), PortfolioNumber(0))
321+
})
322+
);
323+
let dispatchable_names = DispatchableNames::elems(
324+
(0..e as u64).map(|e| {
325+
DispatchableName(Ticker::generate(e))
326+
})
327+
);
328+
let extrinsic = ExtrinsicPermissions::elems(
329+
(0..l as u64).map(|p| {
330+
PalletPermissions {
331+
pallet_name: PalletName(Ticker::generate(p)),
332+
dispatchable_names: dispatchable_names.clone(),
333+
}
334+
})
335+
);
336+
337+
let permissions = Permissions {
338+
asset,
339+
extrinsic,
340+
portfolio
341+
};
342+
343+
let orig = permissions.clone();
344+
}: {
345+
let enc = permissions.encode();
346+
// Panic the benchmarks if decoding fails.
347+
let perm = Permissions::decode(&mut enc.as_slice())
348+
.expect("Permissions should decode correctly.");
349+
assert_eq!(orig, perm);
350+
}
351+
298352
freeze_secondary_keys {
299353
let caller = user::<T>("caller", 0);
300354
}: _(caller.origin)

pallets/identity/src/lib.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -397,15 +397,15 @@ decl_module! {
397397
/// Sets permissions for an specific `target_key` key.
398398
///
399399
/// Only the primary key of an identity is able to set secondary key permissions.
400-
#[weight = <T as Config>::WeightInfo::set_permission_to_signer()]
400+
#[weight = <T as Config>::WeightInfo::set_permission_to_signer_full(&perms)]
401401
pub fn set_permission_to_signer(origin, signer: Signatory<T::AccountId>, perms: Permissions) {
402402
Self::base_set_permission_to_signer(origin, signer, perms)?;
403403
}
404404

405405
/// This function is a workaround for https://github.com/polkadot-js/apps/issues/3632
406406
/// It sets permissions for an specific `target_key` key.
407407
/// Only the primary key of an identity is able to set secondary key permissions.
408-
#[weight = <T as Config>::WeightInfo::set_permission_to_signer()]
408+
#[weight = <T as Config>::WeightInfo::legacy_set_permission_to_signer_full(&permissions)]
409409
pub fn legacy_set_permission_to_signer(
410410
origin,
411411
signer: Signatory<T::AccountId>,
@@ -431,7 +431,7 @@ decl_module! {
431431

432432
// Manage generic authorizations
433433
/// Adds an authorization.
434-
#[weight = <T as Config>::WeightInfo::add_authorization()]
434+
#[weight = <T as Config>::WeightInfo::add_authorization_full::<T::AccountId>(&data)]
435435
pub fn add_authorization(
436436
origin,
437437
target: Signatory<T::AccountId>,
@@ -465,7 +465,7 @@ decl_module! {
465465
/// Failure
466466
/// - It can only called by primary key owner.
467467
/// - Keys should be able to linked to any identity.
468-
#[weight = <T as Config>::WeightInfo::add_secondary_keys_with_authorization(additional_keys.len() as u32)]
468+
#[weight = <T as Config>::WeightInfo::add_secondary_keys_full::<T::AccountId>(&additional_keys)]
469469
pub fn add_secondary_keys_with_authorization(
470470
origin,
471471
additional_keys: Vec<SecondaryKeyWithAuth<T::AccountId>>,

pallets/weights/src/pallet_identity.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,17 @@ impl pallet_identity::WeightInfo for WeightInfo {
118118
.saturating_add(DbWeight::get().reads(4 as Weight))
119119
.saturating_add(DbWeight::get().writes(1 as Weight))
120120
}
121+
fn permissions_cost(a: u32, p: u32, l: u32, e: u32) -> Weight {
122+
(0 as Weight)
123+
// Standard Error: 200_000
124+
.saturating_add((1_254_000 as Weight).saturating_mul(a as Weight))
125+
// Standard Error: 200_000
126+
.saturating_add((1_027_000 as Weight).saturating_mul(p as Weight))
127+
// Standard Error: 200_000
128+
.saturating_add((75_415_000 as Weight).saturating_mul(l as Weight))
129+
// Standard Error: 200_000
130+
.saturating_add((72_009_000 as Weight).saturating_mul(e as Weight))
131+
}
121132
fn freeze_secondary_keys() -> Weight {
122133
(56_201_000 as Weight)
123134
.saturating_add(DbWeight::get().reads(4 as Weight))

primitives/src/secondary_key.rs

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ use sp_runtime::{Deserialize, Serialize};
2020
use sp_std::{
2121
cmp::{Ord, Ordering, PartialOrd},
2222
collections::btree_set::BTreeSet,
23+
convert::TryInto,
2324
iter,
2425
mem::size_of,
2526
};
@@ -88,6 +89,11 @@ impl PalletPermissions {
8889
cost.saturating_add(name_complexity(&dispatch_name))
8990
})
9091
}
92+
93+
/// Return the number of dispatchable names.
94+
pub fn dispatchables_len(&self) -> usize {
95+
self.dispatchable_names.complexity()
96+
}
9197
}
9298

9399
/// Extrinsic permissions.
@@ -180,6 +186,28 @@ impl Permissions {
180186
.saturating_mul(size_of::<PortfolioId>()),
181187
)
182188
}
189+
190+
/// Return number of assets, portfolios, pallets, and extrinsics.
191+
///
192+
/// This is used for weight calculation.
193+
pub fn get_weights(&self) -> (u32, u32, u32, u32) {
194+
// Count the number of assets.
195+
let assets = self.asset.complexity().try_into().unwrap_or(u32::MAX);
196+
// Count the number of portfolios.
197+
let portfolios = self.portfolio.complexity().try_into().unwrap_or(u32::MAX);
198+
// Count the number of pallets.
199+
let pallets = self.extrinsic.complexity().try_into().unwrap_or(u32::MAX);
200+
// Count the total number of extrinsics.
201+
let extrinsics = self
202+
.extrinsic
203+
.fold(0usize, |count, pallet| {
204+
count.saturating_add(pallet.dispatchables_len())
205+
})
206+
.try_into()
207+
.unwrap_or(u32::MAX);
208+
209+
(assets, portfolios, pallets, extrinsics)
210+
}
183211
}
184212

185213
/// It supports different elements as a signer.
@@ -373,6 +401,7 @@ pub mod api {
373401
use codec::{Decode, Encode};
374402
#[cfg(feature = "std")]
375403
use sp_runtime::{Deserialize, Serialize};
404+
use sp_std::convert::TryInto;
376405
use sp_std::vec::Vec;
377406

378407
/// A permission to call functions within a given pallet.
@@ -419,6 +448,34 @@ pub mod api {
419448
portfolio: SubsetRestriction::empty(),
420449
}
421450
}
451+
452+
/// Return number of assets, portfolios, pallets, and extrinsics.
453+
///
454+
/// This is used for weight calculation.
455+
pub fn get_weights(&self) -> (u32, u32, u32, u32) {
456+
// Count the number of assets.
457+
let assets = self.asset.complexity().try_into().unwrap_or(u32::MAX);
458+
// Count the number of portfolios.
459+
let portfolios = self.portfolio.complexity().try_into().unwrap_or(u32::MAX);
460+
// Count the number of pallets and total number of extrinsics.
461+
let (pallets, extrinsics) = match &self.extrinsic.0 {
462+
Some(pallets) => {
463+
let num_pallets = pallets.len().try_into().unwrap_or(u32::MAX);
464+
// Count all extrinsics.
465+
let extrinsics = pallets
466+
.iter()
467+
.fold(0usize, |count, pallet| {
468+
count.saturating_add(pallet.dispatchable_names.len())
469+
})
470+
.try_into()
471+
.unwrap_or(u32::MAX);
472+
(num_pallets, extrinsics)
473+
}
474+
None => (0, 0),
475+
};
476+
477+
(assets, portfolios, pallets, extrinsics)
478+
}
422479
}
423480

424481
/// The same secondary key object without the extra trait constraints.

0 commit comments

Comments
 (0)