diff --git a/lib/evmone_precompiles/CMakeLists.txt b/lib/evmone_precompiles/CMakeLists.txt index d29b6631cc..0e4eaadaa2 100644 --- a/lib/evmone_precompiles/CMakeLists.txt +++ b/lib/evmone_precompiles/CMakeLists.txt @@ -20,6 +20,8 @@ target_sources( pairing/bn254/pairing.cpp pairing/bn254/utils.hpp pairing/field_template.hpp + modexp.hpp + modexp.cpp ripemd160.hpp ripemd160.cpp secp256k1.hpp diff --git a/lib/evmone_precompiles/modexp.cpp b/lib/evmone_precompiles/modexp.cpp new file mode 100644 index 0000000000..cf7c6a6c83 --- /dev/null +++ b/lib/evmone_precompiles/modexp.cpp @@ -0,0 +1,227 @@ +#include "modexp.hpp" +#include + +#include + +using namespace intx; + +namespace +{ +template +UIntT modexp_odd(const UIntT& base, const evmc::bytes_view& exp, const UIntT& mod) +{ + const evmmax::ModArith arith(mod); + + UIntT ret = arith.to_mont(UIntT{1}); + const auto base_mont = arith.to_mont(base); + const auto base2 = arith.mul(base_mont, base_mont); + const auto base3 = arith.mul(base_mont, base2); + + for (const auto e : exp) + { + for (size_t i = 8; i != 0; i -= 2) + { + ret = arith.mul(ret, ret); + const auto bits = e >> (i - 2) & 0b11; + + const auto& x = bits == 0b11 ? base3 : base_mont; + + switch (bits) + { + case 0b00: + ret = arith.mul(ret, ret); + break; + case 0b01: + ret = arith.mul(ret, ret); + ret = arith.mul(ret, x); + break; + case 0b10: + ret = arith.mul(ret, x); + ret = arith.mul(ret, ret); + break; + case 0b11: + ret = arith.mul(ret, ret); + ret = arith.mul(ret, x); + break; + default: + __builtin_unreachable(); + } + } + } + + return arith.from_mont(ret); +} + +template +UIntT modexp_pow_of_two(const UIntT& base, const evmc::bytes_view& exp, const UIntT& mod) +{ + const auto nlz = clz(mod); + + const UIntT mod_mask = std::numeric_limits::max() >> (nlz + 1); + UIntT ret = UIntT{1}; + for (auto e : exp) + { + unsigned char mask = 0x80; + while (mask != 0) + { + ret = ret * ret; + ret &= mod_mask; + if ((mask & e) != 0) + { + ret = ret * base; + ret &= mod_mask; + } + + mask >>= 1; + } + } + + return ret; +} + +template +size_t ctz(const UIntT& value) +{ + size_t mod_tailing_zeros = 0; + for (size_t i = 0; i < value.num_words; ++i) + { + if (value[i] == 0) + { + mod_tailing_zeros += value.word_num_bits; + continue; + } + else + { + mod_tailing_zeros += static_cast(std::countr_zero(value[i])); + break; + } + } + + return mod_tailing_zeros; +} + +template +UIntT modinv_2k(const UIntT& x, size_t k) +{ + UIntT b{1}; + UIntT res; + for (size_t i = 0; i < k; ++i) + { + UIntT t = b & UIntT{1}; + b = (b - x * t) >> 1; + res += t << i; + } + + return res; +} + +template +UIntT modexp_impl(const UIntT& base, const evmc::bytes_view& exp, const UIntT& mod) +{ + // is odd + if ((mod & UIntT{1}) == UIntT{1}) + { + return modexp_odd(base, exp, mod); + } + else if ((mod << (clz(mod) + 1)) == 0) // is power of 2 + { + return modexp_pow_of_two(base, exp, mod); + } + else // is even + { + const auto mod_tailing_zeros = ctz(mod); + + auto const N = mod >> mod_tailing_zeros; + const UIntT K = UIntT{1} << mod_tailing_zeros; + + const auto x1 = modexp_odd(base, exp, N); + const auto x2 = modexp_pow_of_two(base, exp, K); + + const auto N_inv = modinv_2k(N, mod_tailing_zeros); + + return x1 + (((x2 - x1) * N_inv) % K) * N; + } +} + +template +UIntT load_from_bytes(const evmc::bytes_view& data) +{ + constexpr auto num_bytes = UIntT::num_words * sizeof(typename UIntT::word_type); + assert(data.size() <= num_bytes); + if (data.size() == num_bytes) + { + return intx::be::unsafe::load(data.data()); + } + else + { + evmc::bytes tmp; + tmp.resize(num_bytes); + std::memcpy(&tmp[num_bytes - data.size()], data.data(), data.size()); + return intx::be::unsafe::load(tmp.data()); + } +} + +} // namespace + +namespace evmone::crypto +{ +bool modexp(uint8_t* output, size_t output_size, const evmc::bytes_view& base, + const evmc::bytes_view& exp, const evmc::bytes_view& mod) +{ + constexpr auto MAX_INPUT_SIZE = 1024; + if (base.size() > MAX_INPUT_SIZE || exp.size() > MAX_INPUT_SIZE || mod.size() > MAX_INPUT_SIZE) + return false; + + // mod is zero + if (mod.find_first_not_of(uint8_t{0}) == std::string::npos) + { + memset(output, 0, output_size); + return true; + } + + const auto size = std::max(mod.size(), base.size()); + + assert(output_size >= mod.size()); + + evmc::bytes res_bytes; + if (size <= 32) + { + res_bytes.resize(32); + intx::be::unsafe::store(res_bytes.data(), + modexp_impl(load_from_bytes(base), exp, load_from_bytes(mod))); + } + else if (size <= 64) + { + res_bytes.resize(64); + intx::be::unsafe::store(res_bytes.data(), + modexp_impl(load_from_bytes(base), exp, load_from_bytes(mod))); + } + else if (size <= 128) + { + res_bytes.resize(128); + intx::be::unsafe::store( + res_bytes.data(), modexp_impl(load_from_bytes>(base), exp, + load_from_bytes>(mod))); + } + else if (size <= 256) + { + res_bytes.resize(256); + intx::be::unsafe::store( + res_bytes.data(), modexp_impl(load_from_bytes>(base), exp, + load_from_bytes>(mod))); + } + else + { + assert(output_size <= 1024); + res_bytes.resize(1024); + intx::be::unsafe::store( + res_bytes.data(), modexp_impl(load_from_bytes>(base), exp, + load_from_bytes>(mod))); + } + + memcpy(output, &res_bytes[res_bytes.size() - output_size], output_size); + return true; +} + + +} // namespace evmone::crypto diff --git a/lib/evmone_precompiles/modexp.hpp b/lib/evmone_precompiles/modexp.hpp new file mode 100644 index 0000000000..528974a551 --- /dev/null +++ b/lib/evmone_precompiles/modexp.hpp @@ -0,0 +1,13 @@ +// evmone: Fast Ethereum Virtual Machine implementation +// Copyright 2025 The evmone Authors. +// SPDX-License-Identifier: Apache-2.0 + +#pragma once +#include +#include + +namespace evmone::crypto +{ +bool modexp(uint8_t* output, size_t output_size, const evmc::bytes_view& base, + const evmc::bytes_view& exp, const evmc::bytes_view& mod); +} diff --git a/test/precompiles_bench/precompiles_bench.cpp b/test/precompiles_bench/precompiles_bench.cpp index 3e3cc6375f..9511381e25 100644 --- a/test/precompiles_bench/precompiles_bench.cpp +++ b/test/precompiles_bench/precompiles_bench.cpp @@ -9,6 +9,10 @@ #include #include +#ifdef EVMONE_PRECOMPILES_OPENSSL +#include +#endif + #ifdef EVMONE_PRECOMPILES_SILKPRE #include #endif @@ -28,6 +32,8 @@ constexpr auto analyze = identity_analyze; template <> constexpr auto analyze = ecrecover_analyze; template <> +constexpr auto analyze = expmod_analyze; +template <> constexpr auto analyze = ecadd_analyze; template <> constexpr auto analyze = ecmul_analyze; @@ -65,6 +71,22 @@ const inline std::array inputs{ }; +template <> +const inline std::array inputs{ + "000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000020 3038f57abc91abff7dcbc5b55cd6aa454503850ce62e941f81273ba6008e82a5 30644e72e131a029b85045b68181585d2833e84879b9709143e1f593efffffff 30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001"_hex, + "000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000020 239ea33f993130afd678f591cd1685d44779b7717156f2a715220955e10a2348 30644e72e131a029b85045b68181585d2833e84879b9709143e1f593efffffff 30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001"_hex, + "000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000020 3914aeddf3af39bd5e0e231d09a8438cf38c7d0274a5aa61bd9a2bbcd77fd2c7 ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63254f ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551"_hex, + "000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000020 27c816cec3d048eaae22d948c42f9d803d765d0827a7b49e01273031566eed92 ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63254f ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551"_hex, + "000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000020 0cf7d1e109b5b8f6a682be51e152d3668acc1b4d762ecbf5cdca7a807cc5fe4c ffffffff00000001000000000000000000000000fffffffffffffffffffffffd ffffffff00000001000000000000000000000000ffffffffffffffffffffffff"_hex, + "000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000020 3a122fd889a09d3a19c587ab486d5a6a2b39836d6d665c6ebad2a68a615e6736 ffffffff00000001000000000000000000000000fffffffffffffffffffffffd ffffffff00000001000000000000000000000000ffffffffffffffffffffffff"_hex, + "000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000020 161455250ee1d7ff76e4eb2f6a16a636a4bc69dd20416f6ea5647b7fb311e932 0000000000000000000000000000000000000000000000000000000000ffffff 30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001"_hex, + "000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000020 0d96428856df2f1b728ce955f28f50befa405a61e8984acbaf678af9be0e0dfd 0000000000000000000000000000000000000000000000000000000001000000 30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001"_hex, + "000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000020 2369f74b39dddb516bb17d20f24ba72c8f0ec09bea7d7f38ad54dbc3cfd4b476 0c19139cb84c680a6e14116da060561765e05aa45a1c72a34f082305b61f3f52 30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47"_hex, + "000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000020 19b01e88eb4a62d7df2da453deb859f6113004675370b6f54ff9f20499cfc4cf 0c19139cb84c680a6e14116da060561765e05aa45a1c72a34f082305b61f3f52 30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47"_hex, + "000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000020 c943d0f2b95b88d8a3ad7782221659f05cb697047a9793a65ec7db59439afb0a 3fffffffffffffffffffffffffffffffffffffffffffffffffffffffbfffff0c fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f"_hex, + "000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000020 307c38188f3b804fc399b7195579269fd60fddbe7e6d8174b3ad38b64b1bb2fa 3fffffffffffffffffffffffffffffffffffffffffffffffffffffffbfffff0c fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f"_hex, +}; + template <> const inline std::array inputs{ "0f25929bcb43d5a57391564615c9e70a992b10eafa4db109709649cf48c50dd2" @@ -184,6 +206,20 @@ BENCHMARK_TEMPLATE(precompile, PrecompileId::ecrecover, libsecp256k1); #endif } // namespace bench_ecrecovery +namespace bench_expmod +{ +constexpr auto evmmax_cpp = expmod_execute; +BENCHMARK_TEMPLATE(precompile, PrecompileId::expmod, evmmax_cpp); +#ifdef EVMONE_PRECOMPILES_OPENSSL +constexpr auto openssl = openssl_expmod_execute; +BENCHMARK_TEMPLATE(precompile, PrecompileId::expmod, openssl); +#endif +#ifdef EVMONE_PRECOMPILES_SILKPRE +constexpr auto gmp = silkpre_expmod_execute; +BENCHMARK_TEMPLATE(precompile, PrecompileId::expmod, gmp); +#endif +} // namespace bench_ecadd + namespace bench_ecadd { constexpr auto evmmax_cpp = ecadd_execute; diff --git a/test/state/CMakeLists.txt b/test/state/CMakeLists.txt index 8c9cc253e3..365e365ca8 100644 --- a/test/state/CMakeLists.txt +++ b/test/state/CMakeLists.txt @@ -26,8 +26,6 @@ target_sources( precompiles.hpp precompiles.cpp precompiles_internal.hpp - precompiles_stubs.hpp - precompiles_stubs.cpp requests.hpp requests.cpp rlp.hpp @@ -43,6 +41,17 @@ target_sources( transaction.cpp ) +find_package(OpenSSL COMPONENTS Crypto) +if(OPENSSL_FOUND) + target_compile_definitions(evmone-state PUBLIC EVMONE_PRECOMPILES_OPENSSL=1) + target_link_libraries(evmone-state PRIVATE OpenSSL::Crypto) + target_sources( + evmone-state PRIVATE + precompiles_openssl.hpp + precompiles_openssl.cpp + ) +endif() + option(EVMONE_PRECOMPILES_SILKPRE "Enable precompiles support via silkpre library" OFF) if(EVMONE_PRECOMPILES_SILKPRE) include(FetchContent) diff --git a/test/state/precompiles.cpp b/test/state/precompiles.cpp index aeb355f3d5..cb36888527 100644 --- a/test/state/precompiles.cpp +++ b/test/state/precompiles.cpp @@ -4,11 +4,11 @@ #include "precompiles.hpp" #include "precompiles_internal.hpp" -#include "precompiles_stubs.hpp" #include #include #include #include +#include #include #include #include @@ -19,6 +19,10 @@ #include #include +#ifdef EVMONE_PRECOMPILES_OPENSSL +#include "precompiles_openssl.hpp" +#endif + #ifdef EVMONE_PRECOMPILES_SILKPRE #include "precompiles_silkpre.hpp" #endif @@ -299,24 +303,51 @@ ExecutionResult ripemd160_execute(const uint8_t* input, size_t input_size, uint8 return {EVMC_SUCCESS, 32}; } -static ExecutionResult expmod_execute( +ExecutionResult expmod_execute( const uint8_t* input, size_t input_size, uint8_t* output, size_t output_size) noexcept { static constexpr auto LEN_SIZE = sizeof(intx::uint256); // The output size equal to the modulus size. // Handle short incomplete input up front. The answer is 0 of the length of the modulus. - if (output_size == 0 || input_size < 3 * LEN_SIZE) [[unlikely]] + if (output_size == 0 || input_size <= 3 * LEN_SIZE) [[unlikely]] { std::fill_n(output, output_size, 0); return {EVMC_SUCCESS, output_size}; } -#ifdef EVMONE_PRECOMPILES_SILKPRE - return silkpre_expmod_execute(input, input_size, output, output_size); -#else - return expmod_stub(input, input_size, output, output_size); -#endif + static constexpr size_t input_header_required_size = 3 * LEN_SIZE; + uint8_t input_header[input_header_required_size]{}; + std::copy_n(input, std::min(input_size, input_header_required_size), input_header); + const auto base_len = intx::be::unsafe::load(input_header); + const auto exp_len = intx::be::unsafe::load(&input_header[32]); + const auto mod_len = intx::be::unsafe::load(&input_header[64]); + + // This is assured by the analysis. + assert(output_size == mod_len); + + // Extend input to full size (input_header_required_size + base_len + exp_len + mod_len). + // Filled with zeros + const auto full_input_size = + input_header_required_size + static_cast(base_len + exp_len + mod_len); + evmc::bytes full_input(full_input_size, 0); + std::copy_n(input, std::min(input_size, full_input_size), full_input.data()); + + evmone::crypto::modexp(output, output_size, + { + &full_input[input_header_required_size], + static_cast(base_len), + }, + { + &full_input[input_header_required_size + static_cast(base_len)], + static_cast(exp_len), + }, + { + &full_input[input_header_required_size + static_cast(base_len + exp_len)], + static_cast(mod_len), + }); + + return {EVMC_SUCCESS, output_size}; } ExecutionResult ecadd_execute(const uint8_t* input, size_t input_size, uint8_t* output, diff --git a/test/state/precompiles_internal.hpp b/test/state/precompiles_internal.hpp index fdfdbedf89..c87b28e272 100644 --- a/test/state/precompiles_internal.hpp +++ b/test/state/precompiles_internal.hpp @@ -45,6 +45,8 @@ ExecutionResult ripemd160_execute( const uint8_t* input, size_t input_size, uint8_t* output, size_t output_size) noexcept; ExecutionResult identity_execute( const uint8_t* input, size_t input_size, uint8_t* output, size_t output_size) noexcept; +ExecutionResult expmod_execute( + const uint8_t* input, size_t input_size, uint8_t* output, size_t output_size) noexcept; ExecutionResult ecadd_execute( const uint8_t* input, size_t input_size, uint8_t* output, size_t output_size) noexcept; ExecutionResult ecmul_execute( diff --git a/test/state/precompiles_openssl.cpp b/test/state/precompiles_openssl.cpp new file mode 100644 index 0000000000..c2d5d98b39 --- /dev/null +++ b/test/state/precompiles_openssl.cpp @@ -0,0 +1,45 @@ +// evmone: Fast Ethereum Virtual Machine implementation +// Copyright 2025 The evmone Authors. +// SPDX-License-Identifier: Apache-2.0 + +#include "precompiles_openssl.hpp" +#include +#include +#include + +namespace evmone::state +{ +ExecutionResult openssl_expmod_execute(const uint8_t* input, size_t input_size, uint8_t* output_buf, + [[maybe_unused]] size_t max_output_size) noexcept +{ + assert(input_size >= 3 * sizeof(intx::uint256)); + const auto base_len = static_cast(intx::be::unsafe::load(input)); + const auto exp_len = static_cast(intx::be::unsafe::load(input + 32)); + const auto mod_len = static_cast(intx::be::unsafe::load(input + 64)); + assert(mod_len == max_output_size); + + // FIXME: Don't copy full input, just modulus should be enough. + const auto input_padded = std::make_unique(base_len + exp_len + mod_len); + std::copy_n(input + 96, input_size - 96, input_padded.get()); + + const auto base = BN_bin2bn(&input_padded[0], static_cast(base_len), nullptr); + const auto exp = BN_bin2bn(&input_padded[base_len], static_cast(exp_len), nullptr); + const auto mod = + BN_bin2bn(&input_padded[base_len + exp_len], static_cast(mod_len), nullptr); + + if (BN_is_zero(mod) == 0) + { + const auto ctx = BN_CTX_new(); + [[maybe_unused]] const auto status = BN_mod_exp(mod, base, exp, mod, ctx); + assert(status == 1); + BN_CTX_free(ctx); + } + + BN_bn2binpad(mod, output_buf, static_cast(mod_len)); + + BN_free(base); + BN_free(exp); + BN_free(mod); + return {EVMC_SUCCESS, mod_len}; +} +} // namespace evmone::state diff --git a/test/state/precompiles_stubs.hpp b/test/state/precompiles_openssl.hpp similarity index 53% rename from test/state/precompiles_stubs.hpp rename to test/state/precompiles_openssl.hpp index 5920f6360c..1a221c3025 100644 --- a/test/state/precompiles_stubs.hpp +++ b/test/state/precompiles_openssl.hpp @@ -1,5 +1,5 @@ // evmone: Fast Ethereum Virtual Machine implementation -// Copyright 2024 The evmone Authors. +// Copyright 2025 The evmone Authors. // SPDX-License-Identifier: Apache-2.0 #pragma once @@ -7,6 +7,6 @@ namespace evmone::state { -ExecutionResult expmod_stub( - const uint8_t* input, size_t input_size, uint8_t* output, size_t max_output_size) noexcept; +ExecutionResult openssl_expmod_execute( + const uint8_t* input, size_t input_size, uint8_t* output_buf, size_t max_output_size) noexcept; } // namespace evmone::state diff --git a/test/state/precompiles_stubs.cpp b/test/state/precompiles_stubs.cpp deleted file mode 100644 index 4fe832758f..0000000000 --- a/test/state/precompiles_stubs.cpp +++ /dev/null @@ -1,373 +0,0 @@ -// evmone: Fast Ethereum Virtual Machine implementation -// Copyright 2024 The evmone Authors. -// SPDX-License-Identifier: Apache-2.0 - -#include "precompiles_stubs.hpp" -#include "../utils/utils.hpp" -#include "hash_utils.hpp" -#include -#include -#include - -namespace evmone::state -{ -using test::operator""_hex; - -namespace -{ -struct HashedInputStubs : std::unordered_map -{ - using unordered_map::unordered_map; - - ExecutionResult lookup(bytes_view input, uint8_t* output, size_t max_output_size) const - { - if (const auto it = find(keccak256(input)); it != end()) - { - if (it->second.size() > max_output_size) - return {EVMC_INTERNAL_ERROR, 0}; // invalid stub entry. - std::ranges::copy(it->second, output); - return {EVMC_SUCCESS, it->second.size()}; - } - return {EVMC_PRECOMPILE_FAILURE, 0}; // not found, treat as a failure. - } -}; -} // namespace - -ExecutionResult expmod_stub( - const uint8_t* input, size_t input_size, uint8_t* output, size_t max_output_size) noexcept -{ - static const HashedInputStubs stubs{ - {0x010d1c26efabac677596f64e2e4f8894606e3636370a8665756ebc184e745aba_bytes32, - "000000000001"_hex}, - {0x033274602281965ae0382e28ea7584792e3d846b4ead2f1529e0d61a63afa9b9_bytes32, - "0000000000000000000000000000000000000000000000000000000000000000"_hex}, - {0x034d54cdad5956fb28f9060287fad9073c1e87fb7c6d1709e00f362c9052aff7_bytes32, - "0000000000000000000000000000000000000000000000000000000000000001"_hex}, - {0x03c85b4c0caf8657ff29b05743c33f9ffbb8df604c46cc86caa2f051e6a065a8_bytes32, - "0000000000000000000000000000000000000000000000000000000000000000"_hex}, - {0x067b3e4d57e1fe2d23c71a95cdd86c8019a649e466d5fcf8e22cce66ceea36fc_bytes32, - "0000000000000000000000000000000000000000000000000000000000000001"_hex}, - {0x08774b45b9263bbdd4f040b01c444d167f20686daf1d9dc0be2703ac5b79898f_bytes32, - "0000000000000000000000000000000000000000000000000000000000000001"_hex}, - {0x0ea4f1fe8ab439ed65bf736c2d1e75244a52fec0e96cefadf09ea5d170956d52_bytes32, - "0e7de84a5bcf0e16fa56b80cbf55f39877229030e5a8af78a0a78e003cdb657b"_hex}, - {0x0f38b3a063df12614121ae2d0cd202213a5fa95e3536e0f82c3bbffb311f9152_bytes32, "02"_hex}, - {0x0ff064739dbad34456d55c4dafd7d33b7e0e7c63b18a1252ef9fd8bc88867234_bytes32, - "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009"_hex}, - {0x10eab4762daae8abab287dd86a83326a78f5bbb8641f38a6792819576c94e35a_bytes32, - "0000000000000000000000000000000000000000000000000000000000000001"_hex}, - {0x12292042f822da16c3db8dc1fc978be48218e0fb997cfff35857e16abba41300_bytes32, - "0000000000000000000000000000000000000000000000000000000000000001"_hex}, - {0x12993abd44b4858730eb18a794ee686dc20b54cfee0e75a1f2e345cf9568ecc1_bytes32, "01"_hex}, - {0x12fc00c16a89e602782828a84667390d4a14bf74c1fd16dab784c7ebae45de06_bytes32, - "0000000000000000000000000000000000000000000000000000000000000000"_hex}, - {0x130508100dd1f8b1c72b7eb16f82ee3b8a6f3bcbc8461c9f02c06f14ead89d75_bytes32, - "0000000000000000000000000000000000000000000000000000000000000000"_hex}, - {0x1403e9d046887460408ff2c1956a064def64c4bb221b7bdff146b097b3a282c5_bytes32, - "0000000000000000000000000000000000000000000000000000000000000001"_hex}, - {0x1669beee2b904266bc5a6eef210d6869ccea5c9a25e173d940428ccfbd6310c4_bytes32, "0000"_hex}, - {0x180fd71813c81062f2cdf852bc03fb8e8b8b98d21436001e255dc7141cb299d7_bytes32, - "0000000000000000000000000000000000000000000000000000000000000000"_hex}, - {0x18c5b4c6cf9fccb97b1cf7f966b2ca8e951365e13eaf63ec93d3fd4ad87fadb5_bytes32, - "0000000000000000000000000000000000000000000000000000000000000000"_hex}, - {0x18ca0a599a7bcdfd7e487cafca8ab1dfb6ef18074841fc3da95b73479eee3270_bytes32, - "0000000000000000000000000000000000000000000000000000000000000000"_hex}, - {0x1a949941ca6b99c817a4e16cefe478308222535d19f1437ae2fdd892cb8ac789_bytes32, - "0000000000000000000000000000000000000000000000000000000000000001"_hex}, - {0x1d885466c9ed74249248ad01d298eb4f509d9102a849d767f893da1e78799a9d_bytes32, "0002"_hex}, - {0x1e2d85db0c7c63bcc2054bf2d3caaf5d61920c77bb16f10572e6115458b0c352_bytes32, "00"_hex}, - {0x1e6d8ff8f706b4b423086b9c725a43e4aa6ce504b790612fb0e6f738cafa5b00_bytes32, - "0000000000000000000000000000000000000000000000000000000000000000"_hex}, - {0x1ea137b55c9c2a68d4dd701fc31c5a11a2fcb3f9cc4c2fe6b2bf968d250ece35_bytes32, - "0000000000000000000000000000000000000000000000000000000000000000"_hex}, - {0x1fe8359bcf1145edd7e23e4c32df953ea82d5db7a0d840ebe1d436f73bf93c5d_bytes32, - "0000000000000000000000000000000000000000000000000000000000000000"_hex}, - {0x216ff577ab4b6adc22902060367bba5d514a67cb53b6171bc62569e58ce1a8ce_bytes32, - "0000000000000000000000000000000000000000000000000000000000000001"_hex}, - {0x21879cfde84f139c4c53262a49dff3c774b0e2949fce670e2f471e54f1ffbc23_bytes32, "00"_hex}, - {0x21915510d6f6b58738bc790d97df3881396743ef975eb2a4d7dd0cd4bc10bc4b_bytes32, - "0000000000000000000000000000000000000000000000000000000000000001"_hex}, - {0x244fa8474b97c1fc5589e3372062373bc939e2c2c8d51733cb62dd1af06d93ae_bytes32, - "0000000000000000000000000000000000000000000000000000000000000000"_hex}, - {0x251828ea0fa55eeff4920c784f29d02b3d462893b0a53b35da407951f670d4c3_bytes32, - "0000000000000000000000000000000000000000000000000000000000000000"_hex}, - {0x251f23d45faa62fd4edee6c7ca9d0e522dd618b21ca79c0ececcf6b4ab1d418e_bytes32, - "0000000000000000000000000000000000000000000000000000000000000000"_hex}, - {0x2559c03f8499faccfb5d86c5a9c6857b9882045939b54fcab26046debc586400_bytes32, - "0000000000000000000000000000000000000000000000000000000000000000"_hex}, - {0x25612858eb4e5086b12e02d2fbb70b8b64bb55022fdd629ec789f2c84607688f_bytes32, - "0000000000000000000000000000000000000000000000000000000000000000"_hex}, - {0x26d4791888c6a5a6dad93c613727e1025a5e629993ace97b6f60a168ba5b643b_bytes32, "3e"_hex}, - {0x274f35379f9c71d56060a980068aa27bbb6b0163485b566c98f23208d9afebe8_bytes32, - "0000000000000000000000000000000000000000000000000000000000000001"_hex}, - {0x27611fee3bcae57830f4acede0e4ddc28d6b80307e4e3c24518ff8427870b1a2_bytes32, - "0000000000000000000000000000000000000000000000000000000000000000"_hex}, - {0x2815ce44f31ea08706a5b434ba9241be790bb99a9a14f2abc58f44e4c7ed5258_bytes32, - "0000000000000000000000000000000000000000000000000000000000000001"_hex}, - {0x2aa26dd05f29718306030f45826699e7cfa5cee2d7e693743f08ca1890c70471_bytes32, "00"_hex}, - {0x2bbbf3147d86f35e028afe730dbe8a309c343a5af574d686b4de6f0299f44b62_bytes32, "00"_hex}, - {0x2e2b0152d440cb2300acb1a66f126dc6a55d48429cd4d1c65a6b08b1d70faa1a_bytes32, "00"_hex}, - {0x2e7668b70ebbbf0427b7206105b43be56ed44866084aef806b455c4302bb09ed_bytes32, - "0000000000000000000000000000000000000000000000000000000000000000"_hex}, - {0x2ebcffbe9bfd10639c61895d63dc4adbea44b1ef949f81ec56b684a553ac3325_bytes32, - "0000000000000000000000000000000000000000000000000000000000000000"_hex}, - {0x2fa614a47cc9c85b69679204e1ef9ac927b19471ded492b8ece1e8e67262fb51_bytes32, - "0000000000000000000000000000000000000000000000000000000000000000"_hex}, - {0x31d7d7f3d30e2f6915813b0eae348106f9c36033685f734d666df55950721e09_bytes32, - "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009"_hex}, - {0x35de80ebb4a020482ef20b08e76ccf3047a069603f0f298ca69d20d652e8d84b_bytes32, - "00000000000000000000000001"_hex}, - {0x39d0581989c293b89482bfa1e116cec4009a18aa00b89c5242b7fe5c3766ed7e_bytes32, - "0000000000000000000000000000000000000000000000000000000000000001"_hex}, - {0x39e4706fe515d7364d5d89bca544e81f9ef187062620ac4e97b4c64e9dba668a_bytes32, - "0000000000000000000000000000000000000000000000000000000000000000"_hex}, - {0x3b41faafc90d54978545a2f7f0a0fbc5710b148872dd6e1d6c2ec4c94fee3617_bytes32, - "0000000000000000000000000000000000000000000000000000000000000001"_hex}, - {0x3b73107bd69d6198ed057833aac40d0dcdc99e568c5e4f2ff154688bbab5fb26_bytes32, - "000000000000000000000000000000000000000000000000000000000000000001"_hex}, - {0x3bf09109c39d56015c8905aa26907c8f8c509e4a54ff4efee2f896a8b1176042_bytes32, - "0000000000000000000000000000000000000000000000000000000000000000"_hex}, - {0x3cc1cc331ba2e9897c734d97dfb178fecedbc4cc90c706eee0c6059c94b36297_bytes32, "0000"_hex}, - {0x3d8f5d715374acba3f92a425b8bad30eae5f2f534a63c4cea5ad4401fe46ad75_bytes32, - "0000000000000000000000000000000000000000000000000000000000000000"_hex}, - {0x4084709b90b82b198ec95c387a53f65e5492611a56a9bf34a46d7c5fa02907dd_bytes32, - "0000000000000000000000000000000000000000000000000000000000000001"_hex}, - {0x418b0655db32fa5820ed237053dfe34869c9a1c39460ed8d58e6e87e5164f8ec_bytes32, - "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"_hex}, - {0x4262e4bfbfbc25391172acaa697e2b36c9aa60be165a81de92f9a6be0ed447ca_bytes32, - "0000000000000000000000000000000000000000000000000000000000000000"_hex}, - {0x42c4e39cf1e2224199b3895508025d4cf89fc21154dd0ba0c9f86ebbe81667a1_bytes32, - "0000000000000000000000000000000000000000000000000000000000000000"_hex}, - {0x42d09d5551133d4982c7c496aa710fdeb46c2974fa2ee405bd0cf2d8687f5eb4_bytes32, "0000"_hex}, - {0x469eae86b1701336b3d583df4527d639b1cccca716608b728563a0eeeeeb55ba_bytes32, - "0000000000000000000000000000000000000000000000000000000000000001"_hex}, - {0x4798efaf9795653086f314b2a745a3c677befc3a143f8e71f6961410234d4aa7_bytes32, - "0000000000000000000000000000000000000000000000000000000000000000"_hex}, - {0x48cbcce9cddcfc87a9dfb28f8c07a498c6cae91c3577410009e009de8ae15426_bytes32, - "0000000000000000000000000000000000000000000000000000000000000001"_hex}, - {0x48d102df204080cb58f6131e8de27892647da0958ab111e3b7604279fe7638d9_bytes32, - "0000000000000000000000000000000000000000000000000000000000000001"_hex}, - {0x49daba1e38b9fdb769584f02a5cf0d5ccc52e1dcc5f1683c384e308cbda1aefb_bytes32, - "0000000000000000000000000000000000000000000000000000000000000000"_hex}, - {0x4a4e7e22f228bbfeef1e2e652aeb39630a3fea4545ce98694e34b3a13cbf4d9c_bytes32, - "162ead82cadefaeaf6e9283248fdf2f2845f6396f6f17c4d5a39f820b6f6b5f9"_hex}, - {0x4b1c0353029df7c0e24c97c1caa608b2447a736abd6ec92c6a6ad19c74af6764_bytes32, - "0000000000000000000000000000000000000000000000000000000000001c3b"_hex}, - {0x4c1451f2f475e314e13ab026083f0e75042da3757331579bcc2acf982eb93e47_bytes32, - "0000000000000000000000000000000000000000000000000000000000000001"_hex}, - {0x4d26511722a244d920d5b388b5008248c71b7232df5e2dad0c68731ecea7baca_bytes32, - "0000000000000000000000000000000000000000000000000000000000000000"_hex}, - {0x4e895772ea04e2bebc4494c0f61d649af0ec15eb35e3d6fb23ccd43cec8fc477_bytes32, - "0000000000000000000000000000000000000000000000000000000000000001"_hex}, - {0x4e9bc8aacd818468cd54729198300a542eaa7ed24d172b0fa62eaca18c80320f_bytes32, "0000"_hex}, - {0x560aefbbe4dc7910322f1a57808798dd21e6f20b6804497d76feb28109d9e4b4_bytes32, "00"_hex}, - {0x56cd39d56e15e186eb742169736637742fe0129e3816caa42199e1d11444a087_bytes32, - "0000000000000000000000000000000000000000000000000000000000000001"_hex}, - {0x57f24ba6197dd6bca4b92b2b069547c4d9715cb715b118fd06b6c506f3fe9a6f_bytes32, - "0000000000000000000000000000000000000000000000000000000000000001"_hex}, - {0x58dca178acf545c5f569bf230c25f4b299df65d50427e5599c062de84ae8e117_bytes32, - "0000000000000000000000000000000000000000000000000000000000000000"_hex}, - {0x59083a31c083633493c1f0fff98188fc553195939b97664ddf4f1f7372fdb9ed_bytes32, "00"_hex}, - {0x5913b435dbacbaf8a060c4901cb61a7aeea4f64e04bed5194a9cda0e3f7407b9_bytes32, - "0000000000000000000000000000000000000000000000000000000000000000"_hex}, - {0x5ad3326c83fc81b119a19e072abec9b015d3230407d61fddeac53d8d622665d2_bytes32, - "0000000000000000000000000000000000000000000000000000000000000000"_hex}, - {0x5d8c10bff855aeafad14cc8945d96363078f03b05fdd68cc8bf7db0f345f344d_bytes32, "0000"_hex}, - {0x5daa348868b1c7f027498f63593dc226890161a6e9fc6a458299fb2d954354d2_bytes32, - "0000000000000000000000000000000000000000000000000000000000003e80"_hex}, - {0x5ec71d7c8e69482d0e0118734635e881ff05f5a87604da2302f19e3ade457b42_bytes32, - "0000000000000000000000000000000000000000000000000000000000000000"_hex}, - {0x5ef61126f34e679f7b6d859b4f20cb716481fe3e7003d0bcfb017694f6d28649_bytes32, - "0000000000000000000000000000000000000000000000000000000000000000"_hex}, - {0x65a35fae82f3775f4e1b92c56cd68718784dd29d132d62722e7bda3853a3d837_bytes32, "04"_hex}, - {0x66b7f8ac5bd4017cc1ae82dc7a1a5334bcb127a1f64ebe4f1a7595196da10a58_bytes32, "0000"_hex}, - {0x67f7c6a923a7558c8cb23e8475dda653460be6ee507466645d79d5fa6dd5c63f_bytes32, "01"_hex}, - {0x68ad0981c9f951bdbcad78d21e35e5ec7918595b341c8b3dd81d5f50eca06b78_bytes32, - "0000000000000000000000000000000000000000000000000000000000000000"_hex}, - {0x6b1061285efade3c0b2593286bb08db69ae28df9e1d6714041b063e362ba1988_bytes32, - "0000000000000000000000000000000000000000000000000000000000000000"_hex}, - {0x6beafa77883efd2c221ea4cb29831d1fe10a2190379312217dbe57909ac356b0_bytes32, - "0000000000000000000000000000000000000000000000000000000000000001"_hex}, - {0x6d835e80050760971242c410fa7ddaf8b268d3669e2db343fd61343cd87d80f4_bytes32, - "0000000000000000000000000000000000000000000000000000000000000000"_hex}, - {0x6de36875921c76ab5434e64791cc62395d65f49eb21f9ddaa82aa8756b44ed3d_bytes32, - "000000000000000000000000000000000000000000000000000000000000866a"_hex}, - {0x6edab1ef76af731a34f9a306bfdeeaefe48aa8f4826c329e1fdd702652e17927_bytes32, - "0000000000000000000000000000000000000000000000000000000000000000"_hex}, - {0x6f64f08deaeee1f2aa90289b4aaafc4d76bf5d79a6f0aee01cce6f914d6523af_bytes32, - "0000000000000000000000000000000000000000000000000000000000009c00"_hex}, - {0x7030a0dcea1e544f2f20cab453564c3f7343ea3c7949e30b35c9b562d2a6f532_bytes32, - "0000000000000000000000000000000000000000000000000000000000000001"_hex}, - {0x72937ea411f48b90764786c97d4229d192cc6b1426fabdc86b59298816af97bc_bytes32, - "0000000000000000000000000000000000000000000000000000000000000000"_hex}, - {0x73291d37d5bdc108723a04c171d113d6c323c46000569d0eaa319e295497a911_bytes32, - "0000000000000000000000000000000000000000000000000000000000000000"_hex}, - {0x75137d2ac452fa56c54f3a84b6a5032cf7e9979578b76da3d8893684ffc3c0c7_bytes32, - "0000000000000000000000000000000000000000000000000000000000000000"_hex}, - {0x75e5c2f08ba7f4f5196eeee2fa5d4585c1a7d13d94c8dd01d8db7c6664bf5dc0_bytes32, "0000"_hex}, - {0x7687fd0273528d2f1aa49723afefa95a867eaa5a6a898a75d8d1c1774f244cdb_bytes32, - "0000000000000000000000000000000000000000000000000000000000000000"_hex}, - {0x77d6ede055e1bf3669db1b8e965fcced0a76864f364f6135e6cabe1037fe4809_bytes32, - "0000000000000000000000000000000000000000000000000000000000000000"_hex}, - {0x7870eaca19c10f38ad151dabd337cbc8e2df484ac4801b07b0d80348b645931e_bytes32, - "0000000000000000000000000000000000000000000000000000000000000001"_hex}, - {0x7bf0fbb8f1754a19c5efdf2dbdc4288c2d8728852734b30dc057d53beb59e5de_bytes32, - "0000000000000000000000000000000000000000000000000000000000000001"_hex}, - {0x7d24c042d652db2f2d9e2e5d1eae97d19b44109420f11b6eadb6b90cb1ba50ea_bytes32, - "0000000000000000000000000000000000000000000000000000000000000001"_hex}, - {0x7f2686134db3a520c34fdf758eba9a0d4f9c8945a3f06d1f4d7eb68b433be142_bytes32, - "0000000000000000000000000000000000000000000000000000000000000001"_hex}, - {0x80de6c463032565ad835285aac5101f9748b93dde6ad45bb1136190bb8f5c253_bytes32, - "0000000000000000000000000000000000000000000000000000000000000000"_hex}, - {0x8187355fc5e82694be920349dee28c7d4ec2a7bc15a85db4db530b13f34b4050_bytes32, - "0000000000000000000000000000000000000000000000000000000000000000"_hex}, - {0x8191431cab44389a73030b5819d7af3bcdb3cb49e618810032cb1fd4e746bb41_bytes32, "0000"_hex}, - {0x8257bcfd8eb8eb906d8f3a0f3cb71577e6267f1a4af7f3fc611dc19dd96192bc_bytes32, - "0000000000000000000000000000000000000000000000000000000000000001"_hex}, - {0x8507835cf8ffeccb9e5a2ef45b957ae5f463861884bcd279214fa36b2965619b_bytes32, - "0000000000000000000000000000000000000000000000000000000000001c3b"_hex}, - {0x86d444d512bd04db648bc23e024132fbc2186aa73cda0bf0741114132324124b_bytes32, - "0000000000000000000000000000000000000000000000000000000000000000"_hex}, - {0x87b97726f9d1d6e04d170320fc2d8b16a971ecaa1048ac38dabab51369bd4543_bytes32, - "0000000000000000000000000000000000000000000000000000000000000000"_hex}, - {0x880480a0dbe4cddcdb5cea5a9d483524b2f6c4e7b492bfe236b8d15649d0673d_bytes32, "00"_hex}, - {0x88451def3af9b5d137d0082f973d90facb971643f4eabf3c201a634861facef4_bytes32, - "000000000000000000000000000000000000000000000000000000000000001b"_hex}, - {0x8a068cd204782a5859890b4201f784e3ade964c45f373bc4e20f2f0c60c927f6_bytes32, - "0000000000000000000000000000000000000000000000000000000000000000"_hex}, - {0x8ad16be55060aff4f690974f6b8c74de388599e798c8ff48261897a95729fb9f_bytes32, - "0000000000000000000000000000000000000000000000000000000000000000"_hex}, - {0x8b4d99f7357e3cf1c7ad74cfce0c1bab1ab69920595b7bb2c20ed919aa03f77c_bytes32, - "0000000000000000000000000000000000000000000000000000000000000001"_hex}, - {0x8bf994b1ef100d61c6b3857392be820ae7855cc194cfffa90d3b43d0a28b13b5_bytes32, - "3b01b01ac41f2d6e917c6d6a221ce793802469026d9ab7578fa2e79e4da6aaab"_hex}, - {0x8d69df480ceb95c657631fe973f8777f032a807fe36e698458813ae8ac5276e4_bytes32, - "0000000000000000000000000000000000000000000000000000000000000001"_hex}, - {0x90ac1c964e1edcf937f9332f953f971919ef44a105ec663be0eb6707ef52de9b_bytes32, "0002"_hex}, - {0x91bbd8d35060a647704e6e8410263135b9df075665d0286495fba2ad2129d178_bytes32, - "0000000000000000000000000000000000000000000000000000000000000001"_hex}, - {0x93d390c50ad9871ea4b3ec9de9c3f10646951691931e069e03c0de0675bc6b05_bytes32, "00"_hex}, - {0x96cf34086b42afae29477ebe8d6eeba6fef1da1690e0ea32d8c4947466324569_bytes32, - "0000000000000000000000000000000000000000000000000000000000000000"_hex}, - {0x993d6040be7987f83bb56811395b7d76d577bd885b943d2755b44fda0b44cf50_bytes32, - "0000000000000000000000000000000000000000000000000000000000000000"_hex}, - {0x996f9283a0477c8eaddbd50c4a9927c80b0281d3193538469f79ae95f8ec2f5e_bytes32, - "0000000000000000000000000000000000000000000000000000000000000001"_hex}, - {0x9ab09ec74fdfe6a0f390d51b70f6b31a9b99287080d91395864c689ec8ef96e1_bytes32, - "0000000000000000000000000000000000000000000000000000000000000050"_hex}, - {0x9c3a806764dc757a3c4f3e4ab27f2d645f13684a5d0f65b3e527fd144464d052_bytes32, - "0000000000000000000000000000000000000000000000000000000000000000"_hex}, - {0x9ce2281a0a9ead36edc758647abc060766f200a5210d5b97a9b7d1752578c3ee_bytes32, - "0000000000000000000000000000000000000000000000000000000000008615"_hex}, - {0x9e24cd89db1e412aa85e71e9ea955e00a1c22d66716bbd19fc92df1a122a71bf_bytes32, "01"_hex}, - {0x9e6a8ff68b83a4a01c2c344f507ab1c738cf5df1f6f846d47fea6f5d397b06e4_bytes32, - "000000000000000000000000000000000001"_hex}, - {0xa05b578a2942544883921581b74d7bc5f44de59ae5d1a3cc21626658b5d9cf41_bytes32, - "0000000000000000000000000000000000000000000000000000000000000001"_hex}, - {0xa4ddac19e1b86ed2a29ecc5ca2e2d840923f30380f5c2a732b746427b97c7970_bytes32, - "0000000000000000000000000000000000000000000000000000000000000001"_hex}, - {0xa923d0e400cbbe1e0915c5a699cb8a51578ae87755f1aae7929289166ff23f33_bytes32, - "0000000000000000000000000000000000000000000000000000000000000001"_hex}, - {0xab76f1d5488b8542336a386818cf99412b7aa17c589d244c29f9ae9cb3901815_bytes32, - "0000000000000000000000000000000000000000000000000000000000000001"_hex}, - {0xada673786089f911b5dc7c5fc3405c206e6e7564e4dd4466b563d03e659e94a2_bytes32, - "0000000000000000000000000000000000000000000000000000000000000000"_hex}, - {0xb07a3d24561ccfb56dd51bed4d640a0f00d5d86fe953d986846be0930c35157d_bytes32, - "0000000000000000000000000000000000000000000000000000000000000000"_hex}, - {0xb0e9dd0b5749795680b0cc0db0167b85f1d2417acf9b44869d17a876a4f422ba_bytes32, "02"_hex}, - {0xb2f231521511b65fba5f194f65a93426b16df90c4ca4bbf0b51e2c3b02d59b2b_bytes32, - "0000000000000000000000000000000000000000000000000000000000000001"_hex}, - {0xb303e361c4edd99c9e86513e769056c2faf0359ed8ec911ab473f14d5e8bfe95_bytes32, "0001"_hex}, - {0xb50e0123a517ebb42db0e4d926c86a515d5cc55cbe6cebe6b6a99ecd3a0dcd90_bytes32, "01"_hex}, - {0xb5a34ff06af3b01441b6ee4ffac60feee6f0b63ed6be80a21c8aaf8b9e7f0b4d_bytes32, - "0000000000000000000000000000000000000000000000000000000000000000"_hex}, - {0xb7c17933a8cb769998187b25ea82c3ac8dffcf3d1976a60b023b9d06c0cd9a4f_bytes32, - "0000000000000000000000000000000000000000000000000000000000000000"_hex}, - {0xb97681ddced4ee8f4efffc5b58044de3100b2dc7c1f7f6b72161200f10b0604c_bytes32, - "0000000000000000000000000000000000000000000000000000000000000001"_hex}, - {0xb9d52ce810f7c808324c717f1a5b612512a24a3227d311f508edec3c931344ad_bytes32, - "000000000000000000000000000000000000000000000000000000000000005f"_hex}, - {0xbafcbd8a4bbc5837e3a637e432c4ee0a48e30a6b760efaaed699aed606b0c768_bytes32, - "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"_hex}, - {0xbc2ae76808e3de30404a4dd4221f3289cf20a272161d4f8c0c58c2e736706256_bytes32, - "3b01b01ac41f2d6e917c6d6a221ce793802469026d9ab7578fa2e79e4da6aaab"_hex}, - {0xbc8a5df0db3fc6a076ea676a8dd5f6689777de551a235d75f77a520bd243208d_bytes32, - "0000000000000000000000000000000000000000000000000000000000000000"_hex}, - {0xbd59618a09cdeb7538ce8cf97820ae2ab18102ac903c34c7de6d72c63c3d0f08_bytes32, "00"_hex}, - {0xbe17aa6916c3d516ea45c2b8fc312f6bffc47f14325b7a9005786f878e1bb3ba_bytes32, - "0000000000000000000000000000000000000000000000000000000000000001"_hex}, - {0xbf528ce5e535e2cf241dc944b153d5925ab2cdd488c386e326716b6a8ecf751a_bytes32, "0000"_hex}, - {0xc1ec6ef309c736331efc3000afc186d2021944309ee6b20a4bf3bc735b7aea75_bytes32, - "0000000000000000000000000000000000000000000000000000000000006801"_hex}, - {0xc3e4a3530ca51ae69ee63be92701c84c6ebd820e1f89ca15548c94dbb851101e_bytes32, - "00000000000000000000000000000001"_hex}, - {0xc4527e59efc328e49b6926353042b1758cc422461230653e83a433634155adcd_bytes32, - "0000000000000000000000000000000000000000000000000000000000000000"_hex}, - {0xca29ae8887f56b58494b8404be63728fb620247345837253ee264b09b9c1057a_bytes32, "01"_hex}, - {0xcba5ff6688618456c8228b8c2bfb4ed254ad8620b99ef3ed8fbcb5bc66feb478_bytes32, - "0000000000000000000000000000000000000000000000000000000000000000"_hex}, - {0xcd223a9e187147d1712bdeed93889e2edad86091108b10bb97790428717dee31_bytes32, - "0000000000000000000000000000000000000000000000000000000000000000"_hex}, - {0xce9b2bf13532af4013c467e57479a71625bf1a7c8190393f29ffe8d3f3275aae_bytes32, - "0000000000000000000000000000000000000000000000000000000000000000"_hex}, - {0xd09419104ce1c64b6a06bcf063e98c2c91ad9e1beaf98b21c9d4734b4a3c9956_bytes32, - "0000000000000000000000000000000000000000000000000000000000000000"_hex}, - {0xd6c0c03ec1f713b63be3d39b4fa8ef082b3407adc29baf74669fd2a574c638ac_bytes32, "01"_hex}, - {0xd837f9dcf93155fe558c02c7a660edc0cd238a8b8f95ee6b68e4a5c6a41fc70a_bytes32, - "0000000000000000000000000000000000000000000000000000000000000001"_hex}, - {0xdb5d4994d6dae845a6fd76e91ade4d3a35f270d86673ccc32405042c3c3d37ba_bytes32, - "0000000000000000000000000000000000000000000000000000000000000001"_hex}, - {0xdbc6ddf9220c7ccfc94057fd3d25b712a0d7f51c3ff44e291458f2daf4ef2ec4_bytes32, - "0000000000000000000000000000000000000000000000000000000000000000"_hex}, - {0xdf244f503af99f62276115256c481d3cf0786d477553cf0bb25df1579dbc9ee3_bytes32, - "0000000000000000000000000000000000000000000000000000000000000001"_hex}, - {0xdfab0a2d13154e415f4f999b6570efd185de14a2cf07a14eb543feef7542a5fa_bytes32, - "000000000000000000000001"_hex}, - {0xe0aed3305cfbf6b99096f7ea895c0f2d721dea396d08c75c892152e757668eb8_bytes32, - "0000000000000000000000000000000000000000000000000000000000000001"_hex}, - {0xe1223738398f40c909a2f63d7f617ea86f1c6b8bd82786ec6e3ff0a8729ee803_bytes32, - "0000000000000000000000000000000000000000000000000000000000000000"_hex}, - {0xe1d19f16b8648afb5fd13c5bd437554c9d1bd61855b47cf4069d6068f27f90c5_bytes32, - "0000000000000000000000000000000000000000000000000000000000000001"_hex}, - {0xe6f0c93cd48787b5c65c1df991ab038e7fd1512ae6fa680ca79051348e4bd2c5_bytes32, "2b"_hex}, - {0xe7e08425a2da0d12f7d6cdefc8722e15f577c8b7908924ef5a6f09dc8a8df381_bytes32, - "0000000000000000000000000000000000000000000000000000000000000001"_hex}, - {0xe9321ede4409baf4d20ce11283a0267a934062cd546b6fb0097d755686ff0194_bytes32, - "0000000000000000000000000000000000000000000000000000000000000000"_hex}, - {0xe99b55f3b486798837a08b10ad2cd917ab907b7c3d62ab7cc31f0d9aeb19c043_bytes32, - "0000000000000000000000000000000000000000000000000000000000000001"_hex}, - {0xebd3e19945cff9b7462359bb882a8005d9d1d69d9f82db099f29508447ec7b59_bytes32, - "0000000000000000000000000000000000000000000000000000000000000000"_hex}, - {0xece1937784110ebc937ef343c108c6385a8b13b3e8d0617d30bb6bd95701f270_bytes32, "01"_hex}, - {0xf0001b79c0ca5c8fa824f187c3e987fd066688f64c1763648df46d59bfcd7a32_bytes32, - "0000000000000000000000000000000000000000000000000000000000000000"_hex}, - {0xf109ca1998eda403604fe597551159daf3bf1c60b6a9f28b02c66fea4594fa33_bytes32, - "0000000000000000000000000000000000000000000000000000000000000001"_hex}, - {0xf206ef1f61673596e4abc05dca7be9148dbd34841d85584e8c41d75ecdf5a936_bytes32, - "0000000000000000000000000000000000000000000000000000000000000000"_hex}, - {0xf344c28b47c6de556d35ec1e82c6ec3d06f1951d36aa1cd7351d4255e7f04a9c_bytes32, - "0000000000000000000000000000000000000000000000000000000000000001"_hex}, - {0xf3f136516fd855c4cd4bd193c2bc38fab112196b023eb22510da3c6cc276eb72_bytes32, - "0000000000000000000000000000000000000000000000000000000000000000"_hex}, - {0xf6183b77357ae6ff58dc23d48b3f1d9e76098e6f884751ed03a261a0e7bab231_bytes32, - "0000000000000000000000000000000000000000000000000000000000000001"_hex}, - {0xf77262efc56997fdcd4a91cc1449b01f93ebca8c758efcc1c85027e69cc6618b_bytes32, - "cd433bbd1fa6457602a79d957ee85a37e2496d0a"_hex}, - {0xf9adfd03d4d3cf7e9245f9677b882459f0f0ea492b36ebbe34fe965bf3b4e05c_bytes32, - "000000000000000000000000000000000000000000000000000000000000002b"_hex}, - {0xfa22beaea48d8a5e37b2f00efdc83600d4a9d1e1ff5a08cea987db6e6d168833_bytes32, - "0000000000000000000000000000000000000000000000000000000000000001"_hex}, - {0xfaccb2379850753cd96f3a4f37dd3f431863cab480cd1f808f696b0cafab5da4_bytes32, - "0000000000000000000000000000000000000000000000000000000000000000"_hex}, - {0xfb859356d00b38d191345159ca428ce6b47c7c03000e91d93ba541f2db07ee75_bytes32, - "0000000000000000000000000000000000000000000000000000000000000000"_hex}, - {0xfc08a758057657032bc36068292a2e3dfa490f21697d4e5841ce2bcbf50b12ba_bytes32, - "0000000000000000000000000000000000000000000000000000000000000000"_hex}, - {0xfc94ce88596dbda4103ce1ee25fe0f05e0d8e1a57a2d8660d45800ef89ea2f64_bytes32, - "0000000000000000000000000000000000000000000000000000000000000000"_hex}, - {0xfe0d647b508fe5dbc76db4136a295fcc960ec1990c7639bb8ddcd06c1761e9e5_bytes32, - "0000000000000000000000000000000000000000000000000000000000000000"_hex}, - }; - return stubs.lookup({input, input_size}, output, max_output_size); -} -} // namespace evmone::state diff --git a/test/unittests/CMakeLists.txt b/test/unittests/CMakeLists.txt index 81d1cae6ac..5a60837fc7 100644 --- a/test/unittests/CMakeLists.txt +++ b/test/unittests/CMakeLists.txt @@ -41,6 +41,7 @@ target_sources( evmmax_bn254_add_test.cpp evmmax_bn254_mul_test.cpp evmmax_bn254_pairing_test.cpp + evmmax_modexp.cpp evmmax_test.cpp evmmax_secp256k1_test.cpp evmone_test.cpp @@ -54,6 +55,7 @@ target_sources( precompiles_kzg_test.cpp precompiles_ripemd160_test.cpp precompiles_sha256_test.cpp + precompiles_expmod_test.cpp state_block_test.cpp state_bloom_filter_test.cpp state_deposit_requests_test.cpp diff --git a/test/unittests/evmmax_modexp.cpp b/test/unittests/evmmax_modexp.cpp new file mode 100644 index 0000000000..cc96f286c9 --- /dev/null +++ b/test/unittests/evmmax_modexp.cpp @@ -0,0 +1,99 @@ +// evmone: Fast Ethereum Virtual Machine implementation +// Copyright 2023 The evmone Authors. +// SPDX-License-Identifier: Apache-2.0 + +#include +#include +#include + +#include +using namespace evmone::test; + +TEST(evmmax, modexp) +{ + { + evmc::bytes res; + res.resize(32); + EXPECT_TRUE(evmone::crypto::modexp( + res.data(), res.size(), evmc::bytes{0x9}, evmc::bytes{0x5}, evmc::bytes{0x10})); + EXPECT_EQ(res, "0000000000000000000000000000000000000000000000000000000000000009"_hex); + } + { + evmc::bytes res; + res.resize(32); + EXPECT_TRUE(evmone::crypto::modexp( + res.data(), res.size(), evmc::bytes{0x9}, evmc::bytes{0x5}, evmc::bytes{0x11})); + EXPECT_EQ(res, "0000000000000000000000000000000000000000000000000000000000000008"_hex); + } + { + evmc::bytes res; + res.resize(32); + EXPECT_TRUE(evmone::crypto::modexp( + res.data(), res.size(), evmc::bytes{0x9}, evmc::bytes{0x5}, evmc::bytes{0x13})); + EXPECT_EQ(res, "0000000000000000000000000000000000000000000000000000000000000010"_hex); + } + { + evmc::bytes res; + res.resize(32); + EXPECT_TRUE(evmone::crypto::modexp( + res.data(), res.size(), evmc::bytes{0x9}, evmc::bytes{0x5}, evmc::bytes{0x17})); + EXPECT_EQ(res, "0000000000000000000000000000000000000000000000000000000000000008"_hex); + } + { + evmc::bytes res; + res.resize(32); + EXPECT_TRUE(evmone::crypto::modexp( + res.data(), res.size(), evmc::bytes{0x9}, evmc::bytes{0x5}, evmc::bytes{0x18})); + EXPECT_EQ(res, "0000000000000000000000000000000000000000000000000000000000000009"_hex); + } + { + evmc::bytes res; + res.resize(1); + EXPECT_TRUE(evmone::crypto::modexp( + res.data(), res.size(), evmc::bytes{0x2}, evmc::bytes{0x3}, evmc::bytes{0x6})); + EXPECT_EQ(res, "02"_hex); + } + { + evmc::bytes res; + res.resize(2); + EXPECT_TRUE(evmone::crypto::modexp(res.data(), res.size(), evmc::bytes{0x2}, + "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003"_hex, + evmc::bytes{0x0006})); + EXPECT_EQ(res, "0002"_hex); + } + { + evmc::bytes res; + res.resize(1); + EXPECT_TRUE(evmone::crypto::modexp( + res.data(), res.size(), evmc::bytes{0x2}, evmc::bytes{0x3}, evmc::bytes{0x0})); + EXPECT_EQ(res, "00"_hex); + } + { + evmc::bytes res; + res.resize(160); + EXPECT_TRUE(evmone::crypto::modexp(res.data(), res.size(), + "20000000000000000000000000000000000000000000000000000000000000000000000000000010200000000000000000000000000000000000000000000000000000000000000000000000000000102000000000000000000000000000000000000000000000000000000000000000000000000000001020000000000000000000000000000000000000000000000000000000000000000000000000000010"_hex, + evmc::bytes{0x3}, + "60000000000000000000000000000000000000000000000000000000000000000000000000000010600000000000000000000000000000000000000000000000000000000000000000000000000000106000000000000000000000000000000000000000000000000000000000000000000000000000001060000000000000000000000000000000000000000000000000000000000000000000000000000010"_hex)); + EXPECT_EQ(res, + "291b1e2948112b098f3c987bec2dbac8022f5e4ebd3d4c47f333b30e3de21ca3b8aca475da7d3240291b1e2948112b098f3c987bec2dbac8022f5e4ebd3d4c47f333b30e3de21ca3b8aca475da7d3240291b1e2948112b098f3c987bec2dbac8022f5e4ebd3d4c47f333b30e3de21ca3b8aca475da7d3240291b1e2948112b098f3c987bec2dbac8022f5e4ebd3d4c47f333b30e3de21ca3b8aca475da7d3240"_hex); + } + { + evmc::bytes res; + res.resize(320); + EXPECT_TRUE(evmone::crypto::modexp(res.data(), res.size(), + "2000000000000000000000000000000000000000000000000000000000000000000000000000001020000000000000000000000000000000000000000000000000000000000000000000000000000010200000000000000000000000000000000000000000000000000000000000000000000000000000102000000000000000000000000000000000000000000000000000000000000000000000000000001020000000000000000000000000000000000000000000000000000000000000000000000000000010200000000000000000000000000000000000000000000000000000000000000000000000000000102000000000000000000000000000000000000000000000000000000000000000000000000000001020000000000000000000000000000000000000000000000000000000000000000000000000000010"_hex, + evmc::bytes{0x3}, + "6000000000000000000000000000000000000000000000000000000000000000000000000000001060000000000000000000000000000000000000000000000000000000000000000000000000000010600000000000000000000000000000000000000000000000000000000000000000000000000000106000000000000000000000000000000000000000000000000000000000000000000000000000001060000000000000000000000000000000000000000000000000000000000000000000000000000010600000000000000000000000000000000000000000000000000000000000000000000000000000106000000000000000000000000000000000000000000000000000000000000000000000000000001060000000000000000000000000000000000000000000000000000000000000000000000000000010"_hex)); + EXPECT_EQ(res, + "2d408bba3fa657dbb2cd49d4a1d329966c23e59e10c2a65950af0c4b047e185de46ee3d11f9b6b202d408bba3fa657dbb2cd49d4a1d329966c23e59e10c2a65950af0c4b047e185de46ee3d11f9b6b202d408bba3fa657dbb2cd49d4a1d329966c23e59e10c2a65950af0c4b047e185de46ee3d11f9b6b202d408bba3fa657dbb2cd49d4a1d329966c23e59e10c2a65950af0c4b047e185de46ee3d11f9b6b202d408bba3fa657dbb2cd49d4a1d329966c23e59e10c2a65950af0c4b047e185de46ee3d11f9b6b202d408bba3fa657dbb2cd49d4a1d329966c23e59e10c2a65950af0c4b047e185de46ee3d11f9b6b202d408bba3fa657dbb2cd49d4a1d329966c23e59e10c2a65950af0c4b047e185de46ee3d11f9b6b202d408bba3fa657dbb2cd49d4a1d329966c23e59e10c2a65950af0c4b047e185de46ee3d11f9b6b20"_hex); + } + { + evmc::bytes res; + res.resize(1025); + EXPECT_FALSE(evmone::crypto::modexp(res.data(), res.size(), + "2000000000000000000000000000000000000000000000000000000000000000000000000000001020000000000000000000000000000000000000000000000000000000000000000000000000000010200000000000000000000000000000000000000000000000000000000000000000000000000000102000000000000000000000000000000000000000000000000000000000000000000000000000001020000000000000000000000000000000000000000000000000000000000000000000000000000010200000000000000000000000000000000000000000000000000000000000000000000000000000102000000000000000000000000000000000000000000000000000000000000000000000000000001020000000000000000000000000000000000000000000000000000000000000000000000000000010"_hex, + evmc::bytes{0x3}, + "1060000000000000000000000000000010600000000000000000006000000000000000000000000000000000000000000000000000001060000000000000000000600000000000000000000000000000000000000000000000000000000000000000000000000000106000000000000000000000000000000000000000000000000000000000000000000000000000001060000000000000000000000000000000000000000000000000000000000000000000000000000010600000000000000000000000000000000000000000000000000000000000000000000000000000106000000000000000000000000000000000000000000000000000000000000000000000000000001060000000000000000000000000000000000000000000000000000000000000000000000000000010600000000000000000000000000000000000000000000000000000000000000000000000000000106000000000000000000000000000000000000000000000000000000000000000000000000000001060000000000000000000000000000000000000000000000000000000000000000000000000000010600000000000000000000000000000000000000000000000000000000000000000000000000000106000000000000000000000000000000000000000000000000000000000000000000000000000001060000000000000000000000000000000000000000000000000000000000000000000000000000010600000000000000000000000000000000000000000000000000000000000000000000000000000106000000000000000000000000000000000000000000000000000000000000000000000000000001060000000000000000000000000000000000000000000000000000000000000000000000000000010600000000000000000000000000000000000000000000000000000000000000000000000000000106000000000000000000000000000000000000000000000000000000000000000000000000000001060000000000000000000000000000000000000000000000000000000000000000000000000000010600000000000000000000000000000000000000000000000000000000000000000000000000000106000000000000000000000000000000000000000000000000000000000000000000000000000001060000000000000000000000000000000000000000000000000000000000000000000000000000010600000000000000000000000000000000000000000000000000000000000000000000000000000106000000000000000000000000000000000000000000000000000000000000000000000000000001060000000000000000000000000000000000000000000000000000000000000000000000000000010"_hex)); + } +} diff --git a/test/unittests/precompiles_expmod_test.cpp b/test/unittests/precompiles_expmod_test.cpp new file mode 100644 index 0000000000..3a003f72ea --- /dev/null +++ b/test/unittests/precompiles_expmod_test.cpp @@ -0,0 +1,49 @@ +// evmone: Fast Ethereum Virtual Machine implementation +// Copyright 2025 The evmone Authors. +// SPDX-License-Identifier: Apache-2.0 + +#include +#include +#include +#include +#include + +struct TestCase +{ + std::string base; + std::string exp; + std::string mod; + std::string expected_result; +}; + +static const std::vector test_cases{ + {"", "", "", ""}, + {"", "", "00", "00"}, + {"02", "01", "03", "02"}, +}; + +TEST(expmod, test_vectors) +{ + for (const auto& [base, exp, mod, expected_result] : test_cases) + { + const auto base_bytes = *evmc::from_hex(base); + const auto exp_bytes = *evmc::from_hex(exp); + const auto mod_bytes = *evmc::from_hex(mod); + const auto expected_result_bytes = *evmc::from_hex(expected_result); + + evmc::bytes input(3 * 32, 0); + input[31] = static_cast(base_bytes.size()); + input[32 + 31] = static_cast(exp_bytes.size()); + input[64 + 31] = static_cast(mod_bytes.size()); + input += base_bytes; + input += exp_bytes; + input += mod_bytes; + + evmc::bytes result(expected_result_bytes.size(), 0xfe); + const auto r = + evmone::state::expmod_execute(input.data(), input.size(), result.data(), result.size()); + EXPECT_EQ(r.status_code, EVMC_SUCCESS); + EXPECT_EQ(r.output_size, expected_result_bytes.size()); + EXPECT_EQ(hex(result), expected_result); + } +}