LCOV - differential code coverage report
Current view: top level - lib/evmone_precompiles - ecc.hpp (source / functions) Coverage Total Hit UBC
Current: DIFF_COVERAGE Lines: 0.0 % 100 0 100
Current Date: 2024-03-20 16:29:22 Functions: 0.0 % 7 0 7
Baseline: coverage_BASE.lcov
Baseline Date: 2024-03-20 14:19:08

           TLA  Line data    Source code
       1                 : // evmone: Fast Ethereum Virtual Machine implementation
       2                 : // Copyright 2023 The evmone Authors.
       3                 : // SPDX-License-Identifier: Apache-2.0
       4                 : #pragma once
       5                 : 
       6                 : #include <evmmax/evmmax.hpp>
       7                 : 
       8                 : namespace evmmax::ecc
       9                 : {
      10                 : 
      11                 : /// The affine (two coordinates) point on an Elliptic Curve over a prime field.
      12                 : template <typename IntT>
      13                 : struct Point
      14                 : {
      15                 :     IntT x = 0;
      16                 :     IntT y = 0;
      17                 : 
      18 UBC           0 :     friend constexpr bool operator==(const Point& a, const Point& b) noexcept
      19                 :     {
      20                 :         // TODO(intx): C++20 operator<=> = default does not work for uint256.
      21               0 :         return a.x == b.x && a.y == b.y;
      22                 :     }
      23                 : 
      24                 :     /// Checks if the point represents the special "infinity" value.
      25               0 :     [[nodiscard]] constexpr bool is_inf() const noexcept { return *this == Point{}; }
      26                 : };
      27                 : 
      28                 : static_assert(Point<unsigned>{}.is_inf());
      29                 : 
      30                 : template <typename IntT>
      31                 : struct ProjPoint
      32                 : {
      33                 :     IntT x = 0;
      34                 :     IntT y = 1;
      35                 :     IntT z = 0;
      36                 : 
      37                 :     /// Checks if the point represents the special "infinity" value.
      38                 :     [[nodiscard]] constexpr bool is_inf() const noexcept { return x == 0 && z == 0; }
      39                 : };
      40                 : 
      41                 : static_assert(ProjPoint<unsigned>{}.is_inf());
      42                 : 
      43                 : template <typename IntT>
      44                 : using InvFn = IntT (*)(const ModArith<IntT>&, const IntT& x) noexcept;
      45                 : 
      46                 : /// Converts an affine point to a projected point with coordinates in Montgomery form.
      47                 : template <typename IntT>
      48               0 : inline ProjPoint<IntT> to_proj(const ModArith<IntT>& s, const Point<IntT>& p) noexcept
      49                 : {
      50                 :     // FIXME: Add to_mont(1) to ModArith?
      51                 :     // FIXME: Handle inf
      52               0 :     return {s.to_mont(p.x), s.to_mont(p.y), s.to_mont(1)};
      53                 : }
      54                 : 
      55                 : /// Converts a projected point to an affine point.
      56                 : template <typename IntT>
      57               0 : inline Point<IntT> to_affine(
      58                 :     const ModArith<IntT>& s, InvFn<IntT> inv, const ProjPoint<IntT>& p) noexcept
      59                 : {
      60                 :     // FIXME: Split to_affine() and to/from_mont(). This is not good idea.
      61                 :     // FIXME: Add tests for inf.
      62               0 :     const auto z_inv = inv(s, p.z);
      63               0 :     return {s.from_mont(s.mul(p.x, z_inv)), s.from_mont(s.mul(p.y, z_inv))};
      64                 : }
      65                 : 
      66                 : template <typename IntT, int A = 0>
      67               0 : ProjPoint<IntT> add(const evmmax::ModArith<IntT>& s, const ProjPoint<IntT>& p,
      68                 :     const ProjPoint<IntT>& q, const IntT& b3) noexcept
      69                 : {
      70                 :     static_assert(A == 0, "point addition procedure is simplified for a = 0");
      71                 : 
      72                 :     // Joost Renes and Craig Costello and Lejla Batina
      73                 :     // "Complete addition formulas for prime order elliptic curves"
      74                 :     // Cryptology ePrint Archive, Paper 2015/1060
      75                 :     // https://eprint.iacr.org/2015/1060
      76                 :     // Algorithm 7.
      77                 : 
      78               0 :     const auto& x1 = p.x;
      79               0 :     const auto& y1 = p.y;
      80               0 :     const auto& z1 = p.z;
      81               0 :     const auto& x2 = q.x;
      82               0 :     const auto& y2 = q.y;
      83               0 :     const auto& z2 = q.z;
      84               0 :     IntT x3;
      85               0 :     IntT y3;
      86               0 :     IntT z3;
      87               0 :     IntT t0;
      88               0 :     IntT t1;
      89               0 :     IntT t2;
      90               0 :     IntT t3;
      91               0 :     IntT t4;
      92                 : 
      93               0 :     t0 = s.mul(x1, x2);  // 1
      94               0 :     t1 = s.mul(y1, y2);  // 2
      95               0 :     t2 = s.mul(z1, z2);  // 3
      96               0 :     t3 = s.add(x1, y1);  // 4
      97               0 :     t4 = s.add(x2, y2);  // 5
      98               0 :     t3 = s.mul(t3, t4);  // 6
      99               0 :     t4 = s.add(t0, t1);  // 7
     100               0 :     t3 = s.sub(t3, t4);  // 8
     101               0 :     t4 = s.add(y1, z1);  // 9
     102               0 :     x3 = s.add(y2, z2);  // 10
     103               0 :     t4 = s.mul(t4, x3);  // 11
     104               0 :     x3 = s.add(t1, t2);  // 12
     105               0 :     t4 = s.sub(t4, x3);  // 13
     106               0 :     x3 = s.add(x1, z1);  // 14
     107               0 :     y3 = s.add(x2, z2);  // 15
     108               0 :     x3 = s.mul(x3, y3);  // 16
     109               0 :     y3 = s.add(t0, t2);  // 17
     110               0 :     y3 = s.sub(x3, y3);  // 18
     111               0 :     x3 = s.add(t0, t0);  // 19
     112               0 :     t0 = s.add(x3, t0);  // 20
     113               0 :     t2 = s.mul(b3, t2);  // 21
     114               0 :     z3 = s.add(t1, t2);  // 22
     115               0 :     t1 = s.sub(t1, t2);  // 23
     116               0 :     y3 = s.mul(b3, y3);  // 24
     117               0 :     x3 = s.mul(t4, y3);  // 25
     118               0 :     t2 = s.mul(t3, t1);  // 26
     119               0 :     x3 = s.sub(t2, x3);  // 27
     120               0 :     y3 = s.mul(y3, t0);  // 28
     121               0 :     t1 = s.mul(t1, z3);  // 29
     122               0 :     y3 = s.add(t1, y3);  // 30
     123               0 :     t0 = s.mul(t0, t3);  // 31
     124               0 :     z3 = s.mul(z3, t4);  // 32
     125               0 :     z3 = s.add(z3, t0);  // 33
     126                 : 
     127               0 :     return {x3, y3, z3};
     128                 : }
     129                 : 
     130                 : 
     131                 : template <typename IntT, int A = 0>
     132               0 : ProjPoint<IntT> dbl(
     133                 :     const evmmax::ModArith<IntT>& s, const ProjPoint<IntT>& p, const IntT& b3) noexcept
     134                 : {
     135                 :     static_assert(A == 0, "point doubling procedure is simplified for a = 0");
     136                 : 
     137                 :     // Joost Renes and Craig Costello and Lejla Batina
     138                 :     // "Complete addition formulas for prime order elliptic curves"
     139                 :     // Cryptology ePrint Archive, Paper 2015/1060
     140                 :     // https://eprint.iacr.org/2015/1060
     141                 :     // Algorithm 9.
     142                 : 
     143               0 :     const auto& x = p.x;
     144               0 :     const auto& y = p.y;
     145               0 :     const auto& z = p.z;
     146               0 :     IntT x3;
     147               0 :     IntT y3;
     148               0 :     IntT z3;
     149               0 :     IntT t0;
     150               0 :     IntT t1;
     151               0 :     IntT t2;
     152                 : 
     153               0 :     t0 = s.mul(y, y);    // 1
     154               0 :     z3 = s.add(t0, t0);  // 2
     155               0 :     z3 = s.add(z3, z3);  // 3
     156               0 :     z3 = s.add(z3, z3);  // 4
     157               0 :     t1 = s.mul(y, z);    // 5
     158               0 :     t2 = s.mul(z, z);    // 6
     159               0 :     t2 = s.mul(b3, t2);  // 7
     160               0 :     x3 = s.mul(t2, z3);  // 8
     161               0 :     y3 = s.add(t0, t2);  // 9
     162               0 :     z3 = s.mul(t1, z3);  // 10
     163               0 :     t1 = s.add(t2, t2);  // 11
     164               0 :     t2 = s.add(t1, t2);  // 12
     165               0 :     t0 = s.sub(t0, t2);  // 13
     166               0 :     y3 = s.mul(t0, y3);  // 14
     167               0 :     y3 = s.add(x3, y3);  // 15
     168               0 :     t1 = s.mul(x, y);    // 16
     169               0 :     x3 = s.mul(t0, t1);  // 17
     170               0 :     x3 = s.add(x3, x3);  // 18
     171                 : 
     172               0 :     return {x3, y3, z3};
     173                 : }
     174                 : 
     175                 : template <typename IntT, int A = 0>
     176               0 : ProjPoint<IntT> mul(const evmmax::ModArith<IntT>& s, const ProjPoint<IntT>& z, const IntT& c,
     177                 :     const IntT& b3) noexcept
     178                 : {
     179               0 :     ProjPoint<IntT> p;
     180               0 :     auto q = z;
     181               0 :     auto first_significant_met = false;
     182                 : 
     183               0 :     for (int i = 255; i >= 0; --i)
     184                 :     {
     185               0 :         const auto d = c & (IntT{1} << i);
     186               0 :         if (d == 0)
     187                 :         {
     188               0 :             if (first_significant_met)
     189                 :             {
     190               0 :                 q = ecc::add(s, p, q, b3);
     191               0 :                 p = ecc::dbl(s, p, b3);
     192                 :             }
     193                 :         }
     194                 :         else
     195                 :         {
     196               0 :             p = ecc::add(s, p, q, b3);
     197               0 :             q = ecc::dbl(s, q, b3);
     198               0 :             first_significant_met = true;
     199                 :         }
     200                 :     }
     201                 : 
     202               0 :     return p;
     203                 : }
     204                 : 
     205                 : 
     206                 : }  // namespace evmmax::ecc
        

Generated by: LCOV version 2.0-1