This commit is contained in:
wborgeaud 2021-04-12 10:34:40 +02:00
commit 5abd49bf47
3 changed files with 48 additions and 121 deletions

View File

@ -22,8 +22,13 @@ pub struct CircuitBuilder<F: Field> {
/// The types of gates used in this circuit.
gates: HashSet<GateRef<F>>,
/// The concrete placement of each gate.
gate_instances: Vec<GateInstance<F>>,
/// The next available index for a VirtualAdviceTarget.
virtual_target_index: usize,
/// Generators used to generate the witness.
generators: Vec<Box<dyn WitnessGenerator<F>>>,
}
@ -33,10 +38,29 @@ impl<F: Field> CircuitBuilder<F> {
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<Target> {
(0..n).map(|_i| self.add_virtual_advice_target()).collect()
}
pub fn add_gate_no_constants(&mut self, gate_type: GateRef<F>) -> usize {
self.add_gate(gate_type, Vec::new())
}

View File

@ -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<F: Field> {
/// The Merkle digest of each sibling subtree, staying from the bottommost layer.
pub siblings: Vec<Hash<F>>,
}
pub struct MerkleProofTarget {
/// The Merkle digest of each sibling subtree, staying from the bottommost layer.
pub siblings: Vec<HashTarget>,
}
#[derive(Clone, Debug)]
pub struct MerkleTree<F: Field> {
/// The data in the leaves of the Merkle tree.
pub leaves: Vec<Vec<F>>,
/// The layers of hashes in the tree. The first layer is the one at the bottom.
pub layers: Vec<Vec<Hash<F>>>,
/// The Merkle root.
pub root: Hash<F>,
}
impl<F: Field> MerkleTree<F> {
pub fn new(leaves: Vec<Vec<F>>) -> Self {
let mut layers = vec![leaves.iter().map(|l| hash_n_to_hash(l.clone(), false)).collect::<Vec<_>>()];
loop {
match layers.last() {
Some(l) if l.len() > 1 => {
layers.push(l.chunks(2).map(|chunk| compress(chunk[0], chunk[1])).collect::<Vec<_>>());
},
_ => 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<F> {
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<F: Field>(
leaf_data: Vec<F>,
leaf_index: usize,
merkle_root: Hash<F>,
proof: MerkleProof<F>,
) -> 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<F: Field> CircuitBuilder<F> {
/// 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<Target>,
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::<Vec<_>>();
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));
}
}
}

View File

@ -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<F: Field> {
}
impl<F: Field> Hash<F> {
pub(crate) fn from_vec(elements: Vec<F>) -> Self {
debug_assert!(elements.len() == 4);
Self { elements: elements.try_into().unwrap() }
}
pub(crate) fn from_partial(mut elements: Vec<F>) -> Self {
debug_assert!(elements.len() <= 4);
while elements.len() < 4 {
@ -19,8 +24,24 @@ impl<F: Field> Hash<F> {
}
}
/// Represents a ~256 bit hash output.
pub struct HashTarget {
pub(crate) elements: Vec<Target>,
pub(crate) elements: [Target; 4],
}
impl HashTarget {
pub(crate) fn from_vec(elements: Vec<Target>) -> Self {
debug_assert!(elements.len() == 4);
Self { elements: elements.try_into().unwrap() }
}
pub(crate) fn from_partial(mut elements: Vec<Target>, 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<F: Field> {