diff --git a/src/circuit_builder.rs b/src/circuit_builder.rs index 5d9d42d3..71a3d245 100644 --- a/src/circuit_builder.rs +++ b/src/circuit_builder.rs @@ -22,8 +22,13 @@ pub struct CircuitBuilder { /// The types of gates used in this circuit. gates: HashSet>, + /// The concrete placement of each gate. gate_instances: Vec>, + /// The next available index for a VirtualAdviceTarget. + virtual_target_index: usize, + + /// Generators used to generate the witness. generators: Vec>>, } @@ -33,10 +38,29 @@ impl CircuitBuilder { config, gates: HashSet::new(), gate_instances: Vec::new(), + virtual_target_index: 0, generators: Vec::new(), } } + /// Adds a new "virtual" advice target. This is not an actual wire in the witness, but just a + /// target that help facilitate witness generation. In particular, a generator can assign a + /// values to a virtual target, which can then be copied to other (virtual or concrete) targets + /// via `generate_copy`. When we generate the final witness (a grid of wire values), these + /// virtual targets will go away. + /// + /// Since virtual targets are not part of the actual permutation argument, they cannot be used + /// with `assert_equal`. + pub fn add_virtual_advice_target(&mut self) -> Target { + let index = self.virtual_target_index; + self.virtual_target_index += 1; + Target::VirtualAdviceTarget { index } + } + + pub fn add_virtual_advice_targets(&mut self, n: usize) -> Vec { + (0..n).map(|_i| self.add_virtual_advice_target()).collect() + } + pub fn add_gate_no_constants(&mut self, gate_type: GateRef) -> usize { self.add_gate(gate_type, Vec::new()) } diff --git a/src/gadgets/merkle_proofs.rs b/src/gadgets/merkle_proofs.rs deleted file mode 100644 index 595081ef..00000000 --- a/src/gadgets/merkle_proofs.rs +++ /dev/null @@ -1,118 +0,0 @@ -use crate::circuit_builder::CircuitBuilder; -use crate::field::field::Field; -use crate::hash::{compress, hash_n_to_hash}; -use crate::proof::{Hash, HashTarget}; -use crate::target::Target; - -#[derive(Clone, Debug)] -pub struct MerkleProof { - /// The Merkle digest of each sibling subtree, staying from the bottommost layer. - pub siblings: Vec>, -} - -pub struct MerkleProofTarget { - /// The Merkle digest of each sibling subtree, staying from the bottommost layer. - pub siblings: Vec, -} - -#[derive(Clone, Debug)] -pub struct MerkleTree { - /// The data in the leaves of the Merkle tree. - pub leaves: Vec>, - - /// The layers of hashes in the tree. The first layer is the one at the bottom. - pub layers: Vec>>, - - /// The Merkle root. - pub root: Hash, -} - -impl MerkleTree { - pub fn new(leaves: Vec>) -> Self { - let mut layers = vec![leaves.iter().map(|l| hash_n_to_hash(l.clone(), false)).collect::>()]; - loop { - match layers.last() { - Some(l) if l.len() > 1 => { - layers.push(l.chunks(2).map(|chunk| compress(chunk[0], chunk[1])).collect::>()); - }, - _ => break - } - } - let root = layers.pop().unwrap()[0]; - Self { - leaves, - layers, - root - } - - } - - /// Create a Merkle proof from a leaf index. - pub fn prove(&self, leaf_index: usize) -> MerkleProof { - MerkleProof { - siblings: self.layers - .iter() - .scan(leaf_index, |acc, layer| { - let index = *acc ^ 1; - *acc >>= 1; - Some(layer[index]) - }) - .collect(), - } - } -} - - - -/// Verifies that the given leaf data is present at the given index in the Merkle tree with the -/// given root. -pub(crate) fn verify_merkle_proof( - leaf_data: Vec, - leaf_index: usize, - merkle_root: Hash, - proof: MerkleProof, -) -> bool { - let mut index = leaf_index; - let mut h = hash_n_to_hash(leaf_data, false); - for s in &proof.siblings { - h = if index & 1 == 0 { - compress(h, *s) - } else { - compress(*s, h) - }; - index >>= 1; - } - h == merkle_root -} - -impl CircuitBuilder { - /// Verifies that the given leaf data is present at the given index in the Merkle tree with the - /// given root. - pub(crate) fn verify_merkle_proof( - &mut self, - leaf_data: Vec, - leaf_index: Target, - merkle_root: HashTarget, - proof: MerkleProofTarget, - ) { - todo!() - } -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::field::crandall_field::CrandallField; - - #[test] - fn test_merkle_proofs() { - type F = CrandallField; - let num_leaves = 128; - let leaves = (0..num_leaves).map(|_| vec![F::rand()]).collect::>(); - let tree = MerkleTree::new(leaves); - for i in 0..num_leaves { - let proof = tree.prove(i); - assert!(verify_merkle_proof(tree.leaves[i].clone(),i, tree.root, proof)); - } - } -} diff --git a/src/proof.rs b/src/proof.rs index f30ef028..471a808e 100644 --- a/src/proof.rs +++ b/src/proof.rs @@ -1,7 +1,7 @@ use crate::field::field::Field; use crate::target::Target; -use crate::gadgets::merkle_proofs::{MerkleProofTarget, MerkleProof}; -use crate::polynomial::polynomial::PolynomialCoeffs; +use crate::merkle_proofs::{MerkleProofTarget, MerkleProof}; +use std::convert::TryInto; /// Represents a ~256 bit hash output. #[derive(Copy, Clone, Debug, Eq, PartialEq)] @@ -10,6 +10,11 @@ pub struct Hash { } impl Hash { + pub(crate) fn from_vec(elements: Vec) -> Self { + debug_assert!(elements.len() == 4); + Self { elements: elements.try_into().unwrap() } + } + pub(crate) fn from_partial(mut elements: Vec) -> Self { debug_assert!(elements.len() <= 4); while elements.len() < 4 { @@ -19,8 +24,24 @@ impl Hash { } } +/// Represents a ~256 bit hash output. pub struct HashTarget { - pub(crate) elements: Vec, + pub(crate) elements: [Target; 4], +} + +impl HashTarget { + pub(crate) fn from_vec(elements: Vec) -> Self { + debug_assert!(elements.len() == 4); + Self { elements: elements.try_into().unwrap() } + } + + pub(crate) fn from_partial(mut elements: Vec, zero: Target) -> Self { + debug_assert!(elements.len() <= 4); + while elements.len() < 4 { + elements.push(zero); + } + Self { elements: [elements[0], elements[1], elements[2], elements[3]] } + } } pub struct Proof {