Skip to content

Commit

Permalink
fix: Fix client ivc incorrect srs size issue and parallelise srs gene…
Browse files Browse the repository at this point in the history
…ration for grumpkin (#6913)

1. Fixes an off-by-one issue
2. Adds paralllelisation to srs generation (now it's much faster on the
mainframe)

---------

Co-authored-by: ludamad <[email protected]>
  • Loading branch information
Rumata888 and ludamad authored Jun 5, 2024
1 parent 620d3da commit f015736
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 33 deletions.
5 changes: 4 additions & 1 deletion barretenberg/cpp/src/barretenberg/eccvm/eccvm_flavor.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -667,7 +667,10 @@ class ECCVMFlavor {

VerificationKey(const std::shared_ptr<ProvingKey>& proving_key)
{
this->pcs_verification_key = std::make_shared<VerifierCommitmentKey>(proving_key->circuit_size);
// IPA verification key requires one more point.
// TODO(https://github.com/AztecProtocol/barretenberg/issues/1025): make it so that PCSs inform the crs of
// how many points they need
this->pcs_verification_key = std::make_shared<VerifierCommitmentKey>(proving_key->circuit_size + 1);
this->circuit_size = proving_key->circuit_size;
this->log_circuit_size = numeric::get_msb(this->circuit_size);
this->num_public_inputs = proving_key->num_public_inputs;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#include <iostream>

#include "barretenberg/common/net.hpp"
#include "barretenberg/common/thread.hpp"
#include "barretenberg/crypto/sha256/sha256.hpp"
#include "barretenberg/ecc/curves/grumpkin/grumpkin.hpp"
#include "barretenberg/srs/io.hpp"
Expand Down Expand Up @@ -36,40 +37,49 @@ int main(int argc, char** argv)

std::vector<bb::grumpkin::g1::affine_element> srs(subgroup_size);

std::vector<uint8_t> hash_input;

for (size_t point_idx = 0; point_idx < subgroup_size; ++point_idx) {
bool rational_point_found = false;
size_t attempt = 0;
while (!rational_point_found) {
hash_input.clear();
// We hash |BARRETENBERG_GRUMPKIN_IPA_CRS|POINT_INDEX_IN_LITTLE_ENDIAN|POINT_ATTEMPT_INDEX_IN_LITTLE_ENDIAN|
std::copy(protocol_name.begin(), protocol_name.end(), std::back_inserter(hash_input));
uint64_t point_index_le_order = htonll(static_cast<uint64_t>(point_idx));
uint64_t point_attempt_le_order = htonll(static_cast<uint64_t>(attempt));
hash_input.insert(hash_input.end(),
reinterpret_cast<uint8_t*>(&point_index_le_order),
reinterpret_cast<uint8_t*>(&point_index_le_order) + sizeof(uint64_t));
hash_input.insert(hash_input.end(),
reinterpret_cast<uint8_t*>(&point_attempt_le_order),
reinterpret_cast<uint8_t*>(&point_attempt_le_order) + sizeof(uint64_t));
auto hash_result = crypto::sha256(hash_input);
uint256_t hash_result_uint(ntohll(*reinterpret_cast<uint64_t*>(hash_result.data())),
ntohll(*reinterpret_cast<uint64_t*>(hash_result.data() + sizeof(uint64_t))),
ntohll(*reinterpret_cast<uint64_t*>(hash_result.data() + 2 * sizeof(uint64_t))),
ntohll(*reinterpret_cast<uint64_t*>(hash_result.data() + 3 * sizeof(uint64_t))));
// We try to get a point from the resulting hash
auto crs_element = grumpkin::g1::affine_element::from_compressed(hash_result_uint);
// If the points coordinates are (0,0) then the compressed representation didn't land on an actual point
// (happens half of the time) and we need to continue searching
if (!crs_element.x.is_zero() || !crs_element.y.is_zero()) {
rational_point_found = true;
srs.at(point_idx) = static_cast<grumpkin::g1::affine_element>(crs_element);
break;
#ifndef NO_MULTITHREADING
std::mutex vector_access_mutex;
#endif
run_loop_in_parallel(subgroup_size, [&](size_t start, size_t end) {
std::vector<uint8_t> hash_input;
for (size_t point_idx = start; point_idx < end; ++point_idx) {
bool rational_point_found = false;
size_t attempt = 0;
while (!rational_point_found) {
hash_input.clear();
// We hash
// |BARRETENBERG_GRUMPKIN_IPA_CRS|POINT_INDEX_IN_LITTLE_ENDIAN|POINT_ATTEMPT_INDEX_IN_LITTLE_ENDIAN|
std::copy(protocol_name.begin(), protocol_name.end(), std::back_inserter(hash_input));
uint64_t point_index_le_order = htonll(static_cast<uint64_t>(point_idx));
uint64_t point_attempt_le_order = htonll(static_cast<uint64_t>(attempt));
hash_input.insert(hash_input.end(),
reinterpret_cast<uint8_t*>(&point_index_le_order),
reinterpret_cast<uint8_t*>(&point_index_le_order) + sizeof(uint64_t));
hash_input.insert(hash_input.end(),
reinterpret_cast<uint8_t*>(&point_attempt_le_order),
reinterpret_cast<uint8_t*>(&point_attempt_le_order) + sizeof(uint64_t));
auto hash_result = crypto::sha256(hash_input);
uint256_t hash_result_uint(
ntohll(*reinterpret_cast<uint64_t*>(hash_result.data())),
ntohll(*reinterpret_cast<uint64_t*>(hash_result.data() + sizeof(uint64_t))),
ntohll(*reinterpret_cast<uint64_t*>(hash_result.data() + 2 * sizeof(uint64_t))),
ntohll(*reinterpret_cast<uint64_t*>(hash_result.data() + 3 * sizeof(uint64_t))));
// We try to get a point from the resulting hash
auto crs_element = grumpkin::g1::affine_element::from_compressed(hash_result_uint);
// If the points coordinates are (0,0) then the compressed representation didn't land on an actual point
// (happens half of the time) and we need to continue searching
if (!crs_element.x.is_zero() || !crs_element.y.is_zero()) {
rational_point_found = true;
{
std::unique_lock<std::mutex> lock(vector_access_mutex);
srs.at(point_idx) = static_cast<grumpkin::g1::affine_element>(crs_element);
}
break;
}
attempt += 1;
}
attempt += 1;
}
}
});

bb::srs::Manifest manifest{ 0, 1, static_cast<uint32_t>(subgroup_size), 0, static_cast<uint32_t>(subgroup_size),
0, 0 };
Expand Down

0 comments on commit f015736

Please sign in to comment.