Merge pull request #6049

45fd72b Updated paper references (SarangNoether)
277003f Minor prover simplification (SarangNoether)
This commit is contained in:
luigi1111 2019-12-12 13:43:57 -06:00
commit e629db18f4
No known key found for this signature in database
GPG Key ID: F4ACA0183641E010

View File

@ -27,6 +27,7 @@
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// //
// Adapted from Java code by Sarang Noether // Adapted from Java code by Sarang Noether
// Paper references are to https://eprint.iacr.org/2017/1066 (revision 1 July 2018)
#include <stdlib.h> #include <stdlib.h>
#include <boost/thread/mutex.hpp> #include <boost/thread/mutex.hpp>
@ -521,6 +522,7 @@ Bulletproof bulletproof_PROVE(const rct::keyV &sv, const rct::keyV &gamma)
} }
PERF_TIMER_STOP_BP(PROVE_v); PERF_TIMER_STOP_BP(PROVE_v);
// PAPER LINES 41-42
PERF_TIMER_START_BP(PROVE_aLaR); PERF_TIMER_START_BP(PROVE_aLaR);
for (size_t j = 0; j < M; ++j) for (size_t j = 0; j < M; ++j)
{ {
@ -566,14 +568,14 @@ try_again:
rct::key hash_cache = rct::hash_to_scalar(V); rct::key hash_cache = rct::hash_to_scalar(V);
PERF_TIMER_START_BP(PROVE_step1); PERF_TIMER_START_BP(PROVE_step1);
// PAPER LINES 38-39 // PAPER LINES 43-44
rct::key alpha = rct::skGen(); rct::key alpha = rct::skGen();
rct::key ve = vector_exponent(aL8, aR8); rct::key ve = vector_exponent(aL8, aR8);
rct::key A; rct::key A;
sc_mul(tmp.bytes, alpha.bytes, INV_EIGHT.bytes); sc_mul(tmp.bytes, alpha.bytes, INV_EIGHT.bytes);
rct::addKeys(A, ve, rct::scalarmultBase(tmp)); rct::addKeys(A, ve, rct::scalarmultBase(tmp));
// PAPER LINES 40-42 // PAPER LINES 45-47
rct::keyV sL = rct::skvGen(MN), sR = rct::skvGen(MN); rct::keyV sL = rct::skvGen(MN), sR = rct::skvGen(MN);
rct::key rho = rct::skGen(); rct::key rho = rct::skGen();
ve = vector_exponent(sL, sR); ve = vector_exponent(sL, sR);
@ -581,7 +583,7 @@ try_again:
rct::addKeys(S, ve, rct::scalarmultBase(rho)); rct::addKeys(S, ve, rct::scalarmultBase(rho));
S = rct::scalarmultKey(S, INV_EIGHT); S = rct::scalarmultKey(S, INV_EIGHT);
// PAPER LINES 43-45 // PAPER LINES 48-50
rct::key y = hash_cache_mash(hash_cache, A, S); rct::key y = hash_cache_mash(hash_cache, A, S);
if (y == rct::zero()) if (y == rct::zero())
{ {
@ -598,24 +600,20 @@ try_again:
} }
// Polynomial construction by coefficients // Polynomial construction by coefficients
// PAPER LINES 70-71
rct::keyV l0 = vector_subtract(aL, z); rct::keyV l0 = vector_subtract(aL, z);
const rct::keyV &l1 = sL; const rct::keyV &l1 = sL;
// This computes the ugly sum/concatenation from PAPER LINE 65
rct::keyV zero_twos(MN); rct::keyV zero_twos(MN);
const rct::keyV zpow = vector_powers(z, M+2); const rct::keyV zpow = vector_powers(z, M+2);
for (size_t i = 0; i < MN; ++i) for (size_t j = 0; j < M; ++j)
{ {
zero_twos[i] = rct::zero(); for (size_t i = 0; i < N; ++i)
for (size_t j = 1; j <= M; ++j)
{
if (i >= (j-1)*N && i < j*N)
{ {
CHECK_AND_ASSERT_THROW_MES(1+j < zpow.size(), "invalid zpow index"); CHECK_AND_ASSERT_THROW_MES(j+2 < zpow.size(), "invalid zpow index");
CHECK_AND_ASSERT_THROW_MES(i-(j-1)*N < twoN.size(), "invalid twoN index"); CHECK_AND_ASSERT_THROW_MES(i < twoN.size(), "invalid twoN index");
sc_muladd(zero_twos[i].bytes, zpow[1+j].bytes, twoN[i-(j-1)*N].bytes, zero_twos[i].bytes); sc_mul(zero_twos[j*N+i].bytes,zpow[j+2].bytes,twoN[i].bytes);
} }
}
} }
rct::keyV r0 = vector_add(aR, z); rct::keyV r0 = vector_add(aR, z);
@ -624,7 +622,7 @@ try_again:
r0 = vector_add(r0, zero_twos); r0 = vector_add(r0, zero_twos);
rct::keyV r1 = hadamard(yMN, sR); rct::keyV r1 = hadamard(yMN, sR);
// Polynomial construction before PAPER LINE 46 // Polynomial construction before PAPER LINE 51
rct::key t1_1 = inner_product(l0, r1); rct::key t1_1 = inner_product(l0, r1);
rct::key t1_2 = inner_product(l1, r0); rct::key t1_2 = inner_product(l1, r0);
rct::key t1; rct::key t1;
@ -634,7 +632,7 @@ try_again:
PERF_TIMER_STOP_BP(PROVE_step1); PERF_TIMER_STOP_BP(PROVE_step1);
PERF_TIMER_START_BP(PROVE_step2); PERF_TIMER_START_BP(PROVE_step2);
// PAPER LINES 47-48 // PAPER LINES 52-53
rct::key tau1 = rct::skGen(), tau2 = rct::skGen(); rct::key tau1 = rct::skGen(), tau2 = rct::skGen();
rct::key T1, T2; rct::key T1, T2;
@ -648,7 +646,7 @@ try_again:
ge_double_scalarmult_base_vartime_p3(&p3, tmp.bytes, &ge_p3_H, tmp2.bytes); ge_double_scalarmult_base_vartime_p3(&p3, tmp.bytes, &ge_p3_H, tmp2.bytes);
ge_p3_tobytes(T2.bytes, &p3); ge_p3_tobytes(T2.bytes, &p3);
// PAPER LINES 49-51 // PAPER LINES 54-56
rct::key x = hash_cache_mash(hash_cache, z, T1, T2); rct::key x = hash_cache_mash(hash_cache, z, T1, T2);
if (x == rct::zero()) if (x == rct::zero())
{ {
@ -657,7 +655,7 @@ try_again:
goto try_again; goto try_again;
} }
// PAPER LINES 52-53 // PAPER LINES 61-63
rct::key taux; rct::key taux;
sc_mul(taux.bytes, tau1.bytes, x.bytes); sc_mul(taux.bytes, tau1.bytes, x.bytes);
rct::key xsq; rct::key xsq;
@ -671,7 +669,7 @@ try_again:
rct::key mu; rct::key mu;
sc_muladd(mu.bytes, x.bytes, rho.bytes, alpha.bytes); sc_muladd(mu.bytes, x.bytes, rho.bytes, alpha.bytes);
// PAPER LINES 54-57 // PAPER LINES 58-60
rct::keyV l = l0; rct::keyV l = l0;
l = vector_add(l, vector_scalar(l1, x)); l = vector_add(l, vector_scalar(l1, x));
rct::keyV r = r0; rct::keyV r = r0;
@ -690,7 +688,7 @@ try_again:
CHECK_AND_ASSERT_THROW_MES(test_t == t, "test_t check failed"); CHECK_AND_ASSERT_THROW_MES(test_t == t, "test_t check failed");
#endif #endif
// PAPER LINES 32-33 // PAPER LINE 6
rct::key x_ip = hash_cache_mash(hash_cache, x, taux, mu, t); rct::key x_ip = hash_cache_mash(hash_cache, x, taux, mu, t);
if (x_ip == rct::zero()) if (x_ip == rct::zero())
{ {
@ -725,20 +723,19 @@ try_again:
PERF_TIMER_STOP_BP(PROVE_step3); PERF_TIMER_STOP_BP(PROVE_step3);
PERF_TIMER_START_BP(PROVE_step4); PERF_TIMER_START_BP(PROVE_step4);
// PAPER LINE 13
const rct::keyV *scale = &yinvpow; const rct::keyV *scale = &yinvpow;
while (nprime > 1) while (nprime > 1)
{ {
// PAPER LINE 15 // PAPER LINE 20
nprime /= 2; nprime /= 2;
// PAPER LINES 16-17 // PAPER LINES 21-22
PERF_TIMER_START_BP(PROVE_inner_product); PERF_TIMER_START_BP(PROVE_inner_product);
rct::key cL = inner_product(slice(aprime, 0, nprime), slice(bprime, nprime, bprime.size())); 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)); rct::key cR = inner_product(slice(aprime, nprime, aprime.size()), slice(bprime, 0, nprime));
PERF_TIMER_STOP_BP(PROVE_inner_product); PERF_TIMER_STOP_BP(PROVE_inner_product);
// PAPER LINES 18-19 // PAPER LINES 23-24
PERF_TIMER_START_BP(PROVE_LR); PERF_TIMER_START_BP(PROVE_LR);
sc_mul(tmp.bytes, cL.bytes, x_ip.bytes); sc_mul(tmp.bytes, cL.bytes, x_ip.bytes);
L[round] = cross_vector_exponent8(nprime, Gprime, nprime, Hprime, 0, aprime, 0, bprime, nprime, scale, &ge_p3_H, &tmp); L[round] = cross_vector_exponent8(nprime, Gprime, nprime, Hprime, 0, aprime, 0, bprime, nprime, scale, &ge_p3_H, &tmp);
@ -746,7 +743,7 @@ try_again:
R[round] = cross_vector_exponent8(nprime, Gprime, 0, Hprime, nprime, aprime, nprime, bprime, 0, scale, &ge_p3_H, &tmp); R[round] = cross_vector_exponent8(nprime, Gprime, 0, Hprime, nprime, aprime, nprime, bprime, 0, scale, &ge_p3_H, &tmp);
PERF_TIMER_STOP_BP(PROVE_LR); PERF_TIMER_STOP_BP(PROVE_LR);
// PAPER LINES 21-22 // PAPER LINES 25-27
w[round] = hash_cache_mash(hash_cache, L[round], R[round]); w[round] = hash_cache_mash(hash_cache, L[round], R[round]);
if (w[round] == rct::zero()) if (w[round] == rct::zero())
{ {
@ -755,7 +752,7 @@ try_again:
goto try_again; goto try_again;
} }
// PAPER LINES 24-25 // PAPER LINES 29-30
const rct::key winv = invert(w[round]); const rct::key winv = invert(w[round]);
if (nprime > 1) if (nprime > 1)
{ {
@ -765,7 +762,7 @@ try_again:
PERF_TIMER_STOP_BP(PROVE_hadamard2); PERF_TIMER_STOP_BP(PROVE_hadamard2);
} }
// PAPER LINES 28-29 // PAPER LINES 33-34
PERF_TIMER_START_BP(PROVE_prime); PERF_TIMER_START_BP(PROVE_prime);
aprime = vector_add(vector_scalar(slice(aprime, 0, nprime), w[round]), vector_scalar(slice(aprime, nprime, aprime.size()), winv)); 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])); bprime = vector_add(vector_scalar(slice(bprime, 0, nprime), winv), vector_scalar(slice(bprime, nprime, bprime.size()), w[round]));
@ -776,7 +773,6 @@ try_again:
} }
PERF_TIMER_STOP_BP(PROVE_step4); PERF_TIMER_STOP_BP(PROVE_step4);
// PAPER LINE 58 (with inclusions from PAPER LINE 8 and PAPER LINE 20)
return Bulletproof(std::move(V), A, S, T1, T2, taux, mu, std::move(L), std::move(R), aprime[0], bprime[0], t); return Bulletproof(std::move(V), A, S, T1, T2, taux, mu, std::move(L), std::move(R), aprime[0], bprime[0], t);
} }
@ -810,7 +806,10 @@ struct proof_data_t
size_t logM, inv_offset; size_t logM, inv_offset;
}; };
/* Given a range proof, determine if it is valid */ /* Given a range proof, determine if it is valid
* This uses the method in PAPER LINES 95-105,
* weighted across multiple proofs in a batch
*/
bool bulletproof_VERIFY(const std::vector<const Bulletproof*> &proofs) bool bulletproof_VERIFY(const std::vector<const Bulletproof*> &proofs)
{ {
init_exponents(); init_exponents();
@ -871,7 +870,6 @@ bool bulletproof_VERIFY(const std::vector<const Bulletproof*> &proofs)
CHECK_AND_ASSERT_MES(rounds > 0, false, "Zero rounds"); CHECK_AND_ASSERT_MES(rounds > 0, false, "Zero rounds");
PERF_TIMER_START_BP(VERIFY_line_21_22); PERF_TIMER_START_BP(VERIFY_line_21_22);
// PAPER LINES 21-22
// The inner product challenges are computed per round // The inner product challenges are computed per round
pd.w.resize(rounds); pd.w.resize(rounds);
for (size_t i = 0; i < rounds; ++i) for (size_t i = 0; i < rounds; ++i)
@ -929,7 +927,6 @@ bool bulletproof_VERIFY(const std::vector<const Bulletproof*> &proofs)
rct::key proof8_A = rct::scalarmult8(proof.A); rct::key proof8_A = rct::scalarmult8(proof.A);
PERF_TIMER_START_BP(VERIFY_line_61); PERF_TIMER_START_BP(VERIFY_line_61);
// PAPER LINE 61
sc_mulsub(m_y0.bytes, proof.taux.bytes, weight_y.bytes, m_y0.bytes); sc_mulsub(m_y0.bytes, proof.taux.bytes, weight_y.bytes, m_y0.bytes);
const rct::keyV zpow = vector_powers(pd.z, M+3); const rct::keyV zpow = vector_powers(pd.z, M+3);
@ -962,7 +959,6 @@ bool bulletproof_VERIFY(const std::vector<const Bulletproof*> &proofs)
PERF_TIMER_STOP_BP(VERIFY_line_61rl_new); PERF_TIMER_STOP_BP(VERIFY_line_61rl_new);
PERF_TIMER_START_BP(VERIFY_line_62); PERF_TIMER_START_BP(VERIFY_line_62);
// PAPER LINE 62
multiexp_data.emplace_back(weight_z, proof8_A); multiexp_data.emplace_back(weight_z, proof8_A);
sc_mul(tmp.bytes, pd.x.bytes, weight_z.bytes); sc_mul(tmp.bytes, pd.x.bytes, weight_z.bytes);
multiexp_data.emplace_back(tmp, proof8_S); multiexp_data.emplace_back(tmp, proof8_S);
@ -973,7 +969,6 @@ bool bulletproof_VERIFY(const std::vector<const Bulletproof*> &proofs)
CHECK_AND_ASSERT_MES(rounds > 0, false, "Zero rounds"); CHECK_AND_ASSERT_MES(rounds > 0, false, "Zero rounds");
PERF_TIMER_START_BP(VERIFY_line_24_25); PERF_TIMER_START_BP(VERIFY_line_24_25);
// Basically PAPER LINES 24-25
// Compute the curvepoints from G[i] and H[i] // Compute the curvepoints from G[i] and H[i]
rct::key yinvpow = rct::identity(); rct::key yinvpow = rct::identity();
rct::key ypow = rct::identity(); rct::key ypow = rct::identity();
@ -1010,7 +1005,6 @@ bool bulletproof_VERIFY(const std::vector<const Bulletproof*> &proofs)
sc_mul(g_scalar.bytes, g_scalar.bytes, w_cache[i].bytes); sc_mul(g_scalar.bytes, g_scalar.bytes, w_cache[i].bytes);
sc_mul(h_scalar.bytes, h_scalar.bytes, w_cache[(~i) & (MN-1)].bytes); sc_mul(h_scalar.bytes, h_scalar.bytes, w_cache[(~i) & (MN-1)].bytes);
// Adjust the scalars using the exponents from PAPER LINE 62
sc_add(g_scalar.bytes, g_scalar.bytes, pd.z.bytes); sc_add(g_scalar.bytes, g_scalar.bytes, pd.z.bytes);
CHECK_AND_ASSERT_MES(2+i/N < zpow.size(), false, "invalid zpow index"); CHECK_AND_ASSERT_MES(2+i/N < zpow.size(), false, "invalid zpow index");
CHECK_AND_ASSERT_MES(i%N < twoN.size(), false, "invalid twoN index"); CHECK_AND_ASSERT_MES(i%N < twoN.size(), false, "invalid twoN index");
@ -1043,7 +1037,6 @@ bool bulletproof_VERIFY(const std::vector<const Bulletproof*> &proofs)
PERF_TIMER_STOP_BP(VERIFY_line_24_25); PERF_TIMER_STOP_BP(VERIFY_line_24_25);
// PAPER LINE 26
PERF_TIMER_START_BP(VERIFY_line_26_new); PERF_TIMER_START_BP(VERIFY_line_26_new);
sc_muladd(z1.bytes, proof.mu.bytes, weight_z.bytes, z1.bytes); sc_muladd(z1.bytes, proof.mu.bytes, weight_z.bytes, z1.bytes);
for (size_t i = 0; i < rounds; ++i) for (size_t i = 0; i < rounds; ++i)