Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
get_bn254_crs.cpp
Go to the documentation of this file.
1#include "get_bn254_crs.hpp"
3#include <algorithm>
8#include "bn254_crs_data.hpp"
10#include "http_download.hpp"
11
12namespace {
13// Primary CRS URL (Cloudflare R2)
14constexpr const char* CRS_PRIMARY_URL = "http://crs.aztec-cdn.foundation/g1.dat";
15// Fallback CRS URL (AWS S3)
16constexpr const char* CRS_FALLBACK_URL = "http://crs.aztec-labs.com/g1.dat";
17
18std::vector<uint8_t> download_bn254_g1_data(size_t num_points,
19 const std::string& primary_url,
20 const std::string& fallback_url)
21{
22 // Round up download size to next 8MB chunk boundary so every downloaded chunk
23 // can be fully verified against embedded SHA256 hashes.
24 // Cap at 256 full chunks to avoid requesting past end-of-file (the full CRS has
25 // 256 full 8MB chunks + a 64-byte remainder that can't fill another chunk).
26 constexpr size_t points_per_chunk = bb::srs::CRS_HASH_CHUNK_SIZE / sizeof(bb::g1::affine_element);
27 constexpr size_t max_aligned_points = bb::srs::CRS_NUM_FULL_CHUNKS * points_per_chunk;
28 size_t aligned_points = ((num_points + points_per_chunk - 1) / points_per_chunk) * points_per_chunk;
29 if (aligned_points > max_aligned_points) {
30 aligned_points = max_aligned_points;
31 }
32 // Request enough bytes for whichever is larger: the chunk-aligned amount or the actual request.
33 size_t download_points = std::max(aligned_points, num_points);
34 size_t g1_end = (download_points * sizeof(bb::g1::affine_element)) - 1;
35
36 // Try primary URL first, with fallback on failure.
37 // Note: WASM is compiled with -fno-exceptions, so try/catch is not available.
38 // In practice, WASM never calls this function - it initializes CRS via srs_init_srs from JavaScript.
39 std::vector<uint8_t> data;
40#ifndef __wasm__
41 try {
42 data = bb::srs::http_download(primary_url, 0, g1_end);
43 } catch (const std::exception& e) {
44 vinfo("Primary CRS download failed: ", e.what(), ". Trying fallback...");
45 data = bb::srs::http_download(fallback_url, 0, g1_end);
46 }
47#else
48 // WASM fallback: just try primary (will abort on failure)
49 data = bb::srs::http_download(primary_url, 0, g1_end);
50 static_cast<void>(fallback_url);
51#endif
52
53 if (data.size() < sizeof(bb::g1::affine_element)) {
54 throw_or_abort("Downloaded g1 data is too small");
55 }
56
57 // Verify first element matches the expected generator point (quick sanity check for all download sizes).
58 auto first_element = from_buffer<bb::g1::affine_element>(data, 0);
59 if (first_element != bb::srs::BN254_G1_FIRST_ELEMENT) {
60 throw_or_abort("Downloaded BN254 G1 CRS first element does not match expected point.");
61 }
62
63 // Verify integrity of all complete 8MB chunks against embedded SHA256 hashes.
64 // This protects against man-in-the-middle attacks on HTTP downloads without requiring SSL/TLS.
66
67 return data;
68}
69} // namespace
70
71namespace bb {
72
73// Main implementation with configurable URLs
74std::vector<g1::affine_element> get_bn254_g1_data(const std::filesystem::path& path,
75 size_t num_points,
76 bool allow_download,
77 const std::string& primary_url,
78 const std::string& fallback_url)
79{
80 std::filesystem::create_directories(path);
81
82 auto g1_path = path / "bn254_g1.dat";
83 auto lock_path = path / "crs.lock";
84 // Acquire exclusive lock to prevent simultaneous downloads
85 FileLockGuard lock(lock_path.string());
86
87 size_t g1_downloaded_points = get_file_size(g1_path) / sizeof(g1::affine_element);
88
89 if (g1_downloaded_points >= num_points) {
90 vinfo("using cached bn254 crs with num points ", std::to_string(g1_downloaded_points), " at ", g1_path);
91 auto data = read_file(g1_path, num_points * sizeof(g1::affine_element));
92 auto points = std::vector<g1::affine_element>(num_points);
93 for (size_t i = 0; i < num_points; ++i) {
94 points[i] = from_buffer<g1::affine_element>(data, i * sizeof(g1::affine_element));
95 }
96 return points;
97 }
98
99 if (!allow_download && g1_downloaded_points == 0) {
100 throw_or_abort("bn254 g1 data not found and download not allowed in this context");
101 } else if (!allow_download) {
102 throw_or_abort(format("bn254 g1 data had ",
103 g1_downloaded_points,
104 " points and ",
105 num_points,
106 " were requested but download not allowed in this context"));
107 }
108
109 // Double-check after acquiring lock (another process may have downloaded while we waited)
110 g1_downloaded_points = get_file_size(g1_path) / sizeof(g1::affine_element);
111 if (g1_downloaded_points >= num_points) {
112 vinfo("using cached bn254 crs with num points ", std::to_string(g1_downloaded_points), " at ", g1_path);
113 auto data = read_file(g1_path, num_points * sizeof(g1::affine_element));
114 auto points = std::vector<g1::affine_element>(num_points);
115 for (size_t i = 0; i < num_points; ++i) {
116 points[i] = from_buffer<g1::affine_element>(data, i * sizeof(g1::affine_element));
117 }
118 return points;
119 }
120
121 vinfo("downloading bn254 crs...");
122 auto data = download_bn254_g1_data(num_points, primary_url, fallback_url);
123 write_file(g1_path, data);
124
125 auto points = std::vector<g1::affine_element>(num_points);
126 for (size_t i = 0; i < num_points; ++i) {
127 points[i] = from_buffer<g1::affine_element>(data, i * sizeof(g1::affine_element));
128 }
129 return points;
130}
131
132// Default overload using production URLs
133std::vector<g1::affine_element> get_bn254_g1_data(const std::filesystem::path& path,
134 size_t num_points,
135 bool allow_download)
136{
137 return get_bn254_g1_data(path, num_points, allow_download, CRS_PRIMARY_URL, CRS_FALLBACK_URL);
138}
139
140} // namespace bb
group_elements::affine_element< Fq, Fr, Params > affine_element
Definition group.hpp:42
std::string format(Args... args)
Definition log.hpp:23
#define vinfo(...)
Definition log.hpp:94
const std::vector< MemoryValue > data
const size_t num_points
void verify_bn254_crs_integrity(const std::vector< uint8_t > &data)
Verify downloaded CRS data against embedded SHA256 chunk hashes.
std::vector< uint8_t > http_download(const std::string &url, size_t start_byte=0, size_t end_byte=0)
Download data from a URL with optional Range header support.
constexpr size_t CRS_NUM_FULL_CHUNKS
constexpr g1::affine_element BN254_G1_FIRST_ELEMENT
Expected first G1 element from BN254 CRS.
constexpr size_t CRS_HASH_CHUNK_SIZE
SHA256 hashes for integrity verification of downloaded BN254 CRS G1 data.
Entry point for Barretenberg command-line interface.
Definition api.hpp:5
std::vector< g1::affine_element > get_bn254_g1_data(const std::filesystem::path &path, size_t num_points, bool allow_download, const std::string &primary_url, const std::string &fallback_url)
std::vector< uint8_t > read_file(const std::string &filename, size_t bytes=0)
Definition file_io.hpp:30
void write_file(const std::string &filename, std::vector< uint8_t > const &data)
Definition file_io.hpp:59
size_t get_file_size(std::string const &filename)
Definition file_io.hpp:18
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
Definition tuple.hpp:13
std::string to_string(bb::avm2::ValueTag tag)
void throw_or_abort(std::string const &err)