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: not started, auditors: [], date: YYYY-MM-DD }
3// external_1: { status: not started, auditors: [], date: YYYY-MM-DD }
4// external_2: { status: not started, auditors: [], date: YYYY-MM-DD }
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_g1_hihi = 0;
18 uint64_t endo_g2_lo = 0;
19 uint64_t endo_g2_mid = 0;
20 uint64_t endo_g2_hi = 0;
21 uint64_t endo_g2_hihi = 0;
22 uint64_t endo_minus_b1_lo = 0;
23 uint64_t endo_minus_b1_mid = 0;
24 uint64_t endo_b2_lo = 0;
25 uint64_t endo_b2_mid = 0;
26 uint64_t endo_a1_lo = 0;
27 uint64_t endo_a1_mid = 0;
28 uint64_t endo_a1_hi = 0;
29 uint64_t endo_a2_lo = 0;
30 uint64_t endo_a2_mid = 0;
31 uint64_t endo_a2_hi = 0;
32
33 bool real = false;
34};
35[[maybe_unused]] static basis_vectors get_endomorphism_basis_vectors(const secp256k1::fr& lambda)
36{
37 uint512_t approximate_square_root;
40 while (z < y) {
41 y = z;
42 z = (uint512_t(secp256k1::fr::modulus) / z + z) >> 1;
43 }
44 approximate_square_root = y;
45 // Run the extended greatest common divisor algorithm until out * (\lambda + 1) < approximate_square_root
46
47 uint512_t u(lambda);
49 uint512_t x1 = 1;
50 uint512_t y1 = 0;
51 uint512_t x2 = 0;
52 uint512_t y2 = 1;
53
54 uint512_t a0 = 0;
55 uint512_t b0 = 0;
56
57 uint512_t a1 = 0;
58 uint512_t b1 = 0;
59
60 uint512_t a2 = 0;
61 uint512_t b2 = 0;
62
63 uint512_t prevOut = 0;
64 uint512_t i = 0;
65 uint512_t out = 0;
66 uint512_t x = 0;
67
68 while (u != 0) {
69 uint512_t q = v / u;
70 out = v - uint512_t(uint512_t(q) * uint512_t(u));
71 x = x2 - (q * x1);
72 uint512_t y = y2 - (q * y1);
73 if ((a1 == 0) && (out < approximate_square_root)) {
74 a0 = -prevOut;
75 b0 = x1;
76 a1 = -out;
77 b1 = x;
78 } else if ((a1 > 0) && (++i == 2)) {
79 break;
80 }
81 prevOut = out;
82
83 v = u;
84 u = out;
85 x2 = x1;
86 x1 = x;
87 y2 = y1;
88 y1 = y;
89 }
90
91 a2 = -out;
92 b2 = x;
93
94 uint512_t len1 = (a1 * a1) + (b1 * b1);
95 uint512_t len2 = (a2 * a2) + (b2 * b2);
96 if (len2 >= len1) {
97 a2 = a0;
98 b2 = b0;
99 }
100
101 if (a1.get_msb() >= 128) {
102 a1 = -a1;
103 b1 = -b1;
104 }
105 if (a2.get_msb() >= 128) {
106 a2 = -a2;
107 b2 = -b2;
108 }
109
110 uint512_t minus_b1 = -b1;
111 uint512_t shift256 = uint512_t(1) << 384;
112 uint512_t g1 = (-b1 * shift256) / uint512_t(secp256k1::fr::modulus);
113 uint512_t g2 = (b2 * shift256) / uint512_t(secp256k1::fr::modulus);
114
115 basis_vectors result;
116 result.endo_g1_lo = g1.lo.data[0];
117 result.endo_g1_mid = g1.lo.data[1];
118 result.endo_g1_hi = g1.lo.data[2];
119 result.endo_g1_hihi = g1.lo.data[3];
120 result.endo_g2_lo = g2.lo.data[0];
121 result.endo_g2_mid = g2.lo.data[1];
122 result.endo_g2_hi = g2.lo.data[2];
123 result.endo_g2_hihi = g2.lo.data[3];
124 result.endo_minus_b1_lo = minus_b1.lo.data[0];
125 result.endo_minus_b1_mid = minus_b1.lo.data[1];
126 result.endo_b2_lo = b2.lo.data[0];
127 result.endo_b2_mid = b2.lo.data[1];
128 result.endo_a1_lo = a1.lo.data[0];
129 result.endo_a1_mid = a1.lo.data[1];
130 result.endo_a1_hi = a1.lo.data[2];
131 result.endo_a2_lo = a2.lo.data[0];
132 result.endo_a2_mid = a2.lo.data[1];
133 result.endo_a2_hi = a2.lo.data[2];
134 return result;
135}
136
137[[maybe_unused]] static std::pair<secp256k1::fq, secp256k1::fr> get_endomorphism_scalars()
138{
139 // find beta \in secp256k1::fq and lambda \in secp256k1::fr such that:
140
141 // 1. beta^3 = 1 mod q
142 // 2. lambda^3 = 1 mod r
143 // 3. for [P] \in G with coordinates (P.x, P.y) \in secp256k1::fq:
144 // \lambda.[P] = (\beta . P.x, P.y)
147
148 if (beta * beta * beta != secp256k1::fq(1)) {
149 std::cerr << "beta is not a cube root of unity" << std::endl;
150 }
151 if (lambda * lambda * lambda != secp256k1::fr(1)) {
152 std::cerr << "lambda is not a cube root of unity" << std::endl;
153 }
154
156 secp256k1::g1::element endoP = P;
157 endoP.x *= beta;
158
159 if (P * lambda == endoP) {
160 return { beta, lambda };
161 }
162 endoP.x *= beta;
163 if ((P * lambda) == endoP) {
164 return { beta * beta, lambda };
165 }
166 endoP.y = -endoP.y;
167 std::cerr << "could not find endomorphism scalars???" << std::endl;
168 return { secp256k1::fq(0), secp256k1::fr(0) };
169}
170}; // 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:69
uintx< uint256_t > uint512_t
Definition uintx.hpp:307
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
General class for prime fields see Prime field documentation["field documentation"] for general imple...
static constexpr field cube_root_of_unity()
static constexpr uint256_t modulus