1pub mod domain_block_er;
4
5use sc_client_api::execution_extensions::ExtensionsFactory as ExtensionsFactoryT;
6use sc_executor::RuntimeVersionOf;
7use sp_api::ProvideRuntimeApi;
8use sp_blockchain::HeaderBackend;
9use sp_core::traits::CodeExecutor;
10use sp_core::H256;
11use sp_domains::DomainsApi;
12use sp_domains_fraud_proof::storage_proof::{
13 FraudProofStorageKeyProviderInstance, FraudProofStorageKeyRequest,
14};
15use sp_domains_fraud_proof::FraudProofApi;
16use sp_externalities::Extensions;
17use sp_messenger_host_functions::{MessengerApi, MessengerExtension, MessengerHostFunctionsImpl};
18use sp_runtime::traits::{Block as BlockT, Header as HeaderT, NumberFor, One};
19use sp_subspace_mmr::host_functions::{MmrApi, SubspaceMmrExtension, SubspaceMmrHostFunctionsImpl};
20use sp_subspace_mmr::ConsensusChainMmrLeafProof;
21use std::marker::PhantomData;
22use std::sync::Arc;
23
24#[cfg(not(feature = "runtime-benchmarks"))]
26pub type HostFunctions = (
27 sp_auto_id::auto_id_runtime_interface::HostFunctions,
28 sp_io::SubstrateHostFunctions,
29 sp_messenger_host_functions::HostFunctions,
30 sp_subspace_mmr::DomainHostFunctions,
31);
32
33#[cfg(feature = "runtime-benchmarks")]
35pub type HostFunctions = (
36 sp_auto_id::auto_id_runtime_interface::HostFunctions,
37 sp_io::SubstrateHostFunctions,
38 sp_messenger_host_functions::HostFunctions,
39 sp_subspace_mmr::DomainHostFunctions,
40 frame_benchmarking::benchmarking::HostFunctions,
41);
42
43pub type RuntimeExecutor = sc_executor::WasmExecutor<HostFunctions>;
45
46pub struct ExtensionsFactory<CClient, CBlock, Block, Executor> {
48 consensus_client: Arc<CClient>,
49 executor: Arc<Executor>,
50 confirmation_depth_k: u32,
51 _marker: PhantomData<(CBlock, Block)>,
52}
53
54impl<CClient, CBlock, Block, Executor> ExtensionsFactory<CClient, CBlock, Block, Executor> {
55 pub fn new(
56 consensus_client: Arc<CClient>,
57 executor: Arc<Executor>,
58 confirmation_depth_k: u32,
59 ) -> Self {
60 Self {
61 consensus_client,
62 executor,
63 confirmation_depth_k,
64 _marker: Default::default(),
65 }
66 }
67}
68
69impl<CClient, CBlock, Block, Executor> ExtensionsFactoryT<Block>
70 for ExtensionsFactory<CClient, CBlock, Block, Executor>
71where
72 Block: BlockT,
73 CBlock: BlockT,
74 CBlock::Hash: From<H256> + Into<H256>,
75 CClient: HeaderBackend<CBlock> + ProvideRuntimeApi<CBlock> + 'static,
76 CClient::Api: MmrApi<CBlock, H256, NumberFor<CBlock>>
77 + MessengerApi<CBlock, NumberFor<CBlock>, CBlock::Hash>
78 + DomainsApi<CBlock, Block::Header>,
79 Executor: CodeExecutor + RuntimeVersionOf,
80{
81 fn extensions_for(
82 &self,
83 _block_hash: Block::Hash,
84 _block_number: NumberFor<Block>,
85 ) -> Extensions {
86 let mut exts = Extensions::new();
87 exts.register(SubspaceMmrExtension::new(Arc::new(
88 SubspaceMmrHostFunctionsImpl::<CBlock, _>::new(
89 self.consensus_client.clone(),
90 self.confirmation_depth_k,
91 ),
92 )));
93
94 exts.register(MessengerExtension::new(Arc::new(
95 MessengerHostFunctionsImpl::<CBlock, _, Block, _>::new(
96 self.consensus_client.clone(),
97 self.executor.clone(),
98 ),
99 )));
100
101 exts.register(sp_auto_id::host_functions::HostFunctionExtension::new(
102 Arc::new(sp_auto_id::host_functions::HostFunctionsImpl),
103 ));
104
105 exts
106 }
107}
108
109pub struct FPStorageKeyProvider<CBlock, DomainHeader, CClient> {
110 consensus_client: Arc<CClient>,
111 _phantom: PhantomData<(CBlock, DomainHeader)>,
112}
113
114impl<CBlock, DomainHeader, CClient> Clone for FPStorageKeyProvider<CBlock, DomainHeader, CClient> {
115 fn clone(&self) -> Self {
116 Self {
117 consensus_client: self.consensus_client.clone(),
118 _phantom: self._phantom,
119 }
120 }
121}
122
123impl<CBlock, DomainHeader, CClient> FPStorageKeyProvider<CBlock, DomainHeader, CClient> {
124 pub fn new(consensus_client: Arc<CClient>) -> Self {
125 Self {
126 consensus_client,
127 _phantom: Default::default(),
128 }
129 }
130}
131
132impl<CBlock, DomainHeader, CClient> FraudProofStorageKeyProviderInstance<NumberFor<CBlock>>
133 for FPStorageKeyProvider<CBlock, DomainHeader, CClient>
134where
135 CBlock: BlockT,
136 DomainHeader: HeaderT,
137 CClient: HeaderBackend<CBlock> + ProvideRuntimeApi<CBlock> + 'static,
138 CClient::Api: FraudProofApi<CBlock, DomainHeader>,
139{
140 fn storage_key(&self, req: FraudProofStorageKeyRequest<NumberFor<CBlock>>) -> Option<Vec<u8>> {
141 let best_hash = self.consensus_client.info().best_hash;
142 self.consensus_client
143 .runtime_api()
144 .fraud_proof_storage_key(best_hash, req)
145 .ok()
146 }
147}
148
149pub fn generate_mmr_proof<CClient, CBlock>(
154 consensus_client: &Arc<CClient>,
155 to_prove: NumberFor<CBlock>,
156) -> sp_blockchain::Result<ConsensusChainMmrLeafProof<NumberFor<CBlock>, CBlock::Hash, H256>>
157where
158 CBlock: BlockT,
159 CClient: HeaderBackend<CBlock> + ProvideRuntimeApi<CBlock> + 'static,
160 CClient::Api: MmrApi<CBlock, H256, NumberFor<CBlock>>,
161{
162 let api = consensus_client.runtime_api();
163 let prove_at_hash = consensus_client.info().best_hash;
164 let prove_at_number = consensus_client.info().best_number;
165
166 if to_prove >= prove_at_number {
167 return Err(sp_blockchain::Error::Application(Box::from(format!(
168 "Can't generate MMR proof for block {to_prove:?} >= best block {prove_at_number:?}"
169 ))));
170 }
171
172 let (mut leaves, proof) = api
173 .generate_proof(
176 prove_at_hash,
177 vec![to_prove + One::one()],
178 Some(prove_at_number),
179 )?
180 .map_err(|err| {
181 sp_blockchain::Error::Application(Box::from(format!(
182 "Failed to generate MMR proof: {err}"
183 )))
184 })?;
185 debug_assert!(leaves.len() == 1, "should always be of length 1");
186 let leaf = leaves
187 .pop()
188 .ok_or(sp_blockchain::Error::Application(Box::from(
189 "Unexpected missing mmr leaf".to_string(),
190 )))?;
191
192 Ok(ConsensusChainMmrLeafProof {
193 consensus_block_number: prove_at_number,
194 consensus_block_hash: prove_at_hash,
195 opaque_mmr_leaf: leaf,
196 proof,
197 })
198}