sp_subspace_mmr/
runtime_interface.rs

1//! Runtime interface for Subspace-specific MMR operations.
2//! Used to verify MMR proofs in the domain runtime, based on the consensus MMR state.
3
4#[cfg(all(feature = "std", not(feature = "runtime-benchmarks")))]
5use crate::host_functions::SubspaceMmrExtension;
6use parity_scale_codec::{Decode, Encode};
7use scale_info::TypeInfo;
8use scale_info::prelude::vec::Vec;
9use sp_core::H256;
10#[cfg(all(feature = "std", not(feature = "runtime-benchmarks")))]
11use sp_externalities::ExternalitiesExt;
12use sp_mmr_primitives::EncodableOpaqueLeaf;
13use sp_runtime_interface::runtime_interface;
14use subspace_core_primitives::BlockNumber;
15
16/// MMR related runtime interface
17#[runtime_interface]
18pub trait SubspaceMmrRuntimeInterface {
19    /// Returns the MMR leaf for the given consensus block.
20    fn get_mmr_leaf_data(&mut self, consensus_block_hash: H256) -> Option<LeafData> {
21        #[cfg(not(feature = "runtime-benchmarks"))]
22        {
23            self.extension::<SubspaceMmrExtension>()
24                .expect("No `SubspaceMmrExtension` associated for the current context!")
25                .get_mmr_leaf_data(consensus_block_hash)
26        }
27
28        // We assume this implementation costs slightly less than the real implementation,
29        // but it's the best we can do for now.
30        // TODO: when custom extensions are supported in benchmarks, remove this code and call
31        // directly into SubspaceMmrExtension.
32        // <https://github.com/paritytech/polkadot-sdk/issues/137>
33        #[cfg(feature = "runtime-benchmarks")]
34        {
35            crate::benchmarking::mock_subspace_mmr_extension()
36                .get_mmr_leaf_data(consensus_block_hash)
37        }
38    }
39
40    /// Returns the consensus block hash for a given block number.
41    fn consensus_block_hash(&mut self, block_number: BlockNumber) -> Option<H256> {
42        #[cfg(not(feature = "runtime-benchmarks"))]
43        {
44            self.extension::<SubspaceMmrExtension>()
45                .expect("No `SubspaceMmrExtension` associated for the current context!")
46                .consensus_block_hash(block_number)
47        }
48
49        // We assume this implementation costs slightly less than the real implementation,
50        // but it's the best we can do for now.
51        // TODO: when custom extensions are supported, call directly into SubspaceMmrExtension.
52        #[cfg(feature = "runtime-benchmarks")]
53        {
54            crate::benchmarking::mock_subspace_mmr_extension().consensus_block_hash(block_number)
55        }
56    }
57}
58
59/// Leaf data sent back from host function.
60#[derive(Debug, Decode, Encode, TypeInfo, PartialEq, Eq, Clone, Default)]
61pub struct LeafData {
62    pub state_root: H256,
63    pub extrinsics_root: H256,
64}
65
66#[runtime_interface]
67pub trait DomainMmrRuntimeInterface {
68    /// Verifies the given MMR proof using the leaves provided.
69    fn verify_mmr_proof(
70        &mut self,
71        leaves: Vec<EncodableOpaqueLeaf>,
72        encoded_proof: Vec<u8>,
73    ) -> bool {
74        #[cfg(not(feature = "runtime-benchmarks"))]
75        {
76            self.extension::<SubspaceMmrExtension>()
77                .expect("No `SubspaceMmrExtension` associated for the current context!")
78                .verify_mmr_proof(leaves, encoded_proof)
79        }
80
81        // We assume this implementation costs slightly less than the real implementation,
82        // but it's the best we can do for now.
83        // TODO: when custom extensions are supported, call directly into SubspaceMmrExtension.
84        #[cfg(feature = "runtime-benchmarks")]
85        {
86            crate::benchmarking::mock_subspace_mmr_extension()
87                .verify_mmr_proof(leaves, encoded_proof)
88        }
89    }
90
91    // Return `true` if the given consensus block is finalized.
92    fn is_consensus_block_finalized(&mut self, block_number: BlockNumber) -> bool {
93        #[cfg(not(feature = "runtime-benchmarks"))]
94        {
95            self.extension::<SubspaceMmrExtension>()
96                .expect("No `SubspaceMmrExtension` associated for the current context!")
97                .is_consensus_block_finalized(block_number)
98        }
99
100        // This implementation obviously costs less than the real implementation, but it's the best
101        // we can do for now.
102        // TODO: when custom extensions are supported, call directly into SubspaceMmrExtension.
103        #[cfg(feature = "runtime-benchmarks")]
104        {
105            crate::benchmarking::mock_subspace_mmr_extension()
106                .is_consensus_block_finalized(block_number)
107        }
108    }
109}