github.com/consensys/gnark-crypto@v0.14.0/ecc/bls12-378/fr/iop/ratios_test.go (about) 1 // Copyright 2020 Consensys Software Inc. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 // Code generated by consensys/gnark-crypto DO NOT EDIT 16 17 package iop 18 19 import ( 20 "testing" 21 22 "github.com/consensys/gnark-crypto/ecc/bls12-378/fr" 23 "github.com/consensys/gnark-crypto/ecc/bls12-378/fr/fft" 24 ) 25 26 // getPermutation returns a deterministic permutation 27 // of n elements where n is even. The result should be 28 // interpreted as 29 // a permutation σ(i)=permutation[i] 30 // g is a generator of ℤ/nℤ 31 func getPermutation(n, g int) []int { 32 33 res := make([]int, n) 34 a := g 35 for i := 0; i < n; i++ { 36 res[i] = a 37 a += g 38 a %= n 39 } 40 return res 41 } 42 43 func getPermutedPolynomials(sizePolynomials, nbPolynomials int) ([]*Polynomial, []*Polynomial, []int) { 44 45 numerator := make([]*Polynomial, nbPolynomials) 46 for i := 0; i < nbPolynomials; i++ { 47 numerator[i] = NewPolynomial(randomVector(sizePolynomials), Form{Basis: Lagrange, Layout: Regular}) 48 } 49 50 // get permutation 51 sigma := getPermutation(sizePolynomials*nbPolynomials, 3) 52 53 // the denominator is the permuted version of the numerators 54 // concatenated 55 denominator := make([]*Polynomial, nbPolynomials) 56 for i := 0; i < nbPolynomials; i++ { 57 denominator[i] = NewPolynomial(randomVector(sizePolynomials), Form{Basis: Lagrange, Layout: Regular}) 58 } 59 for i := 0; i < len(sigma); i++ { 60 id := int(sigma[i] / sizePolynomials) 61 od := sigma[i] % sizePolynomials 62 in := int(i / sizePolynomials) 63 on := i % sizePolynomials 64 denominator[in].Coefficients()[on].Set(&numerator[id].Coefficients()[od]) 65 } 66 67 return numerator, denominator, sigma 68 69 } 70 71 func TestBuildRatioShuffledVectors(t *testing.T) { 72 73 // generate random vectors, interpreted in Lagrange form, 74 // regular layout. It is enough for this test if TestPutInLagrangeForm 75 // passes. 76 sizePolynomials := 8 77 nbPolynomials := 4 78 numerator, denominator, _ := getPermutedPolynomials(sizePolynomials, nbPolynomials) 79 80 // save the originals for further tests with polynomials in different forms 81 backupNumerator := make([]*Polynomial, nbPolynomials) 82 backupDenominator := make([]*Polynomial, nbPolynomials) 83 for i := 0; i < nbPolynomials; i++ { 84 backupNumerator[i] = numerator[i].Clone() 85 backupDenominator[i] = denominator[i].Clone() 86 } 87 88 // build the ratio polynomial 89 expectedForm := Form{Basis: Lagrange, Layout: Regular} 90 domain := fft.NewDomain(uint64(sizePolynomials)) 91 var beta fr.Element 92 beta.SetRandom() 93 ratio, err := BuildRatioShuffledVectors(numerator, denominator, beta, expectedForm, domain) 94 if err != nil { 95 t.Fatal() 96 } 97 98 // check that the whole product is equal to one 99 var a, b, c, d fr.Element 100 b.SetOne() 101 d.SetOne() 102 for i := 0; i < nbPolynomials; i++ { 103 a.Sub(&beta, &numerator[i].Coefficients()[sizePolynomials-1]) 104 b.Mul(&a, &b) 105 c.Sub(&beta, &denominator[i].Coefficients()[sizePolynomials-1]) 106 d.Mul(&c, &d) 107 } 108 a.Mul(&b, &ratio.Coefficients()[sizePolynomials-1]). 109 Div(&a, &d) 110 var one fr.Element 111 one.SetOne() 112 if !a.Equal(&one) { 113 t.Fatal("accumulating ratio is not equal to one") 114 } 115 116 // check that the ratio is correct when the inputs are 117 // bit reversed 118 for i := 0; i < nbPolynomials; i++ { 119 numerator[i] = backupNumerator[i].Clone() 120 fft.BitReverse(numerator[i].Coefficients()) 121 numerator[i].Layout = BitReverse 122 123 denominator[i] = backupDenominator[i].Clone() 124 fft.BitReverse(denominator[i].Coefficients()) 125 denominator[i].Layout = BitReverse 126 } 127 { 128 var err error 129 _ratio, err := BuildRatioShuffledVectors(numerator, denominator, beta, expectedForm, domain) 130 if err != nil { 131 t.Fatal(err) 132 } 133 checkCoeffs := cmpCoefficents(_ratio.coefficients, ratio.coefficients) 134 if !checkCoeffs { 135 t.Fatal(err) 136 } 137 } 138 139 // check that the ratio is correct when the inputs are in 140 // canonical form, regular 141 for i := 0; i < nbPolynomials; i++ { 142 numerator[i] = backupNumerator[i].Clone() 143 domain.FFTInverse(numerator[i].Coefficients(), fft.DIF) 144 fft.BitReverse(numerator[i].Coefficients()) 145 numerator[i].Basis = Canonical 146 147 denominator[i] = backupDenominator[i].Clone() 148 domain.FFTInverse(denominator[i].Coefficients(), fft.DIF) 149 fft.BitReverse(denominator[i].Coefficients()) 150 denominator[i].Basis = Canonical 151 } 152 { 153 var err error 154 _ratio, err := BuildRatioShuffledVectors(numerator, denominator, beta, expectedForm, domain) 155 if err != nil { 156 t.Fatal(err) 157 } 158 checkCoeffs := cmpCoefficents(_ratio.coefficients, ratio.coefficients) 159 if !checkCoeffs { 160 t.Fatal("coefficients of ratio are not consistent") 161 } 162 } 163 164 // check that the ratio is correct when the inputs are in 165 // canonical form, bit reverse 166 for i := 0; i < nbPolynomials; i++ { 167 numerator[i] = backupNumerator[i].Clone() 168 domain.FFTInverse(numerator[i].Coefficients(), fft.DIF) 169 numerator[i].Layout = BitReverse 170 numerator[i].Basis = Canonical 171 172 denominator[i] = backupDenominator[i].Clone() 173 domain.FFTInverse(denominator[i].Coefficients(), fft.DIF) 174 denominator[i].Layout = BitReverse 175 denominator[i].Basis = Canonical 176 } 177 { 178 var err error 179 _ratio, err := BuildRatioShuffledVectors(numerator, denominator, beta, expectedForm, domain) 180 if err != nil { 181 t.Fatal(err) 182 } 183 checkCoeffs := cmpCoefficents(_ratio.coefficients, ratio.coefficients) 184 if !checkCoeffs { 185 t.Fatal("coefficients of ratio are not consistent") 186 } 187 } 188 189 } 190 191 // sizePolynomial*nbPolynomial must be divisible by 2. 192 // The function generates a list of nbPolynomials (P_i) of size n=sizePolynomials 193 // such that [P₁ ∥ .. ∥ P₂ ] is invariant under the permutation 194 // σ defined by: 195 // σ = (12)(34)..(2n-1 2n) 196 // so σ is a product of cycles length 2. 197 func getInvariantEntriesUnderPermutation(sizePolynomials, nbPolynomials int) ([]*Polynomial, []int64) { 198 res := make([]*Polynomial, nbPolynomials) 199 form := Form{Layout: Regular, Basis: Lagrange} 200 for i := 0; i < nbPolynomials; i++ { 201 v := make([]fr.Element, sizePolynomials) 202 res[i] = NewPolynomial(&v, form) 203 for j := 0; j < sizePolynomials/2; j++ { 204 res[i].Coefficients()[2*j].SetRandom() 205 res[i].Coefficients()[2*j+1].Set(&res[i].Coefficients()[2*j]) 206 } 207 } 208 permutation := make([]int64, nbPolynomials*sizePolynomials) 209 for i := int64(0); i < int64(nbPolynomials*sizePolynomials/2); i++ { 210 permutation[2*i] = 2*i + 1 211 permutation[2*i+1] = 2 * i 212 } 213 return res, permutation 214 } 215 216 func TestBuildRatioCopyConstraint(t *testing.T) { 217 218 // generate random vectors, interpreted in Lagrange form, 219 // regular layout. It is enough for this test if TestPutInLagrangeForm 220 // passes. 221 sizePolynomials := 8 222 nbPolynomials := 4 223 entries, sigma := getInvariantEntriesUnderPermutation(sizePolynomials, nbPolynomials) 224 225 // save the originals for further tests with polynomials in different forms 226 backupEntries := make([]*Polynomial, nbPolynomials) 227 for i := 0; i < nbPolynomials; i++ { 228 backupEntries[i] = entries[i].Clone() 229 } 230 231 // build the ratio polynomial 232 expectedForm := Form{Basis: Lagrange, Layout: Regular} 233 domain := fft.NewDomain(uint64(sizePolynomials)) 234 var beta, gamma fr.Element 235 beta.SetRandom() 236 gamma.SetRandom() 237 ratio, err := BuildRatioCopyConstraint(entries, sigma, beta, gamma, expectedForm, domain) 238 if err != nil { 239 t.Fatal() 240 } 241 242 // check that the whole product is equal to one 243 suppID := getSupportIdentityPermutation(nbPolynomials, domain) 244 var a, b, c, d fr.Element 245 b.SetOne() 246 d.SetOne() 247 for i := 0; i < nbPolynomials; i++ { 248 a.Mul(&beta, &suppID[(i+1)*sizePolynomials-1]). 249 Add(&a, &entries[i].Coefficients()[sizePolynomials-1]). 250 Add(&a, &gamma) 251 b.Mul(&b, &a) 252 253 c.Mul(&beta, &suppID[sigma[(i+1)*sizePolynomials-1]]). 254 Add(&c, &entries[i].Coefficients()[sizePolynomials-1]). 255 Add(&c, &gamma) 256 d.Mul(&d, &c) 257 } 258 a.Mul(&b, &ratio.Coefficients()[sizePolynomials-1]). 259 Div(&a, &d) 260 var one fr.Element 261 one.SetOne() 262 if !a.Equal(&one) { 263 t.Fatal("accumulating ratio is not equal to one") 264 } 265 266 // check that the ratio is correct when the inputs are 267 // bit reversed 268 for i := 0; i < nbPolynomials; i++ { 269 entries[i] = backupEntries[i].Clone() 270 fft.BitReverse(entries[i].Coefficients()) 271 entries[i].Layout = BitReverse 272 } 273 { 274 var err error 275 _ratio, err := BuildRatioCopyConstraint(entries, sigma, beta, gamma, expectedForm, domain) 276 if err != nil { 277 t.Fatal(err) 278 } 279 checkCoeffs := cmpCoefficents(_ratio.coefficients, ratio.coefficients) 280 if !checkCoeffs { 281 t.Fatal(err) 282 } 283 } 284 285 // check that the ratio is correct when the inputs are in 286 // canonical form, regular 287 for i := 0; i < nbPolynomials; i++ { 288 entries[i] = backupEntries[i].Clone() 289 domain.FFTInverse(entries[i].Coefficients(), fft.DIF) 290 fft.BitReverse(entries[i].Coefficients()) 291 entries[i].Layout = Regular 292 entries[i].Basis = Canonical 293 } 294 { 295 var err error 296 _ratio, err := BuildRatioCopyConstraint(entries, sigma, beta, gamma, expectedForm, domain) 297 if err != nil { 298 t.Fatal(err) 299 } 300 checkCoeffs := cmpCoefficents(_ratio.coefficients, ratio.coefficients) 301 if !checkCoeffs { 302 t.Fatal("coefficients of ratio are not consistent") 303 } 304 } 305 306 // check that the ratio is correct when the inputs are in 307 // canonical form, bit reverse 308 for i := 0; i < nbPolynomials; i++ { 309 entries[i] = backupEntries[i].Clone() 310 domain.FFTInverse(entries[i].Coefficients(), fft.DIF) 311 entries[i].Layout = BitReverse 312 entries[i].Basis = Canonical 313 } 314 315 { 316 var err error 317 _ratio, err := BuildRatioCopyConstraint(entries, sigma, beta, gamma, expectedForm, domain) 318 if err != nil { 319 t.Fatal(err) 320 } 321 checkCoeffs := cmpCoefficents(_ratio.coefficients, ratio.coefficients) 322 if !checkCoeffs { 323 t.Fatal("coefficients of ratio are not consistent") 324 } 325 } 326 }