Skip to content
Snippets Groups Projects
Commit 1a837959 authored by Cédric Moreau's avatar Cédric Moreau
Browse files

feat(smith-members): only WoT members can be invited

parent 3283b0fa
No related branches found
No related tags found
No related merge requests found
...@@ -6298,6 +6298,7 @@ dependencies = [ ...@@ -6298,6 +6298,7 @@ dependencies = [
"maplit", "maplit",
"pallet-authority-members", "pallet-authority-members",
"pallet-balances", "pallet-balances",
"pallet-identity",
"parity-scale-codec", "parity-scale-codec",
"scale-info", "scale-info",
"serde", "serde",
......
...@@ -38,6 +38,7 @@ pub enum IdtyEvent<T: crate::Config> { ...@@ -38,6 +38,7 @@ pub enum IdtyEvent<T: crate::Config> {
/// removing an identity (unvalidated or revoked) /// removing an identity (unvalidated or revoked)
// pallet wot removes associated certifications if status is not revoked // pallet wot removes associated certifications if status is not revoked
// pallet quota removes associated quota // pallet quota removes associated quota
// pallet smith-members exclude smith
Removed { status: IdtyStatus }, Removed { status: IdtyStatus },
// TODO add a way to unlink accounts corresponding to revoked or removed identities // TODO add a way to unlink accounts corresponding to revoked or removed identities
} }
......
...@@ -18,6 +18,7 @@ log = { version = "0.4.17", default-features = false } ...@@ -18,6 +18,7 @@ log = { version = "0.4.17", default-features = false }
scale-info = { version = "2.1.1", default-features = false, features = ["derive"] } scale-info = { version = "2.1.1", default-features = false, features = ["derive"] }
serde = { version = "1.0.101", default-features = false, optional = true } serde = { version = "1.0.101", default-features = false, optional = true }
pallet-authority-members = { path = "../authority-members", default-features = false } pallet-authority-members = { path = "../authority-members", default-features = false }
pallet-identity = { path = "../identity", default-features = false }
frame-support = { git = 'https://github.com/duniter/substrate', branch = 'duniter-substrate-v0.9.42', default-features = false } frame-support = { git = 'https://github.com/duniter/substrate', branch = 'duniter-substrate-v0.9.42', default-features = false }
frame-system = { git = 'https://github.com/duniter/substrate', branch = 'duniter-substrate-v0.9.42', default-features = false } frame-system = { git = 'https://github.com/duniter/substrate', branch = 'duniter-substrate-v0.9.42', default-features = false }
pallet-balances = { git = 'https://github.com/duniter/substrate', branch = 'duniter-substrate-v0.9.42', default-features = false } pallet-balances = { git = 'https://github.com/duniter/substrate', branch = 'duniter-substrate-v0.9.42', default-features = false }
......
use crate::{Config, CurrentSession, Pallet}; use crate::{Config, CurrentSession, Pallet};
use frame_support::Parameter;
use pallet_authority_members::SessionIndex; use pallet_authority_members::SessionIndex;
use pallet_identity::IdtyEvent;
use sp_runtime::traits::Convert; use sp_runtime::traits::Convert;
/// We want to remove a Smith when he is removed from the higher level set of "authorities". /// We want to remove a Smith when he is removed from the higher level set of "authorities".
...@@ -47,3 +49,20 @@ impl<T: Config> pallet_authority_members::OnNewSession for Pallet<T> { ...@@ -47,3 +49,20 @@ impl<T: Config> pallet_authority_members::OnNewSession for Pallet<T> {
Pallet::<T>::do_exclude_expired_smiths(index); Pallet::<T>::do_exclude_expired_smiths(index);
} }
} }
// implement identity event handler
impl<
IdtyIndex: Copy + Parameter,
T: Config<IdtyIndex = IdtyIndex> + pallet_identity::Config<IdtyIndex = IdtyIndex>,
> pallet_identity::traits::OnIdtyChange<T> for Pallet<T>
{
fn on_idty_change(idty_id: IdtyIndex, idty_event: &IdtyEvent<T>) {
match idty_event {
// initialize quota on identity creation
IdtyEvent::Created { .. } => {}
IdtyEvent::Removed { .. } => {
Pallet::<T>::do_exclude_removed_wot_member(idty_id);
}
}
}
}
...@@ -444,36 +444,7 @@ impl<T: Config> Pallet<T> { ...@@ -444,36 +444,7 @@ impl<T: Config> Pallet<T> {
if let Some(smith_meta) = Smiths::<T>::get(smith) { if let Some(smith_meta) = Smiths::<T>::get(smith) {
if let Some(expires_on) = smith_meta.expires_on { if let Some(expires_on) = smith_meta.expires_on {
if expires_on == at { if expires_on == at {
let mut lost_certs = vec![]; Self::do_exclude_smith(smith, SmithRemovalReason::OfflineTooLong);
Smiths::<T>::mutate(smith, |maybe_smith_meta| {
let maybe_smith_meta =
maybe_smith_meta.as_mut().expect("checked earlier");
maybe_smith_meta.expires_on = None;
maybe_smith_meta.status = SmithStatus::Excluded;
for cert in &maybe_smith_meta.received_certs {
lost_certs.push(*cert);
}
maybe_smith_meta.received_certs = vec![];
// N.B.: the issued certs are kept in case the smith joins back
});
// We remove the lost certs from their issuer's stock
for lost_cert in lost_certs {
Smiths::<T>::mutate(lost_cert, |maybe_smith_meta| {
let maybe_smith_meta =
maybe_smith_meta.as_mut().expect("checked earlier");
if let Ok(index) =
maybe_smith_meta.issued_certs.binary_search(&smith)
{
maybe_smith_meta.issued_certs.remove(index);
}
});
}
// Deletion done
T::OnSmithDelete::on_smith_delete(
smith,
SmithRemovalReason::OfflineTooLong,
);
Self::deposit_event(Event::<T>::SmithExcluded { idty_index: smith });
} }
} }
} }
...@@ -481,6 +452,36 @@ impl<T: Config> Pallet<T> { ...@@ -481,6 +452,36 @@ impl<T: Config> Pallet<T> {
} }
} }
fn do_exclude_removed_wot_member(idty_index: T::IdtyIndex) {
Self::do_exclude_smith(idty_index, SmithRemovalReason::LostMembership);
}
fn do_exclude_smith(idty_index: T::IdtyIndex, reason: SmithRemovalReason) {
let mut lost_certs = vec![];
Smiths::<T>::mutate(idty_index, |maybe_smith_meta| {
let maybe_smith_meta = maybe_smith_meta.as_mut().expect("checked earlier");
maybe_smith_meta.expires_on = None;
maybe_smith_meta.status = SmithStatus::Excluded;
for cert in &maybe_smith_meta.received_certs {
lost_certs.push(*cert);
}
maybe_smith_meta.received_certs = vec![];
// N.B.: the issued certs are kept in case the smith joins back
});
// We remove the lost certs from their issuer's stock
for lost_cert in lost_certs {
Smiths::<T>::mutate(lost_cert, |maybe_smith_meta| {
let maybe_smith_meta = maybe_smith_meta.as_mut().expect("checked earlier");
if let Ok(index) = maybe_smith_meta.issued_certs.binary_search(&idty_index) {
maybe_smith_meta.issued_certs.remove(index);
}
});
}
// Deletion done: notify (authority-members) for cascading
T::OnSmithDelete::on_smith_delete(idty_index, reason);
Self::deposit_event(Event::<T>::SmithExcluded { idty_index });
}
// TODO: return what? // TODO: return what?
fn smith_goes_online(idty_index: T::IdtyIndex) { fn smith_goes_online(idty_index: T::IdtyIndex) {
if let Some(smith_meta) = Smiths::<T>::get(idty_index) { if let Some(smith_meta) = Smiths::<T>::get(idty_index) {
......
...@@ -486,3 +486,73 @@ fn invitation_on_non_wot_member() { ...@@ -486,3 +486,73 @@ fn invitation_on_non_wot_member() {
); );
}); });
} }
#[test]
fn losing_wot_membership_cascades_to_smith_members() {
new_test_ext(GenesisConfig {
certs_by_receiver: btreemap![
1 => vec![2, 3, 4],
2 => vec![3, 4],
3 => vec![1, 2],
4 => vec![],
],
})
.execute_with(|| {
// State before
assert_eq!(
Smiths::<Runtime>::get(1),
Some(SmithMeta {
status: Smith,
expires_on: Some(5),
issued_certs: vec![3],
received_certs: vec![2, 3, 4],
})
);
assert_eq!(
Smiths::<Runtime>::get(1).unwrap().issued_certs,
Vec::<u64>::from([3])
);
assert_eq!(
Smiths::<Runtime>::get(2).unwrap().issued_certs,
Vec::<u64>::from([1, 3])
);
assert_eq!(
Smiths::<Runtime>::get(3).unwrap().issued_certs,
Vec::<u64>::from([1, 2])
);
assert_eq!(
Smiths::<Runtime>::get(4).unwrap().issued_certs,
Vec::<u64>::from([1, 2])
);
Pallet::<Runtime>::do_exclude_removed_wot_member(1);
// Excluded
assert_eq!(
Smiths::<Runtime>::get(1),
Some(SmithMeta {
status: Excluded,
expires_on: None,
issued_certs: vec![3],
received_certs: vec![],
})
);
// Issued certifications updated for certifiers of 1
assert_eq!(
Smiths::<Runtime>::get(1).unwrap().issued_certs,
Vec::<u64>::from([3])
);
assert_eq!(
Smiths::<Runtime>::get(2).unwrap().issued_certs,
Vec::<u64>::from([3])
);
assert_eq!(
Smiths::<Runtime>::get(3).unwrap().issued_certs,
Vec::<u64>::from([2])
);
assert_eq!(
Smiths::<Runtime>::get(4).unwrap().issued_certs,
Vec::<u64>::from([2])
);
});
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment