mirror of
https://github.com/logos-storage/plonky2.git
synced 2026-01-03 14:23:07 +00:00
Pass bits around
This commit is contained in:
parent
15a64017dc
commit
22fcc3bc06
@ -20,7 +20,7 @@ impl<F: Extendable<D>, const D: usize> CircuitBuilder<F, D> {
|
||||
fn compute_evaluation(
|
||||
&mut self,
|
||||
x: Target,
|
||||
old_x_index: Target,
|
||||
old_x_index_bits: &[Target],
|
||||
arity_bits: usize,
|
||||
last_evals: &[ExtensionTarget<D>],
|
||||
beta: ExtensionTarget<D>,
|
||||
@ -33,7 +33,7 @@ impl<F: Extendable<D>, const D: usize> CircuitBuilder<F, D> {
|
||||
// The evaluation vector needs to be reordered first.
|
||||
let mut evals = last_evals.to_vec();
|
||||
reverse_index_bits_in_place(&mut evals);
|
||||
let mut old_x_index_bits = self.split_le(old_x_index, arity_bits);
|
||||
let mut old_x_index_bits = old_x_index_bits.to_vec();
|
||||
old_x_index_bits.reverse();
|
||||
// Want `g^(arity - rev_old_x_index)` as in the out-of-circuit version.
|
||||
// Compute it as `g^(arity-1-rev_old_x_index) * g`, where the first term is gotten using two's complement.
|
||||
@ -148,7 +148,7 @@ impl<F: Extendable<D>, const D: usize> CircuitBuilder<F, D> {
|
||||
|
||||
fn fri_verify_initial_proof(
|
||||
&mut self,
|
||||
x_index: Target,
|
||||
x_index_bits: &[Target],
|
||||
proof: &FriInitialTreeProofTarget,
|
||||
initial_merkle_roots: &[HashTarget],
|
||||
) {
|
||||
@ -161,7 +161,7 @@ impl<F: Extendable<D>, const D: usize> CircuitBuilder<F, D> {
|
||||
context!(
|
||||
self,
|
||||
&format!("verify {}'th initial Merkle proof", i),
|
||||
self.verify_merkle_proof(evals.clone(), x_index, root, merkle_proof)
|
||||
self.verify_merkle_proof(evals.clone(), x_index_bits, root, merkle_proof)
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -255,18 +255,19 @@ impl<F: Extendable<D>, const D: usize> CircuitBuilder<F, D> {
|
||||
// TODO: Do we need to range check `x_index` to a target smaller than `p`?
|
||||
let mut x_index = challenger.get_challenge(self);
|
||||
x_index = self.split_low_high(x_index, n_log, 64).0;
|
||||
let mut x_index_bits = self.low_bits(x_index, n_log, 64);
|
||||
let mut x_index_num_bits = n_log;
|
||||
let mut domain_size = n;
|
||||
context!(
|
||||
self,
|
||||
"check FRI initial proof",
|
||||
self.fri_verify_initial_proof(
|
||||
x_index,
|
||||
&x_index_bits,
|
||||
&round_proof.initial_trees_proof,
|
||||
initial_merkle_roots,
|
||||
)
|
||||
);
|
||||
let mut old_x_index = self.zero();
|
||||
let mut old_x_index_bits = Vec::new();
|
||||
|
||||
// `subgroup_x` is `subgroup[x_index]`, i.e., the actual field element in the domain.
|
||||
let mut subgroup_x = context!(self, "compute x from its index", {
|
||||
@ -302,7 +303,7 @@ impl<F: Extendable<D>, const D: usize> CircuitBuilder<F, D> {
|
||||
"infer evaluation using interpolation",
|
||||
self.compute_evaluation(
|
||||
subgroup_x,
|
||||
old_x_index,
|
||||
&old_x_index_bits,
|
||||
config.reduction_arity_bits[i - 1],
|
||||
last_evals,
|
||||
betas[i - 1],
|
||||
@ -313,13 +314,15 @@ impl<F: Extendable<D>, const D: usize> CircuitBuilder<F, D> {
|
||||
// Insert P(y) into the evaluation vector, since it wasn't included by the prover.
|
||||
let (low_x_index, high_x_index) =
|
||||
self.split_low_high(x_index, arity_bits, x_index_num_bits);
|
||||
let high_x_index_bits = x_index_bits.split_off(arity_bits);
|
||||
old_x_index_bits = x_index_bits;
|
||||
evals = self.insert(low_x_index, e_x, evals);
|
||||
context!(
|
||||
self,
|
||||
"verify FRI round Merkle proof.",
|
||||
self.verify_merkle_proof(
|
||||
flatten_target(&evals),
|
||||
high_x_index,
|
||||
&high_x_index_bits,
|
||||
proof.commit_phase_merkle_roots[i],
|
||||
&round_proof.steps[i].merkle_proof,
|
||||
)
|
||||
@ -331,9 +334,9 @@ impl<F: Extendable<D>, const D: usize> CircuitBuilder<F, D> {
|
||||
subgroup_x = self.exp_power_of_2(subgroup_x, config.reduction_arity_bits[i - 1]);
|
||||
}
|
||||
domain_size = next_domain_size;
|
||||
old_x_index = low_x_index;
|
||||
x_index = high_x_index;
|
||||
x_index_num_bits -= arity_bits;
|
||||
x_index_bits = high_x_index_bits;
|
||||
}
|
||||
|
||||
let last_evals = evaluations.last().unwrap();
|
||||
@ -343,7 +346,7 @@ impl<F: Extendable<D>, const D: usize> CircuitBuilder<F, D> {
|
||||
"infer final evaluation using interpolation",
|
||||
self.compute_evaluation(
|
||||
subgroup_x,
|
||||
old_x_index,
|
||||
&old_x_index_bits,
|
||||
final_arity_bits,
|
||||
last_evals,
|
||||
*betas.last().unwrap(),
|
||||
|
||||
@ -14,6 +14,14 @@ impl<F: Extendable<D>, const D: usize> CircuitBuilder<F, D> {
|
||||
self.route(x, sum);
|
||||
}
|
||||
|
||||
/// Returns the first `n_log` little-endian bits of `x`.
|
||||
/// Note: `x` is assumed to be range-checked for having `num_bits` bits.
|
||||
pub fn low_bits(&mut self, x: Target, n_log: usize, num_bits: usize) -> Vec<Target> {
|
||||
let mut res = self.split_le(x, num_bits);
|
||||
res.truncate(n_log);
|
||||
res
|
||||
}
|
||||
|
||||
/// Returns `(a,b)` such that `x = a + 2^n_log * b` with `a < 2^n_log`.
|
||||
/// `x` is assumed to be range-checked for having `num_bits` bits.
|
||||
pub fn split_low_high(&mut self, x: Target, n_log: usize, num_bits: usize) -> (Target, Target) {
|
||||
|
||||
@ -59,23 +59,20 @@ pub(crate) fn verify_merkle_proof<F: Field>(
|
||||
|
||||
impl<F: Extendable<D>, const D: usize> CircuitBuilder<F, D> {
|
||||
/// Verifies that the given leaf data is present at the given index in the Merkle tree with the
|
||||
/// given root.
|
||||
/// given root. The index is given by it's little-endian bits.
|
||||
pub(crate) fn verify_merkle_proof(
|
||||
&mut self,
|
||||
leaf_data: Vec<Target>,
|
||||
leaf_index: Target,
|
||||
leaf_index_bits: &[Target],
|
||||
merkle_root: HashTarget,
|
||||
proof: &MerkleProofTarget,
|
||||
) {
|
||||
let zero = self.zero();
|
||||
let two = self.two();
|
||||
let height = proof.siblings.len();
|
||||
let purported_index_bits = self.split_le_virtual(leaf_index, height);
|
||||
|
||||
let mut state: HashTarget = self.hash_or_noop(leaf_data);
|
||||
let mut acc_leaf_index = zero;
|
||||
|
||||
for (bit, &sibling) in purported_index_bits.into_iter().zip(&proof.siblings) {
|
||||
for (&bit, &sibling) in leaf_index_bits.iter().zip(&proof.siblings) {
|
||||
let gate = self
|
||||
.add_gate_no_constants(GMiMCGate::<F, D, GMIMC_ROUNDS>::with_automatic_constants());
|
||||
|
||||
@ -86,8 +83,6 @@ impl<F: Extendable<D>, const D: usize> CircuitBuilder<F, D> {
|
||||
});
|
||||
self.generate_copy(bit, swap_wire);
|
||||
|
||||
acc_leaf_index = self.mul_add(two, acc_leaf_index, bit);
|
||||
|
||||
let input_wires = (0..12)
|
||||
.map(|i| {
|
||||
Target::Wire(Wire {
|
||||
@ -115,10 +110,6 @@ impl<F: Extendable<D>, const D: usize> CircuitBuilder<F, D> {
|
||||
)
|
||||
}
|
||||
|
||||
// TODO: this is far from optimal.
|
||||
let leaf_index_rev = self.reverse_limbs::<2>(leaf_index, height);
|
||||
self.assert_equal(acc_leaf_index, leaf_index_rev);
|
||||
|
||||
self.named_assert_hashes_equal(state, merkle_root, "check Merkle root".into())
|
||||
}
|
||||
|
||||
@ -180,13 +171,14 @@ mod tests {
|
||||
pw.set_hash_target(root_t, tree.root);
|
||||
|
||||
let i_c = builder.constant(F::from_canonical_usize(i));
|
||||
let i_bits = builder.split_le(i_c, log_n);
|
||||
|
||||
let data = builder.add_virtual_targets(tree.leaves[i].len());
|
||||
for j in 0..data.len() {
|
||||
pw.set_target(data[j], tree.leaves[i][j]);
|
||||
}
|
||||
|
||||
builder.verify_merkle_proof(data, i_c, root_t, &proof_t);
|
||||
builder.verify_merkle_proof(data, &i_bits, root_t, &proof_t);
|
||||
|
||||
let data = builder.build();
|
||||
let proof = data.prove(pw)?;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user