github.com/jiajun1992/watercarver@v0.0.0-20191031150618-dfc2b17c0c4a/go-ethereum/ctcrypto/crypto/ringct/bulletproof_regulation.go (about) 1 package ringct 2 3 import ( 4 "bytes" 5 "fmt" 6 7 "github.com/ethereum/go-ethereum/ctcrypto/crypto" 8 ) 9 10 func GenRegulationParaForBulletproof() (sL, sR *[64]crypto.Key, rho *crypto.Key, S *crypto.Key) { 11 var sLTemp, sRTemp [64]crypto.Key 12 var STemp crypto.Key 13 for i := range sL { 14 sLTemp[i] = crypto.SkGen() 15 sRTemp[i] = crypto.SkGen() 16 } 17 sL = &sLTemp 18 sR = &sRTemp 19 rhoTemp := crypto.SkGen() 20 rho = &rhoTemp 21 ve := vector_exponent(sL[:], sR[:]) 22 rho_base_tmp := crypto.ScalarmultBase(*rho) 23 crypto.AddKeys(&STemp, &ve, &rho_base_tmp) 24 S = &STemp 25 return 26 } 27 28 func GenRegulationParaForBulletproof2(num uint32) (sL, sR []crypto.Key, rho *crypto.Key, S *crypto.Key) { 29 var M, logM int 30 for { 31 M = 1 << uint(logM) 32 if M <= maxM && M < int(num) { 33 logM++ 34 } else { 35 break 36 } 37 } 38 vlen := M * 64 39 sLTemp := make([]crypto.Key, vlen) 40 sRTemp := make([]crypto.Key, vlen) 41 var STemp crypto.Key 42 for i := range sLTemp { 43 sLTemp[i] = crypto.SkGen() 44 sRTemp[i] = crypto.SkGen() 45 } 46 sL = sLTemp 47 sR = sRTemp 48 rhoTemp := crypto.SkGen() 49 rho = &rhoTemp 50 ve := vector_exponent(sL[:], sR[:]) 51 rho_base_tmp := crypto.ScalarmultBase(*rho) 52 crypto.AddKeys(&STemp, &ve, &rho_base_tmp) 53 S = &STemp 54 return 55 } 56 57 //ProveRangeBulletproofWithRegulation is a bulletproof with regulation 58 func ProveRangeBulletproofWithRegulation(C *crypto.Key, mask *crypto.Key, amount uint64, sL, sR *[64]crypto.Key, rho *crypto.Key) BulletProof { 59 tmpmask := crypto.SkGen() 60 copy(mask[:], tmpmask[:]) 61 proof := BULLETPROOF_Prove_Amount_WithRegulation(amount, mask, sL, sR, rho) 62 if len(proof.V) != 1 { 63 panic(fmt.Sprintf("V has not exactly one element")) 64 } 65 copy(C[:], proof.V[0][:]) //C = proof.V[0]; 66 return *proof 67 } 68 69 //BULLETPROOF_Prove_Amount_WithRegulation proves an amount with regulation 70 func BULLETPROOF_Prove_Amount_WithRegulation(v uint64, gamma *crypto.Key, sL, sR *[64]crypto.Key, rho *crypto.Key) *BulletProof { 71 sv := crypto.Zero 72 73 sv[0] = byte(v & 255) 74 sv[1] = byte((v >> 8) & 255) 75 sv[2] = byte((v >> 16) & 255) 76 sv[3] = byte((v >> 24) & 255) 77 sv[4] = byte((v >> 32) & 255) 78 sv[5] = byte((v >> 40) & 255) 79 sv[6] = byte((v >> 48) & 255) 80 sv[7] = byte((v >> 56) & 255) 81 82 return BULLETPROOF_Prove_WithRegulation(&sv, gamma, sL, sR, rho) 83 } 84 85 //BULLETPROOF_Prove_WithRegulation : Given a value v (0..2^N-1) and a mask gamma, construct a range proof 86 func BULLETPROOF_Prove_WithRegulation(sv *crypto.Key, gamma *crypto.Key, sL, sR *[64]crypto.Key, rho *crypto.Key) *BulletProof { 87 const logN = int(6) // log2(64) 88 const N = int(64) // 1 << logN 89 90 var V crypto.Key 91 var aL, aR [N]crypto.Key 92 var A, S crypto.Key 93 94 // prove V 95 crypto.AddKeys2(&V, gamma, sv, &crypto.H) 96 97 // prove aL,aR 98 // the entire amount in uint64 is extracted into bits and 99 // different action taken if bit is zero or bit is one 100 for i := N - 1; i >= 0; i-- { 101 if (sv[i/8] & (1 << (uint64(i) % 8))) >= 1 { 102 aL[i] = crypto.Identity 103 } else { 104 aL[i] = crypto.Zero 105 } 106 crypto.ScSub(&aR[i], &aL[i], &crypto.Identity) 107 } 108 109 hashcache := *(crypto.HashToScalar(V[:])) 110 111 // prove STEP 1 112 113 // PAPER LINES 38-39 114 alpha := crypto.SkGen() 115 ve := vector_exponent(aL[:], aR[:]) 116 117 alpha_base_tmp := crypto.ScalarmultBase(alpha) 118 crypto.AddKeys(&A, &ve, &alpha_base_tmp) 119 120 // PAPER LINES 40-42 121 // var sL, sR [N]crypto.Key 122 // for i := range sL { 123 // sL[i] = crypto.SkGen() 124 // sR[i] = crypto.SkGen() 125 // } 126 // //rct::keyV sL = rct::skvGen(N), sR = rct::skvGen(N); 127 // rho := crypto.SkGen() 128 ve = vector_exponent(sL[:], sR[:]) 129 rho_base_tmp := crypto.ScalarmultBase(*rho) 130 crypto.AddKeys(&S, &ve, &rho_base_tmp) 131 132 // PAPER LINES 43-45 133 y := hash_cache_mash2(&hashcache, A, S) // rct::key y = hash_cache_mash(hash_cache, A, S); 134 hashcache = *(crypto.HashToScalar(y[:])) // rct::key z = hash_cache = rct::hash_to_scalar(y); 135 z := hashcache 136 137 // Polynomial construction before PAPER LINE 46 138 t0 := crypto.Zero // rct::key t0 = rct::zero(); 139 t1 := crypto.Zero // rct::key t1 = rct::zero(); 140 t2 := crypto.Zero // rct::key t2 = rct::zero(); 141 142 yN := vector_powers(y, int64(N)) // const auto yN = vector_powers(y, N); 143 144 ip1y := inner_product(oneN, yN) //rct::key ip1y = inner_product(oneN, yN); 145 crypto.ScMulAdd(&t0, &z, &ip1y, &t0) // sc_muladd(t0.bytes, z.bytes, ip1y.bytes, t0.bytes); 146 147 var zsq crypto.Key //rct::key zsq; 148 crypto.ScMul(&zsq, &z, &z) // sc_mul(zsq.bytes, z.bytes, z.bytes); 149 crypto.ScMulAdd(&t0, &zsq, sv, &t0) // sc_muladd(t0.bytes, zsq.bytes, sv.bytes, t0.bytes); 150 151 k := crypto.Zero // rct::key k = rct::zero(); 152 crypto.ScMulSub(&k, &zsq, &ip1y, &k) //sc_mulsub(k.bytes, zsq.bytes, ip1y.bytes, k.bytes); 153 154 var zcu crypto.Key // rct::key zcu; 155 crypto.ScMul(&zcu, &zsq, &z) //sc_mul(zcu.bytes, zsq.bytes, z.bytes); 156 crypto.ScMulSub(&k, &zcu, &ip12, &k) //sc_mulsub(k.bytes, zcu.bytes, ip12.bytes, k.bytes); 157 crypto.ScAdd(&t0, &t0, &k) //sc_add(t0.bytes, t0.bytes, k.bytes); 158 159 if DEBUGGING_MODE { // verify intermediate variables for correctness 160 test_t0 := crypto.Zero //rct::key test_t0 = rct::zero(); 161 iph := inner_product(aL[:], hadamard(aR[:], yN)) // rct::key iph = inner_product(aL, hadamard(aR, yN)); 162 crypto.ScAdd(&test_t0, &test_t0, &iph) //sc_add(test_t0.bytes, test_t0.bytes, iph.bytes); 163 ips := inner_product(vector_subtract(aL[:], aR[:]), yN) //rct::key ips = inner_product(vector_subtract(aL, aR), yN); 164 crypto.ScMulAdd(&test_t0, &z, &ips, &test_t0) // sc_muladd(test_t0.bytes, z.bytes, ips.bytes, test_t0.bytes); 165 ipt := inner_product(twoN, aL[:]) // rct::key ipt = inner_product(twoN, aL); 166 crypto.ScMulAdd(&test_t0, &zsq, &ipt, &test_t0) // sc_muladd(test_t0.bytes, zsq.bytes, ipt.bytes, test_t0.bytes); 167 crypto.ScAdd(&test_t0, &test_t0, &k) // sc_add(test_t0.bytes, test_t0.bytes, k.bytes); 168 169 //CHECK_AND_ASSERT_THROW_MES(t0 == test_t0, "t0 check failed"); 170 if t0 != test_t0 { 171 panic("t0 check failed") 172 } 173 174 //fmt.Printf("t0 %s\ntest_t0 %s\n",t0,test_t0) 175 176 } 177 178 // STEP 1 complete above 179 180 // STEP 2 starts 181 182 HyNsR := hadamard(yN, sR[:]) // const auto HyNsR = hadamard(yN, sR); 183 vpIz := vector_scalar(oneN, z) // const auto vpIz = vector_scalar(oneN, z); 184 vp2zsq := vector_scalar(twoN, zsq) // const auto vp2zsq = vector_scalar(twoN, zsq); 185 aL_vpIz := vector_subtract(aL[:], vpIz) // const auto aL_vpIz = vector_subtract(aL, vpIz); 186 aR_vpIz := vector_add(aR[:], vpIz) //const auto aR_vpIz = vector_add(aR, vpIz); 187 188 ip1 := inner_product(aL_vpIz, HyNsR) // rct::key ip1 = inner_product(aL_vpIz, HyNsR); 189 crypto.ScAdd(&t1, &t1, &ip1) // sc_add(t1.bytes, t1.bytes, ip1.bytes); 190 191 ip2 := inner_product(sL[:], vector_add(hadamard(yN, aR_vpIz), vp2zsq)) // rct::key ip2 = inner_product(sL, vector_add(hadamard(yN, aR_vpIz), vp2zsq)); 192 crypto.ScAdd(&t1, &t1, &ip2) // sc_add(t1.bytes, t1.bytes, ip2.bytes); 193 194 ip3 := inner_product(sL[:], HyNsR) // rct::key ip3 = inner_product(sL, HyNsR); 195 crypto.ScAdd(&t2, &t2, &ip3) //sc_add(t2.bytes, t2.bytes, ip3.bytes); 196 197 // PAPER LINES 47-48 198 tau1 := crypto.SkGen() // rct::key tau1 = rct::skGen(), tau2 = rct::skGen(); 199 tau2 := crypto.SkGen() 200 201 // rct::key T1 = rct::addKeys(rct::scalarmultKey(rct::H, t1), rct::scalarmultBase(tau1)); 202 tau1_base := crypto.ScalarmultBase(tau1) 203 T1 := AddKeys_return(crypto.ScalarMultKey(&crypto.H, &t1), &tau1_base) 204 205 //rct::key T2 = rct::addKeys(rct::scalarmultKey(rct::H, t2), rct::scalarmultBase(tau2)); 206 tau2_base := crypto.ScalarmultBase(tau2) 207 T2 := AddKeys_return(crypto.ScalarMultKey(&crypto.H, &t2), &tau2_base) 208 209 // PAPER LINES 49-51 210 x := hash_cache_mash3(&hashcache, z, T1, T2) //rct::key x = hash_cache_mash(hash_cache, z, T1, T2); 211 212 // PAPER LINES 52-53 213 taux := crypto.Zero // rct::key taux = rct::zero(); 214 crypto.ScMul(&taux, &tau1, &x) //sc_mul(taux.bytes, tau1.bytes, x.bytes); 215 var xsq crypto.Key //rct::key xsq; 216 crypto.ScMul(&xsq, &x, &x) //sc_mul(xsq.bytes, x.bytes, x.bytes); 217 crypto.ScMulAdd(&taux, &tau2, &xsq, &taux) // sc_muladd(taux.bytes, tau2.bytes, xsq.bytes, taux.bytes); 218 crypto.ScMulAdd(&taux, gamma, &zsq, &taux) //sc_muladd(taux.bytes, gamma.bytes, zsq.bytes, taux.bytes); 219 220 var mu crypto.Key //rct::key mu; 221 crypto.ScMulAdd(&mu, &x, rho, &alpha) //sc_muladd(mu.bytes, x.bytes, rho.bytes, alpha.bytes); 222 223 // PAPER LINES 54-57 224 l := vector_add(aL_vpIz, vector_scalar(sL[:], x)) //rct::keyV l = vector_add(aL_vpIz, vector_scalar(sL, x)); 225 r := vector_add(hadamard(yN, vector_add(aR_vpIz, vector_scalar(sR[:], x))), vp2zsq) // rct::keyV r = vector_add(hadamard(yN, vector_add(aR_vpIz, vector_scalar(sR, x))), vp2zsq); 226 227 // STEP 2 complete 228 229 // STEP 3 starts 230 t := inner_product(l, r) //rct::key t = inner_product(l, r); 231 232 //DEBUG: Test if the l and r vectors match the polynomial forms 233 if DEBUGGING_MODE { 234 var test_t crypto.Key 235 236 crypto.ScMulAdd(&test_t, &t1, &x, &t0) // sc_muladd(test_t.bytes, t1.bytes, x.bytes, t0.bytes); 237 crypto.ScMulAdd(&test_t, &t2, &xsq, &test_t) //sc_muladd(test_t.bytes, t2.bytes, xsq.bytes, test_t.bytes); 238 239 if test_t != t { 240 //panic("test_t check failed") 241 } 242 243 //fmt.Printf("t %s\ntest_t %s\n",t,test_t) 244 } 245 246 // PAPER LINES 32-33 247 x_ip := hash_cache_mash4(&hashcache, x, taux, mu, t) //rct::key x_ip = hash_cache_mash(hash_cache, x, taux, mu, t); 248 249 // These are used in the inner product rounds 250 // declared in step 4 //size_t nprime = N; 251 var Gprime, Hprime, aprime, bprime []crypto.Key 252 Gprime = make([]crypto.Key, N, N) //rct::keyV Gprime(N); 253 Hprime = make([]crypto.Key, N, N) //rct::keyV Hprime(N); 254 aprime = make([]crypto.Key, N, N) // rct::keyV aprime(N); 255 bprime = make([]crypto.Key, N, N) //rct::keyV bprime(N); 256 257 yinv := invert_scalar(y) //const rct::key yinv = invert(y); 258 yinvpow := crypto.Identity // rct::key yinvpow = rct::identity(); 259 260 for i := 0; i < N; i++ { ///for (size_t i = 0; i < N; ++i) 261 Gprime[i] = Gi[i] // Gprime[i] = Gi[i]; 262 Hprime[i] = *(crypto.ScalarMultKey(&Hi[i], &yinvpow)) //Hprime[i] = scalarmultKey(Hi[i], yinvpow); 263 crypto.ScMul(&yinvpow, &yinvpow, &yinv) //sc_mul(yinvpow.bytes, yinvpow.bytes, yinv.bytes); 264 265 aprime[i] = l[i] // aprime[i] = l[i]; 266 bprime[i] = r[i] // bprime[i] = r[i]; 267 } 268 269 // STEP 3 complete 270 271 // STEP 4 starts 272 round := 0 273 nprime := N 274 //var L,R,w [logN]crypto.Key // w is the challenge x in the inner product protocol 275 L := make([]crypto.Key, logN, logN) 276 R := make([]crypto.Key, logN, logN) 277 w := make([]crypto.Key, logN, logN) 278 var tmp crypto.Key 279 280 // PAPER LINE 13 281 for nprime > 1 { // while (nprime > 1) 282 // PAPER LINE 15 283 nprime /= 2 // nprime /= 2; 284 285 // PAPER LINES 16-17 286 cL := inner_product(slice_vector(aprime[:], 0, nprime), slice_vector(bprime[:], nprime, len(bprime))) // rct::key cL = inner_product(slice(aprime, 0, nprime), slice(bprime, nprime, bprime.size())); 287 cR := inner_product(slice_vector(aprime[:], nprime, len(aprime)), slice_vector(bprime[:], 0, nprime)) // rct::key cR = inner_product(slice(aprime, nprime, aprime.size()), slice(bprime, 0, nprime)); 288 289 // PAPER LINES 18-19 290 //L[round] = vector_exponent_custom(slice(Gprime, nprime, Gprime.size()), slice(Hprime, 0, nprime), slice(aprime, 0, nprime), slice(bprime, nprime, bprime.size())); 291 292 L[round] = vector_exponent_custom(slice_vector(Gprime[:], nprime, len(Gprime)), slice_vector(Hprime[:], 0, nprime), slice_vector(aprime[:], 0, nprime), slice_vector(bprime[:], nprime, len(bprime))) 293 crypto.ScMul(&tmp, &cL, &x_ip) // sc_mul(tmp.bytes, cL.bytes, x_ip.bytes); 294 crypto.AddKeys(&L[round], &L[round], crypto.ScalarMultKey(&crypto.H, &tmp)) //rct::addKeys(L[round], L[round], rct::scalarmultKey(rct::H, tmp)); 295 //R[round] = vector_exponent_custom(slice(Gprime, 0, nprime), slice(Hprime, nprime, Hprime.size()), slice(aprime, nprime, aprime.size()), slice(bprime, 0, nprime)); 296 R[round] = vector_exponent_custom(slice_vector(Gprime[:], 0, nprime), slice_vector(Hprime[:], nprime, len(Hprime)), slice_vector(aprime[:], nprime, len(aprime)), slice_vector(bprime[:], 0, nprime)) 297 crypto.ScMul(&tmp, &cR, &x_ip) // sc_mul(tmp.bytes, cR.bytes, x_ip.bytes); 298 crypto.AddKeys(&R[round], &R[round], crypto.ScalarMultKey(&crypto.H, &tmp)) // rct::addKeys(R[round], R[round], rct::scalarmultKey(rct::H, tmp)); 299 300 // PAPER LINES 21-22 301 w[round] = hash_cache_mash2(&hashcache, L[round], R[round]) // w[round] = hash_cache_mash(hash_cache, L[round], R[round]); 302 303 // PAPER LINES 24-25 304 winv := invert_scalar(w[round]) //const rct::key winv = invert(w[round]); 305 //Gprime = hadamard2(vector_scalar2(slice(Gprime, 0, nprime), winv), vector_scalar2(slice(Gprime, nprime, Gprime.size()), w[round])); 306 Gprime = hadamard2(vector_scalar2(slice_vector(Gprime[:], 0, nprime), winv), vector_scalar2(slice_vector(Gprime[:], nprime, len(Gprime)), w[round])) 307 308 //Hprime = hadamard2(vector_scalar2(slice(Hprime, 0, nprime), w[round]), vector_scalar2(slice(Hprime, nprime, Hprime.size()), winv)); 309 Hprime = hadamard2(vector_scalar2(slice_vector(Hprime[:], 0, nprime), w[round]), vector_scalar2(slice_vector(Hprime[:], nprime, len(Hprime)), winv)) 310 311 // PAPER LINES 28-29 312 //aprime = vector_add(vector_scalar(slice(aprime, 0, nprime), w[round]), vector_scalar(slice(aprime, nprime, aprime.size()), winv)); 313 aprime = vector_add(vector_scalar(slice_vector(aprime[:], 0, nprime), w[round]), vector_scalar(slice_vector(aprime[:], nprime, len(aprime)), winv)) 314 315 //bprime = vector_add(vector_scalar(slice(bprime, 0, nprime), winv), vector_scalar(slice(bprime, nprime, bprime.size()), w[round])); 316 bprime = vector_add(vector_scalar(slice_vector(bprime[:], 0, nprime), winv), vector_scalar(slice_vector(bprime[:], nprime, len(bprime)), w[round])) 317 318 round++ 319 320 } 321 return &BulletProof{ 322 V: []crypto.Key{V}, 323 A: A, 324 S: S, 325 T1: T1, 326 T2: T2, 327 taux: taux, 328 mu: mu, 329 L: L, 330 R: R, 331 a: aprime[0], 332 b: bprime[0], 333 t: t, 334 } 335 } 336 337 //BULLETPROOF_Prove_Amount_WithRegulation proves an amount with regulation 338 func BULLETPROOF_Prove_Amount_WithRegulation_Raw(v uint64, gamma *crypto.Key, sL, sR *[64]crypto.Key, rho *crypto.Key) *BulletProof { 339 sv := crypto.Zero 340 341 sv[0] = byte(v & 255) 342 sv[1] = byte((v >> 8) & 255) 343 sv[2] = byte((v >> 16) & 255) 344 sv[3] = byte((v >> 24) & 255) 345 sv[4] = byte((v >> 32) & 255) 346 sv[5] = byte((v >> 40) & 255) 347 sv[6] = byte((v >> 48) & 255) 348 sv[7] = byte((v >> 56) & 255) 349 350 return BULLETPROOF_Prove_WithRegulation_Raw(&sv, gamma, sL, sR, rho) 351 } 352 353 //BULLETPROOF_Prove_WithRegulation : Given a value v (0..2^N-1) and a mask gamma, construct a range proof 354 func BULLETPROOF_Prove_WithRegulation_Raw(sv *crypto.Key, gamma *crypto.Key, sL, sR *[64]crypto.Key, rho *crypto.Key) *BulletProof { 355 const logN = int(6) // log2(64) 356 const N = int(64) // 1 << logN 357 358 var V crypto.Key 359 var aL, aR [N]crypto.Key 360 var A, S crypto.Key 361 362 // prove V 363 crypto.AddKeys2(&V, gamma, sv, &crypto.H) 364 365 // prove aL,aR 366 // the entire amount in uint64 is extracted into bits and 367 // different action taken if bit is zero or bit is one 368 for i := N - 1; i >= 0; i-- { 369 if (sv[i/8] & (1 << (uint64(i) % 8))) >= 1 { 370 aL[i] = crypto.Identity 371 } else { 372 aL[i] = crypto.Zero 373 } 374 crypto.ScSub(&aR[i], &aL[i], &crypto.Identity) 375 } 376 377 hashcache := *(crypto.HashToScalar(V[:])) 378 379 // prove STEP 1 380 381 // PAPER LINES 38-39 382 alpha := crypto.SkGen() 383 ve := vector_exponent(aL[:], aR[:]) 384 385 alpha_base_tmp := crypto.ScalarmultBase(alpha) 386 crypto.AddKeys(&A, &ve, &alpha_base_tmp) 387 388 // PAPER LINES 40-42 389 // var sL, sR [N]crypto.Key 390 // for i := range sL { 391 // sL[i] = crypto.SkGen() 392 // sR[i] = crypto.SkGen() 393 // } 394 // //rct::keyV sL = rct::skvGen(N), sR = rct::skvGen(N); 395 // rho := crypto.SkGen() 396 ve = vector_exponent(sL[:], sR[:]) 397 rho_base_tmp := crypto.ScalarmultBase(*rho) 398 crypto.AddKeys(&S, &ve, &rho_base_tmp) 399 400 // PAPER LINES 43-45 401 y := hash_cache_mash2(&hashcache, A, S) // rct::key y = hash_cache_mash(hash_cache, A, S); 402 hashcache = *(crypto.HashToScalar(y[:])) // rct::key z = hash_cache = rct::hash_to_scalar(y); 403 z := hashcache 404 405 // Polynomial construction before PAPER LINE 46 406 t0 := crypto.Zero // rct::key t0 = rct::zero(); 407 t1 := crypto.Zero // rct::key t1 = rct::zero(); 408 t2 := crypto.Zero // rct::key t2 = rct::zero(); 409 410 yN := vector_powers(y, int64(N)) // const auto yN = vector_powers(y, N); 411 412 ip1y := inner_product(oneN, yN) //rct::key ip1y = inner_product(oneN, yN); 413 crypto.ScMulAdd(&t0, &z, &ip1y, &t0) // sc_muladd(t0.bytes, z.bytes, ip1y.bytes, t0.bytes); 414 415 var zsq crypto.Key //rct::key zsq; 416 crypto.ScMul(&zsq, &z, &z) // sc_mul(zsq.bytes, z.bytes, z.bytes); 417 crypto.ScMulAdd(&t0, &zsq, sv, &t0) // sc_muladd(t0.bytes, zsq.bytes, sv.bytes, t0.bytes); 418 419 k := crypto.Zero // rct::key k = rct::zero(); 420 crypto.ScMulSub(&k, &zsq, &ip1y, &k) //sc_mulsub(k.bytes, zsq.bytes, ip1y.bytes, k.bytes); 421 422 var zcu crypto.Key // rct::key zcu; 423 crypto.ScMul(&zcu, &zsq, &z) //sc_mul(zcu.bytes, zsq.bytes, z.bytes); 424 crypto.ScMulSub(&k, &zcu, &ip12, &k) //sc_mulsub(k.bytes, zcu.bytes, ip12.bytes, k.bytes); 425 crypto.ScAdd(&t0, &t0, &k) //sc_add(t0.bytes, t0.bytes, k.bytes); 426 427 if DEBUGGING_MODE { // verify intermediate variables for correctness 428 test_t0 := crypto.Zero //rct::key test_t0 = rct::zero(); 429 iph := inner_product(aL[:], hadamard(aR[:], yN)) // rct::key iph = inner_product(aL, hadamard(aR, yN)); 430 crypto.ScAdd(&test_t0, &test_t0, &iph) //sc_add(test_t0.bytes, test_t0.bytes, iph.bytes); 431 ips := inner_product(vector_subtract(aL[:], aR[:]), yN) //rct::key ips = inner_product(vector_subtract(aL, aR), yN); 432 crypto.ScMulAdd(&test_t0, &z, &ips, &test_t0) // sc_muladd(test_t0.bytes, z.bytes, ips.bytes, test_t0.bytes); 433 ipt := inner_product(twoN, aL[:]) // rct::key ipt = inner_product(twoN, aL); 434 crypto.ScMulAdd(&test_t0, &zsq, &ipt, &test_t0) // sc_muladd(test_t0.bytes, zsq.bytes, ipt.bytes, test_t0.bytes); 435 crypto.ScAdd(&test_t0, &test_t0, &k) // sc_add(test_t0.bytes, test_t0.bytes, k.bytes); 436 437 //CHECK_AND_ASSERT_THROW_MES(t0 == test_t0, "t0 check failed"); 438 if t0 != test_t0 { 439 panic("t0 check failed") 440 } 441 442 //fmt.Printf("t0 %s\ntest_t0 %s\n",t0,test_t0) 443 444 } 445 446 // STEP 1 complete above 447 448 // STEP 2 starts 449 450 HyNsR := hadamard(yN, sR[:]) // const auto HyNsR = hadamard(yN, sR); 451 vpIz := vector_scalar(oneN, z) // const auto vpIz = vector_scalar(oneN, z); 452 vp2zsq := vector_scalar(twoN, zsq) // const auto vp2zsq = vector_scalar(twoN, zsq); 453 aL_vpIz := vector_subtract(aL[:], vpIz) // const auto aL_vpIz = vector_subtract(aL, vpIz); 454 aR_vpIz := vector_add(aR[:], vpIz) //const auto aR_vpIz = vector_add(aR, vpIz); 455 456 ip1 := inner_product(aL_vpIz, HyNsR) // rct::key ip1 = inner_product(aL_vpIz, HyNsR); 457 crypto.ScAdd(&t1, &t1, &ip1) // sc_add(t1.bytes, t1.bytes, ip1.bytes); 458 459 ip2 := inner_product(sL[:], vector_add(hadamard(yN, aR_vpIz), vp2zsq)) // rct::key ip2 = inner_product(sL, vector_add(hadamard(yN, aR_vpIz), vp2zsq)); 460 crypto.ScAdd(&t1, &t1, &ip2) // sc_add(t1.bytes, t1.bytes, ip2.bytes); 461 462 ip3 := inner_product(sL[:], HyNsR) // rct::key ip3 = inner_product(sL, HyNsR); 463 crypto.ScAdd(&t2, &t2, &ip3) //sc_add(t2.bytes, t2.bytes, ip3.bytes); 464 465 // PAPER LINES 47-48 466 tau1 := crypto.SkGen() // rct::key tau1 = rct::skGen(), tau2 = rct::skGen(); 467 tau2 := crypto.SkGen() 468 469 // rct::key T1 = rct::addKeys(rct::scalarmultKey(rct::H, t1), rct::scalarmultBase(tau1)); 470 tau1_base := crypto.ScalarmultBase(tau1) 471 T1 := AddKeys_return(crypto.ScalarMultKey(&crypto.H, &t1), &tau1_base) 472 473 //rct::key T2 = rct::addKeys(rct::scalarmultKey(rct::H, t2), rct::scalarmultBase(tau2)); 474 tau2_base := crypto.ScalarmultBase(tau2) 475 T2 := AddKeys_return(crypto.ScalarMultKey(&crypto.H, &t2), &tau2_base) 476 477 // PAPER LINES 49-51 478 x := hash_cache_mash3(&hashcache, z, T1, T2) //rct::key x = hash_cache_mash(hash_cache, z, T1, T2); 479 480 // PAPER LINES 52-53 481 taux := crypto.Zero // rct::key taux = rct::zero(); 482 crypto.ScMul(&taux, &tau1, &x) //sc_mul(taux.bytes, tau1.bytes, x.bytes); 483 var xsq crypto.Key //rct::key xsq; 484 crypto.ScMul(&xsq, &x, &x) //sc_mul(xsq.bytes, x.bytes, x.bytes); 485 crypto.ScMulAdd(&taux, &tau2, &xsq, &taux) // sc_muladd(taux.bytes, tau2.bytes, xsq.bytes, taux.bytes); 486 crypto.ScMulAdd(&taux, gamma, &zsq, &taux) //sc_muladd(taux.bytes, gamma.bytes, zsq.bytes, taux.bytes); 487 488 var mu crypto.Key //rct::key mu; 489 crypto.ScMulAdd(&mu, &x, rho, &alpha) //sc_muladd(mu.bytes, x.bytes, rho.bytes, alpha.bytes); 490 491 // PAPER LINES 54-57 492 l := vector_add(aL_vpIz, vector_scalar(sL[:], x)) //rct::keyV l = vector_add(aL_vpIz, vector_scalar(sL, x)); 493 r := vector_add(hadamard(yN, vector_add(aR_vpIz, vector_scalar(sR[:], x))), vp2zsq) // rct::keyV r = vector_add(hadamard(yN, vector_add(aR_vpIz, vector_scalar(sR, x))), vp2zsq); 494 495 // STEP 2 complete 496 497 // STEP 3 starts 498 t := inner_product(l, r) //rct::key t = inner_product(l, r); 499 //fmt.Println("In raw, V = ", []crypto.Key{V}, " , mu = ", mu) 500 return &BulletProof{ 501 V: []crypto.Key{V}, 502 A: A, 503 S: S, 504 T1: T1, 505 T2: T2, 506 taux: taux, 507 mu: mu, 508 L: l, 509 R: r, 510 t: t, 511 } 512 } 513 514 func (proof *BulletProof) BULLETPROOF_BasicChecks_Raw() (result bool) { 515 516 // check whether any of the values in the proof are not 0 or 1 517 if proof.V[0] == crypto.Zero || 518 proof.A == crypto.Zero || 519 proof.S == crypto.Zero || 520 proof.T1 == crypto.Zero || 521 proof.T2 == crypto.Zero || 522 proof.taux == crypto.Zero || 523 proof.mu == crypto.Zero || 524 proof.t == crypto.Zero { 525 return false 526 } 527 for i := range proof.L { 528 if proof.L[i] == crypto.Zero || proof.R[i] == crypto.Zero { 529 return false 530 } 531 } 532 533 if proof.V[0] == crypto.Identity || 534 proof.A == crypto.Identity || 535 proof.S == crypto.Identity || 536 proof.T1 == crypto.Identity || 537 proof.T2 == crypto.Identity || 538 proof.taux == crypto.Identity || 539 proof.mu == crypto.Identity || 540 proof.t == crypto.Identity { 541 return false 542 } 543 for i := range proof.L { 544 if proof.L[i] == crypto.Identity || proof.R[i] == crypto.Identity { 545 return false 546 } 547 } 548 // time to verify that cofactors cannnot be exploited 549 curve_order := crypto.CurveOrder() 550 if *crypto.ScalarMultKey(&proof.V[0], &curve_order) != crypto.Identity { 551 return false 552 } 553 554 if *crypto.ScalarMultKey(&proof.A, &curve_order) != crypto.Identity { 555 return false 556 } 557 if *crypto.ScalarMultKey(&proof.S, &curve_order) != crypto.Identity { 558 return false 559 } 560 if *crypto.ScalarMultKey(&proof.T1, &curve_order) != crypto.Identity { 561 return false 562 } 563 if *crypto.ScalarMultKey(&proof.T2, &curve_order) != crypto.Identity { 564 return false 565 } 566 567 return true 568 } 569 570 func (proof *BulletProof) BULLETPROOF_Verify_Raw_ultrafast() (result bool) { 571 572 defer func() { // safety so if anything wrong happens, verification fails 573 if r := recover(); r != nil { 574 result = false 575 } 576 }() 577 578 //ultraonce.Do(precompute_tables_ultra) // generate pre compute tables 579 580 N := 64 581 582 if !(len(proof.V) == 1) { 583 //V does not have exactly one element 584 return false 585 } 586 587 if len(proof.L) != len(proof.R) { 588 //Mismatched L and R sizes 589 return false 590 } 591 if len(proof.L) == 0 { 592 // Empty Proof 593 return false 594 } 595 596 if len(proof.L) != N { 597 //Proof is not for 64 bits 598 return false 599 } 600 601 // these checks try to filter out rogue inputs 602 if proof.BULLETPROOF_BasicChecks_Raw() == false { 603 return false 604 } 605 // reconstruct the challenges 606 hashcache := *(crypto.HashToScalar(proof.V[0][:])) //rct::key hash_cache = rct::hash_to_scalar(proof.V[0]); 607 y := hash_cache_mash2(&hashcache, proof.A, proof.S) // rct::key y = hash_cache_mash(hash_cache, proof.A, proof.S); 608 609 hashcache = *(crypto.HashToScalar(y[:])) // rct::key z = hash_cache = rct::hash_to_scalar(y); 610 z := hashcache 611 x := hash_cache_mash3(&hashcache, z, proof.T1, proof.T2) //rct::key x = hash_cache_mash(hash_cache, z, proof.T1, proof.T2); 612 613 // PAPER LINE 61 614 //rct::key L61Left = rct::addKeys(rct::scalarmultBase(proof.taux), rct::scalarmultKey(rct::H, proof.t)); 615 taux_base := crypto.ScalarmultBase(proof.taux) 616 L61Left := AddKeys_return(&taux_base, crypto.ScalarMultKey(&crypto.H, &proof.t)) 617 618 k := crypto.Zero //rct::key k = rct::zero(); 619 yN := vector_powers(y, int64(N)) //const auto yN = vector_powers(y, N); 620 ip1y := inner_product(oneN, yN) //rct::key ip1y = inner_product(oneN, yN); 621 zsq := crypto.Zero //rct::key zsq; 622 crypto.ScMul(&zsq, &z, &z) //sc_mul(zsq.bytes, z.bytes, z.bytes); 623 624 var tmp crypto.Key //rct::key tmp, tmp2; 625 crypto.ScMulSub(&k, &zsq, &ip1y, &k) // sc_mulsub(k.bytes, zsq.bytes, ip1y.bytes, k.bytes); 626 var zcu crypto.Key //rct::key zcu; 627 crypto.ScMul(&zcu, &zsq, &z) //sc_mul(zcu.bytes, zsq.bytes, z.bytes); 628 crypto.ScMulSub(&k, &zcu, &ip12, &k) //sc_mulsub(k.bytes, zcu.bytes, ip12.bytes, k.bytes); 629 630 crypto.ScMulAdd(&tmp, &z, &ip1y, &k) // sc_muladd(tmp.bytes, z.bytes, ip1y.bytes, k.bytes); 631 L61Right := *(crypto.ScalarMultKey(&crypto.H, &tmp)) //rct::key L61Right = rct::scalarmultKey(rct::H, tmp); 632 633 tmp = *(crypto.ScalarMultKey(&proof.V[0], &zsq)) //tmp = rct::scalarmultKey(proof.V[0], zsq); 634 crypto.AddKeys(&L61Right, &L61Right, &tmp) //rct::addKeys(L61Right, L61Right, tmp); 635 636 tmp = *(crypto.ScalarMultKey(&proof.T1, &x)) // tmp = rct::scalarmultKey(proof.T1, x); 637 crypto.AddKeys(&L61Right, &L61Right, &tmp) //ct::addKeys(L61Right, L61Right, tmp); 638 639 var xsq crypto.Key //rct::key xsq; 640 crypto.ScMul(&xsq, &x, &x) // sc_mul(xsq.bytes, x.bytes, x.bytes); 641 tmp = *(crypto.ScalarMultKey(&proof.T2, &xsq)) //tmp = rct::scalarmultKey(proof.T2, xsq); 642 crypto.AddKeys(&L61Right, &L61Right, &tmp) //rct::addKeys(L61Right, L61Right, tmp); 643 644 if !(L61Right == L61Left) { 645 //MERROR("Verification failure at step 1"); 646 // fmt.Printf("erification failure at step 1") 647 //fmt.Println("return false here111") 648 return false 649 } 650 651 //fmt.Println("Verification passed at step 1") 652 653 // PAPER LINE 62 654 P := AddKeys_return(&proof.A, crypto.ScalarMultKey(&proof.S, &x)) //rct::key P = rct::addKeys(proof.A, rct::scalarmultKey(proof.S, x)); 655 ///////////////////////////////////////////////////////////////////////////////////// 656 //fmt.Println("P0 in verification raw = ", P) 657 //h_base_scalar = y^{-i + 1}, i \in [1,n] 658 h_base_scalar := make([]crypto.Key, N, N) 659 yinv := invert_scalar(y) //const rct::key yinv = invert(y); 660 yinvpow := y 661 662 //fmt.Println("here yinv = ", yinv) 663 for i := 0; i < N; i++ { 664 crypto.ScMul(&yinvpow, &yinvpow, &yinv) 665 h_base_scalar[i] = yinvpow 666 // fmt.Println("here y = ", h_base_scalar[i]) 667 } 668 //fmt.Println("Verification passed at step 2") 669 //g_scalar = z, h_scalar = z * y^n + z^2 * 2^n 670 g_scalar := make([]crypto.Key, N, N) 671 h_scalar := make([]crypto.Key, N, N) 672 vp2zsq := vector_scalar(twoN, zsq) 673 //ypow := yinv 674 //fmt.Println("Verification passed at step 2.1") 675 for i := 0; i < N; i++ { 676 //fmt.Println("i = ", i) 677 tmp := crypto.Zero 678 g_scalar[i] = z 679 h_scalar[i] = crypto.Zero 680 //fmt.Println("here i = ", i) 681 682 crypto.ScMul(&tmp, &z, &yN[i]) 683 //fmt.Println("3here i = ", i) 684 //ScMulAdd(s,a,b,c), s = c + ab 685 crypto.ScAdd(&tmp, &vp2zsq[i], &tmp) 686 //fmt.Println("4here i = ", i) 687 //tmp = z * y^n + z^2 * 2^n 688 crypto.ScSub(&h_scalar[i], &h_scalar[i], &tmp) 689 //fmt.Println("i = ", i) 690 } 691 //fmt.Println("Verification passed at step 3") 692 g_scalar = vector_add(proof.L, g_scalar) 693 h_scalar = vector_add(proof.R, h_scalar) 694 h_scalar = hadamard(h_scalar, h_base_scalar) 695 inner_prod := vector_exponent(g_scalar[:], h_scalar[:]) 696 //inner_prod := vector_exponent(h_scalar[:], g_scalar[:]) 697 tmp = crypto.ScalarmultBase(proof.mu) 698 crypto.AddKeys(&tmp, &tmp, &inner_prod) 699 //fmt.Println("Verification passed at step 4") 700 if P != tmp { 701 // fmt.Println("P = ", P) 702 // fmt.Println("tmp = ", tmp) 703 // fmt.Println("return false here9") 704 return false 705 } 706 return true 707 } 708 709 //Given a set of values v (0..2^N-1) and masks gamma, construct a range proof 710 func BULLETPROOF_Prove2_WithRegulation(sv []crypto.Key, gamma []crypto.Key, sL, sR []crypto.Key, rho crypto.Key) *BulletProof { 711 712 if len(sv) != len(gamma) { 713 return nil 714 } 715 716 const logN = int(6) // log2(64) 717 const N = int(64) // 1 << logN 718 var M, logM int 719 for { 720 M = 1 << uint(logM) 721 if M <= maxM && M < len(sv) { 722 logM++ 723 } else { 724 break 725 } 726 } 727 if M > maxM { 728 // sv/gamma are too large 729 return nil 730 } 731 732 MN := M * N 733 734 if len(sL) != MN || len(sR) != MN { 735 return nil 736 } 737 738 V := make([]crypto.Key, len(sv)) 739 aL := make([]crypto.Key, MN) 740 aR := make([]crypto.Key, MN) 741 aL8 := make([]crypto.Key, MN) 742 aR8 := make([]crypto.Key, MN) 743 var tmp, tmp2 crypto.Key 744 745 // prove V 746 for i := range sv { 747 var gamma8, sv8 crypto.Key 748 crypto.ScMul(&gamma8, &gamma[i], &crypto.INV_EIGHT) 749 crypto.ScMul(&sv8, &sv[i], &crypto.INV_EIGHT) 750 crypto.AddKeys2(&V[i], &gamma8, &sv8, &crypto.H) 751 } 752 753 // prove aL,aR 754 // the entire amount in uint64 is extracted into bits and 755 // different action taken if bit is zero or bit is one 756 for j := 0; j < M; j++ { 757 for i := N - 1; i >= 0; i-- { 758 if j < len(sv) && (sv[j][i/8]&(1<<(uint64(i)%8))) != 0 { 759 aL[j*N+i] = crypto.Identity 760 aL8[j*N+i] = crypto.INV_EIGHT 761 aR[j*N+i] = crypto.Zero 762 aR8[j*N+i] = crypto.Zero 763 } else { 764 aL[j*N+i] = crypto.Zero 765 aL8[j*N+i] = crypto.Zero 766 aR[j*N+i] = crypto.MINUS_ONE 767 aR8[j*N+i] = crypto.MINUS_INV_EIGHT 768 } 769 } 770 } 771 772 //for j := 0; j < M; j++ { 773 // var test_aL, test_aR uint64 774 // for i := 0; i < N; i++ { 775 // if bytes.Equal(aL[j*N+1][:], crypto.Identity[:]) { 776 // test_aL += 1 << uint(i) 777 // } 778 // if bytes.Equal(aR[j*N+1][:], crypto.Zero[:]) { 779 // test_aR += 1 << uint(i) 780 // } 781 // } 782 // var v_test uint64 783 // if j < len(sv) { 784 // for n := 0; n < 8; n++ { 785 // v_test |= uint64(sv[j][n]) << uint(8*n) 786 // } 787 // } 788 // if test_aL != v_test { 789 // panic("test_aL failed") 790 // } 791 // if test_aR != v_test { 792 // panic("test_aL failed") 793 // } 794 //} 795 796 try_again: 797 hashcache := *(crypto.HashToScalar2(V...)) 798 799 // prove STEP 1 800 801 // PAPER LINES 38-39 802 alpha := crypto.SkGen() 803 ve := vector_exponent(aL8, aR8) 804 var A crypto.Key 805 crypto.ScMul(&tmp, &alpha, &crypto.INV_EIGHT) 806 alphaTmp := crypto.ScalarmultBase(tmp) 807 crypto.AddKeys(&A, &ve, &alphaTmp) 808 809 // PAPER LINES 40-42 810 // sL := make([]crypto.Key, MN) 811 // sR := make([]crypto.Key, MN) 812 // for i := range sL { 813 // sL[i] = crypto.SkGen() 814 // sR[i] = crypto.SkGen() 815 // } 816 //rct::keyV sL = rct::skvGen(N), sR = rct::skvGen(N); 817 //rho := crypto.SkGen() 818 ve = vector_exponent(sL[:], sR[:]) 819 var S crypto.Key 820 rho_base_tmp := crypto.ScalarmultBase(rho) 821 crypto.AddKeys(&S, &ve, &rho_base_tmp) 822 S = *crypto.ScalarMultKey(&S, &crypto.INV_EIGHT) 823 824 // PAPER LINES 43-45 825 y := hash_cache_mash2(&hashcache, A, S) // rct::key y = hash_cache_mash(hash_cache, A, S); 826 if bytes.Equal(y[:], crypto.Zero[:]) { 827 // y is 0, trying again 828 goto try_again 829 } 830 hashcache = *(crypto.HashToScalar(y[:])) // rct::key z = hash_cache = rct::hash_to_scalar(y); 831 z := hashcache 832 if bytes.Equal(z[:], crypto.Zero[:]) { 833 // z is 0, trying again 834 goto try_again 835 } 836 837 l0 := vector_subtract_single(aL, &z) 838 l1 := &sL 839 840 zero_twos := make([]crypto.Key, MN) 841 zpow := vector_powers(z, int64(M+2)) 842 for i := 0; i < MN; i++ { 843 zero_twos[i] = crypto.Zero 844 for j := 1; j <= M; j++ { 845 if i >= (j-1)*N && i < j*N { 846 crypto.ScMulAdd(&zero_twos[i], &zpow[1+j], &twoN[i-(j-1)*N], &zero_twos[i]) 847 } 848 } 849 } 850 851 r0 := vector_add_single(aR, &z) 852 yMN := vector_powers(y, int64(MN)) 853 r0 = hadamard(r0, yMN) 854 r0 = vector_add(r0, zero_twos) 855 r1 := hadamard(yMN, sR) 856 857 // Polynomial construction before PAPER LINE 46 858 t1_1 := inner_product(l0, r1) 859 t1_2 := inner_product(*l1, r0) 860 var t1 crypto.Key 861 crypto.ScAdd(&t1, &t1_1, &t1_2) 862 t2 := inner_product(*l1, r1) 863 864 // PAPER LINES 47-48 865 tau1 := crypto.SkGen() // rct::key tau1 = rct::skGen(), tau2 = rct::skGen(); 866 tau2 := crypto.SkGen() 867 868 var T1, T2 crypto.Key 869 var p3 crypto.ExtendedGroupElement 870 var ge_p3_H crypto.ExtendedGroupElement 871 ge_p3_H.FromBytes(&crypto.H) 872 crypto.ScMul(&tmp, &t1, &crypto.INV_EIGHT) 873 crypto.ScMul(&tmp2, &tau1, &crypto.INV_EIGHT) 874 crypto.GeDoubleScalarMultVartime2(&p3, &tmp, &ge_p3_H, &tmp2) 875 p3.ToBytes(&T1) 876 crypto.ScMul(&tmp, &t2, &crypto.INV_EIGHT) 877 crypto.ScMul(&tmp2, &tau2, &crypto.INV_EIGHT) 878 crypto.GeDoubleScalarMultVartime2(&p3, &tmp, &ge_p3_H, &tmp2) 879 p3.ToBytes(&T2) 880 881 // PAPER LINES 49-51 882 x := hash_cache_mash3(&hashcache, z, T1, T2) //rct::key x = hash_cache_mash(hash_cache, z, T1, T2); 883 if bytes.Equal(x[:], crypto.Zero[:]) { 884 // x is 0, trying again 885 goto try_again 886 } 887 888 // PAPER LINES 52-53 889 taux := crypto.Zero // rct::key Taux = rct::zero(); 890 crypto.ScMul(&taux, &tau1, &x) //sc_mul(Taux.bytes, tau1.bytes, x.bytes); 891 var xsq crypto.Key //rct::key xsq; 892 crypto.ScMul(&xsq, &x, &x) //sc_mul(xsq.bytes, x.bytes, x.bytes); 893 crypto.ScMulAdd(&taux, &tau2, &xsq, &taux) // sc_muladd(Taux.bytes, tau2.bytes, xsq.bytes, Taux.bytes); 894 for j := 1; j <= len(sv); j++ { 895 crypto.ScMulAdd(&taux, &zpow[j+1], &gamma[j-1], &taux) 896 } 897 var mu crypto.Key //rct::key Mu; 898 crypto.ScMulAdd(&mu, &x, &rho, &alpha) //sc_muladd(Mu.bytes, x.bytes, rho.bytes, alpha.bytes); 899 900 // PAPER LINES 54-57 901 l := vector_add(l0, vector_scalar(*l1, x)) //rct::keyV l = vector_add(aL_vpIz, vector_scalar(sL, x)); 902 r := vector_add(r0, vector_scalar(r1, x)) // rct::keyV r = vector_add(hadamard(yN, vector_add(aR_vpIz, vector_scalar(sR, x))), vp2zsq); 903 904 // STEP 2 complete 905 906 // STEP 3 starts 907 t := inner_product(l, r) //rct::key t = inner_product(l, r); 908 909 return &BulletProof{ 910 V: V, 911 A: A, 912 S: S, 913 T1: T1, 914 T2: T2, 915 taux: taux, 916 mu: mu, 917 L: l, 918 R: r, 919 t: t, 920 } 921 } 922 923 //Given a set of values v (0..2^N-1) and masks gamma, construct a range proof 924 func BULLETPROOF_Prove2_raw(sv []crypto.Key, gamma []crypto.Key) *BulletProof { 925 const logN = int(6) // log2(64) 926 const N = int(64) // 1 << logN 927 var M, logM int 928 for { 929 M = 1 << uint(logM) 930 if M <= maxM && M < len(sv) { 931 logM++ 932 } else { 933 break 934 } 935 } 936 if M > maxM { 937 // sv/gamma are too large 938 return nil 939 } 940 MN := M * N 941 942 V := make([]crypto.Key, len(sv)) 943 aL := make([]crypto.Key, MN) 944 aR := make([]crypto.Key, MN) 945 aL8 := make([]crypto.Key, MN) 946 aR8 := make([]crypto.Key, MN) 947 var tmp, tmp2 crypto.Key 948 949 // prove V 950 for i := range sv { 951 var gamma8, sv8 crypto.Key 952 crypto.ScMul(&gamma8, &gamma[i], &crypto.INV_EIGHT) 953 crypto.ScMul(&sv8, &sv[i], &crypto.INV_EIGHT) 954 crypto.AddKeys2(&V[i], &gamma8, &sv8, &crypto.H) 955 } 956 957 // prove aL,aR 958 // the entire amount in uint64 is extracted into bits and 959 // different action taken if bit is zero or bit is one 960 for j := 0; j < M; j++ { 961 for i := N - 1; i >= 0; i-- { 962 if j < len(sv) && (sv[j][i/8]&(1<<(uint64(i)%8))) != 0 { 963 aL[j*N+i] = crypto.Identity 964 aL8[j*N+i] = crypto.INV_EIGHT 965 aR[j*N+i] = crypto.Zero 966 aR8[j*N+i] = crypto.Zero 967 } else { 968 aL[j*N+i] = crypto.Zero 969 aL8[j*N+i] = crypto.Zero 970 aR[j*N+i] = crypto.MINUS_ONE 971 aR8[j*N+i] = crypto.MINUS_INV_EIGHT 972 } 973 } 974 } 975 976 //for j := 0; j < M; j++ { 977 // var test_aL, test_aR uint64 978 // for i := 0; i < N; i++ { 979 // if bytes.Equal(aL[j*N+1][:], crypto.Identity[:]) { 980 // test_aL += 1 << uint(i) 981 // } 982 // if bytes.Equal(aR[j*N+1][:], crypto.Zero[:]) { 983 // test_aR += 1 << uint(i) 984 // } 985 // } 986 // var v_test uint64 987 // if j < len(sv) { 988 // for n := 0; n < 8; n++ { 989 // v_test |= uint64(sv[j][n]) << uint(8*n) 990 // } 991 // } 992 // if test_aL != v_test { 993 // panic("test_aL failed") 994 // } 995 // if test_aR != v_test { 996 // panic("test_aL failed") 997 // } 998 //} 999 1000 try_again: 1001 hashcache := *(crypto.HashToScalar2(V...)) 1002 1003 // prove STEP 1 1004 1005 // PAPER LINES 38-39 1006 alpha := crypto.SkGen() 1007 ve := vector_exponent(aL8, aR8) 1008 var A crypto.Key 1009 crypto.ScMul(&tmp, &alpha, &crypto.INV_EIGHT) 1010 alphaTmp := crypto.ScalarmultBase(tmp) 1011 crypto.AddKeys(&A, &ve, &alphaTmp) 1012 1013 // PAPER LINES 40-42 1014 sL := make([]crypto.Key, MN) 1015 sR := make([]crypto.Key, MN) 1016 for i := range sL { 1017 sL[i] = crypto.SkGen() 1018 sR[i] = crypto.SkGen() 1019 } 1020 //rct::keyV sL = rct::skvGen(N), sR = rct::skvGen(N); 1021 rho := crypto.SkGen() 1022 ve = vector_exponent(sL[:], sR[:]) 1023 var S crypto.Key 1024 rho_base_tmp := crypto.ScalarmultBase(rho) 1025 crypto.AddKeys(&S, &ve, &rho_base_tmp) 1026 S = *crypto.ScalarMultKey(&S, &crypto.INV_EIGHT) 1027 1028 // PAPER LINES 43-45 1029 y := hash_cache_mash2(&hashcache, A, S) // rct::key y = hash_cache_mash(hash_cache, A, S); 1030 if bytes.Equal(y[:], crypto.Zero[:]) { 1031 // y is 0, trying again 1032 goto try_again 1033 } 1034 hashcache = *(crypto.HashToScalar(y[:])) // rct::key z = hash_cache = rct::hash_to_scalar(y); 1035 z := hashcache 1036 if bytes.Equal(z[:], crypto.Zero[:]) { 1037 // z is 0, trying again 1038 goto try_again 1039 } 1040 1041 l0 := vector_subtract_single(aL, &z) 1042 l1 := &sL 1043 1044 zero_twos := make([]crypto.Key, MN) 1045 zpow := vector_powers(z, int64(M+2)) 1046 for i := 0; i < MN; i++ { 1047 zero_twos[i] = crypto.Zero 1048 for j := 1; j <= M; j++ { 1049 if i >= (j-1)*N && i < j*N { 1050 crypto.ScMulAdd(&zero_twos[i], &zpow[1+j], &twoN[i-(j-1)*N], &zero_twos[i]) 1051 } 1052 } 1053 } 1054 1055 r0 := vector_add_single(aR, &z) 1056 yMN := vector_powers(y, int64(MN)) 1057 r0 = hadamard(r0, yMN) 1058 r0 = vector_add(r0, zero_twos) 1059 r1 := hadamard(yMN, sR) 1060 1061 // Polynomial construction before PAPER LINE 46 1062 t1_1 := inner_product(l0, r1) 1063 t1_2 := inner_product(*l1, r0) 1064 var t1 crypto.Key 1065 crypto.ScAdd(&t1, &t1_1, &t1_2) 1066 t2 := inner_product(*l1, r1) 1067 1068 // PAPER LINES 47-48 1069 tau1 := crypto.SkGen() // rct::key tau1 = rct::skGen(), tau2 = rct::skGen(); 1070 tau2 := crypto.SkGen() 1071 1072 var T1, T2 crypto.Key 1073 var p3 crypto.ExtendedGroupElement 1074 var ge_p3_H crypto.ExtendedGroupElement 1075 ge_p3_H.FromBytes(&crypto.H) 1076 crypto.ScMul(&tmp, &t1, &crypto.INV_EIGHT) 1077 crypto.ScMul(&tmp2, &tau1, &crypto.INV_EIGHT) 1078 crypto.GeDoubleScalarMultVartime2(&p3, &tmp, &ge_p3_H, &tmp2) 1079 p3.ToBytes(&T1) 1080 crypto.ScMul(&tmp, &t2, &crypto.INV_EIGHT) 1081 crypto.ScMul(&tmp2, &tau2, &crypto.INV_EIGHT) 1082 crypto.GeDoubleScalarMultVartime2(&p3, &tmp, &ge_p3_H, &tmp2) 1083 p3.ToBytes(&T2) 1084 1085 // PAPER LINES 49-51 1086 x := hash_cache_mash3(&hashcache, z, T1, T2) //rct::key x = hash_cache_mash(hash_cache, z, T1, T2); 1087 if bytes.Equal(x[:], crypto.Zero[:]) { 1088 // x is 0, trying again 1089 goto try_again 1090 } 1091 1092 // PAPER LINES 52-53 1093 taux := crypto.Zero // rct::key Taux = rct::zero(); 1094 crypto.ScMul(&taux, &tau1, &x) //sc_mul(Taux.bytes, tau1.bytes, x.bytes); 1095 var xsq crypto.Key //rct::key xsq; 1096 crypto.ScMul(&xsq, &x, &x) //sc_mul(xsq.bytes, x.bytes, x.bytes); 1097 crypto.ScMulAdd(&taux, &tau2, &xsq, &taux) // sc_muladd(Taux.bytes, tau2.bytes, xsq.bytes, Taux.bytes); 1098 for j := 1; j <= len(sv); j++ { 1099 crypto.ScMulAdd(&taux, &zpow[j+1], &gamma[j-1], &taux) 1100 } 1101 var mu crypto.Key //rct::key Mu; 1102 crypto.ScMulAdd(&mu, &x, &rho, &alpha) //sc_muladd(Mu.bytes, x.bytes, rho.bytes, alpha.bytes); 1103 1104 // PAPER LINES 54-57 1105 l := vector_add(l0, vector_scalar(*l1, x)) //rct::keyV l = vector_add(aL_vpIz, vector_scalar(sL, x)); 1106 r := vector_add(r0, vector_scalar(r1, x)) // rct::keyV r = vector_add(hadamard(yN, vector_add(aR_vpIz, vector_scalar(sR, x))), vp2zsq); 1107 1108 // STEP 2 complete 1109 1110 // STEP 3 starts 1111 t := inner_product(l, r) //rct::key t = inner_product(l, r); 1112 1113 // PAPER LINES 32-33 1114 x_ip := hash_cache_mash4(&hashcache, x, taux, mu, t) //rct::key x_ip = hash_cache_mash(hash_cache, x, Taux, Mu, t); 1115 if bytes.Equal(x_ip[:], crypto.Zero[:]) { 1116 // x_ip is 0, trying again 1117 goto try_again 1118 } 1119 1120 // These are used in the inner product rounds 1121 //nprime := MN 1122 var aprime, bprime []crypto.Key 1123 Gprime := make([]crypto.ExtendedGroupElement, MN) //rct::keyV Gprime(N); 1124 Hprime := make([]crypto.ExtendedGroupElement, MN) //rct::keyV Hprime(N); 1125 aprime = make([]crypto.Key, MN) // rct::keyV aprime(N); 1126 bprime = make([]crypto.Key, MN) //rct::keyV bprime(N); 1127 1128 yinv := invert_scalar(y) //const rct::key yinv = invert(y); 1129 yinvpow := make([]crypto.Key, MN) // rct::key yinvpow = rct::identity(); 1130 yinvpow[0] = crypto.Identity 1131 yinvpow[1] = yinv 1132 for i := 0; i < MN; i++ { ///for (size_t i = 0; i < N; ++i) 1133 Gprime[i] = Gi_p3[i] // Gprime[i] = Gi[i]; 1134 Hprime[i] = Hi_p3[i] //Hprime[i] = scalarmultKey(Hi[i], yinvpow); 1135 if i > 1 { 1136 crypto.ScMul(&yinvpow[i], &yinvpow[i-1], &yinv) 1137 } 1138 aprime[i] = l[i] // aprime[i] = l[i]; 1139 bprime[i] = r[i] // bprime[i] = r[i]; 1140 } 1141 1142 // STEP 3 complete 1143 1144 return &BulletProof{ 1145 V: V, 1146 A: A, 1147 S: S, 1148 T1: T1, 1149 T2: T2, 1150 taux: taux, 1151 mu: mu, 1152 L: l, 1153 R: r, 1154 t: t, 1155 } 1156 } 1157 1158 func BULLETPROOF_Verify2_Optimized_WithRegulation(proofs []BulletProof) bool { 1159 const logN = int(6) // log2(64) 1160 const N = int(64) // 1 << logN 1161 max_length := 0 1162 nV := 0 1163 proof_data := make([]proof_data_t, len(proofs)) 1164 // inv_offset := 0 1165 //var to_invert []crypto.Key 1166 // max_logM := 0 1167 for i_proofs := range proofs { 1168 proof := &proofs[i_proofs] 1169 // check scalar range 1170 if !crypto.Sc_check(&proof.taux) || !crypto.Sc_check(&proof.mu) || !crypto.Sc_check(&proof.a) || !crypto.Sc_check(&proof.b) || !crypto.Sc_check(&proof.t) { 1171 // Input scalar not in range 1172 return false 1173 } 1174 if len(proof.V) < 1 { 1175 // V does not have at least one element 1176 return false 1177 } 1178 if len(proof.L) != len(proof.R) { 1179 // Mismatched L and R sizes 1180 return false 1181 } 1182 if len(proof.L) < 1 { 1183 // Empty proof 1184 return false 1185 } 1186 if len(proof.L) > max_length { 1187 max_length = len(proof.L) 1188 } 1189 nV += len(proof.V) 1190 1191 // Reconstruct the challenges 1192 pd := &proof_data[i_proofs] 1193 hash_cache := crypto.HashToScalar2(proof.V...) 1194 pd.y = hash_cache_mash2(hash_cache, proof.A, proof.S) 1195 if bytes.Equal(pd.y[:], crypto.Zero[:]) { 1196 return false 1197 } 1198 hash_cache = crypto.HashToScalar(pd.y[:]) 1199 pd.z = *hash_cache 1200 if bytes.Equal(pd.z[:], crypto.Zero[:]) { 1201 return false 1202 } 1203 pd.x = hash_cache_mash3(hash_cache, pd.z, proof.T1, proof.T2) 1204 if bytes.Equal(pd.x[:], crypto.Zero[:]) { 1205 return false 1206 } 1207 pd.x_ip = hash_cache_mash4(hash_cache, pd.x, proof.taux, proof.mu, proof.t) 1208 if bytes.Equal(pd.x_ip[:], crypto.Zero[:]) { 1209 return false 1210 } 1211 1212 M := 0 1213 pd.logM = 0 1214 for { 1215 M = 1 << uint(pd.logM) 1216 if M <= maxM && M < len(proof.V) { 1217 pd.logM++ 1218 } else { 1219 break 1220 } 1221 } 1222 // if len(proof.L) != 6+pd.logM { 1223 // // Proof is not the expected size 1224 // return false 1225 // } 1226 // if max_logM < pd.logM { 1227 // max_logM = pd.logM 1228 // } 1229 1230 // rounds := pd.logM + logN 1231 // if rounds < 1 { 1232 // // Zero rounds 1233 // return false 1234 // } 1235 1236 // PAPER LINES 21-22 1237 // The inner product challenges are computed per round 1238 // pd.w = make([]crypto.Key, rounds) 1239 // for i := 0; i < rounds; i++ { 1240 // pd.w[i] = hash_cache_mash2(hash_cache, proof.L[i], proof.R[i]) 1241 // if bytes.Equal(pd.w[i][:], crypto.Zero[:]) { 1242 // // w[i] == 0 1243 // return false 1244 // } 1245 // } 1246 1247 // pd.inv_offset = inv_offset 1248 // for i := 0; i < rounds; i++ { 1249 // to_invert = append(to_invert, pd.w[i]) 1250 // } 1251 // to_invert = append(to_invert, pd.y) 1252 // inv_offset += rounds + 1 1253 } 1254 1255 // if max_length >= 32 { 1256 // // At least one proof is too large 1257 // return false 1258 // } 1259 maxMN := max_length 1260 //fmt.Println("MaxMN = ", maxMN) 1261 //twoMN := vector_powers(TWO, int64(maxMN)) 1262 var tmp crypto.Key 1263 multiexp_data := make([]crypto.MultiexpData, 2*maxMN) 1264 1265 // inverse := invert(to_invert) 1266 1267 // setup weighted aggregates 1268 z1 := crypto.Zero 1269 z3 := crypto.Zero 1270 m_z4 := make([]crypto.Key, maxMN) 1271 m_z5 := make([]crypto.Key, maxMN) 1272 m_y0 := crypto.Zero 1273 y1 := crypto.Zero 1274 proof_data_index := 0 1275 //var w_cache []crypto.Key 1276 for i_proofs := range proofs { 1277 proof := &proofs[i_proofs] 1278 pd := &proof_data[proof_data_index] 1279 proof_data_index++ 1280 1281 // if len(proof.L) != 6+pd.logM { 1282 // // Proof is not the expected size 1283 // return false 1284 // } 1285 M := 1 << uint(pd.logM) 1286 MN := M * N 1287 //fmt.Println("M = ", M, ", MN = ", MN) 1288 weight_y := crypto.SkGen() 1289 weight_z := crypto.SkGen() 1290 1291 // pre-multiply some points by 8 1292 proof8_V := make([]crypto.Key, len(proof.V)) 1293 for i := range proof.V { 1294 proof8_V[i] = *crypto.Scalarmult8(&proof.V[i]) 1295 } 1296 proof8_L := make([]crypto.Key, len(proof.L)) 1297 //fmt.Println("len of L = ", len(proof.L)) 1298 for i := range proof.L { 1299 proof8_L[i] = proof.L[i] 1300 } 1301 proof8_R := make([]crypto.Key, len(proof.R)) 1302 for i := range proof.R { 1303 proof8_R[i] = proof.R[i] 1304 } 1305 proof8_T1 := *crypto.Scalarmult8(&proof.T1) 1306 proof8_T2 := *crypto.Scalarmult8(&proof.T2) 1307 proof8_S := *crypto.Scalarmult8(&proof.S) 1308 proof8_A := *crypto.Scalarmult8(&proof.A) 1309 1310 // PAPER LINE 61 1311 crypto.ScMulSub(&m_y0, &proof.taux, &weight_y, &m_y0) 1312 1313 ypow := vector_powers(pd.y, int64(MN)) 1314 zpow := vector_powers(pd.z, int64(M+3)) 1315 1316 var k crypto.Key 1317 ip1y := vector_power_sum(pd.y, MN) 1318 crypto.ScMulSub(&k, &zpow[2], &ip1y, &k) 1319 for j := 1; j <= M; j++ { 1320 if j+2 >= len(zpow) { 1321 // invalid zpow index 1322 return false 1323 } 1324 crypto.ScMulSub(&k, &zpow[j+2], &ip12, &k) 1325 } 1326 1327 crypto.ScMulAdd(&tmp, &pd.z, &ip1y, &k) 1328 crypto.ScSub(&tmp, &proof.t, &tmp) 1329 crypto.ScMulAdd(&y1, &tmp, &weight_y, &y1) 1330 for j := 0; j < len(proof8_V); j++ { 1331 crypto.ScMul(&tmp, &zpow[j+2], &weight_y) 1332 crypto.AppendMultiexpData(&multiexp_data, &proof8_V[j], &tmp) 1333 } 1334 crypto.ScMul(&tmp, &pd.x, &weight_y) 1335 crypto.AppendMultiexpData(&multiexp_data, &proof8_T1, &tmp) 1336 var xsq crypto.Key 1337 crypto.ScMul(&xsq, &pd.x, &pd.x) 1338 crypto.ScMul(&tmp, &xsq, &weight_y) 1339 crypto.AppendMultiexpData(&multiexp_data, &proof8_T2, &tmp) 1340 1341 // PAPER LINE 62 1342 crypto.AppendMultiexpData(&multiexp_data, &proof8_A, &weight_z) 1343 crypto.ScMul(&tmp, &pd.x, &weight_z) 1344 crypto.AppendMultiexpData(&multiexp_data, &proof8_S, &tmp) 1345 1346 { 1347 h_base_scalar := make([]crypto.Key, MN, MN) 1348 yinv := invert_scalar(pd.y) //const rct::key yinv = invert(y); 1349 yinvpow := pd.y 1350 1351 //fmt.Println("here yinv = ", yinv) 1352 for i := 0; i < MN; i++ { 1353 crypto.ScMul(&yinvpow, &yinvpow, &yinv) 1354 h_base_scalar[i] = yinvpow 1355 // fmt.Println("here y = ", h_base_scalar[i]) 1356 } 1357 //fmt.Println("Verification passed at step 2") 1358 //g_scalar = z, h_scalar = z * y^n + z^2 * 2^n 1359 g_scalar := make([]crypto.Key, MN, MN) 1360 h_scalar := make([]crypto.Key, MN, MN) 1361 //vp2zsq := vector_scalar(twoN, zpow[2]) 1362 //ypow := yinv 1363 //fmt.Println("Verification passed at step 2.1") 1364 for i := 0; i < MN; i++ { 1365 //fmt.Println("i = ", i) 1366 tmp := crypto.Zero 1367 h_scalar[i] = crypto.Zero 1368 crypto.ScSub(&g_scalar[i], &crypto.Zero, &pd.z) 1369 //g_scalar[i] = pd.z 1370 h_scalar[i] = crypto.Zero 1371 //fmt.Println("here i = ", i) 1372 crypto.ScMul(&tmp, &pd.z, &ypow[i]) 1373 //fmt.Println("3here i = ", i) 1374 //ScMulAdd(s,a,b,c), s = c + ab 1375 //crypto.ScAdd(&tmp, &vp2zsq[i], &tmp) 1376 //j := i / N 1377 //iDivided := i % N 1378 //fmt.Println("test here i = ", i, ", j + 1 = ", 2+i/N) 1379 crypto.ScMulAdd(&tmp, &twoN[i%N], &zpow[2+i/N], &tmp) 1380 crypto.ScAdd(&h_scalar[i], &h_scalar[i], &tmp) 1381 1382 //deal with innner product 1383 crypto.ScSub(&g_scalar[i], &g_scalar[i], &proof.L[i]) 1384 crypto.ScSub(&h_scalar[i], &h_scalar[i], &proof.R[i]) 1385 crypto.ScMul(&h_scalar[i], &h_scalar[i], &h_base_scalar[i]) 1386 //h_scalar = hadamard(h_scalar, h_base_scalar) 1387 //add to final scalar 1388 crypto.ScMulAdd(&m_z4[i], &g_scalar[i], &weight_z, &m_z4[i]) 1389 crypto.ScMulAdd(&m_z5[i], &h_scalar[i], &weight_z, &m_z5[i]) 1390 //fmt.Println("i = ", i) 1391 } 1392 //fmt.Println("Verification passed at step 3") 1393 // g_scalar = vector_add(proof.L, g_scalar) 1394 // h_scalar = vector_add(proof.R, h_scalar) 1395 //**g base scalar and h base scalar need to be updated 1396 1397 //inner_prod := vector_exponent(g_scalar[:], h_scalar[:]) 1398 //inner_prod := vector_exponent(h_scalar[:], g_scalar[:]) 1399 //tmp = crypto.ScalarmultBase(proof.mu) 1400 //crypto.AddKeys(&tmp, &tmp, &inner_prod) 1401 } 1402 1403 crypto.ScMulAdd(&z1, &proof.mu, &weight_z, &z1) 1404 1405 } 1406 1407 // now check all proofs at once 1408 crypto.ScSub(&tmp, &m_y0, &z1) 1409 crypto.AppendMultiexpData(&multiexp_data, &crypto.GBASE, &tmp) 1410 crypto.ScSub(&tmp, &z3, &y1) 1411 crypto.AppendMultiexpData(&multiexp_data, &crypto.H, &tmp) 1412 for i := 0; i < maxMN; i++ { 1413 multiexp_data[i*2].Scalar = m_z4[i] 1414 multiexp_data[i*2].Point = Gi_p3[i] 1415 multiexp_data[i*2+1].Scalar = m_z5[i] 1416 multiexp_data[i*2+1].Point = Hi_p3[i] 1417 } 1418 1419 sum, err := crypto.Multiexp(&multiexp_data, 2*maxMN) 1420 if err != nil || !bytes.Equal(sum[:], crypto.Identity[:]) { 1421 // Verification failure 1422 return false 1423 } 1424 return true 1425 } 1426 1427 func (proof *BulletProof) ExtractAmount(sL *[64]crypto.Key) (amount crypto.Key) { 1428 // reconstruct the challenges 1429 hashcache := *(crypto.HashToScalar(proof.V[0][:])) //rct::key hash_cache = rct::hash_to_scalar(proof.V[0]); 1430 y := hash_cache_mash2(&hashcache, proof.A, proof.S) // rct::key y = hash_cache_mash(hash_cache, proof.A, proof.S); 1431 1432 hashcache = *(crypto.HashToScalar(y[:])) // rct::key z = hash_cache = rct::hash_to_scalar(y); 1433 z := hashcache 1434 x := hash_cache_mash3(&hashcache, z, proof.T1, proof.T2) //rct::key x = hash_cache_mash(hash_cache, z, proof.T1, proof.T2); 1435 aL_vpIz := vector_subtract(proof.L, vector_scalar(sL[:], x)) 1436 vpIz := vector_scalar(oneN, z) // const auto vpIz = vector_scalar(oneN, z); 1437 aL := vector_add(aL_vpIz, vpIz) 1438 for i := 0; i < len(aL); i++ { 1439 if aL[i] == crypto.Identity { 1440 amount[i/8] = amount[i/8] | (1 << uint(i%8)) 1441 } 1442 } 1443 return amount 1444 }