mirror of
https://github.com/logos-storage/plonky2.git
synced 2026-01-04 14:53:08 +00:00
Merge
This commit is contained in:
commit
5abd49bf47
@ -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())
|
||||
}
|
||||
|
||||
@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
27
src/proof.rs
27
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<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> {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user