Skip to content

Commit

Permalink
First stab at the process validation pallet (#34)
Browse files Browse the repository at this point in the history
This lays the foundations for the process validation storage and evaluation pallet. There's no real functionality yet but what I have done is:

* created a new pallet `pallet-process-validation` which will store and manage the creation/disabling of process restrictions
* loosely coupled the new pallet to `pallet-simple-nft` via a shared trait and a struct that can describe a process input or output `ProcessIO`
* boiler plate for tests, benchmarking, weights

Types will need updating elsewhere
  • Loading branch information
mattdean-digicatapult authored Jan 31, 2022
1 parent 19b2ded commit 5ef50b9
Show file tree
Hide file tree
Showing 18 changed files with 512 additions and 17 deletions.
31 changes: 29 additions & 2 deletions Cargo.lock

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

13 changes: 13 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ In order to use the API within `polkadot.js` you'll need to configure the follow
"TokenMetadataValue": "MetadataValue",
"Token": {
"id": "TokenId",
"original_id": "TokenId",
"roles": "BTreeMap<RoleKey, AccountId>",
"creator": "AccountId",
"created_at": "BlockNumber",
Expand All @@ -133,6 +134,18 @@ In order to use the API within `polkadot.js` you'll need to configure the follow
},
"Role": {
"_enum": ["Owner", "Customer", "AdditiveManufacturer", "Laboratory", "Buyer", "Supplier", "Reviewer"]
},
"ProcessIdentifier": "[u8; 32]",
"ProcessVersion": "u32",
"Process": {
"status": "ProcessStatus",
"restrictions": "Vec<Restriction>"
},
"ProcessStatus": {
"_enum": ["Disabled", "Enabled"]
},
"Restriction": {
"_enum": ["None"]
}
}
```
Expand Down
2 changes: 1 addition & 1 deletion node/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ edition = '2018'
license = 'Apache-2.0'
repository = 'https://github.com/digicatapult/vitalam-node/'
name = 'vitalam-node'
version = '2.7.1'
version = '2.8.0'

[[bin]]
name = 'vitalam-node'
Expand Down
50 changes: 50 additions & 0 deletions pallets/process-validation/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
[package]
authors = ['Digital Catapult <https://www.digicatapult.org.uk>']
description = 'A FRAME pallet for storing and evaluating process validation restrictions'
edition = '2018'
license = 'Apache-2.0'
repository = 'https://github.com/digicatapult/vitalam-node/'
name = 'pallet-process-validation'
version = "1.0.0"


[package.metadata.docs.rs]
targets = ['x86_64-unknown-linux-gnu']


# alias "parity-scale-code" to "codec"
[dependencies.codec]
default-features = false
features = ['derive']
package = 'parity-scale-codec'
version = '2.0.0'


[dependencies]
vitalam-pallet-traits = { version = '1.0.0', default-features = false, path = '../traits' }
frame-support = { default-features = false, version = '3.0.0' }
frame-system = { default-features = false, version = '3.0.0' }
frame-benchmarking = { default-features = false, optional = true, version = '3.0.0' }
sp-runtime = { default-features = false, version = '3.0.0' }
sp-io = { default-features = false, version = '3.0.0' }
sp-std = { default-features = false, version = '3.0.0' }


[dev-dependencies]
serde = { version = "1.0.119" }
sp-core = { default-features = false, version = '3.0.0' }
sp-io = { default-features = false, version = '3.0.0' }
sp-runtime = { default-features = false, version = '3.0.0' }


[features]
default = ['std']
std = [
'codec/std',
'frame-support/std',
'frame-system/std',
'frame-benchmarking/std',
'sp-std/std',
'vitalam-pallet-traits/std',
]
runtime-benchmarks = ['frame-benchmarking']
25 changes: 25 additions & 0 deletions pallets/process-validation/src/benchmarking.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// ! Benchmarking setup for pallet-template

use super::*;

use frame_benchmarking::{benchmarks, impl_benchmark_test_suite};
use frame_system::RawOrigin;
use sp_std::{boxed::Box, vec, vec::Vec};

#[allow(unused)]
use crate::Module as ProcessValidation;

// TODO implement benchmarking
benchmarks! {
create_process {
}: _(RawOrigin::Root)
verify {
}

disable_process {
}: _(RawOrigin::Root)
verify {
}
}

impl_benchmark_test_suite!(ProcessValidation, crate::mock::new_test_ext(), crate::mock::Test,);
146 changes: 146 additions & 0 deletions pallets/process-validation/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
#![cfg_attr(not(feature = "std"), no_std)]

use codec::{Decode, Encode};
pub use pallet::*;
use sp_std::prelude::*;

use vitalam_pallet_traits::{ProcessIO, ProcessValidator};

#[cfg(test)]
mod tests;

#[cfg(feature = "runtime-benchmarks")]
mod benchmarking;

// import the restrictions module where all our restriction types are defined
mod restrictions;
use restrictions::{Restriction};

#[derive(Encode, Decode, Clone, PartialEq)]
#[cfg_attr(feature = "std", derive(Debug))]
pub enum ProcessStatus {
Disabled,
Enabled
}

impl Default for ProcessStatus {
fn default() -> Self {
ProcessStatus::Disabled
}
}

#[derive(Encode, Decode, Default, Clone, PartialEq)]
#[cfg_attr(feature = "std", derive(Debug))]
pub struct Process {
status: ProcessStatus,
restrictions: Vec<Restriction>
}

pub mod weights;

pub use weights::WeightInfo;

#[frame_support::pallet]
pub mod pallet {

use super::*;
use frame_support::pallet_prelude::*;
use frame_system::pallet_prelude::*;
use sp_runtime::traits::AtLeast32Bit;

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

// The primary identifier for a process (i.e. it's name)
type ProcessIdentifier: Parameter;
type ProcessVersion: Parameter + AtLeast32Bit;

// Origins for calling these extrinsics. For now these are expected to be root
type CreateProcessOrigin: EnsureOrigin<Self::Origin>;
type DisableProcessOrigin: EnsureOrigin<Self::Origin>;

type RoleKey: Parameter + Default + Ord;
type TokenMetadataKey: Parameter + Default + Ord;
type TokenMetadataValue: Parameter + Default;

// Origin for overriding weight calculation implementation
type WeightInfo: WeightInfo;
}

#[pallet::pallet]
#[pallet::generate_store(pub(super) trait Store)]
pub struct Pallet<T>(PhantomData<T>);

#[pallet::hooks]
impl<T: Config> Hooks<BlockNumberFor<T>> for Pallet<T> {}

/// Storage map definition
#[pallet::storage]
#[pallet::getter(fn processes_by_id_and_version)]
pub(super) type ProcessesByIdAndVersion<T: Config> = StorageDoubleMap<
_,
Blake2_128Concat,
T::ProcessIdentifier,
Blake2_128Concat,
T::ProcessVersion,
Process,
ValueQuery
>;

#[pallet::event]
#[pallet::generate_deposit(pub(super) fn deposit_event)]
pub enum Event<T: Config> {
// TODO: implement correct events for extrinsics including params
ProcessCreated,
ProcessDisabled
}

#[pallet::error]
pub enum Error<T> {
// TODO: implement errors for extrinsics
}

// The pallet's dispatchable functions.
#[pallet::call]
impl<T: Config> Pallet<T> {
// TODO: implement create_process with correct parameters and impl
#[pallet::weight(T::WeightInfo::create_process())]
pub(super) fn create_process(
origin: OriginFor<T>
) -> DispatchResultWithPostInfo {
// Check it was signed and get the signer
T::CreateProcessOrigin::ensure_origin(origin)?;

Self::deposit_event(Event::ProcessCreated);
Ok(().into())
}

// TODO: implement disable_process with correct parameters and impl
#[pallet::weight(T::WeightInfo::disable_process())]
pub(super) fn disable_process(
origin: OriginFor<T>
) -> DispatchResultWithPostInfo {
T::DisableProcessOrigin::ensure_origin(origin)?;
Self::deposit_event(Event::ProcessDisabled);
Ok(().into())
}
}
}

impl<T: Config> ProcessValidator<T::AccountId, T::RoleKey, T::TokenMetadataKey, T::TokenMetadataValue> for Pallet<T> {
type ProcessIdentifier = T::ProcessIdentifier;
type ProcessVersion = T::ProcessVersion;

// TODO: implement lookup of process and checking of restrictions
fn validate_process(
_id: T::ProcessIdentifier,
_version: T::ProcessVersion,
_sender: T::AccountId,
_inputs: &Vec<ProcessIO<T::AccountId, T::RoleKey, T::TokenMetadataKey, T::TokenMetadataValue>>,
_outputs: &Vec<ProcessIO<T::AccountId, T::RoleKey, T::TokenMetadataKey, T::TokenMetadataValue>>) -> bool {
true
}
}
27 changes: 27 additions & 0 deletions pallets/process-validation/src/restrictions.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// This file contains the different types of restrictions that can be evaluated during
// a call to `validate_process`

use codec::{Decode, Encode};

#[derive(Encode, Decode, Clone, PartialEq)]
#[cfg_attr(feature = "std", derive(Debug))]
pub enum Restriction {
None
// TODO: implement some actual restrictions
}

impl Default for Restriction {
fn default() -> Self {
Restriction::None
}
}

// TODO: update args appropriately and implement restriction functionality
#[allow(dead_code)]
pub fn validate_restriction(restriction: &Restriction) -> bool {
match *restriction {
Restriction::None => true
// TODO implement some actual restrictions
}
}

Loading

0 comments on commit 5ef50b9

Please sign in to comment.