test-runtime: GenesisBuilder runtime API impl + tests (#14310)

* test-runtime: GenesisBuilder runtime API impl + tests

This PR provides implementation of `GenesisBuilder` API for `substrate-test-runtime`, can be considered as reference imiplementation for other runtimes.
The `GenesisBuilder` implementation is gated by `gensis-config` feature.

Tested scenarios:
- default `GenesisConfig` to JSON blob,
- deserialization of `GenesisConfig` from custom JSON, and storing its keys into the Storage (genesis storage creation).
- creation of genesis storage using partial JSON definition,
- checking if invalid/renamed JSON files causes the runtime to panic,

* missing file added

* client: GenesisBuilder helper added

* feature renamed: genesis-config -> genesis-builder

* Update Cargo.toml

* Update Cargo.toml

* Update Cargo.toml

* Update Cargo.toml

* redundant function removed

* genesis builder helper: introduced RuntimeGenesisBuild

* test-runtime: get rid of unused T

* redundant bound removed

* helper: use GenesisBuild again

* tests adjusted for on_genesis

* test-runtime: support for BuildGenesisConfig

* helper: BuildGenesisConfig support

* Update client/genesis-builder/src/lib.rs

Co-authored-by: Davide Galassi <davxy@datawok.net>

* Update test-utils/runtime/src/test_json/readme.md

Co-authored-by: Davide Galassi <davxy@datawok.net>

* Update test-utils/runtime/src/test_json/readme.md

Co-authored-by: Davide Galassi <davxy@datawok.net>

* Update test-utils/runtime/src/genesismap.rs

Co-authored-by: Davide Galassi <davxy@datawok.net>

* jsons are now human-friendly

* fix

* improvements

* jsons fixed

* helper: no_defaults added

* test-runtime: no_defaults added

* test-runtime: patching fn removed

* helper: patching fn removed

* helper: moved to frame_support

* test-runtime: fixes

* Cargo.lock updated

* fmt + naming

* test-runtime: WasmExecutor used

* helper / test-runtime: struct removed

* test-runtime: merge fixes

* Cargo.lock + test-utils/runtime/Cargo.toml updated

* doc fixed

* client/rpc: test fixed (new rt api)

* client/rpc-spec-v2: test fix

* doc fix

* test-runtime: disable-genesis-builder feature

* fix

* fix

* ".git/.scripts/commands/fmt/fmt.sh"

* test-runtime: rerun added to build script

---------

Co-authored-by: Davide Galassi <davxy@datawok.net>
Co-authored-by: parity-processbot <>
This commit is contained in:
Michal Kucharczyk
2023-07-24 18:12:52 +02:00
committed by GitHub
parent 7fdcb83117
commit 53cbda1de6
14 changed files with 730 additions and 24 deletions
+15 -11
View File
@@ -73,10 +73,10 @@ impl Default for GenesisStorageBuilder {
}
impl GenesisStorageBuilder {
/// Creates a storage builder for genesis config. `substrage test runtime` `GenesisConfig` is
/// initialized with provided `authorities`, `endowed_accounts` with given balance. Key-pairs
/// from `extra_storage` will be injected into built storage. `HEAP_PAGES` key and value will
/// also be placed into storage.
/// Creates a storage builder for genesis config. `substrage test runtime`
/// [`RuntimeGenesisConfig`] is initialized with provided `authorities`, `endowed_accounts` with
/// given balance. Key-value pairs from `extra_storage` will be injected into built storage.
/// `HEAP_PAGES` key and value will also be placed into storage.
pub fn new(
authorities: Vec<AccountId>,
endowed_accounts: Vec<AccountId>,
@@ -91,7 +91,7 @@ impl GenesisStorageBuilder {
}
}
/// Override default wasm code to be placed into GenesisConfig.
/// Override default wasm code to be placed into RuntimeGenesisConfig.
pub fn with_wasm_code(mut self, wasm_code: &Option<Vec<u8>>) -> Self {
self.wasm_code = wasm_code.clone();
self
@@ -107,8 +107,8 @@ impl GenesisStorageBuilder {
self
}
/// Builds the `GenesisConfig` and returns its storage.
pub fn build(self) -> Storage {
/// A `RuntimeGenesisConfig` from internal configuration
pub fn genesis_config(&self) -> RuntimeGenesisConfig {
let authorities_sr25519: Vec<_> = self
.authorities
.clone()
@@ -116,7 +116,7 @@ impl GenesisStorageBuilder {
.map(|id| sr25519::Public::from(id))
.collect();
let genesis_config = RuntimeGenesisConfig {
RuntimeGenesisConfig {
system: frame_system::GenesisConfig {
code: self.wasm_code.clone().unwrap_or(wasm_binary_unwrap().to_vec()),
..Default::default()
@@ -135,11 +135,15 @@ impl GenesisStorageBuilder {
..Default::default()
},
balances: pallet_balances::GenesisConfig { balances: self.balances.clone() },
};
}
}
let mut storage = genesis_config
/// Builds the `RuntimeGenesisConfig` and returns its storage.
pub fn build(self) -> Storage {
let mut storage = self
.genesis_config()
.build_storage()
.expect("Build storage from substrate-test-runtime GenesisConfig");
.expect("Build storage from substrate-test-runtime RuntimeGenesisConfig");
if let Some(heap_pages) = self.heap_pages_override {
storage.top.insert(well_known_keys::HEAP_PAGES.into(), heap_pages.encode());
+264 -5
View File
@@ -26,6 +26,8 @@ pub mod genesismap;
pub mod substrate_test_pallet;
use codec::{Decode, Encode};
#[cfg(not(feature = "disable-genesis-builder"))]
use frame_support::genesis_builder_helper::{build_config, create_default_config};
use frame_support::{
construct_runtime,
dispatch::DispatchClass,
@@ -42,6 +44,8 @@ use frame_system::{
};
use scale_info::TypeInfo;
use sp_std::prelude::*;
#[cfg(not(feature = "std"))]
use sp_std::vec;
use sp_application_crypto::{ecdsa, ed25519, sr25519, RuntimeAppPublic};
use sp_core::{OpaqueMetadata, RuntimeDebug};
@@ -717,6 +721,17 @@ impl_runtime_apis! {
None
}
}
#[cfg(not(feature = "disable-genesis-builder"))]
impl sp_genesis_builder::GenesisBuilder<Block> for Runtime {
fn create_default_config() -> Vec<u8> {
create_default_config::<RuntimeGenesisConfig>()
}
fn build_config(config: Vec<u8>) -> sp_genesis_builder::Result {
build_config::<RuntimeGenesisConfig>(config)
}
}
}
fn test_ed25519_crypto() -> (ed25519::AppSignature, ed25519::AppPublic) {
@@ -850,24 +865,23 @@ pub mod storage_key_generator {
}
let keys: Vec<Vec<&[u8]>> = vec![
vec![b"Babe", b":__STORAGE_VERSION__:"],
vec![b"Babe", b"Authorities"],
vec![b"Babe", b"EpochConfig"],
vec![b"Babe", b"NextAuthorities"],
vec![b"Babe", b"SegmentIndex"],
vec![b"Babe", b":__STORAGE_VERSION__:"],
vec![b"Balances", b":__STORAGE_VERSION__:"],
vec![b"Balances", b"TotalIssuance"],
vec![b"SubstrateTest", b"Authorities"],
vec![b"SubstrateTest", b":__STORAGE_VERSION__:"],
vec![b"SubstrateTest", b"Authorities"],
vec![b"System", b":__STORAGE_VERSION__:"],
vec![b"System", b"LastRuntimeUpgrade"],
vec![b"System", b"ParentHash"],
vec![b"System", b":__STORAGE_VERSION__:"],
vec![b"System", b"UpgradedToTripleRefCount"],
vec![b"System", b"UpgradedToU32RefCount"],
];
let mut expected_keys = keys.iter().map(concat_hashes).collect::<Vec<String>>();
expected_keys.extend(literals.into_iter().map(hex));
let balances_map_keys = (0..16_usize)
@@ -912,7 +926,7 @@ pub mod storage_key_generator {
/// aka when overriding the heap pages to be used by the executor.
pub fn get_expected_storage_hashed_keys(custom_heap_pages: bool) -> Vec<&'static str> {
let mut res = vec![
//System|:__STORAGE_VERSION__:
//SubstrateTest|:__STORAGE_VERSION__:
"00771836bebdd29870ff246d305c578c4e7b9012096b41c4eb3aaf947f6ea429",
//SubstrateTest|Authorities
"00771836bebdd29870ff246d305c578c5e0621c4869aa60c02be9adcc98a0d1d",
@@ -1190,4 +1204,249 @@ mod tests {
);
})
}
#[cfg(not(feature = "disable-genesis-builder"))]
mod genesis_builder_tests {
use super::*;
use crate::genesismap::GenesisStorageBuilder;
use sc_executor::{error::Result, WasmExecutor};
use sc_executor_common::runtime_blob::RuntimeBlob;
use serde_json::json;
use sp_application_crypto::Ss58Codec;
use sp_core::traits::Externalities;
use sp_genesis_builder::Result as BuildResult;
use sp_state_machine::BasicExternalities;
use std::{fs, io::Write};
use storage_key_generator::hex;
pub fn executor_call(
ext: &mut dyn Externalities,
method: &str,
data: &[u8],
) -> Result<Vec<u8>> {
let executor = WasmExecutor::<sp_io::SubstrateHostFunctions>::builder().build();
executor.uncached_call(
RuntimeBlob::uncompress_if_needed(wasm_binary_unwrap()).unwrap(),
ext,
true,
method,
data,
)
}
#[test]
fn build_minimal_genesis_config_works() {
sp_tracing::try_init_simple();
let default_minimal_json = r#"{"system":{"code":"0x"},"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())
.unwrap();
let mut keys = t.into_storages().top.keys().cloned().map(hex).collect::<Vec<String>>();
keys.sort();
let mut expected = [
//SubstrateTest|Authorities
"00771836bebdd29870ff246d305c578c5e0621c4869aa60c02be9adcc98a0d1d",
//Babe|SegmentIndex
"1cb6f36e027abb2091cfb5110ab5087f66e8f035c8adbe7f1547b43c51e6f8a4",
//Babe|EpochConfig
"1cb6f36e027abb2091cfb5110ab5087fdc6b171b77304263c292cc3ea5ed31ef",
//System|UpgradedToU32RefCount
"26aa394eea5630e07c48ae0c9558cef75684a022a34dd8bfa2baaf44f172b710",
//System|ParentHash
"26aa394eea5630e07c48ae0c9558cef78a42f33323cb5ced3b44dd825fda9fcc",
//System::BlockHash|0
"26aa394eea5630e07c48ae0c9558cef7a44704b568d21667356a5a050c118746bb1bdbcacd6ac9340000000000000000",
//System|UpgradedToTripleRefCount
"26aa394eea5630e07c48ae0c9558cef7a7fd6c28836b9a28522dc924110cf439",
// System|LastRuntimeUpgrade
"26aa394eea5630e07c48ae0c9558cef7f9cce9c888469bb1a0dceaa129672ef8",
// :code
"3a636f6465",
// :extrinsic_index
"3a65787472696e7369635f696e646578",
// Balances|TotalIssuance
"c2261276cc9d1f8598ea4b6a74b15c2f57c875e4cff74148e4628f264b974c80",
// added by on_genesis:
// Balances|:__STORAGE_VERSION__:
"c2261276cc9d1f8598ea4b6a74b15c2f4e7b9012096b41c4eb3aaf947f6ea429",
//System|:__STORAGE_VERSION__:
"26aa394eea5630e07c48ae0c9558cef74e7b9012096b41c4eb3aaf947f6ea429",
//Babe|:__STORAGE_VERSION__:
"1cb6f36e027abb2091cfb5110ab5087f4e7b9012096b41c4eb3aaf947f6ea429",
//SubstrateTest|:__STORAGE_VERSION__:
"00771836bebdd29870ff246d305c578c4e7b9012096b41c4eb3aaf947f6ea429",
].into_iter().map(String::from).collect::<Vec<_>>();
expected.sort();
assert_eq!(keys, expected);
}
#[test]
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 json = String::from_utf8(r.into()).expect("returned value is json. qed.");
let expected = r#"{"system":{"code":"0x"},"babe":{"authorities":[],"epochConfig":null},"substrateTest":{"authorities":[]},"balances":{"balances":[]}}"#;
assert_eq!(expected.to_string(), json);
}
#[test]
fn build_config_from_json_works() {
sp_tracing::try_init_simple();
let j = include_str!("test_json/default_genesis_config.json");
let mut t = BasicExternalities::new_empty();
let r = executor_call(&mut t, "GenesisBuilder_build_config", &j.encode()).unwrap();
let r = BuildResult::decode(&mut &r[..]);
assert!(r.is_ok());
let keys = t.into_storages().top.keys().cloned().map(hex).collect::<Vec<String>>();
assert_eq!(keys, storage_key_generator::get_expected_storage_hashed_keys(false));
}
#[test]
fn build_config_from_invalid_json_fails() {
sp_tracing::try_init_simple();
let j = include_str!("test_json/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 = BuildResult::decode(&mut &r[..]).unwrap();
log::info!("result: {:#?}", r);
assert_eq!(r, Err(
sp_runtime::RuntimeString::Owned(
"Invalid JSON blob: unknown field `renamed_authorities`, expected `authorities` or `epochConfig` at line 6 column 25".to_string(),
))
);
}
#[test]
fn build_config_from_incomplete_json_fails() {
sp_tracing::try_init_simple();
let j = include_str!("test_json/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 =
core::result::Result::<(), sp_runtime::RuntimeString>::decode(&mut &r[..]).unwrap();
assert_eq!(
r,
Err(sp_runtime::RuntimeString::Owned(
"Invalid JSON blob: missing field `authorities` at line 13 column 3"
.to_string()
))
);
}
#[test]
fn write_default_config_to_tmp_file() {
if std::env::var("WRITE_DEFAULT_JSON_FOR_STR_GC").is_ok() {
sp_tracing::try_init_simple();
let mut file = fs::OpenOptions::new()
.create(true)
.write(true)
.open("/tmp/default_genesis_config.json")
.unwrap();
let j = serde_json::to_string(&GenesisStorageBuilder::default().genesis_config())
.unwrap()
.into_bytes();
file.write_all(&j).unwrap();
}
}
#[test]
fn build_genesis_config_with_patch_json_works() {
//this tests shows how to do patching on native side
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 mut default_config: serde_json::Value =
serde_json::from_slice(&r[..]).expect("returned value is json. qed.");
// Patch default json with some custom values:
let patch = json!({
"babe": {
"epochConfig": {
"c": [
7,
10
],
"allowed_slots": "PrimaryAndSecondaryPlainSlots"
}
},
"substrateTest": {
"authorities": [
AccountKeyring::Ferdie.public().to_ss58check(),
AccountKeyring::Alice.public().to_ss58check()
],
}
});
json_patch::merge(&mut default_config, &patch);
// Build genesis config using custom json:
let mut t = BasicExternalities::new_empty();
executor_call(
&mut t,
"GenesisBuilder_build_config",
&default_config.to_string().encode(),
)
.unwrap();
// Ensure that custom values are in the genesis storage:
let storage = t.into_storages();
let get_from_storage = |key: &str| -> Vec<u8> {
storage.top.get(&array_bytes::hex2bytes(key).unwrap()).unwrap().clone()
};
//SubstrateTest|Authorities
let value: Vec<u8> = get_from_storage(
"00771836bebdd29870ff246d305c578c5e0621c4869aa60c02be9adcc98a0d1d",
);
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());
//Babe|Authorities
let value: Vec<u8> = get_from_storage(
"1cb6f36e027abb2091cfb5110ab5087fdc6b171b77304263c292cc3ea5ed31ef",
);
assert_eq!(
BabeEpochConfiguration::decode(&mut &value[..]).unwrap(),
BabeEpochConfiguration {
c: (7, 10),
allowed_slots: AllowedSlots::PrimaryAndSecondaryPlainSlots
}
);
// Ensure that some values are default ones:
// Balances|TotalIssuance
let value: Vec<u8> = get_from_storage(
"c2261276cc9d1f8598ea4b6a74b15c2f57c875e4cff74148e4628f264b974c80",
);
assert_eq!(u64::decode(&mut &value[..]).unwrap(), 0);
// :code
let value: Vec<u8> = get_from_storage("3a636f6465");
assert!(Vec::<u8>::decode(&mut &value[..]).is_err());
//System|ParentHash
let value: Vec<u8> = get_from_storage(
"26aa394eea5630e07c48ae0c9558cef78a42f33323cb5ced3b44dd825fda9fcc",
);
assert_eq!(H256::decode(&mut &value[..]).unwrap(), [69u8; 32].into());
}
}
}
@@ -0,0 +1,24 @@
`default_genesis_config.json` file has been generated by the following code:
```
use crate::genesismap::GenesisStorageBuilder;
#[test]
fn write_default_config_to_tmp_file() {
let j = json::to_string(&GenesisStorageBuilder::default().genesis_config()).unwrap().into_bytes();
let mut file = fs::OpenOptions::new()
.create(true)
.write(true)
.open("/tmp/default_genesis_config.json").unwrap();
file.write_all(&j);
}
```
`:code` field has been manually truncated to reduce file size. Test is only
comparing keys, not the values.
`default_genesis_config_invalid.json` is just a broken copy of
`default_genesis_config.json` with `authorities` field renamed to
`renamed_authorities`.
`default_genesis_config_invalid.json` is just an imcomplete copy of
`default_genesis_config.json` with `babe::authorities` field removed.
@@ -0,0 +1,115 @@
{
"system": {
"code": "0x52"
},
"babe": {
"authorities": [
[
"5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY",
1
],
[
"5FHneW46xGXgs5mUiveU4sbTyGBzmstUspZC92UhjJM694ty",
1
],
[
"5FLSigC9HGRKVhB9FiEo4Y3koPsNmBmLJbpXg2mp1hXcS59Y",
1
]
],
"epochConfig": {
"c": [
3,
10
],
"allowed_slots": "PrimaryAndSecondaryPlainSlots"
}
},
"substrateTest": {
"authorities": [
"5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY",
"5FHneW46xGXgs5mUiveU4sbTyGBzmstUspZC92UhjJM694ty",
"5FLSigC9HGRKVhB9FiEo4Y3koPsNmBmLJbpXg2mp1hXcS59Y"
]
},
"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
]
]
}
}
@@ -0,0 +1,101 @@
{
"system": {
"code": "0x52"
},
"babe": {
"epochConfig": {
"c": [
3,
10
],
"allowed_slots": "PrimaryAndSecondaryPlainSlots"
}
},
"substrateTest": {
"authorities": [
"5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY",
"5FHneW46xGXgs5mUiveU4sbTyGBzmstUspZC92UhjJM694ty",
"5FLSigC9HGRKVhB9FiEo4Y3koPsNmBmLJbpXg2mp1hXcS59Y"
]
},
"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
]
]
}
}
@@ -0,0 +1,115 @@
{
"system": {
"code": "0x52"
},
"babe": {
"renamed_authorities": [
[
"5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY",
1
],
[
"5FHneW46xGXgs5mUiveU4sbTyGBzmstUspZC92UhjJM694ty",
1
],
[
"5FLSigC9HGRKVhB9FiEo4Y3koPsNmBmLJbpXg2mp1hXcS59Y",
1
]
],
"epochConfig": {
"c": [
3,
10
],
"allowed_slots": "PrimaryAndSecondaryPlainSlots"
}
},
"substrateTest": {
"authorities": [
"5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY",
"5FHneW46xGXgs5mUiveU4sbTyGBzmstUspZC92UhjJM694ty",
"5FLSigC9HGRKVhB9FiEo4Y3koPsNmBmLJbpXg2mp1hXcS59Y"
]
},
"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
]
]
}
}