diff options
author | Wei-Ning Huang <w@dexon.org> | 2019-04-11 18:32:33 +0800 |
---|---|---|
committer | Wei-Ning Huang <w@byzantine-lab.io> | 2019-06-15 22:09:55 +0800 |
commit | 21ac6a5ed287112f685174b482d36392c594f0e8 (patch) | |
tree | f36d198fdee235aac353ae32b8d927890bcae060 /vendor/github.com/dexon-foundation/mcl/test | |
parent | 67637a63cab266b30d2a634bb8039bd7ff1ae335 (diff) | |
download | go-tangerine-21ac6a5ed287112f685174b482d36392c594f0e8.tar.gz go-tangerine-21ac6a5ed287112f685174b482d36392c594f0e8.tar.zst go-tangerine-21ac6a5ed287112f685174b482d36392c594f0e8.zip |
vendor: use BLS-12_384 curve and update dependencies (#356)
Diffstat (limited to 'vendor/github.com/dexon-foundation/mcl/test')
40 files changed, 9546 insertions, 0 deletions
diff --git a/vendor/github.com/dexon-foundation/mcl/test/aggregate_sig_test.cpp b/vendor/github.com/dexon-foundation/mcl/test/aggregate_sig_test.cpp new file mode 100644 index 000000000..c3a0e758d --- /dev/null +++ b/vendor/github.com/dexon-foundation/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/dexon-foundation/mcl/test/array_test.cpp b/vendor/github.com/dexon-foundation/mcl/test/array_test.cpp new file mode 100644 index 000000000..2168a28fa --- /dev/null +++ b/vendor/github.com/dexon-foundation/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/dexon-foundation/mcl/test/base_test.cpp b/vendor/github.com/dexon-foundation/mcl/test/base_test.cpp new file mode 100644 index 000000000..2733d17ca --- /dev/null +++ b/vendor/github.com/dexon-foundation/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/dexon-foundation/mcl/test/bench.hpp b/vendor/github.com/dexon-foundation/mcl/test/bench.hpp new file mode 100644 index 000000000..cc1639e6e --- /dev/null +++ b/vendor/github.com/dexon-foundation/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/dexon-foundation/mcl/test/bls12_test.cpp b/vendor/github.com/dexon-foundation/mcl/test/bls12_test.cpp new file mode 100644 index 000000000..7011516bd --- /dev/null +++ b/vendor/github.com/dexon-foundation/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/dexon-foundation/mcl/test/bn384_test.cpp b/vendor/github.com/dexon-foundation/mcl/test/bn384_test.cpp new file mode 100644 index 000000000..b5674a918 --- /dev/null +++ b/vendor/github.com/dexon-foundation/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/dexon-foundation/mcl/test/bn512_test.cpp b/vendor/github.com/dexon-foundation/mcl/test/bn512_test.cpp new file mode 100644 index 000000000..905bfd3db --- /dev/null +++ b/vendor/github.com/dexon-foundation/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/dexon-foundation/mcl/test/bn_c256_test.cpp b/vendor/github.com/dexon-foundation/mcl/test/bn_c256_test.cpp new file mode 100644 index 000000000..2ce85162d --- /dev/null +++ b/vendor/github.com/dexon-foundation/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/dexon-foundation/mcl/test/bn_c384_256_test.cpp b/vendor/github.com/dexon-foundation/mcl/test/bn_c384_256_test.cpp new file mode 100644 index 000000000..e7bbefda9 --- /dev/null +++ b/vendor/github.com/dexon-foundation/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/dexon-foundation/mcl/test/bn_c384_test.cpp b/vendor/github.com/dexon-foundation/mcl/test/bn_c384_test.cpp new file mode 100644 index 000000000..a9f20243a --- /dev/null +++ b/vendor/github.com/dexon-foundation/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/dexon-foundation/mcl/test/bn_c512_test.cpp b/vendor/github.com/dexon-foundation/mcl/test/bn_c512_test.cpp new file mode 100644 index 000000000..c6af3989f --- /dev/null +++ b/vendor/github.com/dexon-foundation/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/dexon-foundation/mcl/test/bn_c_test.hpp b/vendor/github.com/dexon-foundation/mcl/test/bn_c_test.hpp new file mode 100644 index 000000000..e9dc59393 --- /dev/null +++ b/vendor/github.com/dexon-foundation/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/dexon-foundation/mcl/test/bn_test.cpp b/vendor/github.com/dexon-foundation/mcl/test/bn_test.cpp new file mode 100644 index 000000000..071ec706c --- /dev/null +++ b/vendor/github.com/dexon-foundation/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/dexon-foundation/mcl/test/conversion_test.cpp b/vendor/github.com/dexon-foundation/mcl/test/conversion_test.cpp new file mode 100644 index 000000000..ec11fe900 --- /dev/null +++ b/vendor/github.com/dexon-foundation/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/dexon-foundation/mcl/test/ec_test.cpp b/vendor/github.com/dexon-foundation/mcl/test/ec_test.cpp new file mode 100644 index 000000000..ec49adbfe --- /dev/null +++ b/vendor/github.com/dexon-foundation/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/dexon-foundation/mcl/test/ecdsa_c_test.cpp b/vendor/github.com/dexon-foundation/mcl/test/ecdsa_c_test.cpp new file mode 100644 index 000000000..e0af38182 --- /dev/null +++ b/vendor/github.com/dexon-foundation/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/dexon-foundation/mcl/test/ecdsa_test.cpp b/vendor/github.com/dexon-foundation/mcl/test/ecdsa_test.cpp new file mode 100644 index 000000000..332c9ee27 --- /dev/null +++ b/vendor/github.com/dexon-foundation/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/dexon-foundation/mcl/test/elgamal_test.cpp b/vendor/github.com/dexon-foundation/mcl/test/elgamal_test.cpp new file mode 100644 index 000000000..9532fc597 --- /dev/null +++ b/vendor/github.com/dexon-foundation/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/dexon-foundation/mcl/test/fp_generator_test.cpp b/vendor/github.com/dexon-foundation/mcl/test/fp_generator_test.cpp new file mode 100644 index 000000000..60ec5cd41 --- /dev/null +++ b/vendor/github.com/dexon-foundation/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/dexon-foundation/mcl/test/fp_test.cpp b/vendor/github.com/dexon-foundation/mcl/test/fp_test.cpp new file mode 100644 index 000000000..dc1b01ef4 --- /dev/null +++ b/vendor/github.com/dexon-foundation/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/dexon-foundation/mcl/test/fp_tower_test.cpp b/vendor/github.com/dexon-foundation/mcl/test/fp_tower_test.cpp new file mode 100644 index 000000000..a7123f7a5 --- /dev/null +++ b/vendor/github.com/dexon-foundation/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/dexon-foundation/mcl/test/fp_util_test.cpp b/vendor/github.com/dexon-foundation/mcl/test/fp_util_test.cpp new file mode 100644 index 000000000..e8a9f9aa5 --- /dev/null +++ b/vendor/github.com/dexon-foundation/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/dexon-foundation/mcl/test/glv_test.cpp b/vendor/github.com/dexon-foundation/mcl/test/glv_test.cpp new file mode 100644 index 000000000..a917f51f4 --- /dev/null +++ b/vendor/github.com/dexon-foundation/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/dexon-foundation/mcl/test/gmp_test.cpp b/vendor/github.com/dexon-foundation/mcl/test/gmp_test.cpp new file mode 100644 index 000000000..1fe9d4eb6 --- /dev/null +++ b/vendor/github.com/dexon-foundation/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/dexon-foundation/mcl/test/low_test.cpp b/vendor/github.com/dexon-foundation/mcl/test/low_test.cpp new file mode 100644 index 000000000..f5e72a0b3 --- /dev/null +++ b/vendor/github.com/dexon-foundation/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/dexon-foundation/mcl/test/mk32.sh b/vendor/github.com/dexon-foundation/mcl/test/mk32.sh new file mode 100644 index 000000000..4d5f60711 --- /dev/null +++ b/vendor/github.com/dexon-foundation/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/dexon-foundation/mcl/test/modp_test.cpp b/vendor/github.com/dexon-foundation/mcl/test/modp_test.cpp new file mode 100644 index 000000000..bf9da38bf --- /dev/null +++ b/vendor/github.com/dexon-foundation/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/dexon-foundation/mcl/test/mont_fp_test.cpp b/vendor/github.com/dexon-foundation/mcl/test/mont_fp_test.cpp new file mode 100644 index 000000000..e41e77a53 --- /dev/null +++ b/vendor/github.com/dexon-foundation/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/dexon-foundation/mcl/test/paillier_test.cpp b/vendor/github.com/dexon-foundation/mcl/test/paillier_test.cpp new file mode 100644 index 000000000..31d2b26fc --- /dev/null +++ b/vendor/github.com/dexon-foundation/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/dexon-foundation/mcl/test/proj/bn_test/bn_test.vcxproj b/vendor/github.com/dexon-foundation/mcl/test/proj/bn_test/bn_test.vcxproj new file mode 100644 index 000000000..936e075aa --- /dev/null +++ b/vendor/github.com/dexon-foundation/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/dexon-foundation/mcl/test/proj/ec_test/ec_test.vcxproj b/vendor/github.com/dexon-foundation/mcl/test/proj/ec_test/ec_test.vcxproj new file mode 100644 index 000000000..4bdfda2cb --- /dev/null +++ b/vendor/github.com/dexon-foundation/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/dexon-foundation/mcl/test/proj/fp_test/fp_test.vcxproj b/vendor/github.com/dexon-foundation/mcl/test/proj/fp_test/fp_test.vcxproj new file mode 100644 index 000000000..f705982bf --- /dev/null +++ b/vendor/github.com/dexon-foundation/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/dexon-foundation/mcl/test/proj/fp_tower_test/fp_tower_test.vcxproj b/vendor/github.com/dexon-foundation/mcl/test/proj/fp_tower_test/fp_tower_test.vcxproj new file mode 100644 index 000000000..d5720678f --- /dev/null +++ b/vendor/github.com/dexon-foundation/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/dexon-foundation/mcl/test/she_c256_test.cpp b/vendor/github.com/dexon-foundation/mcl/test/she_c256_test.cpp new file mode 100644 index 000000000..3e458b623 --- /dev/null +++ b/vendor/github.com/dexon-foundation/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/dexon-foundation/mcl/test/she_c384_test.cpp b/vendor/github.com/dexon-foundation/mcl/test/she_c384_test.cpp new file mode 100644 index 000000000..5c7bd9882 --- /dev/null +++ b/vendor/github.com/dexon-foundation/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/dexon-foundation/mcl/test/she_c_test.hpp b/vendor/github.com/dexon-foundation/mcl/test/she_c_test.hpp new file mode 100644 index 000000000..8287c0e0a --- /dev/null +++ b/vendor/github.com/dexon-foundation/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/dexon-foundation/mcl/test/she_test.cpp b/vendor/github.com/dexon-foundation/mcl/test/she_test.cpp new file mode 100644 index 000000000..9292c35f4 --- /dev/null +++ b/vendor/github.com/dexon-foundation/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/dexon-foundation/mcl/test/sq_test.cpp b/vendor/github.com/dexon-foundation/mcl/test/sq_test.cpp new file mode 100644 index 000000000..4c386d23b --- /dev/null +++ b/vendor/github.com/dexon-foundation/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/dexon-foundation/mcl/test/vint_test.cpp b/vendor/github.com/dexon-foundation/mcl/test/vint_test.cpp new file mode 100644 index 000000000..15e14266a --- /dev/null +++ b/vendor/github.com/dexon-foundation/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/dexon-foundation/mcl/test/window_method_test.cpp b/vendor/github.com/dexon-foundation/mcl/test/window_method_test.cpp new file mode 100644 index 000000000..1b0f702af --- /dev/null +++ b/vendor/github.com/dexon-foundation/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); +} |