aboutsummaryrefslogtreecommitdiff
path: root/tests/unit_tests
diff options
context:
space:
mode:
authorAlexander Blair <snipa@jagtech.io>2020-08-27 12:03:18 -0700
committerAlexander Blair <snipa@jagtech.io>2020-08-27 12:03:24 -0700
commit39a087406d20e2d2df6e9b66037a1271daef0592 (patch)
treef988a1e1a85cfc2f5db3412315619b61d7746a15 /tests/unit_tests
parentMerge pull request #6771 (diff)
parentdraft support of clsag (diff)
downloadmonero-39a087406d20e2d2df6e9b66037a1271daef0592.tar.xz
Merge pull request #6739
1660fe8a2 draft support of clsag (cslashm) 703944c4d CLSAG device support (Sarang Noether) aff87b5f6 Added balance check to MLSAG/CLSAG performance tests (Sarang Noether) f964a92c5 Updated MLSAG and CLSAG tests for consistency (Sarang Noether) 5aa1575e9 CLSAG verification performance test (Sarang Noether) 641b08c92 CLSAG optimizations (Sarang Noether) 82ee01699 Integrate CLSAGs into monero (moneromooo-monero) 8cd1d6df8 unit_tests: add ge_triple_scalarmult_base_vartime test (moneromooo-monero) 4b328c661 CLSAG signatures (Sarang Noether)
Diffstat (limited to 'tests/unit_tests')
-rw-r--r--tests/unit_tests/multiexp.cpp62
-rw-r--r--tests/unit_tests/ringct.cpp162
-rw-r--r--tests/unit_tests/serialization.cpp22
3 files changed, 245 insertions, 1 deletions
diff --git a/tests/unit_tests/multiexp.cpp b/tests/unit_tests/multiexp.cpp
index f12dd6b49..722c568da 100644
--- a/tests/unit_tests/multiexp.cpp
+++ b/tests/unit_tests/multiexp.cpp
@@ -252,3 +252,65 @@ TEST(multiexp, pippenger_cached)
ASSERT_TRUE(basic(data) == pippenger(data, cache));
}
}
+
+TEST(multiexp, scalarmult_triple)
+{
+ std::vector<rct::MultiexpData> data;
+ ge_p2 p2;
+ rct::key res;
+ ge_p3 Gp3;
+
+ ge_frombytes_vartime(&Gp3, rct::G.bytes);
+
+ static const rct::key scalars[] = {
+ rct::Z,
+ rct::I,
+ rct::L,
+ rct::EIGHT,
+ rct::INV_EIGHT,
+ };
+ static const ge_p3 points[] = {
+ ge_p3_identity,
+ ge_p3_H,
+ Gp3,
+ };
+ ge_dsmp ppre[sizeof(points) / sizeof(points[0])];
+
+ for (size_t i = 0; i < sizeof(points) / sizeof(points[0]); ++i)
+ ge_dsm_precomp(ppre[i], &points[i]);
+
+ data.resize(3);
+ for (const rct::key &x: scalars)
+ {
+ data[0].scalar = x;
+ for (const rct::key &y: scalars)
+ {
+ data[1].scalar = y;
+ for (const rct::key &z: scalars)
+ {
+ data[2].scalar = z;
+ for (size_t i = 0; i < sizeof(points) / sizeof(points[0]); ++i)
+ {
+ data[1].point = points[i];
+ for (size_t j = 0; j < sizeof(points) / sizeof(points[0]); ++j)
+ {
+ data[0].point = Gp3;
+ data[2].point = points[j];
+
+ ge_triple_scalarmult_base_vartime(&p2, data[0].scalar.bytes, data[1].scalar.bytes, ppre[i], data[2].scalar.bytes, ppre[j]);
+ ge_tobytes(res.bytes, &p2);
+ ASSERT_TRUE(basic(data) == res);
+
+ for (size_t k = 0; k < sizeof(points) / sizeof(points[0]); ++k)
+ {
+ data[0].point = points[k];
+ ge_triple_scalarmult_precomp_vartime(&p2, data[0].scalar.bytes, ppre[k], data[1].scalar.bytes, ppre[i], data[2].scalar.bytes, ppre[j]);
+ ge_tobytes(res.bytes, &p2);
+ ASSERT_TRUE(basic(data) == res);
+ }
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/tests/unit_tests/ringct.cpp b/tests/unit_tests/ringct.cpp
index 807bab64a..2388d647b 100644
--- a/tests/unit_tests/ringct.cpp
+++ b/tests/unit_tests/ringct.cpp
@@ -38,6 +38,7 @@
#include "ringct/rctSigs.h"
#include "ringct/rctOps.h"
#include "device/device.hpp"
+#include "string_tools.h"
using namespace std;
using namespace crypto;
@@ -137,6 +138,167 @@ TEST(ringct, MG_sigs)
ASSERT_FALSE(MLSAG_Ver(message, P, IIccss, R));
}
+TEST(ringct, CLSAG)
+{
+ const size_t N = 11;
+ const size_t idx = 5;
+ ctkeyV pubs;
+ key p, t, t2, u;
+ const key message = identity();
+ ctkey backup;
+ clsag clsag;
+
+ for (size_t i = 0; i < N; ++i)
+ {
+ key sk;
+ ctkey tmp;
+
+ skpkGen(sk, tmp.dest);
+ skpkGen(sk, tmp.mask);
+
+ pubs.push_back(tmp);
+ }
+
+ // 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 = 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
+ {
+ 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 = pubs[idx];
+ pubs[idx].mask = scalarmultBase(skGen());
+ try
+ {
+ 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 */ }
+ pubs[idx] = backup;
+
+ // bad p at creation
+ try
+ {
+ 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 = pubs[idx];
+ pubs[idx].dest = scalarmultBase(skGen());
+ try
+ {
+ 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 */ }
+ 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(rct::verRctCLSAGSimple(message,clsag,pubs,Cout));
+ clsag.s = sbackup;
+
+ // too few s elements
+ key backup_key;
+ backup_key = clsag.s.back();
+ clsag.s.pop_back();
+ 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(rct::verRctCLSAGSimple(message,clsag,pubs,Cout));
+ clsag.s.pop_back();
+
+ // bad s in clsag at verification
+ for (auto &s: clsag.s)
+ {
+ backup_key = s;
+ s = skGen();
+ ASSERT_FALSE(rct::verRctCLSAGSimple(message,clsag,pubs,Cout));
+ s = backup_key;
+ }
+
+ // bad c1 in clsag at verification
+ backup_key = clsag.c1;
+ clsag.c1 = skGen();
+ ASSERT_FALSE(rct::verRctCLSAGSimple(message,clsag,pubs,Cout));
+ clsag.c1 = backup_key;
+
+ // bad I in clsag at verification
+ backup_key = clsag.I;
+ clsag.I = scalarmultBase(skGen());
+ ASSERT_FALSE(rct::verRctCLSAGSimple(message,clsag,pubs,Cout));
+ clsag.I = backup_key;
+
+ // bad D in clsag at verification
+ backup_key = clsag.D;
+ clsag.D = scalarmultBase(skGen());
+ ASSERT_FALSE(rct::verRctCLSAGSimple(message,clsag,pubs,Cout));
+ clsag.D = backup_key;
+
+ // D not in main subgroup in clsag at verification
+ 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(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(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(rct::verRctCLSAGSimple(message,clsag,pubs,Cout));
+}
+
TEST(ringct, range_proofs)
{
//Ring CT Stuff
diff --git a/tests/unit_tests/serialization.cpp b/tests/unit_tests/serialization.cpp
index e730f6867..7b8a291d0 100644
--- a/tests/unit_tests/serialization.cpp
+++ b/tests/unit_tests/serialization.cpp
@@ -477,6 +477,7 @@ TEST(Serialization, serializes_ringct_types)
rct::ecdhTuple ecdh0, ecdh1;
rct::boroSig boro0, boro1;
rct::mgSig mg0, mg1;
+ rct::clsag clsag0, clsag1;
rct::Bulletproof bp0, bp1;
rct::rctSig s0, s1;
cryptonote::transaction tx0, tx1;
@@ -592,9 +593,11 @@ TEST(Serialization, serializes_ringct_types)
rct::skpkGen(Sk, Pk);
destinations.push_back(Pk);
//compute rct data with mixin 3
- const rct::RCTConfig rct_config{ rct::RangeProofPaddedBulletproof, 0 };
+ const rct::RCTConfig rct_config{ rct::RangeProofPaddedBulletproof, 2 };
s0 = rct::genRctSimple(rct::zero(), sc, pc, destinations, inamounts, amounts, amount_keys, NULL, NULL, 0, 3, rct_config, hw::get_device("default"));
+ ASSERT_FALSE(s0.p.MGs.empty());
+ ASSERT_TRUE(s0.p.CLSAGs.empty());
mg0 = s0.p.MGs[0];
ASSERT_TRUE(serialization::dump_binary(mg0, blob));
ASSERT_TRUE(serialization::parse_binary(blob, mg1));
@@ -614,6 +617,23 @@ TEST(Serialization, serializes_ringct_types)
ASSERT_TRUE(serialization::parse_binary(blob, bp1));
bp1.V = bp0.V; // this is not saved, as it is reconstructed from other tx data
ASSERT_EQ(bp0, bp1);
+
+ const rct::RCTConfig rct_config_clsag{ rct::RangeProofPaddedBulletproof, 3 };
+ s0 = rct::genRctSimple(rct::zero(), sc, pc, destinations, inamounts, amounts, amount_keys, NULL, NULL, 0, 3, rct_config_clsag, hw::get_device("default"));
+
+ ASSERT_FALSE(s0.p.CLSAGs.empty());
+ ASSERT_TRUE(s0.p.MGs.empty());
+ clsag0 = s0.p.CLSAGs[0];
+ ASSERT_TRUE(serialization::dump_binary(clsag0, blob));
+ ASSERT_TRUE(serialization::parse_binary(blob, clsag1));
+ ASSERT_TRUE(clsag0.s.size() == clsag1.s.size());
+ for (size_t n = 0; n < clsag0.s.size(); ++n)
+ {
+ ASSERT_TRUE(clsag0.s[n] == clsag1.s[n]);
+ }
+ ASSERT_TRUE(clsag0.c1 == clsag1.c1);
+ // I is not serialized, they are meant to be reconstructed
+ ASSERT_TRUE(clsag0.D == clsag1.D);
}
TEST(Serialization, portability_wallet)