aboutsummaryrefslogtreecommitdiffstats
path: root/vendor/github.com/tangerine-network/mcl/test
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/tangerine-network/mcl/test')
-rw-r--r--vendor/github.com/tangerine-network/mcl/test/aggregate_sig_test.cpp74
-rw-r--r--vendor/github.com/tangerine-network/mcl/test/array_test.cpp104
-rw-r--r--vendor/github.com/tangerine-network/mcl/test/base_test.cpp392
-rw-r--r--vendor/github.com/tangerine-network/mcl/test/bench.hpp192
-rw-r--r--vendor/github.com/tangerine-network/mcl/test/bls12_test.cpp720
-rw-r--r--vendor/github.com/tangerine-network/mcl/test/bn384_test.cpp83
-rw-r--r--vendor/github.com/tangerine-network/mcl/test/bn512_test.cpp68
-rw-r--r--vendor/github.com/tangerine-network/mcl/test/bn_c256_test.cpp6
-rw-r--r--vendor/github.com/tangerine-network/mcl/test/bn_c384_256_test.cpp7
-rw-r--r--vendor/github.com/tangerine-network/mcl/test/bn_c384_test.cpp6
-rw-r--r--vendor/github.com/tangerine-network/mcl/test/bn_c512_test.cpp6
-rw-r--r--vendor/github.com/tangerine-network/mcl/test/bn_c_test.hpp699
-rw-r--r--vendor/github.com/tangerine-network/mcl/test/bn_test.cpp408
-rw-r--r--vendor/github.com/tangerine-network/mcl/test/conversion_test.cpp96
-rw-r--r--vendor/github.com/tangerine-network/mcl/test/ec_test.cpp573
-rw-r--r--vendor/github.com/tangerine-network/mcl/test/ecdsa_c_test.cpp51
-rw-r--r--vendor/github.com/tangerine-network/mcl/test/ecdsa_test.cpp69
-rw-r--r--vendor/github.com/tangerine-network/mcl/test/elgamal_test.cpp155
-rw-r--r--vendor/github.com/tangerine-network/mcl/test/fp_generator_test.cpp207
-rw-r--r--vendor/github.com/tangerine-network/mcl/test/fp_test.cpp1046
-rw-r--r--vendor/github.com/tangerine-network/mcl/test/fp_tower_test.cpp477
-rw-r--r--vendor/github.com/tangerine-network/mcl/test/fp_util_test.cpp270
-rw-r--r--vendor/github.com/tangerine-network/mcl/test/glv_test.cpp209
-rw-r--r--vendor/github.com/tangerine-network/mcl/test/gmp_test.cpp70
-rw-r--r--vendor/github.com/tangerine-network/mcl/test/low_test.cpp73
-rw-r--r--vendor/github.com/tangerine-network/mcl/test/mk32.sh1
-rw-r--r--vendor/github.com/tangerine-network/mcl/test/modp_test.cpp37
-rw-r--r--vendor/github.com/tangerine-network/mcl/test/mont_fp_test.cpp332
-rw-r--r--vendor/github.com/tangerine-network/mcl/test/paillier_test.cpp24
-rw-r--r--vendor/github.com/tangerine-network/mcl/test/proj/bn_test/bn_test.vcxproj88
-rw-r--r--vendor/github.com/tangerine-network/mcl/test/proj/ec_test/ec_test.vcxproj88
-rw-r--r--vendor/github.com/tangerine-network/mcl/test/proj/fp_test/fp_test.vcxproj88
-rw-r--r--vendor/github.com/tangerine-network/mcl/test/proj/fp_tower_test/fp_tower_test.vcxproj88
-rw-r--r--vendor/github.com/tangerine-network/mcl/test/she_c256_test.cpp2
-rw-r--r--vendor/github.com/tangerine-network/mcl/test/she_c384_test.cpp2
-rw-r--r--vendor/github.com/tangerine-network/mcl/test/she_c_test.hpp535
-rw-r--r--vendor/github.com/tangerine-network/mcl/test/she_test.cpp756
-rw-r--r--vendor/github.com/tangerine-network/mcl/test/sq_test.cpp21
-rw-r--r--vendor/github.com/tangerine-network/mcl/test/vint_test.cpp1353
-rw-r--r--vendor/github.com/tangerine-network/mcl/test/window_method_test.cpp70
40 files changed, 9546 insertions, 0 deletions
diff --git a/vendor/github.com/tangerine-network/mcl/test/aggregate_sig_test.cpp b/vendor/github.com/tangerine-network/mcl/test/aggregate_sig_test.cpp
new file mode 100644
index 000000000..c3a0e758d
--- /dev/null
+++ b/vendor/github.com/tangerine-network/mcl/test/aggregate_sig_test.cpp
@@ -0,0 +1,74 @@
+//#define MCLBN_FP_UNIT_SIZE 8
+#include <cybozu/test.hpp>
+#include <mcl/aggregate_sig.hpp>
+#include <cybozu/benchmark.hpp>
+#include <cybozu/xorshift.hpp>
+
+using namespace mcl::aggs;
+
+CYBOZU_TEST_AUTO(init)
+{
+ AGGS::init();
+// AGGS::init(mcl::BN381_1);
+// AGGS::init(mcl::BLS12_381);
+ SecretKey sec;
+ sec.init();
+ PublicKey pub;
+ sec.getPublicKey(pub);
+ const std::string m = "abc";
+ Signature sig;
+ sec.sign(sig, m);
+ CYBOZU_TEST_ASSERT(pub.verify(sig, m));
+}
+
+void aggregateTest(const std::vector<std::string>& msgVec)
+{
+ const size_t n = msgVec.size();
+ std::vector<SecretKey> secVec(n);
+ std::vector<PublicKey> pubVec(n);
+ std::vector<Signature> sigVec(n);
+ Signature aggSig;
+ for (size_t i = 0; i < n; i++) {
+ secVec[i].init();
+ secVec[i].getPublicKey(pubVec[i]);
+ secVec[i].sign(sigVec[i], msgVec[i]);
+ CYBOZU_TEST_ASSERT(pubVec[i].verify(sigVec[i], msgVec[i]));
+ }
+ aggSig.aggregate(sigVec);
+ CYBOZU_TEST_ASSERT(aggSig.verify(msgVec, pubVec));
+ CYBOZU_BENCH_C("aggSig.verify", 10, aggSig.verify, msgVec, pubVec);
+}
+
+CYBOZU_TEST_AUTO(aggregate)
+{
+#if 0
+ /*
+ Core i7-7700 CPU @ 3.60GHz
+ BN254 Fp382 Fp462
+ security bit 100 115? 128
+ # of sig 100 69 200 476
+ 1000 693 2037 4731
+ 10000 6969 20448 47000(Mclk)
+ */
+ const size_t n = 1000;
+ const size_t msgSize = 16;
+ std::vector<std::string> msgVec(n);
+ cybozu::XorShift rg;
+ for (size_t i = 0; i < n; i++) {
+ std::string& msg = msgVec[i];
+ msg.resize(msgSize);
+ for (size_t j = 0; j < msgSize; j++) {
+ msg[j] = (char)rg();
+ }
+ }
+ aggregateTest(msgVec);
+#else
+ const std::string msgArray[] = { "abc", "12345", "xyz", "pqr", "aggregate signature" };
+ const size_t n = sizeof(msgArray) / sizeof(msgArray[0]);
+ std::vector<std::string> msgVec(n);
+ for (size_t i = 0; i < n; i++) {
+ msgVec[i] = msgArray[i];
+ }
+ aggregateTest(msgVec);
+#endif
+}
diff --git a/vendor/github.com/tangerine-network/mcl/test/array_test.cpp b/vendor/github.com/tangerine-network/mcl/test/array_test.cpp
new file mode 100644
index 000000000..2168a28fa
--- /dev/null
+++ b/vendor/github.com/tangerine-network/mcl/test/array_test.cpp
@@ -0,0 +1,104 @@
+#include <mcl/array.hpp>
+#include <cybozu/test.hpp>
+
+template<class Array, size_t n>
+void setArray(Array& a, const int (&tbl)[n])
+{
+ CYBOZU_TEST_ASSERT(a.resize(n));
+ for (size_t i = 0; i < n; i++) a[i] = tbl[i];
+}
+
+template<class Array, size_t an, size_t bn>
+void swapTest(const int (&a)[an], const int (&b)[bn])
+{
+ Array s, t;
+ setArray(s, a);
+ setArray(t, b);
+ s.swap(t);
+ CYBOZU_TEST_EQUAL(s.size(), bn);
+ CYBOZU_TEST_EQUAL(t.size(), an);
+ CYBOZU_TEST_EQUAL_ARRAY(s, b, s.size());
+ CYBOZU_TEST_EQUAL_ARRAY(t, a, t.size());
+}
+
+CYBOZU_TEST_AUTO(resize)
+{
+ mcl::Array<int> a, b;
+ CYBOZU_TEST_EQUAL(a.size(), 0);
+ CYBOZU_TEST_EQUAL(b.size(), 0);
+
+ const size_t n = 5;
+ bool ok = a.resize(n);
+ CYBOZU_TEST_ASSERT(ok);
+ CYBOZU_TEST_EQUAL(n, a.size());
+ for (size_t i = 0; i < n; i++) {
+ a[i] = i;
+ }
+ ok = b.copy(a);
+ CYBOZU_TEST_ASSERT(ok);
+ CYBOZU_TEST_EQUAL(b.size(), n);
+ CYBOZU_TEST_EQUAL_ARRAY(a.data(), b.data(), n);
+
+ const size_t small = n - 1;
+ ok = b.resize(small);
+ CYBOZU_TEST_ASSERT(ok);
+ CYBOZU_TEST_EQUAL(b.size(), small);
+ CYBOZU_TEST_EQUAL_ARRAY(a.data(), b.data(), small);
+ const size_t large = n * 2;
+ ok = b.resize(large);
+ CYBOZU_TEST_ASSERT(ok);
+ CYBOZU_TEST_EQUAL(b.size(), large);
+ CYBOZU_TEST_EQUAL_ARRAY(a.data(), b.data(), small);
+
+ const int aTbl[] = { 3, 4 };
+ const int bTbl[] = { 7, 6, 5, 3 };
+ swapTest<mcl::Array<int> >(aTbl, bTbl);
+ swapTest<mcl::Array<int> >(bTbl, aTbl);
+}
+
+CYBOZU_TEST_AUTO(FixedArray)
+{
+ const size_t n = 5;
+ mcl::FixedArray<int, n> a, b;
+ CYBOZU_TEST_EQUAL(a.size(), 0);
+ CYBOZU_TEST_EQUAL(b.size(), 0);
+
+ bool ok = a.resize(n);
+ CYBOZU_TEST_ASSERT(ok);
+ CYBOZU_TEST_EQUAL(n, a.size());
+ for (size_t i = 0; i < n; i++) {
+ a[i] = i;
+ }
+ ok = b.copy(a);
+ CYBOZU_TEST_ASSERT(ok);
+ CYBOZU_TEST_EQUAL(b.size(), n);
+ CYBOZU_TEST_EQUAL_ARRAY(a.data(), b.data(), n);
+
+ const size_t small = n - 1;
+ ok = b.resize(small);
+ CYBOZU_TEST_ASSERT(ok);
+ CYBOZU_TEST_EQUAL(b.size(), small);
+ CYBOZU_TEST_EQUAL_ARRAY(a.data(), b.data(), small);
+ const size_t large = n + 1;
+ ok = b.resize(large);
+ CYBOZU_TEST_ASSERT(!ok);
+
+ const int aTbl[] = { 3, 4 };
+ const int bTbl[] = { 7, 6, 5, 3 };
+ swapTest<mcl::FixedArray<int, n> >(aTbl, bTbl);
+ swapTest<mcl::FixedArray<int, n> >(bTbl, aTbl);
+}
+
+#ifndef CYBOZU_DONT_USE_EXCEPTION
+CYBOZU_TEST_AUTO(assign)
+{
+ const int aTbl[] = { 3, 4, 2 };
+ const int bTbl[] = { 3, 4, 2, 1, 5 };
+ mcl::Array<int> a, b;
+ setArray(a, aTbl);
+ setArray(b, bTbl);
+ a = b;
+ CYBOZU_TEST_EQUAL(a.size(), b.size());
+ CYBOZU_TEST_EQUAL_ARRAY(a.data(), b.data(), a.size());
+}
+#endif
diff --git a/vendor/github.com/tangerine-network/mcl/test/base_test.cpp b/vendor/github.com/tangerine-network/mcl/test/base_test.cpp
new file mode 100644
index 000000000..2733d17ca
--- /dev/null
+++ b/vendor/github.com/tangerine-network/mcl/test/base_test.cpp
@@ -0,0 +1,392 @@
+// not compiled
+#include <map>
+#include <mcl/op.hpp>
+#include <cybozu/test.hpp>
+#include <cybozu/benchmark.hpp>
+#include <cybozu/xorshift.hpp>
+#include <cybozu/bit_operation.hpp>
+#include <mcl/conversion.hpp>
+#include <mcl/fp.hpp>
+
+#include "../src/fp_generator.hpp"
+#if (CYBOZU_HOST == CYBOZU_HOST_INTEL) && (MCL_SIZEOF_UNIT == 8)
+ #define USE_XBYAK
+ static mcl::FpGenerator fg;
+#endif
+#define PUT(x) std::cout << #x "=" << (x) << std::endl
+
+const size_t MAX_N = 32;
+typedef mcl::fp::Unit Unit;
+
+size_t getUnitSize(size_t bitSize)
+{
+ return (bitSize + sizeof(Unit) * 8 - 1) / (sizeof(Unit) * 8);
+}
+
+void setMpz(mpz_class& mx, const Unit *x, size_t n)
+{
+ mcl::gmp::setArray(mx, x, n);
+}
+void getMpz(Unit *x, size_t n, const mpz_class& mx)
+{
+ mcl::fp::toArray(x, n, mx.get_mpz_t());
+}
+
+struct Montgomery {
+ mpz_class p_;
+ mpz_class R_; // (1 << (n_ * 64)) % p
+ mpz_class RR_; // (R * R) % p
+ Unit r_; // p * r = -1 mod M = 1 << 64
+ size_t n_;
+ Montgomery() {}
+ explicit Montgomery(const mpz_class& p)
+ {
+ p_ = p;
+ r_ = mcl::montgomery::getCoff(mcl::gmp::getUnit(p, 0));
+ n_ = mcl::gmp::getUnitSize(p);
+ R_ = 1;
+ R_ = (R_ << (n_ * 64)) % p_;
+ RR_ = (R_ * R_) % p_;
+ }
+
+ void toMont(mpz_class& x) const { mul(x, x, RR_); }
+ void fromMont(mpz_class& x) const { mul(x, x, 1); }
+
+ void mont(Unit *z, const Unit *x, const Unit *y) const
+ {
+ mpz_class mx, my;
+ setMpz(mx, x, n_);
+ setMpz(my, y, n_);
+ mul(mx, mx, my);
+ getMpz(z, n_, mx);
+ }
+ void mul(mpz_class& z, const mpz_class& x, const mpz_class& y) const
+ {
+#if 1
+ const size_t ySize = mcl::gmp::getUnitSize(y);
+ mpz_class c = y == 0 ? mpz_class(0) : x * mcl::gmp::getUnit(y, 0);
+ Unit q = c == 0 ? 0 : mcl::gmp::getUnit(c, 0) * r_;
+ c += p_ * q;
+ c >>= sizeof(Unit) * 8;
+ for (size_t i = 1; i < n_; i++) {
+ if (i < ySize) {
+ c += x * mcl::gmp::getUnit(y, i);
+ }
+ Unit q = c == 0 ? 0 : mcl::gmp::getUnit(c, 0) * r_;
+ c += p_ * q;
+ c >>= sizeof(Unit) * 8;
+ }
+ if (c >= p_) {
+ c -= p_;
+ }
+ z = c;
+#else
+ z = x * y;
+ const size_t zSize = mcl::gmp::getUnitSize(z);
+ for (size_t i = 0; i < n_; i++) {
+ if (i < zSize) {
+ Unit q = mcl::gmp::getUnit(z, 0) * r_;
+ z += p_ * (mp_limb_t)q;
+ }
+ z >>= sizeof(Unit) * 8;
+ }
+ if (z >= p_) {
+ z -= p_;
+ }
+#endif
+ }
+};
+
+void put(const char *msg, const Unit *x, size_t n)
+{
+ printf("%s ", msg);
+ for (size_t i = 0; i < n; i++) printf("%016llx ", (long long)x[n - 1 - i]);
+ printf("\n");
+}
+void verifyEqual(const Unit *x, const Unit *y, size_t n, const char *file, int line)
+{
+ bool ok = mcl::fp::isEqualArray(x, y, n);
+ CYBOZU_TEST_ASSERT(ok);
+ if (ok) return;
+ printf("%s:%d\n", file, line);
+ put("L", x, n);
+ put("R", y, n);
+ exit(1);
+}
+#define VERIFY_EQUAL(x, y, n) verifyEqual(x, y, n, __FILE__, __LINE__)
+
+void addC(Unit *z, const Unit *x, const Unit *y, const Unit *p, size_t n)
+{
+ mpz_class mx, my, mp;
+ setMpz(mx, x, n);
+ setMpz(my, y, n);
+ setMpz(mp, p, n);
+ mx += my;
+ if (mx >= mp) mx -= mp;
+ getMpz(z, n, mx);
+}
+void subC(Unit *z, const Unit *x, const Unit *y, const Unit *p, size_t n)
+{
+ mpz_class mx, my, mp;
+ setMpz(mx, x, n);
+ setMpz(my, y, n);
+ setMpz(mp, p, n);
+ mx -= my;
+ if (mx < 0) mx += mp;
+ getMpz(z, n, mx);
+}
+static inline void set_zero(mpz_t& z, Unit *p, size_t n)
+{
+ z->_mp_alloc = (int)n;
+ z->_mp_size = 0;
+ z->_mp_d = (mp_limb_t*)p;
+}
+static inline void set_mpz_t(mpz_t& z, const Unit* p, int n)
+{
+ z->_mp_alloc = n;
+ int i = n;
+ while (i > 0 && p[i - 1] == 0) {
+ i--;
+ }
+ z->_mp_size = i;
+ z->_mp_d = (mp_limb_t*)p;
+}
+
+// z[2n] <- x[n] * y[n]
+void mulPreC(Unit *z, const Unit *x, const Unit *y, size_t n)
+{
+#if 1
+ mpz_t mx, my, mz;
+ set_zero(mz, z, n * 2);
+ set_mpz_t(mx, x, n);
+ set_mpz_t(my, y, n);
+ mpz_mul(mz, mx, my);
+ mcl::fp::toArray(z, n * 2, mz);
+#else
+ mpz_class mx, my;
+ setMpz(mx, x, n);
+ setMpz(my, y, n);
+ mx *= my;
+ getMpz(z, n * 2, mx);
+#endif
+}
+
+void modC(Unit *y, const Unit *x, const Unit *p, size_t n)
+{
+ mpz_t mx, my, mp;
+ set_mpz_t(mx, x, n * 2);
+ set_mpz_t(my, y, n);
+ set_mpz_t(mp, p, n);
+ mpz_mod(my, mx, mp);
+ mcl::fp::clearArray(y, my->_mp_size, n);
+}
+
+void mul(Unit *z, const Unit *x, const Unit *y, const Unit *p, size_t n)
+{
+ Unit ret[MAX_N * 2];
+ mpz_t mx, my, mz, mp;
+ set_zero(mz, ret, MAX_N * 2);
+ set_mpz_t(mx, x, n);
+ set_mpz_t(my, y, n);
+ set_mpz_t(mp, p, n);
+ mpz_mul(mz, mx, my);
+ mpz_mod(mz, mz, mp);
+ mcl::fp::toArray(z, n, mz);
+}
+
+typedef mcl::fp::void3op void3op;
+typedef mcl::fp::void4op void4op;
+typedef mcl::fp::void4Iop void4Iop;
+
+const struct FuncOp {
+ size_t bitSize;
+ void4op addS;
+ void4op addL;
+ void4op subS;
+ void4op subL;
+ void3op mulPre;
+ void4Iop mont;
+} gFuncOpTbl[] = {
+ { 128, mcl_fp_add128S, mcl_fp_add128L, mcl_fp_sub128S, mcl_fp_sub128L, mcl_fp_mul128pre, mcl_fp_mont128 },
+ { 192, mcl_fp_add192S, mcl_fp_add192L, mcl_fp_sub192S, mcl_fp_sub192L, mcl_fp_mul192pre, mcl_fp_mont192 },
+ { 256, mcl_fp_add256S, mcl_fp_add256L, mcl_fp_sub256S, mcl_fp_sub256L, mcl_fp_mul256pre, mcl_fp_mont256 },
+ { 320, mcl_fp_add320S, mcl_fp_add320L, mcl_fp_sub320S, mcl_fp_sub320L, mcl_fp_mul320pre, mcl_fp_mont320 },
+ { 384, mcl_fp_add384S, mcl_fp_add384L, mcl_fp_sub384S, mcl_fp_sub384L, mcl_fp_mul384pre, mcl_fp_mont384 },
+ { 448, mcl_fp_add448S, mcl_fp_add448L, mcl_fp_sub448S, mcl_fp_sub448L, mcl_fp_mul448pre, mcl_fp_mont448 },
+ { 512, mcl_fp_add512S, mcl_fp_add512L, mcl_fp_sub512S, mcl_fp_sub512L, mcl_fp_mul512pre, mcl_fp_mont512 },
+#if MCL_SIZEOF_UNIT == 4
+ { 160, mcl_fp_add160S, mcl_fp_add160L, mcl_fp_sub160S, mcl_fp_sub160L, mcl_fp_mul160pre, mcl_fp_mont160 },
+ { 224, mcl_fp_add224S, mcl_fp_add224L, mcl_fp_sub224S, mcl_fp_sub224L, mcl_fp_mul224pre, mcl_fp_mont224 },
+ { 288, mcl_fp_add288S, mcl_fp_add288L, mcl_fp_sub288S, mcl_fp_sub288L, mcl_fp_mul288pre, mcl_fp_mont288 },
+ { 352, mcl_fp_add352S, mcl_fp_add352L, mcl_fp_sub352S, mcl_fp_sub352L, mcl_fp_mul352pre, mcl_fp_mont352 },
+ { 416, mcl_fp_add416S, mcl_fp_add416L, mcl_fp_sub416S, mcl_fp_sub416L, mcl_fp_mul416pre, mcl_fp_mont416 },
+ { 480, mcl_fp_add480S, mcl_fp_add480L, mcl_fp_sub480S, mcl_fp_sub480L, mcl_fp_mul480pre, mcl_fp_mont480 },
+ { 544, mcl_fp_add544S, mcl_fp_add544L, mcl_fp_sub544S, mcl_fp_sub544L, mcl_fp_mul544pre, mcl_fp_mont544 },
+#else
+ { 576, mcl_fp_add576S, mcl_fp_add576L, mcl_fp_sub576S, mcl_fp_sub576L, mcl_fp_mul576pre, mcl_fp_mont576 },
+#endif
+};
+
+FuncOp getFuncOp(size_t bitSize)
+{
+ typedef std::map<size_t, FuncOp> Map;
+ static Map map;
+ static bool init = false;
+ if (!init) {
+ init = true;
+ for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(gFuncOpTbl); i++) {
+ map[gFuncOpTbl[i].bitSize] = gFuncOpTbl[i];
+ }
+ }
+ for (Map::const_iterator i = map.begin(), ie = map.end(); i != ie; ++i) {
+ if (bitSize <= i->second.bitSize) {
+ return i->second;
+ }
+ }
+ printf("ERR bitSize=%d\n", (int)bitSize);
+ exit(1);
+}
+
+void test(const Unit *p, size_t bitSize)
+{
+ printf("bitSize %d\n", (int)bitSize);
+ const size_t n = getUnitSize(bitSize);
+#ifdef NDEBUG
+ bool doBench = true;
+#else
+ bool doBench = false;
+#endif
+ const FuncOp funcOp = getFuncOp(bitSize);
+ const void4op addS = funcOp.addS;
+ const void4op addL = funcOp.addL;
+ const void4op subS = funcOp.subS;
+ const void4op subL = funcOp.subL;
+ const void3op mulPre = funcOp.mulPre;
+ const void4Iop mont = funcOp.mont;
+
+ mcl::fp::Unit x[MAX_N], y[MAX_N];
+ mcl::fp::Unit z[MAX_N], w[MAX_N];
+ mcl::fp::Unit z2[MAX_N * 2];
+ mcl::fp::Unit w2[MAX_N * 2];
+ cybozu::XorShift rg;
+ mcl::fp::getRandVal(x, rg, p, bitSize);
+ mcl::fp::getRandVal(y, rg, p, bitSize);
+ const size_t C = 10;
+
+ addC(z, x, y, p, n);
+ addS(w, x, y, p);
+ VERIFY_EQUAL(z, w, n);
+ for (size_t i = 0; i < C; i++) {
+ addC(z, y, z, p, n);
+ addS(w, y, w, p);
+ VERIFY_EQUAL(z, w, n);
+ addC(z, y, z, p, n);
+ addL(w, y, w, p);
+ VERIFY_EQUAL(z, w, n);
+ subC(z, x, z, p, n);
+ subS(w, x, w, p);
+ VERIFY_EQUAL(z, w, n);
+ subC(z, x, z, p, n);
+ subL(w, x, w, p);
+ VERIFY_EQUAL(z, w, n);
+ mulPreC(z2, x, z, n);
+ mulPre(w2, x, z);
+ VERIFY_EQUAL(z2, w2, n * 2);
+ }
+ {
+ mpz_class mp;
+ setMpz(mp, p, n);
+ Montgomery m(mp);
+#ifdef USE_XBYAK
+ if (bitSize > 128) fg.init(p, n);
+#endif
+ /*
+ real mont
+ 0 0
+ 1 R^-1
+ R 1
+ -1 -R^-1
+ -R -1
+ */
+ mpz_class t = 1;
+ const mpz_class R = (t << (n * 64)) % mp;
+ const mpz_class tbl[] = {
+ 0, 1, R, mp - 1, mp - R
+ };
+ for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) {
+ const mpz_class& mx = tbl[i];
+ for (size_t j = i; j < CYBOZU_NUM_OF_ARRAY(tbl); j++) {
+ const mpz_class& my = tbl[j];
+ getMpz(x, n, mx);
+ getMpz(y, n, my);
+ m.mont(z, x, y);
+ mont(w, x, y, p, m.r_);
+ VERIFY_EQUAL(z, w, n);
+#ifdef USE_XBYAK
+ if (bitSize > 128) {
+ fg.mul_(w, x, y);
+ VERIFY_EQUAL(z, w, n);
+ }
+#endif
+ }
+ }
+ if (doBench) {
+// CYBOZU_BENCH("montC", m.mont, x, y, x);
+ CYBOZU_BENCH("montA ", mont, x, y, x, p, m.r_);
+ }
+ }
+ if (doBench) {
+// CYBOZU_BENCH("addS", addS, x, y, x, p); // slow
+// CYBOZU_BENCH("subS", subS, x, y, x, p);
+// CYBOZU_BENCH("addL", addL, x, y, x, p);
+// CYBOZU_BENCH("subL", subL, x, y, x, p);
+ CYBOZU_BENCH("mulPreA", mulPre, w2, y, x);
+ CYBOZU_BENCH("mulPreC", mulPreC, w2, y, x, n);
+ CYBOZU_BENCH("modC ", modC, x, w2, p, n);
+ }
+#ifdef USE_XBYAK
+ if (bitSize <= 128) return;
+ if (doBench) {
+ fg.init(p, n);
+ CYBOZU_BENCH("addA ", fg.add_, x, y, x);
+ CYBOZU_BENCH("subA ", fg.sub_, x, y, x);
+// CYBOZU_BENCH("mulA", fg.mul_, x, y, x);
+ }
+#endif
+ printf("mont test %d\n", (int)bitSize);
+}
+
+CYBOZU_TEST_AUTO(all)
+{
+ const struct {
+ size_t n;
+ const uint64_t p[9];
+ } tbl[] = {
+// { 2, { 0xf000000000000001, 1, } },
+ { 2, { 0x000000000000001d, 0x8000000000000000, } },
+ { 3, { 0x000000000000012b, 0x0000000000000000, 0x0000000080000000, } },
+// { 3, { 0x0f69466a74defd8d, 0xfffffffe26f2fc17, 0x07ffffffffffffff, } },
+// { 3, { 0x7900342423332197, 0x1234567890123456, 0x1480948109481904, } },
+ { 3, { 0x0f69466a74defd8d, 0xfffffffe26f2fc17, 0xffffffffffffffff, } },
+// { 4, { 0x7900342423332197, 0x4242342420123456, 0x1234567892342342, 0x1480948109481904, } },
+// { 4, { 0x0f69466a74defd8d, 0xfffffffe26f2fc17, 0x17ffffffffffffff, 0x1513423423423415, } },
+ { 4, { 0xa700000000000013, 0x6121000000000013, 0xba344d8000000008, 0x2523648240000001, } },
+// { 5, { 0x0000000000000009, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x8000000000000000, } },
+ { 5, { 0xfffffffffffffc97, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, } },
+// { 6, { 0x4720422423332197, 0x0034230847204720, 0x3456789012345679, 0x4820984290482212, 0x9482094820948209, 0x0194810841094810, } },
+// { 6, { 0x7204224233321972, 0x0342308472047204, 0x4567890123456790, 0x0948204204243123, 0x2098420984209482, 0x2093482094810948, } },
+ { 6, { 0x00000000ffffffff, 0xffffffff00000000, 0xfffffffffffffffe, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, } },
+// { 7, { 0x0000000000000063, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x8000000000000000, } },
+ { 7, { 0x000000000fffcff1, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, } },
+ { 8, { 0xffffffffffffd0c9, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, } },
+ { 9, { 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0x00000000000001ff, } },
+// { 9, { 0x4720422423332197, 0x0034230847204720, 0x3456789012345679, 0x2498540975555312, 0x9482904924029424, 0x0948209842098402, 0x1098410948109482, 0x0820958209582094, 0x0000000000000029, } },
+// { 9, { 0x0f69466a74defd8d, 0xfffffffe26f2fc17, 0x7fffffffffffffff, 0x8572938572398583, 0x5732057823857293, 0x9820948205872380, 0x3409238420492034, 0x9483842098340298, 0x0000000000000003, } },
+ };
+ for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) {
+ const size_t n = tbl[i].n;
+ const size_t bitSize = (n - 1) * 64 + cybozu::bsr<uint64_t>(tbl[i].p[n - 1]) + 1;
+ test((const Unit*)tbl[i].p, bitSize);
+ }
+}
+
diff --git a/vendor/github.com/tangerine-network/mcl/test/bench.hpp b/vendor/github.com/tangerine-network/mcl/test/bench.hpp
new file mode 100644
index 000000000..cc1639e6e
--- /dev/null
+++ b/vendor/github.com/tangerine-network/mcl/test/bench.hpp
@@ -0,0 +1,192 @@
+#include <mcl/lagrange.hpp>
+
+void benchAddDblG1()
+{
+ puts("benchAddDblG1");
+ const int C = 100000;
+ G1 P1, P2, P3;
+ hashAndMapToG1(P1, "a");
+ hashAndMapToG1(P2, "b");
+ P1 += P2;
+ P2 += P1;
+ printf("z.isOne()=%d %d\n", P1.z.isOne(), P2.z.isOne());
+ CYBOZU_BENCH_C("G1::add(1)", C, G1::add, P3, P1, P2);
+ P1.normalize();
+ printf("z.isOne()=%d %d\n", P1.z.isOne(), P2.z.isOne());
+ CYBOZU_BENCH_C("G1::add(2)", C, G1::add, P3, P1, P2);
+ CYBOZU_BENCH_C("G1::add(3)", C, G1::add, P3, P2, P1);
+ P2.normalize();
+ printf("z.isOne()=%d %d\n", P1.z.isOne(), P2.z.isOne());
+ CYBOZU_BENCH_C("G1::add(4)", C, G1::add, P3, P1, P2);
+ P1 = P3;
+ printf("z.isOne()=%d\n", P1.z.isOne());
+ CYBOZU_BENCH_C("G1::dbl(1)", C, G1::dbl, P3, P1);
+ P1.normalize();
+ printf("z.isOne()=%d\n", P1.z.isOne());
+ CYBOZU_BENCH_C("G1::dbl(2)", C, G1::dbl, P3, P1);
+}
+
+void benchAddDblG2()
+{
+ puts("benchAddDblG2");
+ const int C = 100000;
+ G2 P1, P2, P3;
+ hashAndMapToG2(P1, "a");
+ hashAndMapToG2(P2, "b");
+ P1 += P2;
+ P2 += P1;
+ printf("z.isOne()=%d %d\n", P1.z.isOne(), P2.z.isOne());
+ CYBOZU_BENCH_C("G2::add(1)", C, G2::add, P3, P1, P2);
+ P1.normalize();
+ printf("z.isOne()=%d %d\n", P1.z.isOne(), P2.z.isOne());
+ CYBOZU_BENCH_C("G2::add(2)", C, G2::add, P3, P1, P2);
+ CYBOZU_BENCH_C("G2::add(3)", C, G2::add, P3, P2, P1);
+ P2.normalize();
+ printf("z.isOne()=%d %d\n", P1.z.isOne(), P2.z.isOne());
+ CYBOZU_BENCH_C("G2::add(4)", C, G2::add, P3, P1, P2);
+ P1 = P3;
+ printf("z.isOne()=%d\n", P1.z.isOne());
+ CYBOZU_BENCH_C("G2::dbl(1)", C, G2::dbl, P3, P1);
+ P1.normalize();
+ printf("z.isOne()=%d\n", P1.z.isOne());
+ CYBOZU_BENCH_C("G2::dbl(2)", C, G2::dbl, P3, P1);
+}
+
+
+void testBench(const G1& P, const G2& Q)
+{
+ G1 Pa;
+ G2 Qa;
+ Fp12 e1, e2;
+ pairing(e1, P, Q);
+ Fp12::pow(e2, e1, 12345);
+ Fp x, y;
+ x.setHashOf("abc");
+ y.setHashOf("xyz");
+ const int C = 1000;
+ const int C3 = 100000;
+#if 1
+ const int C2 = 3000;
+ mpz_class a = x.getMpz();
+ CYBOZU_BENCH_C("G1::mulCT ", C, G1::mulCT, Pa, P, a);
+ CYBOZU_BENCH_C("G1::mul ", C, G1::mul, Pa, Pa, a);
+ CYBOZU_BENCH_C("G1::add ", C, G1::add, Pa, Pa, P);
+ CYBOZU_BENCH_C("G1::dbl ", C, G1::dbl, Pa, Pa);
+ CYBOZU_BENCH_C("G2::mulCT ", C, G2::mulCT, Qa, Q, a);
+ CYBOZU_BENCH_C("G2::mul ", C, G2::mul, Qa, Qa, a);
+ CYBOZU_BENCH_C("G2::add ", C, G2::add, Qa, Qa, Q);
+ CYBOZU_BENCH_C("G2::dbl ", C, G2::dbl, Qa, Qa);
+ CYBOZU_BENCH_C("GT::pow ", C, GT::pow, e1, e1, a);
+// CYBOZU_BENCH_C("GT::powGLV ", C, BN::param.glv2.pow, e1, e1, a);
+ G1 PP;
+ G2 QQ;
+ std::string s;
+ s = P.getStr();
+ CYBOZU_BENCH_C("G1::setStr chk", C, PP.setStr, s);
+ verifyOrderG1(false);
+ CYBOZU_BENCH_C("G1::setStr ", C, PP.setStr, s);
+ verifyOrderG1(true);
+ s = Q.getStr();
+ CYBOZU_BENCH_C("G2::setStr chk", C, QQ.setStr, s);
+ verifyOrderG2(false);
+ CYBOZU_BENCH_C("G2::setStr ", C, QQ.setStr, s);
+ verifyOrderG2(true);
+ CYBOZU_BENCH_C("hashAndMapToG1", C, hashAndMapToG1, PP, "abc", 3);
+ CYBOZU_BENCH_C("hashAndMapToG2", C, hashAndMapToG2, QQ, "abc", 3);
+#endif
+ CYBOZU_BENCH_C("Fp::add ", C3, Fp::add, x, x, y);
+ CYBOZU_BENCH_C("Fp::sub ", C3, Fp::sub, x, x, y);
+ CYBOZU_BENCH_C("Fp::neg ", C3, Fp::neg, x, x);
+ CYBOZU_BENCH_C("Fp::mul ", C3, Fp::mul, x, x, y);
+ CYBOZU_BENCH_C("Fp::sqr ", C3, Fp::sqr, x, x);
+ CYBOZU_BENCH_C("Fp::inv ", C3, Fp::inv, x, x);
+ Fp2 xx, yy;
+ xx.a = x;
+ xx.b = 3;
+ yy.a = y;
+ yy.b = -5;
+ FpDbl d0, d1;
+ x = 9;
+ y = 3;
+#if 1
+ CYBOZU_BENCH_C("Fp2::add ", C3, Fp2::add, xx, xx, yy);
+ CYBOZU_BENCH_C("Fp2::sub ", C3, Fp2::sub, xx, xx, yy);
+ CYBOZU_BENCH_C("Fp2::neg ", C3, Fp2::neg, xx, xx);
+ CYBOZU_BENCH_C("Fp2::mul ", C3, Fp2::mul, xx, xx, yy);
+ CYBOZU_BENCH_C("Fp2::mul_xi ", C3, Fp2::mul_xi, xx, xx);
+ CYBOZU_BENCH_C("Fp2::sqr ", C3, Fp2::sqr, xx, xx);
+ CYBOZU_BENCH_C("Fp2::inv ", C3, Fp2::inv, xx, xx);
+ CYBOZU_BENCH_C("FpDbl::addPre ", C3, FpDbl::addPre, d1, d1, d0);
+ CYBOZU_BENCH_C("FpDbl::subPre ", C3, FpDbl::subPre, d1, d1, d0);
+ CYBOZU_BENCH_C("FpDbl::add ", C3, FpDbl::add, d1, d1, d0);
+ CYBOZU_BENCH_C("FpDbl::sub ", C3, FpDbl::sub, d1, d1, d0);
+ CYBOZU_BENCH_C("FpDbl::mulPre ", C3, FpDbl::mulPre, d0, x, y);
+ CYBOZU_BENCH_C("FpDbl::sqrPre ", C3, FpDbl::sqrPre, d1, x);
+ CYBOZU_BENCH_C("FpDbl::mod ", C3, FpDbl::mod, x, d0);
+ Fp2Dbl D;
+ CYBOZU_BENCH_C("Fp2Dbl::mulPre ", C3, Fp2Dbl::mulPre, D, xx, yy);
+ CYBOZU_BENCH_C("Fp2Dbl::sqrPre ", C3, Fp2Dbl::sqrPre, D, xx);
+
+ CYBOZU_BENCH_C("GT::add ", C2, GT::add, e1, e1, e2);
+ CYBOZU_BENCH_C("GT::mul ", C2, GT::mul, e1, e1, e2);
+ CYBOZU_BENCH_C("GT::sqr ", C2, GT::sqr, e1, e1);
+ CYBOZU_BENCH_C("GT::inv ", C2, GT::inv, e1, e1);
+#endif
+ CYBOZU_BENCH_C("FpDbl::mulPre ", C3, FpDbl::mulPre, d0, x, y);
+ CYBOZU_BENCH_C("pairing ", 3000, pairing, e1, P, Q);
+ CYBOZU_BENCH_C("millerLoop ", 3000, millerLoop, e1, P, Q);
+ CYBOZU_BENCH_C("finalExp ", 3000, finalExp, e1, e1);
+//exit(1);
+ std::vector<Fp6> Qcoeff;
+ CYBOZU_BENCH_C("precomputeG2 ", C, precomputeG2, Qcoeff, Q);
+ precomputeG2(Qcoeff, Q);
+ CYBOZU_BENCH_C("precomputedML ", C, precomputedMillerLoop, e2, P, Qcoeff);
+}
+
+inline void SquareRootPrecomputeTest(const mpz_class& p)
+{
+ mcl::SquareRoot sq1, sq2;
+ bool b;
+ sq1.set(&b, p, true);
+ CYBOZU_TEST_ASSERT(b);
+ CYBOZU_TEST_ASSERT(sq1.isPrecomputed());
+ sq2.set(&b, p, false);
+ CYBOZU_TEST_ASSERT(sq1 == sq2);
+ if (sq1 != sq2) {
+ puts("dump");
+ puts("sq1");
+ sq1.dump();
+ puts("sq2");
+ sq2.dump();
+ puts("---");
+ }
+}
+
+void testSquareRoot()
+{
+ if (BN::param.cp == mcl::BN254 || BN::param.cp == mcl::BLS12_381) {
+ SquareRootPrecomputeTest(BN::param.p);
+ SquareRootPrecomputeTest(BN::param.r);
+ }
+}
+
+void testLagrange()
+{
+ puts("testLagrange");
+ const int k = 7;
+ Fr c[k], x[k], y[k];
+ for (size_t i = 0; i < k; i++) {
+ c[i].setByCSPRNG();
+ x[i].setByCSPRNG();
+ }
+ for (size_t i = 0; i < k; i++) {
+ mcl::evaluatePolynomial(y[i], c, k, x[i]);
+ }
+ Fr s;
+ mcl::LagrangeInterpolation(s, x, y, k);
+ CYBOZU_TEST_EQUAL(s, c[0]);
+ mcl::LagrangeInterpolation(s, x, y, 1);
+ CYBOZU_TEST_EQUAL(s, y[0]);
+ mcl::evaluatePolynomial(y[0], c, 1, x[0]);
+ CYBOZU_TEST_EQUAL(y[0], c[0]);
+}
diff --git a/vendor/github.com/tangerine-network/mcl/test/bls12_test.cpp b/vendor/github.com/tangerine-network/mcl/test/bls12_test.cpp
new file mode 100644
index 000000000..7011516bd
--- /dev/null
+++ b/vendor/github.com/tangerine-network/mcl/test/bls12_test.cpp
@@ -0,0 +1,720 @@
+#define PUT(x) std::cout << #x "=" << x << std::endl;
+#define CYBOZU_TEST_DISABLE_AUTO_RUN
+#include <cybozu/benchmark.hpp>
+cybozu::CpuClock clk;
+#include <cybozu/test.hpp>
+#include <mcl/bls12_381.hpp>
+#include <cybozu/option.hpp>
+#include <cybozu/xorshift.hpp>
+
+#if defined(__EMSCRIPTEN__) && !defined(MCL_AVOID_EXCEPTION_TEST)
+ #define MCL_AVOID_EXCEPTION_TEST
+#endif
+
+using namespace mcl::bls12;
+
+mcl::fp::Mode g_mode;
+
+const struct TestSet {
+ mcl::CurveParam cp;
+ const char *name;
+ const char *p;
+ const char *r;
+ struct G2 {
+ const char *aa;
+ const char *ab;
+ const char *ba;
+ const char *bb;
+ } g2;
+ struct G1 {
+ const char *a;
+ const char *b;
+ } g1;
+ const char *e;
+} g_testSetTbl[] = {
+ {
+ mcl::BLS12_381,
+ "BLS12_381",
+ "0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaab",
+ "0x73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001",
+ {
+ "0x024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb8",
+ "0x13e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e",
+ "0x0ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801",
+ "0x0606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be",
+ },
+ {
+ "0x17f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb",
+ "0x08b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e1",
+ },
+ "0x1250EBD871FC0A92A7B2D83168D0D727272D441BEFA15C503DD8E90CE98DB3E7B6D194F60839C508A84305AACA1789B6 "
+ "0x089A1C5B46E5110B86750EC6A532348868A84045483C92B7AF5AF689452EAFABF1A8943E50439F1D59882A98EAA0170F "
+ "0x1368BB445C7C2D209703F239689CE34C0378A68E72A6B3B216DA0E22A5031B54DDFF57309396B38C881C4C849EC23E87 "
+ "0x193502B86EDB8857C273FA075A50512937E0794E1E65A7617C90D8BD66065B1FFFE51D7A579973B1315021EC3C19934F "
+ "0x01B2F522473D171391125BA84DC4007CFBF2F8DA752F7C74185203FCCA589AC719C34DFFBBAAD8431DAD1C1FB597AAA5 "
+ "0x018107154F25A764BD3C79937A45B84546DA634B8F6BE14A8061E55CCEBA478B23F7DACAA35C8CA78BEAE9624045B4B6 "
+ "0x19F26337D205FB469CD6BD15C3D5A04DC88784FBB3D0B2DBDEA54D43B2B73F2CBB12D58386A8703E0F948226E47EE89D "
+ "0x06FBA23EB7C5AF0D9F80940CA771B6FFD5857BAAF222EB95A7D2809D61BFE02E1BFD1B68FF02F0B8102AE1C2D5D5AB1A "
+ "0x11B8B424CD48BF38FCEF68083B0B0EC5C81A93B330EE1A677D0D15FF7B984E8978EF48881E32FAC91B93B47333E2BA57 "
+ "0x03350F55A7AEFCD3C31B4FCB6CE5771CC6A0E9786AB5973320C806AD360829107BA810C5A09FFDD9BE2291A0C25A99A2 "
+ "0x04C581234D086A9902249B64728FFD21A189E87935A954051C7CDBA7B3872629A4FAFC05066245CB9108F0242D0FE3EF "
+ "0x0F41E58663BF08CF068672CBD01A7EC73BACA4D72CA93544DEFF686BFD6DF543D48EAA24AFE47E1EFDE449383B676631 "
+ },
+};
+
+CYBOZU_TEST_AUTO(size)
+{
+ CYBOZU_TEST_EQUAL(sizeof(Fp), 48u);
+ CYBOZU_TEST_EQUAL(sizeof(Fr), 32u);
+ CYBOZU_TEST_EQUAL(sizeof(Fp2), sizeof(Fp) * 2);
+ CYBOZU_TEST_EQUAL(sizeof(Fp6), sizeof(Fp) * 6);
+ CYBOZU_TEST_EQUAL(sizeof(Fp12), sizeof(Fp) * 12);
+ CYBOZU_TEST_EQUAL(sizeof(G1), sizeof(Fp) * 3);
+ CYBOZU_TEST_EQUAL(sizeof(G2), sizeof(Fp2) * 3);
+}
+
+void testParam(const TestSet& ts)
+{
+ CYBOZU_TEST_EQUAL(BN::param.r, mpz_class(ts.r));
+ CYBOZU_TEST_EQUAL(BN::param.p, mpz_class(ts.p));
+}
+
+void finalExpC(Fp12& y, const Fp12& x)
+{
+ const mpz_class& r = BN::param.r;
+ const mpz_class& p = BN::param.p;
+ mpz_class p2 = p * p;
+ mpz_class p4 = p2 * p2;
+#if 1
+ Fp12::pow(y, x, p2 + 1);
+ Fp12::pow(y, y, p4 * p2 - 1);
+ Fp12::pow(y, y, (p4 - p2 + 1) / r * 3);
+#else
+ Fp12::pow(y, x, (p4 * p4 * p4 - 1) / r * 3);
+#endif
+}
+
+void pairingC(Fp12& e, const G1& P, const G2& Q)
+{
+ millerLoop(e, P, Q);
+ finalExp(e, e);
+}
+void testIoAll(const G1& P, const G2& Q)
+{
+ const int FpTbl[] = { 0, 2, 2|mcl::IoPrefix, 10, 16, 16|mcl::IoPrefix, mcl::IoArray, mcl::IoArrayRaw };
+ const int EcTbl[] = { mcl::IoEcAffine, mcl::IoEcProj, mcl::IoEcCompY, mcl::IoSerialize };
+ for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(FpTbl); i++) {
+ for (size_t j = 0; j < CYBOZU_NUM_OF_ARRAY(EcTbl); j++) {
+ G1 P2 = P, P3;
+ G2 Q2 = Q, Q3;
+ int ioMode = FpTbl[i] | EcTbl[j];
+ std::string s = P2.getStr(ioMode);
+ P3.setStr(s, ioMode);
+ CYBOZU_TEST_EQUAL(P2, P3);
+ s = Q2.getStr(ioMode);
+ Q3.setStr(s, ioMode);
+ CYBOZU_TEST_EQUAL(Q2, Q3);
+ s = P.x.getStr(ioMode);
+ Fp Px;
+ Px.setStr(s, ioMode);
+ CYBOZU_TEST_EQUAL(P.x, Px);
+ s = Q.x.getStr(ioMode);
+ Fp2 Qx;
+ Qx.setStr(s, ioMode);
+ CYBOZU_TEST_EQUAL(Q.x, Qx);
+ }
+ }
+}
+
+void testIo(const G1& P, const G2& Q)
+{
+ testIoAll(P, Q);
+ G1 Z1;
+ G2 Z2;
+ Z1.clear();
+ Z2.clear();
+ testIoAll(Z1, Z2);
+}
+
+void testSetStr(const G2& Q0)
+{
+ G2::setCompressedExpression();
+ G2 Q;
+ Q.clear();
+ for (int i = 0; i < 10; i++) {
+ G2 R;
+ R.setStr(Q.getStr());
+ CYBOZU_TEST_EQUAL(Q, R);
+ G2::add(Q, Q, Q0);
+ }
+}
+
+void testMapToG1()
+{
+ G1 g;
+ for (int i = 1; i < 10; i++) {
+ mapToG1(g, i);
+ CYBOZU_TEST_ASSERT(!g.isZero());
+ G1 gr;
+ G1::mul(gr, g, BN::param.r);
+ CYBOZU_TEST_ASSERT(gr.isZero());
+ }
+}
+
+void testMapToG2()
+{
+ G2 g;
+ for (int i = 1; i < 10; i++) {
+ mapToG2(g, i);
+ CYBOZU_TEST_ASSERT(!g.isZero());
+ G2 gr;
+ G2::mul(gr, g, BN::param.r);
+ CYBOZU_TEST_ASSERT(gr.isZero());
+ }
+ Fp x;
+ x.setHashOf("abc");
+ mapToG2(g, Fp2(x, 0));
+ CYBOZU_TEST_ASSERT(g.isValid());
+}
+
+void testPrecomputed(const G1& P, const G2& Q)
+{
+ Fp12 e1, e2;
+ pairing(e1, P, Q);
+ std::vector<Fp6> Qcoeff;
+ precomputeG2(Qcoeff, Q);
+ precomputedMillerLoop(e2, P, Qcoeff);
+ finalExp(e2, e2);
+ CYBOZU_TEST_EQUAL(e1, e2);
+}
+
+#if 0
+void testFp12pow(const G1& P, const G2& Q)
+{
+ Fp12 e, e1, e2;
+ pairing(e, P, Q);
+ cybozu::XorShift rg;
+ for (int i = -10; i < 10; i++) {
+ mpz_class xm = i;
+ Fp12::pow(e1, e, xm);
+ Fp12::powGeneric(e2, e, xm);
+ CYBOZU_TEST_EQUAL(e1, e2);
+ }
+ for (int i = 0; i < 10; i++) {
+ Fr x;
+ x.setRand(rg);
+ mpz_class xm = x.getMpz();
+ Fp12::pow(e1, e, xm);
+ param.glv2.pow(e2, e, xm);
+ CYBOZU_TEST_EQUAL(e1, e2);
+ }
+}
+#endif
+
+void testMillerLoop2(const G1& P1, const G2& Q1)
+{
+ Fp12 e1, e2, e3;
+ mpz_class c1("12342342423442");
+ mpz_class c2("329428049820348209482");
+ G2 Q2;
+ G1 P2;
+ G2::mul(Q2, Q1, c1);
+ G1::mul(P2, P1, c2);
+ pairing(e1, P1, Q1);
+ pairing(e2, P2, Q2);
+ e1 *= e2;
+
+ std::vector<Fp6> Q1coeff, Q2coeff;
+ precomputeG2(Q1coeff, Q1);
+ precomputeG2(Q2coeff, Q2);
+ precomputedMillerLoop2(e2, P1, Q1coeff, P2, Q2coeff);
+ precomputedMillerLoop2mixed(e3, P1, Q1, P2, Q2coeff);
+ CYBOZU_TEST_EQUAL(e2, e3);
+ finalExp(e2, e2);
+ CYBOZU_TEST_EQUAL(e1, e2);
+
+ // special value
+ G2 Z;
+ Z.clear();
+ Q2 += Q2;
+ precomputeG2(Q1coeff, Z);
+ precomputeG2(Q2coeff, Q2);
+ precomputedMillerLoop2(e2, P1, Q1coeff, P2, Q2coeff);
+ precomputedMillerLoop2mixed(e3, P1, Z, P2, Q2coeff);
+ finalExp(e2, e2);
+ finalExp(e3, e3);
+ CYBOZU_TEST_EQUAL(e2, e3);
+}
+
+void testPairing(const G1& P, const G2& Q, const char *eStr)
+{
+ Fp12 e1;
+ pairing(e1, P, Q);
+ Fp12 e2;
+ {
+ std::stringstream ss(eStr);
+ ss >> e2;
+ }
+ CYBOZU_TEST_EQUAL(e1, e2);
+ Fp12 e = e1, ea;
+ G1 Pa;
+ G2 Qa;
+#if defined(__EMSCRIPTEN__) || MCL_SIZEOF_UNIT == 4
+ const int count = 100;
+#else
+ const int count = 1000;
+#endif
+ mpz_class a;
+ cybozu::XorShift rg;
+ for (int i = 0; i < count; i++) {
+ Fr r;
+ r.setRand(rg);
+ a = r.getMpz();
+ Fp12::pow(ea, e, a);
+ G1::mul(Pa, P, a);
+ G2::mul(Qa, Q, a);
+ G1 T;
+ G1::mulCT(T, P, a);
+ CYBOZU_TEST_EQUAL(Pa, T);
+ pairing(e1, Pa, Q);
+ pairing(e2, P, Qa);
+ CYBOZU_TEST_EQUAL(ea, e1);
+ CYBOZU_TEST_EQUAL(ea, e2);
+ }
+}
+
+void testTrivial(const G1& P, const G2& Q)
+{
+ G1 Z1; Z1.clear();
+ G2 Z2; Z2.clear();
+ Fp12 e;
+ pairing(e, Z1, Q);
+ CYBOZU_TEST_EQUAL(e, 1);
+ pairing(e, P, Z2);
+ CYBOZU_TEST_EQUAL(e, 1);
+ pairing(e, Z1, Z2);
+ CYBOZU_TEST_EQUAL(e, 1);
+
+ std::vector<Fp6> Qcoeff;
+ precomputeG2(Qcoeff, Z2);
+ precomputedMillerLoop(e, P, Qcoeff);
+ finalExp(e, e);
+ CYBOZU_TEST_EQUAL(e, 1);
+
+ precomputeG2(Qcoeff, Q);
+ precomputedMillerLoop(e, Z1, Qcoeff);
+ finalExp(e, e);
+ CYBOZU_TEST_EQUAL(e, 1);
+}
+
+#include "bench.hpp"
+
+CYBOZU_TEST_AUTO(naive)
+{
+ for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(g_testSetTbl); i++) {
+ const TestSet& ts = g_testSetTbl[i];
+ printf("i=%d curve=%s\n", int(i), ts.name);
+ initPairing(ts.cp, g_mode);
+ const G1 P(Fp(ts.g1.a), Fp(ts.g1.b));
+ const G2 Q(Fp2(ts.g2.aa, ts.g2.ab), Fp2(ts.g2.ba, ts.g2.bb));
+#ifdef ONLY_BENCH
+ {
+ Fp12 e;
+ for (int i = 0; i < 1000; i++) pairing(e, P, Q);
+ }
+ clk.put();
+ return;
+#endif
+ testParam(ts);
+ testIo(P, Q);
+// testFp12pow(P, Q);
+ testTrivial(P, Q);
+ testSetStr(Q);
+ testMapToG1();
+ testMapToG2();
+ testPairing(P, Q, ts.e);
+ testPrecomputed(P, Q);
+ testMillerLoop2(P, Q);
+ testBench(P, Q);
+ }
+ int count = (int)clk.getCount();
+ if (count) {
+ printf("count=%d ", count);
+ clk.put();
+ }
+}
+
+CYBOZU_TEST_AUTO(finalExp)
+{
+ const char *e0Str =
+"012974491575E232199B73B30FE53FF643FEAE11023BCA7AF961C3600B45DFECFE4B30D52A62E73DA4C0409810304997\n"
+"05CE2FB890FE65E20EC36347190ECB4884E401A64B666557B53E561F6D0979B7A96AD9E647ED78BD47187195C00F563C\n"
+"02E85D1E559488603A70FEE99354DA8847215EC97282CA230DE96FED6DD5D4DD4EF4D901DB7F544A1A45EBEBA1450109\n"
+"048FB1E44DDABF18D55C95704158A24678AA2A6ED0844108762E88306E5880E8C67BF44E24E40AB3F93D9E3713170341\n"
+"07EF7BE685DC0DBA1B3E1D2E9090CD98EAD1325B60881772F17077386A3182B117F5FD839363F5891D08E82B88EC6F12\n"
+"17803435700EF7A16C06404C6D17EB4FD84079FE9872207302A36C791B6E90447B33D703BBFE04ECB641C3A573E2CD50\n"
+"19A494E6A872E46FC85D09FD6D30844B6FF05729BC253A9640F7BE64AAA8C2C8E0AE014A9DD816C53A3EDEBB2FA649EB\n"
+"020949ABAA14F1DCE17FA9E091DDA963E9E492BA788E12B9B610E80A4D94DB9CC50341ED107C7D50E5738052595D4A27\n"
+"09E217B513B3603723DAC3188A2F7CBDD84A56E7E5004446E7D4C63D6E378DA26E411C10898E48DB4B0C065E4699A9C5\n"
+"12393BD23D0EC122082A1EC892A982F3C9AFD14240CE85258D8A3EF0A13CB545D6EF7848FD40DD4AEF1554341C5C5BBF\n"
+"07EA8A0D6A57C78E5663F94E2B1ABC0D760ED18DBA64305EAD5EE350FB0342A7A81C0D5C8B3AD826D009276B0F32D2C8\n"
+"16804D0D4A2633ED01568B0F8F06C4497E46E88D05FD191AAE530ACA791D0E114D74874FA88E33FAF48757153B09BB0E";
+
+const char *e1Str =
+"0E05D19E90D2C501E5502C7AC80D77201C47DF147DD1076440F0DF0179DF9802CA0775E0E73DD9174F1094D2280787B3\n"
+"14D2F5C84279E7177A3543FBEAE261DE8F6C97EFD5F3FF3F959EC9FC0303F620A4B3AF00DF409496CECADDD0A7F0A164\n"
+"1414E9B9DF8DF1EAC2E70D5538018377788C62016A54F28B037A68740705089AE431B86756F98CBE19690A5EAC0C2466\n"
+"12D8B32157836A131CCA3CA313DAAAF909BC3AD6BDD15885BB429922B9CD7D1246D1163E5E6F88D68BF1B75E451EFABB\n"
+"102C9A839A924E0D603D13F2E08A919E0B9EE2A269FC75727BA13D66027C157B9BB4077977FA94557DE4427BF11B234B\n"
+"19DBEB7F2E3096AFFD44837655BD8249741B484B0EB0DBEE569DEA8D9E38AE09D210C8BC16AA6DFBC923095B2C9A8B2B\n"
+"19B9A6DCCD01FA0D04D5CE94D8BDCE1DF64AFEB7FD493B955180A5C6B236E469F0E07CC9BB4203FCAC46AE6F8E5419D6\n"
+"02BFA87AF7A3726A7ABACDCFDD53694AF651554F3A431AB4274F67D5DAD2D6C88AF794705FF456A936C83594731AD8DC\n"
+"0F21E0173E3B50DD98EFA815B410631A57399B451FD6E1056FFD09C9FE50EFAD3D026F0C46C8BB1583A50B7853D990DA\n"
+"02230237AE04B61F9269F6E7CD2FCF1231CEE4690AA658B0018EFC0D0770FD0A56B3B7294086E8D306B1465CDDD858CD\n"
+"087EB8F6547015661E9CD48D6525C808636FCB8420B867CB2A87E006B2A93BBD5EF675E6CDDA9E6F94519C49EA8BB689\n"
+"19F5C988B2DD6E33D7D3D34EFB1991F80DC28006AC75E0AB53FD98FC6F2476D05DD4ECA582F5FF72B8DDD9DDDE80FFC9";
+
+ Fp12 e0, e1, e2;
+ e0.setStr(e0Str, 16);
+ e1.setStr(e1Str, 16);
+ finalExp(e2, e0);
+// finalExpC(e2, e0);
+ CYBOZU_TEST_EQUAL(e1, e2);
+ CYBOZU_BENCH_C("finalExp", 100, finalExp, e2, e0);
+}
+
+CYBOZU_TEST_AUTO(addLine)
+{
+const char *l0Str=
+"0EF586FCDB69442CB41C0DA719AC5C92BD99A916C1F01BCFC7606AA7A23D680C04620FDFC2144E0EA6025F05241A791F\n"
+"164CFDADE9B91150C6D2C7F7CDF29BC3105A7EA51217283CDF801EBEE9E86CE5078253E322C72129DAA42F6DBAD17D37";
+const char *l1Str =
+"07A124F536BE83CCB3AF8D3DA2AE094942755040B9DA8E0796C462ACE3805D6916ACA7E9281261D8025571E2F31AAF0D\n"
+"12D05751A9B255143541D0A4E57E120F937D51F9A07D31982390CA6EB5DF8CC0640FD291521069BF9964AE33EDD1323D";
+const char *l4Str =
+"0D609DE41CF1260B332C1A53AA54703F62AB8224777E34FEEAB09AA06187CA71D8C7C2EB66F59D3622D431BE17D0FEE6\n"
+"0A93C2984041171BE701560017D64D0640B6F61D7DCA8F527FA6B6A1A1033261C0761CAA56A00D4D16C9D3B7371E02D9";
+
+const char *rStr =
+"4 0A8DFA69FDD43EDCCC6375750373B443157EF4641E5B4CA82FBF23E3E8EA72351EA754168CEC77573D337E6227C0D0DD\n"
+"12C8508CF1828C52A9A1A71779129D605327191EE459AED3C0B4B14657B08B2927173FADF8E4275188E8D49E57A75B33\n"
+"12AD7EB96734F2C93B669FD54845CD2FF351AFDF0123E96772021DC3F4F3B456DB1B37CB1C380B1947616165FF0DDAEA\n"
+"03D80F92C8A6005DEB291AF28406B7B4FCEDD81A244997DBB719B01D162BD7D71F0FD63BF76F8F1AC90618C3702294DF\n"
+"199F7A719EA1CA2CD03CFFBB9A4BC2FE1BD8BCA7C772D223E6CB20C1313C3D3C52CFBB88445E56C833908C52A4EC68F1\n"
+"0A3F6B27A6DDA00DB848574ECB06F179271D5844BDA66CD5AE1792A8FDD25E3A504A95839113BAA8B1FCB53EEE5F1FF0";
+
+const char *qStr =
+"4 0B5C339C23F8EAB3647E974BCDDF72C96F97A444346BE72CA73AB1323B83B8F6161257AB34C7E0CF34F6C45086CA5868\n"
+"13C2235E9F9DFB33344BA2EE5A71435859022880732EDC9EC75AC79AE9DA972593CDC40A0AC334D6D2E8D7FAD1D98D0B\n"
+"134B8EED8196A00D3B70ADBC26FF963B725A351CF0B73FE1A541788AFB0BB081AF82A438021B5E878B15D53B1D27C6A7\n"
+"18CC69F847BEE826B939DCB4030D33020D03B046465C9EE103AA8009A175DB169070294E75771586687FE361DB884BCD\n"
+"000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001\n"
+"000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+
+const char *pStr =
+"4 0FD3977C60EC322BC281C915955ED534B491E39C72E8E800271CEF3F0492D890829FA69C45FCE93D9847A0CAB325D871\n"
+"17CC2C36C5D283C05BFCECCF48DBB2050332DA058DD67326A9EE520967DBCAEDFCB5F05A085D1A49DF08BB968CC782C5\n"
+"000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001";
+
+const char *m0Str =
+"1010A4F9944514352AAD5D290AFB95C435EB64B5E74519807C9602DABCD6B6F5494E419758AE9A43F539F812252C65E5\n"
+"1622F7A52BAAC10EBFF0977F61866544BF9B91315FA66ADB6AC200AFF7A3676C1AD3480340B23C66F7C6AE50A703F245";
+const char *m1Str =
+"0905180B20FCE2AA545A73D6B9EA1F82479EF3FB5A3BA8DDB656D9B2A4DA7B63CCF75538D15093949B442E27804C8CE2\n"
+"0FE834508BBAD2F22DCBF1C3C1BCCD69561827613EB63F4907832A7ABBBC6040CF2E517D0D5E22D3812EEE1EC55640DD";
+const char *m4Str =
+"1197D94A8DAFE6F72B17A31964CA5D0C3B2A12BEFF959F7DF7A37938C64C01508D12C24479E5C3D314F862A9977D6C7D\n"
+"0B0254A26810307964E2A05680C19DE7C63CCBD7CC3558AD366BA48D9F7049E245BF2C54EA0339301739851E6EB2158F";
+
+const char *r1Str =
+"4 16A33C4ED01E95833D39EECE223380FE860B6DC1F71B1DDBEE2BE39B5D682B090F18758495E202010D3B9B45A46FF80E\n"
+"01CECF5CC255E32B833C16EF3F983CCA9996A33504615909AD5685D9F637BF2357442BEC89DAFC747B69EFEF57D5A213\n"
+"061C33850E5E4A418F3B68D6097C3911A551D6DB3C7E21196410F69D510C1A888635B6B699F98C14912A8D97742D36A9\n"
+"0457FB78282C2B8F8BA803E77D058EF3BF6B06C6241D6FA6E2B1607F3E9D7597D1A10B7AA4E06B89FBA01736901AD826\n"
+"0B45E9B7D311B8C37F7E9262227A4D721F2D148DE6F12EC5D599B45E4790F35B37A1D6928709F438849324A807EC1913\n"
+"0E771545F892C247A5365BA1F14934D8ED37483A6B7DD3EB4C3FBA0AC884D7EE9C080C3B39ADA64AE545E7339F83AFB0";
+
+ const int mode = mcl::IoEcProj | 16;
+ Fp6 l, m;
+ G2 R, Q, R1;
+ G1 P;
+
+ R.setStr(rStr, mode);
+ Q.setStr(qStr, mode);
+ P.setStr(pStr, mode);
+ l.a.setStr(l0Str, mode);
+ l.b.setStr(l4Str, mode);
+ l.c.setStr(l1Str, mode);
+ local::addLine(l, R, Q, P);
+ m.a.setStr(m0Str, mode);
+ m.b.setStr(m4Str, mode);
+ m.c.setStr(m1Str, mode);
+ R1.setStr(r1Str, mode);
+ CYBOZU_TEST_EQUAL(l, m);
+ CYBOZU_TEST_EQUAL(R, R1);
+}
+
+CYBOZU_TEST_AUTO(dblLine)
+{
+const char *l0Str=
+"0905F47F07FA2177E4B73559D93D9B41A2FD20E0440167E63A0F62321EB73C784405DE360477245F5E4AE8FA2EAEC6FF\n"
+"02DA455C573517EE8BD4E40A60851E2EC85CF514351681B89B1B72664E384A3678A25DC5C4CF84C086C13968BC701F91";
+const char *l1Str =
+"0F48059E31CEF9546D41DEF31FB3BFD13BBCC38248E4846AFD216350B4B661FA1382E74BCF904BE8E33C26FF0D29ABA0\n"
+"0D7FAEE426E4A6F32E4DE1CCB76BBA870A183113589CF58A358DC9C284C82B54C65A754F9A71EAD87304744CFD105051";
+
+const char *l4Str =
+"162AE8B029F8420BEDE5A399BA19C09FED01DE2748F4458065DBE51044FBFE749B28EF1B7F79A5E4545EB550DD0CFE02\n"
+"091042B589FD59FBF286D21475CCCF444D8DCC49389EA3B98AF864DDB9C08BDDEB320D6D88F0C07D7CD1733A41404C1F";
+
+const char *qStr =
+"4 047ACF79048EDCA97A19DB1779A44CE610CEA9FDCC62D1C4014B335834BC63414F55B670CCF15A86E58BC3737FB70919\n"
+"11D8063B2FFA2E1F5224593FF74D0E9650CAB6AF702B74159F7F97E2CF0843FBCD561D41FEC779BEB48746CD2F30FF74\n"
+"17684E8EA85C990DF5472B4EBAF51002CDBBECF79BA2988FC610A5CE09F4A584248DCC506E78C39C9BB4F6008115DE64\n"
+"1334CA7263ED9395BBEDBB6C938C642200C239FB0CADF1F652332A037FFBC7E567CCE09540939F25316CBC4FC68CE4DB\n"
+"0670DCF344F027CB92F7B1F569B281C8FF756D83CD7B65EB118FE95FBE16ED28649B8F739FE3A2BECA1979FC18484ECD\n"
+"13E3E30759DCC1FA9F1A62D54BEF0EE1CC75E194A559F2D6BE3025BE4BEB9F7351A7608FE8D4CCAD30BA2A8748205487";
+
+const char *pStr =
+"4 1579B48AE944AFE8FC69B38A7CD0D2C6B93E5F506535A5410E25FB1C1707938D6932F3D620A2BBB90ED7E2601971DEA8\n"
+"0234E5B373AD62D9EF1EBAE6FA6FFAD26144717F65AE9F98BD4280978ED52B3621F60FA4A8F6E5B5DAF64469733827E6\n"
+"0B4D1755924541041F75FF399E3B5F535BC85D5A982AEEC5FC2404F06AC7F062C090C4545D1602C3D8B559801EE7B9A2";
+
+const char *m0Str =
+"198D1123A9817C40A914A3FF9E29BB16DD2F0DF98D0AB5C3A6014D60E31AE973051C35ADCEA0A41F32BB16E6688DC73F\n"
+"10339DB2F26D1B867FD3E60A24F938210EABEFC51536845A490F28A088A4AC53575DBBAA218D70D34E28EBDE14DB3465\n";
+const char *m1Str =
+"066852248D915F6378B3F4A8E6173AC748FBFAE236AAEEAECC3F34D2D22706A06B925A83DD8276B2B240F61D761587B0\n"
+"17CC8195E6607FF19A26AA69CA50C32487E35D2D75301AC4B6988F1B77523BF472927EE5710DF49A563534D86C684BE0\n";
+const char *m4Str =
+"10B67D1A0CE430B7AD74F64DD6C2E44C4788EADF8340909843C96B918BF54703CC14686B26E350EB1140ACC3337EEEB4\n"
+"0F5D52E6F0B10A081EFF885CC858109241B379985ADD8982E6B8A202FD283897EFBA4CBE444C29751410A61FC8346545";
+
+const char *q1Str =
+"4 17B5E51EC931E724ABACE9C7F8AFDD51F3929478B47C222F99844D166936063D3BFCDF7AD7079EEF4BE8514E3D09EF0F\n"
+"0F5794F38BAEC0FA3C30AC4C0B8E9024B2047F2F4576434F91768F2B51AD58C48E88414B1D4B7A9119A947D3CFEDEF0A\n"
+"1320714A8B7E23C4C558D2B1C556CC8FB6B41F3669EFD70B6D204C2A7C6EF2E0CBCA945AA7BACB402E00ED338F7D12FC\n"
+"0C2846E386161F123344704528D9944677806C3F784E3997857C91D2F3F37AB6AD92360CD97CABD5D631E9FC74708AD3\n"
+"17F92FF3D71B473B802F2DE90C19A5F5DBFAA397293871AB58E5B813F7D686EA8E1814C69C50C02D062F3A13C1D045E1\n"
+"05214392858DE04B3B468B2D0C703A485508C29157D81E9F799BAB2FEF0F514C99D5F8085D8062281418C6CCE5621D18\n";
+
+ const int mode = mcl::IoEcProj | 16;
+ Fp6 l, m;
+ G2 Q, Q1;
+ G1 P;
+
+ G1::setOrder(0);
+ Q.setStr(qStr, mode);
+ P.setStr(pStr, mode);
+ l.a.setStr(l0Str, mode);
+ l.b.setStr(l4Str, mode);
+ l.c.setStr(l1Str, mode);
+ local::dblLine(l, Q, P);
+ m.a.setStr(m0Str, mode);
+ m.b.setStr(m4Str, mode);
+ m.c.setStr(m1Str, mode);
+ Q1.setStr(q1Str, mode);
+ CYBOZU_TEST_EQUAL(l, m);
+ CYBOZU_TEST_EQUAL(Q, Q1);
+ G1::setOrder(BN::param.r);
+}
+
+CYBOZU_TEST_AUTO(mul_012)
+{
+ const char *fStr =
+"087590AFBFEB8F85DD912EC297C2B5DD7BC0A9B0914348C5D99F0089C09CDBA0DCDAF1C704A7B092D8FB9A75B7C06D88\n"
+"119DD8B08C40D4EB3D7AF19221E41639A98A10EF1A22F9AD8CB1350526B9335F47E76B2FFD6652E693A67440574D5A0C\n"
+"134ADA7C4ABFBA4324900D25E5077A119F9E55A7F337C03FD539D8DAC392B458F11261BEA007393D43657E9656B984D6\n"
+"01032DDB3CAEC38B7DA916CA111C46A013F1DC83AF13DFF5B71CC3789974F946CFC43FE7B8EE519E524627248369FCE7\n"
+"19E9455C14A9640139224BB1337E4EC5EE92BFF757DB179CC98CF0F09682E44ED4B6004F31D4788DE28BB2D8F41DDAE4\n"
+"0B9877DF6AC1015375AB421363A5B06D2DC1763B923FF674A06AE101306A4A39967A3F9EF12E870C124A26CE68E2D003\n"
+"02AA5AC5901C9C91CD0B43CA62F21FA541896802A8AAF0FD5EDF8DAF4A98CEC19F457A67369E795594543677B4A16EA4\n"
+"0604DB7CE2A0ABD8ADB5F4F06F20B01510BF9787C912B1036F570E7368D341D9B794F078DFD3265306841180865500D0\n"
+"08145045CF5751502778739EFE6FEA6036C8F14800F4818C2FD8BA5AF98E89B0BBE6510D511C4E5A83A2813A92B655F0\n"
+"0FDE93D3326321ECF6171FBC4665F1C171F19A6F1D521BFA1A1B80E0B08CEBB78B255AF0B5F7E45AA6C1D01005200FB1\n"
+"0F2A9EA2891A683AE15A79EDB0C6DF45FFAD4D22F3293AE59D3CE8F6E0E59A097673D05D81ACAD8C59817FFDD3E89CF1\n"
+"0724BD07BDDCA23775C1DECD80CE7722F98C10E75A0CD9A1FA81921A04EEFAC55BE0740C5F01ED83FDFC66380339D417\n";
+
+const char *l0Str =
+"198D1123A9817C40A914A3FF9E29BB16DD2F0DF98D0AB5C3A6014D60E31AE973051C35ADCEA0A41F32BB16E6688DC73F\n"
+"10339DB2F26D1B867FD3E60A24F938210EABEFC51536845A490F28A088A4AC53575DBBAA218D70D34E28EBDE14DB3465";
+const char *l1Str =
+"066852248D915F6378B3F4A8E6173AC748FBFAE236AAEEAECC3F34D2D22706A06B925A83DD8276B2B240F61D761587B0\n"
+"17CC8195E6607FF19A26AA69CA50C32487E35D2D75301AC4B6988F1B77523BF472927EE5710DF49A563534D86C684BE0\n";
+const char *l4Str =
+"10B67D1A0CE430B7AD74F64DD6C2E44C4788EADF8340909843C96B918BF54703CC14686B26E350EB1140ACC3337EEEB4\n"
+"0F5D52E6F0B10A081EFF885CC858109241B379985ADD8982E6B8A202FD283897EFBA4CBE444C29751410A61FC8346545\n";
+
+const char *f2Str =
+"10128E1A9BD00FC81F6550921D0FED3944F63F980ABF91FDB73B1ED162337ED16075730ACD60A0FA7DFABAD9FC9657C5\n"
+"055BE26091D8CDA32241F4991A1F184E403C3FFDD54858B23D5CE4B44402B65B26BCA6855DA7AC1C60F1D6651632DCD8\n"
+"0D70827981F0D33185DE8767FDDFEC26CEB6A28F82C83BBABB0057E432FCF9072B666974123274751E35F371E931D6CC\n"
+"02382B1A80E5BC95C75AE71BE2E097FD59365279CDD7EA358D87DEF132430744DABBF1B685D110CC731A9FDA40EEFC1B\n"
+"0AAB560FB99D57A9B1B6C753DAF6B0619ED598C9B5FB0908F2DAE83C530E6365DBEDE29B9357D63803F46247A1F41C73\n"
+"13C048F553BFC3C56516786DD26FF9D59ECFB9BE6B165F90E77CCED623BC66C6E93EFBF14576DB7E33C8C4F4E21F64DC\n"
+"0987D7DEBB96A10D977F256432871BEBB4B3A620E4AE822E089E9DAA192CD278E9FA0CF598444F6758628BC38C33A5AD\n"
+"0A4F1B75845B6C976BF49C35134AE73CA7A3C16D2E0BDA39C70367E3829E94EB7CAFBB0F8B57F4734B696D9CEF84FE73\n"
+"0DFAB9C035F3DA51226F27998A494A32245800F0313446D6437D2F5B3F34A9E91428818B0C9AF63EB3AA618E80055FD5\n"
+"06A58B9640FF8931616F6D08BA16ECE71F341C61F22E5EC5B556DF217179C3ECEC20E4BE425A3471F1D6648D14F89FBF\n"
+"1614391845CDC212937BC1070010603FB4DF99A6B3FA7E7CD3316C56BA8B633B3DC7D864B36DA2F9A1E6B977DB150100\n"
+"144A44415BCCB077EAA64C8DAC50631AF432C1420EBD8538818D65D6176BC1EB699579CED8340493306AF842B4B6822E";
+
+ Fp6 l;
+ Fp12 f, f2;
+ l.a.setStr(l0Str, 16);
+ l.b.setStr(l4Str, 16);
+ l.c.setStr(l1Str, 16);
+ f.setStr(fStr, 16);
+ f2.setStr(f2Str, 16);
+ local::mulSparse(f, l);
+ CYBOZU_TEST_EQUAL(f, f2);
+}
+
+CYBOZU_TEST_AUTO(pairing)
+{
+ const int mode = mcl::IoEcProj | 16;
+
+const char *pStr =
+"4 0FD3977C60EC322BC281C915955ED534B491E39C72E8E800271CEF3F0492D890829FA69C45FCE93D9847A0CAB325D871\n"
+"17CC2C36C5D283C05BFCECCF48DBB2050332DA058DD67326A9EE520967DBCAEDFCB5F05A085D1A49DF08BB968CC782C5\n"
+"000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001";
+const char *qStr =
+"4 0B5C339C23F8EAB3647E974BCDDF72C96F97A444346BE72CA73AB1323B83B8F6161257AB34C7E0CF34F6C45086CA5868\n"
+"13C2235E9F9DFB33344BA2EE5A71435859022880732EDC9EC75AC79AE9DA972593CDC40A0AC334D6D2E8D7FAD1D98D0B\n"
+"134B8EED8196A00D3B70ADBC26FF963B725A351CF0B73FE1A541788AFB0BB081AF82A438021B5E878B15D53B1D27C6A7\n"
+"18CC69F847BEE826B939DCB4030D33020D03B046465C9EE103AA8009A175DB169070294E75771586687FE361DB884BCD\n"
+"000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001\n"
+"000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+const char *eStr =
+"0E05D19E90D2C501E5502C7AC80D77201C47DF147DD1076440F0DF0179DF9802CA0775E0E73DD9174F1094D2280787B3\n"
+"14D2F5C84279E7177A3543FBEAE261DE8F6C97EFD5F3FF3F959EC9FC0303F620A4B3AF00DF409496CECADDD0A7F0A164\n"
+"1414E9B9DF8DF1EAC2E70D5538018377788C62016A54F28B037A68740705089AE431B86756F98CBE19690A5EAC0C2466\n"
+"12D8B32157836A131CCA3CA313DAAAF909BC3AD6BDD15885BB429922B9CD7D1246D1163E5E6F88D68BF1B75E451EFABB\n"
+"102C9A839A924E0D603D13F2E08A919E0B9EE2A269FC75727BA13D66027C157B9BB4077977FA94557DE4427BF11B234B\n"
+"19DBEB7F2E3096AFFD44837655BD8249741B484B0EB0DBEE569DEA8D9E38AE09D210C8BC16AA6DFBC923095B2C9A8B2B\n"
+"19B9A6DCCD01FA0D04D5CE94D8BDCE1DF64AFEB7FD493B955180A5C6B236E469F0E07CC9BB4203FCAC46AE6F8E5419D6\n"
+"02BFA87AF7A3726A7ABACDCFDD53694AF651554F3A431AB4274F67D5DAD2D6C88AF794705FF456A936C83594731AD8DC\n"
+"0F21E0173E3B50DD98EFA815B410631A57399B451FD6E1056FFD09C9FE50EFAD3D026F0C46C8BB1583A50B7853D990DA\n"
+"02230237AE04B61F9269F6E7CD2FCF1231CEE4690AA658B0018EFC0D0770FD0A56B3B7294086E8D306B1465CDDD858CD\n"
+"087EB8F6547015661E9CD48D6525C808636FCB8420B867CB2A87E006B2A93BBD5EF675E6CDDA9E6F94519C49EA8BB689\n"
+"19F5C988B2DD6E33D7D3D34EFB1991F80DC28006AC75E0AB53FD98FC6F2476D05DD4ECA582F5FF72B8DDD9DDDE80FFC9";
+ G1 P;
+ G2 Q;
+ P.setStr(pStr, mode);
+ Q.setStr(qStr, mode);
+ Fp12 e1, e2;
+ e1.setStr(eStr, 16);
+ pairing(e2, P, Q);
+ CYBOZU_TEST_EQUAL(e1, e2);
+}
+
+void testCurve(const mcl::CurveParam& cp)
+{
+ initPairing(cp, g_mode);
+ G1 P;
+ G2 Q;
+ mapToG1(P, 1);
+ mapToG2(Q, 1);
+ GT e1, e2;
+ pairing(e1, P, Q);
+ cybozu::XorShift rg;
+ mpz_class a, b;
+ Fr r;
+ r.setRand(rg); a = r.getMpz();
+ r.setRand(rg); b = r.getMpz();
+ G1 aP;
+ G2 bQ;
+ G1::mul(aP, P, a);
+ G2::mul(bQ, Q, b);
+ pairing(e2, aP, bQ);
+ GT::pow(e1, e1, a * b);
+ CYBOZU_TEST_EQUAL(e1, e2);
+}
+CYBOZU_TEST_AUTO(multi)
+{
+ G1 P;
+ G2 Q;
+ int i;
+ puts("BN254");
+ testCurve(mcl::BN254);
+ i = 1;
+ CYBOZU_BENCH_C("calcBN1", 100, (BN::param.mapTo.calcBN<G1, Fp>), P, i++);
+ CYBOZU_BENCH_C("naiveG2", 100, (BN::param.mapTo.naiveMapTo<G1, Fp>), P, i++);
+ CYBOZU_BENCH_C("calcBN2", 100, (BN::param.mapTo.calcBN<G2, Fp2>), Q, i++);
+ CYBOZU_BENCH_C("naiveG2", 100, (BN::param.mapTo.naiveMapTo<G2, Fp2>), Q, i++);
+ puts("BLS12_381");
+ testCurve(mcl::BLS12_381);
+ i = 1;
+ CYBOZU_BENCH_C("calcBN1", 100, (BN::param.mapTo.calcBN<G1, Fp>), P, i++);
+ CYBOZU_BENCH_C("naiveG1", 100, (BN::param.mapTo.naiveMapTo<G1, Fp>), P, i++);
+ CYBOZU_BENCH_C("calcBN2", 100, (BN::param.mapTo.calcBN<G2, Fp2>), Q, i++);
+ CYBOZU_BENCH_C("naiveG2", 100, (BN::param.mapTo.naiveMapTo<G2, Fp2>), Q, i++);
+}
+
+CYBOZU_TEST_AUTO(BLS12_G1mulCofactor)
+{
+ if (BN::param.cp.curveType != MCL_BLS12_381) return;
+}
+
+typedef std::vector<Fp> FpVec;
+
+void f(FpVec& zv, const FpVec& xv, const FpVec& yv)
+{
+ for (size_t i = 0; i < zv.size(); i++) {
+ Fp::mul(zv[i], xv[i], yv[i]);
+ }
+}
+int main(int argc, char *argv[])
+ try
+{
+ cybozu::Option opt;
+ std::string mode;
+ opt.appendOpt(&mode, "auto", "m", ": mode(gmp/gmp_mont/llvm/llvm_mont/xbyak)");
+ if (!opt.parse(argc, argv)) {
+ opt.usage();
+ return 1;
+ }
+ g_mode = mcl::fp::StrToMode(mode);
+ printf("JIT %d\n", mcl::fp::isEnableJIT());
+#if 0
+ initPairing(mcl::BLS12_381);
+ cybozu::XorShift rg;
+ const int n = 1;
+ std::vector<Fp> xv(n), yv(n), zv(n);
+ for (int i = 0; i < n; i++) {
+ xv[i].setByCSPRNG(rg);
+ yv[i].setByCSPRNG(rg);
+ }
+ FpDbl dx;
+ FpDbl::mulPre(dx, xv[0], yv[0]);
+ Fp2 x2, y2;
+ x2.a.setByCSPRNG(rg);
+ x2.b.setByCSPRNG(rg);
+ y2.a.setByCSPRNG(rg);
+ y2.b.setByCSPRNG(rg);
+ Fp2Dbl x2d, y2d;
+ Fp2Dbl::mulPre(x2d, x2, x2);
+ Fp2Dbl::mulPre(y2d, x2, y2);
+if(0){
+ puts("----------");
+ xv[0].dump();
+ yv[0].dump();
+ dx.dump();
+ puts("----------");
+// exit(1);
+}
+// CYBOZU_BENCH_C("Fp2::neg", 10000000, Fp2::neg, x2, x2);
+ CYBOZU_BENCH_C("Fp2::sqr", 10000000, Fp2::sqr, x2, x2);
+// CYBOZU_BENCH_C("Fp2::sqrPre", 100000000, Fp2Dbl::sqrPre, x2d, x2);
+// CYBOZU_BENCH_C("Fp2::mulPre", 100000000, Fp2Dbl::mulPre, x2d, x2, y2);
+// CYBOZU_BENCH_C("sqrPre", 100000000, FpDbl::sqrPre, dx, xv[0]);
+// CYBOZU_BENCH_C("mod ", 100000000, FpDbl::mod, xv[0], dx);
+// CYBOZU_BENCH_C("mul ", 100000000, Fp::mul, xv[0], yv[0], xv[0]);
+// CYBOZU_BENCH_C("sqr ", 100000000, Fp::sqr, xv[0], xv[0]);
+ return 0;
+#endif
+ return cybozu::test::autoRun.run(argc, argv);
+} catch (std::exception& e) {
+ printf("ERR %s\n", e.what());
+ return 1;
+}
diff --git a/vendor/github.com/tangerine-network/mcl/test/bn384_test.cpp b/vendor/github.com/tangerine-network/mcl/test/bn384_test.cpp
new file mode 100644
index 000000000..b5674a918
--- /dev/null
+++ b/vendor/github.com/tangerine-network/mcl/test/bn384_test.cpp
@@ -0,0 +1,83 @@
+#define CYBOZU_TEST_DISABLE_AUTO_RUN
+#include <cybozu/test.hpp>
+#include <cybozu/benchmark.hpp>
+#include <cybozu/option.hpp>
+#include <cybozu/xorshift.hpp>
+#include <mcl/bn384.hpp>
+#include <mcl/bn.hpp>
+
+using namespace mcl::bn384;
+
+mcl::fp::Mode g_mode;
+
+#include "bench.hpp"
+
+void testCurve(const mcl::CurveParam& cp)
+{
+ initPairing(cp, g_mode);
+ G1 P;
+ G2 Q;
+ mapToG1(P, 1);
+ mapToG2(Q, 1);
+ GT e1, e2;
+#ifdef ONLY_BENCH
+ cybozu::CpuClock clk;
+ for (int i = 0; i < 10000; i++) { clk.begin(); pairing(e1, P, Q); clk.end(); }
+ clk.put();
+ return;
+#endif
+ pairing(e1, P, Q);
+ cybozu::XorShift rg;
+ mpz_class a, b;
+ Fr r;
+ r.setRand(rg); a = r.getMpz();
+ r.setRand(rg); b = r.getMpz();
+ G1 aP;
+ G2 bQ;
+ G1::mul(aP, P, a);
+ G2::mul(bQ, Q, b);
+ pairing(e2, aP, bQ);
+ GT::pow(e1, e1, a * b);
+ CYBOZU_TEST_EQUAL(e1, e2);
+ testBench(P, Q);
+ testSquareRoot();
+ testLagrange();
+}
+
+CYBOZU_TEST_AUTO(pairing)
+{
+// puts("BN160");
+// testCurve(mcl::BN160);
+ puts("BN254");
+ // support 256-bit pairing
+ testCurve(mcl::BN254);
+ puts("BN381_1");
+ testCurve(mcl::BN381_1);
+ puts("BN381_2");
+ testCurve(mcl::BN381_2);
+ puts("BLS12_381");
+ testCurve(mcl::BLS12_381);
+ // Q is not on EcT, but bad order
+ {
+ const char *s = "1 18d3d8c085a5a5e7553c3a4eb628e88b8465bf4de2612e35a0a4eb018fb0c82e9698896031e62fd7633ffd824a859474 1dc6edfcf33e29575d4791faed8e7203832217423bf7f7fbf1f6b36625b12e7132c15fbc15562ce93362a322fb83dd0d 65836963b1f7b6959030ddfa15ab38ce056097e91dedffd996c1808624fa7e2644a77be606290aa555cda8481cfb3cb 1b77b708d3d4f65aeedf54b58393463a42f0dc5856baadb5ce608036baeca398c5d9e6b169473a8838098fd72fd28b50";
+ G2 Q;
+ CYBOZU_TEST_EXCEPTION(Q.setStr(s, 16), std::exception);
+ }
+}
+
+int main(int argc, char *argv[])
+ try
+{
+ cybozu::Option opt;
+ std::string mode;
+ opt.appendOpt(&mode, "auto", "m", ": mode(gmp/gmp_mont/llvm/llvm_mont/xbyak)");
+ if (!opt.parse(argc, argv)) {
+ opt.usage();
+ return 1;
+ }
+ g_mode = mcl::fp::StrToMode(mode);
+ return cybozu::test::autoRun.run(argc, argv);
+} catch (std::exception& e) {
+ printf("ERR %s\n", e.what());
+ return 1;
+}
diff --git a/vendor/github.com/tangerine-network/mcl/test/bn512_test.cpp b/vendor/github.com/tangerine-network/mcl/test/bn512_test.cpp
new file mode 100644
index 000000000..905bfd3db
--- /dev/null
+++ b/vendor/github.com/tangerine-network/mcl/test/bn512_test.cpp
@@ -0,0 +1,68 @@
+#define CYBOZU_TEST_DISABLE_AUTO_RUN
+#include <cybozu/test.hpp>
+#include <cybozu/benchmark.hpp>
+#include <cybozu/option.hpp>
+#include <cybozu/xorshift.hpp>
+#include <mcl/bn512.hpp>
+#include <mcl/bn.hpp>
+
+using namespace mcl::bn512;
+
+mcl::fp::Mode g_mode;
+
+#include "bench.hpp"
+
+void testCurve(const mcl::CurveParam& cp)
+{
+ initPairing(cp, g_mode);
+ G1 P;
+ G2 Q;
+ mapToG1(P, 1);
+ mapToG2(Q, 1);
+ GT e1, e2;
+ pairing(e1, P, Q);
+ cybozu::XorShift rg;
+ mpz_class a, b;
+ Fr r;
+ r.setRand(rg); a = r.getMpz();
+ r.setRand(rg); b = r.getMpz();
+ G1 aP;
+ G2 bQ;
+ G1::mul(aP, P, a);
+ G2::mul(bQ, Q, b);
+ pairing(e2, aP, bQ);
+ GT::pow(e1, e1, a * b);
+ CYBOZU_TEST_EQUAL(e1, e2);
+ testBench(P, Q);
+ testSquareRoot();
+ testLagrange();
+}
+
+CYBOZU_TEST_AUTO(pairing)
+{
+ puts("BN462");
+ testCurve(mcl::BN462);
+ puts("BN381_1");
+ testCurve(mcl::BN381_1);
+ puts("BLS12_381");
+ testCurve(mcl::BLS12_381);
+ puts("BN254");
+ testCurve(mcl::BN254);
+}
+
+int main(int argc, char *argv[])
+ try
+{
+ cybozu::Option opt;
+ std::string mode;
+ opt.appendOpt(&mode, "auto", "m", ": mode(gmp/gmp_mont/llvm/llvm_mont/xbyak)");
+ if (!opt.parse(argc, argv)) {
+ opt.usage();
+ return 1;
+ }
+ g_mode = mcl::fp::StrToMode(mode);
+ return cybozu::test::autoRun.run(argc, argv);
+} catch (std::exception& e) {
+ printf("ERR %s\n", e.what());
+ return 1;
+}
diff --git a/vendor/github.com/tangerine-network/mcl/test/bn_c256_test.cpp b/vendor/github.com/tangerine-network/mcl/test/bn_c256_test.cpp
new file mode 100644
index 000000000..2ce85162d
--- /dev/null
+++ b/vendor/github.com/tangerine-network/mcl/test/bn_c256_test.cpp
@@ -0,0 +1,6 @@
+#include <mcl/bn256.hpp>
+using namespace mcl::bn256;
+#define MCLBN_DEFINE_STRUCT
+#define MCLBN_FP_UNIT_SIZE 4
+#include "bn_c_test.hpp"
+
diff --git a/vendor/github.com/tangerine-network/mcl/test/bn_c384_256_test.cpp b/vendor/github.com/tangerine-network/mcl/test/bn_c384_256_test.cpp
new file mode 100644
index 000000000..e7bbefda9
--- /dev/null
+++ b/vendor/github.com/tangerine-network/mcl/test/bn_c384_256_test.cpp
@@ -0,0 +1,7 @@
+#include <mcl/bls12_381.hpp>
+using namespace mcl::bls12;
+#define MCLBN_DEFINE_STRUCT
+#define MCLBN_FP_UNIT_SIZE 6
+#define MCLBN_FR_UNIT_SIZE 4
+#include "bn_c_test.hpp"
+
diff --git a/vendor/github.com/tangerine-network/mcl/test/bn_c384_test.cpp b/vendor/github.com/tangerine-network/mcl/test/bn_c384_test.cpp
new file mode 100644
index 000000000..a9f20243a
--- /dev/null
+++ b/vendor/github.com/tangerine-network/mcl/test/bn_c384_test.cpp
@@ -0,0 +1,6 @@
+#include <mcl/bn384.hpp>
+using namespace mcl::bn384;
+#define MCLBN_DEFINE_STRUCT
+#define MCLBN_FP_UNIT_SIZE 6
+#include "bn_c_test.hpp"
+
diff --git a/vendor/github.com/tangerine-network/mcl/test/bn_c512_test.cpp b/vendor/github.com/tangerine-network/mcl/test/bn_c512_test.cpp
new file mode 100644
index 000000000..c6af3989f
--- /dev/null
+++ b/vendor/github.com/tangerine-network/mcl/test/bn_c512_test.cpp
@@ -0,0 +1,6 @@
+#include <mcl/bn512.hpp>
+using namespace mcl::bn512;
+#define MCLBN_DEFINE_STRUCT
+#define MCLBN_FP_UNIT_SIZE 8
+#include "bn_c_test.hpp"
+
diff --git a/vendor/github.com/tangerine-network/mcl/test/bn_c_test.hpp b/vendor/github.com/tangerine-network/mcl/test/bn_c_test.hpp
new file mode 100644
index 000000000..e9dc59393
--- /dev/null
+++ b/vendor/github.com/tangerine-network/mcl/test/bn_c_test.hpp
@@ -0,0 +1,699 @@
+/*
+ include from bn_if256_test.cpp and bn_if384_test.cpp
+*/
+#include <mcl/bn.h>
+#include <mcl/ecparam.hpp>
+#include <cybozu/test.hpp>
+#include <iostream>
+#include <gmpxx.h>
+
+template<size_t N>
+std::ostream& dump(std::ostream& os, const uint64_t (&x)[N])
+{
+ for (size_t i = 0; i < N; i++) {
+ char buf[64];
+ CYBOZU_SNPRINTF(buf, sizeof(buf), "%016llx", (long long)x[i]);
+ os << buf;
+ }
+ return os;
+}
+
+CYBOZU_TEST_AUTO(init)
+{
+ int ret;
+ CYBOZU_TEST_EQUAL(sizeof(mclBnFr), sizeof(Fr));
+ CYBOZU_TEST_EQUAL(sizeof(mclBnG1), sizeof(G1));
+ CYBOZU_TEST_EQUAL(sizeof(mclBnG2), sizeof(G2));
+ CYBOZU_TEST_EQUAL(sizeof(mclBnGT), sizeof(Fp12));
+
+#if MCLBN_FP_UNIT_SIZE >= 4
+ printf("test BN254 %d\n", MCLBN_FP_UNIT_SIZE);
+ ret = mclBn_init(MCL_BN254, MCLBN_COMPILED_TIME_VAR);
+#endif
+#if MCLBN_FP_UNIT_SIZE >= 6 && MCLBN_FR_UNIT_SIZE >= 4
+ printf("test BLS12_381 %d\n", MCLBN_FP_UNIT_SIZE);
+ ret = mclBn_init(MCL_BLS12_381, MCLBN_COMPILED_TIME_VAR);
+#endif
+#if MCLBN_FP_UNIT_SIZE >= 6 && MCLBN_FR_UNIT_SIZE >= 6
+ printf("test BN381_1 %d\n", MCLBN_FP_UNIT_SIZE);
+ ret = mclBn_init(MCL_BN381_1, MCLBN_COMPILED_TIME_VAR);
+#endif
+#if MCLBN_FP_UNIT_SIZE == 8
+ printf("test BN462 %d\n", MCLBN_FP_UNIT_SIZE);
+ ret = mclBn_init(MCL_BN462, MCLBN_COMPILED_TIME_VAR);
+#endif
+ CYBOZU_TEST_EQUAL(ret, 0);
+ if (ret != 0) exit(1);
+}
+
+CYBOZU_TEST_AUTO(Fr)
+{
+ mclBnFr x, y;
+ memset(&x, 0xff, sizeof(x));
+ CYBOZU_TEST_ASSERT(!mclBnFr_isValid(&x));
+ CYBOZU_TEST_ASSERT(!mclBnFr_isZero(&x));
+
+ mclBnFr_clear(&x);
+ CYBOZU_TEST_ASSERT(mclBnFr_isZero(&x));
+
+ mclBnFr_setInt(&x, 1);
+ CYBOZU_TEST_ASSERT(mclBnFr_isOne(&x));
+
+ mclBnFr_setInt(&y, -1);
+ CYBOZU_TEST_ASSERT(!mclBnFr_isEqual(&x, &y));
+
+ y = x;
+ CYBOZU_TEST_ASSERT(mclBnFr_isEqual(&x, &y));
+
+ mclBnFr_setHashOf(&x, "", 0);
+ mclBnFr_setHashOf(&y, "abc", 3);
+ CYBOZU_TEST_ASSERT(!mclBnFr_isEqual(&x, &y));
+ mclBnFr_setHashOf(&x, "abc", 3);
+ CYBOZU_TEST_ASSERT(mclBnFr_isEqual(&x, &y));
+
+ char buf[1024];
+ mclBnFr_setInt(&x, 12345678);
+ size_t size;
+ size = mclBnFr_getStr(buf, sizeof(buf), &x, 10);
+ CYBOZU_TEST_EQUAL(size, 8);
+ CYBOZU_TEST_EQUAL(buf, "12345678");
+
+ mclBnFr_setInt(&x, -7654321);
+ mclBnFr_neg(&x, &x);
+ size = mclBnFr_getStr(buf, sizeof(buf), &x, 10);
+ CYBOZU_TEST_EQUAL(size, 7);
+ CYBOZU_TEST_EQUAL(buf, "7654321");
+
+ mclBnFr_setInt(&y, 123 - 7654321);
+ mclBnFr_add(&x, &x, &y);
+ size = mclBnFr_getStr(buf, sizeof(buf), &x, 10);
+ CYBOZU_TEST_EQUAL(size, 3);
+ CYBOZU_TEST_EQUAL(buf, "123");
+
+ mclBnFr_setInt(&y, 100);
+ mclBnFr_sub(&x, &x, &y);
+ size = mclBnFr_getStr(buf, sizeof(buf), &x, 10);
+ CYBOZU_TEST_EQUAL(size, 2);
+ CYBOZU_TEST_EQUAL(buf, "23");
+
+ mclBnFr_mul(&x, &x, &y);
+ size = mclBnFr_getStr(buf, sizeof(buf), &x, 10);
+ CYBOZU_TEST_EQUAL(size, 4);
+ CYBOZU_TEST_EQUAL(buf, "2300");
+
+ mclBnFr_div(&x, &x, &y);
+ size = mclBnFr_getStr(buf, sizeof(buf), &x, 10);
+ CYBOZU_TEST_EQUAL(size, 2);
+ CYBOZU_TEST_EQUAL(buf, "23");
+
+ mclBnFr_mul(&x, &y, &y);
+ mclBnFr_sqr(&y, &y);
+ CYBOZU_TEST_ASSERT(mclBnFr_isEqual(&x, &y));
+
+ const char *s = "12345678901234567";
+ CYBOZU_TEST_ASSERT(!mclBnFr_setStr(&x, s, strlen(s), 10));
+ s = "20000000000000000";
+ CYBOZU_TEST_ASSERT(!mclBnFr_setStr(&y, s, strlen(s), 10));
+ mclBnFr_add(&x, &x, &y);
+ size = mclBnFr_getStr(buf, sizeof(buf), &x, 10);
+ CYBOZU_TEST_EQUAL(size, 17);
+ CYBOZU_TEST_EQUAL(buf, "32345678901234567");
+
+ mclBnFr_setInt(&x, 1);
+ mclBnFr_neg(&x, &x);
+ size = mclBnFr_getStr(buf, sizeof(buf), &x, 10);
+ CYBOZU_TEST_ASSERT(size > 0);
+ CYBOZU_TEST_EQUAL(size, strlen(buf));
+ CYBOZU_TEST_ASSERT(!mclBnFr_setStr(&y, buf, size, 10));
+ CYBOZU_TEST_ASSERT(mclBnFr_isEqual(&x, &y));
+
+ for (int i = 0; i < 10; i++) {
+ mclBnFr_setByCSPRNG(&x);
+ mclBnFr_getStr(buf, sizeof(buf), &x, 16);
+ printf("%s\n", buf);
+ }
+}
+
+void G1test()
+{
+ mclBnG1 x, y, z;
+ memset(&x, 0x1, sizeof(x));
+ /*
+ assert() of carry operation fails if use 0xff, so use 0x1
+ */
+ CYBOZU_TEST_ASSERT(!mclBnG1_isValid(&x));
+ mclBnG1_clear(&x);
+ CYBOZU_TEST_ASSERT(mclBnG1_isValid(&x));
+ CYBOZU_TEST_ASSERT(mclBnG1_isZero(&x));
+
+ CYBOZU_TEST_ASSERT(!mclBnG1_hashAndMapTo(&y, "abc", 3));
+ CYBOZU_TEST_ASSERT(mclBnG1_isValidOrder(&y));
+
+ char buf[1024];
+ size_t size;
+ size = mclBnG1_getStr(buf, sizeof(buf), &y, 10);
+ CYBOZU_TEST_ASSERT(size > 0);
+ CYBOZU_TEST_EQUAL(size, strlen(buf));
+ CYBOZU_TEST_ASSERT(!mclBnG1_setStr(&x, buf, strlen(buf), 10));
+ CYBOZU_TEST_ASSERT(mclBnG1_isEqual(&x, &y));
+
+ mclBnG1_neg(&x, &x);
+ mclBnG1_add(&x, &x, &y);
+ CYBOZU_TEST_ASSERT(mclBnG1_isZero(&x));
+
+ mclBnG1_dbl(&x, &y); // x = 2y
+ mclBnG1_add(&z, &y, &y);
+ CYBOZU_TEST_ASSERT(mclBnG1_isEqual(&x, &z));
+ mclBnG1_add(&z, &z, &y); // z = 3y
+ mclBnFr n;
+ mclBnFr_setInt(&n, 3);
+ mclBnG1_mul(&x, &y, &n); // x = 3y
+ CYBOZU_TEST_ASSERT(mclBnG1_isEqual(&x, &z));
+ mclBnG1_sub(&x, &x, &y); // x = 2y
+
+ mclBnFr_setInt(&n, 2);
+ mclBnG1_mul(&z, &y, &n); // z = 2y
+ CYBOZU_TEST_ASSERT(mclBnG1_isEqual(&x, &z));
+ mclBnG1_normalize(&y, &z);
+ CYBOZU_TEST_ASSERT(mclBnG1_isEqual(&y, &z));
+}
+
+CYBOZU_TEST_AUTO(G1)
+{
+ G1test();
+}
+
+CYBOZU_TEST_AUTO(G2)
+{
+ mclBnG2 x, y, z;
+ /*
+ assert() of carry operation fails if use 0xff, so use 0x1
+ */
+ memset(&x, 0x1, sizeof(x));
+ CYBOZU_TEST_ASSERT(!mclBnG2_isValid(&x));
+ mclBnG2_clear(&x);
+ CYBOZU_TEST_ASSERT(mclBnG2_isValid(&x));
+ CYBOZU_TEST_ASSERT(mclBnG2_isZero(&x));
+
+ CYBOZU_TEST_ASSERT(!mclBnG2_hashAndMapTo(&x, "abc", 3));
+ CYBOZU_TEST_ASSERT(mclBnG2_isValidOrder(&x));
+
+ char buf[1024];
+ size_t size;
+ size = mclBnG2_getStr(buf, sizeof(buf), &x, 10);
+ CYBOZU_TEST_ASSERT(size > 0);
+ CYBOZU_TEST_EQUAL(size, strlen(buf));
+ CYBOZU_TEST_ASSERT(!mclBnG2_setStr(&y, buf, strlen(buf), 10));
+ CYBOZU_TEST_ASSERT(mclBnG2_isEqual(&x, &y));
+
+ mclBnG2_neg(&x, &x);
+ mclBnG2_add(&x, &x, &y);
+ CYBOZU_TEST_ASSERT(mclBnG2_isZero(&x));
+
+ mclBnG2_dbl(&x, &y); // x = 2y
+ mclBnG2_add(&z, &y, &y);
+ CYBOZU_TEST_ASSERT(mclBnG2_isEqual(&x, &z));
+ mclBnG2_add(&z, &z, &y); // z = 3y
+ mclBnFr n;
+ mclBnFr_setInt(&n, 3);
+ mclBnG2_mul(&x, &y, &n); // x = 3y
+ CYBOZU_TEST_ASSERT(mclBnG2_isEqual(&x, &z));
+ mclBnG2_sub(&x, &x, &y); // x = 2y
+
+ mclBnFr_setInt(&n, 2);
+ mclBnG2_mul(&z, &y, &n); // z = 2y
+ CYBOZU_TEST_ASSERT(mclBnG2_isEqual(&x, &z));
+ mclBnG2_normalize(&y, &z);
+ CYBOZU_TEST_ASSERT(mclBnG2_isEqual(&y, &z));
+}
+
+CYBOZU_TEST_AUTO(GT)
+{
+ mclBnGT x, y, z;
+ memset(&x, 1, sizeof(x));
+ CYBOZU_TEST_ASSERT(!mclBnGT_isZero(&x));
+
+ mclBnGT_clear(&x);
+ CYBOZU_TEST_ASSERT(mclBnGT_isZero(&x));
+
+ mclBnGT_setInt(&x, 1);
+ CYBOZU_TEST_ASSERT(mclBnGT_isOne(&x));
+ char buf[2048];
+ size_t size;
+ size = mclBnGT_getStr(buf, sizeof(buf), &x, 10);
+ CYBOZU_TEST_ASSERT(size > 0);
+ CYBOZU_TEST_EQUAL(size, strlen(buf));
+ const char *s = "1 0 0 0 0 0 0 0 0 0 0 0";
+ CYBOZU_TEST_EQUAL(buf, s);
+
+ s = "1 2 3 4 5 6 7 8 9 10 11 12";
+ CYBOZU_TEST_ASSERT(!mclBnGT_setStr(&x,s , strlen(s), 10));
+ size = mclBnGT_getStr(buf, sizeof(buf), &x, 10);
+ CYBOZU_TEST_ASSERT(size > 0);
+ CYBOZU_TEST_EQUAL(size, strlen(buf));
+ CYBOZU_TEST_EQUAL(buf, s);
+
+ y = x;
+ CYBOZU_TEST_ASSERT(mclBnGT_isEqual(&x, &y));
+
+ s = "-1 -2 -3 -4 -5 -6 -7 -8 -9 -10 -11 -12";
+ CYBOZU_TEST_ASSERT(!mclBnGT_setStr(&z, s, strlen(s), 10));
+ size = mclBnGT_getStr(buf, sizeof(buf), &z, 10);
+ CYBOZU_TEST_ASSERT(size > 0);
+ CYBOZU_TEST_EQUAL(size, strlen(buf));
+ CYBOZU_TEST_ASSERT(!mclBnGT_setStr(&y, buf, size, 10));
+
+ mclBnGT_neg(&z, &y);
+ CYBOZU_TEST_ASSERT(mclBnGT_isEqual(&x, &z));
+
+ mclBnGT_add(&y, &x, &y);
+ CYBOZU_TEST_ASSERT(mclBnGT_isZero(&y));
+
+ s = "2 0 0 0 0 0 0 0 0 0 0 0";
+ CYBOZU_TEST_ASSERT(!mclBnGT_setStr(&y, s, strlen(s), 10));
+ mclBnGT_mul(&z, &x, &y);
+ size = mclBnGT_getStr(buf, sizeof(buf), &z, 10);
+ CYBOZU_TEST_ASSERT(size > 0);
+ CYBOZU_TEST_EQUAL(size, strlen(buf));
+ CYBOZU_TEST_EQUAL(buf, "2 4 6 8 10 12 14 16 18 20 22 24");
+
+ mclBnGT_div(&z, &z, &y);
+ size = mclBnGT_getStr(buf, sizeof(buf), &x, 10);
+ CYBOZU_TEST_ASSERT(size > 0);
+ CYBOZU_TEST_EQUAL(size, strlen(buf));
+ CYBOZU_TEST_ASSERT(mclBnGT_isEqual(&x, &z));
+
+ /*
+ can't use mclBnGT_pow because x is not in GT
+ */
+ mclBnFr n;
+ mclBnFr_setInt(&n, 3);
+ mclBnGT_powGeneric(&z, &x, &n);
+ mclBnGT_mul(&y, &x, &x);
+ mclBnGT_mul(&y, &y, &x);
+ CYBOZU_TEST_ASSERT(mclBnGT_isEqual(&y, &z));
+
+ mclBnGT_mul(&x, &y, &y);
+ mclBnGT_sqr(&y, &y);
+ CYBOZU_TEST_ASSERT(mclBnGT_isEqual(&x, &y));
+}
+
+CYBOZU_TEST_AUTO(pairing)
+{
+ mclBnFr a, b, ab;
+ mclBnFr_setInt(&a, 123);
+ mclBnFr_setInt(&b, 456);
+ mclBnFr_mul(&ab, &a, &b);
+ mclBnG1 P, aP;
+ mclBnG2 Q, bQ;
+ mclBnGT e, e1, e2;
+
+ CYBOZU_TEST_ASSERT(!mclBnG1_hashAndMapTo(&P, "1", 1));
+ CYBOZU_TEST_ASSERT(!mclBnG2_hashAndMapTo(&Q, "1", 1));
+
+ mclBnG1_mul(&aP, &P, &a);
+ mclBnG2_mul(&bQ, &Q, &b);
+
+ mclBn_pairing(&e, &P, &Q);
+ mclBnGT_pow(&e1, &e, &a);
+ mclBn_pairing(&e2, &aP, &Q);
+ CYBOZU_TEST_ASSERT(mclBnGT_isEqual(&e1, &e2));
+
+ mclBnGT_pow(&e1, &e, &b);
+ mclBn_pairing(&e2, &P, &bQ);
+ CYBOZU_TEST_ASSERT(mclBnGT_isEqual(&e1, &e2));
+
+ mclBnFr n;
+ mclBnFr_setInt(&n, 3);
+ mclBnGT_pow(&e1, &e, &n);
+ mclBnGT_mul(&e2, &e, &e);
+ mclBnGT_mul(&e2, &e2, &e);
+ CYBOZU_TEST_ASSERT(mclBnGT_isEqual(&e1, &e2));
+}
+
+CYBOZU_TEST_AUTO(precomputed)
+{
+ mclBnG1 P1, P2;
+ mclBnG2 Q1, Q2;
+ CYBOZU_TEST_ASSERT(!mclBnG1_hashAndMapTo(&P1, "1", 1));
+ CYBOZU_TEST_ASSERT(!mclBnG1_hashAndMapTo(&P2, "123", 3));
+ CYBOZU_TEST_ASSERT(!mclBnG2_hashAndMapTo(&Q1, "1", 1));
+ CYBOZU_TEST_ASSERT(!mclBnG2_hashAndMapTo(&Q2, "2", 1));
+
+ const int size = mclBn_getUint64NumToPrecompute();
+ std::vector<uint64_t> Q1buf, Q2buf;
+ Q1buf.resize(size);
+ Q2buf.resize(size);
+ mclBn_precomputeG2(Q1buf.data(), &Q1);
+ mclBn_precomputeG2(Q2buf.data(), &Q2);
+
+ mclBnGT e1, e2, f1, f2, f3, f4;
+ mclBn_pairing(&e1, &P1, &Q1);
+ mclBn_precomputedMillerLoop(&f1, &P1, Q1buf.data());
+ mclBn_finalExp(&f1, &f1);
+ CYBOZU_TEST_ASSERT(mclBnGT_isEqual(&e1, &f1));
+
+ mclBn_pairing(&e2, &P2, &Q2);
+ mclBn_precomputedMillerLoop(&f2, &P2, Q2buf.data());
+ mclBn_finalExp(&f2, &f2);
+ CYBOZU_TEST_ASSERT(mclBnGT_isEqual(&e2, &f2));
+
+ mclBn_precomputedMillerLoop2(&f3, &P1, Q1buf.data(), &P2, Q2buf.data());
+ mclBn_precomputedMillerLoop2mixed(&f4, &P1, &Q1, &P2, Q2buf.data());
+ CYBOZU_TEST_ASSERT(mclBnGT_isEqual(&f3, &f4));
+ mclBn_finalExp(&f3, &f3);
+
+ mclBnGT_mul(&e1, &e1, &e2);
+ CYBOZU_TEST_ASSERT(mclBnGT_isEqual(&e1, &f3));
+}
+
+CYBOZU_TEST_AUTO(serialize)
+{
+ const size_t FrSize = mclBn_getFrByteSize();
+ const size_t G1Size = mclBn_getG1ByteSize();
+ mclBnFr x1, x2;
+ mclBnG1 P1, P2;
+ mclBnG2 Q1, Q2;
+ char buf[1024];
+ size_t n;
+ size_t expectSize;
+ size_t ret;
+ // Fr
+ expectSize = FrSize;
+ mclBnFr_setInt(&x1, -1);
+ n = mclBnFr_serialize(buf, sizeof(buf), &x1);
+ CYBOZU_TEST_EQUAL(n, expectSize);
+
+ ret = mclBnFr_deserialize(&x2, buf, n);
+ CYBOZU_TEST_EQUAL(ret, n);
+ CYBOZU_TEST_ASSERT(mclBnFr_isEqual(&x1, &x2));
+
+ ret = mclBnFr_deserialize(&x2, buf, n - 1);
+ CYBOZU_TEST_EQUAL(ret, 0);
+
+ memset(&x2, 0, sizeof(x2));
+ ret = mclBnFr_deserialize(&x2, buf, n + 1);
+ CYBOZU_TEST_EQUAL(ret, n);
+ CYBOZU_TEST_ASSERT(mclBnFr_isEqual(&x1, &x2));
+
+ n = mclBnFr_serialize(buf, expectSize, &x1);
+ CYBOZU_TEST_EQUAL(n, expectSize);
+
+ // G1
+ expectSize = G1Size;
+ mclBnG1_hashAndMapTo(&P1, "1", 1);
+ n = mclBnG1_serialize(buf, sizeof(buf), &P1);
+ CYBOZU_TEST_EQUAL(n, expectSize);
+
+ ret = mclBnG1_deserialize(&P2, buf, n);
+ CYBOZU_TEST_EQUAL(ret, n);
+ CYBOZU_TEST_ASSERT(mclBnG1_isEqual(&P1, &P2));
+
+ ret = mclBnG1_deserialize(&P2, buf, n - 1);
+ CYBOZU_TEST_EQUAL(ret, 0);
+
+ memset(&P2, 0, sizeof(P2));
+ ret = mclBnG1_deserialize(&P2, buf, n + 1);
+ CYBOZU_TEST_EQUAL(ret, n);
+ CYBOZU_TEST_ASSERT(mclBnG1_isEqual(&P1, &P2));
+
+ n = mclBnG1_serialize(buf, expectSize, &P1);
+ CYBOZU_TEST_EQUAL(n, expectSize);
+
+ // G2
+ expectSize = G1Size * 2;
+ mclBnG2_hashAndMapTo(&Q1, "1", 1);
+ n = mclBnG2_serialize(buf, sizeof(buf), &Q1);
+ CYBOZU_TEST_EQUAL(n, expectSize);
+
+ ret = mclBnG2_deserialize(&Q2, buf, n);
+ CYBOZU_TEST_EQUAL(ret, n);
+ CYBOZU_TEST_ASSERT(mclBnG2_isEqual(&Q1, &Q2));
+
+ ret = mclBnG2_deserialize(&Q2, buf, n - 1);
+ CYBOZU_TEST_EQUAL(ret, 0);
+
+ memset(&Q2, 0, sizeof(Q2));
+ ret = mclBnG2_deserialize(&Q2, buf, n + 1);
+ CYBOZU_TEST_EQUAL(ret, n);
+ CYBOZU_TEST_ASSERT(mclBnG2_isEqual(&Q1, &Q2));
+
+ n = mclBnG2_serialize(buf, expectSize, &Q1);
+ CYBOZU_TEST_EQUAL(n, expectSize);
+}
+
+CYBOZU_TEST_AUTO(serializeToHexStr)
+{
+ const size_t FrSize = mclBn_getFrByteSize();
+ const size_t G1Size = mclBn_getG1ByteSize();
+ mclBnFr x1, x2;
+ mclBnG1 P1, P2;
+ mclBnG2 Q1, Q2;
+ char buf[1024];
+ size_t n;
+ size_t expectSize;
+ size_t ret;
+ // Fr
+ expectSize = FrSize * 2; // hex string
+ mclBnFr_setInt(&x1, -1);
+ n = mclBnFr_getStr(buf, sizeof(buf), &x1, MCLBN_IO_SERIALIZE_HEX_STR);
+ CYBOZU_TEST_EQUAL(n, expectSize);
+
+ ret = mclBnFr_setStr(&x2, buf, n, MCLBN_IO_SERIALIZE_HEX_STR);
+ CYBOZU_TEST_EQUAL(ret, 0);
+ CYBOZU_TEST_ASSERT(mclBnFr_isEqual(&x1, &x2));
+
+ ret = mclBnFr_setStr(&x2, buf, n - 1, MCLBN_IO_SERIALIZE_HEX_STR);
+ CYBOZU_TEST_ASSERT(ret != 0);
+
+ memset(&x2, 0, sizeof(x2));
+ ret = mclBnFr_setStr(&x2, buf, n + 1, MCLBN_IO_SERIALIZE_HEX_STR);
+ CYBOZU_TEST_EQUAL(ret, 0);
+ CYBOZU_TEST_ASSERT(mclBnFr_isEqual(&x1, &x2));
+
+ n = mclBnFr_getStr(buf, expectSize, &x1, MCLBN_IO_SERIALIZE_HEX_STR);
+ CYBOZU_TEST_EQUAL(n, expectSize);
+
+ // G1
+ expectSize = G1Size * 2; // hex string
+ mclBnG1_hashAndMapTo(&P1, "1", 1);
+ n = mclBnG1_getStr(buf, sizeof(buf), &P1, MCLBN_IO_SERIALIZE_HEX_STR);
+ CYBOZU_TEST_EQUAL(n, expectSize);
+
+ ret = mclBnG1_setStr(&P2, buf, n, MCLBN_IO_SERIALIZE_HEX_STR);
+ CYBOZU_TEST_EQUAL(ret, 0);
+ CYBOZU_TEST_ASSERT(mclBnG1_isEqual(&P1, &P2));
+
+ ret = mclBnG1_setStr(&P2, buf, n - 1, MCLBN_IO_SERIALIZE_HEX_STR);
+ CYBOZU_TEST_ASSERT(ret != 0);
+
+ memset(&P2, 0, sizeof(P2));
+ ret = mclBnG1_setStr(&P2, buf, n + 1, MCLBN_IO_SERIALIZE_HEX_STR);
+ CYBOZU_TEST_EQUAL(ret, 0);
+ CYBOZU_TEST_ASSERT(mclBnG1_isEqual(&P1, &P2));
+
+ n = mclBnG1_getStr(buf, expectSize, &P1, MCLBN_IO_SERIALIZE_HEX_STR);
+ CYBOZU_TEST_EQUAL(n, expectSize);
+
+ // G2
+ expectSize = G1Size * 2 * 2; // hex string
+ mclBnG2_hashAndMapTo(&Q1, "1", 1);
+ n = mclBnG2_getStr(buf, sizeof(buf), &Q1, MCLBN_IO_SERIALIZE_HEX_STR);
+ CYBOZU_TEST_EQUAL(n, expectSize);
+
+ ret = mclBnG2_setStr(&Q2, buf, n, MCLBN_IO_SERIALIZE_HEX_STR);
+ CYBOZU_TEST_EQUAL(ret, 0);
+ CYBOZU_TEST_ASSERT(mclBnG2_isEqual(&Q1, &Q2));
+
+ ret = mclBnG2_setStr(&Q2, buf, n - 1, MCLBN_IO_SERIALIZE_HEX_STR);
+ CYBOZU_TEST_ASSERT(ret != 0);
+
+ memset(&Q2, 0, sizeof(Q2));
+ ret = mclBnG2_setStr(&Q2, buf, n + 1, MCLBN_IO_SERIALIZE_HEX_STR);
+ CYBOZU_TEST_EQUAL(ret, 0);
+ CYBOZU_TEST_ASSERT(mclBnG2_isEqual(&Q1, &Q2));
+
+ n = mclBnG2_getStr(buf, expectSize, &Q1, MCLBN_IO_SERIALIZE_HEX_STR);
+ CYBOZU_TEST_EQUAL(n, expectSize);
+}
+
+#if MCLBN_FP_UNIT_SIZE == 6 && MCLBN_FR_UNIT_SIZE >= 6
+CYBOZU_TEST_AUTO(badG2)
+{
+ int ret;
+ ret = mclBn_init(MCL_BN381_1, MCLBN_COMPILED_TIME_VAR);
+ CYBOZU_TEST_EQUAL(ret, 0);
+ const char *s = "1 18d3d8c085a5a5e7553c3a4eb628e88b8465bf4de2612e35a0a4eb018fb0c82e9698896031e62fd7633ffd824a859474 1dc6edfcf33e29575d4791faed8e7203832217423bf7f7fbf1f6b36625b12e7132c15fbc15562ce93362a322fb83dd0d 65836963b1f7b6959030ddfa15ab38ce056097e91dedffd996c1808624fa7e2644a77be606290aa555cda8481cfb3cb 1b77b708d3d4f65aeedf54b58393463a42f0dc5856baadb5ce608036baeca398c5d9e6b169473a8838098fd72fd28b50";
+ mclBnG2 Q;
+ ret = mclBnG2_setStr(&Q, s, strlen(s), 16);
+ CYBOZU_TEST_ASSERT(ret != 0);
+}
+#endif
+
+struct Sequential {
+ uint32_t pos;
+ Sequential() : pos(0) {}
+ static uint32_t read(void *self, void *buf, uint32_t bufSize)
+ {
+ Sequential *seq = reinterpret_cast<Sequential*>(self);
+ uint8_t *p = reinterpret_cast<uint8_t*>(buf);
+ for (uint32_t i = 0; i < bufSize; i++) {
+ p[i] = uint8_t(seq->pos + i) & 0x1f; // mask is to make valid Fp
+ }
+ seq->pos += bufSize;
+ return bufSize;
+ }
+};
+
+CYBOZU_TEST_AUTO(setRandFunc)
+{
+ Sequential seq;
+ for (int j = 0; j < 3; j++) {
+ puts(j == 1 ? "sequential rand" : "true rand");
+ for (int i = 0; i < 5; i++) {
+ mclBnFr x;
+ int ret;
+ char buf[1024];
+ ret = mclBnFr_setByCSPRNG(&x);
+ CYBOZU_TEST_EQUAL(ret, 0);
+ ret = mclBnFr_getStr(buf, sizeof(buf), &x, 16);
+ CYBOZU_TEST_ASSERT(ret > 0);
+ printf("%d %s\n", i, buf);
+ }
+ if (j == 0) {
+ mclBn_setRandFunc(&seq, Sequential::read);
+ } else {
+ mclBn_setRandFunc(0, 0);
+ }
+ }
+}
+
+CYBOZU_TEST_AUTO(Fp)
+{
+ mclBnFp x1, x2;
+ char buf[1024];
+ int ret = mclBnFp_setHashOf(&x1, "abc", 3);
+ CYBOZU_TEST_ASSERT(ret == 0);
+ mclSize n = mclBnFp_serialize(buf, sizeof(buf), &x1);
+ CYBOZU_TEST_ASSERT(n > 0);
+ n = mclBnFp_deserialize(&x2, buf, n);
+ CYBOZU_TEST_ASSERT(n > 0);
+ CYBOZU_TEST_ASSERT(mclBnFp_isEqual(&x1, &x2));
+ for (size_t i = 0; i < n; i++) {
+ buf[i] = char(i);
+ }
+ ret = mclBnFp_setLittleEndian(&x1, buf, n);
+ CYBOZU_TEST_ASSERT(ret == 0);
+ memset(buf, 0, sizeof(buf));
+ n = mclBnFp_serialize(buf, sizeof(buf), &x1);
+ CYBOZU_TEST_ASSERT(n > 0);
+ for (size_t i = 0; i < n - 1; i++) {
+ CYBOZU_TEST_EQUAL(buf[i], char(i));
+ }
+ mclBnFp_clear(&x1);
+ memset(&x2, 0, sizeof(x2));
+ CYBOZU_TEST_ASSERT(mclBnFp_isEqual(&x1, &x2));
+}
+
+CYBOZU_TEST_AUTO(mod)
+{
+ {
+ // Fp
+ char buf[1024];
+ mclBn_getFieldOrder(buf, sizeof(buf));
+ mpz_class p(buf);
+ mpz_class x = mpz_class(1) << (mclBn_getFpByteSize() * 2);
+ mclBnFp y;
+ int ret = mclBnFp_setLittleEndianMod(&y, x.get_mpz_t()->_mp_d, x.get_mpz_t()->_mp_size * sizeof(void*));
+ CYBOZU_TEST_EQUAL(ret, 0);
+ mclBnFp_getStr(buf, sizeof(buf), &y, 10);
+ CYBOZU_TEST_EQUAL(mpz_class(buf), x % p);
+ }
+ {
+ // Fr
+ char buf[1024];
+ mclBn_getCurveOrder(buf, sizeof(buf));
+ mpz_class p(buf);
+ mpz_class x = mpz_class(1) << (mclBn_getFrByteSize() * 2);
+ mclBnFr y;
+ int ret = mclBnFr_setLittleEndianMod(&y, x.get_mpz_t()->_mp_d, x.get_mpz_t()->_mp_size * sizeof(void*));
+ CYBOZU_TEST_EQUAL(ret, 0);
+ mclBnFr_getStr(buf, sizeof(buf), &y, 10);
+ CYBOZU_TEST_EQUAL(mpz_class(buf), x % p);
+ }
+}
+
+CYBOZU_TEST_AUTO(Fp2)
+{
+ mclBnFp2 x1, x2;
+ char buf[1024];
+ int ret = mclBnFp_setHashOf(&x1.d[0], "abc", 3);
+ CYBOZU_TEST_ASSERT(ret == 0);
+ ret = mclBnFp_setHashOf(&x1.d[1], "xyz", 3);
+ CYBOZU_TEST_ASSERT(ret == 0);
+ mclSize n = mclBnFp2_serialize(buf, sizeof(buf), &x1);
+ CYBOZU_TEST_ASSERT(n > 0);
+ n = mclBnFp2_deserialize(&x2, buf, n);
+ CYBOZU_TEST_ASSERT(n > 0);
+ CYBOZU_TEST_ASSERT(mclBnFp2_isEqual(&x1, &x2));
+ mclBnFp2_clear(&x1);
+ memset(&x2, 0, sizeof(x2));
+ CYBOZU_TEST_ASSERT(mclBnFp2_isEqual(&x1, &x2));
+}
+
+CYBOZU_TEST_AUTO(mapToG1)
+{
+ mclBnFp x;
+ mclBnG1 P1, P2;
+ mclBnFp_setHashOf(&x, "abc", 3);
+ int ret = mclBnFp_mapToG1(&P1, &x);
+ CYBOZU_TEST_ASSERT(ret == 0);
+ mclBnG1_hashAndMapTo(&P2, "abc", 3);
+ CYBOZU_TEST_ASSERT(mclBnG1_isEqual(&P1, &P2));
+}
+
+CYBOZU_TEST_AUTO(mapToG2)
+{
+ mclBnFp2 x;
+ mclBnG2 P1, P2;
+ mclBnFp_setHashOf(&x.d[0], "abc", 3);
+ mclBnFp_clear(&x.d[1]);
+ int ret = mclBnFp2_mapToG2(&P1, &x);
+ CYBOZU_TEST_ASSERT(ret == 0);
+ mclBnG2_hashAndMapTo(&P2, "abc", 3);
+ CYBOZU_TEST_ASSERT(mclBnG2_isEqual(&P1, &P2));
+}
+
+void G1onlyTest(int curve)
+{
+ printf("curve=%d\n", curve);
+ int ret;
+ ret = mclBn_init(curve, MCLBN_COMPILED_TIME_VAR);
+ CYBOZU_TEST_EQUAL(ret, 0);
+ mclBnG1 P0;
+ ret = mclBnG1_getBasePoint(&P0);
+ CYBOZU_TEST_EQUAL(ret, 0);
+ char buf[256];
+ ret = mclBnG1_getStr(buf, sizeof(buf), &P0, 16);
+ CYBOZU_TEST_ASSERT(ret > 0);
+ printf("basePoint=%s\n", buf);
+ G1test();
+}
+
+CYBOZU_TEST_AUTO(G1only)
+{
+ const int tbl[] = {
+ MCL_SECP192K1,
+ MCL_NIST_P192,
+ MCL_SECP224K1,
+ MCL_NIST_P224, // hashAndMapTo is error
+ MCL_SECP256K1,
+ MCL_NIST_P256,
+#if MCLBN_FP_UNIT_SIZE >= 6 && MCLBN_FR_UNIT_SIZE >= 6
+ MCL_SECP384R1,
+#endif
+ };
+ for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) {
+ G1onlyTest(tbl[i]);
+ }
+}
diff --git a/vendor/github.com/tangerine-network/mcl/test/bn_test.cpp b/vendor/github.com/tangerine-network/mcl/test/bn_test.cpp
new file mode 100644
index 000000000..071ec706c
--- /dev/null
+++ b/vendor/github.com/tangerine-network/mcl/test/bn_test.cpp
@@ -0,0 +1,408 @@
+#define PUT(x) std::cout << #x "=" << x << std::endl;
+#define CYBOZU_TEST_DISABLE_AUTO_RUN
+#include <cybozu/benchmark.hpp>
+cybozu::CpuClock clk;
+#include <cybozu/test.hpp>
+#include <mcl/bn256.hpp>
+#include <cybozu/option.hpp>
+#include <cybozu/xorshift.hpp>
+
+#if defined(__EMSCRIPTEN__) && !defined(MCL_AVOID_EXCEPTION_TEST)
+ #define MCL_AVOID_EXCEPTION_TEST
+#endif
+
+typedef mcl::bn::local::Compress Compress;
+using namespace mcl::bn;
+
+mcl::fp::Mode g_mode;
+
+const struct TestSet {
+ mcl::CurveParam cp;
+ const char *name;
+ struct G2 {
+ const char *aa;
+ const char *ab;
+ const char *ba;
+ const char *bb;
+ } g2;
+ struct G1 {
+ int a;
+ int b;
+ } g1;
+ const char *e;
+} g_testSetTbl[] = {
+ {
+ mcl::BN254,
+ "BN254",
+ {
+ "12723517038133731887338407189719511622662176727675373276651903807414909099441",
+ "4168783608814932154536427934509895782246573715297911553964171371032945126671",
+ "13891744915211034074451795021214165905772212241412891944830863846330766296736",
+ "7937318970632701341203597196594272556916396164729705624521405069090520231616",
+ },
+ {
+ -1, 1
+ },
+ "8118772341496577043438385328606447626730215814727396173233264007541007797690 "
+ "6742571767760762192519140673058087976840103832045324348366170860928670686713 "
+ "9727912590495366720378364920530546614235713408261568635512172059018197267630 "
+ "10180700148605185348549931182990442059136187839792856455707820203302941578832 "
+ "5054507763444412917986776641611331046146804026682679569910978464879371792565 "
+ "6917005519826733659554708445125877487590687705432214234949972860245110398023 "
+ "10448556317747236258066222816126375978842661908560317699736569642190930635294 "
+ "1516980358051268127904344653343215863076753141133525905743113718749531324025 "
+ "9794836735385959178744195210089532061310424844916928682580569566332541022353 "
+ "9375574834170998962484906689780052970915033987453510324648351251071086068423 "
+ "710778048594563655498360873129325895716179849942646859397874562033386335205 "
+ "10688745994254573144943003027511098295097561129365638275727908595677791826005"
+ },
+ {
+ mcl::BN_SNARK1,
+ "BN_SNARK1",
+ {
+ "15267802884793550383558706039165621050290089775961208824303765753922461897946",
+ "9034493566019742339402378670461897774509967669562610788113215988055021632533",
+ "644888581738283025171396578091639672120333224302184904896215738366765861164",
+ "20532875081203448695448744255224543661959516361327385779878476709582931298750",
+ },
+ {
+ 1, 2
+ },
+ "15163392945550945552839911839294582974434771053565812675833291179413834896953 "
+ "20389211011850518572149982239826345669421868561029856883955740401696801984953 "
+ "17766795911013516700216709333389761327222334145011922123798810516425387779347 "
+ "6064163297423711021549973931984064750876944939004405231004441199168710504090 "
+ "296093106139306574860102680862436174771023602986903675151017278048818344347 "
+ "1573596951222456889652521728261836933382094474023551133585236991207205981715 "
+ "3511871642997169996730611220058787939468653751355351269812083879279936651479 "
+ "17848534184080172844395614793152774197360421729995967636680357250333093768504 "
+ "3273860031361637906105800996652640969711942192883181518057117446820546419132 "
+ "7212721189663231589365009629980400132745687533815732336503876102977912682966 "
+ "18569236611881855981733896549089319395087993987737891870319625215675547032585 "
+ "10088832670068482545658647976676953228519838542958787800193793260459700064172 "
+ },
+};
+
+CYBOZU_TEST_AUTO(size)
+{
+ CYBOZU_TEST_EQUAL(sizeof(Fp), 32u);
+ CYBOZU_TEST_EQUAL(sizeof(Fp2), sizeof(Fp) * 2);
+ CYBOZU_TEST_EQUAL(sizeof(Fp6), sizeof(Fp) * 6);
+ CYBOZU_TEST_EQUAL(sizeof(Fp12), sizeof(Fp) * 12);
+ CYBOZU_TEST_EQUAL(sizeof(G1), sizeof(Fp) * 3);
+ CYBOZU_TEST_EQUAL(sizeof(G2), sizeof(Fp2) * 3);
+}
+
+void testSetStr(const G2& Q0)
+{
+ G2::setCompressedExpression();
+ G2 Q;
+ Q.clear();
+ for (int i = 0; i < 10; i++) {
+ G2 R;
+ R.setStr(Q.getStr());
+ CYBOZU_TEST_EQUAL(Q, R);
+ G2::add(Q, Q, Q0);
+ }
+}
+
+void testMapToG1()
+{
+ G1 g;
+ for (int i = 1; i < 10; i++) {
+ mapToG1(g, i);
+ CYBOZU_TEST_ASSERT(!g.isZero());
+ G1 gr;
+ G1::mulGeneric(gr, g, BN::param.r);
+ CYBOZU_TEST_ASSERT(gr.isZero());
+ }
+#ifndef MCL_AVOID_EXCEPTION_TEST
+ if (BN::param.cp.b == 2) {
+ Fp c1;
+ bool b = Fp::squareRoot(c1, -3);
+ CYBOZU_TEST_ASSERT(b);
+ CYBOZU_TEST_EXCEPTION(mapToG1(g, 0), cybozu::Exception);
+ CYBOZU_TEST_EXCEPTION(mapToG1(g, c1), cybozu::Exception);
+ CYBOZU_TEST_EXCEPTION(mapToG1(g, -c1), cybozu::Exception);
+ }
+#endif
+}
+
+void testMapToG2()
+{
+ G2 g;
+ for (int i = 1; i < 10; i++) {
+ mapToG2(g, i);
+ CYBOZU_TEST_ASSERT(!g.isZero());
+ G2 gr;
+ G2::mulGeneric(gr, g, BN::param.r);
+ CYBOZU_TEST_ASSERT(gr.isZero());
+ }
+#ifndef MCL_AVOID_EXCEPTION_TEST
+ if (BN::param.cp.b == 2) {
+ CYBOZU_TEST_EXCEPTION(mapToG2(g, 0), cybozu::Exception);
+ }
+#endif
+ Fp x;
+ x.setHashOf("abc");
+ mapToG2(g, Fp2(x, 0));
+ CYBOZU_TEST_ASSERT(g.isValid());
+}
+
+void testCyclotomic()
+{
+ Fp12 a;
+ for (int i = 0; i < 12; ++i) {
+ a.getFp0()[i] = i * i;
+ }
+ local::mapToCyclotomic(a, a);
+ Fp12 d;
+ Compress b(d, a);
+ a *= a;
+ Fp12 d2;
+ Compress c(d2, b);
+ Compress::square_n(c, 1);
+ c.decompress();
+ CYBOZU_TEST_EQUAL(a, d2);
+ Compress::square_n(b, 1);
+ b.decompress();
+ CYBOZU_TEST_EQUAL(a, d);
+}
+
+void testCompress(const G1& P, const G2& Q)
+{
+ if (BN::param.cp.curveType != MCL_BN254) return;
+ Fp12 a;
+ pairing(a, P, Q);
+ local::mapToCyclotomic(a, a);
+ Fp12 b;
+ Compress::fixed_power(b, a);
+ Fp12 c;
+ Fp12::pow(c, a, BN::param.abs_z);
+ CYBOZU_TEST_EQUAL(b, c);
+}
+
+void testPrecomputed(const G1& P, const G2& Q)
+{
+ Fp12 e1, e2;
+ pairing(e1, P, Q);
+ std::vector<Fp6> Qcoeff;
+ precomputeG2(Qcoeff, Q);
+ precomputedMillerLoop(e2, P, Qcoeff);
+ finalExp(e2, e2);
+ CYBOZU_TEST_EQUAL(e1, e2);
+}
+
+void testFp12pow(const G1& P, const G2& Q)
+{
+ Fp12 e, e1, e2;
+ pairing(e, P, Q);
+ cybozu::XorShift rg;
+ for (int i = -10; i < 10; i++) {
+ mpz_class xm = i;
+ Fp12::pow(e1, e, xm);
+ Fp12::powGeneric(e2, e, xm);
+ CYBOZU_TEST_EQUAL(e1, e2);
+ }
+ for (int i = 0; i < 10; i++) {
+ Fr x;
+ x.setRand(rg);
+ mpz_class xm = x.getMpz();
+ Fp12::pow(e1, e, xm);
+ BN::param.glv2.pow(e2, e, xm);
+ CYBOZU_TEST_EQUAL(e1, e2);
+ }
+}
+
+void testMillerLoop2(const G1& P1, const G2& Q1)
+{
+ Fp12 e1, e2, e3;
+ mpz_class c1("12342342423442");
+ mpz_class c2("329428049820348209482");
+ G2 Q2;
+ G1 P2;
+ G2::mul(Q2, Q1, c1);
+ G1::mul(P2, P1, c2);
+ pairing(e1, P1, Q1);
+ pairing(e2, P2, Q2);
+ e1 *= e2;
+
+ std::vector<Fp6> Q1coeff, Q2coeff;
+ precomputeG2(Q1coeff, Q1);
+ precomputeG2(Q2coeff, Q2);
+ precomputedMillerLoop2(e2, P1, Q1coeff, P2, Q2coeff);
+ precomputedMillerLoop2mixed(e3, P1, Q1, P2, Q2coeff);
+ CYBOZU_TEST_EQUAL(e2, e3);
+ finalExp(e2, e2);
+ CYBOZU_TEST_EQUAL(e1, e2);
+
+ // special value
+ G2 Z;
+ Z.clear();
+ Q2 += Q2;
+ precomputeG2(Q1coeff, Z);
+ precomputeG2(Q2coeff, Q2);
+ precomputedMillerLoop2(e2, P1, Q1coeff, P2, Q2coeff);
+ precomputedMillerLoop2mixed(e3, P1, Z, P2, Q2coeff);
+ finalExp(e2, e2);
+ finalExp(e3, e3);
+ CYBOZU_TEST_EQUAL(e2, e3);
+}
+
+void testPairing(const G1& P, const G2& Q, const char *eStr)
+{
+ Fp12 e1;
+ pairing(e1, P, Q);
+ Fp12 e2;
+ {
+ std::stringstream ss(eStr);
+ ss >> e2;
+ }
+ CYBOZU_TEST_EQUAL(e1, e2);
+
+ Fp12 e = e1, ea;
+ G1 Pa;
+ G2 Qa;
+#if defined(__EMSCRIPTEN__) || MCL_SIZEOF_UNIT == 4
+ const int count = 100;
+#else
+ const int count = 1000;
+#endif
+ mpz_class a;
+ cybozu::XorShift rg;
+ for (int i = 0; i < count; i++) {
+ Fr r;
+ r.setRand(rg);
+ a = r.getMpz();
+ Fp12::pow(ea, e, a);
+ G1::mul(Pa, P, a);
+ G2::mul(Qa, Q, a);
+ G1 T;
+ G1::mulCT(T, P, a);
+ CYBOZU_TEST_EQUAL(Pa, T);
+ pairing(e1, Pa, Q);
+ pairing(e2, P, Qa);
+ CYBOZU_TEST_EQUAL(ea, e1);
+ CYBOZU_TEST_EQUAL(ea, e2);
+ }
+}
+
+void testTrivial(const G1& P, const G2& Q)
+{
+ G1 Z1; Z1.clear();
+ G2 Z2; Z2.clear();
+ Fp12 e;
+ pairing(e, Z1, Q);
+ CYBOZU_TEST_EQUAL(e, 1);
+ pairing(e, P, Z2);
+ CYBOZU_TEST_EQUAL(e, 1);
+ pairing(e, Z1, Z2);
+ CYBOZU_TEST_EQUAL(e, 1);
+
+ std::vector<Fp6> Qcoeff;
+ precomputeG2(Qcoeff, Z2);
+ precomputedMillerLoop(e, P, Qcoeff);
+ finalExp(e, e);
+ CYBOZU_TEST_EQUAL(e, 1);
+
+ precomputeG2(Qcoeff, Q);
+ precomputedMillerLoop(e, Z1, Qcoeff);
+ finalExp(e, e);
+ CYBOZU_TEST_EQUAL(e, 1);
+}
+
+void testIoAll(const G1& P, const G2& Q)
+{
+ const int FpTbl[] = { 0, 2, 2|mcl::IoPrefix, 10, 16, 16|mcl::IoPrefix, mcl::IoArray, mcl::IoArrayRaw };
+ const int EcTbl[] = { mcl::IoEcAffine, mcl::IoEcProj, mcl::IoEcCompY, mcl::IoSerialize };
+ for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(FpTbl); i++) {
+ for (size_t j = 0; j < CYBOZU_NUM_OF_ARRAY(EcTbl); j++) {
+ G1 P2 = P, P3;
+ G2 Q2 = Q, Q3;
+ int ioMode = FpTbl[i] | EcTbl[j];
+ std::string s = P2.getStr(ioMode);
+ P3.setStr(s, ioMode);
+ CYBOZU_TEST_EQUAL(P2, P3);
+ s = Q2.getStr(ioMode);
+ Q3.setStr(s, ioMode);
+ CYBOZU_TEST_EQUAL(Q2, Q3);
+ s = P.x.getStr(ioMode);
+ Fp Px;
+ Px.setStr(s, ioMode);
+ CYBOZU_TEST_EQUAL(P.x, Px);
+ s = Q.x.getStr(ioMode);
+ Fp2 Qx;
+ Qx.setStr(s, ioMode);
+ CYBOZU_TEST_EQUAL(Q.x, Qx);
+ }
+ }
+}
+
+void testIo(const G1& P, const G2& Q)
+{
+ testIoAll(P, Q);
+ G1 Z1;
+ G2 Z2;
+ Z1.clear();
+ Z2.clear();
+ testIoAll(Z1, Z2);
+}
+
+#include "bench.hpp"
+
+CYBOZU_TEST_AUTO(naive)
+{
+ printf("mcl version=%03x\n", mcl::version);
+ for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(g_testSetTbl); i++) {
+ const TestSet& ts = g_testSetTbl[i];
+ printf("i=%d curve=%s\n", int(i), ts.name);
+ initPairing(ts.cp, g_mode);
+ const G1 P(ts.g1.a, ts.g1.b);
+ const G2 Q(Fp2(ts.g2.aa, ts.g2.ab), Fp2(ts.g2.ba, ts.g2.bb));
+#ifdef ONLY_BENCH
+ {
+ Fp12 e;
+ for (int i = 0; i < 10000; i++) { clk.begin(); pairing(e, P, Q); clk.end(); }
+ }
+ clk.put();
+ return;
+#endif
+ testFp12pow(P, Q);
+ testIo(P, Q);
+ testTrivial(P, Q);
+ testSetStr(Q);
+ testMapToG1();
+ testMapToG2();
+ testCyclotomic();
+ testCompress(P, Q);
+ testPairing(P, Q, ts.e);
+ testPrecomputed(P, Q);
+ testMillerLoop2(P, Q);
+ testBench(P, Q);
+ benchAddDblG1();
+ benchAddDblG2();
+ }
+ int count = (int)clk.getCount();
+ if (count) {
+ printf("count=%d ", count);
+ clk.put();
+ }
+}
+
+int main(int argc, char *argv[])
+ try
+{
+ cybozu::Option opt;
+ std::string mode;
+ opt.appendOpt(&mode, "auto", "m", ": mode(gmp/gmp_mont/llvm/llvm_mont/xbyak)");
+ if (!opt.parse(argc, argv)) {
+ opt.usage();
+ return 1;
+ }
+ g_mode = mcl::fp::StrToMode(mode);
+ printf("JIT %d\n", mcl::fp::isEnableJIT());
+ return cybozu::test::autoRun.run(argc, argv);
+} catch (std::exception& e) {
+ printf("ERR %s\n", e.what());
+ return 1;
+}
diff --git a/vendor/github.com/tangerine-network/mcl/test/conversion_test.cpp b/vendor/github.com/tangerine-network/mcl/test/conversion_test.cpp
new file mode 100644
index 000000000..ec11fe900
--- /dev/null
+++ b/vendor/github.com/tangerine-network/mcl/test/conversion_test.cpp
@@ -0,0 +1,96 @@
+#include <cybozu/test.hpp>
+#include <mcl/conversion.hpp>
+
+CYBOZU_TEST_AUTO(arrayToDec)
+{
+ const struct {
+ uint32_t x[5];
+ size_t xn;
+ const char *s;
+ } tbl[] = {
+ { { 0, 0, 0, 0, 0 }, 1, "0" },
+ { { 9, 0, 0, 0, 0 }, 1, "9" },
+ { { 123456789, 0, 0, 0, 0 }, 1, "123456789" },
+ { { 2147483647, 0, 0, 0, 0 }, 1, "2147483647" },
+ { { 0xffffffff, 0, 0, 0, 0 }, 1, "4294967295" },
+ { { 0x540be400, 0x2, 0, 0, 0 }, 2, "10000000000" },
+ { { 0xffffffff, 0xffffffff, 0, 0, 0 }, 2, "18446744073709551615" },
+ { { 0x89e80001, 0x8ac72304, 0, 0, 0 }, 2, "10000000000000000001" },
+ { { 0xc582ca00, 0x8ac72304, 0, 0, 0 }, 2, "10000000001000000000" },
+ { { 0, 0, 1, 0, 0 }, 3, "18446744073709551616" },
+ { { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0 }, 4, "340282366920938463463374607431768211455" },
+ { { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff }, 5, "1461501637330902918203684832716283019655932542975" },
+ { { 0x3b9aca00, 0x5e3f3700, 0x1cbfa532, 0x04f6433a, 0xd83ff078 }, 5, "1234567901234560000000000000000000000001000000000" },
+ };
+ for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) {
+ const size_t bufSize = 128;
+ char buf[bufSize] = {};
+ const char *str = tbl[i].s;
+ const uint32_t *x = tbl[i].x;
+ const size_t strLen = strlen(str);
+ size_t n = mcl::fp::arrayToDec(buf, bufSize, x, tbl[i].xn);
+ CYBOZU_TEST_EQUAL(n, strLen);
+ CYBOZU_TEST_EQUAL_ARRAY(buf + bufSize - n, str, n);
+ const size_t maxN = 32;
+ uint32_t xx[maxN] = {};
+ size_t xn = mcl::fp::decToArray(xx, maxN, str, strLen);
+ CYBOZU_TEST_EQUAL(xn, tbl[i].xn);
+ CYBOZU_TEST_EQUAL_ARRAY(xx, x, xn);
+ }
+ for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) {
+ const size_t bufSize = 128;
+ char buf[bufSize] = {};
+ const char *str = tbl[i].s;
+ const size_t strLen = strlen(str);
+ uint64_t x[8] = {};
+ size_t xn = (tbl[i].xn + 1) / 2;
+ memcpy(x, tbl[i].x, tbl[i].xn * sizeof(uint32_t));
+ size_t n = mcl::fp::arrayToDec(buf, bufSize, x, xn);
+ CYBOZU_TEST_EQUAL(n, strLen);
+ CYBOZU_TEST_EQUAL_ARRAY(buf + bufSize - n, str, n);
+ const size_t maxN = 32;
+ uint64_t xx[maxN] = {};
+ size_t xxn = mcl::fp::decToArray(xx, maxN, str, strLen);
+ CYBOZU_TEST_EQUAL(xxn, xn);
+ CYBOZU_TEST_EQUAL_ARRAY(xx, x, xn);
+ }
+}
+
+CYBOZU_TEST_AUTO(writeHexStr)
+{
+ const char *hex1tbl = "0123456789abcdef";
+ const char *hex2tbl = "0123456789ABCDEF";
+ for (size_t i = 0; i < 16; i++) {
+ uint8_t v = 0xff;
+ CYBOZU_TEST_ASSERT(mcl::fp::local::hexCharToUint8(&v, hex1tbl[i]));
+ CYBOZU_TEST_EQUAL(v, i);
+ CYBOZU_TEST_ASSERT(mcl::fp::local::hexCharToUint8(&v, hex2tbl[i]));
+ CYBOZU_TEST_EQUAL(v, i);
+ }
+ const struct Tbl {
+ const char *bin;
+ size_t n;
+ const char *hex;
+ } tbl[] = {
+ { "", 0, "" },
+ { "\x12\x34\xab", 3, "1234ab" },
+ { "\xff\xfc\x00\x12", 4, "fffc0012" },
+ };
+ for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) {
+ char buf[32];
+ cybozu::MemoryOutputStream os(buf, sizeof(buf));
+ const char *bin = tbl[i].bin;
+ const char *hex = tbl[i].hex;
+ size_t n = tbl[i].n;
+ bool b;
+ mcl::fp::writeHexStr(&b, os, bin, n);
+ CYBOZU_TEST_ASSERT(b);
+ CYBOZU_TEST_EQUAL(os.getPos(), n * 2);
+ CYBOZU_TEST_EQUAL_ARRAY(buf, hex, n * 2);
+
+ cybozu::MemoryInputStream is(hex, n * 2);
+ size_t w = mcl::fp::readHexStr(buf, n, is);
+ CYBOZU_TEST_EQUAL(w, n);
+ CYBOZU_TEST_EQUAL_ARRAY(buf, bin, n);
+ }
+}
diff --git a/vendor/github.com/tangerine-network/mcl/test/ec_test.cpp b/vendor/github.com/tangerine-network/mcl/test/ec_test.cpp
new file mode 100644
index 000000000..ec49adbfe
--- /dev/null
+++ b/vendor/github.com/tangerine-network/mcl/test/ec_test.cpp
@@ -0,0 +1,573 @@
+//#define MCL_EC_USE_AFFINE
+#define PUT(x) std::cout << #x "=" << (x) << std::endl
+#define CYBOZU_TEST_DISABLE_AUTO_RUN
+#include <cybozu/test.hpp>
+#include <cybozu/benchmark.hpp>
+#include <mcl/gmp_util.hpp>
+
+#include <mcl/fp.hpp>
+#include <mcl/ec.hpp>
+#include <mcl/ecparam.hpp>
+#include <time.h>
+#include <math.h>
+
+typedef mcl::FpT<> Fp;
+struct tagZn;
+typedef mcl::FpT<tagZn> Zn;
+typedef mcl::EcT<Fp> Ec;
+
+CYBOZU_TEST_AUTO(sizeof)
+{
+ CYBOZU_TEST_EQUAL(sizeof(Fp), sizeof(mcl::fp::Unit) * Fp::maxSize);
+#ifdef MCL_EC_USE_AFFINE
+ CYBOZU_TEST_EQUAL(sizeof(Ec), sizeof(Fp) * 2 + sizeof(mcl::fp::Unit));
+#else
+ CYBOZU_TEST_EQUAL(sizeof(Ec), sizeof(Fp) * 3);
+#endif
+}
+
+struct Test {
+ const mcl::EcParam& para;
+ Test(const mcl::EcParam& para, mcl::fp::Mode fpMode, mcl::ec::Mode ecMode)
+ : para(para)
+ {
+ printf("fpMode=%s\n", mcl::fp::ModeToStr(fpMode));
+ Fp::init(para.p, fpMode);
+ Zn::init(para.n, fpMode);
+ Ec::init(para.a, para.b, ecMode);
+ }
+ void cstr() const
+ {
+ Ec O;
+ O.clear();
+ CYBOZU_TEST_ASSERT(O.isZero());
+ CYBOZU_TEST_ASSERT(O.isValid());
+ Ec P;
+ P.clear();
+ Ec::neg(P, O);
+ CYBOZU_TEST_EQUAL(P, O);
+ }
+ void pow2(Ec& Q, const Ec& P, int n) const
+ {
+ Q = P;
+ for (int i = 0; i < n; i++) {
+ Q += Q;
+ }
+ }
+ void pow2test(const Ec& P, int n) const
+ {
+ Ec Q, R;
+ pow2(Q, P, n);
+ Q -= P; // Q = (2^n - 1)P
+ Fp x = 1;
+ for (int i = 0; i < n; i++) {
+ x += x;
+ }
+ x -= 1; // x = 2^n - 1
+ Ec::mul(R, P, x);
+ CYBOZU_TEST_EQUAL(Q, R);
+ Q = P;
+ Ec::mul(Q, Q, x);
+ CYBOZU_TEST_EQUAL(Q, R);
+ }
+ void ope() const
+ {
+ Fp x(para.gx);
+ Fp y(para.gy);
+ Zn n = 0;
+ CYBOZU_TEST_NO_EXCEPTION(Ec(x, y));
+ CYBOZU_TEST_EXCEPTION(Ec(x, y + 1), cybozu::Exception);
+ Ec P(x, y), Q, R, O;
+ O.clear();
+ CYBOZU_TEST_ASSERT(P.isNormalized());
+ {
+ Ec::neg(Q, P);
+ CYBOZU_TEST_EQUAL(Q.x, P.x);
+ CYBOZU_TEST_EQUAL(Q.y, -P.y);
+
+ R = P + Q;
+ CYBOZU_TEST_ASSERT(R.isZero());
+ CYBOZU_TEST_ASSERT(R.isNormalized());
+ CYBOZU_TEST_ASSERT(R.isValid());
+
+ R = P + O;
+ CYBOZU_TEST_EQUAL(R, P);
+ R = O + P;
+ CYBOZU_TEST_EQUAL(R, P);
+ }
+
+ {
+ Ec::dbl(R, P);
+#ifndef MCL_EC_USE_AFFINE
+ CYBOZU_TEST_ASSERT(!R.isNormalized());
+#endif
+ CYBOZU_TEST_ASSERT(R.isValid());
+ Ec R2 = P + P;
+ CYBOZU_TEST_EQUAL(R, R2);
+ {
+ Ec P2 = P;
+ Ec::dbl(P2, P2);
+ CYBOZU_TEST_EQUAL(P2, R2);
+ }
+ Ec R3L = R2 + P;
+ Ec R3R = P + R2;
+ CYBOZU_TEST_EQUAL(R3L, R3R);
+ {
+ Ec RR = R2;
+ RR = RR + P;
+ CYBOZU_TEST_EQUAL(RR, R3L);
+ RR = R2;
+ RR = P + RR;
+ CYBOZU_TEST_EQUAL(RR, R3L);
+ RR = P;
+ RR = RR + RR;
+ CYBOZU_TEST_EQUAL(RR, R2);
+ }
+ Ec::mul(R, P, 2);
+ CYBOZU_TEST_EQUAL(R, R2);
+ Ec R4L = R3L + R2;
+ Ec R4R = R2 + R3L;
+ CYBOZU_TEST_EQUAL(R4L, R4R);
+ Ec::mul(R, P, 5);
+ CYBOZU_TEST_EQUAL(R, R4L);
+ }
+ {
+ R = P;
+ for (int i = 0; i < 10; i++) {
+ R += P;
+ }
+ Ec R2;
+ Ec::mul(R2, P, 11);
+ CYBOZU_TEST_EQUAL(R, R2);
+ }
+ Ec::mul(R, P, n - 1);
+ CYBOZU_TEST_EQUAL(R, -P);
+ R += P; // Ec::mul(R, P, n);
+ CYBOZU_TEST_ASSERT(R.isZero());
+ {
+ const int tbl[] = { 1, 2, 63, 64, 65, 127, 128, 129 };
+ for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) {
+ pow2test(P, tbl[i]);
+ }
+ }
+ {
+ Ec::mul(Q, P, 0);
+ CYBOZU_TEST_ASSERT(Q.isZero());
+ Q = P;
+ CYBOZU_TEST_ASSERT(!Q.isZero());
+ Ec::mul(Q, Q, 0);
+ CYBOZU_TEST_ASSERT(Q.isZero());
+ Ec::mul(Q, P, 1);
+ CYBOZU_TEST_EQUAL(P, Q);
+ }
+ {
+ Ec R2;
+ P += P;
+ Q += P;
+ CYBOZU_TEST_ASSERT(!P.z.isOne());
+ CYBOZU_TEST_ASSERT(!Q.z.isOne());
+ Ec::add(R2, P, Q);
+
+ P.normalize();
+ CYBOZU_TEST_ASSERT(P.z.isOne());
+ CYBOZU_TEST_ASSERT(!Q.z.isOne());
+ // affine + generic
+ Ec::add(R, P, Q);
+ CYBOZU_TEST_EQUAL(R, R2);
+ // generic + affine
+ Ec::add(R, Q, P);
+ CYBOZU_TEST_EQUAL(R, R2);
+
+ Q.normalize();
+ CYBOZU_TEST_ASSERT(P.z.isOne());
+ CYBOZU_TEST_ASSERT(Q.z.isOne());
+ // affine + affine
+ Ec::add(R, P, Q);
+ CYBOZU_TEST_EQUAL(R, R2);
+
+ P += P;
+ CYBOZU_TEST_ASSERT(!P.z.isOne());
+ // generic
+ Ec::dbl(R2, P);
+
+ P.normalize();
+ CYBOZU_TEST_ASSERT(P.z.isOne());
+ // affine
+ Ec::dbl(R, P);
+ CYBOZU_TEST_EQUAL(R, R2);
+ }
+ }
+
+ void mul() const
+ {
+ Fp x(para.gx);
+ Fp y(para.gy);
+ Ec P(x, y);
+ Ec Q;
+ Ec R;
+ R.clear();
+ for (int i = 0; i < 100; i++) {
+ Ec::mul(Q, P, i);
+ CYBOZU_TEST_EQUAL(Q, R);
+ R += P;
+ }
+ }
+
+ void neg_mul() const
+ {
+ Fp x(para.gx);
+ Fp y(para.gy);
+ Ec P(x, y);
+ Ec Q;
+ Ec R;
+ R.clear();
+ for (int i = 0; i < 100; i++) {
+ Ec::mul(Q, P, -i);
+ CYBOZU_TEST_EQUAL(Q, R);
+ R -= P;
+ }
+ }
+ void squareRoot() const
+ {
+ Fp x(para.gx);
+ Fp y(para.gy);
+ bool odd = y.isOdd();
+ Fp yy;
+ bool b = Ec::getYfromX(yy, x, odd);
+ CYBOZU_TEST_ASSERT(b);
+ CYBOZU_TEST_EQUAL(yy, y);
+ Fp::neg(y, y);
+ odd = y.isOdd();
+ yy.clear();
+ b = Ec::getYfromX(yy, x, odd);
+ CYBOZU_TEST_ASSERT(b);
+ CYBOZU_TEST_EQUAL(yy, y);
+ }
+ void mul_fp() const
+ {
+ Fp x(para.gx);
+ Fp y(para.gy);
+ Ec P(x, y);
+ Ec Q;
+ Ec R;
+ R.clear();
+ for (int i = 0; i < 100; i++) {
+ Ec::mul(Q, P, Zn(i));
+ CYBOZU_TEST_EQUAL(Q, R);
+ R += P;
+ }
+ }
+ void str() const
+ {
+ const Fp x(para.gx);
+ const Fp y(para.gy);
+ Ec P(x, y);
+ Ec Q;
+ // not compressed
+ Ec::setCompressedExpression(false);
+ {
+ std::stringstream ss;
+ ss << P;
+ ss >> Q;
+ CYBOZU_TEST_EQUAL(P, Q);
+ }
+ {
+ Q.clear();
+ CYBOZU_TEST_EQUAL(Q.getStr(), "0");
+ }
+ for (int i = 0; i < 2; i++) {
+ for (int j = 0; j < 2; j++) {
+ int base = i == 0 ? 10 : 16;
+ bool withPrefix = j == 0;
+ int ioMode = base | (withPrefix ? mcl::IoPrefix : 0);
+ std::string expected = "1 " + x.getStr(ioMode) + " " + y.getStr(ioMode);
+ CYBOZU_TEST_EQUAL(P.getStr(ioMode), expected);
+ std::ostringstream os;
+ if (base == 16) {
+ os << std::hex;
+ }
+ if (withPrefix) {
+ os << std::showbase;
+ }
+ os << P;
+ CYBOZU_TEST_EQUAL(os.str(), expected);
+ }
+ }
+ {
+ P = -P;
+ std::stringstream ss;
+ ss << P;
+ ss >> Q;
+ CYBOZU_TEST_EQUAL(P, Q);
+ }
+ P.clear();
+ {
+ std::stringstream ss;
+ ss << P;
+ ss >> Q;
+ CYBOZU_TEST_EQUAL(P, Q);
+ }
+ CYBOZU_TEST_EXCEPTION(P.setStr("1 3 5"), cybozu::Exception);
+ // compressed
+ Ec::setCompressedExpression(true);
+ P.set(x, y);
+ {
+ std::stringstream ss;
+ ss << P;
+ ss >> Q;
+ CYBOZU_TEST_EQUAL(P, Q);
+ }
+ {
+ P = -P;
+ std::stringstream ss;
+ ss << P;
+ ss >> Q;
+ CYBOZU_TEST_EQUAL(P, Q);
+ }
+ P.clear();
+ {
+ std::stringstream ss;
+ ss << P;
+ ss >> Q;
+ CYBOZU_TEST_EQUAL(P, Q);
+ }
+ // IoSerialize, IoSerializeHexStr
+ const size_t adj = Ec::isMSBserialize() ? 0 : 1;
+ P.set(x, y);
+ {
+ std::string s = P.getStr(mcl::IoSerialize);
+ CYBOZU_TEST_EQUAL(s.size(), Fp::getByteSize() + adj);
+ Q.setStr(s, mcl::IoSerialize);
+ CYBOZU_TEST_EQUAL(P, Q);
+ }
+ {
+ std::string s = P.getStr(mcl::IoSerializeHexStr);
+ CYBOZU_TEST_EQUAL(s.size(), (Fp::getByteSize() + adj) * 2);
+ Q.setStr(s, mcl::IoSerializeHexStr);
+ CYBOZU_TEST_EQUAL(P, Q);
+ }
+ P = -P;
+ {
+ std::string s = P.getStr(mcl::IoSerialize);
+ CYBOZU_TEST_EQUAL(s.size(), Fp::getByteSize() + adj);
+ Q.setStr(s, mcl::IoSerialize);
+ CYBOZU_TEST_EQUAL(P, Q);
+ }
+ {
+ std::string s = P.getStr(mcl::IoSerializeHexStr);
+ CYBOZU_TEST_EQUAL(s.size(), (Fp::getByteSize() + adj) * 2);
+ Q.setStr(s, mcl::IoSerializeHexStr);
+ CYBOZU_TEST_EQUAL(P, Q);
+ }
+ P.clear();
+ {
+ std::string s = P.getStr(mcl::IoSerialize);
+ CYBOZU_TEST_EQUAL(s.size(), Fp::getByteSize() + adj);
+ CYBOZU_TEST_ASSERT(mcl::fp::isZeroArray(s.c_str(), s.size()));
+ Q.setStr(s, mcl::IoSerialize);
+ CYBOZU_TEST_EQUAL(P, Q);
+ }
+ {
+ std::string s = P.getStr(mcl::IoSerializeHexStr);
+ CYBOZU_TEST_EQUAL(s.size(), (Fp::getByteSize() + adj) * 2);
+ for (size_t i = 0; i < s.size(); i++) {
+ CYBOZU_TEST_EQUAL(s[i], '0');
+ }
+ Q.setStr(s, mcl::IoSerializeHexStr);
+ CYBOZU_TEST_EQUAL(P, Q);
+ }
+ }
+ void ioMode() const
+ {
+ const Fp x(para.gx);
+ const Fp y(para.gy);
+ Ec P(x, y);
+ const mcl::IoMode tbl[] = {
+ mcl::IoBin,
+ mcl::IoDec,
+ mcl::IoHex,
+ mcl::IoArray,
+ mcl::IoArrayRaw,
+ };
+ for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) {
+ Fp::setIoMode(tbl[i]);
+ {
+ std::stringstream ss;
+ ss << P;
+ Ec Q;
+ ss >> Q;
+ CYBOZU_TEST_EQUAL(P, Q);
+ }
+ {
+ std::stringstream ss;
+ Ec Q;
+ Q.clear();
+ ss << Q;
+ Ec R;
+ ss >> R;
+ CYBOZU_TEST_EQUAL(Q, R);
+ }
+ }
+ Fp::setIoMode(mcl::IoAuto);
+ }
+ void mulCT() const
+ {
+ Fp x(para.gx);
+ Fp y(para.gy);
+ Ec P(x, y), Q1, Q2;
+ for (int i = 0; i < 100; i++) {
+ Zn r = i;
+ Ec::mul(Q1, P, r);
+ Ec::mulCT(Q2, P, r);
+ CYBOZU_TEST_EQUAL(Q1, Q2);
+ }
+ }
+ void compare() const
+ {
+ Fp x(para.gx);
+ Fp y(para.gy);
+ Ec P1(x, y);
+ Ec P2(x, -y);
+ int c = Ec::compare(P1, P2);
+ int cx = Fp::compare(y, -y);
+ CYBOZU_TEST_EQUAL(c, cx);
+ c = Ec::compare(P2, P1);
+ cx = Fp::compare(-y, y);
+ CYBOZU_TEST_EQUAL(c, cx);
+ CYBOZU_TEST_EQUAL(Ec::compare(P1, P1), 0);
+ bool b1, b2;
+ b1 = P1 <= P2;
+ b2 = y <= -y;
+ CYBOZU_TEST_EQUAL(b1, b2);
+ b1 = P1 < P2;
+ b2 = y < -y;
+ CYBOZU_TEST_EQUAL(b1, b2);
+ CYBOZU_TEST_ASSERT(!(P1 < P1));
+ CYBOZU_TEST_ASSERT((P1 <= P1));
+ }
+
+ template<class F>
+ void test(F f, const char *msg) const
+ {
+ const int N = 300000;
+ Fp x(para.gx);
+ Fp y(para.gy);
+ Ec P(x, y);
+ Ec Q = P + P + P;
+ clock_t begin = clock();
+ for (int i = 0; i < N; i++) {
+ f(Q, P, Q);
+ }
+ clock_t end = clock();
+ printf("%s %.2fusec\n", msg, (end - begin) / double(CLOCKS_PER_SEC) / N * 1e6);
+ }
+/*
+Affine : sandy-bridge
+add 3.17usec
+sub 2.43usec
+dbl 3.32usec
+mul 905.00usec
+Jacobi
+add 2.34usec
+sub 2.65usec
+dbl 1.56usec
+mul 499.00usec
+*/
+ void run() const
+ {
+ cstr();
+ ope();
+ mul();
+ neg_mul();
+ mul_fp();
+ squareRoot();
+ str();
+ ioMode();
+ mulCT();
+ compare();
+ }
+private:
+ Test(const Test&);
+ void operator=(const Test&);
+};
+
+void test_sub_sub(const mcl::EcParam& para, mcl::fp::Mode fpMode)
+{
+ puts("Proj");
+ Test(para, fpMode, mcl::ec::Proj).run();
+ puts("Jacobi");
+ Test(para, fpMode, mcl::ec::Jacobi).run();
+}
+
+void test_sub(const mcl::EcParam *para, size_t paraNum)
+{
+ for (size_t i = 0; i < paraNum; i++) {
+ puts(para[i].name);
+ test_sub_sub(para[i], mcl::fp::FP_GMP);
+#ifdef MCL_USE_LLVM
+ test_sub_sub(para[i], mcl::fp::FP_LLVM);
+ test_sub_sub(para[i], mcl::fp::FP_LLVM_MONT);
+#endif
+#ifdef MCL_USE_XBYAK
+ test_sub_sub(para[i], mcl::fp::FP_XBYAK);
+#endif
+ }
+}
+
+int g_partial = -1;
+
+CYBOZU_TEST_AUTO(all)
+{
+ if (g_partial & (1 << 3)) {
+ const struct mcl::EcParam para3[] = {
+ // mcl::ecparam::p160_1,
+ mcl::ecparam::secp160k1,
+ mcl::ecparam::secp192k1,
+ mcl::ecparam::NIST_P192,
+ };
+ test_sub(para3, CYBOZU_NUM_OF_ARRAY(para3));
+ }
+
+ if (g_partial & (1 << 4)) {
+ const struct mcl::EcParam para4[] = {
+ mcl::ecparam::secp224k1,
+ mcl::ecparam::secp256k1,
+ mcl::ecparam::NIST_P224,
+ mcl::ecparam::NIST_P256,
+ };
+ test_sub(para4, CYBOZU_NUM_OF_ARRAY(para4));
+ }
+
+#if MCL_MAX_BIT_SIZE >= 384
+ if (g_partial & (1 << 6)) {
+ const struct mcl::EcParam para6[] = {
+ // mcl::ecparam::secp384r1,
+ mcl::ecparam::NIST_P384,
+ };
+ test_sub(para6, CYBOZU_NUM_OF_ARRAY(para6));
+ }
+#endif
+
+#if MCL_MAX_BIT_SIZE >= 521
+ if (g_partial & (1 << 9)) {
+ const struct mcl::EcParam para9[] = {
+ // mcl::ecparam::secp521r1,
+ mcl::ecparam::NIST_P521,
+ };
+ test_sub(para9, CYBOZU_NUM_OF_ARRAY(para9));
+ }
+#endif
+}
+
+int main(int argc, char *argv[])
+{
+ if (argc == 1) {
+ g_partial = -1;
+ } else {
+ g_partial = 0;
+ for (int i = 1; i < argc; i++) {
+ g_partial |= 1 << atoi(argv[i]);
+ }
+ }
+ return cybozu::test::autoRun.run(argc, argv);
+}
diff --git a/vendor/github.com/tangerine-network/mcl/test/ecdsa_c_test.cpp b/vendor/github.com/tangerine-network/mcl/test/ecdsa_c_test.cpp
new file mode 100644
index 000000000..e0af38182
--- /dev/null
+++ b/vendor/github.com/tangerine-network/mcl/test/ecdsa_c_test.cpp
@@ -0,0 +1,51 @@
+#include <mcl/ecdsa.h>
+#include <cybozu/test.hpp>
+#include <string.h>
+
+template<class T, class Serializer, class Deserializer>
+void serializeTest(const T& x, const Serializer& serialize, const Deserializer& deserialize)
+{
+ char buf[128];
+ size_t n = serialize(buf, sizeof(buf), &x);
+ CYBOZU_TEST_ASSERT(n > 0);
+ T y;
+ size_t m = deserialize(&y, buf, n);
+ CYBOZU_TEST_EQUAL(m, n);
+ CYBOZU_TEST_ASSERT(memcmp(&x, &y, n) == 0);
+}
+
+CYBOZU_TEST_AUTO(ecdsa)
+{
+ int ret;
+ ret = ecdsaInit();
+ CYBOZU_TEST_EQUAL(ret, 0);
+ ecdsaSecretKey sec;
+ ecdsaPublicKey pub;
+ ecdsaPrecomputedPublicKey *ppub;
+ ecdsaSignature sig;
+ const char *msg = "hello";
+ mclSize msgSize = strlen(msg);
+
+ ret = ecdsaSecretKeySetByCSPRNG(&sec);
+ CYBOZU_TEST_EQUAL(ret, 0);
+ serializeTest(sec, ecdsaSecretKeySerialize, ecdsaSecretKeyDeserialize);
+
+ ecdsaGetPublicKey(&pub, &sec);
+ serializeTest(pub, ecdsaPublicKeySerialize, ecdsaPublicKeyDeserialize);
+ ecdsaSign(&sig, &sec, msg, msgSize);
+ serializeTest(sig, ecdsaSignatureSerialize, ecdsaSignatureDeserialize);
+ CYBOZU_TEST_ASSERT(ecdsaVerify(&sig, &pub, msg, msgSize));
+
+ ppub = ecdsaPrecomputedPublicKeyCreate();
+ CYBOZU_TEST_ASSERT(ppub);
+ ret = ecdsaPrecomputedPublicKeyInit(ppub, &pub);
+ CYBOZU_TEST_EQUAL(ret, 0);
+
+ CYBOZU_TEST_ASSERT(ecdsaVerifyPrecomputed(&sig, ppub, msg, msgSize));
+
+ sig.d[0]++;
+ CYBOZU_TEST_ASSERT(!ecdsaVerify(&sig, &pub, msg, msgSize));
+ CYBOZU_TEST_ASSERT(!ecdsaVerifyPrecomputed(&sig, ppub, msg, msgSize));
+
+ ecdsaPrecomputedPublicKeyDestroy(ppub);
+}
diff --git a/vendor/github.com/tangerine-network/mcl/test/ecdsa_test.cpp b/vendor/github.com/tangerine-network/mcl/test/ecdsa_test.cpp
new file mode 100644
index 000000000..332c9ee27
--- /dev/null
+++ b/vendor/github.com/tangerine-network/mcl/test/ecdsa_test.cpp
@@ -0,0 +1,69 @@
+#define PUT(x) std::cout << #x "=" << x << std::endl;
+#include <stdlib.h>
+#include <stdio.h>
+void put(const void *buf, size_t bufSize)
+{
+ const unsigned char* p = (const unsigned char*)buf;
+ for (size_t i = 0; i < bufSize; i++) {
+ printf("%02x", p[i]);
+ }
+ printf("\n");
+}
+#include <mcl/ecdsa.hpp>
+#include <cybozu/test.hpp>
+#include <cybozu/benchmark.hpp>
+
+using namespace mcl::ecdsa;
+
+CYBOZU_TEST_AUTO(ecdsa)
+{
+ init();
+ SecretKey sec;
+ PublicKey pub;
+ sec.setByCSPRNG();
+ getPublicKey(pub, sec);
+ Signature sig;
+ const std::string msg = "hello";
+ sign(sig, sec, msg.c_str(), msg.size());
+ CYBOZU_TEST_ASSERT(verify(sig, pub, msg.c_str(), msg.size()));
+ sig.s += 1;
+ CYBOZU_TEST_ASSERT(!verify(sig, pub, msg.c_str(), msg.size()));
+}
+
+CYBOZU_TEST_AUTO(value)
+{
+ const std::string msg = "hello";
+ const char *secStr = "83ecb3984a4f9ff03e84d5f9c0d7f888a81833643047acc58eb6431e01d9bac8";
+ const char *pubxStr = "653bd02ba1367e5d4cd695b6f857d1cd90d4d8d42bc155d85377b7d2d0ed2e71";
+ const char *pubyStr = "04e8f5da403ab78decec1f19e2396739ea544e2b14159beb5091b30b418b813a";
+ const char *sigStr = "a598a8030da6d86c6bc7f2f5144ea549d28211ea58faa70ebf4c1e665c1fe9b5de5d79a2ba44e311d04fdca263639283965780bce9169822be9cc81756e95a24";
+
+ SecretKey sec;
+ sec.setStr(secStr, 16);
+ CYBOZU_TEST_EQUAL(sec.getStr(16), secStr);
+ PublicKey pub;
+ getPublicKey(pub, sec);
+ pub.normalize();
+ Ec t(Fp(pubxStr, 16), Fp(pubyStr, 16));
+ CYBOZU_TEST_EQUAL(pub, t);
+ Signature sig;
+ sig.r.setStr(std::string(sigStr, 64), 16);
+ sig.s.setStr(std::string(sigStr + 64, 64), 16);
+ PUT(sig);
+ CYBOZU_TEST_ASSERT(verify(sig, pub, msg.c_str(), msg.size()));
+}
+
+CYBOZU_TEST_AUTO(bench)
+{
+ const std::string msg = "hello";
+ SecretKey sec;
+ PublicKey pub;
+ PrecomputedPublicKey ppub;
+ sec.setByCSPRNG();
+ getPublicKey(pub, sec);
+ ppub.init(pub);
+ Signature sig;
+ CYBOZU_BENCH_C("sign", 1000, sign, sig, sec, msg.c_str(), msg.size());
+ CYBOZU_BENCH_C("pub.verify ", 1000, verify, sig, pub, msg.c_str(), msg.size());
+ CYBOZU_BENCH_C("ppub.verify", 1000, verify, sig, ppub, msg.c_str(), msg.size());
+}
diff --git a/vendor/github.com/tangerine-network/mcl/test/elgamal_test.cpp b/vendor/github.com/tangerine-network/mcl/test/elgamal_test.cpp
new file mode 100644
index 000000000..9532fc597
--- /dev/null
+++ b/vendor/github.com/tangerine-network/mcl/test/elgamal_test.cpp
@@ -0,0 +1,155 @@
+#include <cybozu/test.hpp>
+#include <cybozu/random_generator.hpp>
+#include <mcl/fp.hpp>
+#include <mcl/ecparam.hpp>
+#include <mcl/elgamal.hpp>
+
+struct TagZn;
+typedef mcl::FpT<> Fp;
+typedef mcl::FpT<TagZn> Zn;
+typedef mcl::EcT<Fp> Ec;
+typedef mcl::ElgamalT<Ec, Zn> ElgamalEc;
+
+const mcl::EcParam& para = mcl::ecparam::secp192k1;
+cybozu::RandomGenerator rg;
+
+CYBOZU_TEST_AUTO(testEc)
+{
+ Fp::init(para.p);
+ Zn::init(para.n);
+ Ec::init(para.a, para.b);
+ const Fp x0(para.gx);
+ const Fp y0(para.gy);
+ const size_t bitSize = Zn::getBitSize();
+ const Ec P(x0, y0);
+ /*
+ Zn = <P>
+ */
+ ElgamalEc::PrivateKey prv;
+ prv.init(P, bitSize, rg);
+ prv.setCache(0, 60000);
+ const ElgamalEc::PublicKey& pub = prv.getPublicKey();
+
+ const int m1 = 12345;
+ const int m2 = 17655;
+ ElgamalEc::CipherText c1, c2;
+ pub.enc(c1, m1, rg);
+ pub.enc(c2, m2, rg);
+ Zn dec1, dec2;
+ prv.dec(dec1, c1);
+ prv.dec(dec2, c2);
+ // dec(enc) = id
+ CYBOZU_TEST_EQUAL(dec1, m1);
+ CYBOZU_TEST_EQUAL(dec2, m2);
+ CYBOZU_TEST_EQUAL(prv.dec(c1), m1);
+ CYBOZU_TEST_EQUAL(prv.dec(c2), m2);
+ // iostream
+ {
+ ElgamalEc::PublicKey pub2;
+ ElgamalEc::PrivateKey prv2;
+ ElgamalEc::CipherText cc1, cc2;
+ {
+ std::stringstream ss;
+ ss << prv;
+ ss >> prv2;
+ }
+ Zn d;
+ prv2.dec(d, c1);
+ CYBOZU_TEST_EQUAL(d, m1);
+ {
+ std::stringstream ss;
+ ss << c1;
+ ss >> cc1;
+ }
+ d = 0;
+ prv2.dec(d, cc1);
+ CYBOZU_TEST_EQUAL(d, m1);
+ {
+ std::stringstream ss;
+ ss << pub;
+ ss >> pub2;
+ }
+ pub2.enc(cc2, m2, rg);
+ prv.dec(d, cc2);
+ CYBOZU_TEST_EQUAL(d, m2);
+ }
+ // enc(m1) enc(m2) = enc(m1 + m2)
+ c1.add(c2);
+ prv.dec(dec1, c1);
+ CYBOZU_TEST_EQUAL(dec1, m1 + m2);
+ // enc(m1) x = enc(m1 + x)
+ {
+ const int x = 555;
+ pub.add(c1, x);
+ prv.dec(dec1, c1);
+ CYBOZU_TEST_EQUAL(dec1, m1 + m2 + x);
+ }
+ // rerandomize
+ c1 = c2;
+ pub.rerandomize(c1, rg);
+ // verify c1 != c2
+ CYBOZU_TEST_ASSERT(c1.c1 != c2.c1);
+ CYBOZU_TEST_ASSERT(c1.c2 != c2.c2);
+ prv.dec(dec1, c1);
+ // dec(c1) = dec(c2)
+ CYBOZU_TEST_EQUAL(dec1, m2);
+
+ // check neg
+ {
+ ElgamalEc::CipherText c;
+ Zn m = 1234;
+ pub.enc(c, m, rg);
+ c.neg();
+ Zn dec;
+ prv.dec(dec, c);
+ CYBOZU_TEST_EQUAL(dec, -m);
+ }
+ // check mul
+ {
+ ElgamalEc::CipherText c;
+ Zn m = 123;
+ int x = 111;
+ pub.enc(c, m, rg);
+ Zn dec;
+ prv.dec(dec, c);
+ c.mul(x);
+ prv.dec(dec, c);
+ m *= x;
+ CYBOZU_TEST_EQUAL(dec, m);
+ }
+
+ // check negative value
+ for (int i = -10; i < 10; i++) {
+ ElgamalEc::CipherText c;
+ const Zn mm = i;
+ pub.enc(c, mm, rg);
+ Zn dec;
+ prv.dec(dec, c, 1000);
+ CYBOZU_TEST_EQUAL(dec, mm);
+ }
+
+ // isZeroMessage
+ for (int m = 0; m < 10; m++) {
+ ElgamalEc::CipherText c0;
+ pub.enc(c0, m, rg);
+ if (m == 0) {
+ CYBOZU_TEST_ASSERT(prv.isZeroMessage(c0));
+ } else {
+ CYBOZU_TEST_ASSERT(!prv.isZeroMessage(c0));
+ }
+ }
+ // zkp
+ {
+ ElgamalEc::Zkp zkp;
+ ElgamalEc::CipherText c;
+ pub.encWithZkp(c, zkp, 0, rg);
+ CYBOZU_TEST_ASSERT(pub.verify(c, zkp));
+ zkp.s0 += 1;
+ CYBOZU_TEST_ASSERT(!pub.verify(c, zkp));
+ pub.encWithZkp(c, zkp, 1, rg);
+ CYBOZU_TEST_ASSERT(pub.verify(c, zkp));
+ zkp.s0 += 1;
+ CYBOZU_TEST_ASSERT(!pub.verify(c, zkp));
+ CYBOZU_TEST_EXCEPTION_MESSAGE(pub.encWithZkp(c, zkp, 2, rg), cybozu::Exception, "encWithZkp");
+ }
+}
diff --git a/vendor/github.com/tangerine-network/mcl/test/fp_generator_test.cpp b/vendor/github.com/tangerine-network/mcl/test/fp_generator_test.cpp
new file mode 100644
index 000000000..60ec5cd41
--- /dev/null
+++ b/vendor/github.com/tangerine-network/mcl/test/fp_generator_test.cpp
@@ -0,0 +1,207 @@
+#include <cybozu/test.hpp>
+#if MCL_SIZEOF_UNIT == 4
+// not support
+#else
+#include <mcl/gmp_util.hpp>
+#include <stdint.h>
+#include <string>
+#include <cybozu/itoa.hpp>
+#include <mcl/fp.hpp>
+#include "../src/fp_generator.hpp"
+#include <iostream>
+#include <cybozu/xorshift.hpp>
+#include <cybozu/benchmark.hpp>
+
+typedef mcl::FpT<> Fp;
+
+const int MAX_N = 4;
+
+const char *primeTable[] = {
+ "0x7fffffffffffffffffffffffffffffff", // 127bit(not full)
+ "0xffffffffffffffffffffffffffffff61", // 128bit(full)
+ "0xfffffffffffffffffffffffffffffffffffffffeffffee37", // 192bit(full)
+ "0x2523648240000001ba344d80000000086121000000000013a700000000000013", // 254bit(not full)
+};
+
+void strToArray(uint64_t *p, size_t n, const char *pStr)
+{
+ mpz_class x;
+ mcl::gmp::setStr(x, pStr, 16);
+ mcl::gmp::getArray(p, n, x);
+}
+
+struct Int {
+ int vn;
+ uint64_t v[MAX_N];
+ Int()
+ : vn(0)
+ {
+ }
+ explicit Int(int vn)
+ {
+ if (vn > MAX_N) {
+ printf("vn(%d) is too large\n", vn);
+ exit(1);
+ }
+ this->vn = vn;
+ }
+ void set(const char *str) { setStr(str); }
+ void set(const Fp& rhs)
+ {
+ mcl::gmp::getArray(v, MAX_N, rhs.getMpz());
+ }
+ void set(const uint64_t* x)
+ {
+ for (int i = 0; i < vn; i++) v[i] = x[i];
+ }
+ void setStr(const char *str)
+ {
+ strToArray(v, MAX_N, str);
+ }
+ std::string getStr() const
+ {
+ std::string ret;
+ for (int i = 0; i < vn; i++) {
+ ret += cybozu::itohex(v[vn - 1 - i], false);
+ }
+ return ret;
+ }
+ void put(const char *msg = "") const
+ {
+ if (msg) printf("%s=", msg);
+ printf("%s\n", getStr().c_str());
+ }
+ bool operator==(const Int& rhs) const
+ {
+ if (vn != rhs.vn) return false;
+ for (int i = 0; i < vn; i++) {
+ if (v[i] != rhs.v[i]) return false;
+ }
+ return true;
+ }
+ bool operator!=(const Int& rhs) const { return !operator==(rhs); }
+ bool operator==(const Fp& rhs) const
+ {
+ Int t(vn);
+ t.set(rhs);
+ return operator==(t);
+ }
+ bool operator!=(const Fp& rhs) const { return !operator==(rhs); }
+};
+static inline std::ostream& operator<<(std::ostream& os, const Int& x)
+{
+ return os << x.getStr();
+}
+
+void testAddSub(const mcl::fp::Op& op)
+{
+ Fp x, y;
+ const uint64_t *p = op.p;
+ Int mx(op.N), my(op.N);
+ x.setStr("0x8811aabb23427cc");
+ y.setStr("0x8811aabb23427cc11");
+ mx.set(x);
+ my.set(y);
+ for (int i = 0; i < 30; i++) {
+ CYBOZU_TEST_EQUAL(mx, x);
+ x += x;
+ op.fp_add(mx.v, mx.v, mx.v, p);
+ }
+ for (int i = 0; i < 30; i++) {
+ CYBOZU_TEST_EQUAL(mx, x);
+ x += y;
+ op.fp_add(mx.v, mx.v, my.v, p);
+ }
+ for (int i = 0; i < 30; i++) {
+ CYBOZU_TEST_EQUAL(my, y);
+ y -= x;
+ op.fp_sub(my.v, my.v, mx.v, p);
+ }
+}
+
+void testNeg(const mcl::fp::Op& op)
+{
+ Fp x;
+ Int mx(op.N), my(op.N);
+ const char *tbl[] = {
+ "0",
+ "0x12346",
+ "0x11223344556677881122334455667788",
+ "0x0abbccddeeffaabb0000000000000000",
+ };
+ for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) {
+ x.setStr(tbl[i]);
+ mx.set(x);
+ x = -x;
+ op.fp_neg(mx.v, mx.v, op.p);
+ CYBOZU_TEST_EQUAL(mx, x);
+ }
+}
+
+#if 0
+void testMulI(const mcl::fp::FpGenerator& fg, int pn)
+{
+ cybozu::XorShift rg;
+//printf("pn=%d, %p\n", pn, fg.mulUnit_);
+ for (int i = 0; i < 100; i++) {
+ uint64_t x[MAX_N];
+ uint64_t z[MAX_N + 1];
+ rg.read(x, pn);
+ uint64_t y = rg.get64();
+ mpz_class mx;
+ mcl::gmp::setArray(mx, x, pn);
+ mpz_class my;
+ mcl::gmp::set(my, y);
+ mx *= my;
+ uint64_t d = fg.mulUnit_(z, x, y);
+ z[pn] = d;
+ mcl::gmp::setArray(my, z, pn + 1);
+ CYBOZU_TEST_EQUAL(mx, my);
+ }
+ {
+ uint64_t x[MAX_N];
+ uint64_t z[MAX_N + 1];
+ rg.read(x, pn);
+ uint64_t y = rg.get64();
+ CYBOZU_BENCH_C("mulUnit", 10000000, fg.mulUnit_, z, x, y);
+ }
+}
+#endif
+
+void testShr1(const mcl::fp::Op& op, int pn)
+{
+ cybozu::XorShift rg;
+ for (int i = 0; i < 100; i++) {
+ uint64_t x[MAX_N];
+ uint64_t z[MAX_N];
+ rg.read(x, pn);
+ mpz_class mx;
+ mcl::gmp::setArray(mx, x, pn);
+ mx >>= 1;
+ op.fp_shr1(z, x);
+ mpz_class my;
+ mcl::gmp::setArray(my, z, pn);
+ CYBOZU_TEST_EQUAL(mx, my);
+ }
+}
+
+void test(const char *pStr)
+{
+ printf("test %s\n", pStr);
+ Fp::init(pStr, mcl::fp::FP_XBYAK);
+ const mcl::fp::Op& op = Fp::getOp();
+ const int pn = (int)op.N;
+ testAddSub(op);
+ testNeg(op);
+// testMulI(*op.fg, pn);
+ testShr1(op, pn);
+}
+
+CYBOZU_TEST_AUTO(all)
+{
+ if (!mcl::fp::isEnableJIT()) return;
+ for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(primeTable); i++) {
+ test(primeTable[i]);
+ }
+}
+#endif
diff --git a/vendor/github.com/tangerine-network/mcl/test/fp_test.cpp b/vendor/github.com/tangerine-network/mcl/test/fp_test.cpp
new file mode 100644
index 000000000..dc1b01ef4
--- /dev/null
+++ b/vendor/github.com/tangerine-network/mcl/test/fp_test.cpp
@@ -0,0 +1,1046 @@
+#define PUT(x) std::cout << #x "=" << (x) << std::endl
+#define CYBOZU_TEST_DISABLE_AUTO_RUN
+#include <cybozu/test.hpp>
+#include <mcl/fp.hpp>
+#include "../src/low_func.hpp"
+#include "../src/proto.hpp"
+#include <time.h>
+#include <cybozu/benchmark.hpp>
+#include <cybozu/option.hpp>
+#include <cybozu/sha2.hpp>
+
+#ifdef _MSC_VER
+ #pragma warning(disable: 4127) // const condition
+#endif
+
+typedef mcl::FpT<> Fp;
+
+CYBOZU_TEST_AUTO(sizeof)
+{
+ CYBOZU_TEST_EQUAL(sizeof(Fp), sizeof(mcl::fp::Unit) * Fp::maxSize);
+}
+
+void cstrTest()
+{
+ const struct {
+ const char *str;
+ int val;
+ } tbl[] = {
+ { "0", 0 },
+ { "1", 1 },
+ { "123", 123 },
+ { "0x123", 0x123 },
+ { "0b10101", 21 },
+ };
+ for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) {
+ // string cstr
+ Fp x(tbl[i].str);
+ CYBOZU_TEST_EQUAL(x, tbl[i].val);
+
+ // int cstr
+ Fp y(tbl[i].val);
+ CYBOZU_TEST_EQUAL(y, x);
+
+ // copy cstr
+ Fp z(x);
+ CYBOZU_TEST_EQUAL(z, x);
+
+ // assign int
+ Fp w;
+ w = tbl[i].val;
+ CYBOZU_TEST_EQUAL(w, x);
+
+ // assign self
+ Fp u;
+ u = w;
+ CYBOZU_TEST_EQUAL(u, x);
+
+ // conv
+ std::ostringstream os;
+ os << tbl[i].val;
+
+ std::string str;
+ x.getStr(str);
+ CYBOZU_TEST_EQUAL(str, os.str());
+ }
+ const struct {
+ const char *str;
+ int val;
+ } tbl2[] = {
+ { "-123", 123 },
+ { "-0x123", 0x123 },
+ { "-0b10101", 21 },
+ };
+ for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl2); i++) {
+ Fp x(tbl2[i].str);
+ x = -x;
+ CYBOZU_TEST_EQUAL(x, tbl2[i].val);
+ }
+}
+
+void setStrTest()
+{
+ const struct {
+ const char *in;
+ int out;
+ int base;
+ } tbl[] = {
+ { "100", 100, 0 }, // set base = 10 if base = 0
+ { "100", 4, 2 },
+ { "100", 256, 16 },
+ { "0b100", 4, 0 },
+ { "0b100", 4, 2 },
+ { "0x100", 256, 0 },
+ { "0x100", 256, 16 },
+ };
+ for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) {
+ Fp x;
+ x.setStr(tbl[i].in, tbl[i].base);
+ CYBOZU_TEST_EQUAL(x, tbl[i].out);
+ }
+ // use prefix if base conflicts with prefix
+ {
+ Fp x;
+ CYBOZU_TEST_EXCEPTION(x.setStr("0b100", 16), cybozu::Exception);
+ CYBOZU_TEST_EXCEPTION(x.setStr("0b100", 10), cybozu::Exception);
+ CYBOZU_TEST_EXCEPTION(x.setStr("0x100", 2), cybozu::Exception);
+ CYBOZU_TEST_EXCEPTION(x.setStr("0x100", 10), cybozu::Exception);
+ }
+}
+
+void streamTest()
+{
+ const struct {
+ const char *in;
+ int out10;
+ int out16;
+ } tbl[] = {
+ { "100", 100, 256 }, // set base = 10 if base = 0
+ { "0x100", 256, 256 },
+ };
+ Fp::setIoMode(0);
+ for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) {
+ {
+ std::istringstream is(tbl[i].in);
+ Fp x;
+ is >> x;
+ CYBOZU_TEST_EQUAL(x, tbl[i].out10);
+ }
+ {
+ std::istringstream is(tbl[i].in);
+ Fp x;
+ is >> std::hex >> x;
+ CYBOZU_TEST_EQUAL(x, tbl[i].out16);
+ }
+ }
+ // use prefix if base conflicts with prefix
+ std::istringstream is("0b100");
+ Fp x;
+ CYBOZU_TEST_EXCEPTION(is >> std::hex >> x, cybozu::Exception);
+ {
+ std::ostringstream os;
+ os << Fp(123);
+ CYBOZU_TEST_EQUAL(os.str(), "123");
+ }
+ {
+ std::ostringstream os;
+ os << std::hex << Fp(0x123);
+ CYBOZU_TEST_EQUAL(os.str(), "123");
+ }
+ {
+ std::ostringstream os;
+ os << std::hex << std::showbase << Fp(0x123);
+ CYBOZU_TEST_EQUAL(os.str(), "0x123");
+ }
+}
+
+void ioModeTest()
+{
+ Fp x(123);
+ const struct {
+ mcl::IoMode ioMode;
+ std::string expected;
+ } tbl[] = {
+ { mcl::IoBin, "1111011" },
+ { mcl::IoDec, "123" },
+ { mcl::IoHex, "7b" },
+ };
+ for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) {
+ Fp::setIoMode(tbl[i].ioMode);
+ for (int j = 0; j < 2; j++) {
+ std::stringstream ss;
+ if (j == 1) {
+ ss << std::hex;
+ }
+ ss << x;
+ CYBOZU_TEST_EQUAL(ss.str(), tbl[i].expected);
+ Fp y;
+ y.clear();
+ ss >> y;
+ CYBOZU_TEST_EQUAL(x, y);
+ }
+ }
+ for (int i = 0; i < 2; i++) {
+ if (i == 0) {
+ Fp::setIoMode(mcl::IoArray);
+ } else {
+ Fp::setIoMode(mcl::IoArrayRaw);
+ }
+ std::stringstream ss;
+ ss << x;
+ CYBOZU_TEST_EQUAL(ss.str().size(), Fp::getByteSize());
+ Fp y;
+ ss >> y;
+ CYBOZU_TEST_EQUAL(x, y);
+ }
+ Fp::setIoMode(mcl::IoAuto);
+}
+
+void edgeTest()
+{
+ const mpz_class& m = Fp::getOp().mp;
+ /*
+ real mont
+ 0 0
+ 1 R^-1
+ R 1
+ -1 -R^-1
+ -R -1
+ */
+ mpz_class t = 1;
+ const size_t N = Fp::getUnitSize();
+ const mpz_class R = (t << (N * mcl::fp::UnitBitSize)) % m;
+ const mpz_class tbl[] = {
+ 0, 1, R, m - 1, m - R
+ };
+ for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) {
+ const mpz_class& x = tbl[i];
+ for (size_t j = i; j < CYBOZU_NUM_OF_ARRAY(tbl); j++) {
+ const mpz_class& y = tbl[j];
+ mpz_class z = (x * y) % m;
+ Fp xx, yy;
+ xx.setMpz(x);
+ yy.setMpz(y);
+ Fp zz = xx * yy;
+ zz.getMpz(t);
+ CYBOZU_TEST_EQUAL(z, t);
+ }
+ }
+ t = m;
+ t /= 2;
+ Fp x;
+ x.setMpz(t);
+ CYBOZU_TEST_EQUAL(x * 2, -1);
+ t += 1;
+ x.setMpz(t);
+ CYBOZU_TEST_EQUAL(x * 2, 1);
+}
+
+void convTest()
+{
+#if 1
+ const char *bin, *hex, *dec;
+ if (Fp::getBitSize() <= 117) {
+ bin = "0b1000000000000000000000000000000000000000000000000000000000001110";
+ hex = "0x800000000000000e";
+ dec = "9223372036854775822";
+ } else {
+ bin = "0b100100011010001010110011110001001000000010010001101000101011001111000100100000001001000110100010101100111100010010000";
+ hex = "0x123456789012345678901234567890";
+ dec = "94522879687365475552814062743484560";
+ }
+#else
+ const char *bin = "0b1001000110100";
+ const char *hex = "0x1234";
+ const char *dec = "4660";
+#endif
+ Fp b(bin);
+ Fp h(hex);
+ Fp d(dec);
+ CYBOZU_TEST_EQUAL(b, h);
+ CYBOZU_TEST_EQUAL(b, d);
+
+ std::string str;
+ b.getStr(str, mcl::IoBinPrefix);
+ CYBOZU_TEST_EQUAL(str, bin);
+ b.getStr(str);
+ CYBOZU_TEST_EQUAL(str, dec);
+ b.getStr(str, mcl::IoHexPrefix);
+ CYBOZU_TEST_EQUAL(str, hex);
+}
+
+void compareTest()
+{
+ {
+ const struct {
+ int lhs;
+ int rhs;
+ int cmp;
+ } tbl[] = {
+ { 0, 0, 0 },
+ { 1, 0, 1 },
+ { 0, 1, -1 },
+ { -1, 0, 1 }, // m-1, 0
+ { 0, -1, -1 }, // 0, m-1
+ { 123, 456, -1 },
+ { 456, 123, 1 },
+ };
+ for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) {
+ const Fp x(tbl[i].lhs);
+ const Fp y(tbl[i].rhs);
+ const int cmp = tbl[i].cmp;
+ if (cmp == 0) {
+ CYBOZU_TEST_EQUAL(x, y);
+ CYBOZU_TEST_ASSERT(x >= y);
+ CYBOZU_TEST_ASSERT(x <= y);
+ } else if (cmp > 0) {
+ CYBOZU_TEST_ASSERT(x > y);
+ CYBOZU_TEST_ASSERT(x >= y);
+ } else {
+ CYBOZU_TEST_ASSERT(x < y);
+ CYBOZU_TEST_ASSERT(x <= y);
+ }
+ }
+ }
+ {
+ Fp x(5);
+ CYBOZU_TEST_ASSERT(x < 10);
+ CYBOZU_TEST_ASSERT(x == 5);
+ CYBOZU_TEST_ASSERT(x > 2);
+ }
+ {
+ Fp x(1);
+ CYBOZU_TEST_ASSERT(x.isOne());
+ x = 2;
+ CYBOZU_TEST_ASSERT(!x.isOne());
+ }
+ {
+ const struct {
+ int v;
+ bool expected;
+ } tbl[] = {
+ { 0, false },
+ { 1, false },
+ { -1, true },
+ };
+ for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) {
+ Fp x = tbl[i].v;
+ CYBOZU_TEST_EQUAL(x.isNegative(), tbl[i].expected);
+ }
+ std::string str;
+ Fp::getModulo(str);
+ char buf[1024];
+ size_t n = Fp::getModulo(buf, sizeof(buf));
+ CYBOZU_TEST_EQUAL(n, str.size());
+ CYBOZU_TEST_EQUAL(buf, str.c_str());
+ mpz_class half(str);
+ half = (half - 1) / 2;
+ Fp x;
+ x.setMpz(half - 1);
+ CYBOZU_TEST_ASSERT(!x.isNegative());
+ x.setMpz(half);
+ CYBOZU_TEST_ASSERT(!x.isNegative());
+ x.setMpz(half + 1);
+ CYBOZU_TEST_ASSERT(x.isNegative());
+ }
+}
+
+void moduloTest(const char *pStr)
+{
+ std::string str;
+ Fp::getModulo(str);
+ CYBOZU_TEST_EQUAL(str, mcl::gmp::getStr(mpz_class(pStr)));
+}
+
+void opeTest()
+{
+ const struct {
+ int x;
+ int y;
+ int add; // x + y
+ int sub; // x - y
+ int mul; // x * y
+ int sqr; // x^2
+ } tbl[] = {
+ { 0, 1, 1, -1, 0, 0 },
+ { 9, 5, 14, 4, 45, 81 },
+ { 10, 13, 23, -3, 130, 100 },
+ { 2000, 1000, 3000, 1000, 2000 * 1000, 2000 * 2000 },
+ { 12345, 9999, 12345 + 9999, 12345 - 9999, 12345 * 9999, 12345 * 12345 },
+ };
+ for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) {
+ const Fp x(tbl[i].x);
+ const Fp y(tbl[i].y);
+ Fp z;
+ Fp::add(z, x, y);
+ CYBOZU_TEST_EQUAL(z, tbl[i].add);
+ Fp::sub(z, x, y);
+ CYBOZU_TEST_EQUAL(z, tbl[i].sub);
+ Fp::mul(z, x, y);
+ CYBOZU_TEST_EQUAL(z, tbl[i].mul);
+
+ Fp r;
+ Fp::inv(r, y);
+ Fp::mul(z, z, r);
+ CYBOZU_TEST_EQUAL(z, tbl[i].x);
+ z = x + y;
+ CYBOZU_TEST_EQUAL(z, tbl[i].add);
+ z = x - y;
+ CYBOZU_TEST_EQUAL(z, tbl[i].sub);
+ z = x * y;
+ CYBOZU_TEST_EQUAL(z, tbl[i].mul);
+
+ Fp::sqr(z, x);
+ CYBOZU_TEST_EQUAL(z, tbl[i].sqr);
+
+ z = x / y;
+ z *= y;
+ CYBOZU_TEST_EQUAL(z, tbl[i].x);
+ }
+ if (!Fp::isFullBit()) {
+ Fp x(5), y(3), z;
+ Fp::addPre(z, x, y);
+ if (Fp::compareRaw(z, Fp::getP()) >= 0) {
+ Fp::subPre(z, z, Fp::getP());
+ }
+ CYBOZU_TEST_EQUAL(z, Fp(8));
+ if (Fp::compareRaw(x, y) < 0) {
+ Fp::addPre(x, x, Fp::getP());
+ }
+ Fp::subPre(x, x, y);
+ CYBOZU_TEST_EQUAL(x, Fp(2));
+ }
+}
+
+struct tag2;
+
+void powTest()
+{
+ Fp x, y, z;
+ x = 12345;
+ z = 1;
+ for (int i = 0; i < 100; i++) {
+ Fp::pow(y, x, i);
+ CYBOZU_TEST_EQUAL(y, z);
+ z *= x;
+ }
+ x = z;
+ Fp::pow(z, x, Fp::getOp().mp - 1);
+ CYBOZU_TEST_EQUAL(z, 1);
+ Fp::pow(z, x, Fp::getOp().mp);
+ CYBOZU_TEST_EQUAL(z, x);
+ typedef mcl::FpT<tag2, 128> Fp_other;
+ Fp_other::init("1009");
+ x = 5;
+ Fp_other n = 3;
+ z = 3;
+ Fp::pow(x, x, z);
+ CYBOZU_TEST_EQUAL(x, 125);
+ x = 5;
+ Fp::pow(x, x, n);
+ CYBOZU_TEST_EQUAL(x, 125);
+}
+
+void mulUnitTest()
+{
+ Fp x(-1), y, z;
+ for (unsigned int u = 0; u < 20; u++) {
+ Fp::mul(y, x, u);
+ Fp::mulUnit(z, x, u);
+ CYBOZU_TEST_EQUAL(y, z);
+ }
+}
+
+void powNegTest()
+{
+ Fp x, y, z;
+ x = 12345;
+ z = 1;
+ Fp rx = 1 / x;
+ for (int i = 0; i < 100; i++) {
+ Fp::pow(y, x, -i);
+ CYBOZU_TEST_EQUAL(y, z);
+ z *= rx;
+ }
+}
+
+void powFpTest()
+{
+ Fp x, y, z;
+ x = 12345;
+ z = 1;
+ for (int i = 0; i < 100; i++) {
+ Fp::pow(y, x, Fp(i));
+ CYBOZU_TEST_EQUAL(y, z);
+ z *= x;
+ }
+}
+
+void powGmp()
+{
+ Fp x, y, z;
+ x = 12345;
+ z = 1;
+ for (int i = 0; i < 100; i++) {
+ Fp::pow(y, x, mpz_class(i));
+ CYBOZU_TEST_EQUAL(y, z);
+ z *= x;
+ }
+}
+
+struct TagAnother;
+
+void anotherFpTest(mcl::fp::Mode mode)
+{
+ typedef mcl::FpT<TagAnother, 128> G;
+ G::init("13", mode);
+ G a = 3;
+ G b = 9;
+ a *= b;
+ CYBOZU_TEST_EQUAL(a, 1);
+}
+
+void setArrayTest1()
+{
+ char b1[] = { 0x56, 0x34, 0x12 };
+ Fp x;
+ x.setArray(b1, 3);
+ CYBOZU_TEST_EQUAL(x, 0x123456);
+ int b2[] = { 0x12, 0x34 };
+ x.setArray(b2, 2);
+ CYBOZU_TEST_EQUAL(x, Fp("0x3400000012"));
+}
+
+void setArrayTest2(mcl::fp::Mode mode)
+{
+ Fp::init("0x10000000000001234567a5", mode);
+ const struct {
+ uint32_t buf[3];
+ size_t bufN;
+ const char *expected;
+ } tbl[] = {
+ { { 0x234567a4, 0x00000001, 0x00100000}, 1, "0x234567a4" },
+ { { 0x234567a4, 0x00000001, 0x00100000}, 2, "0x1234567a4" },
+ { { 0x234567a4, 0x00000001, 0x00080000}, 3, "0x08000000000001234567a4" },
+ { { 0x234567a4, 0x00000001, 0x00100000}, 3, "0x10000000000001234567a4" },
+ };
+ Fp x;
+ for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) {
+ x.setArray(tbl[i].buf, tbl[i].bufN);
+ CYBOZU_TEST_EQUAL(x, Fp(tbl[i].expected));
+ }
+ uint32_t large[3] = { 0x234567a5, 0x00000001, 0x00100000};
+ CYBOZU_TEST_EXCEPTION(x.setArray(large, 3), cybozu::Exception);
+}
+
+void setArrayMaskTest1()
+{
+ char b1[] = { 0x56, 0x34, 0x12 };
+ Fp x;
+ x.setArrayMask(b1, 3);
+ CYBOZU_TEST_EQUAL(x, 0x123456);
+ int b2[] = { 0x12, 0x34 };
+ x.setArrayMask(b2, 2);
+ CYBOZU_TEST_EQUAL(x, Fp("0x3400000012"));
+}
+
+void setArrayMaskTest2(mcl::fp::Mode mode)
+{
+ Fp::init("0x10000000000001234567a5", mode);
+ const struct {
+ uint32_t buf[3];
+ size_t bufN;
+ const char *expected;
+ } tbl[] = {
+ { { 0x234567a4, 0x00000001, 0x00100000}, 1, "0x234567a4" },
+ { { 0x234567a4, 0x00000001, 0x00100000}, 2, "0x1234567a4" },
+ { { 0x234567a4, 0x00000001, 0x00100000}, 3, "0x10000000000001234567a4" },
+ { { 0x234567a5, 0xfffffff1, 0xffffffff}, 3, "0x0ffffffffffff1234567a5" },
+ };
+ Fp x;
+ for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) {
+ x.setArrayMask(tbl[i].buf, tbl[i].bufN);
+ CYBOZU_TEST_EQUAL(x, Fp(tbl[i].expected));
+ }
+}
+
+void setArrayModTest()
+{
+ const mpz_class& p = Fp::getOp().mp;
+ const mpz_class tbl[] = {
+ 0,
+ 1,
+ p - 1,
+ p,
+ p + 1,
+ p * 2 - 1,
+ p * 2,
+ p * 2 + 1,
+ p * (p - 1) - 1,
+ p * (p - 1),
+ p * (p - 1) + 1,
+ p * p - 1,
+ p * p,
+ p * p + 1,
+ (mpz_class(1) << Fp::getOp().N * mcl::fp::UnitBitSize * 2) - 1,
+ };
+ const size_t unitByteSize = sizeof(mcl::fp::Unit);
+ for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) {
+ const mpz_class& x = tbl[i];
+ const mcl::fp::Unit *px = mcl::gmp::getUnit(x);
+ const size_t xn = mcl::gmp::getUnitSize(x);
+ const size_t xByteSize = xn * unitByteSize;
+ const size_t fpByteSize = unitByteSize * Fp::getOp().N;
+ Fp y;
+ bool b;
+ y.setArray(&b, px, xn, mcl::fp::Mod);
+ bool expected = xByteSize <= fpByteSize * 2;
+ CYBOZU_TEST_EQUAL(b, expected);
+ if (!b) continue;
+ CYBOZU_TEST_EQUAL(y.getMpz(), x % p);
+ }
+}
+
+CYBOZU_TEST_AUTO(set64bit)
+{
+ Fp::init("0x1000000000000000000f");
+ const struct {
+ const char *p;
+ int64_t i;
+ } tbl[] = {
+ { "0x1234567812345678", int64_t(0x1234567812345678ull) },
+ { "0xfffedcba987edcba997", -int64_t(0x1234567812345678ull) },
+ };
+ for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) {
+ Fp x(tbl[i].p);
+ Fp y(tbl[i].i);
+ CYBOZU_TEST_EQUAL(x, y);
+ }
+}
+
+void getUint64Test()
+{
+ const uint64_t tbl[] = {
+ 0, 1, 123, 0xffffffff, int64_t(0x7fffffffffffffffull)
+ };
+ for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) {
+ uint64_t a = tbl[i];
+ Fp x(a);
+ uint64_t b = x.getUint64();
+ CYBOZU_TEST_ASSERT(!x.isNegative());
+ CYBOZU_TEST_EQUAL(a, b);
+ }
+ {
+ Fp x("0xffffffffffffffff");
+ CYBOZU_TEST_EQUAL(x.getUint64(), uint64_t(0xffffffffffffffffull));
+ }
+ {
+ Fp x("0x10000000000000000");
+ CYBOZU_TEST_EXCEPTION(x.getUint64(), cybozu::Exception);
+ x = -1;
+ CYBOZU_TEST_EXCEPTION(x.getUint64(), cybozu::Exception);
+ }
+ {
+ Fp x("0x10000000000000000");
+ bool b = true;
+ CYBOZU_TEST_EQUAL(x.getUint64(&b), 0u);
+ CYBOZU_TEST_ASSERT(!b);
+ }
+}
+
+void getInt64Test()
+{
+ const int64_t tbl[] = {
+ 0, 1, 123, 0xffffffff, int64_t(0x7fffffffffffffffull),
+ -1, -2, -12345678, int64_t(-9223372036854775808ull)/*-int64_t(1) << 63*/,
+ };
+ for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) {
+ int64_t a = tbl[i];
+ Fp x(a);
+ CYBOZU_TEST_EQUAL(x.isNegative(), a < 0);
+ int64_t b = x.getInt64();
+ CYBOZU_TEST_EQUAL(a, b);
+ }
+ {
+ Fp x("0x8000000000000000");
+ CYBOZU_TEST_EXCEPTION(x.getInt64(), cybozu::Exception);
+ }
+ {
+ Fp x("0x8000000000000000");
+ bool b = true;
+ CYBOZU_TEST_EQUAL(x.getInt64(&b), 0u);
+ CYBOZU_TEST_ASSERT(!b);
+ }
+}
+
+void divBy2Test()
+{
+ const int tbl[] = { -4, -3, -2, -1, 0, 1, 2, 3 };
+ for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) {
+ Fp x(tbl[i]), y;
+ Fp::divBy2(y, x);
+ y *= 2;
+ CYBOZU_TEST_EQUAL(y, x);
+ y = x;
+ Fp::divBy2(y, y);
+ y *= 2;
+ CYBOZU_TEST_EQUAL(y, x);
+ }
+}
+
+void getStrTest()
+{
+ Fp x(0);
+ std::string str;
+ str = x.getStr();
+ CYBOZU_TEST_EQUAL(str, "0");
+ str = x.getStr(mcl::IoBinPrefix);
+ CYBOZU_TEST_EQUAL(str, "0b0");
+ str = x.getStr(mcl::IoBin);
+ CYBOZU_TEST_EQUAL(str, "0");
+ str = x.getStr(mcl::IoHexPrefix);
+ CYBOZU_TEST_EQUAL(str, "0x0");
+ str = x.getStr(mcl::IoHex);
+ CYBOZU_TEST_EQUAL(str, "0");
+
+ x = 123;
+ str = x.getStr();
+ CYBOZU_TEST_EQUAL(str, "123");
+ str = x.getStr(mcl::IoBinPrefix);
+ CYBOZU_TEST_EQUAL(str, "0b1111011");
+ str = x.getStr(mcl::IoBin);
+ CYBOZU_TEST_EQUAL(str, "1111011");
+ str = x.getStr(mcl::IoHexPrefix);
+ CYBOZU_TEST_EQUAL(str, "0x7b");
+ str = x.getStr(mcl::IoHex);
+ CYBOZU_TEST_EQUAL(str, "7b");
+
+ {
+ std::ostringstream os;
+ os << x;
+ CYBOZU_TEST_EQUAL(os.str(), "123");
+ }
+ {
+ std::ostringstream os;
+ os << std::hex << std::showbase << x;
+ CYBOZU_TEST_EQUAL(os.str(), "0x7b");
+ }
+ {
+ std::ostringstream os;
+ os << std::hex << x;
+ CYBOZU_TEST_EQUAL(os.str(), "7b");
+ }
+ const char *tbl[] = {
+ "0x0",
+ "0x5",
+ "0x123",
+ "0x123456789012345679adbc",
+ "0xffffffff26f2fc170f69466a74defd8d",
+ "0x100000000000000000000000000000033",
+ "0x11ee12312312940000000000000000000000000002342343"
+ };
+ for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) {
+ const char *s = tbl[i];
+ mpz_class mx(s);
+ if (mx >= Fp::getOp().mp) continue;
+ Fp y(s);
+ std::string xs, ys;
+ mcl::gmp::getStr(xs, mx, 16);
+ y.getStr(ys, 16);
+ CYBOZU_TEST_EQUAL(xs, ys);
+ }
+}
+
+void setHashOfTest()
+{
+ const std::string msgTbl[] = {
+ "", "abc", "111111111111111111111111111111111111",
+ };
+ for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(msgTbl); i++) {
+ size_t bitSize = Fp::getBitSize();
+ std::string digest;
+ if (bitSize <= 256) {
+ digest = cybozu::Sha256().digest(msgTbl[i]);
+ } else {
+ digest = cybozu::Sha512().digest(msgTbl[i]);
+ }
+ Fp x, y;
+ x.setArrayMask(digest.c_str(), digest.size());
+ y.setHashOf(msgTbl[i]);
+ CYBOZU_TEST_EQUAL(x, y);
+ }
+}
+
+CYBOZU_TEST_AUTO(getArray)
+{
+ const struct {
+ const char *s;
+ uint32_t v[4];
+ size_t vn;
+ } tbl[] = {
+ { "0", { 0, 0, 0, 0 }, 1 },
+ { "1234", { 1234, 0, 0, 0 }, 1 },
+ { "0xaabbccdd12345678", { 0x12345678, 0xaabbccdd, 0, 0 }, 2 },
+ { "0x11112222333344445555666677778888", { 0x77778888, 0x55556666, 0x33334444, 0x11112222 }, 4 },
+ };
+ for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) {
+ mpz_class x(tbl[i].s);
+ const size_t bufN = 8;
+ uint32_t buf[bufN];
+ mcl::gmp::getArray(buf, bufN, x);
+ size_t n = mcl::fp::getNonZeroArraySize(buf, bufN);
+ CYBOZU_TEST_EQUAL(n, tbl[i].vn);
+ CYBOZU_TEST_EQUAL_ARRAY(buf, tbl[i].v, n);
+ }
+}
+
+void serializeTest()
+{
+ const char *tbl[] = { "0", "-1", "123" };
+ for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) {
+ char buf[1024];
+ Fp x, y;
+ x.setStr(tbl[i]);
+ size_t n = x.serialize(buf, sizeof(buf));
+ CYBOZU_TEST_EQUAL(n, Fp::getByteSize());
+ y.deserialize(buf, n);
+ CYBOZU_TEST_EQUAL(x, y);
+
+ n = x.serialize(buf, sizeof(buf), mcl::IoSerializeHexStr);
+ CYBOZU_TEST_EQUAL(n, Fp::getByteSize() * 2);
+ y.deserialize(buf, n, mcl::IoSerializeHexStr);
+ CYBOZU_TEST_EQUAL(x, y);
+ }
+}
+
+void modpTest()
+{
+ const mpz_class& p = Fp::getOp().mp;
+ const mpz_class tbl[] = {
+ 0,
+ 1,
+ p - 1,
+ p,
+ p + 1,
+ p * 2 - 1,
+ p * 2,
+ p * 2 + 1,
+ p * (p - 1) - 1,
+ p * (p - 1),
+ p * (p - 1) + 1,
+ p * p - 1,
+ p * p,
+ p * p + 1,
+ (mpz_class(1) << Fp::getOp().N * mcl::fp::UnitBitSize * 2) - 1,
+ };
+ mcl::Modp modp;
+ modp.init(p);
+ for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) {
+ const mpz_class& x = tbl[i];
+ mpz_class r1, r2;
+ r1 = x % p;
+ modp.modp(r2, x);
+ CYBOZU_TEST_EQUAL(r1, r2);
+ }
+}
+
+#include <iostream>
+#if (defined(MCL_USE_LLVM) || defined(MCL_USE_XBYAK)) && (MCL_MAX_BIT_SIZE >= 521)
+CYBOZU_TEST_AUTO(mod_NIST_P521)
+{
+ const size_t len = 521;
+ const size_t N = len / mcl::fp::UnitBitSize;
+ const char *tbl[] = {
+ "0",
+ "0xffffffff",
+ "0x1fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0",
+ "0x1fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe",
+ "0x1ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
+ "0x20000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "0x20000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001",
+ "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00111423424",
+ "0x11111111111111112222222222222222333333333333333344444444444444445555555555555555666666666666666677777777777777778888888888888888aaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbccccccccccccccccddddddddddddddddeeeeeeeeeeeeeeeeffffffffffffffff1234712341234123412341234123412341234",
+ "0x3ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
+ };
+ const char *p = "0x1ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff";
+ Fp::init(p, mcl::fp::FP_XBYAK);
+ const mpz_class mp(p);
+ for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) {
+ mpz_class mx(tbl[i]);
+ mcl::fp::Unit in[N * 2 + 1] = {};
+ mcl::fp::Unit ok[N + 1];
+ mcl::fp::Unit ex[N + 1];
+ mcl::gmp::getArray(in, N * 2 + 1, mx);
+ mpz_class my = mx % mp;
+ mcl::gmp::getArray(ok, N + 1, my);
+#ifdef MCL_USE_LLVM
+ mcl_fpDbl_mod_NIST_P521L(ex, in, Fp::getOp().p);
+ CYBOZU_TEST_EQUAL_ARRAY(ex, ok, N + 1);
+#endif
+#ifdef MCL_USE_XBYAK
+ const mcl::fp::Op& op = Fp::getOp();
+ if (!op.isMont) {
+ op.fpDbl_mod(ex, in, op.p);
+ CYBOZU_TEST_EQUAL_ARRAY(ex, ok, N + 1);
+ }
+#endif
+ }
+}
+#endif
+
+void sub(mcl::fp::Mode mode)
+{
+ printf("mode=%s\n", mcl::fp::ModeToStr(mode));
+ const char *tbl[] = {
+ // N = 2
+ "0x0000000000000001000000000000000d",
+ "0x7fffffffffffffffffffffffffffffff",
+ "0x8000000000000000000000000000001d",
+ "0xffffffffffffffffffffffffffffff61",
+
+ // N = 3
+ "0x000000000000000100000000000000000000000000000033", // min prime
+ "0x00000000fffffffffffffffffffffffffffffffeffffac73",
+ "0x0000000100000000000000000001b8fa16dfab9aca16b6b3",
+ "0x000000010000000000000000000000000000000000000007",
+ "0x30000000000000000000000000000000000000000000002b",
+ "0x70000000000000000000000000000000000000000000001f",
+ "0x800000000000000000000000000000000000000000000005",
+ "0xfffffffffffffffffffffffffffffffffffffffeffffee37",
+ "0xfffffffffffffffffffffffe26f2fc170f69466a74defd8d",
+ "0xffffffffffffffffffffffffffffffffffffffffffffff13", // max prime
+
+ // N = 4
+ "0x0000000000000001000000000000000000000000000000000000000000000085", // min prime
+ "0x2523648240000001ba344d80000000086121000000000013a700000000000013",
+ "0x7523648240000001ba344d80000000086121000000000013a700000000000017",
+ "0x800000000000000000000000000000000000000000000000000000000000005f",
+ "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff43", // max prime
+#if MCL_MAX_BIT_SIZE >= 384
+
+ // N = 6
+ "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000000ffffffff",
+#endif
+
+#if MCL_MAX_BIT_SIZE >= 521
+ // N = 9
+ "0x1ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
+#endif
+ };
+ for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) {
+ const char *pStr = tbl[i];
+ printf("prime=%s\n", pStr);
+ Fp::init(pStr, mode);
+ cstrTest();
+ setStrTest();
+ streamTest();
+ ioModeTest();
+ edgeTest();
+ convTest();
+ compareTest();
+ moduloTest(pStr);
+ opeTest();
+ mulUnitTest();
+ powTest();
+ powNegTest();
+ powFpTest();
+ powGmp();
+ setArrayTest1();
+ setArrayMaskTest1();
+ setArrayModTest();
+ getUint64Test();
+ getInt64Test();
+ divBy2Test();
+ getStrTest();
+ setHashOfTest();
+ serializeTest();
+ modpTest();
+ }
+ anotherFpTest(mode);
+ setArrayTest2(mode);
+ setArrayMaskTest2(mode);
+}
+
+std::string g_mode;
+
+CYBOZU_TEST_AUTO(main)
+{
+ if (g_mode.empty() || g_mode == "auto") {
+ sub(mcl::fp::FP_AUTO);
+ }
+ if (g_mode.empty() || g_mode == "gmp") {
+ sub(mcl::fp::FP_GMP);
+ }
+ if (g_mode.empty() || g_mode == "gmp_mont") {
+ sub(mcl::fp::FP_GMP_MONT);
+ }
+#ifdef MCL_USE_LLVM
+ if (g_mode.empty() || g_mode == "llvm") {
+ sub(mcl::fp::FP_LLVM);
+ }
+ if (g_mode.empty() || g_mode == "llvm_mont") {
+ sub(mcl::fp::FP_LLVM_MONT);
+ }
+#endif
+#ifdef MCL_USE_XBYAK
+ if (g_mode.empty() || g_mode == "xbyak") {
+ sub(mcl::fp::FP_XBYAK);
+ }
+#endif
+}
+
+CYBOZU_TEST_AUTO(copyUnitToByteAsLE)
+{
+ using namespace mcl::fp;
+#if MCL_SIZEOF_UNIT == 4
+ const Unit src[] = { 0x12345678, 0xaabbccdd, 0xffeeddcc, 0x87654321 };
+#else
+ const Unit src[] = { uint64_t(0xaabbccdd12345678ull), uint64_t(0x87654321ffeeddcc) };
+#endif
+ const uint8_t ok[] = { 0x78, 0x56, 0x34, 0x12, 0xdd, 0xcc, 0xbb, 0xaa, 0xcc, 0xdd, 0xee, 0xff, 0x21, 0x43, 0x65, 0x87 };
+ const size_t okN = CYBOZU_NUM_OF_ARRAY(ok);
+ for (size_t i = 0; i < okN; i++) {
+ uint8_t buf[okN] = {};
+ copyUnitToByteAsLE(buf, src, i);
+ CYBOZU_TEST_EQUAL_ARRAY(ok, buf, i);
+ }
+ mcl::fp::Unit dst[2];
+ for (size_t i = 1; i <= sizeof(dst); i++) {
+ memset(dst, 0xff, sizeof(dst));
+ mcl::fp::copyByteToUnitAsLE(dst, ok, i);
+ if (i < sizeof(Unit)) {
+ CYBOZU_TEST_EQUAL(src[0] & ((uint64_t(1) << (i * 8)) - 1), dst[0]);
+ CYBOZU_TEST_EQUAL(dst[1], Unit(-1));
+ continue;
+ }
+ CYBOZU_TEST_EQUAL(dst[0], src[0]);
+ if (i == sizeof(Unit)) {
+ CYBOZU_TEST_EQUAL(dst[1], Unit(-1));
+ continue;
+ }
+ if (i < sizeof(dst)) {
+ CYBOZU_TEST_EQUAL(src[1] & ((uint64_t(1) << ((i - sizeof(Unit)) * 8)) - 1), dst[1]);
+ continue;
+ }
+ CYBOZU_TEST_EQUAL(src[1], dst[1]);
+ }
+ dst[0] = 1;
+ copyByteToUnitAsLE(dst, ok, 0);
+ CYBOZU_TEST_EQUAL(dst[0], 1u);
+}
+
+int main(int argc, char *argv[])
+ try
+{
+ cybozu::Option opt;
+ opt.appendOpt(&g_mode, "", "m", ": mode(auto/gmp/gmp_mont/llvm/llvm_mont/xbyak)");
+ opt.appendHelp("h", ": show this message");
+ if (!opt.parse(argc, argv)) {
+ opt.usage();
+ return 1;
+ }
+ return cybozu::test::autoRun.run(argc, argv);
+} catch (std::exception& e) {
+ printf("ERR %s\n", e.what());
+ return 1;
+}
diff --git a/vendor/github.com/tangerine-network/mcl/test/fp_tower_test.cpp b/vendor/github.com/tangerine-network/mcl/test/fp_tower_test.cpp
new file mode 100644
index 000000000..a7123f7a5
--- /dev/null
+++ b/vendor/github.com/tangerine-network/mcl/test/fp_tower_test.cpp
@@ -0,0 +1,477 @@
+#define PUT(x) std::cout << #x "=" << (x) << std::endl
+#define CYBOZU_TEST_DISABLE_AUTO_RUN
+#include <cybozu/test.hpp>
+#include <cybozu/benchmark.hpp>
+#include <cybozu/xorshift.hpp>
+#include <time.h>
+#include <mcl/fp.hpp>
+#include <mcl/fp_tower.hpp>
+
+#ifdef _MSC_VER
+ #pragma warning(disable : 4456)
+#endif
+
+#if MCL_MAX_BIT_SIZE >= 768
+typedef mcl::FpT<mcl::FpTag, MCL_MAX_BIT_SIZE> Fp;
+#else
+typedef mcl::FpT<mcl::FpTag, 384> Fp;
+#endif
+typedef mcl::Fp2T<Fp> Fp2;
+typedef mcl::FpDblT<Fp> FpDbl;
+typedef mcl::Fp6T<Fp> Fp6;
+typedef mcl::Fp12T<Fp> Fp12;
+
+bool g_benchOnly = false;
+
+void testFp2()
+{
+ using namespace mcl;
+ puts(__FUNCTION__);
+#if MCL_MAX_BIT_SIZE < 768
+ const size_t FpSize = 48;
+ CYBOZU_TEST_EQUAL(sizeof(Fp), FpSize);
+ CYBOZU_TEST_EQUAL(sizeof(Fp2), FpSize * 2);
+ CYBOZU_TEST_EQUAL(sizeof(Fp6), FpSize * 6);
+ CYBOZU_TEST_EQUAL(sizeof(Fp12), FpSize * 12);
+#endif
+ Fp2 x, y, z;
+ x.a = 1;
+ x.b = 2;
+
+ {
+ std::stringstream os;
+ os << x;
+ os >> y;
+ CYBOZU_TEST_EQUAL(x, y);
+ }
+ y.a = 3;
+ y.b = 4;
+ /*
+ x = 1 + 2i
+ y = 3 + 4i
+ */
+ Fp2::add(z, x, y);
+ CYBOZU_TEST_EQUAL(z, Fp2(4, 6));
+ Fp2::sub(z, x, y);
+ CYBOZU_TEST_EQUAL(z, Fp2(-2, -2));
+ Fp2::mul(z, x, y);
+ /*
+ (1 + 2i)(3 + 4i) = (3 - 8) + (4 + 6)i = -5 + 10i
+ */
+ CYBOZU_TEST_EQUAL(z, Fp2(-5, 10));
+ Fp2::neg(z, z);
+ CYBOZU_TEST_EQUAL(z, Fp2(5, -10));
+ /*
+ xi = xi_a + i
+ (1 - 2i)(xi_a + i) = (xi_a + 2) + (1 - 2 xi_a)i
+ */
+ z = Fp2(1, -2);
+ Fp2::mul_xi(z, z);
+ Fp a = Fp2::get_xi_a();
+ CYBOZU_TEST_EQUAL(z, Fp2(a + 2, a * (-2) + 1));
+ z = x * x;
+ Fp2::sqr(y, x);
+ CYBOZU_TEST_EQUAL(z, y);
+ x.a = -123456789;
+ x.b = 464652165165;
+ y = x * x;
+ Fp2::sqr(x, x);
+ CYBOZU_TEST_EQUAL(x, y);
+ {
+ std::ostringstream oss;
+ oss << x;
+ std::istringstream iss(oss.str());
+ Fp2 w;
+ iss >> w;
+ CYBOZU_TEST_EQUAL(x, w);
+ }
+ y = 1;
+ for (int i = 0; i < 10; i++) {
+ Fp2::pow(z, x, i);
+ CYBOZU_TEST_EQUAL(z, y);
+ y *= x;
+ }
+ /*
+ (a + bi)^p = a + bi if p % 4 = 1
+ (a + bi)^p = a - bi if p % 4 = 3
+ */
+ {
+ const mpz_class& mp = Fp::getOp().mp;
+ y = x;
+ Fp2::pow(z, y, mp);
+ if ((mp % 4) == 3) {
+ Fp::neg(z.b, z.b);
+ }
+ CYBOZU_TEST_EQUAL(z, y);
+ }
+ {
+ mpz_class t = Fp::getOp().mp;
+ t /= 2;
+ Fp x;
+ x.setMpz(t);
+ CYBOZU_TEST_EQUAL(x * 2, Fp(-1));
+ t += 1;
+ x.setMpz(t);
+ CYBOZU_TEST_EQUAL(x * 2, 1);
+ }
+ {
+ Fp2 a(1, 1);
+ Fp2 b(1, -1);
+ Fp2 c(Fp2(2) / a);
+ CYBOZU_TEST_EQUAL(c, b);
+ CYBOZU_TEST_EQUAL(a * b, Fp2(2));
+ CYBOZU_TEST_EQUAL(a * c, Fp2(2));
+ }
+ y = x;
+ Fp2::inv(y, x);
+ y *= x;
+ CYBOZU_TEST_EQUAL(y, 1);
+
+ // square root
+ for (int i = 0; i < 3; i++) {
+ x.a = i * i + i * 2;
+ x.b = i;
+ Fp2::sqr(y, x);
+ CYBOZU_TEST_ASSERT(Fp2::squareRoot(z, y));
+ CYBOZU_TEST_EQUAL(z * z, y);
+ CYBOZU_TEST_ASSERT(Fp2::squareRoot(y, y));
+ CYBOZU_TEST_EQUAL(z * z, y * y);
+ x.b = 0;
+ Fp2::sqr(y, x);
+ CYBOZU_TEST_ASSERT(Fp2::squareRoot(z, y));
+ CYBOZU_TEST_EQUAL(z * z, y);
+ x.a = 0;
+ x.b = i * i + i * 3;
+ Fp2::sqr(y, x);
+ CYBOZU_TEST_ASSERT(Fp2::squareRoot(z, y));
+ CYBOZU_TEST_EQUAL(z * z, y);
+ }
+}
+
+void testFp6sqr(const Fp2& a, const Fp2& b, const Fp2& c, const Fp6& x)
+{
+ Fp2 t;
+ t = b * c * 2;
+ Fp2::mul_xi(t, t);
+ t += a * a;
+ CYBOZU_TEST_EQUAL(x.a, t);
+ t = c * c;
+ Fp2::mul_xi(t, t);
+ t += a * b * 2;
+ CYBOZU_TEST_EQUAL(x.b, t);
+ t = b * b + a * c * 2;
+ CYBOZU_TEST_EQUAL(x.c, t);
+}
+
+void testFp6()
+{
+ using namespace mcl;
+ puts(__FUNCTION__);
+ Fp2 a(1, 2), b(3, 4), c(5, 6);
+ Fp6 x(a, b, c);
+ Fp6 y(Fp2(-1, 1), Fp2(4, -3), Fp2(-6, 2));
+ Fp6 z, w;
+ {
+ std::stringstream ss;
+ ss << x;
+ ss >> z;
+ CYBOZU_TEST_EQUAL(x, z);
+ }
+ Fp6::add(z, x, y);
+ CYBOZU_TEST_EQUAL(z, Fp6(Fp2(0, 3), Fp2(7, 1), Fp2(-1, 8)));
+ Fp6::sub(z, x, y);
+ CYBOZU_TEST_EQUAL(z, Fp6(Fp2(2, 1), Fp2(-1, 7), Fp2(11, 4)));
+ Fp6::neg(z, x);
+ CYBOZU_TEST_EQUAL(z, Fp6(-a, -b, -c));
+ Fp6::sqr(z, x);
+ Fp6::mul(w, x, x);
+ testFp6sqr(a, b, c, z);
+ testFp6sqr(a, b, c, w);
+ z = x;
+ Fp6::sqr(z, z);
+ Fp6::mul(w, x, x);
+ testFp6sqr(a, b, c, z);
+ testFp6sqr(a, b, c, w);
+ for (int i = 0; i < 10; i++) {
+ Fp6::inv(y, x);
+ Fp6::mul(z, y, x);
+ CYBOZU_TEST_EQUAL(z, 1);
+ x += y;
+ y = x;
+ Fp6::inv(y, y);
+ y *= x;
+ CYBOZU_TEST_EQUAL(y, 1);
+ }
+}
+
+void testFp12()
+{
+ puts(__FUNCTION__);
+ Fp6 xa(Fp2(1, 2), Fp2(3, 4), Fp2(5, 6));
+ Fp6 xb(Fp2(3, 1), Fp2(6, -1), Fp2(-2, 5));
+ Fp12 x(xa, xb);
+ Fp6 ya(Fp2(2, 1), Fp2(5, 3), Fp2(4, 1));
+ Fp6 yb(Fp2(1, -3), Fp2(2, -1), Fp2(-3, 1));
+ Fp12 y(ya, yb);
+ Fp12 z;
+ Fp12::add(z, x, y);
+ CYBOZU_TEST_EQUAL(z, Fp12(Fp6(Fp2(3, 3), Fp2(8, 7), Fp2(9, 7)), Fp6(Fp2(4, -2), Fp2(8, -2), Fp2(-5, 6))));
+ Fp12::sub(z, x, y);
+ CYBOZU_TEST_EQUAL(z, Fp12(Fp6(Fp2(-1, 1), Fp2(-2, 1), Fp2(1, 5)), Fp6(Fp2(2, 4), Fp2(4, 0), Fp2(1, 4))));
+ Fp12::neg(z, x);
+ CYBOZU_TEST_EQUAL(z, Fp12(-xa, -xb));
+
+ y.b.clear();
+ z = y;
+ Fp12::sqr(z, z);
+ CYBOZU_TEST_EQUAL(z.a, y.a * y.a);
+ z = y * y;
+ CYBOZU_TEST_EQUAL(z.a, y.a * y.a);
+ CYBOZU_TEST_ASSERT(z.b.isZero());
+ Fp12 w;
+ y = x;
+ z = x * x;
+ w = x;
+ Fp12::sqr(w, w);
+ CYBOZU_TEST_EQUAL(z, w);
+ y = x;
+ y *= y;
+ Fp12::sqr(x, x);
+ CYBOZU_TEST_EQUAL(x, y);
+ for (int i = 0; i < 10; i++) {
+ w = x;
+ Fp12::inv(w, w);
+ Fp12::mul(y, w, x);
+ CYBOZU_TEST_EQUAL(y, 1);
+ x += y;
+ }
+}
+
+void testFpDbl()
+{
+ puts(__FUNCTION__);
+ {
+ std::string pstr;
+ Fp::getModulo(pstr);
+ mpz_class mp(pstr);
+ mp <<= Fp::getUnitSize() * mcl::fp::UnitBitSize;
+ mpz_class mp1 = mp - 1;
+ mcl::gmp::getStr(pstr, mp1);
+ const char *tbl[] = {
+ "0", "1", "123456", "123456789012345668909", pstr.c_str(),
+ };
+ for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) {
+ mpz_class mx(tbl[i]);
+ FpDbl x;
+ x.setMpz(mx);
+ for (size_t j = 0; j < CYBOZU_NUM_OF_ARRAY(tbl); j++) {
+ FpDbl y, z;
+ mpz_class mz, mo;
+ mpz_class my(tbl[j]);
+ y.setMpz(my);
+ FpDbl::add(z, x, y);
+ mcl::gmp::addMod(mo, mx, my, mp);
+ z.getMpz(mz);
+ CYBOZU_TEST_EQUAL(mz, mo);
+ mcl::gmp::subMod(mo, mx, my, mp);
+ FpDbl::sub(z, x, y);
+ z.getMpz(mz);
+ CYBOZU_TEST_EQUAL(mz, mo);
+ if (!Fp::isFullBit()) {
+ FpDbl::addPre(z, x, y);
+ mo = mx + my;
+ z.getMpz(mz);
+ CYBOZU_TEST_EQUAL(mz, mo);
+ if (mx >= my) {
+ FpDbl::subPre(z, x, y);
+ mo = mx - my;
+ z.getMpz(mz);
+ CYBOZU_TEST_EQUAL(mz, mo);
+ }
+ }
+ }
+ }
+ }
+ {
+ std::string pstr;
+ Fp::getModulo(pstr);
+ const mpz_class mp(pstr);
+ cybozu::XorShift rg;
+ for (int i = 0; i < 3; i++) {
+ Fp x, y, z;
+ mpz_class mx, my, mz, mo;
+ x.setRand(rg);
+ y.setRand(rg);
+ x.getMpz(mx);
+ y.getMpz(my);
+ FpDbl d;
+ FpDbl::mulPre(d, x, y);
+ d.getMpz(mz);
+ {
+ Fp tx, ty;
+ tx = x;
+ ty = y;
+ tx.toMont();
+ ty.toMont();
+ mpz_class mtx, mty;
+ tx.getMpz(mtx);
+ ty.getMpz(mty);
+ mo = mtx * mty;
+ }
+ CYBOZU_TEST_EQUAL(mz, mo);
+
+ FpDbl::mod(z, d);
+ z.getMpz(mz);
+ mo = (mx * my) % mp;
+ CYBOZU_TEST_EQUAL(mz, mo);
+ CYBOZU_TEST_EQUAL(z, x * y);
+
+ FpDbl::sqrPre(d, x);
+ d.getMpz(mz);
+ {
+ Fp tx;
+ tx = x;
+ tx.toMont();
+ mpz_class mtx;
+ tx.getMpz(mtx);
+ mo = mtx * mtx;
+ }
+ CYBOZU_TEST_EQUAL(mz, mo);
+
+ FpDbl::mod(z, d);
+ z.getMpz(mz);
+ mo = (mx * mx) % mp;
+ CYBOZU_TEST_EQUAL(mz, mo);
+ CYBOZU_TEST_EQUAL(z, x * x);
+ }
+ }
+}
+
+void testIo()
+{
+ int modeTbl[] = { 0, 2, 2 | mcl::IoPrefix, 10, 16, 16 | mcl::IoPrefix, mcl::IoArray, mcl::IoArrayRaw };
+ for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(modeTbl); i++) {
+ int ioMode = modeTbl[i];
+ Fp12 x;
+ for (int j = 0; j < 12; j++) {
+ x.getFp0()[j] = j * j;
+ }
+ std::string s = x.getStr(ioMode);
+ Fp12 y;
+ y.setStr(s, ioMode);
+ CYBOZU_TEST_EQUAL(x, y);
+ }
+}
+
+void benchFp2()
+{
+ puts(__FUNCTION__);
+ Fp2 x, y;
+ x.a.setStr("4");
+ x.b.setStr("464652165165");
+ y = x * x;
+ double addT, subT, mulT, sqrT, invT, mul_xiT;
+ CYBOZU_BENCH_T(addT, Fp2::add, x, x, y);
+ CYBOZU_BENCH_T(subT, Fp2::sub, x, x, y);
+ CYBOZU_BENCH_T(mulT, Fp2::mul, x, x, y);
+ CYBOZU_BENCH_T(sqrT, Fp2::sqr, x, x);
+ CYBOZU_BENCH_T(invT, Fp2::inv, x, x);
+ CYBOZU_BENCH_T(mul_xiT, Fp2::mul_xi, x, x);
+// CYBOZU_BENCH("Fp2::mul_Fp_0", Fp2::mul_Fp_0, x, x, Param::half);
+// CYBOZU_BENCH("Fp2::mul_Fp_1", Fp2::mul_Fp_1, x, Param::half);
+// CYBOZU_BENCH("Fp2::divBy2 ", Fp2::divBy2, x, x);
+// CYBOZU_BENCH("Fp2::divBy4 ", Fp2::divBy4, x, x);
+ printf("add %8.2f|sub %8.2f|mul %8.2f|sqr %8.2f|inv %8.2f|mul_xi %8.2f\n", addT, subT, mulT, sqrT, invT, mul_xiT);
+}
+
+void test(const char *p, mcl::fp::Mode mode)
+{
+ const int xi_a = 1;
+ Fp::init(xi_a, p, mode);
+ printf("mode=%s\n", mcl::fp::ModeToStr(mode));
+ Fp2::init();
+#if 0
+ if (Fp::getBitSize() > 256) {
+ printf("not support p=%s\n", p);
+ return;
+ }
+#endif
+ if (g_benchOnly) {
+ benchFp2();
+ return;
+ }
+ testFp2();
+ testFpDbl();
+ testFp6();
+ testFp12();
+ testIo();
+}
+
+void testAll()
+{
+ const char *tbl[] = {
+ // N = 2
+ "0x0000000000000001000000000000000d",
+ "0x7fffffffffffffffffffffffffffffff",
+ "0x8000000000000000000000000000001d",
+ "0xffffffffffffffffffffffffffffff61",
+
+ // N = 3
+ "0x000000000000000100000000000000000000000000000033", // min prime
+ "0x00000000fffffffffffffffffffffffffffffffeffffac73",
+ "0x0000000100000000000000000001b8fa16dfab9aca16b6b3",
+ "0x000000010000000000000000000000000000000000000007",
+ "0x30000000000000000000000000000000000000000000002b",
+ "0x70000000000000000000000000000000000000000000001f",
+ "0x800000000000000000000000000000000000000000000005",
+ "0xfffffffffffffffffffffffffffffffeffffffffffffffff",
+ "0xfffffffffffffffffffffffffffffffffffffffeffffee37",
+ "0xfffffffffffffffffffffffe26f2fc170f69466a74defd8d",
+ "0xffffffffffffffffffffffffffffffffffffffffffffff13", // max prime
+
+ // N = 4
+ "0x0000000000000001000000000000000000000000000000000000000000000085", // min prime
+ "0x2523648240000001ba344d80000000086121000000000013a700000000000013",
+ "0x7523648240000001ba344d80000000086121000000000013a700000000000017",
+ "0x800000000000000000000000000000000000000000000000000000000000005f",
+ "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff43", // max prime
+#if MCL_MAX_BIT_SIZE >= 384
+ // N = 6
+ "0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaab",
+ "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000000ffffffff",
+#endif
+#if MCL_MAX_BIT_SIZE >= 768
+ "776259046150354467574489744231251277628443008558348305569526019013025476343188443165439204414323238975243865348565536603085790022057407195722143637520590569602227488010424952775132642815799222412631499596858234375446423426908029627",
+#endif
+ };
+ for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) {
+ const char *p = tbl[i];
+ printf("prime=%s %d\n", p, (int)(strlen(p) - 2) * 4);
+ test(p, mcl::fp::FP_GMP);
+#ifdef MCL_USE_LLVM
+ test(p, mcl::fp::FP_LLVM);
+ test(p, mcl::fp::FP_LLVM_MONT);
+#endif
+#ifdef MCL_USE_XBYAK
+ test(p, mcl::fp::FP_XBYAK);
+#endif
+ }
+}
+
+CYBOZU_TEST_AUTO(testAll)
+{
+ testAll();
+}
+
+int main(int argc, char *argv[])
+{
+ if (argc > 1 && strcmp(argv[1], "-bench") == 0) {
+ g_benchOnly = true;
+ }
+ if (g_benchOnly) {
+ testAll();
+ return 0;
+ } else {
+ return cybozu::test::autoRun.run(argc, argv);
+ }
+}
diff --git a/vendor/github.com/tangerine-network/mcl/test/fp_util_test.cpp b/vendor/github.com/tangerine-network/mcl/test/fp_util_test.cpp
new file mode 100644
index 000000000..e8a9f9aa5
--- /dev/null
+++ b/vendor/github.com/tangerine-network/mcl/test/fp_util_test.cpp
@@ -0,0 +1,270 @@
+#define PUT(x) std::cout << #x "=" << (x) << std::endl
+#include <cybozu/test.hpp>
+#include <mcl/conversion.hpp>
+#include <mcl/gmp_util.hpp>
+#include <mcl/fp.hpp>
+#include <vector>
+
+CYBOZU_TEST_AUTO(arrayToHex)
+{
+ const struct {
+ uint32_t x[4];
+ size_t n;
+ const char *str;
+ } tbl[] = {
+ { { 0, 0, 0, 0 }, 0, "0" },
+ { { 0x123, 0, 0, 0 }, 1, "123" },
+ { { 0x12345678, 0xaabbcc, 0, 0 }, 2, "aabbcc12345678" },
+ { { 0, 0x12, 0x234a, 0 }, 3, "234a0000001200000000" },
+ { { 1, 2, 0xffffffff, 0x123abc }, 4, "123abcffffffff0000000200000001" },
+ };
+ for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) {
+ char buf[64];
+ size_t n = mcl::fp::arrayToHex(buf, sizeof(buf), tbl[i].x, tbl[i].n, false);
+ CYBOZU_TEST_ASSERT(n > 0);
+ CYBOZU_TEST_EQUAL_ARRAY(buf + sizeof(buf) - n, tbl[i].str, n);
+ n = mcl::fp::arrayToHex(buf, sizeof(buf), tbl[i].x, tbl[i].n, true);
+ CYBOZU_TEST_ASSERT(n > 0);
+ CYBOZU_TEST_EQUAL_ARRAY(buf + sizeof(buf) - n, (std::string("0x") + tbl[i].str).c_str(), n);
+ }
+}
+
+CYBOZU_TEST_AUTO(arrayToBin)
+{
+ const struct {
+ uint32_t x[4];
+ size_t n;
+ const char *str;
+ } tbl[] = {
+ { { 0, 0, 0, 0 }, 0, "0" },
+ { { 0x123, 0, 0, 0 }, 1, "100100011" },
+ { { 0x12345678, 0xaabbcc, 0, 0 }, 2, "10101010101110111100110000010010001101000101011001111000" },
+ { { 0, 0x12, 0x234a, 0 }, 3, "100011010010100000000000000000000000000001001000000000000000000000000000000000" },
+ { { 1, 2, 0xffffffff, 0x123abc }, 4, "100100011101010111100111111111111111111111111111111110000000000000000000000000000001000000000000000000000000000000001" },
+ };
+ for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) {
+ char buf[512];
+ size_t n = mcl::fp::arrayToBin(buf, sizeof(buf), tbl[i].x, tbl[i].n, false);
+ CYBOZU_TEST_ASSERT(n > 0);
+ CYBOZU_TEST_EQUAL_ARRAY(buf + sizeof(buf) - n, tbl[i].str, n);
+ n = mcl::fp::arrayToBin(buf, sizeof(buf), tbl[i].x, tbl[i].n, true);
+ CYBOZU_TEST_ASSERT(n > 0);
+ CYBOZU_TEST_EQUAL_ARRAY(buf + sizeof(buf) - n, (std::string("0b") + tbl[i].str).c_str(), n);
+ }
+}
+// CYBOZU_TEST_AUTO(verifyStr) // QQQ
+
+CYBOZU_TEST_AUTO(hexToArray)
+{
+ const struct {
+ const char *str;
+ uint64_t x[4];
+ } tbl[] = {
+ { "0", { 0, 0, 0, 0 } },
+ { "5", { 5, 0, 0, 0 } },
+ { "123", { 0x123, 0, 0, 0 } },
+ { "123456789012345679adbc", { uint64_t(0x789012345679adbcull), 0x123456, 0, 0 } },
+ { "ffffffff26f2fc170f69466a74defd8d", { uint64_t(0x0f69466a74defd8dull), uint64_t(0xffffffff26f2fc17ull), 0, 0 } },
+ { "100000000000000000000000000000033", { uint64_t(0x0000000000000033ull), 0, 1, 0 } },
+ { "11ee12312312940000000000000000000000000002342343", { uint64_t(0x0000000002342343ull), uint64_t(0x0000000000000000ull), uint64_t(0x11ee123123129400ull), 0 } },
+ { "1234567890abcdefABCDEF123456789aba32134723424242424", { uint64_t(0x2134723424242424ull), uint64_t(0xDEF123456789aba3ull), uint64_t(0x4567890abcdefABCull), 0x123 } },
+ };
+ for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) {
+ const size_t xN = 4;
+ uint64_t x[xN];
+ size_t n = mcl::fp::hexToArray(x, xN, tbl[i].str, strlen(tbl[i].str));
+ CYBOZU_TEST_ASSERT(n > 0);
+ CYBOZU_TEST_EQUAL_ARRAY(x, tbl[i].x, n);
+ }
+}
+
+CYBOZU_TEST_AUTO(compareArray)
+{
+ const struct {
+ uint32_t a[4];
+ uint32_t b[4];
+ size_t n;
+ int expect;
+ } tbl[] = {
+ { { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, 0, 0 },
+ { { 1, 0, 0, 0 }, { 0, 0, 0, 0 }, 1, 1 },
+ { { 0, 0, 0, 0 }, { 1, 0, 0, 0 }, 1, -1 },
+ { { 1, 0, 0, 0 }, { 1, 0, 0, 0 }, 1, 0 },
+ { { 3, 1, 1, 0 }, { 2, 1, 1, 0 }, 4, 1 },
+ { { 9, 2, 1, 1 }, { 1, 3, 1, 1 }, 4, -1 },
+ { { 1, 7, 8, 4 }, { 1, 7, 8, 9 }, 3, 0 },
+ { { 1, 7, 8, 4 }, { 1, 7, 8, 9 }, 4, -1 },
+ };
+ for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) {
+ int e = mcl::fp::compareArray(tbl[i].a, tbl[i].b, tbl[i].n);
+ CYBOZU_TEST_EQUAL(e, tbl[i].expect);
+ }
+}
+
+CYBOZU_TEST_AUTO(isLessArray)
+{
+ const struct {
+ uint32_t a[4];
+ uint32_t b[4];
+ size_t n;
+ bool expect;
+ } tbl[] = {
+ { { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, 0, false },
+ { { 1, 0, 0, 0 }, { 0, 0, 0, 0 }, 1, false },
+ { { 0, 0, 0, 0 }, { 1, 0, 0, 0 }, 1, true },
+ { { 1, 0, 0, 0 }, { 1, 0, 0, 0 }, 1, false },
+ { { 3, 1, 1, 0 }, { 2, 1, 1, 0 }, 4, false },
+ { { 3, 1, 2, 0 }, { 2, 2, 2, 0 }, 4, true },
+ { { 9, 2, 1, 1 }, { 1, 3, 1, 1 }, 4, true },
+ { { 1, 7, 8, 4 }, { 1, 7, 8, 9 }, 3, false },
+ { { 1, 7, 8, 4 }, { 1, 7, 8, 9 }, 4, true },
+ };
+ for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) {
+ bool e = mcl::fp::isLessArray(tbl[i].a, tbl[i].b, tbl[i].n);
+ CYBOZU_TEST_EQUAL(e, tbl[i].expect);
+ e = mcl::fp::isGreaterArray(tbl[i].b, tbl[i].a, tbl[i].n);
+ CYBOZU_TEST_EQUAL(e, tbl[i].expect);
+ }
+}
+
+CYBOZU_TEST_AUTO(isLessOrEqualArray)
+{
+ const struct {
+ uint32_t a[4];
+ uint32_t b[4];
+ size_t n;
+ bool expect;
+ } tbl[] = {
+ { { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, 0, true },
+ { { 1, 0, 0, 0 }, { 0, 0, 0, 0 }, 1, false },
+ { { 0, 0, 0, 0 }, { 1, 0, 0, 0 }, 1, true },
+ { { 1, 0, 0, 0 }, { 1, 0, 0, 0 }, 1, true },
+ { { 3, 1, 1, 0 }, { 2, 1, 1, 0 }, 4, false },
+ { { 3, 1, 2, 0 }, { 2, 2, 2, 0 }, 4, true },
+ { { 9, 2, 1, 1 }, { 1, 3, 1, 1 }, 4, true },
+ { { 1, 7, 8, 4 }, { 1, 7, 8, 9 }, 3, true },
+ { { 1, 7, 8, 4 }, { 1, 7, 8, 9 }, 4, true },
+ };
+ for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) {
+ bool e = mcl::fp::isLessOrEqualArray(tbl[i].a, tbl[i].b, tbl[i].n);
+ CYBOZU_TEST_EQUAL(e, tbl[i].expect);
+ e = mcl::fp::isGreaterOrEqualArray(tbl[i].b, tbl[i].a, tbl[i].n);
+ CYBOZU_TEST_EQUAL(e, tbl[i].expect);
+ }
+}
+
+struct Rand {
+ std::vector<uint32_t> v;
+ const uint8_t *p;
+ size_t pos;
+ size_t endPos;
+ void read(bool *pb, void *x, size_t n)
+ {
+ if (pos + n > endPos) {
+ *pb = false;
+ return;
+ }
+ uint8_t *dst = (uint8_t*)x;
+ memcpy(dst, p + pos, n);
+ pos += n;
+ *pb = true;
+ }
+ void read(void *x, size_t n)
+ {
+ bool b;
+ read(&b, x, n);
+ if (!b) throw cybozu::Exception("Rand") << n;
+ }
+ uint32_t operator()()
+ {
+ char buf[4];
+ read(buf, 4);
+ uint32_t v;
+ memcpy(&v, buf, 4);
+ return v;
+ }
+ Rand(const uint32_t *x, size_t n)
+ : p(0)
+ , pos(0)
+ {
+ for (size_t i = 0; i < n; i++) {
+ v.push_back(x[i]);
+ }
+ p = (uint8_t*)&v[0];
+ endPos = v.size() * 4;
+ }
+};
+
+CYBOZU_TEST_AUTO(maskArray)
+{
+#if 1
+ const size_t n = 2;
+ uint32_t org[n] = { 0xabce1234, 0xffffef32 };
+ for (size_t i = 0; i <= sizeof(org) * 8; i++) {
+ uint32_t x[n];
+ memcpy(x, org, sizeof(org));
+ mcl::fp::maskArray(x, n, i);
+ mpz_class t;
+ mcl::gmp::setArray(t, org, n);
+ t &= (mpz_class(1) << i) - 1;
+ uint32_t y[n];
+ mcl::gmp::getArray(y, n, t);
+ CYBOZU_TEST_EQUAL_ARRAY(x, y, n);
+ }
+#else
+ const size_t n = 4;
+ uint16_t org[n] = { 0x1234, 0xabce, 0xef32, 0xffff };
+ for (size_t i = 0; i <= sizeof(org) * 8; i++) {
+ uint16_t x[n];
+ memcpy(x, org, sizeof(org));
+ mcl::fp::maskArray(x, n, i);
+ mpz_class t;
+ mcl::gmp::setArray(t, org, n);
+ t &= (mpz_class(1) << i) - 1;
+ uint16_t y[n];
+ mcl::gmp::getArray(y, n, t);
+ CYBOZU_TEST_EQUAL_ARRAY(x, y, n);
+ }
+#endif
+}
+
+CYBOZU_TEST_AUTO(stream)
+{
+ const char *nulTbl[] = { "", " ", " \t\t\n\n " };
+ for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(nulTbl); i++) {
+ const char *p = nulTbl[i];
+ cybozu::MemoryInputStream is(p, strlen(p));
+ std::string w = "abc";
+ mcl::fp::local::loadWord(w, is);
+ CYBOZU_TEST_ASSERT(w.empty());
+ }
+ const struct {
+ const char *buf;
+ const char *expect[2];
+ size_t n;
+ } tbl[] = {
+ { "\t\t \n\rabc\r\r\n def", { "abc", "def" }, 2 },
+ { "123", { "123" }, 1 },
+ { "123\n", { "123" }, 1 },
+ { "123 456", { "123", "456" }, 2 },
+ };
+ for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) {
+ const char *buf = tbl[i].buf;
+ {
+ cybozu::MemoryInputStream is(buf, strlen(buf));
+ for (size_t j = 0; j < tbl[i].n; j++) {
+ std::string w;
+ mcl::fp::local::loadWord(w, is);
+ CYBOZU_TEST_EQUAL(w, tbl[i].expect[j]);
+ }
+ }
+ {
+ std::istringstream is(buf);
+ for (size_t j = 0; j < tbl[i].n; j++) {
+ std::string w;
+ mcl::fp::local::loadWord(w, is);
+ CYBOZU_TEST_EQUAL(w, tbl[i].expect[j]);
+ }
+ }
+ }
+}
diff --git a/vendor/github.com/tangerine-network/mcl/test/glv_test.cpp b/vendor/github.com/tangerine-network/mcl/test/glv_test.cpp
new file mode 100644
index 000000000..a917f51f4
--- /dev/null
+++ b/vendor/github.com/tangerine-network/mcl/test/glv_test.cpp
@@ -0,0 +1,209 @@
+#define PUT(x) std::cout << #x "=" << (x) << std::endl;
+#include <cybozu/test.hpp>
+#include <cybozu/xorshift.hpp>
+#include <cybozu/benchmark.hpp>
+
+#if 1
+#include <mcl/bn384.hpp>
+using namespace mcl::bn384;
+#else
+#include <mcl/bn256.hpp>
+using namespace mcl::bn256;
+#endif
+
+#define PUT(x) std::cout << #x "=" << (x) << std::endl;
+
+/*
+ Skew Frobenius Map and Efficient Scalar Multiplication for Pairing-Based Cryptography
+ Y. Sakemi, Y. Nogami, K. Okeya, H. Kato, Y. Morikawa
+*/
+struct oldGLV {
+ Fp w; // (-1 + sqrt(-3)) / 2
+ mpz_class r;
+ mpz_class v; // 6z^2 + 4z + 1 > 0
+ mpz_class c; // 2z + 1
+ void init(const mpz_class& r, const mpz_class& z)
+ {
+ if (!Fp::squareRoot(w, -3)) throw cybozu::Exception("oldGLV:init");
+ w = (w - 1) / 2;
+ this->r = r;
+ v = 1 + z * (4 + z * 6);
+ c = 2 * z + 1;
+ }
+ /*
+ (p^2 mod r) (x, y) = (wx, -y)
+ */
+ void mulP2(G1& Q, const G1& P) const
+ {
+ Fp::mul(Q.x, P.x, w);
+ Fp::neg(Q.y, P.y);
+ Q.z = P.z;
+ }
+ /*
+ x = ap^2 + b mod r
+ assume(x < r);
+ */
+ void split(mpz_class& a, mpz_class& b, const mpz_class& x) const
+ {
+ assert(0 < x && x < r);
+ /*
+ x = s1 * v + s2 // s1 = x / v, s2 = x % v
+ = s1 * c * p^2 + s2 // vP = cp^2 P
+ = (s3 * v + s4) * p^2 + s2 // s3 = (s1 * c) / v, s4 = (s1 * c) % v
+ = (s3 * c * p^2 + s4) * p^2 + s2
+ = (s3 * c) * p^4 + s4 * p^2 + s2 // s5 = s3 * c, p^4 = p^2 - 1
+ = s5 * (p^2 - 1) + s4 * p^2 + s2
+ = (s4 + s5) * p^2 + (s2 - s5)
+ */
+ mpz_class t;
+ mcl::gmp::divmod(a, t, x, v); // a = t / v, t = t % v
+ a *= c;
+ mcl::gmp::divmod(b, a, a, v); // b = a / v, a = a % v
+ b *= c;
+ a += b;
+ b = t - b;
+ }
+ template<class G1>
+ void mul(G1& Q, const G1& P, const mpz_class& x) const
+ {
+ G1 A, B;
+ mpz_class a, b;
+ split(a, b, x);
+ mulP2(A, P);
+ G1::mul(A, A, a);
+ G1::mul(B, P, b);
+ G1::add(Q, A, B);
+ }
+};
+
+template<class GLV1, class GLV2>
+void compareLength(const GLV1& rhs, const GLV2& lhs)
+{
+ cybozu::XorShift rg;
+ int lt = 0;
+ int eq = 0;
+ int gt = 0;
+ mpz_class R0, R1, L0, L1, x;
+ Fr r;
+ for (int i = 1; i < 1000; i++) {
+ r.setRand(rg);
+ x = r.getMpz();
+ rhs.split(R0, R1, x);
+ lhs.split(L0, L1, x);
+
+ size_t R0n = mcl::gmp::getBitSize(R0);
+ size_t R1n = mcl::gmp::getBitSize(R1);
+ size_t L0n = mcl::gmp::getBitSize(L0);
+ size_t L1n = mcl::gmp::getBitSize(L1);
+ size_t Rn = std::max(R0n, R1n);
+ size_t Ln = std::max(L0n, L1n);
+ if (Rn == Ln) {
+ eq++;
+ }
+ if (Rn > Ln) {
+ gt++;
+ }
+ if (Rn < Ln) {
+ lt++;
+ }
+ }
+ printf("#of{<} = %d, #of{=} = %d #of{>} = %d\n", lt, eq, gt);
+}
+
+void testGLV1()
+{
+ G1 P0, P1, P2;
+ mapToG1(P0, 1);
+ cybozu::XorShift rg;
+
+ oldGLV oldGlv;
+ if (!BN::param.isBLS12) {
+ oldGlv.init(BN::param.r, BN::param.z);
+ }
+
+ mcl::bn::local::GLV1 glv;
+ glv.init(BN::param.r, BN::param.z, BN::param.isBLS12);
+ if (!BN::param.isBLS12) {
+ compareLength(glv, oldGlv);
+ }
+
+ for (int i = 1; i < 100; i++) {
+ mapToG1(P0, i);
+ Fr s;
+ s.setRand(rg);
+ mpz_class ss = s.getMpz();
+ G1::mulGeneric(P1, P0, ss);
+ glv.mul(P2, P0, ss);
+ CYBOZU_TEST_EQUAL(P1, P2);
+ glv.mul(P2, P0, ss, true);
+ CYBOZU_TEST_EQUAL(P1, P2);
+ if (!BN::param.isBLS12) {
+ oldGlv.mul(P2, P0, ss);
+ CYBOZU_TEST_EQUAL(P1, P2);
+ }
+ }
+ for (int i = -100; i < 100; i++) {
+ mpz_class ss = i;
+ G1::mulGeneric(P1, P0, ss);
+ glv.mul(P2, P0, ss);
+ CYBOZU_TEST_EQUAL(P1, P2);
+ glv.mul(P2, P0, ss, true);
+ CYBOZU_TEST_EQUAL(P1, P2);
+ }
+ Fr s;
+ mapToG1(P0, 123);
+ CYBOZU_BENCH_C("Ec::mul", 100, P1 = P0; s.setRand(rg); G1::mulGeneric, P2, P1, s.getMpz());
+ CYBOZU_BENCH_C("Ec::glv", 100, P1 = P0; s.setRand(rg); glv.mul, P2, P1, s.getMpz());
+}
+
+/*
+ lambda = 6 * z * z
+ mul (lambda * 2) = FrobeniusOnTwist * 2
+*/
+void testGLV2()
+{
+ G2 Q0, Q1, Q2;
+ mpz_class z = BN::param.z;
+ mpz_class r = BN::param.r;
+ mpz_class lambda = 6 * z * z;
+ mcl::bn::local::GLV2 glv2;
+ glv2.init(r, z, BN::param.isBLS12);
+ mpz_class n;
+ cybozu::XorShift rg;
+ mapToG2(Q0, 1);
+ for (int i = -10; i < 10; i++) {
+ n = i;
+ G2::mulGeneric(Q1, Q0, n);
+ glv2.mul(Q2, Q0, n);
+ CYBOZU_TEST_EQUAL(Q1, Q2);
+ }
+ for (int i = 1; i < 100; i++) {
+ mcl::gmp::getRand(n, glv2.rBitSize, rg);
+ n %= r;
+ n -= r/2;
+ mapToG2(Q0, i);
+ G2::mulGeneric(Q1, Q0, n);
+ glv2.mul(Q2, Q0, n);
+ CYBOZU_TEST_EQUAL(Q1, Q2);
+ }
+ Fr s;
+ mapToG2(Q0, 123);
+ CYBOZU_BENCH_C("G2::mul", 1000, Q2 = Q0; s.setRand(rg); G2::mulGeneric, Q2, Q1, s.getMpz());
+ CYBOZU_BENCH_C("G2::glv", 1000, Q1 = Q0; s.setRand(rg); glv2.mul, Q2, Q1, s.getMpz());
+}
+
+CYBOZU_TEST_AUTO(glv)
+{
+ const mcl::CurveParam tbl[] = {
+ mcl::BN254,
+ mcl::BN381_1,
+ mcl::BN381_2,
+ mcl::BLS12_381,
+ };
+ for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) {
+ const mcl::CurveParam& cp = tbl[i];
+ initPairing(cp);
+ testGLV1();
+ testGLV2();
+ }
+}
diff --git a/vendor/github.com/tangerine-network/mcl/test/gmp_test.cpp b/vendor/github.com/tangerine-network/mcl/test/gmp_test.cpp
new file mode 100644
index 000000000..1fe9d4eb6
--- /dev/null
+++ b/vendor/github.com/tangerine-network/mcl/test/gmp_test.cpp
@@ -0,0 +1,70 @@
+#include <mcl/gmp_util.hpp>
+#include <vector>
+#include <cybozu/test.hpp>
+
+CYBOZU_TEST_AUTO(testBit)
+{
+ const size_t maxBit = 100;
+ const size_t tbl[] = {
+ 3, 9, 5, 10, 50, maxBit
+ };
+ mpz_class a;
+ std::vector<bool> b(maxBit + 1);
+ for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) {
+ a |= mpz_class(1) << tbl[i];
+ b[tbl[i]] = 1;
+ }
+ for (size_t i = 0; i <= maxBit; i++) {
+ bool c1 = mcl::gmp::testBit(a, i);
+ bool c2 = b[i] != 0;
+ CYBOZU_TEST_EQUAL(c1, c2);
+ }
+}
+
+CYBOZU_TEST_AUTO(getStr)
+{
+ const struct {
+ int x;
+ const char *dec;
+ const char *hex;
+ } tbl[] = {
+ { 0, "0", "0" },
+ { 1, "1", "1" },
+ { 10, "10", "a" },
+ { 16, "16", "10" },
+ { 123456789, "123456789", "75bcd15" },
+ { -1, "-1", "-1" },
+ { -10, "-10", "-a" },
+ { -16, "-16", "-10" },
+ { -100000000, "-100000000", "-5f5e100" },
+ { -987654321, "-987654321", "-3ade68b1" },
+ { -2147483647, "-2147483647", "-7fffffff" },
+ };
+ for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) {
+ mpz_class x = tbl[i].x;
+ char buf[32];
+ size_t n, len;
+ len = strlen(tbl[i].dec);
+ n = mcl::gmp::getStr(buf, len, x, 10);
+ CYBOZU_TEST_EQUAL(n, 0);
+ n = mcl::gmp::getStr(buf, len + 1, x, 10);
+ CYBOZU_TEST_EQUAL(n, len);
+ CYBOZU_TEST_EQUAL_ARRAY(buf, tbl[i].dec, n);
+
+ len = strlen(tbl[i].hex);
+ n = mcl::gmp::getStr(buf, len, x, 16);
+ CYBOZU_TEST_EQUAL(n, 0);
+ n = mcl::gmp::getStr(buf, len + 1, x, 16);
+ CYBOZU_TEST_EQUAL(n, len);
+ CYBOZU_TEST_EQUAL_ARRAY(buf, tbl[i].hex, n);
+ }
+}
+
+CYBOZU_TEST_AUTO(getRandPrime)
+{
+ for (int i = 0; i < 10; i++) {
+ mpz_class z;
+ mcl::gmp::getRandPrime(z, i * 10 + 3);
+ CYBOZU_TEST_ASSERT(mcl::gmp::isPrime(z));
+ }
+}
diff --git a/vendor/github.com/tangerine-network/mcl/test/low_test.cpp b/vendor/github.com/tangerine-network/mcl/test/low_test.cpp
new file mode 100644
index 000000000..f5e72a0b3
--- /dev/null
+++ b/vendor/github.com/tangerine-network/mcl/test/low_test.cpp
@@ -0,0 +1,73 @@
+#ifndef MCL_USE_LLVM
+ #define MCL_USE_LLVM
+#endif
+#include <cybozu/test.hpp>
+#include <cybozu/xorshift.hpp>
+#include <cybozu/itoa.hpp>
+#include "../src/low_func.hpp"
+#include <cybozu/benchmark.hpp>
+
+cybozu::XorShift rg;
+
+extern "C" void add_test(mcl::fp::Unit *z, const mcl::fp::Unit *x, const mcl::fp::Unit *y);
+
+template<size_t bit>
+void bench()
+{
+ using namespace mcl::fp;
+ const size_t N = bit / UnitBitSize;
+ Unit x[N], y[N];
+ for (int i = 0; i < 10; i++) {
+ Unit z[N];
+ Unit w[N];
+ rg.read(x, N);
+ rg.read(y, N);
+ AddPre<N, Gtag>::f(z, x, y);
+ AddPre<N, Ltag>::f(w, x, y);
+ CYBOZU_TEST_EQUAL_ARRAY(z, w, N);
+
+ SubPre<N, Gtag>::f(z, x, y);
+ SubPre<N, Ltag>::f(w, x, y);
+ CYBOZU_TEST_EQUAL_ARRAY(z, w, N);
+ }
+ const std::string bitS = cybozu::itoa(bit);
+ std::string name;
+ name = "add" + bitS; CYBOZU_BENCH(name.c_str(), (AddPre<N, Ltag>::f), x, x, y);
+ name = "sub" + bitS; CYBOZU_BENCH(name.c_str(), (SubPre<N, Ltag>::f), x, x, y);
+}
+
+CYBOZU_TEST_AUTO(addPre64) { bench<64>(); }
+CYBOZU_TEST_AUTO(addPre128) { bench<128>(); }
+CYBOZU_TEST_AUTO(addPre192) { bench<192>(); }
+CYBOZU_TEST_AUTO(addPre256) { bench<256>(); }
+CYBOZU_TEST_AUTO(addPre320) { bench<320>(); }
+CYBOZU_TEST_AUTO(addPre384) { bench<384>(); }
+CYBOZU_TEST_AUTO(addPre448) { bench<448>(); }
+CYBOZU_TEST_AUTO(addPre512) { bench<512>(); }
+//CYBOZU_TEST_AUTO(addPre96) { bench<96>(); }
+//CYBOZU_TEST_AUTO(addPre160) { bench<160>(); }
+//CYBOZU_TEST_AUTO(addPre224) { bench<224>(); }
+#if 0
+CYBOZU_TEST_AUTO(addPre)
+{
+ using namespace mcl::fp;
+ const size_t bit = 128;
+ const size_t N = bit / UnitBitSize;
+ Unit x[N], y[N];
+ for (int i = 0; i < 10; i++) {
+ Unit z[N];
+ Unit w[N];
+ rg.read(x, N);
+ rg.read(y, N);
+ low_addPre_G<N>(z, x, y);
+ addPre<bit>(w, x, y);
+ CYBOZU_TEST_EQUAL_ARRAY(z, w, N);
+ add_test(w, x, y);
+ CYBOZU_TEST_EQUAL_ARRAY(z, w, N);
+ }
+ std::string name = "add" + cybozu::itoa(bit);
+ CYBOZU_BENCH(name.c_str(), addPre<bit>, x, x, y);
+ CYBOZU_BENCH("add", add_test, x, x, y);
+}
+#endif
+
diff --git a/vendor/github.com/tangerine-network/mcl/test/mk32.sh b/vendor/github.com/tangerine-network/mcl/test/mk32.sh
new file mode 100644
index 000000000..4d5f60711
--- /dev/null
+++ b/vendor/github.com/tangerine-network/mcl/test/mk32.sh
@@ -0,0 +1 @@
+g++ -O3 -march=native base_test.cpp ../src/x86.s -m32 -I ~/32/include/ -I ../include/ -I ../../xbyak/ -I ../../cybozulib/include ~/32/lib/libgmp.a ~/32/lib/libgmpxx.a -I ~/32/lib -DNDEBUG
diff --git a/vendor/github.com/tangerine-network/mcl/test/modp_test.cpp b/vendor/github.com/tangerine-network/mcl/test/modp_test.cpp
new file mode 100644
index 000000000..bf9da38bf
--- /dev/null
+++ b/vendor/github.com/tangerine-network/mcl/test/modp_test.cpp
@@ -0,0 +1,37 @@
+#include <mcl/gmp_util.hpp>
+#include <cybozu/benchmark.hpp>
+#include <cybozu/test.hpp>
+
+#define PUT(x) std::cout << #x << "=" << x << std::endl;
+
+CYBOZU_TEST_AUTO(modp)
+{
+ const int C = 1000000;
+ const char *pTbl[] = {
+ "0x2523648240000001ba344d8000000007ff9f800000000010a10000000000000d",
+ "0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaab",
+ "0x73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001",
+ };
+ const char *xTbl[] = {
+ "0x12345678892082039482094823",
+ "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
+ "0x10000000000000000000000000000000000000000000000000000000000000000",
+ "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
+ };
+ mcl::Modp modp;
+ for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(pTbl); i++) {
+ const mpz_class p(pTbl[i]);
+ std::cout << std::hex << "p=" << p << std::endl;
+ modp.init(p);
+ for (size_t j = 0; j < CYBOZU_NUM_OF_ARRAY(xTbl); j++) {
+ const mpz_class x(xTbl[j]);
+ std::cout << std::hex << "x=" << x << std::endl;
+ mpz_class r1, r2;
+ r1 = x % p;
+ modp.modp(r2, x);
+ CYBOZU_TEST_EQUAL(r1, r2);
+ CYBOZU_BENCH_C("x % p", C, mcl::gmp::mod, r1, x, p);
+ CYBOZU_BENCH_C("modp ", C, modp.modp, r2, x);
+ }
+ }
+}
diff --git a/vendor/github.com/tangerine-network/mcl/test/mont_fp_test.cpp b/vendor/github.com/tangerine-network/mcl/test/mont_fp_test.cpp
new file mode 100644
index 000000000..e41e77a53
--- /dev/null
+++ b/vendor/github.com/tangerine-network/mcl/test/mont_fp_test.cpp
@@ -0,0 +1,332 @@
+#define PUT(x) std::cout << #x "=" << (x) << std::endl
+#include <cybozu/test.hpp>
+#include <cybozu/benchmark.hpp>
+#include <cybozu/xorshift.hpp>
+#include <time.h>
+
+#if 0
+#include <mcl/bls12_381.hpp>
+using namespace mcl::bls12;
+typedef Fr Zn;
+#else
+#include <mcl/fp.hpp>
+struct ZnTag;
+typedef mcl::FpT<ZnTag> Zn;
+typedef mcl::FpT<> Fp;
+#endif
+
+struct Montgomery {
+ typedef mcl::fp::Unit Unit;
+ mpz_class p_;
+ mpz_class R_; // (1 << (pn_ * 64)) % p
+ mpz_class RR_; // (R * R) % p
+ Unit rp_; // rp * p = -1 mod M = 1 << 64
+ size_t pn_;
+ Montgomery() {}
+ explicit Montgomery(const mpz_class& p)
+ {
+ p_ = p;
+ rp_ = mcl::fp::getMontgomeryCoeff(mcl::gmp::getUnit(p, 0));
+ pn_ = mcl::gmp::getUnitSize(p);
+ R_ = 1;
+ R_ = (R_ << (pn_ * 64)) % p_;
+ RR_ = (R_ * R_) % p_;
+ }
+
+ void toMont(mpz_class& x) const { mul(x, x, RR_); }
+ void fromMont(mpz_class& x) const { mul(x, x, 1); }
+
+ void mul(mpz_class& z, const mpz_class& x, const mpz_class& y) const
+ {
+#if 0
+ const size_t ySize = mcl::gmp::getUnitSize(y);
+ mpz_class c = x * mcl::gmp::getUnit(y, 0);
+ Unit q = mcl::gmp::getUnit(c, 0) * rp_;
+ c += p_ * q;
+ c >>= sizeof(Unit) * 8;
+ for (size_t i = 1; i < pn_; i++) {
+ if (i < ySize) {
+ c += x * mcl::gmp::getUnit(y, i);
+ }
+ Unit q = mcl::gmp::getUnit(c, 0) * rp_;
+ c += p_ * q;
+ c >>= sizeof(Unit) * 8;
+ }
+ if (c >= p_) {
+ c -= p_;
+ }
+ z = c;
+#else
+ z = x * y;
+ for (size_t i = 0; i < pn_; i++) {
+ Unit q = mcl::gmp::getUnit(z, 0) * rp_;
+#ifdef MCL_USE_VINT
+ z += p_ * q;
+#else
+ mpz_class t;
+ mcl::gmp::set(t, q);
+ z += p_ * t;
+#endif
+ z >>= sizeof(Unit) * 8;
+ }
+ if (z >= p_) {
+ z -= p_;
+ }
+#endif
+ }
+ void mod(mpz_class& z, const mpz_class& xy) const
+ {
+ z = xy;
+ for (size_t i = 0; i < pn_; i++) {
+//printf("i=%zd\n", i);
+//std::cout << "z=" << std::hex << z << std::endl;
+ Unit q = mcl::gmp::getUnit(z, 0) * rp_;
+//std::cout << "q=" << q << std::endl;
+ mpz_class t;
+ mcl::gmp::set(t, q);
+ z += p_ * t;
+ z >>= sizeof(Unit) * 8;
+//std::cout << "z=" << std::hex << z << std::endl;
+ }
+ if (z >= p_) {
+ z -= p_;
+ }
+//std::cout << "z=" << std::hex << z << std::endl;
+ }
+};
+
+template<class T>
+mpz_class getMpz(const T& x)
+{
+ std::string str = x.getStr();
+ mpz_class t;
+ mcl::gmp::setStr(t, str);
+ return t;
+}
+
+template<class T>
+std::string getStr(const T& x)
+{
+ std::ostringstream os;
+ os << x;
+ return os.str();
+}
+
+template<class T, class U>
+T castTo(const U& x)
+{
+ T t;
+ t.setStr(getStr(x));
+ return t;
+}
+
+template<class T>
+void putRaw(const T& x)
+{
+ const uint64_t *p = x.getInnerValue();
+ for (size_t i = 0, n = T::BlockSize; i < n; i++) {
+ printf("%016llx", p[n - 1 - i]);
+ }
+ printf("\n");
+}
+
+template<size_t N>
+void put(const uint64_t (&x)[N])
+{
+ for (size_t i = 0; i < N; i++) {
+ printf("%016llx", x[N - 1 - i]);
+ }
+ printf("\n");
+}
+
+struct Test {
+ typedef mcl::FpT<> Fp;
+ void run(const char *p)
+ {
+ Fp::init(p);
+ Fp x("-123456789");
+ Fp y("-0x7ffffffff");
+ CYBOZU_BENCH("add", operator+, x, x);
+ CYBOZU_BENCH("sub", operator-, x, y);
+ CYBOZU_BENCH("mul", operator*, x, x);
+ CYBOZU_BENCH("sqr", Fp::sqr, x, x);
+ CYBOZU_BENCH("div", y += x; operator/, x, y);
+ }
+};
+
+void customTest(const char *pStr, const char *xStr, const char *yStr)
+{
+#if 0
+ {
+ pStr = "0xfffffffffffffffffffffffffffffffffffffffeffffee37",
+ Fp::init(pStr);
+ static uint64_t x[3] = { 1, 0, 0 };
+ uint64_t z[3];
+std::cout<<std::hex;
+ Fp::inv(*(Fp*)z, *(const Fp*)x);
+put(z);
+ exit(1);
+ }
+#endif
+#if 0
+ std::cout << std::hex;
+ uint64_t x[9] = { 0xff7fffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0x1ff };
+ uint64_t y[9] = { 0xff7fffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0x1ff };
+ uint64_t z1[9], z2[9];
+ Fp::init(pStr);
+ Fp::fg_.mul_(z2, x, y);
+ put(z2);
+ {
+ puts("C");
+ mpz_class p(pStr);
+ Montgomery mont(p);
+ mpz_class xx, yy;
+ mcl::gmp::setArray(xx, x, CYBOZU_NUM_OF_ARRAY(x));
+ mcl::gmp::setArray(yy, y, CYBOZU_NUM_OF_ARRAY(y));
+ mpz_class z;
+ mont.mul(z, xx, yy);
+ std::cout << std::hex << z << std::endl;
+ }
+ exit(1);
+#else
+ std::string rOrg, rC, rAsm;
+ Zn::init(pStr);
+ Zn s(xStr), t(yStr);
+ s *= t;
+ rOrg = getStr(s);
+ {
+ puts("C");
+ mpz_class p(pStr);
+ Montgomery mont(p);
+ mpz_class x(xStr), y(yStr);
+ mont.toMont(x);
+ mont.toMont(y);
+ mpz_class z;
+ mont.mul(z, x, y);
+ mont.fromMont(z);
+ rC = getStr(z);
+ }
+
+ puts("asm");
+ Fp::init(pStr);
+ Fp x(xStr), y(yStr);
+ x *= y;
+ rAsm = getStr(x);
+ CYBOZU_TEST_EQUAL(rOrg, rC);
+ CYBOZU_TEST_EQUAL(rOrg, rAsm);
+#endif
+}
+
+#if MCL_MAX_BIT_SIZE >= 521
+CYBOZU_TEST_AUTO(customTest)
+{
+ const struct {
+ const char *p;
+ const char *x;
+ const char *y;
+ } tbl[] = {
+ {
+ "0x1ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
+// "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000000ffffffff",
+// "0xfffffffffffffffffffffffffffffffffffffffeffffee37",
+ "0x1fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe",
+ "0x1fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"
+ },
+ };
+ for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) {
+ customTest(tbl[i].p, tbl[i].x, tbl[i].y);
+ }
+}
+#endif
+
+CYBOZU_TEST_AUTO(test)
+{
+ Test test;
+ const char *tbl[] = {
+#if 1
+ // N = 2
+ "0x0000000000000001000000000000000d",
+ "0x7fffffffffffffffffffffffffffffff",
+ "0x8000000000000000000000000000001d",
+ "0xffffffffffffffffffffffffffffff61",
+
+ // N = 3
+ "0x000000000000000100000000000000000000000000000033", // min prime
+ "0x00000000fffffffffffffffffffffffffffffffeffffac73",
+ "0x0000000100000000000000000001b8fa16dfab9aca16b6b3",
+ "0x000000010000000000000000000000000000000000000007",
+ "0x30000000000000000000000000000000000000000000002b",
+ "0x70000000000000000000000000000000000000000000001f",
+ "0x800000000000000000000000000000000000000000000005",
+ "0xfffffffffffffffffffffffffffffffffffffffeffffee37",
+ "0xfffffffffffffffffffffffe26f2fc170f69466a74defd8d",
+ "0xffffffffffffffffffffffffffffffffffffffffffffff13", // max prime
+
+ // N = 4
+ "0x0000000000000001000000000000000000000000000000000000000000000085", // min prime
+ "0x2523648240000001ba344d80000000086121000000000013a700000000000013",
+ "0x7523648240000001ba344d80000000086121000000000013a700000000000017",
+ "0x800000000000000000000000000000000000000000000000000000000000005f",
+ "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff43", // max prime
+#endif
+
+#if MCL_MAX_BIT_SIZE >= 384
+ // N = 6
+ "0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaab",
+ "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000000ffffffff",
+#endif
+
+#if MCL_MAX_BIT_SIZE >= 521
+ // N = 9
+ "0x1ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
+#endif
+ };
+ for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) {
+ printf("prime=%s\n", tbl[i]);
+#if 0
+ mpz_class p(tbl[i]);
+ initPairing(mcl::BLS12_381);
+#if 1
+ cybozu::XorShift rg;
+ for (int i = 0; i < 1000; i++) {
+ Fp x, y, z;
+ FpDbl xy;
+ x.setByCSPRNG(rg);
+ y.setByCSPRNG(rg);
+ FpDbl::mulPre(xy, x, y);
+ FpDbl::mod(z, xy);
+ if (z != x * y) {
+ puts("ERR");
+ std::cout << std::hex;
+ PUT(x);
+ PUT(y);
+ PUT(z);
+ PUT(x * y);
+ exit(1);
+ }
+ }
+#else
+ Montgomery mont(p);
+ mpz_class x("19517141aafb2ffc39517141aafb2ffc39517141aafb2ffc39517141aafb2ffc39517141aafb2ffc39517141aafb2ffc", 16);
+ mpz_class y("139517141aafb2ffc39517141aafb2ffc39517141aafb2ffc39517141aafb2ffc39517141aafb2ffc39517141aafb2ff", 16);
+ std::cout << std::hex;
+ PUT(x);
+ PUT(y);
+ mpz_class z;
+ mont.mul(z, x, y);
+ PUT(z);
+ Fp x1, y1, z1;
+ puts("aaa");
+ memcpy(&x1, mcl::gmp::getUnit(x), sizeof(x1));
+ memcpy(&y1, mcl::gmp::getUnit(y), sizeof(y1));
+ z1.clear();
+ x1.dump();
+ y1.dump();
+ Fp::mul(z1, x1, y1);
+ z1.dump();
+#endif
+ exit(1);
+#endif
+ test.run(tbl[i]);
+ }
+}
diff --git a/vendor/github.com/tangerine-network/mcl/test/paillier_test.cpp b/vendor/github.com/tangerine-network/mcl/test/paillier_test.cpp
new file mode 100644
index 000000000..31d2b26fc
--- /dev/null
+++ b/vendor/github.com/tangerine-network/mcl/test/paillier_test.cpp
@@ -0,0 +1,24 @@
+#include <cybozu/test.hpp>
+#include <mcl/paillier.hpp>
+
+CYBOZU_TEST_AUTO(paillier)
+{
+ using namespace mcl::paillier;
+ SecretKey sec;
+ sec.init(2048);
+ PublicKey pub;
+ sec.getPublicKey(pub);
+ mpz_class m1("12342340928409"), m2("23049820498204");
+ mpz_class c1, c2, c3;
+ pub.enc(c1, m1);
+ pub.enc(c2, m2);
+ std::cout << std::hex << "c1=" << c1 << "\nc2=" << c2 << std::endl;
+ pub.add(c3, c1, c2);
+ mpz_class d1, d2, d3;
+ sec.dec(d1, c1);
+ sec.dec(d2, c2);
+ sec.dec(d3, c3);
+ CYBOZU_TEST_EQUAL(m1, d1);
+ CYBOZU_TEST_EQUAL(m2, d2);
+ CYBOZU_TEST_EQUAL(m1 + m2, d3);
+}
diff --git a/vendor/github.com/tangerine-network/mcl/test/proj/bn_test/bn_test.vcxproj b/vendor/github.com/tangerine-network/mcl/test/proj/bn_test/bn_test.vcxproj
new file mode 100644
index 000000000..936e075aa
--- /dev/null
+++ b/vendor/github.com/tangerine-network/mcl/test/proj/bn_test/bn_test.vcxproj
@@ -0,0 +1,88 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|x64">
+ <Configuration>Debug</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|x64">
+ <Configuration>Release</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{9F935350-2F4C-45FA-A1C2-1D5AA0EADC96}</ProjectGuid>
+ <Keyword>Win32Proj</Keyword>
+ <RootNamespace>bn_test</RootNamespace>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <PlatformToolset>v120</PlatformToolset>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <PlatformToolset>v120</PlatformToolset>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ <Import Project="$(SolutionDir)common.props" />
+ <Import Project="$(SolutionDir)debug.props" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ <Import Project="$(SolutionDir)common.props" />
+ <Import Project="$(SolutionDir)release.props" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <LinkIncremental>true</LinkIncremental>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <LinkIncremental>false</LinkIncremental>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <ClCompile>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="$(SolutionDir)test\\bn_test.cpp" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project> \ No newline at end of file
diff --git a/vendor/github.com/tangerine-network/mcl/test/proj/ec_test/ec_test.vcxproj b/vendor/github.com/tangerine-network/mcl/test/proj/ec_test/ec_test.vcxproj
new file mode 100644
index 000000000..4bdfda2cb
--- /dev/null
+++ b/vendor/github.com/tangerine-network/mcl/test/proj/ec_test/ec_test.vcxproj
@@ -0,0 +1,88 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|x64">
+ <Configuration>Debug</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|x64">
+ <Configuration>Release</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{46B6E88E-739A-406B-9F68-BC46C5950FA3}</ProjectGuid>
+ <Keyword>Win32Proj</Keyword>
+ <RootNamespace>ec_test</RootNamespace>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <PlatformToolset>v120</PlatformToolset>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <PlatformToolset>v120</PlatformToolset>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ <Import Project="$(SolutionDir)common.props" />
+ <Import Project="$(SolutionDir)debug.props" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ <Import Project="$(SolutionDir)common.props" />
+ <Import Project="$(SolutionDir)release.props" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <LinkIncremental>true</LinkIncremental>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <LinkIncremental>false</LinkIncremental>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <ClCompile>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="$(SolutionDir)test\ec_test.cpp" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project>
diff --git a/vendor/github.com/tangerine-network/mcl/test/proj/fp_test/fp_test.vcxproj b/vendor/github.com/tangerine-network/mcl/test/proj/fp_test/fp_test.vcxproj
new file mode 100644
index 000000000..f705982bf
--- /dev/null
+++ b/vendor/github.com/tangerine-network/mcl/test/proj/fp_test/fp_test.vcxproj
@@ -0,0 +1,88 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|x64">
+ <Configuration>Debug</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|x64">
+ <Configuration>Release</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{51266DE6-B57B-4AE3-B85C-282F170E1728}</ProjectGuid>
+ <Keyword>Win32Proj</Keyword>
+ <RootNamespace>fp_test</RootNamespace>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <PlatformToolset>v120</PlatformToolset>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <PlatformToolset>v120</PlatformToolset>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ <Import Project="$(SolutionDir)common.props" />
+ <Import Project="$(SolutionDir)debug.props" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ <Import Project="$(SolutionDir)common.props" />
+ <Import Project="$(SolutionDir)release.props" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <LinkIncremental>true</LinkIncremental>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <LinkIncremental>false</LinkIncremental>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <ClCompile>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="$(SolutionDir)test\\fp_test.cpp" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project> \ No newline at end of file
diff --git a/vendor/github.com/tangerine-network/mcl/test/proj/fp_tower_test/fp_tower_test.vcxproj b/vendor/github.com/tangerine-network/mcl/test/proj/fp_tower_test/fp_tower_test.vcxproj
new file mode 100644
index 000000000..d5720678f
--- /dev/null
+++ b/vendor/github.com/tangerine-network/mcl/test/proj/fp_tower_test/fp_tower_test.vcxproj
@@ -0,0 +1,88 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|x64">
+ <Configuration>Debug</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|x64">
+ <Configuration>Release</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{733B6250-D249-4A99-B2A6-C8FAF6A90E97}</ProjectGuid>
+ <Keyword>Win32Proj</Keyword>
+ <RootNamespace>fp_tower_test</RootNamespace>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <PlatformToolset>v120</PlatformToolset>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <PlatformToolset>v120</PlatformToolset>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ <Import Project="$(SolutionDir)common.props" />
+ <Import Project="$(SolutionDir)debug.props" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ <Import Project="$(SolutionDir)common.props" />
+ <Import Project="$(SolutionDir)release.props" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <LinkIncremental>true</LinkIncremental>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <LinkIncremental>false</LinkIncremental>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <ClCompile>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="$(SolutionDir)test\\fp_tower_test.cpp" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project> \ No newline at end of file
diff --git a/vendor/github.com/tangerine-network/mcl/test/she_c256_test.cpp b/vendor/github.com/tangerine-network/mcl/test/she_c256_test.cpp
new file mode 100644
index 000000000..3e458b623
--- /dev/null
+++ b/vendor/github.com/tangerine-network/mcl/test/she_c256_test.cpp
@@ -0,0 +1,2 @@
+#define MCLBN_FP_UNIT_SIZE 4
+#include "she_c_test.hpp"
diff --git a/vendor/github.com/tangerine-network/mcl/test/she_c384_test.cpp b/vendor/github.com/tangerine-network/mcl/test/she_c384_test.cpp
new file mode 100644
index 000000000..5c7bd9882
--- /dev/null
+++ b/vendor/github.com/tangerine-network/mcl/test/she_c384_test.cpp
@@ -0,0 +1,2 @@
+#define MCLBN_FP_UNIT_SIZE 6
+#include "she_c_test.hpp"
diff --git a/vendor/github.com/tangerine-network/mcl/test/she_c_test.hpp b/vendor/github.com/tangerine-network/mcl/test/she_c_test.hpp
new file mode 100644
index 000000000..8287c0e0a
--- /dev/null
+++ b/vendor/github.com/tangerine-network/mcl/test/she_c_test.hpp
@@ -0,0 +1,535 @@
+#include <mcl/she.h>
+#define CYBOZU_TEST_DISABLE_AUTO_RUN
+#include <cybozu/test.hpp>
+#include <cybozu/option.hpp>
+#include <fstream>
+
+const size_t hashSize = 1 << 10;
+const size_t tryNum = 1024;
+
+CYBOZU_TEST_AUTO(init)
+{
+ int curve;
+#if MCLBN_FP_UNIT_SIZE == 4
+ curve = MCL_BN254;
+#elif MCLBN_FP_UNIT_SIZE == 6
+// curve = MCL_BN381_1;
+ curve = MCL_BLS12_381;
+#elif MCLBN_FP_UNIT_SIZE == 8
+ curve = MCL_BN462;
+#endif
+ int ret;
+ ret = sheInit(curve, MCLBN_COMPILED_TIME_VAR);
+ CYBOZU_TEST_EQUAL(ret, 0);
+ ret = sheSetRangeForDLP(hashSize);
+ CYBOZU_TEST_EQUAL(ret, 0);
+}
+
+CYBOZU_TEST_AUTO(encDec)
+{
+ sheSecretKey sec;
+ sheSecretKeySetByCSPRNG(&sec);
+ shePublicKey pub;
+ sheGetPublicKey(&pub, &sec);
+
+ int64_t m = 123;
+ sheCipherTextG1 c1;
+ sheCipherTextG2 c2;
+ sheCipherTextGT ct;
+ sheEncG1(&c1, &pub, m);
+ sheEncG2(&c2, &pub, m);
+ sheEncGT(&ct, &pub, m);
+
+ int64_t dec;
+ CYBOZU_TEST_EQUAL(sheDecG1(&dec, &sec, &c1), 0);
+ CYBOZU_TEST_EQUAL(dec, m);
+ dec = 0;
+ CYBOZU_TEST_EQUAL(sheDecG1ViaGT(&dec, &sec, &c1), 0);
+ CYBOZU_TEST_EQUAL(dec, m);
+ dec = 0;
+ CYBOZU_TEST_EQUAL(sheDecG2(&dec, &sec, &c2), 0);
+ CYBOZU_TEST_EQUAL(dec, m);
+ dec = 0;
+ CYBOZU_TEST_EQUAL(sheDecG2ViaGT(&dec, &sec, &c2), 0);
+ CYBOZU_TEST_EQUAL(dec, m);
+ dec = 0;
+ CYBOZU_TEST_EQUAL(sheDecGT(&dec, &sec, &ct), 0);
+ CYBOZU_TEST_EQUAL(dec, m);
+
+ for (int m = -3; m < 3; m++) {
+ sheEncG1(&c1, &pub, m);
+ CYBOZU_TEST_EQUAL(sheIsZeroG1(&sec, &c1), m == 0);
+ sheEncG2(&c2, &pub, m);
+ CYBOZU_TEST_EQUAL(sheIsZeroG2(&sec, &c2), m == 0);
+ sheEncGT(&ct, &pub, m);
+ CYBOZU_TEST_EQUAL(sheIsZeroGT(&sec, &ct), m == 0);
+ }
+}
+
+CYBOZU_TEST_AUTO(addMul)
+{
+ sheSecretKey sec;
+ sheSecretKeySetByCSPRNG(&sec);
+ shePublicKey pub;
+ sheGetPublicKey(&pub, &sec);
+
+ int64_t m1 = 12;
+ int64_t m2 = -9;
+ sheCipherTextG1 c1;
+ sheCipherTextG2 c2;
+ sheCipherTextGT ct;
+ sheEncG1(&c1, &pub, m1);
+ sheEncG2(&c2, &pub, m2);
+ sheMul(&ct, &c1, &c2);
+
+ int64_t dec;
+ CYBOZU_TEST_EQUAL(sheDecGT(&dec, &sec, &ct), 0);
+ CYBOZU_TEST_EQUAL(dec, m1 * m2);
+}
+
+CYBOZU_TEST_AUTO(allOp)
+{
+ sheSecretKey sec;
+ sheSecretKeySetByCSPRNG(&sec);
+ shePublicKey pub;
+ sheGetPublicKey(&pub, &sec);
+
+ int64_t m1 = 12;
+ int64_t m2 = -9;
+ int64_t m3 = 12;
+ int64_t m4 = -9;
+ int64_t dec;
+ sheCipherTextG1 c11, c12;
+ sheCipherTextG2 c21, c22;
+ sheCipherTextGT ct;
+
+ sheEncG1(&c11, &pub, m1);
+ sheNegG1(&c12, &c11);
+ CYBOZU_TEST_EQUAL(sheDecG1(&dec, &sec, &c12), 0);
+ CYBOZU_TEST_EQUAL(dec, -m1);
+
+ sheEncG1(&c12, &pub, m2);
+ sheSubG1(&c11, &c11, &c12); // m1 - m2
+ sheMulG1(&c11, &c11, 4); // 4 * (m1 - m2)
+
+ sheEncG2(&c21, &pub, m3);
+ sheNegG2(&c22, &c21);
+ CYBOZU_TEST_EQUAL(sheDecG2(&dec, &sec, &c22), 0);
+ CYBOZU_TEST_EQUAL(dec, -m3);
+ sheEncG2(&c22, &pub, m4);
+ sheSubG2(&c21, &c21, &c22); // m3 - m4
+ sheMulG2(&c21, &c21, -5); // -5 * (m3 - m4)
+ sheMul(&ct, &c11, &c21); // -20 * (m1 - m2) * (m3 - m4)
+ sheAddGT(&ct, &ct, &ct); // -40 * (m1 - m2) * (m3 - m4)
+ sheMulGT(&ct, &ct, -4); // 160 * (m1 - m2) * (m3 - m4)
+
+ int64_t t = 160 * (m1 - m2) * (m3 - m4);
+ CYBOZU_TEST_EQUAL(sheDecGT(&dec, &sec, &ct), 0);
+ CYBOZU_TEST_EQUAL(dec, t);
+
+ sheCipherTextGT ct2;
+ sheNegGT(&ct2, &ct);
+ CYBOZU_TEST_EQUAL(sheDecGT(&dec, &sec, &ct2), 0);
+ CYBOZU_TEST_EQUAL(dec, -t);
+}
+
+CYBOZU_TEST_AUTO(rerand)
+{
+ sheSecretKey sec;
+ sheSecretKeySetByCSPRNG(&sec);
+ shePublicKey pub;
+ sheGetPublicKey(&pub, &sec);
+
+ int64_t m1 = 12;
+ int64_t m2 = -9;
+ int64_t m3 = 12;
+ sheCipherTextG1 c1;
+ sheCipherTextG2 c2;
+ sheCipherTextGT ct1, ct2;
+ sheEncG1(&c1, &pub, m1);
+ sheReRandG1(&c1, &pub);
+
+ sheEncG2(&c2, &pub, m2);
+ sheReRandG2(&c2, &pub);
+
+ sheEncGT(&ct1, &pub, m3);
+ sheReRandGT(&ct1, &pub);
+
+ sheMul(&ct2, &c1, &c2);
+ sheReRandGT(&ct2, &pub);
+ sheAddGT(&ct1, &ct1, &ct2);
+
+ int64_t dec;
+ CYBOZU_TEST_EQUAL(sheDecGT(&dec, &sec, &ct1), 0);
+ CYBOZU_TEST_EQUAL(dec, m1 * m2 + m3);
+}
+
+CYBOZU_TEST_AUTO(serialize)
+{
+ sheSecretKey sec1, sec2;
+ sheSecretKeySetByCSPRNG(&sec1);
+ shePublicKey pub1, pub2;
+ sheGetPublicKey(&pub1, &sec1);
+
+ char buf1[4096], buf2[4096];
+ size_t n1, n2;
+ size_t r, size;
+ const size_t sizeofFr = mclBn_getFrByteSize();
+ const size_t sizeofFp = mclBn_getG1ByteSize();
+
+ size = sizeofFr * 2;
+ n1 = sheSecretKeySerialize(buf1, sizeof(buf1), &sec1);
+ CYBOZU_TEST_EQUAL(n1, size);
+ r = sheSecretKeyDeserialize(&sec2, buf1, n1);
+ CYBOZU_TEST_EQUAL(r, n1);
+ n2 = sheSecretKeySerialize(buf2, sizeof(buf2), &sec2);
+ CYBOZU_TEST_EQUAL(n2, size);
+ CYBOZU_TEST_EQUAL_ARRAY(buf1, buf2, n2);
+
+ size = sizeofFp * 3;
+ n1 = shePublicKeySerialize(buf1, sizeof(buf1), &pub1);
+ CYBOZU_TEST_EQUAL(n1, size);
+ r = shePublicKeyDeserialize(&pub2, buf1, n1);
+ CYBOZU_TEST_EQUAL(r, n1);
+ n2 = shePublicKeySerialize(buf2, sizeof(buf2), &pub2);
+ CYBOZU_TEST_EQUAL(n2, size);
+ CYBOZU_TEST_EQUAL_ARRAY(buf1, buf2, n2);
+
+ int m = 123;
+ sheCipherTextG1 c11, c12;
+ sheCipherTextG2 c21, c22;
+ sheCipherTextGT ct1, ct2;
+ sheEncG1(&c11, &pub2, m);
+ sheEncG2(&c21, &pub2, m);
+ sheEncGT(&ct1, &pub2, m);
+
+ size = sizeofFp * 2;
+ n1 = sheCipherTextG1Serialize(buf1, sizeof(buf1), &c11);
+ CYBOZU_TEST_EQUAL(n1, size);
+ r = sheCipherTextG1Deserialize(&c12, buf1, n1);
+ CYBOZU_TEST_EQUAL(r, n1);
+ n2 = sheCipherTextG1Serialize(buf2, sizeof(buf2), &c12);
+ CYBOZU_TEST_EQUAL(n2, size);
+ CYBOZU_TEST_EQUAL_ARRAY(buf1, buf2, n2);
+
+ size = sizeofFp * 4;
+ n1 = sheCipherTextG2Serialize(buf1, sizeof(buf1), &c21);
+ CYBOZU_TEST_EQUAL(n1, size);
+ r = sheCipherTextG2Deserialize(&c22, buf1, n1);
+ CYBOZU_TEST_EQUAL(r, n1);
+ n2 = sheCipherTextG2Serialize(buf2, sizeof(buf2), &c22);
+ CYBOZU_TEST_EQUAL(n2, size);
+ CYBOZU_TEST_EQUAL_ARRAY(buf1, buf2, n2);
+
+ size = sizeofFp * 12 * 4;
+ n1 = sheCipherTextGTSerialize(buf1, sizeof(buf1), &ct1);
+ CYBOZU_TEST_EQUAL(n1, size);
+ r = sheCipherTextGTDeserialize(&ct2, buf1, n1);
+ CYBOZU_TEST_EQUAL(r, n1);
+ n2 = sheCipherTextGTSerialize(buf2, sizeof(buf2), &ct2);
+ CYBOZU_TEST_EQUAL(n2, size);
+ CYBOZU_TEST_EQUAL_ARRAY(buf1, buf2, n2);
+}
+
+CYBOZU_TEST_AUTO(convert)
+{
+ sheSecretKey sec;
+ sheSecretKeySetByCSPRNG(&sec);
+ shePublicKey pub;
+ sheGetPublicKey(&pub, &sec);
+ sheCipherTextGT ct;
+ const int64_t m = 123;
+ int64_t dec;
+ sheCipherTextG1 c1;
+ sheEncG1(&c1, &pub, m);
+ CYBOZU_TEST_EQUAL(sheDecG1(&dec, &sec, &c1), 0);
+ CYBOZU_TEST_EQUAL(dec, 123);
+ sheConvertG1(&ct, &pub, &c1);
+ dec = 0;
+ CYBOZU_TEST_EQUAL(sheDecGT(&dec, &sec, &ct), 0);
+ CYBOZU_TEST_EQUAL(dec, 123);
+
+ sheCipherTextG2 c2;
+ sheEncG2(&c2, &pub, m);
+ CYBOZU_TEST_EQUAL(sheDecG2(&dec, &sec, &c2), 0);
+ CYBOZU_TEST_EQUAL(dec, 123);
+ sheConvertG2(&ct, &pub, &c2);
+ dec = 0;
+ CYBOZU_TEST_EQUAL(sheDecGT(&dec, &sec, &ct), 0);
+ CYBOZU_TEST_EQUAL(dec, 123);
+}
+
+CYBOZU_TEST_AUTO(precomputed)
+{
+ sheSecretKey sec;
+ sheSecretKeySetByCSPRNG(&sec);
+ shePublicKey pub;
+ sheGetPublicKey(&pub, &sec);
+ shePrecomputedPublicKey *ppub = shePrecomputedPublicKeyCreate();
+ CYBOZU_TEST_EQUAL(shePrecomputedPublicKeyInit(ppub, &pub), 0);
+ const int64_t m = 152;
+ sheCipherTextG1 c1;
+ sheCipherTextG2 c2;
+ sheCipherTextGT ct;
+ int64_t dec = 0;
+ CYBOZU_TEST_EQUAL(shePrecomputedPublicKeyEncG1(&c1, ppub, m), 0);
+ CYBOZU_TEST_EQUAL(sheDecG1(&dec, &sec, &c1), 0);
+ CYBOZU_TEST_EQUAL(dec, m);
+ dec = 0;
+ CYBOZU_TEST_EQUAL(shePrecomputedPublicKeyEncG2(&c2, ppub, m), 0);
+ CYBOZU_TEST_EQUAL(sheDecG2(&dec, &sec, &c2), 0);
+ CYBOZU_TEST_EQUAL(dec, m);
+ dec = 0;
+ CYBOZU_TEST_EQUAL(shePrecomputedPublicKeyEncGT(&ct, ppub, m), 0);
+ CYBOZU_TEST_EQUAL(sheDecGT(&dec, &sec, &ct), 0);
+ CYBOZU_TEST_EQUAL(dec, m);
+
+ shePrecomputedPublicKeyDestroy(ppub);
+}
+
+template<class CT, class PK, class encWithZkpFunc, class decFunc, class verifyFunc>
+void ZkpBinTest(const sheSecretKey *sec, const PK *pub, encWithZkpFunc encWithZkp, decFunc dec, verifyFunc verify)
+{
+ CT c;
+ sheZkpBin zkp;
+ for (int m = 0; m < 2; m++) {
+ CYBOZU_TEST_EQUAL(encWithZkp(&c, &zkp, pub, m), 0);
+ mclInt mDec;
+ CYBOZU_TEST_EQUAL(dec(&mDec, sec, &c), 0);
+ CYBOZU_TEST_EQUAL(mDec, m);
+ CYBOZU_TEST_EQUAL(verify(pub, &c, &zkp), 1);
+ {
+ char buf[4096];
+ size_t n = sheZkpBinSerialize(buf, sizeof(buf), &zkp);
+ CYBOZU_TEST_EQUAL(n, mclBn_getFrByteSize() * CYBOZU_NUM_OF_ARRAY(zkp.d));
+ sheZkpBin zkp2;
+ size_t r = sheZkpBinDeserialize(&zkp2, buf, n);
+ CYBOZU_TEST_EQUAL(r, n);
+ CYBOZU_TEST_EQUAL(r, n);
+ for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(zkp.d); i++) {
+ CYBOZU_TEST_ASSERT(mclBnFr_isEqual(&zkp.d[i], &zkp2.d[i]));
+ }
+ }
+ zkp.d[0].d[0]++;
+ CYBOZU_TEST_EQUAL(verify(pub, &c, &zkp), 0);
+ }
+ CYBOZU_TEST_ASSERT(encWithZkp(&c, &zkp, pub, 2) != 0);
+}
+
+CYBOZU_TEST_AUTO(ZkpBin)
+{
+ sheSecretKey sec;
+ sheSecretKeySetByCSPRNG(&sec);
+ shePublicKey pub;
+ sheGetPublicKey(&pub, &sec);
+
+ ZkpBinTest<sheCipherTextG1>(&sec, &pub, sheEncWithZkpBinG1, sheDecG1, sheVerifyZkpBinG1);
+ ZkpBinTest<sheCipherTextG2>(&sec, &pub, sheEncWithZkpBinG2, sheDecG2, sheVerifyZkpBinG2);
+
+ shePrecomputedPublicKey *ppub = shePrecomputedPublicKeyCreate();
+ CYBOZU_TEST_EQUAL(shePrecomputedPublicKeyInit(ppub, &pub), 0);
+
+ ZkpBinTest<sheCipherTextG1>(&sec, ppub, shePrecomputedPublicKeyEncWithZkpBinG1, sheDecG1, shePrecomputedPublicKeyVerifyZkpBinG1);
+ ZkpBinTest<sheCipherTextG2>(&sec, ppub, shePrecomputedPublicKeyEncWithZkpBinG2, sheDecG2, shePrecomputedPublicKeyVerifyZkpBinG2);
+
+ shePrecomputedPublicKeyDestroy(ppub);
+}
+
+template<class PK, class encWithZkpFunc, class verifyFunc>
+void ZkpBinEqTest(const sheSecretKey *sec, const PK *pub, encWithZkpFunc encWithZkp, verifyFunc verify)
+{
+ sheCipherTextG1 c1;
+ sheCipherTextG2 c2;
+ sheZkpBinEq zkp;
+ for (int m = 0; m < 2; m++) {
+ CYBOZU_TEST_EQUAL(encWithZkp(&c1, &c2, &zkp, pub, m), 0);
+ mclInt mDec = -1;
+ CYBOZU_TEST_EQUAL(sheDecG1(&mDec, sec, &c1), 0);
+ CYBOZU_TEST_EQUAL(mDec, m);
+ mDec = -1;
+ CYBOZU_TEST_EQUAL(sheDecG2(&mDec, sec, &c2), 0);
+ CYBOZU_TEST_EQUAL(mDec, m);
+ CYBOZU_TEST_EQUAL(verify(pub, &c1, &c2, &zkp), 1);
+ {
+ char buf[2048];
+ size_t n = sheZkpBinEqSerialize(buf, sizeof(buf), &zkp);
+ CYBOZU_TEST_EQUAL(n, mclBn_getFrByteSize() * CYBOZU_NUM_OF_ARRAY(zkp.d));
+ sheZkpBinEq zkp2;
+ size_t r = sheZkpBinEqDeserialize(&zkp2, buf, n);
+ CYBOZU_TEST_EQUAL(r, n);
+ for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(zkp.d); i++) {
+ CYBOZU_TEST_ASSERT(mclBnFr_isEqual(&zkp.d[i], &zkp2.d[i]));
+ }
+ }
+ zkp.d[0].d[0]++;
+ CYBOZU_TEST_EQUAL(verify(pub, &c1, &c2, &zkp), 0);
+ }
+ CYBOZU_TEST_ASSERT(encWithZkp(&c1, &c2, &zkp, pub, 2) != 0);
+}
+
+CYBOZU_TEST_AUTO(ZkpBinEq)
+{
+ sheSecretKey sec;
+ sheSecretKeySetByCSPRNG(&sec);
+ shePublicKey pub;
+ sheGetPublicKey(&pub, &sec);
+
+ ZkpBinEqTest(&sec, &pub, sheEncWithZkpBinEq, sheVerifyZkpBinEq);
+
+ shePrecomputedPublicKey *ppub = shePrecomputedPublicKeyCreate();
+ CYBOZU_TEST_EQUAL(shePrecomputedPublicKeyInit(ppub, &pub), 0);
+
+ ZkpBinEqTest(&sec, ppub, shePrecomputedPublicKeyEncWithZkpBinEq, shePrecomputedPublicKeyVerifyZkpBinEq);
+
+ shePrecomputedPublicKeyDestroy(ppub);
+}
+
+template<class PK, class encWithZkpFunc, class verifyFunc>
+void ZkpEqTest(const sheSecretKey *sec, const PK *pub, encWithZkpFunc encWithZkp, verifyFunc verify)
+{
+ sheCipherTextG1 c1;
+ sheCipherTextG2 c2;
+ sheZkpEq zkp;
+ for (int m = -5; m < 5; m++) {
+ CYBOZU_TEST_EQUAL(encWithZkp(&c1, &c2, &zkp, pub, m), 0);
+ mclInt mDec = -1;
+ CYBOZU_TEST_EQUAL(sheDecG1(&mDec, sec, &c1), 0);
+ CYBOZU_TEST_EQUAL(mDec, m);
+ mDec = -1;
+ CYBOZU_TEST_EQUAL(sheDecG2(&mDec, sec, &c2), 0);
+ CYBOZU_TEST_EQUAL(mDec, m);
+ CYBOZU_TEST_EQUAL(verify(pub, &c1, &c2, &zkp), 1);
+ {
+ char buf[2048];
+ size_t n = sheZkpEqSerialize(buf, sizeof(buf), &zkp);
+ CYBOZU_TEST_EQUAL(n, mclBn_getFrByteSize() * CYBOZU_NUM_OF_ARRAY(zkp.d));
+ sheZkpEq zkp2;
+ size_t r = sheZkpEqDeserialize(&zkp2, buf, n);
+ CYBOZU_TEST_EQUAL(r, n);
+ for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(zkp.d); i++) {
+ CYBOZU_TEST_ASSERT(mclBnFr_isEqual(&zkp.d[i], &zkp2.d[i]));
+ }
+ }
+ zkp.d[0].d[0]++;
+ CYBOZU_TEST_EQUAL(verify(pub, &c1, &c2, &zkp), 0);
+ }
+}
+
+CYBOZU_TEST_AUTO(ZkpEq)
+{
+ sheSecretKey sec;
+ sheSecretKeySetByCSPRNG(&sec);
+ shePublicKey pub;
+ sheGetPublicKey(&pub, &sec);
+
+ ZkpEqTest(&sec, &pub, sheEncWithZkpEq, sheVerifyZkpEq);
+
+ shePrecomputedPublicKey *ppub = shePrecomputedPublicKeyCreate();
+ CYBOZU_TEST_EQUAL(shePrecomputedPublicKeyInit(ppub, &pub), 0);
+
+ ZkpEqTest(&sec, ppub, shePrecomputedPublicKeyEncWithZkpEq, shePrecomputedPublicKeyVerifyZkpEq);
+
+ shePrecomputedPublicKeyDestroy(ppub);
+}
+
+CYBOZU_TEST_AUTO(finalExp)
+{
+ sheSecretKey sec;
+ sheSecretKeySetByCSPRNG(&sec);
+ shePublicKey pub;
+ sheGetPublicKey(&pub, &sec);
+ const int64_t m11 = 5;
+ const int64_t m12 = 7;
+ const int64_t m21 = -3;
+ const int64_t m22 = 9;
+ sheCipherTextG1 c11, c12;
+ sheCipherTextG2 c21, c22;
+ sheCipherTextGT ct1, ct2;
+ sheCipherTextGT ct;
+ sheEncG1(&c11, &pub, m11);
+ sheEncG1(&c12, &pub, m12);
+ sheEncG2(&c21, &pub, m21);
+ sheEncG2(&c22, &pub, m22);
+
+ int64_t dec;
+ // sheMul = sheMulML + sheFinalExpGT
+ sheMul(&ct1, &c11, &c21);
+ CYBOZU_TEST_EQUAL(sheDecGT(&dec, &sec, &ct1), 0);
+ CYBOZU_TEST_EQUAL(dec, m11 * m21);
+
+ sheMulML(&ct1, &c11, &c21);
+ sheFinalExpGT(&ct, &ct1);
+ CYBOZU_TEST_EQUAL(sheDecGT(&dec, &sec, &ct), 0);
+ CYBOZU_TEST_EQUAL(dec, m11 * m21);
+
+ sheMulML(&ct2, &c12, &c22);
+ sheFinalExpGT(&ct, &ct2);
+ CYBOZU_TEST_EQUAL(sheDecGT(&dec, &sec, &ct), 0);
+ CYBOZU_TEST_EQUAL(dec, m12 * m22);
+
+ /*
+ Mul(c11, c21) + Mul(c21, c22)
+ = finalExp(ML(c11, c21) + ML(c21, c22))
+ */
+ sheAddGT(&ct, &ct1, &ct2);
+ sheFinalExpGT(&ct, &ct);
+ CYBOZU_TEST_EQUAL(sheDecGT(&dec, &sec, &ct), 0);
+ CYBOZU_TEST_EQUAL(dec, (m11 * m21) + (m12 * m22));
+}
+
+int g_hashBitSize = 8;
+std::string g_tableName;
+
+CYBOZU_TEST_AUTO(saveLoad)
+{
+ sheSecretKey sec;
+ sheSecretKeySetByCSPRNG(&sec);
+ shePublicKey pub;
+ sheGetPublicKey(&pub, &sec);
+ const size_t hashSize = 1 << g_hashBitSize;
+ const size_t byteSizePerEntry = 8;
+ sheSetRangeForGTDLP(hashSize);
+ std::string buf;
+ buf.resize(hashSize * byteSizePerEntry + 1024);
+ const size_t n1 = sheSaveTableForGTDLP(&buf[0], buf.size());
+ CYBOZU_TEST_ASSERT(n1 > 0);
+ if (!g_tableName.empty()) {
+ printf("use table=%s\n", g_tableName.c_str());
+ std::ofstream ofs(g_tableName.c_str(), std::ios::binary);
+ ofs.write(buf.c_str(), n1);
+ }
+ const int64_t m = hashSize - 1;
+ sheCipherTextGT ct;
+ CYBOZU_TEST_ASSERT(sheEncGT(&ct, &pub, m) == 0);
+ sheSetRangeForGTDLP(1);
+ sheSetTryNum(1);
+ int64_t dec = 0;
+ CYBOZU_TEST_ASSERT(sheDecGT(&dec, &sec, &ct) != 0);
+ if (!g_tableName.empty()) {
+ std::ifstream ifs(g_tableName.c_str(), std::ios::binary);
+ buf.clear();
+ buf.resize(n1);
+ ifs.read(&buf[0], n1);
+ }
+ const size_t n2 = sheLoadTableForGTDLP(&buf[0], n1);
+ CYBOZU_TEST_ASSERT(n2 > 0);
+ CYBOZU_TEST_ASSERT(sheDecGT(&dec, &sec, &ct) == 0);
+ CYBOZU_TEST_EQUAL(dec, m);
+}
+
+int main(int argc, char *argv[])
+ try
+{
+ cybozu::Option opt;
+ opt.appendOpt(&g_hashBitSize, 8, "bit", ": hashBitSize");
+ opt.appendOpt(&g_tableName, "", "f", ": table name");
+ opt.appendHelp("h", ": show this message");
+ if (!opt.parse(argc, argv)) {
+ opt.usage();
+ return 1;
+ }
+ return cybozu::test::autoRun.run(argc, argv);
+} catch (std::exception& e) {
+ printf("ERR %s\n", e.what());
+ return 1;
+}
diff --git a/vendor/github.com/tangerine-network/mcl/test/she_test.cpp b/vendor/github.com/tangerine-network/mcl/test/she_test.cpp
new file mode 100644
index 000000000..9292c35f4
--- /dev/null
+++ b/vendor/github.com/tangerine-network/mcl/test/she_test.cpp
@@ -0,0 +1,756 @@
+#define PUT(x) std::cout << #x << "=" << (x) << std::endl;
+#include <cybozu/test.hpp>
+#include <cybozu/benchmark.hpp>
+#include <cybozu/xorshift.hpp>
+#include <fstream>
+#include <time.h>
+#include <mcl/she.hpp>
+#include <mcl/ecparam.hpp> // for secp192k1
+
+using namespace mcl::she;
+
+SecretKey g_sec;
+
+CYBOZU_TEST_AUTO(log)
+{
+#if MCLBN_FP_UNIT_SIZE == 4
+ const mcl::CurveParam& cp = mcl::BN254;
+ puts("BN254");
+#elif MCLBN_FP_UNIT_SIZE == 6
+ const mcl::CurveParam& cp = mcl::BN381_1;
+ puts("BN381_1");
+#elif MCLBN_FP_UNIT_SIZE == 8
+ const mcl::CurveParam& cp = mcl::BN462;
+ puts("BN462");
+#endif
+ init(cp);
+ G1 P;
+ hashAndMapToG1(P, "abc");
+ for (int i = -5; i < 5; i++) {
+ G1 iP;
+ G1::mul(iP, P, i);
+ CYBOZU_TEST_EQUAL(mcl::she::local::log(P, iP), i);
+ }
+}
+
+//#define PAPER
+#ifdef PAPER
+double clk2msec(const cybozu::CpuClock& clk, int n)
+{
+ const double rate = (1 / 3.4e9) * 1.e3; // 3.4GHz
+ return clk.getClock() / (double)clk.getCount() / n * rate;
+}
+
+CYBOZU_TEST_AUTO(bench2)
+{
+ puts("msec");
+ setTryNum(1 << 16);
+ useDecG1ViaGT(true);
+ useDecG2ViaGT(true);
+#if 0
+ setRangeForDLP(1 << 21);
+#else
+ {
+ const char *tblName = "../she-dlp-table/she-dlp-0-20-gt.bin";
+ std::ifstream ifs(tblName, std::ios::binary);
+ getHashTableGT().load(ifs);
+ }
+#endif
+ SecretKey sec;
+ sec.setByCSPRNG();
+ PublicKey pub;
+ sec.getPublicKey(pub);
+ PrecomputedPublicKey ppub;
+ ppub.init(pub);
+ const int C = 500;
+ double t1, t2;
+ int64_t m = (1ll << 31) - 12345;
+ CipherTextG1 c1, d1;
+ CipherTextG2 c2, d2;
+ CipherTextGT ct, dt;
+ CYBOZU_BENCH_C("", C, ppub.enc, c1, m);
+ t1 = clk2msec(cybozu::bench::g_clk, C);
+ CYBOZU_TEST_EQUAL(sec.dec(c1), m);
+
+ CYBOZU_BENCH_C("", C, ppub.enc, c2, m);
+ t2 = clk2msec(cybozu::bench::g_clk, C);
+ CYBOZU_TEST_EQUAL(sec.dec(c2), m);
+ printf("Enc G1 %.2e\n", t1);
+ printf("Enc G2 %.2e\n", t2);
+ printf("Enc L1(G1+G2) %.2e\n", t1 + t2);
+
+ CYBOZU_BENCH_C("", C, ppub.enc, ct, m);
+ t1 = clk2msec(cybozu::bench::g_clk, C);
+ CYBOZU_TEST_EQUAL(sec.dec(ct), m);
+ printf("Enc L2 %.2e\n", t1);
+
+ CYBOZU_BENCH_C("", C, sec.dec, c1);
+ t1 = clk2msec(cybozu::bench::g_clk, C);
+ printf("Dec L1 %.2e\n", t1);
+
+ CYBOZU_BENCH_C("", C, sec.dec, ct);
+ t1 = clk2msec(cybozu::bench::g_clk, C);
+ printf("Dec L2 %.2e\n", t1);
+
+ pub.enc(ct, 1234);
+ CYBOZU_BENCH_C("", C, sec.dec, ct);
+ t1 = clk2msec(cybozu::bench::g_clk, C);
+ printf("Dec L2(small) %.2e\n", t1);
+
+ CYBOZU_BENCH_C("", C, add, d1, d1, c1);
+ t1 = clk2msec(cybozu::bench::g_clk, C);
+
+ CYBOZU_BENCH_C("", C, add, d2, d2, c2);
+ t2 = clk2msec(cybozu::bench::g_clk, C);
+ printf("Add G1 %.2e\n", t1);
+ printf("Add G2 %.2e\n", t2);
+ printf("Add L1(G1+G2) %.2e\n", t1 + t2);
+
+ CYBOZU_BENCH_C("", C, add, dt, dt, ct);
+ t1 = clk2msec(cybozu::bench::g_clk, C);
+ printf("Add L2 %.2e\n", t1);
+
+ CYBOZU_BENCH_C("", C, mul, ct, c1, c2);
+ t1 = clk2msec(cybozu::bench::g_clk, C);
+ printf("Mul %.2e\n", t1);
+
+ CYBOZU_BENCH_C("", C, ppub.reRand, c1);
+ t1 = clk2msec(cybozu::bench::g_clk, C);
+ CYBOZU_BENCH_C("", C, ppub.reRand, c2);
+ t2 = clk2msec(cybozu::bench::g_clk, C);
+ printf("ReRand G1 %.2e\n", t1);
+ printf("ReRand G2 %.2e\n", t2);
+ printf("ReRand L1(G1+G2) %.2e\n", t1 + t2);
+
+ CYBOZU_BENCH_C("", C, ppub.reRand, ct);
+ t1 = clk2msec(cybozu::bench::g_clk, C);
+ printf("ReRand L2 %.2e\n", t1);
+}
+#endif
+
+template<class G, class HashTbl>
+void GAHashTableTest(int maxSize, int tryNum, const G& P, const HashTbl& hashTbl)
+{
+ for (int i = -maxSize; i <= maxSize; i++) {
+ G xP;
+ G::mul(xP, P, i);
+ CYBOZU_TEST_EQUAL(hashTbl.basicLog(xP), i);
+ }
+ for (int i = -maxSize * tryNum; i <= maxSize * tryNum; i++) {
+ G xP;
+ G::mul(xP, P, i);
+ CYBOZU_TEST_EQUAL(hashTbl.log(xP), i);
+ }
+}
+
+template<class G>
+void HashTableTest(const G& P)
+{
+ mcl::she::local::HashTable<G> hashTbl, hashTbl2;
+ const int maxSize = 100;
+ const int tryNum = 3;
+ hashTbl.init(P, maxSize, tryNum);
+ GAHashTableTest(maxSize, tryNum, P, hashTbl);
+ std::stringstream ss;
+ hashTbl.save(ss);
+ hashTbl2.load(ss);
+ GAHashTableTest(maxSize, tryNum, P, hashTbl2);
+}
+
+CYBOZU_TEST_AUTO(HashTable)
+{
+ G1 P;
+ hashAndMapToG1(P, "abc");
+ G2 Q;
+ hashAndMapToG2(Q, "abc");
+ HashTableTest(P);
+ HashTableTest(Q);
+}
+
+template<class HashTbl>
+void GTHashTableTest(int maxSize, int tryNum, const GT& g, const HashTbl& hashTbl)
+{
+ for (int i = -maxSize; i <= maxSize; i++) {
+ GT gx;
+ GT::pow(gx, g, i);
+ CYBOZU_TEST_EQUAL(hashTbl.basicLog(gx), i);
+ }
+ for (int i = -maxSize * tryNum; i <= maxSize * tryNum; i++) {
+ GT gx;
+ GT::pow(gx, g, i);
+ CYBOZU_TEST_EQUAL(hashTbl.log(gx), i);
+ }
+}
+
+CYBOZU_TEST_AUTO(GTHashTable)
+{
+ mcl::she::local::HashTable<GT, false> hashTbl, hashTbl2;
+ GT g;
+ {
+ G1 P;
+ hashAndMapToG1(P, "abc");
+ G2 Q;
+ hashAndMapToG2(Q, "abc");
+ pairing(g, P, Q);
+ }
+ const int maxSize = 100;
+ const int tryNum = 3;
+ hashTbl.init(g, maxSize, tryNum);
+ GTHashTableTest(maxSize, tryNum, g, hashTbl);
+ std::stringstream ss;
+ hashTbl.save(ss);
+ hashTbl2.load(ss);
+ GTHashTableTest(maxSize, tryNum, g, hashTbl2);
+}
+
+CYBOZU_TEST_AUTO(enc_dec)
+{
+ SecretKey& sec = g_sec;
+ sec.setByCSPRNG();
+ setRangeForDLP(1024);
+ PublicKey pub;
+ sec.getPublicKey(pub);
+ CipherText c;
+ for (int i = -5; i < 5; i++) {
+ pub.enc(c, i);
+ CYBOZU_TEST_EQUAL(sec.dec(c), i);
+ pub.reRand(c);
+ CYBOZU_TEST_EQUAL(sec.dec(c), i);
+ }
+ PrecomputedPublicKey ppub;
+ ppub.init(pub);
+ CipherTextG1 c1;
+ CipherTextG2 c2;
+ CipherTextGT ct1, ct2;
+ for (int i = -5; i < 5; i++) {
+ pub.enc(ct1, i);
+ CYBOZU_TEST_EQUAL(sec.dec(ct1), i);
+ CYBOZU_TEST_EQUAL(sec.isZero(ct1), i == 0);
+ ppub.enc(ct2, i);
+ CYBOZU_TEST_EQUAL(sec.dec(ct2), i);
+ ppub.enc(c1, i);
+ CYBOZU_TEST_EQUAL(sec.dec(c1), i);
+ CYBOZU_TEST_EQUAL(sec.decViaGT(c1), i);
+ CYBOZU_TEST_EQUAL(sec.isZero(c1), i == 0);
+ ct1.clear();
+ pub.convert(ct1, c1);
+ CYBOZU_TEST_EQUAL(sec.dec(ct1), i);
+ ppub.enc(c2, i);
+ CYBOZU_TEST_EQUAL(sec.dec(c2), i);
+ CYBOZU_TEST_EQUAL(sec.decViaGT(c2), i);
+ CYBOZU_TEST_EQUAL(sec.isZero(c2), i == 0);
+ ct1.clear();
+ pub.convert(ct1, c2);
+ CYBOZU_TEST_EQUAL(sec.dec(ct1), i);
+ pub.enc(c, i);
+ CYBOZU_TEST_EQUAL(sec.isZero(c), i == 0);
+ }
+}
+
+template<class CT, class PK>
+void ZkpBinTest(const SecretKey& sec, const PK& pub)
+{
+ CT c;
+ ZkpBin zkp;
+ for (int m = 0; m < 2; m++) {
+ pub.encWithZkpBin(c, zkp, m);
+ CYBOZU_TEST_EQUAL(sec.dec(c), m);
+ CYBOZU_TEST_ASSERT(pub.verify(c, zkp));
+ zkp.d_[0] += 1;
+ CYBOZU_TEST_ASSERT(!pub.verify(c, zkp));
+ }
+ CYBOZU_TEST_EXCEPTION(pub.encWithZkpBin(c, zkp, 2), cybozu::Exception);
+}
+CYBOZU_TEST_AUTO(ZkpBin)
+{
+ const SecretKey& sec = g_sec;
+ PublicKey pub;
+ sec.getPublicKey(pub);
+ ZkpBinTest<CipherTextG1>(sec, pub);
+ ZkpBinTest<CipherTextG2>(sec, pub);
+
+ PrecomputedPublicKey ppub;
+ ppub.init(pub);
+ ZkpBinTest<CipherTextG1>(sec, ppub);
+ ZkpBinTest<CipherTextG2>(sec, ppub);
+}
+
+template<class PubT>
+void ZkpEqTest(const SecretKey& sec, const PubT& pub)
+{
+ CipherTextG1 c1;
+ CipherTextG2 c2;
+ ZkpEq zkp;
+ for (int m = -4; m < 4; m++) {
+ pub.encWithZkpEq(c1, c2, zkp, m);
+ CYBOZU_TEST_EQUAL(sec.dec(c1), m);
+ CYBOZU_TEST_EQUAL(sec.dec(c2), m);
+ CYBOZU_TEST_ASSERT(pub.verify(c1, c2, zkp));
+ zkp.d_[0] += 1;
+ CYBOZU_TEST_ASSERT(!pub.verify(c1, c2, zkp));
+ }
+}
+
+CYBOZU_TEST_AUTO(ZkpEq)
+{
+ const SecretKey& sec = g_sec;
+ PublicKey pub;
+ sec.getPublicKey(pub);
+ PrecomputedPublicKey ppub;
+ ppub.init(pub);
+ ZkpEqTest(sec, pub);
+ ZkpEqTest(sec, ppub);
+}
+
+template<class PK>
+void ZkpBinEqTest(const SecretKey& sec, const PK& pub)
+{
+ CipherTextG1 c1;
+ CipherTextG2 c2;
+ ZkpBinEq zkp;
+ for (int m = 0; m < 2; m++) {
+ pub.encWithZkpBinEq(c1, c2, zkp, m);
+ CYBOZU_TEST_EQUAL(sec.dec(c1), m);
+ CYBOZU_TEST_EQUAL(sec.dec(c2), m);
+ CYBOZU_TEST_ASSERT(pub.verify(c1, c2, zkp));
+ zkp.d_[0] += 1;
+ CYBOZU_TEST_ASSERT(!pub.verify(c1, c2, zkp));
+ }
+ CYBOZU_TEST_EXCEPTION(pub.encWithZkpBinEq(c1, c2, zkp, 2), cybozu::Exception);
+}
+
+CYBOZU_TEST_AUTO(ZkpBinEq)
+{
+ const SecretKey& sec = g_sec;
+ PublicKey pub;
+ sec.getPublicKey(pub);
+ ZkpBinEqTest(sec, pub);
+
+ PrecomputedPublicKey ppub;
+ ppub.init(pub);
+ ZkpBinEqTest(sec, ppub);
+}
+
+CYBOZU_TEST_AUTO(add_sub_mul)
+{
+ const SecretKey& sec = g_sec;
+ PublicKey pub;
+ sec.getPublicKey(pub);
+ for (int m1 = -5; m1 < 5; m1++) {
+ for (int m2 = -5; m2 < 5; m2++) {
+ CipherText c1, c2, c3;
+ pub.enc(c1, m1);
+ pub.enc(c2, m2);
+ add(c3, c1, c2);
+ CYBOZU_TEST_EQUAL(m1 + m2, sec.dec(c3));
+
+ pub.reRand(c3);
+ CYBOZU_TEST_EQUAL(m1 + m2, sec.dec(c3));
+
+ sub(c3, c1, c2);
+ CYBOZU_TEST_EQUAL(m1 - m2, sec.dec(c3));
+
+ mul(c3, c1, 5);
+ CYBOZU_TEST_EQUAL(m1 * 5, sec.dec(c3));
+ mul(c3, c1, -123);
+ CYBOZU_TEST_EQUAL(m1 * -123, sec.dec(c3));
+
+ mul(c3, c1, c2);
+ CYBOZU_TEST_EQUAL(m1 * m2, sec.dec(c3));
+
+ pub.reRand(c3);
+ CYBOZU_TEST_EQUAL(m1 * m2, sec.dec(c3));
+
+ CipherText::mul(c3, c3, -25);
+ CYBOZU_TEST_EQUAL(m1 * m2 * -25, sec.dec(c3));
+
+ pub.enc(c1, m1, true);
+ CYBOZU_TEST_EQUAL(m1, sec.dec(c1));
+ pub.enc(c2, m2, true);
+ add(c3, c1, c2);
+ CYBOZU_TEST_EQUAL(m1 + m2, sec.dec(c3));
+ }
+ }
+}
+
+CYBOZU_TEST_AUTO(largeEnc)
+{
+ const SecretKey& sec = g_sec;
+ PublicKey pub;
+ sec.getPublicKey(pub);
+
+ Fr x;
+ x.setRand();
+ CipherTextG1 c1, c2;
+ pub.enc(c1, x);
+ const int64_t m = 123;
+ pub.enc(c2, x + m);
+ sub(c1, c1, c2);
+ CYBOZU_TEST_EQUAL(sec.dec(c1), -m);
+
+ pub.enc(c1, 0);
+ mul(c1, c1, x);
+ CYBOZU_TEST_ASSERT(sec.isZero(c1));
+ pub.enc(c1, 1);
+ mul(c1, c1, x);
+ CYBOZU_TEST_ASSERT(!sec.isZero(c1));
+}
+
+CYBOZU_TEST_AUTO(add_mul_add_sub)
+{
+ const SecretKey& sec = g_sec;
+ PublicKey pub;
+ sec.getPublicKey(pub);
+ int m[8] = { 1, -2, 3, 4, -5, 6, -7, 8 };
+ CipherText c[8];
+ for (int i = 0; i < 8; i++) {
+ pub.enc(c[i], m[i]);
+ CYBOZU_TEST_EQUAL(sec.dec(c[i]), m[i]);
+ CYBOZU_TEST_ASSERT(!c[i].isMultiplied());
+ CipherText mc;
+ pub.convert(mc, c[i]);
+ CYBOZU_TEST_ASSERT(mc.isMultiplied());
+ CYBOZU_TEST_EQUAL(sec.dec(mc), m[i]);
+ }
+ int ok1 = (m[0] + m[1]) * (m[2] + m[3]);
+ int ok2 = (m[4] + m[5]) * (m[6] + m[7]);
+ int ok = ok1 + ok2;
+ for (int i = 0; i < 4; i++) {
+ c[i * 2].add(c[i * 2 + 1]);
+ CYBOZU_TEST_EQUAL(sec.dec(c[i * 2]), m[i * 2] + m[i * 2 + 1]);
+ }
+ c[0].mul(c[2]);
+ CYBOZU_TEST_EQUAL(sec.dec(c[0]), ok1);
+ c[4].mul(c[6]);
+ CYBOZU_TEST_EQUAL(sec.dec(c[4]), ok2);
+ c[0].add(c[4]);
+ CYBOZU_TEST_EQUAL(sec.dec(c[0]), ok);
+ c[0].sub(c[4]);
+ CYBOZU_TEST_EQUAL(sec.dec(c[0]), ok1);
+}
+
+CYBOZU_TEST_AUTO(finalExp)
+{
+ const SecretKey& sec = g_sec;
+ PublicKey pub;
+ sec.getPublicKey(pub);
+ const int64_t m11 = 5;
+ const int64_t m12 = 3;
+ const int64_t m21 = -2;
+ const int64_t m22 = 9;
+ CipherTextG1 c11, c12;
+ CipherTextG2 c21, c22;
+ CipherTextGT ct1, ct2, ct;
+ pub.enc(c11, m11);
+ pub.enc(c12, m12);
+ pub.enc(c21, m21);
+ pub.enc(c22, m22);
+ CipherTextGT::mulML(ct1, c11, c21);
+ CipherTextGT::finalExp(ct, ct1);
+ CYBOZU_TEST_EQUAL(sec.dec(ct), m11 * m21);
+ CipherTextGT::mulML(ct2, c12, c22);
+ CipherTextGT::finalExp(ct, ct2);
+ CYBOZU_TEST_EQUAL(sec.dec(ct), m12 * m22);
+ CipherTextGT::add(ct1, ct1, ct2);
+ CipherTextGT::finalExp(ct1, ct1);
+ CYBOZU_TEST_EQUAL(sec.dec(ct1), (m11 * m21) + (m12 * m22));
+}
+
+CYBOZU_TEST_AUTO(innerProduct)
+{
+ const SecretKey& sec = g_sec;
+ PublicKey pub;
+ sec.getPublicKey(pub);
+
+ cybozu::XorShift rg;
+ const size_t n = 1000;
+ std::vector<int> v1, v2;
+ std::vector<CipherText> c1, c2;
+ v1.resize(n);
+ v2.resize(n);
+ c1.resize(n);
+ c2.resize(n);
+ int innerProduct = 0;
+ for (size_t i = 0; i < n; i++) {
+ v1[i] = rg() % 2;
+ v2[i] = rg() % 2;
+ innerProduct += v1[i] * v2[i];
+ pub.enc(c1[i], v1[i]);
+ pub.enc(c2[i], v2[i]);
+ }
+ CipherText c, t;
+ CipherText::mul(c, c1[0], c2[0]);
+ for (size_t i = 1; i < n; i++) {
+ CipherText::mul(t, c1[i], c2[i]);
+ c.add(t);
+ }
+ CYBOZU_TEST_EQUAL(innerProduct, sec.dec(c));
+}
+
+template<class T>
+T testIo(const T& x)
+{
+ std::stringstream ss;
+ ss << x;
+ T y;
+ ss >> y;
+ CYBOZU_TEST_EQUAL(x, y);
+ return y;
+}
+
+CYBOZU_TEST_AUTO(io)
+{
+ setRangeForDLP(100);
+ int64_t m;
+ for (int i = 0; i < 2; i++) {
+ if (i == 1) {
+ Fp::setIoMode(mcl::IoSerialize);
+ G1::setIoMode(mcl::IoSerialize);
+ }
+ SecretKey sec;
+ sec.setByCSPRNG();
+ testIo(sec);
+ PublicKey pub;
+ sec.getPublicKey(pub);
+ testIo(pub);
+ CipherTextG1 g1;
+ pub.enc(g1, 3);
+ m = sec.dec(testIo(g1));
+ CYBOZU_TEST_EQUAL(m, 3);
+ CipherTextG2 g2;
+ pub.enc(g2, 5);
+ testIo(g2);
+ CipherTextA ca;
+ pub.enc(ca, -4);
+ m = sec.dec(testIo(ca));
+ CYBOZU_TEST_EQUAL(m, -4);
+ CipherTextGT ct;
+ CipherTextGT::mul(ct, g1, g2);
+ m = sec.dec(testIo(ct));
+ CYBOZU_TEST_EQUAL(m, 15);
+ }
+}
+
+#ifndef PAPER
+CYBOZU_TEST_AUTO(bench)
+{
+ const SecretKey& sec = g_sec;
+ PublicKey pub;
+ sec.getPublicKey(pub);
+ CipherText c1, c2, c3;
+ CYBOZU_BENCH("enc", pub.enc, c1, 5);
+ pub.enc(c2, 4);
+ CYBOZU_BENCH("add", c1.add, c2);
+ CYBOZU_BENCH("mul", CipherText::mul, c3, c1, c2);
+ pub.enc(c1, 5);
+ pub.enc(c2, 4);
+ c1.mul(c2);
+ CYBOZU_BENCH("dec", sec.dec, c1);
+ c2 = c1;
+ CYBOZU_BENCH("add after mul", c1.add, c2);
+}
+#endif
+
+CYBOZU_TEST_AUTO(saveHash)
+{
+ mcl::she::local::HashTable<G1> hashTbl1, hashTbl2;
+ hashTbl1.init(SHE::P_, 1234, 123);
+ std::stringstream ss;
+ hashTbl1.save(ss);
+ hashTbl2.load(ss);
+ CYBOZU_TEST_ASSERT(hashTbl1 == hashTbl2);
+}
+
+static inline void putK(double t) { printf("%.2e\n", t * 1e-3); }
+
+template<class CT>
+void decBench(const char *msg, int C, const SecretKey& sec, const PublicKey& pub, int64_t (SecretKey::*dec)(const CT& c) const = &SecretKey::dec)
+{
+ int64_t begin = 1 << 20;
+ int64_t end = 1LL << 32;
+ while (begin < end) {
+ CT c;
+ int64_t x = begin - 1;
+ pub.enc(c, x);
+ printf("m=%08x ", (uint32_t)x);
+ CYBOZU_BENCH_C(msg, C, (sec.*dec), c);
+ CYBOZU_TEST_EQUAL((sec.*dec)(c), x);
+ begin *= 2;
+ }
+ int64_t mTbl[] = { -0x80000003ll, 0x80000000ll, 0x80000005ll };
+ for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(mTbl); i++) {
+ int64_t m = mTbl[i];
+ CT c;
+ pub.enc(c, m);
+ CYBOZU_TEST_EQUAL((sec.*dec)(c), m);
+ }
+}
+
+#ifndef PAPER
+CYBOZU_TEST_AUTO(hashBench)
+{
+ SecretKey& sec = g_sec;
+ sec.setByCSPRNG();
+ const int C = 500;
+ const size_t hashSize = 1u << 21;
+
+ clock_t begin = clock(), end;
+ setRangeForG1DLP(hashSize);
+ end = clock();
+ printf("init G1 DLP %f\n", double(end - begin) / CLOCKS_PER_SEC);
+ begin = end;
+ setRangeForG2DLP(hashSize);
+ end = clock();
+ printf("init G2 DLP %f\n", double(end - begin) / CLOCKS_PER_SEC);
+ begin = end;
+ setRangeForGTDLP(hashSize);
+ end = clock();
+ printf("init GT DLP %f\n", double(end - begin) / CLOCKS_PER_SEC);
+
+ PublicKey pub;
+ sec.getPublicKey(pub);
+ PrecomputedPublicKey ppub;
+ ppub.init(pub);
+ puts("Kclk");
+ cybozu::bench::setPutCallback(putK);
+ decBench<CipherTextG1>("decG1", C, sec, pub);
+ puts("");
+ decBench<CipherTextG2>("decG2", C, sec, pub);
+ puts("");
+ decBench<CipherTextGT>("decGT", C, sec, pub);
+ puts("");
+ decBench<CipherTextG1>("decG1ViaGT", C, sec, pub, &SecretKey::decViaGT);
+ puts("");
+ decBench<CipherTextG2>("decG2ViaGT", C, sec, pub, &SecretKey::decViaGT);
+
+ G1 P, P2;
+ G2 Q, Q2;
+ GT e, e2;
+ mpz_class mr;
+ {
+ Fr r;
+ r.setRand();
+ mr = r.getMpz();
+ }
+ hashAndMapToG1(P, "abc");
+ hashAndMapToG2(Q, "abc");
+ pairing(e, P, Q);
+ P2.clear();
+ Q2.clear();
+ e2 = 1;
+
+ printf("large m\n");
+ CYBOZU_BENCH_C("G1::add ", C, G1::add, P2, P2, P);
+ CYBOZU_BENCH_C("G1::mul ", C, G1::mul, P, P, mr);
+ CYBOZU_BENCH_C("G2::add ", C, G2::add, Q2, Q2, Q);
+ CYBOZU_BENCH_C("G2::mul ", C, G2::mul, Q, Q, mr);
+ CYBOZU_BENCH_C("GT::mul ", C, GT::mul, e2, e2, e);
+ CYBOZU_BENCH_C("GT::pow ", C, GT::pow, e, e, mr);
+ CYBOZU_BENCH_C("G1window", C, SHE::PhashTbl_.mulByWindowMethod, P2, mr);
+ CYBOZU_BENCH_C("G2window", C, SHE::QhashTbl_.mulByWindowMethod, Q2, mr);
+ CYBOZU_BENCH_C("GTwindow", C, SHE::ePQhashTbl_.mulByWindowMethod, e, mr);
+#if 1
+ typedef mcl::GroupMtoA<Fp12> AG;
+ mcl::fp::WindowMethod<AG> wm;
+ wm.init(static_cast<AG&>(e), Fr::getBitSize(), 10);
+ for (int i = 0; i < 100; i++) {
+ GT t1, t2;
+ GT::pow(t1, e, i);
+ wm.mul(static_cast<AG&>(t2), i);
+ CYBOZU_TEST_EQUAL(t1, t2);
+ }
+// CYBOZU_BENCH_C("GTwindow", C, wm.mul, static_cast<AG&>(e), mr);
+#endif
+
+ CYBOZU_BENCH_C("miller ", C, millerLoop, e, P, Q);
+ CYBOZU_BENCH_C("finalExp", C, finalExp, e, e);
+ CYBOZU_BENCH_C("precomML", C, precomputedMillerLoop, e, P, SHE::Qcoeff_);
+
+ CipherTextG1 c1;
+ CipherTextG2 c2;
+ CipherTextGT ct;
+
+ int m = int(hashSize - 1);
+ printf("small m = %d\n", m);
+ CYBOZU_BENCH_C("G1::mul ", C, G1::mul, P, P, m);
+ CYBOZU_BENCH_C("G2::mul ", C, G2::mul, Q, Q, m);
+ CYBOZU_BENCH_C("GT::pow ", C, GT::pow, e, e, m);
+ CYBOZU_BENCH_C("G1window", C, SHE::PhashTbl_.mulByWindowMethod, P2, m);
+ CYBOZU_BENCH_C("G2window", C, SHE::QhashTbl_.mulByWindowMethod, Q2, m);
+ CYBOZU_BENCH_C("GTwindow", C, SHE::ePQhashTbl_.mulByWindowMethod, e, m);
+// CYBOZU_BENCH_C("GTwindow", C, wm.mul, static_cast<AG&>(e), m);
+
+ CYBOZU_BENCH_C("encG1 ", C, pub.enc, c1, m);
+ CYBOZU_BENCH_C("encG2 ", C, pub.enc, c2, m);
+ CYBOZU_BENCH_C("encGT ", C, pub.enc, ct, m);
+ CYBOZU_BENCH_C("encG1pre", C, ppub.enc, c1, m);
+ CYBOZU_BENCH_C("encG2pre", C, ppub.enc, c2, m);
+ CYBOZU_BENCH_C("encGTpre", C, ppub.enc, ct, m);
+
+ CYBOZU_BENCH_C("decG1 ", C, sec.dec, c1);
+ CYBOZU_BENCH_C("decG2 ", C, sec.dec, c2);
+ CYBOZU_BENCH_C("degGT ", C, sec.dec, ct);
+
+ CYBOZU_BENCH_C("CT:mul ", C, CipherTextGT::mul, ct, c1, c2);
+ CYBOZU_BENCH_C("CT:mulML", C, CipherTextGT::mulML, ct, c1, c2);
+ CYBOZU_BENCH_C("CT:finalExp", C, CipherTextGT::finalExp, ct, ct);
+
+ CYBOZU_BENCH_C("addG1 ", C, CipherTextG1::add, c1, c1, c1);
+ CYBOZU_BENCH_C("addG2 ", C, CipherTextG2::add, c2, c2, c2);
+ CYBOZU_BENCH_C("addGT ", C, CipherTextGT::add, ct, ct, ct);
+ CYBOZU_BENCH_C("reRandG1", C, pub.reRand, c1);
+ CYBOZU_BENCH_C("reRandG2", C, pub.reRand, c2);
+ CYBOZU_BENCH_C("reRandGT", C, pub.reRand, ct);
+ CYBOZU_BENCH_C("reRandG1pre", C, ppub.reRand, c1);
+ CYBOZU_BENCH_C("reRandG2pre", C, ppub.reRand, c2);
+ CYBOZU_BENCH_C("reRandGTpre", C, ppub.reRand, ct);
+ CYBOZU_BENCH_C("mulG1 ", C, CipherTextG1::mul, c1, c1, m);
+ CYBOZU_BENCH_C("mulG2 ", C, CipherTextG2::mul, c2, c2, m);
+ CYBOZU_BENCH_C("mulGT ", C, CipherTextGT::mul, ct, ct, m);
+
+ CYBOZU_BENCH_C("convG1toGT", C, pub.convert, ct, c1);
+ CYBOZU_BENCH_C("convG2toGT", C, pub.convert, ct, c2);
+}
+#endif
+
+CYBOZU_TEST_AUTO(liftedElGamal)
+{
+ const size_t hashSize = 1024;
+ initG1only(mcl::ecparam::secp192k1, hashSize);
+ const size_t byteSize = 192 / 8;
+ SecretKey sec;
+ sec.setByCSPRNG();
+ PublicKey pub;
+ sec.getPublicKey(pub);
+ CipherTextG1 c1, c2, c3;
+ int m1 = 12, m2 = 34;
+ pub.enc(c1, m1);
+ pub.enc(c2, m2);
+ CYBOZU_TEST_EQUAL(sec.dec(c1), m1);
+ CYBOZU_TEST_EQUAL(sec.dec(c2), m2);
+ add(c3, c1, c2);
+ CYBOZU_TEST_EQUAL(sec.dec(c3), m1 + m2);
+ neg(c1, c2);
+ CYBOZU_TEST_EQUAL(sec.dec(c1), -m2);
+ mul(c1, c2, m1);
+ CYBOZU_TEST_EQUAL(sec.dec(c1), m2 * m1);
+
+ char buf[1024];
+ size_t n = sec.serialize(buf, sizeof(buf));
+ CYBOZU_TEST_EQUAL(n, byteSize);
+ SecretKey sec2;
+ n = sec2.deserialize(buf, n);
+ CYBOZU_TEST_EQUAL(n, byteSize);
+ CYBOZU_TEST_EQUAL(sec, sec2);
+
+ n = pub.serialize(buf, sizeof(buf));
+ CYBOZU_TEST_EQUAL(n, byteSize + 1); // +1 is for sign of y
+ PublicKey pub2;
+ n = pub2.deserialize(buf, n);
+ CYBOZU_TEST_EQUAL(n, byteSize + 1);
+ CYBOZU_TEST_EQUAL(pub, pub2);
+
+ PublicKey pub3;
+ sec2.getPublicKey(pub3);
+ CYBOZU_TEST_EQUAL(pub, pub3);
+}
diff --git a/vendor/github.com/tangerine-network/mcl/test/sq_test.cpp b/vendor/github.com/tangerine-network/mcl/test/sq_test.cpp
new file mode 100644
index 000000000..4c386d23b
--- /dev/null
+++ b/vendor/github.com/tangerine-network/mcl/test/sq_test.cpp
@@ -0,0 +1,21 @@
+#include <mcl/gmp_util.hpp>
+#include <cybozu/test.hpp>
+#include <iostream>
+
+CYBOZU_TEST_AUTO(sqrt)
+{
+ const int tbl[] = { 3, 5, 7, 11, 13, 17, 19, 257, 997, 1031 };
+ mcl::SquareRoot sq;
+ for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) {
+ const mpz_class p = tbl[i];
+ sq.set(p);
+ for (mpz_class a = 0; a < p; a++) {
+ mpz_class x;
+ if (sq.get(x, a)) {
+ mpz_class y;
+ y = (x * x) % p;
+ CYBOZU_TEST_EQUAL(a, y);
+ }
+ }
+ }
+}
diff --git a/vendor/github.com/tangerine-network/mcl/test/vint_test.cpp b/vendor/github.com/tangerine-network/mcl/test/vint_test.cpp
new file mode 100644
index 000000000..15e14266a
--- /dev/null
+++ b/vendor/github.com/tangerine-network/mcl/test/vint_test.cpp
@@ -0,0 +1,1353 @@
+#include <stdio.h>
+#include <mcl/vint.hpp>
+#include <iostream>
+#include <sstream>
+#include <set>
+#include <cybozu/benchmark.hpp>
+#include <cybozu/test.hpp>
+#include <cybozu/xorshift.hpp>
+#ifndef DONT_USE_GMP_IN_TEST
+#include <gmpxx.h>
+#endif
+
+#define PUT(x) std::cout << #x "=" << x << std::endl;
+
+#if defined(__EMSCRIPTEN__) && !defined(MCL_AVOID_EXCEPTION_TEST)
+ #define MCL_AVOID_EXCEPTION_TEST
+#endif
+
+using namespace mcl;
+
+struct V {
+ int n;
+ unsigned int p[16];
+};
+
+CYBOZU_TEST_AUTO(addSub)
+{
+ static const struct {
+ V a;
+ V b;
+ V c;
+ } tbl[] = {
+ {
+ { 1, { 123, } },
+ { 1, { 456, } },
+ { 1, { 579, } },
+ },
+ {
+ { 1, { 0xffffffff, } },
+ { 1, { 3, } },
+ { 2, { 2, 1 } },
+ },
+ {
+ { 3, { 0xffffffff, 1, 0xffffffff } },
+ { 2, { 1, 0xfffffffe, } },
+ { 4, { 0, 0, 0, 1 } },
+ },
+ {
+ { 3, { 0xffffffff, 5, 0xffffffff } },
+ { 2, { 1, 0xfffffffe, } },
+ { 4, { 0, 4, 0, 1 } },
+ },
+ {
+ { 3, { 0xffffffff, 5, 0xffffffff } },
+ { 1, { 1, } },
+ { 3, { 0, 6, 0xffffffff } },
+ },
+ {
+ { 3, { 1, 0xffffffff, 1 } },
+ { 3, { 0xffffffff, 0, 1 } },
+ { 3, { 0, 0, 3 } },
+ },
+ {
+ { 1, { 1 } },
+ { 3, { 0xffffffff, 0xffffffff, 0xffffffff } },
+ { 4, { 0, 0, 0, 1 } },
+ },
+ {
+ { 1, { 0xffffffff } },
+ { 1, { 0xffffffff } },
+ { 2, { 0xfffffffe, 1 } },
+ },
+ {
+ { 2, { 0xffffffff, 0xffffffff } },
+ { 2, { 0xffffffff, 0xffffffff } },
+ { 3, { 0xfffffffe, 0xffffffff, 1 } },
+ },
+ {
+ { 3, { 0xffffffff, 0xffffffff, 0xffffffff } },
+ { 3, { 0xffffffff, 0xffffffff, 0xffffffff } },
+ { 4, { 0xfffffffe, 0xffffffff, 0xffffffff, 1 } },
+ },
+ {
+ { 4, { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff } },
+ { 4, { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff } },
+ { 5, { 0xfffffffe, 0xffffffff, 0xffffffff, 0xffffffff, 1 } },
+ },
+ };
+ for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) {
+ Vint x, y, z, t;
+ x.setArray(tbl[i].a.p, tbl[i].a.n);
+ y.setArray(tbl[i].b.p, tbl[i].b.n);
+ z.setArray(tbl[i].c.p, tbl[i].c.n);
+ Vint::add(t, x, y);
+ CYBOZU_TEST_EQUAL(t, z);
+
+ Vint::add(t, y, x);
+ CYBOZU_TEST_EQUAL(t, z);
+
+ Vint::sub(t, z, x);
+ CYBOZU_TEST_EQUAL(t, y);
+ }
+ {
+ const uint32_t in[] = { 0xffffffff, 0xffffffff };
+ const uint32_t out[] = { 0xfffffffe, 0xffffffff, 1 };
+ Vint x, y;
+ x.setArray(in, 2);
+ y.setArray(out, 3);
+ Vint::add(x, x, x);
+ CYBOZU_TEST_EQUAL(x, y);
+ Vint::sub(x, x, x);
+ y.clear();
+ CYBOZU_TEST_EQUAL(x, y);
+ }
+ {
+ const uint32_t t0[] = {1, 2};
+ const uint32_t t1[] = {3, 4, 5};
+ const uint32_t t2[] = {4, 6, 5};
+ Vint x, y, z;
+ z.setArray(t2, 3);
+
+ x.setArray(t0, 2);
+ y.setArray(t1, 3);
+ Vint::add(x, x, y);
+ CYBOZU_TEST_EQUAL(x, z);
+
+ x.setArray(t0, 2);
+ y.setArray(t1, 3);
+ Vint::add(x, y, x);
+ CYBOZU_TEST_EQUAL(x, z);
+
+ x.setArray(t0, 2);
+ y.setArray(t1, 3);
+ Vint::add(y, x, y);
+ CYBOZU_TEST_EQUAL(y, z);
+
+ x.setArray(t0, 2);
+ y.setArray(t1, 3);
+ Vint::add(y, y, x);
+ CYBOZU_TEST_EQUAL(y, z);
+ }
+}
+
+CYBOZU_TEST_AUTO(mul1)
+{
+ static const struct {
+ V a;
+ int b;
+ V c;
+ } tbl[] = {
+ {
+ { 1, { 12, } },
+ 5,
+ { 1, { 60, } },
+ },
+ {
+ { 1, { 1234567, } },
+ 1,
+ { 1, { 1234567, } },
+ },
+ {
+ { 1, { 1234567, } },
+ 89012345,
+ { 2, { 0x27F6EDCF, 0x63F2, } },
+ },
+ {
+ { 3, { 0xffffffff, 0xffffffff, 0xffffffff, } },
+ 0x7fffffff,
+ { 4, { 0x80000001, 0xffffffff, 0xffffffff, 0x7ffffffe } },
+ },
+ {
+ { 3, { 0xffffffff, 0xffffffff, 0xffffffff, } },
+ 1,
+ { 3, { 0xffffffff, 0xffffffff, 0xffffffff, } },
+ },
+ {
+ { 2, { 0xffffffff, 1 } },
+ 0x7fffffff,
+ { 2, { 0x80000001, 0xfffffffd } },
+ },
+ };
+ for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) {
+ Vint x, z, t;
+ int y;
+ x.setArray(tbl[i].a.p, tbl[i].a.n);
+ y = tbl[i].b;
+ z.setArray(tbl[i].c.p, tbl[i].c.n);
+ Vint::mul(t, x, y);
+ CYBOZU_TEST_EQUAL(t, z);
+
+ Vint::mul(x, x, y);
+ CYBOZU_TEST_EQUAL(x, z);
+ }
+}
+
+CYBOZU_TEST_AUTO(mul2)
+{
+ static const struct {
+ V a;
+ V b;
+ V c;
+ } tbl[] = {
+ {
+ { 1, { 12, } },
+ { 1, { 5, } },
+ { 1, { 60, } },
+ },
+ {
+ { 1, { 1234567, } },
+ { 1, { 89012345, } },
+ { 2, { 0x27F6EDCF, 0x63F2, } },
+ },
+ {
+ { 3, { 0xffffffff, 0xffffffff, 0xffffffff, } },
+ { 1, { 0xffffffff, } },
+ { 4, { 0x00000001, 0xffffffff, 0xffffffff, 0xfffffffe } },
+ },
+ {
+ { 2, { 0xffffffff, 1 } },
+ { 1, { 0xffffffff, } },
+ { 3, { 0x00000001, 0xfffffffd, 1 } },
+ },
+ {
+ { 2, { 0xffffffff, 1 } },
+ { 1, { 0xffffffff, } },
+ { 3, { 0x00000001, 0xfffffffd, 1 } },
+ },
+ {
+ { 2, { 1, 1 } },
+ { 2, { 1, 1 } },
+ { 3, { 1, 2, 1 } },
+ },
+ {
+ { 3, { 0xffffffff, 0xffffffff, 1 } },
+ { 2, { 0xffffffff, 0xffffffff } },
+ { 5, { 1, 0, 0xfffffffd, 0xffffffff, 1 } },
+ },
+ };
+ for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) {
+ Vint x, y, z, t;
+ x.setArray(tbl[i].a.p, tbl[i].a.n);
+ y.setArray(tbl[i].b.p, tbl[i].b.n);
+ z.setArray(tbl[i].c.p, tbl[i].c.n);
+ Vint::mul(t, x, y);
+ CYBOZU_TEST_EQUAL(t, z);
+
+ Vint::mul(t, y, x);
+ CYBOZU_TEST_EQUAL(t, z);
+ }
+ {
+ const uint32_t in[] = { 0xffffffff, 1 };
+ const uint32_t out[] = { 1, 0xfffffffc, 3 };
+ Vint x, y, z;
+ y.setArray(out, 3);
+ x.setArray(in, 2);
+ z = x;
+ Vint::mul(x, x, x);
+ CYBOZU_TEST_EQUAL(x, y);
+
+ x.setArray(in, 2);
+ Vint::mul(x, x, z);
+ CYBOZU_TEST_EQUAL(x, y);
+
+ x.setArray(in, 2);
+ Vint::mul(x, z, x);
+ CYBOZU_TEST_EQUAL(x, y);
+
+ x.setArray(in, 2);
+ Vint::mul(x, z, z);
+ CYBOZU_TEST_EQUAL(x, y);
+ }
+ {
+ Vint a("285434247217355341057");
+ a *= a;
+ CYBOZU_TEST_EQUAL(a, Vint("81472709484538325259309302444004789877249"));
+ }
+}
+
+CYBOZU_TEST_AUTO(div1)
+{
+ static const struct {
+ V a;
+ unsigned int b;
+ unsigned int r;
+ V c;
+ } tbl[] = {
+ {
+ { 1, { 100, } },
+ 1, 0,
+ { 1, { 100, } },
+ },
+ {
+ { 1, { 100, } },
+ 100, 0,
+ { 1, { 1, } },
+ },
+ {
+ { 1, { 100, } },
+ 101, 100,
+ { 1, { 0, } },
+ },
+ {
+ { 1, { 100, } },
+ 2, 0,
+ { 1, { 50, } },
+ },
+ {
+ { 1, { 100, } },
+ 3, 1,
+ { 1, { 33, } },
+ },
+ {
+ { 2, { 0xffffffff, 0xffffffff } },
+ 1, 0,
+ { 2, { 0xffffffff, 0xffffffff, } },
+ },
+ {
+ { 2, { 0xffffffff, 0xffffffff } },
+ 123, 15,
+ { 2, { 0x4d0214d0, 0x214d021 } },
+ },
+ };
+ for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) {
+ Vint x, z, t;
+ unsigned int b, r, u;
+ x.setArray(tbl[i].a.p, tbl[i].a.n);
+ b = tbl[i].b;
+ r = tbl[i].r;
+ z.setArray(tbl[i].c.p, tbl[i].c.n);
+
+ u = (unsigned int)Vint::divMods1(&t, x, b);
+ CYBOZU_TEST_EQUAL(t, z);
+ CYBOZU_TEST_EQUAL(u, r);
+
+ u = (unsigned int)Vint::divMods1(&x, x, b);
+ CYBOZU_TEST_EQUAL(x, z);
+ CYBOZU_TEST_EQUAL(u, r);
+ }
+}
+
+CYBOZU_TEST_AUTO(div2)
+{
+ static const struct {
+ V x;
+ V y;
+ V q;
+ V r;
+ } tbl[] = {
+ {
+ { 1, { 100 } },
+ { 1, { 3 } },
+ { 1, { 33 } },
+ { 1, { 1 } },
+ },
+ {
+ { 2, { 1, 1 } },
+ { 2, { 0, 1 } },
+ { 1, { 1 } },
+ { 1, { 1 } },
+ },
+ {
+ { 2, { 0xffffffff, 0xffffffff } },
+ { 2, { 0, 1 } },
+ { 1, { 0xffffffff } },
+ { 1, { 0xffffffff } },
+ },
+ {
+ { 2, { 0xffffffff, 0xffffffff } },
+ { 2, { 0xffffffff, 1 } },
+ { 1, { 0x80000000 } },
+ { 1, { 0x7fffffff } },
+ },
+ {
+ { 3, { 0xffffffff, 0xffffffff, 0xffffffff } },
+ { 2, { 0xffffffff, 1 } },
+ { 2, { 0x40000000, 0x80000000 } },
+ { 1, { 0x3fffffff } },
+ },
+ {
+ { 4, { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff } },
+ { 3, { 1, 0, 1 } },
+ { 2, { 0xffffffff, 0xffffffff } },
+ { 1, { 0 } },
+ },
+ {
+ { 4, { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff } },
+ { 3, { 1, 0xffffffff, 0xffffffff } },
+ { 2, { 0, 1 } },
+ { 2, { 0xffffffff, 0xfffffffe } },
+ },
+ {
+ { 4, { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff } },
+ { 3, { 1, 0, 0xffffffff } },
+ { 2, { 1, 1 } },
+ { 2, { 0xfffffffe, 0xfffffffe } },
+ },
+ {
+ { 4, { 0xffffffff, 0xffffffff, 0xffffffff, 1 } },
+ { 3, { 1, 0, 0xffffffff } },
+ { 1, { 2 } },
+ { 3, { 0xfffffffd, 0xffffffff, 1 } },
+ },
+ {
+ { 4, { 0, 0, 1, 1 } },
+ { 2, { 1, 1 } },
+ { 3, { 0, 0, 1 } },
+ { 1, { 0 } },
+ },
+ {
+ { 3, { 5, 5, 1} },
+ { 2, { 1, 2 } },
+ { 1, { 0x80000002 } },
+ { 1, { 0x80000003, } },
+ },
+ {
+ { 2, { 5, 5} },
+ { 2, { 1, 1 } },
+ { 1, { 5 } },
+ { 1, { 0, } },
+ },
+ {
+ { 2, { 5, 5} },
+ { 2, { 2, 1 } },
+ { 1, { 4 } },
+ { 1, { 0xfffffffd, } },
+ },
+ {
+ { 3, { 5, 0, 5} },
+ { 3, { 2, 0, 1 } },
+ { 1, { 4 } },
+ { 2, { 0xfffffffd, 0xffffffff } },
+ },
+ {
+ { 2, { 4, 5 } },
+ { 2, { 5, 5 } },
+ { 1, { 0 } },
+ { 2, { 4, 5 } },
+ },
+ {
+ { 1, { 123 } },
+ { 2, { 1, 1 } },
+ { 1, { 0 } },
+ { 1, { 123 } },
+ },
+ {
+ { 1, { 123 } },
+ { 3, { 1, 1, 1 } },
+ { 1, { 0 } },
+ { 1, { 123 } },
+ },
+ };
+ for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) {
+ Vint x, y, q, r;
+ x.setArray(tbl[i].x.p, tbl[i].x.n);
+ y.setArray(tbl[i].y.p, tbl[i].y.n);
+ q.setArray(tbl[i].q.p, tbl[i].q.n);
+ r.setArray(tbl[i].r.p, tbl[i].r.n);
+
+ Vint qt, rt;
+ Vint::quotRem(&qt, rt, x, y);
+ CYBOZU_TEST_EQUAL(qt, q);
+ CYBOZU_TEST_EQUAL(rt, r);
+
+ Vint::mul(y, y, qt);
+ Vint::add(y, y, rt);
+ CYBOZU_TEST_EQUAL(x, y);
+
+ x.setArray(tbl[i].x.p, tbl[i].x.n);
+ y.setArray(tbl[i].y.p, tbl[i].y.n);
+ Vint::quotRem(&x, rt, x, y);
+ CYBOZU_TEST_EQUAL(x, q);
+ CYBOZU_TEST_EQUAL(rt, r);
+
+ x.setArray(tbl[i].x.p, tbl[i].x.n);
+ y.setArray(tbl[i].y.p, tbl[i].y.n);
+ Vint::quotRem(&y, rt, x, y);
+ CYBOZU_TEST_EQUAL(y, q);
+ CYBOZU_TEST_EQUAL(rt, r);
+
+ x.setArray(tbl[i].x.p, tbl[i].x.n);
+ y.setArray(tbl[i].y.p, tbl[i].y.n);
+ Vint::quotRem(&x, y, x, y);
+ CYBOZU_TEST_EQUAL(x, q);
+ CYBOZU_TEST_EQUAL(y, r);
+
+ x.setArray(tbl[i].x.p, tbl[i].x.n);
+ y.setArray(tbl[i].y.p, tbl[i].y.n);
+ Vint::quotRem(&y, x, x, y);
+ CYBOZU_TEST_EQUAL(y, q);
+ CYBOZU_TEST_EQUAL(x, r);
+ }
+ {
+ const uint32_t in[] = { 1, 1 };
+ Vint x, y, z;
+ x.setArray(in, 2);
+ Vint::quotRem(&x, y, x, x);
+ z = 1;
+ CYBOZU_TEST_EQUAL(x, z);
+ z.clear();
+ CYBOZU_TEST_EQUAL(y, z);
+
+ Vint::quotRem(&y, x, x, x);
+ z = 1;
+ CYBOZU_TEST_EQUAL(y, z);
+ z.clear();
+ CYBOZU_TEST_EQUAL(x, z);
+ }
+}
+
+CYBOZU_TEST_AUTO(quotRem)
+{
+ const struct {
+ const char *x;
+ const char *y;
+ const char *r;
+ } tbl[] = {
+ {
+ "1448106640508192452750709206294683535529268965445799785581837640324321797831381715960812126274894517677713278300997728292641936248881345120394299128611830",
+ "82434016654300679721217353503190038836571781811386228921167322412819029493183",
+ "72416512377294697540770834088766459385112079195086911762075702918882982361282"
+ },
+ {
+ "97086308670107713719105336221824613370040805954034005192338040686500414395543303807941158656814978071549225072789349941064484974666540443679601226744652",
+ "82434016654300679721217353503190038836571781811386228921167322412819029493183",
+ "41854959563040430269871677548536437787164514279279911478858426970427834388586",
+ },
+ {
+ "726838724295606887174238120788791626017347752989142414466410919788841485181240131619880050064495352797213258935807786970844241989010252",
+ "82434016654300679721217353503190038836571781811386228921167322412819029493183",
+ "81378967132566843036693176764684783485107373533583677681931133755003929106966",
+ },
+ {
+ "85319207237201203511459960875801690195851794174784746933408178697267695525099750",
+ "82434016654300679721217353503190038836571781811386228921167322412819029493183",
+ "82434016654300679721217353503190038836571781811386228921167322412819029148528",
+ },
+ {
+ "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
+ "0x100000000000000000000000000000000000000000000000001",
+ "1606938044258990275541962092341162602522202993782724115824640",
+ },
+ {
+ "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
+ "0x1000000000000000000000000000000000000000000000000000000000000000000000000000000001",
+ "34175792574734561318320347298712833833643272357332299899995954578095372295314880347335474659983360",
+ },
+ {
+ "0xfffffffffffff000000000000000000000000000000000000000000000000000000000000000000",
+ "0x100000000000000000000000000000000000000000000000000000000000000000001",
+ "7558907585412001237250713901367146624661464598973016020495791084036551510708977665",
+ },
+ {
+ "0xfffffffffffff000000000000000000000000000000000000000000000000000000000000000000",
+ "0xfffffffffffff0000000000000000000000000000000000000000000000000000000000000001",
+ "521481209941628322292632858916605385658190900090571826892867289394157573281830188869820088065",
+ },
+ {
+ "0x1230000000000000456",
+ "0x1230000000000000457",
+ "0x1230000000000000456",
+ },
+ {
+ "0x1230000000000000456",
+ "0x1230000000000000456",
+ "0",
+ },
+ {
+ "0x1230000000000000456",
+ "0x1230000000000000455",
+ "1",
+ },
+ {
+ "0x1230000000000000456",
+ "0x2000000000000000000",
+ "0x1230000000000000456",
+ },
+ {
+ "0xffffffffffffffffffffffffffffffff",
+ "0x80000000000000000000000000000000",
+ "0x7fffffffffffffffffffffffffffffff",
+ },
+ {
+ "0xffffffffffffffffffffffffffffffff",
+ "0x7fffffffffffffffffffffffffffffff",
+ "1",
+ },
+ {
+ "0xffffffffffffffffffffffffffffffff",
+ "0x70000000000000000000000000000000",
+ "0x1fffffffffffffffffffffffffffffff",
+ },
+ {
+ "0xffffffffffffffffffffffffffffffff",
+ "0x30000000000000000000000000000000",
+ "0x0fffffffffffffffffffffffffffffff",
+ },
+ {
+ "0xffffffffffffffffffffffffffffffff",
+ "0x10000000000000000000000000000000",
+ "0x0fffffffffffffffffffffffffffffff",
+ },
+ {
+ "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
+ "0x2523648240000001ba344d80000000086121000000000013a700000000000013",
+ "0x212ba4f27ffffff5a2c62effffffffcdb939ffffffffff8a15ffffffffffff8d",
+ },
+ {
+ "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
+ "0x2523648240000001ba344d8000000007ff9f800000000010a10000000000000d",
+ "0x212ba4f27ffffff5a2c62effffffffd00242ffffffffff9c39ffffffffffffb1",
+ },
+ };
+ mcl::Vint x, y, q, r1, r2;
+ for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) {
+ x.setStr(tbl[i].x);
+ y.setStr(tbl[i].y);
+ r1.setStr(tbl[i].r);
+ mcl::Vint::divMod(&q, r2, x, y);
+ CYBOZU_TEST_EQUAL(r1, r2);
+ CYBOZU_TEST_EQUAL(x, q * y + r2);
+ }
+}
+
+CYBOZU_TEST_AUTO(string)
+{
+ const struct {
+ uint32_t v[5];
+ size_t vn;
+ const char *str;
+ const char *hex;
+ const char *bin;
+ } tbl[] = {
+ { { 0 }, 0, "0", "0x0", "0b0" },
+ { { 12345 }, 1, "12345", "0x3039", "0b11000000111001" },
+ { { 0xffffffff }, 1, "4294967295", "0xffffffff", "0b11111111111111111111111111111111" },
+ { { 0, 1 }, 2, "4294967296", "0x100000000", "0b100000000000000000000000000000000" },
+ { { 0, 0, 0, 0, 1 }, 5, "340282366920938463463374607431768211456", "0x100000000000000000000000000000000", "0b100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" },
+ { { 0, 0x0b22a000, 0xe2f768a0, 0xe086b93c, 0x2cd76f }, 5, "1000000000000000000000000000000000000000000000", "0x2cd76fe086b93ce2f768a00b22a00000000000", "0b101100110101110110111111100000100001101011100100111100111000101111011101101000101000000000101100100010101000000000000000000000000000000000000000000000" },
+ };
+ for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) {
+ Vint x, y;
+ x.setArray(tbl[i].v,tbl[i].vn);
+ CYBOZU_TEST_EQUAL(x.getStr(10), tbl[i].str);
+ char buf[1024];
+ size_t n = x.getStr(buf, sizeof(buf), 10);
+ CYBOZU_TEST_ASSERT(n > 0);
+ CYBOZU_TEST_EQUAL(tbl[i].str, buf);
+ y.setStr(tbl[i].str);
+ CYBOZU_TEST_EQUAL(x.getStr(16), tbl[i].hex + 2);
+ n = x.getStr(buf, sizeof(buf), 16);
+ CYBOZU_TEST_ASSERT(n > 0);
+ CYBOZU_TEST_EQUAL(tbl[i].hex + 2, buf);
+ CYBOZU_TEST_EQUAL(x, y);
+ x = 1;
+ x.setStr(tbl[i].hex);
+ CYBOZU_TEST_EQUAL(x, y);
+ }
+}
+
+CYBOZU_TEST_AUTO(shift)
+{
+ Vint x("123423424918471928374192874198274981274918274918274918243");
+ Vint y, z;
+
+ const size_t unitBitSize = Vint::unitBitSize;
+ Vint s;
+ // shl
+ for (size_t i = 1; i < 31; i++) {
+ Vint::shl(y, x, i);
+ z = x * (Vint::Unit(1) << i);
+ CYBOZU_TEST_EQUAL(y, z);
+ y = x << i;
+ CYBOZU_TEST_EQUAL(y, z);
+ y = x;
+ y <<= i;
+ CYBOZU_TEST_EQUAL(y, z);
+ }
+ for (int i = 0; i < 4; i++) {
+ Vint::shl(y, x, i * unitBitSize);
+ Vint::pow(s, Vint(2), i * unitBitSize);
+ z = x * s;
+ CYBOZU_TEST_EQUAL(y, z);
+ y = x << (i * unitBitSize);
+ CYBOZU_TEST_EQUAL(y, z);
+ y = x;
+ y <<= (i * unitBitSize);
+ CYBOZU_TEST_EQUAL(y, z);
+ }
+ for (int i = 0; i < 100; i++) {
+ y = x << i;
+ Vint::pow(s, Vint(2), i);
+ z = x * s;
+ CYBOZU_TEST_EQUAL(y, z);
+ y = x;
+ y <<= i;
+ CYBOZU_TEST_EQUAL(y, z);
+ }
+
+ // shr
+ for (size_t i = 1; i < 31; i++) {
+ Vint::shr(y, x, i);
+ z = x / (Vint::Unit(1) << i);
+ CYBOZU_TEST_EQUAL(y, z);
+ y = x >> i;
+ CYBOZU_TEST_EQUAL(y, z);
+ y = x;
+ y >>= i;
+ CYBOZU_TEST_EQUAL(y, z);
+ }
+ for (int i = 0; i < 3; i++) {
+ Vint::shr(y, x, i * unitBitSize);
+ Vint::pow(s, Vint(2), i * unitBitSize);
+ z = x / s;
+ CYBOZU_TEST_EQUAL(y, z);
+ y = x >> (i * unitBitSize);
+ CYBOZU_TEST_EQUAL(y, z);
+ y = x;
+ y >>= (i * unitBitSize);
+ CYBOZU_TEST_EQUAL(y, z);
+ }
+ for (int i = 0; i < 100; i++) {
+ y = x >> i;
+ Vint::pow(s, Vint(2), i);
+ z = x / s;
+ CYBOZU_TEST_EQUAL(y, z);
+ y = x;
+ y >>= i;
+ CYBOZU_TEST_EQUAL(y, z);
+ }
+ {
+ Vint a = 0, zero = 0;
+ a <<= Vint::unitBitSize;
+ CYBOZU_TEST_EQUAL(a, zero);
+ }
+}
+
+CYBOZU_TEST_AUTO(getBitSize)
+{
+ {
+ Vint zero = 0;
+ CYBOZU_TEST_EQUAL(zero.getBitSize(), 1);
+ zero <<= (Vint::unitBitSize - 1);
+ CYBOZU_TEST_EQUAL(zero.getBitSize(), 1);
+ zero <<= Vint::unitBitSize;
+ CYBOZU_TEST_EQUAL(zero.getBitSize(), 1);
+ }
+
+ {
+ Vint a = 1;
+ CYBOZU_TEST_EQUAL(a.getBitSize(), 1);
+ a = 2;
+ CYBOZU_TEST_EQUAL(a.getBitSize(), 2);
+ a = 3;
+ CYBOZU_TEST_EQUAL(a.getBitSize(), 2);
+ a = 4;
+ CYBOZU_TEST_EQUAL(a.getBitSize(), 3);
+ }
+
+ {
+ Vint a = 5;
+ const size_t msbindex = a.getBitSize();
+ const size_t width = 100;
+ const size_t time = 3;
+ for (size_t i = 0; i < time; ++i) {
+ a <<= width;
+ CYBOZU_TEST_EQUAL(a.getBitSize(), msbindex + width*(i + 1));
+ }
+
+ for (size_t i = 0; i < time*2; ++i) {
+ a >>= width/2;
+ CYBOZU_TEST_EQUAL(a.getBitSize(), msbindex + width*time - (width/2)*(i + 1));
+ }
+ a >>= width;
+ CYBOZU_TEST_ASSERT(a.isZero());
+ CYBOZU_TEST_EQUAL(a.getBitSize(), 1);
+ }
+
+ {
+ Vint b("12"), c("345"), d("67890");
+ size_t bl = b.getBitSize(), cl = c.getBitSize(), dl = d.getBitSize();
+ CYBOZU_TEST_ASSERT((b*c).getBitSize() <= bl + cl);
+ CYBOZU_TEST_ASSERT((c*d).getBitSize() <= cl + dl);
+ CYBOZU_TEST_ASSERT((b*c*d).getBitSize() <= bl + cl + dl);
+ }
+}
+
+CYBOZU_TEST_AUTO(bit)
+{
+ Vint a;
+ a.setStr("0x1234567890abcdef");
+ bool tvec[] = {
+ 1,1,1,1,0 ,1,1,1,1,0
+ ,1,1,0,0,1 ,1,1,1,0,1
+ ,0,1,0,1,0 ,0,0,0,1,0
+ ,0,1,0,0,0 ,1,1,1,1,0
+ ,0,1,1,0,1 ,0,1,0,0,0
+ ,1,0,1,1,0 ,0,0,1,0,0
+ ,1
+ };
+ CYBOZU_TEST_EQUAL(a.getBitSize(), sizeof(tvec)/sizeof(*tvec));
+ for (int i = (int)a.getBitSize() - 1; i >= 0; --i) {
+ CYBOZU_TEST_EQUAL(a.testBit(i), tvec[i]);
+ }
+}
+
+CYBOZU_TEST_AUTO(sample)
+{
+ using namespace mcl;
+ Vint x(1);
+ Vint y("123456789");
+ Vint z;
+
+ x = 1; // set by int
+ y.setStr("123456789"); // set by decimal
+ z.setStr("0xffffffff"); // set by hex
+ x += z;
+
+ x = 2;
+ y = 250;
+ Vint::pow(x, x, y);
+ Vint r, q;
+ r = x % y;
+ q = x / y;
+ CYBOZU_TEST_EQUAL(q * y + r, x);
+
+ Vint::quotRem(&q, r, x, y); // get both r and q
+ CYBOZU_TEST_EQUAL(q * y + r, x);
+}
+
+CYBOZU_TEST_AUTO(Vint)
+{
+ const struct {
+ int a;
+ int b;
+ /*
+ q, r ; like C
+ q2, r2 ; like Python
+ */
+ int add, sub, mul, q, r, q2, r2;
+ } tbl[] = {
+ { 13, 5, 18, 8, 65, 2, 3, 2, 3 },
+ { 13, -5, 8, 18, -65, -2, 3, -3, -2 },
+ { -13, 5, -8, -18, -65, -2, -3, -3, 2 },
+ { -13, -5, -18, -8, 65, 2, -3, 2, -3 },
+ { 5, 13, 18, -8, 65, 0, 5 , 0, 5},
+ { 5, -13, -8, 18, -65, 0, 5 , -1, -8},
+ { -5, 13, 8, -18, -65, 0, -5 , -1, 8},
+ { -5, -13, -18, 8, 65, 0, -5 , 0, -5},
+ };
+ for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) {
+ Vint a = tbl[i].a;
+ Vint b = tbl[i].b;
+ Vint add = a + b;
+ Vint sub = a - b;
+ Vint mul = a * b;
+ Vint q = a / b;
+ Vint r = a % b;
+ Vint q2, r2;
+ Vint::quotRem(&q2, r2, a, b);
+ CYBOZU_TEST_EQUAL(add, tbl[i].add);
+ CYBOZU_TEST_EQUAL(sub, tbl[i].sub);
+ CYBOZU_TEST_EQUAL(mul, tbl[i].mul);
+ CYBOZU_TEST_EQUAL(q, tbl[i].q);
+ CYBOZU_TEST_EQUAL(r, tbl[i].r);
+ CYBOZU_TEST_EQUAL(q * b + r, a);
+ CYBOZU_TEST_EQUAL(q2, tbl[i].q2);
+ CYBOZU_TEST_EQUAL(r2, tbl[i].r2);
+ CYBOZU_TEST_EQUAL(q2 * b + r2, a);
+ }
+ CYBOZU_TEST_EQUAL(Vint("15") / Vint("3"), Vint("5"));
+ CYBOZU_TEST_EQUAL(Vint("15") / Vint("-3"), Vint("-5"));
+ CYBOZU_TEST_EQUAL(Vint("-15") / Vint("3"), Vint("-5"));
+ CYBOZU_TEST_EQUAL(Vint("-15") / Vint("-3"), Vint("5"));
+
+ CYBOZU_TEST_EQUAL(Vint("15") % Vint("3"), Vint("0"));
+ CYBOZU_TEST_EQUAL(Vint("15") % Vint("-3"), Vint("0"));
+ CYBOZU_TEST_EQUAL(Vint("-15") % Vint("3"), Vint("0"));
+ CYBOZU_TEST_EQUAL(Vint("-15") % Vint("-3"), Vint("0"));
+
+ CYBOZU_TEST_EQUAL(Vint("-0") + Vint("-3"), Vint("-3"));
+ CYBOZU_TEST_EQUAL(Vint("-0") - Vint("-3"), Vint("3"));
+ CYBOZU_TEST_EQUAL(Vint("-3") + Vint("-0"), Vint("-3"));
+ CYBOZU_TEST_EQUAL(Vint("-3") - Vint("-0"), Vint("-3"));
+
+ CYBOZU_TEST_EQUAL(Vint("-0") + Vint("3"), Vint("3"));
+ CYBOZU_TEST_EQUAL(Vint("-0") - Vint("3"), Vint("-3"));
+ CYBOZU_TEST_EQUAL(Vint("3") + Vint("-0"), Vint("3"));
+ CYBOZU_TEST_EQUAL(Vint("3") - Vint("-0"), Vint("3"));
+
+ CYBOZU_TEST_EQUAL(Vint("0"), Vint("0"));
+ CYBOZU_TEST_EQUAL(Vint("0"), Vint("-0"));
+ CYBOZU_TEST_EQUAL(Vint("-0"), Vint("0"));
+ CYBOZU_TEST_EQUAL(Vint("-0"), Vint("-0"));
+
+ CYBOZU_TEST_ASSERT(Vint("2") < Vint("3"));
+ CYBOZU_TEST_ASSERT(Vint("-2") < Vint("3"));
+ CYBOZU_TEST_ASSERT(Vint("-5") < Vint("-3"));
+ CYBOZU_TEST_ASSERT(Vint("-0") < Vint("1"));
+ CYBOZU_TEST_ASSERT(Vint("-1") < Vint("-0"));
+
+ CYBOZU_TEST_ASSERT(Vint("5") > Vint("3"));
+ CYBOZU_TEST_ASSERT(Vint("5") > Vint("-3"));
+ CYBOZU_TEST_ASSERT(Vint("-2") > Vint("-3"));
+ CYBOZU_TEST_ASSERT(Vint("3") > Vint("-0"));
+ CYBOZU_TEST_ASSERT(Vint("-0") > Vint("-1"));
+
+ {
+ const struct {
+ const char *str;
+ int s;
+ int shl;
+ int shr;
+ } tbl2[] = {
+ { "0", 1, 0, 0 },
+ { "-0", 1, 0, 0 },
+ { "1", 1, 2, 0 },
+ { "-1", 1, -2, 0 },
+ { "12345", 3, 98760, 1543 },
+ { "-12345", 3, -98760, 0 },
+ };
+ for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl2); i++) {
+ Vint a = Vint(tbl2[i].str);
+ Vint shl = a << tbl2[i].s;
+ CYBOZU_TEST_EQUAL(shl, tbl2[i].shl);
+ if (!a.isNegative()) {
+ Vint shr = a >> tbl2[i].s;
+ CYBOZU_TEST_EQUAL(shr, tbl2[i].shr);
+ }
+ }
+ }
+}
+
+CYBOZU_TEST_AUTO(add2)
+{
+ Vint x, y, z, w;
+ x.setStr("2416089439321382744001761632872637936198961520379024187947524965775137204955564426500438089001375107581766516460437532995850581062940399321788596606850");
+ y.setStr("2416089439321382743300544243711595219403446085161565705825288050160594425031420687263897209379984490503106207071010949258995096347962762372787916800000");
+ z.setStr("701217389161042716795515435217458482122236915614542779924143739236540879621390617078660309389426583736855484714977636949000679806850");
+ Vint::sub(w, x, y);
+ CYBOZU_TEST_EQUAL(w, z);
+
+ Vint a, c, d;
+
+ a.setStr("-2416089439321382744001761632872637936198961520379024187947524965775137204955564426500438089001375107581766516460437532995850581062940399321788596606850");
+ c.setStr("2416089439321382743300544243711595219403446085161565705825288050160594425031420687263897209379984490503106207071010949258995096347962762372787916800000");
+ a = a + c;
+
+ d.setStr("-701217389161042716795515435217458482122236915614542779924143739236540879621390617078660309389426583736855484714977636949000679806850");
+ CYBOZU_TEST_EQUAL(a, d);
+}
+
+CYBOZU_TEST_AUTO(stream)
+{
+ {
+ Vint x, y, z, w;
+ x.setStr("12345678901232342424242423423429922");
+ y.setStr("23423423452424242343");
+ std::ostringstream oss;
+ oss << x << ' ' << y;
+ std::istringstream iss(oss.str());
+ iss >> z >> w;
+ CYBOZU_TEST_EQUAL(x, z);
+ CYBOZU_TEST_EQUAL(y, w);
+ }
+ {
+ Vint x, y, z, w;
+ x.setStr("0x100");
+ y.setStr("123");
+ std::ostringstream oss;
+ oss << x << ' ' << y;
+ std::istringstream iss(oss.str());
+ iss >> z >> w;
+ CYBOZU_TEST_EQUAL(x, z);
+ CYBOZU_TEST_EQUAL(y, w);
+ }
+ {
+ Vint x, y, z, w;
+ x.setStr("12345678901232342424242423423429922");
+ y.setStr("-23423423452424242343");
+ std::ostringstream oss;
+ oss << x << ' ' << y;
+ std::istringstream iss(oss.str());
+ iss >> z >> w;
+ CYBOZU_TEST_EQUAL(x, z);
+ CYBOZU_TEST_EQUAL(y, w);
+ }
+}
+
+CYBOZU_TEST_AUTO(inc_dec)
+{
+ Vint x = 3;
+ CYBOZU_TEST_EQUAL(x++, 3);
+ CYBOZU_TEST_EQUAL(x, 4);
+ CYBOZU_TEST_EQUAL(++x, 5);
+ CYBOZU_TEST_EQUAL(x, 5);
+
+ CYBOZU_TEST_EQUAL(x--, 5);
+ CYBOZU_TEST_EQUAL(x, 4);
+ CYBOZU_TEST_EQUAL(--x, 3);
+ CYBOZU_TEST_EQUAL(x, 3);
+}
+
+CYBOZU_TEST_AUTO(withInt)
+{
+ Vint x = 15;
+ x += 3;
+ CYBOZU_TEST_EQUAL(x, 18);
+ x -= 2;
+ CYBOZU_TEST_EQUAL(x, 16);
+ x *= 2;
+ CYBOZU_TEST_EQUAL(x, 32);
+ x /= 3;
+ CYBOZU_TEST_EQUAL(x, 10);
+ x = -x;
+ CYBOZU_TEST_EQUAL(x, -10);
+ x += 1;
+ CYBOZU_TEST_EQUAL(x, -9);
+ x -= 2;
+ CYBOZU_TEST_EQUAL(x, -11);
+ x *= 2;
+ CYBOZU_TEST_EQUAL(x, -22);
+ x /= 5;
+ CYBOZU_TEST_EQUAL(x, -4);
+ x = -22;
+ x %= 5;
+ CYBOZU_TEST_EQUAL(x, -2);
+
+ x = 3;
+ x += -2;
+ CYBOZU_TEST_EQUAL(x, 1);
+ x += -5;
+ CYBOZU_TEST_EQUAL(x, -4);
+ x -= -7;
+ CYBOZU_TEST_EQUAL(x, 3);
+ x *= -1;
+ CYBOZU_TEST_EQUAL(x, -3);
+ x /= -1;
+ CYBOZU_TEST_EQUAL(x, 3);
+
+ x++;
+ CYBOZU_TEST_EQUAL(x, 4);
+ x--;
+ CYBOZU_TEST_EQUAL(x, 3);
+ x = -3;
+ x++;
+ CYBOZU_TEST_EQUAL(x, -2);
+ x--;
+ CYBOZU_TEST_EQUAL(x, -3);
+
+ ++x;
+ CYBOZU_TEST_EQUAL(x, -2);
+ --x;
+ CYBOZU_TEST_EQUAL(x, -3);
+ x = 3;
+ ++x;
+ CYBOZU_TEST_EQUAL(x, 4);
+ --x;
+ CYBOZU_TEST_EQUAL(x, 3);
+}
+
+CYBOZU_TEST_AUTO(addu1)
+{
+ Vint x = 4;
+ Vint::addu1(x, x, 2);
+ CYBOZU_TEST_EQUAL(x, 6);
+ Vint::subu1(x, x, 2);
+ CYBOZU_TEST_EQUAL(x, 4);
+ Vint::subu1(x, x, 10);
+ CYBOZU_TEST_EQUAL(x, -6);
+ x = -4;
+ Vint::addu1(x, x, 2);
+ CYBOZU_TEST_EQUAL(x, -2);
+ Vint::subu1(x, x, 2);
+ CYBOZU_TEST_EQUAL(x, -4);
+ Vint::addu1(x, x, 10);
+ CYBOZU_TEST_EQUAL(x, 6);
+
+ x.setStr("0x10000000000000000000000002");
+ Vint::subu1(x, x, 3);
+ CYBOZU_TEST_EQUAL(x, Vint("0xfffffffffffffffffffffffff"));
+ x.setStr("-0x10000000000000000000000000");
+ Vint::addu1(x, x, 5);
+ CYBOZU_TEST_EQUAL(x, Vint("-0xffffffffffffffffffffffffb"));
+}
+
+CYBOZU_TEST_AUTO(pow)
+{
+ Vint x = 2;
+ Vint y;
+ Vint::pow(y, x, 3);
+ CYBOZU_TEST_EQUAL(y, 8);
+ x = -2;
+ Vint::pow(y, x, 3);
+ CYBOZU_TEST_EQUAL(y, -8);
+#ifndef MCL_AVOID_EXCEPTION_TEST
+// CYBOZU_TEST_EXCEPTION(Vint::pow(y, x, -2), cybozu::Exception);
+#endif
+}
+
+CYBOZU_TEST_AUTO(powMod)
+{
+ Vint x = 7;
+ Vint m = 65537;
+ Vint y;
+ Vint::powMod(y, x, 20, m);
+ CYBOZU_TEST_EQUAL(y, 55277);
+ Vint::powMod(y, x, m - 1, m);
+ CYBOZU_TEST_EQUAL(y, 1);
+}
+
+CYBOZU_TEST_AUTO(andOr)
+{
+ Vint x("1223480928420984209849242");
+ Vint y("29348220482094820948208420984209482048204289482");
+ Vint z;
+ z = x & y;
+ CYBOZU_TEST_EQUAL(z, Vint("1209221003550923564822922"));
+ z = x | y;
+ CYBOZU_TEST_EQUAL(z, Vint("29348220482094820948208435244134352108849315802"));
+#ifndef MCL_AVOID_EXCEPTION_TEST
+// CYBOZU_TEST_EXCEPTION(Vint("-2") | Vint("5"), cybozu::Exception);
+// CYBOZU_TEST_EXCEPTION(Vint("-2") & Vint("5"), cybozu::Exception);
+#endif
+ x = 8;
+ x |= 7;
+ CYBOZU_TEST_EQUAL(x, 15);
+ x = 65536;
+ y = 8;
+ y &= x;
+ CYBOZU_TEST_EQUAL(y, 0);
+}
+
+CYBOZU_TEST_AUTO(invMod)
+{
+ Vint m("100000000000000000039");
+ for (int i = 1; i < 100; i++) {
+ Vint x = i;
+ Vint y;
+ Vint::invMod(y, x, m);
+ CYBOZU_TEST_EQUAL((y * x) % m, 1);
+ }
+}
+
+CYBOZU_TEST_AUTO(isPrime)
+{
+ int primeTbl[] = {
+ 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61,
+ 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137,
+ 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193,197, 199, 211,
+ 223, 227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283,
+ 293, 307, 311, 313, 317, 331, 337, 347, 349, 353, 359, 367, 373, 379,
+ 383, 389, 397, 401, 409, 419, 421, 431, 433, 439, 443, 449, 457, 461,
+ 463, 467, 479, 487, 491, 499, 503, 509, 521, 523, 541, 547, 557, 563,
+ 569, 571, 577, 587, 593, 599, 601, 607, 613, 617, 619, 631, 641, 643,
+ 647, 653, 659, 661, 673, 677, 683, 691, 701, 709, 719, 727, 733, 739,
+ 743, 751, 757, 761, 769, 773, 787, 797, 809, 811, 821, 823, 827, 829,
+ 839, 853, 857, 859, 863, 877, 881, 883, 887, 907, 911, 919, 929, 937,
+ 941, 947, 953, 967, 971, 977, 983, 991, 997
+ };
+ typedef std::set<int> IntSet;
+ IntSet primes;
+ for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(primeTbl); i++) {
+ primes.insert(primeTbl[i]);
+ }
+ for (int i = 0; i < 1000; i++) {
+ bool ok = primes.find(i) != primes.end();
+ bool my = Vint(i).isPrime();
+ CYBOZU_TEST_EQUAL(ok, my);
+ }
+ const struct {
+ const char *n;
+ bool isPrime;
+ } tbl[] = {
+ { "65537", true },
+ { "449065", false },
+ { "488881", false },
+ { "512461", false },
+ { "18446744073709551629", true },
+ { "18446744073709551631", false },
+ { "0x10000000000000000000000000000000000000007", true },
+ { "0x10000000000000000000000000000000000000009", false },
+ { "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f", true },
+ { "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2d", false },
+ };
+ for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) {
+ Vint x(tbl[i].n);
+ CYBOZU_TEST_EQUAL(x.isPrime(), tbl[i].isPrime);
+ }
+}
+
+CYBOZU_TEST_AUTO(gcd)
+{
+ Vint x = 12;
+ Vint y = 18;
+ Vint z;
+ Vint::gcd(z, x, y);
+ CYBOZU_TEST_EQUAL(z, 6);
+ Vint::lcm(z, x, y);
+ CYBOZU_TEST_EQUAL(z, 36);
+ Vint::lcm(x, x, y);
+ CYBOZU_TEST_EQUAL(x, 36);
+ Vint::lcm(x, x, x);
+ CYBOZU_TEST_EQUAL(x, 36);
+}
+
+CYBOZU_TEST_AUTO(jacobi)
+{
+ const struct {
+ const char *m;
+ const char *n;
+ int ok;
+ } tbl[] = {
+ { "0", "1", 1 },
+ { "1", "1", 1 },
+ { "123", "1", 1 },
+ { "45", "77", -1 },
+ { "60", "121", 1 },
+ { "12345672342342342342428", "923423423424753211", 1 },
+ { "12345672342342342342428","34592342234235424753211", -1 },
+ };
+ for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) {
+ int my = Vint::jacobi(Vint(tbl[i].m), Vint(tbl[i].n));
+ CYBOZU_TEST_EQUAL(my, tbl[i].ok);
+ }
+}
+
+CYBOZU_TEST_AUTO(bench)
+{
+ Vint x, y, z;
+ x.setStr("0x2523648240000001ba344d80000000086121000000000013a700000000000013");
+ y.setStr("0x1802938109810498104982094820498203942804928049284092424902424243");
+
+ int N = 100000;
+ CYBOZU_BENCH_C("add", N, Vint::add, z, x, y);
+ CYBOZU_BENCH_C("sub", N, Vint::sub, z, x, y);
+ CYBOZU_BENCH_C("mul", N, Vint::mul, z, x, y);
+ CYBOZU_BENCH_C("div", N, Vint::div, y, z, x);
+
+ const struct {
+ const char *x;
+ const char *y;
+ } tbl[] = {
+ {
+ "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
+ "0x2523648240000001ba344d8000000007ff9f800000000010a10000000000000d"
+ },
+ {
+ "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
+ "0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaab",
+ },
+ {
+ "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
+ "0x73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001",
+ },
+
+ };
+ for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) {
+ x.setStr(tbl[i].x);
+ y.setStr(tbl[i].y);
+ CYBOZU_BENCH_C("fast div", N, Vint::div, z, x, y);
+#ifndef DONT_USE_GMP_IN_TEST
+ {
+ mpz_class mx(tbl[i].x), my(tbl[i].y), mz;
+ CYBOZU_BENCH_C("gmp", N, mpz_div, mz.get_mpz_t(), mx.get_mpz_t(), my.get_mpz_t());
+ }
+#endif
+ }
+}
+
+struct Seq {
+ const uint32_t *tbl;
+ size_t n;
+ size_t i, j;
+ Seq(const uint32_t *tbl, size_t n) : tbl(tbl), n(n), i(0), j(0) {}
+ bool next(uint64_t *v)
+ {
+ if (i == n) {
+ if (j == n - 1) return false;
+ i = 0;
+ j++;
+ }
+ *v = (uint64_t(tbl[j]) << 32) | tbl[i];
+ i++;
+ return true;
+ }
+};
+
+#if MCL_SIZEOF_UNIT == 8
+CYBOZU_TEST_AUTO(divUnit)
+{
+ const uint32_t tbl[] = {
+ 0, 1, 3,
+ 0x7fffffff,
+ 0x80000000,
+ 0x80000001,
+ 0xffffffff,
+ };
+ const size_t n = sizeof(tbl) / sizeof(tbl[0]);
+ Seq seq3(tbl, n);
+ uint64_t y;
+ while (seq3.next(&y)) {
+ if (y == 0) continue;
+ Seq seq2(tbl, n);
+ uint64_t r;
+ while (seq2.next(&r)) {
+ if (r >= y) break;
+ Seq seq1(tbl, n);
+ uint64_t q;
+ while (seq1.next(&q)) {
+ uint64_t x[2];
+ x[0] = mcl::vint::mulUnit(&x[1], q, y);
+ mcl::vint::addu1(x, x, 2, r);
+ uint64_t Q, R;
+//printf("q=0x%016llxull, r=0x%016llxull, y=0x%016llxull\n", (long long)q, (long long)r, (long long)y);
+ Q = mcl::vint::divUnit(&R, x[1], x[0], y);
+ CYBOZU_TEST_EQUAL(q, Q);
+ CYBOZU_TEST_EQUAL(r, R);
+ }
+ }
+ }
+}
+
+void compareMod(const uint64_t *x, const uint64_t *p)
+{
+ uint64_t y1[4] = {};
+ uint64_t y2[4] = {};
+ mcl::vint::divNM((uint64_t*)0, 0, y1, x, 8, p, 4);
+ mcl::vint::mcl_fpDbl_mod_SECP256K1(y2, x, p);
+ CYBOZU_TEST_EQUAL_ARRAY(y1, y2, 4);
+}
+CYBOZU_TEST_AUTO(SECP256k1)
+{
+ const uint64_t F = uint64_t(-1);
+ const uint64_t p[4] = { uint64_t(0xfffffffefffffc2full), F, F, F };
+ const uint64_t tbl[][8] = {
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+ { F, F, F, F, F, F, F, F },
+ { F, F, F, F, 1, 0, 0, 0 },
+ };
+ for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) {
+ const uint64_t *x = tbl[i];
+ compareMod(x, p);
+ }
+ cybozu::XorShift rg;
+ for (size_t i = 0; i < 100; i++) {
+ uint64_t x[8];
+ for (int j = 0; j < 8; j++) {
+ x[j] = rg();
+ }
+ compareMod(x, p);
+ }
+}
+#endif
diff --git a/vendor/github.com/tangerine-network/mcl/test/window_method_test.cpp b/vendor/github.com/tangerine-network/mcl/test/window_method_test.cpp
new file mode 100644
index 000000000..1b0f702af
--- /dev/null
+++ b/vendor/github.com/tangerine-network/mcl/test/window_method_test.cpp
@@ -0,0 +1,70 @@
+#include <cybozu/test.hpp>
+#include <mcl/window_method.hpp>
+#include <mcl/ec.hpp>
+#include <mcl/fp.hpp>
+#include <mcl/ecparam.hpp>
+
+CYBOZU_TEST_AUTO(ArrayIterator)
+{
+ const uint32_t in[2] = { 0x12345678, 0xabcdef89 };
+ const size_t bitSize = 64;
+ for (size_t w = 1; w <= 32; w++) {
+ const uint32_t mask = uint32_t((uint64_t(1) << w) - 1);
+ mpz_class x;
+ mcl::gmp::setArray(x, in, 2);
+ mcl::fp::ArrayIterator<uint32_t> ai(in, bitSize, w);
+ size_t n = (bitSize + w - 1) / w;
+ for (size_t j = 0; j < n; j++) {
+ CYBOZU_TEST_ASSERT(ai.hasNext());
+ uint32_t v = ai.getNext();
+ CYBOZU_TEST_EQUAL(x & mask, v);
+ x >>= w;
+ }
+ CYBOZU_TEST_ASSERT(!ai.hasNext());
+ }
+}
+
+CYBOZU_TEST_AUTO(int)
+{
+ typedef mcl::FpT<> Fp;
+ typedef mcl::EcT<Fp> Ec;
+ const struct mcl::EcParam& para = mcl::ecparam::secp192k1;
+ Fp::init(para.p);
+ Ec::init(para.a, para.b);
+ const Fp x(para.gx);
+ const Fp y(para.gy);
+ const Ec P(x, y);
+
+ typedef mcl::fp::WindowMethod<Ec> PW;
+ const size_t bitSize = 13;
+ Ec Q, R;
+
+ for (size_t winSize = 10; winSize <= bitSize; winSize++) {
+ PW pw(P, bitSize, winSize);
+ for (int i = 0; i < (1 << bitSize); i++) {
+ pw.mul(Q, i);
+ Ec::mul(R, P, i);
+ CYBOZU_TEST_EQUAL(Q, R);
+ }
+ }
+ PW pw(P, para.bitSize, 10);
+ pw.mul(Q, -12345);
+ Ec::mul(R, P, -12345);
+ CYBOZU_TEST_EQUAL(Q, R);
+ mpz_class t(para.gx);
+ pw.mul(Q, t);
+ Ec::mul(R, P, t);
+ CYBOZU_TEST_EQUAL(Q, R);
+ t = -t;
+ pw.mul(Q, t);
+ Ec::mul(R, P, t);
+ CYBOZU_TEST_EQUAL(Q, R);
+
+ pw.mul(Q, x);
+ Ec::mul(R, P, x);
+ CYBOZU_TEST_EQUAL(Q, R);
+
+ pw.mul(Q, y);
+ Ec::mul(R, P, y);
+ CYBOZU_TEST_EQUAL(Q, R);
+}