mirror of
https://github.com/logos-storage/plonky2.git
synced 2026-04-18 17:43:14 +00:00
Fix bugs
This commit is contained in:
parent
f8dd35b748
commit
81ce0eb710
@ -11,8 +11,11 @@ use crate::witness::PartialWitness;
|
|||||||
impl<F: Extendable<D>, const D: usize> CircuitBuilder<F, D> {
|
impl<F: Extendable<D>, const D: usize> CircuitBuilder<F, D> {
|
||||||
/// Split the given element into a list of targets, where each one represents a
|
/// Split the given element into a list of targets, where each one represents a
|
||||||
/// base-B limb of the element, with little-endian ordering.
|
/// base-B limb of the element, with little-endian ordering.
|
||||||
pub(crate) fn split_le_base<const B: usize>(&mut self, x: Target) -> Vec<Target> {
|
pub(crate) fn split_le_base<const B: usize>(
|
||||||
let num_limbs = num_limbs_to_check(64, B);
|
&mut self,
|
||||||
|
x: Target,
|
||||||
|
num_limbs: usize,
|
||||||
|
) -> Vec<Target> {
|
||||||
let gate = self.add_gate(BaseSumGate::<B>::new(num_limbs), vec![]);
|
let gate = self.add_gate(BaseSumGate::<B>::new(num_limbs), vec![]);
|
||||||
let sum = Target::wire(gate, BaseSumGate::<B>::WIRE_SUM);
|
let sum = Target::wire(gate, BaseSumGate::<B>::WIRE_SUM);
|
||||||
self.route(x, sum);
|
self.route(x, sum);
|
||||||
@ -25,8 +28,9 @@ impl<F: Extendable<D>, const D: usize> CircuitBuilder<F, D> {
|
|||||||
|
|
||||||
/// Asserts that `x`'s bit representation has at least `trailing_zeros` trailing zeros.
|
/// Asserts that `x`'s bit representation has at least `trailing_zeros` trailing zeros.
|
||||||
pub(crate) fn assert_trailing_zeros<const B: usize>(&mut self, x: Target, trailing_zeros: u32) {
|
pub(crate) fn assert_trailing_zeros<const B: usize>(&mut self, x: Target, trailing_zeros: u32) {
|
||||||
let limbs = self.split_le_base::<B>(x);
|
let num_limbs = num_limbs(64, B);
|
||||||
let num_limbs_to_check = num_limbs_to_check(trailing_zeros, B);
|
let num_limbs_to_check = num_limbs_to_check(trailing_zeros, B);
|
||||||
|
let limbs = self.split_le_base::<B>(x, num_limbs);
|
||||||
assert!(
|
assert!(
|
||||||
num_limbs_to_check < self.config.num_routed_wires,
|
num_limbs_to_check < self.config.num_routed_wires,
|
||||||
"Not enough routed wires."
|
"Not enough routed wires."
|
||||||
@ -47,6 +51,7 @@ impl<F: Extendable<D>, const D: usize> CircuitBuilder<F, D> {
|
|||||||
|
|
||||||
/// Returns `k` such that any number with `k` trailing zeros in base `base` has at least
|
/// Returns `k` such that any number with `k` trailing zeros in base `base` has at least
|
||||||
/// `n` trailing zeros in base 2.
|
/// `n` trailing zeros in base 2.
|
||||||
|
#[allow(unconditional_panic)]
|
||||||
const fn num_limbs_to_check(n: u32, base: usize) -> usize {
|
const fn num_limbs_to_check(n: u32, base: usize) -> usize {
|
||||||
if base % 2 == 1 {
|
if base % 2 == 1 {
|
||||||
// Dirty trick to panic if the base is odd.
|
// Dirty trick to panic if the base is odd.
|
||||||
@ -57,6 +62,10 @@ const fn num_limbs_to_check(n: u32, base: usize) -> usize {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn num_limbs(n_log: u32, base: usize) -> usize {
|
||||||
|
((n_log as f64) * 2.0_f64.log(base as f64)).ceil() as usize
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
@ -68,7 +77,7 @@ mod tests {
|
|||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_split_base() -> Result<()> {
|
fn test_split_base() {
|
||||||
type F = CrandallField;
|
type F = CrandallField;
|
||||||
let config = CircuitConfig {
|
let config = CircuitConfig {
|
||||||
num_wires: 134,
|
num_wires: 134,
|
||||||
@ -85,24 +94,23 @@ mod tests {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
let mut builder = CircuitBuilder::<F, 4>::new(config);
|
let mut builder = CircuitBuilder::<F, 4>::new(config);
|
||||||
let x = F::from_canonical_usize(0b10100000); // 160 =1120 in base 5.
|
let x = F::from_canonical_usize(0b110100000); // 416 = 1532 in base 6.
|
||||||
let xt = builder.constant(x);
|
let xt = builder.constant(x);
|
||||||
let limbs = builder.split_le_base::<5>(xt);
|
let limbs = builder.split_le_base::<6>(xt, 24);
|
||||||
assert_eq!(limbs.len(), 28); // 5^27 < 2^64 <= 5^28
|
|
||||||
let zero = builder.zero();
|
|
||||||
let one = builder.one();
|
let one = builder.one();
|
||||||
let two = builder.two();
|
let two = builder.two();
|
||||||
builder.assert_equal(limbs[0], zero);
|
let three = builder.constant(F::from_canonical_u64(3));
|
||||||
builder.assert_equal(limbs[1], two);
|
let five = builder.constant(F::from_canonical_u64(5));
|
||||||
builder.assert_equal(limbs[2], one);
|
builder.assert_equal(limbs[0], two);
|
||||||
|
builder.assert_equal(limbs[1], three);
|
||||||
|
builder.assert_equal(limbs[2], five);
|
||||||
builder.assert_equal(limbs[3], one);
|
builder.assert_equal(limbs[3], one);
|
||||||
|
|
||||||
builder.assert_trailing_zeros::<3>(xt, 4);
|
builder.assert_trailing_zeros::<6>(xt, 4);
|
||||||
builder.assert_trailing_zeros::<3>(xt, 5);
|
builder.assert_trailing_zeros::<4>(xt, 5);
|
||||||
builder.assert_trailing_zeros::<13>(xt, 5);
|
builder.assert_trailing_zeros::<12>(xt, 5);
|
||||||
let data = builder.build();
|
let data = builder.build();
|
||||||
|
|
||||||
let proof = data.prove(PartialWitness::new());
|
let proof = data.prove(PartialWitness::new());
|
||||||
verify(proof, &data.verifier_only, &data.common)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -146,7 +146,7 @@ impl<F: Field> SimpleGenerator<F> for WireSplitGenerator {
|
|||||||
sum,
|
sum,
|
||||||
F::from_canonical_u64(integer_value & ((1 << self.num_limbs) - 1)),
|
F::from_canonical_u64(integer_value & ((1 << self.num_limbs) - 1)),
|
||||||
);
|
);
|
||||||
integer_value >> self.num_limbs;
|
integer_value >>= self.num_limbs;
|
||||||
}
|
}
|
||||||
|
|
||||||
debug_assert_eq!(
|
debug_assert_eq!(
|
||||||
|
|||||||
@ -134,6 +134,12 @@ impl<F: Field, const B: usize> SimpleGenerator<F> for BaseSplitGenerator<B> {
|
|||||||
let sum_value = witness
|
let sum_value = witness
|
||||||
.get_target(Target::wire(self.gate_index, BaseSumGate::<B>::WIRE_SUM))
|
.get_target(Target::wire(self.gate_index, BaseSumGate::<B>::WIRE_SUM))
|
||||||
.to_canonical_u64() as usize;
|
.to_canonical_u64() as usize;
|
||||||
|
debug_assert_eq!(
|
||||||
|
(0..self.num_limbs).fold(sum_value, |acc, _| acc / B),
|
||||||
|
0,
|
||||||
|
"Integer too large to fit in given number of limbs"
|
||||||
|
);
|
||||||
|
|
||||||
let limbs = (BaseSumGate::<B>::WIRE_LIMBS_START
|
let limbs = (BaseSumGate::<B>::WIRE_LIMBS_START
|
||||||
..BaseSumGate::<B>::WIRE_LIMBS_START + self.num_limbs)
|
..BaseSumGate::<B>::WIRE_LIMBS_START + self.num_limbs)
|
||||||
.map(|i| Target::wire(self.gate_index, i));
|
.map(|i| Target::wire(self.gate_index, i));
|
||||||
@ -156,11 +162,6 @@ impl<F: Field, const B: usize> SimpleGenerator<F> for BaseSplitGenerator<B> {
|
|||||||
result.set_target(b, F::from_canonical_usize(b_value));
|
result.set_target(b, F::from_canonical_usize(b_value));
|
||||||
}
|
}
|
||||||
|
|
||||||
debug_assert_eq!(
|
|
||||||
sum_value, 0,
|
|
||||||
"Integer too large to fit in given number of limbs"
|
|
||||||
);
|
|
||||||
|
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user