diff --git a/pallets/oracle-data-collection/src/lib.rs b/pallets/oracle-data-collection/src/lib.rs index 8f66c85336..59385f674d 100644 --- a/pallets/oracle-data-collection/src/lib.rs +++ b/pallets/oracle-data-collection/src/lib.rs @@ -41,6 +41,7 @@ pub mod pallet { use sp_std::{collections::btree_map::BTreeMap, vec::Vec}; use crate::{ + traits::AggregationProvider, types::{CachedCollection, Change, KeyInfo}, util, }; @@ -67,17 +68,21 @@ pub mod pallet { /// Represent an oracle value type OracleValue: Parameter + Member + Copy + MaxEncodedLen + Ord; - /// Represent the a time moment - type Moment: Parameter + Member + Copy + MaxEncodedLen + Ord; + /// Represent the time moment when the value was fed + type Timestamp: Parameter + Member + Copy + MaxEncodedLen + Ord; /// A way to obtain oracle values from feeders type OracleProvider: ValueProvider< (Self::AccountId, Self::CollectionId), Self::OracleKey, Value = Self::OracleValue, - Timestamp = Self::Moment, + Timestamp = Self::Timestamp, >; + /// A way to perform aggregations from a list of feeders feeding the + /// same keys + type AggregationProvider: AggregationProvider; + /// Used to verify collection admin permissions type IsAdmin: PreConditions<(Self::AccountId, Self::CollectionId), Result = bool>; @@ -104,7 +109,7 @@ pub mod pallet { _, Blake2_128Concat, T::CollectionId, - BoundedBTreeMap, + BoundedBTreeMap, ValueQuery, >; @@ -253,7 +258,7 @@ pub mod pallet { impl DataRegistry for Pallet { type Collection = CachedCollection; - type Data = (T::OracleValue, T::Moment); + type Data = (T::OracleValue, T::Timestamp); #[cfg(feature = "runtime-benchmarks")] type MaxCollectionSize = T::MaxCollectionSize; @@ -378,16 +383,16 @@ pub mod types { /// A collection cached in memory pub struct CachedCollection( - pub BoundedBTreeMap, + pub BoundedBTreeMap, ); impl DataCollection for CachedCollection { - type Data = (T::OracleValue, T::Moment); + type Data = (T::OracleValue, T::Timestamp); fn get( &self, data_id: &T::OracleKey, - ) -> Result<(T::OracleValue, T::Moment), DispatchError> { + ) -> Result<(T::OracleValue, T::Timestamp), DispatchError> { self.0 .get(data_id) .cloned() @@ -403,9 +408,42 @@ pub mod types { } } -mod util { +/// Traits specifically used by this pallet +pub mod traits { + /// Defined an aggregation behavior + pub trait AggregationProvider { + fn aggregate(pairs: impl Iterator) + -> Option<(Value, Timestamp)>; + } +} + +/// Provide types to use in runtime to configure this pallet +pub mod util { use sp_std::vec::Vec; + use super::traits::AggregationProvider; + + /// Type that performs an aggregation using the median for values and + /// timestamps + pub struct MedianAggregation; + + impl AggregationProvider for MedianAggregation + where + Value: Ord + Clone, + Timestamp: Ord + Clone, + { + fn aggregate( + pairs: impl Iterator, + ) -> Option<(Value, Timestamp)> { + let (mut values, mut timestamps): (Vec<_>, Vec<_>) = pairs.unzip(); + + let value = median(&mut values)?.clone(); + let timestamp = median(&mut timestamps)?.clone(); + + Some((value, timestamp)) + } + } + /// Computes fastly the median of a list of values /// Extracted from orml pub fn median<'a, T: Ord>(items: &'a mut Vec) -> Option<&'a T> { diff --git a/runtime/development/src/lib.rs b/runtime/development/src/lib.rs index 72c5150f6e..ff91cc7df0 100644 --- a/runtime/development/src/lib.rs +++ b/runtime/development/src/lib.rs @@ -1324,6 +1324,8 @@ impl pallet_membership::Config for Runtime { } parameter_types! { + #[derive(Clone, PartialEq, Eq, Debug, TypeInfo, Encode, Decode, MaxEncodedLen)] + pub const MaxFeedersPerKey: u32 = 10; pub const FirstValueFee: Fee = Fee::Balance(10 * CFG); } @@ -1336,17 +1338,18 @@ impl pallet_oracle_feed::Config for Runtime { } impl pallet_oracle_data_collection::Config for Runtime { + type AggregationProvider = pallet_oracle_data_collection::util::MedianAggregation; type ChangeGuard = PoolSystem; type CollectionId = PoolId; type IsAdmin = PoolAdminCheck; type MaxCollectionSize = MaxActiveLoansPerPool; - type MaxFeedersPerKey = ConstU32<10>; - type Moment = Millis; + type MaxFeedersPerKey = MaxFeedersPerKey; type OracleKey = OracleKey; type OracleProvider = OracleConverterBridge; type OracleValue = Balance; - type RuntimeChange = runtime_common::changes::fast::RuntimeChange; + type RuntimeChange = runtime_common::changes::RuntimeChange; type RuntimeEvent = RuntimeEvent; + type Timestamp = Millis; } parameter_types! {