2#include "../ecc/curves/bn254/bn254.hpp"
3#include "../ecc/curves/grumpkin/grumpkin.hpp"
10namespace barretenberg::srs {
39 uint32_t transcript_number;
40 uint32_t total_transcripts;
41 uint32_t total_g1_points;
42 uint32_t total_g2_points;
43 uint32_t num_g1_points;
44 uint32_t num_g2_points;
49template <
typename Curve>
50concept HasG2 =
requires {
typename Curve::G2AffineElement; };
53template <
typename Curve,
typename T>
57template <
typename Curve,
typename T>
60template <
typename Curve>
class IO {
61 using Fq =
typename Curve::BaseField;
62 using Fr =
typename Curve::ScalarField;
63 using Element =
typename Curve::Element;
64 using AffineElement =
typename Curve::AffineElement;
66 static constexpr size_t BLAKE2B_CHECKSUM_LENGTH = 64;
68 static size_t get_transcript_size(
const Manifest& manifest)
70 const size_t manifest_size =
sizeof(
Manifest);
71 const size_t g1_buffer_size =
sizeof(Fq) * 2 * manifest.num_g1_points;
72 size_t result = manifest_size + g1_buffer_size + BLAKE2B_CHECKSUM_LENGTH;
75 const size_t g2_buffer_size = 2 *
sizeof(Fq) * 2 * manifest.num_g2_points;
77 result += g2_buffer_size;
83 static void read_manifest(std::string
const& filename,
Manifest& manifest)
86 file.open(filename, std::ifstream::binary);
87 file.read((
char*)&manifest,
sizeof(
Manifest));
89 ptrdiff_t read = file.gcount();
90 throw_or_abort(format(
"Only read ", read,
" bytes from file but expected ",
sizeof(
Manifest),
"."));
94 manifest.transcript_number = ntohl(manifest.transcript_number);
95 manifest.total_transcripts = ntohl(manifest.total_transcripts);
96 manifest.total_g1_points = ntohl(manifest.total_g1_points);
97 manifest.total_g2_points = ntohl(manifest.total_g2_points);
98 manifest.num_g1_points = ntohl(manifest.num_g1_points);
99 manifest.num_g2_points = ntohl(manifest.num_g2_points);
100 manifest.start_from = ntohl(manifest.start_from);
103 static void write_buffer_to_file(std::string
const& filename,
char const* buffer,
size_t buffer_size)
107 file.write(&buffer[0], (
int)(buffer_size));
111 static size_t get_file_size(std::string
const& filename)
114 if (stat(filename.c_str(), &st) != 0) {
117 return (
size_t)st.st_size;
120 static void read_file_into_buffer(
121 char* buffer,
size_t& size, std::string
const& filename,
size_t offset = 0,
size_t amount = 0)
123 size = amount ? amount : get_file_size(filename) - offset;
126 file.open(filename, std::ifstream::binary);
127 file.seekg((
int)offset);
130 file.read(buffer, (
int)size);
132 ptrdiff_t read = file.gcount();
133 throw_or_abort(format(
"Only read ", read,
" bytes from file but expected ", size,
"."));
139 static std::string get_transcript_path(std::string
const& dir,
size_t num)
141 return format(dir,
"/monomial/transcript", (num < 10) ?
"0" :
"", std::to_string(num),
".dat");
144 static bool is_file_exist(std::string
const& fileName)
146 std::ifstream infile(fileName);
147 return infile.good();
150 template <
typename AffineElementType>
151 static void write_elements_to_buffer(AffineElementType
const* elements,
char* buffer,
size_t num_elements)
159 if (is_little_endian()) {
160 for (
size_t i = 0; i < num_elements; ++i) {
161 size_t byte_position_1 =
sizeof(Fq) * i * 2;
162 size_t byte_position_2 =
sizeof(Fq) * (i * 2 + 1);
164 temp_x_g1 = elements[i].x.from_montgomery_form();
165 temp_y_g1 = elements[i].y.from_montgomery_form();
167 temp_x[0] = __builtin_bswap64(temp_x_g1.data[0]);
168 temp_x[1] = __builtin_bswap64(temp_x_g1.data[1]);
169 temp_x[2] = __builtin_bswap64(temp_x_g1.data[2]);
170 temp_x[3] = __builtin_bswap64(temp_x_g1.data[3]);
171 temp_y[0] = __builtin_bswap64(temp_y_g1.data[0]);
172 temp_y[1] = __builtin_bswap64(temp_y_g1.data[1]);
173 temp_y[2] = __builtin_bswap64(temp_y_g1.data[2]);
174 temp_y[3] = __builtin_bswap64(temp_y_g1.data[3]);
176 memcpy((
void*)(buffer + byte_position_1), (
void*)temp_x,
sizeof(Fq));
177 memcpy((
void*)(buffer + byte_position_2), (
void*)temp_y,
sizeof(Fq));
188 if (is_little_endian()) {
189 for (
size_t i = 0; i < num_elements; ++i) {
190 size_t byte_position_1 =
sizeof(Fq) * (4 * i);
191 size_t byte_position_2 =
sizeof(Fq) * (4 * i + 2);
193 temp_x_g2_1 = elements[i].x.c0.from_montgomery_form();
194 temp_x_g2_2 = elements[i].x.c1.from_montgomery_form();
195 temp_y_g2_1 = elements[i].y.c0.from_montgomery_form();
196 temp_y_g2_2 = elements[i].y.c1.from_montgomery_form();
198 temp_x[0] = __builtin_bswap64(temp_x_g2_1.data[0]);
199 temp_x[1] = __builtin_bswap64(temp_x_g2_1.data[1]);
200 temp_x[2] = __builtin_bswap64(temp_x_g2_1.data[2]);
201 temp_x[3] = __builtin_bswap64(temp_x_g2_1.data[3]);
202 temp_x[4] = __builtin_bswap64(temp_x_g2_2.data[0]);
203 temp_x[5] = __builtin_bswap64(temp_x_g2_2.data[1]);
204 temp_x[6] = __builtin_bswap64(temp_x_g2_2.data[2]);
205 temp_x[7] = __builtin_bswap64(temp_x_g2_2.data[3]);
207 temp_y[0] = __builtin_bswap64(temp_y_g2_1.data[0]);
208 temp_y[1] = __builtin_bswap64(temp_y_g2_1.data[1]);
209 temp_y[2] = __builtin_bswap64(temp_y_g2_1.data[2]);
210 temp_y[3] = __builtin_bswap64(temp_y_g2_1.data[3]);
211 temp_y[4] = __builtin_bswap64(temp_y_g2_2.data[0]);
212 temp_y[5] = __builtin_bswap64(temp_y_g2_2.data[1]);
213 temp_y[6] = __builtin_bswap64(temp_y_g2_2.data[2]);
214 temp_y[7] = __builtin_bswap64(temp_y_g2_2.data[3]);
216 memcpy((
void*)(buffer + byte_position_1), (
void*)temp_x, 2 *
sizeof(Fq));
217 memcpy((
void*)(buffer + byte_position_2), (
void*)temp_y, 2 *
sizeof(Fq));
224 template <
typename AffineElementType>
static void byteswap(AffineElementType* elements,
size_t elements_size)
227 constexpr size_t bytes_per_element =
sizeof(AffineElementType);
228 size_t num_elements = elements_size / bytes_per_element;
230 if (is_little_endian()) {
231 for (
size_t i = 0; i < num_elements; ++i) {
232 elements[i].x.data[0] = __builtin_bswap64(elements[i].x.data[0]);
233 elements[i].x.data[1] = __builtin_bswap64(elements[i].x.data[1]);
234 elements[i].x.data[2] = __builtin_bswap64(elements[i].x.data[2]);
235 elements[i].x.data[3] = __builtin_bswap64(elements[i].x.data[3]);
236 elements[i].y.data[0] = __builtin_bswap64(elements[i].y.data[0]);
237 elements[i].y.data[1] = __builtin_bswap64(elements[i].y.data[1]);
238 elements[i].y.data[2] = __builtin_bswap64(elements[i].y.data[2]);
239 elements[i].y.data[3] = __builtin_bswap64(elements[i].y.data[3]);
240 elements[i].x.self_to_montgomery_form();
241 elements[i].y.self_to_montgomery_form();
245 constexpr size_t bytes_per_element =
sizeof(AffineElementType);
246 size_t num_elements = elements_size / bytes_per_element;
248 if (is_little_endian()) {
249 for (
size_t i = 0; i < num_elements; ++i) {
250 elements[i].x.c0.data[0] = __builtin_bswap64(elements[i].x.c0.data[0]);
251 elements[i].x.c0.data[1] = __builtin_bswap64(elements[i].x.c0.data[1]);
252 elements[i].x.c0.data[2] = __builtin_bswap64(elements[i].x.c0.data[2]);
253 elements[i].x.c0.data[3] = __builtin_bswap64(elements[i].x.c0.data[3]);
254 elements[i].y.c0.data[0] = __builtin_bswap64(elements[i].y.c0.data[0]);
255 elements[i].y.c0.data[1] = __builtin_bswap64(elements[i].y.c0.data[1]);
256 elements[i].y.c0.data[2] = __builtin_bswap64(elements[i].y.c0.data[2]);
257 elements[i].y.c0.data[3] = __builtin_bswap64(elements[i].y.c0.data[3]);
258 elements[i].x.c1.data[0] = __builtin_bswap64(elements[i].x.c1.data[0]);
259 elements[i].x.c1.data[1] = __builtin_bswap64(elements[i].x.c1.data[1]);
260 elements[i].x.c1.data[2] = __builtin_bswap64(elements[i].x.c1.data[2]);
261 elements[i].x.c1.data[3] = __builtin_bswap64(elements[i].x.c1.data[3]);
262 elements[i].y.c1.data[0] = __builtin_bswap64(elements[i].y.c1.data[0]);
263 elements[i].y.c1.data[1] = __builtin_bswap64(elements[i].y.c1.data[1]);
264 elements[i].y.c1.data[2] = __builtin_bswap64(elements[i].y.c1.data[2]);
265 elements[i].y.c1.data[3] = __builtin_bswap64(elements[i].y.c1.data[3]);
266 elements[i].x.c0.self_to_montgomery_form();
267 elements[i].x.c1.self_to_montgomery_form();
268 elements[i].y.c0.self_to_montgomery_form();
269 elements[i].y.c1.self_to_montgomery_form();
275 template <
typename AffineElementType>
276 static void read_affine_elements_from_buffer(AffineElementType* elements,
char const* buffer,
size_t buffer_size)
278 memcpy((
void*)elements, (
void*)buffer, buffer_size);
279 byteswap<>(elements, buffer_size);
282 static void read_transcript_g1(AffineElement* monomials,
size_t degree, std::string
const& dir)
286 std::string path = get_transcript_path(dir, num);
288 while (is_file_exist(path) && num_read < degree) {
290 read_manifest(path, manifest);
293 const size_t num_to_read = std::min((
size_t)manifest.num_g1_points, degree - num_read);
294 const size_t g1_buffer_size =
sizeof(Fq) * 2 * num_to_read;
296 char* buffer = (
char*)&monomials[num_read];
301 read_file_into_buffer(buffer, size, path, offset, g1_buffer_size);
304 num_read += num_to_read;
305 path = get_transcript_path(dir, ++num);
308 const bool monomial_srs_condition = num_read < degree;
309 if (monomial_srs_condition) {
317 ". Is your srs large enough? Either run bootstrap.sh to download the transcript.dat "
318 "files to `srs_db/ignition/`, or you might need to download extra transcript.dat files "
319 "by editing `srs_db/download_ignition.sh` (but be careful, as this suggests you've "
320 "just changed a circuit to exceed a new 'power of two' boundary)."));
324 static void read_transcript_g2(
auto& g2_x, std::string
const& dir)
327 const size_t g2_size =
sizeof(
typename Curve::G2BaseField) * 2;
328 std::string path = format(dir,
"/g2.dat");
330 if (is_file_exist(path)) {
331 char* buffer = (
char*)&g2_x;
335 read_file_into_buffer(buffer, size, path, 0, g2_size);
336 byteswap(&g2_x, size);
342 path = get_transcript_path(dir, 0);
345 read_manifest(path, manifest);
347 const size_t g2_buffer_offset =
sizeof(Fq) * 2 * manifest.num_g1_points;
348 auto offset =
sizeof(
Manifest) + g2_buffer_offset;
350 char* buffer = (
char*)&g2_x;
354 read_file_into_buffer(buffer, size, path, offset, g2_size);
355 byteswap(&g2_x, size);
358 static void read_transcript(AffineElement* monomials,
auto& g2_x,
size_t degree, std::string
const& path)
361 read_transcript_g1(monomials, degree, path);
362 read_transcript_g2(g2_x, path);
365 static void read_transcript(AffineElement* monomials,
size_t degree, std::string
const& path)
367 read_transcript_g1(monomials, degree, path);
371 static void write_transcript(AffineElement
const* g1_x,
374 std::string
const& dir)
377 const size_t num_g1_x = manifest.num_g1_points;
378 const size_t num_g2_x = manifest.num_g2_points;
379 const size_t transcript_num = manifest.transcript_number;
380 const size_t manifest_size =
sizeof(
Manifest);
381 const size_t g1_buffer_size =
sizeof(Fq) * 2 * num_g1_x;
382 const size_t g2_buffer_size =
sizeof(Fq) * 4 * num_g2_x;
383 const size_t transcript_size = manifest_size + g1_buffer_size + g2_buffer_size;
384 std::string path = get_transcript_path(dir, transcript_num);
385 std::vector<char> buffer(transcript_size);
388 net_manifest.transcript_number = htonl(manifest.transcript_number);
389 net_manifest.total_transcripts = htonl(manifest.total_transcripts);
390 net_manifest.total_g1_points = htonl(manifest.total_g1_points);
391 net_manifest.total_g2_points = htonl(manifest.total_g2_points);
392 net_manifest.num_g1_points = htonl(manifest.num_g1_points);
393 net_manifest.num_g2_points = htonl(manifest.num_g2_points);
394 net_manifest.start_from = htonl(manifest.start_from);
396 std::copy(&net_manifest, &net_manifest + 1, (
Manifest*)&buffer[0]);
398 write_g1_elements_to_buffer(g1_x, &buffer[manifest_size], num_g1_x);
399 write_g2_elements_to_buffer(g2_x, &buffer[manifest_size + g1_buffer_size], num_g2_x);
400 write_buffer_to_file(path, &buffer[0], transcript_size);
403 static void write_transcript(AffineElement
const* g1_x,
Manifest const& manifest, std::string
const& dir)
405 const size_t num_g1_x = manifest.num_g1_points;
406 const size_t transcript_num = manifest.transcript_number;
407 const size_t manifest_size =
sizeof(
Manifest);
408 const size_t g1_buffer_size =
sizeof(Fq) * 2 * num_g1_x;
409 const size_t transcript_size = manifest_size + g1_buffer_size;
410 std::string path = get_transcript_path(dir, transcript_num);
411 std::vector<char> buffer(transcript_size);
414 net_manifest.transcript_number = htonl(manifest.transcript_number);
415 net_manifest.total_transcripts = htonl(manifest.total_transcripts);
416 net_manifest.total_g1_points = htonl(manifest.total_g1_points);
417 net_manifest.total_g2_points = htonl(0);
418 net_manifest.num_g1_points = htonl(manifest.num_g1_points);
419 net_manifest.num_g2_points = htonl(0);
420 net_manifest.start_from = htonl(manifest.start_from);
422 std::copy(&net_manifest, &net_manifest + 1, (
Manifest*)&buffer[0]);
424 write_elements_to_buffer<AffineElement>(g1_x, &buffer[manifest_size], num_g1_x);
425 write_buffer_to_file(path, &buffer[0], transcript_size);
The manifest structure holds the header of a transcript file.
Definition: io.hpp:38