From 4b328c66161d11ddb240ca9c10298b0581aaa6b5 Mon Sep 17 00:00:00 2001 From: Sarang Noether <32460187+SarangNoether@users.noreply.github.com> Date: Thu, 29 Aug 2019 11:35:12 +0000 Subject: CLSAG signatures --- tests/performance_tests/main.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'tests/performance_tests/main.cpp') diff --git a/tests/performance_tests/main.cpp b/tests/performance_tests/main.cpp index ca0528e16..b0cec464c 100644 --- a/tests/performance_tests/main.cpp +++ b/tests/performance_tests/main.cpp @@ -60,6 +60,8 @@ #include "bulletproof.h" #include "crypto_ops.h" #include "multiexp.h" +#include "sig_mlsag.h" +#include "sig_clsag.h" namespace po = boost::program_options; @@ -213,6 +215,9 @@ int main(int argc, char** argv) TEST_PERFORMANCE1(filter, p, test_cn_fast_hash, 32); TEST_PERFORMANCE1(filter, p, test_cn_fast_hash, 16384); + TEST_PERFORMANCE2(filter, p, test_sig_mlsag, 11, true); // MLSAG verification + TEST_PERFORMANCE3(filter, p, test_sig_clsag, 11, true, 0); // CLSAG verification + TEST_PERFORMANCE2(filter, p, test_ringct_mlsag, 11, false); TEST_PERFORMANCE2(filter, p, test_ringct_mlsag, 11, true); @@ -257,11 +262,15 @@ int main(int argc, char** argv) TEST_PERFORMANCE1(filter, p, test_crypto_ops, op_scalarmult8_p3); TEST_PERFORMANCE1(filter, p, test_crypto_ops, op_ge_dsm_precomp); TEST_PERFORMANCE1(filter, p, test_crypto_ops, op_ge_double_scalarmult_base_vartime); + TEST_PERFORMANCE1(filter, p, test_crypto_ops, op_ge_triple_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_triple_scalarmult_precomp_vartime); TEST_PERFORMANCE1(filter, p, test_crypto_ops, op_ge_double_scalarmult_precomp_vartime2); TEST_PERFORMANCE1(filter, p, test_crypto_ops, op_addKeys2); TEST_PERFORMANCE1(filter, p, test_crypto_ops, op_addKeys3); TEST_PERFORMANCE1(filter, p, test_crypto_ops, op_addKeys3_2); + TEST_PERFORMANCE1(filter, p, test_crypto_ops, op_addKeys_aGbBcC); + TEST_PERFORMANCE1(filter, p, test_crypto_ops, op_addKeys_aAbBcC); TEST_PERFORMANCE1(filter, p, test_crypto_ops, op_isInMainSubgroup); TEST_PERFORMANCE1(filter, p, test_crypto_ops, op_zeroCommitUncached); TEST_PERFORMANCE1(filter, p, test_crypto_ops, op_zeroCommitCached); -- cgit v1.2.3 From 641b08c920f9c68d957e13147cf9c3e329cf83f1 Mon Sep 17 00:00:00 2001 From: Sarang Noether <32460187+SarangNoether@users.noreply.github.com> Date: Tue, 10 Mar 2020 18:46:37 -0400 Subject: CLSAG optimizations --- src/ringct/rctSigs.cpp | 264 ++++++++++++++++++++------------------- src/ringct/rctSigs.h | 7 +- tests/performance_tests/main.cpp | 2 - tests/unit_tests/ringct.cpp | 166 ++++++++++++------------ 4 files changed, 221 insertions(+), 218 deletions(-) (limited to 'tests/performance_tests/main.cpp') diff --git a/src/ringct/rctSigs.cpp b/src/ringct/rctSigs.cpp index 074812156..2e56dad58 100644 --- a/src/ringct/rctSigs.cpp +++ b/src/ringct/rctSigs.cpp @@ -168,12 +168,17 @@ namespace rct { // Generate a CLSAG signature // See paper by Goodell et al. (https://eprint.iacr.org/2019/654) - clsag CLSAG_Gen(const key &message, const keyV & P, const key & p, const keyV & C, const key & z, const unsigned int l, const multisig_kLRki *kLRki, key *mscout, key *mspout) { + // + // The keys are set as follows: + // P[l] == p*G + // C[l] == z*G + // C[i] == C_nonzero[i] - C_offset (for hashing purposes) for all i + clsag CLSAG_Gen(const key &message, const keyV & P, const key & p, const keyV & C, const key & z, const keyV & C_nonzero, const key & C_offset, const unsigned int l, const multisig_kLRki *kLRki, key *mscout, key *mspout) { clsag sig; size_t n = P.size(); // ring size CHECK_AND_ASSERT_THROW_MES(n == C.size(), "Signing and commitment key vector sizes must match!"); + CHECK_AND_ASSERT_THROW_MES(n == C_nonzero.size(), "Signing and commitment key vector sizes must match!"); CHECK_AND_ASSERT_THROW_MES(l < n, "Signing index out of range!"); - CHECK_AND_ASSERT_THROW_MES(scalarmultBase(z) == C[l], "C does not match z!"); CHECK_AND_ASSERT_THROW_MES((kLRki && mscout) || (!kLRki && !mscout), "Only one of kLRki/mscout is present"); CHECK_AND_ASSERT_THROW_MES((mscout && mspout) || !kLRki, "Multisig pointers are not all present"); @@ -212,8 +217,8 @@ namespace rct { scalarmultKey(aH,H,a); // Aggregation hashes - keyV mu_P_to_hash(2*n+3); // domain, I, D, P, C - keyV mu_C_to_hash(2*n+3); // domain, I, D, P, C + keyV mu_P_to_hash(2*n+4); // domain, I, D, P, C, C_offset + keyV mu_C_to_hash(2*n+4); // domain, I, D, P, C, C_offset sc_0(mu_P_to_hash[0].bytes); memcpy(mu_P_to_hash[0].bytes,config::HASH_KEY_CLSAG_AGG_0,sizeof(config::HASH_KEY_CLSAG_AGG_0)-1); sc_0(mu_C_to_hash[0].bytes); @@ -223,40 +228,43 @@ namespace rct { mu_C_to_hash[i] = P[i-1]; } for (size_t i = n+1; i < 2*n+1; ++i) { - mu_P_to_hash[i] = C[i-n-1]; - mu_C_to_hash[i] = C[i-n-1]; + mu_P_to_hash[i] = C_nonzero[i-n-1]; + mu_C_to_hash[i] = C_nonzero[i-n-1]; } mu_P_to_hash[2*n+1] = sig.I; mu_P_to_hash[2*n+2] = sig.D; + mu_P_to_hash[2*n+3] = C_offset; mu_C_to_hash[2*n+1] = sig.I; mu_C_to_hash[2*n+2] = sig.D; + mu_C_to_hash[2*n+3] = C_offset; key mu_P, mu_C; mu_P = hash_to_scalar(mu_P_to_hash); mu_C = hash_to_scalar(mu_C_to_hash); // Initial commitment - keyV c_to_hash(2*n+4); // domain, P, C, message, aG, aH + keyV c_to_hash(2*n+5); // domain, P, C, C_offset, message, aG, aH key c; sc_0(c_to_hash[0].bytes); memcpy(c_to_hash[0].bytes,config::HASH_KEY_CLSAG_ROUND,sizeof(config::HASH_KEY_CLSAG_ROUND)-1); for (size_t i = 1; i < n+1; ++i) { c_to_hash[i] = P[i-1]; - c_to_hash[i+n] = C[i-1]; + c_to_hash[i+n] = C_nonzero[i-1]; } - c_to_hash[2*n+1] = message; + c_to_hash[2*n+1] = C_offset; + c_to_hash[2*n+2] = message; // Multisig data is present if (kLRki) { a = kLRki->k; - c_to_hash[2*n+2] = kLRki->L; - c_to_hash[2*n+3] = kLRki->R; + c_to_hash[2*n+3] = kLRki->L; + c_to_hash[2*n+4] = kLRki->R; } else { - c_to_hash[2*n+2] = aG; - c_to_hash[2*n+3] = aH; + c_to_hash[2*n+3] = aG; + c_to_hash[2*n+4] = aH; } c = hash_to_scalar(c_to_hash); @@ -295,8 +303,8 @@ namespace rct { ge_dsm_precomp(H_precomp.k, &Hi_p3); addKeys_aAbBcC(R,sig.s[i],H_precomp.k,c_p,I_precomp.k,c_c,D_precomp.k); - c_to_hash[2*n+2] = L; - c_to_hash[2*n+3] = R; + c_to_hash[2*n+3] = L; + c_to_hash[2*n+4] = R; c_new = hash_to_scalar(c_to_hash); copy(c,c_new); @@ -320,99 +328,8 @@ namespace rct { return sig; } - clsag CLSAG_Gen(const key &message, const keyV & P, const key & p, const keyV & C, const key & z, const unsigned int l) { - return CLSAG_Gen(message, P, p, C, z, l, NULL, NULL, NULL); - } - - // Verify a CLSAG signature - // See paper by Goodell et al. (https://eprint.iacr.org/2019/654) - bool CLSAG_Ver(const key &message, const keyV & P, const keyV & C, const clsag & sig) - { - size_t n = P.size(); // ring size - CHECK_AND_ASSERT_MES(n == C.size(), false, "Signing and commitment key vector sizes must match!"); - CHECK_AND_ASSERT_MES(n == sig.s.size(), false, "Signature scalar vector is the wrong size!"); - for (size_t i = 0; i < n; ++i) - CHECK_AND_ASSERT_MES(sc_check(sig.s[i].bytes) == 0, false, "Bad signature scalar!"); - CHECK_AND_ASSERT_MES(sc_check(sig.c1.bytes) == 0, false, "Bad signature commitment!"); - - key c = copy(sig.c1); - key D_8 = scalarmult8(sig.D); - geDsmp I_precomp; - geDsmp D_precomp; - precomp(I_precomp.k,sig.I); - precomp(D_precomp.k,D_8); - - // Aggregation hashes - keyV mu_P_to_hash(2*n+3); // domain, I, D, P, C - keyV mu_C_to_hash(2*n+3); // domain, I, D, P, C - sc_0(mu_P_to_hash[0].bytes); - memcpy(mu_P_to_hash[0].bytes,config::HASH_KEY_CLSAG_AGG_0,sizeof(config::HASH_KEY_CLSAG_AGG_0)-1); - sc_0(mu_C_to_hash[0].bytes); - memcpy(mu_C_to_hash[0].bytes,config::HASH_KEY_CLSAG_AGG_1,sizeof(config::HASH_KEY_CLSAG_AGG_1)-1); - for (size_t i = 1; i < n+1; ++i) { - mu_P_to_hash[i] = P[i-1]; - mu_C_to_hash[i] = P[i-1]; - } - for (size_t i = n+1; i < 2*n+1; ++i) { - mu_P_to_hash[i] = C[i-n-1]; - mu_C_to_hash[i] = C[i-n-1]; - } - mu_P_to_hash[2*n+1] = sig.I; - mu_P_to_hash[2*n+2] = sig.D; - mu_C_to_hash[2*n+1] = sig.I; - mu_C_to_hash[2*n+2] = sig.D; - key mu_P, mu_C; - mu_P = hash_to_scalar(mu_P_to_hash); - mu_C = hash_to_scalar(mu_C_to_hash); - - keyV c_to_hash(2*n+4); // domain, P, C, message, L, R - sc_0(c_to_hash[0].bytes); - memcpy(c_to_hash[0].bytes,config::HASH_KEY_CLSAG_ROUND,sizeof(config::HASH_KEY_CLSAG_ROUND)-1); - for (size_t i = 1; i < n+1; ++i) - { - c_to_hash[i] = P[i-1]; - c_to_hash[i+n] = C[i-1]; - } - c_to_hash[2*n+1] = message; - key c_p; // = c[i]*mu_P - key c_c; // = c[i]*mu_C - key c_new; - key L; - key R; - geDsmp P_precomp; - geDsmp C_precomp; - geDsmp H_precomp; - size_t i = 0; - ge_p3 hash8_p3; - geDsmp hash_precomp; - - while (i < n) { - sc_0(c_new.bytes); - sc_mul(c_p.bytes,mu_P.bytes,c.bytes); - sc_mul(c_c.bytes,mu_C.bytes,c.bytes); - - // Precompute points - precomp(P_precomp.k,P[i]); - precomp(C_precomp.k,C[i]); - - // Compute L - addKeys_aGbBcC(L,sig.s[i],c_p,P_precomp.k,c_c,C_precomp.k); - - // Compute R - hash_to_p3(hash8_p3,P[i]); - ge_dsm_precomp(hash_precomp.k, &hash8_p3); - addKeys_aAbBcC(R,sig.s[i],hash_precomp.k,c_p,I_precomp.k,c_c,D_precomp.k); - - c_to_hash[2*n+2] = L; - c_to_hash[2*n+3] = R; - c_new = hash_to_scalar(c_to_hash); - CHECK_AND_ASSERT_MES(!(c_new == rct::zero()), false, "Bad signature hash"); - copy(c,c_new); - - i = i + 1; - } - sc_sub(c_new.bytes,c.bytes,sig.c1.bytes); - return sc_isnonzero(c_new.bytes) == 0; + clsag CLSAG_Gen(const key &message, const keyV & P, const key & p, const keyV & C, const key & z, const keyV & C_nonzero, const key & C_offset, const unsigned int l) { + return CLSAG_Gen(message, P, p, C, z, C_nonzero, C_offset, l, NULL, NULL, NULL); } // MLSAG signatures @@ -816,12 +733,14 @@ namespace rct { size_t i; keyM M(cols, tmp); - keyV P, C; + keyV P, C, C_nonzero; P.reserve(pubs.size()); C.reserve(pubs.size()); + C_nonzero.reserve(pubs.size()); for (const ctkey &k: pubs) { P.push_back(k.dest); + C_nonzero.push_back(k.mask); rct::key tmp; subKeys(tmp, k.mask, Cout); C.push_back(tmp); @@ -829,7 +748,7 @@ namespace rct { sk[0] = copy(inSk.dest); sc_sub(sk[1].bytes, inSk.mask.bytes, a.bytes); - clsag result = CLSAG_Gen(message, P, sk[0], C, sk[1], index, kLRki, mscout, mspout); + clsag result = CLSAG_Gen(message, P, sk[0], C, sk[1], C_nonzero, Cout, index, kLRki, mscout, mspout); memwipe(sk.data(), sk.size() * sizeof(key)); return result; } @@ -913,29 +832,116 @@ namespace rct { catch (...) { return false; } } - bool verRctCLSAGSimple(const key &message, const clsag &clsag, const ctkeyV & pubs, const key & C) { + bool verRctCLSAGSimple(const key &message, const clsag &sig, const ctkeyV & pubs, const key & C_offset) { try { PERF_TIMER(verRctCLSAGSimple); - //setup vars - const size_t cols = pubs.size(); - CHECK_AND_ASSERT_MES(cols >= 1, false, "Empty pubs"); - keyV Pi(cols), Ci(cols); - ge_p3 Cp3; - CHECK_AND_ASSERT_MES_L1(ge_frombytes_vartime(&Cp3, C.bytes) == 0, false, "point conv failed"); - ge_cached Ccached; - ge_p3_to_cached(&Ccached, &Cp3); - ge_p1p1 p1; - //create the matrix to mg sig - for (size_t i = 0; i < cols; i++) { - Pi[i] = pubs[i].dest; - ge_p3 p3; - CHECK_AND_ASSERT_MES_L1(ge_frombytes_vartime(&p3, pubs[i].mask.bytes) == 0, false, "point conv failed"); - ge_sub(&p1, &p3, &Ccached); - ge_p1p1_to_p3(&p3, &p1); - ge_p3_tobytes(Ci[i].bytes, &p3); + const size_t n = pubs.size(); + + // Check data + CHECK_AND_ASSERT_MES(n >= 1, false, "Empty pubs"); + CHECK_AND_ASSERT_MES(n == sig.s.size(), false, "Signature scalar vector is the wrong size!"); + for (size_t i = 0; i < n; ++i) + CHECK_AND_ASSERT_MES(sc_check(sig.s[i].bytes) == 0, false, "Bad signature scalar!"); + CHECK_AND_ASSERT_MES(sc_check(sig.c1.bytes) == 0, false, "Bad signature commitment!"); + CHECK_AND_ASSERT_MES(!(sig.I == rct::identity()), false, "Bad key image!"); + + // Cache commitment offset for efficient subtraction later + ge_p3 C_offset_p3; + CHECK_AND_ASSERT_MES(ge_frombytes_vartime(&C_offset_p3, C_offset.bytes) == 0, false, "point conv failed"); + ge_cached C_offset_cached; + ge_p3_to_cached(&C_offset_cached, &C_offset_p3); + + // Prepare key images + key c = copy(sig.c1); + key D_8 = scalarmult8(sig.D); + CHECK_AND_ASSERT_MES(!(D_8 == rct::identity()), false, "Bad auxiliary key image!"); + geDsmp I_precomp; + geDsmp D_precomp; + precomp(I_precomp.k,sig.I); + precomp(D_precomp.k,D_8); + + // Aggregation hashes + keyV mu_P_to_hash(2*n+4); // domain, I, D, P, C, C_offset + keyV mu_C_to_hash(2*n+4); // domain, I, D, P, C, C_offset + sc_0(mu_P_to_hash[0].bytes); + memcpy(mu_P_to_hash[0].bytes,config::HASH_KEY_CLSAG_AGG_0,sizeof(config::HASH_KEY_CLSAG_AGG_0)-1); + sc_0(mu_C_to_hash[0].bytes); + memcpy(mu_C_to_hash[0].bytes,config::HASH_KEY_CLSAG_AGG_1,sizeof(config::HASH_KEY_CLSAG_AGG_1)-1); + for (size_t i = 1; i < n+1; ++i) { + mu_P_to_hash[i] = pubs[i-1].dest; + mu_C_to_hash[i] = pubs[i-1].dest; + } + for (size_t i = n+1; i < 2*n+1; ++i) { + mu_P_to_hash[i] = pubs[i-n-1].mask; + mu_C_to_hash[i] = pubs[i-n-1].mask; + } + mu_P_to_hash[2*n+1] = sig.I; + mu_P_to_hash[2*n+2] = sig.D; + mu_P_to_hash[2*n+3] = C_offset; + mu_C_to_hash[2*n+1] = sig.I; + mu_C_to_hash[2*n+2] = sig.D; + mu_C_to_hash[2*n+3] = C_offset; + key mu_P, mu_C; + mu_P = hash_to_scalar(mu_P_to_hash); + mu_C = hash_to_scalar(mu_C_to_hash); + + // Set up round hash + keyV c_to_hash(2*n+5); // domain, P, C, C_offset, message, L, R + sc_0(c_to_hash[0].bytes); + memcpy(c_to_hash[0].bytes,config::HASH_KEY_CLSAG_ROUND,sizeof(config::HASH_KEY_CLSAG_ROUND)-1); + for (size_t i = 1; i < n+1; ++i) + { + c_to_hash[i] = pubs[i-1].dest; + c_to_hash[i+n] = pubs[i-1].mask; + } + c_to_hash[2*n+1] = C_offset; + c_to_hash[2*n+2] = message; + key c_p; // = c[i]*mu_P + key c_c; // = c[i]*mu_C + key c_new; + key L; + key R; + geDsmp P_precomp; + geDsmp C_precomp; + geDsmp H_precomp; + size_t i = 0; + ge_p3 hash8_p3; + geDsmp hash_precomp; + ge_p3 temp_p3; + ge_p1p1 temp_p1; + + while (i < n) { + sc_0(c_new.bytes); + sc_mul(c_p.bytes,mu_P.bytes,c.bytes); + sc_mul(c_c.bytes,mu_C.bytes,c.bytes); + + // Precompute points for L/R + precomp(P_precomp.k,pubs[i].dest); + + CHECK_AND_ASSERT_MES(ge_frombytes_vartime(&temp_p3, pubs[i].mask.bytes) == 0, false, "point conv failed"); + ge_sub(&temp_p1,&temp_p3,&C_offset_cached); + ge_p1p1_to_p3(&temp_p3,&temp_p1); + ge_dsm_precomp(C_precomp.k,&temp_p3); + + // Compute L + addKeys_aGbBcC(L,sig.s[i],c_p,P_precomp.k,c_c,C_precomp.k); + + // Compute R + hash_to_p3(hash8_p3,pubs[i].dest); + ge_dsm_precomp(hash_precomp.k, &hash8_p3); + addKeys_aAbBcC(R,sig.s[i],hash_precomp.k,c_p,I_precomp.k,c_c,D_precomp.k); + + c_to_hash[2*n+3] = L; + c_to_hash[2*n+4] = R; + c_new = hash_to_scalar(c_to_hash); + CHECK_AND_ASSERT_MES(!(c_new == rct::zero()), false, "Bad signature hash"); + copy(c,c_new); + + i = i + 1; } - return CLSAG_Ver(message, Pi, Ci, clsag); + sc_sub(c_new.bytes,c.bytes,sig.c1.bytes); + return sc_isnonzero(c_new.bytes) == 0; } catch (...) { return false; } } diff --git a/src/ringct/rctSigs.h b/src/ringct/rctSigs.h index ed82f6bc5..199ad9aef 100644 --- a/src/ringct/rctSigs.h +++ b/src/ringct/rctSigs.h @@ -77,9 +77,10 @@ namespace rct { mgSig MLSAG_Gen(const key &message, const keyM & pk, const keyV & xx, const multisig_kLRki *kLRki, key *mscout, const unsigned int index, size_t dsRows, hw::device &hwdev); bool MLSAG_Ver(const key &message, const keyM &pk, const mgSig &sig, size_t dsRows); - clsag CLSAG_Gen(const key &message, const keyV & P, const key & p, const keyV & C, const key & z, const unsigned int l, const multisig_kLRki *kLRki, key *mscout, key *mspout); - clsag CLSAG_Gen(const key &message, const keyV & P, const key & p, const keyV & C, const key & z, const unsigned int l); - bool CLSAG_Ver(const key &message, const keyV & P, const keyV & C, const clsag & sig); + clsag CLSAG_Gen(const key &message, const keyV & P, const key & p, const keyV & C, const keyV & C_nonzero, const key & C_offset, const key & z, const unsigned int l, const multisig_kLRki *kLRki, key *mscout, key *mspout); + clsag CLSAG_Gen(const key &message, const keyV & P, const key & p, const keyV & C, const keyV & C_nonzero, const key & C_offset, const key & z, const unsigned int l); + clsag proveRctCLSAGSimple(const key &, const ctkeyV &, const ctkey &, const key &, const key &, const multisig_kLRki *, key *, key *, unsigned int, hw::device &); + bool verRctCLSAGSimple(const key &, const clsag &, const ctkeyV &, const key &); //proveRange and verRange //proveRange gives C, and mask such that \sumCi = C diff --git a/tests/performance_tests/main.cpp b/tests/performance_tests/main.cpp index b0cec464c..fde14b229 100644 --- a/tests/performance_tests/main.cpp +++ b/tests/performance_tests/main.cpp @@ -61,7 +61,6 @@ #include "crypto_ops.h" #include "multiexp.h" #include "sig_mlsag.h" -#include "sig_clsag.h" namespace po = boost::program_options; @@ -216,7 +215,6 @@ int main(int argc, char** argv) TEST_PERFORMANCE1(filter, p, test_cn_fast_hash, 16384); TEST_PERFORMANCE2(filter, p, test_sig_mlsag, 11, true); // MLSAG verification - TEST_PERFORMANCE3(filter, p, test_sig_clsag, 11, true, 0); // CLSAG verification TEST_PERFORMANCE2(filter, p, test_ringct_mlsag, 11, false); TEST_PERFORMANCE2(filter, p, test_ringct_mlsag, 11, true); diff --git a/tests/unit_tests/ringct.cpp b/tests/unit_tests/ringct.cpp index 75fe9ecfb..2388d647b 100644 --- a/tests/unit_tests/ringct.cpp +++ b/tests/unit_tests/ringct.cpp @@ -140,165 +140,163 @@ TEST(ringct, MG_sigs) TEST(ringct, CLSAG) { - const size_t ring_size = 11; + const size_t N = 11; const size_t idx = 5; - keyV P, C; - key p, z; + ctkeyV pubs; + key p, t, t2, u; const key message = identity(); - key backup; + ctkey backup; clsag clsag; - for (size_t i = 0; i < ring_size; ++i) + for (size_t i = 0; i < N; ++i) { - key Sk, Pk; - skpkGen(Sk, Pk); - P.push_back(Pk); - skpkGen(Sk, Pk); - C.push_back(Pk); + key sk; + ctkey tmp; + + skpkGen(sk, tmp.dest); + skpkGen(sk, tmp.mask); + + pubs.push_back(tmp); } - skpkGen(p, P[idx]); - skpkGen(z, C[idx]); - // bad p at creation - clsag = CLSAG_Gen(zero(), P, p, C, z, idx); //, hw::get_device("default")); - ASSERT_FALSE(CLSAG_Ver(message, P, C, clsag)); + // Set P[idx] + skpkGen(p, pubs[idx].dest); + + // Set C[idx] + t = skGen(); + u = skGen(); + addKeys2(pubs[idx].mask,t,u,H); + + // Set commitment offset + key Cout; + t2 = skGen(); + addKeys2(Cout,t2,u,H); + + // Prepare generation inputs + ctkey insk; + insk.dest = p; + insk.mask = t; + + // bad message + clsag = rct::proveRctCLSAGSimple(zero(),pubs,insk,t2,Cout,NULL,NULL,NULL,idx,hw::get_device("default")); + ASSERT_FALSE(rct::verRctCLSAGSimple(message,clsag,pubs,Cout)); // bad index at creation try { - clsag = CLSAG_Gen(message, P, p, C, z, (idx + 1) % ring_size); //, hw::get_device("default")); - ASSERT_FALSE(CLSAG_Ver(message, P, C, clsag)); + clsag = rct::proveRctCLSAGSimple(message,pubs,insk,t2,Cout,NULL,NULL,NULL,(idx + 1) % N,hw::get_device("default")); + ASSERT_FALSE(rct::verRctCLSAGSimple(message,clsag,pubs,Cout)); } catch (...) { /* either exception, or failure to verify above */ } // bad z at creation try { - clsag = CLSAG_Gen(message, P, p, C, skGen(), idx); //, hw::get_device("default")); - ASSERT_FALSE(CLSAG_Ver(message, P, C, clsag)); + ctkey insk2; + insk2.dest = insk.dest; + insk2.mask = skGen(); + clsag = rct::proveRctCLSAGSimple(message,pubs,insk2,t2,Cout,NULL,NULL,NULL,idx,hw::get_device("default")); + ASSERT_FALSE(rct::verRctCLSAGSimple(message,clsag,pubs,Cout)); } catch (...) { /* either exception, or failure to verify above */ } // bad C at creation - backup = C[idx]; - C[idx] = scalarmultBase(skGen()); + backup = pubs[idx]; + pubs[idx].mask = scalarmultBase(skGen()); try { - clsag = CLSAG_Gen(message, P, p, C, z, idx); //, hw::get_device("default")); - ASSERT_FALSE(CLSAG_Ver(message, P, C, clsag)); + clsag = rct::proveRctCLSAGSimple(message,pubs,insk,t2,Cout,NULL,NULL,NULL,idx,hw::get_device("default")); + ASSERT_FALSE(rct::verRctCLSAGSimple(message,clsag,pubs,Cout)); } catch (...) { /* either exception, or failure to verify above */ } - C[idx] = backup; + pubs[idx] = backup; // bad p at creation try { - clsag = CLSAG_Gen(message, P, skGen(), C, z, idx); //, hw::get_device("default")); - ASSERT_FALSE(CLSAG_Ver(message, P, C, clsag)); + ctkey insk2; + insk2.dest = skGen(); + insk2.mask = insk.mask; + clsag = rct::proveRctCLSAGSimple(message,pubs,insk2,t2,Cout,NULL,NULL,NULL,idx,hw::get_device("default")); + ASSERT_FALSE(rct::verRctCLSAGSimple(message,clsag,pubs,Cout)); } catch (...) { /* either exception, or failure to verify above */ } // bad P at creation - backup = P[idx]; - P[idx] = scalarmultBase(skGen()); + backup = pubs[idx]; + pubs[idx].dest = scalarmultBase(skGen()); try { - clsag = CLSAG_Gen(message, P, p, C, z, idx); //, hw::get_device("default")); - ASSERT_FALSE(CLSAG_Ver(message, P, C, clsag)); + clsag = rct::proveRctCLSAGSimple(message,pubs,insk,t2,Cout,NULL,NULL,NULL,idx,hw::get_device("default")); + ASSERT_FALSE(rct::verRctCLSAGSimple(message,clsag,pubs,Cout)); } catch (...) { /* either exception, or failure to verify above */ } - P[idx] = backup; - - // good - clsag = CLSAG_Gen(message, P, p, C, z, idx); //, hw::get_device("default")); - ASSERT_TRUE(CLSAG_Ver(message, P, C, clsag)); - - // bad message at verification - ASSERT_FALSE(CLSAG_Ver(zero(), P, C, clsag)); - - // bad real P at verification - backup = P[idx]; - P[idx] = scalarmultBase(skGen()); - ASSERT_FALSE(CLSAG_Ver(zero(), P, C, clsag)); - P[idx] = backup; - - // bad fake P at verification - backup = P[(idx + 1) % ring_size]; - P[(idx + 1) % ring_size] = scalarmultBase(skGen()); - ASSERT_FALSE(CLSAG_Ver(zero(), P, C, clsag)); - P[(idx + 1) % ring_size] = backup; - - // bad real C at verification - backup = C[idx]; - C[idx] = scalarmultBase(skGen()); - ASSERT_FALSE(CLSAG_Ver(zero(), P, C, clsag)); - C[idx] = backup; - - // bad fake C at verification - backup = C[(idx + 1) % ring_size]; - C[(idx + 1) % ring_size] = scalarmultBase(skGen()); - ASSERT_FALSE(CLSAG_Ver(zero(), P, C, clsag)); - C[(idx + 1) % ring_size] = backup; + pubs[idx] = backup; + + // Test correct signature + clsag = rct::proveRctCLSAGSimple(message,pubs,insk,t2,Cout,NULL,NULL,NULL,idx,hw::get_device("default")); + ASSERT_TRUE(rct::verRctCLSAGSimple(message,clsag,pubs,Cout)); // empty s auto sbackup = clsag.s; clsag.s.clear(); - ASSERT_FALSE(CLSAG_Ver(identity(), P, C, clsag)); + ASSERT_FALSE(rct::verRctCLSAGSimple(message,clsag,pubs,Cout)); clsag.s = sbackup; // too few s elements - backup = clsag.s.back(); + key backup_key; + backup_key = clsag.s.back(); clsag.s.pop_back(); - ASSERT_FALSE(CLSAG_Ver(identity(), P, C, clsag)); - clsag.s.push_back(backup); + ASSERT_FALSE(rct::verRctCLSAGSimple(message,clsag,pubs,Cout)); + clsag.s.push_back(backup_key); // too many s elements clsag.s.push_back(skGen()); - ASSERT_FALSE(CLSAG_Ver(identity(), P, C, clsag)); + ASSERT_FALSE(rct::verRctCLSAGSimple(message,clsag,pubs,Cout)); clsag.s.pop_back(); // bad s in clsag at verification for (auto &s: clsag.s) { - backup = s; + backup_key = s; s = skGen(); - ASSERT_FALSE(CLSAG_Ver(identity(), P, C, clsag)); - s = backup; + ASSERT_FALSE(rct::verRctCLSAGSimple(message,clsag,pubs,Cout)); + s = backup_key; } // bad c1 in clsag at verification - backup = clsag.c1; + backup_key = clsag.c1; clsag.c1 = skGen(); - ASSERT_FALSE(CLSAG_Ver(identity(), P, C, clsag)); - clsag.c1 = backup; + ASSERT_FALSE(rct::verRctCLSAGSimple(message,clsag,pubs,Cout)); + clsag.c1 = backup_key; // bad I in clsag at verification - backup = clsag.I; + backup_key = clsag.I; clsag.I = scalarmultBase(skGen()); - ASSERT_FALSE(CLSAG_Ver(identity(), P, C, clsag)); - clsag.I = backup; + ASSERT_FALSE(rct::verRctCLSAGSimple(message,clsag,pubs,Cout)); + clsag.I = backup_key; // bad D in clsag at verification - backup = clsag.D; + backup_key = clsag.D; clsag.D = scalarmultBase(skGen()); - ASSERT_FALSE(CLSAG_Ver(identity(), P, C, clsag)); - clsag.D = backup; + ASSERT_FALSE(rct::verRctCLSAGSimple(message,clsag,pubs,Cout)); + clsag.D = backup_key; // D not in main subgroup in clsag at verification - backup = clsag.D; + backup_key = clsag.D; rct::key x; ASSERT_TRUE(epee::string_tools::hex_to_pod("c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac03fa", x)); clsag.D = rct::addKeys(clsag.D, x); - ASSERT_FALSE(CLSAG_Ver(identity(), P, C, clsag)); - clsag.D = backup; + ASSERT_FALSE(rct::verRctCLSAGSimple(message,clsag,pubs,Cout)); + clsag.D = backup_key; // swapped I and D in clsag at verification std::swap(clsag.I, clsag.D); - ASSERT_FALSE(CLSAG_Ver(identity(), P, C, clsag)); + ASSERT_FALSE(rct::verRctCLSAGSimple(message,clsag,pubs,Cout)); std::swap(clsag.I, clsag.D); // check it's still good, in case we failed to restore - ASSERT_TRUE(CLSAG_Ver(message, P, C, clsag)); + ASSERT_TRUE(rct::verRctCLSAGSimple(message,clsag,pubs,Cout)); } TEST(ringct, range_proofs) -- cgit v1.2.3 From 5aa1575e91459e0ed787ccc88d82dc9d86d8e21c Mon Sep 17 00:00:00 2001 From: Sarang Noether <32460187+SarangNoether@users.noreply.github.com> Date: Wed, 11 Mar 2020 10:42:17 -0400 Subject: CLSAG verification performance test --- tests/performance_tests/main.cpp | 2 ++ tests/performance_tests/sig_clsag.h | 60 +++++++++++++++++++++++-------------- 2 files changed, 40 insertions(+), 22 deletions(-) (limited to 'tests/performance_tests/main.cpp') diff --git a/tests/performance_tests/main.cpp b/tests/performance_tests/main.cpp index fde14b229..dcd10703c 100644 --- a/tests/performance_tests/main.cpp +++ b/tests/performance_tests/main.cpp @@ -61,6 +61,7 @@ #include "crypto_ops.h" #include "multiexp.h" #include "sig_mlsag.h" +#include "sig_clsag.h" namespace po = boost::program_options; @@ -215,6 +216,7 @@ int main(int argc, char** argv) TEST_PERFORMANCE1(filter, p, test_cn_fast_hash, 16384); TEST_PERFORMANCE2(filter, p, test_sig_mlsag, 11, true); // MLSAG verification + TEST_PERFORMANCE2(filter, p, test_sig_clsag, 11, 1); // CLSAG verification (with commitment offset) TEST_PERFORMANCE2(filter, p, test_ringct_mlsag, 11, false); TEST_PERFORMANCE2(filter, p, test_ringct_mlsag, 11, true); diff --git a/tests/performance_tests/sig_clsag.h b/tests/performance_tests/sig_clsag.h index 2f738679c..255eac63b 100644 --- a/tests/performance_tests/sig_clsag.h +++ b/tests/performance_tests/sig_clsag.h @@ -32,14 +32,17 @@ #include "ringct/rctSigs.h" #include "cryptonote_basic/cryptonote_basic.h" +#include "device/device.hpp" #include "single_tx_test_base.h" -template +using namespace rct; + +template class test_sig_clsag : public single_tx_test_base { public: - static const size_t n = ring_size; + static const size_t N = ring_size; static const size_t loop_count = 1000; static const size_t l = index; @@ -48,36 +51,49 @@ public: if (!single_tx_test_base::init()) return false; - p = rct::skGen(); - z = rct::skGen(); - P = rct::skvGen(n); - C = rct::skvGen(n); - for (size_t i = 0 ; i < n; i++) + message = identity(); + + pubs.reserve(N); + for (size_t i = 0; i < N; i++) { - P[i] = rct::scalarmultBase(P[i]); - C[i] = rct::scalarmultBase(C[i]); + key sk; + ctkey tmp; + + skpkGen(sk, tmp.dest); + skpkGen(sk, tmp.mask); + + pubs.push_back(tmp); } - P[l] = rct::scalarmultBase(p); - C[l] = rct::scalarmultBase(z); + + key p; + skpkGen(p,pubs[l].dest); - sig = CLSAG_Gen(rct::identity(),P,p,C,z,l); + key t,u; + t = skGen(); + u = skGen(); + addKeys2(pubs[l].mask,t,u,H); + + key t2; + t2 = skGen(); + addKeys2(C_offset,t2,u,H); + + ctkey insk; + insk.dest = p; + insk.mask = t; + + sig = proveRctCLSAGSimple(message,pubs,insk,t2,C_offset,NULL,NULL,NULL,l,hw::get_device("default")); return true; } bool test() { - if (ver) - return CLSAG_Ver(rct::identity(),P,C,sig); - else - CLSAG_Gen(rct::identity(),P,p,C,z,l); - return true; + return verRctCLSAGSimple(message,sig,pubs,C_offset); } private: - rct::key p; - rct::key z; - rct::keyV P; - rct::keyV C; - rct::clsag sig; + ctkeyV pubs; + key C_offset; + clsag sig; + key message; }; -- cgit v1.2.3 From f964a92c57d53e6ae38e664a178c9b7f56dcfd4a Mon Sep 17 00:00:00 2001 From: Sarang Noether <32460187+SarangNoether@users.noreply.github.com> Date: Tue, 21 Apr 2020 00:19:13 -0400 Subject: Updated MLSAG and CLSAG tests for consistency --- tests/performance_tests/main.cpp | 14 ++++++- tests/performance_tests/sig_clsag.h | 7 +++- tests/performance_tests/sig_mlsag.h | 73 +++++++++++++++++++++++-------------- 3 files changed, 63 insertions(+), 31 deletions(-) (limited to 'tests/performance_tests/main.cpp') diff --git a/tests/performance_tests/main.cpp b/tests/performance_tests/main.cpp index dcd10703c..675a8c19f 100644 --- a/tests/performance_tests/main.cpp +++ b/tests/performance_tests/main.cpp @@ -215,8 +215,18 @@ int main(int argc, char** argv) TEST_PERFORMANCE1(filter, p, test_cn_fast_hash, 32); TEST_PERFORMANCE1(filter, p, test_cn_fast_hash, 16384); - TEST_PERFORMANCE2(filter, p, test_sig_mlsag, 11, true); // MLSAG verification - TEST_PERFORMANCE2(filter, p, test_sig_clsag, 11, 1); // CLSAG verification (with commitment offset) + TEST_PERFORMANCE2(filter, p, test_sig_mlsag, 8, 1); // MLSAG verification + TEST_PERFORMANCE2(filter, p, test_sig_mlsag, 16, 1); + TEST_PERFORMANCE2(filter, p, test_sig_mlsag, 32, 1); + TEST_PERFORMANCE2(filter, p, test_sig_mlsag, 64, 1); + TEST_PERFORMANCE2(filter, p, test_sig_mlsag, 128, 1); + TEST_PERFORMANCE2(filter, p, test_sig_mlsag, 256, 1); + TEST_PERFORMANCE2(filter, p, test_sig_clsag, 8, 1); // CLSAG verification + TEST_PERFORMANCE2(filter, p, test_sig_clsag, 16, 1); + TEST_PERFORMANCE2(filter, p, test_sig_clsag, 32, 1); + TEST_PERFORMANCE2(filter, p, test_sig_clsag, 64, 1); + TEST_PERFORMANCE2(filter, p, test_sig_clsag, 128, 1); + TEST_PERFORMANCE2(filter, p, test_sig_clsag, 256, 1); TEST_PERFORMANCE2(filter, p, test_ringct_mlsag, 11, false); TEST_PERFORMANCE2(filter, p, test_ringct_mlsag, 11, true); diff --git a/tests/performance_tests/sig_clsag.h b/tests/performance_tests/sig_clsag.h index 255eac63b..c15668adb 100644 --- a/tests/performance_tests/sig_clsag.h +++ b/tests/performance_tests/sig_clsag.h @@ -51,8 +51,9 @@ public: if (!single_tx_test_base::init()) return false; - message = identity(); + message = skGen(); + // Random signing/commitment keys pubs.reserve(N); for (size_t i = 0; i < N; i++) { @@ -65,18 +66,22 @@ public: pubs.push_back(tmp); } + // Signing key key p; skpkGen(p,pubs[l].dest); + // Commitment key key t,u; t = skGen(); u = skGen(); addKeys2(pubs[l].mask,t,u,H); + // Offset key t2; t2 = skGen(); addKeys2(C_offset,t2,u,H); + // Final signing keys ctkey insk; insk.dest = p; insk.mask = t; diff --git a/tests/performance_tests/sig_mlsag.h b/tests/performance_tests/sig_mlsag.h index fc987fcf5..c9745b504 100644 --- a/tests/performance_tests/sig_mlsag.h +++ b/tests/performance_tests/sig_mlsag.h @@ -32,56 +32,73 @@ #include "ringct/rctSigs.h" #include "cryptonote_basic/cryptonote_basic.h" +#include "device/device.hpp" #include "single_tx_test_base.h" -template +using namespace rct; + +template class test_sig_mlsag : public single_tx_test_base { public: - static const size_t cols = ring_size; - static const size_t rows = 2; // 1 spend + 1 commitment + static const size_t N = ring_size; static const size_t loop_count = 1000; + static const size_t l = index; bool init() { if (!single_tx_test_base::init()) return false; - rct::keyV xtmp = rct::skvGen(rows); - rct::keyM xm = rct::keyMInit(rows, cols);// = [[None]*N] #just used to generate test public keys - sk = rct::skvGen(rows); - P = rct::keyMInit(rows, cols);// = keyM[[None]*N] #stores the public keys; - ind = 0; // fixed spend index - for (size_t j = 0 ; j < rows ; j++) - { - for (size_t i = 0 ; i < cols ; i++) - { - xm[i][j] = rct::skGen(); - P[i][j] = rct::scalarmultBase(xm[i][j]); - } - } - for (size_t j = 0 ; j < rows ; j++) + message = skGen(); + + // Random signing/commitment keys + pubs.reserve(N); + for (size_t i = 0; i < N; i++) { - sk[j] = xm[ind][j]; + key sk; + ctkey tmp; + + skpkGen(sk, tmp.dest); + skpkGen(sk, tmp.mask); + + pubs.push_back(tmp); } - IIccss = MLSAG_Gen(rct::identity(), P, sk, NULL, NULL, ind, rows-1, hw::get_device("default")); + + // Signing key + key p; + skpkGen(p,pubs[l].dest); + + // Commitment key + key t,u; + t = skGen(); + u = skGen(); + addKeys2(pubs[l].mask,t,u,H); + + // Offset + key t2; + t2 = skGen(); + addKeys2(C_offset,t2,u,H); + + // Final signing keys + ctkey insk; + insk.dest = p; + insk.mask = t; + + sig = proveRctMGSimple(message,pubs,insk,t2,C_offset,NULL,NULL,l,hw::get_device("default")); return true; } bool test() { - if (ver) - return MLSAG_Ver(rct::identity(), P, IIccss, rows-1); - else - MLSAG_Gen(rct::identity(), P, sk, NULL, NULL, ind, rows-1, hw::get_device("default")); - return true; + return verRctMGSimple(message,sig,pubs,C_offset); } private: - rct::keyV sk; - rct::keyM P; - size_t ind; - rct::mgSig IIccss; + ctkeyV pubs; + key C_offset; + mgSig sig; + key message; }; -- cgit v1.2.3 From aff87b5f6a3eb1f41b5fb31db9b1ccb8568cc340 Mon Sep 17 00:00:00 2001 From: Sarang Noether <32460187+SarangNoether@users.noreply.github.com> Date: Tue, 12 May 2020 13:53:10 -0400 Subject: Added balance check to MLSAG/CLSAG performance tests --- tests/performance_tests/main.cpp | 26 ++--- tests/performance_tests/sig_clsag.h | 200 ++++++++++++++++++++++++------------ tests/performance_tests/sig_mlsag.h | 200 ++++++++++++++++++++++++------------ 3 files changed, 282 insertions(+), 144 deletions(-) (limited to 'tests/performance_tests/main.cpp') diff --git a/tests/performance_tests/main.cpp b/tests/performance_tests/main.cpp index 675a8c19f..e59bb52fd 100644 --- a/tests/performance_tests/main.cpp +++ b/tests/performance_tests/main.cpp @@ -215,18 +215,20 @@ int main(int argc, char** argv) TEST_PERFORMANCE1(filter, p, test_cn_fast_hash, 32); TEST_PERFORMANCE1(filter, p, test_cn_fast_hash, 16384); - TEST_PERFORMANCE2(filter, p, test_sig_mlsag, 8, 1); // MLSAG verification - TEST_PERFORMANCE2(filter, p, test_sig_mlsag, 16, 1); - TEST_PERFORMANCE2(filter, p, test_sig_mlsag, 32, 1); - TEST_PERFORMANCE2(filter, p, test_sig_mlsag, 64, 1); - TEST_PERFORMANCE2(filter, p, test_sig_mlsag, 128, 1); - TEST_PERFORMANCE2(filter, p, test_sig_mlsag, 256, 1); - TEST_PERFORMANCE2(filter, p, test_sig_clsag, 8, 1); // CLSAG verification - TEST_PERFORMANCE2(filter, p, test_sig_clsag, 16, 1); - TEST_PERFORMANCE2(filter, p, test_sig_clsag, 32, 1); - TEST_PERFORMANCE2(filter, p, test_sig_clsag, 64, 1); - TEST_PERFORMANCE2(filter, p, test_sig_clsag, 128, 1); - TEST_PERFORMANCE2(filter, p, test_sig_clsag, 256, 1); + TEST_PERFORMANCE3(filter, p, test_sig_mlsag, 4, 2, 2); // MLSAG verification + TEST_PERFORMANCE3(filter, p, test_sig_mlsag, 8, 2, 2); + TEST_PERFORMANCE3(filter, p, test_sig_mlsag, 16, 2, 2); + TEST_PERFORMANCE3(filter, p, test_sig_mlsag, 32, 2, 2); + TEST_PERFORMANCE3(filter, p, test_sig_mlsag, 64, 2, 2); + TEST_PERFORMANCE3(filter, p, test_sig_mlsag, 128, 2, 2); + TEST_PERFORMANCE3(filter, p, test_sig_mlsag, 256, 2, 2); + TEST_PERFORMANCE3(filter, p, test_sig_clsag, 4, 2, 2); // CLSAG verification + TEST_PERFORMANCE3(filter, p, test_sig_clsag, 8, 2, 2); + TEST_PERFORMANCE3(filter, p, test_sig_clsag, 16, 2, 2); + TEST_PERFORMANCE3(filter, p, test_sig_clsag, 32, 2, 2); + TEST_PERFORMANCE3(filter, p, test_sig_clsag, 64, 2, 2); + TEST_PERFORMANCE3(filter, p, test_sig_clsag, 128, 2, 2); + TEST_PERFORMANCE3(filter, p, test_sig_clsag, 256, 2, 2); TEST_PERFORMANCE2(filter, p, test_ringct_mlsag, 11, false); TEST_PERFORMANCE2(filter, p, test_ringct_mlsag, 11, true); diff --git a/tests/performance_tests/sig_clsag.h b/tests/performance_tests/sig_clsag.h index c15668adb..c59e1e869 100644 --- a/tests/performance_tests/sig_clsag.h +++ b/tests/performance_tests/sig_clsag.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2019, The Monero Project +// Copyright (c) 2014-2020, The Monero Project // // All rights reserved. // @@ -31,74 +31,142 @@ #pragma once #include "ringct/rctSigs.h" -#include "cryptonote_basic/cryptonote_basic.h" +#include "ringct/rctTypes.h" #include "device/device.hpp" -#include "single_tx_test_base.h" - using namespace rct; -template -class test_sig_clsag : public single_tx_test_base +template +class test_sig_clsag { -public: - static const size_t N = ring_size; - static const size_t loop_count = 1000; - static const size_t l = index; - - bool init() - { - if (!single_tx_test_base::init()) - return false; - - message = skGen(); - - // Random signing/commitment keys - pubs.reserve(N); - for (size_t i = 0; i < N; i++) - { - key sk; - ctkey tmp; - - skpkGen(sk, tmp.dest); - skpkGen(sk, tmp.mask); - - pubs.push_back(tmp); - } - - // Signing key - key p; - skpkGen(p,pubs[l].dest); - - // Commitment key - key t,u; - t = skGen(); - u = skGen(); - addKeys2(pubs[l].mask,t,u,H); - - // Offset - key t2; - t2 = skGen(); - addKeys2(C_offset,t2,u,H); - - // Final signing keys - ctkey insk; - insk.dest = p; - insk.mask = t; - - sig = proveRctCLSAGSimple(message,pubs,insk,t2,C_offset,NULL,NULL,NULL,l,hw::get_device("default")); - - return true; - } - - bool test() - { - return verRctCLSAGSimple(message,sig,pubs,C_offset); - } - -private: - ctkeyV pubs; - key C_offset; - clsag sig; - key message; + public: + static const size_t loop_count = 1000; + static const size_t N = a_N; + static const size_t T = a_T; + static const size_t w = a_w; + + bool init() + { + pubs.reserve(N); + pubs.resize(N); + + r = keyV(w); // M[l[u]] = Com(0,r[u]) + + a = keyV(w); // P[l[u]] = Com(a[u],s[u]) + s = keyV(w); + + Q = keyV(T); // Q[j] = Com(b[j],t[j]) + b = keyV(T); + t = keyV(T); + + // Random keys + key temp; + for (size_t k = 0; k < N; k++) + { + skpkGen(temp,pubs[k].dest); + skpkGen(temp,pubs[k].mask); + } + + // Signing and commitment keys (assumes fixed signing indices 0,1,...,w-1 for this test) + // TODO: random signing indices + C_offsets = keyV(w); // P[l[u]] - C_offsets[u] = Com(0,s[u]-s1[u]) + s1 = keyV(w); + key a_sum = zero(); + key s1_sum = zero(); + messages = keyV(w); + for (size_t u = 0; u < w; u++) + { + skpkGen(r[u],pubs[u].dest); // M[u] = Com(0,r[u]) + + a[u] = skGen(); // P[u] = Com(a[u],s[u]) + s[u] = skGen(); + addKeys2(pubs[u].mask,s[u],a[u],H); + + s1[u] = skGen(); // C_offsets[u] = Com(a[u],s1[u]) + addKeys2(C_offsets[u],s1[u],a[u],H); + + sc_add(a_sum.bytes,a_sum.bytes,a[u].bytes); + sc_add(s1_sum.bytes,s1_sum.bytes,s1[u].bytes); + + messages[u] = skGen(); + } + + // Outputs + key b_sum = zero(); + key t_sum = zero(); + for (size_t j = 0; j < T-1; j++) + { + b[j] = skGen(); // Q[j] = Com(b[j],t[j]) + t[j] = skGen(); + addKeys2(Q[j],t[j],b[j],H); + + sc_add(b_sum.bytes,b_sum.bytes,b[j].bytes); + sc_add(t_sum.bytes,t_sum.bytes,t[j].bytes); + } + // Value/mask balance for Q[T-1] + sc_sub(b[T-1].bytes,a_sum.bytes,b_sum.bytes); + sc_sub(t[T-1].bytes,s1_sum.bytes,t_sum.bytes); + addKeys2(Q[T-1],t[T-1],b[T-1],H); + + // Build proofs + sigs.reserve(w); + sigs.resize(0); + ctkey sk; + for (size_t u = 0; u < w; u++) + { + sk.dest = r[u]; + sk.mask = s[u]; + + sigs.push_back(proveRctCLSAGSimple(messages[u],pubs,sk,s1[u],C_offsets[u],NULL,NULL,NULL,u,hw::get_device("default"))); + } + + return true; + } + + bool test() + { + for (size_t u = 0; u < w; u++) + { + if (!verRctCLSAGSimple(messages[u],sigs[u],pubs,C_offsets[u])) + { + return false; + } + } + + // Check balanace + std::vector balance; + balance.reserve(w + T); + balance.resize(0); + key ZERO = zero(); + key ONE = identity(); + key MINUS_ONE; + sc_sub(MINUS_ONE.bytes,ZERO.bytes,ONE.bytes); + for (size_t u = 0; u < w; u++) + { + balance.push_back({ONE,C_offsets[u]}); + } + for (size_t j = 0; j < T; j++) + { + balance.push_back({MINUS_ONE,Q[j]}); + } + if (!(straus(balance) == ONE)) // group identity + { + return false; + } + + return true; + } + + private: + ctkeyV pubs; + keyV Q; + keyV r; + keyV s; + keyV s1; + keyV t; + keyV a; + keyV b; + keyV C_offsets; + keyV messages; + std::vector sigs; }; diff --git a/tests/performance_tests/sig_mlsag.h b/tests/performance_tests/sig_mlsag.h index c9745b504..89645e155 100644 --- a/tests/performance_tests/sig_mlsag.h +++ b/tests/performance_tests/sig_mlsag.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2019, The Monero Project +// Copyright (c) 2014-2020, The Monero Project // // All rights reserved. // @@ -31,74 +31,142 @@ #pragma once #include "ringct/rctSigs.h" -#include "cryptonote_basic/cryptonote_basic.h" +#include "ringct/rctTypes.h" #include "device/device.hpp" -#include "single_tx_test_base.h" - using namespace rct; -template -class test_sig_mlsag : public single_tx_test_base +template +class test_sig_mlsag { -public: - static const size_t N = ring_size; - static const size_t loop_count = 1000; - static const size_t l = index; - - bool init() - { - if (!single_tx_test_base::init()) - return false; - - message = skGen(); - - // Random signing/commitment keys - pubs.reserve(N); - for (size_t i = 0; i < N; i++) - { - key sk; - ctkey tmp; - - skpkGen(sk, tmp.dest); - skpkGen(sk, tmp.mask); - - pubs.push_back(tmp); - } - - // Signing key - key p; - skpkGen(p,pubs[l].dest); - - // Commitment key - key t,u; - t = skGen(); - u = skGen(); - addKeys2(pubs[l].mask,t,u,H); - - // Offset - key t2; - t2 = skGen(); - addKeys2(C_offset,t2,u,H); - - // Final signing keys - ctkey insk; - insk.dest = p; - insk.mask = t; - - sig = proveRctMGSimple(message,pubs,insk,t2,C_offset,NULL,NULL,l,hw::get_device("default")); - - return true; - } - - bool test() - { - return verRctMGSimple(message,sig,pubs,C_offset); - } - -private: - ctkeyV pubs; - key C_offset; - mgSig sig; - key message; + public: + static const size_t loop_count = 1000; + static const size_t N = a_N; + static const size_t T = a_T; + static const size_t w = a_w; + + bool init() + { + pubs.reserve(N); + pubs.resize(N); + + r = keyV(w); // M[l[u]] = Com(0,r[u]) + + a = keyV(w); // P[l[u]] = Com(a[u],s[u]) + s = keyV(w); + + Q = keyV(T); // Q[j] = Com(b[j],t[j]) + b = keyV(T); + t = keyV(T); + + // Random keys + key temp; + for (size_t k = 0; k < N; k++) + { + skpkGen(temp,pubs[k].dest); + skpkGen(temp,pubs[k].mask); + } + + // Signing and commitment keys (assumes fixed signing indices 0,1,...,w-1 for this test) + // TODO: random signing indices + C_offsets = keyV(w); // P[l[u]] - C_offsets[u] = Com(0,s[u]-s1[u]) + s1 = keyV(w); + key a_sum = zero(); + key s1_sum = zero(); + messages = keyV(w); + for (size_t u = 0; u < w; u++) + { + skpkGen(r[u],pubs[u].dest); // M[u] = Com(0,r[u]) + + a[u] = skGen(); // P[u] = Com(a[u],s[u]) + s[u] = skGen(); + addKeys2(pubs[u].mask,s[u],a[u],H); + + s1[u] = skGen(); // C_offsets[u] = Com(a[u],s1[u]) + addKeys2(C_offsets[u],s1[u],a[u],H); + + sc_add(a_sum.bytes,a_sum.bytes,a[u].bytes); + sc_add(s1_sum.bytes,s1_sum.bytes,s1[u].bytes); + + messages[u] = skGen(); + } + + // Outputs + key b_sum = zero(); + key t_sum = zero(); + for (size_t j = 0; j < T-1; j++) + { + b[j] = skGen(); // Q[j] = Com(b[j],t[j]) + t[j] = skGen(); + addKeys2(Q[j],t[j],b[j],H); + + sc_add(b_sum.bytes,b_sum.bytes,b[j].bytes); + sc_add(t_sum.bytes,t_sum.bytes,t[j].bytes); + } + // Value/mask balance for Q[T-1] + sc_sub(b[T-1].bytes,a_sum.bytes,b_sum.bytes); + sc_sub(t[T-1].bytes,s1_sum.bytes,t_sum.bytes); + addKeys2(Q[T-1],t[T-1],b[T-1],H); + + // Build proofs + sigs.reserve(w); + sigs.resize(0); + ctkey sk; + for (size_t u = 0; u < w; u++) + { + sk.dest = r[u]; + sk.mask = s[u]; + + sigs.push_back(proveRctMGSimple(messages[u],pubs,sk,s1[u],C_offsets[u],NULL,NULL,u,hw::get_device("default"))); + } + + return true; + } + + bool test() + { + for (size_t u = 0; u < w; u++) + { + if (!verRctMGSimple(messages[u],sigs[u],pubs,C_offsets[u])) + { + return false; + } + } + + // Check balanace + std::vector balance; + balance.reserve(w + T); + balance.resize(0); + key ZERO = zero(); + key ONE = identity(); + key MINUS_ONE; + sc_sub(MINUS_ONE.bytes,ZERO.bytes,ONE.bytes); + for (size_t u = 0; u < w; u++) + { + balance.push_back({ONE,C_offsets[u]}); + } + for (size_t j = 0; j < T; j++) + { + balance.push_back({MINUS_ONE,Q[j]}); + } + if (!(straus(balance) == ONE)) // group identity + { + return false; + } + + return true; + } + + private: + ctkeyV pubs; + keyV Q; + keyV r; + keyV s; + keyV s1; + keyV t; + keyV a; + keyV b; + keyV C_offsets; + keyV messages; + std::vector sigs; }; -- cgit v1.2.3