aboutsummaryrefslogtreecommitdiff
path: root/src/ringct
diff options
context:
space:
mode:
authormoneromooo-monero <moneromooo-monero@users.noreply.github.com>2018-08-08 18:39:31 +0000
committermoneromooo-monero <moneromooo-monero@users.noreply.github.com>2018-10-22 16:07:44 +0000
commita281b950bff73fc715554d00ec32292ef97b56ec (patch)
tree5425701ffb353a97ac47ea58c49d837469cf5373 /src/ringct
parentbulletproofs: some more speedup (diff)
downloadmonero-a281b950bff73fc715554d00ec32292ef97b56ec.tar.xz
bulletproofs: remove single value prover
It is now expressed in terms of the array prover
Diffstat (limited to 'src/ringct')
-rw-r--r--src/ringct/bulletproofs.cc284
-rw-r--r--src/ringct/rctSigs.cpp9
2 files changed, 2 insertions, 291 deletions
diff --git a/src/ringct/bulletproofs.cc b/src/ringct/bulletproofs.cc
index 5c75e6418..09d22c6d1 100644
--- a/src/ringct/bulletproofs.cc
+++ b/src/ringct/bulletproofs.cc
@@ -313,17 +313,6 @@ static rct::keyV vector_dup(const rct::key &x, size_t N)
return rct::keyV(N, x);
}
-/* Get the sum of a vector's elements */
-static rct::key vector_sum(const rct::keyV &a)
-{
- rct::key res = rct::zero();
- for (size_t i = 0; i < a.size(); ++i)
- {
- sc_add(res.bytes, res.bytes, a[i].bytes);
- }
- return res;
-}
-
static rct::key switch_endianness(rct::key k)
{
std::reverse(k.bytes, k.bytes + sizeof(k));
@@ -414,281 +403,12 @@ static rct::key hash_cache_mash(rct::key &hash_cache, const rct::key &mash0, con
/* Given a value v (0..2^N-1) and a mask gamma, construct a range proof */
Bulletproof bulletproof_PROVE(const rct::key &sv, const rct::key &gamma)
{
- init_exponents();
-
- PERF_TIMER_UNIT(PROVE, 1000000);
-
- constexpr size_t logN = 6; // log2(64)
- constexpr size_t N = 1<<logN;
-
- rct::key V;
- rct::keyV aL(N), aR(N);
- rct::keyV aL8(N), aR8(N);
- rct::key tmp, tmp2;
-
- PERF_TIMER_START_BP(PROVE_v);
- rct::key gamma8, sv8;
- sc_mul(gamma8.bytes, gamma.bytes, INV_EIGHT.bytes);
- sc_mul(sv8.bytes, sv.bytes, INV_EIGHT.bytes);
- rct::addKeys2(V, gamma8, sv8, rct::H);
- PERF_TIMER_STOP(PROVE_v);
-
- PERF_TIMER_START_BP(PROVE_aLaR);
- for (size_t i = N; i-- > 0; )
- {
- if (sv[i/8] & (((uint64_t)1)<<(i%8)))
- {
- aL[i] = rct::identity();
- aL8[i] = INV_EIGHT;
- aR[i] = aR8[i] = rct::zero();
- }
- else
- {
- aL[i] = aL8[i] = rct::zero();
- aR[i] = MINUS_ONE;
- aR8[i] = MINUS_INV_EIGHT;
- }
- }
- PERF_TIMER_STOP(PROVE_aLaR);
-
- rct::key hash_cache = rct::hash_to_scalar(V);
-
- // DEBUG: Test to ensure this recovers the value
-#ifdef DEBUG_BP
- uint64_t test_aL = 0, test_aR = 0;
- for (size_t i = 0; i < N; ++i)
- {
- if (aL[i] == rct::identity())
- test_aL += ((uint64_t)1)<<i;
- if (aR[i] == rct::zero())
- test_aR += ((uint64_t)1)<<i;
- }
- uint64_t v_test = 0;
- for (int n = 0; n < 8; ++n) v_test |= (((uint64_t)sv[n]) << (8*n));
- CHECK_AND_ASSERT_THROW_MES(test_aL == v_test, "test_aL failed");
- CHECK_AND_ASSERT_THROW_MES(test_aR == v_test, "test_aR failed");
-#endif
-
-try_again:
- PERF_TIMER_START_BP(PROVE_step1);
- // PAPER LINES 38-39
- rct::key alpha = rct::skGen();
- rct::key ve = vector_exponent(aL8, aR8);
- rct::key A;
- sc_mul(tmp.bytes, alpha.bytes, INV_EIGHT.bytes);
- rct::addKeys(A, ve, rct::scalarmultBase(tmp));
-
- // PAPER LINES 40-42
- rct::keyV sL = rct::skvGen(N), sR = rct::skvGen(N);
- rct::key rho = rct::skGen();
- ve = vector_exponent(sL, sR);
- rct::key S;
- rct::addKeys(S, ve, rct::scalarmultBase(rho));
- S = rct::scalarmultKey(S, INV_EIGHT);
-
- // PAPER LINES 43-45
- rct::key y = hash_cache_mash(hash_cache, A, S);
- if (y == rct::zero())
- {
- PERF_TIMER_STOP(PROVE_step1);
- MINFO("y is 0, trying again");
- goto try_again;
- }
- rct::key z = hash_cache = rct::hash_to_scalar(y);
- if (z == rct::zero())
- {
- PERF_TIMER_STOP(PROVE_step1);
- MINFO("z is 0, trying again");
- goto try_again;
- }
-
- // Polynomial construction before PAPER LINE 46
- rct::key t0 = rct::zero();
- rct::key t1 = rct::zero();
- rct::key t2 = rct::zero();
-
- const auto yN = vector_powers(y, N);
-
- rct::key ip1y = vector_sum(yN);
- sc_muladd(t0.bytes, z.bytes, ip1y.bytes, t0.bytes);
-
- rct::key zsq;
- sc_mul(zsq.bytes, z.bytes, z.bytes);
- sc_muladd(t0.bytes, zsq.bytes, sv.bytes, t0.bytes);
-
- rct::key k = rct::zero();
- sc_mulsub(k.bytes, zsq.bytes, ip1y.bytes, k.bytes);
-
- rct::key zcu;
- sc_mul(zcu.bytes, zsq.bytes, z.bytes);
- sc_mulsub(k.bytes, zcu.bytes, ip12.bytes, k.bytes);
- sc_add(t0.bytes, t0.bytes, k.bytes);
-
- // DEBUG: Test the value of t0 has the correct form
-#ifdef DEBUG_BP
- rct::key test_t0 = rct::zero();
- rct::key iph = inner_product(aL, hadamard(aR, yN));
- sc_add(test_t0.bytes, test_t0.bytes, iph.bytes);
- rct::key ips = inner_product(vector_subtract(aL, aR), yN);
- sc_muladd(test_t0.bytes, z.bytes, ips.bytes, test_t0.bytes);
- rct::key ipt = inner_product(twoN, aL);
- sc_muladd(test_t0.bytes, zsq.bytes, ipt.bytes, test_t0.bytes);
- sc_add(test_t0.bytes, test_t0.bytes, k.bytes);
- CHECK_AND_ASSERT_THROW_MES(t0 == test_t0, "t0 check failed");
-#endif
- PERF_TIMER_STOP(PROVE_step1);
-
- PERF_TIMER_START_BP(PROVE_step2);
- const auto HyNsR = hadamard(yN, sR);
- const auto vpIz = vector_dup(z, N);
- const auto vp2zsq = vector_scalar(twoN, zsq);
- const auto aL_vpIz = vector_subtract(aL, vpIz);
- const auto aR_vpIz = vector_add(aR, vpIz);
-
- rct::key ip1 = inner_product(aL_vpIz, HyNsR);
- sc_add(t1.bytes, t1.bytes, ip1.bytes);
-
- rct::key ip2 = inner_product(sL, vector_add(hadamard(yN, aR_vpIz), vp2zsq));
- sc_add(t1.bytes, t1.bytes, ip2.bytes);
-
- rct::key ip3 = inner_product(sL, HyNsR);
- sc_add(t2.bytes, t2.bytes, ip3.bytes);
-
- // PAPER LINES 47-48
- rct::key tau1 = rct::skGen(), tau2 = rct::skGen();
-
- rct::key T1, T2;
- ge_p3 p3;
- sc_mul(tmp.bytes, t1.bytes, INV_EIGHT.bytes);
- sc_mul(tmp2.bytes, tau1.bytes, INV_EIGHT.bytes);
- ge_double_scalarmult_base_vartime_p3(&p3, tmp.bytes, &ge_p3_H, tmp2.bytes);
- ge_p3_tobytes(T1.bytes, &p3);
- sc_mul(tmp.bytes, t2.bytes, INV_EIGHT.bytes);
- sc_mul(tmp2.bytes, tau2.bytes, INV_EIGHT.bytes);
- ge_double_scalarmult_base_vartime_p3(&p3, tmp.bytes, &ge_p3_H, tmp2.bytes);
- ge_p3_tobytes(T2.bytes, &p3);
-
- // PAPER LINES 49-51
- rct::key x = hash_cache_mash(hash_cache, z, T1, T2);
- if (x == rct::zero())
- {
- PERF_TIMER_STOP(PROVE_step2);
- MINFO("x is 0, trying again");
- goto try_again;
- }
-
- // PAPER LINES 52-53
- rct::key taux = rct::zero();
- sc_mul(taux.bytes, tau1.bytes, x.bytes);
- rct::key xsq;
- sc_mul(xsq.bytes, x.bytes, x.bytes);
- sc_muladd(taux.bytes, tau2.bytes, xsq.bytes, taux.bytes);
- sc_muladd(taux.bytes, gamma.bytes, zsq.bytes, taux.bytes);
- rct::key mu;
- sc_muladd(mu.bytes, x.bytes, rho.bytes, alpha.bytes);
-
- // PAPER LINES 54-57
- rct::keyV l = vector_add(aL_vpIz, vector_scalar(sL, x));
- rct::keyV r = vector_add(hadamard(yN, vector_add(aR_vpIz, vector_scalar(sR, x))), vp2zsq);
- PERF_TIMER_STOP(PROVE_step2);
-
- PERF_TIMER_START_BP(PROVE_step3);
- rct::key t = inner_product(l, r);
-
- // DEBUG: Test if the l and r vectors match the polynomial forms
-#ifdef DEBUG_BP
- rct::key test_t;
- sc_muladd(test_t.bytes, t1.bytes, x.bytes, t0.bytes);
- sc_muladd(test_t.bytes, t2.bytes, xsq.bytes, test_t.bytes);
- CHECK_AND_ASSERT_THROW_MES(test_t == t, "test_t check failed");
-#endif
-
- // PAPER LINES 32-33
- rct::key x_ip = hash_cache_mash(hash_cache, x, taux, mu, t);
-
- // These are used in the inner product rounds
- size_t nprime = N;
- std::vector<ge_p3> Gprime(N);
- std::vector<ge_p3> Hprime(N);
- rct::keyV aprime(N);
- rct::keyV bprime(N);
- const rct::key yinv = invert(y);
- rct::key yinvpow = rct::identity();
- for (size_t i = 0; i < N; ++i)
- {
- Gprime[i] = Gi_p3[i];
- ge_scalarmult_p3(&Hprime[i], yinvpow.bytes, &Hi_p3[i]);
- sc_mul(yinvpow.bytes, yinvpow.bytes, yinv.bytes);
- aprime[i] = l[i];
- bprime[i] = r[i];
- }
- rct::keyV L(logN);
- rct::keyV R(logN);
- int round = 0;
- rct::keyV w(logN); // this is the challenge x in the inner product protocol
- PERF_TIMER_STOP(PROVE_step3);
-
- PERF_TIMER_START_BP(PROVE_step4);
- // PAPER LINE 13
- while (nprime > 1)
- {
- // PAPER LINE 15
- nprime /= 2;
-
- // PAPER LINES 16-17
- rct::key cL = inner_product(slice(aprime, 0, nprime), slice(bprime, nprime, bprime.size()));
- rct::key cR = inner_product(slice(aprime, nprime, aprime.size()), slice(bprime, 0, nprime));
-
- // PAPER LINES 18-19
- sc_mul(tmp.bytes, cL.bytes, x_ip.bytes);
- L[round] = cross_vector_exponent8(nprime, Gprime, nprime, Hprime, 0, aprime, 0, bprime, nprime, &ge_p3_H, &tmp);
- sc_mul(tmp.bytes, cR.bytes, x_ip.bytes);
- R[round] = cross_vector_exponent8(nprime, Gprime, 0, Hprime, nprime, aprime, nprime, bprime, 0, &ge_p3_H, &tmp);
-
- // PAPER LINES 21-22
- w[round] = hash_cache_mash(hash_cache, L[round], R[round]);
- if (w[round] == rct::zero())
- {
- PERF_TIMER_STOP(PROVE_step4);
- MINFO("w[round] is 0, trying again");
- goto try_again;
- }
-
- // PAPER LINES 24-25
- const rct::key winv = invert(w[round]);
- if (nprime > 1)
- {
- hadamard_fold(Gprime, winv, w[round]);
- hadamard_fold(Hprime, w[round], winv);
- }
-
- // PAPER LINES 28-29
- aprime = vector_add(vector_scalar(slice(aprime, 0, nprime), w[round]), vector_scalar(slice(aprime, nprime, aprime.size()), winv));
- bprime = vector_add(vector_scalar(slice(bprime, 0, nprime), winv), vector_scalar(slice(bprime, nprime, bprime.size()), w[round]));
-
- ++round;
- }
- PERF_TIMER_STOP(PROVE_step4);
-
- // PAPER LINE 58 (with inclusions from PAPER LINE 8 and PAPER LINE 20)
- return Bulletproof(V, A, S, T1, T2, taux, mu, std::move(L), std::move(R), aprime[0], bprime[0], t);
+ return bulletproof_PROVE(rct::keyV(1, sv), rct::keyV(1, gamma));
}
Bulletproof bulletproof_PROVE(uint64_t v, const rct::key &gamma)
{
- // vG + gammaH
- PERF_TIMER_START_BP(PROVE_v);
- rct::key sv = rct::zero();
- sv.bytes[0] = v & 255;
- sv.bytes[1] = (v >> 8) & 255;
- sv.bytes[2] = (v >> 16) & 255;
- sv.bytes[3] = (v >> 24) & 255;
- sv.bytes[4] = (v >> 32) & 255;
- sv.bytes[5] = (v >> 40) & 255;
- sv.bytes[6] = (v >> 48) & 255;
- sv.bytes[7] = (v >> 56) & 255;
- PERF_TIMER_STOP(PROVE_v);
- return bulletproof_PROVE(sv, gamma);
+ return bulletproof_PROVE(std::vector<uint64_t>(1, v), rct::keyV(1, gamma));
}
/* Given a set of values v (0..2^N-1) and masks gamma, construct a range proof */
diff --git a/src/ringct/rctSigs.cpp b/src/ringct/rctSigs.cpp
index 0d1789a38..5ec9a1750 100644
--- a/src/ringct/rctSigs.cpp
+++ b/src/ringct/rctSigs.cpp
@@ -45,15 +45,6 @@ using namespace std;
#define CHECK_AND_ASSERT_MES_L1(expr, ret, message) {if(!(expr)) {MCERROR("verify", message); return ret;}}
namespace rct {
- Bulletproof proveRangeBulletproof(key &C, key &mask, uint64_t amount)
- {
- mask = rct::skGen();
- Bulletproof proof = bulletproof_PROVE(amount, mask);
- CHECK_AND_ASSERT_THROW_MES(proof.V.size() == 1, "V has not exactly one element");
- C = proof.V[0];
- return proof;
- }
-
Bulletproof proveRangeBulletproof(keyV &C, keyV &masks, const std::vector<uint64_t> &amounts)
{
masks = rct::skvGen(amounts.size());