diff --git a/client/distance/src/lib.rs b/client/distance/src/lib.rs index 9563138d5060ae72bcb8f4a199150789ca9c10e7..821be0c6de3ffcb154af4bcb9447f3c39c0d1900 100644 --- a/client/distance/src/lib.rs +++ b/client/distance/src/lib.rs @@ -76,14 +76,12 @@ where ), )? .map_or_else(Default::default, |raw| { - pallet_distance::EvaluationPool::<AccountId32, IdtyIndex, ConstU32<100>, 100>::decode( - &mut &raw.0[..], - ) - .expect("cannot decode EvaluationPool") + pallet_distance::EvaluationPool::<AccountId32, IdtyIndex>::decode(&mut &raw.0[..]) + .expect("cannot decode EvaluationPool") }); // Have we already published a result for this session? - if published_results.1.contains(&owner_key) { + if published_results.evaluators.contains(&owner_key) { return Ok(sp_distance::InherentDataProvider::<IdtyIndex>::new(None)); } diff --git a/pallets/distance/src/lib.rs b/pallets/distance/src/lib.rs index e1ef348a549a766efec31cc5c0f64ad9c9da261c..1fefe5711e10c1a75c9d8011183b6da886737e3f 100644 --- a/pallets/distance/src/lib.rs +++ b/pallets/distance/src/lib.rs @@ -34,6 +34,11 @@ use sp_std::convert::TryInto; type IdtyIndex = u32; +/// Maximum number of identities to be evaluated in a session +pub const MAX_EVALUATIONS_PER_SESSION: u32 = 600; +/// Maximum number of evaluators in a session +pub const MAX_EVALUATORS_PER_SESSION: u32 = 100; + #[frame_support::pallet(dev_mode)] // dev mode while waiting for benchmarks pub mod pallet { use super::*; @@ -63,11 +68,6 @@ pub mod pallet { type EvaluationPrice: Get< <Self::Currency as frame_support::traits::Currency<Self::AccountId>>::Balance, >; - /// Maximum number of identities to be evaluated in a session - type MaxEvaluationsPerSession: Get<u32>; - /// Maximum number of evaluators in a session - #[pallet::constant] - type MaxEvaluatorsPerSession: Get<u32>; /// Minimum ratio of accessible referees type MinAccessibleReferees: Get<Perbill>; /// Number of session to keep a positive evaluation result @@ -86,8 +86,6 @@ pub mod pallet { EvaluationPool< <T as frame_system::Config>::AccountId, <T as pallet_certification::Config<I>>::IdtyIndex, - <T as Config<I>>::MaxEvaluationsPerSession, - 100, >, ValueQuery, >; @@ -99,8 +97,6 @@ pub mod pallet { EvaluationPool< <T as frame_system::Config>::AccountId, <T as pallet_certification::Config<I>>::IdtyIndex, - <T as Config<I>>::MaxEvaluationsPerSession, - 100, >, ValueQuery, >; @@ -112,8 +108,6 @@ pub mod pallet { EvaluationPool< <T as frame_system::Config>::AccountId, <T as pallet_certification::Config<I>>::IdtyIndex, - <T as Config<I>>::MaxEvaluationsPerSession, - 100, >, ValueQuery, >; @@ -124,6 +118,10 @@ pub mod pallet { StorageValue<_, <T as frame_system::Config>::Hash, ValueQuery>; /// Distance evaluation status by identity + /// + /// * `.0` is the account who requested an evaluation and reserved the price, + /// for whom the price will be unreserved or slashed when the evaluation completes. + /// * `.1` is the status of the evaluation. #[pallet::storage] #[pallet::getter(fn identity_distance_status)] pub type IdentityDistanceStatus<T: Config<I>, I: 'static = ()> = StorageMap< @@ -141,7 +139,10 @@ pub mod pallet { _, Twox64Concat, u32, - BoundedVec<<T as pallet_certification::Config<I>>::IdtyIndex, T::MaxEvaluationsPerSession>, + BoundedVec< + <T as pallet_certification::Config<I>>::IdtyIndex, + ConstU32<MAX_EVALUATIONS_PER_SESSION>, + >, ValueQuery, >; @@ -247,7 +248,13 @@ pub mod pallet { Pallet::<T, I>::do_update_evaluation(evaluator, computation_result) } - /// Push an evaluation result to the pool + /// Set the distance evaluation status of an identity + /// + /// Removes the status if `status` is `None`. + /// + /// * `status.0` is the account for whom the price will be unreserved or slashed + /// when the evaluation completes. + /// * `status.1` is the status of the evaluation. #[pallet::call_index(3)] #[pallet::weight(0)] // #[pallet::weight(T::WeightInfo::force_set_distance_status())] @@ -282,8 +289,6 @@ pub mod pallet { &mut EvaluationPool< <T as frame_system::Config>::AccountId, <T as pallet_certification::Config<I>>::IdtyIndex, - <T as Config<I>>::MaxEvaluationsPerSession, - 100, //<T as Config<I>>::MaxEvaluatorsPerSession, >, ) -> R, >( @@ -304,8 +309,6 @@ pub mod pallet { &mut EvaluationPool< <T as frame_system::Config>::AccountId, <T as pallet_certification::Config<I>>::IdtyIndex, - <T as Config<I>>::MaxEvaluationsPerSession, - 100, //<T as Config<I>>::MaxEvaluatorsPerSession, >, ) -> R, >( @@ -329,8 +332,6 @@ pub mod pallet { ) -> EvaluationPool< <T as frame_system::Config>::AccountId, <T as pallet_certification::Config<I>>::IdtyIndex, - <T as Config<I>>::MaxEvaluationsPerSession, - 100, //<T as Config<I>>::MaxEvaluatorsPerSession, > { match index % 3 { 0 => EvaluationPool2::<T, I>::take(), @@ -348,15 +349,14 @@ pub mod pallet { pallet_session::CurrentIndex::<T>::get(), |current_pool| { ensure!( - current_pool.0.len() - < (<T as Config<I>>::MaxEvaluationsPerSession::get() as usize), + current_pool.evaluations.len() < (MAX_EVALUATIONS_PER_SESSION as usize), Error::<T, I>::QueueFull ); T::Currency::reserve(&who, <T as Config<I>>::EvaluationPrice::get())?; current_pool - .0 + .evaluations .try_push((idty_index, median::MedianAcc::new())) .map_err(|_| Error::<T, I>::QueueFull)?; @@ -383,19 +383,19 @@ pub mod pallet { pallet_session::CurrentIndex::<T>::get(), |result_pool| { ensure!( - computation_result.distances.len() == result_pool.0.len(), + computation_result.distances.len() == result_pool.evaluations.len(), Error::<T, I>::WrongResultLength ); if result_pool - .1 + .evaluators .try_insert(evaluator) .map_err(|_| Error::<T, I>::TooManyEvaluators)? { for (distance_value, (_identity, median_acc)) in computation_result .distances .into_iter() - .zip(result_pool.0.iter_mut()) + .zip(result_pool.evaluations.iter_mut()) { median_acc.push(distance_value); } @@ -422,10 +422,8 @@ pub mod pallet { let current_pool: EvaluationPool< <T as frame_system::Config>::AccountId, <T as pallet_certification::Config<I>>::IdtyIndex, - <T as Config<I>>::MaxEvaluationsPerSession, - 100, //<T as Config<I>>::MaxEvaluatorsPerSession, > = Pallet::<T, I>::take_current_pool(index); - for (idty, median_acc) in current_pool.0.into_iter() { + for (idty, median_acc) in current_pool.evaluations.into_iter() { if let Some(median_result) = median_acc.get_median() { let median = match median_result { MedianResult::One(m) => m, diff --git a/pallets/distance/src/types.rs b/pallets/distance/src/types.rs index 256c6dc5d8ab3fd7f121dd986a76e801ec61b0ad..8a3613344fd711661fefd1ff854c3dae71b41dab 100644 --- a/pallets/distance/src/types.rs +++ b/pallets/distance/src/types.rs @@ -14,14 +14,14 @@ // You should have received a copy of the GNU Affero General Public License // along with Duniter-v2S. If not, see <https://www.gnu.org/licenses/>. -pub use crate::median::*; +pub use crate::{median::*, MAX_EVALUATIONS_PER_SESSION, MAX_EVALUATORS_PER_SESSION}; pub use sp_distance::ComputationResult; use codec::{Decode, Encode}; use frame_support::{pallet_prelude::*, BoundedBTreeSet}; use sp_runtime::Perbill; -/// Status of the distance computation of an identity in the wot +/// Status of the distance evaluation of an identity #[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug, TypeInfo)] pub enum DistanceStatus { /// Identity is in evaluation. @@ -31,24 +31,30 @@ pub enum DistanceStatus { } /// Pool where distance evaluation requests and results are stored -pub type EvaluationPool< - AccountId, - IdtyIndex, - MaxEvaluationsPerSession, - const MAX_EVALUATORS_PER_SESSION: u32, -> = ( - // .0 vector of published results - BoundedVec< - ( - // index of the identity waiting for results - IdtyIndex, - // vector of results from evaluators - // stored in median accumulator to update median while adding results - MedianAcc<Perbill, MAX_EVALUATORS_PER_SESSION>, - ), - MaxEvaluationsPerSession, +/// +/// Depending on the pool rotation, this may not be complete, and still be accepting +/// new evaluation requests (with empty median accumulators) or new evaluations (with evaluators +/// and new samples in the median accumulators). +#[derive(Encode, Decode, Clone, RuntimeDebug, TypeInfo)] +pub struct EvaluationPool<AccountId: Ord, IdtyIndex> { + /// List of identities with their evaluation result + /// The result is the median of all the evaluations. + pub evaluations: BoundedVec< + (IdtyIndex, MedianAcc<Perbill, MAX_EVALUATORS_PER_SESSION>), + ConstU32<MAX_EVALUATIONS_PER_SESSION>, >, - // .1 set of evaluators who already publised a result in this pool - // prevents an evaluator from publishing a result multiple times - BoundedBTreeSet<AccountId, ConstU32<MAX_EVALUATORS_PER_SESSION>>, -); + /// Evaluators who have published a result + /// Its length should be the same as the number of samples + /// in each evaluation result `MedianAcc`. + /// An evaluator is not allowed to publish twice in a single session. + pub evaluators: BoundedBTreeSet<AccountId, ConstU32<MAX_EVALUATORS_PER_SESSION>>, +} + +impl<AccountId: Ord, IdtyIndex> Default for EvaluationPool<AccountId, IdtyIndex> { + fn default() -> Self { + Self { + evaluations: BoundedVec::default(), + evaluators: BoundedBTreeSet::new(), + } + } +} diff --git a/runtime/common/src/pallets_config.rs b/runtime/common/src/pallets_config.rs index b38bb7cbcb958d0d67ca4d40e862cb422c53b178..3338277477c382fd2ca2d37c8cdd8f9910cb6dec 100644 --- a/runtime/common/src/pallets_config.rs +++ b/runtime/common/src/pallets_config.rs @@ -488,8 +488,6 @@ parameter_types! { impl pallet_distance::Config<Instance1> for Runtime { type Currency = Balances; type EvaluationPrice = frame_support::traits::ConstU64<1000>; - type MaxEvaluationsPerSession = frame_support::traits::ConstU32<1000>; - type MaxEvaluatorsPerSession = frame_support::traits::ConstU32<100>; type MinAccessibleReferees = MinAccessibleReferees; type ResultExpiration = frame_support::traits::ConstU32<720>; }