@@ -29,6 +29,59 @@ pub struct VIDProof {
2929 pub opening_proof : OpeningProof < Curve > ,
3030}
3131
32+ /// Divide `self` by the vanishing polynomial for the sub-domain, `X^{domain_size} - coeff`.
33+ pub fn divide_by_sub_vanishing_poly (
34+ poly : & DensePolynomial < ScalarField > ,
35+ domain_size : usize ,
36+ coeff : ScalarField ,
37+ ) -> ( DensePolynomial < ScalarField > , DensePolynomial < ScalarField > ) {
38+ if poly. coeffs . len ( ) < domain_size {
39+ // If degree(poly) < len(Domain), then the quotient is zero, and the entire polynomial is the remainder
40+ ( DensePolynomial :: < ScalarField > :: zero ( ) , poly. clone ( ) )
41+ } else {
42+ // Compute the quotient
43+ //
44+ // If `poly.len() <= 2 * domain_size`
45+ // then quotient is simply `poly.coeffs[domain_size..]`
46+ // Otherwise
47+ // during the division by `x^domain_size - 1`, some of `poly.coeffs[domain_size..]` will be updated as well
48+ // which can be computed using the following algorithm.
49+ //
50+
51+ let mut quotient_vec = poly. coeffs [ domain_size..] . to_vec ( ) ;
52+ //println!("poly.len(): {:?}", poly.len());
53+ assert ! ( poly. len( ) / domain_size <= 2 ) ;
54+ for i in 1 ..( poly. len ( ) / domain_size) {
55+ quotient_vec
56+ . iter_mut ( )
57+ . zip ( & poly. coeffs [ domain_size * ( i + 1 ) ..] )
58+ . for_each ( |( s, c) | * s += c * & coeff) ;
59+ }
60+
61+ // Compute the remainder
62+ //
63+ // `remainder = poly - quotient_vec * (x^domain_size - 1)`
64+ //
65+ // Note that remainder must be smaller than `domain_size`.
66+ // So we can look at only the first `domain_size` terms.
67+ //
68+ // Therefore,
69+ // `remainder = poly.coeffs[0..domain_size] - quotient_vec * (-1)`
70+ // i.e.,
71+ // `remainder = poly.coeffs[0..domain_size] + quotient_vec`
72+ //
73+ let mut remainder_vec = poly. coeffs [ 0 ..domain_size] . to_vec ( ) ;
74+ remainder_vec
75+ . iter_mut ( )
76+ . zip ( & quotient_vec)
77+ . for_each ( |( s, c) | * s += c * & coeff) ;
78+
79+ let quotient = DensePolynomial :: from_coefficients_vec ( quotient_vec) ;
80+ let remainder = DensePolynomial :: from_coefficients_vec ( remainder_vec) ;
81+ ( quotient, remainder)
82+ }
83+ }
84+
3285//pub fn precompute_quotient_helpers_alt(
3386// srs: &SRS<Curve>,
3487// domain: EvaluationDomains<ScalarField>,
@@ -564,4 +617,100 @@ mod tests {
564617 ) ;
565618 assert ! ( res, "proof must verify" )
566619 }
620+
621+ #[ test]
622+ fn test_vid_poly_div ( ) {
623+ let mut rng = OsRng ;
624+ let srs = poly_commitment:: precomputed_srs:: get_srs_test :: < Vesta > ( ) ;
625+ let domain: EvaluationDomains < ScalarField > =
626+ EvaluationDomains :: < ScalarField > :: create ( srs. size ( ) ) . unwrap ( ) ;
627+
628+ let data: Vec < ScalarField > = ( 0 ..domain. d2 . size )
629+ . map ( |_| ScalarField :: rand ( & mut rng) )
630+ . collect ( ) ;
631+
632+ let data_eval: Evaluations < ScalarField , R2D < ScalarField > > =
633+ Evaluations :: from_vec_and_domain ( data, domain. d2 ) ;
634+
635+ let verifier_ix = 1 ;
636+ //let per_node_size = 256;
637+ let per_node_size = domain. d1 . size ( ) ;
638+ let proofs_number = domain. d2 . size ( ) / per_node_size;
639+
640+ let indices: Vec < usize > = ( 0 ..per_node_size)
641+ . map ( |j| j * proofs_number + verifier_ix)
642+ . collect ( ) ;
643+
644+ let numerator_eval: Evaluations < ScalarField , R2D < ScalarField > > = {
645+ let mut res = data_eval. clone ( ) ;
646+ for i in indices {
647+ res. evals [ i] = ScalarField :: zero ( ) ;
648+ }
649+ res
650+ } ;
651+
652+ let coset_omega = domain
653+ . d2
654+ . group_gen
655+ . pow ( [ ( verifier_ix * per_node_size) as u64 ] ) ;
656+
657+ // X^per_node_size - w^verifier_ix
658+ let divisor = {
659+ let mut res = DensePolynomial {
660+ coeffs : vec ! [ ScalarField :: zero( ) ; per_node_size + 1 ] ,
661+ } ;
662+ res[ 0 ] = -coset_omega;
663+ //res[0] = -ScalarField::one();
664+ res[ per_node_size] = ScalarField :: one ( ) ;
665+ res
666+ } ;
667+
668+ println ! ( "Numerator eval interpolate" ) ;
669+ let numerator_eval_interpolated = numerator_eval. interpolate ( ) ;
670+
671+ // sanity checking numerator_eval
672+ {
673+ let numerator_1 = DensePolynomial {
674+ coeffs : numerator_eval_interpolated[ ..per_node_size] . to_vec ( ) ,
675+ } ;
676+ let numerator_2 = DensePolynomial {
677+ coeffs : numerator_eval_interpolated[ per_node_size..2 * per_node_size] . to_vec ( ) ,
678+ } ;
679+ let numerator_3 = DensePolynomial {
680+ coeffs : numerator_eval_interpolated[ 2 * per_node_size..] . to_vec ( ) ,
681+ } ;
682+
683+ for zero_point in ( 0 ..per_node_size)
684+ . map ( |i| domain. d2 . group_gen . pow ( [ i as u64 ] ) * coset_omega)
685+ . take ( 15 )
686+ {
687+ assert ! (
688+ numerator_1. evaluate( & zero_point)
689+ + coset_omega * numerator_2. evaluate( & zero_point)
690+ + coset_omega * coset_omega * numerator_3. evaluate( & zero_point)
691+ == ScalarField :: zero( )
692+ ) ;
693+ }
694+ }
695+
696+ println ! ( "Division" ) ;
697+ let ( quot, rem) =
698+ divide_by_sub_vanishing_poly ( & numerator_eval_interpolated, per_node_size, coset_omega) ;
699+
700+ println ! (
701+ "Degree of numerator_eval_interpolated: {:?}" ,
702+ numerator_eval_interpolated. degree( )
703+ ) ;
704+ println ! ( "Degree of divisor: {:?}" , divisor. degree( ) ) ;
705+ println ! ( "Degree of quot: {:?}" , quot. degree( ) ) ;
706+
707+ let error = & ( & quot * & divisor) - & numerator_eval_interpolated;
708+
709+ println ! ( "error degree: {:?}" , error. degree( ) ) ;
710+
711+ assert ! ( & quot * & divisor == numerator_eval_interpolated) ;
712+ assert ! ( & quot * & divisor + & rem == numerator_eval_interpolated) ;
713+ println ! ( "rem degree: {:?}" , rem. degree( ) ) ;
714+ assert ! ( rem. is_zero( ) ) ;
715+ }
567716}
0 commit comments