mirror of
https://github.com/logos-storage/plonky2.git
synced 2026-01-10 17:53:06 +00:00
Merge pull request #730 from mir-protocol/plonky2_examples
Plonky2 examples
This commit is contained in:
commit
9e02e24df0
@ -427,6 +427,59 @@ pub trait Field:
|
||||
|
||||
pub trait PrimeField: Field {
|
||||
fn to_canonical_biguint(&self) -> BigUint;
|
||||
|
||||
fn is_quadratic_residue(&self) -> bool {
|
||||
if self.is_zero() {
|
||||
return true;
|
||||
}
|
||||
// This is based on Euler's criterion.
|
||||
let power = Self::NEG_ONE.to_canonical_biguint() / 2u8;
|
||||
let exp = self.exp_biguint(&power);
|
||||
if exp == Self::ONE {
|
||||
return true;
|
||||
}
|
||||
if exp == Self::NEG_ONE {
|
||||
return false;
|
||||
}
|
||||
panic!("Unreachable")
|
||||
}
|
||||
|
||||
fn sqrt(&self) -> Option<Self> {
|
||||
if self.is_zero() {
|
||||
Some(*self)
|
||||
} else if self.is_quadratic_residue() {
|
||||
let t = (Self::order() - BigUint::from(1u32))
|
||||
/ (BigUint::from(2u32).pow(Self::TWO_ADICITY as u32));
|
||||
let mut z = Self::POWER_OF_TWO_GENERATOR;
|
||||
let mut w = self.exp_biguint(&((t - BigUint::from(1u32)) / BigUint::from(2u32)));
|
||||
let mut x = w * *self;
|
||||
let mut b = x * w;
|
||||
|
||||
let mut v = Self::TWO_ADICITY as usize;
|
||||
|
||||
while !b.is_one() {
|
||||
let mut k = 0usize;
|
||||
let mut b2k = b;
|
||||
while !b2k.is_one() {
|
||||
b2k = b2k * b2k;
|
||||
k += 1;
|
||||
}
|
||||
let j = v - k - 1;
|
||||
w = z;
|
||||
for _ in 0..j {
|
||||
w = w * w;
|
||||
}
|
||||
|
||||
z = w * w;
|
||||
b *= z;
|
||||
x *= w;
|
||||
v = k;
|
||||
}
|
||||
Some(x)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A finite field of order less than 2^64.
|
||||
|
||||
43
plonky2/examples/factorial.rs
Normal file
43
plonky2/examples/factorial.rs
Normal file
@ -0,0 +1,43 @@
|
||||
use anyhow::Result;
|
||||
use plonky2::field::types::Field;
|
||||
use plonky2::iop::witness::{PartialWitness, Witness};
|
||||
use plonky2::plonk::circuit_builder::CircuitBuilder;
|
||||
use plonky2::plonk::circuit_data::CircuitConfig;
|
||||
use plonky2::plonk::config::{GenericConfig, PoseidonGoldilocksConfig};
|
||||
|
||||
/// An example of using Plonky2 to prove a statement of the form
|
||||
/// "I know n * (n + 1) * ... * (n + 99)".
|
||||
/// When n == 1, this is proving knowledge of 100!.
|
||||
fn main() -> Result<()> {
|
||||
const D: usize = 2;
|
||||
type C = PoseidonGoldilocksConfig;
|
||||
type F = <C as GenericConfig<D>>::F;
|
||||
|
||||
let config = CircuitConfig::standard_recursion_config();
|
||||
let mut builder = CircuitBuilder::<F, D>::new(config);
|
||||
|
||||
// The arithmetic circuit.
|
||||
let initial = builder.add_virtual_target();
|
||||
let mut cur_target = initial;
|
||||
for i in 2..101 {
|
||||
let i_target = builder.constant(F::from_canonical_u32(i));
|
||||
cur_target = builder.mul(cur_target, i_target);
|
||||
}
|
||||
|
||||
// Public inputs are the initial value (provided below) and the result (which is generated).
|
||||
builder.register_public_input(initial);
|
||||
builder.register_public_input(cur_target);
|
||||
|
||||
let mut pw = PartialWitness::new();
|
||||
pw.set_target(initial, F::ONE);
|
||||
|
||||
let data = builder.build::<C>();
|
||||
let proof = data.prove(pw)?;
|
||||
|
||||
println!(
|
||||
"Factorial starting at {} is {}!",
|
||||
proof.public_inputs[0], proof.public_inputs[1]
|
||||
);
|
||||
|
||||
data.verify(proof)
|
||||
}
|
||||
49
plonky2/examples/fibonacci.rs
Normal file
49
plonky2/examples/fibonacci.rs
Normal file
@ -0,0 +1,49 @@
|
||||
use anyhow::Result;
|
||||
use plonky2::field::types::Field;
|
||||
use plonky2::iop::witness::{PartialWitness, Witness};
|
||||
use plonky2::plonk::circuit_builder::CircuitBuilder;
|
||||
use plonky2::plonk::circuit_data::CircuitConfig;
|
||||
use plonky2::plonk::config::{GenericConfig, PoseidonGoldilocksConfig};
|
||||
|
||||
/// An example of using Plonky2 to prove a statement of the form
|
||||
/// "I know the 100th element of the Fibonacci sequence, starting with constants a and b."
|
||||
/// When a == 0 and b == 1, this is proving knowledge of the 100th (standard) Fibonacci number.
|
||||
fn main() -> Result<()> {
|
||||
const D: usize = 2;
|
||||
type C = PoseidonGoldilocksConfig;
|
||||
type F = <C as GenericConfig<D>>::F;
|
||||
|
||||
let config = CircuitConfig::standard_recursion_config();
|
||||
let mut builder = CircuitBuilder::<F, D>::new(config);
|
||||
|
||||
// The arithmetic circuit.
|
||||
let initial_a = builder.add_virtual_target();
|
||||
let initial_b = builder.add_virtual_target();
|
||||
let mut prev_target = initial_a;
|
||||
let mut cur_target = initial_b;
|
||||
for _ in 0..99 {
|
||||
let temp = builder.add(prev_target, cur_target);
|
||||
prev_target = cur_target;
|
||||
cur_target = temp;
|
||||
}
|
||||
|
||||
// Public inputs are the two initial values (provided below) and the result (which is generated).
|
||||
builder.register_public_input(initial_a);
|
||||
builder.register_public_input(initial_b);
|
||||
builder.register_public_input(cur_target);
|
||||
|
||||
// Provide initial values.
|
||||
let mut pw = PartialWitness::new();
|
||||
pw.set_target(initial_a, F::ZERO);
|
||||
pw.set_target(initial_b, F::ONE);
|
||||
|
||||
let data = builder.build::<C>();
|
||||
let proof = data.prove(pw)?;
|
||||
|
||||
println!(
|
||||
"100th Fibonacci number mod |F| (starting with {}, {}) is: {}",
|
||||
proof.public_inputs[0], proof.public_inputs[1], proof.public_inputs[2]
|
||||
);
|
||||
|
||||
data.verify(proof)
|
||||
}
|
||||
81
plonky2/examples/square_root.rs
Normal file
81
plonky2/examples/square_root.rs
Normal file
@ -0,0 +1,81 @@
|
||||
use std::marker::PhantomData;
|
||||
|
||||
use anyhow::Result;
|
||||
use plonky2::field::types::{Field, PrimeField};
|
||||
use plonky2::hash::hash_types::RichField;
|
||||
use plonky2::iop::generator::{GeneratedValues, SimpleGenerator};
|
||||
use plonky2::iop::target::Target;
|
||||
use plonky2::iop::witness::{PartialWitness, PartitionWitness, Witness};
|
||||
use plonky2::plonk::circuit_builder::CircuitBuilder;
|
||||
use plonky2::plonk::circuit_data::CircuitConfig;
|
||||
use plonky2::plonk::config::{GenericConfig, PoseidonGoldilocksConfig};
|
||||
use plonky2_field::extension::Extendable;
|
||||
|
||||
/// A generator used by the prover to calculate the square root (`x`) of a given value
|
||||
/// (`x_squared`), outside of the circuit, in order to supply it as an additional public input.
|
||||
#[derive(Debug)]
|
||||
struct SquareRootGenerator<F: RichField + Extendable<D>, const D: usize> {
|
||||
x: Target,
|
||||
x_squared: Target,
|
||||
_phantom: PhantomData<F>,
|
||||
}
|
||||
|
||||
impl<F: RichField + Extendable<D>, const D: usize> SimpleGenerator<F>
|
||||
for SquareRootGenerator<F, D>
|
||||
{
|
||||
fn dependencies(&self) -> Vec<Target> {
|
||||
vec![self.x_squared]
|
||||
}
|
||||
|
||||
fn run_once(&self, witness: &PartitionWitness<F>, out_buffer: &mut GeneratedValues<F>) {
|
||||
let x_squared = witness.get_target(self.x_squared);
|
||||
let x = x_squared.sqrt().unwrap();
|
||||
|
||||
println!("Square root: {}", x);
|
||||
|
||||
out_buffer.set_target(self.x, x);
|
||||
}
|
||||
}
|
||||
|
||||
/// An example of using Plonky2 to prove a statement of the form
|
||||
/// "I know the square root of this field element."
|
||||
fn main() -> Result<()> {
|
||||
const D: usize = 2;
|
||||
type C = PoseidonGoldilocksConfig;
|
||||
type F = <C as GenericConfig<D>>::F;
|
||||
|
||||
let config = CircuitConfig::standard_recursion_config();
|
||||
|
||||
let mut builder = CircuitBuilder::<F, D>::new(config);
|
||||
|
||||
let x = builder.add_virtual_target();
|
||||
let x_squared = builder.square(x);
|
||||
|
||||
builder.register_public_input(x_squared);
|
||||
|
||||
builder.add_simple_generator(SquareRootGenerator::<F, D> {
|
||||
x,
|
||||
x_squared,
|
||||
_phantom: PhantomData,
|
||||
});
|
||||
|
||||
// Randomly generate the value of x^2: any quadratic residue in the field works.
|
||||
let x_squared_value = {
|
||||
let mut val = F::rand();
|
||||
while !val.is_quadratic_residue() {
|
||||
val = F::rand();
|
||||
}
|
||||
val
|
||||
};
|
||||
|
||||
let mut pw = PartialWitness::new();
|
||||
pw.set_target(x_squared, x_squared_value);
|
||||
|
||||
let data = builder.build::<C>();
|
||||
let proof = data.prove(pw.clone())?;
|
||||
|
||||
let x_squared_actual = proof.public_inputs[0];
|
||||
println!("Field element (square): {}", x_squared_actual);
|
||||
|
||||
data.verify(proof)
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user