diff --git a/lib/evmone_precompiles/CMakeLists.txt b/lib/evmone_precompiles/CMakeLists.txt index 6daaa8d78f..d89a182822 100644 --- a/lib/evmone_precompiles/CMakeLists.txt +++ b/lib/evmone_precompiles/CMakeLists.txt @@ -7,6 +7,8 @@ add_library(evmone::precompiles ALIAS evmone_precompiles) target_link_libraries(evmone_precompiles PUBLIC evmc::evmc_cpp PRIVATE evmone::evmmax) target_sources( evmone_precompiles PRIVATE + bn254.hpp + bn254.cpp ecc.hpp secp256k1.cpp secp256k1.hpp diff --git a/lib/evmone_precompiles/bn254.cpp b/lib/evmone_precompiles/bn254.cpp new file mode 100644 index 0000000000..3340593f30 --- /dev/null +++ b/lib/evmone_precompiles/bn254.cpp @@ -0,0 +1,421 @@ +// evmone: Fast Ethereum Virtual Machine implementation +// Copyright 2023 The evmone Authors. +// SPDX-License-Identifier: Apache-2.0 + +#include "bn254.hpp" + +namespace evmmax::bn254 +{ + +namespace +{ +const ModArith Fp{FieldPrime}; +const auto B = Fp.to_mont(3); +const auto B3 = Fp.to_mont(3 * 3); +} // namespace + +bool validate(const Point& pt) noexcept +{ + if (pt.is_inf()) + return true; + + const auto xm = Fp.to_mont(pt.x); + const auto ym = Fp.to_mont(pt.y); + const auto y2 = Fp.mul(ym, ym); + const auto x2 = Fp.mul(xm, xm); + const auto x3 = Fp.mul(x2, xm); + const auto x3_3 = Fp.add(x3, B); + return y2 == x3_3; +} + +Point add(const Point& pt1, const Point& pt2) noexcept +{ + if (pt1.is_inf()) + return pt2; + if (pt2.is_inf()) + return pt1; + + // b3 == 9 for y^2 == x^3 + 3 + const auto r = ecc::add(Fp, ecc::to_proj(Fp, pt1), ecc::to_proj(Fp, pt2), B3); + + return ecc::to_affine(Fp, field_inv, r); +} + +Point mul(const Point& pt, const uint256& c) noexcept +{ + if (pt.is_inf()) + return pt; + + if (c == 0) + return {0, 0}; + + const auto pr = ecc::mul(Fp, ecc::to_proj(Fp, pt), c, B3); + + return ecc::to_affine(Fp, field_inv, pr); +} + +uint256 field_inv(const ModArith& m, const uint256& x) noexcept +{ + // Computes modular exponentiation + // x^0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd45 + // Operations: 247 squares 56 multiplies + // Generated by github.com/mmcloughlin/addchain v0.4.0. + // addchain search + // 0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd45 + // > bn254_field_inv.acc + // addchain gen -tmpl expmod.tmpl bn254_field_inv.acc > bn254_field_inv.cpp + // + // Inversion computation is derived from the addition chain: + // + // _10 = 2*1 + // _11 = 1 + _10 + // _101 = _10 + _11 + // _110 = 1 + _101 + // _1000 = _10 + _110 + // _1101 = _101 + _1000 + // _10010 = _101 + _1101 + // _10011 = 1 + _10010 + // _10100 = 1 + _10011 + // _10111 = _11 + _10100 + // _11100 = _101 + _10111 + // _100000 = _1101 + _10011 + // _100011 = _11 + _100000 + // _101011 = _1000 + _100011 + // _101111 = _10011 + _11100 + // _1000001 = _10010 + _101111 + // _1010011 = _10010 + _1000001 + // _1011011 = _1000 + _1010011 + // _1100001 = _110 + _1011011 + // _1110101 = _10100 + _1100001 + // _10010001 = _11100 + _1110101 + // _10010101 = _100000 + _1110101 + // _10110101 = _100000 + _10010101 + // _10111011 = _110 + _10110101 + // _11000001 = _110 + _10111011 + // _11000011 = _10 + _11000001 + // _11010011 = _10010 + _11000001 + // _11100001 = _100000 + _11000001 + // _11100011 = _10 + _11100001 + // _11100111 = _110 + _11100001 + // i57 = ((_11000001 << 8 + _10010001) << 10 + _11100111) << 7 + // i76 = ((_10111 + i57) << 9 + _10011) << 7 + _1101 + // i109 = ((i76 << 14 + _1010011) << 9 + _11100001) << 8 + // i127 = ((_1000001 + i109) << 10 + _1011011) << 5 + _1101 + // i161 = ((i127 << 8 + _11) << 12 + _101011) << 12 + // i186 = ((_10111011 + i161) << 8 + _101111) << 14 + _10110101 + // i214 = ((i186 << 9 + _10010001) << 5 + _1101) << 12 + // i236 = ((_11100011 + i214) << 8 + _10010101) << 11 + _11010011 + // i268 = ((i236 << 7 + _1100001) << 11 + _100011) << 12 + // i288 = ((_1011011 + i268) << 9 + _11000011) << 8 + _11100111 + // return (i288 << 7 + _1110101) << 6 + _101 + // + // Operations: 247 squares 56 m.multiplies + // + // Generated by github.com/mmcloughlin/addchain v0.4.0. + + // Allocate Temporaries. + uint256 t0; + uint256 t1; + uint256 t2; + uint256 t3; + uint256 t4; + uint256 t5; + uint256 t6; + uint256 t7; + uint256 t8; + uint256 t9; + uint256 t10; + uint256 t11; + uint256 t12; + uint256 t13; + uint256 t14; + uint256 t15; + uint256 t16; + uint256 t17; + uint256 t18; + uint256 t19; + uint256 t20; + uint256 t21; + // Step 1: t8 = x^0x2 + t8 = m.mul(x, x); + + // Step 2: t15 = x^0x3 + t15 = m.mul(x, t8); + + // Step 3: z = x^0x5 + auto z = m.mul(t8, t15); + + // Step 4: t1 = x^0x6 + t1 = m.mul(x, z); + + // Step 5: t3 = x^0x8 + t3 = m.mul(t8, t1); + + // Step 6: t9 = x^0xd + t9 = m.mul(z, t3); + + // Step 7: t6 = x^0x12 + t6 = m.mul(z, t9); + + // Step 8: t19 = x^0x13 + t19 = m.mul(x, t6); + + // Step 9: t0 = x^0x14 + t0 = m.mul(x, t19); + + // Step 10: t20 = x^0x17 + t20 = m.mul(t15, t0); + + // Step 11: t2 = x^0x1c + t2 = m.mul(z, t20); + + // Step 12: t17 = x^0x20 + t17 = m.mul(t9, t19); + + // Step 13: t4 = x^0x23 + t4 = m.mul(t15, t17); + + // Step 14: t14 = x^0x2b + t14 = m.mul(t3, t4); + + // Step 15: t12 = x^0x2f + t12 = m.mul(t19, t2); + + // Step 16: t16 = x^0x41 + t16 = m.mul(t6, t12); + + // Step 17: t18 = x^0x53 + t18 = m.mul(t6, t16); + + // Step 18: t3 = x^0x5b + t3 = m.mul(t3, t18); + + // Step 19: t5 = x^0x61 + t5 = m.mul(t1, t3); + + // Step 20: t0 = x^0x75 + t0 = m.mul(t0, t5); + + // Step 21: t10 = x^0x91 + t10 = m.mul(t2, t0); + + // Step 22: t7 = x^0x95 + t7 = m.mul(t17, t0); + + // Step 23: t11 = x^0xb5 + t11 = m.mul(t17, t7); + + // Step 24: t13 = x^0xbb + t13 = m.mul(t1, t11); + + // Step 25: t21 = x^0xc1 + t21 = m.mul(t1, t13); + + // Step 26: t2 = x^0xc3 + t2 = m.mul(t8, t21); + + // Step 27: t6 = x^0xd3 + t6 = m.mul(t6, t21); + + // Step 28: t17 = x^0xe1 + t17 = m.mul(t17, t21); + + // Step 29: t8 = x^0xe3 + t8 = m.mul(t8, t17); + + // Step 30: t1 = x^0xe7 + t1 = m.mul(t1, t17); + + // Step 38: t21 = x^0xc100 + for (int i = 0; i < 8; ++i) + t21 = m.mul(t21, t21); + + // Step 39: t21 = x^0xc191 + t21 = m.mul(t10, t21); + + // Step 49: t21 = x^0x3064400 + for (int i = 0; i < 10; ++i) + t21 = m.mul(t21, t21); + + // Step 50: t21 = x^0x30644e7 + t21 = m.mul(t1, t21); + + // Step 57: t21 = x^0x183227380 + for (int i = 0; i < 7; ++i) + t21 = m.mul(t21, t21); + + // Step 58: t20 = x^0x183227397 + t20 = m.mul(t20, t21); + + // Step 67: t20 = x^0x30644e72e00 + for (int i = 0; i < 9; ++i) + t20 = m.mul(t20, t20); + + // Step 68: t19 = x^0x30644e72e13 + t19 = m.mul(t19, t20); + + // Step 75: t19 = x^0x1832273970980 + for (int i = 0; i < 7; ++i) + t19 = m.mul(t19, t19); + + // Step 76: t19 = x^0x183227397098d + t19 = m.mul(t9, t19); + + // Step 90: t19 = x^0x60c89ce5c2634000 + for (int i = 0; i < 14; ++i) + t19 = m.mul(t19, t19); + + // Step 91: t18 = x^0x60c89ce5c2634053 + t18 = m.mul(t18, t19); + + // Step 100: t18 = x^0xc19139cb84c680a600 + for (int i = 0; i < 9; ++i) + t18 = m.mul(t18, t18); + + // Step 101: t17 = x^0xc19139cb84c680a6e1 + t17 = m.mul(t17, t18); + + // Step 109: t17 = x^0xc19139cb84c680a6e100 + for (int i = 0; i < 8; ++i) + t17 = m.mul(t17, t17); + + // Step 110: t16 = x^0xc19139cb84c680a6e141 + t16 = m.mul(t16, t17); + + // Step 120: t16 = x^0x30644e72e131a029b850400 + for (int i = 0; i < 10; ++i) + t16 = m.mul(t16, t16); + + // Step 121: t16 = x^0x30644e72e131a029b85045b + t16 = m.mul(t3, t16); + + // Step 126: t16 = x^0x60c89ce5c263405370a08b60 + for (int i = 0; i < 5; ++i) + t16 = m.mul(t16, t16); + + // Step 127: t16 = x^0x60c89ce5c263405370a08b6d + t16 = m.mul(t9, t16); + + // Step 135: t16 = x^0x60c89ce5c263405370a08b6d00 + for (int i = 0; i < 8; ++i) + t16 = m.mul(t16, t16); + + // Step 136: t15 = x^0x60c89ce5c263405370a08b6d03 + t15 = m.mul(t15, t16); + + // Step 148: t15 = x^0x60c89ce5c263405370a08b6d03000 + for (int i = 0; i < 12; ++i) + t15 = m.mul(t15, t15); + + // Step 149: t14 = x^0x60c89ce5c263405370a08b6d0302b + t14 = m.mul(t14, t15); + + // Step 161: t14 = x^0x60c89ce5c263405370a08b6d0302b000 + for (int i = 0; i < 12; ++i) + t14 = m.mul(t14, t14); + + // Step 162: t13 = x^0x60c89ce5c263405370a08b6d0302b0bb + t13 = m.mul(t13, t14); + + // Step 170: t13 = x^0x60c89ce5c263405370a08b6d0302b0bb00 + for (int i = 0; i < 8; ++i) + t13 = m.mul(t13, t13); + + // Step 171: t12 = x^0x60c89ce5c263405370a08b6d0302b0bb2f + t12 = m.mul(t12, t13); + + // Step 185: t12 = x^0x183227397098d014dc2822db40c0ac2ecbc000 + for (int i = 0; i < 14; ++i) + t12 = m.mul(t12, t12); + + // Step 186: t11 = x^0x183227397098d014dc2822db40c0ac2ecbc0b5 + t11 = m.mul(t11, t12); + + // Step 195: t11 = x^0x30644e72e131a029b85045b68181585d97816a00 + for (int i = 0; i < 9; ++i) + t11 = m.mul(t11, t11); + + // Step 196: t10 = x^0x30644e72e131a029b85045b68181585d97816a91 + t10 = m.mul(t10, t11); + + // Step 201: t10 = x^0x60c89ce5c263405370a08b6d0302b0bb2f02d5220 + for (int i = 0; i < 5; ++i) + t10 = m.mul(t10, t10); + + // Step 202: t9 = x^0x60c89ce5c263405370a08b6d0302b0bb2f02d522d + t9 = m.mul(t9, t10); + + // Step 214: t9 = x^0x60c89ce5c263405370a08b6d0302b0bb2f02d522d000 + for (int i = 0; i < 12; ++i) + t9 = m.mul(t9, t9); + + // Step 215: t8 = x^0x60c89ce5c263405370a08b6d0302b0bb2f02d522d0e3 + t8 = m.mul(t8, t9); + + // Step 223: t8 = x^0x60c89ce5c263405370a08b6d0302b0bb2f02d522d0e300 + for (int i = 0; i < 8; ++i) + t8 = m.mul(t8, t8); + + // Step 224: t7 = x^0x60c89ce5c263405370a08b6d0302b0bb2f02d522d0e395 + t7 = m.mul(t7, t8); + + // Step 235: t7 = x^0x30644e72e131a029b85045b68181585d97816a916871ca800 + for (int i = 0; i < 11; ++i) + t7 = m.mul(t7, t7); + + // Step 236: t6 = x^0x30644e72e131a029b85045b68181585d97816a916871ca8d3 + t6 = m.mul(t6, t7); + + // Step 243: t6 = x^0x183227397098d014dc2822db40c0ac2ecbc0b548b438e546980 + for (int i = 0; i < 7; ++i) + t6 = m.mul(t6, t6); + + // Step 244: t5 = x^0x183227397098d014dc2822db40c0ac2ecbc0b548b438e5469e1 + t5 = m.mul(t5, t6); + + // Step 255: t5 = x^0xc19139cb84c680a6e14116da060561765e05aa45a1c72a34f0800 + for (int i = 0; i < 11; ++i) + t5 = m.mul(t5, t5); + + // Step 256: t4 = x^0xc19139cb84c680a6e14116da060561765e05aa45a1c72a34f0823 + t4 = m.mul(t4, t5); + + // Step 268: t4 = x^0xc19139cb84c680a6e14116da060561765e05aa45a1c72a34f0823000 + for (int i = 0; i < 12; ++i) + t4 = m.mul(t4, t4); + + // Step 269: t3 = x^0xc19139cb84c680a6e14116da060561765e05aa45a1c72a34f082305b + t3 = m.mul(t3, t4); + + // Step 278: t3 = x^0x183227397098d014dc2822db40c0ac2ecbc0b548b438e5469e10460b600 + for (int i = 0; i < 9; ++i) + t3 = m.mul(t3, t3); + + // Step 279: t2 = x^0x183227397098d014dc2822db40c0ac2ecbc0b548b438e5469e10460b6c3 + t2 = m.mul(t2, t3); + + // Step 287: t2 = x^0x183227397098d014dc2822db40c0ac2ecbc0b548b438e5469e10460b6c300 + for (int i = 0; i < 8; ++i) + t2 = m.mul(t2, t2); + + // Step 288: t1 = x^0x183227397098d014dc2822db40c0ac2ecbc0b548b438e5469e10460b6c3e7 + t1 = m.mul(t1, t2); + + // Step 295: t1 = x^0xc19139cb84c680a6e14116da060561765e05aa45a1c72a34f082305b61f380 + for (int i = 0; i < 7; ++i) + t1 = m.mul(t1, t1); + + // Step 296: t0 = x^0xc19139cb84c680a6e14116da060561765e05aa45a1c72a34f082305b61f3f5 + t0 = m.mul(t0, t1); + + // Step 302: t0 = x^0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd40 + for (int i = 0; i < 6; ++i) + t0 = m.mul(t0, t0); + + // Step 303: z = x^0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd45 + z = m.mul(z, t0); + + return z; +} + +} // namespace evmmax::bn254 diff --git a/lib/evmone_precompiles/bn254.hpp b/lib/evmone_precompiles/bn254.hpp new file mode 100644 index 0000000000..1f0d5f2412 --- /dev/null +++ b/lib/evmone_precompiles/bn254.hpp @@ -0,0 +1,39 @@ +// evmone: Fast Ethereum Virtual Machine implementation +// Copyright 2023 The evmone Authors. +// SPDX-License-Identifier: Apache-2.0 +#pragma once + +#include "ecc.hpp" + +namespace evmmax::bn254 +{ +using namespace intx; + +/// The bn254 field prime number (P). +inline constexpr auto FieldPrime = + 0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47_u256; + +using Point = ecc::Point; + +/// Validates that point is from the bn254 curve group +/// +/// Returns true if y^2 == x^3 + 3. Input is converted to the Montgomery form. +bool validate(const Point& pt) noexcept; + +/// Modular inversion for bn254 prime field. +/// +/// Computes 1/x mod P modular inversion by computing modular exponentiation x^(P-2), +/// where P is ::FieldPrime. +uint256 field_inv(const ModArith& m, const uint256& x) noexcept; + +/// Addition in bn254 curve group. +/// +/// Computes P ⊕ Q for two points in affine coordinates on the bn254 curve, +Point add(const Point& pt1, const Point& pt2) noexcept; + +/// Scalar multiplication in bn254 curve group. +/// +/// Computes [c]P for a point in affine coordinate on the bn254 curve, +Point mul(const Point& pt, const uint256& c) noexcept; + +} // namespace evmmax::bn254 diff --git a/test/state/precompiles.cpp b/test/state/precompiles.cpp index aeeebff6c0..8200b14f39 100644 --- a/test/state/precompiles.cpp +++ b/test/state/precompiles.cpp @@ -4,6 +4,7 @@ #include "precompiles.hpp" #include "precompiles_cache.hpp" +#include #include #include #include @@ -174,6 +175,61 @@ ExecutionResult ecrecover_execute(const uint8_t* input, size_t input_size, uint8 return {EVMC_SUCCESS, 0}; } +ExecutionResult ecadd_execute(const uint8_t* input, size_t input_size, uint8_t* output, + [[maybe_unused]] size_t output_size) noexcept +{ + assert(output_size >= 64); + + uint8_t input_buffer[128]{}; + if (input_size != 0) + std::memcpy(input_buffer, input, std::min(input_size, std::size(input_buffer))); + + ethash::hash256 h{}; + std::memcpy(h.bytes, input_buffer, sizeof(h)); + + const evmmax::bn254::Point p = {intx::be::unsafe::load(input_buffer), + intx::be::unsafe::load(input_buffer + 32)}; + const evmmax::bn254::Point q = {intx::be::unsafe::load(input_buffer + 64), + intx::be::unsafe::load(input_buffer + 96)}; + + if (evmmax::bn254::validate(p) && evmmax::bn254::validate(q)) + { + const auto res = evmmax::bn254::add(p, q); + intx::be::unsafe::store(output, res.x); + intx::be::unsafe::store(output + 32, res.y); + return {EVMC_SUCCESS, 64}; + } + else + return {EVMC_PRECOMPILE_FAILURE, 0}; +} + +ExecutionResult ecmul_execute(const uint8_t* input, size_t input_size, uint8_t* output, + [[maybe_unused]] size_t output_size) noexcept +{ + assert(output_size >= 64); + + uint8_t input_buffer[96]{}; + if (input_size != 0) + std::memcpy(input_buffer, input, std::min(input_size, std::size(input_buffer))); + + ethash::hash256 h{}; + std::memcpy(h.bytes, input_buffer, sizeof(h)); + + const evmmax::bn254::Point p = {intx::be::unsafe::load(input_buffer), + intx::be::unsafe::load(input_buffer + 32)}; + const auto c = intx::be::unsafe::load(input_buffer + 64); + + if (evmmax::bn254::validate(p)) + { + const auto res = evmmax::bn254::mul(p, c); + intx::be::unsafe::store(output, res.x); + intx::be::unsafe::store(output + 32, res.y); + return {EVMC_SUCCESS, 64}; + } + else + return {EVMC_PRECOMPILE_FAILURE, 0}; +} + ExecutionResult identity_execute(const uint8_t* input, size_t input_size, uint8_t* output, [[maybe_unused]] size_t output_size) noexcept { @@ -203,8 +259,8 @@ inline constexpr auto traits = []() noexcept { {ripemd160_analyze, dummy_execute}, {identity_analyze, identity_execute}, {expmod_analyze, dummy_execute}, - {ecadd_analyze, dummy_execute}, - {ecmul_analyze, dummy_execute}, + {ecadd_analyze, ecadd_execute}, + {ecmul_analyze, ecmul_execute}, {ecpairing_analyze, dummy_execute}, {blake2bf_analyze, dummy_execute}, }}; @@ -213,8 +269,8 @@ inline constexpr auto traits = []() noexcept { tbl[static_cast(PrecompileId::sha256)].execute = silkpre_sha256_execute; tbl[static_cast(PrecompileId::ripemd160)].execute = silkpre_ripemd160_execute; tbl[static_cast(PrecompileId::expmod)].execute = silkpre_expmod_execute; - tbl[static_cast(PrecompileId::ecadd)].execute = silkpre_ecadd_execute; - tbl[static_cast(PrecompileId::ecmul)].execute = silkpre_ecmul_execute; + // tbl[static_cast(PrecompileId::ecadd)].execute = silkpre_ecadd_execute; + // tbl[static_cast(PrecompileId::ecmul)].execute = silkpre_ecmul_execute; tbl[static_cast(PrecompileId::ecpairing)].execute = silkpre_ecpairing_execute; tbl[static_cast(PrecompileId::blake2bf)].execute = silkpre_blake2bf_execute; #endif diff --git a/test/unittests/CMakeLists.txt b/test/unittests/CMakeLists.txt index 589e1dcb7c..b2009ea29b 100644 --- a/test/unittests/CMakeLists.txt +++ b/test/unittests/CMakeLists.txt @@ -31,6 +31,8 @@ target_sources( evm_storage_test.cpp evm_other_test.cpp evm_benchmark_test.cpp + evmmax_bn254_add_test.cpp + evmmax_bn254_mul_test.cpp evmmax_test.cpp evmmax_secp256k1_test.cpp evmone_test.cpp diff --git a/test/unittests/evmmax_bn254_add_test.cpp b/test/unittests/evmmax_bn254_add_test.cpp new file mode 100644 index 0000000000..f8b1998aeb --- /dev/null +++ b/test/unittests/evmmax_bn254_add_test.cpp @@ -0,0 +1,167 @@ +// evmone: Fast Ethereum Virtual Machine implementation +// Copyright 2023 The evmone Authors. +// SPDX-License-Identifier: Apache-2.0 + +#include "../utils/utils.hpp" +#include "evmone_precompiles/bn254.hpp" +#include + +using namespace evmmax::bn254; +using namespace intx; + +namespace +{ +struct TestCase +{ + bytes input; + bytes expected_output; + + TestCase(bytes i, bytes o) : input{std::move(i)}, expected_output{std::move(o)} + { + input.resize(128); + expected_output.resize(64); + } +}; + +const TestCase + test_cases + [] = + { + {"0f25929bcb43d5a57391564615c9e70a992b10eafa4db109709649cf48c50dd216da2f5cb6be7a0aa72c440c53c9bbdfec6c36c7d515536431b3a865468acbba1de49a4b0233273bba8146af82042d004f2085ec982397db0d97da17204cc2860217327ffc463919bef80cc166d09c6172639d8589799928761bcd9f22c903d4"_hex, + "1f4d1d80177b1377743d1901f70d7389be7f7a35a35bfd234a8aaee615b88c49018683193ae021a2f8920fed186cde5d9b1365116865281ccf884c1f28b1df8f"_hex}, + {"1de49a4b0233273bba8146af82042d004f2085ec982397db0d97da17204cc2860217327ffc463919bef80cc166d09c6172639d8589799928761bcd9f22c903d400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"_hex, + "1de49a4b0233273bba8146af82042d004f2085ec982397db0d97da17204cc2860217327ffc463919bef80cc166d09c6172639d8589799928761bcd9f22c903d4"_hex}, + {"0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"_hex, + "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"_hex}, + {"0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002"_hex, + "030644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd315ed738c0e0a7c92e7845f96b2ae9c0a68a6a449e3538fc7ff3ebf7a5a18a2c4"_hex}, + {"0f25929bcb43d5a57391564615c9e70a992b10eafa4db109709649cf48c50dd216da2f5cb6be7a0aa72c440c53c9bbdfec6c36c7d515536431b3a865468acbba00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"_hex, + "0f25929bcb43d5a57391564615c9e70a992b10eafa4db109709649cf48c50dd216da2f5cb6be7a0aa72c440c53c9bbdfec6c36c7d515536431b3a865468acbba"_hex}, + {"000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f25929bcb43d5a57391564615c9e70a992b10eafa4db109709649cf48c50dd216da2f5cb6be7a0aa72c440c53c9bbdfec6c36c7d515536431b3a865468acbba"_hex, + "0f25929bcb43d5a57391564615c9e70a992b10eafa4db109709649cf48c50dd216da2f5cb6be7a0aa72c440c53c9bbdfec6c36c7d515536431b3a865468acbba"_hex}, + {"0f25929bcb43d5a57391564615c9e70a992b10eafa4db109709649cf48c50dd216da2f5cb6be7a0aa72c440c53c9bbdfec6c36c7d515536431b3a865468acbba0f25929bcb43d5a57391564615c9e70a992b10eafa4db109709649cf48c50dd216da2f5cb6be7a0aa72c440c53c9bbdfec6c36c7d515536431b3a865468acbba"_hex, + "1de49a4b0233273bba8146af82042d004f2085ec982397db0d97da17204cc2860217327ffc463919bef80cc166d09c6172639d8589799928761bcd9f22c903d4"_hex}, + {"0f25929bcb43d5a57391564615c9e70a992b10eafa4db109709649cf48c50dd216da2f5cb6be7a0aa72c440c53c9bbdfec6c36c7d515536431b3a865468acbba00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002"_hex, + "059a381fec09e29448a58ae8905f41d1eb8ff0ed755aa0f827821aefde02ec7d269d2516bf8c4f5798cc1267162e59add561e5537a328fe0f28a252fa287a72a"_hex}, + {"00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002"_hex, + "00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002"_hex}, + {"00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"_hex, + "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"_hex}, + {"0f25929bcb43d5a57391564615c9e70a992b10eafa4db109709649cf48c50dd216da2f5cb6be7a0aa72c440c53c9bbdfec6c36c7d515536431b3a865468acbba"_hex, + "0f25929bcb43d5a57391564615c9e70a992b10eafa4db109709649cf48c50dd216da2f5cb6be7a0aa72c440c53c9bbdfec6c36c7d515536431b3a865468acbba"_hex}, + {"1de49a4b0233273bba8146af82042d004f2085ec982397db0d97da17204cc2860217327ffc463919bef80cc166d09c6172639d8589799928761bcd9f22c903d40f25929bcb43d5a57391564615c9e70a992b10eafa4db109709649cf48c50dd216da2f5cb6be7a0aa72c440c53c9bbdfec6c36c7d515536431b3a865468acbba"_hex, + "1f4d1d80177b1377743d1901f70d7389be7f7a35a35bfd234a8aaee615b88c49018683193ae021a2f8920fed186cde5d9b1365116865281ccf884c1f28b1df8f"_hex}, + {"1f4d1d80177b1377743d1901f70d7389be7f7a35a35bfd234a8aaee615b88c492eddcb59a6517e86bfbe35c9691479fffc6e0580000ca2706c983ff7afcb1db81f4d1d80177b1377743d1901f70d7389be7f7a35a35bfd234a8aaee615b88c49018683193ae021a2f8920fed186cde5d9b1365116865281ccf884c1f28b1df8f"_hex, + "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"_hex}, + {"1f4d1d80177b1377743d1901f70d7389be7f7a35a35bfd234a8aaee615b88c492eddcb59a6517e86bfbe35c9691479fffc6e0580000ca2706c983ff7afcb1db81f4d1d80177b1377743d1901f70d7389be7f7a35a35bfd234a8aaee615b88c492eddcb59a6517e86bfbe35c9691479fffc6e0580000ca2706c983ff7afcb1db8"_hex, + "255e468453d7636cc1563e43f7521755f95e6c56043c7321b4ae04e772945fb00225c5f1623620fd84bfbab2d861a9d1e570f7727c540f403085998ebaf407c4"_hex}, + {"1f4d1d80177b1377743d1901f70d7389be7f7a35a35bfd234a8aaee615b88c492eddcb59a6517e86bfbe35c9691479fffc6e0580000ca2706c983ff7afcb1db800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"_hex, + "1f4d1d80177b1377743d1901f70d7389be7f7a35a35bfd234a8aaee615b88c492eddcb59a6517e86bfbe35c9691479fffc6e0580000ca2706c983ff7afcb1db8"_hex}, + {"00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000130644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd45"_hex, + "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"_hex}, + {"000000000000000000000000000000000000000000000000000000000000000130644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd4500000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002"_hex, + "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"_hex}, + {"000000000000000000000000000000000000000000000000000000000000000130644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd45000000000000000000000000000000000000000000000000000000000000000130644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd45"_hex, + "030644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd31a76dae6d3272396d0cbe61fced2bc532edac647851e3ac53ce1cc9c7e645a83"_hex}, + {"030644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd31a76dae6d3272396d0cbe61fced2bc532edac647851e3ac53ce1cc9c7e645a83000000000000000000000000000000000000000000000000000000000000000130644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd45"_hex, + "0769bf9ac56bea3ff40232bcb1b6bd159315d84715b8e679f2d355961915abf005acb4b400e90c0063006a39f478f3e865e306dd5cd56f356e2e8cd8fe7edae6"_hex}, + {"0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"_hex, + "00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002"_hex}, + {"000000000000000000000000000000000000000000000000000000000000000130644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd4500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"_hex, + "000000000000000000000000000000000000000000000000000000000000000130644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd45"_hex}, + {"0ccbec17235f5b9cc5e42f3df6364a76ecdd0101ddda8fc5dc0ba0b59c0e5628069ef5e376c0a1ea82f9dfc2e0001a7f385d655eef9a6f976c7a5d2c493ea3ad000000000000000000000000000000000000000000000000000000000000000130644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd45"_hex, + "113aeccecdaf57cd8c0aace591774949dcdaf892555fa86726fa7e679b89c0670bffba84127a19abde488a8251a9a3fce33b34a76f96aafb11ab4a6cef3e9979"_hex}, + {"0ccbec17235f5b9cc5e42f3df6364a76ecdd0101ddda8fc5dc0ba0b59c0e5628069ef5e376c0a1ea82f9dfc2e0001a7f385d655eef9a6f976c7a5d2c493ea3ad0ccbec17235f5b9cc5e42f3df6364a76ecdd0101ddda8fc5dc0ba0b59c0e5628069ef5e376c0a1ea82f9dfc2e0001a7f385d655eef9a6f976c7a5d2c493ea3ad"_hex, + "1fd3b816d9951dcb9aa9797d25e51a865987703ae83cd69c4658679f0350ae2b29ce3d80a74ddc13784beb25ca9fbfd048a3265a32c6f38b92060c5093a0e7a7"_hex}, + {"0ccbec17235f5b9cc5e42f3df6364a76ecdd0101ddda8fc5dc0ba0b59c0e5628069ef5e376c0a1ea82f9dfc2e0001a7f385d655eef9a6f976c7a5d2c493ea3ad00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"_hex, + "0ccbec17235f5b9cc5e42f3df6364a76ecdd0101ddda8fc5dc0ba0b59c0e5628069ef5e376c0a1ea82f9dfc2e0001a7f385d655eef9a6f976c7a5d2c493ea3ad"_hex}, + {"2f588cffe99db877a4434b598ab28f81e0522910ea52b45f0adaa772b2d5d3521d701ec9e3fca50e84777f0f68caff5bff48cf6a6bd4428462ae9366cf0582b0000000000000000000000000000000000000000000000000000000000000000130644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd45"_hex, + "1d78954c630b3895fbbfafac1294f2c0158879fdc70bfe18222890e7bfb66fba101c3346e98b136a7078aebd427dced763722d77e3d7985342e0bffcc6ea4d56"_hex}, + {"2f588cffe99db877a4434b598ab28f81e0522910ea52b45f0adaa772b2d5d3521d701ec9e3fca50e84777f0f68caff5bff48cf6a6bd4428462ae9366cf0582b02f588cffe99db877a4434b598ab28f81e0522910ea52b45f0adaa772b2d5d3521d701ec9e3fca50e84777f0f68caff5bff48cf6a6bd4428462ae9366cf0582b0"_hex, + "2fa739d4cde056d8fd75427345cbb34159856e06a4ffad64159c4773f23fbf4b1eed5d5325c31fc89dd541a13d7f63b981fae8d4bf78a6b08a38a601fcfea97b"_hex}, + {"2f588cffe99db877a4434b598ab28f81e0522910ea52b45f0adaa772b2d5d3521d701ec9e3fca50e84777f0f68caff5bff48cf6a6bd4428462ae9366cf0582b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"_hex, + "2f588cffe99db877a4434b598ab28f81e0522910ea52b45f0adaa772b2d5d3521d701ec9e3fca50e84777f0f68caff5bff48cf6a6bd4428462ae9366cf0582b0"_hex}, + {"030644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd315ed738c0e0a7c92e7845f96b2ae9c0a68a6a449e3538fc7ff3ebf7a5a18a2c400000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002"_hex, + "0769bf9ac56bea3ff40232bcb1b6bd159315d84715b8e679f2d355961915abf02ab799bee0489429554fdb7c8d086475319e63b40b9c5b57cdf1ff3dd9fe2261"_hex}, + {"0ccbec17235f5b9cc5e42f3df6364a76ecdd0101ddda8fc5dc0ba0b59c0e562829c5588f6a70fe3f355665f3a1813dde5f24053278d75af5cfa62eea8f3e599a00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002"_hex, + "113aeccecdaf57cd8c0aace591774949dcdaf892555fa86726fa7e679b89c067246493eeceb7867dda07bb342fd7b460b44635e9f8db1f922a7541a9e93e63ce"_hex}, + {"0ccbec17235f5b9cc5e42f3df6364a76ecdd0101ddda8fc5dc0ba0b59c0e562829c5588f6a70fe3f355665f3a1813dde5f24053278d75af5cfa62eea8f3e599a0ccbec17235f5b9cc5e42f3df6364a76ecdd0101ddda8fc5dc0ba0b59c0e562829c5588f6a70fe3f355665f3a1813dde5f24053278d75af5cfa62eea8f3e599a"_hex, + "1fd3b816d9951dcb9aa9797d25e51a865987703ae83cd69c4658679f0350ae2b069610f239e3c41640045a90b6e1988d4ede443735aad701aa1a7fc644dc15a0"_hex}, + {"0ccbec17235f5b9cc5e42f3df6364a76ecdd0101ddda8fc5dc0ba0b59c0e562829c5588f6a70fe3f355665f3a1813dde5f24053278d75af5cfa62eea8f3e599a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"_hex, + "0ccbec17235f5b9cc5e42f3df6364a76ecdd0101ddda8fc5dc0ba0b59c0e562829c5588f6a70fe3f355665f3a1813dde5f24053278d75af5cfa62eea8f3e599a"_hex}, + {"2f588cffe99db877a4434b598ab28f81e0522910ea52b45f0adaa772b2d5d35212f42fa8fd34fb1b33d8c6a718b6590198389b26fc9d8808d971f8b009777a9700000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002"_hex, + "1d78954c630b3895fbbfafac1294f2c0158879fdc70bfe18222890e7bfb66fba20481b2bf7a68cbf47d796f93f038986340f3d19849a3239f93fcc1a1192aff1"_hex}, + {"2f588cffe99db877a4434b598ab28f81e0522910ea52b45f0adaa772b2d5d35212f42fa8fd34fb1b33d8c6a718b6590198389b26fc9d8808d971f8b009777a972f588cffe99db877a4434b598ab28f81e0522910ea52b45f0adaa772b2d5d35212f42fa8fd34fb1b33d8c6a718b6590198389b26fc9d8808d971f8b009777a97"_hex, + "2fa739d4cde056d8fd75427345cbb34159856e06a4ffad64159c4773f23fbf4b1176f11fbb6e80611a7b04154401f4a4158681bca8f923dcb1e7e614db7e53cc"_hex}, + {"2f588cffe99db877a4434b598ab28f81e0522910ea52b45f0adaa772b2d5d35212f42fa8fd34fb1b33d8c6a718b6590198389b26fc9d8808d971f8b009777a9700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"_hex, + "2f588cffe99db877a4434b598ab28f81e0522910ea52b45f0adaa772b2d5d35212f42fa8fd34fb1b33d8c6a718b6590198389b26fc9d8808d971f8b009777a97"_hex}, + {"000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"_hex, + "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"_hex}, + {"0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"_hex, + "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"_hex}, + {"0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002"_hex, + "00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002"_hex}, + {"000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"_hex, + "00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002"_hex}, + {"000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"_hex, + "00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002"_hex}, + {"000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"_hex, + "030644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd315ed738c0e0a7c92e7845f96b2ae9c0a68a6a449e3538fc7ff3ebf7a5a18a2c4"_hex}, + {"17c139df0efee0f766bc0204762b774362e4ded88953a39ce849a8a7fa163fa901e0559bacb160664764a357af8a9fe70baa9258e0b959273ffc5718c6d4cc7c17c139df0efee0f766bc0204762b774362e4ded88953a39ce849a8a7fa163fa92e83f8d734803fc370eba25ed1f6b8768bd6d83887b87165fc2434fe11a830cb00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"_hex, + "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"_hex}, + {"17c139df0efee0f766bc0204762b774362e4ded88953a39ce849a8a7fa163fa901e0559bacb160664764a357af8a9fe70baa9258e0b959273ffc5718c6d4cc7c039730ea8dff1254c0fee9c0ea777d29a9c710b7e616683f194f18c43b43b869073a5ffcc6fc7a28c30723d6e58ce577356982d65b833a5a5c15bf9024b43d98"_hex, + "15bf2bb17880144b5d1cd2b1f46eff9d617bffd1ca57c37fb5a49bd84e53cf66049c797f9ce0d17083deb32b5e36f2ea2a212ee036598dd7624c168993d1355f"_hex}, + +}; +} // namespace + +TEST(evmmax, bn254_validate_inputs) +{ + const evmmax::ModArith s{evmmax::bn254::FieldPrime}; + + for (const auto& t : test_cases) + { + ASSERT_EQ(t.input.size(), 128); + ASSERT_EQ(t.expected_output.size(), 64); + + const Point a{ + be::unsafe::load(t.input.data()), be::unsafe::load(&t.input[32])}; + const Point b{ + be::unsafe::load(&t.input[64]), be::unsafe::load(&t.input[96])}; + const Point e{be::unsafe::load(t.expected_output.data()), + be::unsafe::load(&t.expected_output[32])}; + + EXPECT_TRUE(validate(a)); + EXPECT_TRUE(validate(b)); + EXPECT_TRUE(validate(e)); + } +} + +TEST(evmmax, bn254_pt_add) +{ + const evmmax::ModArith s{evmmax::bn254::FieldPrime}; + + for (const auto& t : test_cases) + { + const Point a{ + be::unsafe::load(t.input.data()), be::unsafe::load(&t.input[32])}; + const Point b{ + be::unsafe::load(&t.input[64]), be::unsafe::load(&t.input[96])}; + const Point e{be::unsafe::load(t.expected_output.data()), + be::unsafe::load(&t.expected_output[32])}; + + EXPECT_EQ(add(a, b), e); + } +} + +TEST(evmmax, inv_1) +{ + const evmmax::ModArith m{evmmax::bn254::FieldPrime}; + + const auto a = + m.to_mont(0x6e140df17432311190232a91a38daed3ee9ed7f038645dd0278da7ca6e497de_u256); + + const auto a_inv = field_inv(m, a); + const auto p = m.mul(a, a_inv); + EXPECT_EQ(m.from_mont(p), 1); +} diff --git a/test/unittests/evmmax_bn254_mul_test.cpp b/test/unittests/evmmax_bn254_mul_test.cpp new file mode 100644 index 0000000000..944ff3fd73 --- /dev/null +++ b/test/unittests/evmmax_bn254_mul_test.cpp @@ -0,0 +1,249 @@ +// evmone: Fast Ethereum Virtual Machine implementation +// Copyright 2023 The evmone Authors. +// SPDX-License-Identifier: Apache-2.0 + +#include "../utils/utils.hpp" +#include "evmone_precompiles/bn254.hpp" +#include + +using namespace evmmax::bn254; +using namespace intx; + +namespace +{ +struct TestCase +{ + bytes input; + bytes expected_output; + + TestCase(bytes i, bytes o) : input{std::move(i)}, expected_output{std::move(o)} + { + input.resize(96); + expected_output.resize(64); + } +}; + +const TestCase + test_cases + [] = + { + {"025a6f4181d2b4ea8b724290ffb40156eb0adb514c688556eb79cdea0752c2bb2eff3f31dea215f1eb86023a133a996eb6300b44da664d64251d05381bb8a02e183227397098d014dc2822db40c0ac2ecbc0b548b438e5469e10460b6c3e7ea3"_hex, + "14789d0d4a730b354403b5fac948113739e276c23e0258d8596ee72f9cd9d3230af18a63153e0ec25ff9f2951dd3fa90ed0197bfef6e2a1a62b5095b9d2b4a27"_hex}, // from https://github.com/sedaprotocol/bn254/blob/main/src/bn256.json#L68 + {"070a8d6a982153cae4be29d434e8faef8a47b274a053f5a4ee2a6c9c13c31e5c031b8ce914eba3a9ffb989f9cdd5b0f01943074bf4f0f315690ec3cec6981afc30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd46"_hex, + "025a6f4181d2b4ea8b724290ffb40156eb0adb514c688556eb79cdea0752c2bb2eff3f31dea215f1eb86023a133a996eb6300b44da664d64251d05381bb8a02e"_hex}, // https://github.com/sedaprotocol/bn254/blob/main/src/bn256.json#LL62C1-L62C1 + {"0f25929bcb43d5a57391564615c9e70a992b10eafa4db109709649cf48c50dd216da2f5cb6be7a0aa72c440c53c9bbdfec6c36c7d515536431b3a865468acbba0000000000000000000000000000000000000000000000000000000000000003"_hex, + "1f4d1d80177b1377743d1901f70d7389be7f7a35a35bfd234a8aaee615b88c49018683193ae021a2f8920fed186cde5d9b1365116865281ccf884c1f28b1df8f"_hex}, + {"0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"_hex, + "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"_hex}, + {"0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000"_hex, + "030644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd315ed738c0e0a7c92e7845f96b2ae9c0a68a6a449e3538fc7ff3ebf7a5a18a2c4"_hex}, + {"000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002"_hex, + "030644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd315ed738c0e0a7c92e7845f96b2ae9c0a68a6a449e3538fc7ff3ebf7a5a18a2c4"_hex}, + {"0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"_hex, + "13b8fec4a1eb2c7e3ccc07061ad516277c3bbe57bd4a302012b58a517f6437a4224d978b5763831dff16ce9b2c42222684835fedfc70ffec005789bb0c10de36"_hex}, + {"0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000001"_hex, + "13b8fec4a1eb2c7e3ccc07061ad516277c3bbe57bd4a302012b58a517f6437a4224d978b5763831dff16ce9b2c42222684835fedfc70ffec005789bb0c10de36"_hex}, + {"000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000100000000000000000000000000000000"_hex, + "13b8fec4a1eb2c7e3ccc07061ad516277c3bbe57bd4a302012b58a517f6437a4224d978b5763831dff16ce9b2c42222684835fedfc70ffec005789bb0c10de36"_hex}, + {"0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000230644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000000000000000000000000000000000000000000000000000000000000000000000"_hex, + "000000000000000000000000000000000000000000000000000000000000000130644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd45"_hex}, + {"0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000230644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000000"_hex, + "000000000000000000000000000000000000000000000000000000000000000130644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd45"_hex}, + {"0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000230644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000010000000000000000000000000000000000000000000000000000000000000000"_hex, + "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"_hex}, + {"0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000230644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001"_hex, + "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"_hex}, + {"00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000"_hex, + "2f588cffe99db877a4434b598ab28f81e0522910ea52b45f0adaa772b2d5d35212f42fa8fd34fb1b33d8c6a718b6590198389b26fc9d8808d971f8b009777a97"_hex}, + {"00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"_hex, + "2f588cffe99db877a4434b598ab28f81e0522910ea52b45f0adaa772b2d5d35212f42fa8fd34fb1b33d8c6a718b6590198389b26fc9d8808d971f8b009777a97"_hex}, + {"0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000090000000000000000000000000000000000000000000000000000000000000000"_hex, + "039730ea8dff1254c0fee9c0ea777d29a9c710b7e616683f194f18c43b43b869073a5ffcc6fc7a28c30723d6e58ce577356982d65b833a5a5c15bf9024b43d98"_hex}, + {"000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000009"_hex, + "039730ea8dff1254c0fee9c0ea777d29a9c710b7e616683f194f18c43b43b869073a5ffcc6fc7a28c30723d6e58ce577356982d65b833a5a5c15bf9024b43d98"_hex}, + {"1a87b0584ce92f4593d161480614f2989035225609f08058ccfa3d0f940febe31a2f3c951f6dadcc7ee9007dff81504b0fcd6d7cf59996efdc33d92bf7f9f8f600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"_hex, + "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"_hex}, + {"1a87b0584ce92f4593d161480614f2989035225609f08058ccfa3d0f940febe31a2f3c951f6dadcc7ee9007dff81504b0fcd6d7cf59996efdc33d92bf7f9f8f6"_hex, + "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"_hex}, + {"1a87b0584ce92f4593d161480614f2989035225609f08058ccfa3d0f940febe31a2f3c951f6dadcc7ee9007dff81504b0fcd6d7cf59996efdc33d92bf7f9f8f600000000000000000000000000000000"_hex, + "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"_hex}, + {"1a87b0584ce92f4593d161480614f2989035225609f08058ccfa3d0f940febe31a2f3c951f6dadcc7ee9007dff81504b0fcd6d7cf59996efdc33d92bf7f9f8f60000000000000000000000000000000000000000000000000000000000000000"_hex, + "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"_hex}, + {"1a87b0584ce92f4593d161480614f2989035225609f08058ccfa3d0f940febe31a2f3c951f6dadcc7ee9007dff81504b0fcd6d7cf59996efdc33d92bf7f9f8f600000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"_hex, + "1051acb0700ec6d42a88215852d582efbaef31529b6fcbc3277b5c1b300f5cf0135b2394bb45ab04b8bd7611bd2dfe1de6a4e6e2ccea1ea1955f577cd66af85b"_hex}, + {"1a87b0584ce92f4593d161480614f2989035225609f08058ccfa3d0f940febe31a2f3c951f6dadcc7ee9007dff81504b0fcd6d7cf59996efdc33d92bf7f9f8f600000000000000000000000000000001"_hex, + "1051acb0700ec6d42a88215852d582efbaef31529b6fcbc3277b5c1b300f5cf0135b2394bb45ab04b8bd7611bd2dfe1de6a4e6e2ccea1ea1955f577cd66af85b"_hex}, + {"1a87b0584ce92f4593d161480614f2989035225609f08058ccfa3d0f940febe31a2f3c951f6dadcc7ee9007dff81504b0fcd6d7cf59996efdc33d92bf7f9f8f60000000000000000000000000000000100000000000000000000000000000000"_hex, + "1051acb0700ec6d42a88215852d582efbaef31529b6fcbc3277b5c1b300f5cf0135b2394bb45ab04b8bd7611bd2dfe1de6a4e6e2ccea1ea1955f577cd66af85b"_hex}, + {"1a87b0584ce92f4593d161480614f2989035225609f08058ccfa3d0f940febe31a2f3c951f6dadcc7ee9007dff81504b0fcd6d7cf59996efdc33d92bf7f9f8f600000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000"_hex, + "1a87b0584ce92f4593d161480614f2989035225609f08058ccfa3d0f940febe31a2f3c951f6dadcc7ee9007dff81504b0fcd6d7cf59996efdc33d92bf7f9f8f6"_hex}, + {"1a87b0584ce92f4593d161480614f2989035225609f08058ccfa3d0f940febe31a2f3c951f6dadcc7ee9007dff81504b0fcd6d7cf59996efdc33d92bf7f9f8f60000000000000000000000000000000000000000000000000000000000000001"_hex, + "1a87b0584ce92f4593d161480614f2989035225609f08058ccfa3d0f940febe31a2f3c951f6dadcc7ee9007dff81504b0fcd6d7cf59996efdc33d92bf7f9f8f6"_hex}, + {"1a87b0584ce92f4593d161480614f2989035225609f08058ccfa3d0f940febe31a2f3c951f6dadcc7ee9007dff81504b0fcd6d7cf59996efdc33d92bf7f9f8f600000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000"_hex, + "03d64e49ebb3c56c99e0769c1833879c9b86ead23945e1e7477cbd057e961c500d6840b39f8c2fefe0eced3e7d210b830f50831e756f1cc9039af65dc292e6d0"_hex}, + {"1a87b0584ce92f4593d161480614f2989035225609f08058ccfa3d0f940febe31a2f3c951f6dadcc7ee9007dff81504b0fcd6d7cf59996efdc33d92bf7f9f8f60000000000000000000000000000000000000000000000000000000000000002"_hex, + "03d64e49ebb3c56c99e0769c1833879c9b86ead23945e1e7477cbd057e961c500d6840b39f8c2fefe0eced3e7d210b830f50831e756f1cc9039af65dc292e6d0"_hex}, + {"1a87b0584ce92f4593d161480614f2989035225609f08058ccfa3d0f940febe31a2f3c951f6dadcc7ee9007dff81504b0fcd6d7cf59996efdc33d92bf7f9f8f630644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000000000000000000000000000000000000000000000000000000000000000000000"_hex, + "1a87b0584ce92f4593d161480614f2989035225609f08058ccfa3d0f940febe3163511ddc1c3f25d396745388200081287b3fd1472d8339d5fecb2eae0830451"_hex}, + {"1a87b0584ce92f4593d161480614f2989035225609f08058ccfa3d0f940febe31a2f3c951f6dadcc7ee9007dff81504b0fcd6d7cf59996efdc33d92bf7f9f8f630644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000000"_hex, + "1a87b0584ce92f4593d161480614f2989035225609f08058ccfa3d0f940febe3163511ddc1c3f25d396745388200081287b3fd1472d8339d5fecb2eae0830451"_hex}, + {"1a87b0584ce92f4593d161480614f2989035225609f08058ccfa3d0f940febe31a2f3c951f6dadcc7ee9007dff81504b0fcd6d7cf59996efdc33d92bf7f9f8f630644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000010000000000000000000000000000000000000000000000000000000000000000"_hex, + "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"_hex}, + {"1a87b0584ce92f4593d161480614f2989035225609f08058ccfa3d0f940febe31a2f3c951f6dadcc7ee9007dff81504b0fcd6d7cf59996efdc33d92bf7f9f8f630644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001"_hex, + "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"_hex}, + {"1a87b0584ce92f4593d161480614f2989035225609f08058ccfa3d0f940febe31a2f3c951f6dadcc7ee9007dff81504b0fcd6d7cf59996efdc33d92bf7f9f8f6ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000"_hex, + "2cde5879ba6f13c0b5aa4ef627f159a3347df9722efce88a9afbb20b763b4c411aa7e43076f6aee272755a7f9b84832e71559ba0d2e0b17d5f9f01755e5b0d11"_hex}, + {"1a87b0584ce92f4593d161480614f2989035225609f08058ccfa3d0f940febe31a2f3c951f6dadcc7ee9007dff81504b0fcd6d7cf59996efdc33d92bf7f9f8f6ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"_hex, + "2cde5879ba6f13c0b5aa4ef627f159a3347df9722efce88a9afbb20b763b4c411aa7e43076f6aee272755a7f9b84832e71559ba0d2e0b17d5f9f01755e5b0d11"_hex}, + {"1a87b0584ce92f4593d161480614f2989035225609f08058ccfa3d0f940febe31a2f3c951f6dadcc7ee9007dff81504b0fcd6d7cf59996efdc33d92bf7f9f8f600000000000000000000000000000000000000000000000000000000000000090000000000000000000000000000000000000000000000000000000000000000"_hex, + "1dbad7d39dbc56379f78fac1bca147dc8e66de1b9d183c7b167351bfe0aeab742cd757d51289cd8dbd0acf9e673ad67d0f0a89f912af47ed1be53664f5692575"_hex}, + {"1a87b0584ce92f4593d161480614f2989035225609f08058ccfa3d0f940febe31a2f3c951f6dadcc7ee9007dff81504b0fcd6d7cf59996efdc33d92bf7f9f8f60000000000000000000000000000000000000000000000000000000000000009"_hex, + "1dbad7d39dbc56379f78fac1bca147dc8e66de1b9d183c7b167351bfe0aeab742cd757d51289cd8dbd0acf9e673ad67d0f0a89f912af47ed1be53664f5692575"_hex}, + {"0f25929bcb43d5a57391564615c9e70a992b10eafa4db109709649cf48c50dd216da2f5cb6be7a0aa72c440c53c9bbdfec6c36c7d515536431b3a865468acbba0000000000000000000000000000000000000000000000000000000000000002"_hex, + "1de49a4b0233273bba8146af82042d004f2085ec982397db0d97da17204cc2860217327ffc463919bef80cc166d09c6172639d8589799928761bcd9f22c903d4"_hex}, + {"1f4d1d80177b1377743d1901f70d7389be7f7a35a35bfd234a8aaee615b88c49018683193ae021a2f8920fed186cde5d9b1365116865281ccf884c1f28b1df8f0000000000000000000000000000000000000000000000000000000000000000"_hex, + "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"_hex}, + {"1f4d1d80177b1377743d1901f70d7389be7f7a35a35bfd234a8aaee615b88c492eddcb59a6517e86bfbe35c9691479fffc6e0580000ca2706c983ff7afcb1db80000000000000000000000000000000000000000000000000000000000000002"_hex, + "255e468453d7636cc1563e43f7521755f95e6c56043c7321b4ae04e772945fb00225c5f1623620fd84bfbab2d861a9d1e570f7727c540f403085998ebaf407c4"_hex}, + {"1f4d1d80177b1377743d1901f70d7389be7f7a35a35bfd234a8aaee615b88c49018683193ae021a2f8920fed186cde5d9b1365116865281ccf884c1f28b1df8f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000000"_hex, + "1f4d1d80177b1377743d1901f70d7389be7f7a35a35bfd234a8aaee615b88c492eddcb59a6517e86bfbe35c9691479fffc6e0580000ca2706c983ff7afcb1db8"_hex}, + {"1f4d1d80177b1377743d1901f70d7389be7f7a35a35bfd234a8aaee615b88c49018683193ae021a2f8920fed186cde5d9b1365116865281ccf884c1f28b1df8f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593efffffff"_hex, + "255e468453d7636cc1563e43f7521755f95e6c56043c7321b4ae04e772945fb00225c5f1623620fd84bfbab2d861a9d1e570f7727c540f403085998ebaf407c4"_hex}, + {"000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000"_hex, + "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"_hex}, + {"000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002"_hex, + "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"_hex}, + {"000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003"_hex, + "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"_hex}, + {"000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"_hex, + "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"_hex}, + {"0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000000"_hex, + "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"_hex}, + {"0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030644e72e131a029b85045b68181585d2833e84879b9709143e1f593efffffff"_hex, + "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"_hex}, + {"000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001"_hex, + "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"_hex}, + {"0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd46"_hex, + "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"_hex}, + {"0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd45"_hex, + "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"_hex}, + {"00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"_hex, + "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"_hex}, + {"00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"_hex, + "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"_hex}, + {"000000000000000000000000000000000000000000000000000000000000000130644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd450000000000000000000000000000000000000000000000000000000000000000"_hex, + "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"_hex}, + {"000000000000000000000000000000000000000000000000000000000000000130644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd450000000000000000000000000000000000000000000000000000000000000002"_hex, + "030644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd31a76dae6d3272396d0cbe61fced2bc532edac647851e3ac53ce1cc9c7e645a83"_hex}, + {"000000000000000000000000000000000000000000000000000000000000000130644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd450000000000000000000000000000000000000000000000000000000000000003"_hex, + "0769bf9ac56bea3ff40232bcb1b6bd159315d84715b8e679f2d355961915abf005acb4b400e90c0063006a39f478f3e865e306dd5cd56f356e2e8cd8fe7edae6"_hex}, + {"000000000000000000000000000000000000000000000000000000000000000130644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd4530644e72e131a029b85045b68181585d2833e84879b9709143e1f593efffffff"_hex, + "030644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd315ed738c0e0a7c92e7845f96b2ae9c0a68a6a449e3538fc7ff3ebf7a5a18a2c4"_hex}, + {"000000000000000000000000000000000000000000000000000000000000000130644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd4530644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000000"_hex, + "00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002"_hex}, + {"000000000000000000000000000000000000000000000000000000000000000130644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd450000000000000000000000000000000000000000000000000000000000000001"_hex, + "000000000000000000000000000000000000000000000000000000000000000130644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd45"_hex}, + {"0ccbec17235f5b9cc5e42f3df6364a76ecdd0101ddda8fc5dc0ba0b59c0e5628069ef5e376c0a1ea82f9dfc2e0001a7f385d655eef9a6f976c7a5d2c493ea3ad0000000000000000000000000000000000000000000000000000000000000002"_hex, + "1fd3b816d9951dcb9aa9797d25e51a865987703ae83cd69c4658679f0350ae2b29ce3d80a74ddc13784beb25ca9fbfd048a3265a32c6f38b92060c5093a0e7a7"_hex}, + {"000000000000000000000000000000000000000000000000000000000000000130644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd4530644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd46"_hex, + "0ccbec17235f5b9cc5e42f3df6364a76ecdd0101ddda8fc5dc0ba0b59c0e5628069ef5e376c0a1ea82f9dfc2e0001a7f385d655eef9a6f976c7a5d2c493ea3ad"_hex}, + {"000000000000000000000000000000000000000000000000000000000000000130644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd4530644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd45"_hex, + "2c15ed1902e189486ab6b625aa982510aef6246b21a1e1bcea382da4d735e8ba02103e58cbd2fa8081763442ab46c26a9b8051e9b049c3948c8d7d0e139c5e3f"_hex}, + {"2f588cffe99db877a4434b598ab28f81e0522910ea52b45f0adaa772b2d5d3521d701ec9e3fca50e84777f0f68caff5bff48cf6a6bd4428462ae9366cf0582b00000000000000000000000000000000000000000000000000000000000000002"_hex, + "2fa739d4cde056d8fd75427345cbb34159856e06a4ffad64159c4773f23fbf4b1eed5d5325c31fc89dd541a13d7f63b981fae8d4bf78a6b08a38a601fcfea97b"_hex}, + {"000000000000000000000000000000000000000000000000000000000000000130644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd45ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"_hex, + "2f588cffe99db877a4434b598ab28f81e0522910ea52b45f0adaa772b2d5d3521d701ec9e3fca50e84777f0f68caff5bff48cf6a6bd4428462ae9366cf0582b0"_hex}, + {"000000000000000000000000000000000000000000000000000000000000000130644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd45fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"_hex, + "08e2142845db159bd105879a109fe7a6f254ed3ddae0e9cd8a2aeae05e5f647b221108ee615499d2e0a1113ca1a858a34e055f9da2d30e6e6ab392b049944a92"_hex}, + {"000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000003"_hex, + "0769bf9ac56bea3ff40232bcb1b6bd159315d84715b8e679f2d355961915abf02ab799bee0489429554fdb7c8d086475319e63b40b9c5b57cdf1ff3dd9fe2261"_hex}, + {"0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000230644e72e131a029b85045b68181585d2833e84879b9709143e1f593efffffff"_hex, + "030644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd31a76dae6d3272396d0cbe61fced2bc532edac647851e3ac53ce1cc9c7e645a83"_hex}, + {"000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000001"_hex, + "00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002"_hex}, + {"0ccbec17235f5b9cc5e42f3df6364a76ecdd0101ddda8fc5dc0ba0b59c0e562829c5588f6a70fe3f355665f3a1813dde5f24053278d75af5cfa62eea8f3e599a0000000000000000000000000000000000000000000000000000000000000002"_hex, + "1fd3b816d9951dcb9aa9797d25e51a865987703ae83cd69c4658679f0350ae2b069610f239e3c41640045a90b6e1988d4ede443735aad701aa1a7fc644dc15a0"_hex}, + {"0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000230644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd46"_hex, + "0ccbec17235f5b9cc5e42f3df6364a76ecdd0101ddda8fc5dc0ba0b59c0e562829c5588f6a70fe3f355665f3a1813dde5f24053278d75af5cfa62eea8f3e599a"_hex}, + {"0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000230644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd45"_hex, + "2c15ed1902e189486ab6b625aa982510aef6246b21a1e1bcea382da4d735e8ba2e54101a155ea5a936da1173d63a95f2fc0118a7b82806f8af930f08c4e09f08"_hex}, + {"2f588cffe99db877a4434b598ab28f81e0522910ea52b45f0adaa772b2d5d35212f42fa8fd34fb1b33d8c6a718b6590198389b26fc9d8808d971f8b009777a970000000000000000000000000000000000000000000000000000000000000002"_hex, + "2fa739d4cde056d8fd75427345cbb34159856e06a4ffad64159c4773f23fbf4b1176f11fbb6e80611a7b04154401f4a4158681bca8f923dcb1e7e614db7e53cc"_hex}, + {"00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"_hex, + "08e2142845db159bd105879a109fe7a6f254ed3ddae0e9cd8a2aeae05e5f647b0e5345847fdd0656d7af3479dfd8ffba497c0af3c59ebc1ed16cf9668ee8b2b5"_hex}, + {"00000000000000000000000000000000000000000000000000000000000000000000000000000000"_hex, + "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"_hex}, + {"00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"_hex, + "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"_hex}, + {"0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"_hex, + "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"_hex}, + {"0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000"_hex, + "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"_hex}, + {"0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000"_hex, + "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"_hex}, + {"0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"_hex, + "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"_hex}, + {"0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001"_hex, + "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"_hex}, + {"000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000"_hex, + "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"_hex}, + {"0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000000000000000000000000000000000000000000000000000000000000000000000"_hex, + "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"_hex}, + {"0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000010000000000000000000000000000000000000000000000000000000000000000"_hex, + "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"_hex}, + {"0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001"_hex, + "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"_hex}, + {"00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000"_hex, + "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"_hex}, + {"0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000090000000000000000000000000000000000000000000000000000000000000000"_hex, + "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"_hex}, + {"000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009"_hex, + "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"_hex}, + {"0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"_hex, + "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"_hex}, + {"00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002"_hex, + "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"_hex}, + {"0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000"_hex, + "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"_hex}, + {"0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000"_hex, + "00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002"_hex}, +}; + +} // namespace + +TEST(evmmax, bn254_mul_validate_inputs) +{ + const evmmax::ModArith s{evmmax::bn254::FieldPrime}; + + for (const auto& t : test_cases) + { + ASSERT_EQ(t.input.size(), 96); + ASSERT_EQ(t.expected_output.size(), 64); + + const Point a{ + be::unsafe::load(t.input.data()), be::unsafe::load(&t.input[32])}; + const Point e{be::unsafe::load(t.expected_output.data()), + be::unsafe::load(&t.expected_output[32])}; + + EXPECT_TRUE(validate(a)); + EXPECT_TRUE(validate(e)); + } +} + +TEST(evmmax, bn254_pt_mul) +{ + const evmmax::ModArith s{evmmax::bn254::FieldPrime}; + + for (const auto& t : test_cases) + { + const Point p{ + be::unsafe::load(t.input.data()), be::unsafe::load(&t.input[32])}; + const auto d{be::unsafe::load(&t.input[64])}; + const Point e{be::unsafe::load(t.expected_output.data()), + be::unsafe::load(&t.expected_output[32])}; + + auto r = mul(p, d); + + EXPECT_EQ(r, e); + } +}