Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor(mainnet): use genesis presets for mainnet runtime. #473

Merged
Show file tree
Hide file tree
Changes from 15 commits
Commits
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
11 changes: 1 addition & 10 deletions networks/mainnet.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ validator = true

[[parachains]]
id = 4001
chain = "mainnet"
chain = "pop-dev" # mainnet runtime with development config.
default_command = "./target/release/pop-node"

[parachains.genesis_overrides.balances]
Expand All @@ -34,15 +34,6 @@ balances = [
["5CiPPseXPECbkjWCa6MnjNokrgYjMqmKndv2rSnekmSK2DjL", 10000000000000000],
]

[parachains.genesis_overrides.council]
members = [
# Dev accounts
"5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY",
"5FHneW46xGXgs5mUiveU4sbTyGBzmstUspZC92UhjJM694ty",
"5FLSigC9HGRKVhB9FiEo4Y3koPsNmBmLJbpXg2mp1hXcS59Y",
"5DAAnrj7VHTznn2AWBemMuyBwZWs6FNFjdyVXUeYum3PTXFy",
]

[[parachains.collators]]
name = "pop"
rpc_port = 9944
Expand Down
284 changes: 121 additions & 163 deletions node/src/chain_spec.rs
Original file line number Diff line number Diff line change
@@ -1,26 +1,10 @@
use cumulus_primitives_core::ParaId;
use pop_runtime_common::{AccountId, AuraId};
use pop_runtime_mainnet::config::governance::SudoAddress;
use sc_chain_spec::{ChainSpecExtension, ChainSpecGroup};
use sc_service::{ChainType, GenericChainSpec};
use serde::{Deserialize, Serialize};
use sp_core::crypto::Ss58Codec;

/// Generic `ChainSpec` for a parachain runtime.
pub type ChainSpec = GenericChainSpec<Extensions>;

/// Specialized `ChainSpec` for the mainnet parachain runtime.
pub type MainnetChainSpec = sc_service::GenericChainSpec<Extensions>;

/// The default XCM version to set in genesis config.
const SAFE_XCM_VERSION: u32 = xcm::prelude::XCM_VERSION;

pub(crate) enum Relay {
Paseo,
PaseoLocal,
Polkadot,
}

/// Chainspec builder trait: to be implemented for the different runtimes (i.e. `devnet`, `testnet`
/// & `mainnet`) to ease building.
trait ChainSpecBuilder {
Expand Down Expand Up @@ -173,163 +157,137 @@ pub mod testnet {
}
}

/// Generate the session keys from individual elements.
///
/// The input must be a tuple of individual keys (a single arg for now since we have just one key).
pub fn pop_mainnet_session_keys(keys: AuraId) -> pop_runtime_mainnet::SessionKeys {
pop_runtime_mainnet::SessionKeys { aura: keys }
}
pub mod mainnet {
use pop_runtime_mainnet as runtime;
use pop_runtime_mainnet::Runtime;
pub use runtime::genesis::{MAINNET, MAINNET_DEV, MAINNET_LOCAL};

fn configure_for_relay(
relay: Relay,
properties: &mut sc_chain_spec::Properties,
) -> (Extensions, u32) {
let para_id;
use super::*;

match relay {
Relay::Paseo | Relay::PaseoLocal => {
para_id = 4001;
properties.insert("tokenSymbol".into(), "PAS".into());
properties.insert("tokenDecimals".into(), 10.into());
impl ChainSpecBuilder for Runtime {
fn para_id() -> u32 {
runtime::genesis::PARA_ID.into()
}

let relay_chain = if let Relay::Paseo = relay {
properties.insert("ss58Format".into(), 0.into());
"paseo".into()
} else {
properties.insert("ss58Format".into(), 42.into());
"paseo-local".into()
};
(Extensions { relay_chain, para_id }, para_id)
},
Relay::Polkadot => {
para_id = 3395;
properties.insert("ss58Format".into(), 0.into());
fn properties() -> sc_chain_spec::Properties {
let mut properties = sc_chain_spec::Properties::new();
properties.insert("tokenSymbol".into(), "DOT".into());
properties.insert("tokenDecimals".into(), 10.into());
(Extensions { relay_chain: "polkadot".into(), para_id }, para_id)
},
properties.insert("ss58Format".into(), 0.into());
properties
}

fn wasm_binary() -> &'static [u8] {
runtime::WASM_BINARY.expect("WASM binary was not built, please build it!")
}
}
}

pub fn mainnet_chain_spec(relay: Relay) -> MainnetChainSpec {
let mut properties = sc_chain_spec::Properties::new();
let (extensions, para_id) = configure_for_relay(relay, &mut properties);

let collator_0_account_id: AccountId =
AccountId::from_ss58check("15B6eUkXgoLA3dWruCRYWeBGNC8SCwuqiMtMTM1Zh2auSg3w").unwrap();
let collator_0_aura_id: AuraId =
AuraId::from_ss58check("15B6eUkXgoLA3dWruCRYWeBGNC8SCwuqiMtMTM1Zh2auSg3w").unwrap();

// Multisig account for sudo, generated from the following signatories:
// - 15VPagCVayS6XvT5RogPYop3BJTJzwqR2mCGR1kVn3w58ygg
// - 142zako1kfvrpQ7pJKYR8iGUD58i4wjb78FUsmJ9WcXmkM5z
// - 15k9niqckMg338cFBoz9vWFGwnCtwPBquKvqJEfHApijZkDz
// - 14G3CUFnZUBnHZUhahexSZ6AgemaW9zMHBnGccy3df7actf4
// - Threshold 2
let sudo_account_id: AccountId = SudoAddress::get();

#[allow(deprecated)]
MainnetChainSpec::builder(
pop_runtime_mainnet::WASM_BINARY.expect("WASM binary was not built, please build it!"),
extensions,
)
.with_name("Pop Network")
.with_id("pop")
.with_chain_type(ChainType::Live)
.with_genesis_config_patch(mainnet_genesis(
// initial collators.
vec![
// POP COLLATOR 0
(collator_0_account_id, collator_0_aura_id),
],
sudo_account_id,
para_id.into(),
// councillors
vec![],
))
.with_protocol_id("pop")
.with_properties(properties)
.build()
}
/// Configures a development chain running on a single node, using the mainnet runtime.
pub fn development_chain_spec() -> ChainSpec {
const ID: &str = MAINNET_DEV;
Runtime::build(ID, "Pop (Development)", ChainType::Development, ID, ID, "paseo-local")
}

fn mainnet_genesis(
invulnerables: Vec<(AccountId, AuraId)>,
root: AccountId,
id: ParaId,
councillors: Vec<AccountId>,
) -> serde_json::Value {
use pop_runtime_mainnet::EXISTENTIAL_DEPOSIT;

serde_json::json!({
"balances": {
"balances": [],
},
"parachainInfo": {
"parachainId": id,
},
"collatorSelection": {
"invulnerables": invulnerables.iter().cloned().map(|(acc, _)| acc).collect::<Vec<_>>(),
"candidacyBond": EXISTENTIAL_DEPOSIT * 16,
"desiredCandidates": 0,
},
"session": {
"keys": invulnerables
.into_iter()
.map(|(acc, aura)| {
(
acc.clone(), // account id
acc, // validator id
pop_mainnet_session_keys(aura), // session keys
)
/// Configures a local chain running on multiple nodes for testing purposes, using the mainnet
/// runtime.
pub fn local_chain_spec() -> ChainSpec {
const ID: &str = MAINNET_LOCAL;
Runtime::build(ID, "Pop (Local)", ChainType::Local, ID, ID, "paseo-local")
}

/// Configures a live chain running on multiple nodes publicly, using the mainnet
/// runtime.
pub fn live_chain_spec() -> ChainSpec {
const ID: &str = MAINNET;
Runtime::build(ID, "Pop", ChainType::Live, ID, ID, "polkadot")
}

#[cfg(test)]
mod tests {
use sc_chain_spec::ChainSpec;
use serde_json::json;

use super::*;

#[test]
fn dev_configuration_is_correct() {
let chain_spec = development_chain_spec();
assert!(chain_spec.boot_nodes().is_empty());
assert_eq!(chain_spec.name(), "Pop (Development)");
assert_eq!(chain_spec.id(), "pop-dev");
assert_eq!(chain_spec.chain_type(), ChainType::Development);
assert!(chain_spec.telemetry_endpoints().is_none());
assert_eq!(chain_spec.protocol_id().unwrap(), "pop-dev");
assert!(chain_spec.fork_id().is_none());
assert_eq!(
&chain_spec.properties(),
json!({
"ss58Format": 0, // Paseo uses Polkadot's SS58.
"tokenDecimals": 10,
"tokenSymbol": "DOT",
})
.collect::<Vec<_>>(),
},
"polkadotXcm": {
"safeXcmVersion": Some(SAFE_XCM_VERSION),
},
"sudo": { "key": Some(root) },
"council": {
"members": councillors,
.as_object()
.unwrap()
);
assert_eq!(
chain_spec.extensions(),
&Extensions { relay_chain: "paseo-local".to_string(), para_id: 3395 }
);
assert!(chain_spec.code_substitutes().is_empty());
}
})
}

#[test]
fn sudo_key_valid() {
// Source: https://github.com/paritytech/extended-parachain-template/blob/d08cec37117731953119ecaed79522a0812b46f5/node/src/chain_spec.rs#L79
fn get_multisig_sudo_key(mut authority_set: Vec<AccountId>, threshold: u16) -> AccountId {
assert!(threshold > 0, "Threshold for sudo multisig cannot be 0");
assert!(!authority_set.is_empty(), "Sudo authority set cannot be empty");
assert!(
authority_set.len() >= threshold.into(),
"Threshold must be less than or equal to authority set members"
);
// Sorting is done to deterministically order the multisig set
// So that a single authority set (A, B, C) may generate only a single unique multisig key
// Otherwise, (B, A, C) or (C, A, B) could produce different keys and cause chaos
authority_set.sort();

// Define a multisig threshold for `threshold / authority_set.len()` members
pallet_multisig::Pallet::<pop_runtime_mainnet::Runtime>::multi_account_id(
&authority_set[..],
threshold,
)
}
#[test]
fn local_configuration_is_correct() {
let chain_spec = local_chain_spec();
assert!(chain_spec.boot_nodes().is_empty());
assert_eq!(chain_spec.name(), "Pop (Local)");
assert_eq!(chain_spec.id(), "pop-local");
assert_eq!(chain_spec.chain_type(), ChainType::Local);
assert!(chain_spec.telemetry_endpoints().is_none());
assert_eq!(chain_spec.protocol_id().unwrap(), "pop-local");
assert!(chain_spec.fork_id().is_none());
assert_eq!(
&chain_spec.properties(),
json!({
"ss58Format": 0, // Paseo uses Polkadot's SS58.
"tokenDecimals": 10,
"tokenSymbol": "DOT",
})
.as_object()
.unwrap()
);
assert_eq!(
chain_spec.extensions(),
&Extensions { relay_chain: "paseo-local".to_string(), para_id: 3395 }
);
assert!(chain_spec.code_substitutes().is_empty());
}

assert_eq!(
get_multisig_sudo_key(
vec![
AccountId::from_ss58check("15VPagCVayS6XvT5RogPYop3BJTJzwqR2mCGR1kVn3w58ygg")
.unwrap(),
AccountId::from_ss58check("142zako1kfvrpQ7pJKYR8iGUD58i4wjb78FUsmJ9WcXmkM5z")
.unwrap(),
AccountId::from_ss58check("15k9niqckMg338cFBoz9vWFGwnCtwPBquKvqJEfHApijZkDz")
.unwrap(),
AccountId::from_ss58check("14G3CUFnZUBnHZUhahexSZ6AgemaW9zMHBnGccy3df7actf4")
.unwrap(),
],
2
),
SudoAddress::get()
)
#[test]
fn live_configuration_is_correct() {
let chain_spec = live_chain_spec();
assert!(chain_spec.boot_nodes().is_empty());
assert_eq!(chain_spec.name(), "Pop");
assert_eq!(chain_spec.id(), "pop");
assert_eq!(chain_spec.chain_type(), ChainType::Live);
assert!(chain_spec.telemetry_endpoints().is_none());
assert_eq!(chain_spec.protocol_id().unwrap(), "pop");
assert!(chain_spec.fork_id().is_none());
assert_eq!(
&chain_spec.properties(),
json!({
"ss58Format": 0, // Polkadot's SS58.
"tokenDecimals": 10,
"tokenSymbol": "DOT",
})
.as_object()
.unwrap()
);
assert_eq!(
chain_spec.extensions(),
&Extensions { relay_chain: "polkadot".to_string(), para_id: 3395 }
);
assert!(chain_spec.code_substitutes().is_empty());
}
}
}
9 changes: 5 additions & 4 deletions node/src/command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ use sc_service::config::{BasePath, PrometheusConfig};
use sp_runtime::traits::HashingFor;

use crate::{
chain_spec::{self, devnet::*, testnet::*, Relay},
chain_spec::{self, devnet::*, mainnet::*, testnet::*},
cli::{Cli, RelayChainCli, Subcommand},
service::new_partial,
};
Expand All @@ -37,7 +37,7 @@ fn runtime(id: &str) -> Runtime {
Runtime::Devnet
} else if [TESTNET_DEV, TESTNET_LOCAL, TESTNET].contains(&id) {
Runtime::Testnet
} else if id.eq("pop") || id.ends_with("mainnet") {
} else if [MAINNET_DEV, MAINNET_LOCAL, MAINNET].contains(&id) {
Runtime::Mainnet
} else {
log::warn!(
Expand Down Expand Up @@ -82,8 +82,9 @@ fn load_spec(id: &str) -> std::result::Result<Box<dyn ChainSpec>, String> {
TESTNET_LOCAL => Box::new(chain_spec::testnet::local_chain_spec()),
TESTNET => Box::new(chain_spec::testnet::live_chain_spec()),
// Mainnet.
"pop" | "mainnet" | "pop-polkadot" | "pop-network" =>
Box::new(chain_spec::mainnet_chain_spec(Relay::Polkadot)),
MAINNET_DEV => Box::new(chain_spec::mainnet::development_chain_spec()),
MAINNET_LOCAL => Box::new(chain_spec::mainnet::local_chain_spec()),
MAINNET => Box::new(chain_spec::mainnet::live_chain_spec()),
// Path.
path => Box::new(chain_spec::ChainSpec::from_json_file(path.into())?),
})
Expand Down
4 changes: 2 additions & 2 deletions runtime/mainnet/src/apis.rs
Original file line number Diff line number Diff line change
Expand Up @@ -283,7 +283,7 @@

use frame_system_benchmarking::Pallet as SystemBench;

impl frame_system_benchmarking::Config for Runtime {

Check warning on line 286 in runtime/mainnet/src/apis.rs

View workflow job for this annotation

GitHub Actions / clippy

non-local `impl` definition, `impl` blocks should be written at the same level as their item

warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item --> runtime/mainnet/src/apis.rs:286:4 | 278 | / fn dispatch_benchmark( 279 | | config: frame_benchmarking::BenchmarkConfig 280 | | ) -> Result<Vec<frame_benchmarking::BenchmarkBatch>, alloc::string::String> { | |___________________________________________________________________________________- move the `impl` block outside of this associated function `dispatch_benchmark` ... 286 | impl frame_system_benchmarking::Config for Runtime { | ^^^^^---------------------------------^^^^^------- | | | | | `Runtime` is not local | `Config` is not local | = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` = note: `#[warn(non_local_definitions)]` on by default
fn setup_set_code_requirements(code: &Vec<u8>) -> Result<(), BenchmarkError> {
ParachainSystem::initialize_for_set_code_benchmark(code.len() as u32);
Ok(())
Expand All @@ -295,7 +295,7 @@
}

use cumulus_pallet_session_benchmarking::Pallet as SessionBench;
impl cumulus_pallet_session_benchmarking::Config for Runtime {}

Check warning on line 298 in runtime/mainnet/src/apis.rs

View workflow job for this annotation

GitHub Actions / clippy

non-local `impl` definition, `impl` blocks should be written at the same level as their item

warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item --> runtime/mainnet/src/apis.rs:298:4 | 278 | / fn dispatch_benchmark( 279 | | config: frame_benchmarking::BenchmarkConfig 280 | | ) -> Result<Vec<frame_benchmarking::BenchmarkBatch>, alloc::string::String> { | |___________________________________________________________________________________- move the `impl` block outside of this associated function `dispatch_benchmark` ... 298 | impl cumulus_pallet_session_benchmarking::Config for Runtime {} | ^^^^^-------------------------------------------^^^^^------- | | | | | `Runtime` is not local | `Config` is not local | = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl`

use frame_support::traits::WhitelistedStorageKeys;
let whitelist = AllPalletsWithSystem::whitelisted_storage_keys();
Expand All @@ -315,11 +315,11 @@
}

fn get_preset(id: &Option<sp_genesis_builder::PresetId>) -> Option<Vec<u8>> {
get_preset::<RuntimeGenesisConfig>(id, |_| None)
get_preset::<RuntimeGenesisConfig>(id, super::genesis::get_preset)
}

fn preset_names() -> Vec<sp_genesis_builder::PresetId> {
Default::default()
super::genesis::presets()
}
}

Expand Down
2 changes: 1 addition & 1 deletion runtime/mainnet/src/config/mod.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Assets.
mod assets;
// Collation.
mod collation;
pub(crate) mod collation;
/// Governance.
pub mod governance;
/// Monetary matters.
Expand Down
Loading
Loading