Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
bbapi_srs.cpp
Go to the documentation of this file.
1
16#include <span>
17
18namespace bb::bbapi {
19
21{
22 constexpr size_t COMPRESSED_POINT_SIZE = 32;
23 constexpr size_t UNCOMPRESSED_POINT_SIZE = sizeof(g1::affine_element); // 64
24
25 size_t bytes_per_point = num_points > 0 ? points_buf.size() / num_points : 0;
26 std::vector<g1::affine_element> g1_points(num_points);
27 std::vector<uint8_t> uncompressed_out;
28
29 if (bytes_per_point == UNCOMPRESSED_POINT_SIZE) {
30 // Already uncompressed: fast path with from_buffer
31 parallel_for([&](ThreadChunk chunk) {
32 for (auto i : chunk.range(static_cast<size_t>(num_points))) {
33 g1_points[i] = from_buffer<g1::affine_element>(points_buf.data(), i * UNCOMPRESSED_POINT_SIZE);
34 }
35 });
36 } else if (bytes_per_point == COMPRESSED_POINT_SIZE) {
37 // Verify SHA-256 of every 4 MB chunk against the in-binary pin BN254_G1_CHUNK_HASHES.
38 // Require chunk-aligned input so every byte is covered (no partial trailing chunk).
39 if (points_buf.size() == 0 || points_buf.size() % bb::srs::SRS_CHUNK_SIZE_BYTES != 0) {
40 throw_or_abort("SrsInitSrs: compressed points_buf size " + std::to_string(points_buf.size()) +
41 " must be a positive multiple of " + std::to_string(bb::srs::SRS_CHUNK_SIZE_BYTES));
42 }
43 size_t num_full_chunks = points_buf.size() / bb::srs::SRS_CHUNK_SIZE_BYTES;
44 size_t chunks_to_verify = std::min(num_full_chunks, static_cast<size_t>(bb::srs::SRS_NUM_FULL_CHUNKS));
45 for (size_t i = 0; i < chunks_to_verify; ++i) {
46 auto chunk = std::span<const uint8_t>(points_buf.data() + i * bb::srs::SRS_CHUNK_SIZE_BYTES,
47 bb::srs::SRS_CHUNK_SIZE_BYTES);
48 auto hash = bb::crypto::sha256(chunk);
49 if (hash != bb::srs::BN254_G1_CHUNK_HASHES[i]) {
50 throw_or_abort("SrsInitSrs: g1 compressed chunk " + std::to_string(i) + " SHA-256 mismatch");
51 }
52 }
53
54 // Compressed: decompress and return uncompressed bytes for caller to cache
55 parallel_for([&](ThreadChunk chunk) {
56 for (auto i : chunk.range(static_cast<size_t>(num_points))) {
57 uint256_t c = from_buffer<uint256_t>(points_buf.data(), i * COMPRESSED_POINT_SIZE);
58 g1_points[i] = g1::affine_element::from_compressed(c);
59 }
60 });
61 // Serialize uncompressed points to return to caller for caching
62 uncompressed_out.resize(static_cast<size_t>(num_points) * UNCOMPRESSED_POINT_SIZE);
63 parallel_for([&](ThreadChunk chunk) {
64 for (auto i : chunk.range(static_cast<size_t>(num_points))) {
65 auto buf = to_buffer(g1_points[i]);
66 std::copy(buf.begin(), buf.end(), &uncompressed_out[i * UNCOMPRESSED_POINT_SIZE]);
67 }
68 });
69 } else {
70 throw_or_abort("SrsInitSrs: invalid points_buf size. Expected 32 or 64 bytes per point, got " +
71 std::to_string(bytes_per_point));
72 }
73
74 // Pin the first two G1 points to their canonical trusted-setup values. Defense in depth on the
75 // compressed path; the only gate on the uncompressed (cached) path.
76 if (num_points >= 1 && g1_points[0] != bb::srs::BN254_G1_FIRST_ELEMENT) {
77 throw_or_abort("SrsInitSrs: g1_points[0] is not the canonical BN254 generator");
78 }
79 if (num_points >= 2 && g1_points[1] != bb::srs::get_bn254_g1_second_element()) {
80 throw_or_abort("SrsInitSrs: g1_points[1] does not match the canonical trusted-setup tau·G");
81 }
82
83 // Defense in depth: hash-pin AND subgroup-check the G2 input. Hash equality alone is sufficient
84 // for the canonical case (it implies prime-order membership); the subgroup check is kept so
85 // that any future relaxation of the hash gate (e.g. a flag to allow a different trusted setup)
86 // does not silently reopen audit finding #7's small-subgroup attack.
87 auto g2_hash = bb::crypto::sha256(std::span<const uint8_t>(g2_point.data(), g2_point.size()));
88 if (g2_hash != bb::srs::BN254_G2_ELEMENT_SHA256) {
89 throw_or_abort("SrsInitSrs: g2_point bytes do not match the canonical Aztec [x]_2 SHA-256");
90 }
91 auto g2_point_elem = from_buffer<g2::affine_element>(g2_point.data());
92 if (!g2_point_elem.is_in_prime_subgroup()) {
93 throw_or_abort("SrsInitSrs: g2_point is not in the BN254 G2 prime-order subgroup");
94 }
95
96 // Initialize BN254 SRS
97 bb::srs::init_bn254_mem_crs_factory(g1_points, g2_point_elem);
98
99 return { .points_buf = std::move(uncompressed_out) };
100}
101
103{
104 // Validate buffer size before accessing raw pointer
105 const size_t required_size = static_cast<size_t>(num_points) * sizeof(curve::Grumpkin::AffineElement);
106 if (points_buf.size() < required_size) {
107 throw_or_abort("SrsInitGrumpkinSrs: points_buf too small (" + std::to_string(points_buf.size()) +
108 " bytes) for num_points=" + std::to_string(num_points) + " (need " +
109 std::to_string(required_size) + ")");
110 }
111
112 // Parse Grumpkin affine elements from buffer
114 for (uint32_t i = 0; i < num_points; ++i) {
115 points[i] =
116 from_buffer<curve::Grumpkin::AffineElement>(points_buf.data(), i * sizeof(curve::Grumpkin::AffineElement));
117 }
118
119 // Initialize Grumpkin SRS
121
122 return {};
123}
124
125} // namespace bb::bbapi
SRS (Structured Reference String) initialization command definitions for the Barretenberg RPC API.
typename Group::affine_element AffineElement
Definition grumpkin.hpp:64
group_elements::affine_element< Fq, Fr, Params > affine_element
Definition group.hpp:44
#define BB_UNUSED
Sha256Hash sha256(const ByteContainer &input)
SHA-256 hash function (FIPS 180-4)
Definition sha256.cpp:150
constexpr std::array< uint8_t, 32 > BN254_G2_ELEMENT_SHA256
SHA-256 hash of BN254_G2_ELEMENT_BYTES.
constexpr g1::affine_element BN254_G1_FIRST_ELEMENT
Expected first G1 element from BN254 CRS.
void init_grumpkin_mem_crs_factory(std::vector< curve::Grumpkin::AffineElement > const &points)
g1::affine_element get_bn254_g1_second_element()
Expected second G1 element from BN254 CRS.
void init_bn254_mem_crs_factory(std::vector< g1::affine_element > const &points, g2::affine_element const &g2_point)
void parallel_for(size_t num_iterations, const std::function< void(size_t)> &func)
Definition thread.cpp:111
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
Definition tuple.hpp:13
std::string to_string(bb::avm2::ValueTag tag)
std::vector< uint8_t > to_buffer(T const &value)
auto range(size_t size, size_t offset=0) const
Definition thread.hpp:152
Response execute(BBApiRequest &request) &&
Response execute(BBApiRequest &request) &&
Definition bbapi_srs.cpp:20
void throw_or_abort(std::string const &err)