domain_block_builder/
genesis_block_builder.rs1use hexlit::hex;
4use sc_chain_spec::{construct_genesis_block, resolve_state_version_from_wasm, BuildGenesisBlock};
5use sc_client_api::{Backend, BlockImportOperation};
6use sc_executor::RuntimeVersionOf;
7use sp_api::ProvideRuntimeApi;
8use sp_blockchain::HeaderBackend;
9use sp_core::storage::Storage;
10use sp_core::H256;
11use sp_domains::{DomainId, DomainsApi};
12use sp_runtime::traits::{Block as BlockT, HashingFor};
13use sp_runtime::BuildStorage;
14use std::marker::PhantomData;
15use std::sync::Arc;
16
17pub struct CustomGenesisBlockBuilder<CClient, CBlock: BlockT, Block: BlockT, B, E> {
19 domain_id: DomainId,
20 consensus_client: Arc<CClient>,
21 genesis_storage: Storage,
22 commit_genesis_state: bool,
23 backend: Arc<B>,
24 executor: E,
25 _data: PhantomData<(CBlock, Block)>,
26}
27
28impl<CClient, CBlock, Block: BlockT, B: Backend<Block>, E: RuntimeVersionOf>
29 CustomGenesisBlockBuilder<CClient, CBlock, Block, B, E>
30where
31 Block: BlockT,
32 B: Backend<Block>,
33 E: RuntimeVersionOf,
34 CBlock: BlockT,
35{
36 pub fn new(
38 domain_id: DomainId,
39 consensus_client: Arc<CClient>,
40 build_genesis_storage: &dyn BuildStorage,
41 commit_genesis_state: bool,
42 backend: Arc<B>,
43 executor: E,
44 ) -> sp_blockchain::Result<Self> {
45 let genesis_storage = build_genesis_storage
46 .build_storage()
47 .map_err(sp_blockchain::Error::Storage)?;
48 Ok(Self {
49 domain_id,
50 consensus_client,
51 genesis_storage,
52 commit_genesis_state,
53 backend,
54 executor,
55 _data: Default::default(),
56 })
57 }
58}
59
60impl<CClient, CBlock, Block: BlockT, B: Backend<Block>, E: RuntimeVersionOf>
61 BuildGenesisBlock<Block> for CustomGenesisBlockBuilder<CClient, CBlock, Block, B, E>
62where
63 Block: BlockT,
64 Block::Hash: From<H256>,
65 B: Backend<Block>,
66 E: RuntimeVersionOf,
67 CBlock: BlockT,
68 CBlock::Hash: From<H256>,
69 CClient: ProvideRuntimeApi<CBlock> + HeaderBackend<CBlock>,
70 CClient::Api: DomainsApi<CBlock, Block::Header>,
71{
72 type BlockImportOperation = <B as Backend<Block>>::BlockImportOperation;
73
74 fn build_genesis_block(self) -> sp_blockchain::Result<(Block, Self::BlockImportOperation)> {
75 let Self {
76 domain_id,
77 consensus_client,
78 genesis_storage,
79 commit_genesis_state,
80 backend,
81 executor,
82 _data,
83 } = self;
84
85 let maybe_expected_state_root = {
86 let runtime_api = consensus_client.runtime_api();
87 let consensus_best_hash = consensus_client.info().best_hash;
88
89 match runtime_api.genesis_state_root(consensus_best_hash, domain_id)? {
90 Some(hash) => Some(hash.into()),
91 None => {
92 if consensus_client.info().genesis_hash
96 == H256::from(hex!(
97 "0x295aeafca762a304d92ee1505548695091f6082d3f0aa4d092ac3cd6397a6c5e"
98 ))
99 .into()
100 && domain_id == DomainId::new(0)
101 {
102 Some(
103 H256::from(hex!(
104 "0x530eae1878202aa0ab5997eadf2b7245ee78f44a35ab25ff84151fab489aa334"
105 ))
106 .into(),
107 )
108 } else {
109 None
110 }
111 }
112 }
113 };
114
115 let genesis_state_version =
116 resolve_state_version_from_wasm::<_, HashingFor<Block>>(&genesis_storage, &executor)?;
117 let mut op = backend.begin_operation()?;
118 let state_root =
119 op.set_genesis_state(genesis_storage, commit_genesis_state, genesis_state_version)?;
120
121 let genesis_block = if let Some(expected_state_root) = maybe_expected_state_root
122 && expected_state_root != state_root
123 {
124 construct_genesis_block::<Block>(expected_state_root, genesis_state_version)
125 } else {
126 construct_genesis_block::<Block>(state_root, genesis_state_version)
127 };
128
129 Ok((genesis_block, op))
130 }
131}