Unverified Commit d5fb3276 authored by Peter Goodspeed-Niklaus's avatar Peter Goodspeed-Niklaus Committed by GitHub
Browse files

Companion for Decouple Staking and Election - Part 3: Signed Phase (#2793)

* Companion for Decouple Staking and Election - Part 3: Signed Phase

https://github.com/paritytech/substrate/pull/7910

* remove some config types

* allow up to 5 signed submissions on polkadot and kusama

* signed phase is equal induration to unsigned phase

* use chain defaults for base and per-byte deposits; >= 16 SignedMaxSubmissions

* use a small but non-trivial solution reward

* reduce signed deposit per byte fee

* reduce signed reward, adjust polkadot expected soln size

* copy submit benchmark from substrate

* demo calculating an appropriate fee for the signed reward

Unfortunately, this doesn't work: it needs to be a constant function,
and AFAIK there's no way to make a trait method constant.

* SignedRewardBase is 1.5x the fee to submit a signed solution

* all chains use deposit byte of base per 50k

* update Substrate

* cargo update -p pallet-election-provider-multi-phase

Co-authored-by: parity-processbot <>
parent 2b855f35
Pipeline #144548 passed with stages
in 36 minutes and 53 seconds
This diff is collapsed.
......@@ -35,7 +35,7 @@ pallet-vesting = { git = "https://github.com/paritytech/substrate", branch = "ma
pallet-offences = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
pallet-transaction-payment = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
pallet-treasury = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
pallet-election-provider-multi-phase = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
pallet-beefy = { git = "https://github.com/paritytech/grandpa-bridge-gadget", branch = "master", default-features = false }
pallet-mmr = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
......@@ -91,6 +91,7 @@ std = [
"pallet-vesting/std",
"pallet-transaction-payment/std",
"pallet-treasury/std",
"pallet-election-provider-multi-phase/std",
"slot-range-helper/std",
"sp-runtime/std",
"sp-session/std",
......
// Copyright 2021 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/>.
//! Code for elections.
use frame_support::{
parameter_types,
traits::Get,
weights::{DispatchClass, Weight, WeightToFeePolynomial},
};
use sp_runtime::Perbill;
use super::{BlockExecutionWeight, BlockLength, BlockWeights};
parameter_types! {
/// A limit for off-chain phragmen unsigned solution submission.
///
/// We want to keep it as high as possible, but can't risk having it reject,
/// so we always subtract the base block execution weight.
pub OffchainSolutionWeightLimit: Weight = BlockWeights::get()
.get(DispatchClass::Normal)
.max_extrinsic
.expect("Normal extrinsics have weight limit configured by default; qed")
.saturating_sub(BlockExecutionWeight::get());
/// A limit for off-chain phragmen unsigned solution length.
///
/// We allow up to 90% of the block's size to be consumed by the solution.
pub OffchainSolutionLengthLimit: u32 = Perbill::from_rational(90_u32, 100) *
*BlockLength::get()
.max
.get(DispatchClass::Normal);
}
/// Compute the expected fee for submitting an election solution.
///
/// This is `multiplier` multiplied by the fee for the expected submission weight according to the
/// weight info.
///
/// Assumes that the signed submission queue is full.
pub fn fee_for_submit_call<T, WeightToFee, WeightInfo>(multiplier: Perbill) -> WeightToFee::Balance
where
T: pallet_election_provider_multi_phase::Config,
WeightToFee: WeightToFeePolynomial,
WeightInfo: pallet_election_provider_multi_phase::WeightInfo,
{
let expected_weight = WeightInfo::submit(T::SignedMaxSubmissions::get());
multiplier * WeightToFee::calc(&expected_weight)
}
// Copyright 2019-2020 Parity Technologies (UK) Ltd.
// Copyright 2019-2021 Parity Technologies (UK) Ltd.
// This file is part of Polkadot.
// Polkadot is free software: you can redistribute it and/or modify
......@@ -30,6 +30,7 @@ pub mod paras_registrar;
pub mod slot_range;
pub mod traits;
pub mod xcm_sender;
pub mod elections;
#[cfg(test)]
mod mock;
......@@ -54,6 +55,7 @@ pub use pallet_staking::StakerStatus;
pub use sp_runtime::BuildStorage;
pub use pallet_timestamp::Call as TimestampCall;
pub use pallet_balances::Call as BalancesCall;
pub use elections::{OffchainSolutionLengthLimit, OffchainSolutionWeightLimit};
/// Implementations of some helper traits passed into runtime modules as associated types.
pub use impls::ToAuthor;
......@@ -108,26 +110,6 @@ parameter_types! {
.build_or_panic();
}
parameter_types! {
/// A limit for off-chain phragmen unsigned solution submission.
///
/// We want to keep it as high as possible, but can't risk having it reject,
/// so we always subtract the base block execution weight.
pub OffchainSolutionWeightLimit: Weight = BlockWeights::get()
.get(DispatchClass::Normal)
.max_extrinsic
.expect("Normal extrinsics have weight limit configured by default; qed")
.saturating_sub(BlockExecutionWeight::get());
/// A limit for off-chain phragmen unsigned solution length.
///
/// We allow up to 90% of the block's size to be consumed by the solution.
pub OffchainSolutionLengthLimit: u32 = Perbill::from_rational(90_u32, 100) *
*BlockLength::get()
.max
.get(DispatchClass::Normal);
}
/// Parameterized slow adjusting fee updated based on
/// https://w3f-research.readthedocs.io/en/latest/polkadot/Token%20Economics.html#-2.-slow-adjusting-mechanism
pub type SlowAdjustingFeeUpdate<R> = TargetedFeeAdjustment<
......
......@@ -34,7 +34,8 @@ use primitives::v1::{
use runtime_common::{
claims, paras_registrar, xcm_sender, slots, auctions, crowdloan,
SlowAdjustingFeeUpdate, CurrencyToVote, impls::DealWithFees,
BlockHashCount, RocksDbWeight, BlockWeights, BlockLength, OffchainSolutionWeightLimit, OffchainSolutionLengthLimit,
BlockHashCount, RocksDbWeight, BlockWeights, BlockLength,
OffchainSolutionWeightLimit, OffchainSolutionLengthLimit, elections::fee_for_submit_call,
ToAuthor,
};
......@@ -348,11 +349,24 @@ impl pallet_session::historical::Config for Runtime {
}
parameter_types! {
// no signed phase for now, just unsigned.
pub const SignedPhase: u32 = 0;
// phase durations. 1/4 of the last session for each.
pub const SignedPhase: u32 = EPOCH_DURATION_IN_SLOTS / 4;
pub const UnsignedPhase: u32 = EPOCH_DURATION_IN_SLOTS / 4;
// fallback: run election on-chain.
// signed config
pub const SignedMaxSubmissions: u32 = 16;
pub const SignedDepositBase: Balance = deposit(1, 0);
// A typical solution occupies within an order of magnitude of 50kb.
// This formula is currently adjusted such that a typical solution will spend an amount equal
// to the base deposit for every 50 kb.
pub const SignedDepositByte: Balance = deposit(1, 0) / (50 * 1024);
pub SignedRewardBase: Balance = fee_for_submit_call::<
Runtime,
crate::constants::fee::WeightToFee,
crate::weights::pallet_election_provider_multi_phase::WeightInfo<Runtime>,
>(Perbill::from_perthousand(1500));
// fallback: emergency phase.
pub const Fallback: pallet_election_provider_multi_phase::FallbackStrategy =
pallet_election_provider_multi_phase::FallbackStrategy::Nothing;
pub SolutionImprovementThreshold: Perbill = Perbill::from_rational(5u32, 10_000);
......@@ -375,6 +389,14 @@ impl pallet_election_provider_multi_phase::Config for Runtime {
type Event = Event;
type Currency = Balances;
type UnsignedPhase = UnsignedPhase;
type SignedMaxSubmissions = SignedMaxSubmissions;
type SignedRewardBase = SignedRewardBase;
type SignedDepositBase = SignedDepositBase;
type SignedDepositByte = SignedDepositByte;
type SignedDepositWeight = ();
type SignedMaxWeight = Self::MinerMaxWeight;
type SlashHandler = (); // burn slashes
type RewardHandler = (); // nothing to do upon rewards
type SignedPhase = SignedPhase;
type SolutionImprovementThreshold = SolutionImprovementThreshold;
type MinerMaxIterations = MinerMaxIterations;
......
......@@ -67,6 +67,13 @@ impl<T: frame_system::Config> pallet_election_provider_multi_phase::WeightInfo f
.saturating_add(T::DbWeight::get().reads(2 as Weight))
.saturating_add(T::DbWeight::get().writes(6 as Weight))
}
fn submit(c: u32, ) -> Weight {
(84_430_000 as Weight)
// Standard Error: 146_000
.saturating_add((2_758_000 as Weight).saturating_mul(c as Weight))
.saturating_add(T::DbWeight::get().reads(3 as Weight))
.saturating_add(T::DbWeight::get().writes(1 as Weight))
}
fn submit_unsigned(v: u32, t: u32, a: u32, d: u32, ) -> Weight {
(0 as Weight)
// Standard Error: 13_000
......@@ -92,4 +99,14 @@ impl<T: frame_system::Config> pallet_election_provider_multi_phase::WeightInfo f
.saturating_add((4_469_000 as Weight).saturating_mul(d as Weight))
.saturating_add(T::DbWeight::get().reads(4 as Weight))
}
fn finalize_signed_phase_accept_solution() -> Weight {
(47_783_000 as Weight)
.saturating_add(T::DbWeight::get().reads(1 as Weight))
.saturating_add(T::DbWeight::get().writes(2 as Weight))
}
fn finalize_signed_phase_reject_solution() -> Weight {
(21_277_000 as Weight)
.saturating_add(T::DbWeight::get().reads(1 as Weight))
.saturating_add(T::DbWeight::get().writes(1 as Weight))
}
}
......@@ -26,6 +26,7 @@ use runtime_common::{
impls::DealWithFees,
BlockHashCount, RocksDbWeight, BlockWeights, BlockLength,
OffchainSolutionWeightLimit, OffchainSolutionLengthLimit,
elections::fee_for_submit_call,
ParachainSessionKeyPlaceholder, AssignmentSessionKeyPlaceholder,
};
......@@ -328,11 +329,24 @@ impl pallet_session::historical::Config for Runtime {
}
parameter_types! {
// no signed phase for now, just unsigned.
pub const SignedPhase: u32 = 0;
// phase durations. 1/4 of the last session for each.
pub const SignedPhase: u32 = EPOCH_DURATION_IN_SLOTS / 4;
pub const UnsignedPhase: u32 = EPOCH_DURATION_IN_SLOTS / 4;
// fallback: run election on-chain.
// signed config
pub const SignedMaxSubmissions: u32 = 16;
pub const SignedDepositBase: Balance = deposit(1, 0);
// A typical solution occupies within an order of magnitude of 50kb.
// This formula is currently adjusted such that a typical solution will spend an amount equal
// to the base deposit for every 50 kb.
pub const SignedDepositByte: Balance = deposit(1, 0) / (50 * 1024);
pub SignedRewardBase: Balance = fee_for_submit_call::<
Runtime,
crate::constants::fee::WeightToFee,
crate::weights::pallet_election_provider_multi_phase::WeightInfo<Runtime>,
>(Perbill::from_perthousand(1500));
// fallback: emergency phase.
pub const Fallback: pallet_election_provider_multi_phase::FallbackStrategy =
pallet_election_provider_multi_phase::FallbackStrategy::Nothing;
pub SolutionImprovementThreshold: Perbill = Perbill::from_rational(5u32, 10_000);
......@@ -356,6 +370,14 @@ impl pallet_election_provider_multi_phase::Config for Runtime {
type Currency = Balances;
type SignedPhase = SignedPhase;
type UnsignedPhase = UnsignedPhase;
type SignedMaxSubmissions = SignedMaxSubmissions;
type SignedRewardBase = SignedRewardBase;
type SignedDepositBase = SignedDepositBase;
type SignedDepositByte = SignedDepositByte;
type SignedDepositWeight = ();
type SignedMaxWeight = Self::MinerMaxWeight;
type SlashHandler = (); // burn slashes
type RewardHandler = (); // nothing to do upon rewards
type SolutionImprovementThreshold = SolutionImprovementThreshold;
type MinerMaxIterations = MinerMaxIterations;
type MinerMaxWeight = OffchainSolutionWeightLimit; // For now use the one from staking.
......
......@@ -92,4 +92,21 @@ impl<T: frame_system::Config> pallet_election_provider_multi_phase::WeightInfo f
.saturating_add((3_606_000 as Weight).saturating_mul(d as Weight))
.saturating_add(T::DbWeight::get().reads(4 as Weight))
}
fn finalize_signed_phase_accept_solution() -> Weight {
(47_783_000 as Weight)
.saturating_add(T::DbWeight::get().reads(1 as Weight))
.saturating_add(T::DbWeight::get().writes(2 as Weight))
}
fn finalize_signed_phase_reject_solution() -> Weight {
(21_277_000 as Weight)
.saturating_add(T::DbWeight::get().reads(1 as Weight))
.saturating_add(T::DbWeight::get().writes(1 as Weight))
}
fn submit(c: u32) -> Weight {
(78_972_000 as Weight)
// Standard Error: 16_000
.saturating_add((308_000 as Weight).saturating_mul(c as Weight))
.saturating_add(T::DbWeight::get().reads(4 as Weight))
.saturating_add(T::DbWeight::get().writes(3 as Weight))
}
}
......@@ -36,6 +36,7 @@ use runtime_common::{
impls::ToAuthor,
BlockHashCount, BlockWeights, BlockLength, RocksDbWeight,
OffchainSolutionWeightLimit, OffchainSolutionLengthLimit,
elections::fee_for_submit_call,
};
use runtime_parachains::origin as parachains_origin;
......@@ -333,11 +334,24 @@ impl pallet_session::historical::Config for Runtime {
}
parameter_types! {
// no signed phase for now, just unsigned.
pub const SignedPhase: u32 = 0;
// phase durations. 1/4 of the last session for each.
pub const SignedPhase: u32 = EPOCH_DURATION_IN_SLOTS / 4;
pub const UnsignedPhase: u32 = EPOCH_DURATION_IN_SLOTS / 4;
// fallback: run election on-chain.
// signed config
pub const SignedMaxSubmissions: u32 = 128;
pub const SignedDepositBase: Balance = deposit(1, 0);
// A typical solution occupies within an order of magnitude of 50kb.
// This formula is currently adjusted such that a typical solution will spend an amount equal
// to the base deposit for every 50 kb.
pub const SignedDepositByte: Balance = deposit(1, 0) / (50 * 1024);
pub SignedRewardBase: Balance = fee_for_submit_call::<
Runtime,
crate::constants::fee::WeightToFee,
crate::weights::pallet_election_provider_multi_phase::WeightInfo<Runtime>,
>(Perbill::from_perthousand(1500));
// fallback: emergency phase.
pub const Fallback: pallet_election_provider_multi_phase::FallbackStrategy =
pallet_election_provider_multi_phase::FallbackStrategy::Nothing;
......@@ -362,6 +376,14 @@ impl pallet_election_provider_multi_phase::Config for Runtime {
type Currency = Balances;
type SignedPhase = SignedPhase;
type UnsignedPhase = UnsignedPhase;
type SignedMaxSubmissions = SignedMaxSubmissions;
type SignedRewardBase = SignedRewardBase;
type SignedDepositBase = SignedDepositBase;
type SignedDepositByte = SignedDepositByte;
type SignedDepositWeight = ();
type SignedMaxWeight = Self::MinerMaxWeight;
type SlashHandler = (); // burn slashes
type RewardHandler = (); // nothing to do upon rewards
type SolutionImprovementThreshold = SolutionImprovementThreshold;
type MinerMaxIterations = MinerMaxIterations;
type MinerMaxWeight = OffchainSolutionWeightLimit; // For now use the one from staking.
......
......@@ -92,4 +92,21 @@ impl<T: frame_system::Config> pallet_election_provider_multi_phase::WeightInfo f
.saturating_add((3_731_000 as Weight).saturating_mul(d as Weight))
.saturating_add(T::DbWeight::get().reads(4 as Weight))
}
fn finalize_signed_phase_accept_solution() -> Weight {
(47_783_000 as Weight)
.saturating_add(T::DbWeight::get().reads(1 as Weight))
.saturating_add(T::DbWeight::get().writes(2 as Weight))
}
fn finalize_signed_phase_reject_solution() -> Weight {
(21_277_000 as Weight)
.saturating_add(T::DbWeight::get().reads(1 as Weight))
.saturating_add(T::DbWeight::get().writes(1 as Weight))
}
fn submit(c: u32) -> Weight {
(78_972_000 as Weight)
// Standard Error: 16_000
.saturating_add((308_000 as Weight).saturating_mul(c as Weight))
.saturating_add(T::DbWeight::get().reads(4 as Weight))
.saturating_add(T::DbWeight::get().writes(3 as Weight))
}
}
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment