github.com/incognitochain/go-incognito-sdk@v1.0.1/privacy/zkp/aggregaterange/innerproductargument.go (about) 1 package aggregaterange 2 3 import ( 4 "errors" 5 "github.com/incognitochain/go-incognito-sdk/privacy" 6 "math" 7 ) 8 9 type InnerProductWitness struct { 10 a []*privacy.Scalar 11 b []*privacy.Scalar 12 p *privacy.Point 13 } 14 15 type InnerProductProof struct { 16 l []*privacy.Point 17 r []*privacy.Point 18 a *privacy.Scalar 19 b *privacy.Scalar 20 p *privacy.Point 21 } 22 23 func (proof InnerProductProof) ValidateSanity() bool { 24 if len(proof.l) != len(proof.r) { 25 return false 26 } 27 28 for i := 0; i < len(proof.l); i++ { 29 if !proof.l[i].PointValid() || !proof.r[i].PointValid() { 30 return false 31 } 32 } 33 34 if !proof.a.ScalarValid() || !proof.b.ScalarValid() { 35 return false 36 } 37 38 return proof.p.PointValid() 39 } 40 41 func (proof InnerProductProof) Bytes() []byte { 42 var res []byte 43 44 res = append(res, byte(len(proof.l))) 45 for _, l := range proof.l { 46 res = append(res, l.ToBytesS()...) 47 } 48 49 for _, r := range proof.r { 50 res = append(res, r.ToBytesS()...) 51 } 52 53 res = append(res, proof.a.ToBytesS()...) 54 res = append(res, proof.b.ToBytesS()...) 55 res = append(res, proof.p.ToBytesS()...) 56 57 return res 58 } 59 60 func (proof *InnerProductProof) SetBytes(bytes []byte) error { 61 if len(bytes) == 0 { 62 return nil 63 } 64 65 lenLArray := int(bytes[0]) 66 offset := 1 67 var err error 68 69 proof.l = make([]*privacy.Point, lenLArray) 70 for i := 0; i < lenLArray; i++ { 71 proof.l[i], err = new(privacy.Point).FromBytesS(bytes[offset : offset+privacy.Ed25519KeySize]) 72 if err != nil { 73 return err 74 } 75 offset += privacy.Ed25519KeySize 76 } 77 78 proof.r = make([]*privacy.Point, lenLArray) 79 for i := 0; i < lenLArray; i++ { 80 proof.r[i], err = new(privacy.Point).FromBytesS(bytes[offset : offset+privacy.Ed25519KeySize]) 81 if err != nil { 82 return err 83 } 84 offset += privacy.Ed25519KeySize 85 } 86 87 proof.a = new(privacy.Scalar).FromBytesS(bytes[offset : offset+privacy.Ed25519KeySize]) 88 offset += privacy.Ed25519KeySize 89 90 proof.b = new(privacy.Scalar).FromBytesS(bytes[offset : offset+privacy.Ed25519KeySize]) 91 offset += privacy.Ed25519KeySize 92 93 proof.p, err = new(privacy.Point).FromBytesS(bytes[offset : offset+privacy.Ed25519KeySize]) 94 if err != nil { 95 return err 96 } 97 98 return nil 99 } 100 101 func (wit InnerProductWitness) Prove(aggParam *bulletproofParams) (*InnerProductProof, error) { 102 if len(wit.a) != len(wit.b) { 103 return nil, errors.New("invalid inputs") 104 } 105 106 n := len(wit.a) 107 108 a := make([]*privacy.Scalar, n) 109 b := make([]*privacy.Scalar, n) 110 111 for i := range wit.a { 112 a[i] = new(privacy.Scalar).Set(wit.a[i]) 113 b[i] = new(privacy.Scalar).Set(wit.b[i]) 114 } 115 116 p := new(privacy.Point).Set(wit.p) 117 G := make([]*privacy.Point, n) 118 H := make([]*privacy.Point, n) 119 for i := range G { 120 G[i] = new(privacy.Point).Set(aggParam.g[i]) 121 H[i] = new(privacy.Point).Set(aggParam.h[i]) 122 } 123 124 proof := new(InnerProductProof) 125 proof.l = make([]*privacy.Point, 0) 126 proof.r = make([]*privacy.Point, 0) 127 proof.p = new(privacy.Point).Set(wit.p) 128 129 for n > 1 { 130 nPrime := n / 2 131 132 cL, err := innerProduct(a[:nPrime], b[nPrime:]) 133 if err != nil { 134 return nil, err 135 } 136 137 cR, err := innerProduct(a[nPrime:], b[:nPrime]) 138 if err != nil { 139 return nil, err 140 } 141 142 L, err := encodeVectors(a[:nPrime], b[nPrime:], G[nPrime:], H[:nPrime]) 143 if err != nil { 144 return nil, err 145 } 146 L.Add(L, new(privacy.Point).ScalarMult(aggParam.u, cL)) 147 proof.l = append(proof.l, L) 148 149 R, err := encodeVectors(a[nPrime:], b[:nPrime], G[:nPrime], H[nPrime:]) 150 if err != nil { 151 return nil, err 152 } 153 R.Add(R, new(privacy.Point).ScalarMult(aggParam.u, cR)) 154 proof.r = append(proof.r, R) 155 156 // calculate challenge x = hash(G || H || u || x || l || r) 157 x := generateChallenge([][]byte{aggParam.cs, p.ToBytesS(), L.ToBytesS(), R.ToBytesS()}) 158 //x := generateChallengeOld(aggParam, [][]byte{p.ToBytesS(), L.ToBytesS(), R.ToBytesS()}) 159 xInverse := new(privacy.Scalar).Invert(x) 160 xSquare := new(privacy.Scalar).Mul(x, x) 161 xSquareInverse := new(privacy.Scalar).Mul(xInverse, xInverse) 162 163 // calculate GPrime, HPrime, PPrime for the next loop 164 GPrime := make([]*privacy.Point, nPrime) 165 HPrime := make([]*privacy.Point, nPrime) 166 167 for i := range GPrime { 168 GPrime[i] = new(privacy.Point).AddPedersen(xInverse, G[i], x, G[i+nPrime]) 169 HPrime[i] = new(privacy.Point).AddPedersen(x, H[i], xInverse, H[i+nPrime]) 170 } 171 172 // x^2 * l + P + xInverse^2 * r 173 PPrime := new(privacy.Point).AddPedersen(xSquare, L, xSquareInverse, R) 174 PPrime.Add(PPrime, p) 175 176 // calculate aPrime, bPrime 177 aPrime := make([]*privacy.Scalar, nPrime) 178 bPrime := make([]*privacy.Scalar, nPrime) 179 180 for i := range aPrime { 181 aPrime[i] = new(privacy.Scalar).Mul(a[i], x) 182 aPrime[i] = new(privacy.Scalar).MulAdd(a[i+nPrime], xInverse, aPrime[i]) 183 184 bPrime[i] = new(privacy.Scalar).Mul(b[i], xInverse) 185 bPrime[i] = new(privacy.Scalar).MulAdd(b[i+nPrime], x, bPrime[i]) 186 } 187 188 a = aPrime 189 b = bPrime 190 p.Set(PPrime) 191 G = GPrime 192 H = HPrime 193 n = nPrime 194 } 195 196 proof.a = new(privacy.Scalar).Set(a[0]) 197 proof.b = new(privacy.Scalar).Set(b[0]) 198 199 return proof, nil 200 } 201 202 func (proof InnerProductProof) Verify(aggParam *bulletproofParams) bool { 203 //var aggParam = newBulletproofParams(1) 204 p := new(privacy.Point) 205 p.Set(proof.p) 206 n := len(aggParam.g) 207 G := make([]*privacy.Point, n) 208 H := make([]*privacy.Point, n) 209 s := make([]*privacy.Scalar, n) 210 sInverse := make([]*privacy.Scalar, n) 211 212 for i := range G { 213 G[i] = new(privacy.Point).Set(aggParam.g[i]) 214 H[i] = new(privacy.Point).Set(aggParam.h[i]) 215 s[i] = new(privacy.Scalar).FromUint64(1) 216 sInverse[i] = new(privacy.Scalar).FromUint64(1) 217 } 218 logN := int(math.Log2(float64(n))) 219 xList := make([]*privacy.Scalar, logN) 220 xInverseList := make([]*privacy.Scalar, logN) 221 xSquareList := make([]*privacy.Scalar, logN) 222 xInverseSquare_List := make([]*privacy.Scalar, logN) 223 224 //a*s ; b*s^-1 225 for i := range proof.l { 226 // calculate challenge x = hash(hash(G || H || u || p) || x || l || r) 227 xList[i] = generateChallenge([][]byte{aggParam.cs, p.ToBytesS(), proof.l[i].ToBytesS(), proof.r[i].ToBytesS()}) 228 xInverseList[i] = new(privacy.Scalar).Invert(xList[i]) 229 xSquareList[i] = new(privacy.Scalar).Mul(xList[i], xList[i]) 230 xInverseSquare_List[i] = new(privacy.Scalar).Mul(xInverseList[i], xInverseList[i]) 231 232 //Update s, s^-1 233 for j := 0; j < n; j++ { 234 if j&int(math.Pow(2, float64(logN-i-1))) != 0 { 235 s[j] = new(privacy.Scalar).Mul(s[j], xList[i]) 236 sInverse[j] = new(privacy.Scalar).Mul(sInverse[j], xInverseList[i]) 237 } else { 238 s[j] = new(privacy.Scalar).Mul(s[j], xInverseList[i]) 239 sInverse[j] = new(privacy.Scalar).Mul(sInverse[j], xList[i]) 240 } 241 } 242 PPrime := new(privacy.Point).AddPedersen(xSquareList[i], proof.l[i], xInverseSquare_List[i], proof.r[i]) 243 PPrime.Add(PPrime, p) 244 p = PPrime 245 } 246 247 // Compute (g^s)^a (h^-s)^b u^(ab) = p l^(x^2) r^(-x^2) 248 c := new(privacy.Scalar).Mul(proof.a, proof.b) 249 rightHSPart1 := new(privacy.Point).MultiScalarMult(s, G) 250 rightHSPart1.ScalarMult(rightHSPart1, proof.a) 251 rightHSPart2 := new(privacy.Point).MultiScalarMult(sInverse, H) 252 rightHSPart2.ScalarMult(rightHSPart2, proof.b) 253 rightHS := new(privacy.Point).Add(rightHSPart1, rightHSPart2) 254 rightHS.Add(rightHS, new(privacy.Point).ScalarMult(aggParam.u, c)) 255 256 leftHSPart1 := new(privacy.Point).MultiScalarMult(xSquareList, proof.l) 257 leftHSPart2 := new(privacy.Point).MultiScalarMult(xInverseSquare_List, proof.r) 258 leftHS := new(privacy.Point).Add(leftHSPart1, leftHSPart2) 259 leftHS.Add(leftHS, proof.p) 260 261 res := privacy.IsPointEqual(rightHS, leftHS) 262 if !res { 263 264 } 265 266 return res 267 } 268 269 func VerifyBatchingInnerProductProofs(proofs []*InnerProductProof, csList [][]byte) bool { 270 batchSize := len(proofs) 271 // Generate list of random value 272 sum_abAlpha := new(privacy.Scalar).FromUint64(0) 273 pList := make([]*privacy.Point, 0) 274 alphaList := make([]*privacy.Scalar, 0) 275 LList := make([]*privacy.Point, 0) 276 nXSquareList := make([]*privacy.Scalar, 0) 277 RList := make([]*privacy.Point, 0) 278 nXInverseSquareList := make([]*privacy.Scalar, 0) 279 280 maxN := 0 281 asAlphaList := make([]*privacy.Scalar, len(AggParam.g)) 282 bsInverseAlphaList := make([]*privacy.Scalar, len(AggParam.g)) 283 for k := 0; k < len(AggParam.g); k++ { 284 asAlphaList[k] = new(privacy.Scalar).FromUint64(0) 285 bsInverseAlphaList[k] = new(privacy.Scalar).FromUint64(0) 286 } 287 for i := 0; i < batchSize; i++ { 288 alpha := privacy.RandomScalar() 289 abAlpha := new(privacy.Scalar).Mul(proofs[i].a, proofs[i].b) 290 abAlpha.Mul(abAlpha, alpha) 291 sum_abAlpha.Add(sum_abAlpha, abAlpha) 292 293 //prod_PAlpha.Add(prod_PAlpha, new(privacy.Point).ScalarMult(proofs[i].p,alpha)) 294 pList = append(pList, proofs[i].p) 295 alphaList = append(alphaList, alpha) 296 297 n := int(math.Pow(2, float64(len(proofs[i].l)))) 298 if maxN < n { 299 maxN = n 300 } 301 logN := int(math.Log2(float64(n))) 302 s := make([]*privacy.Scalar, n) 303 sInverse := make([]*privacy.Scalar, n) 304 xList := make([]*privacy.Scalar, logN) 305 xInverseList := make([]*privacy.Scalar, logN) 306 xSquareList := make([]*privacy.Scalar, logN) 307 xSquareAlphaList := make([]*privacy.Scalar, logN) 308 xInverseSquareList := make([]*privacy.Scalar, logN) 309 xInverseSquareAlphaList := make([]*privacy.Scalar, logN) 310 311 for k := 0; k < n; k++ { 312 s[k] = new(privacy.Scalar).Mul(alpha, proofs[i].a) 313 sInverse[k] = new(privacy.Scalar).Mul(alpha, proofs[i].b) 314 } 315 316 p := new(privacy.Point).Set(proofs[i].p) 317 for j := 0; j < len(proofs[i].l); j++ { 318 // calculate challenge x = hash(hash(G || H || u || p) || x || l || r) 319 xList[j] = generateChallenge([][]byte{csList[i], p.ToBytesS(), proofs[i].l[j].ToBytesS(), proofs[i].r[j].ToBytesS()}) 320 xInverseList[j] = new(privacy.Scalar).Invert(xList[j]) 321 xSquareList[j] = new(privacy.Scalar).Mul(xList[j], xList[j]) 322 xSquareAlphaList[j] = new(privacy.Scalar).Mul(xSquareList[j], alpha) 323 xInverseSquareList[j] = new(privacy.Scalar).Mul(xInverseList[j], xInverseList[j]) 324 xInverseSquareAlphaList[j] = new(privacy.Scalar).Mul(xInverseSquareList[j], alpha) 325 326 pPrime := new(privacy.Point).AddPedersen(xSquareList[j], proofs[i].l[j], xInverseSquareList[j], proofs[i].r[j]) 327 pPrime.Add(pPrime, p) 328 p = pPrime 329 330 //Update s, s^-1 331 for k := 0; k < n; k++ { 332 if k&int(math.Pow(2, float64(logN-j-1))) != 0 { 333 s[k] = new(privacy.Scalar).Mul(s[k], xList[j]) 334 sInverse[k] = new(privacy.Scalar).Mul(sInverse[k], xInverseList[j]) 335 } else { 336 s[k] = new(privacy.Scalar).Mul(s[k], xInverseList[j]) 337 sInverse[k] = new(privacy.Scalar).Mul(sInverse[k], xList[j]) 338 } 339 } 340 } 341 for k := 0; k < n; k++ { 342 asAlphaList[k].Add(asAlphaList[k], s[k]) 343 bsInverseAlphaList[k].Add(bsInverseAlphaList[k], sInverse[k]) 344 } 345 346 LList = append(LList, proofs[i].l...) 347 nXSquareList = append(nXSquareList, xSquareAlphaList...) 348 RList = append(RList, proofs[i].r...) 349 nXInverseSquareList = append(nXInverseSquareList, xInverseSquareAlphaList...) 350 } 351 352 gAlphaAS := new(privacy.Point).MultiScalarMult(asAlphaList[0:maxN], AggParam.g[0:maxN]) 353 hAlphaBSInverse := new(privacy.Point).MultiScalarMult(bsInverseAlphaList[0:maxN], AggParam.h[0:maxN]) 354 LHS := new(privacy.Point).Add(gAlphaAS, hAlphaBSInverse) 355 LHS.Add(LHS, new(privacy.Point).ScalarMult(AggParam.u, sum_abAlpha)) 356 //fmt.Println("LHS:", LHS ) 357 358 prod_PAlpha := new(privacy.Point).MultiScalarMult(alphaList, pList) 359 prod_LX := new(privacy.Point).MultiScalarMult(nXSquareList, LList) 360 prod_RX := new(privacy.Point).MultiScalarMult(nXInverseSquareList, RList) 361 362 RHS := new(privacy.Point).Add(prod_LX, prod_RX) 363 RHS.Add(RHS, prod_PAlpha) 364 //fmt.Println("RHS:", RHS) 365 366 res := privacy.IsPointEqual(RHS, LHS) 367 if !res { 368 } 369 370 return res 371 }