From a2bd50826ce73241f11e19c0f75a931a59efe0f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Mon, 10 Aug 2026 23:48:53 +0200 Subject: [PATCH] crypto: Fold the pairing line coefficients into one function MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit lin_func and lin_func_and_add computed the same line coefficients: t[0] = (x0 − U2)·z0³ is −H·z0³ for H = U2 − x0, and t[1] and t[2] match term for term. Make lin_func the single implementation, returning the H and R terms the addition needs so lin_func_and_add only adds the point update; z0² and z0³ are no longer needed there since Z3 = H·z0. Its doc comment was a copy of lin_func_and_add's, describing an addition lin_func does not perform and a P2 parameter neither function has. The always_inline is load-bearing: without it the struct return costs about 0.3%, with it the change is instruction-neutral. --- .../pairing/bn254/utils.hpp | 55 ++++++++----------- 1 file changed, 24 insertions(+), 31 deletions(-) diff --git a/lib/evmone_precompiles/pairing/bn254/utils.hpp b/lib/evmone_precompiles/pairing/bn254/utils.hpp index b1ab9bf211..b38a3d7c19 100644 --- a/lib/evmone_precompiles/pairing/bn254/utils.hpp +++ b/lib/evmone_precompiles/pairing/bn254/utils.hpp @@ -295,10 +295,17 @@ constexpr ecc::ProjPoint lin_func_and_dbl( return ecc::ProjPoint{Xp, Yp, Zp}; } -/// Computes points P0 and P1 addition for twisted curve + line defined by untwisted P1 and P2 -/// points on the curve (not twisted curve) evaluated at point P. Formula is simplified for P1.z -/// == 1. For more details see https://notes.ethereum.org/@ipsilon/Hkn2a2qk0 -[[nodiscard]] constexpr ecc::ProjPoint lin_func_and_add( +/// The line terms that the point addition of lin_func_and_add() needs as well. +struct LineTerms +{ + Fq2 H; ///< x1·z0² − x0 + Fq2 R; ///< y1·z0³ − y0 +}; + +/// Computes the line defined by the untwisted P0 and P1 points on the curve (not twisted curve), +/// evaluated at point P and returned in `t`. Formula is simplified for P1.z == 1. +/// For more details see https://notes.ethereum.org/@ipsilon/Hkn2a2qk0 +[[gnu::always_inline]] constexpr LineTerms lin_func( const ecc::ProjPoint& P0, const ecc::AffinePoint& P1, std::array& t) noexcept { const auto& x0 = P0.x; @@ -316,45 +323,31 @@ constexpr ecc::ProjPoint lin_func_and_dbl( const auto H = U2 - x0; // x1 * z0^2 - x0 * z1^2 const auto R = S2 - y0; // y1 * z0^3 - y0 * z1^3 - const auto H_squared = H * H; - const auto H_cubed = H * H_squared; - const auto R_squared = R * R; - - const auto V = x0 * H_squared; - - const auto X3 = R_squared - H_cubed - (V + V); - const auto Y3 = R * (V - X3) - y0 * H_cubed; - const auto Z3 = H * z0; - t[0] = -H * z0_cubed; // = x0·z0³ − U2·z0³ t[1] = R * z0_squared; // = S2·z0² − y0·z0² t[2] = y0 * U2 - x0 * S2; - return ecc::ProjPoint{X3, Y3, Z3}; + return {H, R}; } -/// Computes points P0 and P1 addition for twisted curve + line defined by untwisted P1 and P2 -/// points on the curve (not twisted curve) evaluated at point P. Formula is simplified for P1.z -/// == 1. For more details see https://notes.ethereum.org/@ipsilon/Hkn2a2qk0 -constexpr void lin_func( +/// Computes points P0 and P1 addition on the twisted curve, along with the line of lin_func(). +/// For more details see https://notes.ethereum.org/@ipsilon/Hkn2a2qk0 +[[nodiscard]] constexpr ecc::ProjPoint lin_func_and_add( const ecc::ProjPoint& P0, const ecc::AffinePoint& P1, std::array& t) noexcept { - const auto& x0 = P0.x; - const auto& y0 = P0.y; - const auto& z0 = P0.z; + const auto [H, R] = lin_func(P0, P1, t); - const auto& x1 = P1.x; - const auto& y1 = P1.y; + const auto H_squared = H * H; + const auto H_cubed = H * H_squared; + const auto R_squared = R * R; - const auto z0_squared = z0 * z0; - const auto z0_cubed = z0 * z0_squared; + const auto V = P0.x * H_squared; - const auto U2 = x1 * z0_squared; - const auto S2 = y1 * z0_cubed; + const auto X3 = R_squared - H_cubed - (V + V); + const auto Y3 = R * (V - X3) - P0.y * H_cubed; + const auto Z3 = H * P0.z; - t[0] = (x0 - U2) * z0_cubed; // = x0·z0³ − U2·z0³ - t[1] = (S2 - y0) * z0_squared; // = S2·z0² − y0·z0² - t[2] = y0 * U2 - x0 * S2; + return ecc::ProjPoint{X3, Y3, Z3}; } /// Computes f^2 for f in Fq12. For more ref https://eprint.iacr.org/2010/354.pdf Algorithm 22