From 862c493c40fd878705caae0d4fd015879b636669 Mon Sep 17 00:00:00 2001 From: rodiazet Date: Tue, 2 Apr 2024 13:08:04 +0200 Subject: [PATCH] evmmax: Add ate pairing benchmark tests. --- test/precompiles_bench/precompiles_bench.cpp | 45 ++++++++++++++++ test/state/precompiles.cpp | 57 ++++++++++++++++++++ test/state/precompiles_internal.hpp | 2 + 3 files changed, 104 insertions(+) diff --git a/test/precompiles_bench/precompiles_bench.cpp b/test/precompiles_bench/precompiles_bench.cpp index ce832a47e3..0d4ef2ab49 100644 --- a/test/precompiles_bench/precompiles_bench.cpp +++ b/test/precompiles_bench/precompiles_bench.cpp @@ -141,6 +141,51 @@ BENCHMARK_TEMPLATE(ecmul, evmone::state::ecmul_execute); BENCHMARK_TEMPLATE(ecmul, evmone::state::silkpre_ecmul_execute); #endif + +template +void ecpairing(benchmark::State& state) +{ + const auto input = evmc::from_hex( + "105456a333e6d636854f987ea7bb713dfd0ae8371a72aea313ae0c32c0bf10160cf031d41b41557f3e7e3ba0c5" + "1bebe5da8e6ecd855ec50fc87efcdeac168bcc0476be093a6d2b4bbf907172049874af11e1b6267606e00804d3" + "ff0037ec57fd3010c68cb50161b7d1d96bb71edfec9880171954e56871abf3d93cc94d745fa114c059d74e5b6c" + "4ec14ae5864ebe23a71781d86c29fb8fb6cce94f70d3de7a2101b33461f39d9e887dbb100f170a2345dde3c07e" + "256d1dfa2b657ba5cd030427000000000000000000000000000000000000000000000000000000000000000100" + "000000000000000000000000000000000000000000000000000000000000021a2c3013d2ea92e13c800cde68ef" + "56a294b883f6ac35d25f587c09b1b3c635f7290158a80cd3d66530f74dc94c94adb88f5cdb481acca997b6e600" + "71f08a115f2f997f3dbd66a7afe07fe7862ce239edba9e05c5afff7f8a1259c9733b2dfbb929d1691530ca701b" + "4a106054688728c9972c8512e9789e9567aae23e302ccd75000000000000000000000000000000000000000000" + "000000000000000000000100000000000000000000000000000000000000000000000000000000000000020000" + "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000") + .value(); + uint8_t output[32]; + + const auto [gas_cost, max_output_size] = + evmone::state::ecpairing_analyze(input, EVMC_LATEST_STABLE_REVISION); + if (max_output_size > std::size(output)) + return state.SkipWithError("too small output"); + + int64_t total_gas_used = 0; + for ([[maybe_unused]] auto _ : state) + { + const auto [status, _2] = Fn(input.data(), input.size(), output, std::size(output)); + if (status != EVMC_SUCCESS) [[unlikely]] + return state.SkipWithError("invalid result"); + total_gas_used += gas_cost; + } + + using benchmark::Counter; + state.counters["gas_used"] = Counter(static_cast(gas_cost)); + state.counters["gas_rate"] = Counter(static_cast(total_gas_used), Counter::kIsRate); +} + +BENCHMARK_TEMPLATE(ecpairing, evmone::state::ecpairing_execute); +#ifdef EVMONE_PRECOMPILES_SILKPRE +BENCHMARK_TEMPLATE(ecpairing, evmone::state::silkpre_ecpairing_execute); +#endif + } // namespace BENCHMARK_MAIN(); diff --git a/test/state/precompiles.cpp b/test/state/precompiles.cpp index 68f22fbcc5..efbd4e9022 100644 --- a/test/state/precompiles.cpp +++ b/test/state/precompiles.cpp @@ -240,6 +240,63 @@ ExecutionResult identity_execute(const uint8_t* input, size_t input_size, uint8_ return {EVMC_SUCCESS, input_size}; } +ExecutionResult ecpairing_execute(const uint8_t* input, size_t input_size, uint8_t* output, + [[maybe_unused]] size_t output_size) noexcept +{ + assert(output_size >= 32); + + const auto pair_size = 192; + + if (input_size % pair_size != 0) + return {EVMC_PRECOMPILE_FAILURE, 0}; + + const auto pair_count = input_size / pair_size; + + if (pair_count > 0) + { + auto input_idx = input; + + std::vector vG1(pair_count); + std::vector vG2(pair_count); + + for (size_t i = 0; i < pair_count; ++i) + { + const evmmax::bn254::Point p = { + intx::be::unsafe::load(input_idx), + intx::be::unsafe::load(input_idx + 32), + }; + + const evmmax::bn254::ExtPoint q = { + {intx::be::unsafe::load(input_idx + 96), + intx::be::unsafe::load(input_idx + 64)}, + {intx::be::unsafe::load(input_idx + 160), + intx::be::unsafe::load(input_idx + 128)}, + }; + + vG1[i] = p; + vG2[i] = q; + + input_idx += pair_size; + } + + const auto res = evmmax::bn254::pairing(vG2, vG1); + + if (res.has_value()) + { + intx::be::unsafe::store(output, res.value() ? intx::uint256{1} : intx::uint256{0}); + return {EVMC_SUCCESS, 64}; + } + else + return {EVMC_PRECOMPILE_FAILURE, 0}; + } + else + { + intx::be::unsafe::store(output, intx::uint256{1}); + return {EVMC_SUCCESS, 32}; + } +} + + namespace { struct PrecompileTraits diff --git a/test/state/precompiles_internal.hpp b/test/state/precompiles_internal.hpp index 7ff905e864..f2e41c707d 100644 --- a/test/state/precompiles_internal.hpp +++ b/test/state/precompiles_internal.hpp @@ -38,4 +38,6 @@ ExecutionResult ecadd_execute( const uint8_t* input, size_t input_size, uint8_t* output, size_t output_size) noexcept; ExecutionResult ecmul_execute( const uint8_t* input, size_t input_size, uint8_t* output, size_t output_size) noexcept; +ExecutionResult ecpairing_execute( + const uint8_t* input, size_t input_size, uint8_t* output, size_t output_size) noexcept; } // namespace evmone::state