referrerpolicy=no-referrer-when-downgrade

chain_spec_guide_runtime/
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//! Presets for the chain-spec demo runtime.
19
20use crate::{
21	pallets::{FooEnum, SomeFooData1, SomeFooData2},
22	runtime::{BarConfig, FooConfig, RuntimeGenesisConfig},
23};
24use alloc::vec;
25use frame_support::build_struct_json_patch;
26use serde_json::{json, to_string, Value};
27use sp_application_crypto::Ss58Codec;
28use sp_keyring::Sr25519Keyring;
29
30/// A demo preset with strings only.
31pub const PRESET_1: &str = "preset_1";
32/// A demo preset with real types.
33pub const PRESET_2: &str = "preset_2";
34/// Another demo preset with real types and manually created json object.
35pub const PRESET_3: &str = "preset_3";
36/// A single value patch preset.
37pub const PRESET_4: &str = "preset_4";
38/// A single value patch preset.
39pub const PRESET_INVALID: &str = "preset_invalid";
40
41#[docify::export]
42/// Function provides a preset demonstrating how use string representation of preset's internal
43/// values.
44fn preset_1() -> Value {
45	json!({
46		"bar": {
47			"initialAccount": "5CiPPseXPECbkjWCa6MnjNokrgYjMqmKndv2rSnekmSK2DjL",
48		},
49		"foo": {
50			"someEnum": {
51				"Data2": {
52					"values": "0x0c0f"
53				}
54			},
55			"someStruct" : {
56				"fieldA": 10,
57				"fieldB": 20
58			},
59			"someInteger": 100
60		},
61	})
62}
63
64#[docify::export]
65/// Function provides a preset demonstrating how to create a preset using
66/// [`build_struct_json_patch`] macro.
67fn preset_2() -> Value {
68	build_struct_json_patch!(RuntimeGenesisConfig {
69		foo: FooConfig {
70			some_integer: 200,
71			some_enum: FooEnum::Data2(SomeFooData2 { values: vec![0x0c, 0x10] })
72		},
73		bar: BarConfig { initial_account: Some(Sr25519Keyring::Ferdie.public().into()) },
74	})
75}
76
77#[docify::export]
78/// Function provides a preset demonstrating how use the actual types to manually create a JSON
79/// representing the preset.
80fn preset_3() -> Value {
81	json!({
82		"bar": {
83			"initialAccount": Sr25519Keyring::Alice.public().to_ss58check(),
84		},
85		"foo": {
86			"someEnum": FooEnum::Data1(
87				SomeFooData1 {
88					a: 12,
89					b: 16
90				}
91			),
92			"someInteger": 300
93		},
94	})
95}
96
97#[docify::export]
98/// Function provides a minimal preset demonstrating how to patch single key in
99/// `RuntimeGenesisConfig` using [`build_struct_json_patch`] macro.
100pub fn preset_4() -> Value {
101	build_struct_json_patch!(RuntimeGenesisConfig {
102		foo: FooConfig { some_enum: FooEnum::Data2(SomeFooData2 { values: vec![0x0c, 0x10] }) },
103	})
104}
105
106#[docify::export]
107/// Function provides an invalid preset demonstrating how important is use of
108/// `deny_unknown_fields` in data structures used in `GenesisConfig`.
109fn preset_invalid() -> Value {
110	json!({
111		"foo": {
112			"someStruct": {
113				"fieldC": 5
114			},
115		},
116	})
117}
118
119/// Provides a JSON representation of preset identified by given `id`.
120///
121/// If no preset with given `id` exits `None` is returned.
122#[docify::export]
123pub fn get_builtin_preset(id: &sp_genesis_builder::PresetId) -> Option<alloc::vec::Vec<u8>> {
124	let preset = match id.as_ref() {
125		PRESET_1 => preset_1(),
126		PRESET_2 => preset_2(),
127		PRESET_3 => preset_3(),
128		PRESET_4 => preset_4(),
129		PRESET_INVALID => preset_invalid(),
130		_ => return None,
131	};
132
133	Some(
134		to_string(&preset)
135			.expect("serialization to json is expected to work. qed.")
136			.into_bytes(),
137	)
138}
139
140#[test]
141#[docify::export]
142fn check_presets() {
143	let builder = sc_chain_spec::GenesisConfigBuilderRuntimeCaller::<()>::new(
144		crate::WASM_BINARY.expect("wasm binary shall exists"),
145	);
146	assert!(builder.get_storage_for_named_preset(Some(&PRESET_1.to_string())).is_ok());
147	assert!(builder.get_storage_for_named_preset(Some(&PRESET_2.to_string())).is_ok());
148	assert!(builder.get_storage_for_named_preset(Some(&PRESET_3.to_string())).is_ok());
149	assert!(builder.get_storage_for_named_preset(Some(&PRESET_4.to_string())).is_ok());
150}
151
152#[test]
153#[docify::export]
154fn invalid_preset_works() {
155	let builder = sc_chain_spec::GenesisConfigBuilderRuntimeCaller::<()>::new(
156		crate::WASM_BINARY.expect("wasm binary shall exists"),
157	);
158	// Even though a preset contains invalid_key, conversion to raw storage does not fail. This is
159	// because the [`FooStruct`] structure is not annotated with `deny_unknown_fields` [`serde`]
160	// attribute.
161	// This may lead to hard to debug problems, that's why using ['deny_unknown_fields'] is
162	// recommended.
163	assert!(builder.get_storage_for_named_preset(Some(&PRESET_INVALID.to_string())).is_ok());
164}