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::{PartialBlockchainFilter, 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(crate) async fn build_current_partial_mmr(&self) -> Result<PartialMmr, ClientError> {
49 let current_block_num = self.store.get_sync_height().await?;
50
51 let tracked_nodes =
52 self.store.get_partial_blockchain_nodes(PartialBlockchainFilter::All).await?;
53 let current_peaks =
54 self.store.get_partial_blockchain_peaks_by_block_num(current_block_num).await?;
55
56 let (current_block, has_client_notes) = self
68 .store
69 .get_block_header_by_num(current_block_num)
70 .await?
71 .expect("Current block should be in the store");
72
73 let mut current_partial_mmr = PartialMmr::from_peaks(current_peaks);
74 let has_client_notes = has_client_notes.into();
75 current_partial_mmr.add(current_block.commitment(), has_client_notes);
76
77 let current_partial_mmr =
78 PartialMmr::from_parts(current_partial_mmr.peaks(), tracked_nodes, has_client_notes);
79
80 Ok(current_partial_mmr)
81 }
82
83 pub(crate) async fn get_and_store_authenticated_block(
89 &self,
90 block_num: BlockNumber,
91 current_partial_mmr: &mut PartialMmr,
92 ) -> Result<BlockHeader, ClientError> {
93 if current_partial_mmr.is_tracked(block_num.as_usize()) {
94 warn!("Current partial MMR already contains the requested data");
95 let (block_header, _) = self
96 .store
97 .get_block_header_by_num(block_num)
98 .await?
99 .expect("Block header should be tracked");
100 return Ok(block_header);
101 }
102
103 let (block_header, path_nodes) =
105 fetch_block_header(self.rpc_api.clone(), block_num, current_partial_mmr).await?;
106
107 self.store
109 .insert_block_header(&block_header, current_partial_mmr.peaks(), true)
110 .await?;
111 self.store.insert_partial_blockchain_nodes(&path_nodes).await?;
112
113 Ok(block_header)
114 }
115}
116
117pub(crate) fn adjust_merkle_path_for_forest(
129 merkle_path: &MerklePath,
130 block_num: BlockNumber,
131 forest: Forest,
132) -> Vec<(InOrderIndex, Word)> {
133 assert!(
134 forest.num_leaves() > block_num.as_usize(),
135 "Can't adjust merkle path for a forest that does not include the block number"
136 );
137
138 let rightmost_index = InOrderIndex::from_leaf_pos(forest.num_leaves() - 1);
139
140 let mut idx = InOrderIndex::from_leaf_pos(block_num.as_usize());
141 let mut path_nodes = vec![];
142 for node in merkle_path.iter() {
143 idx = idx.sibling();
144 if idx <= rightmost_index {
147 path_nodes.push((idx, *node));
148 }
149 idx = idx.parent();
150 }
151
152 path_nodes
153}
154
155pub(crate) async fn fetch_block_header(
156 rpc_api: Arc<dyn NodeRpcClient>,
157 block_num: BlockNumber,
158 current_partial_mmr: &mut PartialMmr,
159) -> Result<(BlockHeader, Vec<(InOrderIndex, Word)>), ClientError> {
160 let (block_header, mmr_proof) = rpc_api.get_block_header_with_proof(block_num).await?;
161
162 let path_nodes = adjust_merkle_path_for_forest(
165 &mmr_proof.merkle_path,
166 block_num,
167 current_partial_mmr.forest(),
168 );
169
170 let merkle_path = MerklePath::new(path_nodes.iter().map(|(_, n)| *n).collect());
171
172 current_partial_mmr
173 .track(block_num.as_usize(), block_header.commitment(), &merkle_path)
174 .map_err(StoreError::MmrError)?;
175
176 Ok((block_header, path_nodes))
177}