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