miden_client/sync/
block_header.rs1use alloc::{sync::Arc, vec::Vec};
2
3use crypto::merkle::{InOrderIndex, MmrPeaks, PartialMmr};
4use miden_objects::{
5 Digest,
6 block::{BlockHeader, BlockNumber},
7 crypto::{self, merkle::MerklePath},
8};
9use tracing::warn;
10
11use crate::{
12 Client, ClientError,
13 rpc::NodeRpcClient,
14 store::{PartialBlockchainFilter, StoreError},
15};
16
17impl Client {
19 pub async fn ensure_genesis_in_place(&mut self) -> Result<BlockHeader, ClientError> {
22 let genesis = self.store.get_block_header_by_num(0.into()).await?;
23
24 match genesis {
25 Some((block, _)) => Ok(block),
26 None => self.retrieve_and_store_genesis().await,
27 }
28 }
29
30 async fn retrieve_and_store_genesis(&mut self) -> Result<BlockHeader, ClientError> {
33 let (genesis_block, _) = self
34 .rpc_api
35 .get_block_header_by_number(Some(BlockNumber::GENESIS), false)
36 .await?;
37
38 let blank_mmr_peaks =
39 MmrPeaks::new(0, vec![]).expect("Blank MmrPeaks should not fail to instantiate");
40 self.store.insert_block_header(&genesis_block, blank_mmr_peaks, false).await?;
41 Ok(genesis_block)
42 }
43
44 pub(crate) async fn build_current_partial_mmr(&self) -> Result<PartialMmr, ClientError> {
51 let current_block_num = self.store.get_sync_height().await?;
52
53 let tracked_nodes =
54 self.store.get_partial_blockchain_nodes(PartialBlockchainFilter::All).await?;
55 let current_peaks =
56 self.store.get_partial_blockchain_peaks_by_block_num(current_block_num).await?;
57
58 let (current_block, has_client_notes) = self
70 .store
71 .get_block_header_by_num(current_block_num)
72 .await?
73 .expect("Current block should be in the store");
74
75 let mut current_partial_mmr = PartialMmr::from_peaks(current_peaks);
76 current_partial_mmr.add(current_block.commitment(), has_client_notes);
77
78 let current_partial_mmr =
79 PartialMmr::from_parts(current_partial_mmr.peaks(), tracked_nodes, has_client_notes);
80
81 Ok(current_partial_mmr)
82 }
83
84 pub(crate) async fn get_and_store_authenticated_block(
90 &self,
91 block_num: BlockNumber,
92 current_partial_mmr: &mut PartialMmr,
93 ) -> Result<BlockHeader, ClientError> {
94 if current_partial_mmr.is_tracked(block_num.as_usize()) {
95 warn!("Current partial MMR already contains the requested data");
96 let (block_header, _) = self
97 .store
98 .get_block_header_by_num(block_num)
99 .await?
100 .expect("Block header should be tracked");
101 return Ok(block_header);
102 }
103
104 let (block_header, path_nodes) =
106 fetch_block_header(self.rpc_api.clone(), block_num, current_partial_mmr).await?;
107
108 self.store
110 .insert_block_header(&block_header, current_partial_mmr.peaks(), true)
111 .await?;
112 self.store.insert_partial_blockchain_nodes(&path_nodes).await?;
113
114 Ok(block_header)
115 }
116}
117
118pub(crate) fn adjust_merkle_path_for_forest(
130 merkle_path: &MerklePath,
131 block_num: BlockNumber,
132 forest: usize,
133) -> Vec<(InOrderIndex, Digest)> {
134 assert!(
135 forest > block_num.as_usize(),
136 "Can't adjust merkle path for a forest that does not include the block number"
137 );
138
139 let rightmost_index = InOrderIndex::from_leaf_pos(forest - 1);
140
141 let mut idx = InOrderIndex::from_leaf_pos(block_num.as_usize());
142 let mut path_nodes = vec![];
143 for node in merkle_path.iter() {
144 idx = idx.sibling();
145 if idx <= rightmost_index {
148 path_nodes.push((idx, *node));
149 }
150 idx = idx.parent();
151 }
152
153 path_nodes
154}
155
156pub(crate) async fn fetch_block_header(
157 rpc_api: Arc<dyn NodeRpcClient>,
158 block_num: BlockNumber,
159 current_partial_mmr: &mut PartialMmr,
160) -> Result<(BlockHeader, Vec<(InOrderIndex, Digest)>), ClientError> {
161 let (block_header, mmr_proof) = rpc_api.get_block_header_with_proof(block_num).await?;
162
163 let path_nodes = adjust_merkle_path_for_forest(
166 &mmr_proof.merkle_path,
167 block_num,
168 current_partial_mmr.forest(),
169 );
170
171 let merkle_path = MerklePath::new(path_nodes.iter().map(|(_, n)| *n).collect());
172
173 current_partial_mmr
174 .track(block_num.as_usize(), block_header.commitment(), &merkle_path)
175 .map_err(StoreError::MmrError)?;
176
177 Ok((block_header, path_nodes))
178}