-
Notifications
You must be signed in to change notification settings - Fork 285
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
Conversation
Codecov Report
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
Flags with carried forward coverage won't be shown. Click here to find out more.
|
1884473
to
6789e2e
Compare
include/evmmax/evmmax.hpp
Outdated
/// 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. |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It doesn't matter.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
include/evmmax/evmmax.hpp
Outdated
/// 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. |
There was a problem hiding this comment.
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.
template <typename UintT> | ||
UintT ModArith<UintT>::to_mont(const UintT& x) const noexcept | ||
{ | ||
return mul(x, m_r_squared); |
There was a problem hiding this comment.
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
?
There was a problem hiding this comment.
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.
There was a problem hiding this 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, R²
is passed and the extra factor of R
cancels out.
There was a problem hiding this comment.
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()
?
There was a problem hiding this comment.
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.
lib/evmmax/evmmax.cpp
Outdated
{ | ||
namespace | ||
{ | ||
inline constexpr uint64_t mul_inv64(uint64_t base) noexcept |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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
.
const auto s = d.value + mod; | ||
return (d.carry) ? s : d.value; |
There was a problem hiding this comment.
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
const auto s = d.value + mod; | |
return (d.carry) ? s : d.value; | |
return d.carry ? (d.value + mod) : d.value; |
There was a problem hiding this comment.
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 | ||
{}; |
There was a problem hiding this comment.
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
.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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
2d24c2d
to
6dc5877
Compare
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++.
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: