Wire Sysio Wire Sysion 1.0.0
Loading...
Searching...
No Matches
alt_bn128.cpp
Go to the documentation of this file.
1#include <gmp.h>
3
8
10#include <boost/throw_exception.hpp>
11#include <algorithm>
12
13namespace fc {
14
16
17 void initLibSnark() noexcept {
18 static bool s_initialized = []() noexcept {
22 return true;
23 }();
24 (void)s_initialized;
25 }
26
27 Scalar to_scalar(const bytes& be) noexcept {
28 mpz_t m;
29 mpz_init(m);
30 mpz_import(m, be.size(), /*order=*/1, /*size=*/1, /*endian=*/0, /*nails=*/0, &be[0]);
31 Scalar out{m};
32 mpz_clear(m);
33 return out;
34 }
35
36 // Notation warning: Yellow Paper's p is the same libff's q.
37 // Returns x < p (YP notation).
38 static bool valid_element_of_fp(const Scalar& x) noexcept {
39 return mpn_cmp(x.data, libff::alt_bn128_modulus_q.data, libff::alt_bn128_q_limbs) < 0;
40 }
41
42 std::variant<alt_bn128_error, libff::alt_bn128_G1> decode_g1_element(const bytes& bytes64_be) noexcept {
43 if(bytes64_be.size() != 64) {
45 }
46
47 bytes sub1(bytes64_be.begin(), bytes64_be.begin()+32);
48 bytes sub2(bytes64_be.begin()+32, bytes64_be.begin()+64);
49
50 Scalar x{to_scalar(sub1)};
51 Scalar y{to_scalar(sub2)};
52
53 if (!valid_element_of_fp(x) || !valid_element_of_fp(y)) {
55 }
56
57 if (x.is_zero() && y.is_zero()) {
59 }
60
62 if (!point.is_well_formed()) {
64 }
65 return point;
66 }
67
68 std::variant<alt_bn128_error, libff::alt_bn128_Fq2> decode_fp2_element(const bytes& bytes64_be) noexcept {
69 if(bytes64_be.size() != 64) {
71 }
72
73 // big-endian encoding
74 bytes sub1(bytes64_be.begin()+32, bytes64_be.begin()+64);
75 bytes sub2(bytes64_be.begin(), bytes64_be.begin()+32);
76
77 Scalar c0{to_scalar(sub1)};
78 Scalar c1{to_scalar(sub2)};
79
80 if (!valid_element_of_fp(c0) || !valid_element_of_fp(c1)) {
82 }
83
84 return libff::alt_bn128_Fq2{c0, c1};
85 }
86
87 std::variant<alt_bn128_error, libff::alt_bn128_G2> decode_g2_element(const bytes& bytes128_be) noexcept {
88 if(bytes128_be.size() != 128) {
90 }
91
92 bytes sub1(bytes128_be.begin(), bytes128_be.begin()+64);
93 auto maybe_x = decode_fp2_element(sub1);
94 if (std::holds_alternative<alt_bn128_error>(maybe_x)) {
95 return std::get<alt_bn128_error>(maybe_x);
96 }
97
98 bytes sub2(bytes128_be.begin()+64, bytes128_be.begin()+128);
99 auto maybe_y = decode_fp2_element(sub2);
100 if (std::holds_alternative<alt_bn128_error>(maybe_y)) {
101 return std::get<alt_bn128_error>(maybe_y);
102 }
103
104 const auto& x = std::get<libff::alt_bn128_Fq2>(maybe_x);
105 const auto& y = std::get<libff::alt_bn128_Fq2>(maybe_y);
106
107 if (x.is_zero() && y.is_zero()) {
109 }
110
112 if (!point.is_well_formed()) {
114 }
115
116 if (!(libff::alt_bn128_G2::order() * point).is_zero()) {
117 // wrong order, doesn't belong to the subgroup G2
119 }
120
121 return point;
122 }
123
125 bytes out(64, '\0');
126 if (p.is_zero()) {
127 return out;
128 }
129
130 p.to_affine_coordinates();
131
132 auto x{p.X.as_bigint()};
133 auto y{p.Y.as_bigint()};
134
135 std::memcpy(&out[0], y.data, 32);
136 std::memcpy(&out[32], x.data, 32);
137
138 std::reverse(out.begin(), out.end());
139 return out;
140 }
141
142 std::variant<alt_bn128_error, bytes> alt_bn128_add(const bytes& op1, const bytes& op2) {
144
145 auto maybe_x = decode_g1_element(op1);
146 if (std::holds_alternative<alt_bn128_error>(maybe_x)) {
147 return std::get<alt_bn128_error>(maybe_x);
148 }
149
150 auto maybe_y = decode_g1_element(op2);
151 if (std::holds_alternative<alt_bn128_error>(maybe_y)) {
152 return std::get<alt_bn128_error>(maybe_y);
153 }
154
155 const auto& x = std::get<libff::alt_bn128_G1>(maybe_x);
156 const auto& y = std::get<libff::alt_bn128_G1>(maybe_y);
157
158 libff::alt_bn128_G1 g1Sum = x + y;
159 return encode_g1_element(g1Sum);
160 }
161
162 std::variant<alt_bn128_error, bytes> alt_bn128_mul(const bytes& g1_point, const bytes& scalar) {
163 initLibSnark();
164
165 auto maybe_x = decode_g1_element(g1_point);
166 if (std::holds_alternative<alt_bn128_error>(maybe_x)) {
167 return std::get<alt_bn128_error>(maybe_x);
168 }
169
170 auto& x = std::get<libff::alt_bn128_G1>(maybe_x);
171
172 if(scalar.size() != 32) {
174 }
175
176 Scalar n{to_scalar(scalar)};
177
178 libff::alt_bn128_G1 g1Product = n * x;
179 return encode_g1_element(g1Product);
180 }
181
182 static constexpr size_t kSnarkvStride{192};
183
184 std::variant<alt_bn128_error, bool> alt_bn128_pair(const bytes& g1_g2_pairs, const yield_function_t& yield) {
185 if (g1_g2_pairs.size() % kSnarkvStride != 0) {
187 }
188
189 size_t k{g1_g2_pairs.size() / kSnarkvStride};
190
191 initLibSnark();
192 using namespace libff;
193
194 static const auto one{alt_bn128_Fq12::one()};
195 auto accumulator{one};
196
197 for (size_t i{0}; i < k; ++i) {
198 auto offset = i * kSnarkvStride;
199
200 bytes sub1(g1_g2_pairs.begin()+offset, g1_g2_pairs.begin()+offset+64);
201 auto maybe_a = decode_g1_element(sub1);
202 if (std::holds_alternative<alt_bn128_error>(maybe_a)) {
203 return std::get<alt_bn128_error>(maybe_a);
204 }
205
206 bytes sub2(g1_g2_pairs.begin()+offset+64, g1_g2_pairs.begin()+offset+64+128);
207 auto maybe_b = decode_g2_element(sub2);
208 if (std::holds_alternative<alt_bn128_error>(maybe_b)) {
209 return std::get<alt_bn128_error>(maybe_b);
210 }
211
212 const auto& a = std::get<libff::alt_bn128_G1>(maybe_a);
213 const auto& b = std::get<libff::alt_bn128_G2>(maybe_b);
214
215 if (a.is_zero() || b.is_zero()) {
216 continue;
217 }
218
219 accumulator = accumulator * alt_bn128_miller_loop(alt_bn128_precompute_G1(a), alt_bn128_precompute_G2(b));
220 yield();
221 }
222
223 bool pair_result = false;
224 if (alt_bn128_final_exponentiation(accumulator) == one) {
225 pair_result = true;
226 }
227
228 return pair_result;
229 }
230}
std::string one()
const mie::Vuint & p
Definition bn.cpp:27
static alt_bn128_G1 zero()
static alt_bn128_G2 zero()
static bigint< scalar_field::num_limbs > order()
static void init_public_params()
namespace sysio::chain
Definition authority.cpp:3
Scalar to_scalar(const bytes &be) noexcept
Definition alt_bn128.cpp:27
std::variant< alt_bn128_error, libff::alt_bn128_G2 > decode_g2_element(const bytes &bytes128_be) noexcept
Definition alt_bn128.cpp:87
bytes encode_g1_element(libff::alt_bn128_G1 p) noexcept
std::vector< char > bytes
Definition alt_bn128.hpp:10
void initLibSnark() noexcept
Definition alt_bn128.cpp:17
std::variant< alt_bn128_error, libff::alt_bn128_Fq2 > decode_fp2_element(const bytes &bytes64_be) noexcept
Definition alt_bn128.cpp:68
std::variant< alt_bn128_error, bytes > alt_bn128_add(const bytes &op1, const bytes &op2)
uint64_t y
Definition sha3.cpp:34
std::variant< alt_bn128_error, bytes > alt_bn128_mul(const bytes &g1_point, const bytes &scalar)
libff::bigint< libff::alt_bn128_q_limbs > Scalar
Definition alt_bn128.cpp:15
std::variant< alt_bn128_error, libff::alt_bn128_G1 > decode_g1_element(const bytes &bytes64_be) noexcept
Definition alt_bn128.cpp:42
std::variant< alt_bn128_error, bool > alt_bn128_pair(const bytes &g1_g2_pairs, const yield_function_t &yield)
bigint< alt_bn128_q_limbs > alt_bn128_modulus_q
const mp_size_t alt_bn128_q_limbs
bool inhibit_profiling_info
Definition profiling.cpp:95
bool inhibit_profiling_counters
Definition profiling.cpp:96
const GenericPointer< typename T::ValueType > T2 T::AllocatorType & a
Definition pointer.h:1181