Skip to content

Commit 647213b

Browse files
committed
precompiles: Implement expmod with GMP
1 parent e3ff3b9 commit 647213b

File tree

5 files changed

+87
-9
lines changed

5 files changed

+87
-9
lines changed

cmake/FindGMP.cmake

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
# evmone: Fast Ethereum Virtual Machine implementation
2+
# Copyright 2025 The evmone Authors.
3+
# SPDX-License-Identifier: Apache-2.0
4+
5+
# Finds the GMP or MPIR library and its include directories.
6+
7+
find_library(GMP_LIBRARY NAMES gmp mpir DOC "GMP/MPIR library")
8+
find_path(GMP_INCLUDE_DIR NAMES gmp.h DOC "GMP header")
9+
10+
include(FindPackageHandleStandardArgs)
11+
find_package_handle_standard_args(
12+
GMP
13+
REQUIRED_VARS GMP_LIBRARY GMP_INCLUDE_DIR
14+
)
15+
16+
if(GMP_FOUND)
17+
if(NOT TARGET GMP::gmp)
18+
add_library(GMP::gmp UNKNOWN IMPORTED)
19+
set_target_properties(GMP::gmp PROPERTIES
20+
IMPORTED_LOCATION ${GMP_LIBRARY}
21+
IMPORTED_LINK_INTERFACE_LANGUAGES C
22+
INTERFACE_INCLUDE_DIRECTORIES ${GMP_INCLUDE_DIR}
23+
)
24+
endif()
25+
endif()

test/state/CMakeLists.txt

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,3 +72,16 @@ if(EVMONE_PRECOMPILES_SILKPRE)
7272
precompiles_silkpre.cpp
7373
)
7474
endif()
75+
76+
# This is done after Silkpre because it also tries to find GMP.
77+
option(EVMONE_PRECOMPILES_GMP "Enable precompiles implementations via the GMP/MPIR library" ON)
78+
if(EVMONE_PRECOMPILES_GMP)
79+
find_package(GMP REQUIRED)
80+
target_link_libraries(evmone-state PRIVATE GMP::gmp)
81+
target_compile_definitions(evmone-state PRIVATE EVMONE_PRECOMPILES_GMP=1)
82+
target_sources(
83+
evmone-state PRIVATE
84+
precompiles_gmp.hpp
85+
precompiles_gmp.cpp
86+
)
87+
endif()

test/state/precompiles.cpp

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,8 @@
1919
#include <limits>
2020
#include <span>
2121

22-
#ifdef EVMONE_PRECOMPILES_SILKPRE
23-
#include "precompiles_silkpre.hpp"
22+
#ifdef EVMONE_PRECOMPILES_GMP
23+
#include "precompiles_gmp.hpp"
2424
#endif
2525

2626
namespace evmone::state
@@ -363,16 +363,12 @@ ExecutionResult expmod_execute(
363363
const auto exp = payload.substr(base_len, exp_len);
364364
const auto mod = mod_requires_padding ? bytes_view{output, mod_len} : mod_explicit;
365365

366-
#ifdef EVMONE_PRECOMPILES_SILKPRE
367-
(void)base;
368-
(void)exp;
369-
(void)mod;
370-
// For Silkpre use the raw input for compatibility.
371-
return silkpre_expmod_execute(input, input_size, output, output_size);
366+
#ifdef EVMONE_PRECOMPILES_GMP
367+
expmod_gmp(base, exp, mod, output);
372368
#else
373369
expmod_stub(base, exp, mod, output);
374-
return {EVMC_SUCCESS, mod.size()};
375370
#endif
371+
return {EVMC_SUCCESS, mod.size()};
376372
}
377373

378374
ExecutionResult ecadd_execute(const uint8_t* input, size_t input_size, uint8_t* output,

test/state/precompiles_gmp.cpp

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
// evmone: Fast Ethereum Virtual Machine implementation
2+
// Copyright 2025 The evmone Authors.
3+
// SPDX-License-Identifier: Apache-2.0
4+
5+
#include "precompiles_gmp.hpp"
6+
#include <gmp.h>
7+
#include <cassert>
8+
9+
namespace evmone::state
10+
{
11+
void expmod_gmp(bytes_view base, bytes_view exp, bytes_view mod, uint8_t* output) noexcept
12+
{
13+
mpz_t b, e, m, r; // NOLINT(*-isolate-declaration)
14+
mpz_inits(b, e, m, r, nullptr);
15+
mpz_import(b, base.size(), 1, 1, 0, 0, base.data());
16+
mpz_import(e, exp.size(), 1, 1, 0, 0, exp.data());
17+
mpz_import(m, mod.size(), 1, 1, 0, 0, mod.data());
18+
assert(mpz_sgn(m) != 0);
19+
20+
mpz_powm(r, b, e, m);
21+
22+
size_t export_size = 0;
23+
mpz_export(output, &export_size, 1, 1, 0, 0, r);
24+
assert(export_size <= mod.size());
25+
mpz_clears(b, e, m, r, nullptr);
26+
27+
std::copy_backward(output, output + export_size, output + mod.size());
28+
std::fill_n(output, mod.size() - export_size, 0);
29+
}
30+
} // namespace evmone::state

test/state/precompiles_gmp.hpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// evmone: Fast Ethereum Virtual Machine implementation
2+
// Copyright 2025 The evmone Authors.
3+
// SPDX-License-Identifier: Apache-2.0
4+
#pragma once
5+
6+
#include <evmc/evmc.hpp>
7+
8+
namespace evmone::state
9+
{
10+
using evmc::bytes_view;
11+
12+
/// Executes the expmod precompile using the GMP library.
13+
void expmod_gmp(bytes_view base, bytes_view exp, bytes_view mod, uint8_t* output) noexcept;
14+
} // namespace evmone::state

0 commit comments

Comments
 (0)