add optimized_swu_G2

update-fork
MITSUNARI Shigeo 5 years ago
parent f483ec41d7
commit e4f3027737
  1. 101
      include/mcl/mapto_wb19.hpp
  2. 68
      test/mapto_wb19_test.cpp

@ -314,12 +314,101 @@ struct MapToG2_WB19 {
if (!x.b.isZero()) return false; if (!x.b.isZero()) return false;
return false; return false;
} }
/*
z = sqrt(u/v) = (uv^7) (uv^15)^((p^2-9)/16) * root4
return true if found
*/
bool sqr_div(Fp2& z, const Fp2& u, const Fp2& v) const
{
Fp2 gamma, t1, t2;
Fp2::sqr(gamma, v); // v^2
Fp2::sqr(t2, gamma); // v^4
Fp2::mul(t1, u, v); // uv
t1 *= gamma; // uv^3
t1 *= t2; // uv^7
Fp2::sqr(t2, t2); // v^8
t2 *= t1;
Fp2::pow(gamma, t2, sqrtConst);
gamma *= t1;
Fp2 candi;
for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(root4); i++) {
Fp2::mul(candi, gamma, root4[i]);
Fp2::sqr(t1, candi);
t1 *= v;
if (t1 == u) {
z = candi;
return true;
}
}
z = gamma;
return false;
}
// https://github.com/ethereum/py_ecc
void optimized_swu_G2(Point& P, const Fp2& t) const
{
Fp2 t2, t2xi, t2xi2;
Fp2::sqr(t2, t);
mul_xi(t2xi, t2);
Fp2::sqr(t2xi2, t2xi);
Fp2 nume, deno;
// (t^2 * xi)^2 + (t^2 * xi)
Fp2::add(deno, t2xi2, t2xi);
Fp2::add(nume, deno, 1);
nume *= Ell2p_b;
if (deno.isZero()) {
Fp2::mul(deno, Ell2p_a, xi);
} else {
deno *= -Ell2p_a;
}
Fp2 u, v;
{
Fp2 deno2, tmp, tmp1, tmp2;
Fp2::sqr(deno2, deno);
Fp2::mul(v, deno2, deno);
Fp2::mul(u, Ell2p_b, v);
Fp2::mul(tmp, Ell2p_a, nume);
tmp *= deno2;
u += tmp;
Fp2::sqr(tmp, nume);
tmp *= nume;
u += tmp;
}
Fp2 candi;
bool success = sqr_div(candi, u, v);
P.y = candi;
candi *= t2;
candi *= t;
u *= t2xi2;
u *= t2xi;
bool success2 = false;
for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(etas); i++) {
Fp2 t1;
Fp2::mul(t1, etas[i], candi);
Fp2::sqr(t2, t1);
t2 *= v;
if (t2 == u && !success && !success2) {
P.y = t1;
success2 = true;
}
}
assert(success || success2);
if (!success) {
nume *= t2xi;
}
if (isNegSign(t) != isNegSign(P.y)) {
Fp2::neg(P.y, P.y);
}
P.y *= deno;
P.x = nume;
P.z = deno;
}
// https://github.com/algorand/bls_sigs_ref
void osswu2_help(Point& P, const Fp2& t) const void osswu2_help(Point& P, const Fp2& t) const
{ {
Fp2 t2, t2xi; Fp2 t2, t2xi;
Fp2::sqr(t2, t); Fp2::sqr(t2, t);
Fp2 den, den2; Fp2 den, den2;
// Fp2::mul(t2xi, t2, xi);
mul_xi(t2xi, t2); mul_xi(t2xi, t2);
den = t2xi; den = t2xi;
Fp2::sqr(den2, den); Fp2::sqr(den2, den);
@ -473,13 +562,23 @@ struct MapToG2_WB19 {
add(Q, work, work2); add(Q, work, work2);
#endif #endif
} }
template<class T>
void put(const T& P) const
{
const int base = 10;
printf("x=%s\n", P.x.getStr(base).c_str());
printf("y=%s\n", P.y.getStr(base).c_str());
printf("z=%s\n", P.z.getStr(base).c_str());
}
void opt_swu2_map(G2& P, const Fp2& t, const Fp2 *t2 = 0) const void opt_swu2_map(G2& P, const Fp2& t, const Fp2 *t2 = 0) const
{ {
Point Pp; Point Pp;
osswu2_help(Pp, t); osswu2_help(Pp, t);
//put(Pp);
if (t2) { if (t2) {
Point P2; Point P2;
osswu2_help(P2, *t2); osswu2_help(P2, *t2);
//put(P2);
add(Pp, Pp, P2); add(Pp, Pp, P2);
} }
iso3(P, Pp); iso3(P, Pp);

@ -1,3 +1,4 @@
#define PUT(x) std::cout << #x "=" << (x) << std::endl;
#include <cybozu/test.hpp> #include <cybozu/test.hpp>
#include <cybozu/sha2.hpp> #include <cybozu/sha2.hpp>
#include <mcl/bls12_381.hpp> #include <mcl/bls12_381.hpp>
@ -6,8 +7,6 @@
#include <cybozu/atoi.hpp> #include <cybozu/atoi.hpp>
#include <cybozu/file.hpp> #include <cybozu/file.hpp>
#define PUT(x) std::cout << #x "=" << (x) << std::endl;
using namespace mcl; using namespace mcl;
using namespace mcl::bn; using namespace mcl::bn;
@ -172,8 +171,10 @@ void ethMsgToG2test()
CYBOZU_TEST_EQUAL(out, ok); CYBOZU_TEST_EQUAL(out, ok);
} }
void test2() template<class T>
void test2(const T& mapto)
{ {
(void)mapto;
/* /*
testHashToBaseFP2 testHashToBaseFP2
https://github.com/status-im/nim-blscurve/blob/de64516a5933a6e8ebb01a346430e61a201b5775/blscurve/hash_to_curve.nim#L492 https://github.com/status-im/nim-blscurve/blob/de64516a5933a6e8ebb01a346430e61a201b5775/blscurve/hash_to_curve.nim#L492
@ -219,14 +220,38 @@ void test2()
{ {
// https://media.githubusercontent.com/media/ethereum/eth2.0-spec-tests/v0.10.1/tests/general/phase0/bls/sign/small/sign_case_11b8c7cad5238946/data.yaml // https://media.githubusercontent.com/media/ethereum/eth2.0-spec-tests/v0.10.1/tests/general/phase0/bls/sign/small/sign_case_11b8c7cad5238946/data.yaml
const char *secs = "47b8192d77bf871b62e87859d653922725724a5c031afeabc60bcef5ff665138"; const char *secs = "47b8192d77bf871b62e87859d653922725724a5c031afeabc60bcef5ff665138";
const char msg[32] = {}; const char msg[33] = {};
const char *expect = "b2deb7c656c86cb18c43dae94b21b107595486438e0b906f3bdb29fa316d0fc3cab1fc04c6ec9879c773849f2564d39317bfa948b4a35fc8509beafd3a2575c25c077ba8bca4df06cb547fe7ca3b107d49794b7132ef3b5493a6ffb2aad2a441"; const char *expect = "b2deb7c656c86cb18c43dae94b21b107595486438e0b906f3bdb29fa316d0fc3cab1fc04c6ec9879c773849f2564d39317bfa948b4a35fc8509beafd3a2575c25c077ba8bca4df06cb547fe7ca3b107d49794b7132ef3b5493a6ffb2aad2a441";
Fr sec; Fr sec;
sec.deserializeHexStr(secs); sec.deserializeHexStr(secs);
G2 Q; G2 Q;
Q.deserializeHexStr(expect); Q.deserializeHexStr(expect);
Q *= (1/sec); Q *= (1/sec);
G2 P;
const char *dst = "BLS_SIG_BLS12381G2-SHA256-SSWU-RO-_POP_";
std::cout << std::hex;
ethMsgToG2(P, msg, 33, dst, strlen(dst));
printf("P=%s\n", P.serializeToHexStr().c_str());
printf("Q=%s\n", Q.serializeToHexStr().c_str()); printf("Q=%s\n", Q.serializeToHexStr().c_str());
mapto.put(P);
printf("equal %d\n", P == Q);
PointStr ss = {
{
"3257676086538823567761244186080544403330427395946948635449582231233180442322077484215757257097813156392664917178234",
"228537154970146118588036771068753907531432250550232803895899422656339347346840810590265440478956079727608969412311",
},
{
"2211656311977487430400091470761449132135875543285725344573261083165139360734602590585740129428161178745780787382986",
"40258781102313547933704047733645277081466097003572358028270922475602169023300010845551344432311507156784289541037",
},
{
"3554635405737095173231135338330740471713348364117258010850826274365262386961694608537862757803628655357449929362973",
"3305133470803621861948711123350198492693369595391902116552614265910644738630055172693143208260379598437272858586799",
},
};
Point RR;
set(RR, ss);
mapto.put(RR);
} }
} }
@ -509,13 +534,46 @@ void testVec(const char *file)
} }
} }
template<class T>
void test3(const T& mapto)
{
Fp2Str ts = {
"1918231859236664604157448091070531325862162392395253569013354101088957561890652491757605826252839368362075816084620",
"1765592454498940438559713185757713516213027777891663285362602185795653989012303939547547418058658378320847225866857",
};
PointStr out1s = {
{
"3927184272261705576225284664838663573624313247854459615864888213007837227449093837336748448846489186151562481034580",
"1903293468617299241460799312855927163610998535569367868293984916087966126786510088134190993502241498025510393259948",
},
{
"3991322739214666504999201807778913642377537002372597995520099276113880862779909709825029178857593814896063515454176",
"2999367925154329126226224834594837693635617675385117964685771461463180146028553717562548600391126160503718637741311",
},
{
"2578853905647618145305524664579860566455691148296386065391659245709237478565628968511959291772795541098532647163712",
"3910188857576114167072883940429120413632909260968721432280195359371907407125083761682822023489835923188989938783197",
},
};
Fp2 t;
set(t, ts);
Point P, Q;
mapto.optimized_swu_G2(P, t);
set(Q, out1s);
CYBOZU_TEST_EQUAL(P.x, Q.x);
CYBOZU_TEST_EQUAL(P.y, Q.y);
CYBOZU_TEST_EQUAL(P.z, Q.z);
}
CYBOZU_TEST_AUTO(test) CYBOZU_TEST_AUTO(test)
{ {
initPairing(mcl::BLS12_381); initPairing(mcl::BLS12_381);
Fp::setETHserialization(true); Fp::setETHserialization(true);
bn::setMapToMode(MCL_MAP_TO_MODE_WB19); bn::setMapToMode(MCL_MAP_TO_MODE_WB19);
const mcl::bn::local::MapToG2_WB19& mapto = BN::param.mapTo.mapToG2_WB19_; const mcl::bn::local::MapToG2_WB19& mapto = BN::param.mapTo.mapToG2_WB19_;
test2(); test3(mapto);
return;
test2(mapto);
osswu2_helpTest(mapto); osswu2_helpTest(mapto);
addTest(mapto); addTest(mapto);
iso3Test(mapto); iso3Test(mapto);

Loading…
Cancel
Save