Skip to content

precompiles: Add EC mixed-add formula #1170

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

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion lib/evmone_precompiles/bn254.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,8 @@ Point mul(const Point& pt, const uint256& c) noexcept
if (c == 0)
return {};

const auto pr = ecc::mul(Fp, ecc::to_proj(Fp, pt), c, B3);
const Point p_mont{Fp.to_mont(pt.x), Fp.to_mont(pt.y)};
const auto pr = ecc::mul(Fp, p_mont, c, B3);

return ecc::to_affine(Fp, pr);
}
Expand Down
58 changes: 57 additions & 1 deletion lib/evmone_precompiles/ecc.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,62 @@ ProjPoint<IntT> add(const evmmax::ModArith<IntT>& s, const ProjPoint<IntT>& p,
return {x3, y3, z3};
}

template <typename IntT, int A = 0>
ProjPoint<IntT> add(const ModArith<IntT>& s, const ProjPoint<IntT>& p, const Point<IntT>& q,
const IntT& b3) noexcept
{
(void)s;
static_assert(A == 0, "point addition procedure is simplified for a = 0");

// Joost Renes and Craig Costello and Lejla Batina
// "Complete addition formulas for prime order elliptic curves"
// Cryptology ePrint Archive, Paper 2015/1060
// https://eprint.iacr.org/2015/1060
// Algorithm 8.

const auto& x1 = p.x;
const auto& y1 = p.y;
const auto& z1 = p.z;
const auto& x2 = q.x;
const auto& y2 = q.y;
IntT x3;
IntT y3;
IntT z3;
IntT t0;
IntT t1;
IntT t2;
IntT t3;
IntT t4;

t0 = s.mul(x1, x2);
t1 = s.mul(y1, y2);
t3 = s.add(x2, y2);
t4 = s.add(x1, y1);
t3 = s.mul(t3, t4);
t4 = s.add(t0, t1);
t3 = s.sub(t3, t4);
t4 = s.mul(y2, z1);
t4 = s.add(t4, y1);
y3 = s.mul(x2, z1);
y3 = s.add(y3, x1);
x3 = s.add(t0, t0);
t0 = s.add(x3, t0);
t2 = s.mul(b3, z1);
z3 = s.add(t1, t2);
t1 = s.sub(t1, t2);
y3 = s.mul(b3, y3);
x3 = s.mul(t4, y3);
t2 = s.mul(t3, t1);
x3 = s.sub(t2, x3);
y3 = s.mul(y3, t0);
t1 = s.mul(t1, z3);
y3 = s.add(t1, y3);
t0 = s.mul(t0, t3);
z3 = s.mul(z3, t4);
z3 = s.add(z3, t0);

return {x3, y3, z3};
}

template <typename IntT, int A = 0>
ProjPoint<IntT> dbl(
Expand Down Expand Up @@ -239,7 +295,7 @@ ProjPoint<IntT> dbl(

template <typename IntT>
ProjPoint<IntT> mul(
const ModArith<IntT>& m, const ProjPoint<IntT>& p, const IntT& c, const IntT& b3) noexcept
const ModArith<IntT>& m, const Point<IntT>& p, const IntT& c, const IntT& b3) noexcept
{
ProjPoint<IntT> r;
const auto bit_width = sizeof(IntT) * 8 - intx::clz(c);
Expand Down
7 changes: 4 additions & 3 deletions lib/evmone_precompiles/secp256k1.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,8 @@ Point mul(const Point& p, const uint256& c) noexcept
if (c == 0)
return {0, 0};

const auto r = ecc::mul(Fp, ecc::to_proj(Fp, p), c, B3);
const Point p_mont{Fp.to_mont(p.x), Fp.to_mont(p.y)};
const auto r = ecc::mul(Fp, p_mont, c, B3);
return ecc::to_affine(Fp, r);
}

Expand Down Expand Up @@ -115,8 +116,8 @@ std::optional<Point> secp256k1_ecdsa_recover(
const auto y = Fp.from_mont(*y_mont);

// 6. Calculate public key point Q.
const auto R = ecc::to_proj(Fp, {r, y});
const auto pG = ecc::to_proj(Fp, G);
const auto R = Point{Fp.to_mont(r), Fp.to_mont(y)};
const auto pG = Point{Fp.to_mont(G.x), Fp.to_mont(G.y)};
const auto T1 = ecc::mul(Fp, pG, u1, B3);
const auto T2 = ecc::mul(Fp, R, u2, B3);
const auto pQ = ecc::add(Fp, T1, T2, B3);
Expand Down