miden_client/sync/
block_header.rs1use alloc::sync::Arc;
2use alloc::vec::Vec;
3
4use crypto::merkle::{InOrderIndex, MmrPeaks, PartialMmr};
5use miden_objects::Word;
6use miden_objects::block::{BlockHeader, BlockNumber};
7use miden_objects::crypto::merkle::{Forest, MerklePath};
8use miden_objects::crypto::{self};
9use tracing::warn;
10
11use crate::rpc::NodeRpcClient;
12use crate::store::StoreError;
13use crate::{Client, ClientError};
14
15impl<AUTH> Client<AUTH> {
17 pub async fn ensure_genesis_in_place(&mut self) -> Result<BlockHeader, ClientError> {
20 let genesis = match self.store.get_block_header_by_num(0.into()).await? {
21 Some((block, _)) => block,
22 None => self.retrieve_and_store_genesis().await?,
23 };
24
25 Ok(genesis)
26 }
27
28 async fn retrieve_and_store_genesis(&mut self) -> Result<BlockHeader, ClientError> {
31 let (genesis_block, _) = self
32 .rpc_api
33 .get_block_header_by_number(Some(BlockNumber::GENESIS), false)
34 .await?;
35
36 let blank_mmr_peaks = MmrPeaks::new(Forest::empty(), vec![])
37 .expect("Blank MmrPeaks should not fail to instantiate");
38 self.store.insert_block_header(&genesis_block, blank_mmr_peaks, false).await?;
39 Ok(genesis_block)
40 }
41
42 pub async fn get_current_partial_mmr(&self) -> Result<PartialMmr, ClientError> {
44 self.store.get_current_partial_mmr().await.map_err(Into::into)
45 }
46
47 pub(crate) async fn get_and_store_authenticated_block(
56 &self,
57 block_num: BlockNumber,
58 current_partial_mmr: &mut PartialMmr,
59 ) -> Result<BlockHeader, ClientError> {
60 if current_partial_mmr.is_tracked(block_num.as_usize()) {
61 warn!("Current partial MMR already contains the requested data");
62 let (block_header, _) = self
63 .store
64 .get_block_header_by_num(block_num)
65 .await?
66 .expect("Block header should be tracked");
67 return Ok(block_header);
68 }
69
70 let (block_header, path_nodes) =
72 fetch_block_header(self.rpc_api.clone(), block_num, current_partial_mmr).await?;
73
74 self.store
76 .insert_block_header(&block_header, current_partial_mmr.peaks(), true)
77 .await?;
78 self.store.insert_partial_blockchain_nodes(&path_nodes).await?;
79
80 Ok(block_header)
81 }
82}
83
84pub(crate) fn adjust_merkle_path_for_forest(
96 merkle_path: &MerklePath,
97 block_num: BlockNumber,
98 forest: Forest,
99) -> Vec<(InOrderIndex, Word)> {
100 assert!(
101 forest.num_leaves() > block_num.as_usize(),
102 "Can't adjust merkle path for a forest that does not include the block number"
103 );
104
105 let rightmost_index = InOrderIndex::from_leaf_pos(forest.num_leaves() - 1);
106
107 let mut idx = InOrderIndex::from_leaf_pos(block_num.as_usize());
108 let mut path_nodes = vec![];
109 for node in merkle_path.iter() {
110 idx = idx.sibling();
111 if idx <= rightmost_index {
114 path_nodes.push((idx, *node));
115 }
116 idx = idx.parent();
117 }
118
119 path_nodes
120}
121
122pub(crate) async fn fetch_block_header(
123 rpc_api: Arc<dyn NodeRpcClient>,
124 block_num: BlockNumber,
125 current_partial_mmr: &mut PartialMmr,
126) -> Result<(BlockHeader, Vec<(InOrderIndex, Word)>), ClientError> {
127 let (block_header, mmr_proof) = rpc_api.get_block_header_with_proof(block_num).await?;
128
129 let path_nodes = adjust_merkle_path_for_forest(
132 &mmr_proof.merkle_path,
133 block_num,
134 current_partial_mmr.forest(),
135 );
136
137 let merkle_path = MerklePath::new(path_nodes.iter().map(|(_, n)| *n).collect());
138
139 current_partial_mmr
140 .track(block_num.as_usize(), block_header.commitment(), &merkle_path)
141 .map_err(StoreError::MmrError)?;
142
143 Ok((block_header, path_nodes))
144}