() {
76 | let data = vec![1u8, 2, 3, 4, 5];
77 | let _g1 =
78 | ::hash_to_group::<&[u8]>(data.as_ref(), "bls signature".as_ref())
79 | .unwrap();
80 | }
81 | }
82 |
--------------------------------------------------------------------------------
/jellyfish/primitives/src/hash_to_group/twisted_edwards.rs:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2022 Espresso Systems (espressosys.com)
2 | // This file is part of the Jellyfish library.
3 |
4 | // You should have received a copy of the MIT License
5 | // along with the Jellyfish library. If not, see .
6 |
7 | //! Hash to Elliptic Curve implementation of
8 |
9 | use crate::errors::PrimitivesError;
10 | use ark_ec::{
11 | twisted_edwards_extended::{GroupAffine, GroupProjective},
12 | AffineCurve, TEModelParameters,
13 | };
14 | use ark_std::{
15 | rand::{Rng, SeedableRng},
16 | UniformRand,
17 | };
18 | use digest::Digest;
19 | use rand_chacha::ChaCha20Rng;
20 | use sha2::Sha256;
21 |
22 | /// Trait definition and default implementation for hash to group functions for
23 | /// Twisted Edwards Curves.
24 | pub trait TEHashToGroup: TEModelParameters + Sized {
25 | /// Hash to Group point, using sha2-512 function
26 | /// hashing to G1 point of `C: ProjectiveCurve`.
27 | // Default implementation implements a naive solution via rejection sampling.
28 | // Slow, and non-constant time.
29 | //
30 | // For specific curves we may want to overload it with a more efficient
31 | // algorithm, such as IETF BLS draft.
32 | fn hash_to_group>(
33 | data: B,
34 | cs_id: B,
35 | ) -> Result, PrimitivesError> {
36 | let mut hasher = Sha256::new();
37 | hasher.update([cs_id.as_ref(), data.as_ref()].concat());
38 | let mut seed = [0u8; 32];
39 | seed.copy_from_slice(hasher.finalize().as_ref());
40 | let mut rng = ChaCha20Rng::from_seed(seed);
41 | loop {
42 | let x = Self::BaseField::rand(&mut rng);
43 | // a boolean flag to decide if y is positive or not
44 | let y_flag = rng.gen();
45 | if let Some(p) = GroupAffine::::get_point_from_x(x, y_flag) {
46 | return Ok(p.mul_by_cofactor_to_projective());
47 | }
48 | }
49 | }
50 | }
51 |
52 | impl TEHashToGroup for ark_ed_on_bls12_377::EdwardsParameters {
53 | // TODO:
54 | // overload hash to group with the method in
55 | //
56 | }
57 |
58 | impl TEHashToGroup for ark_ed_on_bls12_381::EdwardsParameters {
59 | // TODO:
60 | // overload hash to group with the method in
61 | //
62 | }
63 |
64 | #[cfg(test)]
65 | mod test {
66 | use super::*;
67 | use ark_std::vec;
68 |
69 | #[test]
70 | fn test_hash_to_group() {
71 | test_hash_to_group_helper::();
72 | test_hash_to_group_helper::();
73 | }
74 |
75 | fn test_hash_to_group_helper() {
76 | let data = vec![1u8, 2, 3, 4, 5];
77 | let _g1 =
78 | ::hash_to_group::<&[u8]>(data.as_ref(), "Jubjub curves".as_ref())
79 | .unwrap();
80 | }
81 | }
82 |
--------------------------------------------------------------------------------
/jellyfish/primitives/src/lib.rs:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2022 Espresso Systems (espressosys.com)
2 | // This file is part of the Jellyfish library.
3 |
4 | // You should have received a copy of the MIT License
5 | // along with the Jellyfish library. If not, see .
6 |
7 | //! Crate implements various cryptography primitives, as
8 | //! well as the plonk circuit implementation of those primitives.
9 |
10 | #![cfg_attr(not(feature = "std"), no_std)]
11 | #![deny(warnings)]
12 | #![deny(missing_docs)]
13 | #[cfg(test)]
14 | extern crate std;
15 |
16 | #[macro_use]
17 | extern crate derivative;
18 |
19 | pub mod aead;
20 | pub mod circuit;
21 | pub mod commitment;
22 | pub mod constants;
23 | pub mod crhf;
24 | pub mod elgamal;
25 | pub mod errors;
26 | pub mod hash_to_group;
27 | pub mod merkle_tree;
28 | pub mod pasta;
29 | pub mod pcs;
30 | pub mod prf;
31 | pub mod rescue;
32 | pub mod scalars_n_bases;
33 | pub mod signatures;
34 | pub mod vrf;
35 |
36 | pub(crate) mod utils;
37 |
--------------------------------------------------------------------------------
/jellyfish/primitives/src/merkle_tree/examples.rs:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2022 Espresso Systems (espressosys.com)
2 | // This file is part of the Jellyfish library.
3 |
4 | // You should have received a copy of the MIT License
5 | // along with the Jellyfish library. If not, see .
6 |
7 | //! Provides sample instantiations of merkle tree.
8 | //! E.g. Sparse merkle tree with BigUInt index.
9 |
10 | use super::{append_only::MerkleTree, prelude::RescueHash, DigestAlgorithm, Element, Index};
11 | use crate::rescue::{sponge::RescueCRHF, RescueParameter};
12 | use ark_ff::Field;
13 | use ark_serialize::{CanonicalDeserialize, CanonicalSerialize, Read, SerializationError, Write};
14 | use sha3::{Digest, Sha3_256};
15 | use typenum::U3;
16 |
17 | /// Element type for interval merkle tree
18 | #[derive(PartialEq, Eq, Copy, Clone)]
19 | pub struct Interval(pub F, pub F);
20 | // impl Element for Interval {}
21 |
22 | impl DigestAlgorithm, u64, F> for RescueHash {
23 | fn digest(data: &[F]) -> F {
24 | RescueCRHF::::sponge_no_padding(data, 1).unwrap()[0]
25 | }
26 |
27 | fn digest_leaf(pos: &u64, elem: &Interval) -> F {
28 | let data = [F::from(*pos), elem.0, elem.1];
29 | RescueCRHF::::sponge_no_padding(&data, 1).unwrap()[0]
30 | }
31 | }
32 |
33 | /// Interval merkle tree instantiation for interval merkle tree using Rescue
34 | /// hash function.
35 | pub type IntervalMerkleTree = MerkleTree, RescueHash, u64, U3, F>;
36 |
37 | /// Update the array length here
38 | #[derive(Default, Eq, PartialEq, Clone, Copy, Debug, Ord, PartialOrd, Hash)]
39 | pub struct Sha3Node([u8; 32]);
40 |
41 | impl AsRef<[u8]> for Sha3Node {
42 | fn as_ref(&self) -> &[u8] {
43 | &self.0
44 | }
45 | }
46 |
47 | impl CanonicalSerialize for Sha3Node {
48 | fn serialize(&self, mut writer: W) -> Result<(), SerializationError> {
49 | writer.write_all(&self.0)?;
50 | Ok(())
51 | }
52 |
53 | fn serialized_size(&self) -> usize {
54 | 32
55 | }
56 | }
57 | impl CanonicalDeserialize for Sha3Node {
58 | fn deserialize(mut reader: R) -> Result {
59 | let mut ret = [0u8; 32];
60 | reader.read_exact(&mut ret)?;
61 | Ok(Sha3Node(ret))
62 | }
63 | }
64 |
65 | /// Wrapper for SHA3_512 hash function
66 | pub struct Sha3Digest();
67 |
68 | impl DigestAlgorithm for Sha3Digest {
69 | fn digest(data: &[Sha3Node]) -> Sha3Node {
70 | let mut hasher = Sha3_256::new();
71 | for value in data {
72 | hasher.update(value);
73 | }
74 | Sha3Node(hasher.finalize().into())
75 | }
76 |
77 | fn digest_leaf(_pos: &I, _elem: &E) -> Sha3Node {
78 | // Serialize and hash
79 | todo!()
80 | }
81 | }
82 |
83 | /// Merkle tree using SHA3 hash
84 | pub type SHA3MerkleTree = MerkleTree;
85 |
--------------------------------------------------------------------------------
/jellyfish/primitives/src/merkle_tree/prelude.rs:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2022 Espresso Systems (espressosys.com)
2 | // This file is part of the Jellyfish library.
3 |
4 | // You should have received a copy of the MIT License
5 | // along with the Jellyfish library. If not, see .
6 |
7 | //! Prelude
8 |
9 | pub use crate::{
10 | impl_to_traversal_path_biguint, impl_to_traversal_path_primitives,
11 | merkle_tree::{
12 | append_only::MerkleTree, universal_merkle_tree::UniversalMerkleTree,
13 | AppendableMerkleTreeScheme, DigestAlgorithm, Element, ForgetableMerkleTreeScheme,
14 | ForgetableUniversalMerkleTreeScheme, Index, LookupResult, MerkleCommitment,
15 | MerkleTreeScheme, NodeValue, ToTraversalPath, UniversalMerkleTreeScheme,
16 | },
17 | };
18 |
19 | use crate::rescue::{sponge::RescueCRHF, RescueParameter};
20 | use ark_std::marker::PhantomData;
21 | use num_bigint::BigUint;
22 | use typenum::U3;
23 |
24 | use super::light_weight::LightWeightMerkleTree;
25 |
26 | /// Wrapper for rescue hash function
27 | #[derive(Clone, Copy, Debug, PartialEq, Eq)]
28 | pub struct RescueHash {
29 | phantom_f: PhantomData,
30 | }
31 |
32 | impl DigestAlgorithm for RescueHash {
33 | fn digest(data: &[F]) -> F {
34 | RescueCRHF::::sponge_no_padding(data, 1).unwrap()[0]
35 | }
36 |
37 | fn digest_leaf(pos: &u64, elem: &F) -> F {
38 | let data = [F::zero(), F::from(*pos), *elem];
39 | RescueCRHF::::sponge_no_padding(&data, 1).unwrap()[0]
40 | }
41 | }
42 |
43 | /// A standard merkle tree using RATE-3 rescue hash function
44 | pub type RescueMerkleTree = MerkleTree, u64, U3, F>;
45 |
46 | /// A standard light merkle tree using RATE-3 rescue hash function
47 | pub type RescueLightWeightMerkleTree = LightWeightMerkleTree, u64, U3, F>;
48 |
49 | impl DigestAlgorithm for RescueHash {
50 | fn digest(data: &[F]) -> F {
51 | RescueCRHF::::sponge_no_padding(data, 1).unwrap()[0]
52 | }
53 |
54 | fn digest_leaf(pos: &BigUint, elem: &F) -> F {
55 | let data = [F::zero(), F::from(pos.clone()), *elem];
56 | RescueCRHF::::sponge_no_padding(&data, 1).unwrap()[0]
57 | }
58 | }
59 |
60 | impl DigestAlgorithm for RescueHash {
61 | fn digest(data: &[F]) -> F {
62 | RescueCRHF::::sponge_no_padding(data, 1).unwrap()[0]
63 | }
64 |
65 | fn digest_leaf(pos: &F, elem: &F) -> F {
66 | let data = [F::zero(), *pos, *elem];
67 | RescueCRHF::::sponge_no_padding(&data, 1).unwrap()[0]
68 | }
69 | }
70 |
71 | /// Example instantiation of a SparseMerkleTree indexed by I
72 | pub type RescueSparseMerkleTree = UniversalMerkleTree, I, U3, F>;
73 |
--------------------------------------------------------------------------------
/jellyfish/primitives/src/pasta/mod.rs:
--------------------------------------------------------------------------------
1 | //! Trait implementations for the Pasta curves.
2 |
3 | use ark_pallas::Affine as PallasAffine;
4 | use ark_pallas::Projective as PallasProjective;
5 | use ark_pallas::{Fq, Fr};
6 | use ark_vesta::Affine as VestaAffine;
7 | use ark_vesta::Projective as VestaProjective;
8 |
9 | // this is analogous to the ark_pallas::PallasParameters struct
10 | /// A struct to hang the `CommitmentGroup` trait for Pallas on.
11 | #[derive(Copy, Clone, Debug, Default, PartialEq, Eq)]
12 | pub struct PallasGroup;
13 |
14 | impl crate::pcs::CommitmentGroup for PallasGroup {
15 | type Fr = Fr;
16 | type G1Affine = PallasAffine;
17 | type G1Projective = PallasProjective;
18 | type Fq = Fq;
19 | }
20 |
21 | // this is analogous to the ark_pallas::VestaParameters struct
22 | /// A struct to hang the `CommitmentGroup` trait for Vesta on.
23 | #[derive(Copy, Clone, Debug, Default, PartialEq, Eq)]
24 | pub struct VestaGroup;
25 |
26 | impl crate::pcs::CommitmentGroup for VestaGroup {
27 | type Fr = Fq;
28 | type G1Affine = VestaAffine;
29 | type G1Projective = VestaProjective;
30 | type Fq = Fr;
31 | }
32 |
--------------------------------------------------------------------------------
/jellyfish/primitives/src/pcs/errors.rs:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2022 Espresso Systems (espressosys.com)
2 | // This file is part of the Jellyfish library.
3 |
4 | // You should have received a copy of the MIT License
5 | // along with the Jellyfish library. If not, see .
6 |
7 | //! Error module.
8 |
9 | use super::transcript::TranscriptError;
10 | use ark_serialize::SerializationError;
11 | use ark_std::string::String;
12 | use displaydoc::Display;
13 |
14 | /// A `enum` specifying the possible failure modes of the PCS.
15 | #[derive(Display, Debug)]
16 | pub enum PCSError {
17 | /// Invalid Prover: {0}
18 | InvalidProver(String),
19 | /// Invalid Verifier: {0}
20 | InvalidVerifier(String),
21 | /// Invalid Proof: {0}
22 | InvalidProof(String),
23 | /// Invalid parameters: {0}
24 | InvalidParameters(String),
25 | /// An error during (de)serialization: {0}
26 | SerializationError(SerializationError),
27 | /// Transcript error {0}
28 | TranscriptError(TranscriptError),
29 | /// Error from the internal ark_poly_commit primitive
30 | ArkPolyCommitError(ark_poly_commit::Error),
31 | }
32 |
33 | impl From for PCSError {
34 | fn from(e: ark_serialize::SerializationError) -> Self {
35 | Self::SerializationError(e)
36 | }
37 | }
38 |
39 | impl From for PCSError {
40 | fn from(e: TranscriptError) -> Self {
41 | Self::TranscriptError(e)
42 | }
43 | }
44 |
45 | impl From for PCSError {
46 | fn from(e: ark_poly_commit::Error) -> Self {
47 | Self::ArkPolyCommitError(e)
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/jellyfish/primitives/src/pcs/prelude.rs:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2022 Espresso Systems (espressosys.com)
2 | // This file is part of the Jellyfish library.
3 |
4 | // You should have received a copy of the MIT License
5 | // along with the Jellyfish library. If not, see .
6 |
7 | //! Prelude
8 | pub use crate::pcs::{
9 | errors::PCSError,
10 | multilinear_kzg::{
11 | srs::{MultilinearProverParam, MultilinearUniversalParams, MultilinearVerifierParam},
12 | util::{compute_qx_degree, get_batched_nv, merge_polynomials},
13 | MultilinearKzgBatchProof, MultilinearKzgPCS, MultilinearKzgProof,
14 | },
15 | structs::Commitment,
16 | univariate_kzg::{
17 | srs::{UnivariateProverParam, UnivariateUniversalParams, UnivariateVerifierParam},
18 | UnivariateKzgBatchProof, UnivariateKzgPCS, UnivariateKzgProof,
19 | },
20 | PolynomialCommitmentScheme, StructuredReferenceString, UVPCS,
21 | };
22 |
--------------------------------------------------------------------------------
/jellyfish/primitives/src/pcs/structs.rs:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2022 Espresso Systems (espressosys.com)
2 | // This file is part of the Jellyfish library.
3 |
4 | // You should have received a copy of the MIT License
5 | // along with the Jellyfish library. If not, see .
6 |
7 | use ark_serialize::{CanonicalDeserialize, CanonicalSerialize, Read, SerializationError, Write};
8 |
9 | use super::CommitmentGroup;
10 |
11 | #[derive(Derivative, CanonicalSerialize, CanonicalDeserialize)]
12 | #[derivative(
13 | Default(bound = ""),
14 | Hash(bound = ""),
15 | Clone(bound = ""),
16 | Copy(bound = ""),
17 | Debug(bound = ""),
18 | PartialEq(bound = ""),
19 | Eq(bound = "")
20 | )]
21 | /// A commitment is an Affine point.
22 | pub struct Commitment(
23 | /// the actual commitment is an affine point.
24 | pub E::G1Affine,
25 | );
26 |
--------------------------------------------------------------------------------
/jellyfish/primitives/src/pcs/transcript.rs:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2022 Espresso Systems (espressosys.com)
2 | // This file is part of the Jellyfish library.
3 |
4 | // You should have received a copy of the MIT License
5 | // along with the Jellyfish library. If not, see .
6 |
7 | //! Module for PolyIOP transcript.
8 |
9 | mod errors {
10 | use ark_std::string::String;
11 | use displaydoc::Display;
12 |
13 | /// A `enum` specifying the possible failure modes of the Transcript.
14 | #[derive(Display, Debug)]
15 | pub enum TranscriptError {
16 | /// Invalid Transcript: {0}
17 | InvalidTranscript(String),
18 | /// An error during (de)serialization: {0}
19 | SerializationError(ark_serialize::SerializationError),
20 | }
21 |
22 | impl From for TranscriptError {
23 | fn from(e: ark_serialize::SerializationError) -> Self {
24 | Self::SerializationError(e)
25 | }
26 | }
27 | }
28 |
29 | pub(crate) use errors::TranscriptError;
30 |
31 | use ark_ff::PrimeField;
32 | use ark_serialize::CanonicalSerialize;
33 | use ark_std::{marker::PhantomData, string::ToString};
34 | use jf_utils::to_bytes;
35 | use merlin::Transcript;
36 |
37 | /// An IOP transcript consists of a Merlin transcript and a flag `is_empty` to
38 | /// indicate that if the transcript is empty.
39 | ///
40 | /// It is associated with a prime field `F` for which challenges are generated
41 | /// over.
42 | ///
43 | /// The `is_empty` flag is useful in the case where a protocol is initiated by
44 | /// the verifier, in which case the prover should start its phase by receiving a
45 | /// `non-empty` transcript.
46 | #[derive(Clone)]
47 | pub(crate) struct IOPTranscript {
48 | transcript: Transcript,
49 | is_empty: bool,
50 | #[doc(hidden)]
51 | phantom: PhantomData,
52 | }
53 |
54 | // TODO: merge this with jf_plonk::transcript
55 | impl IOPTranscript {
56 | /// Create a new IOP transcript.
57 | pub fn new(label: &'static [u8]) -> Self {
58 | Self {
59 | transcript: Transcript::new(label),
60 | is_empty: true,
61 | phantom: PhantomData::default(),
62 | }
63 | }
64 |
65 | /// Append the message to the transcript.
66 | pub(crate) fn append_message(
67 | &mut self,
68 | label: &'static [u8],
69 | msg: &[u8],
70 | ) -> Result<(), TranscriptError> {
71 | self.transcript.append_message(label, msg);
72 | self.is_empty = false;
73 | Ok(())
74 | }
75 |
76 | /// Append the message to the transcript.
77 | pub(crate) fn append_serializable_element(
78 | &mut self,
79 | label: &'static [u8],
80 | group_elem: &S,
81 | ) -> Result<(), TranscriptError> {
82 | self.append_message(label, &to_bytes!(group_elem)?)
83 | }
84 |
85 | /// Generate the challenge from the current transcript
86 | /// and append it to the transcript.
87 | ///
88 | /// The output field element is statistical uniform as long
89 | /// as the field has a size less than 2^384.
90 | pub(crate) fn get_and_append_challenge(
91 | &mut self,
92 | label: &'static [u8],
93 | ) -> Result {
94 | // we need to reject when transcript is empty
95 | if self.is_empty {
96 | return Err(TranscriptError::InvalidTranscript(
97 | "transcript is empty".to_string(),
98 | ));
99 | }
100 |
101 | let mut buf = [0u8; 64];
102 | self.transcript.challenge_bytes(label, &mut buf);
103 | let challenge = F::from_le_bytes_mod_order(&buf);
104 | self.append_serializable_element(label, &challenge)?;
105 | Ok(challenge)
106 | }
107 | }
108 |
--------------------------------------------------------------------------------
/jellyfish/primitives/src/pcs/univariate_kzg/srs.rs:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2022 Espresso Systems (espressosys.com)
2 | // This file is part of the Jellyfish library.
3 |
4 | // You should have received a copy of the MIT License
5 | // along with the Jellyfish library. If not, see .
6 |
7 | //! Implementing Structured Reference Strings for univariate polynomial KZG
8 |
9 | use crate::pcs::{PCSError, StructuredReferenceString, WithMaxDegree};
10 | use ark_ec::{msm::FixedBaseMSM, AffineCurve, PairingEngine, ProjectiveCurve};
11 | use ark_ff::PrimeField;
12 | use ark_serialize::{CanonicalDeserialize, CanonicalSerialize, Read, SerializationError, Write};
13 | use ark_std::{
14 | end_timer,
15 | rand::{CryptoRng, RngCore},
16 | start_timer, vec,
17 | vec::Vec,
18 | One, UniformRand,
19 | };
20 |
21 | /// `UniversalParams` are the universal parameters for the KZG10 scheme.
22 | // Adapted from
23 | // https://github.com/arkworks-rs/poly-commit/blob/master/src/kzg10/data_structures.rs#L20
24 | #[derive(Debug, Clone, Eq, PartialEq, CanonicalSerialize, CanonicalDeserialize, Default)]
25 | pub struct UnivariateUniversalParams {
26 | /// Group elements of the form `{ \beta^i G }`, where `i` ranges from 0 to
27 | /// `degree`.
28 | pub powers_of_g: Vec,
29 | /// The generator of G2.
30 | pub h: E::G2Affine,
31 | /// \beta times the above generator of G2.
32 | pub beta_h: E::G2Affine,
33 | }
34 |
35 | impl UnivariateUniversalParams {
36 | /// Returns the maximum supported degree
37 | pub fn max_degree(&self) -> usize {
38 | self.powers_of_g.len()
39 | }
40 | }
41 |
42 | impl WithMaxDegree for UnivariateUniversalParams {
43 | fn max_degree(&self) -> usize {
44 | self.max_degree()
45 | }
46 | }
47 |
48 | /// `UnivariateProverParam` is used to generate a proof
49 | #[derive(CanonicalSerialize, CanonicalDeserialize, Clone, Debug, Eq, PartialEq, Default)]
50 | pub struct UnivariateProverParam {
51 | /// Parameters
52 | pub powers_of_g: Vec,
53 | }
54 |
55 | /// `UnivariateVerifierParam` is used to check evaluation proofs for a given
56 | /// commitment.
57 | #[derive(Derivative, CanonicalSerialize, CanonicalDeserialize)]
58 | #[derivative(
59 | Default(bound = ""),
60 | Clone(bound = ""),
61 | Copy(bound = ""),
62 | Debug(bound = ""),
63 | PartialEq(bound = ""),
64 | Eq(bound = "")
65 | )]
66 | pub struct UnivariateVerifierParam {
67 | /// The generator of G1.
68 | pub g: E::G1Affine,
69 | /// The generator of G2.
70 | pub h: E::G2Affine,
71 | /// \beta times the above generator of G2.
72 | pub beta_h: E::G2Affine,
73 | }
74 |
75 | impl StructuredReferenceString for UnivariateUniversalParams {
76 | type ProverParam = UnivariateProverParam;
77 | type VerifierParam = UnivariateVerifierParam;
78 |
79 | /// Extract the prover parameters from the public parameters.
80 | fn extract_prover_param(&self, supported_size: usize) -> Self::ProverParam {
81 | let powers_of_g = self.powers_of_g[..=supported_size].to_vec();
82 |
83 | Self::ProverParam { powers_of_g }
84 | }
85 |
86 | /// Extract the verifier parameters from the public parameters.
87 | fn extract_verifier_param(&self, _supported_size: usize) -> Self::VerifierParam {
88 | Self::VerifierParam {
89 | g: self.powers_of_g[0],
90 | h: self.h,
91 | beta_h: self.beta_h,
92 | }
93 | }
94 |
95 | /// Trim the universal parameters to specialize the public parameters
96 | /// for univariate polynomials to the given `supported_size`, and
97 | /// returns committer key and verifier key. `supported_size` should
98 | /// be in range `1..params.len()`
99 | fn trim(
100 | &self,
101 | supported_size: usize,
102 | ) -> Result<(Self::ProverParam, Self::VerifierParam), PCSError> {
103 | let powers_of_g = self.powers_of_g[..=supported_size].to_vec();
104 |
105 | let pk = Self::ProverParam { powers_of_g };
106 | let vk = Self::VerifierParam {
107 | g: self.powers_of_g[0],
108 | h: self.h,
109 | beta_h: self.beta_h,
110 | };
111 | Ok((pk, vk))
112 | }
113 |
114 | /// Build SRS for testing.
115 | /// WARNING: THIS FUNCTION IS FOR TESTING PURPOSE ONLY.
116 | /// THE OUTPUT SRS SHOULD NOT BE USED IN PRODUCTION.
117 | fn gen_srs_for_testing(
118 | rng: &mut R,
119 | max_degree: usize,
120 | ) -> Result {
121 | let setup_time = start_timer!(|| format!("KZG10::Setup with degree {}", max_degree));
122 | let beta = E::Fr::rand(rng);
123 | let g = E::G1Projective::rand(rng);
124 | let h = E::G2Projective::rand(rng);
125 |
126 | let mut powers_of_beta = vec![E::Fr::one()];
127 |
128 | let mut cur = beta;
129 | for _ in 0..max_degree {
130 | powers_of_beta.push(cur);
131 | cur *= β
132 | }
133 |
134 | let window_size = FixedBaseMSM::get_mul_window_size(max_degree + 1);
135 |
136 | let scalar_bits = E::Fr::size_in_bits();
137 | let g_time = start_timer!(|| "Generating powers of G");
138 | // TODO: parallelization
139 | let g_table = FixedBaseMSM::get_window_table(scalar_bits, window_size, g);
140 | let powers_of_g = FixedBaseMSM::multi_scalar_mul::(
141 | scalar_bits,
142 | window_size,
143 | &g_table,
144 | &powers_of_beta,
145 | );
146 | end_timer!(g_time);
147 |
148 | let powers_of_g = E::G1Projective::batch_normalization_into_affine(&powers_of_g);
149 |
150 | let h = h.into_affine();
151 | let beta_h = h.mul(beta).into_affine();
152 |
153 | let pp = Self {
154 | powers_of_g,
155 | h,
156 | beta_h,
157 | };
158 | end_timer!(setup_time);
159 | Ok(pp)
160 | }
161 | }
162 |
--------------------------------------------------------------------------------
/jellyfish/primitives/src/prf.rs:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2022 Espresso Systems (espressosys.com)
2 | // This file is part of the Jellyfish library.
3 |
4 | // You should have received a copy of the MIT License
5 | // along with the Jellyfish library. If not, see .
6 |
7 | //! This module implements a pseudo random function that is derived from
8 | //! the rescue hash function.
9 |
10 | use crate::{
11 | errors::PrimitivesError,
12 | rescue::{sponge::RescuePRFCore, RescueParameter},
13 | };
14 | use ark_std::{
15 | borrow::Borrow,
16 | fmt::Debug,
17 | marker::PhantomData,
18 | rand::{CryptoRng, RngCore},
19 | UniformRand,
20 | };
21 |
22 | /// Trait for Pseudo-random Functions
23 | pub trait PRF {
24 | // TODO: (alex) add `CanonicalDeserialize` to `Input`, `CanonicalSerialize` to
25 | // `Output`, both to `Seed`, when we move to arkworks 0.4.0
26 | /// Input to the PRF
27 | type Input: Clone;
28 | /// Output of the PRF
29 | type Output: Clone + Debug + PartialEq + Eq;
30 | /// The random seed/key that index a specific function from the PRF
31 | /// ensembles
32 | type Seed: Clone + Debug + Default + UniformRand;
33 |
34 | /// Compute PRF output with a user-provided randomly generated `seed`
35 | fn evaluate, I: Borrow>(
36 | seed: S,
37 | input: I,
38 | ) -> Result;
39 |
40 | /// same as [`Self::evaluate`] except that we generate a fresh random seed
41 | /// for the evaluation
42 | fn evaluate_with_rand_seed>(
43 | rng: &mut R,
44 | input: T,
45 | ) -> Result<(Self::Seed, Self::Output), PrimitivesError> {
46 | let seed = Self::Seed::rand(rng);
47 | let output = Self::evaluate(&seed, input)?;
48 | Ok((seed, output))
49 | }
50 | }
51 |
52 | #[derive(Debug, Clone)]
53 | /// A rescue-based PRF that leverages on Full State Keyed (FSK) sponge
54 | /// construction
55 | pub struct RescuePRF(
56 | PhantomData,
57 | );
58 |
59 | impl PRF
60 | for RescuePRF
61 | {
62 | type Input = [F; INPUT_LEN];
63 | type Output = [F; OUTPUT_LEN];
64 | type Seed = F;
65 |
66 | fn evaluate, I: Borrow>(
67 | seed: S,
68 | input: I,
69 | ) -> Result {
70 | let mut output = [F::zero(); OUTPUT_LEN];
71 | output.clone_from_slice(&RescuePRFCore::full_state_keyed_sponge_with_zero_padding(
72 | seed.borrow(),
73 | input.borrow(),
74 | OUTPUT_LEN,
75 | )?);
76 | Ok(output)
77 | }
78 | }
79 | #[cfg(test)]
80 | mod tests {
81 | use crate::{
82 | prf::{RescuePRF, PRF},
83 | rescue::sponge::RescuePRFCore,
84 | };
85 | use ark_bls12_377::Fq as Fq377;
86 | use ark_ed_on_bls12_377::Fq as FqEd377;
87 | use ark_ed_on_bls12_381::Fq as FqEd381;
88 | use ark_ed_on_bn254::Fq as FqEd254;
89 | use ark_std::UniformRand;
90 | macro_rules! test_prf {
91 | ($tr:tt) => {
92 | let mut rng = ark_std::test_rng();
93 | let seed = $tr::rand(&mut rng);
94 | let input = [$tr::from(1u8)];
95 |
96 | assert!(RescuePRF::<$tr, 1, 15>::evaluate(&seed, &input).is_ok());
97 | // check correctness
98 | assert_eq!(
99 | RescuePRF::<$tr, 1, 15>::evaluate(&seed, &input)
100 | .unwrap()
101 | .to_vec(),
102 | RescuePRFCore::full_state_keyed_sponge_with_zero_padding(&seed, &input, 15)
103 | .unwrap()
104 | );
105 | };
106 | }
107 |
108 | #[test]
109 | pub fn test_prf() {
110 | test_prf!(FqEd254);
111 | test_prf!(FqEd377);
112 | test_prf!(FqEd381);
113 | test_prf!(Fq377);
114 | }
115 | }
116 |
--------------------------------------------------------------------------------
/jellyfish/primitives/src/rescue/errors.rs:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2022 Espresso Systems (espressosys.com)
2 | // This file is part of the Jellyfish library.
3 |
4 | // You should have received a copy of the MIT License
5 | // along with the Jellyfish library. If not, see .
6 |
7 | //! Error types.
8 |
9 | // using `displaydoc` instead of `thiserror`, see
10 | // https://github.com/dtolnay/thiserror/pull/64#issuecomment-735805334
11 | // `thiserror` does not support #![no_std]
12 |
13 | use ark_std::string::String;
14 | use displaydoc::Display;
15 |
16 | /// Various error modes.
17 | #[derive(Debug, Display, Eq, PartialEq)]
18 | pub enum RescueError {
19 | /// Bad parameter in function call, {0}
20 | ParameterError(String),
21 | }
22 |
--------------------------------------------------------------------------------
/jellyfish/primitives/src/rescue/rescue_constants/bls12_381_base.rs:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2022 Espresso Systems (espressosys.com)
2 | // This file is part of the Jellyfish library.
3 |
4 | // You should have received a copy of the MIT License
5 | // along with the Jellyfish library. If not, see .
6 |
7 | //! !!!Warning!!!
8 | //! The parameters in this file are mock parameters for testing purpose.
9 | //! They are not correct and shall not be used for anything else
10 |
11 | use crate::rescue::{RescueParameter, ROUNDS, STATE_SIZE};
12 | use ark_bls12_381::Fq;
13 |
14 | /// This is a dummy implementation of Rescue parameters
15 | /// to satisfy trait bound for Fq.
16 | /// This code should not be used for any other purpose.
17 | impl RescueParameter for Fq {
18 | const A: u64 = 5;
19 | const A_INV: &'static [u64] = &[0, 0, 0, 0, 0, 0];
20 |
21 | const MDS_LE: [[&'static [u8]; STATE_SIZE]; STATE_SIZE] =
22 | [[&[0u8; 32]; STATE_SIZE]; STATE_SIZE];
23 |
24 | const INIT_VEC_LE: [&'static [u8]; STATE_SIZE] = [&[0u8; 32]; STATE_SIZE];
25 |
26 | const KEY_INJECTION_LE: [[&'static [u8]; 4]; 2 * ROUNDS] = [[&[0u8; 32]; 4]; 2 * ROUNDS];
27 |
28 | const PERMUTATION_ROUND_KEYS: [[&'static [u8]; 4]; 25] = [[&[0u8; 32]; 4]; 25];
29 | }
30 |
--------------------------------------------------------------------------------
/jellyfish/primitives/src/rescue/rescue_constants/bn254_base.rs:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2022 Espresso Systems (espressosys.com)
2 | // This file is part of the Jellyfish library.
3 |
4 | // You should have received a copy of the MIT License
5 | // along with the Jellyfish library. If not, see .
6 |
7 | //! !!!Warning!!!
8 | //! The parameters in this file are mock parameters for testing purpose.
9 | //! They are not correct and shall not be used for anything else
10 |
11 | use crate::rescue::{RescueParameter, ROUNDS, STATE_SIZE};
12 | use ark_bn254::Fq;
13 |
14 | /// This is a dummy implementation of Rescue parameters
15 | /// to satisfy trait bound for Fq.
16 | /// This code should not be used for any other purpose.
17 | impl RescueParameter for Fq {
18 | const A: u64 = 5;
19 | const A_INV: &'static [u64] = &[0, 0, 0, 0];
20 |
21 | const MDS_LE: [[&'static [u8]; STATE_SIZE]; STATE_SIZE] =
22 | [[&[0u8; 32]; STATE_SIZE]; STATE_SIZE];
23 |
24 | const INIT_VEC_LE: [&'static [u8]; STATE_SIZE] = [&[0u8; 32]; STATE_SIZE];
25 |
26 | const KEY_INJECTION_LE: [[&'static [u8]; 4]; 2 * ROUNDS] = [[&[0u8; 32]; 4]; 2 * ROUNDS];
27 |
28 | const PERMUTATION_ROUND_KEYS: [[&'static [u8]; 4]; 25] = [[&[0u8; 32]; 4]; 25];
29 | }
30 |
--------------------------------------------------------------------------------
/jellyfish/primitives/src/rescue/rescue_constants/bw6_761_base.rs:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2022 Espresso Systems (espressosys.com)
2 | // This file is part of the Jellyfish library.
3 |
4 | // You should have received a copy of the MIT License
5 | // along with the Jellyfish library. If not, see .
6 |
7 | //! !!!Warning!!!
8 | //! The parameters in this file are mock parameters for testing purpose.
9 | //! They are not correct and shall not be used for anything else
10 |
11 | use crate::rescue::{RescueParameter, ROUNDS, STATE_SIZE};
12 | use ark_bw6_761::Fq;
13 |
14 | /// This is a dummy implementation of Rescue parameters
15 | /// to satisfy trait bound for Fq.
16 | /// This code should not be used for any other purpose.
17 | impl RescueParameter for Fq {
18 | const A: u64 = 5;
19 |
20 | const A_INV: &'static [u64] = &[0, 0, 0, 0, 0, 0];
21 |
22 | const MDS_LE: [[&'static [u8]; STATE_SIZE]; STATE_SIZE] =
23 | [[&[0u8; 32]; STATE_SIZE]; STATE_SIZE];
24 |
25 | const INIT_VEC_LE: [&'static [u8]; STATE_SIZE] = [&[0u8; 32]; STATE_SIZE];
26 |
27 | const KEY_INJECTION_LE: [[&'static [u8]; 4]; 2 * ROUNDS] = [[&[0u8; 32]; 4]; 2 * ROUNDS];
28 |
29 | const PERMUTATION_ROUND_KEYS: [[&'static [u8]; 4]; 25] = [[&[0u8; 32]; 4]; 25];
30 | }
31 |
--------------------------------------------------------------------------------
/jellyfish/primitives/src/rescue/rescue_constants/mod.rs:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2022 Espresso Systems (espressosys.com)
2 | // This file is part of the Jellyfish library.
3 |
4 | // You should have received a copy of the MIT License
5 | // along with the Jellyfish library. If not, see .
6 |
7 | mod bls12_377_base;
8 | mod bls12_381_base;
9 | mod bn254_base;
10 | mod bw6_761_base;
11 | mod ed_on_bls12_377_base;
12 | mod ed_on_bls12_381_base;
13 | mod ed_on_bn254_base;
14 |
--------------------------------------------------------------------------------
/jellyfish/primitives/src/scalars_n_bases.rs:
--------------------------------------------------------------------------------
1 | //! A vector representation of bases and corresponding scalars
2 | use crate::pcs::CommitmentGroup;
3 | use ark_ec::msm::VariableBaseMSM;
4 | use ark_ff::vec::Vec;
5 | use ark_ff::PrimeField;
6 | use ark_std::Zero;
7 | use hashbrown::HashMap;
8 |
9 | /// The vector representation of bases and corresponding scalars.
10 | #[derive(Debug, Clone)]
11 | pub struct ScalarsAndBases {
12 | /// The scalars and bases collection
13 | pub base_scalar_map: HashMap,
14 | }
15 |
16 | impl ScalarsAndBases {
17 | /// Create an empty collection of scalars and bases.
18 | pub fn new() -> Self {
19 | Self {
20 | base_scalar_map: HashMap::new(),
21 | }
22 | }
23 | /// Insert a base point and the corresponding scalar.
24 | pub fn push(&mut self, scalar: E::Fr, base: E::G1Affine) {
25 | let entry_scalar = self.base_scalar_map.entry(base).or_insert_with(E::Fr::zero);
26 | *entry_scalar += scalar;
27 | }
28 |
29 | /// Add a list of scalars and bases into self, where each scalar is
30 | /// multiplied by a constant c.
31 | pub fn merge(&mut self, c: E::Fr, scalars_and_bases: &Self) {
32 | for (base, scalar) in &scalars_and_bases.base_scalar_map {
33 | self.push(c * scalar, *base);
34 | }
35 | }
36 | /// Compute the multi-scalar multiplication.
37 | pub fn multi_scalar_mul(&self) -> E::G1Projective {
38 | let (bases, scalars): (Vec<_>, Vec<_>) = self
39 | .base_scalar_map
40 | .iter()
41 | .map(|(base, scalar)| (*base, scalar.into_repr()))
42 | .unzip();
43 | VariableBaseMSM::multi_scalar_mul(&bases, &scalars)
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/jellyfish/primitives/src/signatures/mod.rs:
--------------------------------------------------------------------------------
1 | //! Module for signature primitives.
2 |
3 | use crate::errors::PrimitivesError;
4 | use ark_std::rand::{CryptoRng, RngCore};
5 |
6 | pub mod bls;
7 | pub mod schnorr;
8 | pub use bls::BLSSignatureScheme;
9 | use core::fmt::Debug;
10 | pub use schnorr::SchnorrSignatureScheme;
11 | use serde::{Deserialize, Serialize};
12 | use zeroize::Zeroize;
13 | /// Trait definition for a signature scheme.
14 | // A signature scheme is associated with a hash function H that is
15 | // to be used for challenge generation.
16 | // FIXME: update H bound once hash-api is merged.
17 | pub trait SignatureScheme {
18 | /// Ciphersuite Identifier
19 | const CS_ID: &'static str;
20 |
21 | /// Signing key.
22 | type SigningKey: Debug
23 | + Clone
24 | + Send
25 | + Sync
26 | + Zeroize
27 | + for<'a> Deserialize<'a>
28 | + Serialize
29 | + PartialEq
30 | + Eq;
31 |
32 | /// Verification key
33 | type VerificationKey: Debug
34 | + Clone
35 | + Send
36 | + Sync
37 | + for<'a> Deserialize<'a>
38 | + Serialize
39 | + PartialEq
40 | + Eq;
41 |
42 | /// Public Parameter
43 | type PublicParameter;
44 |
45 | /// Signature
46 | type Signature: Debug
47 | + Clone
48 | + Send
49 | + Sync
50 | + for<'a> Deserialize<'a>
51 | + Serialize
52 | + PartialEq
53 | + Eq;
54 |
55 | /// A message is &\[MessageUnit\]
56 | type MessageUnit: Debug + Clone + Send + Sync;
57 |
58 | /// generate public parameters from RNG.
59 | /// If the RNG is not presented, use the default group generator.
60 | // FIXME: the API looks a bit strange when the default generator is used.
61 | // For example:
62 | // `S::param_gen::(None)`
63 | // wheere `StdRng` is redundent.
64 | fn param_gen(
65 | prng: Option<&mut R>,
66 | ) -> Result;
67 |
68 | /// Sample a pair of keys.
69 | fn key_gen(
70 | pp: &Self::PublicParameter,
71 | prng: &mut R,
72 | ) -> Result<(Self::SigningKey, Self::VerificationKey), PrimitivesError>;
73 |
74 | /// Sign a message with the signing key
75 | fn sign>(
76 | pp: &Self::PublicParameter,
77 | sk: &Self::SigningKey,
78 | msg: M,
79 | prng: &mut R,
80 | ) -> Result;
81 |
82 | /// Verify a signature.
83 | fn verify>(
84 | pp: &Self::PublicParameter,
85 | vk: &Self::VerificationKey,
86 | msg: M,
87 | sig: &Self::Signature,
88 | ) -> Result<(), PrimitivesError>;
89 | }
90 |
91 | /// Trait for aggregatable signatures.
92 | pub trait AggregateableSignatureSchemes: SignatureScheme {
93 | // TODO: APIs for aggregateable signatures
94 | }
95 |
96 | #[cfg(test)]
97 | mod tests {
98 | use super::*;
99 | use ark_std::{rand::prelude::StdRng, test_rng};
100 |
101 | pub(crate) fn sign_and_verify(message: &[S::MessageUnit]) {
102 | let rng = &mut test_rng();
103 | let parameters = S::param_gen(Some(rng)).unwrap();
104 | let (sk, pk) = S::key_gen(¶meters, rng).unwrap();
105 | let sig = S::sign(¶meters, &sk, message, rng).unwrap();
106 | assert!(S::verify(¶meters, &pk, message, &sig).is_ok());
107 |
108 | let parameters = S::param_gen::(None).unwrap();
109 | let (sk, pk) = S::key_gen(¶meters, rng).unwrap();
110 | let sig = S::sign(¶meters, &sk, message, rng).unwrap();
111 | assert!(S::verify(¶meters, &pk, message, &sig).is_ok());
112 | }
113 |
114 | pub(crate) fn failed_verification(
115 | message: &[S::MessageUnit],
116 | bad_message: &[S::MessageUnit],
117 | ) {
118 | let rng = &mut test_rng();
119 | let parameters = S::param_gen(Some(rng)).unwrap();
120 | let (sk, pk) = S::key_gen(¶meters, rng).unwrap();
121 | let sig = S::sign(¶meters, &sk, message, rng).unwrap();
122 | assert!(S::verify(¶meters, &pk, bad_message, &sig).is_err());
123 | }
124 | }
125 |
--------------------------------------------------------------------------------
/jellyfish/primitives/src/utils.rs:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2022 Espresso Systems (espressosys.com)
2 | // This file is part of the Jellyfish library.
3 |
4 | // You should have received a copy of the MIT License
5 | // along with the Jellyfish library. If not, see .
6 |
7 | use crate::{elgamal, signatures::schnorr};
8 | use ark_ec::{models::TEModelParameters, ProjectiveCurve, TEModelParameters as Parameters};
9 | use ark_ff::{FpParameters, PrimeField};
10 | use ark_std::vec::Vec;
11 | use jf_relation::Variable;
12 |
13 | impl From<&schnorr::VerKey> for (F, F)
14 | where
15 | F: PrimeField,
16 | P: Parameters,
17 | {
18 | fn from(vk: &schnorr::VerKey) -> Self {
19 | let point = vk.0.into_affine();
20 | (point.x, point.y)
21 | }
22 | }
23 |
24 | impl
From<&elgamal::EncKey
> for (P::BaseField, P::BaseField)
25 | where
26 | P: Parameters,
27 | {
28 | fn from(pk: &elgamal::EncKey
) -> Self {
29 | let point = pk.key.into_affine();
30 | (point.x, point.y)
31 | }
32 | }
33 |
34 | #[inline]
35 | pub(crate) fn pad_with(vec: &mut Vec, multiple: usize, var: Variable) {
36 | let len = vec.len();
37 | let new_len = if len % multiple == 0 {
38 | len
39 | } else {
40 | len + multiple - len % multiple
41 | };
42 | vec.resize(new_len, var);
43 | }
44 |
45 | #[inline]
46 | pub(crate) fn field_byte_len() -> usize {
47 | ((F::Params::MODULUS_BITS + 7) / 8) as usize
48 | }
49 |
50 | #[inline]
51 | pub(crate) fn field_bit_len() -> usize {
52 | F::Params::MODULUS_BITS as usize
53 | }
54 |
55 | #[inline]
56 | pub(crate) fn challenge_bit_len() -> usize {
57 | // Our challenge is of size 248 bits
58 | // This is enough for a soundness error of 2^-128
59 | (field_byte_len::() - 1) << 3
60 | }
61 |
62 | #[inline]
63 | pub(crate) fn curve_cofactor() -> u64 {
64 | P::COFACTOR[0]
65 | }
66 |
--------------------------------------------------------------------------------
/jellyfish/primitives/src/vrf/blsvrf.rs:
--------------------------------------------------------------------------------
1 | //! BLS signature based VRF
2 | use super::Vrf;
3 | use crate::{
4 | errors::PrimitivesError,
5 | signatures::{
6 | bls::{BLSSignKey, BLSSignature, BLSVerKey},
7 | BLSSignatureScheme, SignatureScheme,
8 | },
9 | };
10 | use ark_std::{
11 | boxed::Box,
12 | rand::{CryptoRng, RngCore},
13 | vec::Vec,
14 | };
15 | use digest::{Digest, DynDigest};
16 | use sha2::{Sha256, Sha512};
17 |
18 | /// Supported Cipher Suites for BLS VRF.
19 | #[allow(non_camel_case_types)]
20 | #[derive(Debug)]
21 | pub enum BLSVRFCipherSuite {
22 | /// using blst library and VRF output from SHA256 hashing
23 | VRF_BLS_12_381_SHA256,
24 | /// using blst library and VRF output from SHA512 hashing
25 | VRF_BLS_12_381_SHA512,
26 | }
27 |
28 | /// BLS VRF scheme.
29 | /// Optimized for signature size, i.e.: PK in G2 and sig in G1
30 | pub struct BLSVRFScheme {
31 | hasher: Box,
32 | }
33 |
34 | impl BLSVRFScheme {
35 | /// Creates a new BLS VRF instance with the given ciphersuite.
36 | pub fn new(cs_id: BLSVRFCipherSuite) -> Self {
37 | match cs_id {
38 | BLSVRFCipherSuite::VRF_BLS_12_381_SHA256 => Self {
39 | hasher: Box::new(Sha256::new()),
40 | },
41 | BLSVRFCipherSuite::VRF_BLS_12_381_SHA512 => Self {
42 | hasher: Box::new(Sha512::new()),
43 | },
44 | }
45 | }
46 | }
47 |
48 | impl Vrf for BLSVRFScheme {
49 | /// Public Parameter.
50 | /// For BLS signatures, we want to use default
51 | /// prime subgroup generators. So here we don't need
52 | /// to specify which PP it is.
53 | type PublicParameter = ();
54 |
55 | /// VRF public key.
56 | type PublicKey = BLSVerKey;
57 |
58 | /// VRF secret key.
59 | type SecretKey = BLSSignKey;
60 |
61 | /// VRF signature.
62 | type Proof = BLSSignature;
63 |
64 | /// The input of VRF proof.
65 | type Input = Vec;
66 |
67 | /// The output of VRF evaluation.
68 | type Output = Vec;
69 |
70 | /// generate public parameters from RNG.
71 | fn param_gen(
72 | &self,
73 | _prng: Option<&mut R>,
74 | ) -> Result {
75 | Ok(())
76 | }
77 |
78 | /// Creates a pair of VRF public and private keys.
79 | fn key_gen(
80 | &self,
81 | pp: &Self::PublicParameter,
82 | prng: &mut R,
83 | ) -> Result<(Self::SecretKey, Self::PublicKey), PrimitivesError> {
84 | ::key_gen(pp, prng)
85 | }
86 |
87 | /// Creates the VRF proof associated with a VRF secret key.
88 | fn prove(
89 | &self,
90 | pp: &Self::PublicParameter,
91 | secret_key: &Self::SecretKey,
92 | input: &Self::Input,
93 | prng: &mut R,
94 | ) -> Result {
95 | ::sign(pp, secret_key, input, prng)
96 | }
97 |
98 | /// Computes the VRF output associated with a VRF proof.
99 | fn proof_to_hash(
100 | &mut self,
101 | _pp: &Self::PublicParameter,
102 | proof: &Self::Proof,
103 | ) -> Result {
104 | let proof_serialized = proof.serialize();
105 | let mut hasher = (*self.hasher).box_clone();
106 | hasher.update(&proof_serialized);
107 | let output = hasher.finalize();
108 | Ok(output.to_vec())
109 | }
110 |
111 | /// Verifies a VRF proof.
112 | fn verify(
113 | &mut self,
114 | pp: &Self::PublicParameter,
115 | proof: &Self::Proof,
116 | public_key: &Self::PublicKey,
117 | input: &Self::Input,
118 | ) -> Result<(bool, Option), PrimitivesError> {
119 | if ::verify(pp, public_key, input, proof).is_ok() {
120 | Ok((true, Some(Self::proof_to_hash(self, pp, proof).unwrap())))
121 | } else {
122 | Ok((false, None))
123 | }
124 | }
125 | }
126 |
127 | #[cfg(test)]
128 | mod test {
129 | use super::*;
130 | use ark_std::{rand::Rng, test_rng};
131 |
132 | pub(crate) fn sign_and_verify(
133 | vrf: &mut BLSVRFScheme,
134 | message: &::Input,
135 | bad_message: &