-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
- Loading branch information
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
[package] | ||
name = "pallet-robonomics-digital-twin-v2" | ||
description = "Robonomics Network digital twin runtime module" | ||
version = "0.1.0" | ||
authors = ["Airalab <[email protected]>"] | ||
edition = "2021" | ||
|
||
[dependencies] | ||
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", | ||
] |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,203 @@ | ||
/////////////////////////////////////////////////////////////////////////////// | ||
// | ||
// 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_core::H256; | ||
|
||
#[pallet::config] | ||
pub trait Config: frame_system::Config { | ||
/// The overarching event type. | ||
type RuntimeEvent: From<Event<Self>> + IsType<<Self as frame_system::Config>::RuntimeEvent>; | ||
} | ||
|
||
#[pallet::event] | ||
#[pallet::generate_deposit(pub(super) fn deposit_event)] | ||
pub enum Event<T: Config> { | ||
/// New digital twin was registered: [sender, id]. | ||
NewDigitalTwin(T::AccountId, u32), | ||
/// Digital twin topic was changed: [sender, id, topic, source] | ||
TopicChanged(T::AccountId, u32, H256, T::AccountId), | ||
} | ||
|
||
#[pallet::hooks] | ||
impl<T: Config> Hooks<BlockNumberFor<T>> for Pallet<T> {} | ||
|
||
#[pallet::storage] | ||
#[pallet::getter(fn total)] | ||
/// Total count of registered digital twins. | ||
pub(super) type Total<T> = StorageValue<_, u32>; | ||
|
||
#[pallet::storage] | ||
#[pallet::getter(fn owner)] | ||
/// Get owner of digital twin with given id. | ||
pub(super) type Owner<T> = | ||
StorageMap<_, Twox64Concat, u32, <T as frame_system::Config>::AccountId>; | ||
|
||
#[pallet::storage] | ||
#[pallet::getter(fn digital_twin)] | ||
/// Get internal structure of difital twin in format: source account -> topic hash. | ||
pub(super) type DigitalTwin<T> = | ||
StorageMap<_, Twox64Concat, u32, (<T as frame_system::Config>::AccountId, H256)>; | ||
|
||
#[pallet::pallet] | ||
#[pallet::generate_store(pub(super) trait Store)] | ||
Check warning on line 65 in frame/digital-twin-v2/src/lib.rs GitHub Actions / clippyuse of deprecated struct `pallet::_::Store`: Use of `#[pallet::generate_store(pub(super) trait Store)]` will be removed after July 2023. Check https://github.com/paritytech/substrate/pull/13535 for more details.
|
||
#[pallet::without_storage_info] | ||
pub struct Pallet<T>(PhantomData<T>); | ||
|
||
#[pallet::call] | ||
impl<T: Config> Pallet<T> { | ||
/// Create new digital twin. | ||
#[pallet::weight(50_000)] | ||
Check warning on line 72 in frame/digital-twin-v2/src/lib.rs GitHub Actions / clippythis let-binding has unit value
Check warning on line 72 in frame/digital-twin-v2/src/lib.rs GitHub Actions / clippyuse 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>
|
||
pub fn create(origin: OriginFor<T>) -> DispatchResultWithPostInfo { | ||
Check warning on line 73 in frame/digital-twin-v2/src/lib.rs GitHub Actions / clippythis let-binding has unit value
Check warning on line 73 in frame/digital-twin-v2/src/lib.rs GitHub Actions / clippyuse 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>
|
||
let sender = ensure_signed(origin)?; | ||
let id = <Total<T>>::get().unwrap_or(0); | ||
<Total<T>>::put(id + 1); | ||
<Owner<T>>::insert(id, sender.clone()); | ||
Self::deposit_event(Event::NewDigitalTwin(sender, id)); | ||
Ok(().into()) | ||
} | ||
|
||
/// Set data source account for difital twin. | ||
#[pallet::weight(50_000)] | ||
Check warning on line 83 in frame/digital-twin-v2/src/lib.rs GitHub Actions / clippythis let-binding has unit value
Check warning on line 83 in frame/digital-twin-v2/src/lib.rs GitHub Actions / clippyuse 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>
|
||
pub fn set_source( | ||
Check warning on line 84 in frame/digital-twin-v2/src/lib.rs GitHub Actions / clippythis let-binding has unit value
Check warning on line 84 in frame/digital-twin-v2/src/lib.rs GitHub Actions / clippyuse 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>
|
||
origin: OriginFor<T>, | ||
id: u32, | ||
topic: H256, | ||
source: T::AccountId, | ||
) -> DispatchResultWithPostInfo { | ||
let sender = ensure_signed(origin)?; | ||
ensure!( | ||
<Owner<T>>::get(id) == Some(sender.clone()), | ||
"sender should be a twin owner" | ||
); | ||
Self::deposit_event(Event::TopicChanged(sender, id, topic, source.clone())); | ||
<DigitalTwin<T>>::insert(id, (source, topic)); | ||
Ok(().into()) | ||
} | ||
} | ||
} | ||
|
||
#[cfg(test)] | ||
mod tests { | ||
use crate::{self as digital_twin, *}; | ||
|
||
use frame_support::{assert_err, assert_ok, parameter_types}; | ||
use sp_runtime::{traits::IdentityLookup, 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; | ||
} | ||
|
||
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(|| { | ||
assert_eq!(DigitalTwin::total(), None); | ||
let sender = 1; | ||
assert_ok!(DigitalTwin::create(RuntimeOrigin::signed(sender))); | ||
assert_eq!(DigitalTwin::total(), Some(1)); | ||
assert_eq!(DigitalTwin::owner(0), Some(sender)); | ||
}) | ||
} | ||
|
||
#[test] | ||
fn test_set_source() { | ||
new_test_ext().execute_with(|| { | ||
let sender = 1; | ||
let bad_sender = 2; | ||
assert_ok!(DigitalTwin::create(RuntimeOrigin::signed(sender))); | ||
assert_err!( | ||
DigitalTwin::set_source( | ||
RuntimeOrigin::signed(bad_sender), | ||
0, | ||
Default::default(), | ||
bad_sender | ||
), | ||
DispatchError::Other("sender should be a twin owner") | ||
); | ||
assert_ok!(DigitalTwin::set_source( | ||
RuntimeOrigin::signed(sender), | ||
0, | ||
Default::default(), | ||
bad_sender | ||
)); | ||
}) | ||
} | ||
|
||
#[test] | ||
fn test_bad_origin() { | ||
new_test_ext().execute_with(|| { | ||
assert_err!( | ||
DigitalTwin::create(RuntimeOrigin::none()), | ||
DispatchError::BadOrigin | ||
); | ||
}) | ||
} | ||
} |