Mise à jour de GitLab prévue ce samedi 23 octobre 2021 à partir de 9h00 CET

Commit 1108e322 authored by Éloïs's avatar Éloïs
Browse files

feat: integrate StrongCert in runtime

parent fc4052ce
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"type": "lldb",
"request": "launch",
"name": "Debug unit tests in library 'lc-core'",
"cargo": {
"args": [
"test",
"--no-run",
"--lib",
"--package=lc-core"
],
"filter": {
"name": "lc-core",
"kind": "lib"
}
},
"args": [],
"cwd": "${workspaceFolder}"
},
{
"type": "lldb",
"request": "launch",
"name": "Debug executable 'lc-core'",
"cargo": {
"args": [
"build"
],
"filter": {
"name": "lc-core",
"kind": "bin"
}
},
"args": [
"--tmp",
"--dev",
"--execution",
"Native"
],
"cwd": "${workspaceFolder}"
},
{
"type": "lldb",
"request": "launch",
"name": "Debug unit tests in executable 'lc-core'",
"cargo": {
"args": [
"test",
"--no-run",
"--bin=lc-core",
"--package=lc-core"
],
"filter": {
"name": "lc-core",
"kind": "bin"
}
},
"args": [],
"cwd": "${workspaceFolder}"
},
{
"type": "lldb",
"request": "launch",
"name": "Debug unit tests in library 'lc-core-runtime'",
"cargo": {
"args": [
"test",
"--no-run",
"--lib",
"--package=lc-core-runtime"
],
"filter": {
"name": "lc-core-runtime",
"kind": "lib"
}
},
"args": [],
"cwd": "${workspaceFolder}"
},
{
"type": "lldb",
"request": "launch",
"name": "Debug unit tests in library 'pallet-certification'",
"cargo": {
"args": [
"test",
"--no-run",
"--lib",
"--package=pallet-certification"
],
"filter": {
"name": "pallet-certification",
"kind": "lib"
}
},
"args": [],
"cwd": "${workspaceFolder}"
},
{
"type": "lldb",
"request": "launch",
"name": "Debug unit tests in library 'pallet-identity'",
"cargo": {
"args": [
"test",
"--no-run",
"--lib",
"--package=pallet-identity"
],
"filter": {
"name": "pallet-identity",
"kind": "lib"
}
},
"args": [],
"cwd": "${workspaceFolder}"
},
{
"type": "lldb",
"request": "launch",
"name": "Debug unit tests in library 'pallet-ud-accounts-storage'",
"cargo": {
"args": [
"test",
"--no-run",
"--lib",
"--package=pallet-ud-accounts-storage"
],
"filter": {
"name": "pallet-ud-accounts-storage",
"kind": "lib"
}
},
"args": [],
"cwd": "${workspaceFolder}"
},
{
"type": "lldb",
"request": "launch",
"name": "Debug unit tests in library 'pallet-universal-dividend'",
"cargo": {
"args": [
"test",
"--no-run",
"--lib",
"--package=pallet-universal-dividend"
],
"filter": {
"name": "pallet-universal-dividend",
"kind": "lib"
}
},
"args": [],
"cwd": "${workspaceFolder}"
}
]
}
\ No newline at end of file
......@@ -2742,6 +2742,7 @@ dependencies = [
"hex-literal",
"pallet-aura",
"pallet-balances",
"pallet-certification",
"pallet-grandpa",
"pallet-identity",
"pallet-randomness-collective-flip",
......@@ -3910,6 +3911,7 @@ dependencies = [
"frame-benchmarking",
"frame-support",
"frame-system",
"maplit",
"parity-scale-codec",
"serde",
"sp-core",
......
......@@ -7,5 +7,7 @@ members = [
'pallets/universal-dividend',
'runtime',
]
[profile.dev]
opt-level = 3
[profile.release]
panic = 'unwind'
use lc_core_runtime::{
AccountId, AuraConfig, BalancesConfig, GenesisConfig, GrandpaConfig, IdentityConfig, IdtyDid,
IdtyRight, IdtyValue, Planet, Signature, SudoConfig, SystemConfig, UdAccountsStorageConfig,
UniversalDividendConfig, WASM_BINARY,
IdtyIndex, IdtyRight, IdtyValue, Planet, Signature, StrongCertConfig, SudoConfig, SystemConfig,
UdAccountsStorageConfig, UniversalDividendConfig, WASM_BINARY,
};
use maplit::btreemap;
use sc_service::ChainType;
......@@ -9,7 +9,7 @@ use sp_consensus_aura::sr25519::AuthorityId as AuraId;
use sp_core::{sr25519, Pair, Public};
use sp_finality_grandpa::AuthorityId as GrandpaId;
use sp_runtime::traits::{IdentifyAccount, Verify};
use std::collections::BTreeMap;
use std::collections::{BTreeMap, BTreeSet};
/// Specialized `ChainSpec`. This is a specialization of the general Substrate ChainSpec type.
pub type ChainSpec = sc_service::GenericChainSpec<GenesisConfig>;
......@@ -183,11 +183,26 @@ fn testnet_genesis(
identity: IdentityConfig {
identities: initial_identities
.iter()
.map(|(did, account)| {
IdtyValue::new_valid(*did, account.clone(), vec![IdtyRight::Ud])
.map(|(did, account)| IdtyValue {
did: *did,
expire_on: lc_core_runtime::MaxInactivityPeriod::get(),
owner_key: account.clone(),
removable_on: 0,
renewable_on: lc_core_runtime::StrongCertRenewablePeriod::get(),
rights: vec![
(IdtyRight::CreateIdty, None),
(IdtyRight::StrongCert, None),
(IdtyRight::Ud, None),
],
status: lc_core_runtime::IdtyStatus::Validated,
data: Default::default(),
})
.collect(),
},
strong_cert: StrongCertConfig {
certs_by_issuer: clique_wot(initial_identities.len()),
phantom: std::marker::PhantomData,
},
ud_accounts_storage: UdAccountsStorageConfig {
ud_accounts: initial_identities.values().cloned().collect(),
},
......@@ -197,3 +212,16 @@ fn testnet_genesis(
},
}
}
fn clique_wot(initial_identities_len: usize) -> BTreeMap<IdtyIndex, BTreeSet<IdtyIndex>> {
let mut certs_by_issuer = BTreeMap::new();
for i in 1..=initial_identities_len {
certs_by_issuer.insert(
i as IdtyIndex,
(1..=initial_identities_len)
.filter_map(|j| if i != j { Some(j as IdtyIndex) } else { None })
.collect(),
);
}
certs_by_issuer
}
......@@ -75,6 +75,9 @@ version = '1.0.119'
### DEV ###
[dev-dependencies.maplit]
version = '1.0.2'
[dev-dependencies.sp-io]
default-features = false
git = 'https://github.com/paritytech/substrate.git'
......
......@@ -21,19 +21,23 @@ pub mod traits;
#[cfg(test)]
mod mock;
#[cfg(test)]
mod tests;
pub use pallet::*;
use crate::traits::*;
use codec::Codec;
use sp_runtime::traits::{AtLeast32BitUnsigned, Zero};
use sp_std::collections::btree_map::BTreeMap;
use sp_std::collections::btree_set::BTreeSet;
use sp_std::fmt::Debug;
use sp_std::{
collections::{btree_map::BTreeMap, btree_set::BTreeSet},
fmt::Debug,
vec::Vec,
};
pub mod pallet {
use super::*;
use frame_support::pallet_prelude::*;
//use frame_system::pallet_prelude::*;
/// Configure the pallet by specifying the parameters and types on which it depends.
pub trait Config<I: Instance = DefaultInstance>: frame_system::Config {
......@@ -166,7 +170,7 @@ pub mod pallet {
let mut certs_by_receiver = BTreeMap::<T::IdtyIndex, Vec<T::IdtyIndex>>::new();
for (issuer, receivers) in &config.certs_by_issuer {
assert!(!receivers.contains(issuer), "Identity cannot tcertify it-self.");
assert!(!receivers.len() <= T::MaxByIssuer::get() as usize, "Identity n°{:?} exceed MaxByIssuer.", issuer);
assert!(!receivers.len() >= T::MaxByIssuer::get() as usize, "Identity n°{:?} exceed MaxByIssuer.", issuer);
cert_meta_by_issuer.insert(*issuer, IdtyCertMeta {
issued_count: receivers.len() as u8,
......@@ -221,11 +225,13 @@ pub mod pallet {
#[weight = 0]
pub fn add_cert(origin, issuer: T::IdtyIndex, receiver: T::IdtyIndex) {
T::AddCertOrigin::ensure_origin((origin, issuer, receiver))?;
frame_support::runtime_print!("add_cert({:?}, {:?}): origin OK", issuer, receiver);
let block_number = frame_system::pallet::Pallet::<T>::block_number();
let (create, issuer_issued_count) = if let Ok(mut issuer_idty_cert_meta) = <StorageIdtyCertMeta<T, I>>::try_get(issuer) {
// Verify rules CertPeriod and MaxByIssuer
frame_support::runtime_print!("add_cert({:?}, {:?}): Verify rules CertPeriod and MaxByIssuer", issuer, receiver);
if issuer_idty_cert_meta.next_issuable_on > block_number {
return Err(Error::<T, I>::NotRespectCertPeriod.into());
} else if issuer_idty_cert_meta.issued_count >= T::MaxByIssuer::get() {
......@@ -233,6 +239,7 @@ pub mod pallet {
}
// Verify rule RenewablePeriod
frame_support::runtime_print!("add_cert({:?}, {:?}): Verify rule RenewablePeriod", issuer, receiver);
let create = if let Ok(CertValue { chainable_on, .. }) = <StorageCertsByIssuer<T, I>>::try_get(issuer, receiver) {
if chainable_on > block_number {
return Err(Error::<T, I>::NotRespectRenewablePeriod.into());
......@@ -255,6 +262,7 @@ pub mod pallet {
};
// Write StorageIdtyCertMeta for receiver
frame_support::runtime_print!("add_cert({:?}, {:?}): Write StorageIdtyCertMeta for receiver", issuer, receiver);
let receiver_received_count = <StorageIdtyCertMeta<T, I>>::mutate_exists(receiver, |cert_meta_opt| {
let cert_meta = cert_meta_opt.get_or_insert(IdtyCertMeta::default());
cert_meta.received_count = cert_meta.received_count.saturating_add(1);
......@@ -273,7 +281,7 @@ pub mod pallet {
if create {
// Write StorageCertsByReceiver
<StorageCertsByReceiver<T, I>>::mutate_exists(receiver, |issuers_opt| {
let issuers = issuers_opt.get_or_insert(vec![]);
let issuers = issuers_opt.get_or_insert(Vec::with_capacity(0));
if let Err(index) = issuers.binary_search(&issuer) {
issuers.insert(index, issuer);
}
......
......@@ -30,7 +30,7 @@ use sp_runtime::{
type AccountId = u64;
type BlockNumber = u64;
type Block = frame_system::mocking::MockBlock<Test>;
type IdtyIndex = u64;
pub type IdtyIndex = u64;
type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic<Test>;
// Configure a mock runtime to test the pallet.
......@@ -76,18 +76,13 @@ impl system::Config for Test {
type OnSetCode = ();
}
parameter_types! {
pub const MaxByIssuer: u8 = 3;
pub const RenewablePeriod: BlockNumber = 2;
pub const CertPeriod: u64 = 2;
pub const ValidityPeriod: u64 = 5;
}
pub struct EnsureRoot;
impl frame_support::traits::EnsureOrigin<(Origin, IdtyIndex, IdtyIndex)> for EnsureRoot {
type Success = ();
fn try_origin(o: (Origin, IdtyIndex, IdtyIndex)) -> Result<Self::Success, (Origin, IdtyIndex, IdtyIndex)> {
fn try_origin(
o: (Origin, IdtyIndex, IdtyIndex),
) -> Result<Self::Success, (Origin, IdtyIndex, IdtyIndex)> {
match o.0.clone().into() {
Ok(system::RawOrigin::Root) => Ok(()),
_ => Err(o),
......@@ -95,6 +90,13 @@ impl frame_support::traits::EnsureOrigin<(Origin, IdtyIndex, IdtyIndex)> for Ens
}
}
parameter_types! {
pub const MaxByIssuer: u8 = 3;
pub const RenewablePeriod: BlockNumber = 4;
pub const CertPeriod: u64 = 2;
pub const ValidityPeriod: u64 = 10;
}
impl pallet_certification::Config for Test {
type AddCertOrigin = EnsureRoot;
type CertPeriod = CertPeriod;
......
......@@ -14,89 +14,70 @@
// You should have received a copy of the GNU Affero General Public License
// along with Substrate-Libre-Currency. If not, see <https://www.gnu.org/licenses/>.
use crate::mock::IdtyIndex;
use crate::mock::*;
use crate::Error;
use frame_support::assert_err;
use frame_support::assert_ok;
use frame_system::{EventRecord, Phase};
use maplit::{btreemap, btreeset};
use sp_std::collections::btree_map::BTreeMap;
#[test]
fn test_no_certs() {
let certifications = Vec::with_capacity(0);
new_test_ext(DefaultCertificationConfig { certifications }).execute_with(|| {
//assert_eq!(DefaultCertification::identities_count(), 0);
fn test_must_receive_cert_before_can_issue() {
new_test_ext(DefaultCertificationConfig {
certs_by_issuer: BTreeMap::new(),
phantom: core::marker::PhantomData,
})
.execute_with(|| {
assert_eq!(
DefaultCertification::add_cert(Origin::root(), 0, 1),
Err(Error::<Test, _>::IdtyMustReceiveCertsBeforeCanIssue.into())
);
});
}
/*
#[test]
fn test_two_identities() {
let identities = vec![
crate::IdtyValue {
did: Did(0),
owner_key: 1,
removable_on: None,
rights: vec![(Right::Right2, Some(10))],
status: crate::IdtyStatus::Validated,
data: (),
},
crate::IdtyValue {
did: Did(1),
owner_key: 2,
removable_on: None,
rights: vec![(Right::Right1, Some(20))],
status: crate::IdtyStatus::Validated,
data: (),
},
];
new_test_ext(IdentityConfig { identities }).execute_with(|| {
// Should have two identities
assert_eq!(Identity::identities_count(), 2);
// We need to initialize at least one block before any call
run_to_block(1);
// Add right Right1 for Did(0)
// Should succes and trigger the correct event
assert_ok!(Identity::add_right(Origin::root(), 0, Right::Right1));
let events = System::events();
assert_eq!(events.len(), 1);
#[test]
fn test_cert_period() {
new_test_ext(DefaultCertificationConfig {
certs_by_issuer: btreemap![0 => btreeset![1]],
phantom: core::marker::PhantomData,
})
.execute_with(|| {
assert_eq!(
events[0],
EventRecord {
phase: Phase::Initialization,
event: Event::Identity(crate::Event::IdtyAcquireRight(Did(0), Right::Right1)),
topics: vec![],
}
DefaultCertification::add_cert(Origin::root(), 0, 2),
Err(Error::<Test, _>::NotRespectCertPeriod.into())
);
// Add right Right2 for Did(0)
// Should fail because Did(0) already have this right
assert_err!(
Identity::add_right(Origin::root(), 0, Right::Right2),
Error::<Test>::RightAlreadyAdded
run_to_block(CertPeriod::get());
assert_ok!(DefaultCertification::add_cert(Origin::root(), 0, 2));
run_to_block(CertPeriod::get() + 1);
assert_eq!(
DefaultCertification::add_cert(Origin::root(), 0, 3),
Err(Error::<Test, _>::NotRespectCertPeriod.into())
);
run_to_block((2 * CertPeriod::get()) + 1);
assert_ok!(DefaultCertification::add_cert(Origin::root(), 0, 3));
});
}
run_to_block(3);
// Delete right Right1 for Did(1)
// Should succes and trigger the correct event
assert_ok!(Identity::del_right(Origin::root(), 1, Right::Right1));
let events = System::events();
assert_eq!(events.len(), 2);
#[test]
fn test_renewable_period() {
new_test_ext(DefaultCertificationConfig {
certs_by_issuer: btreemap![0 => btreeset![1]],
phantom: core::marker::PhantomData,
})
.execute_with(|| {
run_to_block(CertPeriod::get());
assert_eq!(
events[1],
EventRecord {
phase: Phase::Initialization,
event: Event::Identity(crate::Event::IdtyLostRight(Did(1), Right::Right1)),
topics: vec![],
}
DefaultCertification::add_cert(Origin::root(), 0, 1),
Err(Error::<Test, _>::NotRespectRenewablePeriod.into())
);
// The Did(1) identity has no more rights, the inactivity period must start to run
let idty2 = Identity::identity(1);
assert!(idty2.rights.is_empty());
assert_eq!(idty2.removable_on, Some(7));
run_to_block(RenewablePeriod::get());
assert_ok!(DefaultCertification::add_cert(Origin::root(), 0, 1));
run_to_block(RenewablePeriod::get() + CertPeriod::get());
assert_eq!(
DefaultCertification::add_cert(Origin::root(), 0, 1),
Err(Error::<Test, _>::NotRespectRenewablePeriod.into())
);
run_to_block((2 * RenewablePeriod::get()) + 1);
assert_ok!(DefaultCertification::add_cert(Origin::root(), 0, 1));
});
}
*/
\ No newline at end of file
This diff is collapsed.
......@@ -101,7 +101,9 @@ impl system::Config for Test {
parameter_types! {
pub const ConfirmPeriod: u64 = 2;
pub const MaxInactivityPeriod: u64 = 4;
pub const MaxInactivityPeriod: u64 = 5;
pub const MaxNoRightPeriod: u64 = 4;
pub const RenewablePeriod: u64 = 3;
pub const ValidationPeriod: u64 = 2;
}
......@@ -116,11 +118,11 @@ impl pallet_identity::Config for Test {
type IdtyIndex = u64;
type IdtyValidationOrigin = system::EnsureRoot<AccountId>;
type IdtyRight = IdtyRight;
type OnIdtyConfirmed = ();
type OnIdtyRemoved = ();
type OnIdtyValidated = ();
type OnIdtyChange = ();
type OnRightKeyChange = ();
type MaxInactivityPeriod = MaxInactivityPeriod;
type MaxNoRightPeriod = MaxNoRightPeriod;
type RenewablePeriod = RenewablePeriod;
type ValidationPeriod = ValidationPeriod;
}
......
......@@ -35,16 +35,20 @@ fn test_two_identities() {
let identities = vec![
crate::IdtyValue {
did: Did(0),
expire_on: 5,
owner_key: 1,
removable_on: None,
removable_on: 0,
renewable_on: 3,
rights: vec![(Right::Right2, Some(10))],
status: crate::IdtyStatus::Validated,
data: (),
},
crate::IdtyValue {
did: Did(1),
expire_on: 5,
owner_key: 2,
removable_on: None,
removable_on: 0,
renewable_on: 3,
rights: vec![(Right::Right1, Some(20))],
status: crate::IdtyStatus::Validated,
data: (),
......@@ -97,6 +101,6 @@ fn test_two_identities() {
// The Did(1) identity has no more rights, the inactivity period must start to run
let idty2 = Identity::identity(1);
assert!(idty2.rights.is_empty());
assert_eq!(idty2.removable_on, Some(7));
assert_eq!(idty2.removable_on, 7);
});
}
......@@ -15,7 +15,7 @@
// along with Substrate-Libre-Currency. If not, see <https://www.gnu.org/licenses/>.
use crate::*;
use frame_support::pallet_prelude::*;
use frame_support::{dispatch::DispatchError, pallet_prelude::*};
use frame_system::pallet_prelude::*;
use sp_runtime::traits::MaybeSerializeDeserialize;
use sp_std::fmt::Debug;
......@@ -26,7 +26,7 @@ pub trait EnsureIdtyCallAllowed<T: Config> {
creator: T::IdtyIndex,
idty_did: &T::IdtyDid,
idty_owner_key: &T::AccountId,
) -> bool;
) -> Result<T::IdtyData, DispatchError>;
}
impl<T: Config> EnsureIdtyCallAllowed<T> for () {
fn create_identity(
......@@ -34,21 +34,14 @@ impl<T: Config> EnsureIdtyCallAllowed<T> for () {
_creator: T::IdtyIndex,
_idty_did: &T::IdtyDid,
_idty_owner_key: &T::AccountId,
) -> bool {
ensure_root(origin).is_ok()
) -> Result<T::IdtyData, DispatchError> {
match ensure_root(origin) {
Ok(()) => Ok(T::IdtyData::default()),