mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-04-26 14:37:57 +00:00
Reward validators for participating in parachains (#2089)
* plumbing for rewarding backers * give validators reward points for participating * fix tests * add bitfield rewarding * add mocks for backing rewards * add testing for backing & availability rewards * implement RewardValidators on top of staking * add to test-runtime and rococo * add to test-runtime & rococo * point to source on rewards values * fix common tests * do not reward availability anymore
This commit is contained in:
committed by
GitHub
parent
34e5812171
commit
f4e930529b
@@ -17,6 +17,7 @@ struct CandidatePendingAvailability {
|
||||
descriptor: CandidateDescriptor,
|
||||
availability_votes: Bitfield, // one bit per validator.
|
||||
relay_parent_number: BlockNumber, // number of the relay-parent.
|
||||
backers: Bitfield, // one bit per validator, set for those who backed the candidate.
|
||||
backed_in_number: BlockNumber,
|
||||
}
|
||||
```
|
||||
@@ -77,6 +78,7 @@ All failed checks should lead to an unrecoverable error making the block invalid
|
||||
* `enact_candidate(relay_parent_number: BlockNumber, CommittedCandidateReceipt)`:
|
||||
1. If the receipt contains a code upgrade, Call `Paras::schedule_code_upgrade(para_id, code, relay_parent_number + config.validationl_upgrade_delay)`.
|
||||
> TODO: Note that this is safe as long as we never enact candidates where the relay parent is across a session boundary. In that case, which we should be careful to avoid with contextual execution, the configuration might have changed and the para may de-sync from the host's understanding of it.
|
||||
1. Reward all backing validators of each candidate, contained within the `backers` field.
|
||||
1. call `Ump::enact_upward_messages` for each backed candidate, using the [`UpwardMessage`s](../types/messages.md#upward-message) from the [`CandidateCommitments`](../types/candidate.md#candidate-commitments).
|
||||
1. call `Dmp::prune_dmq` with the para id of the candidate and the candidate's `processed_downward_messages`.
|
||||
1. call `Hrmp::prune_hrmp` with the para id of the candiate and the candidate's `hrmp_watermark`.
|
||||
|
||||
@@ -262,7 +262,7 @@ mod tests {
|
||||
}, testing::{UintAuthorityId, TestXt}, Perbill, curve::PiecewiseLinear,
|
||||
};
|
||||
use primitives::v1::{
|
||||
Balance, BlockNumber, Header, Signature, AuthorityDiscoveryId,
|
||||
Balance, BlockNumber, Header, Signature, AuthorityDiscoveryId, ValidatorIndex,
|
||||
};
|
||||
use frame_system::limits;
|
||||
use frame_support::{
|
||||
@@ -472,8 +472,16 @@ mod tests {
|
||||
|
||||
impl configuration::Config for Test { }
|
||||
|
||||
pub struct TestRewardValidators;
|
||||
|
||||
impl inclusion::RewardValidators for TestRewardValidators {
|
||||
fn reward_backing(_: impl IntoIterator<Item = ValidatorIndex>) { }
|
||||
fn reward_bitfields(_: impl IntoIterator<Item = ValidatorIndex>) { }
|
||||
}
|
||||
|
||||
impl inclusion::Config for Test {
|
||||
type Event = ();
|
||||
type RewardValidators = TestRewardValidators;
|
||||
}
|
||||
|
||||
impl session_info::AuthorityDiscoveryConfig for Test {
|
||||
|
||||
@@ -62,6 +62,8 @@ pub struct CandidatePendingAvailability<H, N> {
|
||||
descriptor: CandidateDescriptor<H>,
|
||||
/// The received availability votes. One bit per validator.
|
||||
availability_votes: BitVec<BitOrderLsb0, u8>,
|
||||
/// The backers of the candidate pending availability.
|
||||
backers: BitVec<BitOrderLsb0, u8>,
|
||||
/// The block number of the relay-parent of the receipt.
|
||||
relay_parent_number: N,
|
||||
/// The block number of the relay-chain block this was backed in.
|
||||
@@ -85,6 +87,16 @@ impl<H, N> CandidatePendingAvailability<H, N> {
|
||||
}
|
||||
}
|
||||
|
||||
/// A hook for applying validator rewards
|
||||
pub trait RewardValidators {
|
||||
// Reward the validators with the given indices for issuing backing statements.
|
||||
fn reward_backing(validators: impl IntoIterator<Item=ValidatorIndex>);
|
||||
// Reward the validators with the given indices for issuing availability bitfields.
|
||||
// Validators are sent to this hook when they have contributed to the availability
|
||||
// of a candidate by setting a bit in their bitfield.
|
||||
fn reward_bitfields(validators: impl IntoIterator<Item=ValidatorIndex>);
|
||||
}
|
||||
|
||||
pub trait Config:
|
||||
frame_system::Config
|
||||
+ paras::Config
|
||||
@@ -94,6 +106,7 @@ pub trait Config:
|
||||
+ configuration::Config
|
||||
{
|
||||
type Event: From<Event<Self>> + Into<<Self as frame_system::Config>::Event>;
|
||||
type RewardValidators: RewardValidators;
|
||||
}
|
||||
|
||||
decl_storage! {
|
||||
@@ -341,6 +354,8 @@ impl<T: Config> Module<T> {
|
||||
Self::enact_candidate(
|
||||
pending_availability.relay_parent_number,
|
||||
receipt,
|
||||
pending_availability.backers,
|
||||
pending_availability.availability_votes,
|
||||
);
|
||||
|
||||
freed_cores.push(pending_availability.core);
|
||||
@@ -375,9 +390,9 @@ impl<T: Config> Module<T> {
|
||||
let check_cx = CandidateCheckContext::<T>::new();
|
||||
|
||||
// do all checks before writing storage.
|
||||
let core_indices = {
|
||||
let core_indices_and_backers = {
|
||||
let mut skip = 0;
|
||||
let mut core_indices = Vec::with_capacity(candidates.len());
|
||||
let mut core_indices_and_backers = Vec::with_capacity(candidates.len());
|
||||
let mut last_core = None;
|
||||
|
||||
let mut check_assignment_in_order = |assignment: &CoreAssignment| -> DispatchResult {
|
||||
@@ -408,6 +423,7 @@ impl<T: Config> Module<T> {
|
||||
'a:
|
||||
for (candidate_idx, candidate) in candidates.iter().enumerate() {
|
||||
let para_id = candidate.descriptor().para_id;
|
||||
let mut backers = bitvec::bitvec![BitOrderLsb0, u8; 0; validators.len()];
|
||||
|
||||
// we require that the candidate is in the context of the parent block.
|
||||
ensure!(
|
||||
@@ -504,9 +520,19 @@ impl<T: Config> Module<T> {
|
||||
),
|
||||
Err(()) => { Err(Error::<T>::InvalidBacking)?; }
|
||||
}
|
||||
|
||||
for (bit_idx, _) in candidate
|
||||
.validator_indices.iter()
|
||||
.enumerate().filter(|(_, signed)| **signed)
|
||||
{
|
||||
let val_idx = group_vals.get(bit_idx)
|
||||
.expect("this query done above; qed");
|
||||
|
||||
backers.set(*val_idx as _, true);
|
||||
}
|
||||
}
|
||||
|
||||
core_indices.push(assignment.core);
|
||||
core_indices_and_backers.push((assignment.core, backers));
|
||||
continue 'a;
|
||||
}
|
||||
}
|
||||
@@ -525,11 +551,12 @@ impl<T: Config> Module<T> {
|
||||
check_assignment_in_order(assignment)?;
|
||||
}
|
||||
|
||||
core_indices
|
||||
core_indices_and_backers
|
||||
};
|
||||
|
||||
// one more sweep for actually writing to storage.
|
||||
for (candidate, core) in candidates.into_iter().zip(core_indices.iter().cloned()) {
|
||||
let core_indices = core_indices_and_backers.iter().map(|&(ref c, _)| c.clone()).collect();
|
||||
for (candidate, (core, backers)) in candidates.into_iter().zip(core_indices_and_backers) {
|
||||
let para_id = candidate.descriptor().para_id;
|
||||
|
||||
// initialize all availability votes to 0.
|
||||
@@ -551,6 +578,7 @@ impl<T: Config> Module<T> {
|
||||
descriptor,
|
||||
availability_votes,
|
||||
relay_parent_number: check_cx.relay_parent_number,
|
||||
backers,
|
||||
backed_in_number: check_cx.now,
|
||||
});
|
||||
<PendingAvailabilityCommitments>::insert(¶_id, commitments);
|
||||
@@ -589,11 +617,23 @@ impl<T: Config> Module<T> {
|
||||
fn enact_candidate(
|
||||
relay_parent_number: T::BlockNumber,
|
||||
receipt: CommittedCandidateReceipt<T::Hash>,
|
||||
backers: BitVec<BitOrderLsb0, u8>,
|
||||
availability_votes: BitVec<BitOrderLsb0, u8>,
|
||||
) -> Weight {
|
||||
let plain = receipt.to_plain();
|
||||
let commitments = receipt.commitments;
|
||||
let config = <configuration::Module<T>>::config();
|
||||
|
||||
T::RewardValidators::reward_backing(backers.iter().enumerate()
|
||||
.filter(|(_, backed)| **backed)
|
||||
.map(|(i, _)| i as _)
|
||||
);
|
||||
|
||||
T::RewardValidators::reward_bitfields(availability_votes.iter().enumerate()
|
||||
.filter(|(_, voted)| **voted)
|
||||
.map(|(i, _)| i as _)
|
||||
);
|
||||
|
||||
// initial weight is config read.
|
||||
let mut weight = T::DbWeight::get().reads_writes(1, 0);
|
||||
if let Some(new_code) = commitments.new_validation_code {
|
||||
@@ -690,6 +730,8 @@ impl<T: Config> Module<T> {
|
||||
Self::enact_candidate(
|
||||
pending.relay_parent_number,
|
||||
candidate,
|
||||
pending.backers,
|
||||
pending.availability_votes,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -988,6 +1030,18 @@ mod tests {
|
||||
bitvec::bitvec![BitOrderLsb0, u8; 0; Validators::get().len()]
|
||||
}
|
||||
|
||||
fn default_backing_bitfield() -> BitVec<BitOrderLsb0, u8> {
|
||||
bitvec::bitvec![BitOrderLsb0, u8; 0; Validators::get().len()]
|
||||
}
|
||||
|
||||
fn backing_bitfield(v: &[usize]) -> BitVec<BitOrderLsb0, u8> {
|
||||
let mut b = default_backing_bitfield();
|
||||
for i in v {
|
||||
b.set(*i, true);
|
||||
}
|
||||
b
|
||||
}
|
||||
|
||||
fn validator_pubkeys(val_ids: &[Sr25519Keyring]) -> Vec<ValidatorId> {
|
||||
val_ids.iter().map(|v| v.public().into()).collect()
|
||||
}
|
||||
@@ -1062,6 +1116,7 @@ mod tests {
|
||||
availability_votes: default_availability_votes(),
|
||||
relay_parent_number: 0,
|
||||
backed_in_number: 0,
|
||||
backers: default_backing_bitfield(),
|
||||
});
|
||||
PendingAvailabilityCommitments::insert(chain_a, default_candidate.commitments.clone());
|
||||
|
||||
@@ -1071,6 +1126,7 @@ mod tests {
|
||||
availability_votes: default_availability_votes(),
|
||||
relay_parent_number: 0,
|
||||
backed_in_number: 0,
|
||||
backers: default_backing_bitfield(),
|
||||
});
|
||||
PendingAvailabilityCommitments::insert(chain_b, default_candidate.commitments);
|
||||
|
||||
@@ -1234,6 +1290,7 @@ mod tests {
|
||||
availability_votes: default_availability_votes(),
|
||||
relay_parent_number: 0,
|
||||
backed_in_number: 0,
|
||||
backers: default_backing_bitfield(),
|
||||
});
|
||||
PendingAvailabilityCommitments::insert(chain_a, default_candidate.commitments);
|
||||
|
||||
@@ -1268,6 +1325,7 @@ mod tests {
|
||||
availability_votes: default_availability_votes(),
|
||||
relay_parent_number: 0,
|
||||
backed_in_number: 0,
|
||||
backers: default_backing_bitfield(),
|
||||
});
|
||||
|
||||
*bare_bitfield.0.get_mut(0).unwrap() = true;
|
||||
@@ -1339,6 +1397,7 @@ mod tests {
|
||||
availability_votes: default_availability_votes(),
|
||||
relay_parent_number: 0,
|
||||
backed_in_number: 0,
|
||||
backers: backing_bitfield(&[3, 4]),
|
||||
});
|
||||
PendingAvailabilityCommitments::insert(chain_a, candidate_a.commitments);
|
||||
|
||||
@@ -1354,6 +1413,7 @@ mod tests {
|
||||
availability_votes: default_availability_votes(),
|
||||
relay_parent_number: 0,
|
||||
backed_in_number: 0,
|
||||
backers: backing_bitfield(&[0, 2]),
|
||||
});
|
||||
PendingAvailabilityCommitments::insert(chain_b, candidate_b.commitments);
|
||||
|
||||
@@ -1424,6 +1484,25 @@ mod tests {
|
||||
|
||||
// and check that chain head was enacted.
|
||||
assert_eq!(Paras::para_head(&chain_a), Some(vec![1, 2, 3, 4].into()));
|
||||
|
||||
// Check that rewards are applied.
|
||||
{
|
||||
let rewards = crate::mock::availability_rewards();
|
||||
|
||||
assert_eq!(rewards.len(), 4);
|
||||
assert_eq!(rewards.get(&0).unwrap(), &1);
|
||||
assert_eq!(rewards.get(&1).unwrap(), &1);
|
||||
assert_eq!(rewards.get(&2).unwrap(), &1);
|
||||
assert_eq!(rewards.get(&3).unwrap(), &1);
|
||||
}
|
||||
|
||||
{
|
||||
let rewards = crate::mock::backing_rewards();
|
||||
|
||||
assert_eq!(rewards.len(), 2);
|
||||
assert_eq!(rewards.get(&3).unwrap(), &1);
|
||||
assert_eq!(rewards.get(&4).unwrap(), &1);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1764,6 +1843,7 @@ mod tests {
|
||||
availability_votes: default_availability_votes(),
|
||||
relay_parent_number: 3,
|
||||
backed_in_number: 4,
|
||||
backers: default_backing_bitfield(),
|
||||
});
|
||||
<PendingAvailabilityCommitments>::insert(&chain_a, candidate.commitments);
|
||||
|
||||
@@ -2051,6 +2131,7 @@ mod tests {
|
||||
availability_votes: default_availability_votes(),
|
||||
relay_parent_number: System::block_number() - 1,
|
||||
backed_in_number: System::block_number(),
|
||||
backers: backing_bitfield(&[0, 1]),
|
||||
})
|
||||
);
|
||||
assert_eq!(
|
||||
@@ -2066,6 +2147,7 @@ mod tests {
|
||||
availability_votes: default_availability_votes(),
|
||||
relay_parent_number: System::block_number() - 1,
|
||||
backed_in_number: System::block_number(),
|
||||
backers: backing_bitfield(&[2, 3]),
|
||||
})
|
||||
);
|
||||
assert_eq!(
|
||||
@@ -2081,6 +2163,7 @@ mod tests {
|
||||
availability_votes: default_availability_votes(),
|
||||
relay_parent_number: System::block_number() - 1,
|
||||
backed_in_number: System::block_number(),
|
||||
backers: backing_bitfield(&[4]),
|
||||
})
|
||||
);
|
||||
assert_eq!(
|
||||
@@ -2175,6 +2258,7 @@ mod tests {
|
||||
availability_votes: default_availability_votes(),
|
||||
relay_parent_number: System::block_number() - 1,
|
||||
backed_in_number: System::block_number(),
|
||||
backers: backing_bitfield(&[0, 1, 2]),
|
||||
})
|
||||
);
|
||||
assert_eq!(
|
||||
@@ -2249,6 +2333,7 @@ mod tests {
|
||||
availability_votes: default_availability_votes(),
|
||||
relay_parent_number: 5,
|
||||
backed_in_number: 6,
|
||||
backers: default_backing_bitfield(),
|
||||
});
|
||||
<PendingAvailabilityCommitments>::insert(&chain_a, candidate.commitments.clone());
|
||||
|
||||
@@ -2258,6 +2343,7 @@ mod tests {
|
||||
availability_votes: default_availability_votes(),
|
||||
relay_parent_number: 6,
|
||||
backed_in_number: 7,
|
||||
backers: default_backing_bitfield(),
|
||||
});
|
||||
<PendingAvailabilityCommitments>::insert(&chain_b, candidate.commitments);
|
||||
|
||||
|
||||
@@ -33,6 +33,7 @@ pub mod origin;
|
||||
pub mod dmp;
|
||||
pub mod ump;
|
||||
pub mod hrmp;
|
||||
pub mod reward_points;
|
||||
|
||||
pub mod runtime_api_impl;
|
||||
|
||||
|
||||
@@ -21,11 +21,13 @@ use sp_core::H256;
|
||||
use sp_runtime::traits::{
|
||||
BlakeTwo256, IdentityLookup,
|
||||
};
|
||||
use primitives::v1::{AuthorityDiscoveryId, BlockNumber, Header};
|
||||
use primitives::v1::{AuthorityDiscoveryId, BlockNumber, Header, ValidatorIndex};
|
||||
use frame_support::{
|
||||
impl_outer_origin, impl_outer_dispatch, impl_outer_event, parameter_types,
|
||||
traits::Randomness as RandomnessT,
|
||||
};
|
||||
use std::cell::RefCell;
|
||||
use std::collections::HashMap;
|
||||
use crate::inclusion;
|
||||
use crate as parachains;
|
||||
|
||||
@@ -114,6 +116,7 @@ impl crate::scheduler::Config for Test { }
|
||||
|
||||
impl crate::inclusion::Config for Test {
|
||||
type Event = TestEvent;
|
||||
type RewardValidators = TestRewardValidators;
|
||||
}
|
||||
|
||||
impl crate::session_info::Config for Test { }
|
||||
@@ -124,6 +127,43 @@ impl crate::session_info::AuthorityDiscoveryConfig for Test {
|
||||
}
|
||||
}
|
||||
|
||||
thread_local! {
|
||||
pub static BACKING_REWARDS: RefCell<HashMap<ValidatorIndex, usize>>
|
||||
= RefCell::new(HashMap::new());
|
||||
|
||||
pub static AVAILABILITY_REWARDS: RefCell<HashMap<ValidatorIndex, usize>>
|
||||
= RefCell::new(HashMap::new());
|
||||
}
|
||||
|
||||
pub fn backing_rewards() -> HashMap<ValidatorIndex, usize> {
|
||||
BACKING_REWARDS.with(|r| r.borrow().clone())
|
||||
}
|
||||
|
||||
pub fn availability_rewards() -> HashMap<ValidatorIndex, usize> {
|
||||
AVAILABILITY_REWARDS.with(|r| r.borrow().clone())
|
||||
}
|
||||
|
||||
pub struct TestRewardValidators;
|
||||
|
||||
impl inclusion::RewardValidators for TestRewardValidators {
|
||||
fn reward_backing(v: impl IntoIterator<Item = ValidatorIndex>) {
|
||||
BACKING_REWARDS.with(|r| {
|
||||
let mut r = r.borrow_mut();
|
||||
for i in v {
|
||||
*r.entry(i).or_insert(0) += 1;
|
||||
}
|
||||
})
|
||||
}
|
||||
fn reward_bitfields(v: impl IntoIterator<Item = ValidatorIndex>) {
|
||||
AVAILABILITY_REWARDS.with(|r| {
|
||||
let mut r = r.borrow_mut();
|
||||
for i in v {
|
||||
*r.entry(i).or_insert(0) += 1;
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub type System = frame_system::Module<Test>;
|
||||
|
||||
/// Mocked initializer.
|
||||
@@ -155,6 +195,9 @@ pub type SessionInfo = crate::session_info::Module<Test>;
|
||||
|
||||
/// Create a new set of test externalities.
|
||||
pub fn new_test_ext(state: GenesisConfig) -> TestExternalities {
|
||||
BACKING_REWARDS.with(|r| r.borrow_mut().clear());
|
||||
AVAILABILITY_REWARDS.with(|r| r.borrow_mut().clear());
|
||||
|
||||
let mut t = state.system.build_storage::<Test>().unwrap();
|
||||
state.configuration.assimilate_storage(&mut t).unwrap();
|
||||
state.paras.assimilate_storage(&mut t).unwrap();
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
// Copyright 2020 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Polkadot.
|
||||
|
||||
// Polkadot is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
|
||||
// Polkadot is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Polkadot. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//! An implementation of the `RewardValidators` trait used by `inclusion` that employs
|
||||
//! `pallet-staking` to compute the rewards.
|
||||
//!
|
||||
//! Based on https://w3f-research.readthedocs.io/en/latest/polkadot/Token%20Economics.html
|
||||
//! which doesn't currently mention availability bitfields. As such, we don't reward them
|
||||
//! for the time being, although we will build schemes to do so in the future.
|
||||
|
||||
use primitives::v1::ValidatorIndex;
|
||||
use pallet_staking::SessionInterface;
|
||||
|
||||
/// The amount of era points given by backing a candidate that is included.
|
||||
pub const BACKING_POINTS: u32 = 20;
|
||||
|
||||
/// Rewards validators for participating in parachains with era points in pallet-staking.
|
||||
pub struct RewardValidatorsWithEraPoints<C>(sp_std::marker::PhantomData<C>);
|
||||
|
||||
fn reward_by_indices<C, I>(points: u32, indices: I) where
|
||||
C: pallet_staking::Config,
|
||||
I: IntoIterator<Item = ValidatorIndex>
|
||||
{
|
||||
// Fetch the validators from the _session_ because sessions are offset from eras
|
||||
// and we are rewarding for behavior in current session.
|
||||
let validators = C::SessionInterface::validators();
|
||||
let rewards = indices.into_iter()
|
||||
.filter_map(|i| validators.get(i as usize).map(|v| v.clone()))
|
||||
.map(|v| (v, points));
|
||||
|
||||
<pallet_staking::Module<C>>::reward_by_ids(rewards);
|
||||
}
|
||||
|
||||
impl<C> crate::inclusion::RewardValidators for RewardValidatorsWithEraPoints<C>
|
||||
where C: pallet_staking::Config
|
||||
{
|
||||
fn reward_backing(validators: impl IntoIterator<Item=ValidatorIndex>) {
|
||||
reward_by_indices::<C, _>(BACKING_POINTS, validators);
|
||||
}
|
||||
|
||||
fn reward_bitfields(_validators: impl IntoIterator<Item=ValidatorIndex>) { }
|
||||
}
|
||||
@@ -78,6 +78,7 @@ use runtime_parachains::dmp as parachains_dmp;
|
||||
use runtime_parachains::ump as parachains_ump;
|
||||
use runtime_parachains::hrmp as parachains_hrmp;
|
||||
use runtime_parachains::scheduler as parachains_scheduler;
|
||||
use runtime_parachains::reward_points::RewardValidatorsWithEraPoints;
|
||||
|
||||
pub use pallet_balances::Call as BalancesCall;
|
||||
pub use pallet_staking::StakerStatus;
|
||||
@@ -538,6 +539,7 @@ impl parachains_configuration::Config for Runtime {}
|
||||
|
||||
impl parachains_inclusion::Config for Runtime {
|
||||
type Event = Event;
|
||||
type RewardValidators = RewardValidatorsWithEraPoints<Runtime>;
|
||||
}
|
||||
|
||||
impl parachains_paras::Config for Runtime {
|
||||
|
||||
@@ -73,6 +73,7 @@ use frame_support::{
|
||||
use authority_discovery_primitives::AuthorityId as AuthorityDiscoveryId;
|
||||
use pallet_transaction_payment_rpc_runtime_api::RuntimeDispatchInfo;
|
||||
use pallet_session::historical as session_historical;
|
||||
use polkadot_runtime_parachains::reward_points::RewardValidatorsWithEraPoints;
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
pub use pallet_staking::StakerStatus;
|
||||
@@ -446,6 +447,7 @@ impl parachains_configuration::Config for Runtime {}
|
||||
|
||||
impl parachains_inclusion::Config for Runtime {
|
||||
type Event = Event;
|
||||
type RewardValidators = RewardValidatorsWithEraPoints<Runtime>;
|
||||
}
|
||||
|
||||
impl parachains_inclusion_inherent::Config for Runtime {}
|
||||
|
||||
Reference in New Issue
Block a user