From 2bf636503fa09346b02964b2903ca70579f94c6b Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Mon, 6 Aug 2018 15:21:07 +0000 Subject: [PATCH] bulletproofs: speed up the latest changes a bit --- src/ringct/bulletproofs.cc | 68 +++++++++++++++------------- src/ringct/rctOps.cpp | 14 ++++++ src/ringct/rctOps.h | 2 + src/ringct/rctSigs.cpp | 4 +- tests/performance_tests/crypto_ops.h | 4 ++ tests/performance_tests/main.cpp | 2 + tests/unit_tests/ringct.cpp | 7 +++ 7 files changed, 67 insertions(+), 34 deletions(-) diff --git a/src/ringct/bulletproofs.cc b/src/ringct/bulletproofs.cc index 5bcdd968d..165691bfe 100644 --- a/src/ringct/bulletproofs.cc +++ b/src/ringct/bulletproofs.cc @@ -92,30 +92,37 @@ static bool is_reduced(const rct::key &scalar) return scalar == reduced; } -//addKeys3acc_p3 -//aAbB += a*A + b*B where a, b are scalars, A, B are curve points -//A and B must be input after applying "precomp" -static void addKeys3acc_p3(ge_p3 *aAbB, const key &a, const ge_dsmp A, const key &b, const ge_dsmp B) +static void addKeys_acc_p3(ge_p3 *acc_p3, const rct::key &a, const rct::key &point) { - ge_p3 rv; + ge_p3 p3; + CHECK_AND_ASSERT_THROW_MES(ge_frombytes_vartime(&p3, point.bytes) == 0, "ge_frombytes_vartime failed"); + ge_scalarmult_p3(&p3, a.bytes, &p3); + ge_cached cached; + ge_p3_to_cached(&cached, acc_p3); ge_p1p1 p1; - ge_p2 p2; - ge_double_scalarmult_precomp_vartime2_p3(&rv, a.bytes, A, b.bytes, B); + ge_add(&p1, &p3, &cached); + ge_p1p1_to_p3(acc_p3, &p1); +} + +static void add_acc_p3(ge_p3 *acc_p3, const rct::key &point) +{ + ge_p3 p3; + CHECK_AND_ASSERT_THROW_MES(ge_frombytes_vartime(&p3, point.bytes) == 0, "ge_frombytes_vartime failed"); ge_cached cached; - ge_p3_to_cached(&cached, aAbB); - ge_add(&p1, &rv, &cached); - ge_p1p1_to_p3(aAbB, &p1); + ge_p3_to_cached(&cached, &p3); + ge_p1p1 p1; + ge_add(&p1, acc_p3, &cached); + ge_p1p1_to_p3(acc_p3, &p1); } -static void addKeys_acc_p3(ge_p3 *acc_p3, const rct::key &a, const rct::key &point) +static void sub_acc_p3(ge_p3 *acc_p3, const rct::key &point) { ge_p3 p3; CHECK_AND_ASSERT_THROW_MES(ge_frombytes_vartime(&p3, point.bytes) == 0, "ge_frombytes_vartime failed"); - ge_scalarmult_p3(&p3, a.bytes, &p3); ge_cached cached; - ge_p3_to_cached(&cached, acc_p3); + ge_p3_to_cached(&cached, &p3); ge_p1p1 p1; - ge_add(&p1, &p3, &cached); + ge_sub(&p1, acc_p3, &cached); ge_p1p1_to_p3(acc_p3, &p1); } @@ -1087,9 +1094,7 @@ bool bulletproof_VERIFY(const std::vector &proofs) sc_mul(tmp.bytes, zpow[j+2].bytes, EIGHT.bytes); multiexp_data.emplace_back(tmp, proof.V[j]); } - rct::key temp = multiexp(multiexp_data, false); - - rct::addKeys(Y2, Y2, rct::scalarmultKey(temp, weight)); + rct::addKeys(Y2, Y2, rct::scalarmultKey(multiexp(multiexp_data, false), weight)); rct::key weight8; sc_mul(weight8.bytes, weight.bytes, EIGHT.bytes); sc_mul(tmp.bytes, x.bytes, weight8.bytes); @@ -1103,7 +1108,7 @@ bool bulletproof_VERIFY(const std::vector &proofs) PERF_TIMER_START_BP(VERIFY_line_62); // PAPER LINE 62 sc_mul(tmp.bytes, x.bytes, EIGHT.bytes); - rct::addKeys(Z0, Z0, rct::scalarmultKey(rct::addKeys(rct::scalarmultKey(proof.A, EIGHT), rct::scalarmultKey(proof.S, tmp)), weight)); + rct::addKeys(Z0, Z0, rct::scalarmultKey(rct::addKeys(rct::scalarmult8(proof.A), rct::scalarmultKey(proof.S, tmp)), weight)); PERF_TIMER_STOP(VERIFY_line_62); // Compute the number of rounds for the inner product @@ -1202,23 +1207,22 @@ bool bulletproof_VERIFY(const std::vector &proofs) // now check all proofs at once PERF_TIMER_START_BP(VERIFY_step2_check); - rct::key check1 = rct::identity(); - rct::addKeys(check1, check1, rct::scalarmultBase(y0)); - rct::addKeys(check1, check1, rct::scalarmultH(y1)); - rct::subKeys(check1, check1, Y2); - rct::subKeys(check1, check1, Y3); - rct::subKeys(check1, check1, Y4); - if (!(check1 == rct::identity())) + ge_p3 check1; + ge_scalarmult_base(&check1, y0.bytes); + addKeys_acc_p3(&check1, y1, rct::H); + sub_acc_p3(&check1, Y2); + sub_acc_p3(&check1, Y3); + sub_acc_p3(&check1, Y4); + if (!ge_p3_is_point_at_infinity(&check1)) { MERROR("Verification failure at step 1"); return false; } - rct::key check2 = rct::identity(); - rct::addKeys(check2, check2, Z0); + ge_p3 check2; sc_sub(tmp.bytes, rct::zero().bytes, z1.bytes); - rct::addKeys(check2, check2, rct::scalarmultBase(tmp)); - rct::addKeys(check2, check2, Z2); - rct::addKeys(check2, check2, rct::scalarmultH(z3)); + ge_double_scalarmult_base_vartime_p3(&check2, z3.bytes, &ge_p3_H, tmp.bytes); + add_acc_p3(&check2, Z0); + add_acc_p3(&check2, Z2); std::vector multiexp_data; multiexp_data.reserve(2 * maxMN); @@ -1229,10 +1233,10 @@ bool bulletproof_VERIFY(const std::vector &proofs) sc_sub(tmp.bytes, rct::zero().bytes, z5[i].bytes); multiexp_data.emplace_back(tmp, Hi_p3[i]); } - rct::addKeys(check2, check2, multiexp(multiexp_data, true)); + add_acc_p3(&check2, multiexp(multiexp_data, true)); PERF_TIMER_STOP(VERIFY_step2_check); - if (!(check2 == rct::identity())) + if (!ge_p3_is_point_at_infinity(&check2)) { MERROR("Verification failure at step 2"); return false; diff --git a/src/ringct/rctOps.cpp b/src/ringct/rctOps.cpp index df027f4b6..6c3c4500e 100644 --- a/src/ringct/rctOps.cpp +++ b/src/ringct/rctOps.cpp @@ -211,6 +211,20 @@ namespace rct { return aP; } + //Computes 8P + key scalarmult8(const key & P) { + ge_p3 p3; + CHECK_AND_ASSERT_THROW_MES_L1(ge_frombytes_vartime(&p3, P.bytes) == 0, "ge_frombytes_vartime failed at "+boost::lexical_cast(__LINE__)); + ge_p2 p2; + ge_p3_to_p2(&p2, &p3); + ge_p1p1 p1; + ge_mul8(&p1, &p2); + ge_p1p1_to_p2(&p2, &p1); + rct::key res; + ge_tobytes(res.bytes, &p2); + return res; + } + //Computes aL where L is the curve order bool isInMainSubgroup(const key & a) { ge_p3 p3; diff --git a/src/ringct/rctOps.h b/src/ringct/rctOps.h index 53c8e1d01..50645821c 100644 --- a/src/ringct/rctOps.h +++ b/src/ringct/rctOps.h @@ -122,6 +122,8 @@ namespace rct { key scalarmultKey(const key &P, const key &a); //Computes aH where H= toPoint(cn_fast_hash(G)), G the basepoint key scalarmultH(const key & a); + // multiplies a point by 8 + key scalarmult8(const key & P); // checks a is in the main subgroup (ie, not a small one) bool isInMainSubgroup(const key & a); diff --git a/src/ringct/rctSigs.cpp b/src/ringct/rctSigs.cpp index 29743c790..fe0cd9c57 100644 --- a/src/ringct/rctSigs.cpp +++ b/src/ringct/rctSigs.cpp @@ -768,7 +768,7 @@ namespace rct { #endif for (i = 0; i < outamounts.size(); ++i) { - rv.outPk[i].mask = rct::scalarmultKey(C[i], EIGHT); + rv.outPk[i].mask = rct::scalarmult8(C[i]); outSk[i].mask = masks[i]; } } @@ -788,7 +788,7 @@ namespace rct { #endif for (i = 0; i < batch_size; ++i) { - rv.outPk[i + amounts_proved].mask = rct::scalarmultKey(C[i], EIGHT); + rv.outPk[i + amounts_proved].mask = rct::scalarmult8(C[i]); outSk[i + amounts_proved].mask = masks[i]; } amounts_proved += batch_size; diff --git a/tests/performance_tests/crypto_ops.h b/tests/performance_tests/crypto_ops.h index f52faa708..3c68583c5 100644 --- a/tests/performance_tests/crypto_ops.h +++ b/tests/performance_tests/crypto_ops.h @@ -45,6 +45,8 @@ enum test_op op_addKeys, op_scalarmultBase, op_scalarmultKey, + op_scalarmultH, + op_scalarmult8, op_ge_double_scalarmult_base_vartime, op_ge_double_scalarmult_precomp_vartime, op_ge_double_scalarmult_precomp_vartime2, @@ -97,6 +99,8 @@ public: case op_addKeys: rct::addKeys(key, point0, point1); break; case op_scalarmultBase: rct::scalarmultBase(scalar0); break; case op_scalarmultKey: rct::scalarmultKey(point0, scalar0); break; + case op_scalarmultH: rct::scalarmultH(scalar0); break; + case op_scalarmult8: rct::scalarmult8(point0); break; case op_ge_double_scalarmult_base_vartime: ge_double_scalarmult_base_vartime(&tmp_p2, scalar0.bytes, &p3_0, scalar1.bytes); break; case op_ge_double_scalarmult_precomp_vartime: ge_double_scalarmult_precomp_vartime(&tmp_p2, scalar0.bytes, &p3_0, scalar1.bytes, precomp0); break; case op_ge_double_scalarmult_precomp_vartime2: ge_double_scalarmult_precomp_vartime2(&tmp_p2, scalar0.bytes, precomp0, scalar1.bytes, precomp1); break; diff --git a/tests/performance_tests/main.cpp b/tests/performance_tests/main.cpp index d83486296..7c5135c65 100644 --- a/tests/performance_tests/main.cpp +++ b/tests/performance_tests/main.cpp @@ -247,6 +247,8 @@ int main(int argc, char** argv) TEST_PERFORMANCE1(filter, p, test_crypto_ops, op_addKeys); TEST_PERFORMANCE1(filter, p, test_crypto_ops, op_scalarmultBase); TEST_PERFORMANCE1(filter, p, test_crypto_ops, op_scalarmultKey); + TEST_PERFORMANCE1(filter, p, test_crypto_ops, op_scalarmultH); + TEST_PERFORMANCE1(filter, p, test_crypto_ops, op_scalarmult8); TEST_PERFORMANCE1(filter, p, test_crypto_ops, op_ge_double_scalarmult_base_vartime); TEST_PERFORMANCE1(filter, p, test_crypto_ops, op_ge_double_scalarmult_precomp_vartime); TEST_PERFORMANCE1(filter, p, test_crypto_ops, op_ge_double_scalarmult_precomp_vartime2); diff --git a/tests/unit_tests/ringct.cpp b/tests/unit_tests/ringct.cpp index 360529b9e..3877ef785 100644 --- a/tests/unit_tests/ringct.cpp +++ b/tests/unit_tests/ringct.cpp @@ -1093,6 +1093,13 @@ TEST(ringct, H) ASSERT_EQ(memcmp(&p3, &ge_p3_H, sizeof(ge_p3)), 0); } +TEST(ringct, mul8) +{ + ASSERT_EQ(rct::scalarmult8(rct::identity()), rct::identity()); + ASSERT_EQ(rct::scalarmult8(rct::H), rct::scalarmultKey(rct::H, rct::EIGHT)); + ASSERT_EQ(rct::scalarmultKey(rct::scalarmultKey(rct::H, rct::INV_EIGHT), rct::EIGHT), rct::H); +} + TEST(ringct, aggregated) { static const size_t N_PROOFS = 16;