11//! Ring VRF.
22//!
33//! This module is gated by the `ring` feature.
4+
45use crate :: * ;
56use ark_ec:: {
67 pairing:: Pairing ,
@@ -22,6 +23,35 @@ pub const ACCUMULATOR_BASE_SEED: &[u8] =
2223pub const PADDING_SEED : & [ u8 ] =
2324 b"umbra quae vacuum implet ab animabus perditis relictum inter tenebras resonans" ;
2425
26+ /// Max ring size that can be managed with the given PCS domain size.
27+ pub const fn max_ring_size_from_pcs_domain_size < S : Suite > ( pcs_domain_size : usize ) -> usize {
28+ let piop_domain_size = piop_domain_size_from_pcs_domain_size ( pcs_domain_size) ;
29+ max_ring_size_from_piop_domain_size :: < S > ( piop_domain_size)
30+ }
31+
32+ /// PCS domain size required to manage the given ring size.
33+ pub const fn pcs_domain_size < S : Suite > ( ring_size : usize ) -> usize {
34+ 3 * piop_domain_size :: < S > ( ring_size) + 1
35+ }
36+
37+ /// Max ring size that can be managed with the given PIOP domain size.
38+ const fn max_ring_size_from_piop_domain_size < S : Suite > ( piop_domain_size : usize ) -> usize {
39+ piop_domain_size - ( 4 + ScalarField :: < S > :: MODULUS_BIT_SIZE as usize )
40+ }
41+
42+ /// PIOP domain size required to manage the given ring size.
43+ ///
44+ /// Next power of two after accouting for 3 ZK + 1 extra point used internally.
45+ const fn piop_domain_size < S : Suite > ( ring_size : usize ) -> usize {
46+ ( ring_size + 4 + ScalarField :: < S > :: MODULUS_BIT_SIZE as usize ) . next_power_of_two ( )
47+ }
48+
49+ /// A properly constructed PCS domain has size equal to 3*piop_domain_size+1,
50+ /// with piop_domain_size a power of 2.
51+ const fn piop_domain_size_from_pcs_domain_size ( pcs_domain_size : usize ) -> usize {
52+ 1 << ( ( pcs_domain_size - 1 ) / 3 ) . ilog2 ( )
53+ }
54+
2555/// Ring suite.
2656pub trait RingSuite : PedersenSuite
2757where
@@ -191,33 +221,7 @@ where
191221 pub piop : PiopParams < S > ,
192222}
193223
194- /// Evaluation domain size required for the given ring size.
195- ///
196- /// This determines the size of the [`PcsParams`] multiples of g1.
197- #[ inline( always) ]
198- pub fn piop_domain_size < S : RingSuite > ( ring_size : usize ) -> usize
199- where
200- BaseField < S > : ark_ff:: PrimeField ,
201- CurveConfig < S > : TECurveConfig + Clone ,
202- AffinePoint < S > : TEMapping < CurveConfig < S > > ,
203- {
204- 1 << ark_std:: log2 ( ring_size + ScalarField :: < S > :: MODULUS_BIT_SIZE as usize + 4 )
205- }
206-
207- /// PCS params `powers_in_g1` is expected to have length equal to 3*piop_domain_size +1.
208- /// This is a strong assumption, guaranteed only for internal usage (e.g.
209- /// `PcsParams` constructed as part of `RingProofParams`)
210- #[ inline( always) ]
211- fn piop_domain_size_from_pcs_params < S : RingSuite > ( pcs_params : & PcsParams < S > ) -> usize
212- where
213- BaseField < S > : ark_ff:: PrimeField ,
214- CurveConfig < S > : TECurveConfig + Clone ,
215- AffinePoint < S > : TEMapping < CurveConfig < S > > ,
216- {
217- pcs_params. powers_in_g1 . len ( ) / 3
218- }
219-
220- fn piop_params < S : RingSuite > ( domain_size : usize ) -> PiopParams < S >
224+ pub ( crate ) fn piop_params < S : RingSuite > ( domain_size : usize ) -> PiopParams < S >
221225where
222226 BaseField < S > : ark_ff:: PrimeField ,
223227 CurveConfig < S > : TECurveConfig + Clone ,
@@ -237,7 +241,7 @@ where
237241 CurveConfig < S > : TECurveConfig + Clone ,
238242 AffinePoint < S > : TEMapping < CurveConfig < S > > ,
239243{
240- /// Construct a new ring context suitable to manage the given ring size.
244+ /// Construct new ring proof params suitable for the given ring size.
241245 ///
242246 /// Calls into [`RingProofParams::from_rand`] with a `ChaCha20Rng` seeded with `seed`.
243247 pub fn from_seed ( ring_size : usize , seed : [ u8 ; 32 ] ) -> Self {
@@ -248,33 +252,37 @@ where
248252
249253 /// Construct a new random ring context suitable for the given ring size.
250254 ///
251- /// Calls into [`RingProofParams::from_srs`] with a randomly generated [`PcsParams`]
252- /// large enough to be used with the given `ring_size`.
255+ /// Calls into [`RingProofParams::from_srs`] with randomly generated [`PcsParams`]
256+ /// large enough to be used for the given `ring_size`.
253257 pub fn from_rand ( ring_size : usize , rng : & mut impl ark_std:: rand:: RngCore ) -> Self {
254258 use ring_proof:: pcs:: PCS ;
255- let domain_size = piop_domain_size :: < S > ( ring_size) ;
256- let pcs_params = Pcs :: < S > :: setup ( 3 * domain_size , rng) ;
257- Self :: from_srs ( ring_size, pcs_params) . expect ( "PCS params is correct" )
259+ let max_degree = pcs_domain_size :: < S > ( ring_size) - 1 ;
260+ let pcs_params = Pcs :: < S > :: setup ( max_degree , rng) ;
261+ Self :: from_pcs_params ( ring_size, pcs_params) . expect ( "PCS params is correct" )
258262 }
259263
260264 /// Construct a new random ring context suitable for the given [`PcsParams`].
261265 ///
262- /// Fails if `PcsParams` are not
263- pub fn from_srs ( ring_size : usize , mut pcs_params : PcsParams < S > ) -> Result < Self , Error > {
264- let domain_size = piop_domain_size :: < S > ( ring_size) ;
265- if pcs_params. powers_in_g1 . len ( ) <= 3 * domain_size || pcs_params. powers_in_g2 . len ( ) < 2 {
266+ /// Fails if the domain representable via the supplied `PcsParams` is not sufficiently
267+ /// large for the given `ring_size`.
268+ ///
269+ /// If the domain size of `PcsParams` exceeds the required limit, the extra items are truncated.
270+ pub fn from_pcs_params ( ring_size : usize , mut pcs_params : PcsParams < S > ) -> Result < Self , Error > {
271+ let pcs_domain_size = pcs_domain_size :: < S > ( ring_size) ;
272+ if pcs_params. powers_in_g1 . len ( ) < pcs_domain_size || pcs_params. powers_in_g2 . len ( ) < 2 {
266273 return Err ( Error :: InvalidData ) ;
267274 }
268275 // Keep only the required powers of tau.
269- pcs_params. powers_in_g1 . truncate ( 3 * domain_size + 1 ) ;
276+ pcs_params. powers_in_g1 . truncate ( pcs_domain_size ) ;
270277 pcs_params. powers_in_g2 . truncate ( 2 ) ;
278+ let piop_domain_size = piop_domain_size :: < S > ( ring_size) ;
271279 Ok ( Self {
272280 pcs : pcs_params,
273- piop : piop_params :: < S > ( domain_size ) ,
281+ piop : piop_params :: < S > ( piop_domain_size ) ,
274282 } )
275283 }
276284
277- /// The max ring size this context is able to manage .
285+ /// The max ring size these parameters are able to handle .
278286 #[ inline( always) ]
279287 pub fn max_ring_size ( & self ) -> usize {
280288 self . piop . keyset_part_size
@@ -323,15 +331,15 @@ where
323331 RingVerifierKey :: < S > :: from_commitment_and_kzg_vk ( commitment, self . pcs . raw_vk ( ) )
324332 }
325333
326- /// Builder for incremental construction of verifier key.
334+ /// Builder for incremental construction of the verifier key.
327335 ///
328- /// This returns both the builder and `RingBuilderKey`, which may be used to append
329- /// new key items to the ring builder (as it implements `SrsLookup`) .
336+ /// This also returns a `RingBuilderPcsParams` which may be used to append new key items
337+ /// to the `RingVerifierKeyBuilder` instance its tne `SrsLookup` implementation .
330338 pub fn verifier_key_builder ( & self ) -> ( RingVerifierKeyBuilder < S > , RingBuilderPcsParams < S > ) {
331339 type RingBuilderKey < S > =
332340 ring_proof:: ring:: RingBuilderKey < BaseField < S > , <S as RingSuite >:: Pairing > ;
333- let domain_size = piop_domain_size_from_pcs_params :: < S > ( & self . pcs ) ;
334- let builder_key = RingBuilderKey :: < S > :: from_srs ( & self . pcs , domain_size ) ;
341+ let piop_domain_size = piop_domain_size_from_pcs_domain_size ( self . pcs . powers_in_g1 . len ( ) ) ;
342+ let builder_key = RingBuilderKey :: < S > :: from_srs ( & self . pcs , piop_domain_size ) ;
335343 let builder_pcs_params = RingBuilderPcsParams ( builder_key. lis_in_g1 ) ;
336344 let builder = RingVerifierKeyBuilder :: new ( self , & builder_pcs_params) ;
337345 ( builder, builder_pcs_params)
@@ -348,7 +356,7 @@ where
348356
349357 /// Constructs a `RingVerifier` from `RingVerifierKey` without no `RingProofParams`.
350358 ///
351- /// While this approach is slightly less efficient than using a pre-constructed `RingProofParams`,
359+ /// While this approach is slightly less efficient than using pre-constructed `RingProofParams`,
352360 /// as some parameters need to be computed on-the-fly, it is beneficial in memory or
353361 /// storage constrained environments. This avoids the need to retain the full `RingProofParams` for
354362 /// ring signature verification. Instead, the `VerifierKey` contains only the essential information
@@ -366,7 +374,7 @@ where
366374
367375 /// Get the padding point.
368376 ///
369- /// This is a point of unknown dlog that can be used to replace of any key during
377+ /// This is a point of unknown dlog that can be used in place of any key during
370378 /// ring construciton.
371379 #[ inline( always) ]
372380 pub const fn padding_point ( ) -> AffinePoint < S > {
@@ -409,7 +417,7 @@ where
409417 compress,
410418 validate,
411419 ) ?;
412- let piop_domain_size = piop_domain_size_from_pcs_params :: < S > ( & pcs_params) ;
420+ let piop_domain_size = piop_domain_size_from_pcs_domain_size ( pcs_params. powers_in_g1 . len ( ) ) ;
413421 Ok ( Self {
414422 pcs : pcs_params,
415423 piop : piop_params :: < S > ( piop_domain_size) ,
@@ -659,6 +667,14 @@ pub(crate) mod testing {
659667 let output = secret. output ( input) ;
660668
661669 let ring_size = params. max_ring_size ( ) ;
670+ let pcs_dom_size = pcs_domain_size :: < S > ( ring_size) ;
671+ assert_eq ! ( pcs_dom_size, params. pcs. powers_in_g1. len( ) ) ;
672+ assert_eq ! ( pcs_dom_size / 3 , piop_domain_size:: <S >( ring_size) ) ;
673+
674+ assert_eq ! (
675+ max_ring_size_from_pcs_domain_size:: <S >( pcs_dom_size) ,
676+ ring_size
677+ ) ;
662678
663679 let prover_idx = 3 ;
664680 let mut pks = common:: random_vec :: < AffinePoint < S > > ( ring_size, Some ( rng) ) ;
@@ -808,7 +824,8 @@ pub(crate) mod testing {
808824 file. read_to_end ( & mut buf) . unwrap ( ) ;
809825 let pcs_params =
810826 PcsParams :: < Self > :: deserialize_uncompressed_unchecked ( & mut & buf[ ..] ) . unwrap ( ) ;
811- RingProofParams :: from_srs ( crate :: ring:: testing:: TEST_RING_SIZE , pcs_params) . unwrap ( )
827+ RingProofParams :: from_pcs_params ( crate :: ring:: testing:: TEST_RING_SIZE , pcs_params)
828+ . unwrap ( )
812829 }
813830
814831 #[ allow( unused) ]
0 commit comments