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

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

Merged
merged 20 commits into from
Jun 28, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
36502dc
Companion for Decouple Staking and Election - Part 3: Signed Phase
coriolinus Apr 1, 2021
1e509e9
Merge remote-tracking branch 'origin/master' into prgn-companion-for-…
coriolinus May 26, 2021
9638fcf
Merge remote-tracking branch 'origin/master' into prgn-companion-for-…
coriolinus May 27, 2021
0fc8c64
remove some config types
coriolinus May 31, 2021
a7ded3d
Merge remote-tracking branch 'origin/master' into prgn-companion-for-…
coriolinus Jun 18, 2021
5a972b2
Merge remote-tracking branch 'origin/master' into prgn-companion-for-…
coriolinus Jun 23, 2021
3c51221
allow up to 5 signed submissions on polkadot and kusama
coriolinus Jun 23, 2021
9538b7e
signed phase is equal induration to unsigned phase
coriolinus Jun 23, 2021
3da0659
use chain defaults for base and per-byte deposits; >= 16 SignedMaxSub…
coriolinus Jun 23, 2021
0f380ae
use a small but non-trivial solution reward
coriolinus Jun 23, 2021
fd9e8c6
reduce signed deposit per byte fee
coriolinus Jun 23, 2021
a0372e3
reduce signed reward, adjust polkadot expected soln size
coriolinus Jun 23, 2021
e1f3a06
copy submit benchmark from substrate
coriolinus Jun 23, 2021
b19f7e1
demo calculating an appropriate fee for the signed reward
coriolinus Jun 23, 2021
ff228bc
SignedRewardBase is 1.5x the fee to submit a signed solution
coriolinus Jun 24, 2021
f97eca3
Merge remote-tracking branch 'origin/master' into prgn-companion-for-…
coriolinus Jun 24, 2021
f5b6dd5
all chains use deposit byte of base per 50k
coriolinus Jun 25, 2021
99a16f3
Merge remote-tracking branch 'origin/master' into prgn-companion-for-…
Jun 28, 2021
7084efc
update Substrate
Jun 28, 2021
8cf97b6
cargo update -p pallet-election-provider-multi-phase
coriolinus Jun 28, 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
311 changes: 156 additions & 155 deletions Cargo.lock

Large diffs are not rendered by default.

3 changes: 2 additions & 1 deletion runtime/common/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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 }

Expand Down Expand Up @@ -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",
Expand Down
61 changes: 61 additions & 0 deletions runtime/common/src/elections.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
// 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)
Copy link
Contributor

@kianenigma kianenigma Jun 24, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this might lead to negative turnout to run the bot, since your discounting the length fee (which in this case is probably more dominant than the weight fee)(I also forgot about length fee earlier).

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe what you should do is run your polkadot branch and submit a solution to it via the miner, to both obtain this and do an end-to-end test

might still help, but not a blocker since this is too conservattive and thus safe.

}
24 changes: 3 additions & 21 deletions runtime/common/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// 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
Expand Down Expand Up @@ -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;
Expand All @@ -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;
Expand Down Expand Up @@ -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<
Expand Down
30 changes: 26 additions & 4 deletions runtime/kusama/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
};

Expand Down Expand Up @@ -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);
Expand All @@ -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
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same, could use more thought. My initial values here are all placeholders.

type RewardHandler = (); // nothing to do upon rewards
type SignedPhase = SignedPhase;
type SolutionImprovementThreshold = SolutionImprovementThreshold;
type MinerMaxIterations = MinerMaxIterations;
Expand Down
17 changes: 17 additions & 0 deletions runtime/kusama/src/weights/pallet_election_provider_multi_phase.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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))
}
}
28 changes: 25 additions & 3 deletions runtime/polkadot/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ use runtime_common::{
impls::DealWithFees,
BlockHashCount, RocksDbWeight, BlockWeights, BlockLength,
OffchainSolutionWeightLimit, OffchainSolutionLengthLimit,
elections::fee_for_submit_call,
ParachainSessionKeyPlaceholder, AssignmentSessionKeyPlaceholder,
};

Expand Down Expand Up @@ -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);
Expand All @@ -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.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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))
}
}
28 changes: 25 additions & 3 deletions runtime/westend/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;

Expand All @@ -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.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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))
}
}