1616
1717//! Approvals Rewards pallet.
1818
19- use alloc:: vec:: Vec ;
19+ use alloc:: vec:: * ;
2020use crate :: {
2121 configuration,
2222 inclusion:: { QueueFootprinter , UmpQueueId } ,
@@ -31,7 +31,10 @@ use frame_support::{
3131 traits:: { EnsureOriginWithArg , EstimateNextSessionRotation } ,
3232 DefaultNoBound ,
3333} ;
34- use scale_info:: { Type , TypeInfo } ;
34+ use scale_info:: {
35+ Type , TypeInfo ,
36+ prelude:: vec,
37+ } ;
3538use sp_runtime:: {
3639 traits:: { AppVerify , One , Saturating } ,
3740 DispatchResult , SaturatedConversion ,
@@ -40,8 +43,10 @@ use frame_system::pallet_prelude::*;
4043use polkadot_primitives:: {
4144 vstaging:: ApprovalStatistics ,
4245 slashing:: { DisputeProof , DisputesTimeSlot , PendingSlashes } ,
43- CandidateHash , DisputeOffenceKind , SessionIndex , ValidatorId , ValidatorIndex ,
44- ValidatorSignature ,
46+ CandidateHash ,
47+ DisputeOffenceKind ,
48+ SessionIndex , ValidatorId , ValidatorIndex , ValidatorSignature ,
49+ IndexedVec , byzantine_threshold
4550} ;
4651
4752#[ cfg( feature = "runtime-benchmarks" ) ]
@@ -50,6 +55,7 @@ pub mod benchmarking;
5055const LOG_TARGET : & str = "runtime::approvals_rewards" ;
5156
5257pub use pallet:: * ;
58+ use polkadot_primitives:: vstaging:: ApprovalStatisticsTallyLine ;
5359
5460pub trait WeightInfo {
5561 fn include_approvals_rewards_statistics ( ) -> Weight ;
@@ -65,17 +71,12 @@ impl WeightInfo for TestWeightInfo {
6571
6672#[ frame_support:: pallet]
6773pub mod pallet {
68- use polkadot_parachain_primitives:: primitives:: ValidationCodeHash ;
69- use polkadot_primitives:: v9:: ParaId ;
70- use polkadot_primitives:: vstaging:: ApprovalStatisticsTallyLine ;
7174 use super :: * ;
72-
75+ use polkadot_primitives :: vstaging :: ApprovalStatisticsTallyLine ;
7376 use sp_runtime:: transaction_validity:: {
7477 InvalidTransaction , TransactionPriority , TransactionSource , TransactionValidity ,
7578 ValidTransaction ,
7679 } ;
77- use crate :: disputes:: WeightInfo ;
78- use crate :: paras:: CodeByHash ;
7980
8081 #[ pallet:: pallet]
8182 #[ pallet:: without_storage_info]
@@ -93,7 +94,7 @@ pub mod pallet {
9394 type RuntimeEvent : From < Event < Self > > + IsType < <Self as frame_system:: Config >:: RuntimeEvent > ;
9495
9596 // Weight information for extrinsics in this pallet.
96- //type WeightInfo: WeightInfo;
97+ // type WeightInfo: WeightInfo;
9798 }
9899
99100 /// Actual past code hash, indicated by the para id as well as the block number at which it
@@ -102,6 +103,10 @@ pub mod pallet {
102103 pub ( super ) type ApprovalsTallies < T : Config > =
103104 StorageMap < _ , Twox64Concat , ( SessionIndex , ValidatorIndex ) , Vec < ApprovalStatisticsTallyLine > > ;
104105
106+ #[ pallet:: storage]
107+ pub ( super ) type AvailableApprovalsMedians < T : Config > =
108+ StorageMap < _ , Twox64Concat , SessionIndex , Vec < u32 > > ;
109+
105110 #[ pallet:: event]
106111 #[ pallet:: generate_deposit( pub ( super ) fn deposit_event) ]
107112 pub enum Event < T : Config > {
@@ -181,7 +186,7 @@ pub mod pallet {
181186 let approvals_key = ( payload_session_index, payload_validator_index) ;
182187
183188 // Ensure that it is a fresh session tally.
184- if let Some ( _ ) = ApprovalsTallies :: < T > :: get ( & approvals_key) {
189+ if ApprovalsTallies :: < T > :: contains_key ( & approvals_key) {
185190 return Err ( Error :: < T > :: ApprovalTalliesAlreadyStored . into ( ) )
186191 }
187192
@@ -216,6 +221,53 @@ pub mod pallet {
216221 }
217222}
218223
224+ impl < T : Config > Pallet < T > {
225+ /// Handle an incoming session change.
226+ pub ( crate ) fn initializer_on_new_session (
227+ notification : & SessionChangeNotification < BlockNumberFor < T > > ,
228+ ) {
229+ let previous_session = notification. session_index . saturating_sub ( 1 ) ;
230+ let session_info = match session_info:: Sessions :: < T > :: get ( previous_session) {
231+ Some ( s) => s,
232+ None => return ,
233+ } ;
234+
235+ let validators_len = session_info. validators . len ( ) ;
236+
237+ let mut rewards_matrix: Vec < Vec < ApprovalStatisticsTallyLine > > = vec ! [ ] ;
238+ for idx in 0 ..validators_len {
239+ let v_idx = ValidatorIndex ( idx as u32 ) ;
240+ if let Some ( tally) = ApprovalsTallies :: < T > :: get ( ( previous_session, v_idx) ) {
241+ rewards_matrix. push ( tally) ;
242+ }
243+ }
244+
245+ if rewards_matrix. len ( ) >= byzantine_threshold ( validators_len) {
246+ let mut approval_usages_medians = Vec :: new ( ) ;
247+ for ( v_idx, _) in session_info. validators . into_iter ( ) . enumerate ( ) {
248+ let mut v: Vec < u32 > = rewards_matrix. iter ( ) . map ( |at| at[ v_idx] . approvals_usage ) . collect ( ) ;
249+ v. sort ( ) ;
250+ approval_usages_medians. push ( v[ validators_len/2 ] ) ;
251+ }
252+
253+ AvailableApprovalsMedians :: < T > :: insert ( previous_session, approval_usages_medians) ;
254+ }
255+
256+ let mut drop_keys = vec ! [ ] ;
257+ let config = configuration:: ActiveConfig :: < T > :: get ( ) ;
258+ ApprovalsTallies :: < T > :: iter_keys ( ) . for_each ( |( session_idx, validator_idx) | {
259+ let min_session_to_keep = notification. session_index - config. dispute_period ;
260+ if session_idx < min_session_to_keep {
261+ drop_keys. push ( ( session_idx, validator_idx) ) ;
262+ }
263+ } ) ;
264+
265+ for key in drop_keys {
266+ ApprovalsTallies :: < T > :: remove ( key) ;
267+ }
268+ }
269+ }
270+
219271impl < T > Pallet < T >
220272where
221273 T : Config + frame_system:: offchain:: CreateBare < Call < T > >
0 commit comments