domain_block_builder/
genesis_block_builder.rs

1//! Custom genesis block builder to inject correct genesis block.
2
3use sc_chain_spec::{BuildGenesisBlock, construct_genesis_block, resolve_state_version_from_wasm};
4use sc_client_api::{Backend, BlockImportOperation};
5use sc_executor::RuntimeVersionOf;
6use sp_api::ProvideRuntimeApi;
7use sp_blockchain::HeaderBackend;
8use sp_core::H256;
9use sp_core::storage::Storage;
10use sp_domains::{DomainId, DomainsApi};
11use sp_runtime::BuildStorage;
12use sp_runtime::traits::{Block as BlockT, HashingFor};
13use std::marker::PhantomData;
14use std::sync::Arc;
15
16/// Custom genesis block builder to inject correct genesis block for Domains.
17pub struct CustomGenesisBlockBuilder<CClient, CBlock: BlockT, Block: BlockT, B, E> {
18    domain_id: DomainId,
19    consensus_client: Arc<CClient>,
20    genesis_storage: Storage,
21    commit_genesis_state: bool,
22    backend: Arc<B>,
23    executor: E,
24    _data: PhantomData<(CBlock, Block)>,
25}
26
27impl<CClient, CBlock, Block: BlockT, B: Backend<Block>, E: RuntimeVersionOf>
28    CustomGenesisBlockBuilder<CClient, CBlock, Block, B, E>
29where
30    Block: BlockT,
31    B: Backend<Block>,
32    E: RuntimeVersionOf,
33    CBlock: BlockT,
34{
35    /// Constructs a new instance of Genesis block builder
36    pub fn new(
37        domain_id: DomainId,
38        consensus_client: Arc<CClient>,
39        build_genesis_storage: &dyn BuildStorage,
40        commit_genesis_state: bool,
41        backend: Arc<B>,
42        executor: E,
43    ) -> sp_blockchain::Result<Self> {
44        let genesis_storage = build_genesis_storage
45            .build_storage()
46            .map_err(sp_blockchain::Error::Storage)?;
47        Ok(Self {
48            domain_id,
49            consensus_client,
50            genesis_storage,
51            commit_genesis_state,
52            backend,
53            executor,
54            _data: Default::default(),
55        })
56    }
57}
58
59impl<CClient, CBlock, Block: BlockT, B: Backend<Block>, E: RuntimeVersionOf>
60    BuildGenesisBlock<Block> for CustomGenesisBlockBuilder<CClient, CBlock, Block, B, E>
61where
62    Block: BlockT,
63    Block::Hash: From<H256>,
64    B: Backend<Block>,
65    E: RuntimeVersionOf,
66    CBlock: BlockT,
67    CBlock::Hash: From<H256>,
68    CClient: ProvideRuntimeApi<CBlock> + HeaderBackend<CBlock>,
69    CClient::Api: DomainsApi<CBlock, Block::Header>,
70{
71    type BlockImportOperation = <B as Backend<Block>>::BlockImportOperation;
72
73    fn build_genesis_block(self) -> sp_blockchain::Result<(Block, Self::BlockImportOperation)> {
74        let Self {
75            domain_id,
76            consensus_client,
77            genesis_storage,
78            commit_genesis_state,
79            backend,
80            executor,
81            _data,
82        } = self;
83
84        let maybe_expected_state_root = {
85            let runtime_api = consensus_client.runtime_api();
86            let consensus_best_hash = consensus_client.info().best_hash;
87
88            runtime_api
89                .genesis_state_root(consensus_best_hash, domain_id)?
90                .map(Into::into)
91        };
92
93        let genesis_state_version =
94            resolve_state_version_from_wasm::<_, HashingFor<Block>>(&genesis_storage, &executor)?;
95        let mut op = backend.begin_operation()?;
96        let state_root =
97            op.set_genesis_state(genesis_storage, commit_genesis_state, genesis_state_version)?;
98
99        let genesis_block = if let Some(expected_state_root) = maybe_expected_state_root
100            && expected_state_root != state_root
101        {
102            construct_genesis_block::<Block>(expected_state_root, genesis_state_version)
103        } else {
104            construct_genesis_block::<Block>(state_root, genesis_state_version)
105        };
106
107        Ok((genesis_block, op))
108    }
109}