Skip to main content

binius_iop/merkle_tree/
merkle_tree_vcs.rs

1// Copyright 2024-2025 Irreducible Inc.
2// Copyright 2026 The Binius Developers
3
4use binius_transcript::{Buf, TranscriptReader};
5use binius_utils::FixedSizeSerializeBytes;
6
7use super::error::Error;
8
9/// A Merkle tree commitment.
10///
11/// This struct includes the depth of the tree to guard against attacks that exploit the
12/// indistinguishability of leaf digests from inner node digests.
13#[derive(Debug, Clone, PartialEq, Eq)]
14pub struct Commitment<Digest> {
15	/// The root digest of the Merkle tree.
16	pub root: Digest,
17	/// The depth of the Merkle tree.
18	pub depth: usize,
19}
20
21/// A Merkle tree scheme.
22pub trait MerkleTreeScheme<T: FixedSizeSerializeBytes> {
23	/// The digest of a leaf or an inner node.
24	type Digest: Clone + PartialEq + Eq;
25
26	/// Returns the optimal layer that the verifier should verify only once.
27	///
28	/// Decommitting a layer at depth `d` costs `2^d` digests but shortens every one of the
29	/// `n_queries` branches by `d`, so the proof holds
30	///
31	/// ```text
32	/// (tree_depth - d) * n_queries + 2^d
33	/// ```
34	///
35	/// digests. That is minimized at `d = ceil(log2(n_queries))`, clamped to the tree depth.
36	fn optimal_verify_layer(&self, n_queries: usize, tree_depth: usize) -> usize;
37
38	/// Returns the total byte-size of a proof for multiple opening queries.
39	///
40	/// ## Arguments
41	///
42	/// * `len` - the length of the committed vector
43	/// * `n_queries` - the number of opening queries
44	/// * `layer_depth` - the depth of the internal layer the verifier decommits once and verifies
45	///   all openings against (see [`Self::optimal_verify_layer`])
46	///
47	/// ## Preconditions
48	///
49	/// * `len` must be a power of two.
50	/// * `layer_depth` must be at most `log2(len)`.
51	fn proof_size(&self, len: usize, n_queries: usize, layer_depth: usize) -> usize;
52
53	/// Verify the opening of the full vector.
54	///
55	/// The committed values are the whole opening, so there is no decommitment advice to read.
56	///
57	/// ## Preconditions
58	///
59	/// * `batch_size` must be non-zero.
60	/// * `data.len()` must be a multiple of `batch_size`.
61	/// * `data.len() / batch_size` must be a non-zero power of two.
62	fn verify_vector(
63		&self,
64		root: &Self::Digest,
65		data: &[T],
66		batch_size: usize,
67	) -> Result<(), Error>;
68
69	/// Verify a given layer of the Merkle tree.
70	///
71	/// When a protocol requires verification of many openings at independent and randomly sampled
72	/// indices, it is more efficient for the verifier to verifier an internal layer once, then
73	/// verify all openings with respect to that layer.
74	///
75	/// ## Preconditions
76	///
77	/// * `layer_digests.len()` must equal `2^layer_depth`.
78	fn verify_layer(
79		&self,
80		root: &Self::Digest,
81		layer_depth: usize,
82		layer_digests: &[Self::Digest],
83	) -> Result<(), Error>;
84
85	/// Verify an opening proof for an entry in a committed vector at the given index.
86	///
87	/// ## Preconditions
88	///
89	/// * `layer_digests.len()` must equal `2^layer_depth`.
90	/// * `layer_depth` must be at most `tree_depth`.
91	/// * `index` must be less than `2^tree_depth`.
92	fn verify_opening<B: Buf>(
93		&self,
94		index: usize,
95		values: &[T],
96		layer_depth: usize,
97		tree_depth: usize,
98		layer_digests: &[Self::Digest],
99		proof: &mut TranscriptReader<'_, B>,
100	) -> Result<(), Error>;
101}