stwo_gpu/core/vcs/
verifier.rs1use hashbrown::HashMap;
2use itertools::Itertools;
3use serde::{Deserialize, Serialize};
4use std_shims::{vec, BTreeMap, Vec};
5use thiserror::Error;
6
7use super::utils::{next_decommitment_node, option_flatten_peekable};
8use crate::core::fields::m31::BaseField;
9use crate::core::utils::PeekableExt;
10use crate::core::vcs::MerkleHasher;
11
12#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq, PartialOrd)]
13pub struct MerkleDecommitment<H: MerkleHasher> {
14 pub hash_witness: Vec<H::Hash>,
17 pub column_witness: Vec<BaseField>,
22}
23impl<H: MerkleHasher> MerkleDecommitment<H> {
24 pub const fn empty() -> Self {
25 Self {
26 hash_witness: Vec::new(),
27 column_witness: Vec::new(),
28 }
29 }
30}
31
32#[derive(Clone, Debug)]
34pub struct MerkleDecommitmentAux<H: MerkleHasher> {
35 pub all_node_values: Vec<HashMap<usize, H::Hash>>,
37}
38
39pub struct ExtendedMerkleDecommitment<H: MerkleHasher> {
40 pub decommitment: MerkleDecommitment<H>,
41 pub aux: MerkleDecommitmentAux<H>,
42}
43
44pub struct MerkleVerifier<H: MerkleHasher> {
45 pub root: H::Hash,
46 pub column_log_sizes: Vec<u32>,
47 pub n_columns_per_log_size: BTreeMap<u32, usize>,
48}
49impl<H: MerkleHasher> MerkleVerifier<H> {
50 pub fn new(root: H::Hash, column_log_sizes: Vec<u32>) -> Self {
51 let mut n_columns_per_log_size = BTreeMap::new();
52 for log_size in &column_log_sizes {
53 *n_columns_per_log_size.entry(*log_size).or_insert(0) += 1;
54 }
55
56 Self {
57 root,
58 column_log_sizes,
59 n_columns_per_log_size,
60 }
61 }
62 pub fn verify(
86 &self,
87 queries_per_log_size: &BTreeMap<u32, Vec<usize>>,
88 queried_values: Vec<BaseField>,
89 decommitment: MerkleDecommitment<H>,
90 ) -> Result<(), MerkleVerificationError> {
91 let Some(max_log_size) = self.column_log_sizes.iter().max() else {
92 return Ok(());
93 };
94
95 let mut queried_values = queried_values.into_iter();
96
97 let mut hash_witness = decommitment.hash_witness.into_iter();
100 let mut column_witness = decommitment.column_witness.into_iter();
101
102 let mut last_layer_hashes: Option<Vec<(usize, H::Hash)>> = None;
103 for layer_log_size in (0..=*max_log_size).rev() {
104 let n_columns_in_layer = *self
105 .n_columns_per_log_size
106 .get(&layer_log_size)
107 .unwrap_or(&0);
108
109 let mut layer_total_queries = vec![];
112
113 let mut prev_layer_queries = last_layer_hashes
116 .iter()
117 .flatten()
118 .map(|(q, _)| *q)
119 .collect_vec()
120 .into_iter()
121 .peekable();
122 let mut prev_layer_hashes = last_layer_hashes.as_ref().map(|x| x.iter().peekable());
123 let mut layer_column_queries =
124 option_flatten_peekable(queries_per_log_size.get(&layer_log_size));
125
126 while let Some(node_index) =
128 next_decommitment_node(&mut prev_layer_queries, &mut layer_column_queries)
129 {
130 prev_layer_queries
131 .peek_take_while(|q| q / 2 == node_index)
132 .for_each(drop);
133
134 let node_hashes = prev_layer_hashes
135 .as_mut()
136 .map(|prev_layer_hashes| {
137 {
138 let left_hash = prev_layer_hashes
140 .next_if(|(index, _)| *index == 2 * node_index)
141 .map(|(_, hash)| Ok(*hash))
142 .unwrap_or_else(|| {
143 hash_witness
144 .next()
145 .ok_or(MerkleVerificationError::WitnessTooShort)
146 })?;
147
148 let right_hash = prev_layer_hashes
150 .next_if(|(index, _)| *index == 2 * node_index + 1)
151 .map(|(_, hash)| Ok(*hash))
152 .unwrap_or_else(|| {
153 hash_witness
154 .next()
155 .ok_or(MerkleVerificationError::WitnessTooShort)
156 })?;
157 Ok((left_hash, right_hash))
158 }
159 })
160 .transpose()?;
161
162 let (err, node_values_iter) = match layer_column_queries.next_if_eq(&node_index) {
164 Some(_) => (
165 MerkleVerificationError::TooFewQueriedValues,
166 &mut queried_values,
167 ),
168 None => (
170 MerkleVerificationError::WitnessTooShort,
171 &mut column_witness,
172 ),
173 };
174
175 let node_values = node_values_iter.take(n_columns_in_layer).collect_vec();
176 if node_values.len() != n_columns_in_layer {
177 return Err(err);
178 }
179
180 layer_total_queries.push((node_index, H::hash_node(node_hashes, &node_values)));
181 }
182
183 last_layer_hashes = Some(layer_total_queries);
184 }
185
186 if hash_witness.next().is_some() {
188 return Err(MerkleVerificationError::WitnessTooLong);
189 }
190 if queried_values.next().is_some() {
191 return Err(MerkleVerificationError::TooManyQueriedValues);
192 }
193 if column_witness.next().is_some() {
194 return Err(MerkleVerificationError::WitnessTooLong);
195 }
196
197 let [(_, computed_root)] = last_layer_hashes.unwrap().try_into().unwrap();
198 if computed_root != self.root {
199 return Err(MerkleVerificationError::RootMismatch);
200 }
201
202 Ok(())
203 }
204}
205
206#[derive(Clone, Copy, Debug, Error, PartialEq, Eq)]
208pub enum MerkleVerificationError {
209 #[error("Witness is too short")]
210 WitnessTooShort,
211 #[error("Witness is too long.")]
212 WitnessTooLong,
213 #[error("too many Queried values")]
214 TooManyQueriedValues,
215 #[error("too few queried values")]
216 TooFewQueriedValues,
217 #[error("Root mismatch.")]
218 RootMismatch,
219}