use crate::Matrix;
use air::proof::Queries;
use crypto::{ElementHasher, MerkleTree};
use math::FieldElement;
use utils::collections::Vec;
use super::TraceLde;
pub struct TraceCommitment<E: FieldElement, H: ElementHasher<BaseField = E::BaseField>> {
trace_lde: TraceLde<E>,
main_segment_tree: MerkleTree<H>,
aux_segment_trees: Vec<MerkleTree<H>>,
}
impl<E: FieldElement, H: ElementHasher<BaseField = E::BaseField>> TraceCommitment<E, H> {
pub fn new(
main_trace_lde: Matrix<E::BaseField>,
main_trace_tree: MerkleTree<H>,
blowup: usize,
) -> Self {
assert_eq!(
main_trace_lde.num_rows(),
main_trace_tree.leaves().len(),
"number of rows in trace LDE must be the same as number of leaves in trace commitment"
);
Self {
trace_lde: TraceLde::new(main_trace_lde, blowup),
main_segment_tree: main_trace_tree,
aux_segment_trees: Vec::new(),
}
}
pub fn add_segment(&mut self, aux_segment_lde: Matrix<E>, aux_segment_tree: MerkleTree<H>) {
assert_eq!(
aux_segment_lde.num_rows(),
aux_segment_tree.leaves().len(),
"number of rows in trace LDE must be the same as number of leaves in trace commitment"
);
self.trace_lde.add_aux_segment(aux_segment_lde);
self.aux_segment_trees.push(aux_segment_tree);
}
pub fn trace_table(&self) -> &TraceLde<E> {
&self.trace_lde
}
pub fn query(&self, positions: &[usize]) -> Vec<Queries> {
let mut result = vec![build_segment_queries(
self.trace_lde.get_main_segment(),
&self.main_segment_tree,
positions,
)];
for (i, segment_tree) in self.aux_segment_trees.iter().enumerate() {
let segment_lde = self.trace_lde.get_aux_segment(i);
result.push(build_segment_queries(segment_lde, segment_tree, positions));
}
result
}
#[cfg(test)]
pub fn main_trace_root(&self) -> H::Digest {
*self.main_segment_tree.root()
}
#[cfg(test)]
pub fn get_main_trace_column(&self, col_idx: usize) -> &[E::BaseField] {
self.trace_lde.get_main_segment().get_column(col_idx)
}
}
fn build_segment_queries<E, H>(
segment_lde: &Matrix<E>,
segment_tree: &MerkleTree<H>,
positions: &[usize],
) -> Queries
where
E: FieldElement,
H: ElementHasher<BaseField = E::BaseField>,
{
let mut trace_states = Vec::with_capacity(positions.len());
for &i in positions.iter() {
let row = segment_lde.columns().map(|column| column[i]).collect();
trace_states.push(row);
}
let trace_proof = segment_tree
.prove_batch(positions)
.expect("failed to generate a Merkle proof for trace queries");
Queries::new(trace_proof, trace_states)
}