mirror of
https://github.com/monero-project/monero.git
synced 2024-11-17 16:27:39 +00:00
bulletproofs: speed up the latest changes a bit
This commit is contained in:
parent
044dff5a30
commit
2bf636503f
7 changed files with 68 additions and 35 deletions
|
@ -92,21 +92,6 @@ static bool is_reduced(const rct::key &scalar)
|
||||||
return scalar == reduced;
|
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)
|
|
||||||
{
|
|
||||||
ge_p3 rv;
|
|
||||||
ge_p1p1 p1;
|
|
||||||
ge_p2 p2;
|
|
||||||
ge_double_scalarmult_precomp_vartime2_p3(&rv, a.bytes, A, b.bytes, B);
|
|
||||||
ge_cached cached;
|
|
||||||
ge_p3_to_cached(&cached, aAbB);
|
|
||||||
ge_add(&p1, &rv, &cached);
|
|
||||||
ge_p1p1_to_p3(aAbB, &p1);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void addKeys_acc_p3(ge_p3 *acc_p3, const rct::key &a, const rct::key &point)
|
static void addKeys_acc_p3(ge_p3 *acc_p3, const rct::key &a, const rct::key &point)
|
||||||
{
|
{
|
||||||
ge_p3 p3;
|
ge_p3 p3;
|
||||||
|
@ -119,6 +104,28 @@ static void addKeys_acc_p3(ge_p3 *acc_p3, const rct::key &a, const rct::key &poi
|
||||||
ge_p1p1_to_p3(acc_p3, &p1);
|
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, &p3);
|
||||||
|
ge_p1p1 p1;
|
||||||
|
ge_add(&p1, acc_p3, &cached);
|
||||||
|
ge_p1p1_to_p3(acc_p3, &p1);
|
||||||
|
}
|
||||||
|
|
||||||
|
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_cached cached;
|
||||||
|
ge_p3_to_cached(&cached, &p3);
|
||||||
|
ge_p1p1 p1;
|
||||||
|
ge_sub(&p1, acc_p3, &cached);
|
||||||
|
ge_p1p1_to_p3(acc_p3, &p1);
|
||||||
|
}
|
||||||
|
|
||||||
static rct::key scalarmultKey(const ge_p3 &P, const rct::key &a)
|
static rct::key scalarmultKey(const ge_p3 &P, const rct::key &a)
|
||||||
{
|
{
|
||||||
ge_p2 R;
|
ge_p2 R;
|
||||||
|
@ -1087,9 +1094,7 @@ bool bulletproof_VERIFY(const std::vector<const Bulletproof*> &proofs)
|
||||||
sc_mul(tmp.bytes, zpow[j+2].bytes, EIGHT.bytes);
|
sc_mul(tmp.bytes, zpow[j+2].bytes, EIGHT.bytes);
|
||||||
multiexp_data.emplace_back(tmp, proof.V[j]);
|
multiexp_data.emplace_back(tmp, proof.V[j]);
|
||||||
}
|
}
|
||||||
rct::key temp = multiexp(multiexp_data, false);
|
rct::addKeys(Y2, Y2, rct::scalarmultKey(multiexp(multiexp_data, false), weight));
|
||||||
|
|
||||||
rct::addKeys(Y2, Y2, rct::scalarmultKey(temp, weight));
|
|
||||||
rct::key weight8;
|
rct::key weight8;
|
||||||
sc_mul(weight8.bytes, weight.bytes, EIGHT.bytes);
|
sc_mul(weight8.bytes, weight.bytes, EIGHT.bytes);
|
||||||
sc_mul(tmp.bytes, x.bytes, weight8.bytes);
|
sc_mul(tmp.bytes, x.bytes, weight8.bytes);
|
||||||
|
@ -1103,7 +1108,7 @@ bool bulletproof_VERIFY(const std::vector<const Bulletproof*> &proofs)
|
||||||
PERF_TIMER_START_BP(VERIFY_line_62);
|
PERF_TIMER_START_BP(VERIFY_line_62);
|
||||||
// PAPER LINE 62
|
// PAPER LINE 62
|
||||||
sc_mul(tmp.bytes, x.bytes, EIGHT.bytes);
|
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);
|
PERF_TIMER_STOP(VERIFY_line_62);
|
||||||
|
|
||||||
// Compute the number of rounds for the inner product
|
// Compute the number of rounds for the inner product
|
||||||
|
@ -1202,23 +1207,22 @@ bool bulletproof_VERIFY(const std::vector<const Bulletproof*> &proofs)
|
||||||
|
|
||||||
// now check all proofs at once
|
// now check all proofs at once
|
||||||
PERF_TIMER_START_BP(VERIFY_step2_check);
|
PERF_TIMER_START_BP(VERIFY_step2_check);
|
||||||
rct::key check1 = rct::identity();
|
ge_p3 check1;
|
||||||
rct::addKeys(check1, check1, rct::scalarmultBase(y0));
|
ge_scalarmult_base(&check1, y0.bytes);
|
||||||
rct::addKeys(check1, check1, rct::scalarmultH(y1));
|
addKeys_acc_p3(&check1, y1, rct::H);
|
||||||
rct::subKeys(check1, check1, Y2);
|
sub_acc_p3(&check1, Y2);
|
||||||
rct::subKeys(check1, check1, Y3);
|
sub_acc_p3(&check1, Y3);
|
||||||
rct::subKeys(check1, check1, Y4);
|
sub_acc_p3(&check1, Y4);
|
||||||
if (!(check1 == rct::identity()))
|
if (!ge_p3_is_point_at_infinity(&check1))
|
||||||
{
|
{
|
||||||
MERROR("Verification failure at step 1");
|
MERROR("Verification failure at step 1");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
rct::key check2 = rct::identity();
|
ge_p3 check2;
|
||||||
rct::addKeys(check2, check2, Z0);
|
|
||||||
sc_sub(tmp.bytes, rct::zero().bytes, z1.bytes);
|
sc_sub(tmp.bytes, rct::zero().bytes, z1.bytes);
|
||||||
rct::addKeys(check2, check2, rct::scalarmultBase(tmp));
|
ge_double_scalarmult_base_vartime_p3(&check2, z3.bytes, &ge_p3_H, tmp.bytes);
|
||||||
rct::addKeys(check2, check2, Z2);
|
add_acc_p3(&check2, Z0);
|
||||||
rct::addKeys(check2, check2, rct::scalarmultH(z3));
|
add_acc_p3(&check2, Z2);
|
||||||
|
|
||||||
std::vector<MultiexpData> multiexp_data;
|
std::vector<MultiexpData> multiexp_data;
|
||||||
multiexp_data.reserve(2 * maxMN);
|
multiexp_data.reserve(2 * maxMN);
|
||||||
|
@ -1229,10 +1233,10 @@ bool bulletproof_VERIFY(const std::vector<const Bulletproof*> &proofs)
|
||||||
sc_sub(tmp.bytes, rct::zero().bytes, z5[i].bytes);
|
sc_sub(tmp.bytes, rct::zero().bytes, z5[i].bytes);
|
||||||
multiexp_data.emplace_back(tmp, Hi_p3[i]);
|
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);
|
PERF_TIMER_STOP(VERIFY_step2_check);
|
||||||
|
|
||||||
if (!(check2 == rct::identity()))
|
if (!ge_p3_is_point_at_infinity(&check2))
|
||||||
{
|
{
|
||||||
MERROR("Verification failure at step 2");
|
MERROR("Verification failure at step 2");
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -211,6 +211,20 @@ namespace rct {
|
||||||
return aP;
|
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<std::string>(__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
|
//Computes aL where L is the curve order
|
||||||
bool isInMainSubgroup(const key & a) {
|
bool isInMainSubgroup(const key & a) {
|
||||||
ge_p3 p3;
|
ge_p3 p3;
|
||||||
|
|
|
@ -122,6 +122,8 @@ namespace rct {
|
||||||
key scalarmultKey(const key &P, const key &a);
|
key scalarmultKey(const key &P, const key &a);
|
||||||
//Computes aH where H= toPoint(cn_fast_hash(G)), G the basepoint
|
//Computes aH where H= toPoint(cn_fast_hash(G)), G the basepoint
|
||||||
key scalarmultH(const key & a);
|
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)
|
// checks a is in the main subgroup (ie, not a small one)
|
||||||
bool isInMainSubgroup(const key & a);
|
bool isInMainSubgroup(const key & a);
|
||||||
|
|
||||||
|
|
|
@ -768,7 +768,7 @@ namespace rct {
|
||||||
#endif
|
#endif
|
||||||
for (i = 0; i < outamounts.size(); ++i)
|
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];
|
outSk[i].mask = masks[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -788,7 +788,7 @@ namespace rct {
|
||||||
#endif
|
#endif
|
||||||
for (i = 0; i < batch_size; ++i)
|
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];
|
outSk[i + amounts_proved].mask = masks[i];
|
||||||
}
|
}
|
||||||
amounts_proved += batch_size;
|
amounts_proved += batch_size;
|
||||||
|
|
|
@ -45,6 +45,8 @@ enum test_op
|
||||||
op_addKeys,
|
op_addKeys,
|
||||||
op_scalarmultBase,
|
op_scalarmultBase,
|
||||||
op_scalarmultKey,
|
op_scalarmultKey,
|
||||||
|
op_scalarmultH,
|
||||||
|
op_scalarmult8,
|
||||||
op_ge_double_scalarmult_base_vartime,
|
op_ge_double_scalarmult_base_vartime,
|
||||||
op_ge_double_scalarmult_precomp_vartime,
|
op_ge_double_scalarmult_precomp_vartime,
|
||||||
op_ge_double_scalarmult_precomp_vartime2,
|
op_ge_double_scalarmult_precomp_vartime2,
|
||||||
|
@ -97,6 +99,8 @@ public:
|
||||||
case op_addKeys: rct::addKeys(key, point0, point1); break;
|
case op_addKeys: rct::addKeys(key, point0, point1); break;
|
||||||
case op_scalarmultBase: rct::scalarmultBase(scalar0); break;
|
case op_scalarmultBase: rct::scalarmultBase(scalar0); break;
|
||||||
case op_scalarmultKey: rct::scalarmultKey(point0, 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_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_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;
|
case op_ge_double_scalarmult_precomp_vartime2: ge_double_scalarmult_precomp_vartime2(&tmp_p2, scalar0.bytes, precomp0, scalar1.bytes, precomp1); break;
|
||||||
|
|
|
@ -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_addKeys);
|
||||||
TEST_PERFORMANCE1(filter, p, test_crypto_ops, op_scalarmultBase);
|
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_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_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_vartime);
|
||||||
TEST_PERFORMANCE1(filter, p, test_crypto_ops, op_ge_double_scalarmult_precomp_vartime2);
|
TEST_PERFORMANCE1(filter, p, test_crypto_ops, op_ge_double_scalarmult_precomp_vartime2);
|
||||||
|
|
|
@ -1093,6 +1093,13 @@ TEST(ringct, H)
|
||||||
ASSERT_EQ(memcmp(&p3, &ge_p3_H, sizeof(ge_p3)), 0);
|
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)
|
TEST(ringct, aggregated)
|
||||||
{
|
{
|
||||||
static const size_t N_PROOFS = 16;
|
static const size_t N_PROOFS = 16;
|
||||||
|
|
Loading…
Reference in a new issue