subcoin_service/
genesis_block_builder.rs1use sc_client_api::BlockImportOperation;
2use sc_client_api::backend::Backend;
3use sc_executor::RuntimeVersionOf;
4use sc_service::BuildGenesisBlock;
5use sp_core::Encode;
6use sp_core::storage::Storage;
7use sp_runtime::BuildStorage;
8use sp_runtime::traits::{Block as BlockT, HashingFor, Header as HeaderT};
9use std::marker::PhantomData;
10use std::sync::Arc;
11
12pub struct GenesisBlockBuilder<Block: BlockT, B, E, TransactionAdapter> {
17 network: bitcoin::Network,
18 genesis_storage: Storage,
19 commit_genesis_state: bool,
20 backend: Arc<B>,
21 executor: E,
22 _phantom: PhantomData<(Block, TransactionAdapter)>,
23}
24
25impl<Block: BlockT, B, E: Clone, TransactionAdapter> Clone
26 for GenesisBlockBuilder<Block, B, E, TransactionAdapter>
27{
28 fn clone(&self) -> Self {
29 Self {
30 network: self.network,
31 genesis_storage: self.genesis_storage.clone(),
32 commit_genesis_state: self.commit_genesis_state,
33 backend: self.backend.clone(),
34 executor: self.executor.clone(),
35 _phantom: Default::default(),
36 }
37 }
38}
39
40impl<Block, B, E, TransactionAdapter> GenesisBlockBuilder<Block, B, E, TransactionAdapter>
41where
42 Block: BlockT,
43 B: Backend<Block>,
44 E: RuntimeVersionOf,
45 TransactionAdapter: subcoin_primitives::BitcoinTransactionAdapter<Block>,
46{
47 pub fn new(
49 network: bitcoin::Network,
50 build_genesis_storage: &dyn BuildStorage,
51 commit_genesis_state: bool,
52 backend: Arc<B>,
53 executor: E,
54 ) -> sp_blockchain::Result<Self> {
55 let genesis_storage = build_genesis_storage
56 .build_storage()
57 .map_err(sp_blockchain::Error::Storage)?;
58 Ok(Self {
59 network,
60 genesis_storage,
61 commit_genesis_state,
62 backend,
63 executor,
64 _phantom: Default::default(),
65 })
66 }
67}
68
69fn substrate_genesis_block<Block, TransactionAdapter>(
70 network: bitcoin::Network,
71 state_root: Block::Hash,
72) -> Block
73where
74 Block: BlockT,
75 TransactionAdapter: subcoin_primitives::BitcoinTransactionAdapter<Block>,
76{
77 let block = bitcoin::constants::genesis_block(network);
78
79 let extrinsics = block
80 .txdata
81 .clone()
82 .into_iter()
83 .map(TransactionAdapter::bitcoin_transaction_into_extrinsic)
84 .collect::<Vec<_>>();
85
86 let extrinsics_root = frame_system::extrinsics_data_root::<HashingFor<Block>>(
87 extrinsics.iter().map(|xt| xt.encode()).collect(),
88 sp_core::storage::StateVersion::try_from(subcoin_runtime::VERSION.system_version)
89 .expect("Runtime system version config must be valid; qed"),
90 );
91
92 let digest = subcoin_primitives::substrate_header_digest(&block.header);
93
94 let header = <<Block as BlockT>::Header as HeaderT>::new(
95 0u32.into(),
96 extrinsics_root,
97 state_root,
98 Default::default(),
99 digest,
100 );
101
102 Block::new(header, extrinsics)
103}
104
105impl<Block, B, E, TransactionAdapter> BuildGenesisBlock<Block>
106 for GenesisBlockBuilder<Block, B, E, TransactionAdapter>
107where
108 Block: BlockT,
109 B: Backend<Block>,
110 E: RuntimeVersionOf,
111 TransactionAdapter: subcoin_primitives::BitcoinTransactionAdapter<Block>,
112{
113 type BlockImportOperation = <B as Backend<Block>>::BlockImportOperation;
114
115 fn build_genesis_block(self) -> sp_blockchain::Result<(Block, Self::BlockImportOperation)> {
116 let Self {
117 network,
118 genesis_storage,
119 commit_genesis_state,
120 backend,
121 executor,
122 _phantom,
123 } = self;
124
125 let genesis_state_version = sc_service::resolve_state_version_from_wasm::<
126 _,
127 HashingFor<Block>,
128 >(&genesis_storage, &executor)?;
129
130 let mut op = backend.begin_operation()?;
131 let state_root =
132 op.set_genesis_state(genesis_storage, commit_genesis_state, genesis_state_version)?;
133
134 let genesis_block =
135 substrate_genesis_block::<Block, TransactionAdapter>(network, state_root);
136
137 Ok((genesis_block, op))
138 }
139}