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

Commit 3a10ee6

Browse files
s3kritcoriolinus
andcommitted
Staking Miner (#3141)
Co-authored-by: Peter Goodspeed-Niklaus <[email protected]> Co-authored-by: Peter Goodspeed-Niklaus <[email protected]>
1 parent 60ff09e commit 3a10ee6

File tree

16 files changed

+1348
-191
lines changed

16 files changed

+1348
-191
lines changed

Cargo.lock

Lines changed: 198 additions & 154 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ members = [
7979
"parachain/test-parachains",
8080
"parachain/test-parachains/adder",
8181
"parachain/test-parachains/adder/collator",
82+
"utils/staking-miner",
8283
]
8384

8485
# We want to be able to build the bridge relayer without pulling it (and all of its

node/service/src/chain_spec.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1213,7 +1213,7 @@ pub fn polkadot_testnet_genesis(
12131213
},
12141214
staking: polkadot::StakingConfig {
12151215
minimum_validator_count: 1,
1216-
validator_count: 2,
1216+
validator_count: initial_authorities.len() as u32,
12171217
stakers: initial_authorities
12181218
.iter()
12191219
.map(|x| {
@@ -1312,7 +1312,7 @@ pub fn kusama_testnet_genesis(
13121312
},
13131313
staking: kusama::StakingConfig {
13141314
minimum_validator_count: 1,
1315-
validator_count: 2,
1315+
validator_count: initial_authorities.len() as u32,
13161316
stakers: initial_authorities
13171317
.iter()
13181318
.map(|x| {
@@ -1416,7 +1416,7 @@ pub fn westend_testnet_genesis(
14161416
},
14171417
staking: westend::StakingConfig {
14181418
minimum_validator_count: 1,
1419-
validator_count: 2,
1419+
validator_count: initial_authorities.len() as u32,
14201420
stakers: initial_authorities
14211421
.iter()
14221422
.map(|x| {

runtime/common/src/elections.rs

Lines changed: 22 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,14 @@
1818
1919
use frame_support::{
2020
parameter_types,
21-
traits::Get,
22-
weights::{DispatchClass, Weight, WeightToFeePolynomial},
21+
weights::{DispatchClass, Weight},
2322
};
24-
use sp_runtime::Perbill;
23+
use sp_runtime::{
24+
traits::{Zero, Dispatchable},
25+
FixedU128, FixedPointNumber, Perbill,
26+
};
27+
use pallet_transaction_payment::OnChargeTransaction;
28+
use frame_support::weights::{DispatchInfo, Pays};
2529
use super::{BlockExecutionWeight, BlockLength, BlockWeights};
2630

2731
parameter_types! {
@@ -44,18 +48,21 @@ parameter_types! {
4448
.get(DispatchClass::Normal);
4549
}
4650

47-
/// Compute the expected fee for submitting an election solution.
48-
///
49-
/// This is `multiplier` multiplied by the fee for the expected submission weight according to the
50-
/// weight info.
51-
///
52-
/// Assumes that the signed submission queue is full.
53-
pub fn fee_for_submit_call<T, WeightToFee, WeightInfo>(multiplier: Perbill) -> WeightToFee::Balance
51+
pub fn fee_for_submit_call<T>(
52+
multiplier: FixedU128,
53+
weight: Weight,
54+
length: u32,
55+
) -> primitives::v1::Balance
5456
where
55-
T: pallet_election_provider_multi_phase::Config,
56-
WeightToFee: WeightToFeePolynomial,
57-
WeightInfo: pallet_election_provider_multi_phase::WeightInfo,
57+
T: pallet_transaction_payment::Config,
58+
<T as pallet_transaction_payment::Config>::OnChargeTransaction:
59+
OnChargeTransaction<T, Balance = primitives::v1::Balance>,
60+
<T as frame_system::Config>::Call: Dispatchable<Info = DispatchInfo>,
5861
{
59-
let expected_weight = WeightInfo::submit(T::SignedMaxSubmissions::get());
60-
multiplier * WeightToFee::calc(&expected_weight)
62+
let info = DispatchInfo { weight, class: DispatchClass::Normal, pays_fee: Pays::Yes };
63+
multiplier.saturating_mul_int(pallet_transaction_payment::Pallet::<T>::compute_fee(
64+
length,
65+
&info,
66+
Zero::zero(),
67+
))
6168
}

runtime/kusama/src/lib.rs

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -65,8 +65,8 @@ use xcm_builder::{
6565
use xcm_executor::XcmExecutor;
6666
use sp_arithmetic::Perquintill;
6767
use sp_runtime::{
68-
create_runtime_str, generic, impl_opaque_keys,
69-
ApplyExtrinsicResult, KeyTypeId, Percent, Permill, Perbill,
68+
create_runtime_str, generic, impl_opaque_keys, ApplyExtrinsicResult, KeyTypeId, Percent,
69+
Permill, Perbill, FixedPointNumber,
7070
transaction_validity::{TransactionValidity, TransactionSource, TransactionPriority},
7171
traits::{
7272
BlakeTwo256, Block as BlockT, OpaqueKeys, ConvertInto, AccountIdLookup,
@@ -101,6 +101,7 @@ pub use pallet_staking::StakerStatus;
101101
pub use sp_runtime::BuildStorage;
102102
pub use pallet_timestamp::Call as TimestampCall;
103103
pub use pallet_balances::Call as BalancesCall;
104+
pub use pallet_election_provider_multi_phase::Call as EPMCall;
104105

105106
/// Constant values used within the runtime.
106107
pub mod constants;
@@ -348,6 +349,7 @@ impl pallet_session::historical::Config for Runtime {
348349
type FullIdentificationOf = pallet_staking::ExposureOf<Runtime>;
349350
}
350351

352+
use pallet_election_provider_multi_phase::WeightInfo;
351353
parameter_types! {
352354
// phase durations. 1/4 of the last session for each.
353355
pub const SignedPhase: u32 = EPOCH_DURATION_IN_SLOTS / 4;
@@ -360,11 +362,14 @@ parameter_types! {
360362
// This formula is currently adjusted such that a typical solution will spend an amount equal
361363
// to the base deposit for every 50 kb.
362364
pub const SignedDepositByte: Balance = deposit(1, 0) / (50 * 1024);
363-
pub SignedRewardBase: Balance = fee_for_submit_call::<
364-
Runtime,
365-
crate::constants::fee::WeightToFee,
366-
crate::weights::pallet_election_provider_multi_phase::WeightInfo<Runtime>,
367-
>(Perbill::from_perthousand(1500));
365+
pub SignedRewardBase: Balance = fee_for_submit_call::<Runtime>(
366+
// give 20% threshold.
367+
sp_runtime::FixedU128::saturating_from_rational(12, 10),
368+
// maximum weight possible.
369+
weights::pallet_election_provider_multi_phase::WeightInfo::<Runtime>::submit(SignedMaxSubmissions::get()),
370+
// assume a solution of 100kb length.
371+
100 * 1024
372+
);
368373

369374
// fallback: emergency phase.
370375
pub const Fallback: pallet_election_provider_multi_phase::FallbackStrategy =

runtime/polkadot/src/lib.rs

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ use primitives::v1::{
4141
ValidatorIndex, InboundDownwardMessage, InboundHrmpMessage, SessionInfo,
4242
};
4343
use sp_runtime::{
44-
create_runtime_str, generic, impl_opaque_keys, ApplyExtrinsicResult,
44+
create_runtime_str, generic, impl_opaque_keys, ApplyExtrinsicResult, FixedPointNumber,
4545
KeyTypeId, Percent, Permill, Perbill, curve::PiecewiseLinear,
4646
transaction_validity::{TransactionValidity, TransactionSource, TransactionPriority},
4747
traits::{
@@ -77,6 +77,7 @@ pub use pallet_staking::StakerStatus;
7777
pub use sp_runtime::BuildStorage;
7878
pub use pallet_timestamp::Call as TimestampCall;
7979
pub use pallet_balances::Call as BalancesCall;
80+
pub use pallet_election_provider_multi_phase::Call as EPMCall;
8081

8182
/// Constant values used within the runtime.
8283
pub mod constants;
@@ -328,6 +329,7 @@ impl pallet_session::historical::Config for Runtime {
328329
type FullIdentificationOf = pallet_staking::ExposureOf<Runtime>;
329330
}
330331

332+
use pallet_election_provider_multi_phase::WeightInfo;
331333
parameter_types! {
332334
// phase durations. 1/4 of the last session for each.
333335
pub const SignedPhase: u32 = EPOCH_DURATION_IN_SLOTS / 4;
@@ -340,11 +342,14 @@ parameter_types! {
340342
// This formula is currently adjusted such that a typical solution will spend an amount equal
341343
// to the base deposit for every 50 kb.
342344
pub const SignedDepositByte: Balance = deposit(1, 0) / (50 * 1024);
343-
pub SignedRewardBase: Balance = fee_for_submit_call::<
344-
Runtime,
345-
crate::constants::fee::WeightToFee,
346-
crate::weights::pallet_election_provider_multi_phase::WeightInfo<Runtime>,
347-
>(Perbill::from_perthousand(1500));
345+
pub SignedRewardBase: Balance = fee_for_submit_call::<Runtime>(
346+
// give 20% threshold.
347+
sp_runtime::FixedU128::saturating_from_rational(12, 10),
348+
// maximum weight possible.
349+
weights::pallet_election_provider_multi_phase::WeightInfo::<Runtime>::submit(SignedMaxSubmissions::get()),
350+
// assume a solution of 200kb length.
351+
200 * 1024
352+
);
348353

349354
// fallback: emergency phase.
350355
pub const Fallback: pallet_election_provider_multi_phase::FallbackStrategy =

runtime/westend/src/lib.rs

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ use xcm_builder::{
6565
};
6666

6767
use sp_runtime::{
68-
create_runtime_str, generic, impl_opaque_keys,
68+
create_runtime_str, generic, impl_opaque_keys, FixedPointNumber,
6969
ApplyExtrinsicResult, KeyTypeId, Perbill, curve::PiecewiseLinear,
7070
transaction_validity::{TransactionValidity, TransactionSource, TransactionPriority},
7171
traits::{
@@ -100,6 +100,7 @@ pub use pallet_staking::StakerStatus;
100100
pub use sp_runtime::BuildStorage;
101101
pub use pallet_timestamp::Call as TimestampCall;
102102
pub use pallet_balances::Call as BalancesCall;
103+
pub use pallet_election_provider_multi_phase::Call as EPMCall;
103104

104105
/// Constant values used within the runtime.
105106
pub mod constants;
@@ -333,6 +334,7 @@ impl pallet_session::historical::Config for Runtime {
333334
type FullIdentificationOf = pallet_staking::ExposureOf<Runtime>;
334335
}
335336

337+
use pallet_election_provider_multi_phase::WeightInfo;
336338
parameter_types! {
337339
// phase durations. 1/4 of the last session for each.
338340
pub const SignedPhase: u32 = EPOCH_DURATION_IN_SLOTS / 4;
@@ -345,11 +347,14 @@ parameter_types! {
345347
// This formula is currently adjusted such that a typical solution will spend an amount equal
346348
// to the base deposit for every 50 kb.
347349
pub const SignedDepositByte: Balance = deposit(1, 0) / (50 * 1024);
348-
pub SignedRewardBase: Balance = fee_for_submit_call::<
349-
Runtime,
350-
crate::constants::fee::WeightToFee,
351-
crate::weights::pallet_election_provider_multi_phase::WeightInfo<Runtime>,
352-
>(Perbill::from_perthousand(1500));
350+
pub SignedRewardBase: Balance = fee_for_submit_call::<Runtime>(
351+
// give 20% threshold.
352+
sp_runtime::FixedU128::saturating_from_rational(12, 10),
353+
// maximum weight possible.
354+
weights::pallet_election_provider_multi_phase::WeightInfo::<Runtime>::submit(SignedMaxSubmissions::get()),
355+
// assume a solution of 100kb length.
356+
100 * 1024
357+
);
353358

354359
// fallback: emergency phase.
355360
pub const Fallback: pallet_election_provider_multi_phase::FallbackStrategy =

utils/staking-miner/.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
*.key
2+
*.bin

utils/staking-miner/Cargo.toml

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
[package]
2+
name = "staking-miner"
3+
version = "0.9.0"
4+
authors = ["Parity Technologies <[email protected]>"]
5+
edition = "2018"
6+
7+
[dependencies]
8+
codec = { package = "parity-scale-codec", version = "2.0.0" }
9+
tokio = { version = "0.2", features = ["macros"] }
10+
log = "0.4.11"
11+
env_logger = "0.8.3"
12+
structopt = "0.3.0"
13+
jsonrpsee-ws-client = { version = "0.2.0", default-features = false, features = ["tokio02"] }
14+
jsonrpsee-types = { version = "0.2.0" }
15+
jsonrpsee = "=0.2.0-alpha.6"
16+
serde_json = "1.0"
17+
serde = "1.0.0"
18+
hex = "0.4.0"
19+
lazy_static = "1.4.0"
20+
paste = "1.0.5"
21+
thiserror = "1.0.0"
22+
23+
remote-externalities = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.8" }
24+
25+
sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.8" }
26+
sp-io = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.8" }
27+
sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.8" }
28+
sp-npos-elections = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.8" }
29+
sp-transaction-pool = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.8" }
30+
31+
32+
frame-system = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.8" }
33+
frame-support = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.8" }
34+
frame-election-provider-support = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.8" }
35+
pallet-election-provider-multi-phase = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.8" }
36+
pallet-staking = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.8" }
37+
pallet-transaction-payment = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.8" }
38+
39+
core-primitives = { package = "polkadot-core-primitives", path = "../../core-primitives" }
40+
41+
runtime-common = { package = "polkadot-runtime-common", path = "../../runtime/common" }
42+
polkadot-runtime = { path = "../../runtime/polkadot" }
43+
kusama-runtime = { path = "../../runtime/kusama" }
44+
westend-runtime = { path = "../../runtime/westend" }
45+
46+
[dev-dependencies]
47+
sp-version = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.8" }

utils/staking-miner/src/dry_run.rs

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
// Copyright 2021 Parity Technologies (UK) Ltd.
2+
// This file is part of Polkadot.
3+
4+
// Polkadot is free software: you can redistribute it and/or modify
5+
// it under the terms of the GNU General Public License as published by
6+
// the Free Software Foundation, either version 3 of the License, or
7+
// (at your option) any later version.
8+
9+
// Polkadot is distributed in the hope that it will be useful,
10+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
// GNU General Public License for more details.
13+
14+
// You should have received a copy of the GNU General Public License
15+
// along with Polkadot. If not, see <http://www.gnu.org/licenses/>.
16+
17+
//! The dry-run command.
18+
19+
use crate::{
20+
params, prelude::*, rpc_helpers::*, signer::Signer, DryRunConfig, Error, SharedConfig, WsClient,
21+
};
22+
use codec::Encode;
23+
24+
/// Forcefully create the snapshot. This can be used to compute the election at anytime.
25+
fn force_create_snapshot<T: EPM::Config>(ext: &mut Ext) -> Result<(), Error> {
26+
ext.execute_with(|| {
27+
if <EPM::Snapshot<T>>::exists() {
28+
log::info!(target: LOG_TARGET, "snapshot already exists.");
29+
Ok(())
30+
} else {
31+
log::info!(target: LOG_TARGET, "creating a fake snapshot now.");
32+
<EPM::Pallet<T>>::create_snapshot().map(|_| ()).map_err(Into::into)
33+
}
34+
})
35+
}
36+
37+
/// Helper method to print the encoded size of the snapshot.
38+
fn measure_snapshot_size<T: EPM::Config>(ext: &mut Ext) {
39+
ext.execute_with(|| {
40+
log::info!(target: LOG_TARGET, "Metadata: {:?}", <EPM::Pallet<T>>::snapshot_metadata());
41+
log::info!(
42+
target: LOG_TARGET,
43+
"Encoded Length: {:?}",
44+
<EPM::Pallet<T>>::snapshot()
45+
.expect("snapshot must exist before calling `measure_snapshot_size`")
46+
.encode()
47+
.len()
48+
);
49+
})
50+
}
51+
52+
/// Find the stake threshold in order to have at most `count` voters.
53+
#[allow(unused)]
54+
fn find_threshold<T: EPM::Config>(ext: &mut Ext, count: usize) {
55+
ext.execute_with(|| {
56+
let mut voters = <EPM::Pallet<T>>::snapshot()
57+
.expect("snapshot must exist before calling `measure_snapshot_size`")
58+
.voters;
59+
voters.sort_by_key(|(_voter, weight, _targets)| std::cmp::Reverse(*weight));
60+
match voters.get(count) {
61+
Some(threshold_voter) => println!("smallest allowed voter is {:?}", threshold_voter),
62+
None => {
63+
println!("requested truncation to {} voters but had only {}", count, voters.len());
64+
println!("smallest current voter: {:?}", voters.last());
65+
}
66+
}
67+
})
68+
}
69+
70+
macro_rules! dry_run_cmd_for { ($runtime:ident) => { paste::paste! {
71+
/// Execute the dry-run command.
72+
pub(crate) async fn [<dry_run_cmd_ $runtime>](
73+
client: &WsClient,
74+
shared: SharedConfig,
75+
config: DryRunConfig,
76+
signer: Signer,
77+
) -> Result<(), Error> {
78+
use $crate::[<$runtime _runtime_exports>]::*;
79+
let mut ext = crate::create_election_ext::<Runtime, Block>(shared.uri.clone(), config.at, true).await?;
80+
force_create_snapshot::<Runtime>(&mut ext)?;
81+
measure_snapshot_size::<Runtime>(&mut ext);
82+
let (raw_solution, witness) = crate::mine_unchecked::<Runtime>(&mut ext, config.iterations, false)?;
83+
log::info!(target: LOG_TARGET, "mined solution with {:?}", &raw_solution.score);
84+
85+
let nonce = crate::get_account_info::<Runtime>(client, &signer.account, config.at)
86+
.await?
87+
.map(|i| i.nonce)
88+
.expect("signer account is checked to exist upon startup; it can only die if it \
89+
transfers funds out of it, or get slashed. If it does not exist at this point, \
90+
it is likely due to a bug, or the signer got slashed. Terminating."
91+
);
92+
let tip = 0 as Balance;
93+
let era = sp_runtime::generic::Era::Immortal;
94+
let extrinsic = ext.execute_with(|| create_uxt(raw_solution, witness, signer.clone(), nonce, tip, era));
95+
96+
let bytes = sp_core::Bytes(extrinsic.encode().to_vec());
97+
let outcome = rpc_decode::<sp_runtime::ApplyExtrinsicResult>(client, "system_dryRun", params!{ bytes }).await?;
98+
log::info!(target: LOG_TARGET, "dry-run outcome is {:?}", outcome);
99+
Ok(())
100+
}
101+
}}}
102+
103+
dry_run_cmd_for!(polkadot);
104+
dry_run_cmd_for!(kusama);
105+
dry_run_cmd_for!(westend);

0 commit comments

Comments
 (0)