herumi / mcl

a portable and fast pairing-based cryptography library
BSD 3-Clause "New" or "Revised" License
458 stars 157 forks source link

compare with ate-pairing #62

Closed huyuguang closed 5 years ago

huyuguang commented 5 years ago

In https://github.com/herumi/libsnark, you said: ""mcl_bn128": an alternative to "bn128", using the new MCL elliptic curve library. Somewhat slower on x86-64 but supported and optimized for different architectures."

I just added mcl_bn128 to libsnark (latest version) base on your fork(just need to change some include path and function name). But I'm curious the percent of slow, that is for x64 CPU, should I use mcl_bn128 to replace the bn128?

herumi commented 5 years ago

mcl is about 30% slower than ate_pairing for BN_SNARK1 for x64 CPU, so it is not necessary to use mcl_bn128 now.

huyuguang commented 5 years ago

Very thanks!

huyuguang commented 5 years ago

Can I mix them? For example, I use mcl, and link libsnark.a which use ate-pairing. As my understanding, since the curves are same, I can convert a mcl::bn256::Fr to libsnark::Fr? How to convert? Maybe through the underlying mpz_t?

huyuguang commented 5 years ago
typedef libff::Fr<default_r1cs_ppzksnark_pp> ZkFr;
typedef mcl::bn256::Fr MclFr;
ZkFr MclFrToZkFr(MclFr const& mcl_fr) {
  mpz_class m = mcl_fr.getMpz();
  return ZkFr(libff::bigint<ZkFr::num_limbs>(m.get_mpz_t()));
}

I tested the above code, works fine. Very thanks.

ps: I need to prove mimc hash (base on the finite field) through libsnark. I use mcl in my function and need to convert to libff::Fr.

herumi commented 5 years ago

If sizeof(libsnark::Fr) == sizeof(mcl::Fr), then it may be byte compatible to mcl::Fr and you may be able to use *reinterpret_cast<const libsnark::Fr*>(&x) for mcl::Fr x.

G1/G2 operations such as scalar multiplication of mcl are faster than bn128. So if you use many elliptic operations and few pairing operations, then it may be better to use mcl_bn128. Please take a benchmark at yourself.

huyuguang commented 5 years ago

If sizeof(libsnark::Fr) == sizeof(mcl::Fr), then it may be byte compatible to mcl::Fr and you may be able to use *reinterpret_cast<const libsnark::Fr*>(&x) for mcl::Fr x.

G1/G2 operations such as scalar multiplication of mcl are faster than bn128. So if you use many elliptic operations and few pairing operations, then it may be better to use mcl_bn128. Please take a benchmark at yourself.

Oh, it's very important information, thank you! In my project, most of the operation is ecc_mul and ecc_add, only 0.1% pairing operation. So I think I should mix them up: keep used mcl in my project and use ate-pairing in libsnark.

huyuguang commented 5 years ago

Something weird: I replaced the ate-pairing with mcl in libsnark, and got 20% performance improvement. Why? ate-pairing version: use libsnark master branch directly. mcl version: use latest mcl and implement the mcl_bn128_g1.cpp and so on.

herumi commented 5 years ago

Thank you for your information. libsnark uses many elliptic operations, then I don't think that it is strange.