Skip to content

Commit

Permalink
ADD: digital twin v2 storage
Browse files Browse the repository at this point in the history
  • Loading branch information
dkuanyshbaev committed Oct 1, 2024
1 parent 492b059 commit 135ca33
Show file tree
Hide file tree
Showing 7 changed files with 327 additions and 0 deletions.
17 changes: 17 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

31 changes: 31 additions & 0 deletions frame/digital-twin-v2/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
[package]
name = "pallet-robonomics-digital-twin-v2"
description = "Robonomics Network digital twin runtime module version 2"
version = "0.1.0"
authors = ["Airalab <[email protected]>"]
edition = "2021"

[dependencies]
log = { workspace = true }
scale-info = { workspace = true }
parity-scale-codec = { workspace = true }
sp-std = { workspace = true }
sp-core = { workspace = true }
sp-runtime = { workspace = true }
frame-system = { workspace = true }
frame-support = { workspace = true }

[dev-dependencies]
sp-io = { workspace = true }

[features]
default = ["std"]
std = [
"parity-scale-codec/std",
"sp-std/std",
"sp-core/std",
"sp-runtime/std",
"frame-system/std",
"frame-support/std",
"scale-info/std",
]
261 changes: 261 additions & 0 deletions frame/digital-twin-v2/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,261 @@
///////////////////////////////////////////////////////////////////////////////
//
// Copyright 2018-2023 Robonomics Network <[email protected]>
//
// 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.
//
///////////////////////////////////////////////////////////////////////////////
//! Digital twin runtime module. This can be compiled with `#[no_std]`, ready for Wasm.
#![cfg_attr(not(feature = "std"), no_std)]

pub use pallet::*;

#[frame_support::pallet]
pub mod pallet {
use frame_support::pallet_prelude::*;
use frame_system::pallet_prelude::*;
use sp_std::collections::{btree_map::BTreeMap, vec_deque::VecDeque};

Check warning on line 27 in frame/digital-twin-v2/src/lib.rs

View workflow job for this annotation

GitHub Actions / clippy

unused import: `vec_deque::VecDeque`

warning: unused import: `vec_deque::VecDeque` --> frame/digital-twin-v2/src/lib.rs:27:52 | 27 | use sp_std::collections::{btree_map::BTreeMap, vec_deque::VecDeque}; | ^^^^^^^^^^^^^^^^^^^ | = note: `#[warn(unused_imports)]` on by default

#[pallet::config]
pub trait Config: frame_system::Config {
/// The overarching event type.
type RuntimeEvent: From<Event<Self>> + IsType<<Self as frame_system::Config>::RuntimeEvent>;

/// The maximum string length for digital twin storage map.
#[pallet::constant]
type MaxLength: Get<u32>;

/// The maximum map length for digital twin.
#[pallet::constant]
type MaxCount: Get<u32>;
}

#[pallet::event]
#[pallet::generate_deposit(pub(super) fn deposit_event)]
pub enum Event<T: Config> {
/// New digital twin record was added: [sender, count, key, value].
DigitalTwinRecordInserted(
T::AccountId,
u32,
BoundedVec<u8, T::MaxLength>,
BoundedVec<u8, T::MaxLength>,
),
/// Digital twin record was updated: [sender, count, key, value].
DigitalTwinRecordUpdated(
T::AccountId,
u32,
BoundedVec<u8, T::MaxLength>,
BoundedVec<u8, T::MaxLength>,
),
/// Digital twin record was removed: [sender, count, key].
DigitalTwinRecordRemoved(T::AccountId, u32, BoundedVec<u8, T::MaxLength>),
}

#[pallet::hooks]

Check warning on line 64 in frame/digital-twin-v2/src/lib.rs

View workflow job for this annotation

GitHub Actions / clippy

unexpected `cfg` condition value: `try-runtime`

warning: unexpected `cfg` condition value: `try-runtime` --> frame/digital-twin-v2/src/lib.rs:64:15 | 64 | #[pallet::hooks] | ^^^^^ | = note: expected values for `feature` are: `default` and `std` = help: consider adding `try-runtime` as a feature in `Cargo.toml` = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg/cargo-specifics.html> for more information about checking conditional configuration = note: `#[warn(unexpected_cfgs)]` on by default
impl<T: Config> Hooks<BlockNumberFor<T>> for Pallet<T> {}

#[pallet::storage]

Check warning on line 67 in frame/digital-twin-v2/src/lib.rs

View workflow job for this annotation

GitHub Actions / clippy

very complex type used. Consider factoring parts into `type` definitions

warning: very complex type used. Consider factoring parts into `type` definitions --> frame/digital-twin-v2/src/lib.rs:67:15 | 67 | #[pallet::storage] | ^^^^^^^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#type_complexity = note: `#[warn(clippy::type_complexity)]` on by default
#[pallet::getter(fn digital_twin)]
/// Digital twin storage format:
/// address -> digital twin (map string -> string).
pub(super) type DigitalTwins<T: Config> = StorageMap<
_,
Twox64Concat,
T::AccountId,
BTreeMap<BoundedVec<u8, T::MaxLength>, BoundedVec<u8, T::MaxLength>>,
>;

#[pallet::pallet]
#[pallet::without_storage_info]
pub struct Pallet<T>(PhantomData<T>);

#[pallet::call]
impl<T: Config> Pallet<T> {
/// Store data in digital twin.
#[pallet::weight(50_000)]

Check warning on line 85 in frame/digital-twin-v2/src/lib.rs

View workflow job for this annotation

GitHub Actions / clippy

this let-binding has unit value

warning: this let-binding has unit value --> frame/digital-twin-v2/src/lib.rs:85:26 | 85 | #[pallet::weight(50_000)] | ^^^^^^ help: omit the `let` binding: `50_000;` | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#let_unit_value

Check warning on line 85 in frame/digital-twin-v2/src/lib.rs

View workflow job for this annotation

GitHub Actions / clippy

use of deprecated constant `pallet::warnings::ConstantWeight_0::_w`: It is deprecated to use hard-coded constant as call weight. Please instead benchmark all calls or put the pallet into `dev` mode. For more info see: <https://github.com/paritytech/substrate/pull/13798>

warning: use of deprecated constant `pallet::warnings::ConstantWeight_0::_w`: It is deprecated to use hard-coded constant as call weight. Please instead benchmark all calls or put the pallet into `dev` mode. For more info see: <https://github.com/paritytech/substrate/pull/13798> --> frame/digital-twin-v2/src/lib.rs:85:26 | 85 | #[pallet::weight(50_000)] | ^^^^^^
pub fn insert(

Check warning on line 86 in frame/digital-twin-v2/src/lib.rs

View workflow job for this annotation

GitHub Actions / clippy

this let-binding has unit value

warning: this let-binding has unit value --> frame/digital-twin-v2/src/lib.rs:86:16 | 86 | pub fn insert( | ^^^^^^ help: omit the `let` binding: `insert;` | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#let_unit_value = note: `#[warn(clippy::let_unit_value)]` on by default

Check warning on line 86 in frame/digital-twin-v2/src/lib.rs

View workflow job for this annotation

GitHub Actions / clippy

use of deprecated constant `pallet::warnings::ImplicitCallIndex_0::_w`: It is deprecated to use implicit call indices. Please instead ensure that all calls have a `pallet::call_index` attribute or put the pallet into `dev` mode. For more info see: <https://github.com/paritytech/substrate/pull/12891> <https://github.com/paritytech/substrate/pull/11381>

warning: use of deprecated constant `pallet::warnings::ImplicitCallIndex_0::_w`: It is deprecated to use implicit call indices. Please instead ensure that all calls have a `pallet::call_index` attribute or put the pallet into `dev` mode. For more info see: <https://github.com/paritytech/substrate/pull/12891> <https://github.com/paritytech/substrate/pull/11381> --> frame/digital-twin-v2/src/lib.rs:86:16 | 86 | pub fn insert( | ^^^^^^ | = note: `#[warn(deprecated)]` on by default
origin: OriginFor<T>,
key: BoundedVec<u8, T::MaxLength>,
value: BoundedVec<u8, T::MaxLength>,
) -> DispatchResultWithPostInfo {
let sender = ensure_signed(origin)?;
<DigitalTwins<T>>::mutate(sender.clone(), |m| match m {
None => {
// Create map and insert.
let mut map = BTreeMap::new();
map.insert(key.clone(), value.clone());
*m = Some(map);
Self::deposit_event(Event::DigitalTwinRecordInserted(sender, 1, key, value));
Ok(().into())
}
Some(map) => {
if map.contains_key(&key.clone()) {
// Update value.
map.insert(key.clone(), value.clone());
Self::deposit_event(Event::DigitalTwinRecordUpdated(
sender,
map.len() as u32,
key,
value,
));
Ok(().into())
} else {
// Insert new key-value pair.
if (map.len() as u32) < T::MaxCount::get() {
map.insert(key.clone(), value.clone());
Self::deposit_event(Event::DigitalTwinRecordInserted(
sender,
map.len() as u32,
key,
value,
));
Ok(().into())
} else {
Err("Max count!".into())
}
}
}
})
}

/// Remove data from digital twin.
#[pallet::weight(50_000)]

Check warning on line 132 in frame/digital-twin-v2/src/lib.rs

View workflow job for this annotation

GitHub Actions / clippy

this let-binding has unit value

warning: this let-binding has unit value --> frame/digital-twin-v2/src/lib.rs:132:26 | 132 | #[pallet::weight(50_000)] | ^^^^^^ help: omit the `let` binding: `50_000;` | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#let_unit_value

Check warning on line 132 in frame/digital-twin-v2/src/lib.rs

View workflow job for this annotation

GitHub Actions / clippy

use of deprecated constant `pallet::warnings::ConstantWeight_1::_w`: It is deprecated to use hard-coded constant as call weight. Please instead benchmark all calls or put the pallet into `dev` mode. For more info see: <https://github.com/paritytech/substrate/pull/13798>

warning: use of deprecated constant `pallet::warnings::ConstantWeight_1::_w`: It is deprecated to use hard-coded constant as call weight. Please instead benchmark all calls or put the pallet into `dev` mode. For more info see: <https://github.com/paritytech/substrate/pull/13798> --> frame/digital-twin-v2/src/lib.rs:132:26 | 132 | #[pallet::weight(50_000)] | ^^^^^^
pub fn remove(

Check warning on line 133 in frame/digital-twin-v2/src/lib.rs

View workflow job for this annotation

GitHub Actions / clippy

this let-binding has unit value

warning: this let-binding has unit value --> frame/digital-twin-v2/src/lib.rs:133:16 | 133 | pub fn remove( | ^^^^^^ help: omit the `let` binding: `remove;` | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#let_unit_value

Check warning on line 133 in frame/digital-twin-v2/src/lib.rs

View workflow job for this annotation

GitHub Actions / clippy

use of deprecated constant `pallet::warnings::ImplicitCallIndex_1::_w`: It is deprecated to use implicit call indices. Please instead ensure that all calls have a `pallet::call_index` attribute or put the pallet into `dev` mode. For more info see: <https://github.com/paritytech/substrate/pull/12891> <https://github.com/paritytech/substrate/pull/11381>

warning: use of deprecated constant `pallet::warnings::ImplicitCallIndex_1::_w`: It is deprecated to use implicit call indices. Please instead ensure that all calls have a `pallet::call_index` attribute or put the pallet into `dev` mode. For more info see: <https://github.com/paritytech/substrate/pull/12891> <https://github.com/paritytech/substrate/pull/11381> --> frame/digital-twin-v2/src/lib.rs:133:16 | 133 | pub fn remove( | ^^^^^^
origin: OriginFor<T>,
key: BoundedVec<u8, T::MaxLength>,
) -> DispatchResultWithPostInfo {
let sender = ensure_signed(origin)?;
<DigitalTwins<T>>::mutate(sender.clone(), |m| match m {
Some(map) => match map.remove(&key) {
None => Err("Unknown key!".into()),
_ => {
Self::deposit_event(Event::DigitalTwinRecordRemoved(
sender,
map.len() as u32,
key,
));
Ok(().into())
}
},
None => Err("Digital twin doesn't exist!".into()),
})
}
}
}

#[cfg(test)]
mod tests {
use crate::{self as digital_twin, *};

use frame_support::{assert_err, assert_ok, parameter_types};
use sp_core::ConstU32;
use sp_runtime::{traits::IdentityLookup, BoundedVec, BuildStorage, DispatchError};

type Block = frame_system::mocking::MockBlock<Runtime>;

frame_support::construct_runtime!(
pub enum Runtime {
System: frame_system,
DigitalTwin: digital_twin,
}
);

parameter_types! {
pub const BlockHashCount: u64 = 250;
}

impl frame_system::Config for Runtime {
type RuntimeOrigin = RuntimeOrigin;
type Nonce = u64;
type Block = Block;
type RuntimeCall = RuntimeCall;
type Hash = sp_core::H256;
type Hashing = sp_runtime::traits::BlakeTwo256;
type AccountId = u64;
type Lookup = IdentityLookup<Self::AccountId>;
type RuntimeEvent = RuntimeEvent;
type BlockHashCount = BlockHashCount;
type Version = ();
type PalletInfo = PalletInfo;
type AccountData = ();
type OnNewAccount = ();
type OnKilledAccount = ();
type DbWeight = ();
type BaseCallFilter = frame_support::traits::Everything;
type SystemWeightInfo = ();
type BlockWeights = ();
type BlockLength = ();
type SS58Prefix = ();
type OnSetCode = ();
type MaxConsumers = frame_support::traits::ConstU32<16>;
}

impl Config for Runtime {
type RuntimeEvent = RuntimeEvent;
type MaxLength = ConstU32<512>;
type MaxCount = ConstU32<256>;
}

fn new_test_ext() -> sp_io::TestExternalities {
let storage = frame_system::GenesisConfig::<Runtime>::default()
.build_storage()
.unwrap();
storage.into()
}

#[test]
fn test_create() {
new_test_ext().execute_with(|| {
let sender = 1;
assert_eq!(DigitalTwin::digital_twin(sender), None);
let key = BoundedVec::new();
let value = BoundedVec::new();
assert_ok!(DigitalTwin::insert(
RuntimeOrigin::signed(sender),
key,
value
));
assert_eq!(DigitalTwin::digital_twin(sender).expect("").len(), 1);
})
}

#[test]
fn test_destroy() {
new_test_ext().execute_with(|| {
let sender = 1;
assert_eq!(DigitalTwin::digital_twin(sender), None);
let key = BoundedVec::new();
let value = BoundedVec::new();
assert_ok!(DigitalTwin::insert(
RuntimeOrigin::signed(sender),
key.clone(),
value
));
assert_eq!(DigitalTwin::digital_twin(sender).expect("").len(), 1);
assert_ok!(DigitalTwin::remove(RuntimeOrigin::signed(sender), key,));
assert_eq!(DigitalTwin::digital_twin(sender).expect("").len(), 0);
})
}

#[test]
fn test_bad_origin() {
new_test_ext().execute_with(|| {
let key = BoundedVec::new();
let value = BoundedVec::new();
assert_err!(
DigitalTwin::insert(RuntimeOrigin::none(), key, value),
DispatchError::BadOrigin
);
})
}
}
2 changes: 2 additions & 0 deletions runtime/dev/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ pallet-robonomics-launch = { path = "../../frame/launch", default-features = fal
pallet-robonomics-datalog = { path = "../../frame/datalog", default-features = false }
pallet-robonomics-liability = { path = "../../frame/liability", default-features = false }
pallet-robonomics-digital-twin = { path = "../../frame/digital-twin", default-features = false }
pallet-robonomics-digital-twin-v2 = { path = "../../frame/digital-twin-v2", default-features = false }

[build-dependencies]
substrate-wasm-builder = { workspace = true }
Expand Down Expand Up @@ -106,6 +107,7 @@ std = [
"pallet-robonomics-datalog/std",
"pallet-robonomics-liability/std",
"pallet-robonomics-digital-twin/std",
"pallet-robonomics-digital-twin-v2/std",
]
runtime-benchmarks = [
"frame-benchmarking",
Expand Down
7 changes: 7 additions & 0 deletions runtime/dev/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -564,6 +564,12 @@ impl pallet_robonomics_digital_twin::Config for Runtime {
type RuntimeEvent = RuntimeEvent;
}

impl pallet_robonomics_digital_twin_v2::Config for Runtime {
type RuntimeEvent = RuntimeEvent;
type MaxLength = ConstU32<512>;
type MaxCount = ConstU32<256>;
}

impl pallet_robonomics_liability::Config for Runtime {
type Agreement = pallet_robonomics_liability::SignedAgreement<
pallet_robonomics_liability::technics::IPFS,
Expand Down Expand Up @@ -610,6 +616,7 @@ construct_runtime!(
Launch: pallet_robonomics_launch,
RWS: pallet_robonomics_rws,
DigitalTwin: pallet_robonomics_digital_twin,
DigitalTwinV2: pallet_robonomics_digital_twin_v2,
Liability: pallet_robonomics_liability,

// Sudo. Usable initially.
Expand Down
2 changes: 2 additions & 0 deletions runtime/main/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ pallet-transaction-payment-rpc-runtime-api = { workspace = true }
# robonomics dependencies
pallet-robonomics-datalog = { path = "../../frame/datalog", default-features = false }
pallet-robonomics-digital-twin = { path = "../../frame/digital-twin", default-features = false }
pallet-robonomics-digital-twin-v2 = { path = "../../frame/digital-twin-v2", default-features = false }
pallet-robonomics-launch = { path = "../../frame/launch", default-features = false }
pallet-robonomics-liability = { path = "../../frame/liability", default-features = false }
pallet-robonomics-lighthouse = { path = "../../frame/lighthouse", default-features = false }
Expand Down Expand Up @@ -118,6 +119,7 @@ std = [
"pallet-transaction-payment-rpc-runtime-api/std",
"pallet-robonomics-datalog/std",
"pallet-robonomics-digital-twin/std",
"pallet-robonomics-digital-twin-v2/std",
"pallet-robonomics-launch/std",
"pallet-robonomics-liability/std",
"pallet-robonomics-lighthouse/std",
Expand Down
Loading

0 comments on commit 135ca33

Please sign in to comment.