github.com/consensys/gnark-crypto@v0.14.0/ecc/bls12-378/fr/fri/fri_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 fri 18 19 import ( 20 "crypto/sha256" 21 "fmt" 22 "math/big" 23 "testing" 24 25 "github.com/consensys/gnark-crypto/ecc/bls12-378/fr" 26 "github.com/leanovate/gopter" 27 "github.com/leanovate/gopter/gen" 28 "github.com/leanovate/gopter/prop" 29 ) 30 31 // logFiber returns u, v such that {g^u, g^v} = f⁻¹((g²)^{_p}) 32 func logFiber(_p, _n int) (_u, _v big.Int) { 33 if _p%2 == 0 { 34 _u.SetInt64(int64(_p / 2)) 35 _v.SetInt64(int64(_p/2 + _n/2)) 36 } else { 37 l := (_n - 1 - _p) / 2 38 _u.SetInt64(int64(_n - 1 - l)) 39 _v.SetInt64(int64(_n - 1 - l - _n/2)) 40 } 41 return 42 } 43 44 func randomPolynomial(size uint64, seed int32) []fr.Element { 45 p := make([]fr.Element, size) 46 p[0].SetUint64(uint64(seed)) 47 for i := 1; i < len(p); i++ { 48 p[i].Square(&p[i-1]) 49 } 50 return p 51 } 52 53 // convertOrderCanonical convert the index i, an entry in a 54 // sorted polynomial, to the corresponding entry in canonical 55 // representation. n is the size of the polynomial. 56 func convertSortedCanonical(i, n int) int { 57 if i%2 == 0 { 58 return i / 2 59 } else { 60 l := (n - 1 - i) / 2 61 return n - 1 - l 62 } 63 } 64 65 func TestFRI(t *testing.T) { 66 67 parameters := gopter.DefaultTestParameters() 68 parameters.MinSuccessfulTests = 10 69 70 properties := gopter.NewProperties(parameters) 71 72 size := 4096 73 74 properties.Property("verifying wrong opening should fail", prop.ForAll( 75 76 func(m int32) bool { 77 78 _s := RADIX_2_FRI.New(uint64(size), sha256.New()) 79 s := _s.(radixTwoFri) 80 81 p := randomPolynomial(uint64(size), m) 82 83 pos := int64(m % 4096) 84 pp, _ := s.BuildProofOfProximity(p) 85 86 openingProof, err := s.Open(p, uint64(pos)) 87 if err != nil { 88 t.Fatal(err) 89 } 90 91 // check the Merkle path 92 tamperedPosition := pos + 1 93 err = s.VerifyOpening(uint64(tamperedPosition), openingProof, pp) 94 95 return err != nil 96 97 }, 98 gen.Int32Range(1, int32(rho*size)), 99 )) 100 101 properties.Property("verifying correct opening should succeed", prop.ForAll( 102 103 func(m int32) bool { 104 105 _s := RADIX_2_FRI.New(uint64(size), sha256.New()) 106 s := _s.(radixTwoFri) 107 108 p := randomPolynomial(uint64(size), m) 109 110 pos := uint64(m % int32(size)) 111 pp, _ := s.BuildProofOfProximity(p) 112 113 openingProof, err := s.Open(p, uint64(pos)) 114 if err != nil { 115 t.Fatal(err) 116 } 117 118 // check the Merkle path 119 err = s.VerifyOpening(uint64(pos), openingProof, pp) 120 121 return err == nil 122 123 }, 124 gen.Int32Range(0, int32(rho*size)), 125 )) 126 127 properties.Property("The claimed value of a polynomial should match P(x)", prop.ForAll( 128 func(m int32) bool { 129 130 _s := RADIX_2_FRI.New(uint64(size), sha256.New()) 131 s := _s.(radixTwoFri) 132 133 p := randomPolynomial(uint64(size), m) 134 135 // check the opening value 136 var g fr.Element 137 pos := int64(m % 4096) 138 g.Set(&s.domain.Generator) 139 g.Exp(g, big.NewInt(pos)) 140 141 var val fr.Element 142 for i := len(p) - 1; i >= 0; i-- { 143 val.Mul(&val, &g) 144 val.Add(&p[i], &val) 145 } 146 147 openingProof, err := s.Open(p, uint64(pos)) 148 if err != nil { 149 t.Fatal(err) 150 } 151 152 return openingProof.ClaimedValue.Equal(&val) 153 154 }, 155 gen.Int32Range(0, int32(rho*size)), 156 )) 157 158 properties.Property("Derive queries position: points should belong the correct fiber", prop.ForAll( 159 160 func(m int32) bool { 161 162 _s := RADIX_2_FRI.New(uint64(size), sha256.New()) 163 s := _s.(radixTwoFri) 164 165 var g fr.Element 166 167 _m := int(m) % size 168 pos := s.deriveQueriesPositions(_m, int(s.domain.Cardinality)) 169 g.Set(&s.domain.Generator) 170 n := int(s.domain.Cardinality) 171 172 for i := 0; i < len(pos)-1; i++ { 173 174 u, v := logFiber(pos[i], n) 175 176 var g1, g2, g3 fr.Element 177 g1.Exp(g, &u).Square(&g1) 178 g2.Exp(g, &v).Square(&g2) 179 nextPos := convertSortedCanonical(pos[i+1], n/2) 180 g3.Square(&g).Exp(g3, big.NewInt(int64(nextPos))) 181 182 if !g1.Equal(&g2) || !g1.Equal(&g3) { 183 return false 184 } 185 g.Square(&g) 186 n = n >> 1 187 } 188 return true 189 }, 190 gen.Int32Range(0, int32(rho*size)), 191 )) 192 193 properties.Property("verifying a correctly formed proof should succeed", prop.ForAll( 194 195 func(s int32) bool { 196 197 p := randomPolynomial(uint64(size), s) 198 199 iop := RADIX_2_FRI.New(uint64(size), sha256.New()) 200 proof, err := iop.BuildProofOfProximity(p) 201 if err != nil { 202 t.Fatal(err) 203 } 204 205 err = iop.VerifyProofOfProximity(proof) 206 return err == nil 207 }, 208 gen.Int32Range(0, int32(rho*size)), 209 )) 210 211 properties.TestingRun(t, gopter.ConsoleReporter(false)) 212 213 } 214 215 // Benchmarks 216 217 func BenchmarkProximityVerification(b *testing.B) { 218 219 baseSize := 16 220 221 for i := 0; i < 10; i++ { 222 223 size := baseSize << i 224 p := make([]fr.Element, size) 225 for k := 0; k < size; k++ { 226 p[k].SetRandom() 227 } 228 229 iop := RADIX_2_FRI.New(uint64(size), sha256.New()) 230 proof, _ := iop.BuildProofOfProximity(p) 231 232 b.Run(fmt.Sprintf("Polynomial size %d", size), func(b *testing.B) { 233 b.ResetTimer() 234 for l := 0; l < b.N; l++ { 235 iop.VerifyProofOfProximity(proof) 236 } 237 }) 238 239 } 240 }