Skip to content

Commit

Permalink
evmmax: Fix after rebase
Browse files Browse the repository at this point in the history
  • Loading branch information
rodiazet committed Jan 28, 2025
1 parent 75c438c commit da87a62
Show file tree
Hide file tree
Showing 8 changed files with 30 additions and 130 deletions.
2 changes: 2 additions & 0 deletions include/evmmax/evmmax.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,9 @@ class EVMMAXState

void clear() noexcept;

EVMMAXState& operator=(EVMMAXState&&) noexcept;
explicit EVMMAXState() noexcept;
explicit EVMMAXState(EVMMAXState&&) noexcept;
virtual ~EVMMAXState();
};

Expand Down
9 changes: 5 additions & 4 deletions lib/evmmax/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,18 @@
# Copyright 2023 The evmone Authors.
# SPDX-License-Identifier: Apache-2.0

add_library(evmmax INTERFACE)
add_library(evmmax STATIC)
add_library(evmone::evmmax ALIAS evmmax)
target_compile_features(evmmax INTERFACE cxx_std_20)
target_include_directories(evmmax INTERFACE ${PROJECT_SOURCE_DIR}/include)
target_link_libraries(evmmax INTERFACE intx::intx)
target_compile_features(evmmax PUBLIC cxx_std_20)
target_include_directories(evmmax PUBLIC ${PROJECT_SOURCE_DIR}/include)
target_link_libraries(evmmax PUBLIC intx::intx PRIVATE evmc::evmc_cpp)

if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.19)
# We want to add the header file to the library for IDEs.
# However, cmake 3.18 does not support PRIVATE scope for INTERFACE libraries.
target_sources(
evmmax PRIVATE
${PROJECT_SOURCE_DIR}/include/evmmax/evmmax.hpp
evmmax.cpp
)
endif()
109 changes: 2 additions & 107 deletions lib/evmmax/evmmax.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -295,114 +295,9 @@ void EVMMAXState::clear() noexcept
active_mod = nullptr;
}

EVMMAXState& EVMMAXState::operator=(EVMMAXState&&) noexcept = default;
EVMMAXState::EVMMAXState(EVMMAXState&&) noexcept = default;

Check warning on line 299 in lib/evmmax/evmmax.cpp

View check run for this annotation

Codecov / codecov/patch

lib/evmmax/evmmax.cpp#L298-L299

Added lines #L298 - L299 were not covered by tests
EVMMAXState::EVMMAXState() noexcept = default;
EVMMAXState::~EVMMAXState() = default;

namespace
{
/// Compute the modulus inverse for Montgomery multiplication, i.e. N': mod⋅N' = 2⁶⁴-1.
///
/// @param mod0 The least significant word of the modulus.
inline constexpr uint64_t compute_mod_inv(uint64_t mod0) noexcept
{
// TODO: Find what is this algorithm and why it works.
uint64_t base = 0 - mod0;
uint64_t result = 1;
for (auto i = 0; i < 64; ++i)
{
result *= base;
base *= base;
}
return result;
}

/// Compute R² % mod.
template <typename UintT>
inline UintT compute_r_squared(const UintT& mod) noexcept
{
// R is 2^num_bits, R² is 2^(2*num_bits) and needs 2*num_bits+1 bits to represent,
// rounded to 2*num_bits+64) for intx requirements.
static constexpr auto r2 = intx::uint<UintT::num_bits * 2 + 64>{1} << (UintT::num_bits * 2);
return intx::udivrem(r2, mod).rem;
}

inline constexpr std::pair<uint64_t, uint64_t> addmul(
uint64_t t, uint64_t a, uint64_t b, uint64_t c) noexcept
{
const auto p = umul(a, b) + t + c;
return {p[1], p[0]};
}
} // namespace

template <typename UintT>
ModArith<UintT>::ModArith(const UintT& modulus) noexcept
: mod{modulus}, m_r_squared{compute_r_squared(modulus)}, m_mod_inv{compute_mod_inv(modulus[0])}
{}

template <typename UintT>
UintT ModArith<UintT>::mul(const UintT& x, const UintT& y) const noexcept
{
// Coarsely Integrated Operand Scanning (CIOS) Method
// Based on 2.3.2 from
// High-Speed Algorithms & Architectures For Number-Theoretic Cryptosystems
// https://www.microsoft.com/en-us/research/wp-content/uploads/1998/06/97Acar.pdf

static constexpr auto S = UintT::num_words;

intx::uint<UintT::num_bits + 64> t;
for (size_t i = 0; i != S; ++i)
{
uint64_t c = 0;
for (size_t j = 0; j != S; ++j)
std::tie(c, t[j]) = addmul(t[j], x[j], y[i], c);
auto tmp = addc(t[S], c);
t[S] = tmp.value;
auto d = tmp.carry;

c = 0;
auto m = t[0] * m_mod_inv;
std::tie(c, t[0]) = addmul(t[0], m, mod[0], c);
for (size_t j = 1; j != S; ++j)
std::tie(c, t[j - 1]) = addmul(t[j], m, mod[j], c);
tmp = addc(t[S], c);
t[S - 1] = tmp.value;
t[S] = d + tmp.carry; // TODO: Carry is 0 for sparse modulus.
}

if (t >= mod) // TODO: cannot overflow if modulus is sparse (e.g. 255 bits).
t -= mod;

return static_cast<UintT>(t);
}

template <typename UintT>
UintT ModArith<UintT>::to_mont(const UintT& x) const noexcept
{
return mul(x, m_r_squared);
}

template <typename UintT>
UintT ModArith<UintT>::from_mont(const UintT& x) const noexcept
{
return mul(x, 1);
}

template <typename UintT>
UintT ModArith<UintT>::add(const UintT& x, const UintT& y) const noexcept
{
const auto s = addc(x, y); // TODO: cannot overflow if modulus is sparse (e.g. 255 bits).
const auto d = subc(s.value, mod);
return (!s.carry && d.carry) ? s.value : d.value;
}

template <typename UintT>
UintT ModArith<UintT>::sub(const UintT& x, const UintT& y) const noexcept
{
const auto d = subc(x, y);
const auto s = d.value + mod;
return (d.carry) ? s : d.value;
}

template class ModArith<uint256>;
template class ModArith<uint384>;
} // namespace evmmax
4 changes: 2 additions & 2 deletions lib/evmone/advanced_instructions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -99,8 +99,8 @@ template <Opcode Op, code_iterator CoreFn(StackTop, ExecutionState&, code_iterat
int64_t&) noexcept = core::impl<Op>>
inline code_iterator impl(AdvancedExecutionState& state, code_iterator pos) noexcept
{
const auto new_pos = CoreFn(state.stack.top_item, state, pos, state.gas_left);
state.stack.top_item += instr::traits[Op].stack_height_change;
const auto new_pos = CoreFn(state.stack, state, pos, state.gas_left);
state.adjust_stack_size(instr::traits[Op].stack_height_change);
return new_pos;
}
/// @}
Expand Down
17 changes: 8 additions & 9 deletions lib/evmone/instructions_traits.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ inline constexpr auto cold_sload_cost = 2100;
inline constexpr auto cold_account_access_cost = 2600;
inline constexpr auto warm_storage_read_cost = 100;

static constexpr auto EVMC_EVMMAX = evmc_revision::EVMC_PRAGUE;
constexpr auto EVMC_EVMMAX = EVMC_OSAKA;
/// Additional cold account access cost.
///
/// The warm access cost is unconditionally applied for every account access instruction.
Expand Down Expand Up @@ -209,7 +209,6 @@ static_assert(gas_costs[EVMC_MAX_REVISION][OP_ADD] > 0, "gas costs missing for a
/// The revision related to introduction of the EOFv1.
constexpr auto REV_EOF1 = EVMC_OSAKA;


/// The EVM instruction traits.
struct Traits
{
Expand Down Expand Up @@ -285,13 +284,13 @@ constexpr inline std::array<Traits, 256> traits = []() noexcept {
table[OP_SHR] = {"SHR", 0, false, 2, -1, EVMC_CONSTANTINOPLE, REV_EOF1};
table[OP_SAR] = {"SAR", 0, false, 2, -1, EVMC_CONSTANTINOPLE, REV_EOF1};

table[OP_KECCAK256] = {"KECCAK256", 0, false, 2, -1, EVMC_FRONTIER};
table[OP_SETUPX] = {"SETUPX", 0, false, 3, -3, EVMC_EVMMAX};
table[OP_ADDMODX] = {"ADDMODX", 3, false, 0, 0, EVMC_EVMMAX};
table[OP_SUBMODX] = {"SUBMODX", 3, false, 0, 0, EVMC_EVMMAX};
table[OP_MULMODX] = {"MULMODX", 3, false, 0, 0, EVMC_EVMMAX};
table[OP_LOADX] = {"LOADX", 0, false, 3, -3, EVMC_EVMMAX};
table[OP_STOREX] = {"STOREX", 0, false, 3, -3, EVMC_EVMMAX};
table[OP_KECCAK256] = {"KECCAK256", 0, false, 2, -1, EVMC_FRONTIER, REV_EOF1};
table[OP_SETUPX] = {"SETUPX", 0, false, 3, -3, EVMC_EVMMAX, EVMC_EVMMAX};
table[OP_ADDMODX] = {"ADDMODX", 3, false, 0, 0, EVMC_EVMMAX, EVMC_EVMMAX};
table[OP_SUBMODX] = {"SUBMODX", 3, false, 0, 0, EVMC_EVMMAX, EVMC_EVMMAX};
table[OP_MULMODX] = {"MULMODX", 3, false, 0, 0, EVMC_EVMMAX, EVMC_EVMMAX};
table[OP_LOADX] = {"LOADX", 0, false, 3, -3, EVMC_EVMMAX, EVMC_EVMMAX};
table[OP_STOREX] = {"STOREX", 0, false, 3, -3, EVMC_EVMMAX, EVMC_EVMMAX};

table[OP_ADDRESS] = {"ADDRESS", 0, false, 0, 1, EVMC_FRONTIER, REV_EOF1};
table[OP_BALANCE] = {"BALANCE", 0, false, 1, 0, EVMC_FRONTIER, REV_EOF1};
Expand Down
5 changes: 3 additions & 2 deletions test/unittests/eof_validation_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -307,8 +307,9 @@ TEST_F(eof_validation, EOF1_undefined_opcodes)
opcode == OP_SWAPN || opcode == OP_EXCHANGE || opcode == OP_RJUMP ||
opcode == OP_RJUMPI || opcode == OP_CALLF || opcode == OP_RJUMPV ||
opcode == OP_DATALOADN || opcode == OP_JUMPF || opcode == OP_EOFCREATE ||
opcode == OP_RETURNCONTRACT || opcode == OP_ADDMODX || opcode == OP_SUBMODX ||
opcode == OP_MULMODX)
opcode == OP_RETURNCONTRACT || opcode == OP_SETUPX || opcode == OP_ADDMODX ||
opcode == OP_SUBMODX || opcode == OP_MULMODX || opcode == OP_LOADX ||
opcode == OP_STOREX)
continue;
// These opcodes are deprecated since Osaka.
// gas_cost table current implementation does not allow to undef instructions.
Expand Down
7 changes: 4 additions & 3 deletions test/unittests/evmmax_instructions_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,15 @@
using namespace intx;
using namespace evmmax;
using namespace evmc::literals;
using namespace evmone::test;
using evmone::test::evm;

TEST_P(evm, evmmax_32bytes_modulus_test)
{
if (is_advanced())
return;

Check warning on line 19 in test/unittests/evmmax_instructions_test.cpp

View check run for this annotation

Codecov / codecov/patch

test/unittests/evmmax_instructions_test.cpp#L18-L19

Added lines #L18 - L19 were not covered by tests

rev = EVMC_PRAGUE; /// TODO: Use EVMC_EVMMAX
rev = EVMC_OSAKA; /// TODO: Use EVMC_EVMMAX

Check warning on line 21 in test/unittests/evmmax_instructions_test.cpp

View check run for this annotation

Codecov / codecov/patch

test/unittests/evmmax_instructions_test.cpp#L21

Added line #L21 was not covered by tests
// Modulus == 7
auto code = mstore(0, 0x07);

Check warning on line 23 in test/unittests/evmmax_instructions_test.cpp

View check run for this annotation

Codecov / codecov/patch

test/unittests/evmmax_instructions_test.cpp#L23

Added line #L23 was not covered by tests
// 3 values slots
Expand Down Expand Up @@ -54,7 +55,7 @@ TEST_P(evm, evmmax_1byte_modulus_test)
if (is_advanced())
return;

Check warning on line 56 in test/unittests/evmmax_instructions_test.cpp

View check run for this annotation

Codecov / codecov/patch

test/unittests/evmmax_instructions_test.cpp#L55-L56

Added lines #L55 - L56 were not covered by tests

rev = EVMC_PRAGUE; /// TODO: Use EVMC_EVMMAX
rev = EVMC_OSAKA; /// TODO: Use EVMC_EVMMAX

Check warning on line 58 in test/unittests/evmmax_instructions_test.cpp

View check run for this annotation

Codecov / codecov/patch

test/unittests/evmmax_instructions_test.cpp#L58

Added line #L58 was not covered by tests
// Modulus == 7
auto code = mstore8(0, 0x07);

Check warning on line 60 in test/unittests/evmmax_instructions_test.cpp

View check run for this annotation

Codecov / codecov/patch

test/unittests/evmmax_instructions_test.cpp#L60

Added line #L60 was not covered by tests
// 3 values slots
Expand Down Expand Up @@ -93,7 +94,7 @@ TEST_P(evm, evmmax_2byte_modulus_test)
if (is_advanced())
return;

Check warning on line 95 in test/unittests/evmmax_instructions_test.cpp

View check run for this annotation

Codecov / codecov/patch

test/unittests/evmmax_instructions_test.cpp#L94-L95

Added lines #L94 - L95 were not covered by tests

rev = EVMC_PRAGUE; /// TODO: Use EVMC_EVMMAX
rev = EVMC_OSAKA; /// TODO: Use EVMC_EVMMAX

Check warning on line 97 in test/unittests/evmmax_instructions_test.cpp

View check run for this annotation

Codecov / codecov/patch

test/unittests/evmmax_instructions_test.cpp#L97

Added line #L97 was not covered by tests
// Modulus == 263 (0x0107)
auto code = mstore8(0, 0x01);
code += mstore8(1, 0x07);

Check warning on line 100 in test/unittests/evmmax_instructions_test.cpp

View check run for this annotation

Codecov / codecov/patch

test/unittests/evmmax_instructions_test.cpp#L99-L100

Added lines #L99 - L100 were not covered by tests
Expand Down
7 changes: 4 additions & 3 deletions test/unittests/evmmax_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,7 @@ TYPED_TEST(evmmax_test, mul)

namespace
{
using namespace evmone::test;
template <typename UintT>
inline bytecode create_test_bytecode()

Check warning on line 157 in test/unittests/evmmax_test.cpp

View check run for this annotation

Codecov / codecov/patch

test/unittests/evmmax_test.cpp#L157

Added line #L157 was not covered by tests
{
Expand All @@ -169,7 +170,7 @@ TEST_P(evm, exec_bn254_test)
if (evm::is_advanced())
return;

Check warning on line 171 in test/unittests/evmmax_test.cpp

View check run for this annotation

Codecov / codecov/patch

test/unittests/evmmax_test.cpp#L170-L171

Added lines #L170 - L171 were not covered by tests

evm::rev = EVMC_PRAGUE; /// TODO: Use EVMC_EVMMAX
evm::rev = EVMC_OSAKA; /// TODO: Use EVMC_EVMMAX

Check warning on line 173 in test/unittests/evmmax_test.cpp

View check run for this annotation

Codecov / codecov/patch

test/unittests/evmmax_test.cpp#L173

Added line #L173 was not covered by tests

const ModA<uint256, BN254Mod> m;

Expand Down Expand Up @@ -203,7 +204,7 @@ TEST_P(evm, exec_bls_test)
if (evm::is_advanced())
return;

Check warning on line 205 in test/unittests/evmmax_test.cpp

View check run for this annotation

Codecov / codecov/patch

test/unittests/evmmax_test.cpp#L204-L205

Added lines #L204 - L205 were not covered by tests

evm::rev = EVMC_PRAGUE; /// TODO: Use EVMC_EVMMAX
evm::rev = EVMC_OSAKA; /// TODO: Use EVMC_EVMMAX

Check warning on line 207 in test/unittests/evmmax_test.cpp

View check run for this annotation

Codecov / codecov/patch

test/unittests/evmmax_test.cpp#L207

Added line #L207 was not covered by tests

const ModA<uint384, BLS12384Mod> m;

Expand Down Expand Up @@ -239,7 +240,7 @@ TEST_P(evm, exec_invalid_test)
if (evm::is_advanced())

Check warning on line 240 in test/unittests/evmmax_test.cpp

View check run for this annotation

Codecov / codecov/patch

test/unittests/evmmax_test.cpp#L240

Added line #L240 was not covered by tests
return;

evm::rev = EVMC_PRAGUE; /// TODO: Use EVMC_EVMMAX
evm::rev = EVMC_OSAKA; /// TODO: Use EVMC_EVMMAX

Check warning on line 243 in test/unittests/evmmax_test.cpp

View check run for this annotation

Codecov / codecov/patch

test/unittests/evmmax_test.cpp#L243

Added line #L243 was not covered by tests

{
// Even modulus
Expand Down

0 comments on commit da87a62

Please sign in to comment.