Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Created CRHF trait and conform RescueCRH impl #169

Merged
merged 8 commits into from
Dec 22, 2022
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
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
8 changes: 4 additions & 4 deletions plonk/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ pub enum PlonkError {
/// Plonk proof verification failed due to wrong proof
WrongProof,
/// Rescue Error
RescueError(jf_primitives::rescue::errors::RescueError),
PrimitiveError(jf_primitives::errors::PrimitivesError),
/// Invalid parameters
InvalidParameters(String),
/// Non-native field overflow
Expand Down Expand Up @@ -66,9 +66,9 @@ impl From<ark_serialize::SerializationError> for PlonkError {
}
}

impl From<jf_primitives::rescue::errors::RescueError> for PlonkError {
fn from(e: jf_primitives::rescue::errors::RescueError) -> Self {
Self::RescueError(e)
impl From<jf_primitives::errors::PrimitivesError> for PlonkError {
fn from(e: jf_primitives::errors::PrimitivesError) -> Self {
Self::PrimitiveError(e)
}
}

Expand Down
2 changes: 1 addition & 1 deletion plonk/src/transcript/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -207,5 +207,5 @@ pub trait PlonkTranscript<F> {
/// and then append it to the transcript.
fn get_and_append_challenge<E>(&mut self, label: &'static [u8]) -> Result<E::Fr, PlonkError>
where
E: PairingEngine;
E: PairingEngine<Fq = F>;
}
7 changes: 4 additions & 3 deletions plonk/src/transcript/rescue.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,9 @@ use ark_ec::{
};
use ark_std::vec::Vec;
use jf_primitives::{
crhf::{VariableLengthRescueCRHF, CRHF},
pcs::prelude::Commitment,
rescue::{sponge::RescueCRHF, RescueParameter, STATE_SIZE},
rescue::{RescueParameter, STATE_SIZE},
};
use jf_relation::gadgets::ecc::{Point, SWToTEConParam};
use jf_utils::{bytes_to_field_elements, field_switching, fq_to_fr_with_mask};
Expand Down Expand Up @@ -169,14 +170,14 @@ where
/// efficiency.
fn get_and_append_challenge<E>(&mut self, _label: &'static [u8]) -> Result<E::Fr, PlonkError>
where
E: PairingEngine,
E: PairingEngine<Fq = F>,
{
// 1. state: [F: STATE_SIZE] = hash(state|transcript)
// 2. challenge = state[0] in Fr
// 3. transcript = Vec::new()

let input = [self.state.as_ref(), self.transcript.as_ref()].concat();
let tmp = RescueCRHF::sponge_with_padding(&input, STATE_SIZE);
let tmp: [F; STATE_SIZE] = VariableLengthRescueCRHF::evaluate(&(), &input)?;
let challenge = fq_to_fr_with_mask::<F, E::Fr>(&tmp[0]);
self.state.copy_from_slice(&tmp);
self.transcript = Vec::new();
Expand Down
2 changes: 1 addition & 1 deletion primitives/src/circuit/merkle_tree/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ mod rescue_merkle_tree;
/// let (_, proof) = mt.lookup(2).expect_ok().unwrap();
///
/// // Circuit computation with a MT
/// let leaf_var = circuit.create_leaf_variable(Fq::from(2_u64), Fq::from(100_u64)).unwrap();
/// let leaf_var = circuit.create_leaf_variable(2_u64, Fq::from(100_u64)).unwrap();
/// let path_vars = circuit.create_membership_proof_variable(&proof).unwrap();
/// let root_var = circuit.create_root_variable(expected_root).unwrap();
/// circuit.enforce_merkle_proof(leaf_var, path_vars, root_var).unwrap();
Expand Down
117 changes: 117 additions & 0 deletions primitives/src/crhf.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
// Copyright (c) 2022 Espresso Systems (espressosys.com)
// This file is part of the Jellyfish library.

// You should have received a copy of the MIT License
// along with the Jellyfish library. If not, see <https://mit-license.org/>.

//! Collision-resistant Hash Functions (CRHF) definitions and implementations.

use ark_std::{
borrow::Borrow,
fmt::Debug,
hash::Hash,
marker::PhantomData,
rand::{CryptoRng, RngCore},
string::ToString,
vec::Vec,
};

use crate::{
errors::PrimitivesError,
rescue::{sponge::RescueCRHF, RescueParameter, CRHF_RATE},
};

/// A trait for CRHF
/// (based on ark-primitives' definition, but self-declared for minimal
/// dependency and easier future upgradability.)
pub trait CRHF {
/// Input to the CRHF
type Input;
/// Output of the CRHF
// FIXME: (alex) wait until arkwork 0.4.0 to add the following:
// + Default + CanonicalSerialize + CanonicalDeserialize;
// right now, const-generic are not supported yet.
type Output: Clone + PartialEq + Eq + Hash + Debug;

/// Public parameters of the CRHF (if any)
type Parameters: Clone + Debug + Sync + Send;

/// picking the concrete CRHF from the parameterized hash family
fn setup<R: RngCore + CryptoRng>(rng: &mut R) -> Result<Self::Parameters, PrimitivesError>;

/// evaluate inputs and return hash output
fn evaluate<T: Borrow<Self::Input>>(
param: &Self::Parameters,
input: T,
) -> Result<Self::Output, PrimitivesError>;
}

#[derive(Debug, Clone)]
/// A rescue-sponge-based CRHF with fixed-input size (if not multiple of 3 will
/// auto-padded) and variable-output size
pub struct FixedLengthRescueCRHF<
F: RescueParameter,
const INPUT_LEN: usize,
const OUTPUT_LEN: usize,
>(PhantomData<F>);

impl<F: RescueParameter, const INPUT_LEN: usize, const OUTPUT_LEN: usize> CRHF
for FixedLengthRescueCRHF<F, INPUT_LEN, OUTPUT_LEN>
{
type Input = [F; INPUT_LEN];
type Output = [F; OUTPUT_LEN];
type Parameters = ();

fn setup<R: RngCore + CryptoRng>(_rng: &mut R) -> Result<Self::Parameters, PrimitivesError> {
Ok(())
}

fn evaluate<T: Borrow<Self::Input>>(
_param: &Self::Parameters,
input: T,
) -> Result<Self::Output, PrimitivesError> {
let mut output = [F::zero(); OUTPUT_LEN];

let res = match INPUT_LEN % CRHF_RATE {
0 => RescueCRHF::<F>::sponge_no_padding(input.borrow(), OUTPUT_LEN)?,
_ => RescueCRHF::<F>::sponge_with_padding(input.borrow(), OUTPUT_LEN),
};
if res.len() != OUTPUT_LEN {
return Err(PrimitivesError::InternalError(
"Unexpected rescue sponge return length".to_string(),
));
}

output.copy_from_slice(&res[..]);
Ok(output)
}
}

#[derive(Debug, Clone)]
/// A rescue-sponge-based CRHF with variable-input and variable-output size
pub struct VariableLengthRescueCRHF<F: RescueParameter, const OUTPUT_LEN: usize>(PhantomData<F>);

impl<F: RescueParameter, const OUTPUT_LEN: usize> CRHF for VariableLengthRescueCRHF<F, OUTPUT_LEN> {
type Input = Vec<F>;
type Output = [F; OUTPUT_LEN];
type Parameters = ();

fn setup<R: RngCore + CryptoRng>(_rng: &mut R) -> Result<Self::Parameters, PrimitivesError> {
Ok(())
}

fn evaluate<T: Borrow<Self::Input>>(
_param: &Self::Parameters,
input: T,
) -> Result<Self::Output, PrimitivesError> {
let mut output = [F::zero(); OUTPUT_LEN];
let res = RescueCRHF::<F>::sponge_with_padding(input.borrow(), OUTPUT_LEN);
if res.len() != OUTPUT_LEN {
return Err(PrimitivesError::InternalError(
"Unexpected rescue sponge return length".to_string(),
));
}
output.copy_from_slice(&res[..]);
Ok(output)
}
}
1 change: 1 addition & 0 deletions primitives/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ pub mod aead;
pub mod circuit;
pub mod commitment;
pub mod constants;
pub mod crhf;
pub mod elgamal;
pub mod errors;
pub mod hash_to_group;
Expand Down
8 changes: 4 additions & 4 deletions primitives/src/rescue/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ use ark_std::{vec, vec::Vec};
/// The state size of rescue hash.
pub const STATE_SIZE: usize = 4;
/// The rate of the sponge used in RescueCRHF.
pub const CRHF_RATE: usize = 3;
pub(crate) const CRHF_RATE: usize = 3;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we do the same thing to STATE_SIZE

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

currently still usage in transcript in jf-plonk that utilize this constant here, I think we might be able make it consistent after #159 ?

I will think more meanwhile

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suddenly I feel like we should export these 2 constants. Perhaps we could make them trait/struct dependent?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tend to disagree. I think it's intuitive that CRHF_RATE is a internal detail of CRHF, thus try to hide from public is sensible. whereas STATE_SIZE is a parameter of our Rescue permutation instance, which like A and MDS should be public.

I think the current visibility makes sense to me.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But what if the user need to know the "rate of compression"?

Copy link
Contributor Author

@alxiong alxiong Dec 21, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why would the user want to know that? I couldn't think of a use case for now.

alright, maybe I will just expose them. I don't see much harm either.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

changed back in 7b77e79


/// The # of rounds of rescue hash.
// In the paper, to derive ROUND:
Expand Down Expand Up @@ -201,7 +201,7 @@ impl<F: Copy> From<&[F; STATE_SIZE]> for RescueVector<F> {
}

/// A matrix that consists of `STATE_SIZE` number of rescue vectors.
#[derive(Clone)]
#[derive(Debug, Clone)]
pub struct RescueMatrix<F> {
matrix: [RescueVector<F>; STATE_SIZE],
}
Expand Down Expand Up @@ -248,7 +248,7 @@ impl<F: PrimeField> RescueMatrix<F> {
// input to 3 and output to 1
//

#[derive(Clone)]
#[derive(Debug, Clone)]
#[allow(clippy::upper_case_acronyms)]
/// Rescue pseudo-random permutation (PRP) instance
pub struct PRP<F> {
Expand Down Expand Up @@ -371,7 +371,7 @@ impl<F: RescueParameter> PRP<F> {

/// Instance of a unkeyed cryptographic permutation to be used for instantiation
/// hashing, pseudo-random function, and other cryptographic primitives
#[derive(Clone)]
#[derive(Debug, Clone)]
pub struct Permutation<F> {
rescue_prp: PRP<F>,
round_keys: Vec<RescueVector<F>>,
Expand Down
5 changes: 3 additions & 2 deletions primitives/src/rescue/sponge.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ use super::{
errors::RescueError, Permutation, RescueParameter, RescueVector, CRHF_RATE, STATE_SIZE,
};

#[derive(Clone, Default)]
#[derive(Clone, Default, Debug)]
/// A rescue hash function consists of a permutation function and
/// an internal state.
struct RescueSponge<F: RescueParameter, const RATE: usize> {
Expand All @@ -26,7 +26,8 @@ struct RescueSponge<F: RescueParameter, const RATE: usize> {
}

/// CRHF
pub struct RescueCRHF<F: RescueParameter> {
#[derive(Debug, Clone)]
pub(crate) struct RescueCRHF<F: RescueParameter> {
sponge: RescueSponge<F, CRHF_RATE>,
}

Expand Down