Skip to content
This repository has been archived by the owner on Nov 15, 2023. It is now read-only.

Create trait for NPoS election algorithms #9664

Merged
37 commits merged into from
Sep 9, 2021
Merged
Show file tree
Hide file tree
Changes from 34 commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
476669d
build the template, hand it over to zeke now.
kianenigma Aug 29, 2021
1092963
Tests working
emostov Aug 30, 2021
45825e4
save wip
emostov Aug 31, 2021
7efe4ad
Merge branch 'master' of https://github.com/paritytech/substrate into…
emostov Aug 31, 2021
0396144
Some updates
emostov Aug 31, 2021
4081cd7
Merge branch 'master' of https://github.com/paritytech/substrate into…
emostov Aug 31, 2021
faf8647
Some cleanup
emostov Aug 31, 2021
68692f3
mo cleanin
emostov Aug 31, 2021
f404d4d
Link to issue
emostov Aug 31, 2021
8d34eba
Apply suggestions from code review
emostov Sep 1, 2021
a7f9a55
Apply suggestions from code review
emostov Sep 1, 2021
cac39c9
Apply suggestions from code review
emostov Sep 1, 2021
36915eb
Apply suggestions from code review
emostov Sep 1, 2021
bd3f4e9
Bound accuracy for prepare_election_result
emostov Sep 1, 2021
af52933
Use npos_election::Error for phragmms
emostov Sep 1, 2021
5b911ba
save
emostov Sep 1, 2021
bc43230
Apply suggestions from code review
emostov Sep 1, 2021
be84027
Simplify test to use Balancing::set
emostov Sep 1, 2021
d351624
Merge branch 'kiz-election-trait' of https://github.com/paritytech/su…
emostov Sep 1, 2021
f3a8de1
Try merge origin master
emostov Sep 5, 2021
7d726c8
Cargo.lock after build
emostov Sep 5, 2021
9c0a8e6
Revert "Cargo.lock after build"
emostov Sep 5, 2021
4622a9d
Try reduce cargo.lock diff
emostov Sep 5, 2021
44446e9
Update bin/node/runtime/src/lib.rs
emostov Sep 5, 2021
22678fd
Comment
emostov Sep 5, 2021
e749ce0
Apply suggestions from code review
emostov Sep 5, 2021
0cdda23
Set balancing directly
emostov Sep 7, 2021
68e6dae
Document som pub items
emostov Sep 7, 2021
b7ab21f
Merge branch 'kiz-election-trait' of https://github.com/paritytech/su…
emostov Sep 7, 2021
1fc657d
Update frame/election-provider-multi-phase/src/unsigned.rs
emostov Sep 7, 2021
0b1751c
Apply suggestions from code review
emostov Sep 7, 2021
f896242
Improve some comments
emostov Sep 7, 2021
e256252
Revert accidental change to random file
emostov Sep 7, 2021
4601b0b
Merge remote-tracking branch 'origin' into kiz-election-trait
emostov Sep 7, 2021
8a97010
Merge remote-tracking branch 'origin' into kiz-election-trait
emostov Sep 8, 2021
165db44
tiney
emostov Sep 9, 2021
65f5a51
revert
emostov Sep 9, 2021
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 2 additions & 3 deletions bin/node/runtime/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ sp-session = { version = "4.0.0-dev", default-features = false, path = "../../..
sp-transaction-pool = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/transaction-pool" }
sp-version = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/version" }
sp-npos-elections = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/npos-elections" }
sp-io = { version = "4.0.0-dev", default-features = false, path = "../../../primitives/io" }

# frame dependencies
frame-executive = { version = "4.0.0-dev", default-features = false, path = "../../../frame/executive" }
Expand Down Expand Up @@ -98,9 +99,6 @@ pallet-vesting = { version = "4.0.0-dev", default-features = false, path = "../.
[build-dependencies]
substrate-wasm-builder = { version = "5.0.0-dev", path = "../../../utils/wasm-builder" }

[dev-dependencies]
sp-io = { version = "4.0.0-dev", path = "../../../primitives/io" }

[features]
default = ["std"]
with-tracing = ["frame-executive/with-tracing"]
Expand Down Expand Up @@ -169,6 +167,7 @@ std = [
"log/std",
"frame-try-runtime/std",
"sp-npos-elections/std",
"sp-io/std"
]
runtime-benchmarks = [
"frame-benchmarking",
Expand Down
33 changes: 31 additions & 2 deletions bin/node/runtime/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -534,7 +534,6 @@ parameter_types! {

// miner configs
pub const MultiPhaseUnsignedPriority: TransactionPriority = StakingUnsignedPriority::get() - 1u64;
pub const MinerMaxIterations: u32 = 10;
pub MinerMaxWeight: Weight = RuntimeBlockWeights::get()
.get(DispatchClass::Normal)
.max_extrinsic.expect("Normal extrinsics have a weight limit configured; qed")
Expand Down Expand Up @@ -570,6 +569,32 @@ impl pallet_election_provider_multi_phase::BenchmarkingConfig for BenchmarkConfi
const MAXIMUM_TARGETS: u32 = 2000;
}

/// Maximum number of iterations for balancing that will be executed in the embedded OCW
/// miner of election provider multi phase.
pub const MINER_MAX_ITERATIONS: u32 = 10;

/// A source of random balance for NposSolver, which is meant to be run by the OCW election miner.
pub struct OffchainRandomBalancing;
impl frame_support::pallet_prelude::Get<Option<(usize, sp_npos_elections::ExtendedBalance)>>
for OffchainRandomBalancing
{
fn get() -> Option<(usize, sp_npos_elections::ExtendedBalance)> {
use sp_runtime::traits::TrailingZeroInput;
let iters = match MINER_MAX_ITERATIONS {
0 => 0,
max @ _ => {
let seed = sp_io::offchain::random_seed();
let random = <u32>::decode(&mut TrailingZeroInput::new(&seed))
.expect("input is padded with zeroes; qed") %
max.saturating_add(1);
random as usize
},
};

Some((iters, 0))
}
}

impl pallet_election_provider_multi_phase::Config for Runtime {
type Event = Event;
type Currency = Balances;
Expand All @@ -578,7 +603,6 @@ impl pallet_election_provider_multi_phase::Config for Runtime {
type UnsignedPhase = UnsignedPhase;
type SolutionImprovementThreshold = SolutionImprovementThreshold;
type OffchainRepeat = OffchainRepeat;
type MinerMaxIterations = MinerMaxIterations;
type MinerMaxWeight = MinerMaxWeight;
type MinerMaxLength = MinerMaxLength;
type MinerTxPriority = MultiPhaseUnsignedPriority;
Expand All @@ -594,6 +618,11 @@ impl pallet_election_provider_multi_phase::Config for Runtime {
type OnChainAccuracy = Perbill;
type Solution = NposSolution16;
type Fallback = Fallback;
type Solver = frame_election_provider_support::SequentialPhragmen<
AccountId,
pallet_election_provider_multi_phase::SolutionAccuracyOf<Runtime>,
OffchainRandomBalancing,
>;
type WeightInfo = pallet_election_provider_multi_phase::weights::SubstrateWeight<Runtime>;
type ForceOrigin = EnsureRootOrHalfCouncil;
type BenchmarkingConfig = BenchmarkConfig;
Expand Down
37 changes: 20 additions & 17 deletions frame/election-provider-multi-phase/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -485,13 +485,13 @@ pub struct SolutionOrSnapshotSize {
/// Internal errors of the pallet.
///
/// Note that this is different from [`pallet::Error`].
#[derive(Debug, Eq, PartialEq)]
#[derive(frame_support::DebugNoBound, frame_support::PartialEqNoBound)]
#[cfg_attr(feature = "runtime-benchmarks", derive(strum_macros::IntoStaticStr))]
pub enum ElectionError {
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),
Miner(unsigned::MinerError<T>),
/// An error in the on-chain fallback.
OnChainFallback(onchain::Error),
/// An error happened in the data provider.
Expand All @@ -500,20 +500,20 @@ pub enum ElectionError {
NoFallbackConfigured,
}

impl From<onchain::Error> for ElectionError {
impl<T: Config> From<onchain::Error> for ElectionError<T> {
fn from(e: onchain::Error) -> Self {
ElectionError::OnChainFallback(e)
}
}

impl From<FeasibilityError> for ElectionError {
impl<T: Config> From<FeasibilityError> for ElectionError<T> {
fn from(e: FeasibilityError) -> Self {
ElectionError::Feasibility(e)
}
}

impl From<unsigned::MinerError> for ElectionError {
fn from(e: unsigned::MinerError) -> Self {
impl<T: Config> From<unsigned::MinerError<T>> for ElectionError<T> {
fn from(e: unsigned::MinerError<T>) -> Self {
ElectionError::Miner(e)
}
}
Expand Down Expand Up @@ -555,6 +555,7 @@ pub use pallet::*;
#[frame_support::pallet]
pub mod pallet {
use super::*;
use frame_election_provider_support::NposSolver;
use frame_support::{pallet_prelude::*, traits::EstimateCallFee};
use frame_system::pallet_prelude::*;

Expand Down Expand Up @@ -592,10 +593,6 @@ pub mod pallet {
/// The priority of the unsigned transaction submitted in the unsigned-phase
#[pallet::constant]
type MinerTxPriority: Get<TransactionPriority>;
/// Maximum number of iteration of balancing that will be executed in the embedded miner of
/// the pallet.
#[pallet::constant]
type MinerMaxIterations: Get<u32>;

/// Maximum weight that the miner should consume.
///
Expand Down Expand Up @@ -668,6 +665,9 @@ pub mod pallet {
/// Configuration for the fallback
type Fallback: Get<FallbackStrategy>;

/// OCW election solution miner algorithm implementation.
type Solver: NposSolver<AccountId = Self::AccountId>;

/// Origin that can control this pallet. Note that any action taken by this origin (such)
/// as providing an emergency solution is not checked. Thus, it must be a trusted origin.
type ForceOrigin: EnsureOrigin<Self::Origin>;
Expand Down Expand Up @@ -1298,7 +1298,7 @@ impl<T: Config> Pallet<T> {
///
/// Extracted for easier weight calculation.
fn create_snapshot_external(
) -> Result<(Vec<T::AccountId>, Vec<crate::unsigned::Voter<T>>, u32), ElectionError> {
) -> Result<(Vec<T::AccountId>, Vec<crate::unsigned::Voter<T>>, u32), ElectionError<T>> {
let target_limit = <SolutionTargetIndexOf<T>>::max_value().saturated_into::<usize>();
let voter_limit = <SolutionVoterIndexOf<T>>::max_value().saturated_into::<usize>();

Expand Down Expand Up @@ -1328,7 +1328,7 @@ impl<T: Config> Pallet<T> {
///
/// This is a *self-weighing* function, it will register its own extra weight as
/// [`DispatchClass::Mandatory`] with the system pallet.
pub fn create_snapshot() -> Result<(), ElectionError> {
pub fn create_snapshot() -> Result<(), ElectionError<T>> {
// this is self-weighing itself..
let (targets, voters, desired_targets) = Self::create_snapshot_external()?;

Expand Down Expand Up @@ -1471,15 +1471,15 @@ impl<T: Config> Pallet<T> {
}

/// On-chain fallback of election.
fn onchain_fallback() -> Result<Supports<T::AccountId>, ElectionError> {
fn onchain_fallback() -> Result<Supports<T::AccountId>, ElectionError<T>> {
<onchain::OnChainSequentialPhragmen<OnChainConfig<T>> as ElectionProvider<
T::AccountId,
T::BlockNumber,
>>::elect()
.map_err(Into::into)
}

fn do_elect() -> Result<Supports<T::AccountId>, ElectionError> {
fn do_elect() -> Result<Supports<T::AccountId>, ElectionError<T>> {
// We have to unconditionally try finalizing the signed phase here. There are only two
// possibilities:
//
Expand Down Expand Up @@ -1530,7 +1530,7 @@ impl<T: Config> Pallet<T> {
}

impl<T: Config> ElectionProvider<T::AccountId, T::BlockNumber> for Pallet<T> {
type Error = ElectionError;
type Error = ElectionError<T>;
type DataProvider = T::DataProvider;

fn elect() -> Result<Supports<T::AccountId>, Self::Error> {
Expand Down Expand Up @@ -2013,7 +2013,10 @@ mod tests {
roll_to(15);
assert_eq!(MultiPhase::current_phase(), Phase::Signed);

let (solution, _) = MultiPhase::mine_solution(2).unwrap();
// 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();
// Default solution has a score of [50, 100, 5000].
assert_eq!(solution.score, [50, 100, 5000]);

Expand Down
11 changes: 7 additions & 4 deletions frame/election-provider-multi-phase/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@

use super::*;
use crate as multi_phase;
use frame_election_provider_support::{data_provider, ElectionDataProvider};
use frame_election_provider_support::{data_provider, ElectionDataProvider, SequentialPhragmen};
pub use frame_support::{assert_noop, assert_ok};
use frame_support::{parameter_types, traits::Hooks, weights::Weight};
use multi_phase::unsigned::{IndexAssignmentOf, Voter};
Expand All @@ -31,7 +31,7 @@ use sp_core::{
};
use sp_npos_elections::{
assignment_ratio_to_staked_normalized, seq_phragmen, to_supports, to_without_backing,
ElectionResult, EvaluateSupport, NposSolution,
ElectionResult, EvaluateSupport, ExtendedBalance, NposSolution,
};
use sp_runtime::{
testing::Header,
Expand Down Expand Up @@ -262,7 +262,6 @@ parameter_types! {
pub static SignedDepositWeight: Balance = 0;
pub static SignedRewardBase: Balance = 7;
pub static SignedMaxWeight: Weight = BlockWeights::get().max_block;
pub static MinerMaxIterations: u32 = 5;
pub static MinerTxPriority: u64 = 100;
pub static SolutionImprovementThreshold: Perbill = Perbill::zero();
pub static OffchainRepeat: BlockNumber = 5;
Expand Down Expand Up @@ -352,6 +351,10 @@ impl multi_phase::weights::WeightInfo for DualMockWeightInfo {
}
}

parameter_types! {
pub static Balancing: Option<(usize, ExtendedBalance)> = Some((0, 0));
}

impl crate::Config for Runtime {
type Event = Event;
type Currency = Balances;
Expand All @@ -360,7 +363,6 @@ impl crate::Config for Runtime {
type UnsignedPhase = UnsignedPhase;
type SolutionImprovementThreshold = SolutionImprovementThreshold;
type OffchainRepeat = OffchainRepeat;
type MinerMaxIterations = MinerMaxIterations;
type MinerMaxWeight = MinerMaxWeight;
type MinerMaxLength = MinerMaxLength;
type MinerTxPriority = MinerTxPriority;
Expand All @@ -379,6 +381,7 @@ impl crate::Config for Runtime {
type Fallback = Fallback;
type ForceOrigin = frame_system::EnsureRoot<AccountId>;
type Solution = TestNposSolution;
type Solver = SequentialPhragmen<AccountId, SolutionAccuracyOf<Runtime>, Balancing>;
}

impl<LocalCall> frame_system::offchain::SendTransactionTypes<LocalCall> for Runtime
Expand Down
3 changes: 2 additions & 1 deletion frame/election-provider-multi-phase/src/signed.rs
Original file line number Diff line number Diff line change
Expand Up @@ -836,7 +836,8 @@ mod tests {
roll_to(15);
assert!(MultiPhase::current_phase().is_signed());

let (raw, witness) = MultiPhase::mine_solution(2).unwrap();
let (raw, witness) =
MultiPhase::mine_solution::<<Runtime as Config>::Solver>().unwrap();
let solution_weight = <Runtime as Config>::WeightInfo::feasibility_check(
witness.voters,
witness.targets,
Expand Down
Loading