Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
07aff4a
included poseidon-gadget
lydiagarms Nov 29, 2024
abcbf18
sum check comments and and changing to BN254 field for poseidon circuit
lydiagarms Dec 20, 2024
33788fa
Merge remote-tracking branch 'origin/main' into lydia/poseidoncircuit
lydiagarms Dec 20, 2024
715e098
add parameter file and reduce parameter
lydiagarms Dec 20, 2024
ed084d4
move into circuits folder
lydiagarms Dec 20, 2024
b6f0f99
Revert "Merge remote-tracking branch 'origin/main' into lydia/poseido…
lydiagarms Dec 20, 2024
dbdd662
remove old parameters with pasta curves
lydiagarms Dec 20, 2024
de2be28
fix: lint error
lydiagarms Jan 6, 2025
52dca76
fix: lint error
lydiagarms Jan 6, 2025
4ae29bd
fix: lint errors
lydiagarms Jan 6, 2025
3ed3925
fix: lint errors
lydiagarms Jan 6, 2025
2fa3680
fix: lint errors
lydiagarms Jan 6, 2025
8a72d56
fix: lint errors
lydiagarms Jan 6, 2025
18f41e0
fix: lint errors
lydiagarms Jan 6, 2025
2738b66
fix: lint errors
lydiagarms Jan 6, 2025
26edf8d
fix: lint errors
lydiagarms Jan 6, 2025
b79d9a6
change rust version
lydiagarms Jan 6, 2025
8680902
change version back
lydiagarms Jan 6, 2025
dfd0126
remove unnecessary imports
lydiagarms Jan 6, 2025
c1b82de
fix: lint error
lydiagarms Jan 6, 2025
3002187
fix: change version back
lydiagarms Jan 6, 2025
f5ae9e0
Revert "Revert "Merge remote-tracking branch 'origin/main' into lydia…
lydiagarms Jan 6, 2025
2002b42
Merge remote-tracking branch 'origin' into lydia/poseidonCircuit
lydiagarms Jan 6, 2025
dcf5921
working full hash test
lydiagarms Jan 6, 2025
bd0f57d
fix lint errors
lydiagarms Jan 6, 2025
d5fb490
fix lint errors
lydiagarms Jan 6, 2025
f1449a6
fix lint errors
lydiagarms Jan 6, 2025
e2e7a56
chore: poseidon longer input tests and delete unnecessary ones
lydiagarms Jan 8, 2025
351e367
fix: lint error
lydiagarms Jan 8, 2025
95ecf4e
test for all input lengths using macros
lydiagarms Jan 8, 2025
b187f21
fix: lint errors
lydiagarms Jan 8, 2025
3b51883
fix: lint error
lydiagarms Jan 8, 2025
0defc6a
fix: lint error
lydiagarms Jan 8, 2025
ec339c1
remove unnecessary tests and change test to BN256
lydiagarms Jan 8, 2025
cbfa4ce
fix lint errors
lydiagarms Jan 8, 2025
c6de962
remove comments
lydiagarms Jan 8, 2025
6767cee
remove comments
lydiagarms Jan 8, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions plonkish_backend/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@ serde = { version = "1.0", features = ["derive"] }
bincode = "1.3.3"
sha3 = "0.10.6"
poseidon = { git = "https://github.com/han0110/poseidon", branch = "feature/with-spec" }
ff = { version = "0.13", features = ["bits"] }
group = "0.13"
proptest = { version = "1.0.0", optional = true }
uint = "0.9.2"

# timer
ark-std = { version = "^0.4.0", default-features = false, optional = true }
Expand All @@ -30,6 +34,7 @@ halo2_proofs = { git = "https://github.com/han0110/halo2.git", branch = "feature
paste = "1.0.11"
criterion = "0.4.0"
pprof = { version = "0.11.0", features = ["criterion", "flamegraph"] }
proptest = "1.0.0"

[features]
default = ["parallel", "frontend-halo2"]
Expand Down
4 changes: 4 additions & 0 deletions plonkish_backend/src/backend/hyperplonk/verifier.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ pub(crate) fn verify_sum_check<F: PrimeField>(
y: &[F],
transcript: &mut impl FieldTranscriptRead<F>,
) -> Result<(Vec<Vec<F>>, Vec<Evaluation<F>>), Error> {
// In description of the sum check protocol in https://eprint.iacr.org/2022/1355.pdf,
// x_eval corresponds to the v in the final check, x is \alpha_1, ..., \alpha_{\mu} the challenges during the sum check protocol
let (x_eval, x) = ClassicSumCheck::<EvaluationsProver<_>, BinaryField>::verify(
&(),
num_vars,
Expand All @@ -56,6 +58,7 @@ pub(crate) fn verify_sum_check<F: PrimeField>(
transcript,
)?;

// Check that f(\alpha_1, ..., \alpha_{\mu}) = v holds, where f is the expression
let pcs_query = pcs_query(expression, instances.len());
let (evals_for_rotation, evals) = pcs_query
.iter()
Expand All @@ -79,6 +82,7 @@ pub(crate) fn verify_sum_check<F: PrimeField>(
));
}

// Obtain points and evaluations for which we need to verify the opening proofs
let point_offset = point_offset(&pcs_query);
let evals = pcs_query
.iter()
Expand Down
1 change: 1 addition & 0 deletions plonkish_backend/src/circuits.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
pub mod poseidongadget;
14 changes: 14 additions & 0 deletions plonkish_backend/src/circuits/poseidongadget.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// This crate been taking from privacy scaling explorations crate: https://github.com/privacy-scaling-explorations/poseidon-gadget/tree/main/src
//! This crate provides the poseidon gadget for use with `halo2_proofs`.
//! This gadget has been extracted from zcash's halo2_gadgets:
//! https://github.com/zcash/halo2/tree/main/halo2_gadgets

#![cfg_attr(docsrs, feature(doc_cfg))]
// Catch documentation errors caused by code changes.
#![deny(rustdoc::broken_intra_doc_links)]
#![deny(missing_debug_implementations)]
#![deny(missing_docs)]
#![deny(unsafe_code)]

pub mod poseidon;
pub mod utilities;
298 changes: 298 additions & 0 deletions plonkish_backend/src/circuits/poseidongadget/poseidon.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,298 @@
//! The Poseidon algebraic hash function.

use std::convert::TryInto;
use std::fmt;
use std::marker::PhantomData;

use ff::PrimeField;
use group::ff::Field;
use halo2_proofs::{
circuit::{AssignedCell, Chip, Layouter},
plonk::Error,
};

mod pow5;
pub use pow5::{Pow5Chip, Pow5Config, StateWord};

pub mod primitives;
use primitives::{Absorbing, ConstantLength, Domain, Spec, SpongeMode, Squeezing, State};

/// A word from the padded input to a Poseidon sponge.
#[derive(Clone, Debug)]
pub enum PaddedWord<F: Field> {
/// A message word provided by the prover.
Message(AssignedCell<F, F>),
/// A padding word, that will be fixed in the circuit parameters.
Padding(F),
}

/// The set of circuit instructions required to use the Poseidon permutation.
pub trait PoseidonInstructions<F: Field, S: Spec<F, T, RATE>, const T: usize, const RATE: usize>:
Chip<F>
{
/// Variable representing the word over which the Poseidon permutation operates.
type Word: Clone + fmt::Debug + From<AssignedCell<F, F>> + Into<AssignedCell<F, F>>;

/// Applies the Poseidon permutation to the given state.
fn permute(
&self,
layouter: &mut impl Layouter<F>,
initial_state: &State<Self::Word, T>,
) -> Result<State<Self::Word, T>, Error>;
}

/// The set of circuit instructions required to use the [`Sponge`] and [`Hash`] gadgets.
///
/// [`Hash`]: self::Hash
pub trait PoseidonSpongeInstructions<
F: Field,
S: Spec<F, T, RATE>,
D: Domain<F, RATE>,
const T: usize,
const RATE: usize,
>: PoseidonInstructions<F, S, T, RATE>
{
/// Returns the initial empty state for the given domain.
fn initial_state(&self, layouter: &mut impl Layouter<F>)
-> Result<State<Self::Word, T>, Error>;

/// Adds the given input to the state.
fn add_input(
&self,
layouter: &mut impl Layouter<F>,
initial_state: &State<Self::Word, T>,
input: &Absorbing<PaddedWord<F>, RATE>,
) -> Result<State<Self::Word, T>, Error>;

/// Extracts sponge output from the given state.
fn get_output(state: &State<Self::Word, T>) -> Squeezing<Self::Word, RATE>;
}

/// A word over which the Poseidon permutation operates.
#[derive(Debug)]
pub struct Word<
F: Field,
PoseidonChip: PoseidonInstructions<F, S, T, RATE>,
S: Spec<F, T, RATE>,
// Width
const T: usize,
const RATE: usize,
> {
inner: PoseidonChip::Word,
}

impl<
F: Field,
PoseidonChip: PoseidonInstructions<F, S, T, RATE>,
S: Spec<F, T, RATE>,
const T: usize,
const RATE: usize,
> Word<F, PoseidonChip, S, T, RATE>
{
/// The word contained in this gadget.
pub fn inner(&self) -> PoseidonChip::Word {
self.inner.clone()
}

/// Construct a [`Word`] gadget from the inner word.
pub fn from_inner(inner: PoseidonChip::Word) -> Self {
Self { inner }
}
}

fn poseidon_sponge<
F: Field,
PoseidonChip: PoseidonSpongeInstructions<F, S, D, T, RATE>,
S: Spec<F, T, RATE>,
D: Domain<F, RATE>,
const T: usize,
const RATE: usize,
>(
chip: &PoseidonChip,
mut layouter: impl Layouter<F>,
state: &mut State<PoseidonChip::Word, T>,
input: Option<&Absorbing<PaddedWord<F>, RATE>>,
) -> Result<Squeezing<PoseidonChip::Word, RATE>, Error> {
if let Some(input) = input {
*state = chip.add_input(&mut layouter, state, input)?;
}
*state = chip.permute(&mut layouter, state)?;
Ok(PoseidonChip::get_output(state))
}

/// A Poseidon sponge.
#[derive(Debug)]
pub struct Sponge<
F: Field,
PoseidonChip: PoseidonSpongeInstructions<F, S, D, T, RATE>,
S: Spec<F, T, RATE>,
M: SpongeMode,
D: Domain<F, RATE>,
const T: usize,
const RATE: usize,
> {
chip: PoseidonChip,
mode: M,
state: State<PoseidonChip::Word, T>,
_marker: PhantomData<D>,
}

impl<
F: Field,
PoseidonChip: PoseidonSpongeInstructions<F, S, D, T, RATE>,
S: Spec<F, T, RATE>,
D: Domain<F, RATE>,
const T: usize,
const RATE: usize,
> Sponge<F, PoseidonChip, S, Absorbing<PaddedWord<F>, RATE>, D, T, RATE>
{
/// Constructs a new duplex sponge for the given Poseidon specification.
pub fn new(chip: PoseidonChip, mut layouter: impl Layouter<F>) -> Result<Self, Error> {
chip.initial_state(&mut layouter).map(|state| Sponge {
chip,
mode: Absorbing(
(0..RATE)
.map(|_| None)
.collect::<Vec<_>>()
.try_into()
.unwrap(),
),
state,
_marker: PhantomData,
})
}

/// Absorbs an element into the sponge.
pub fn absorb(
&mut self,
mut layouter: impl Layouter<F>,
value: PaddedWord<F>,
) -> Result<(), Error> {
for entry in self.mode.0.iter_mut() {
if entry.is_none() {
*entry = Some(value);
return Ok(());
}
}

// We've already absorbed as many elements as we can
let _ = poseidon_sponge(
&self.chip,
layouter.namespace(|| "PoseidonSponge"),
&mut self.state,
Some(&self.mode),
)?;
self.mode = Absorbing::init_with(value);

Ok(())
}

/// Transitions the sponge into its squeezing state.
#[allow(clippy::type_complexity)]
pub fn finish_absorbing(
mut self,
mut layouter: impl Layouter<F>,
) -> Result<Sponge<F, PoseidonChip, S, Squeezing<PoseidonChip::Word, RATE>, D, T, RATE>, Error>
{
let mode = poseidon_sponge(
&self.chip,
layouter.namespace(|| "PoseidonSponge"),
&mut self.state,
Some(&self.mode),
)?;

Ok(Sponge {
chip: self.chip,
mode,
state: self.state,
_marker: PhantomData,
})
}
}

impl<
F: Field,
PoseidonChip: PoseidonSpongeInstructions<F, S, D, T, RATE>,
S: Spec<F, T, RATE>,
D: Domain<F, RATE>,
const T: usize,
const RATE: usize,
> Sponge<F, PoseidonChip, S, Squeezing<PoseidonChip::Word, RATE>, D, T, RATE>
{
/// Squeezes an element from the sponge.
pub fn squeeze(&mut self, mut layouter: impl Layouter<F>) -> Result<AssignedCell<F, F>, Error> {
loop {
for entry in self.mode.0.iter_mut() {
if let Some(inner) = entry.take() {
return Ok(inner.into());
}
}

// We've already squeezed out all available elements
self.mode = poseidon_sponge(
&self.chip,
layouter.namespace(|| "PoseidonSponge"),
&mut self.state,
None,
)?;
}
}
}

/// A Poseidon hash function, built around a sponge.
#[derive(Debug)]
pub struct Hash<
F: Field,
PoseidonChip: PoseidonSpongeInstructions<F, S, D, T, RATE>,
S: Spec<F, T, RATE>,
D: Domain<F, RATE>,
const T: usize,
const RATE: usize,
> {
sponge: Sponge<F, PoseidonChip, S, Absorbing<PaddedWord<F>, RATE>, D, T, RATE>,
}

impl<
F: Field,
PoseidonChip: PoseidonSpongeInstructions<F, S, D, T, RATE>,
S: Spec<F, T, RATE>,
D: Domain<F, RATE>,
const T: usize,
const RATE: usize,
> Hash<F, PoseidonChip, S, D, T, RATE>
{
/// Initializes a new hasher.
pub fn init(chip: PoseidonChip, layouter: impl Layouter<F>) -> Result<Self, Error> {
Sponge::new(chip, layouter).map(|sponge| Hash { sponge })
}
}

impl<
F: PrimeField,
PoseidonChip: PoseidonSpongeInstructions<F, S, ConstantLength<L>, T, RATE>,
S: Spec<F, T, RATE>,
const T: usize,
const RATE: usize,
const L: usize,
> Hash<F, PoseidonChip, S, ConstantLength<L>, T, RATE>
{
/// Hashes the given input.
pub fn hash(
mut self,
mut layouter: impl Layouter<F>,
message: [AssignedCell<F, F>; L],
) -> Result<AssignedCell<F, F>, Error> {
for (i, value) in message
.into_iter()
.map(PaddedWord::Message)
.chain(<ConstantLength<L> as Domain<F, RATE>>::padding(L).map(PaddedWord::Padding))
.enumerate()
{
self.sponge
.absorb(layouter.namespace(|| format!("absorb_{i}")), value)?;
}
self.sponge
.finish_absorbing(layouter.namespace(|| "finish absorbing"))?
.squeeze(layouter.namespace(|| "squeeze"))
}
}
Loading
Loading