Skip to content

Commit

Permalink
dequeue, hash and verify quotient segments
Browse files Browse the repository at this point in the history
Co-authored-by: Alan Szepieniec <[email protected]>
  • Loading branch information
Sword-Smith and aszepieniec committed Mar 18, 2024
1 parent e73834f commit f664654
Show file tree
Hide file tree
Showing 3 changed files with 106 additions and 37 deletions.
11 changes: 11 additions & 0 deletions src/libraries/recufy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use syn::parse_quote;
use syn::PathArguments;
use tasm_lib::triton_vm::table::NUM_BASE_COLUMNS;
use tasm_lib::triton_vm::table::NUM_EXT_COLUMNS;
use tasm_lib::triton_vm::table::NUM_QUOTIENT_SEGMENTS;

use crate::ast;
use crate::ast_types;
Expand All @@ -20,6 +21,7 @@ use super::Library;

const BASE_ROW_TYPE_NAME: &str = "BaseRow";
const EXT_ROW_TYPE_NAME: &str = "ExtensionRow";
const QUOT_SEGMENTS_TYPE_NAME: &str = "QuotientSegments";

#[derive(Debug)]
pub(crate) struct RecufyLib;
Expand All @@ -35,6 +37,7 @@ impl Library for RecufyLib {
VM_PROOF_ITER_TYPE_NAME => Some(graft_vm_proof_iter(graft)),
BASE_ROW_TYPE_NAME => Some(Self::graft_base_row(path_args, graft)),
EXT_ROW_TYPE_NAME => Some(Self::graft_ext_row(path_args)),
QUOT_SEGMENTS_TYPE_NAME => Some(Self::graft_quot_segments(path_args)),
_ => None,
}
}
Expand Down Expand Up @@ -135,6 +138,14 @@ impl RecufyLib {
})
}

fn graft_quot_segments(arguments: &PathArguments) -> ast_types::DataType {
assert!(matches!(arguments, PathArguments::None));
ast_types::DataType::Array(ast_types::ArrayType {
element_type: Box::new(ast_types::DataType::Xfe),
length: NUM_QUOTIENT_SEGMENTS,
})
}

fn graft_base_row(arguments: &PathArguments, graft: &mut Graft) -> ast_types::DataType {
match arguments {
syn::PathArguments::AngleBracketed(ab) => {
Expand Down
91 changes: 56 additions & 35 deletions src/tests_and_benchmarks/ozk/programs/recufier/fri_verify.rs
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ pub(crate) mod test {
pub(crate) fri_proof_stream: StarkProofStream,
pub(crate) base_tree_authentication_paths: Vec<Vec<Digest>>,
pub(crate) ext_tree_authentication_paths: Vec<Vec<Digest>>,
// quot_tree_authentication_paths: Vec<Vec<Digest>>,
pub(crate) quot_tree_authentication_paths: Vec<Vec<Digest>>,
}

/// Extracts a proof stream that will work for FRI verification from a proof stream that works for
Expand All @@ -124,7 +124,7 @@ pub(crate) mod test {
proof_stream.alter_fiat_shamir_state_with(claim);

// Base-table Merkle root
proof_stream
let base_table_root = proof_stream
.dequeue()
.unwrap()
.try_into_merkle_root()
Expand All @@ -144,7 +144,7 @@ pub(crate) mod test {
proof_stream.sample_scalars(MasterExtTable::NUM_CONSTRAINTS);

// Quotient codeword Merkle root
proof_stream
let quotient_root = proof_stream
.dequeue()
.unwrap()
.try_into_merkle_root()
Expand Down Expand Up @@ -191,68 +191,89 @@ pub(crate) mod test {
let fri: triton_vm::fri::Fri<Tip5> = stark.derive_fri(padded_height).unwrap();
let fri_proof_stream = proof_stream.clone();
let fri_verify_result = fri.verify(&mut proof_stream, &mut None).unwrap();
let indices = fri_verify_result.iter().map(|(i, _)| *i).collect_vec();
let tree_height = fri.domain.length.ilog2() as usize;

// base
let base_table_rows = proof_stream
.dequeue()
.unwrap()
.try_into_master_base_table_rows()
.unwrap();
let base_table_leaf_digests = base_table_rows.iter().map(|x| Tip5::hash_varlen(x));
let base_authentication_structure = proof_stream
.dequeue()
.unwrap()
.try_into_authentication_structure()
.unwrap();
let fri_indexed_base_leaves = fri_verify_result
.iter()
.map(|(index, _)| *index)
.zip(base_table_leaf_digests)
.collect_vec();
let tree_height = fri.domain.length.ilog2() as usize;
let base_tree_inclusion_proof = MerkleTreeInclusionProof::<Tip5> {
let base_tree_auth_paths = extract_paths(
base_table_root,
&indices,
&base_table_rows,
&base_authentication_structure,
tree_height,
indexed_leaves: fri_indexed_base_leaves,
authentication_structure: base_authentication_structure,
_hasher: std::marker::PhantomData,
};
let base_tree_auth_paths = base_tree_inclusion_proof.into_authentication_paths();
if let Err(err) = base_tree_auth_paths {
println!("base_tree_auth_paths: {}", err);
}
let base_tree_auth_paths = base_tree_auth_paths.unwrap();
);

// extension
let ext_table_rows = proof_stream
.dequeue()
.unwrap()
.try_into_master_ext_table_rows()
.unwrap();
let ext_table_leaf_digests = ext_table_rows.iter().map(Tip5::hash).collect_vec();
let ext_authentication_structure = proof_stream
.dequeue()
.unwrap()
.try_into_authentication_structure()
.unwrap();
let fri_indexed_ext_leafs = fri_verify_result
.iter()
.map(|(index, _)| *index)
.zip(ext_table_leaf_digests)
.collect_vec();
let ext_tree_inclusion_proof = MerkleTreeInclusionProof::<Tip5> {
let ext_tree_auth_paths = extract_paths(
ext_mt_root,
&indices,
&ext_table_rows,
&ext_authentication_structure,
tree_height,
indexed_leaves: fri_indexed_ext_leafs,
authentication_structure: ext_authentication_structure,
_hasher: std::marker::PhantomData,
};
assert!(ext_tree_inclusion_proof.clone().verify(ext_mt_root));
let ext_tree_auth_paths = ext_tree_inclusion_proof
.into_authentication_paths()
);

// quotient
let quot_table_rows = proof_stream
.dequeue()
.unwrap()
.try_into_quot_segments_elements()
.unwrap();
let quot_authentication_structure = proof_stream
.dequeue()
.unwrap()
.try_into_authentication_structure()
.unwrap();
let quot_tree_auth_paths = extract_paths(
quotient_root,
&indices,
&quot_table_rows,
&quot_authentication_structure,
tree_height,
);

StarkProofExtraction {
fri_proof_stream,
base_tree_authentication_paths: base_tree_auth_paths,
ext_tree_authentication_paths: ext_tree_auth_paths,
// quot_tree_authentication_paths: todo!(),
quot_tree_authentication_paths: quot_tree_auth_paths,
}
}

fn extract_paths<const N: usize, T: BFieldCodec>(
root: Digest,
indices: &[usize],
rows: &[[T; N]],
authentication_structure: &[Digest],
tree_height: usize,
) -> Vec<Vec<Digest>> {
let leafs = rows.iter().map(Tip5::hash).collect_vec();
let inclusion_proof = MerkleTreeInclusionProof::<Tip5> {
tree_height,
indexed_leaves: indices.iter().cloned().zip(leafs).collect_vec(),
authentication_structure: authentication_structure.to_vec(),
_hasher: std::marker::PhantomData,
};
assert!(inclusion_proof.clone().verify(root));
inclusion_proof.into_authentication_paths().unwrap()
}
}
41 changes: 39 additions & 2 deletions src/tests_and_benchmarks/ozk/programs/recufier/verify.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ use serde_derive::Serialize;
use tasm_lib::triton_vm::table::extension_table::Quotientable;
use tasm_lib::triton_vm::table::master_table::MasterExtTable;
use tasm_lib::triton_vm::table::ExtensionRow;
use tasm_lib::triton_vm::table::QuotientSegments;

use crate::tests_and_benchmarks::ozk::rust_shadows as tasm;
use crate::tests_and_benchmarks::ozk::rust_shadows::Tip5WithState;
Expand Down Expand Up @@ -344,9 +345,9 @@ fn recufy() {
.unwrap();
// println!("quot_codeword_weights: {quot_codeword_weights:?}");
RecufyDebug::dump_xfes(&quot_codeword_weights.to_vec());
let quotient_codeword_merkle_root: Box<Digest> = proof_iter.next_as_merkleroot();
let quotient_tree_merkle_root: Box<Digest> = proof_iter.next_as_merkleroot();
// println!("quotient_codeword_merkle_root: {quotient_codeword_merkle_root:?}");
RecufyDebug::dump_digest(*quotient_codeword_merkle_root);
RecufyDebug::dump_digest(*quotient_tree_merkle_root);

let trace_domain_generator: BFieldElement =
ArithmeticDomain::generator_for_length(padded_height as u64);
Expand Down Expand Up @@ -535,6 +536,37 @@ fn recufy() {
}
}

// dequeue quotient segments
let quotient_segment_elements: Box<Vec<QuotientSegments>> =
proof_iter.next_as_quotientsegmentselements();

// hash rows
let mut leaf_digests_quot: Vec<Digest> = Vec::<Digest>::default();
{
let mut i: usize = 0;
while i < 2 * fri.num_colinearity_checks as usize {
leaf_digests_quot.push(tasm::tasm_hashing_algebraic_hasher_hash_varlen(
&quotient_segment_elements[i],
4 * 3,
));
i += 1;
}
}

// Merkle verify (quotient tree)
{
let mut i: usize = 0;
while i < 2 * fri.num_colinearity_checks as usize {
tasm::tasm_hashing_merkle_verify(
*quotient_tree_merkle_root,
revealed_fri_indices_and_elements[i].0,
leaf_digests_quot[i],
merkle_tree_height,
);
i += 1;
}
}

// Ensure that sponge-states are in sync
RecufyDebug::sponge_state(Tip5WithState::squeeze());
return;
Expand Down Expand Up @@ -619,6 +651,11 @@ mod tests {
.into_iter()
.flatten()
.collect_vec(),
proof_extraction
.quot_tree_authentication_paths
.into_iter()
.flatten()
.collect_vec(),
]
.concat();
NonDeterminism::default()
Expand Down

0 comments on commit f664654

Please sign in to comment.