mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-14 05:11:09 +00:00
New sub-trait to mock staking miner (#11350)
* new separate config trait for staking miner * fix some docs and stuff * relax trait bounds * some cleanup * Update frame/election-provider-multi-phase/src/unsigned.rs * add comment * self review and fix build * fix docs Co-authored-by: Niklas Adolfsson <niklasadolfsson1@gmail.com>
This commit is contained in:
@@ -103,7 +103,7 @@
|
||||
//!
|
||||
//! Validators will only submit solutions if the one that they have computed is sufficiently better
|
||||
//! than the best queued one (see [`pallet::Config::BetterUnsignedThreshold`]) and will limit the
|
||||
//! weight of the solution to [`pallet::Config::MinerMaxWeight`].
|
||||
//! weight of the solution to [`MinerConfig::MaxWeight`].
|
||||
//!
|
||||
//! The unsigned phase can be made passive depending on how the previous signed phase went, by
|
||||
//! setting the first inner value of [`Phase`] to `false`. For now, the signed phase is always
|
||||
@@ -276,16 +276,18 @@ pub use signed::{
|
||||
BalanceOf, NegativeImbalanceOf, PositiveImbalanceOf, SignedSubmission, SignedSubmissionOf,
|
||||
SignedSubmissions, SubmissionIndicesOf,
|
||||
};
|
||||
pub use unsigned::{Miner, MinerConfig};
|
||||
|
||||
/// The solution type used by this crate.
|
||||
pub type SolutionOf<T> = <T as Config>::Solution;
|
||||
pub type SolutionOf<T> = <T as MinerConfig>::Solution;
|
||||
|
||||
/// The voter index. Derived from [`SolutionOf`].
|
||||
pub type SolutionVoterIndexOf<T> = <SolutionOf<T> as NposSolution>::VoterIndex;
|
||||
/// The target index. Derived from [`SolutionOf`].
|
||||
pub type SolutionTargetIndexOf<T> = <SolutionOf<T> as NposSolution>::TargetIndex;
|
||||
/// The accuracy of the election, when submitted from offchain. Derived from [`SolutionOf`].
|
||||
pub type SolutionAccuracyOf<T> = <SolutionOf<T> as NposSolution>::Accuracy;
|
||||
pub type SolutionAccuracyOf<T> =
|
||||
<SolutionOf<<T as crate::Config>::MinerConfig> as NposSolution>::Accuracy;
|
||||
/// The fallback election type.
|
||||
pub type FallbackErrorOf<T> = <<T as crate::Config>::Fallback as ElectionProvider>::Error;
|
||||
|
||||
@@ -488,7 +490,7 @@ pub enum ElectionError<T: Config> {
|
||||
/// An error happened in the feasibility check sub-system.
|
||||
Feasibility(FeasibilityError),
|
||||
/// An error in the miner (offchain) sub-system.
|
||||
Miner(unsigned::MinerError<T>),
|
||||
Miner(unsigned::MinerError),
|
||||
/// An error happened in the data provider.
|
||||
DataProvider(&'static str),
|
||||
/// An error nested in the fallback.
|
||||
@@ -520,8 +522,8 @@ impl<T: Config> From<FeasibilityError> for ElectionError<T> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Config> From<unsigned::MinerError<T>> for ElectionError<T> {
|
||||
fn from(e: unsigned::MinerError<T>) -> Self {
|
||||
impl<T: Config> From<unsigned::MinerError> for ElectionError<T> {
|
||||
fn from(e: unsigned::MinerError) -> Self {
|
||||
ElectionError::Miner(e)
|
||||
}
|
||||
}
|
||||
@@ -605,12 +607,14 @@ pub mod pallet {
|
||||
#[pallet::constant]
|
||||
type MinerTxPriority: Get<TransactionPriority>;
|
||||
|
||||
/// Maximum weight that the miner should consume.
|
||||
/// Configurations of the embedded miner.
|
||||
///
|
||||
/// The miner will ensure that the total weight of the unsigned solution will not exceed
|
||||
/// this value, based on [`WeightInfo::submit_unsigned`].
|
||||
#[pallet::constant]
|
||||
type MinerMaxWeight: Get<Weight>;
|
||||
/// Any external software implementing this can use the [`unsigned::Miner`] type provided,
|
||||
/// which can mine new solutions and trim them accordingly.
|
||||
type MinerConfig: crate::unsigned::MinerConfig<
|
||||
AccountId = Self::AccountId,
|
||||
MaxVotesPerVoter = <Self::DataProvider as ElectionDataProvider>::MaxVotesPerVoter,
|
||||
>;
|
||||
|
||||
/// Maximum number of signed submissions that can be queued.
|
||||
///
|
||||
@@ -624,7 +628,9 @@ pub mod pallet {
|
||||
|
||||
/// Maximum weight of a signed solution.
|
||||
///
|
||||
/// This should probably be similar to [`Config::MinerMaxWeight`].
|
||||
/// If [`Config::MinerConfig`] is being implemented to submit signed solutions (outside of
|
||||
/// this pallet), then [`MinerConfig::solution_weight`] is used to compare against
|
||||
/// this value.
|
||||
#[pallet::constant]
|
||||
type SignedMaxWeight: Get<Weight>;
|
||||
|
||||
@@ -652,11 +658,11 @@ pub mod pallet {
|
||||
/// are only over a single block, but once multi-block elections are introduced they will
|
||||
/// take place over multiple blocks.
|
||||
#[pallet::constant]
|
||||
type MaxElectingVoters: Get<SolutionVoterIndexOf<Self>>;
|
||||
type MaxElectingVoters: Get<SolutionVoterIndexOf<Self::MinerConfig>>;
|
||||
|
||||
/// The maximum number of electable targets to put in the snapshot.
|
||||
#[pallet::constant]
|
||||
type MaxElectableTargets: Get<SolutionTargetIndexOf<Self>>;
|
||||
type MaxElectableTargets: Get<SolutionTargetIndexOf<Self::MinerConfig>>;
|
||||
|
||||
/// Handler for the slashed deposits.
|
||||
type SlashHandler: OnUnbalanced<NegativeImbalanceOf<Self>>;
|
||||
@@ -664,30 +670,12 @@ pub mod pallet {
|
||||
/// Handler for the rewards.
|
||||
type RewardHandler: OnUnbalanced<PositiveImbalanceOf<Self>>;
|
||||
|
||||
/// Maximum length (bytes) that the mined solution should consume.
|
||||
///
|
||||
/// The miner will ensure that the total length of the unsigned solution will not exceed
|
||||
/// this value.
|
||||
#[pallet::constant]
|
||||
type MinerMaxLength: Get<u32>;
|
||||
|
||||
/// Something that will provide the election data.
|
||||
type DataProvider: ElectionDataProvider<
|
||||
AccountId = Self::AccountId,
|
||||
BlockNumber = Self::BlockNumber,
|
||||
>;
|
||||
|
||||
/// The solution type.
|
||||
type Solution: codec::Codec
|
||||
+ Default
|
||||
+ PartialEq
|
||||
+ Eq
|
||||
+ Clone
|
||||
+ sp_std::fmt::Debug
|
||||
+ Ord
|
||||
+ NposSolution
|
||||
+ TypeInfo;
|
||||
|
||||
/// Configuration for the fallback.
|
||||
type Fallback: InstantElectionProvider<
|
||||
AccountId = Self::AccountId,
|
||||
@@ -824,12 +812,12 @@ pub mod pallet {
|
||||
use sp_std::mem::size_of;
|
||||
// The index type of both voters and targets need to be smaller than that of usize (very
|
||||
// unlikely to be the case, but anyhow)..
|
||||
assert!(size_of::<SolutionVoterIndexOf<T>>() <= size_of::<usize>());
|
||||
assert!(size_of::<SolutionTargetIndexOf<T>>() <= size_of::<usize>());
|
||||
assert!(size_of::<SolutionVoterIndexOf<T::MinerConfig>>() <= size_of::<usize>());
|
||||
assert!(size_of::<SolutionTargetIndexOf<T::MinerConfig>>() <= size_of::<usize>());
|
||||
|
||||
// ----------------------------
|
||||
// Based on the requirements of [`sp_npos_elections::Assignment::try_normalize`].
|
||||
let max_vote: usize = <SolutionOf<T> as NposSolution>::LIMIT;
|
||||
let max_vote: usize = <SolutionOf<T::MinerConfig> as NposSolution>::LIMIT;
|
||||
|
||||
// 2. Maximum sum of [SolutionAccuracy; 16] must fit into `UpperOf<OffchainAccuracy>`.
|
||||
let maximum_chain_accuracy: Vec<UpperOf<SolutionAccuracyOf<T>>> = (0..max_vote)
|
||||
@@ -850,7 +838,7 @@ pub mod pallet {
|
||||
// solution cannot represent any voters more than `LIMIT` anyhow.
|
||||
assert_eq!(
|
||||
<T::DataProvider as ElectionDataProvider>::MaxVotesPerVoter::get(),
|
||||
<SolutionOf<T> as NposSolution>::LIMIT as u32,
|
||||
<SolutionOf<T::MinerConfig> as NposSolution>::LIMIT as u32,
|
||||
);
|
||||
|
||||
// While it won't cause any failures, setting `SignedMaxRefunds` gt
|
||||
@@ -887,7 +875,7 @@ pub mod pallet {
|
||||
))]
|
||||
pub fn submit_unsigned(
|
||||
origin: OriginFor<T>,
|
||||
raw_solution: Box<RawSolution<SolutionOf<T>>>,
|
||||
raw_solution: Box<RawSolution<SolutionOf<T::MinerConfig>>>,
|
||||
witness: SolutionOrSnapshotSize,
|
||||
) -> DispatchResultWithPostInfo {
|
||||
ensure_none(origin)?;
|
||||
@@ -976,7 +964,7 @@ pub mod pallet {
|
||||
#[pallet::weight(T::WeightInfo::submit())]
|
||||
pub fn submit(
|
||||
origin: OriginFor<T>,
|
||||
raw_solution: Box<RawSolution<SolutionOf<T>>>,
|
||||
raw_solution: Box<RawSolution<SolutionOf<T::MinerConfig>>>,
|
||||
) -> DispatchResult {
|
||||
let who = ensure_signed(origin)?;
|
||||
|
||||
@@ -991,7 +979,7 @@ pub mod pallet {
|
||||
let size = Self::snapshot_metadata().ok_or(Error::<T>::MissingSnapshotMetadata)?;
|
||||
|
||||
ensure!(
|
||||
Self::feasibility_weight_of(&raw_solution, size) < T::SignedMaxWeight::get(),
|
||||
Self::solution_weight_of(&raw_solution, size) < T::SignedMaxWeight::get(),
|
||||
Error::<T>::SignedTooMuchWeight,
|
||||
);
|
||||
|
||||
@@ -1429,7 +1417,7 @@ impl<T: Config> Pallet<T> {
|
||||
|
||||
/// Checks the feasibility of a solution.
|
||||
pub fn feasibility_check(
|
||||
raw_solution: RawSolution<SolutionOf<T>>,
|
||||
raw_solution: RawSolution<SolutionOf<T::MinerConfig>>,
|
||||
compute: ElectionCompute,
|
||||
) -> Result<ReadySolution<T::AccountId>, FeasibilityError> {
|
||||
let RawSolution { solution, score, round } = raw_solution;
|
||||
@@ -1459,10 +1447,10 @@ impl<T: Config> Pallet<T> {
|
||||
Self::snapshot().ok_or(FeasibilityError::SnapshotUnavailable)?;
|
||||
|
||||
// ----- Start building. First, we need some closures.
|
||||
let cache = helpers::generate_voter_cache::<T>(&snapshot_voters);
|
||||
let voter_at = helpers::voter_at_fn::<T>(&snapshot_voters);
|
||||
let target_at = helpers::target_at_fn::<T>(&snapshot_targets);
|
||||
let voter_index = helpers::voter_index_fn_usize::<T>(&cache);
|
||||
let cache = helpers::generate_voter_cache::<T::MinerConfig>(&snapshot_voters);
|
||||
let voter_at = helpers::voter_at_fn::<T::MinerConfig>(&snapshot_voters);
|
||||
let target_at = helpers::target_at_fn::<T::MinerConfig>(&snapshot_targets);
|
||||
let voter_index = helpers::voter_index_fn_usize::<T::MinerConfig>(&cache);
|
||||
|
||||
// Then convert solution -> assignment. This will fail if any of the indices are gibberish,
|
||||
// namely any of the voters or targets.
|
||||
@@ -1493,7 +1481,7 @@ impl<T: Config> Pallet<T> {
|
||||
})?;
|
||||
|
||||
// ----- Start building support. First, we need one more closure.
|
||||
let stake_of = helpers::stake_of_fn::<T>(&snapshot_voters, &cache);
|
||||
let stake_of = helpers::stake_of_fn::<T::MinerConfig>(&snapshot_voters, &cache);
|
||||
|
||||
// This might fail if the normalization fails. Very unlikely. See `integrity_test`.
|
||||
let staked_assignments = assignment_ratio_to_staked_normalized(assignments, stake_of)
|
||||
@@ -1803,8 +1791,8 @@ mod tests {
|
||||
use super::*;
|
||||
use crate::{
|
||||
mock::{
|
||||
multi_phase_events, roll_to, AccountId, ExtBuilder, MockWeightInfo, MultiPhase,
|
||||
Runtime, SignedMaxSubmissions, System, TargetIndex, Targets,
|
||||
multi_phase_events, roll_to, AccountId, ExtBuilder, MockWeightInfo, MockedWeightInfo,
|
||||
MultiPhase, Runtime, SignedMaxSubmissions, System, TargetIndex, Targets,
|
||||
},
|
||||
Phase,
|
||||
};
|
||||
@@ -2123,7 +2111,7 @@ mod tests {
|
||||
// set the solution balancing to get the desired score.
|
||||
crate::mock::Balancing::set(Some((2, 0)));
|
||||
|
||||
let (solution, _) = MultiPhase::mine_solution::<<Runtime as Config>::Solver>().unwrap();
|
||||
let (solution, _) = MultiPhase::mine_solution().unwrap();
|
||||
// Default solution's score.
|
||||
assert!(matches!(solution.score, ElectionScore { minimal_stake: 50, .. }));
|
||||
|
||||
@@ -2147,7 +2135,7 @@ mod tests {
|
||||
#[test]
|
||||
fn number_of_voters_allowed_2sec_block() {
|
||||
// Just a rough estimate with the substrate weights.
|
||||
assert!(!MockWeightInfo::get());
|
||||
assert_eq!(MockWeightInfo::get(), MockedWeightInfo::Real);
|
||||
|
||||
let all_voters: u32 = 10_000;
|
||||
let all_targets: u32 = 5_000;
|
||||
|
||||
Reference in New Issue
Block a user