17constexpr const char* CRS_PRIMARY_URL =
"http://crs.aztec-cdn.foundation/g1_compressed.dat";
19constexpr const char* CRS_FALLBACK_URL =
"http://crs.aztec-labs.com/g1_compressed.dat";
20constexpr size_t COMPRESSED_POINT_SIZE = 32;
21constexpr size_t UNCOMPRESSED_POINT_SIZE = 64;
28 std::vector<uint8_t> buf(points.size() * UNCOMPRESSED_POINT_SIZE);
30 for (
auto i : chunk.range(points.size())) {
32 std::copy(serialized.begin(), serialized.end(), &buf[i * UNCOMPRESSED_POINT_SIZE]);
47 points[i] = from_buffer<bb::g1::affine_element>(
data, i * UNCOMPRESSED_POINT_SIZE);
56size_t round_up_to_chunk_boundary(
size_t num_points)
58 if (num_points >= bb::srs::SRS_TOTAL_POINTS) {
59 return bb::srs::SRS_TOTAL_POINTS;
61 size_t rounded = ((
num_points + bb::srs::SRS_CHUNK_SIZE_POINTS - 1) / bb::srs::SRS_CHUNK_SIZE_POINTS) *
62 bb::srs::SRS_CHUNK_SIZE_POINTS;
63 return std::min(rounded, bb::srs::SRS_TOTAL_POINTS);
85void verify_bn254_crs_integrity(
const std::vector<uint8_t>&
data)
87 size_t num_full_chunks =
data.size() / bb::srs::SRS_CHUNK_SIZE_BYTES;
88 size_t chunks_to_verify = std::min(num_full_chunks,
static_cast<size_t>(bb::srs::SRS_NUM_FULL_CHUNKS));
91 const size_t sentinel = bb::srs::SRS_NUM_CHUNKS;
92 std::atomic<size_t> failed_chunk{ sentinel };
95 if (chunks_to_verify > 0) {
97 for (
size_t i : tc.range(chunks_to_verify)) {
102 size_t offset = i * bb::srs::SRS_CHUNK_SIZE_BYTES;
105 if (hash != bb::srs::BN254_G1_CHUNK_HASHES[i]) {
106 size_t expected = sentinel;
114 size_t tail_offset = chunks_to_verify * bb::srs::SRS_CHUNK_SIZE_BYTES;
115 size_t tail_size =
data.size() - tail_offset;
116 if (tail_size > 0 && chunks_to_verify < bb::srs::SRS_NUM_CHUNKS) {
119 if (hash != bb::srs::BN254_G1_CHUNK_HASHES[chunks_to_verify]) {
120 size_t expected = sentinel;
125 size_t bad = failed_chunk.load();
126 if (bad < sentinel) {
127 size_t offset = bad * bb::srs::SRS_CHUNK_SIZE_BYTES;
132 vinfo(
"verified ", chunks_to_verify + (tail_size > 0 ? 1 : 0),
" BN254 G1 CRS chunks via SHA-256");
143 uint256_t compressed = from_buffer<uint256_t>(
data, i * COMPRESSED_POINT_SIZE);
144 points[i] = bb::g1::affine_element::from_compressed(compressed);
150std::vector<uint8_t> download_bn254_g1_data(
size_t num_points,
151 const std::string& primary_url,
152 const std::string& fallback_url)
155 size_t download_points = round_up_to_chunk_boundary(num_points);
156 size_t g1_end = (download_points * COMPRESSED_POINT_SIZE) - 1;
161 std::vector<uint8_t>
data;
165 }
catch (
const std::exception& e) {
166 vinfo(
"Primary CRS download failed: ", e.what(),
". Trying fallback...");
172 static_cast<void>(fallback_url);
175 if (
data.size() < COMPRESSED_POINT_SIZE) {
180 auto first = from_buffer<uint256_t>(
data, 0);
182 throw_or_abort(
"Downloaded BN254 G1 CRS first element does not match expected point.");
185 if (
data.size() >= 2 * COMPRESSED_POINT_SIZE) {
186 auto second = from_buffer<uint256_t>(
data, COMPRESSED_POINT_SIZE);
188 throw_or_abort(
"Downloaded BN254 G1 CRS second element does not match expected point.");
193 verify_bn254_crs_integrity(
data);
206 const std::string& primary_url,
207 const std::string& fallback_url)
210 std::filesystem::create_directories(path);
212 auto uncompressed_path = path /
"bn254_g1.dat";
213 auto compressed_path = path /
"bn254_g1_compressed.dat";
214 auto lock_path = path /
"crs.lock";
219 size_t uncompressed_points =
get_file_size(uncompressed_path) / UNCOMPRESSED_POINT_SIZE;
220 if (uncompressed_points >= num_points) {
221 vinfo(
"using cached uncompressed bn254 crs with ", uncompressed_points,
" points at ", uncompressed_path);
222 return read_uncompressed_g1_points(uncompressed_path, num_points);
226 size_t compressed_points =
get_file_size(compressed_path) / COMPRESSED_POINT_SIZE;
227 if (compressed_points >= num_points) {
228 vinfo(
"decompressing cached compressed bn254 crs (", compressed_points,
" points)...");
229 auto data =
read_file(compressed_path, num_points * COMPRESSED_POINT_SIZE);
230 auto points = decompress_g1_points(
data, num_points);
231 write_uncompressed_g1_points(points, uncompressed_path);
232 vinfo(
"cached uncompressed bn254 crs at ", uncompressed_path);
236 if (!allow_download && compressed_points == 0) {
238 " and bb does not automatically download in this context." +
239 " Run barretenberg/crs/bootstrap.sh to download.");
240 }
else if (!allow_download) {
245 " were requested but download not allowed in this context"));
249 uncompressed_points =
get_file_size(uncompressed_path) / UNCOMPRESSED_POINT_SIZE;
250 if (uncompressed_points >= num_points) {
251 return read_uncompressed_g1_points(uncompressed_path, num_points);
253 compressed_points =
get_file_size(compressed_path) / COMPRESSED_POINT_SIZE;
254 if (compressed_points >= num_points) {
255 auto data =
read_file(compressed_path, num_points * COMPRESSED_POINT_SIZE);
256 auto points = decompress_g1_points(
data, num_points);
257 write_uncompressed_g1_points(points, uncompressed_path);
262 vinfo(
"downloading bn254 crs...");
263 auto data = download_bn254_g1_data(num_points, primary_url, fallback_url);
265 auto points = decompress_g1_points(
data, num_points);
266 write_uncompressed_g1_points(points, uncompressed_path);
267 vinfo(
"cached uncompressed bn254 crs at ", uncompressed_path);
276 return get_bn254_g1_data(path, num_points, allow_download, CRS_PRIMARY_URL, CRS_FALLBACK_URL);
283 constexpr size_t G2_BYTES = 128;
284 auto g2_path = path /
"bn254_g2.dat";
287 " or has wrong size. Run barretenberg/crs/bootstrap.sh to provision.");
290 auto point = from_buffer<g2::affine_element>(
data.data());
295 if (point.is_point_at_infinity()) {
302 throw_or_abort(
"bn254 g2 SHA-256 mismatch: payload does not match the canonical [x]_2");
304 if (!point.is_in_prime_subgroup()) {
305 throw_or_abort(
"bn254 g2 deserialized to a point outside the prime-order subgroup");
#define BB_BENCH_NAME(name)
std::string format(Args... args)
const std::vector< MemoryValue > data
Sha256Hash sha256(const ByteContainer &input)
SHA-256 hash function (FIPS 180-4)
constexpr uint256_t BN254_G1_FIRST_ELEMENT_COMPRESSED
Compressed form of the first G1 element (generator point).
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 std::array< uint8_t, 32 > BN254_G2_ELEMENT_SHA256
SHA-256 hash of BN254_G2_ELEMENT_BYTES.
constexpr uint256_t BN254_G1_SECOND_ELEMENT_COMPRESSED
Compressed form of the second G1 element from the trusted setup.
Entry point for Barretenberg command-line interface.
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)
g2::affine_element get_bn254_g2_data(const std::filesystem::path &path)
void write_file(const std::string &filename, std::span< const uint8_t > data)
void parallel_for(size_t num_iterations, const std::function< void(size_t)> &func)
size_t get_file_size(std::string const &filename)
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
std::string to_string(bb::avm2::ValueTag tag)
std::vector< uint8_t > to_buffer(T const &value)
void throw_or_abort(std::string const &err)