Skip to main content

miden_node_store/state/view/
block.rs

1//! Block header reads.
2
3use miden_node_tracing::miden_instrument;
4use miden_protocol::block::{BlockHeader, BlockNumber};
5use miden_protocol::crypto::merkle::mmr::MmrProof;
6
7use super::StateView;
8use crate::COMPONENT;
9use crate::errors::GetBlockHeaderError;
10
11impl StateView {
12    /// Queries a [BlockHeader] from the database, and returns it alongside its inclusion proof.
13    ///
14    /// If [None] is given as the value of `block_num`, the data for the latest [BlockHeader] is
15    /// returned. Returns `(None, None)` for blocks beyond this view's chain tip.
16    #[miden_instrument(
17        level = "debug",
18        target = COMPONENT,
19        err,
20    )]
21    pub async fn get_block_header(
22        &self,
23        block_num: Option<BlockNumber>,
24        include_mmr_proof: bool,
25    ) -> Result<(Option<BlockHeader>, Option<MmrProof>), GetBlockHeaderError> {
26        // Resolve "latest" against the view's snapshot rather than the DB: mid-apply, the DB may
27        // already contain a block that the snapshot's blockchain cannot prove yet. Scoping the DB
28        // query by the view's tip keeps the header and MMR proof consistent.
29        let block_num = block_num.unwrap_or_else(|| *self.tip());
30        let Some(scoped_block) = self.scope_block(block_num) else {
31            return Ok((None, None));
32        };
33
34        let block_header = self.db.select_block_header_by_block_num(Some(scoped_block)).await?;
35        if let Some(header) = block_header {
36            let mmr_proof = if include_mmr_proof {
37                let mmr_proof = self.blockchain().open(header.block_num())?;
38                Some(mmr_proof)
39            } else {
40                None
41            };
42            Ok((Some(header), mmr_proof))
43        } else {
44            Ok((None, None))
45        }
46    }
47}