Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

EVMMAX: Base C++ API for prototyping #673

Merged
merged 3 commits into from
Jul 31, 2023
Merged

EVMMAX: Base C++ API for prototyping #673

merged 3 commits into from
Jul 31, 2023

Conversation

chfast
Copy link
Member

@chfast chfast commented Jul 14, 2023

Add evmmax library with prototype C++ API for Montgomery-based modular arithmetic. This does not implement all aspects of the EVMMAX spec, but is a good starting point for prototyping EVMMAX usage in C++.

See these EIP drafts for more information about EVMMAX:

@codecov
Copy link

codecov bot commented Jul 14, 2023

Codecov Report

Merging #673 (5091a79) into master (18a8972) will increase coverage by 0.03%.
Report is 6 commits behind head on master.
The diff coverage is 100.00%.

❗ Current head 5091a79 differs from pull request most recent head babc0b9. Consider uploading reports for the commit babc0b9 to get more accurate results

Additional details and impacted files
@@            Coverage Diff             @@
##           master     #673      +/-   ##
==========================================
+ Coverage   97.41%   97.45%   +0.03%     
==========================================
  Files          81       83       +2     
  Lines        8013     8120     +107     
==========================================
+ Hits         7806     7913     +107     
  Misses        207      207              
Flag Coverage Δ
blockchaintests 62.95% <ø> (ø)
statetests 74.10% <ø> (ø)
unittests 94.97% <100.00%> (+0.06%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

Files Changed Coverage Δ
lib/evmmax/evmmax.cpp 100.00% <100.00%> (ø)
test/unittests/evmmax_test.cpp 100.00% <100.00%> (ø)

@chfast chfast force-pushed the evmmax_base branch 4 times, most recently from 1884473 to 6789e2e Compare July 15, 2023 20:54
@chfast chfast marked this pull request as ready for review July 15, 2023 20:55
include/evmmax/evmmax.hpp Outdated Show resolved Hide resolved
/// Performs a Montgomery modular multiplication. Inputs must be in Montgomery form.
uint mul(const uint& x, const uint& y) const noexcept;

/// Performs a modular addition.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are these in non-montgomery form? Or for the addition/subtraction implementation it won't matter?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if we should have another type for the montgomery-form version, like uintmont or montuint.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It doesn't matter.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've been wondering if we will need ever these operations for non-mont form, but it look that we won't. At least for pairing. BTW silkpre lib does everything using this form.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will add a comment.

/// Performs a Montgomery modular multiplication. Inputs must be in Montgomery form.
uint mul(const uint& x, const uint& y) const noexcept;

/// Performs a modular addition.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've been wondering if we will need ever these operations for non-mont form, but it look that we won't. At least for pairing. BTW silkpre lib does everything using this form.

@chfast chfast requested a review from gumb0 July 24, 2023 15:00
include/evmmax/evmmax.hpp Outdated Show resolved Hide resolved
lib/evmmax/evmmax.cpp Outdated Show resolved Hide resolved
lib/evmmax/evmmax.cpp Outdated Show resolved Hide resolved
lib/evmmax/evmmax.cpp Outdated Show resolved Hide resolved
template <typename UintT>
UintT ModArith<UintT>::to_mont(const UintT& x) const noexcept
{
return mul(x, m_r_squared);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't Montgomery form aR mod N and not aR² mod N ?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

True, but mul is actually mont_mul which is abR⁻¹ mod N. Therefore: mul(a, R²) is aR²R⁻¹ mod N is aR mod N.

I will add a comment.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Montgomery reduction of an input a yields aR**-1 mod N. So to convert a to Montgomery form, is passed and the extra factor of R cancels out.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oh I see! missed that it calls Montgoemry multiplication. Why not call it mont_mul() ?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The internal representation (e.g. Montgomery form) is abstracted away in EVMMAX. The multiplication is just MULMODX. But to_mont() and from_mont() maps to LOADX and STOREX. Here we started with add, sub and mul, but we don't have proper load, store yet.

{
namespace
{
inline constexpr uint64_t mul_inv64(uint64_t base) noexcept
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you explain this too? what does it calculate and what's the forumla?

Also, why is used only with 1 word of modulus.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know exactly. I copied it from somewhere. But this is some Montgomery multiplication magic. I'm guessing this is R⁻¹ mod N but only most significant bits are needed.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, this is used to compute "Integer N′ in [0, B − 1] such that NN′ ≡ −1 (mod B)" where B is 2^64. This loop looks like exponentiation with exponent being −1 (mod B) i.e. 2^64-1.

Comment on lines +108 to +113
const auto s = d.value + mod;
return (d.carry) ? s : d.value;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This could calculate s only when needed

Suggested change
const auto s = d.value + mod;
return (d.carry) ? s : d.value;
return d.carry ? (d.value + mod) : d.value;

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is done this way on purpose to follow branchless implementation.


template <typename>
class evmmax_test : public testing::Test
{};
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggestion if possible: alias inside fixture class TypeParam as ModA or something close to ModArith.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe also could have an instance of it as class member.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are some limitations to this. Either you need to use this-> or TestFixture::. http://google.github.io/googletest/reference/testing.html#TYPED_TEST

@chfast chfast force-pushed the evmmax_base branch 2 times, most recently from 2d24c2d to 6dc5877 Compare July 31, 2023 14:47
Add evmmax library with prototype C++ API for Montgomery-based modular
arithmetic. This does not implement all aspects of the EVMMAX spec,
but is a good starting point for prototyping EVMMAX usage in C++.
@chfast chfast merged commit eda0beb into master Jul 31, 2023
@chfast chfast deleted the evmmax_base branch July 31, 2023 16:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants