diff --git a/pallets/contracts/src/benchmarking.rs b/pallets/contracts/src/benchmarking.rs
index 103b6b02ba..c591878473 100644
--- a/pallets/contracts/src/benchmarking.rs
+++ b/pallets/contracts/src/benchmarking.rs
@@ -13,29 +13,38 @@
// You should have received a copy of the GNU General Public License
// along with this program. If not, see .
-use crate::chain_extension::*;
-use crate::*;
-
use codec::Encode;
-use frame_benchmarking::benchmarks;
+use frame_benchmarking::{account, benchmarks};
use frame_support::{storage::unhashed, traits::tokens::currency::Currency};
use frame_system::{Config as SysTrait, Pallet as System, RawOrigin};
+use pallet_contracts::benchmarking::code::body::DynInstr::{Counter, Regular};
use pallet_contracts::benchmarking::code::{
body, max_pages, DataSegment, ImportedFunction, ImportedMemory, Location, ModuleDefinition,
WasmModule,
};
use pallet_contracts::Pallet as FrameContracts;
+use sp_runtime::traits::StaticLookup;
+use sp_runtime::Perbill;
+use sp_std::prelude::*;
+use wasm_instrument::parity_wasm::elements::{Instruction, ValueType};
+
use polymesh_common_utilities::{
benchs::{cdd_provider, user, AccountIdOf, User},
constants::currency::POLY,
group::GroupTrait,
TestUtilsFn,
};
-use polymesh_primitives::{Balance, Permissions};
-use sp_runtime::traits::StaticLookup;
-use sp_runtime::Perbill;
-use sp_std::prelude::*;
-use wasm_instrument::parity_wasm::elements::{Instruction, ValueType};
+use polymesh_primitives::identity::limits::{
+ MAX_ASSETS, MAX_EXTRINSICS, MAX_PALLETS, MAX_PORTFOLIOS,
+};
+use polymesh_primitives::secondary_key::DispatchableNames;
+use polymesh_primitives::{
+ AssetPermissions, Balance, DispatchableName, ExtrinsicPermissions, PalletName,
+ PalletPermissions, Permissions, PortfolioId, PortfolioNumber, PortfolioPermissions, Ticker,
+};
+
+use crate::chain_extension::*;
+use crate::*;
pub(crate) const SEED: u32 = 0;
@@ -145,6 +154,29 @@ fn put_storage_value(key: &[u8], len: u32) -> u32 {
Some(value).encoded_size() as u32
}
+fn secondary_key_permission(
+ n_assets: u64,
+ n_portfolios: u128,
+ n_extrinsics: u64,
+ n_pallets: u64,
+) -> Permissions {
+ let asset = AssetPermissions::elems((0..n_assets).map(Ticker::generate_into));
+ let portfolio = PortfolioPermissions::elems(
+ (0..n_portfolios).map(|did| PortfolioId::user_portfolio(did.into(), PortfolioNumber(0))),
+ );
+ let dispatchable_names =
+ DispatchableNames::elems((0..n_extrinsics).map(|e| DispatchableName(Ticker::generate(e))));
+ let extrinsic = ExtrinsicPermissions::elems((0..n_pallets).map(|p| PalletPermissions {
+ pallet_name: PalletName(Ticker::generate(p)),
+ dispatchable_names: dispatchable_names.clone(),
+ }));
+ Permissions {
+ asset,
+ extrinsic,
+ portfolio,
+ }
+}
+
struct Contract {
caller: User,
addr: ::Source,
@@ -168,6 +200,48 @@ where
}
}
+ /// Creates a contract that will call `seal_call_chain_extension' with `FuncId::GetKeyDid`.
+ fn new_seal_chain_extension(
+ repetitions: u32,
+ input: Vec,
+ key_len: u32,
+ output_len: usize,
+ ) -> Self {
+ let code = WasmModule::::from(ModuleDefinition {
+ memory: Some(ImportedMemory::max::()),
+ imported_functions: vec![ImportedFunction {
+ module: "seal0",
+ name: "seal_call_chain_extension",
+ params: vec![ValueType::I32; 5],
+ return_type: Some(ValueType::I32),
+ }],
+ data_segments: vec![
+ DataSegment {
+ offset: 0,
+ value: input.clone(),
+ },
+ DataSegment {
+ offset: input.len() as u32,
+ value: output_len.to_le_bytes().into(),
+ },
+ ],
+ call_body: Some(body::repeated_dyn(
+ repetitions,
+ vec![
+ Regular(Instruction::I32Const(FuncId::GetKeyDid.into())),
+ Counter(0, key_len),
+ Regular(Instruction::I32Const(key_len as i32)),
+ Regular(Instruction::I32Const(input.len() as i32 + 4)),
+ Regular(Instruction::I32Const(input.len() as i32)),
+ Regular(Instruction::Call(0)),
+ Regular(Instruction::Drop),
+ ],
+ )),
+ ..Default::default()
+ });
+ Self::new(code)
+ }
+
/// Create and setup a contract to call the ChainExtension.
fn chain_extension(repeat: u32, func_id: FuncId, input: Vec, out_len: u32) -> Self {
let in_len = input.len() as u32;
@@ -271,14 +345,36 @@ benchmarks! {
// Benchmark ChainExtension GetKeyDid.
chain_extension_get_key_did {
- let r in 1 .. CHAIN_EXTENSION_BATCHES;
-
- // Construct a user for Key -> Identity lookup.
- let lookup = funded_user::(SEED + 1);
- let key = lookup.account().encode();
-
- // Setup ChainExtension.
- let contract = Contract::::chain_extension(r * CHAIN_EXTENSION_BATCH_SIZE, FuncId::GetKeyDid, key, 33);
+ let r in 1..CHAIN_EXTENSION_BATCHES;
+
+ let secondary_key_permission = secondary_key_permission(
+ MAX_ASSETS as u64,
+ MAX_PORTFOLIOS as u128,
+ MAX_EXTRINSICS as u64,
+ MAX_PALLETS as u64
+ );
+
+ let encoded_accounts = (0..r * CHAIN_EXTENSION_BATCH_SIZE)
+ .map(|i| {
+ let primary_user = funded_user::(SEED + i);
+ let secondary_key: T::AccountId = account("key", i, SEED);
+ Identity::::unsafe_join_identity(
+ primary_user.did(),
+ secondary_key_permission.clone(),
+ secondary_key.clone(),
+ );
+ secondary_key.encode()
+ })
+ .collect::>();
+ let account_len = encoded_accounts.get(0).map(|acc| acc.len()).unwrap_or(0) as u32;
+ let accounts_bytes = encoded_accounts.iter().flat_map(|a| a.clone()).collect::>();
+
+ let contract = Contract::::new_seal_chain_extension(
+ r * CHAIN_EXTENSION_BATCH_SIZE,
+ accounts_bytes,
+ account_len,
+ 33
+ );
}: {
contract.call();
}
diff --git a/pallets/contracts/src/chain_extension.rs b/pallets/contracts/src/chain_extension.rs
index cb561ad049..bacaa65651 100644
--- a/pallets/contracts/src/chain_extension.rs
+++ b/pallets/contracts/src/chain_extension.rs
@@ -332,7 +332,7 @@ where
let mut env = env.buf_in_buf_out();
// Charge weight.
- env.charge_weight(::WeightInfo::get_version())?;
+ env.charge_weight(::WeightInfo::get_key_did())?;
let key: T::AccountId = env.read_as()?;
trace!(
diff --git a/pallets/weights/src/polymesh_contracts.rs b/pallets/weights/src/polymesh_contracts.rs
index bc2b6fb4af..05b573c5d3 100644
--- a/pallets/weights/src/polymesh_contracts.rs
+++ b/pallets/weights/src/polymesh_contracts.rs
@@ -114,7 +114,7 @@ impl polymesh_contracts::WeightInfo for SubstrateWeight {
.saturating_add(DbWeight::get().reads(12))
.saturating_add(DbWeight::get().writes(3))
}
- // Storage: Identity KeyRecords (r:3 w:0)
+ // Storage: Identity KeyRecords (r:2002 w:0)
// Proof Skipped: Identity KeyRecords (max_values: None, max_size: None, mode: Measured)
// Storage: System Account (r:1 w:0)
// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen)
@@ -124,7 +124,7 @@ impl polymesh_contracts::WeightInfo for SubstrateWeight {
// Proof: Contracts CodeStorage (max_values: None, max_size: Some(126001), added: 128476, mode: MaxEncodedLen)
// Storage: Timestamp Now (r:1 w:0)
// Proof: Timestamp Now (max_values: Some(1), max_size: Some(8), added: 503, mode: MaxEncodedLen)
- // Storage: Identity IsDidFrozen (r:1 w:0)
+ // Storage: Identity IsDidFrozen (r:2000 w:0)
// Proof Skipped: Identity IsDidFrozen (max_values: None, max_size: None, mode: Measured)
// Storage: Instance2Group ActiveMembers (r:1 w:0)
// Proof Skipped: Instance2Group ActiveMembers (max_values: Some(1), max_size: None, mode: Measured)
@@ -134,11 +134,12 @@ impl polymesh_contracts::WeightInfo for SubstrateWeight {
// Proof Skipped: System EventTopics (max_values: None, max_size: None, mode: Measured)
/// The range of component `r` is `[1, 20]`.
fn chain_extension_get_key_did(r: u32) -> Weight {
- // Minimum execution time: 1_020_067 nanoseconds.
- Weight::from_ref_time(791_765_615)
- // Standard Error: 3_514_259
- .saturating_add(Weight::from_ref_time(365_418_322).saturating_mul(r.into()))
- .saturating_add(DbWeight::get().reads(13))
+ // Minimum execution time: 230_114_055 nanoseconds.
+ Weight::from_ref_time(234_042_835_000)
+ // Standard Error: 645_494_782
+ .saturating_add(Weight::from_ref_time(219_847_004_564).saturating_mul(r.into()))
+ .saturating_add(DbWeight::get().reads(11))
+ .saturating_add(DbWeight::get().reads((200_u64).saturating_mul(r.into())))
.saturating_add(DbWeight::get().writes(3))
}
// Storage: Identity KeyRecords (r:2 w:0)