herumi / mcl

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

MapToG1 seems to return unexpected values (is it Draft07?) #79

Closed tkstanczak closed 3 years ago

tkstanczak commented 4 years ago

TL;DR MapToG2, MulVec, Add, Pairing, Mode <- I am getting correct number here MapToG1 <- I am getting unexpected numbers

===

I was able to implement all of these with herumi/mcl except for MapToG1 https://eips.ethereum.org/EIPS/eip-2537

I was taking test cases from here (and they were verified with two other libraries) https://github.com/matter-labs/eip1962/blob/master/src/test/test_vectors/eip2537/fp_to_g1.csv

Code that I use:

    [DllImport(MclBls12Lib)]
    public static extern int mclBnFp_mapToG1(ref G1 y, ref Fp x);

    [DllImport(MclBls12Lib)]
    public static extern int mclBnFp2_mapToG2(ref G2 y, ref Fp2 x);

    [DllImport(MclBls12Lib)]
    public static extern unsafe void mclBnG1_mulVec(ref G1 z, void* x, void* y, int size);

    [DllImport(MclBls12Lib)]
    public static extern unsafe void mclBnG2_mulVec(ref G2 z, void* x, void* y, int size);

    public (byte[], bool) Run(byte[] inputData)
    {
        Span<byte> inputDataSpan = stackalloc byte[64];
        Mcl.PrepareInputData(inputData, inputDataSpan);

        (byte[], bool) result;
        if (Common.TryReadFp(inputDataSpan, 0, out Fp fp))
        {
            G1 g1 = fp.MapToG1();
            result = (Common.SerializeEthG1(g1), true);
        }
        else
        {
            result = (Bytes.Empty, false);
        }

        return result;
    }

    public static bool TryReadFp(in Span<byte> inputDataSpan, in int offset, out Fp fp)
    {
        bool success;
        if (inputDataSpan.Length < offset + LenFp ||
            !Bytes.AreEqual(Zero16, inputDataSpan.Slice(offset, 16)))
        {
            fp = new Fp();
            success = false;
        }
        else
        {
            Span<byte> fpBytes = inputDataSpan.Slice(offset + 0 * LenFp, LenFp);
            fp = new Fp();
            Bytes.ChangeEndianness8(fpBytes);
            fp.FpSetLittleEndianMod(fpBytes, 48);
            success = fp.IsValid();
        }

        return success;
    }

    public static void PrepareInputData(byte[] inputData, Span<byte> preparedData)
    {
        // nothing special here - just clones the array to span
    }
jochem-brouwer commented 4 years ago

We are using the mcl-wasm implementation at EthereumJS-VM.

What values do you get for the Fp 0e885bb33996e12f07da69073e2c0cc880bc8eff26d2a724299eb12d54f4bcf26f4748bb020e80a7e3794a7b0e47a641 point?

We get the G1 point:

5c2c27c2c7d9717c363bacb2546f96d9eae5b7e964fe01719e95e0df006a7d281b14cc25afa31329c7f7dc487c9b323 187193f8df8ba8618b2b7b06704ab7e33c49fc8916a47935f57f9330c351827a107187d0233d9421adf1a08f12265c7d

Which does not match the test case (this is test 2 of the MapG1 test file which you linked).

herumi commented 4 years ago

I have not implemented MapG1 compatible with IEFT spec.

herumi commented 4 years ago

MapG2 is compatible with IEFT spec. Do you need MapG1?

tkstanczak commented 4 years ago

Hi @herumi, yes for Ethereum 1 Berlin hard fork -> MapG1 is the only thing missing -> everyhting else is passing tests nicely (amazing work from you!). Is that much work - would you be able to implement it? Is there anything that you would need from us to support it? I have created a simple CSharp binding pull request but I could polish it a bit more for you to show that we care :)

tkstanczak commented 4 years ago

image

tkstanczak commented 4 years ago

These are test cases: https://github.com/matter-labs/eip1962/blob/master/src/test/test_vectors/eip2537/fp_to_g1.csv

tkstanczak commented 4 years ago

We have the herumi/mcl supporting both our Eth1 and Eth2 implementations.

herumi commented 4 years ago

I see. I'll implement maptoG1, but it will take a while because I have many tasks.

herumi commented 4 years ago

I've implemented mclBnG1_hashAndMapTo to support hash-to-curve-09 with dst="BLS_SIG_BLS12381G2_XMD:SHA-256_SSWU_RO_POP_".

herumi commented 4 years ago

You can use the function as setHashOf at mcl-wasm.

jochem-brouwer commented 4 years ago

Hey @herumi, thanks a lot so far 😄 ! We'd need the mclBnFp_mapToG1 function for the Ethereum EIP so we can implement the final precompile using this library. Could you implement this as well?

herumi commented 4 years ago

I see. Now mcl::bn::mapToG1 (so mclBnFp_mapToG1) is compatible to eip2537/fp_to_g1.csv . https://github.com/herumi/mcl/commit/7909bd297bd6b9652e9d89ce19b04feb4edfabf6#diff-dda4c369b6f5cbb9b85d5e18eb7948eb

jochem-brouwer commented 4 years ago

Thanks a lot! Could you also expose this in mcl-wasm? 😄

herumi commented 4 years ago

I updated it. https://github.com/herumi/mcl-wasm/blob/master/eth-test.js#L12

jochem-brouwer commented 3 years ago

We implemented it - thanks again! 😄