Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
secp256k1_endo_notes.hpp
Go to the documentation of this file.
1// === AUDIT STATUS ===
2// internal: { status: Planned, auditors: [Raju], commit: }
3// external_1: { status: not started, auditors: [], commit: }
4// external_2: { status: not started, auditors: [], commit: }
5// =====================
6
7#pragma once
8
10#include "secp256k1.hpp"
11
12namespace bb::secp256k1 {
14 uint64_t endo_g1_lo = 0;
15 uint64_t endo_g1_mid = 0;
16 uint64_t endo_g1_hi = 0;
17 uint64_t endo_g2_lo = 0;
18 uint64_t endo_g2_mid = 0;
19 uint64_t endo_g2_hi = 0;
20 uint64_t endo_minus_b1_lo = 0;
21 uint64_t endo_minus_b1_mid = 0;
22 uint64_t endo_b2_lo = 0;
23 uint64_t endo_b2_mid = 0;
24 uint64_t endo_a1_lo = 0;
25 uint64_t endo_a1_mid = 0;
26 uint64_t endo_a1_hi = 0;
27 uint64_t endo_a2_lo = 0;
28 uint64_t endo_a2_mid = 0;
29 uint64_t endo_a2_hi = 0;
30
31 bool real = false;
32};
33[[maybe_unused]] static basis_vectors get_endomorphism_basis_vectors(const secp256k1::fr& lambda)
34{
35 uint512_t approximate_square_root;
38 while (z < y) {
39 y = z;
40 z = (uint512_t(secp256k1::fr::modulus) / z + z) >> 1;
41 }
42 approximate_square_root = y;
43 // Run the extended greatest common divisor algorithm until out * (\lambda + 1) < approximate_square_root
44
45 uint512_t u(lambda);
47 uint512_t x1 = 1;
48 uint512_t y1 = 0;
49 uint512_t x2 = 0;
50 uint512_t y2 = 1;
51
52 uint512_t a0 = 0;
53 uint512_t b0 = 0;
54
55 uint512_t a1 = 0;
56 uint512_t b1 = 0;
57
58 uint512_t a2 = 0;
59 uint512_t b2 = 0;
60
61 uint512_t prevOut = 0;
62 uint512_t i = 0;
63 uint512_t out = 0;
64 uint512_t x = 0;
65
66 while (u != 0) {
67 uint512_t q = v / u;
68 out = v - uint512_t(uint512_t(q) * uint512_t(u));
69 x = x2 - (q * x1);
70 uint512_t y = y2 - (q * y1);
71 if ((a1 == 0) && (out < approximate_square_root)) {
72 a0 = -prevOut;
73 b0 = x1;
74 a1 = -out;
75 b1 = x;
76 } else if ((a1 > 0) && (++i == 2)) {
77 break;
78 }
79 prevOut = out;
80
81 v = u;
82 u = out;
83 x2 = x1;
84 x1 = x;
85 y2 = y1;
86 y1 = y;
87 }
88
89 a2 = -out;
90 b2 = x;
91
92 uint512_t len1 = (a1 * a1) + (b1 * b1);
93 uint512_t len2 = (a2 * a2) + (b2 * b2);
94 if (len2 >= len1) {
95 a2 = a0;
96 b2 = b0;
97 }
98
99 if (a1.get_msb() >= 128) {
100 a1 = -a1;
101 b1 = -b1;
102 }
103 if (a2.get_msb() >= 128) {
104 a2 = -a2;
105 b2 = -b2;
106 }
107
108 uint512_t minus_b1 = -b1;
109 uint512_t shift256 = uint512_t(1) << 256;
110 uint512_t g1 = (-b1 * shift256) / uint512_t(secp256k1::fr::modulus);
111 uint512_t g2 = (b2 * shift256) / uint512_t(secp256k1::fr::modulus);
112
113 basis_vectors result;
114 result.endo_g1_lo = g1.lo.data[0];
115 result.endo_g1_mid = g1.lo.data[1];
116 result.endo_g1_hi = g1.lo.data[2];
117 result.endo_g2_lo = g2.lo.data[0];
118 result.endo_g2_mid = g2.lo.data[1];
119 result.endo_g2_hi = g2.lo.data[2];
120 result.endo_minus_b1_lo = minus_b1.lo.data[0];
121 result.endo_minus_b1_mid = minus_b1.lo.data[1];
122 result.endo_b2_lo = b2.lo.data[0];
123 result.endo_b2_mid = b2.lo.data[1];
124 result.endo_a1_lo = a1.lo.data[0];
125 result.endo_a1_mid = a1.lo.data[1];
126 result.endo_a1_hi = a1.lo.data[2];
127 result.endo_a2_lo = a2.lo.data[0];
128 result.endo_a2_mid = a2.lo.data[1];
129 result.endo_a2_hi = a2.lo.data[2];
130 return result;
131}
132
133[[maybe_unused]] static std::pair<secp256k1::fq, secp256k1::fr> get_endomorphism_scalars()
134{
135 // find beta \in secp256k1::fq and lambda \in secp256k1::fr such that:
136
137 // 1. beta^3 = 1 mod q
138 // 2. lambda^3 = 1 mod r
139 // 3. for [P] \in G with coordinates (P.x, P.y) \in secp256k1::fq:
140 // \lambda.[P] = (\beta . P.x, P.y)
143
144 if (beta * beta * beta != secp256k1::fq(1)) {
145 std::cerr << "beta is not a cube root of unity" << std::endl;
146 }
147 if (lambda * lambda * lambda != secp256k1::fr(1)) {
148 std::cerr << "lambda is not a cube root of unity" << std::endl;
149 }
150
152 secp256k1::g1::element endoP = P;
153 endoP.x *= beta;
154
155 if (P * lambda == endoP) {
156 return { beta, lambda };
157 }
158 endoP.x *= beta;
159 if ((P * lambda) == endoP) {
160 return { beta * beta, lambda };
161 }
162 endoP.y = -endoP.y;
163 std::cerr << "could not find endomorphism scalars???" << std::endl;
164 return { secp256k1::fq(0), secp256k1::fr(0) };
165}
166}; // namespace bb::secp256k1
static constexpr element one
Definition group.hpp:46
group_elements::element< Fq, Fr, Params > element
Definition group.hpp:41
constexpr uint64_t get_msb() const
Definition uintx.hpp:68
uintx< uint256_t > uint512_t
Definition uintx.hpp:306
field< FrParams > fr
group< fq, fr, G1Params > g1
field< FqParams > fq
group< fq2, fr, Bn254G2Params > g2
Definition g2.hpp:39
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
Definition tuple.hpp:13
static constexpr field cube_root_of_unity()
static constexpr uint256_t modulus