diff --git a/test/contracts/src/BLS12381.sol b/test/contracts/src/BLS12381.sol new file mode 100644 index 0000000000..b5c139c551 --- /dev/null +++ b/test/contracts/src/BLS12381.sol @@ -0,0 +1,87 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +contract BLS12381Helper2 { + // Define the addresses for the BLS12-381 precompiles + address constant BLS12_G1ADD = 0x000000000000000000000000000000000000000b; // Replace with actual address + address constant BLS12_G1MULTIEXP = 0x000000000000000000000000000000000000000C; // Replace with actual address + address constant BLS12_G2ADD = 0x000000000000000000000000000000000000000d; // Replace with actual address + address constant BLS12_G2MULTIEXP = 0x000000000000000000000000000000000000000E; // Replace with actual address + + function testAll() public returns (bool) { + // Hardcoded inputs and expected outputs for each precompile test vector + // Test vectors from https://github.com/ethereum/EIPs/tree/master/assets/eip-2537 + // Only the first case was tested for each precompile + bytes memory g1AddInput = hex"0000000000000000000000000000000017f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb0000000000000000000000000000000008b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e100000000000000000000000000000000112b98340eee2777cc3c14163dea3ec97977ac3dc5c70da32e6e87578f44912e902ccef9efe28d4a78b8999dfbca942600000000000000000000000000000000186b28d92356c4dfec4b5201ad099dbdede3781f8998ddf929b4cd7756192185ca7b8f4ef7088f813270ac3d48868a21"; + bytes memory g1AddExpected = hex"000000000000000000000000000000000a40300ce2dec9888b60690e9a41d3004fda4886854573974fab73b046d3147ba5b7a5bde85279ffede1b45b3918d82d0000000000000000000000000000000006d3d887e9f53b9ec4eb6cedf5607226754b07c01ace7834f57f3e7315faefb739e59018e22c492006190fba4a870025"; + + bytes memory g1MultiExpInput = hex"0000000000000000000000000000000017f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb0000000000000000000000000000000008b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e10000000000000000000000000000000000000000000000000000000000000002"; + bytes memory g1MultiExpExpected = hex"000000000000000000000000000000000572cbea904d67468808c8eb50a9450c9721db309128012543902d0ac358a62ae28f75bb8f1c7c42c39a8c5529bf0f4e00000000000000000000000000000000166a9d8cabc673a322fda673779d8e3822ba3ecb8670e461f73bb9021d5fd76a4c56d9d4cd16bd1bba86881979749d28"; + + bytes memory g2AddInput = hex"00000000000000000000000000000000024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80000000000000000000000000000000013e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e000000000000000000000000000000000ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801000000000000000000000000000000000606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be00000000000000000000000000000000103121a2ceaae586d240843a398967325f8eb5a93e8fea99b62b9f88d8556c80dd726a4b30e84a36eeabaf3592937f2700000000000000000000000000000000086b990f3da2aeac0a36143b7d7c824428215140db1bb859338764cb58458f081d92664f9053b50b3fbd2e4723121b68000000000000000000000000000000000f9e7ba9a86a8f7624aa2b42dcc8772e1af4ae115685e60abc2c9b90242167acef3d0be4050bf935eed7c3b6fc7ba77e000000000000000000000000000000000d22c3652d0dc6f0fc9316e14268477c2049ef772e852108d269d9c38dba1d4802e8dae479818184c08f9a569d878451"; + bytes memory g2AddExpected = hex"000000000000000000000000000000000b54a8a7b08bd6827ed9a797de216b8c9057b3a9ca93e2f88e7f04f19accc42da90d883632b9ca4dc38d013f71ede4db00000000000000000000000000000000077eba4eecf0bd764dce8ed5f45040dd8f3b3427cb35230509482c14651713282946306247866dfe39a8e33016fcbe520000000000000000000000000000000014e60a76a29ef85cbd69f251b9f29147b67cfe3ed2823d3f9776b3a0efd2731941d47436dc6d2b58d9e65f8438bad073000000000000000000000000000000001586c3c910d95754fef7a732df78e279c3d37431c6a2b77e67a00c7c130a8fcd4d19f159cbeb997a178108fffffcbd20"; + + bytes memory g2MultiExpInput = hex"00000000000000000000000000000000024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80000000000000000000000000000000013e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e000000000000000000000000000000000ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801000000000000000000000000000000000606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be0000000000000000000000000000000000000000000000000000000000000002"; + bytes memory g2MultiExpExpected = hex"000000000000000000000000000000001638533957d540a9d2370f17cc7ed5863bc0b995b8825e0ee1ea1e1e4d00dbae81f14b0bf3611b78c952aacab827a053000000000000000000000000000000000a4edef9c1ed7f729f520e47730a124fd70662a904ba1074728114d1031e1572c6c886f6b57ec72a6178288c47c33577000000000000000000000000000000000468fb440d82b0630aeb8dca2b5256789a66da69bf91009cbfe6bd221e47aa8ae88dece9764bf3bd999d95d71e4c9899000000000000000000000000000000000f6d4552fa65dd2638b361543f887136a43253d9c66c411697003f7a13c308f5422e1aa0a59c8967acdefd8b6e36ccf3"; + + // Test G1ADD + (bool success, bytes memory result) = BLS12_G1ADD.call(g1AddInput); + require(success, "G1ADD precompile failed"); + require(keccak256(result) == keccak256(g1AddExpected), "G1ADD precompile output mismatch"); + + // Test G1MULTIEXP + (success, result) = BLS12_G1MULTIEXP.call(g1MultiExpInput); + require(success, "G1MULTIEXP precompile failed"); + require(keccak256(result) == keccak256(g1MultiExpExpected), "G1MULTIEXP precompile output mismatch"); + + // Test G2ADD + (success, result) = BLS12_G2ADD.call(g2AddInput); + require(success, "G2ADD precompile failed"); + require(keccak256(result) == keccak256(g2AddExpected), "G2ADD precompile output mismatch"); + + // Test G2MULTIEXP + (success, result) = BLS12_G2MULTIEXP.call(g2MultiExpInput); + require(success, "G2MULTIEXP precompile failed"); + require(keccak256(result) == keccak256(g2MultiExpExpected), "G2MULTIEXP precompile output mismatch"); + + return true; + } +} + +contract BLS12381Helper1 { + // Define the addresses for the BLS12-381 precompiles + address constant BLS12_PAIRING = 0x000000000000000000000000000000000000000F; // Replace with actual address + address constant BLS12_MAP_FP_TO_G1 = 0x0000000000000000000000000000000000000010; // Replace with actual address + address constant BLS12_MAP_FP2_TO_G2 =0x0000000000000000000000000000000000000011; // Replace with actual address + + function testAll() public returns (bool) { + // Hardcoded inputs and expected outputs for each precompile test vector + // Test vectors from https://github.com/ethereum/EIPs/tree/master/assets/eip-2537 + // Only the first case was tested for each precompile + bytes memory pairingInput = hex"0000000000000000000000000000000017f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb0000000000000000000000000000000008b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80000000000000000000000000000000013e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e000000000000000000000000000000000ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801000000000000000000000000000000000606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be"; + bytes memory pairingExpected = hex"0000000000000000000000000000000000000000000000000000000000000001"; + + bytes memory mapFpToG1Input = hex"00000000000000000000000000000000156c8a6a2c184569d69a76be144b5cdc5141d2d2ca4fe341f011e25e3969c55ad9e9b9ce2eb833c81a908e5fa4ac5f03"; + bytes memory mapFpToG1Expected = hex"00000000000000000000000000000000184bb665c37ff561a89ec2122dd343f20e0f4cbcaec84e3c3052ea81d1834e192c426074b02ed3dca4e7676ce4ce48ba0000000000000000000000000000000004407b8d35af4dacc809927071fc0405218f1401a6d15af775810e4e460064bcc9468beeba82fdc751be70476c888bf3"; + + bytes memory mapFp2ToG2Input = hex"0000000000000000000000000000000007355d25caf6e7f2f0cb2812ca0e513bd026ed09dda65b177500fa31714e09ea0ded3a078b526bed3307f804d4b93b040000000000000000000000000000000002829ce3c021339ccb5caf3e187f6370e1e2a311dec9b75363117063ab2015603ff52c3d3b98f19c2f65575e99e8b78c"; + bytes memory mapFp2ToG2Expected = hex"0000000000000000000000000000000000e7f4568a82b4b7dc1f14c6aaa055edf51502319c723c4dc2688c7fe5944c213f510328082396515734b6612c4e7bb700000000000000000000000000000000126b855e9e69b1f691f816e48ac6977664d24d99f8724868a184186469ddfd4617367e94527d4b74fc86413483afb35b000000000000000000000000000000000caead0fd7b6176c01436833c79d305c78be307da5f6af6c133c47311def6ff1e0babf57a0fb5539fce7ee12407b0a42000000000000000000000000000000001498aadcf7ae2b345243e281ae076df6de84455d766ab6fcdaad71fab60abb2e8b980a440043cd305db09d283c895e3d"; + + // Test PAIRING + (bool success, bytes memory result) = BLS12_PAIRING.call(pairingInput); + require(success, "PAIRING precompile failed"); + require(keccak256(result) == keccak256(pairingExpected), "PAIRING precompile output mismatch"); + + // Test MAP_FP_TO_G1 + (success, result) = BLS12_MAP_FP_TO_G1.call(mapFpToG1Input); + require(success, "MAP_FP_TO_G1 precompile failed"); + require(keccak256(result) == keccak256(mapFpToG1Expected), "MAP_FP_TO_G1 precompile output mismatch"); + + // // // Test MAP_FP2_TO_G2 + (success, result) = BLS12_MAP_FP2_TO_G2.call(mapFp2ToG2Input); + require(success, "MAP_FP2_TO_G2 precompile failed"); + require(keccak256(result) == keccak256(mapFp2ToG2Expected), "MAP_FP2_TO_G2 precompile output mismatch"); + + return true; + } +} \ No newline at end of file diff --git a/test/suites/dev/moonbase/test-precompile/test-precompile-bls12381.ts b/test/suites/dev/moonbase/test-precompile/test-precompile-bls12381.ts new file mode 100644 index 0000000000..f84f250852 --- /dev/null +++ b/test/suites/dev/moonbase/test-precompile/test-precompile-bls12381.ts @@ -0,0 +1,55 @@ +import "@moonbeam-network/api-augment"; + +import { beforeAll, deployCreateCompiledContract, describeSuite, expect } from "@moonwall/cli"; +import { encodeFunctionData } from "viem"; + +describeSuite({ + id: "D012999", + title: "Precompiles - BLS123_81", + foundationMethods: "dev", + testCases: ({ context, it, log }) => { + let helper1Address; + let helper1Abi; + + let helper2Address; + let helper2Abi; + + beforeAll(async () => { + const { contractAddress, abi } = await deployCreateCompiledContract(context, "BLS12381Helper1"); + helper1Address = contractAddress; + helper1Abi = abi; + + const { contractAddress: contractAddress2, abi: abi2 } = await deployCreateCompiledContract(context, "BLS12381Helper2"); + helper2Address = contractAddress2; + helper2Abi = abi2; + }); + + it({ + id: "T01", + title: "Test all precompiles with test vectors", + test: async () => { + + // BLS12381.sol contains the test vectors for the precompiles + // and splits them into two contracts to avoid hitting the gas limit + + const tx = await context.viem().sendTransaction({ + to: helper1Address, + data: encodeFunctionData({abi: helper1Abi, functionName: "testAll", args: []}), + }); + await context.createBlock(); + + const receipt = await context.viem().getTransactionReceipt({ hash: tx}); + expect(receipt.status).toBe("success"); + + const tx2 = await context.viem().sendTransaction({ + to: helper2Address, + data: encodeFunctionData({abi: helper2Abi, functionName: "testAll", args: []}), + }); + await context.createBlock(); + + const receipt2 = await context.viem().getTransactionReceipt({ hash: tx2}); + expect(receipt2.status).toBe("success"); + }, + }); + + }});