referrerpolicy=no-referrer-when-downgrade

polkadot_runtime_parachains/
reward_points.rs

1// Copyright (C) Parity Technologies (UK) Ltd.
2// This file is part of Polkadot.
3
4// Polkadot is free software: you can redistribute it and/or modify
5// it under the terms of the GNU General Public License as published by
6// the Free Software Foundation, either version 3 of the License, or
7// (at your option) any later version.
8
9// Polkadot is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12// GNU General Public License for more details.
13
14// You should have received a copy of the GNU General Public License
15// along with Polkadot.  If not, see <http://www.gnu.org/licenses/>.
16
17//! An implementation of the `RewardValidators` trait used by `inclusion` that employs
18//! `pallet-staking` to compute the rewards.
19//!
20//! Based on <https://research.web3.foundation/en/latest/polkadot/overview/2-token-economics.html>
21//! which doesn't currently mention availability bitfields. As such, we don't reward them
22//! for the time being, although we will build schemes to do so in the future.
23
24use crate::{session_info, shared};
25use alloc::collections::btree_set::BTreeSet;
26use frame_support::traits::{Defensive, Get, RewardsReporter, ValidatorSet};
27use polkadot_primitives::{SessionIndex, ValidatorIndex};
28
29/// Rewards validators for participating in parachains with era points in pallet-staking.
30///
31/// `PointsPerWork` is the amount of era points given per unit of work. The unit of work depends on
32/// where this type is used:
33///
34/// - As `inclusion::Config::RewardValidators`: backing a candidate that is included.
35/// - As `disputes::Config::RewardValidators`: casting a dispute statement on a candidate.
36///
37/// Use a separate instance with a different `PointsPerWork` for each pallet to reward them
38/// differently.
39pub struct RewardValidatorsWithEraPoints<C, R, PointsPerWork>(
40	core::marker::PhantomData<(C, R, PointsPerWork)>,
41);
42
43impl<C, R, PointsPerWork> RewardValidatorsWithEraPoints<C, R, PointsPerWork>
44where
45	C: session_info::Config,
46	C::ValidatorSet: ValidatorSet<C::AccountId, ValidatorId = C::AccountId>,
47	R: RewardsReporter<C::AccountId>,
48	PointsPerWork: Get<u32>,
49{
50	/// Reward validators in session with points, but only if they are in the active set.
51	fn reward_only_active(
52		session_index: SessionIndex,
53		indices: impl IntoIterator<Item = ValidatorIndex>,
54	) {
55		let points = PointsPerWork::get();
56		let validators = session_info::AccountKeys::<C>::get(&session_index);
57		let validators = match validators
58			.defensive_proof("account_keys are present for dispute_period sessions")
59		{
60			Some(validators) => validators,
61			None => return,
62		};
63		// limit rewards to the active validator set
64		let active_set: BTreeSet<_> = C::ValidatorSet::validators().into_iter().collect();
65
66		let rewards = indices
67			.into_iter()
68			.filter_map(|i| validators.get(i.0 as usize).cloned())
69			.filter(|v| active_set.contains(v))
70			.map(|v| (v, points));
71
72		R::reward_by_ids(rewards);
73	}
74}
75
76impl<C, R, PointsPerWork> crate::inclusion::RewardValidators
77	for RewardValidatorsWithEraPoints<C, R, PointsPerWork>
78where
79	C: shared::Config + session_info::Config,
80	C::ValidatorSet: ValidatorSet<C::AccountId, ValidatorId = C::AccountId>,
81	R: RewardsReporter<C::AccountId>,
82	PointsPerWork: Get<u32>,
83{
84	fn reward_backing(indices: impl IntoIterator<Item = ValidatorIndex>) {
85		let session_index = shared::CurrentSessionIndex::<C>::get();
86		Self::reward_only_active(session_index, indices);
87	}
88
89	fn reward_bitfields(_validators: impl IntoIterator<Item = ValidatorIndex>) {}
90}
91
92impl<C, R, PointsPerWork> crate::disputes::RewardValidators
93	for RewardValidatorsWithEraPoints<C, R, PointsPerWork>
94where
95	C: session_info::Config,
96	C::ValidatorSet: ValidatorSet<C::AccountId, ValidatorId = C::AccountId>,
97	R: RewardsReporter<C::AccountId>,
98	PointsPerWork: Get<u32>,
99{
100	fn reward_dispute_statement(
101		session: SessionIndex,
102		validators: impl IntoIterator<Item = ValidatorIndex>,
103	) {
104		Self::reward_only_active(session, validators);
105	}
106}