Skip to content

Commit 6cff817

Browse files
committed
evmmax: Add ate pairing benchmark tests.
1 parent 63328e9 commit 6cff817

File tree

3 files changed

+104
-0
lines changed

3 files changed

+104
-0
lines changed

test/precompiles_bench/precompiles_bench.cpp

+45
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,51 @@ BENCHMARK_TEMPLATE(ecmul, evmone::state::ecmul_execute);
141141
BENCHMARK_TEMPLATE(ecmul, evmone::state::silkpre_ecmul_execute);
142142
#endif
143143

144+
145+
template <ExecuteFn Fn>
146+
void ecpairing(benchmark::State& state)
147+
{
148+
const auto input = evmc::from_hex(
149+
"105456a333e6d636854f987ea7bb713dfd0ae8371a72aea313ae0c32c0bf10160cf031d41b41557f3e7e3ba0c5"
150+
"1bebe5da8e6ecd855ec50fc87efcdeac168bcc0476be093a6d2b4bbf907172049874af11e1b6267606e00804d3"
151+
"ff0037ec57fd3010c68cb50161b7d1d96bb71edfec9880171954e56871abf3d93cc94d745fa114c059d74e5b6c"
152+
"4ec14ae5864ebe23a71781d86c29fb8fb6cce94f70d3de7a2101b33461f39d9e887dbb100f170a2345dde3c07e"
153+
"256d1dfa2b657ba5cd030427000000000000000000000000000000000000000000000000000000000000000100"
154+
"000000000000000000000000000000000000000000000000000000000000021a2c3013d2ea92e13c800cde68ef"
155+
"56a294b883f6ac35d25f587c09b1b3c635f7290158a80cd3d66530f74dc94c94adb88f5cdb481acca997b6e600"
156+
"71f08a115f2f997f3dbd66a7afe07fe7862ce239edba9e05c5afff7f8a1259c9733b2dfbb929d1691530ca701b"
157+
"4a106054688728c9972c8512e9789e9567aae23e302ccd75000000000000000000000000000000000000000000"
158+
"000000000000000000000100000000000000000000000000000000000000000000000000000000000000020000"
159+
"000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
160+
"000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
161+
"000000000000000000000000000000000000000000000000000000000000000000000000")
162+
.value();
163+
uint8_t output[32];
164+
165+
const auto [gas_cost, max_output_size] =
166+
evmone::state::ecpairing_analyze(input, EVMC_LATEST_STABLE_REVISION);
167+
if (max_output_size > std::size(output))
168+
return state.SkipWithError("too small output");
169+
170+
int64_t total_gas_used = 0;
171+
for ([[maybe_unused]] auto _ : state)
172+
{
173+
const auto [status, _2] = Fn(input.data(), input.size(), output, std::size(output));
174+
if (status != EVMC_SUCCESS) [[unlikely]]
175+
return state.SkipWithError("invalid result");
176+
total_gas_used += gas_cost;
177+
}
178+
179+
using benchmark::Counter;
180+
state.counters["gas_used"] = Counter(static_cast<double>(gas_cost));
181+
state.counters["gas_rate"] = Counter(static_cast<double>(total_gas_used), Counter::kIsRate);
182+
}
183+
184+
BENCHMARK_TEMPLATE(ecpairing, evmone::state::ecpairing_execute);
185+
#ifdef EVMONE_PRECOMPILES_SILKPRE
186+
BENCHMARK_TEMPLATE(ecpairing, evmone::state::silkpre_ecpairing_execute);
187+
#endif
188+
144189
} // namespace
145190

146191
BENCHMARK_MAIN();

test/state/precompiles.cpp

+57
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,63 @@ ExecutionResult identity_execute(const uint8_t* input, size_t input_size, uint8_
240240
return {EVMC_SUCCESS, input_size};
241241
}
242242

243+
ExecutionResult ecpairing_execute(const uint8_t* input, size_t input_size, uint8_t* output,
244+
[[maybe_unused]] size_t output_size) noexcept
245+
{
246+
assert(output_size >= 32);
247+
248+
const auto pair_size = 192;
249+
250+
if (input_size % pair_size != 0)
251+
return {EVMC_PRECOMPILE_FAILURE, 0};
252+
253+
const auto pair_count = input_size / pair_size;
254+
255+
if (pair_count > 0)
256+
{
257+
auto input_idx = input;
258+
259+
std::vector<evmmax::ecc::Point<intx::uint256>> vG1(pair_count);
260+
std::vector<std::array<intx::uint256, 4>> vG2(pair_count);
261+
262+
for (size_t i = 0; i < pair_count; ++i)
263+
{
264+
const evmmax::bn254::Point p = {
265+
intx::be::unsafe::load<intx::uint256>(input_idx),
266+
intx::be::unsafe::load<intx::uint256>(input_idx + 32),
267+
};
268+
269+
const std::array<intx::uint256, 4> q = {
270+
intx::be::unsafe::load<intx::uint256>(input_idx + 96),
271+
intx::be::unsafe::load<intx::uint256>(input_idx + 64),
272+
intx::be::unsafe::load<intx::uint256>(input_idx + 160),
273+
intx::be::unsafe::load<intx::uint256>(input_idx + 128),
274+
};
275+
276+
vG1[i] = p;
277+
vG2[i] = q;
278+
279+
input_idx += pair_size;
280+
}
281+
282+
const auto res = evmmax::bn254::pairing(vG2, vG1);
283+
284+
if (res.has_value())
285+
{
286+
intx::be::unsafe::store(output, res.value() ? intx::uint256{1} : intx::uint256{0});
287+
return {EVMC_SUCCESS, 64};
288+
}
289+
else
290+
return {EVMC_PRECOMPILE_FAILURE, 0};
291+
}
292+
else
293+
{
294+
intx::be::unsafe::store(output, intx::uint256{1});
295+
return {EVMC_SUCCESS, 32};
296+
}
297+
}
298+
299+
243300
namespace
244301
{
245302
struct PrecompileTraits

test/state/precompiles_internal.hpp

+2
Original file line numberDiff line numberDiff line change
@@ -38,4 +38,6 @@ ExecutionResult ecadd_execute(
3838
const uint8_t* input, size_t input_size, uint8_t* output, size_t output_size) noexcept;
3939
ExecutionResult ecmul_execute(
4040
const uint8_t* input, size_t input_size, uint8_t* output, size_t output_size) noexcept;
41+
ExecutionResult ecpairing_execute(
42+
const uint8_t* input, size_t input_size, uint8_t* output, size_t output_size) noexcept;
4143
} // namespace evmone::state

0 commit comments

Comments
 (0)