referrerpolicy=no-referrer-when-downgrade

kitchensink_runtime/
genesis_config_presets.rs

1// This file is part of Substrate.
2
3// Copyright (C) Parity Technologies (UK) Ltd.
4// SPDX-License-Identifier: Apache-2.0
5
6// Licensed under the Apache License, Version 2.0 (the "License");
7// you may not use this file except in compliance with the License.
8// You may obtain a copy of the License at
9//
10// 	http://www.apache.org/licenses/LICENSE-2.0
11//
12// Unless required by applicable law or agreed to in writing, software
13// distributed under the License is distributed on an "AS IS" BASIS,
14// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15// See the License for the specific language governing permissions and
16// limitations under the License.
17
18//! Genesis Presets for the Kitchensink Runtime
19
20use polkadot_sdk::*;
21
22use crate::{
23	constants::currency::*, frame_support::build_struct_json_patch, AccountId, AssetsConfig,
24	BabeConfig, Balance, BalancesConfig, ElectionsConfig, NominationPoolsConfig, ReviveConfig,
25	RuntimeGenesisConfig, SessionConfig, SessionKeys, SocietyConfig, StakerStatus, StakingConfig,
26	SudoConfig, TechnicalCommitteeConfig, BABE_GENESIS_EPOCH_CONFIG,
27};
28use alloc::{vec, vec::Vec};
29use pallet_im_online::sr25519::AuthorityId as ImOnlineId;
30use pallet_revive::AddressMapper;
31use sp_authority_discovery::AuthorityId as AuthorityDiscoveryId;
32use sp_consensus_babe::AuthorityId as BabeId;
33use sp_consensus_beefy::ecdsa_crypto::AuthorityId as BeefyId;
34use sp_consensus_grandpa::AuthorityId as GrandpaId;
35use sp_core::{crypto::get_public_from_string_or_panic, sr25519, Get};
36use sp_genesis_builder::PresetId;
37use sp_keyring::Sr25519Keyring;
38use sp_mixnet::types::AuthorityId as MixnetId;
39use sp_runtime::Perbill;
40
41pub const ENDOWMENT: Balance = 10_000_000 * DOLLARS;
42pub const STASH: Balance = ENDOWMENT / 1000;
43
44/// The staker type as supplied ot the Staking config.
45pub type Staker = (AccountId, AccountId, Balance, StakerStatus<AccountId>);
46
47/// Helper function to create RuntimeGenesisConfig json patch for testing.
48pub fn kitchensink_genesis(
49	initial_authorities: Vec<(AccountId, AccountId, SessionKeys)>,
50	root_key: AccountId,
51	endowed_accounts: Vec<AccountId>,
52	stakers: Vec<Staker>,
53) -> serde_json::Value {
54	let validator_count = initial_authorities.len() as u32;
55	let minimum_validator_count = validator_count;
56
57	let collective = collective(&endowed_accounts);
58
59	build_struct_json_patch!(RuntimeGenesisConfig {
60		balances: BalancesConfig {
61			balances: endowed_accounts.iter().cloned().map(|x| (x, ENDOWMENT)).collect(),
62			..Default::default()
63		},
64		session: SessionConfig {
65			keys: initial_authorities
66				.iter()
67				.map(|x| { (x.0.clone(), x.1.clone(), x.2.clone()) })
68				.collect(),
69		},
70		staking: StakingConfig {
71			validator_count,
72			minimum_validator_count,
73			invulnerables: initial_authorities
74				.iter()
75				.map(|x| x.0.clone())
76				.collect::<Vec<_>>()
77				.try_into()
78				.expect("Too many invulnerable validators: upper limit is MaxInvulnerables from pallet staking config"),
79			slash_reward_fraction: Perbill::from_percent(10),
80			stakers,
81		},
82		elections: ElectionsConfig {
83			members: collective.iter().cloned().map(|member| (member, STASH)).collect(),
84		},
85		technical_committee: TechnicalCommitteeConfig { members: collective },
86		sudo: SudoConfig { key: Some(root_key) },
87		babe: BabeConfig { epoch_config: BABE_GENESIS_EPOCH_CONFIG },
88		society: SocietyConfig { pot: 0 },
89		assets: AssetsConfig {
90			// This asset is used by the NIS pallet as counterpart currency.
91			assets: vec![(9, Sr25519Keyring::Alice.to_account_id(), true, 1)],
92			..Default::default()
93		},
94		nomination_pools: NominationPoolsConfig {
95			min_create_bond: 10 * DOLLARS,
96			min_join_bond: 1 * DOLLARS,
97		},
98		revive: ReviveConfig {
99			mapped_accounts: if <crate::Runtime as pallet_revive::Config>::AutoMap::get() {
100				vec![]
101			} else {
102				endowed_accounts
103					.iter()
104					.filter(|x| {
105						!<crate::Runtime as pallet_revive::Config>::AddressMapper::is_eth_derived(x)
106					})
107					.cloned()
108					.collect()
109			},
110		},
111	})
112}
113
114/// Provides the JSON representation of predefined genesis config for given `id`.
115pub fn get_preset(id: &PresetId) -> Option<Vec<u8>> {
116	// Note: Can't use `Sr25519Keyring::Alice.to_seed()` because the seed comes with `//`.
117	let (alice_stash, alice, alice_session_keys) = authority_keys_from_seed("Alice");
118	let (bob_stash, _bob, bob_session_keys) = authority_keys_from_seed("Bob");
119
120	let endowed = well_known_including_eth_accounts();
121
122	let patch = match id.as_ref() {
123		sp_genesis_builder::DEV_RUNTIME_PRESET => kitchensink_genesis(
124			// Use stash as controller account, otherwise grandpa can't load the authority set at
125			// genesis.
126			vec![(alice_stash.clone(), alice_stash.clone(), alice_session_keys)],
127			alice.clone(),
128			endowed,
129			vec![validator(alice_stash.clone())],
130		),
131		sp_genesis_builder::LOCAL_TESTNET_RUNTIME_PRESET => kitchensink_genesis(
132			vec![
133				// Use stash as controller account, otherwise grandpa can't load the authority set
134				// at genesis.
135				(alice_stash.clone(), alice_stash.clone(), alice_session_keys),
136				(bob_stash.clone(), bob_stash.clone(), bob_session_keys),
137			],
138			alice,
139			endowed,
140			vec![validator(alice_stash), validator(bob_stash)],
141		),
142		_ => return None,
143	};
144
145	Some(
146		serde_json::to_string(&patch)
147			.expect("serialization to json is expected to work. qed.")
148			.into_bytes(),
149	)
150}
151
152/// List of supported presets.
153pub fn preset_names() -> Vec<PresetId> {
154	vec![
155		PresetId::from(sp_genesis_builder::DEV_RUNTIME_PRESET),
156		PresetId::from(sp_genesis_builder::LOCAL_TESTNET_RUNTIME_PRESET),
157	]
158}
159
160/// Sets up the `account` to be a staker of validator variant as supplied to the
161/// staking config.
162pub fn validator(account: AccountId) -> Staker {
163	// validator, controller, stash, staker status
164	(account.clone(), account, STASH, StakerStatus::Validator)
165}
166
167/// Extract some accounts from endowed to be put into the collective.
168fn collective(endowed: &[AccountId]) -> Vec<AccountId> {
169	const MAX_COLLECTIVE_SIZE: usize = 50;
170	let endowed_accounts_count = endowed.len();
171	endowed
172		.iter()
173		.take((endowed_accounts_count.div_ceil(2)).min(MAX_COLLECTIVE_SIZE))
174		.cloned()
175		.collect()
176}
177
178/// The Keyring's wellknown accounts + Alith and Baltathar.
179///
180/// Some integration tests require these ETH accounts.
181pub fn well_known_including_eth_accounts() -> Vec<AccountId> {
182	Sr25519Keyring::well_known()
183		.map(|k| k.to_account_id())
184		.chain([
185			// subxt_signer::eth::dev::alith()
186			array_bytes::hex_n_into_unchecked(
187				"f24ff3a9cf04c71dbc94d0b566f7a27b94566caceeeeeeeeeeeeeeeeeeeeeeee",
188			),
189			// subxt_signer::eth::dev::baltathar()
190			array_bytes::hex_n_into_unchecked(
191				"3cd0a705a2dc65e5b1e1205896baa2be8a07c6e0eeeeeeeeeeeeeeeeeeeeeeee",
192			),
193		])
194		.collect::<Vec<_>>()
195}
196
197/// Helper function to generate stash, controller and session key from seed.
198///
199/// Note: `//` is prepended internally.
200pub fn authority_keys_from_seed(seed: &str) -> (AccountId, AccountId, SessionKeys) {
201	(
202		get_public_from_string_or_panic::<sr25519::Public>(&alloc::format!("{seed}//stash")).into(),
203		get_public_from_string_or_panic::<sr25519::Public>(seed).into(),
204		session_keys_from_seed(seed),
205	)
206}
207
208pub fn session_keys(
209	grandpa: GrandpaId,
210	babe: BabeId,
211	im_online: ImOnlineId,
212	authority_discovery: AuthorityDiscoveryId,
213	mixnet: MixnetId,
214	beefy: BeefyId,
215) -> SessionKeys {
216	SessionKeys { grandpa, babe, im_online, authority_discovery, mixnet, beefy }
217}
218
219/// We have this method as there is no straight forward way to convert the
220/// account keyring into these ids.
221///
222/// Note: `//` is prepended internally.
223pub fn session_keys_from_seed(seed: &str) -> SessionKeys {
224	session_keys(
225		get_public_from_string_or_panic::<GrandpaId>(seed),
226		get_public_from_string_or_panic::<BabeId>(seed),
227		get_public_from_string_or_panic::<ImOnlineId>(seed),
228		get_public_from_string_or_panic::<AuthorityDiscoveryId>(seed),
229		get_public_from_string_or_panic::<MixnetId>(seed),
230		get_public_from_string_or_panic::<BeefyId>(seed),
231	)
232}