@ -1,9 +1,10 @@
#![ allow(non_snake_case) ]
#![ allow(non_camel_case_types) ]
#![ allow(clippy::upper_case_acronyms) ]
use ark_bn254 ::{ Bn254 , Fq , G1Affine } ;
use ark_groth16 ::VerifyingKey ;
use ark_poly_commit ::kzg10 ::VerifierKey ;
use ark_bn254 ::{ Bn254 , Fq , Fr , G1Affine } ;
use ark_groth16 ::VerifyingKey as ArkG16VerifierKey ;
use ark_poly_commit ::kzg10 ::VerifierKey as ArkKZG10VerifierKey ;
use ark_serialize ::{ CanonicalDeserialize , CanonicalSerialize } ;
use askama ::Template ;
@ -27,6 +28,7 @@ pub fn get_decider_template_for_cyclefold_decider(
#[ derive(Template, Default) ]
#[ template(path = " nova_cyclefold_decider.askama.sol " , ext = " sol " ) ]
pub struct NovaCycleFoldDecider {
pp_hash : Fr , // public params hash
groth16_verifier : Groth16Verifier ,
kzg10_verifier : KZG10Verifier ,
// z_len denotes the FCircuit state (z_i) length
@ -42,6 +44,7 @@ impl From for NovaCycleFoldDecider {
let public_inputs_len = groth16_verifier . gamma_abc_len ;
let bits_per_limb = NonNativeUintVar ::< Fq > ::bits_per_limb ( ) ;
Self {
pp_hash : value . pp_hash ,
groth16_verifier ,
kzg10_verifier : KZG10Verifier ::from ( value . kzg_vk ) ,
z_len : value . z_len ,
@ -54,6 +57,7 @@ impl From for NovaCycleFoldDecider {
#[ derive(CanonicalDeserialize, CanonicalSerialize, PartialEq, Debug, Clone) ]
pub struct NovaCycleFoldVerifierKey {
pp_hash : Fr ,
g16_vk : Groth16VerifierKey ,
kzg_vk : KZG10VerifierKey ,
z_len : usize ,
@ -73,25 +77,37 @@ impl ProtocolVerifierKey for NovaCycleFoldVerifierKey {
}
}
impl From < ( Groth16VerifierKey , KZG10VerifierKey , usize ) > for NovaCycleFoldVerifierKey {
fn from ( value : ( Groth16VerifierKey , KZG10VerifierKey , usize ) ) -> Self {
impl From < ( Fr , Groth16VerifierKey , KZG10VerifierKey , usize ) > for NovaCycleFoldVerifierKey {
fn from ( value : ( Fr , Groth16VerifierKey , KZG10VerifierKey , usize ) ) -> Self {
Self {
g16_vk : value . 0 ,
kzg_vk : value . 1 ,
z_len : value . 2 ,
pp_hash : value . 0 ,
g16_vk : value . 1 ,
kzg_vk : value . 2 ,
z_len : value . 3 ,
}
}
}
// implements From assuming that the 'batchCheck' method from the KZG10 template will not be used
// in the NovaCycleFoldDecider verifier contract
impl From < ( ( VerifyingKey < Bn254 > , VerifierKey < Bn254 > ) , usize ) > for NovaCycleFoldVerifierKey {
fn from ( value : ( ( VerifyingKey < Bn254 > , VerifierKey < Bn254 > ) , usize ) ) -> Self {
impl
From < (
( Fr , ArkG16VerifierKey < Bn254 > , ArkKZG10VerifierKey < Bn254 > ) ,
usize ,
) > for NovaCycleFoldVerifierKey
{
fn from (
value : (
( Fr , ArkG16VerifierKey < Bn254 > , ArkKZG10VerifierKey < Bn254 > ) ,
usize ,
) ,
) -> Self {
let decider_vp = value . 0 ;
let g16_vk = Groth16VerifierKey ::from ( decider_vp . 0 ) ;
let g16_vk = Groth16VerifierKey ::from ( decider_vp . 1 ) ;
// pass `Vec::new()` since batchCheck will not be used
let kzg_vk = KZG10VerifierKey ::from ( ( decider_vp . 1 , Vec ::new ( ) ) ) ;
let kzg_vk = KZG10VerifierKey ::from ( ( decider_vp . 2 , Vec ::new ( ) ) ) ;
Self {
pp_hash : decider_vp . 0 ,
g16_vk ,
kzg_vk ,
z_len : value . 1 ,
@ -101,12 +117,14 @@ impl From<((VerifyingKey, VerifierKey), usize)> for NovaCycleFoldV
impl NovaCycleFoldVerifierKey {
pub fn new (
vkey_g16 : VerifyingKey < Bn254 > ,
vkey_kzg : VerifierKey < Bn254 > ,
pp_hash : Fr ,
vkey_g16 : ArkG16VerifierKey < Bn254 > ,
vkey_kzg : ArkKZG10VerifierKey < Bn254 > ,
crs_points : Vec < G1Affine > ,
z_len : usize ,
) -> Self {
Self {
pp_hash ,
g16_vk : Groth16VerifierKey ::from ( vkey_g16 ) ,
kzg_vk : KZG10VerifierKey ::from ( ( vkey_kzg , crs_points ) ) ,
z_len ,
@ -117,12 +135,9 @@ impl NovaCycleFoldVerifierKey {
#[ cfg(test) ]
mod tests {
use ark_bn254 ::{ constraints ::GVar , Bn254 , Fr , G1Projective as G1 } ;
use ark_crypto_primitives ::snark ::SNARK ;
use ark_ff ::PrimeField ;
use ark_groth16 ::VerifyingKey as G16VerifierKey ;
use ark_groth16 ::{ Groth16 , ProvingKey } ;
use ark_groth16 ::Groth16 ;
use ark_grumpkin ::{ constraints ::GVar as GVar2 , Projective as G2 } ;
use ark_poly_commit ::kzg10 ::VerifierKey as KZGVerifierKey ;
use ark_r1cs_std ::alloc ::AllocVar ;
use ark_r1cs_std ::fields ::fp ::FpVar ;
use ark_relations ::r1cs ::{ ConstraintSystemRef , SynthesisError } ;
@ -132,15 +147,10 @@ mod tests {
use std ::time ::Instant ;
use folding_schemes ::{
commitment ::{
kzg ::{ ProverKey as KZGProverKey , KZG } ,
pedersen ::Pedersen ,
CommitmentScheme ,
} ,
commitment ::{ kzg ::KZG , pedersen ::Pedersen } ,
folding ::nova ::{
decider_eth ::{ prepare_calldata , Decider as DeciderEth } ,
decider_eth_circuit ::DeciderEthCircuit ,
get_cs_params_len , Nova , ProverParams ,
Nova , PreprocessorParam ,
} ,
frontend ::FCircuit ,
transcript ::poseidon ::poseidon_canonical_config ,
@ -156,6 +166,24 @@ mod tests {
NovaCycleFoldVerifierKey , ProtocolVerifierKey ,
} ;
type NOVA < FC > = Nova < G1 , GVar , G2 , GVar2 , FC , KZG < 'static , Bn254 > , Pedersen < G2 > > ;
type DECIDER < FC > = DeciderEth <
G1 ,
GVar ,
G2 ,
GVar2 ,
FC ,
KZG < 'static , Bn254 > ,
Pedersen < G2 > ,
Groth16 < Bn254 > ,
NOVA < FC > ,
> ;
type FS_PP < FC > = < NOVA < FC > as FoldingScheme < G1 , G2 , FC > > ::ProverParam ;
type FS_VP < FC > = < NOVA < FC > as FoldingScheme < G1 , G2 , FC > > ::VerifierParam ;
type DECIDER_PP < FC > = < DECIDER < FC > as Decider < G1 , G2 , FC , NOVA < FC > > > ::ProverParam ;
type DECIDER_VP < FC > = < DECIDER < FC > as Decider < G1 , G2 , FC , NOVA < FC > > > ::VerifierParam ;
/// Test circuit to be folded
#[ derive(Clone, Copy, Debug) ]
pub struct CubicFCircuit < F : PrimeField > {
@ -256,10 +284,10 @@ mod tests {
#[ test ]
fn nova_cyclefold_vk_serde_roundtrip ( ) {
let ( _ , kzg_vk , _ , g16_vk , _ ) = setup ( DEFAULT_SETUP_LEN ) ;
let ( pp_hash , _ , kzg_vk , _ , g16_vk , _ ) = setup ( DEFAULT_SETUP_LEN ) ;
let mut bytes = vec ! [ ] ;
let nova_cyclefold_vk = NovaCycleFoldVerifierKey ::from ( ( ( g16_vk , kzg_vk ) , 1 ) ) ;
let nova_cyclefold_vk = NovaCycleFoldVerifierKey ::from ( ( ( pp_hash , g16_vk , kzg_vk ) , 1 ) ) ;
nova_cyclefold_vk
. serialize_protocol_verifier_key ( & mut bytes )
@ -272,8 +300,8 @@ mod tests {
#[ test ]
fn nova_cyclefold_decider_template_renders ( ) {
let ( _ , kzg_vk , _ , g16_vk , _ ) = setup ( DEFAULT_SETUP_LEN ) ;
let nova_cyclefold_vk = NovaCycleFoldVerifierKey ::from ( ( ( g16_vk , kzg_vk ) , 1 ) ) ;
let ( pp_hash , _ , kzg_vk , _ , g16_vk , _ ) = setup ( DEFAULT_SETUP_LEN ) ;
let nova_cyclefold_vk = NovaCycleFoldVerifierKey ::from ( ( ( pp_hash , g16_vk , kzg_vk ) , 1 ) ) ;
let decider_solidity_code = HeaderInclusion ::< NovaCycleFoldDecider > ::builder ( )
. template ( nova_cyclefold_vk )
@ -282,59 +310,29 @@ mod tests {
save_solidity ( "NovaDecider.sol" , & decider_solidity_code . render ( ) . unwrap ( ) ) ;
}
#[ allow(clippy::type_complexity) ]
fn init_test_prover_params < FC : FCircuit < Fr , Params = ( ) > > ( ) -> (
ProverParams < G1 , G2 , KZG < 'static , Bn254 > , Pedersen < G2 > > ,
KZGVerifierKey < Bn254 > ,
) {
let mut rng = ark_std ::test_rng ( ) ;
let poseidon_config = poseidon_canonical_config ::< Fr > ( ) ;
let f_circuit = FC ::new ( ( ) ) . unwrap ( ) ;
let ( cs_len , cf_cs_len ) =
get_cs_params_len ::< G1 , GVar , G2 , GVar2 , FC > ( & poseidon_config , f_circuit ) . unwrap ( ) ;
let ( kzg_pk , kzg_vk ) : ( KZGProverKey < G1 > , KZGVerifierKey < Bn254 > ) =
KZG ::< Bn254 > ::setup ( & mut rng , cs_len ) . unwrap ( ) ;
let ( cf_pedersen_params , _ ) = Pedersen ::< G2 > ::setup ( & mut rng , cf_cs_len ) . unwrap ( ) ;
let fs_prover_params = ProverParams ::< G1 , G2 , KZG < Bn254 > , Pedersen < G2 > > {
poseidon_config : poseidon_config . clone ( ) ,
cs_pp : kzg_pk . clone ( ) ,
cf_cs_pp : cf_pedersen_params ,
} ;
( fs_prover_params , kzg_vk )
}
/// Initializes Nova parameters and DeciderEth parameters. Only for test purposes.
#[ allow(clippy::type_complexity) ]
fn init_params < FC : FCircuit < Fr , Params = ( ) > > ( ) -> (
ProverParams < G1 , G2 , KZG < 'static , Bn254 > , Pedersen < G2 > > ,
KZGVerifierKey < Bn254 > ,
ProvingKey < Bn254 > ,
G16VerifierKey < Bn254 > ,
) {
fn init_params < FC : FCircuit < Fr , Params = ( ) > > (
) -> ( ( FS_PP < FC > , FS_VP < FC > ) , ( DECIDER_PP < FC > , DECIDER_VP < FC > ) ) {
let mut rng = rand ::rngs ::OsRng ;
let start = Instant ::now ( ) ;
let ( fs_prover_params , kzg_vk ) = init_test_prover_params ::< FC > ( ) ;
println ! ( "generated Nova folding params: {:?}" , start . elapsed ( ) ) ;
let f_circuit = FC ::new ( ( ) ) . unwrap ( ) ;
pub type NOVA_FCircuit < FC > =
Nova < G1 , GVar , G2 , GVar2 , FC , KZG < 'static , Bn254 > , Pedersen < G2 > > ;
let z_0 = vec ! [ Fr ::zero ( ) ; f_circuit . state_len ( ) ] ;
let nova = NOVA_FCircuit ::init ( & fs_prover_params , f_circuit , z_0 . clone ( ) ) . unwrap ( ) ;
let poseidon_config = poseidon_canonical_config ::< Fr > ( ) ;
let decider_circuit =
DeciderEthCircuit ::< G1 , GVar , G2 , GVar2 , KZG < Bn254 > , Pedersen < G2 > > ::from_nova ::< FC > (
nova . clone ( ) ,
)
. unwrap ( ) ;
let start = Instant ::now ( ) ;
let ( g16_pk , g16_vk ) =
Groth16 ::< Bn254 > ::circuit_specific_setup ( decider_circuit . clone ( ) , & mut rng ) . unwrap ( ) ;
println ! (
"generated G16 (Decider circuit) params: {:?}" ,
start . elapsed ( )
let f_circuit = FC ::new ( ( ) ) . unwrap ( ) ;
let prep_param = PreprocessorParam ::< G1 , G2 , FC , KZG < 'static , Bn254 > , Pedersen < G2 > > ::new (
poseidon_config ,
f_circuit . clone ( ) ,
) ;
( fs_prover_params , kzg_vk , g16_pk , g16_vk )
let nova_params = NOVA ::preprocess ( & mut rng , & prep_param ) . unwrap ( ) ;
let nova = NOVA ::init (
nova_params . clone ( ) ,
f_circuit . clone ( ) ,
vec ! [ Fr ::zero ( ) ; f_circuit . state_len ( ) ] . clone ( ) ,
)
. unwrap ( ) ;
let decider_params =
DECIDER ::preprocess ( & mut rng , & nova_params . clone ( ) , nova . clone ( ) ) . unwrap ( ) ;
( nova_params , decider_params )
}
/// This function allows to define which FCircuit to use for the test, and how many prove_step
@ -346,52 +344,31 @@ mod tests {
/// - modifies the z_0 and checks that it does not pass the EVM check
#[ allow(clippy::type_complexity) ]
fn nova_cyclefold_solidity_verifier_opt < FC : FCircuit < Fr , Params = ( ) > > (
params : (
ProverParams < G1 , G2 , KZG < 'static , Bn254 > , Pedersen < G2 > > ,
KZGVerifierKey < Bn254 > ,
ProvingKey < Bn254 > ,
G16VerifierKey < Bn254 > ,
) ,
fs_params : ( FS_PP < FC > , FS_VP < FC > ) ,
decider_params : ( DECIDER_PP < FC > , DECIDER_VP < FC > ) ,
z_0 : Vec < Fr > ,
n_steps : usize ,
) {
let ( fs_prover_params , kzg_vk , g16_pk , g16_vk ) = params . clone ( ) ;
pub type NOVA_FCircuit < FC > =
Nova < G1 , GVar , G2 , GVar2 , FC , KZG < 'static , Bn254 > , Pedersen < G2 > > ;
pub type DECIDERETH_FCircuit < FC > = DeciderEth <
G1 ,
GVar ,
G2 ,
GVar2 ,
FC ,
KZG < 'static , Bn254 > ,
Pedersen < G2 > ,
Groth16 < Bn254 > ,
NOVA_FCircuit < FC > ,
> ;
let ( decider_pp , decider_vp ) = decider_params ;
let f_circuit = FC ::new ( ( ) ) . unwrap ( ) ;
let nova_cyclefold_vk = NovaCycleFoldVerifierKey ::from ( (
( g16_vk . clone ( ) , kzg_vk . clone ( ) ) ,
f_circuit . state_len ( ) ,
) ) ;
let nova_cyclefold_vk =
NovaCycleFoldVerifierKey ::from ( ( decider_vp . clone ( ) , f_circuit . state_len ( ) ) ) ;
let mut rng = rand ::rngs ::OsRng ;
let mut nova = NOVA_FCircuit ::init ( & fs_prover _params , f_circuit , z_0 ) . unwrap ( ) ;
let mut nova = NOVA ::< FC > ::init ( fs_params , f_circuit , z_0 ) . unwrap ( ) ;
for _ in 0 . . n_steps {
nova . prove_step ( & mut rng , vec ! [ ] ) . unwrap ( ) ;
}
let start = Instant ::now ( ) ;
let proof =
DECIDERETH_FCircuit ::prove ( rng , ( g16_pk , fs_prover_params . cs_pp . clone ( ) ) , nova . clone ( ) )
. unwrap ( ) ;
let proof = DECIDER ::< FC > ::prove ( rng , decider_pp , nova . clone ( ) ) . unwrap ( ) ;
println ! ( "generated Decider proof: {:?}" , start . elapsed ( ) ) ;
let verified = DECIDERETH_FCircuit ::< FC > ::verify (
( g16_vk , kzg_vk ) ,
let verified = DECIDER ::< FC > ::verify (
decider_vp ,
nova . i ,
nova . z_0 . clone ( ) ,
nova . z_i . clone ( ) ,
@ -448,12 +425,22 @@ mod tests {
#[ test ]
fn nova_cyclefold_solidity_verifier ( ) {
let params = init_params ::< CubicFCircuit < Fr > > ( ) ;
let ( nova_ params, decider_params ) = init_params ::< CubicFCircuit < Fr > > ( ) ;
let z_0 = vec ! [ Fr ::from ( 3_ u32 ) ] ;
nova_cyclefold_solidity_verifier_opt ::< CubicFCircuit < Fr > > ( params . clone ( ) , z_0 . clone ( ) , 2 ) ;
nova_cyclefold_solidity_verifier_opt ::< CubicFCircuit < Fr > > ( params . clone ( ) , z_0 . clone ( ) , 3 ) ;
nova_cyclefold_solidity_verifier_opt ::< CubicFCircuit < Fr > > (
nova_params . clone ( ) ,
decider_params . clone ( ) ,
z_0 . clone ( ) ,
2 ,
) ;
nova_cyclefold_solidity_verifier_opt ::< CubicFCircuit < Fr > > (
nova_params ,
decider_params ,
z_0 ,
3 ,
) ;
let params = init_params ::< MultiInputsFCircuit < Fr > > ( ) ;
let ( nova_ params, decider_params ) = init_params ::< MultiInputsFCircuit < Fr > > ( ) ;
let z_0 = vec ! [
Fr ::from ( 1_ u32 ) ,
Fr ::from ( 1_ u32 ) ,
@ -462,12 +449,14 @@ mod tests {
Fr ::from ( 1_ u32 ) ,
] ;
nova_cyclefold_solidity_verifier_opt ::< MultiInputsFCircuit < Fr > > (
params . clone ( ) ,
nova_params . clone ( ) ,
decider_params . clone ( ) ,
z_0 . clone ( ) ,
2 ,
) ;
nova_cyclefold_solidity_verifier_opt ::< MultiInputsFCircuit < Fr > > (
params . clone ( ) ,
nova_params ,
decider_params ,
z_0 . clone ( ) ,
3 ,
) ;