From 54119561e07706d40f65c9452a4fd1f2413e93d0 Mon Sep 17 00:00:00 2001 From: Dan Forbes Date: Mon, 4 May 2020 18:06:16 -0700 Subject: [PATCH] Genesis configuration --- current/runtime/storage.md | 97 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 93 insertions(+), 4 deletions(-) diff --git a/current/runtime/storage.md b/current/runtime/storage.md index 569749e..bbaa1f7 100644 --- a/current/runtime/storage.md +++ b/current/runtime/storage.md @@ -243,13 +243,102 @@ decl_storage! { } ``` -### Genesis Config +### Genesis Configuration + +Substrate's runtime storage APIs include capabilities to initialize storage items in the genesis +block of your blockchain. The genesis storage configuration APIs expose a number of mechanisms for +initializing storage, all of which have entry points in the `decl_storage` macro. These mechanisms +all result in the creation of a `GenesisConfig` data type that implements +[the `sp_runtime::BuildModuleGenesisStorage` trait](https://crates.parity.io/sp_runtime/trait.BuildModuleGenesisStorage.html) +and will be added to the storage item's module (e.g. +[`Struct pallet_balances::GenesisConfig`](https://crates.parity.io/pallet_balances/struct.GenesisConfig.html)); +storage items that are tagged for genesis configuration will have a corresponding attribute on this +data type. In order to consume a module's genesis configuration capabilities, you must include the +`Config` element when adding the module to your runtime with +[the `construct_runtime` macro](https://crates.parity.io/frame_support/macro.construct_runtime.html). +All the `GenesisConfig` types for the modules that inform a runtime will be aggregated into a single +`GenesisConfig` type for that runtime, which implements +[the `sp_runtime::BuildStorage` trait](https://crates.parity.io/sp_runtime/trait.BuildStorage.html) +(e.g. +[`Struct node_template_runtime::GenesisConfig`](https://crates.parity.io/node_template_runtime/struct.GenesisConfig.html)); +each attribute on this type corresponds to a `GenesisConfig` from one of the runtime's modules. +Ultimately, the runtime's `GenesisConfig` is exposed by way of +[the `sc_chain_spec::ChainSpec` trait](https://crates.parity.io/sc_chain_spec/trait.ChainSpec.html). +For a complete and concrete example of using Substrate's genesis storage configuration capabilities, +refer to the `decl_storage` macro in +[the Society pallet](https://github.com/paritytech/substrate/blob/master/frame/society/src/lib.rs) +as well as the genesis configuration for the Society module's storage in +[the chain specification that ships with the Substrate code base](https://github.com/paritytech/substrate/blob/master/bin/node/cli/src/chain_spec.rs). +Keep reading for more detailed descriptions of these capabilities. + +#### `config` + +When you use the `decl_storage` macro to declare a storage item, you can provide an optional +`config` extension that will add an attribute to the module's `GenesisConfig` data type; the value +of this attribute will be used as the initial value of the storage item in your chain's genesis +block. The `config` extension takes a parameter that will determine the name of the attribute on the +`GenesisConfig` data type; this parameter is optional if [the `get` extension](#Getter-Methods) is +provided (the name of the `get` function is used as the attribute's name). + +Here is an example that demonstrates using the `config` extension with a Storage Value named `MyVal` +to create an attribute named `init_val` on the `GenesisConfig` data type for the Storage Value's +module. This attribute is then used in an example that demonstrates using the `GenesisConfig` types +to set the Storage Value's initial value in your chain's genesis block. + +In `my_module/src/lib.rs`: -You can define -[an optional `GenesisConfig`](https://crates.parity.io/frame_support/macro.decl_storage.html#genesisconfig) -struct in order to initialize storage items in the genesis block of your blockchain. +```rust +decl_storage! { + trait Store for Module as MyModule { + pub MyVal get(fn my_val) config(init_val): u64; + } +} +``` + +In `chain_spec.rs`: + +```rust +GenesisConfig { + my_module: Some(MyModuleConfig { + init_val: 221u64 + SOME_CONSTANT_VALUE, + }), +} +``` +#### `build` + +Whereas [the `config` extension](#config) to the `decl_storage` macro allows you to configure a +module's genesis storage state within a chain specification, the `build` extension allows you to +perform this same task within the module itself (this gives you access to the module's private +functions). Like `config`, the `build` extension accepts a single parameter, but in this case the +parameter is always required and must be a closure, which is essentially a function. The `build` +closure will be invoked with a single parameter whose type will be the module's `GenesisConfig` type +(this gives you easy access to all the attributes of the `GenesisConfig` type). You may use the +`build` extension along with the `config` extension for a single storage item; in this case, the +module's `GenesisConfig` type will have an attribute that corresponds to what was set using `config` +whose value will be set in the chain specification, but it will be the value returned by the `build` +closure that will be used to set the storage item's genesis value. + +Here is an example that demonstrates using `build` to set the initial value of a storage item. In +this case, the example involves two storage items: one that represents a list of member account IDs +and another that designates a special member from the list, the prime member. The list of members is +provided by way of the `config` extension and the prime member, who is assumed to be the first +element in the list of members, is set using the `build` extension. + +```rust +decl_storage! { + trait Store for Module as MyModule { + pub Members config(orig_ids): Vec; + pub Prime build(|config: &GenesisConfig| config.orig_ids.first().cloned()): T::AccountId; + } +} +``` + +#### `add_extra_genesis` + +```js // TODO +``` ## Accessing Storage Items