From b437f28e3245d0c504f4307d61a0e7c50d6c5aa2 Mon Sep 17 00:00:00 2001
From: Hugo Trentesaux <hugo@trentesaux.fr>
Date: Tue, 19 Dec 2023 16:54:05 +0100
Subject: [PATCH] add certification count check

---
 pallets/distance/src/lib.rs          | 11 ++++++-----
 pallets/distance/src/mock.rs         |  1 +
 pallets/distance/src/traits.rs       | 11 +++++++++++
 pallets/duniter-wot/src/lib.rs       | 18 ++++++++++++++++++
 runtime/common/src/pallets_config.rs |  1 +
 5 files changed, 37 insertions(+), 5 deletions(-)

diff --git a/pallets/distance/src/lib.rs b/pallets/distance/src/lib.rs
index 0e7b8a9d1..064a4276c 100644
--- a/pallets/distance/src/lib.rs
+++ b/pallets/distance/src/lib.rs
@@ -87,6 +87,8 @@ pub mod pallet {
         type WeightInfo: WeightInfo;
         /// Handler for successful distance evaluation
         type OnValidDistanceStatus: OnValidDistanceStatus<Self>;
+        /// Trait to check that distance evaluation request is allowed
+        type CheckRequestDistanceEvaluation: CheckRequestDistanceEvaluation<Self>;
     }
 
     // STORAGE //
@@ -255,7 +257,7 @@ pub mod pallet {
         }
 
         /// Request target identity to be evaluated
-        /// only possible for unconfirmed identity
+        /// only possible for unvalidated identity
         #[pallet::call_index(4)]
         #[pallet::weight(<T as pallet::Config>::WeightInfo::request_distance_evaluation())]
         pub fn request_distance_evaluation_for(
@@ -398,7 +400,6 @@ pub mod pallet {
             // caller has an identity
             let idty_index = pallet_identity::IdentityIndexOf::<T>::get(who)
                 .ok_or(Error::<T>::CallerHasNoIdentity)?;
-            // TODO "check idty call allowed" managed by wot that checks received cert count
             Self::check_request_distance_evaluation_common(idty_index)?;
             Ok(idty_index)
         }
@@ -411,8 +412,6 @@ pub mod pallet {
             // caller has an identity
             let caller_idty_index = pallet_identity::IdentityIndexOf::<T>::get(who)
                 .ok_or(Error::<T>::CallerHasNoIdentity)?;
-            // TODO some of the following can be moved to a "check idty call allowed" managed by wot
-            // which also checks certification count
             let caller_idty = pallet_identity::Identities::<T>::get(caller_idty_index)
                 .ok_or(Error::<T>::CallerIdentityNotFound)?;
             // caller is member
@@ -446,7 +445,9 @@ pub mod pallet {
                 ValidEvaluationResult::<T>::get(target).is_none(),
                 Error::<T>::ValidDistanceResultAlreadyAvailable
             );
-            Ok(())
+            // external validation
+            // target has received enough certifications
+            T::CheckRequestDistanceEvaluation::check_request_distance_evaluation(target)
         }
 
         /// request distance evaluation in current pool
diff --git a/pallets/distance/src/mock.rs b/pallets/distance/src/mock.rs
index 11ab72a13..c6a629753 100644
--- a/pallets/distance/src/mock.rs
+++ b/pallets/distance/src/mock.rs
@@ -260,6 +260,7 @@ impl pallet_distance::Config for Test {
     type RuntimeEvent = RuntimeEvent;
     type WeightInfo = ();
     type OnValidDistanceStatus = ();
+    type CheckRequestDistanceEvaluation = ();
 }
 
 // Build genesis storage according to the mock runtime.
diff --git a/pallets/distance/src/traits.rs b/pallets/distance/src/traits.rs
index eafb5451c..6849d9c25 100644
--- a/pallets/distance/src/traits.rs
+++ b/pallets/distance/src/traits.rs
@@ -15,6 +15,7 @@
 // along with Duniter-v2S. If not, see <https://www.gnu.org/licenses/>.
 
 use crate::*;
+use frame_support::pallet_prelude::*;
 
 pub trait OnValidDistanceStatus<T: Config> {
     /// Handler for valid distance evaluation
@@ -24,3 +25,13 @@ pub trait OnValidDistanceStatus<T: Config> {
 impl<T: Config> OnValidDistanceStatus<T> for () {
     fn on_valid_distance_status(_idty_index: T::IdtyIndex) {}
 }
+
+pub trait CheckRequestDistanceEvaluation<T: Config> {
+    fn check_request_distance_evaluation(idty_index: T::IdtyIndex) -> Result<(), DispatchError>;
+}
+
+impl<T: Config> CheckRequestDistanceEvaluation<T> for () {
+    fn check_request_distance_evaluation(_idty_index: T::IdtyIndex) -> Result<(), DispatchError> {
+        Ok(())
+    }
+}
diff --git a/pallets/duniter-wot/src/lib.rs b/pallets/duniter-wot/src/lib.rs
index a33bec743..0f6bed36a 100644
--- a/pallets/duniter-wot/src/lib.rs
+++ b/pallets/duniter-wot/src/lib.rs
@@ -122,6 +122,8 @@ pub mod pallet {
         CertToRevoked,
         /// Issuer or receiver not found.
         IdtyNotFound,
+        /// Not enough certs received to request distance evaluation.
+        NotEnoughCertsReceivedToRequestDistanceEvaluation,
     }
 }
 
@@ -391,3 +393,19 @@ impl<T: Config<I> + pallet_distance::Config, I: 'static>
         }
     }
 }
+
+/// distance evaluation request allowed check
+impl<T: Config<I> + pallet_distance::Config, I: 'static>
+    pallet_distance::traits::CheckRequestDistanceEvaluation<T> for Pallet<T, I>
+{
+    fn check_request_distance_evaluation(idty_index: IdtyIndex) -> Result<(), DispatchError> {
+        // maybe check idty is not unconfirmed or revoked ?
+        // check cert count
+        let idty_cert_meta = pallet_certification::Pallet::<T, I>::idty_cert_meta(idty_index);
+        ensure!(
+            idty_cert_meta.received_count >= T::MinCertForMembership::get(),
+            Error::<T, I>::NotEnoughCertsReceivedToRequestDistanceEvaluation
+        );
+        Ok(())
+    }
+}
diff --git a/runtime/common/src/pallets_config.rs b/runtime/common/src/pallets_config.rs
index 2af5d92d0..efd7dd157 100644
--- a/runtime/common/src/pallets_config.rs
+++ b/runtime/common/src/pallets_config.rs
@@ -523,6 +523,7 @@ macro_rules! pallets_config {
             type RuntimeEvent = RuntimeEvent;
             type WeightInfo = common_runtime::weights::pallet_distance::WeightInfo<Runtime>;
             type OnValidDistanceStatus = Wot;
+            type CheckRequestDistanceEvaluation = Wot;
         }
 
         // SMITHS SUB-WOT //
-- 
GitLab