GenesisConfig presets for runtime (#2714)

The runtime now can provide a number of predefined presets of
`RuntimeGenesisConfig` struct. This presets are intended to be used in
different deployments, e.g.: `local`, `staging`, etc, and should be
included into the corresponding chain-specs.

Having `GenesisConfig` presets in runtime allows to fully decouple node
from runtime types (the problem is described in #1984).

**Summary of changes:**
- The `GenesisBuilder` API was adjusted to enable this functionality
(and provide better naming - #150):
   ```rust
    fn preset_names() -> Vec<PresetId>;
fn get_preset(id: Option<PresetId>) -> Option<serde_json::Value>;
//`None` means default
    fn build_state(value: serde_json::Value);
    pub struct PresetId(Vec<u8>);
   ```

- **Breaking change**: Old `create_default_config` method was removed,
`build_config` was renamed to `build_state`. As a consequence a node
won't be able to interact with genesis config for older runtimes. The
cleanup was made for sake of API simplicity. Also IMO maintaining
compatibility with old API is not so crucial.
- Reference implementation was provided for `substrate-test-runtime` and
`rococo` runtimes. For rococo new
[`genesis_configs_presets`](https://github.com/paritytech/polkadot-sdk/blob/3b41d66b97c5ff0ec4a1989da5ffd8b9f3f588e3/polkadot/runtime/rococo/src/genesis_config_presets.rs#L530)
module was added and is used in `GenesisBuilder`
[_presets-related_](https://github.com/paritytech/polkadot-sdk/blob/3b41d66b97c5ff0ec4a1989da5ffd8b9f3f588e3/polkadot/runtime/rococo/src/lib.rs#L2462-L2485)
methods.

- The `chain-spec-builder` util was also improved and allows to
([_doc_](https://github.com/paritytech/polkadot-sdk/blob/3b41d66b97c5ff0ec4a1989da5ffd8b9f3f588e3/substrate/bin/utils/chain-spec-builder/src/lib.rs#L19)):
   - list presets provided by given runtime (`list-presets`),
- display preset or default config provided by the runtime
(`display-preset`),
   - build chain-spec using named preset (`create ... named-preset`),


- The `ChainSpecBuilder` is extended with
[`with_genesis_config_preset_name`](https://github.com/paritytech/polkadot-sdk/blob/3b41d66b97c5ff0ec4a1989da5ffd8b9f3f588e3/substrate/client/chain-spec/src/chain_spec.rs#L447)
method which allows to build chain-spec using named preset provided by
the runtime. Sample usage on the node side
[here](https://github.com/paritytech/polkadot-sdk/blob/2caffaae803e08a3d5b46c860e8016da023ff4ce/polkadot/node/service/src/chain_spec.rs#L404).

Implementation of #1984.
fixes: #150
part of: #25

---------

Co-authored-by: Sebastian Kunert <skunert49@gmail.com>
Co-authored-by: Kian Paimani <5588131+kianenigma@users.noreply.github.com>
Co-authored-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>
This commit is contained in:
Michal Kucharczyk
2024-04-04 20:30:54 +02:00
committed by GitHub
parent 9d052b7e09
commit f910a15c1c
47 changed files with 1460 additions and 661 deletions
Generated
+11 -3
View File
@@ -8148,6 +8148,7 @@ dependencies = [
"polkadot-sdk-frame",
"scale-info",
"sp-genesis-builder",
"sp-runtime",
"substrate-wasm-builder",
]
@@ -15048,6 +15049,7 @@ name = "rococo-runtime"
version = "7.0.0"
dependencies = [
"binary-merkle-tree",
"bitvec",
"frame-benchmarking",
"frame-executive",
"frame-remote-externalities",
@@ -15120,6 +15122,7 @@ dependencies = [
"sp-block-builder",
"sp-consensus-babe",
"sp-consensus-beefy",
"sp-consensus-grandpa",
"sp-core",
"sp-genesis-builder",
"sp-inherents",
@@ -15650,7 +15653,7 @@ dependencies = [
[[package]]
name = "sc-chain-spec"
version = "27.0.0"
version = "28.0.0"
dependencies = [
"array-bytes 6.1.0",
"docify",
@@ -15674,6 +15677,7 @@ dependencies = [
"sp-keyring",
"sp-runtime",
"sp-state-machine",
"sp-tracing 16.0.0",
"substrate-test-runtime",
]
@@ -18813,8 +18817,10 @@ dependencies = [
[[package]]
name = "sp-genesis-builder"
version = "0.7.0"
version = "0.8.0"
dependencies = [
"parity-scale-codec",
"scale-info",
"serde_json",
"sp-api",
"sp-runtime",
@@ -19450,7 +19456,7 @@ checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3"
[[package]]
name = "staging-chain-spec-builder"
version = "2.0.0"
version = "3.0.0"
dependencies = [
"clap 4.5.3",
"log",
@@ -19545,6 +19551,7 @@ dependencies = [
"sp-core",
"sp-crypto-hashing",
"sp-externalities 0.25.0",
"sp-genesis-builder",
"sp-inherents",
"sp-io",
"sp-keyring",
@@ -19970,6 +19977,7 @@ dependencies = [
"frame-system",
"frame-system-rpc-runtime-api",
"futures",
"hex-literal",
"log",
"pallet-babe",
"pallet-balances",
@@ -55,7 +55,7 @@ use cumulus_primitives_core::ParaId;
use frame_support::{
construct_runtime, derive_impl,
dispatch::DispatchClass,
genesis_builder_helper::{build_config, create_default_config},
genesis_builder_helper::{build_state, get_preset},
ord_parameter_types, parameter_types,
traits::{
fungible, fungibles, tokens::imbalance::ResolveAssetTo, AsEnsureOriginWithArg, ConstBool,
@@ -1649,12 +1649,16 @@ impl_runtime_apis! {
}
impl sp_genesis_builder::GenesisBuilder<Block> for Runtime {
fn create_default_config() -> Vec<u8> {
create_default_config::<RuntimeGenesisConfig>()
fn build_state(config: Vec<u8>) -> sp_genesis_builder::Result {
build_state::<RuntimeGenesisConfig>(config)
}
fn build_config(config: Vec<u8>) -> sp_genesis_builder::Result {
build_config::<RuntimeGenesisConfig>(config)
fn get_preset(id: &Option<sp_genesis_builder::PresetId>) -> Option<Vec<u8>> {
get_preset::<RuntimeGenesisConfig>(id, |_| None)
}
fn preset_names() -> Vec<sp_genesis_builder::PresetId> {
vec![]
}
}
}
@@ -37,7 +37,7 @@ use cumulus_primitives_core::{AggregateMessageOrigin, ParaId};
use frame_support::{
construct_runtime, derive_impl,
dispatch::DispatchClass,
genesis_builder_helper::{build_config, create_default_config},
genesis_builder_helper::{build_state, get_preset},
ord_parameter_types, parameter_types,
traits::{
fungible, fungibles,
@@ -1726,12 +1726,16 @@ impl_runtime_apis! {
}
impl sp_genesis_builder::GenesisBuilder<Block> for Runtime {
fn create_default_config() -> Vec<u8> {
create_default_config::<RuntimeGenesisConfig>()
fn build_state(config: Vec<u8>) -> sp_genesis_builder::Result {
build_state::<RuntimeGenesisConfig>(config)
}
fn build_config(config: Vec<u8>) -> sp_genesis_builder::Result {
build_config::<RuntimeGenesisConfig>(config)
fn get_preset(id: &Option<sp_genesis_builder::PresetId>) -> Option<Vec<u8>> {
get_preset::<RuntimeGenesisConfig>(id, |_| None)
}
fn preset_names() -> Vec<sp_genesis_builder::PresetId> {
vec![]
}
}
}
@@ -61,7 +61,7 @@ use cumulus_primitives_core::ParaId;
use frame_support::{
construct_runtime, derive_impl,
dispatch::DispatchClass,
genesis_builder_helper::{build_config, create_default_config},
genesis_builder_helper::{build_state, get_preset},
parameter_types,
traits::{ConstBool, ConstU32, ConstU64, ConstU8, TransformOrigin},
weights::{ConstantMultiplier, Weight},
@@ -1451,12 +1451,16 @@ impl_runtime_apis! {
}
impl sp_genesis_builder::GenesisBuilder<Block> for Runtime {
fn create_default_config() -> Vec<u8> {
create_default_config::<RuntimeGenesisConfig>()
fn build_state(config: Vec<u8>) -> sp_genesis_builder::Result {
build_state::<RuntimeGenesisConfig>(config)
}
fn build_config(config: Vec<u8>) -> sp_genesis_builder::Result {
build_config::<RuntimeGenesisConfig>(config)
fn get_preset(id: &Option<sp_genesis_builder::PresetId>) -> Option<Vec<u8>> {
get_preset::<RuntimeGenesisConfig>(id, |_| None)
}
fn preset_names() -> Vec<sp_genesis_builder::PresetId> {
vec![]
}
}
}
@@ -55,7 +55,7 @@ use bridge_hub_common::{
use frame_support::{
construct_runtime, derive_impl,
dispatch::DispatchClass,
genesis_builder_helper::{build_config, create_default_config},
genesis_builder_helper::{build_state, get_preset},
parameter_types,
traits::{ConstBool, ConstU32, ConstU64, ConstU8, TransformOrigin},
weights::{ConstantMultiplier, Weight},
@@ -1112,12 +1112,16 @@ impl_runtime_apis! {
}
impl sp_genesis_builder::GenesisBuilder<Block> for Runtime {
fn create_default_config() -> Vec<u8> {
create_default_config::<RuntimeGenesisConfig>()
fn build_state(config: Vec<u8>) -> sp_genesis_builder::Result {
build_state::<RuntimeGenesisConfig>(config)
}
fn build_config(config: Vec<u8>) -> sp_genesis_builder::Result {
build_config::<RuntimeGenesisConfig>(config)
fn get_preset(id: &Option<sp_genesis_builder::PresetId>) -> Option<Vec<u8>> {
get_preset::<RuntimeGenesisConfig>(id, |_| None)
}
fn preset_names() -> Vec<sp_genesis_builder::PresetId> {
vec![]
}
}
}
@@ -66,7 +66,7 @@ use cumulus_primitives_core::{AggregateMessageOrigin, ParaId};
use frame_support::{
construct_runtime, derive_impl,
dispatch::DispatchClass,
genesis_builder_helper::{build_config, create_default_config},
genesis_builder_helper::{build_state, get_preset},
parameter_types,
traits::{
fungible::HoldConsideration, ConstBool, ConstU16, ConstU32, ConstU64, ConstU8,
@@ -1062,12 +1062,16 @@ impl_runtime_apis! {
}
impl sp_genesis_builder::GenesisBuilder<Block> for Runtime {
fn create_default_config() -> Vec<u8> {
create_default_config::<RuntimeGenesisConfig>()
fn build_state(config: Vec<u8>) -> sp_genesis_builder::Result {
build_state::<RuntimeGenesisConfig>(config)
}
fn build_config(config: Vec<u8>) -> sp_genesis_builder::Result {
build_config::<RuntimeGenesisConfig>(config)
fn get_preset(id: &Option<sp_genesis_builder::PresetId>) -> Option<Vec<u8>> {
get_preset::<RuntimeGenesisConfig>(id, |_| None)
}
fn preset_names() -> Vec<sp_genesis_builder::PresetId> {
vec![]
}
}
}
@@ -48,7 +48,7 @@ use sp_version::RuntimeVersion;
use frame_support::{
construct_runtime, derive_impl,
dispatch::DispatchClass,
genesis_builder_helper::{build_config, create_default_config},
genesis_builder_helper::{build_state, get_preset},
parameter_types,
traits::{ConstBool, ConstU16, ConstU32, ConstU64, ConstU8},
weights::{ConstantMultiplier, Weight},
@@ -794,12 +794,16 @@ impl_runtime_apis! {
}
impl sp_genesis_builder::GenesisBuilder<Block> for Runtime {
fn create_default_config() -> Vec<u8> {
create_default_config::<RuntimeGenesisConfig>()
fn build_state(config: Vec<u8>) -> sp_genesis_builder::Result {
build_state::<RuntimeGenesisConfig>(config)
}
fn build_config(config: Vec<u8>) -> sp_genesis_builder::Result {
build_config::<RuntimeGenesisConfig>(config)
fn get_preset(id: &Option<sp_genesis_builder::PresetId>) -> Option<Vec<u8>> {
get_preset::<RuntimeGenesisConfig>(id, |_| None)
}
fn preset_names() -> Vec<sp_genesis_builder::PresetId> {
vec![]
}
}
}
@@ -38,7 +38,7 @@ use cumulus_primitives_core::{AggregateMessageOrigin, ParaId};
use frame_support::{
construct_runtime, derive_impl,
dispatch::DispatchClass,
genesis_builder_helper::{build_config, create_default_config},
genesis_builder_helper::{build_state, get_preset},
parameter_types,
traits::{ConstBool, ConstU32, ConstU64, ConstU8, EitherOfDiverse, TransformOrigin},
weights::{ConstantMultiplier, Weight},
@@ -878,12 +878,16 @@ impl_runtime_apis! {
}
impl sp_genesis_builder::GenesisBuilder<Block> for Runtime {
fn create_default_config() -> Vec<u8> {
create_default_config::<RuntimeGenesisConfig>()
fn build_state(config: Vec<u8>) -> sp_genesis_builder::Result {
build_state::<RuntimeGenesisConfig>(config)
}
fn build_config(config: Vec<u8>) -> sp_genesis_builder::Result {
build_config::<RuntimeGenesisConfig>(config)
fn get_preset(id: &Option<sp_genesis_builder::PresetId>) -> Option<Vec<u8>> {
get_preset::<RuntimeGenesisConfig>(id, |_| None)
}
fn preset_names() -> Vec<sp_genesis_builder::PresetId> {
vec![]
}
}
}
@@ -38,7 +38,7 @@ use cumulus_primitives_core::{AggregateMessageOrigin, ParaId};
use frame_support::{
construct_runtime, derive_impl,
dispatch::DispatchClass,
genesis_builder_helper::{build_config, create_default_config},
genesis_builder_helper::{build_state, get_preset},
parameter_types,
traits::{ConstBool, ConstU32, ConstU64, ConstU8, EitherOfDiverse, TransformOrigin},
weights::{ConstantMultiplier, Weight},
@@ -869,12 +869,16 @@ impl_runtime_apis! {
}
impl sp_genesis_builder::GenesisBuilder<Block> for Runtime {
fn create_default_config() -> Vec<u8> {
create_default_config::<RuntimeGenesisConfig>()
fn build_state(config: Vec<u8>) -> sp_genesis_builder::Result {
build_state::<RuntimeGenesisConfig>(config)
}
fn build_config(config: Vec<u8>) -> sp_genesis_builder::Result {
build_config::<RuntimeGenesisConfig>(config)
fn get_preset(id: &Option<sp_genesis_builder::PresetId>) -> Option<Vec<u8>> {
get_preset::<RuntimeGenesisConfig>(id, |_| None)
}
fn preset_names() -> Vec<sp_genesis_builder::PresetId> {
vec![]
}
}
}
@@ -66,7 +66,7 @@ use cumulus_primitives_core::AggregateMessageOrigin;
pub use frame_support::{
construct_runtime, derive_impl,
dispatch::DispatchClass,
genesis_builder_helper::{build_config, create_default_config},
genesis_builder_helper::{build_state, get_preset},
parameter_types,
traits::{
ConstBool, ConstU32, ConstU64, ConstU8, EitherOfDiverse, Everything, IsInVec, Randomness,
@@ -474,12 +474,16 @@ impl_runtime_apis! {
}
impl sp_genesis_builder::GenesisBuilder<Block> for Runtime {
fn create_default_config() -> Vec<u8> {
create_default_config::<RuntimeGenesisConfig>()
fn build_state(config: Vec<u8>) -> sp_genesis_builder::Result {
build_state::<RuntimeGenesisConfig>(config)
}
fn build_config(config: Vec<u8>) -> sp_genesis_builder::Result {
build_config::<RuntimeGenesisConfig>(config)
fn get_preset(id: &Option<sp_genesis_builder::PresetId>) -> Option<Vec<u8>> {
get_preset::<RuntimeGenesisConfig>(id, |_| None)
}
fn preset_names() -> Vec<sp_genesis_builder::PresetId> {
vec![]
}
}
}
@@ -27,7 +27,7 @@ use cumulus_primitives_core::{AggregateMessageOrigin, ParaId};
use frame_support::{
construct_runtime, derive_impl,
dispatch::DispatchClass,
genesis_builder_helper::{build_config, create_default_config},
genesis_builder_helper::{build_state, get_preset},
parameter_types,
traits::{
ConstBool, ConstU32, ConstU64, ConstU8, EitherOfDiverse, Everything, TransformOrigin,
@@ -851,12 +851,16 @@ impl_runtime_apis! {
}
impl sp_genesis_builder::GenesisBuilder<Block> for Runtime {
fn create_default_config() -> Vec<u8> {
create_default_config::<RuntimeGenesisConfig>()
fn build_state(config: Vec<u8>) -> sp_genesis_builder::Result {
build_state::<RuntimeGenesisConfig>(config)
}
fn build_config(config: Vec<u8>) -> sp_genesis_builder::Result {
build_config::<RuntimeGenesisConfig>(config)
fn get_preset(id: &Option<sp_genesis_builder::PresetId>) -> Option<Vec<u8>> {
get_preset::<RuntimeGenesisConfig>(id, |_| None)
}
fn preset_names() -> Vec<sp_genesis_builder::PresetId> {
vec![]
}
}
}
@@ -27,7 +27,7 @@ use cumulus_primitives_core::{AggregateMessageOrigin, ParaId};
use frame_support::{
construct_runtime, derive_impl,
dispatch::DispatchClass,
genesis_builder_helper::{build_config, create_default_config},
genesis_builder_helper::{build_state, get_preset},
parameter_types,
traits::{
ConstBool, ConstU32, ConstU64, ConstU8, EitherOfDiverse, Everything, TransformOrigin,
@@ -851,12 +851,16 @@ impl_runtime_apis! {
}
impl sp_genesis_builder::GenesisBuilder<Block> for Runtime {
fn create_default_config() -> Vec<u8> {
create_default_config::<RuntimeGenesisConfig>()
fn build_state(config: Vec<u8>) -> sp_genesis_builder::Result {
build_state::<RuntimeGenesisConfig>(config)
}
fn build_config(config: Vec<u8>) -> sp_genesis_builder::Result {
build_config::<RuntimeGenesisConfig>(config)
fn get_preset(id: &Option<sp_genesis_builder::PresetId>) -> Option<Vec<u8>> {
get_preset::<RuntimeGenesisConfig>(id, |_| None)
}
fn preset_names() -> Vec<sp_genesis_builder::PresetId> {
vec![]
}
}
}
@@ -46,7 +46,7 @@ use sp_version::RuntimeVersion;
pub use frame_support::{
construct_runtime, derive_impl,
dispatch::DispatchClass,
genesis_builder_helper::{build_config, create_default_config},
genesis_builder_helper::{build_state, get_preset},
parameter_types,
traits::{ConstBool, ConstU32, ConstU64, ConstU8, EitherOfDiverse, IsInVec, Randomness},
weights::{
@@ -370,12 +370,16 @@ impl_runtime_apis! {
}
impl sp_genesis_builder::GenesisBuilder<Block> for Runtime {
fn create_default_config() -> Vec<u8> {
create_default_config::<RuntimeGenesisConfig>()
fn build_state(config: Vec<u8>) -> sp_genesis_builder::Result {
build_state::<RuntimeGenesisConfig>(config)
}
fn build_config(config: Vec<u8>) -> sp_genesis_builder::Result {
build_config::<RuntimeGenesisConfig>(config)
fn get_preset(id: &Option<sp_genesis_builder::PresetId>) -> Option<Vec<u8>> {
get_preset::<RuntimeGenesisConfig>(id, |_| None)
}
fn preset_names() -> Vec<sp_genesis_builder::PresetId> {
vec![]
}
}
}
@@ -54,7 +54,7 @@ use sp_version::RuntimeVersion;
pub use frame_support::{
construct_runtime, derive_impl,
dispatch::DispatchClass,
genesis_builder_helper::{build_config, create_default_config},
genesis_builder_helper::{build_state, get_preset},
parameter_types,
traits::{ConstBool, ConstU32, ConstU64, ConstU8, EitherOfDiverse, IsInVec, Randomness},
weights::{
@@ -428,12 +428,16 @@ impl_runtime_apis! {
}
impl sp_genesis_builder::GenesisBuilder<Block> for Runtime {
fn create_default_config() -> Vec<u8> {
create_default_config::<RuntimeGenesisConfig>()
fn build_state(config: Vec<u8>) -> sp_genesis_builder::Result {
build_state::<RuntimeGenesisConfig>(config)
}
fn build_config(config: Vec<u8>) -> sp_genesis_builder::Result {
build_config::<RuntimeGenesisConfig>(config)
fn get_preset(id: &Option<sp_genesis_builder::PresetId>) -> Option<Vec<u8>> {
get_preset::<RuntimeGenesisConfig>(id, |_| None)
}
fn preset_names() -> Vec<sp_genesis_builder::PresetId> {
vec![]
}
}
}
@@ -37,7 +37,7 @@ use cumulus_primitives_core::{AggregateMessageOrigin, ParaId};
use frame_support::{
construct_runtime, derive_impl,
dispatch::DispatchClass,
genesis_builder_helper::{build_config, create_default_config},
genesis_builder_helper::{build_state, get_preset},
pallet_prelude::Weight,
parameter_types,
traits::{
@@ -911,12 +911,16 @@ impl_runtime_apis! {
}
impl sp_genesis_builder::GenesisBuilder<Block> for Runtime {
fn create_default_config() -> Vec<u8> {
create_default_config::<RuntimeGenesisConfig>()
fn build_state(config: Vec<u8>) -> sp_genesis_builder::Result {
build_state::<RuntimeGenesisConfig>(config)
}
fn build_config(config: Vec<u8>) -> sp_genesis_builder::Result {
build_config::<RuntimeGenesisConfig>(config)
fn get_preset(id: &Option<sp_genesis_builder::PresetId>) -> Option<Vec<u8>> {
get_preset::<RuntimeGenesisConfig>(id, |_| None)
}
fn preset_names() -> Vec<sp_genesis_builder::PresetId> {
vec![]
}
}
}
@@ -41,7 +41,7 @@ use sp_version::RuntimeVersion;
pub use frame_support::{
construct_runtime, derive_impl,
dispatch::DispatchClass,
genesis_builder_helper::{build_config, create_default_config},
genesis_builder_helper::{build_state, get_preset},
parameter_types,
traits::{
AsEnsureOriginWithArg, ConstBool, ConstU32, ConstU64, ConstU8, Contains, EitherOfDiverse,
@@ -824,12 +824,16 @@ impl_runtime_apis! {
}
impl sp_genesis_builder::GenesisBuilder<Block> for Runtime {
fn create_default_config() -> Vec<u8> {
create_default_config::<RuntimeGenesisConfig>()
fn build_state(config: Vec<u8>) -> sp_genesis_builder::Result {
build_state::<RuntimeGenesisConfig>(config)
}
fn build_config(config: Vec<u8>) -> sp_genesis_builder::Result {
build_config::<RuntimeGenesisConfig>(config)
fn get_preset(id: &Option<sp_genesis_builder::PresetId>) -> Option<Vec<u8>> {
get_preset::<RuntimeGenesisConfig>(id, |_| None)
}
fn preset_names() -> Vec<sp_genesis_builder::PresetId> {
vec![]
}
}
@@ -189,11 +189,15 @@ sp_api::impl_runtime_apis! {
}
impl sp_genesis_builder::GenesisBuilder<Block> for Runtime {
fn create_default_config() -> Vec<u8> {
fn build_state(_: Vec<u8>) -> sp_genesis_builder::Result {
unimplemented!()
}
fn build_config(_: Vec<u8>) -> sp_genesis_builder::Result {
fn get_preset(_id: &Option<sp_genesis_builder::PresetId>) -> Option<Vec<u8>> {
unimplemented!()
}
fn preset_names() -> Vec<sp_genesis_builder::PresetId> {
unimplemented!()
}
}
@@ -189,11 +189,15 @@ sp_api::impl_runtime_apis! {
}
impl sp_genesis_builder::GenesisBuilder<Block> for Runtime {
fn create_default_config() -> Vec<u8> {
fn build_state(_: Vec<u8>) -> sp_genesis_builder::Result {
unimplemented!()
}
fn build_config(_: Vec<u8>) -> sp_genesis_builder::Result {
fn get_preset(_id: &Option<sp_genesis_builder::PresetId>) -> Option<Vec<u8>> {
unimplemented!()
}
fn preset_names() -> Vec<sp_genesis_builder::PresetId> {
unimplemented!()
}
}
+9 -5
View File
@@ -47,7 +47,7 @@ use sp_version::RuntimeVersion;
pub use frame_support::{
construct_runtime,
dispatch::DispatchClass,
genesis_builder_helper::{build_config, create_default_config},
genesis_builder_helper::{build_state, get_preset},
parameter_types,
traits::{ConstU8, Randomness},
weights::{
@@ -463,12 +463,16 @@ impl_runtime_apis! {
}
impl sp_genesis_builder::GenesisBuilder<Block> for Runtime {
fn create_default_config() -> Vec<u8> {
create_default_config::<RuntimeGenesisConfig>()
fn build_state(config: Vec<u8>) -> sp_genesis_builder::Result {
build_state::<RuntimeGenesisConfig>(config)
}
fn build_config(config: Vec<u8>) -> sp_genesis_builder::Result {
build_config::<RuntimeGenesisConfig>(config)
fn get_preset(id: &Option<sp_genesis_builder::PresetId>) -> Option<Vec<u8>> {
get_preset::<RuntimeGenesisConfig>(id, |_| None)
}
fn preset_names() -> Vec<sp_genesis_builder::PresetId> {
vec![]
}
}
}
+12 -402
View File
@@ -24,12 +24,10 @@ use polkadot_primitives::{AccountId, AccountPublic, AssignmentId, ValidatorId};
use sp_authority_discovery::AuthorityId as AuthorityDiscoveryId;
use sp_consensus_babe::AuthorityId as BabeId;
#[cfg(any(feature = "rococo-native", feature = "westend-native",))]
#[cfg(feature = "westend-native")]
use polkadot_primitives::vstaging::SchedulerParams;
#[cfg(feature = "rococo-native")]
use rococo_runtime as rococo;
#[cfg(feature = "rococo-native")]
use rococo_runtime_constants::currency::UNITS as ROC;
use sc_chain_spec::ChainSpecExtension;
#[cfg(any(feature = "westend-native", feature = "rococo-native"))]
use sc_chain_spec::ChainType;
@@ -118,7 +116,7 @@ pub fn wococo_config() -> Result<RococoChainSpec, String> {
}
/// The default parachains host configuration.
#[cfg(any(feature = "rococo-native", feature = "westend-native",))]
#[cfg(feature = "westend-native")]
fn default_parachains_host_configuration(
) -> polkadot_runtime_parachains::configuration::HostConfiguration<polkadot_primitives::BlockNumber>
{
@@ -173,7 +171,7 @@ fn default_parachains_host_configuration(
}
}
#[cfg(any(feature = "rococo-native", feature = "westend-native",))]
#[cfg(feature = "westend-native")]
#[test]
fn default_parachains_host_configuration_is_consistent() {
default_parachains_host_configuration().panic_if_not_consistent();
@@ -198,25 +196,6 @@ fn westend_session_keys(
}
}
#[cfg(feature = "rococo-native")]
fn rococo_session_keys(
babe: BabeId,
grandpa: GrandpaId,
para_validator: ValidatorId,
para_assignment: AssignmentId,
authority_discovery: AuthorityDiscoveryId,
beefy: BeefyId,
) -> rococo_runtime::SessionKeys {
rococo_runtime::SessionKeys {
babe,
grandpa,
para_validator,
para_assignment,
authority_discovery,
beefy,
}
}
#[cfg(feature = "westend-native")]
fn westend_staging_testnet_config_genesis() -> serde_json::Value {
use hex_literal::hex;
@@ -394,265 +373,6 @@ fn westend_staging_testnet_config_genesis() -> serde_json::Value {
})
}
#[cfg(feature = "rococo-native")]
fn rococo_staging_testnet_config_genesis() -> serde_json::Value {
use hex_literal::hex;
use sp_core::crypto::UncheckedInto;
// subkey inspect "$SECRET"
let endowed_accounts = vec![
// 5DwBmEFPXRESyEam5SsQF1zbWSCn2kCjyLW51hJHXe9vW4xs
hex!["52bc71c1eca5353749542dfdf0af97bf764f9c2f44e860cd485f1cd86400f649"].into(),
];
// ./scripts/prepare-test-net.sh 8
let initial_authorities: Vec<(
AccountId,
AccountId,
BabeId,
GrandpaId,
ValidatorId,
AssignmentId,
AuthorityDiscoveryId,
BeefyId,
)> = vec![
(
//5EHZkbp22djdbuMFH9qt1DVzSCvqi3zWpj6DAYfANa828oei
hex!["62475fe5406a7cb6a64c51d0af9d3ab5c2151bcae982fb812f7a76b706914d6a"].into(),
//5FeSEpi9UYYaWwXXb3tV88qtZkmSdB3mvgj3pXkxKyYLGhcd
hex!["9e6e781a76810fe93187af44c79272c290c2b9e2b8b92ee11466cd79d8023f50"].into(),
//5Fh6rDpMDhM363o1Z3Y9twtaCPfizGQWCi55BSykTQjGbP7H
hex!["a076ef1280d768051f21d060623da3ab5b56944d681d303ed2d4bf658c5bed35"]
.unchecked_into(),
//5CPd3zoV9Aaah4xWucuDivMHJ2nEEmpdi864nPTiyRZp4t87
hex!["0e6d7d1afbcc6547b92995a394ba0daed07a2420be08220a5a1336c6731f0bfa"]
.unchecked_into(),
//5CP6oGfwqbEfML8efqm1tCZsUgRsJztp9L8ZkEUxA16W8PPz
hex!["0e07a51d3213842f8e9363ce8e444255990a225f87e80a3d651db7841e1a0205"]
.unchecked_into(),
//5HQdwiDh8Qtd5dSNWajNYpwDvoyNWWA16Y43aEkCNactFc2b
hex!["ec60e71fe4a567ef9fef99d4bbf37ffae70564b41aa6f94ef0317c13e0a5477b"]
.unchecked_into(),
//5HbSgM72xVuscsopsdeG3sCSCYdAeM1Tay9p79N6ky6vwDGq
hex!["f49eae66a0ac9f610316906ec8f1a0928e20d7059d76a5ca53cbcb5a9b50dd3c"]
.unchecked_into(),
//5DPSWdgw38Spu315r6LSvYCggeeieBAJtP5A1qzuzKhqmjVu
hex!["034f68c5661a41930c82f26a662276bf89f33467e1c850f2fb8ef687fe43d62276"]
.unchecked_into(),
),
(
//5DvH8oEjQPYhzCoQVo7WDU91qmQfLZvxe9wJcrojmJKebCmG
hex!["520b48452969f6ddf263b664de0adb0c729d0e0ad3b0e5f3cb636c541bc9022a"].into(),
//5ENZvCRzyXJJYup8bM6yEzb2kQHEb1NDpY2ZEyVGBkCfRdj3
hex!["6618289af7ae8621981ffab34591e7a6486e12745dfa3fd3b0f7e6a3994c7b5b"].into(),
//5DLjSUfqZVNAADbwYLgRvHvdzXypiV1DAEaDMjcESKTcqMoM
hex!["38757d0de00a0c739e7d7984ef4bc01161bd61e198b7c01b618425c16bb5bd5f"]
.unchecked_into(),
//5HnDVBN9mD6mXyx8oryhDbJtezwNSj1VRXgLoYCBA6uEkiao
hex!["fcd5f87a6fd5707a25122a01b4dac0a8482259df7d42a9a096606df1320df08d"]
.unchecked_into(),
//5EPEWRecy2ApL5n18n3aHyU1956zXTRqaJpzDa9DoqiggNwF
hex!["669a10892119453e9feb4e3f1ee8e028916cc3240022920ad643846fbdbee816"]
.unchecked_into(),
//5ES3fw5X4bndSgLNmtPfSbM2J1kLqApVB2CCLS4CBpM1UxUZ
hex!["68bf52c482630a8d1511f2edd14f34127a7d7082219cccf7fd4c6ecdb535f80d"]
.unchecked_into(),
//5HeXbwb5PxtcRoopPZTp5CQun38atn2UudQ8p2AxR5BzoaXw
hex!["f6f8fe475130d21165446a02fb1dbce3a7bf36412e5d98f4f0473aed9252f349"]
.unchecked_into(),
//5F7nTtN8MyJV4UsXpjg7tHSnfANXZ5KRPJmkASc1ZSH2Xoa5
hex!["03a90c2bb6d3b7000020f6152fe2e5002fa970fd1f42aafb6c8edda8dacc2ea77e"]
.unchecked_into(),
),
(
//5FPMzsezo1PRxYbVpJMWK7HNbR2kUxidsAAxH4BosHa4wd6S
hex!["92ef83665b39d7a565e11bf8d18d41d45a8011601c339e57a8ea88c8ff7bba6f"].into(),
//5G6NQidFG7YiXsvV7hQTLGArir9tsYqD4JDxByhgxKvSKwRx
hex!["b235f57244230589523271c27b8a490922ffd7dccc83b044feaf22273c1dc735"].into(),
//5GpZhzAVg7SAtzLvaAC777pjquPEcNy1FbNUAG2nZvhmd6eY
hex!["d2644c1ab2c63a3ad8d40ad70d4b260969e3abfe6d7e6665f50dc9f6365c9d2a"]
.unchecked_into(),
//5HAes2RQYPbYKbLBfKb88f4zoXv6pPA6Ke8CjN7dob3GpmSP
hex!["e1b68fbd84333e31486c08e6153d9a1415b2e7e71b413702b7d64e9b631184a1"]
.unchecked_into(),
//5FtAGDZYJKXkhVhAxCQrXmaP7EE2mGbBMfmKDHjfYDgq2BiU
hex!["a8e61ffacafaf546283dc92d14d7cc70ea0151a5dd81fdf73ff5a2951f2b6037"]
.unchecked_into(),
//5CtK7JHv3h6UQZ44y54skxdwSVBRtuxwPE1FYm7UZVhg8rJV
hex!["244f3421b310c68646e99cdbf4963e02067601f57756b072a4b19431448c186e"]
.unchecked_into(),
//5D4r6YaB6F7A7nvMRHNFNF6zrR9g39bqDJFenrcaFmTCRwfa
hex!["2c57f81fd311c1ab53813c6817fe67f8947f8d39258252663b3384ab4195494d"]
.unchecked_into(),
//5EPoHj8uV4fFKQHYThc6Z9fDkU7B6ih2ncVzQuDdNFb8UyhF
hex!["039d065fe4f9234f0a4f13cc3ae585f2691e9c25afa469618abb6645111f607a53"]
.unchecked_into(),
),
(
//5DMNx7RoX6d7JQ38NEM7DWRcW2THu92LBYZEWvBRhJeqcWgR
hex!["38f3c2f38f6d47f161e98c697bbe3ca0e47c033460afda0dda314ab4222a0404"].into(),
//5GGdKNDr9P47dpVnmtq3m8Tvowwf1ot1abw6tPsTYYFoKm2v
hex!["ba0898c1964196474c0be08d364cdf4e9e1d47088287f5235f70b0590dfe1704"].into(),
//5EjkyPCzR2SjhDZq8f7ufsw6TfkvgNRepjCRQFc4TcdXdaB1
hex!["764186bc30fd5a02477f19948dc723d6d57ab174debd4f80ed6038ec960bfe21"]
.unchecked_into(),
//5DJV3zCBTJBLGNDCcdWrYxWDacSz84goGTa4pFeKVvehEBte
hex!["36be9069cdb4a8a07ecd51f257875150f0a8a1be44a10d9d98dabf10a030aef4"]
.unchecked_into(),
//5F9FsRjpecP9GonktmtFL3kjqNAMKjHVFjyjRdTPa4hbQRZA
hex!["882d72965e642677583b333b2d173ac94b5fd6c405c76184bb14293be748a13b"]
.unchecked_into(),
//5F1FZWZSj3JyTLs8sRBxU6QWyGLSL9BMRtmSKDmVEoiKFxSP
hex!["821271c99c958b9220f1771d9f5e29af969edfa865631dba31e1ab7bc0582b75"]
.unchecked_into(),
//5CtgRR74VypK4h154s369abs78hDUxZSJqcbWsfXvsjcHJNA
hex!["2496f28d887d84705c6dae98aee8bf90fc5ad10bb5545eca1de6b68425b70f7c"]
.unchecked_into(),
//5CPx6dsr11SCJHKFkcAQ9jpparS7FwXQBrrMznRo4Hqv1PXz
hex!["0307d29bbf6a5c4061c2157b44fda33b7bb4ec52a5a0305668c74688cedf288d58"]
.unchecked_into(),
),
(
//5C8AL1Zb4bVazgT3EgDxFgcow1L4SJjVu44XcLC9CrYqFN4N
hex!["02a2d8cfcf75dda85fafc04ace3bcb73160034ed1964c43098fb1fe831de1b16"].into(),
//5FLYy3YKsAnooqE4hCudttAsoGKbVG3hYYBtVzwMjJQrevPa
hex!["90cab33f0bb501727faa8319f0845faef7d31008f178b65054b6629fe531b772"].into(),
//5Et3tfbVf1ByFThNAuUq5pBssdaPPskip5yob5GNyUFojXC7
hex!["7c94715e5dd8ab54221b1b6b2bfa5666f593f28a92a18e28052531de1bd80813"]
.unchecked_into(),
//5EX1JBghGbQqWohTPU6msR9qZ2nYPhK9r3RTQ2oD1K8TCxaG
hex!["6c878e33b83c20324238d22240f735457b6fba544b383e70bb62a27b57380c81"]
.unchecked_into(),
//5EUNaBpX9mJgcmLQHyG5Pkms6tbDiKuLbeTEJS924Js9cA1N
hex!["6a8570b9c6408e54bacf123cc2bb1b0f087f9c149147d0005badba63a5a4ac01"]
.unchecked_into(),
//5CaZuueRVpMATZG4hkcrgDoF4WGixuz7zu83jeBdY3bgWGaG
hex!["16c69ea8d595e80b6736f44be1eaeeef2ac9c04a803cc4fd944364cb0d617a33"]
.unchecked_into(),
//5DABsdQCDUGuhzVGWe5xXzYQ9rtrVxRygW7RXf9Tsjsw1aGJ
hex!["306ac5c772fe858942f92b6e28bd82fb7dd8cdd25f9a4626c1b0eee075fcb531"]
.unchecked_into(),
//5H91T5mHhoCw9JJG4NjghDdQyhC6L7XcSuBWKD3q3TAhEVvQ
hex!["02fb0330356e63a35dd930bc74525edf28b3bf5eb44aab9e9e4962c8309aaba6a6"]
.unchecked_into(),
),
(
//5C8XbDXdMNKJrZSrQURwVCxdNdk8AzG6xgLggbzuA399bBBF
hex!["02ea6bfa8b23b92fe4b5db1063a1f9475e3acd0ab61e6b4f454ed6ba00b5f864"].into(),
//5GsyzFP8qtF8tXPSsjhjxAeU1v7D1PZofuQKN9TdCc7Dp1JM
hex!["d4ffc4c05b47d1115ad200f7f86e307b20b46c50e1b72a912ec4f6f7db46b616"].into(),
//5GHWB8ZDzegLcMW7Gdd1BS6WHVwDdStfkkE4G7KjPjZNJBtD
hex!["bab3cccdcc34401e9b3971b96a662686cf755aa869a5c4b762199ce531b12c5b"]
.unchecked_into(),
//5GzDPGbUM9uH52ZEwydasTj8edokGUJ7vEpoFWp9FE1YNuFB
hex!["d9c056c98ca0e6b4eb7f5c58c007c1db7be0fe1f3776108f797dd4990d1ccc33"]
.unchecked_into(),
//5CmLCFeSurRXXtwMmLcVo7sdJ9EqDguvJbuCYDcHkr3cpqyE
hex!["1efc23c0b51ad609ab670ecf45807e31acbd8e7e5cb7c07cf49ee42992d2867c"]
.unchecked_into(),
//5DnsSy8a8pfE2aFjKBDtKw7WM1V4nfE5sLzP15MNTka53GqS
hex!["4c64d3f06d28adeb36a892fdaccecace150bec891f04694448a60b74fa469c22"]
.unchecked_into(),
//5CZdFnyzZvKetZTeUwj5APAYskVJe4QFiTezo5dQNsrnehGd
hex!["160ea09c5717270e958a3da42673fa011613a9539b2e4ebcad8626bc117ca04a"]
.unchecked_into(),
//5HgoR9JJkdBusxKrrs3zgd3ToppgNoGj1rDyAJp4e7eZiYyT
hex!["020019a8bb188f8145d02fa855e9c36e9914457d37c500e03634b5223aa5702474"]
.unchecked_into(),
),
(
//5HinEonzr8MywkqedcpsmwpxKje2jqr9miEwuzyFXEBCvVXM
hex!["fa373e25a1c4fe19c7148acde13bc3db1811cf656dc086820f3dda736b9c4a00"].into(),
//5EHJbj6Td6ks5HDnyfN4ttTSi57osxcQsQexm7XpazdeqtV7
hex!["62145d721967bd88622d08625f0f5681463c0f1b8bcd97eb3c2c53f7660fd513"].into(),
//5EeCsC58XgJ1DFaoYA1WktEpP27jvwGpKdxPMFjicpLeYu96
hex!["720537e2c1c554654d73b3889c3ef4c3c2f95a65dd3f7c185ebe4afebed78372"]
.unchecked_into(),
//5DnEySxbnppWEyN8cCLqvGjAorGdLRg2VmkY96dbJ1LHFK8N
hex!["4bea0b37e0cce9bddd80835fa2bfd5606f5dcfb8388bbb10b10c483f0856cf14"]
.unchecked_into(),
//5CAC278tFCHAeHYqE51FTWYxHmeLcENSS1RG77EFRTvPZMJT
hex!["042f07fc5268f13c026bbe199d63e6ac77a0c2a780f71cda05cee5a6f1b3f11f"]
.unchecked_into(),
//5HjRTLWcQjZzN3JDvaj1UzjNSayg5ZD9ZGWMstaL7Ab2jjAa
hex!["fab485e87ed1537d089df521edf983a777c57065a702d7ed2b6a2926f31da74f"]
.unchecked_into(),
//5ELv74v7QcsS6FdzvG4vL2NnYDGWmRnJUSMKYwdyJD7Xcdi7
hex!["64d59feddb3d00316a55906953fb3db8985797472bd2e6c7ea1ab730cc339d7f"]
.unchecked_into(),
//5FaUcPt4fPz93vBhcrCJqmDkjYZ7jCbzAF56QJoCmvPaKrmx
hex!["033f1a6d47fe86f88934e4b83b9fae903b92b5dcf4fec97d5e3e8bf4f39df03685"]
.unchecked_into(),
),
(
//5Ey3NQ3dfabaDc16NUv7wRLsFCMDFJSqZFzKVycAsWuUC6Di
hex!["8062e9c21f1d92926103119f7e8153cebdb1e5ab3e52d6f395be80bb193eab47"].into(),
//5HiWsuSBqt8nS9pnggexXuHageUifVPKPHDE2arTKqhTp1dV
hex!["fa0388fa88f3f0cb43d583e2571fbc0edad57dff3a6fd89775451dd2c2b8ea00"].into(),
//5H168nKX2Yrfo3bxj7rkcg25326Uv3CCCnKUGK6uHdKMdPt8
hex!["da6b2df18f0f9001a6dcf1d301b92534fe9b1f3ccfa10c49449fee93adaa8349"]
.unchecked_into(),
//5DrA2fZdzmNqT5j6DXNwVxPBjDV9jhkAqvjt6Us3bQHKy3cF
hex!["4ee66173993dd0db5d628c4c9cb61a27b76611ad3c3925947f0d0011ee2c5dcc"]
.unchecked_into(),
//5Gx6YeNhynqn8qkda9QKpc9S7oDr4sBrfAu516d3sPpEt26F
hex!["d822d4088b20dca29a580a577a97d6f024bb24c9550bebdfd7d2d18e946a1c7d"]
.unchecked_into(),
//5DhDcHqwxoes5s89AyudGMjtZXx1nEgrk5P45X88oSTR3iyx
hex!["481538f8c2c011a76d7d57db11c2789a5e83b0f9680dc6d26211d2f9c021ae4c"]
.unchecked_into(),
//5DqAvikdpfRdk5rR35ZobZhqaC5bJXZcEuvzGtexAZP1hU3T
hex!["4e262811acdfe94528bfc3c65036080426a0e1301b9ada8d687a70ffcae99c26"]
.unchecked_into(),
//5E41Znrr2YtZu8bZp3nvRuLVHg3jFksfQ3tXuviLku4wsao7
hex!["025e84e95ed043e387ddb8668176b42f8e2773ddd84f7f58a6d9bf436a4b527986"]
.unchecked_into(),
),
];
const ENDOWMENT: u128 = 1_000_000 * ROC;
const STASH: u128 = 100 * ROC;
serde_json::json!({
"balances": {
"balances": endowed_accounts
.iter()
.map(|k: &AccountId| (k.clone(), ENDOWMENT))
.chain(initial_authorities.iter().map(|x| (x.0.clone(), STASH)))
.collect::<Vec<_>>(),
},
"session": {
"keys": initial_authorities
.iter()
.map(|x| {
(
x.0.clone(),
x.0.clone(),
rococo_session_keys(
x.2.clone(),
x.3.clone(),
x.4.clone(),
x.5.clone(),
x.6.clone(),
x.7.clone(),
),
)
})
.collect::<Vec<_>>(),
},
"babe": {
"epochConfig": Some(rococo_runtime::BABE_GENESIS_EPOCH_CONFIG),
},
"sudo": { "key": Some(endowed_accounts[0].clone()) },
"configuration": {
"config": default_parachains_host_configuration(),
},
"registrar": {
"nextFreeParaId": polkadot_primitives::LOWEST_PUBLIC_ID,
},
})
}
/// Westend staging testnet config.
#[cfg(feature = "westend-native")]
pub fn westend_staging_testnet_config() -> Result<WestendChainSpec, String> {
@@ -682,7 +402,7 @@ pub fn rococo_staging_testnet_config() -> Result<RococoChainSpec, String> {
.with_name("Rococo Staging Testnet")
.with_id("rococo_staging_testnet")
.with_chain_type(ChainType::Live)
.with_genesis_config_patch(rococo_staging_testnet_config_genesis())
.with_genesis_config_preset_name("staging_testnet")
.with_telemetry_endpoints(
TelemetryEndpoints::new(vec![(ROCOCO_STAGING_TELEMETRY_URL.to_string(), 0)])
.expect("Rococo Staging telemetry url is valid; qed"),
@@ -712,7 +432,7 @@ pub fn versi_staging_testnet_config() -> Result<RococoChainSpec, String> {
.with_name("Versi Staging Testnet")
.with_id("versi_staging_testnet")
.with_chain_type(ChainType::Live)
.with_genesis_config_patch(rococo_staging_testnet_config_genesis())
.with_genesis_config_preset_name("staging_testnet")
.with_telemetry_endpoints(
TelemetryEndpoints::new(vec![(VERSI_STAGING_TELEMETRY_URL.to_string(), 0)])
.expect("Versi Staging telemetry url is valid; qed"),
@@ -769,7 +489,7 @@ pub fn get_authority_keys_from_seed_no_beefy(
)
}
#[cfg(any(feature = "westend-native", feature = "rococo-native"))]
#[cfg(feature = "westend-native")]
fn testnet_accounts() -> Vec<AccountId> {
vec![
get_account_id_from_seed::<sr25519::Public>("Alice"),
@@ -855,68 +575,6 @@ pub fn westend_testnet_genesis(
})
}
/// Helper function to create rococo runtime `GenesisConfig` patch for testing
#[cfg(feature = "rococo-native")]
pub fn rococo_testnet_genesis(
initial_authorities: Vec<(
AccountId,
AccountId,
BabeId,
GrandpaId,
ValidatorId,
AssignmentId,
AuthorityDiscoveryId,
BeefyId,
)>,
root_key: AccountId,
endowed_accounts: Option<Vec<AccountId>>,
) -> serde_json::Value {
let endowed_accounts: Vec<AccountId> = endowed_accounts.unwrap_or_else(testnet_accounts);
const ENDOWMENT: u128 = 1_000_000 * ROC;
serde_json::json!({
"balances": {
"balances": endowed_accounts.iter().map(|k| (k.clone(), ENDOWMENT)).collect::<Vec<_>>(),
},
"session": {
"keys": initial_authorities
.iter()
.map(|x| {
(
x.0.clone(),
x.0.clone(),
rococo_session_keys(
x.2.clone(),
x.3.clone(),
x.4.clone(),
x.5.clone(),
x.6.clone(),
x.7.clone(),
),
)
})
.collect::<Vec<_>>(),
},
"babe": {
"epochConfig": Some(rococo_runtime::BABE_GENESIS_EPOCH_CONFIG),
},
"sudo": { "key": Some(root_key.clone()) },
"configuration": {
"config": polkadot_runtime_parachains::configuration::HostConfiguration {
scheduler_params: SchedulerParams {
max_validators_per_core: Some(1),
..default_parachains_host_configuration().scheduler_params
},
..default_parachains_host_configuration()
},
},
"registrar": {
"nextFreeParaId": polkadot_primitives::LOWEST_PUBLIC_ID,
}
})
}
#[cfg(feature = "westend-native")]
fn westend_development_config_genesis() -> serde_json::Value {
westend_testnet_genesis(
@@ -926,15 +584,6 @@ fn westend_development_config_genesis() -> serde_json::Value {
)
}
#[cfg(feature = "rococo-native")]
fn rococo_development_config_genesis() -> serde_json::Value {
rococo_testnet_genesis(
vec![get_authority_keys_from_seed("Alice")],
get_account_id_from_seed::<sr25519::Public>("Alice"),
None,
)
}
/// Westend development config (single validator Alice)
#[cfg(feature = "westend-native")]
pub fn westend_development_config() -> Result<WestendChainSpec, String> {
@@ -960,7 +609,7 @@ pub fn rococo_development_config() -> Result<RococoChainSpec, String> {
.with_name("Development")
.with_id("rococo_dev")
.with_chain_type(ChainType::Development)
.with_genesis_config_patch(rococo_development_config_genesis())
.with_genesis_config_preset_name("development")
.with_protocol_id(DEFAULT_PROTOCOL_ID)
.build())
}
@@ -975,7 +624,7 @@ pub fn versi_development_config() -> Result<RococoChainSpec, String> {
.with_name("Development")
.with_id("versi_dev")
.with_chain_type(ChainType::Development)
.with_genesis_config_patch(rococo_development_config_genesis())
.with_genesis_config_preset_name("development")
.with_protocol_id("versi")
.build())
}
@@ -991,7 +640,7 @@ pub fn wococo_development_config() -> Result<RococoChainSpec, String> {
.with_name("Development")
.with_id("wococo_dev")
.with_chain_type(ChainType::Development)
.with_genesis_config_patch(rococo_development_config_genesis())
.with_genesis_config_preset_name("development")
.with_protocol_id(WOCOCO_DEV_PROTOCOL_ID)
.build())
}
@@ -1020,15 +669,6 @@ pub fn westend_local_testnet_config() -> Result<WestendChainSpec, String> {
.build())
}
#[cfg(feature = "rococo-native")]
fn rococo_local_testnet_genesis() -> serde_json::Value {
rococo_testnet_genesis(
vec![get_authority_keys_from_seed("Alice"), get_authority_keys_from_seed("Bob")],
get_account_id_from_seed::<sr25519::Public>("Alice"),
None,
)
}
/// Rococo local testnet config (multivalidator Alice + Bob)
#[cfg(feature = "rococo-native")]
pub fn rococo_local_testnet_config() -> Result<RococoChainSpec, String> {
@@ -1039,26 +679,11 @@ pub fn rococo_local_testnet_config() -> Result<RococoChainSpec, String> {
.with_name("Rococo Local Testnet")
.with_id("rococo_local_testnet")
.with_chain_type(ChainType::Local)
.with_genesis_config_patch(rococo_local_testnet_genesis())
.with_genesis_config_preset_name("local_testnet")
.with_protocol_id(DEFAULT_PROTOCOL_ID)
.build())
}
/// Wococo is a temporary testnet that uses almost the same runtime as rococo.
#[cfg(feature = "rococo-native")]
fn wococo_local_testnet_genesis() -> serde_json::Value {
rococo_testnet_genesis(
vec![
get_authority_keys_from_seed("Alice"),
get_authority_keys_from_seed("Bob"),
get_authority_keys_from_seed("Charlie"),
get_authority_keys_from_seed("Dave"),
],
get_account_id_from_seed::<sr25519::Public>("Alice"),
None,
)
}
/// Wococo local testnet config (multivalidator Alice + Bob + Charlie + Dave)
#[cfg(feature = "rococo-native")]
pub fn wococo_local_testnet_config() -> Result<RococoChainSpec, String> {
@@ -1069,26 +694,11 @@ pub fn wococo_local_testnet_config() -> Result<RococoChainSpec, String> {
.with_name("Wococo Local Testnet")
.with_id("wococo_local_testnet")
.with_chain_type(ChainType::Local)
.with_genesis_config_patch(wococo_local_testnet_genesis())
.with_genesis_config_preset_name("wococo_local_testnet")
.with_protocol_id(DEFAULT_PROTOCOL_ID)
.build())
}
/// `Versi` is a temporary testnet that uses the same runtime as rococo.
#[cfg(feature = "rococo-native")]
fn versi_local_testnet_genesis() -> serde_json::Value {
rococo_testnet_genesis(
vec![
get_authority_keys_from_seed("Alice"),
get_authority_keys_from_seed("Bob"),
get_authority_keys_from_seed("Charlie"),
get_authority_keys_from_seed("Dave"),
],
get_account_id_from_seed::<sr25519::Public>("Alice"),
None,
)
}
/// `Versi` local testnet config (multivalidator Alice + Bob + Charlie + Dave)
#[cfg(feature = "rococo-native")]
pub fn versi_local_testnet_config() -> Result<RococoChainSpec, String> {
@@ -1099,7 +709,7 @@ pub fn versi_local_testnet_config() -> Result<RococoChainSpec, String> {
.with_name("Versi Local Testnet")
.with_id("versi_local_testnet")
.with_chain_type(ChainType::Local)
.with_genesis_config_patch(versi_local_testnet_genesis())
.with_genesis_config_preset_name("versi_local_testnet")
.with_protocol_id("versi")
.build())
}
+6
View File
@@ -16,12 +16,15 @@ scale-info = { version = "2.11.1", default-features = false, features = ["derive
log = { workspace = true }
serde = { workspace = true }
serde_derive = { optional = true, workspace = true }
serde_json = { features = ["alloc"], workspace = true }
static_assertions = "1.1.0"
smallvec = "1.8.0"
bitvec = { version = "1.0.1", default-features = false, features = ["alloc"] }
authority-discovery-primitives = { package = "sp-authority-discovery", path = "../../../substrate/primitives/authority-discovery", default-features = false }
babe-primitives = { package = "sp-consensus-babe", path = "../../../substrate/primitives/consensus/babe", default-features = false }
beefy-primitives = { package = "sp-consensus-beefy", path = "../../../substrate/primitives/consensus/beefy", default-features = false }
grandpa_primitives = { package = "sp-consensus-grandpa", path = "../../../substrate/primitives/consensus/grandpa", default-features = false }
binary-merkle-tree = { path = "../../../substrate/utils/binary-merkle-tree", default-features = false }
rococo-runtime-constants = { package = "rococo-runtime-constants", path = "constants", default-features = false }
sp-api = { path = "../../../substrate/primitives/api", default-features = false }
@@ -126,6 +129,7 @@ std = [
"babe-primitives/std",
"beefy-primitives/std",
"binary-merkle-tree/std",
"bitvec/std",
"block-builder-api/std",
"frame-benchmarking?/std",
"frame-executive/std",
@@ -134,6 +138,7 @@ std = [
"frame-system-rpc-runtime-api/std",
"frame-system/std",
"frame-try-runtime/std",
"grandpa_primitives/std",
"inherents/std",
"log/std",
"offchain-primitives/std",
@@ -190,6 +195,7 @@ std = [
"scale-info/std",
"serde/std",
"serde_derive",
"serde_json/std",
"sp-api/std",
"sp-arithmetic/std",
"sp-core/std",
@@ -0,0 +1,544 @@
// Copyright (C) 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/>.
//! Genesis configs presets for the Rococo runtime
use crate::{SessionKeys, BABE_GENESIS_EPOCH_CONFIG};
use authority_discovery_primitives::AuthorityId as AuthorityDiscoveryId;
use babe_primitives::AuthorityId as BabeId;
use beefy_primitives::ecdsa_crypto::AuthorityId as BeefyId;
use grandpa_primitives::AuthorityId as GrandpaId;
use primitives::{vstaging::SchedulerParams, AccountId, AccountPublic, AssignmentId, ValidatorId};
use rococo_runtime_constants::currency::UNITS as ROC;
use sp_core::{sr25519, Pair, Public};
use sp_runtime::traits::IdentifyAccount;
#[cfg(not(feature = "std"))]
use sp_std::alloc::format;
use sp_std::vec::Vec;
/// Helper function to generate a crypto pair from seed
fn get_from_seed<TPublic: Public>(seed: &str) -> <TPublic::Pair as Pair>::Public {
TPublic::Pair::from_string(&format!("//{}", seed), None)
.expect("static values are valid; qed")
.public()
}
/// Helper function to generate an account ID from seed
fn get_account_id_from_seed<TPublic: Public>(seed: &str) -> AccountId
where
AccountPublic: From<<TPublic::Pair as Pair>::Public>,
{
AccountPublic::from(get_from_seed::<TPublic>(seed)).into_account()
}
/// Helper function to generate stash, controller and session key from seed
fn get_authority_keys_from_seed(
seed: &str,
) -> (
AccountId,
AccountId,
BabeId,
GrandpaId,
ValidatorId,
AssignmentId,
AuthorityDiscoveryId,
BeefyId,
) {
let keys = get_authority_keys_from_seed_no_beefy(seed);
(keys.0, keys.1, keys.2, keys.3, keys.4, keys.5, keys.6, get_from_seed::<BeefyId>(seed))
}
/// Helper function to generate stash, controller and session key from seed
fn get_authority_keys_from_seed_no_beefy(
seed: &str,
) -> (AccountId, AccountId, BabeId, GrandpaId, ValidatorId, AssignmentId, AuthorityDiscoveryId) {
(
get_account_id_from_seed::<sr25519::Public>(&format!("{}//stash", seed)),
get_account_id_from_seed::<sr25519::Public>(seed),
get_from_seed::<BabeId>(seed),
get_from_seed::<GrandpaId>(seed),
get_from_seed::<ValidatorId>(seed),
get_from_seed::<AssignmentId>(seed),
get_from_seed::<AuthorityDiscoveryId>(seed),
)
}
fn testnet_accounts() -> Vec<AccountId> {
Vec::from([
get_account_id_from_seed::<sr25519::Public>("Alice"),
get_account_id_from_seed::<sr25519::Public>("Bob"),
get_account_id_from_seed::<sr25519::Public>("Charlie"),
get_account_id_from_seed::<sr25519::Public>("Dave"),
get_account_id_from_seed::<sr25519::Public>("Eve"),
get_account_id_from_seed::<sr25519::Public>("Ferdie"),
get_account_id_from_seed::<sr25519::Public>("Alice//stash"),
get_account_id_from_seed::<sr25519::Public>("Bob//stash"),
get_account_id_from_seed::<sr25519::Public>("Charlie//stash"),
get_account_id_from_seed::<sr25519::Public>("Dave//stash"),
get_account_id_from_seed::<sr25519::Public>("Eve//stash"),
get_account_id_from_seed::<sr25519::Public>("Ferdie//stash"),
])
}
fn rococo_session_keys(
babe: BabeId,
grandpa: GrandpaId,
para_validator: ValidatorId,
para_assignment: AssignmentId,
authority_discovery: AuthorityDiscoveryId,
beefy: BeefyId,
) -> SessionKeys {
SessionKeys { babe, grandpa, para_validator, para_assignment, authority_discovery, beefy }
}
fn default_parachains_host_configuration(
) -> runtime_parachains::configuration::HostConfiguration<primitives::BlockNumber> {
use primitives::{
node_features::FeatureIndex, AsyncBackingParams, MAX_CODE_SIZE, MAX_POV_SIZE,
};
runtime_parachains::configuration::HostConfiguration {
validation_upgrade_cooldown: 2u32,
validation_upgrade_delay: 2,
code_retention_period: 1200,
max_code_size: MAX_CODE_SIZE,
max_pov_size: MAX_POV_SIZE,
max_head_data_size: 32 * 1024,
max_upward_queue_count: 8,
max_upward_queue_size: 1024 * 1024,
max_downward_message_size: 1024 * 1024,
max_upward_message_size: 50 * 1024,
max_upward_message_num_per_candidate: 5,
hrmp_sender_deposit: 0,
hrmp_recipient_deposit: 0,
hrmp_channel_max_capacity: 8,
hrmp_channel_max_total_size: 8 * 1024,
hrmp_max_parachain_inbound_channels: 4,
hrmp_channel_max_message_size: 1024 * 1024,
hrmp_max_parachain_outbound_channels: 4,
hrmp_max_message_num_per_candidate: 5,
dispute_period: 6,
no_show_slots: 2,
n_delay_tranches: 25,
needed_approvals: 2,
relay_vrf_modulo_samples: 2,
zeroth_delay_tranche_width: 0,
minimum_validation_upgrade_delay: 5,
async_backing_params: AsyncBackingParams {
max_candidate_depth: 3,
allowed_ancestry_len: 2,
},
node_features: bitvec::vec::BitVec::from_element(
1u8 << (FeatureIndex::ElasticScalingMVP as usize),
),
scheduler_params: SchedulerParams {
lookahead: 2,
group_rotation_frequency: 20,
paras_availability_period: 4,
..Default::default()
},
..Default::default()
}
}
#[test]
fn default_parachains_host_configuration_is_consistent() {
default_parachains_host_configuration().panic_if_not_consistent();
}
fn rococo_testnet_genesis(
initial_authorities: Vec<(
AccountId,
AccountId,
BabeId,
GrandpaId,
ValidatorId,
AssignmentId,
AuthorityDiscoveryId,
BeefyId,
)>,
root_key: AccountId,
endowed_accounts: Option<Vec<AccountId>>,
) -> serde_json::Value {
let endowed_accounts: Vec<AccountId> = endowed_accounts.unwrap_or_else(testnet_accounts);
const ENDOWMENT: u128 = 1_000_000 * ROC;
serde_json::json!({
"balances": {
"balances": endowed_accounts.iter().map(|k| (k.clone(), ENDOWMENT)).collect::<Vec<_>>(),
},
"session": {
"keys": initial_authorities
.iter()
.map(|x| {
(
x.0.clone(),
x.0.clone(),
rococo_session_keys(
x.2.clone(),
x.3.clone(),
x.4.clone(),
x.5.clone(),
x.6.clone(),
x.7.clone(),
),
)
})
.collect::<Vec<_>>(),
},
"babe": {
"epochConfig": Some(BABE_GENESIS_EPOCH_CONFIG),
},
"sudo": { "key": Some(root_key.clone()) },
"configuration": {
"config": runtime_parachains::configuration::HostConfiguration {
scheduler_params: SchedulerParams {
max_validators_per_core: Some(1),
..default_parachains_host_configuration().scheduler_params
},
..default_parachains_host_configuration()
},
},
"registrar": {
"nextFreeParaId": primitives::LOWEST_PUBLIC_ID,
}
})
}
// staging_testnet
fn rococo_staging_testnet_config_genesis() -> serde_json::Value {
use hex_literal::hex;
use sp_core::crypto::UncheckedInto;
// subkey inspect "$SECRET"
let endowed_accounts = Vec::from([
// 5DwBmEFPXRESyEam5SsQF1zbWSCn2kCjyLW51hJHXe9vW4xs
hex!["52bc71c1eca5353749542dfdf0af97bf764f9c2f44e860cd485f1cd86400f649"].into(),
]);
// ./scripts/prepare-test-net.sh 8
let initial_authorities: Vec<(
AccountId,
AccountId,
BabeId,
GrandpaId,
ValidatorId,
AssignmentId,
AuthorityDiscoveryId,
BeefyId,
)> = Vec::from([
(
//5EHZkbp22djdbuMFH9qt1DVzSCvqi3zWpj6DAYfANa828oei
hex!["62475fe5406a7cb6a64c51d0af9d3ab5c2151bcae982fb812f7a76b706914d6a"].into(),
//5FeSEpi9UYYaWwXXb3tV88qtZkmSdB3mvgj3pXkxKyYLGhcd
hex!["9e6e781a76810fe93187af44c79272c290c2b9e2b8b92ee11466cd79d8023f50"].into(),
//5Fh6rDpMDhM363o1Z3Y9twtaCPfizGQWCi55BSykTQjGbP7H
hex!["a076ef1280d768051f21d060623da3ab5b56944d681d303ed2d4bf658c5bed35"]
.unchecked_into(),
//5CPd3zoV9Aaah4xWucuDivMHJ2nEEmpdi864nPTiyRZp4t87
hex!["0e6d7d1afbcc6547b92995a394ba0daed07a2420be08220a5a1336c6731f0bfa"]
.unchecked_into(),
//5CP6oGfwqbEfML8efqm1tCZsUgRsJztp9L8ZkEUxA16W8PPz
hex!["0e07a51d3213842f8e9363ce8e444255990a225f87e80a3d651db7841e1a0205"]
.unchecked_into(),
//5HQdwiDh8Qtd5dSNWajNYpwDvoyNWWA16Y43aEkCNactFc2b
hex!["ec60e71fe4a567ef9fef99d4bbf37ffae70564b41aa6f94ef0317c13e0a5477b"]
.unchecked_into(),
//5HbSgM72xVuscsopsdeG3sCSCYdAeM1Tay9p79N6ky6vwDGq
hex!["f49eae66a0ac9f610316906ec8f1a0928e20d7059d76a5ca53cbcb5a9b50dd3c"]
.unchecked_into(),
//5DPSWdgw38Spu315r6LSvYCggeeieBAJtP5A1qzuzKhqmjVu
hex!["034f68c5661a41930c82f26a662276bf89f33467e1c850f2fb8ef687fe43d62276"]
.unchecked_into(),
),
(
//5DvH8oEjQPYhzCoQVo7WDU91qmQfLZvxe9wJcrojmJKebCmG
hex!["520b48452969f6ddf263b664de0adb0c729d0e0ad3b0e5f3cb636c541bc9022a"].into(),
//5ENZvCRzyXJJYup8bM6yEzb2kQHEb1NDpY2ZEyVGBkCfRdj3
hex!["6618289af7ae8621981ffab34591e7a6486e12745dfa3fd3b0f7e6a3994c7b5b"].into(),
//5DLjSUfqZVNAADbwYLgRvHvdzXypiV1DAEaDMjcESKTcqMoM
hex!["38757d0de00a0c739e7d7984ef4bc01161bd61e198b7c01b618425c16bb5bd5f"]
.unchecked_into(),
//5HnDVBN9mD6mXyx8oryhDbJtezwNSj1VRXgLoYCBA6uEkiao
hex!["fcd5f87a6fd5707a25122a01b4dac0a8482259df7d42a9a096606df1320df08d"]
.unchecked_into(),
//5EPEWRecy2ApL5n18n3aHyU1956zXTRqaJpzDa9DoqiggNwF
hex!["669a10892119453e9feb4e3f1ee8e028916cc3240022920ad643846fbdbee816"]
.unchecked_into(),
//5ES3fw5X4bndSgLNmtPfSbM2J1kLqApVB2CCLS4CBpM1UxUZ
hex!["68bf52c482630a8d1511f2edd14f34127a7d7082219cccf7fd4c6ecdb535f80d"]
.unchecked_into(),
//5HeXbwb5PxtcRoopPZTp5CQun38atn2UudQ8p2AxR5BzoaXw
hex!["f6f8fe475130d21165446a02fb1dbce3a7bf36412e5d98f4f0473aed9252f349"]
.unchecked_into(),
//5F7nTtN8MyJV4UsXpjg7tHSnfANXZ5KRPJmkASc1ZSH2Xoa5
hex!["03a90c2bb6d3b7000020f6152fe2e5002fa970fd1f42aafb6c8edda8dacc2ea77e"]
.unchecked_into(),
),
(
//5FPMzsezo1PRxYbVpJMWK7HNbR2kUxidsAAxH4BosHa4wd6S
hex!["92ef83665b39d7a565e11bf8d18d41d45a8011601c339e57a8ea88c8ff7bba6f"].into(),
//5G6NQidFG7YiXsvV7hQTLGArir9tsYqD4JDxByhgxKvSKwRx
hex!["b235f57244230589523271c27b8a490922ffd7dccc83b044feaf22273c1dc735"].into(),
//5GpZhzAVg7SAtzLvaAC777pjquPEcNy1FbNUAG2nZvhmd6eY
hex!["d2644c1ab2c63a3ad8d40ad70d4b260969e3abfe6d7e6665f50dc9f6365c9d2a"]
.unchecked_into(),
//5HAes2RQYPbYKbLBfKb88f4zoXv6pPA6Ke8CjN7dob3GpmSP
hex!["e1b68fbd84333e31486c08e6153d9a1415b2e7e71b413702b7d64e9b631184a1"]
.unchecked_into(),
//5FtAGDZYJKXkhVhAxCQrXmaP7EE2mGbBMfmKDHjfYDgq2BiU
hex!["a8e61ffacafaf546283dc92d14d7cc70ea0151a5dd81fdf73ff5a2951f2b6037"]
.unchecked_into(),
//5CtK7JHv3h6UQZ44y54skxdwSVBRtuxwPE1FYm7UZVhg8rJV
hex!["244f3421b310c68646e99cdbf4963e02067601f57756b072a4b19431448c186e"]
.unchecked_into(),
//5D4r6YaB6F7A7nvMRHNFNF6zrR9g39bqDJFenrcaFmTCRwfa
hex!["2c57f81fd311c1ab53813c6817fe67f8947f8d39258252663b3384ab4195494d"]
.unchecked_into(),
//5EPoHj8uV4fFKQHYThc6Z9fDkU7B6ih2ncVzQuDdNFb8UyhF
hex!["039d065fe4f9234f0a4f13cc3ae585f2691e9c25afa469618abb6645111f607a53"]
.unchecked_into(),
),
(
//5DMNx7RoX6d7JQ38NEM7DWRcW2THu92LBYZEWvBRhJeqcWgR
hex!["38f3c2f38f6d47f161e98c697bbe3ca0e47c033460afda0dda314ab4222a0404"].into(),
//5GGdKNDr9P47dpVnmtq3m8Tvowwf1ot1abw6tPsTYYFoKm2v
hex!["ba0898c1964196474c0be08d364cdf4e9e1d47088287f5235f70b0590dfe1704"].into(),
//5EjkyPCzR2SjhDZq8f7ufsw6TfkvgNRepjCRQFc4TcdXdaB1
hex!["764186bc30fd5a02477f19948dc723d6d57ab174debd4f80ed6038ec960bfe21"]
.unchecked_into(),
//5DJV3zCBTJBLGNDCcdWrYxWDacSz84goGTa4pFeKVvehEBte
hex!["36be9069cdb4a8a07ecd51f257875150f0a8a1be44a10d9d98dabf10a030aef4"]
.unchecked_into(),
//5F9FsRjpecP9GonktmtFL3kjqNAMKjHVFjyjRdTPa4hbQRZA
hex!["882d72965e642677583b333b2d173ac94b5fd6c405c76184bb14293be748a13b"]
.unchecked_into(),
//5F1FZWZSj3JyTLs8sRBxU6QWyGLSL9BMRtmSKDmVEoiKFxSP
hex!["821271c99c958b9220f1771d9f5e29af969edfa865631dba31e1ab7bc0582b75"]
.unchecked_into(),
//5CtgRR74VypK4h154s369abs78hDUxZSJqcbWsfXvsjcHJNA
hex!["2496f28d887d84705c6dae98aee8bf90fc5ad10bb5545eca1de6b68425b70f7c"]
.unchecked_into(),
//5CPx6dsr11SCJHKFkcAQ9jpparS7FwXQBrrMznRo4Hqv1PXz
hex!["0307d29bbf6a5c4061c2157b44fda33b7bb4ec52a5a0305668c74688cedf288d58"]
.unchecked_into(),
),
(
//5C8AL1Zb4bVazgT3EgDxFgcow1L4SJjVu44XcLC9CrYqFN4N
hex!["02a2d8cfcf75dda85fafc04ace3bcb73160034ed1964c43098fb1fe831de1b16"].into(),
//5FLYy3YKsAnooqE4hCudttAsoGKbVG3hYYBtVzwMjJQrevPa
hex!["90cab33f0bb501727faa8319f0845faef7d31008f178b65054b6629fe531b772"].into(),
//5Et3tfbVf1ByFThNAuUq5pBssdaPPskip5yob5GNyUFojXC7
hex!["7c94715e5dd8ab54221b1b6b2bfa5666f593f28a92a18e28052531de1bd80813"]
.unchecked_into(),
//5EX1JBghGbQqWohTPU6msR9qZ2nYPhK9r3RTQ2oD1K8TCxaG
hex!["6c878e33b83c20324238d22240f735457b6fba544b383e70bb62a27b57380c81"]
.unchecked_into(),
//5EUNaBpX9mJgcmLQHyG5Pkms6tbDiKuLbeTEJS924Js9cA1N
hex!["6a8570b9c6408e54bacf123cc2bb1b0f087f9c149147d0005badba63a5a4ac01"]
.unchecked_into(),
//5CaZuueRVpMATZG4hkcrgDoF4WGixuz7zu83jeBdY3bgWGaG
hex!["16c69ea8d595e80b6736f44be1eaeeef2ac9c04a803cc4fd944364cb0d617a33"]
.unchecked_into(),
//5DABsdQCDUGuhzVGWe5xXzYQ9rtrVxRygW7RXf9Tsjsw1aGJ
hex!["306ac5c772fe858942f92b6e28bd82fb7dd8cdd25f9a4626c1b0eee075fcb531"]
.unchecked_into(),
//5H91T5mHhoCw9JJG4NjghDdQyhC6L7XcSuBWKD3q3TAhEVvQ
hex!["02fb0330356e63a35dd930bc74525edf28b3bf5eb44aab9e9e4962c8309aaba6a6"]
.unchecked_into(),
),
(
//5C8XbDXdMNKJrZSrQURwVCxdNdk8AzG6xgLggbzuA399bBBF
hex!["02ea6bfa8b23b92fe4b5db1063a1f9475e3acd0ab61e6b4f454ed6ba00b5f864"].into(),
//5GsyzFP8qtF8tXPSsjhjxAeU1v7D1PZofuQKN9TdCc7Dp1JM
hex!["d4ffc4c05b47d1115ad200f7f86e307b20b46c50e1b72a912ec4f6f7db46b616"].into(),
//5GHWB8ZDzegLcMW7Gdd1BS6WHVwDdStfkkE4G7KjPjZNJBtD
hex!["bab3cccdcc34401e9b3971b96a662686cf755aa869a5c4b762199ce531b12c5b"]
.unchecked_into(),
//5GzDPGbUM9uH52ZEwydasTj8edokGUJ7vEpoFWp9FE1YNuFB
hex!["d9c056c98ca0e6b4eb7f5c58c007c1db7be0fe1f3776108f797dd4990d1ccc33"]
.unchecked_into(),
//5CmLCFeSurRXXtwMmLcVo7sdJ9EqDguvJbuCYDcHkr3cpqyE
hex!["1efc23c0b51ad609ab670ecf45807e31acbd8e7e5cb7c07cf49ee42992d2867c"]
.unchecked_into(),
//5DnsSy8a8pfE2aFjKBDtKw7WM1V4nfE5sLzP15MNTka53GqS
hex!["4c64d3f06d28adeb36a892fdaccecace150bec891f04694448a60b74fa469c22"]
.unchecked_into(),
//5CZdFnyzZvKetZTeUwj5APAYskVJe4QFiTezo5dQNsrnehGd
hex!["160ea09c5717270e958a3da42673fa011613a9539b2e4ebcad8626bc117ca04a"]
.unchecked_into(),
//5HgoR9JJkdBusxKrrs3zgd3ToppgNoGj1rDyAJp4e7eZiYyT
hex!["020019a8bb188f8145d02fa855e9c36e9914457d37c500e03634b5223aa5702474"]
.unchecked_into(),
),
(
//5HinEonzr8MywkqedcpsmwpxKje2jqr9miEwuzyFXEBCvVXM
hex!["fa373e25a1c4fe19c7148acde13bc3db1811cf656dc086820f3dda736b9c4a00"].into(),
//5EHJbj6Td6ks5HDnyfN4ttTSi57osxcQsQexm7XpazdeqtV7
hex!["62145d721967bd88622d08625f0f5681463c0f1b8bcd97eb3c2c53f7660fd513"].into(),
//5EeCsC58XgJ1DFaoYA1WktEpP27jvwGpKdxPMFjicpLeYu96
hex!["720537e2c1c554654d73b3889c3ef4c3c2f95a65dd3f7c185ebe4afebed78372"]
.unchecked_into(),
//5DnEySxbnppWEyN8cCLqvGjAorGdLRg2VmkY96dbJ1LHFK8N
hex!["4bea0b37e0cce9bddd80835fa2bfd5606f5dcfb8388bbb10b10c483f0856cf14"]
.unchecked_into(),
//5CAC278tFCHAeHYqE51FTWYxHmeLcENSS1RG77EFRTvPZMJT
hex!["042f07fc5268f13c026bbe199d63e6ac77a0c2a780f71cda05cee5a6f1b3f11f"]
.unchecked_into(),
//5HjRTLWcQjZzN3JDvaj1UzjNSayg5ZD9ZGWMstaL7Ab2jjAa
hex!["fab485e87ed1537d089df521edf983a777c57065a702d7ed2b6a2926f31da74f"]
.unchecked_into(),
//5ELv74v7QcsS6FdzvG4vL2NnYDGWmRnJUSMKYwdyJD7Xcdi7
hex!["64d59feddb3d00316a55906953fb3db8985797472bd2e6c7ea1ab730cc339d7f"]
.unchecked_into(),
//5FaUcPt4fPz93vBhcrCJqmDkjYZ7jCbzAF56QJoCmvPaKrmx
hex!["033f1a6d47fe86f88934e4b83b9fae903b92b5dcf4fec97d5e3e8bf4f39df03685"]
.unchecked_into(),
),
(
//5Ey3NQ3dfabaDc16NUv7wRLsFCMDFJSqZFzKVycAsWuUC6Di
hex!["8062e9c21f1d92926103119f7e8153cebdb1e5ab3e52d6f395be80bb193eab47"].into(),
//5HiWsuSBqt8nS9pnggexXuHageUifVPKPHDE2arTKqhTp1dV
hex!["fa0388fa88f3f0cb43d583e2571fbc0edad57dff3a6fd89775451dd2c2b8ea00"].into(),
//5H168nKX2Yrfo3bxj7rkcg25326Uv3CCCnKUGK6uHdKMdPt8
hex!["da6b2df18f0f9001a6dcf1d301b92534fe9b1f3ccfa10c49449fee93adaa8349"]
.unchecked_into(),
//5DrA2fZdzmNqT5j6DXNwVxPBjDV9jhkAqvjt6Us3bQHKy3cF
hex!["4ee66173993dd0db5d628c4c9cb61a27b76611ad3c3925947f0d0011ee2c5dcc"]
.unchecked_into(),
//5Gx6YeNhynqn8qkda9QKpc9S7oDr4sBrfAu516d3sPpEt26F
hex!["d822d4088b20dca29a580a577a97d6f024bb24c9550bebdfd7d2d18e946a1c7d"]
.unchecked_into(),
//5DhDcHqwxoes5s89AyudGMjtZXx1nEgrk5P45X88oSTR3iyx
hex!["481538f8c2c011a76d7d57db11c2789a5e83b0f9680dc6d26211d2f9c021ae4c"]
.unchecked_into(),
//5DqAvikdpfRdk5rR35ZobZhqaC5bJXZcEuvzGtexAZP1hU3T
hex!["4e262811acdfe94528bfc3c65036080426a0e1301b9ada8d687a70ffcae99c26"]
.unchecked_into(),
//5E41Znrr2YtZu8bZp3nvRuLVHg3jFksfQ3tXuviLku4wsao7
hex!["025e84e95ed043e387ddb8668176b42f8e2773ddd84f7f58a6d9bf436a4b527986"]
.unchecked_into(),
),
]);
const ENDOWMENT: u128 = 1_000_000 * ROC;
const STASH: u128 = 100 * ROC;
serde_json::json!({
"balances": {
"balances": endowed_accounts
.iter()
.map(|k: &AccountId| (k.clone(), ENDOWMENT))
.chain(initial_authorities.iter().map(|x| (x.0.clone(), STASH)))
.collect::<Vec<_>>(),
},
"session": {
"keys": initial_authorities
.into_iter()
.map(|x| {
(
x.0.clone(),
x.0,
rococo_session_keys(
x.2,
x.3,
x.4,
x.5,
x.6,
x.7,
),
)
})
.collect::<Vec<_>>(),
},
"babe": {
"epochConfig": Some(BABE_GENESIS_EPOCH_CONFIG),
},
"sudo": { "key": Some(endowed_accounts[0].clone()) },
"configuration": {
"config": default_parachains_host_configuration(),
},
"registrar": {
"nextFreeParaId": primitives::LOWEST_PUBLIC_ID,
},
})
}
//development
fn rococo_development_config_genesis() -> serde_json::Value {
rococo_testnet_genesis(
Vec::from([get_authority_keys_from_seed("Alice")]),
get_account_id_from_seed::<sr25519::Public>("Alice"),
None,
)
}
//local_testnet
fn rococo_local_testnet_genesis() -> serde_json::Value {
rococo_testnet_genesis(
Vec::from([get_authority_keys_from_seed("Alice"), get_authority_keys_from_seed("Bob")]),
get_account_id_from_seed::<sr25519::Public>("Alice"),
None,
)
}
/// `Versi` is a temporary testnet that uses the same runtime as rococo.
// versi_local_testnet
fn versi_local_testnet_genesis() -> serde_json::Value {
rococo_testnet_genesis(
Vec::from([
get_authority_keys_from_seed("Alice"),
get_authority_keys_from_seed("Bob"),
get_authority_keys_from_seed("Charlie"),
get_authority_keys_from_seed("Dave"),
]),
get_account_id_from_seed::<sr25519::Public>("Alice"),
None,
)
}
/// Wococo is a temporary testnet that uses almost the same runtime as rococo.
//wococo_local_testnet
fn wococo_local_testnet_genesis() -> serde_json::Value {
rococo_testnet_genesis(
Vec::from([
get_authority_keys_from_seed("Alice"),
get_authority_keys_from_seed("Bob"),
get_authority_keys_from_seed("Charlie"),
get_authority_keys_from_seed("Dave"),
]),
get_account_id_from_seed::<sr25519::Public>("Alice"),
None,
)
}
/// Provides the JSON representation of predefined genesis config for given `id`.
pub fn get_preset(id: &sp_genesis_builder::PresetId) -> Option<sp_std::vec::Vec<u8>> {
let patch = match id.try_into() {
Ok("local_testnet") => rococo_local_testnet_genesis(),
Ok("development") => rococo_development_config_genesis(),
Ok("staging_testnet") => rococo_staging_testnet_config_genesis(),
Ok("wococo_local_testnet") => wococo_local_testnet_genesis(),
Ok("versi_local_testnet") => versi_local_testnet_genesis(),
_ => return None,
};
Some(
serde_json::to_string(&patch)
.expect("serialization to json is expected to work. qed.")
.into_bytes(),
)
}
+24 -14
View File
@@ -20,6 +20,11 @@
// `construct_runtime!` does a lot of recursion and requires us to increase the limit.
#![recursion_limit = "512"]
use authority_discovery_primitives::AuthorityId as AuthorityDiscoveryId;
use beefy_primitives::{
ecdsa_crypto::{AuthorityId as BeefyId, Signature as BeefySignature},
mmr::{BeefyDataProvider, MmrLeafVersion},
};
use pallet_nis::WithMaximumOf;
use parity_scale_codec::{Decode, Encode, MaxEncodedLen};
use primitives::{
@@ -40,9 +45,6 @@ use runtime_common::{
traits::{Leaser, OnSwap},
BlockHashCount, BlockLength, SlowAdjustingFeeUpdate,
};
use scale_info::TypeInfo;
use sp_std::{cmp::Ordering, collections::btree_map::BTreeMap, prelude::*};
use runtime_parachains::{
assigner_coretime as parachains_assigner_coretime,
assigner_on_demand as parachains_assigner_on_demand, configuration as parachains_configuration,
@@ -56,16 +58,13 @@ use runtime_parachains::{
scheduler as parachains_scheduler, session_info as parachains_session_info,
shared as parachains_shared,
};
use authority_discovery_primitives::AuthorityId as AuthorityDiscoveryId;
use beefy_primitives::{
ecdsa_crypto::{AuthorityId as BeefyId, Signature as BeefySignature},
mmr::{BeefyDataProvider, MmrLeafVersion},
};
use scale_info::TypeInfo;
use sp_genesis_builder::PresetId;
use sp_std::{cmp::Ordering, collections::btree_map::BTreeMap, prelude::*};
use frame_support::{
construct_runtime, derive_impl,
genesis_builder_helper::{build_config, create_default_config},
genesis_builder_helper::{build_state, get_preset},
parameter_types,
traits::{
fungible::HoldConsideration, Contains, EitherOf, EitherOfDiverse, EverythingBut,
@@ -127,6 +126,7 @@ use xcm_fee_payment_runtime_api::Error as XcmPaymentApiError;
#[cfg(test)]
mod tests;
mod genesis_config_presets;
mod validator_manager;
impl_runtime_weights!(rococo_runtime_constants);
@@ -2363,12 +2363,22 @@ sp_api::impl_runtime_apis! {
}
impl sp_genesis_builder::GenesisBuilder<Block> for Runtime {
fn create_default_config() -> Vec<u8> {
create_default_config::<RuntimeGenesisConfig>()
fn build_state(config: Vec<u8>) -> sp_genesis_builder::Result {
build_state::<RuntimeGenesisConfig>(config)
}
fn build_config(config: Vec<u8>) -> sp_genesis_builder::Result {
build_config::<RuntimeGenesisConfig>(config)
fn get_preset(id: &Option<PresetId>) -> Option<Vec<u8>> {
get_preset::<RuntimeGenesisConfig>(id, &genesis_config_presets::get_preset)
}
fn preset_names() -> Vec<PresetId> {
vec![
PresetId::from("local_testnet"),
PresetId::from("development"),
PresetId::from("staging_testnet"),
PresetId::from("wococo_local_testnet"),
PresetId::from("versi_local_testnet"),
]
}
}
}
+9 -5
View File
@@ -43,7 +43,7 @@ use frame_election_provider_support::{
};
use frame_support::{
construct_runtime, derive_impl,
genesis_builder_helper::{build_config, create_default_config},
genesis_builder_helper::{build_state, get_preset},
parameter_types,
traits::{KeyOwnerProofSystem, WithdrawReasons},
};
@@ -1171,12 +1171,16 @@ sp_api::impl_runtime_apis! {
}
impl sp_genesis_builder::GenesisBuilder<Block> for Runtime {
fn create_default_config() -> Vec<u8> {
create_default_config::<RuntimeGenesisConfig>()
fn build_state(config: Vec<u8>) -> sp_genesis_builder::Result {
build_state::<RuntimeGenesisConfig>(config)
}
fn build_config(config: Vec<u8>) -> sp_genesis_builder::Result {
build_config::<RuntimeGenesisConfig>(config)
fn get_preset(id: &Option<sp_genesis_builder::PresetId>) -> Option<Vec<u8>> {
get_preset::<RuntimeGenesisConfig>(id, |_| None)
}
fn preset_names() -> Vec<sp_genesis_builder::PresetId> {
vec![]
}
}
}
+9 -5
View File
@@ -28,7 +28,7 @@ use beefy_primitives::{
use frame_election_provider_support::{bounds::ElectionBoundsBuilder, onchain, SequentialPhragmen};
use frame_support::{
derive_impl,
genesis_builder_helper::{build_config, create_default_config},
genesis_builder_helper::{build_state, get_preset},
parameter_types,
traits::{
fungible::HoldConsideration, ConstU32, Contains, EitherOf, EitherOfDiverse, EverythingBut,
@@ -2515,12 +2515,16 @@ sp_api::impl_runtime_apis! {
}
impl sp_genesis_builder::GenesisBuilder<Block> for Runtime {
fn create_default_config() -> Vec<u8> {
create_default_config::<RuntimeGenesisConfig>()
fn build_state(config: Vec<u8>) -> sp_genesis_builder::Result {
build_state::<RuntimeGenesisConfig>(config)
}
fn build_config(config: Vec<u8>) -> sp_genesis_builder::Result {
build_config::<RuntimeGenesisConfig>(config)
fn get_preset(id: &Option<sp_genesis_builder::PresetId>) -> Option<Vec<u8>> {
get_preset::<RuntimeGenesisConfig>(id, |_| None)
}
fn preset_names() -> Vec<sp_genesis_builder::PresetId> {
vec![]
}
}
}
+23
View File
@@ -0,0 +1,23 @@
title: GenesisConfig presets for runtime
doc:
- audience: Runtime Dev
description: |
The runtime now can provide a number of predefined presets of `RuntimeGenesisConfig` struct. This presets are intended to be used in different deployments, e.g.: `local`, `staging`, etc, and should be included into the corresponding chain-specs.
Having `GenesisConfig` presets in runtime allows to fully decouple node from runtime types (the problem is described in #1984).
Summary of changes:
- The `GenesisBuilder` API was adjusted to enable this functionality,
- (Breaking change) Old `create_default_config` method was removed, `build_config` was renamed to `build_state`. As a consequence a node won't be able to interact with genesis config for older runtimes. The cleanup was made for sake of API simplicity.
- audience: Node Dev
description: |
The `ChainSpecBuilder` is extended with `with_genesis_config_preset_name` method which allows to build chain-spec using named preset provided by the runtime.
crates:
- name: sp-genesis-builder
bump: minor
- name: staging-chain-spec-builder
bump: major
- name: sc-chain-spec
bump: major
+1
View File
@@ -58,6 +58,7 @@ sp-api = { path = "../../../primitives/api" }
sp-core = { path = "../../../primitives/core" }
sp-runtime = { path = "../../../primitives/runtime" }
sp-timestamp = { path = "../../../primitives/timestamp" }
sp-genesis-builder = { path = "../../../primitives/genesis-builder" }
sp-inherents = { path = "../../../primitives/inherents" }
sp-keyring = { path = "../../../primitives/keyring" }
sp-keystore = { path = "../../../primitives/keystore" }
+10 -4
View File
@@ -838,10 +838,16 @@ fn should_import_block_with_test_client() {
#[test]
fn default_config_as_json_works() {
let mut t = new_test_ext(compact_code_unwrap());
let r = executor_call(&mut t, "GenesisBuilder_create_default_config", &vec![])
.0
.unwrap();
let r = Vec::<u8>::decode(&mut &r[..]).unwrap();
let r = executor_call(
&mut t,
"GenesisBuilder_get_preset",
&None::<&sp_genesis_builder::PresetId>.encode(),
)
.0
.unwrap();
let r = Option::<Vec<u8>>::decode(&mut &r[..])
.unwrap()
.expect("default config is there");
let json = String::from_utf8(r.into()).expect("returned value is json. qed.");
let expected = include_str!("res/default_genesis_config.json").to_string();
+9 -5
View File
@@ -31,7 +31,7 @@ use frame_support::{
derive_impl,
dispatch::DispatchClass,
dynamic_params::{dynamic_pallet_params, dynamic_params},
genesis_builder_helper::{build_config, create_default_config},
genesis_builder_helper::{build_state, get_preset},
instances::{Instance1, Instance2},
ord_parameter_types,
pallet_prelude::Get,
@@ -3194,12 +3194,16 @@ impl_runtime_apis! {
}
impl sp_genesis_builder::GenesisBuilder<Block> for Runtime {
fn create_default_config() -> Vec<u8> {
create_default_config::<RuntimeGenesisConfig>()
fn build_state(config: Vec<u8>) -> sp_genesis_builder::Result {
build_state::<RuntimeGenesisConfig>(config)
}
fn build_config(config: Vec<u8>) -> sp_genesis_builder::Result {
build_config::<RuntimeGenesisConfig>(config)
fn get_preset(id: &Option<sp_genesis_builder::PresetId>) -> Option<Vec<u8>> {
get_preset::<RuntimeGenesisConfig>(id, |_| None)
}
fn preset_names() -> Vec<sp_genesis_builder::PresetId> {
vec![]
}
}
}
@@ -1,6 +1,6 @@
[package]
name = "staging-chain-spec-builder"
version = "2.0.0"
version = "3.0.0"
authors.workspace = true
edition.workspace = true
build = "build.rs"
@@ -18,14 +18,24 @@
use chain_spec_builder::{
generate_chain_spec_for_runtime, ChainSpecBuilder, ChainSpecBuilderCmd, ConvertToRawCmd,
UpdateCodeCmd, VerifyCmd,
DisplayPresetCmd, ListPresetsCmd, UpdateCodeCmd, VerifyCmd,
};
use clap::Parser;
use sc_chain_spec::{update_code_in_json_chain_spec, GenericChainSpec};
use sc_chain_spec::{
update_code_in_json_chain_spec, GenericChainSpec, GenesisConfigBuilderRuntimeCaller,
};
use staging_chain_spec_builder as chain_spec_builder;
use std::fs;
fn main() -> Result<(), String> {
//avoid error message escaping
fn main() {
match inner_main() {
Err(e) => eprintln!("{}", format!("{e}")),
_ => {},
}
}
fn inner_main() -> Result<(), String> {
sp_tracing::try_init_simple();
let builder = ChainSpecBuilder::parse();
@@ -71,6 +81,36 @@ fn main() -> Result<(), String> {
let _ = serde_json::from_str::<serde_json::Value>(&chain_spec.as_json(true)?)
.map_err(|e| format!("Conversion to json failed: {e}"))?;
},
ChainSpecBuilderCmd::ListPresets(ListPresetsCmd { runtime_wasm_path }) => {
let code = fs::read(runtime_wasm_path.as_path())
.map_err(|e| format!("wasm blob shall be readable {e}"))?;
let caller: GenesisConfigBuilderRuntimeCaller =
GenesisConfigBuilderRuntimeCaller::new(&code[..]);
let presets = caller
.preset_names()
.map_err(|e| format!("getting default config from runtime should work: {e}"))?;
let presets: Vec<String> = presets
.into_iter()
.map(|preset| {
String::from(
TryInto::<&str>::try_into(&preset)
.unwrap_or_else(|_| "cannot display preset id")
.to_string(),
)
})
.collect();
println!("{presets:#?}");
},
ChainSpecBuilderCmd::DisplayPreset(DisplayPresetCmd { runtime_wasm_path, preset_name }) => {
let code = fs::read(runtime_wasm_path.as_path())
.map_err(|e| format!("wasm blob shall be readable {e}"))?;
let caller: GenesisConfigBuilderRuntimeCaller =
GenesisConfigBuilderRuntimeCaller::new(&code[..]);
let preset = caller
.get_named_preset(preset_name.as_ref())
.map_err(|e| format!("getting default config from runtime should work: {e}"))?;
println!("{preset}");
},
};
Ok(())
}
@@ -28,51 +28,84 @@
//! See [`ChainSpecBuilderCmd`] for a list of available commands.
//!
//! ## Typical use-cases.
//! ##### Get default config from runtime.
//! ##### Generate chains-spec using default config from runtime.
//!
//! Query the default genesis config from the provided `runtime.wasm` and use it in the chain
//! spec. The tool allows specifying where to write the chain spec, and optionally also where the
//! write the default genesis state config (which is `/dev/stdout` in the following example):
//! ```text
//! chain-spec-builder --chain_spec_path ./my_chain_spec.json create -r runtime.wasm default /dev/stdout
//! Query the default genesis config from the provided `runtime.wasm` and use it in the chain
//! spec.
//! ```bash
//! chain-spec-builder create -r runtime.wasm default
//! ```
//!
//! _Note:_ [`GenesisBuilder::create_default_config`][sp-genesis-builder-create] runtime function is
//!
//! _Note:_ [`GenesisBuilder::get_preset`][sp-genesis-builder-get-preset] runtime function is
//! called.
//!
//!
//! ##### Display the runtime's default `GenesisConfig`
//!
//! Displays the content of the runtime's default `GenesisConfig`
//! ```bash
//! chain-spec-builder display-preset -r runtime.wasm
//! ```
//!
//! _Note:_ [`GenesisBuilder::get_preset`][sp-genesis-builder-get-preset] runtime function is called.
//!
//! ##### Display the `GenesisConfig` preset with given name
//!
//! Displays the content of the `GenesisConfig` preset for given name
//! ```bash
//! chain-spec-builder display-preset -r runtime.wasm -p "staging"
//! ```
//!
//! _Note:_ [`GenesisBuilder::get_preset`][sp-genesis-builder-get-preset] runtime function is called.
//!
//! ##### List the names of `GenesisConfig` presets provided by runtime.
//!
//! Displays the names of the presets of `GenesisConfigs` provided by runtime.
//! ```bash
//! chain-spec-builder list-presets -r runtime.wasm
//! ```
//!
//! _Note:_ [`GenesisBuilder::preset_names`][sp-genesis-builder-list] runtime function is called.
//!
//! ##### Generate chain spec using runtime provided genesis config preset.
//!
//! Patch the runtime's default genesis config with the named preset provided by the runtime and generate the plain
//! version of chain spec:
//! ```bash
//! chain-spec-builder create -r runtime.wasm named-preset "staging"
//! ```
//!
//! _Note:_ [`GenesisBuilder::get_preset`][sp-genesis-builder-get-preset] and [`GenesisBuilder::build_state`][sp-genesis-builder-build] runtime functions are called.
//!
//! ##### Generate raw storage chain spec using genesis config patch.
//!
//! Patch the runtime's default genesis config with provided `patch.json` and generate raw
//! storage (`-s`) version of chain spec:
//!
//! ```bash
//! chain-spec-builder create -s -r runtime.wasm patch patch.json
//! ```
//!
//! _Note:_ [`GenesisBuilder::build_config`][sp-genesis-builder-build] runtime function is called.
//!
//! _Note:_ [`GenesisBuilder::build_state`][sp-genesis-builder-build] runtime function is called.
//!
//! ##### Generate raw storage chain spec using full genesis config.
//!
//! Build the chain spec using provided full genesis config json file. No defaults will be used:
//!
//! ```bash
//! chain-spec-builder create -s -r runtime.wasm full full-genesis-config.json
//! ```
//!
//! _Note_: [`GenesisBuilder::build_config`][sp-genesis-builder-build] runtime function is called.
//!
//! _Note_: [`GenesisBuilder::build_state`][sp-genesis-builder-build] runtime function is called.
//!
//! ##### Generate human readable chain spec using provided genesis config patch.
//! ```bash
//! chain-spec-builder create -r runtime.wasm patch patch.json
//! ```
//!
//!
//! ##### Generate human readable chain spec using provided full genesis config.
//!
//! ```bash
//! chain-spec-builder create -r runtime.wasm full full-genesis-config.json
//! ```
//!
//!
//! ##### Extra tools.
//! The `chain-spec-builder` provides also some extra utilities: [`VerifyCmd`], [`ConvertToRawCmd`],
//! [`UpdateCodeCmd`].
@@ -80,8 +113,9 @@
//! [`sc-chain-spec`]: ../sc_chain_spec/index.html
//! [`node-cli`]: ../node_cli/index.html
//! [`sp-genesis-builder`]: ../sp_genesis_builder/index.html
//! [sp-genesis-builder-create]: ../sp_genesis_builder/trait.GenesisBuilder.html#method.create_default_config
//! [sp-genesis-builder-build]: ../sp_genesis_builder/trait.GenesisBuilder.html#method.build_config
//! [sp-genesis-builder-build]: ../sp_genesis_builder/trait.GenesisBuilder.html#method.build_state
//! [sp-genesis-builder-list]: ../sp_genesis_builder/trait.GenesisBuilder.html#method.preset_names
//! [sp-genesis-builder-get-preset]: ../sp_genesis_builder/trait.GenesisBuilder.html#method.get_preset
use std::{fs, path::PathBuf};
@@ -107,6 +141,8 @@ pub enum ChainSpecBuilderCmd {
Verify(VerifyCmd),
UpdateCode(UpdateCodeCmd),
ConvertToRaw(ConvertToRawCmd),
ListPresets(ListPresetsCmd),
DisplayPreset(DisplayPresetCmd),
}
/// Create a new chain spec by interacting with the provided runtime wasm blob.
@@ -137,6 +173,7 @@ enum GenesisBuildAction {
Patch(PatchCmd),
Full(FullCmd),
Default(DefaultCmd),
NamedPreset(NamedPresetCmd),
}
/// Patches the runtime's default genesis config with provided patch.
@@ -157,10 +194,12 @@ struct FullCmd {
/// default genesis config may not be valid. For some runtimes initial values should be added there
/// (e.g. session keys, babe epoch).
#[derive(Parser, Debug, Clone)]
struct DefaultCmd {
/// If provided stores the default genesis config json file at given path (in addition to
/// chain-spec).
default_config_path: Option<PathBuf>,
struct DefaultCmd {}
/// Uses named preset provided by runtime to build the chains spec.
#[derive(Parser, Debug, Clone)]
struct NamedPresetCmd {
preset_name: String,
}
/// Updates the code in the provided input chain spec.
@@ -182,6 +221,25 @@ pub struct ConvertToRawCmd {
pub input_chain_spec: PathBuf,
}
/// Lists available presets
#[derive(Parser, Debug, Clone)]
pub struct ListPresetsCmd {
/// The path to runtime wasm blob.
#[arg(long, short)]
pub runtime_wasm_path: PathBuf,
}
/// Displays given preset
#[derive(Parser, Debug, Clone)]
pub struct DisplayPresetCmd {
/// The path to runtime wasm blob.
#[arg(long, short)]
pub runtime_wasm_path: PathBuf,
/// Preset to be displayed. If none is given default will be displayed.
#[arg(long, short)]
pub preset_name: Option<String>,
}
/// Verifies the provided input chain spec.
///
/// Silently checks if given input chain spec can be converted to raw. It allows to check if all
@@ -204,6 +262,8 @@ pub fn generate_chain_spec_for_runtime(cmd: &CreateCmd) -> Result<String, String
.with_chain_type(sc_chain_spec::ChainType::Live);
let builder = match cmd.action {
GenesisBuildAction::NamedPreset(NamedPresetCmd { ref preset_name }) =>
builder.with_genesis_config_preset_name(&preset_name),
GenesisBuildAction::Patch(PatchCmd { ref patch_path }) => {
let patch = fs::read(patch_path.as_path())
.map_err(|e| format!("patch file {patch_path:?} shall be readable: {e}"))?;
@@ -218,16 +278,12 @@ pub fn generate_chain_spec_for_runtime(cmd: &CreateCmd) -> Result<String, String
|e| format!("config file {config_path:?} shall contain a valid json: {e}"),
)?)
},
GenesisBuildAction::Default(DefaultCmd { ref default_config_path }) => {
GenesisBuildAction::Default(DefaultCmd {}) => {
let caller: GenesisConfigBuilderRuntimeCaller =
GenesisConfigBuilderRuntimeCaller::new(&code[..]);
let default_config = caller
.get_default_config()
.map_err(|e| format!("getting default config from runtime should work: {e}"))?;
default_config_path.clone().map(|path| {
fs::write(path.as_path(), serde_json::to_string_pretty(&default_config).unwrap())
.map_err(|err| err.to_string())
});
builder.with_genesis_config(default_config)
},
};
+2 -1
View File
@@ -1,6 +1,6 @@
[package]
name = "sc-chain-spec"
version = "27.0.0"
version = "28.0.0"
authors.workspace = true
edition.workspace = true
license = "GPL-3.0-or-later WITH Classpath-exception-2.0"
@@ -33,6 +33,7 @@ sp-genesis-builder = { path = "../../primitives/genesis-builder" }
sp-runtime = { path = "../../primitives/runtime" }
sp-state-machine = { path = "../../primitives/state-machine" }
log = { workspace = true }
sp-tracing = { path = "../../primitives/tracing" }
array-bytes = { version = "6.1" }
docify = "0.2.8"
@@ -0,0 +1,114 @@
Invalid JSON blob: unknown field `babex`, expected one of `system`, `babe`, `substrateTest`, `balances` at line 2 column 9 for blob:
{
"babex": {
"authorities": [
[
"5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY",
1
],
[
"5FHneW46xGXgs5mUiveU4sbTyGBzmstUspZC92UhjJM694ty",
1
],
[
"5FLSigC9HGRKVhB9FiEo4Y3koPsNmBmLJbpXg2mp1hXcS59Y",
1
]
],
"epochConfig": {
"allowed_slots": "PrimaryAndSecondaryPlainSlots",
"c": [
3,
10
]
}
},
"balances": {
"balances": [
[
"5D34dL5prEUaGNQtPPZ3yN5Y6BnkfXunKXXz6fo7ZJbLwRRH",
100000000000000000
],
[
"5GBNeWRhZc2jXu7D55rBimKYDk8PGk8itRYFTPfC8RJLKG5o",
100000000000000000
],
[
"5Dfis6XL8J2P6JHUnUtArnFWndn62SydeP8ee8sG2ky9nfm9",
100000000000000000
],
[
"5F4H97f7nQovyrbiq4ZetaaviNwThSVcFobcA5aGab6167dK",
100000000000000000
],
[
"5DiDShBWa1fQx6gLzpf3SFBhMinCoyvHM1BWjPNsmXS8hkrW",
100000000000000000
],
[
"5EFb84yH9tpcFuiKUcsmdoF7xeeY3ajG1ZLQimxQoFt9HMKR",
100000000000000000
],
[
"5DZLHESsfGrJ5YzT3HuRPXsSNb589xQ4Unubh1mYLodzKdVY",
100000000000000000
],
[
"5GHJzqvG6tXnngCpG7B12qjUvbo5e4e9z8Xjidk3CQZHxTPZ",
100000000000000000
],
[
"5CUnSsgAyLND3bxxnfNhgWXSe9Wn676JzLpGLgyJv858qhoX",
100000000000000000
],
[
"5CVKn7HAZW1Ky4r7Vkgsr7VEW88C2sHgUNDiwHY9Ct2hjU8q",
100000000000000000
],
[
"5H673aukQ4PeDe1U2nuv1bi32xDEziimh3PZz7hDdYUB7TNz",
100000000000000000
],
[
"5HTe9L15LJryjUAt1jZXZCBPnzbbGnpvFwbjE3NwCWaAqovf",
100000000000000000
],
[
"5D7LFzGpMwHPyDBavkRbWSKWTtJhCaPPZ379wWLT23bJwXJz",
100000000000000000
],
[
"5CLepMARnEgtVR1EkUuJVUvKh97gzergpSxUU3yKGx1v6EwC",
100000000000000000
],
[
"5Chb2UhfvZpmjjEziHbFbotM4quX32ZscRV6QJBt1rUKzz51",
100000000000000000
],
[
"5HmRp3i3ZZk7xsAvbi8hyXVP6whSMnBJGebVC4FsiZVhx52e",
100000000000000000
],
[
"5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY",
100000000000000000
],
[
"5FHneW46xGXgs5mUiveU4sbTyGBzmstUspZC92UhjJM694ty",
100000000000000000
],
[
"5FLSigC9HGRKVhB9FiEo4Y3koPsNmBmLJbpXg2mp1hXcS59Y",
100000000000000000
]
]
},
"substrateTest": {
"authorities": [
"5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY",
"5FHneW46xGXgs5mUiveU4sbTyGBzmstUspZC92UhjJM694ty",
"5FLSigC9HGRKVhB9FiEo4Y3koPsNmBmLJbpXg2mp1hXcS59Y"
]
},
"system": {}
}
@@ -0,0 +1,35 @@
{
"name": "TestName",
"id": "test_id",
"chainType": "Local",
"bootNodes": [],
"telemetryEndpoints": null,
"protocolId": null,
"properties": null,
"codeSubstitutes": {},
"genesis": {
"runtimeGenesis": {
"patch": {
"balances": {
"balances": [
[
"5FHneW46xGXgs5mUiveU4sbTyGBzmstUspZC92UhjJM694ty",
1000000000000000
],
[
"5FLSigC9HGRKVhB9FiEo4Y3koPsNmBmLJbpXg2mp1hXcS59Y",
1000000000000000
]
]
},
"substrateTest": {
"authorities": [
"5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY",
"5CiPPseXPECbkjWCa6MnjNokrgYjMqmKndv2rSnekmSK2DjL"
]
}
},
"code": "0x0"
}
}
}
+63 -14
View File
@@ -40,15 +40,26 @@ use std::{
sync::Arc,
};
#[derive(Serialize, Deserialize, Clone)]
#[derive(Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
enum GenesisBuildAction {
enum GenesisBuildAction<EHF> {
Patch(json::Value),
Full(json::Value),
NamedPreset(String, PhantomData<EHF>),
}
impl<EHF> Clone for GenesisBuildAction<EHF> {
fn clone(&self) -> Self {
match self {
Self::Patch(ref p) => Self::Patch(p.clone()),
Self::Full(ref f) => Self::Full(f.clone()),
Self::NamedPreset(ref p, _) => Self::NamedPreset(p.clone(), Default::default()),
}
}
}
#[allow(deprecated)]
enum GenesisSource<G> {
enum GenesisSource<G, EHF> {
File(PathBuf),
Binary(Cow<'static, [u8]>),
/// factory function + code
@@ -56,10 +67,10 @@ enum GenesisSource<G> {
Factory(Arc<dyn Fn() -> G + Send + Sync>, Vec<u8>),
Storage(Storage),
/// build action + code
GenesisBuilderApi(GenesisBuildAction, Vec<u8>),
GenesisBuilderApi(GenesisBuildAction<EHF>, Vec<u8>),
}
impl<G> Clone for GenesisSource<G> {
impl<G, EHF> Clone for GenesisSource<G, EHF> {
fn clone(&self) -> Self {
match *self {
Self::File(ref path) => Self::File(path.clone()),
@@ -71,7 +82,7 @@ impl<G> Clone for GenesisSource<G> {
}
}
impl<G: RuntimeGenesis> GenesisSource<G> {
impl<G: RuntimeGenesis, EHF: HostFunctions> GenesisSource<G, EHF> {
fn resolve(&self) -> Result<Genesis<G>, String> {
/// helper container for deserializing genesis from the JSON file (ChainSpec JSON file is
/// also supported here)
@@ -118,6 +129,13 @@ impl<G: RuntimeGenesis> GenesisSource<G> {
json_blob: RuntimeGenesisConfigJson::Patch(patch.clone()),
code: code.clone(),
})),
Self::GenesisBuilderApi(GenesisBuildAction::NamedPreset(name, _), code) => {
let patch = RuntimeCaller::<EHF>::new(&code[..]).get_named_preset(Some(name))?;
Ok(Genesis::RuntimeGenesis(RuntimeGenesisInner {
json_blob: RuntimeGenesisConfigJson::Patch(patch),
code: code.clone(),
}))
},
}
}
}
@@ -331,13 +349,13 @@ pub struct ChainSpecBuilder<G, E = NoExtension, EHF = ()> {
name: String,
id: String,
chain_type: ChainType,
genesis_build_action: GenesisBuildAction,
genesis_build_action: GenesisBuildAction<EHF>,
boot_nodes: Option<Vec<MultiaddrWithPeerId>>,
telemetry_endpoints: Option<TelemetryEndpoints>,
protocol_id: Option<String>,
fork_id: Option<String>,
properties: Option<Properties>,
_genesis: PhantomData<(G, EHF)>,
_genesis: PhantomData<G>,
}
impl<G, E, EHF> ChainSpecBuilder<G, E, EHF> {
@@ -425,6 +443,13 @@ impl<G, E, EHF> ChainSpecBuilder<G, E, EHF> {
self
}
/// Sets the name of runtime-provided JSON patch for runtime's GenesisConfig.
pub fn with_genesis_config_preset_name(mut self, name: &str) -> Self {
self.genesis_build_action =
GenesisBuildAction::NamedPreset(name.to_string(), Default::default());
self
}
/// Sets the full runtime's GenesisConfig JSON.
pub fn with_genesis_config(mut self, config: json::Value) -> Self {
self.genesis_build_action = GenesisBuildAction::Full(config);
@@ -463,7 +488,7 @@ impl<G, E, EHF> ChainSpecBuilder<G, E, EHF> {
/// runtime is using the non-standard host function during genesis state creation.
pub struct ChainSpec<G, E = NoExtension, EHF = ()> {
client_spec: ClientSpec<E>,
genesis: GenesisSource<G>,
genesis: GenesisSource<G, EHF>,
_host_functions: PhantomData<EHF>,
}
@@ -1009,7 +1034,30 @@ mod tests {
assert!(raw_chain_spec.is_ok());
}
#[docify::export]
#[test]
fn generate_chain_spec_with_named_preset_works() {
sp_tracing::try_init_simple();
let output: ChainSpec<()> = ChainSpec::builder(
substrate_test_runtime::wasm_binary_unwrap().into(),
Default::default(),
)
.with_name("TestName")
.with_id("test_id")
.with_chain_type(ChainType::Local)
.with_genesis_config_preset_name("staging")
.build();
let actual = output.as_json(false).unwrap();
let expected =
from_str::<Value>(include_str!("../res/substrate_test_runtime_from_named_preset.json"))
.unwrap();
//wasm blob may change overtime so let's zero it. Also ensure it is there:
let actual = zeroize_code_key_in_json(false, actual.as_str());
assert_eq!(actual, expected);
}
#[test]
fn generate_chain_spec_with_patch_works() {
let output = ChainSpec::<()>::builder(
@@ -1089,6 +1137,8 @@ mod tests {
#[test]
fn chain_spec_as_json_fails_with_invalid_config() {
let expected_error_message =
include_str!("../res/chain_spec_as_json_fails_with_invalid_config.err");
let j =
include_str!("../../../test-utils/runtime/res/default_genesis_config_invalid_2.json");
let output = ChainSpec::<()>::builder(
@@ -1101,10 +1151,9 @@ mod tests {
.with_genesis_config(from_str(j).unwrap())
.build();
assert_eq!(
output.as_json(true),
Err("Invalid JSON blob: unknown field `babex`, expected one of `system`, `babe`, `substrateTest`, `balances` at line 1 column 8".to_string())
);
let result = output.as_json(true);
assert_eq!(result.err().unwrap(), expected_error_message);
}
#[test]
@@ -26,7 +26,7 @@ use sp_core::{
storage::Storage,
traits::{CallContext, CodeExecutor, Externalities, FetchRuntimeCode, RuntimeCode},
};
use sp_genesis_builder::Result as BuildResult;
use sp_genesis_builder::{PresetId, Result as BuildResult};
use sp_state_machine::BasicExternalities;
use std::borrow::Cow;
@@ -84,30 +84,46 @@ where
/// Returns a json representation of the default `RuntimeGenesisConfig` provided by the
/// `runtime`.
///
/// Calls [`GenesisBuilder::create_default_config`](sp_genesis_builder::GenesisBuilder::create_default_config) in the `runtime`.
/// Calls [`GenesisBuilder::get_preset`](sp_genesis_builder::GenesisBuilder::get_preset) in the
/// `runtime` with `None` argument.
pub fn get_default_config(&self) -> core::result::Result<Value, String> {
let mut t = BasicExternalities::new_empty();
let call_result = self
.call(&mut t, "GenesisBuilder_create_default_config", &[])
.map_err(|e| format!("wasm call error {e}"))?;
let default_config = Vec::<u8>::decode(&mut &call_result[..])
.map_err(|e| format!("scale codec error: {e}"))?;
Ok(from_slice(&default_config[..]).expect("returned value is json. qed."))
self.get_named_preset(None)
}
/// Builds `RuntimeGenesisConfig` from given json blob and returns the genesis state.
/// Returns a JSON blob representation of the builtin `GenesisConfig` identified by `id`.
///
/// Calls [`GenesisBuilder::build_config`](sp_genesis_builder::GenesisBuilder::build_config)
/// Calls [`GenesisBuilder::get_preset`](sp_genesis_builder::GenesisBuilder::get_preset)
/// provided by the `runtime`.
pub fn get_named_preset(&self, id: Option<&String>) -> core::result::Result<Value, String> {
let mut t = BasicExternalities::new_empty();
let call_result = self
.call(&mut t, "GenesisBuilder_get_preset", &id.encode())
.map_err(|e| format!("wasm call error {e}"))?;
let named_preset = Option::<Vec<u8>>::decode(&mut &call_result[..])
.map_err(|e| format!("scale codec error: {e}"))?;
if let Some(named_preset) = named_preset {
Ok(from_slice(&named_preset[..]).expect("returned value is json. qed."))
} else {
Err(format!("The preset with name {id:?} is not available."))
}
}
/// Calls [`sp_genesis_builder::GenesisBuilder::build_state`] provided by runtime.
pub fn get_storage_for_config(&self, config: Value) -> core::result::Result<Storage, String> {
let mut ext = BasicExternalities::new_empty();
let json_pretty_str = serde_json::to_string_pretty(&config)
.map_err(|e| format!("json to string failed: {e}"))?;
let call_result = self
.call(&mut ext, "GenesisBuilder_build_config", &config.to_string().encode())
.call(&mut ext, "GenesisBuilder_build_state", &json_pretty_str.encode())
.map_err(|e| format!("wasm call error {e}"))?;
BuildResult::decode(&mut &call_result[..])
.map_err(|e| format!("scale codec error: {e}"))??;
.map_err(|e| format!("scale codec error: {e}"))?
.map_err(|e| format!("{e} for blob:\n{}", json_pretty_str))?;
Ok(ext.into_storages())
}
@@ -137,6 +153,25 @@ where
crate::json_patch::merge(&mut config, patch);
self.get_storage_for_config(config)
}
pub fn get_storage_for_named_preset(
&self,
name: Option<&String>,
) -> core::result::Result<Storage, String> {
self.get_storage_for_patch(self.get_named_preset(name)?)
}
pub fn preset_names(&self) -> core::result::Result<Vec<PresetId>, String> {
let mut t = BasicExternalities::new_empty();
let call_result = self
.call(&mut t, "GenesisBuilder_preset_names", &vec![])
.map_err(|e| format!("wasm call error {e}"))?;
let preset_names = Vec::<PresetId>::decode(&mut &call_result[..])
.map_err(|e| format!("scale codec error: {e}"))?;
Ok(preset_names)
}
}
#[cfg(test)]
@@ -144,6 +179,17 @@ mod tests {
use super::*;
use serde_json::{from_str, json};
pub use sp_consensus_babe::{AllowedSlots, BabeEpochConfiguration};
pub use sp_genesis_builder::PresetId;
#[test]
fn list_presets_works() {
sp_tracing::try_init_simple();
let presets =
<GenesisConfigBuilderRuntimeCaller>::new(substrate_test_runtime::wasm_binary_unwrap())
.preset_names()
.unwrap();
assert_eq!(presets, vec![PresetId::from("foobar"), PresetId::from("staging"),]);
}
#[test]
fn get_default_config_works() {
@@ -155,6 +201,17 @@ mod tests {
assert_eq!(from_str::<Value>(expected).unwrap(), config);
}
#[test]
fn get_named_preset_works() {
sp_tracing::try_init_simple();
let config =
<GenesisConfigBuilderRuntimeCaller>::new(substrate_test_runtime::wasm_binary_unwrap())
.get_named_preset(Some(&"foobar".to_string()))
.unwrap();
let expected = r#"{"foo":"bar"}"#;
assert_eq!(from_str::<Value>(expected).unwrap(), config);
}
#[test]
fn get_storage_for_patch_works() {
let patch = json!({
+2 -2
View File
@@ -181,7 +181,7 @@
//! the node needs to interact with the runtime.
//!
//! This interaction involves passing the runtime genesis config JSON blob to the runtime using the
//! [`sp_genesis_builder::GenesisBuilder::build_config`] function. During this operation, the
//! [`sp_genesis_builder::GenesisBuilder::build_state`] function. During this operation, the
//! runtime converts the JSON representation of the genesis config into [`sp_io::storage`] items. It
//! is a crucial step for computing the storage root hash, which is a key component in determining
//! the genesis hash.
@@ -325,7 +325,7 @@ mod chain_spec;
mod extension;
mod genesis_block;
mod genesis_config_builder;
mod json_patch;
pub mod json_patch;
pub use self::{
chain_spec::{
@@ -19,26 +19,39 @@
//!
//! Provides common logic. For more info refer to [`sp_genesis_builder::GenesisBuilder`].
extern crate alloc;
use alloc::vec::Vec;
use frame_support::traits::BuildGenesisConfig;
use sp_genesis_builder::Result as BuildResult;
use sp_genesis_builder::{PresetId, Result as BuildResult};
use sp_runtime::format_runtime_string;
/// Get the default `GenesisConfig` as a JSON blob. For more info refer to
/// [`sp_genesis_builder::GenesisBuilder::create_default_config`]
pub fn create_default_config<GC>() -> sp_std::vec::Vec<u8>
where
GC: BuildGenesisConfig + Default,
{
serde_json::to_string(&GC::default())
.expect("serialization to json is expected to work. qed.")
.into_bytes()
}
/// Build `GenesisConfig` from a JSON blob not using any defaults and store it in the storage. For
/// more info refer to [`sp_genesis_builder::GenesisBuilder::build_config`].
pub fn build_config<GC: BuildGenesisConfig>(json: sp_std::vec::Vec<u8>) -> BuildResult {
/// more info refer to [`sp_genesis_builder::GenesisBuilder::build_state`].
pub fn build_state<GC: BuildGenesisConfig>(json: Vec<u8>) -> BuildResult {
let gc = serde_json::from_slice::<GC>(&json)
.map_err(|e| format_runtime_string!("Invalid JSON blob: {}", e))?;
<GC as BuildGenesisConfig>::build(&gc);
Ok(())
}
/// Get the default `GenesisConfig` as a JSON blob if `name` is None.
///
/// Query of named presets is delegetaed to provided `preset_for_name` closure. For more info refer
/// to [`sp_genesis_builder::GenesisBuilder::get_preset`].
pub fn get_preset<GC>(
name: &Option<PresetId>,
preset_for_name: impl FnOnce(&sp_genesis_builder::PresetId) -> Option<sp_std::vec::Vec<u8>>,
) -> Option<Vec<u8>>
where
GC: BuildGenesisConfig + Default,
{
name.as_ref().map_or(
Some(
serde_json::to_string(&GC::default())
.expect("serialization to json is expected to work. qed.")
.into_bytes(),
),
preset_for_name,
)
}
@@ -1,6 +1,6 @@
[package]
name = "sp-genesis-builder"
version = "0.7.0"
version = "0.8.0"
authors.workspace = true
edition.workspace = true
license = "Apache-2.0"
@@ -16,10 +16,19 @@ workspace = true
targets = ["x86_64-unknown-linux-gnu"]
[dependencies]
codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false, features = ["bytes"] }
scale-info = { version = "2.10.0", default-features = false, features = ["derive"] }
sp-api = { path = "../api", default-features = false }
sp-runtime = { path = "../runtime", default-features = false }
serde_json = { features = ["alloc", "arbitrary_precision"], workspace = true }
[features]
default = ["std"]
std = ["serde_json/std", "sp-api/std", "sp-runtime/std"]
std = [
"codec/std",
"scale-info/std",
"serde_json/std",
"sp-api/std",
"sp-runtime/std",
]
+64 -20
View File
@@ -19,39 +19,83 @@
//! Substrate genesis config builder
//!
//! This Runtime API allows to construct `RuntimeGenesisConfig`, in particular:
//! - serialize the runtime default `RuntimeGenesisConfig` struct into json format,
//! - put the RuntimeGenesisConfig struct into the storage. Internally this operation calls
//! `GenesisBuild::build` function for all runtime pallets, which is typically provided by
//! pallet's author.
//! - deserialize the `RuntimeGenesisConfig` from given json blob and put `RuntimeGenesisConfig`
//! into the state storage. Allows to build customized configuration.
//! For FRAME based runtimes, this runtime interface provides means to interact with
//! `RuntimeGenesisConfig`. Runtime provides a default `RuntimeGenesisConfig` structure in a form of
//! the JSON blob.
//!
//! Providing externalities with empty storage and putting `RuntimeGenesisConfig` into storage
//! allows to catch and build the raw storage of `RuntimeGenesisConfig` which is the foundation for
//! genesis block.
//! For non-FRAME runtimes this interface is intended to build genesis state of the runtime basing
//! on some input arbitrary bytes array. This documentation uses term `RuntimeGenesisConfig`, which
//! for non-FRAME runtimes may be understood as the runtime-side entity representing initial runtime
//! configuration. The representation of the preset is an arbitrary `Vec<u8>` and does not
//! necessarily have to represent a JSON blob.
//!
//! The runtime may provide a number of partial predefined `RuntimeGenesisConfig` configurations in
//! the form of patches which shall be applied on top of the default `RuntimeGenesisConfig`. The
//! patch is a JSON blob, which essentially comprises the list of key-value pairs that are to be
//! customized in the default runtime genesis config. These predefined configurations are referred
//! to as presets.
//!
//! This allows the runtime to provide a number of predefined configs (e.g. for different
//! testnets or development) without neccessity to leak the runtime types outside the itself (e.g.
//! node or chain-spec related tools).
//!
//! This Runtime API allows to interact with `RuntimeGenesisConfig`, in particular:
//! - provide the list of available preset names,
//! - provide a number of named presets of `RuntimeGenesisConfig`,
//! - provide a JSON represention of the default `RuntimeGenesisConfig` (by simply serializing the
//! default `RuntimeGenesisConfig` struct into JSON format),
//! - deserialize the full `RuntimeGenesisConfig` from given JSON blob and put the resulting
//! `RuntimeGenesisConfig` structure into the state storage creating the initial runtime's state.
//! Allows to build customized genesis. This operation internally calls `GenesisBuild::build`
//! function for all runtime pallets.
//!
//! Providing externalities with an empty storage and putting `RuntimeGenesisConfig` into storage
//! (by calling `build_state`) allows to construct the raw storage of `RuntimeGenesisConfig`
//! which is the foundation for genesis block.
extern crate alloc;
use alloc::vec::Vec;
/// The result type alias, used in build methods. `Err` contains formatted error message.
pub type Result = core::result::Result<(), sp_runtime::RuntimeString>;
/// The type representing preset ID.
pub type PresetId = sp_runtime::RuntimeString;
sp_api::decl_runtime_apis! {
/// API to interact with RuntimeGenesisConfig for the runtime
pub trait GenesisBuilder {
/// Creates the default `RuntimeGenesisConfig` and returns it as a JSON blob.
/// Build `RuntimeGenesisConfig` from a JSON blob not using any defaults and store it in the
/// storage.
///
/// This function instantiates the default `RuntimeGenesisConfig` struct for the runtime and serializes it into a JSON
/// blob. It returns a `Vec<u8>` containing the JSON representation of the default `RuntimeGenesisConfig`.
fn create_default_config() -> alloc::vec::Vec<u8>;
/// In the case of a FRAME-based runtime, this function deserializes the full `RuntimeGenesisConfig` from the given JSON blob and
/// puts it into the storage. If the provided JSON blob is incorrect or incomplete or the
/// deserialization fails, an error is returned.
///
/// Please note that provided JSON blob must contain all `RuntimeGenesisConfig` fields, no
/// defaults will be used.
fn build_state(json: Vec<u8>) -> Result;
/// Build `RuntimeGenesisConfig` from a JSON blob not using any defaults and store it in the storage.
/// Returns a JSON blob representation of the built-in `RuntimeGenesisConfig` identified by
/// `id`.
///
/// This function deserializes the full `RuntimeGenesisConfig` from the given JSON blob and puts it into the storage.
/// If the provided JSON blob is incorrect or incomplete or the deserialization fails, an error is returned.
/// It is recommended to log any errors encountered during the process.
/// If `id` is `None` the function returns JSON blob representation of the default
/// `RuntimeGenesisConfig` struct of the runtime. Implementation must provide default
/// `RuntimeGenesisConfig`.
///
/// Please note that provided json blob must contain all `RuntimeGenesisConfig` fields, no defaults will be used.
fn build_config(json: alloc::vec::Vec<u8>) -> Result;
/// Otherwise function returns a JSON representation of the built-in, named
/// `RuntimeGenesisConfig` preset identified by `id`, or `None` if such preset does not
/// exists. Returned `Vec<u8>` contains bytes of JSON blob (patch) which comprises a list of
/// (potentially nested) key-value pairs that are intended for customizing the default
/// runtime genesis config. The patch shall be merged (rfc7386) with the JSON representation
/// of the default `RuntimeGenesisConfig` to create a comprehensive genesis config that can
/// be used in `build_state` method.
fn get_preset(id: &Option<PresetId>) -> Option<Vec<u8>>;
/// Returns a list of identifiers for available builtin `RuntimeGenesisConfig` presets.
///
/// The presets from the list can be queried with [`GenesisBuilder::get_preset`] method. If
/// no named presets are provided by the runtime the list is empty.
fn preset_names() -> Vec<PresetId>;
}
}
+2
View File
@@ -50,7 +50,9 @@ sp-externalities = { path = "../../primitives/externalities", default-features =
# 3rd party
array-bytes = { version = "6.1", optional = true }
serde_json = { workspace = true, features = ["alloc"] }
log = { workspace = true }
hex-literal = { version = "0.4.1" }
[dev-dependencies]
futures = "0.3.30"
+99 -26
View File
@@ -27,11 +27,14 @@ pub mod extrinsic;
pub mod genesismap;
pub mod substrate_test_pallet;
use alloc::boxed::Box;
#[cfg(not(feature = "std"))]
use alloc::{vec, vec::Vec};
use codec::{Decode, Encode};
use frame_support::{
construct_runtime, derive_impl,
dispatch::DispatchClass,
genesis_builder_helper::{build_config, create_default_config},
genesis_builder_helper::{build_state, get_preset},
parameter_types,
traits::{ConstU32, ConstU64},
weights::{
@@ -44,10 +47,8 @@ use frame_system::{
CheckNonce, CheckWeight,
};
use scale_info::TypeInfo;
use alloc::boxed::Box;
#[cfg(not(feature = "std"))]
use alloc::{vec, vec::Vec};
use sp_application_crypto::Ss58Codec;
use sp_keyring::AccountKeyring;
use sp_application_crypto::{ecdsa, ed25519, sr25519, RuntimeAppPublic};
use sp_core::{OpaqueMetadata, RuntimeDebug};
@@ -57,8 +58,10 @@ use sp_trie::{
};
use trie_db::{Trie, TrieMut};
use serde_json::json;
use sp_api::{decl_runtime_apis, impl_runtime_apis};
pub use sp_core::hash::H256;
use sp_genesis_builder::PresetId;
use sp_inherents::{CheckInherentsResult, InherentData};
use sp_runtime::{
create_runtime_str, impl_opaque_keys,
@@ -93,7 +96,7 @@ pub mod wasm_binary_logging_disabled {
#[cfg(feature = "std")]
pub fn wasm_binary_unwrap() -> &'static [u8] {
WASM_BINARY.expect(
"Development wasm binary is not available. Testing is only supported with the flag \
"Development wasm binary is not available. Testing is only supported with the flag
disabled.",
)
}
@@ -102,7 +105,7 @@ pub fn wasm_binary_unwrap() -> &'static [u8] {
#[cfg(feature = "std")]
pub fn wasm_binary_logging_disabled_unwrap() -> &'static [u8] {
wasm_binary_logging_disabled::WASM_BINARY.expect(
"Development wasm binary is not available. Testing is only supported with the flag \
"Development wasm binary is not available. Testing is only supported with the flag
disabled.",
)
}
@@ -725,12 +728,42 @@ impl_runtime_apis! {
}
impl sp_genesis_builder::GenesisBuilder<Block> for Runtime {
fn create_default_config() -> Vec<u8> {
create_default_config::<RuntimeGenesisConfig>()
fn build_state(config: Vec<u8>) -> sp_genesis_builder::Result {
build_state::<RuntimeGenesisConfig>(config)
}
fn build_config(config: Vec<u8>) -> sp_genesis_builder::Result {
build_config::<RuntimeGenesisConfig>(config)
fn get_preset(name: &Option<PresetId>) -> Option<Vec<u8>> {
get_preset::<RuntimeGenesisConfig>(name, |name| {
let patch = match name.try_into() {
Ok("staging") => {
let endowed_accounts: Vec<AccountId> = vec![
AccountKeyring::Bob.public().into(),
AccountKeyring::Charlie.public().into(),
];
json!({
"balances": {
"balances": endowed_accounts.into_iter().map(|k| (k, 10 * currency::DOLLARS)).collect::<Vec<_>>(),
},
"substrateTest": {
"authorities": [
AccountKeyring::Alice.public().to_ss58check(),
AccountKeyring::Ferdie.public().to_ss58check()
],
}
})
},
Ok("foobar") => json!({"foo":"bar"}),
_ => return None,
};
Some(serde_json::to_string(&patch)
.expect("serialization to json is expected to work. qed.")
.into_bytes())
})
}
fn preset_names() -> Vec<PresetId> {
vec![PresetId::from("foobar"), PresetId::from("staging")]
}
}
}
@@ -836,7 +869,6 @@ fn test_witness(proof: StorageProof, root: crate::Hash) {
pub mod storage_key_generator {
use super::*;
use sp_core::Pair;
use sp_keyring::AccountKeyring;
/// Generate hex string without prefix
pub(super) fn hex<T>(x: T) -> String
@@ -1026,7 +1058,6 @@ mod tests {
use sp_api::{ApiExt, ProvideRuntimeApi};
use sp_consensus::BlockOrigin;
use sp_core::{storage::well_known_keys::HEAP_PAGES, traits::CallContext};
use sp_keyring::AccountKeyring;
use sp_runtime::{
traits::{Hash as _, SignedExtension},
transaction_validity::{InvalidTransaction, ValidTransaction},
@@ -1177,7 +1208,7 @@ mod tests {
fn check_substrate_check_signed_extension_works() {
sp_tracing::try_init_simple();
new_test_ext().execute_with(|| {
let x = sp_keyring::AccountKeyring::Alice.into();
let x = AccountKeyring::Alice.into();
let info = DispatchInfo::default();
let len = 0_usize;
assert_eq!(
@@ -1242,7 +1273,7 @@ mod tests {
let default_minimal_json = r#"{"system":{},"babe":{"authorities":[],"epochConfig":{"c": [ 3, 10 ],"allowed_slots":"PrimaryAndSecondaryPlainSlots"}},"substrateTest":{"authorities":[]},"balances":{"balances":[]}}"#;
let mut t = BasicExternalities::new_empty();
executor_call(&mut t, "GenesisBuilder_build_config", &default_minimal_json.encode())
executor_call(&mut t, "GenesisBuilder_build_state", &default_minimal_json.encode())
.unwrap();
let mut keys = t.into_storages().top.keys().cloned().map(hex).collect::<Vec<String>>();
@@ -1290,21 +1321,60 @@ mod tests {
fn default_config_as_json_works() {
sp_tracing::try_init_simple();
let mut t = BasicExternalities::new_empty();
let r = executor_call(&mut t, "GenesisBuilder_create_default_config", &vec![]).unwrap();
let r = Vec::<u8>::decode(&mut &r[..]).unwrap();
let r = executor_call(&mut t, "GenesisBuilder_get_preset", &None::<&PresetId>.encode())
.unwrap();
let r = Option::<Vec<u8>>::decode(&mut &r[..])
.unwrap()
.expect("default config is there");
let json = String::from_utf8(r.into()).expect("returned value is json. qed.");
let expected = r#"{"system":{},"babe":{"authorities":[],"epochConfig":{"c":[1,4],"allowed_slots":"PrimaryAndSecondaryVRFSlots"}},"substrateTest":{"authorities":[]},"balances":{"balances":[]}}"#;
assert_eq!(expected.to_string(), json);
}
#[test]
fn preset_names_listing_works() {
sp_tracing::try_init_simple();
let mut t = BasicExternalities::new_empty();
let r = executor_call(&mut t, "GenesisBuilder_preset_names", &vec![]).unwrap();
let r = Vec::<PresetId>::decode(&mut &r[..]).unwrap();
assert_eq!(r, vec![PresetId::from("foobar"), PresetId::from("staging"),]);
log::info!("r: {:#?}", r);
}
#[test]
fn named_config_works() {
sp_tracing::try_init_simple();
let f = |cfg_name: &str, expected: &str| {
let mut t = BasicExternalities::new_empty();
let name = cfg_name.to_string();
let r = executor_call(
&mut t,
"GenesisBuilder_get_preset",
&Some(name.as_bytes()).encode(),
)
.unwrap();
let r = Option::<Vec<u8>>::decode(&mut &r[..]).unwrap();
let json =
String::from_utf8(r.unwrap().into()).expect("returned value is json. qed.");
log::info!("json: {:#?}", json);
assert_eq!(expected.to_string(), json);
};
f("foobar", r#"{"foo":"bar"}"#);
f(
"staging",
r#"{"balances":{"balances":[["5FHneW46xGXgs5mUiveU4sbTyGBzmstUspZC92UhjJM694ty",1000000000000000],["5FLSigC9HGRKVhB9FiEo4Y3koPsNmBmLJbpXg2mp1hXcS59Y",1000000000000000]]},"substrateTest":{"authorities":["5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY","5CiPPseXPECbkjWCa6MnjNokrgYjMqmKndv2rSnekmSK2DjL"]}}"#,
);
}
#[test]
fn build_config_from_json_works() {
sp_tracing::try_init_simple();
let j = include_str!("../res/default_genesis_config.json");
let mut t = BasicExternalities::new_empty();
let r = executor_call(&mut t, "GenesisBuilder_build_config", &j.encode()).unwrap();
let r = executor_call(&mut t, "GenesisBuilder_build_state", &j.encode()).unwrap();
let r = BuildResult::decode(&mut &r[..]);
assert!(r.is_ok());
@@ -1323,7 +1393,7 @@ mod tests {
sp_tracing::try_init_simple();
let j = include_str!("../res/default_genesis_config_invalid.json");
let mut t = BasicExternalities::new_empty();
let r = executor_call(&mut t, "GenesisBuilder_build_config", &j.encode()).unwrap();
let r = executor_call(&mut t, "GenesisBuilder_build_state", &j.encode()).unwrap();
let r = BuildResult::decode(&mut &r[..]).unwrap();
log::info!("result: {:#?}", r);
assert_eq!(r, Err(
@@ -1338,7 +1408,7 @@ mod tests {
sp_tracing::try_init_simple();
let j = include_str!("../res/default_genesis_config_invalid_2.json");
let mut t = BasicExternalities::new_empty();
let r = executor_call(&mut t, "GenesisBuilder_build_config", &j.encode()).unwrap();
let r = executor_call(&mut t, "GenesisBuilder_build_state", &j.encode()).unwrap();
let r = BuildResult::decode(&mut &r[..]).unwrap();
assert_eq!(r, Err(
sp_runtime::RuntimeString::Owned(
@@ -1353,7 +1423,7 @@ mod tests {
let j = include_str!("../res/default_genesis_config_incomplete.json");
let mut t = BasicExternalities::new_empty();
let r = executor_call(&mut t, "GenesisBuilder_build_config", &j.encode()).unwrap();
let r = executor_call(&mut t, "GenesisBuilder_build_state", &j.encode()).unwrap();
let r =
core::result::Result::<(), sp_runtime::RuntimeString>::decode(&mut &r[..]).unwrap();
assert_eq!(
@@ -1388,8 +1458,11 @@ mod tests {
sp_tracing::try_init_simple();
let mut t = BasicExternalities::new_empty();
let r = executor_call(&mut t, "GenesisBuilder_create_default_config", &vec![]).unwrap();
let r = Vec::<u8>::decode(&mut &r[..]).unwrap();
let r = executor_call(&mut t, "GenesisBuilder_get_preset", &None::<&PresetId>.encode())
.unwrap();
let r = Option::<Vec<u8>>::decode(&mut &r[..])
.unwrap()
.expect("default config is there");
let mut default_config: serde_json::Value =
serde_json::from_slice(&r[..]).expect("returned value is json. qed.");
@@ -1418,7 +1491,7 @@ mod tests {
let mut t = BasicExternalities::new_empty();
executor_call(
&mut t,
"GenesisBuilder_build_config",
"GenesisBuilder_build_state",
&default_config.to_string().encode(),
)
.unwrap();
@@ -1436,8 +1509,8 @@ mod tests {
let authority_key_vec =
Vec::<sp_core::sr25519::Public>::decode(&mut &value[..]).unwrap();
assert_eq!(authority_key_vec.len(), 2);
assert_eq!(authority_key_vec[0], sp_keyring::AccountKeyring::Ferdie.public());
assert_eq!(authority_key_vec[1], sp_keyring::AccountKeyring::Alice.public());
assert_eq!(authority_key_vec[0], AccountKeyring::Ferdie.public());
assert_eq!(authority_key_vec[1], AccountKeyring::Alice.public());
//Babe|Authorities
let value: Vec<u8> = get_from_storage(
+2
View File
@@ -31,6 +31,7 @@ pallet-transaction-payment-rpc-runtime-api = { path = "../../../substrate/frame/
# genesis builder that allows us to interact with runtime genesis config
sp-genesis-builder = { path = "../../../substrate/primitives/genesis-builder", default-features = false }
sp-runtime = { path = "../../../substrate/primitives/runtime", default-features = false, features = ["serde"] }
# local pallet templates
pallet-minimal-template = { path = "../pallets/template", default-features = false }
@@ -55,5 +56,6 @@ std = [
"pallet-minimal-template/std",
"sp-genesis-builder/std",
"sp-runtime/std",
"substrate-wasm-builder",
]
+9 -5
View File
@@ -23,7 +23,7 @@ include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs"));
use frame::{
deps::frame_support::{
genesis_builder_helper::{build_config, create_default_config},
genesis_builder_helper::{build_state, get_preset},
weights::{FixedFee, NoFee},
},
prelude::*,
@@ -221,12 +221,16 @@ impl_runtime_apis! {
}
impl sp_genesis_builder::GenesisBuilder<Block> for Runtime {
fn create_default_config() -> Vec<u8> {
create_default_config::<RuntimeGenesisConfig>()
fn build_state(config: Vec<u8>) -> sp_genesis_builder::Result {
build_state::<RuntimeGenesisConfig>(config)
}
fn build_config(config: Vec<u8>) -> sp_genesis_builder::Result {
build_config::<RuntimeGenesisConfig>(config)
fn get_preset(id: &Option<sp_genesis_builder::PresetId>) -> Option<Vec<u8>> {
get_preset::<RuntimeGenesisConfig>(id, |_| None)
}
fn preset_names() -> Vec<sp_genesis_builder::PresetId> {
vec![]
}
}
}
+9 -5
View File
@@ -25,7 +25,7 @@
// External crates imports
use frame_support::{
genesis_builder_helper::{build_config, create_default_config},
genesis_builder_helper::{build_state, get_preset},
weights::Weight,
};
use pallet_aura::Authorities;
@@ -264,12 +264,16 @@ impl_runtime_apis! {
}
impl sp_genesis_builder::GenesisBuilder<Block> for Runtime {
fn create_default_config() -> Vec<u8> {
create_default_config::<RuntimeGenesisConfig>()
fn build_state(config: Vec<u8>) -> sp_genesis_builder::Result {
build_state::<RuntimeGenesisConfig>(config)
}
fn build_config(config: Vec<u8>) -> sp_genesis_builder::Result {
build_config::<RuntimeGenesisConfig>(config)
fn get_preset(id: &Option<sp_genesis_builder::PresetId>) -> Option<Vec<u8>> {
get_preset::<RuntimeGenesisConfig>(id, |_| None)
}
fn preset_names() -> Vec<sp_genesis_builder::PresetId> {
Default::default()
}
}
}
+9 -5
View File
@@ -18,7 +18,7 @@ use sp_std::prelude::*;
use sp_version::NativeVersion;
use sp_version::RuntimeVersion;
use frame_support::genesis_builder_helper::{build_config, create_default_config};
use frame_support::genesis_builder_helper::{build_state, get_preset};
pub use frame_support::{
construct_runtime, derive_impl, parameter_types,
traits::{
@@ -575,12 +575,16 @@ impl_runtime_apis! {
}
impl sp_genesis_builder::GenesisBuilder<Block> for Runtime {
fn create_default_config() -> Vec<u8> {
create_default_config::<RuntimeGenesisConfig>()
fn build_state(config: Vec<u8>) -> sp_genesis_builder::Result {
build_state::<RuntimeGenesisConfig>(config)
}
fn build_config(config: Vec<u8>) -> sp_genesis_builder::Result {
build_config::<RuntimeGenesisConfig>(config)
fn get_preset(id: &Option<sp_genesis_builder::PresetId>) -> Option<Vec<u8>> {
get_preset::<RuntimeGenesisConfig>(id, |_| None)
}
fn preset_names() -> Vec<sp_genesis_builder::PresetId> {
vec![]
}
}
}