Skip to content

Commit

Permalink
Merge pull request #82 from w3f/real-srs
Browse files Browse the repository at this point in the history
Real srs
  • Loading branch information
swasilyev authored Dec 7, 2023
2 parents d1949b5 + 877ecbb commit e9782f9
Show file tree
Hide file tree
Showing 7 changed files with 204 additions and 38 deletions.
48 changes: 23 additions & 25 deletions bandersnatch_vrfs/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#![doc = include_str!("../README.md")]

pub mod ring;
pub mod zcash_consts;

use ark_ff::MontFp;
use ark_ec::{
Expand Down Expand Up @@ -40,13 +41,11 @@ pub use dleq_vrf::{
scale,
};

// Set usage of SW affine form
// use bandersnatch::EdwardsAffine as E;
use bandersnatch::SWAffine as E;
use bandersnatch::SWAffine as Jubjub;

pub type VrfInput = dleq_vrf::vrf::VrfInput<E>;
pub type VrfPreOut = dleq_vrf::vrf::VrfPreOut<E>;
pub type VrfInOut = dleq_vrf::vrf::VrfInOut<E>;
pub type VrfInput = dleq_vrf::vrf::VrfInput<Jubjub>;
pub type VrfPreOut = dleq_vrf::vrf::VrfPreOut<Jubjub>;
pub type VrfInOut = dleq_vrf::vrf::VrfInOut<Jubjub>;

pub struct Message<'a> {
pub domain: &'a [u8],
Expand All @@ -61,11 +60,11 @@ G1Projective,
>;
pub fn hash_to_bandersnatch_curve(domain: &[u8],message: &[u8]) -> Result<VrfInput,HashToCurveError> {
dleq_vrf::vrf::ark_hash_to_curve::<E,H2C>(domain,message)
dleq_vrf::vrf::ark_hash_to_curve::<Jubjub,H2C>(domain,message)
}
*/

impl<'a> IntoVrfInput<E> for Message<'a> {
impl<'a> IntoVrfInput<Jubjub> for Message<'a> {
fn into_vrf_input(self) -> VrfInput {
// TODO: Add Elligator to Arkworks
// hash_to_bandersnatch_curve(self.domain,self.message)
Expand All @@ -76,40 +75,39 @@ impl<'a> IntoVrfInput<E> for Message<'a> {
t.append(self.domain);
t.label(b"message");
t.append(self.message);
let p: <E as AffineRepr>::Group = t.challenge(b"vrf-input").read_uniform();
let p: <Jubjub as AffineRepr>::Group = t.challenge(b"vrf-input").read_uniform();
vrf::VrfInput( p.into_affine() )
}
}


const BLINDING_BASE_X: bandersnatch::Fq = MontFp!("4956610287995045830459834427365747411162584416641336688940534788579455781570");

const BLINDING_BASE_Y: bandersnatch::Fq = MontFp!("52360910621642801549936840538960627498114783432181489929217988668068368626761");

pub const BLINDING_BASE: E = E::new_unchecked(BLINDING_BASE_X, BLINDING_BASE_Y);
pub const BLINDING_BASE: Jubjub = {
const X: bandersnatch::Fq = MontFp!("4956610287995045830459834427365747411162584416641336688940534788579455781570");
const Y: bandersnatch::Fq = MontFp!("52360910621642801549936840538960627498114783432181489929217988668068368626761");
Jubjub::new_unchecked(X, Y)
};


type ThinVrf = dleq_vrf::ThinVrf<E>;
type ThinVrf = dleq_vrf::ThinVrf<Jubjub>;

/// Then VRF configured by the G1 generator for signatures.
pub fn thin_vrf() -> ThinVrf {
dleq_vrf::ThinVrf::default() // keying_base: E::generator()
dleq_vrf::ThinVrf::default() // keying_base: Jubjub::generator()
}

type PedersenVrf = dleq_vrf::PedersenVrf<E>;
type PedersenVrf = dleq_vrf::PedersenVrf<Jubjub>;

/// Pedersen VRF configured by the G1 generator for public key certs.
pub fn pedersen_vrf() -> PedersenVrf {
thin_vrf().pedersen_vrf([ BLINDING_BASE ])
}


pub type SecretKey = dleq_vrf::SecretKey<E>;
pub type SecretKey = dleq_vrf::SecretKey<Jubjub>;

pub const PUBLIC_KEY_LENGTH: usize = 33;
pub type PublicKeyBytes = [u8; PUBLIC_KEY_LENGTH];

pub type PublicKey = dleq_vrf::PublicKey<E>;
pub type PublicKey = dleq_vrf::PublicKey<Jubjub>;

pub fn serialize_publickey(pk: &PublicKey) -> PublicKeyBytes {
let mut bytes = [0u8; PUBLIC_KEY_LENGTH];
Expand Down Expand Up @@ -137,7 +135,7 @@ pub struct RingVrfProof {
}

impl dleq_vrf::EcVrfProof for RingVrfProof {
type H = E;
type H = Jubjub;
}

// TODO: Can you impl Debug+Eq+PartialEq for ring::RingProof please Sergey? We'll then derive Debug.
Expand Down Expand Up @@ -194,7 +192,7 @@ impl RingVerifier<'_> {
pub fn verify_ring_vrf<const N: usize>(
&self,
t: impl IntoTranscript,
inputs: impl IntoIterator<Item = impl IntoVrfInput<E>>,
inputs: impl IntoIterator<Item = impl IntoVrfInput<Jubjub>>,
signature: &RingVrfSignature<N>,
) -> Result<[VrfInOut; N],SignatureError>
{
Expand Down Expand Up @@ -255,9 +253,9 @@ mod tests {
use ark_std::rand::RngCore;

#[test]
fn blinding_base() {
fn check_blinding_base() {
let mut t = b"Bandersnatch VRF blinding base".into_transcript();
let blinding_base: <E as AffineRepr>::Group = t.challenge(b"vrf-input").read_uniform();
let blinding_base: <Jubjub as AffineRepr>::Group = t.challenge(b"vrf-input").read_uniform();
debug_assert_eq!(blinding_base.into_affine(), BLINDING_BASE);
}

Expand Down Expand Up @@ -303,7 +301,7 @@ mod tests {
let keyset_size = usize::from_le_bytes(l) % keyset_size;

// Gen a bunch of random public keys
let mut pks: Vec<_> = (0..keyset_size).map(|_| E::rand(&mut rng)).collect();
let mut pks: Vec<_> = (0..keyset_size).map(|_| Jubjub::rand(&mut rng)).collect();
// Just select one index for the actual key we are for signing
let secret_key_idx = keyset_size / 2;
pks[secret_key_idx] = pk.0.into();
Expand Down
89 changes: 76 additions & 13 deletions bandersnatch_vrfs/src/ring.rs
Original file line number Diff line number Diff line change
@@ -1,24 +1,25 @@
extern crate alloc;
use alloc::vec::Vec;

use ark_std::rand::{Rng, SeedableRng};
use alloc::vec::Vec;

use ark_ff::{Field, MontFp};
use ark_serialize::{
CanonicalSerialize, CanonicalDeserialize, Valid, Compress, Validate, SerializationError,
Write, Read,
CanonicalDeserialize, CanonicalSerialize, Compress, Read, SerializationError, Valid,
Validate, Write,
};

use merlin::Transcript;

use ark_std::{rand::{Rng, SeedableRng}, vec};
use fflonk::pcs::PCS;
use merlin::Transcript;
use ring::Domain;
use ring::ring::Ring;

use crate::bandersnatch::{Fq, SWConfig, SWAffine}; // Fr
use crate::bandersnatch::{Fq, SWAffine, SWConfig, BandersnatchConfig};
use crate::bls12_381::Bls12_381;
use crate::bls12_381;

type RealKZG = fflonk::pcs::kzg::KZG<bls12_381::Bls12_381>;
type RealKZG = fflonk::pcs::kzg::KZG<Bls12_381>;

type PcsParams = fflonk::pcs::kzg::urs::URS<bls12_381::Bls12_381>;
type PcsParams = fflonk::pcs::kzg::urs::URS<Bls12_381>;

pub type PiopParams = ring::PiopParams<Fq, SWConfig>;
pub type RingProof = ring::RingProof<Fq, RealKZG>;
Expand All @@ -28,10 +29,28 @@ pub type RingVerifier = ring::ring_verifier::RingVerifier<Fq, RealKZG, SWConfig>
pub type ProverKey = ring::ProverKey<Fq, RealKZG, SWAffine>;
pub type VerifierKey = ring::VerifierKey<Fq, RealKZG>;

pub type KzgVk = fflonk::pcs::kzg::params::RawKzgVerifierKey<Bls12_381>;

pub type RingCommitment = Ring<bls12_381::Fr, Bls12_381, BandersnatchConfig>;

// A point on Jubjub, not belonging to the prime order subgroup.
// Used as the point to start summation from, as inf doesn't have an affine representation.
const COMPLEMENT_POINT: crate::Jubjub = {
const X: Fq = Fq::ZERO;
const Y: Fq = MontFp!("11982629110561008531870698410380659621661946968466267969586599013782997959645");
crate::Jubjub::new_unchecked(X, Y)
};

// Just a point of an unknown dlog.
pub(crate) const PADDING_POINT: crate::Jubjub = {
const X: Fq = MontFp!("25448400713078632486748382313960039031302935774474538965225823993599751298535");
const Y: Fq = MontFp!("24382892199244280513693545286348030912870264650402775682704689602954457435722");
crate::Jubjub::new_unchecked(X, Y)
};

pub fn make_piop_params(domain_size: usize) -> PiopParams {
let domain = Domain::new(domain_size, true);
let seed = ring::find_complement_point::<crate::bandersnatch::BandersnatchConfig>();
PiopParams::setup(domain, crate::BLINDING_BASE, seed)
PiopParams::setup(domain, crate::BLINDING_BASE, COMPLEMENT_POINT)
}

pub fn make_ring_verifier(verifier_key: VerifierKey, domain_size: usize) -> RingVerifier {
Expand All @@ -43,9 +62,25 @@ pub fn make_ring_verifier(verifier_key: VerifierKey, domain_size: usize) -> Ring
pub struct KZG {
pub domain_size: u32,
piop_params: PiopParams,
pcs_params: PcsParams,
pub pcs_params: PcsParams,
}

#[derive(CanonicalDeserialize, CanonicalSerialize)]
pub struct StaticVerifierKey {
// `N` Lagrangian bases `L1(tau).G1, ..., LN(tau).G1`, where `N=2^m` is domain size.
// Used to create/update the commitment to the public keys.
pub lag_g1: Vec<bls12_381::G1Affine>,
// KZG vk with unprepared G2 points.
pub kzg_vk: KzgVk,
}

#[derive(CanonicalDeserialize, CanonicalSerialize)]
pub struct StaticProverKey {
// `3N+1` monomial bases `G1, tau.G1, ..., tau^(3N).G1`, where `N=2^m` is domain size.
pub mon_g1: Vec<bls12_381::G1Affine>,
// KZG vk with unprepared G2 points. Used in the Fiat-Shamir transform.
pub kzg_vk: KzgVk,
}

impl KZG {
// TODO: Import powers of tau
Expand All @@ -59,6 +94,19 @@ impl KZG {
}
}

pub fn kzg_setup(domain_size: usize, srs: StaticProverKey) -> Self {
let piop_params = make_piop_params(domain_size);
let pcs_params = fflonk::pcs::kzg::urs::URS {
powers_in_g1: srs.mon_g1,
powers_in_g2: vec![srs.kzg_vk.g2, srs.kzg_vk.tau_in_g2],
};
KZG {
domain_size: domain_size as u32,
piop_params,
pcs_params,
}
}

// Testing only kzg setup.
pub fn testing_kzg_setup(preseed: [u8;32], domain_size: u32) -> Self {
let mut rng = rand_chacha::ChaCha20Rng::from_seed(preseed);
Expand Down Expand Up @@ -141,3 +189,18 @@ impl Valid for KZG {
}
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn check_complement_point() {
assert_eq!(COMPLEMENT_POINT, ring::find_complement_point::<crate::bandersnatch::BandersnatchConfig>());
}

#[test]
fn check_padding_point() {
let padding_point = ring::hash_to_curve::<crate::Jubjub>(b"w3f/ring-proof/common/padding");
assert_eq!(PADDING_POINT, padding_point);
}
}
105 changes: 105 additions & 0 deletions bandersnatch_vrfs/src/zcash_consts.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
use ark_ec::short_weierstrass::SWCurveConfig;
use ark_ff::MontFp;
use ring::ring::Ring;

use crate::bls12_381;
use crate::ring::PADDING_POINT;

// KZG verification key formed using zcash powers of tau setup,
// see https://zfnd.org/conclusion-of-the-powers-of-tau-ceremony/
// This depends only on the trapdoor tau and doesn't change with the SRS size.
pub const ZCASH_KZG_VK: crate::ring::KzgVk = {
const ZCASH_TAU_G2: bls12_381::G2Affine = {
const TAU_G2_X_C0: bls12_381::Fq = MontFp!("186544079744757791750913777923182116923406997981176124505869835669370349308168084101869919858020293159217147453183");
const TAU_G2_X_C1: bls12_381::Fq = MontFp!("2680951345815209329447762511030627858997446358927866220189443219836425021933771668894483091748402109907600527683136");
const TAU_G2_Y_C0: bls12_381::Fq = MontFp!("2902268288386460594512721059125470579172313681349425350948444194000638363935297586336373516015117406788334505343385");
const TAU_G2_Y_C1: bls12_381::Fq = MontFp!("1813420068648567014729235095042931383392721750833188405957278380281750025472382039431377469634297470981522036543739");
const TAU_G2_X: bls12_381::Fq2 = bls12_381::Fq2::new(TAU_G2_X_C0, TAU_G2_X_C1);
const TAU_G2_Y: bls12_381::Fq2 = bls12_381::Fq2::new(TAU_G2_Y_C0, TAU_G2_Y_C1);
bls12_381::G2Affine::new_unchecked(TAU_G2_X, TAU_G2_Y)
};
crate::ring::KzgVk {
g1: bls12_381::g1::Config::GENERATOR,
g2: bls12_381::g2::Config::GENERATOR,
tau_in_g2: ZCASH_TAU_G2,
}
};

pub const EMPTY_RING_ZCASH_16: crate::ring::RingCommitment = {
const CX: bls12_381::G1Affine = {
const CX_X: bls12_381::Fq = MontFp!("3788900533645096359019216841960589653729050156392657543253995350463234398678023194904690783533798180859113443129587");
const CX_Y: bls12_381::Fq = MontFp!("3582602640224975303869289619528171841306894960147190839338637222834230941804329040350369300962553901480636730372581");
bls12_381::G1Affine::new_unchecked(CX_X, CX_Y)
};

const CY: bls12_381::G1Affine = {
const CY_X: bls12_381::Fq = MontFp!("275395450190015856550496699869027966473940409580082325014934185576731671390149219559463097372558226437269657531660");
const CY_Y: bls12_381::Fq = MontFp!("3663288734506896245820179102192865221246127277945565853514629164665454948590285989938009769802061984318296406596594");
bls12_381::G1Affine::new_unchecked(CY_X, CY_Y)
};

const SELECTOR: bls12_381::G1Affine = {
const S_X: bls12_381::Fq = MontFp!("1782119914953303272451532413343785016217423941022111405224636116706617268932874941495968306638218277903118171292714");
const S_Y: bls12_381::Fq = MontFp!("980603551794328446316569624808467604586898338411909681693214961643826527471799191709185815907315792552509777449194");
bls12_381::G1Affine::new_unchecked(S_X, S_Y)
};

Ring::empty_unchecked(1 << 16, CX, CY, SELECTOR, PADDING_POINT)
};

pub const EMPTY_RING_ZCASH_9: crate::ring::RingCommitment = {
const CX: bls12_381::G1Affine = {
const CX_X: bls12_381::Fq = MontFp!("3291131881719335745208408701681071363716236350417454999905110666318371537988666481391841675885214685977620333296347");
const CX_Y: bls12_381::Fq = MontFp!("656646093535020120743664511096703186833125593035677837853779434938235484450936004914833523742524637066850726692849");
bls12_381::G1Affine::new_unchecked(CX_X, CX_Y)
};

const CY: bls12_381::G1Affine = {
const CY_X: bls12_381::Fq = MontFp!("1379935455078958073848938550933991225642174070456251938010549849263825750122860425278454316147982027674102683391035");
const CY_Y: bls12_381::Fq = MontFp!("3310969786079377757118431956146881739794049489592156595529073696500104605627892596749867504817872693129039702247882");
bls12_381::G1Affine::new_unchecked(CY_X, CY_Y)
};

const SELECTOR: bls12_381::G1Affine = {
const S_X: bls12_381::Fq = MontFp!("2908850075820590559825558591796489926137468891350244723135070577033834833074699096095104618216690855741912718144719");
const S_Y: bls12_381::Fq = MontFp!("436343574607707198583869582232412021753441754571435491281710311907340647898134029725340232367691953082908705963261");
bls12_381::G1Affine::new_unchecked(S_X, S_Y)
};

Ring::empty_unchecked(1 << 9, CX, CY, SELECTOR, PADDING_POINT)
};


#[cfg(all(test, feature = "std"))]
mod tests {
use ark_serialize::CanonicalDeserialize;
use ring::ring::RingBuilderKey;

use super::*;

fn build_empty_ring(log_domain_size: usize) -> crate::ring::RingCommitment {
let piop_params = crate::ring::make_piop_params(1 << log_domain_size);
let vk = crate::ring::StaticVerifierKey::deserialize_uncompressed_unchecked(
std::fs::read(format!("zcash-{}.vk", log_domain_size)).unwrap().as_slice()
).unwrap();
let rbk = RingBuilderKey {
lis_in_g1: vk.lag_g1,
g1: ZCASH_KZG_VK.g1.into(),
};
crate::ring::RingCommitment::with_keys(
&piop_params,
&[],
&rbk,
)
}

#[test]
fn check_empty_ring_16() {
assert_eq!(EMPTY_RING_ZCASH_16, build_empty_ring(16));
}

#[test]
fn check_empty_ring_9() {
assert_eq!(EMPTY_RING_ZCASH_9, build_empty_ring(9));
}
}
Binary file added bandersnatch_vrfs/zcash-16.pk
Binary file not shown.
Binary file added bandersnatch_vrfs/zcash-16.vk
Binary file not shown.
Binary file added bandersnatch_vrfs/zcash-9.pk
Binary file not shown.
Binary file added bandersnatch_vrfs/zcash-9.vk
Binary file not shown.

0 comments on commit e9782f9

Please sign in to comment.