diff --git a/Cargo.lock b/Cargo.lock index 765932da..7d096ed8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5573,8 +5573,9 @@ dependencies = [ [[package]] name = "pallet-robonomics-digital-twin" -version = "0.3.0" +version = "3.1.0" dependencies = [ + "frame-benchmarking", "frame-support", "frame-system", "parity-scale-codec", diff --git a/frame/digital-twin/Cargo.toml b/frame/digital-twin/Cargo.toml index 92a128ac..a9e31ea0 100644 --- a/frame/digital-twin/Cargo.toml +++ b/frame/digital-twin/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "pallet-robonomics-digital-twin" description = "Robonomics Network digital twin runtime module" -version = "0.3.0" +version = "3.1.0" authors = ["Airalab "] edition = "2021" @@ -13,6 +13,7 @@ sp-core = { workspace = true } sp-runtime = { workspace = true } frame-system = { workspace = true } frame-support = { workspace = true } +frame-benchmarking = { workspace = true, optional = true } [dev-dependencies] sp-io = { workspace = true } @@ -26,5 +27,12 @@ std = [ "sp-runtime/std", "frame-system/std", "frame-support/std", + "frame-benchmarking/std", "scale-info/std", ] + +runtime-benchmarks = [ + "frame-benchmarking", + "frame-support/runtime-benchmarks", + "frame-system/runtime-benchmarks", +] diff --git a/frame/digital-twin/src/benchmarking.rs b/frame/digital-twin/src/benchmarking.rs new file mode 100644 index 00000000..ceac6b57 --- /dev/null +++ b/frame/digital-twin/src/benchmarking.rs @@ -0,0 +1,80 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// Copyright 2018-2024 Robonomics Network +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +/////////////////////////////////////////////////////////////////////////////// +// Benchmarks for Digital Twin Pallet + +use super::{Pallet as DigitalTwin, *}; +use frame_benchmarking::{account, benchmarks, impl_benchmark_test_suite}; +use frame_system::RawOrigin; +use sp_core::H256; +use sp_std::prelude::*; + +const SEED: u32 = 0; + +benchmarks! { + + create { + let caller: T::AccountId = account("caller", 1, SEED); + + DigitalTwin::::create(RawOrigin::Signed(caller.clone()).into())?; + }: _(RawOrigin::Signed(caller)) + + set_source { + let caller: T::AccountId = account("caller", 1, SEED); + let id: u32 = 0; + let topic: H256 = Default::default(); + let source: T::AccountId = account("caller", 2, SEED); + + DigitalTwin::::create(RawOrigin::Signed(caller.clone()).into())?; + DigitalTwin::::set_source( + RawOrigin::Signed(caller.clone()).into(), + id, + topic, + source.clone(), + )?; + }: _(RawOrigin::Signed(caller), id, topic, source) + + remove_source { + let caller: T::AccountId = account("caller", 1, SEED); + let id: u32 = 0; + let topic: H256 = Default::default(); + let source: T::AccountId = account("caller", 2, SEED); + + DigitalTwin::::create(RawOrigin::Signed(caller.clone()).into())?; + DigitalTwin::::set_source( + RawOrigin::Signed(caller.clone()).into(), + id, + topic, + source.clone(), + )?; + DigitalTwin::::remove_source( + RawOrigin::Signed(caller.clone()).into(), + id, + topic, + source.clone(), + )?; + }: _(RawOrigin::Signed(caller), id, topic, source) + + verify { + } +} + +impl_benchmark_test_suite!( + DigitalTwin, + crate::tests::new_test_ext(), + crate::tests::Runtime, +); diff --git a/frame/digital-twin/src/lib.rs b/frame/digital-twin/src/lib.rs index 3b36432d..5fb416cf 100644 --- a/frame/digital-twin/src/lib.rs +++ b/frame/digital-twin/src/lib.rs @@ -18,10 +18,16 @@ //! Digital twin runtime module. This can be compiled with `#[no_std]`, ready for Wasm. #![cfg_attr(not(feature = "std"), no_std)] +#[cfg(feature = "runtime-benchmarks")] +mod benchmarking; +pub mod weights; + pub use pallet::*; +pub use weights::WeightInfo; #[frame_support::pallet] pub mod pallet { + use super::*; use frame_support::pallet_prelude::*; use frame_system::pallet_prelude::*; use sp_core::H256; @@ -31,6 +37,8 @@ pub mod pallet { pub trait Config: frame_system::Config { /// The overarching event type. type RuntimeEvent: From> + IsType<::RuntimeEvent>; + /// Weight information for extrinsics in this pallet. + type WeightInfo: WeightInfo; } #[pallet::event] @@ -70,7 +78,8 @@ pub mod pallet { #[pallet::call] impl Pallet { /// Create new digital twin. - #[pallet::weight(50_000)] + #[pallet::weight(T::WeightInfo::create())] + #[pallet::call_index(0)] pub fn create(origin: OriginFor) -> DispatchResultWithPostInfo { let sender = ensure_signed(origin)?; let id = >::get().unwrap_or(0); @@ -81,7 +90,8 @@ pub mod pallet { } /// Set data source account for difital twin. - #[pallet::weight(50_000)] + #[pallet::weight(T::WeightInfo::set_source())] + #[pallet::call_index(1)] pub fn set_source( origin: OriginFor, id: u32, @@ -106,6 +116,29 @@ pub mod pallet { }); Ok(().into()) } + + /// Remove data source account for difital twin. + #[pallet::weight(T::WeightInfo::remove_source())] + #[pallet::call_index(2)] + pub fn remove_source( + origin: OriginFor, + id: u32, + topic: H256, + source: T::AccountId, + ) -> DispatchResultWithPostInfo { + let sender = ensure_signed(origin)?; + ensure!( + >::get(id) == Some(sender.clone()), + "sender should be a twin owner" + ); + Self::deposit_event(Event::TopicChanged(sender, id, topic, source.clone())); + >::mutate(id, |m| { + if let Some(map) = m { + map.remove(&topic); + } + }); + Ok(().into()) + } } } @@ -159,7 +192,7 @@ mod tests { type RuntimeEvent = RuntimeEvent; } - fn new_test_ext() -> sp_io::TestExternalities { + pub fn new_test_ext() -> sp_io::TestExternalities { let storage = frame_system::GenesisConfig::::default() .build_storage() .unwrap(); @@ -201,6 +234,37 @@ mod tests { }) } + #[test] + fn test_remove_source() { + new_test_ext().execute_with(|| { + let sender = 1; + let bad_sender = 2; + let source = 3; + assert_ok!(DigitalTwin::create(RuntimeOrigin::signed(sender))); + assert_ok!(DigitalTwin::set_source( + RuntimeOrigin::signed(sender), + 0, + Default::default(), + source + )); + assert_err!( + DigitalTwin::remove_source( + RuntimeOrigin::signed(bad_sender), + 0, + Default::default(), + source + ), + DispatchError::Other("sender should be a twin owner") + ); + assert_ok!(DigitalTwin::remove_source( + RuntimeOrigin::signed(sender), + 0, + Default::default(), + source + )); + }) + } + #[test] fn test_bad_origin() { new_test_ext().execute_with(|| { diff --git a/frame/digital-twin/src/weights.rs b/frame/digital-twin/src/weights.rs new file mode 100644 index 00000000..2832d139 --- /dev/null +++ b/frame/digital-twin/src/weights.rs @@ -0,0 +1,86 @@ +//! Autogenerated weights for `robonomics_digital_twin` +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2024-10-06, STEPS: `20`, REPEAT: `10`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! WORST CASE MAP SIZE: `1000000` +//! CPU: `11th Gen Intel(R) Core(TM) i5-1130G7 @ 1.10GHz` +//! EXECUTION: ``, WASM-EXECUTION: `Compiled`, CHAIN: `Some("dev")`, DB CACHE: 1024 + +// Executed Command: +// ./target/release/robonomics +// benchmark +// pallet +// --chain +// dev +// --pallet +// robonomics_digital_twin +// --extrinsic +// * +// --steps +// 20 +// --repeat +// 10 +// --output +// ~/weights.rs + +#![cfg_attr(rustfmt, rustfmt_skip)] +#![allow(unused_parens)] +#![allow(unused_imports)] +#![allow(missing_docs)] + +use frame_support::{traits::Get, weights::Weight}; +use core::marker::PhantomData; + +/// Weight functions. +pub trait WeightInfo { + fn create() -> Weight; + fn set_source() -> Weight; + fn remove_source() -> Weight; +} + +/// Weight functions for `robonomics_digital_twin`. +pub struct RobonomicsWeight(PhantomData); +impl WeightInfo for RobonomicsWeight { + /// Storage: `DigitalTwin::Total` (r:1 w:1) + /// Proof: `DigitalTwin::Total` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `DigitalTwin::Owner` (r:0 w:1) + /// Proof: `DigitalTwin::Owner` (`max_values`: None, `max_size`: None, mode: `Measured`) + fn create() -> Weight { + // Proof Size summary in bytes: + // Measured: `103` + // Estimated: `1588` + // Minimum execution time: 13_684_000 picoseconds. + Weight::from_parts(14_382_000, 0) + .saturating_add(Weight::from_parts(0, 1588)) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(2)) + } + /// Storage: `DigitalTwin::Owner` (r:1 w:0) + /// Proof: `DigitalTwin::Owner` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `DigitalTwin::DigitalTwin` (r:1 w:1) + /// Proof: `DigitalTwin::DigitalTwin` (`max_values`: None, `max_size`: None, mode: `Measured`) + fn set_source() -> Weight { + // Proof Size summary in bytes: + // Measured: `234` + // Estimated: `3699` + // Minimum execution time: 17_211_000 picoseconds. + Weight::from_parts(17_931_000, 0) + .saturating_add(Weight::from_parts(0, 3699)) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(1)) + } + /// Storage: `DigitalTwin::Owner` (r:1 w:0) + /// Proof: `DigitalTwin::Owner` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `DigitalTwin::DigitalTwin` (r:1 w:1) + /// Proof: `DigitalTwin::DigitalTwin` (`max_values`: None, `max_size`: None, mode: `Measured`) + fn remove_source() -> Weight { + // Proof Size summary in bytes: + // Measured: `166` + // Estimated: `3631` + // Minimum execution time: 16_309_000 picoseconds. + Weight::from_parts(16_437_000, 0) + .saturating_add(Weight::from_parts(0, 3631)) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(1)) + } +} diff --git a/runtime/dev/Cargo.toml b/runtime/dev/Cargo.toml index 03e5f147..78b86118 100644 --- a/runtime/dev/Cargo.toml +++ b/runtime/dev/Cargo.toml @@ -118,6 +118,7 @@ runtime-benchmarks = [ "pallet-timestamp/runtime-benchmarks", "pallet-robonomics-launch/runtime-benchmarks", "pallet-robonomics-datalog/runtime-benchmarks", + "pallet-robonomics-digital-twin/runtime-benchmarks", "frame-system-benchmarking", "hex-literal", ] diff --git a/runtime/dev/src/lib.rs b/runtime/dev/src/lib.rs index f0e92679..4663256b 100644 --- a/runtime/dev/src/lib.rs +++ b/runtime/dev/src/lib.rs @@ -562,6 +562,7 @@ impl pallet_robonomics_rws::Config for Runtime { impl pallet_robonomics_digital_twin::Config for Runtime { type RuntimeEvent = RuntimeEvent; + type WeightInfo = pallet_robonomics_digital_twin::weights::RobonomicsWeight; } impl pallet_robonomics_liability::Config for Runtime { @@ -667,6 +668,7 @@ mod benches { // Robonomics pallets [robonomics_datalog, Datalog] [robonomics_launch, Launch] + [robonomics_digital_twin, DigitalTwin] ); } diff --git a/runtime/main/Cargo.toml b/runtime/main/Cargo.toml index 0c8acdd1..d5e0a05e 100644 --- a/runtime/main/Cargo.toml +++ b/runtime/main/Cargo.toml @@ -149,6 +149,7 @@ runtime-benchmarks = [ "pallet-timestamp/runtime-benchmarks", "pallet-robonomics-launch/runtime-benchmarks", "pallet-robonomics-datalog/runtime-benchmarks", + "pallet-robonomics-digital-twin/runtime-benchmarks", "pallet-xcm/runtime-benchmarks", "xcm-builder/runtime-benchmarks", "frame-system-benchmarking", diff --git a/runtime/main/src/lib.rs b/runtime/main/src/lib.rs index ae16d4b2..4ea0df4a 100644 --- a/runtime/main/src/lib.rs +++ b/runtime/main/src/lib.rs @@ -617,6 +617,7 @@ impl pallet_robonomics_rws::Config for Runtime { impl pallet_robonomics_digital_twin::Config for Runtime { type RuntimeEvent = RuntimeEvent; + type WeightInfo = pallet_robonomics_digital_twin::weights::RobonomicsWeight; } impl pallet_robonomics_liability::Config for Runtime { @@ -729,6 +730,7 @@ mod benches { // Robonomics pallets [robonomics_datalog, Datalog] [robonomics_launch, Launch] + [robonomics_digital_twin, DigitalTwin] ); }