diff --git a/barretenberg/acir_tests/Dockerfile.bb b/barretenberg/acir_tests/Dockerfile.bb index 7e211d62eca..3dee4e370d8 100644 --- a/barretenberg/acir_tests/Dockerfile.bb +++ b/barretenberg/acir_tests/Dockerfile.bb @@ -10,5 +10,7 @@ COPY . . # Run every acir test through native bb build prove_then_verify flow. # This ensures we test independent pk construction through real/garbage witness data paths. RUN FLOW=prove_then_verify ./run_acir_tests.sh +# TODO(https://github.com/AztecProtocol/barretenberg/issues/811) make this able to run the default test +RUN FLOW=prove_and_verify_goblin ./run_acir_tests.sh assert_statement # Run 1_mul through native bb build, all_cmds flow, to test all cli args. RUN VERBOSE=1 FLOW=all_cmds ./run_acir_tests.sh 1_mul \ No newline at end of file diff --git a/barretenberg/acir_tests/Dockerfile.bb.js b/barretenberg/acir_tests/Dockerfile.bb.js index 760b231fc90..4bfb7c27f50 100644 --- a/barretenberg/acir_tests/Dockerfile.bb.js +++ b/barretenberg/acir_tests/Dockerfile.bb.js @@ -14,6 +14,8 @@ COPY . . ENV VERBOSE=1 # Run double_verify_proof through bb.js on node to check 512k support. RUN BIN=../ts/dest/node/main.js FLOW=prove_then_verify ./run_acir_tests.sh double_verify_proof +# TODO(https://github.com/AztecProtocol/barretenberg/issues/811) make this able to run double_verify_proof +RUN BIN=../ts/dest/node/main.js FLOW=prove_and_verify_goblin ./run_acir_tests.sh assert_statement # Run 1_mul through bb.js build, all_cmds flow, to test all cli args. RUN BIN=../ts/dest/node/main.js FLOW=all_cmds ./run_acir_tests.sh 1_mul # Run double_verify_proof through bb.js on chrome testing multi-threaded browser support. diff --git a/barretenberg/acir_tests/flows/prove_and_verify_goblin.sh b/barretenberg/acir_tests/flows/prove_and_verify_goblin.sh new file mode 100755 index 00000000000..a5da48d2738 --- /dev/null +++ b/barretenberg/acir_tests/flows/prove_and_verify_goblin.sh @@ -0,0 +1,6 @@ +#!/bin/sh +set -eu + +VFLAG=${VERBOSE:+-v} + +$BIN prove_and_verify_goblin $VFLAG -c $CRS_PATH -b ./target/acir.gz \ No newline at end of file diff --git a/barretenberg/cpp/.dockerignore b/barretenberg/cpp/.dockerignore index 2f64b1972b1..7c18c4a13f9 100644 --- a/barretenberg/cpp/.dockerignore +++ b/barretenberg/cpp/.dockerignore @@ -8,6 +8,7 @@ # Important srs_db files. !srs_db/download_ignition.sh +!srs_db/download_grumpkin.sh !srs_db/ignition/checksums # Source code. diff --git a/barretenberg/cpp/dockerfiles/Dockerfile.wasm-linux-clang b/barretenberg/cpp/dockerfiles/Dockerfile.wasm-linux-clang index ac811d862f0..115a877758b 100644 --- a/barretenberg/cpp/dockerfiles/Dockerfile.wasm-linux-clang +++ b/barretenberg/cpp/dockerfiles/Dockerfile.wasm-linux-clang @@ -11,5 +11,6 @@ RUN ./scripts/strip-wasm.sh FROM scratch WORKDIR /usr/src/barretenberg/cpp COPY . . +COPY --from=builder /usr/src/barretenberg/cpp/srs_db /usr/src/barretenberg/cpp/srs_db COPY --from=builder /usr/src/barretenberg/cpp/build-wasm/bin/barretenberg.wasm /usr/src/barretenberg/cpp/build-wasm/bin/barretenberg.wasm COPY --from=builder /usr/src/barretenberg/cpp/build-wasm-threads/bin/barretenberg.wasm /usr/src/barretenberg/cpp/build-wasm-threads/bin/barretenberg.wasm diff --git a/barretenberg/cpp/dockerfiles/Dockerfile.x86_64-linux-clang-assert b/barretenberg/cpp/dockerfiles/Dockerfile.x86_64-linux-clang-assert index a44442d0bf4..d487335b597 100644 --- a/barretenberg/cpp/dockerfiles/Dockerfile.x86_64-linux-clang-assert +++ b/barretenberg/cpp/dockerfiles/Dockerfile.x86_64-linux-clang-assert @@ -3,19 +3,20 @@ FROM alpine:3.17 AS builder RUN apk update \ && apk upgrade \ && apk add --no-cache \ - build-base \ - clang15 \ - cmake \ - ninja \ - git \ - curl \ - perl \ - clang-extra-tools \ - bash + build-base \ + clang15 \ + cmake \ + ninja \ + git \ + curl \ + perl \ + clang-extra-tools \ + bash WORKDIR /usr/src/barretenberg/cpp COPY . . # Build everything to ensure everything builds. All tests will be run from the result of this build. RUN ./format.sh check && cmake --preset default -DCMAKE_BUILD_TYPE=RelWithAssert -DCI=ON && cmake --build --preset default +RUN srs_db/download_grumpkin.sh FROM alpine:3.17 RUN apk update && apk add curl libstdc++ diff --git a/barretenberg/cpp/scripts/bb-tests.sh b/barretenberg/cpp/scripts/bb-tests.sh index a3f322b2afa..934817d08a2 100755 --- a/barretenberg/cpp/scripts/bb-tests.sh +++ b/barretenberg/cpp/scripts/bb-tests.sh @@ -44,7 +44,7 @@ TESTS_STR="${TESTS[@]}" docker run --rm -t $IMAGE_URI /bin/sh -c "\ set -xe; \ cd /usr/src/barretenberg/cpp; \ - (cd srs_db && ./download_ignition.sh 1); \ + srs_db/download_ignition.sh 1; \ + srs_db/download_grumpkin.sh; \ cd build; \ - ./bin/grumpkin_srs_gen 1048576; \ for BIN in $TESTS_STR; do ./bin/\$BIN; done" diff --git a/barretenberg/cpp/scripts/run_tests b/barretenberg/cpp/scripts/run_tests index a67f03ee992..e801ad2bde3 100755 --- a/barretenberg/cpp/scripts/run_tests +++ b/barretenberg/cpp/scripts/run_tests @@ -27,8 +27,7 @@ fi docker run --rm -t $IMAGE_URI /bin/sh -c "\ set -xe; \ - cd /usr/src/barretenberg/cpp/srs_db; \ - ./download_ignition.sh $NUM_TRANSCRIPTS; \ + /usr/src/barretenberg/cpp/srs_db/download_ignition.sh $NUM_TRANSCRIPTS; \ + /usr/src/barretenberg/cpp/srs_db/download_grumpkin.sh; \ cd /usr/src/barretenberg/cpp/build; \ - ./bin/grumpkin_srs_gen 1048576; \ for BIN in $TESTS; do ./bin/\$BIN $@; done" diff --git a/barretenberg/cpp/src/CMakeLists.txt b/barretenberg/cpp/src/CMakeLists.txt index 8f3ee4289c5..352a7d1cafe 100644 --- a/barretenberg/cpp/src/CMakeLists.txt +++ b/barretenberg/cpp/src/CMakeLists.txt @@ -96,9 +96,9 @@ include(GNUInstallDirs) # libbarretenberg + libwasi = a wasi "reactor" that implements it's own env (e.g. logstr), e.g. barretenberg.wasm. # libbarretenberg + env = a wasi "command" that expects a full wasi runtime (e.g. wasmtime), e.g. test binaries. message(STATUS "Compiling all-in-one barretenberg archive") -add_library( - barretenberg - STATIC + +set(BARRETENBERG_TARGET_OBJECTS + $ $ $ $ @@ -111,12 +111,17 @@ add_library( $ $ $ + $ $ + $ + $ $ $ $ $ $ + $ + $ $ $ $ @@ -126,9 +131,18 @@ add_library( $ $ $ + $ $ $ + $ $ + $ + $) + +add_library( + barretenberg + STATIC + ${BARRETENBERG_TARGET_OBJECTS} ) if(WASM) @@ -144,36 +158,7 @@ if(WASM) # to implement the functions in env. add_executable( barretenberg.wasm - $ - $ - $ - $ - $ - $ - $ - $ - $ - $ - $ - $ - $ - $ - $ - $ - $ - $ - $ - $ - $ - $ - $ - $ - $ - $ - $ - $ - $ - $ + ${BARRETENBERG_TARGET_OBJECTS} $ ) @@ -194,12 +179,12 @@ if(WASM) target_link_options( barretenberg.wasm PRIVATE - -nostartfiles -Wl,--no-entry,--export-dynamic,--allow-undefined + -nostartfiles -Wl,--no-entry,--export-dynamic ) target_link_options( acvm_backend.wasm PRIVATE - -nostartfiles -Wl,--no-entry,--export-dynamic,--allow-undefined + -nostartfiles -Wl,--no-entry,--export-dynamic ) endif() diff --git a/barretenberg/cpp/src/barretenberg/bb/CMakeLists.txt b/barretenberg/cpp/src/barretenberg/bb/CMakeLists.txt index 910b29b7a14..dc17b35d001 100644 --- a/barretenberg/cpp/src/barretenberg/bb/CMakeLists.txt +++ b/barretenberg/cpp/src/barretenberg/bb/CMakeLists.txt @@ -2,6 +2,8 @@ if (NOT(FUZZING)) add_executable( bb main.cpp + get_bn254_crs.cpp + get_grumpkin_crs.cpp ) target_link_libraries( diff --git a/barretenberg/cpp/src/barretenberg/bb/get_crs.hpp b/barretenberg/cpp/src/barretenberg/bb/get_bn254_crs.cpp similarity index 77% rename from barretenberg/cpp/src/barretenberg/bb/get_crs.hpp rename to barretenberg/cpp/src/barretenberg/bb/get_bn254_crs.cpp index 1c205f2f3e8..06ec36faff6 100644 --- a/barretenberg/cpp/src/barretenberg/bb/get_crs.hpp +++ b/barretenberg/cpp/src/barretenberg/bb/get_bn254_crs.cpp @@ -1,33 +1,27 @@ -#pragma once -#include "exec_pipe.hpp" -#include "file_io.hpp" -#include "log.hpp" -#include -#include -#include -#include -#include +#include "get_bn254_crs.hpp" // Gets the transcript URL from the BARRETENBERG_TRANSCRIPT_URL environment variable, if set. // Otherwise returns the default URL. -inline std::string getTranscriptURL() +namespace { +std::string get_bn254_transcript_url() { const char* ENV_VAR_NAME = "BARRETENBERG_TRANSCRIPT_URL"; const std::string DEFAULT_URL = "https://aztec-ignition.s3.amazonaws.com/MAIN%20IGNITION/monomial/transcript00.dat"; const char* env_url = std::getenv(ENV_VAR_NAME); - auto environment_variable_exists = (env_url && *env_url); + auto environment_variable_exists = ((env_url != nullptr) && *env_url); return environment_variable_exists ? std::string(env_url) : DEFAULT_URL; } +} // namespace -inline std::vector download_g1_data(size_t num_points) +std::vector download_bn254_g1_data(size_t num_points) { size_t g1_start = 28; size_t g1_end = g1_start + num_points * 64 - 1; - std::string url = getTranscriptURL(); + std::string url = get_bn254_transcript_url(); std::string command = "curl -s -H \"Range: bytes=" + std::to_string(g1_start) + "-" + std::to_string(g1_end) + "\" '" + url + "'"; @@ -38,15 +32,15 @@ inline std::vector download_g1_data(size_t num_points) throw std::runtime_error("Failed to download g1 data."); } - return exec_pipe(command); + return data; } -inline std::vector download_g2_data() +std::vector download_bn254_g2_data() { size_t g2_start = 28 + 5040001 * 64; size_t g2_end = g2_start + 128 - 1; - std::string url = getTranscriptURL(); + std::string url = get_bn254_transcript_url(); std::string command = "curl -s -H \"Range: bytes=" + std::to_string(g2_start) + "-" + std::to_string(g2_end) + "\" '" + url + "'"; @@ -54,7 +48,7 @@ inline std::vector download_g2_data() return exec_pipe(command); } -inline std::vector get_g1_data(const std::filesystem::path& path, size_t num_points) +std::vector get_bn254_g1_data(const std::filesystem::path& path, size_t num_points) { std::filesystem::create_directories(path); std::ifstream size_file(path / "size"); @@ -74,7 +68,7 @@ inline std::vector get_g1_data(const std::file } vinfo("downloading crs..."); - auto data = download_g1_data(num_points); + auto data = download_bn254_g1_data(num_points); write_file(path / "g1.dat", data); std::ofstream new_size_file(path / "size"); @@ -90,7 +84,7 @@ inline std::vector get_g1_data(const std::file return points; } -inline barretenberg::g2::affine_element get_g2_data(const std::filesystem::path& path) +barretenberg::g2::affine_element get_bn254_g2_data(const std::filesystem::path& path) { std::filesystem::create_directories(path); @@ -100,7 +94,7 @@ inline barretenberg::g2::affine_element get_g2_data(const std::filesystem::path& barretenberg::srs::IO::read_affine_elements_from_buffer(&g2_point, (char*)data.data(), 128); return g2_point; } catch (std::exception&) { - auto data = download_g2_data(); + auto data = download_bn254_g2_data(); write_file(path / "g2.dat", data); barretenberg::g2::affine_element g2_point; barretenberg::srs::IO::read_affine_elements_from_buffer(&g2_point, (char*)data.data(), 128); diff --git a/barretenberg/cpp/src/barretenberg/bb/get_bn254_crs.hpp b/barretenberg/cpp/src/barretenberg/bb/get_bn254_crs.hpp new file mode 100644 index 00000000000..74c5e7bcea4 --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/bb/get_bn254_crs.hpp @@ -0,0 +1,12 @@ +#pragma once +#include "exec_pipe.hpp" +#include "file_io.hpp" +#include "log.hpp" +#include +#include +#include +#include +#include + +std::vector get_bn254_g1_data(const std::filesystem::path& path, size_t num_points); +barretenberg::g2::affine_element get_bn254_g2_data(const std::filesystem::path& path); \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/bb/get_grumpkin_crs.cpp b/barretenberg/cpp/src/barretenberg/bb/get_grumpkin_crs.cpp new file mode 100644 index 00000000000..2cb7ba42320 --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/bb/get_grumpkin_crs.cpp @@ -0,0 +1,72 @@ +#include "get_grumpkin_crs.hpp" + +// Gets the transcript URL from the BARRETENBERG_GRUMPKIN_TRANSCRIPT_URL environment variable, if set. +// Otherwise returns the default URL. +namespace { +std::string get_grumpkin_transcript_url() +{ + const char* ENV_VAR_NAME = "BARRETENBERG_GRUMPKIN_TRANSCRIPT_URL"; + const std::string DEFAULT_URL = "https://aztec-ignition.s3.amazonaws.com/TEST%20GRUMPKIN/monomial/transcript00.dat"; + + const char* env_url = std::getenv(ENV_VAR_NAME); + + auto environment_variable_exists = ((env_url != nullptr) && *env_url); + + return environment_variable_exists ? env_url : DEFAULT_URL; +} +} // namespace + +std::vector download_grumpkin_g1_data(size_t num_points) +{ + size_t g1_start = 28; + size_t g1_end = g1_start + num_points * 64 - 1; + + std::string url = get_grumpkin_transcript_url(); + + std::string command = + "curl -s -H \"Range: bytes=" + std::to_string(g1_start) + "-" + std::to_string(g1_end) + "\" '" + url + "'"; + + auto data = exec_pipe(command); + // Header + num_points * sizeof point. + if (data.size() < g1_end - g1_start) { + throw std::runtime_error("Failed to download grumpkin g1 data."); + } + + return data; +} + +std::vector get_grumpkin_g1_data(const std::filesystem::path& path, size_t num_points) +{ + std::filesystem::create_directories(path); + std::ifstream size_file(path / "grumpkin_size"); + size_t size = 0; + if (size_file) { + size_file >> size; + size_file.close(); + } + if (size >= num_points) { + vinfo("using cached crs at: ", path); + auto data = read_file(path / "grumpkin_g1.dat", 28 + num_points * 64); + auto points = std::vector(num_points); + auto size_of_points_in_bytes = num_points * 64; + barretenberg::srs::IO::read_affine_elements_from_buffer( + points.data(), (char*)data.data(), size_of_points_in_bytes); + return points; + } + + vinfo("downloading grumpkin crs..."); + auto data = download_grumpkin_g1_data(num_points); + write_file(path / "grumpkin_g1.dat", data); + + std::ofstream new_size_file(path / "grumpkin_size"); + if (!new_size_file) { + throw std::runtime_error("Failed to open size file for writing"); + } + new_size_file << num_points; + new_size_file.close(); + + auto points = std::vector(num_points); + barretenberg::srs::IO::read_affine_elements_from_buffer( + points.data(), (char*)data.data(), data.size()); + return points; +} diff --git a/barretenberg/cpp/src/barretenberg/bb/get_grumpkin_crs.hpp b/barretenberg/cpp/src/barretenberg/bb/get_grumpkin_crs.hpp new file mode 100644 index 00000000000..894885ce97e --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/bb/get_grumpkin_crs.hpp @@ -0,0 +1,11 @@ +#pragma once +#include "exec_pipe.hpp" +#include "file_io.hpp" +#include "log.hpp" +#include +#include +#include +#include +#include + +std::vector get_grumpkin_g1_data(const std::filesystem::path& path, size_t num_points); \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/bb/main.cpp b/barretenberg/cpp/src/barretenberg/bb/main.cpp index 0cc46d9dd24..35c260f8969 100644 --- a/barretenberg/cpp/src/barretenberg/bb/main.cpp +++ b/barretenberg/cpp/src/barretenberg/bb/main.cpp @@ -2,8 +2,9 @@ #include "barretenberg/dsl/types.hpp" #include "barretenberg/plonk/proof_system/proving_key/serialize.hpp" #include "config.hpp" +#include "get_bn254_crs.hpp" #include "get_bytecode.hpp" -#include "get_crs.hpp" +#include "get_grumpkin_crs.hpp" #include "get_witness.hpp" #include "log.hpp" #include @@ -31,17 +32,39 @@ acir_proofs::AcirComposer init(acir_format::acir_format& constraint_system) auto subgroup_size = acir_composer.get_circuit_subgroup_size(); // Must +1! - auto g1_data = get_g1_data(CRS_PATH, subgroup_size + 1); - auto g2_data = get_g2_data(CRS_PATH); - srs::init_crs_factory(g1_data, g2_data); + auto bn254_g1_data = get_bn254_g1_data(CRS_PATH, subgroup_size + 1); + auto bn254_g2_data = get_bn254_g2_data(CRS_PATH); + srs::init_crs_factory(bn254_g1_data, bn254_g2_data); + + // Must +1! + auto grumpkin_g1_data = get_grumpkin_g1_data(CRS_PATH, subgroup_size + 1); + srs::init_grumpkin_crs_factory(grumpkin_g1_data); return acir_composer; } -acir_proofs::AcirComposer init() +void init_reference_strings() +{ + // TODO(https://github.com/AztecProtocol/barretenberg/issues/811): Don't hardcode subgroup size + size_t subgroup_size = 32768; + + // TODO(https://github.com/AztecProtocol/barretenberg/issues/811) reduce duplication with above + // Must +1! + auto g1_data = get_bn254_g1_data(CRS_PATH, subgroup_size + 1); + auto g2_data = get_bn254_g2_data(CRS_PATH); + srs::init_crs_factory(g1_data, g2_data); + + // Must +1! + auto grumpkin_g1_data = get_grumpkin_g1_data(CRS_PATH, subgroup_size + 1); + srs::init_grumpkin_crs_factory(grumpkin_g1_data); +} + +// Initializes without loading G1 +// TODO(https://github.com/AztecProtocol/barretenberg/issues/811) adapt for grumpkin +acir_proofs::AcirComposer verifier_init() { acir_proofs::AcirComposer acir_composer(0, verbose); - auto g2_data = get_g2_data(CRS_PATH); + auto g2_data = get_bn254_g2_data(CRS_PATH); srs::init_crs_factory({}, g2_data); return acir_composer; } @@ -98,6 +121,43 @@ bool proveAndVerify(const std::string& bytecodePath, const std::string& witnessP return verified; } +/** + * @brief Proves and Verifies an ACIR circuit + * + * Communication: + * - proc_exit: A boolean value is returned indicating whether the proof is valid. + * an exit code of 0 will be returned for success and 1 for failure. + * + * @param bytecodePath Path to the file containing the serialized circuit + * @param witnessPath Path to the file containing the serialized witness + * @param recursive Whether to use recursive proof generation of non-recursive + * @return true if the proof is valid + * @return false if the proof is invalid + */ +bool proveAndVerifyGoblin(const std::string& bytecodePath, + const std::string& witnessPath, + [[maybe_unused]] bool recursive) +{ + info("Construct constraint_system and witness."); + auto constraint_system = get_constraint_system(bytecodePath); + auto witness = get_witness(witnessPath); + + init_reference_strings(); + + info("Construct goblin circuit from constraint system and witness."); + acir_proofs::AcirComposer acir_composer; + acir_composer.create_goblin_circuit(constraint_system, witness); + + info("Construct goblin proof."); + auto proof = acir_composer.create_goblin_proof(); + + info("verify_goblin_proof."); + auto verified = acir_composer.verify_goblin_proof(proof); + + vinfo("verified: ", verified); + return verified; +} + /** * @brief Creates a proof for an ACIR circuit * @@ -165,7 +225,7 @@ void gateCount(const std::string& bytecodePath) */ bool verify(const std::string& proof_path, bool recursive, const std::string& vk_path) { - auto acir_composer = init(); + auto acir_composer = verifier_init(); auto vk_data = from_buffer(read_file(vk_path)); acir_composer.load_verification_key(std::move(vk_data)); auto verified = acir_composer.verify_proof(read_file(proof_path), recursive); @@ -231,7 +291,7 @@ void write_pk(const std::string& bytecodePath, const std::string& outputPath) */ void contract(const std::string& output_path, const std::string& vk_path) { - auto acir_composer = init(); + auto acir_composer = verifier_init(); auto vk_data = from_buffer(read_file(vk_path)); acir_composer.load_verification_key(std::move(vk_data)); auto contract = acir_composer.get_solidity_verifier(); @@ -272,7 +332,7 @@ void contract(const std::string& output_path, const std::string& vk_path) */ void proof_as_fields(const std::string& proof_path, std::string const& vk_path, const std::string& output_path) { - auto acir_composer = init(); + auto acir_composer = verifier_init(); auto vk_data = from_buffer(read_file(vk_path)); auto data = acir_composer.serialize_proof_into_fields(read_file(proof_path), vk_data.num_public_inputs); auto json = format("[", join(map(data, [](auto fr) { return format("\"", fr, "\""); })), "]"); @@ -301,7 +361,7 @@ void proof_as_fields(const std::string& proof_path, std::string const& vk_path, */ void vk_as_fields(const std::string& vk_path, const std::string& output_path) { - auto acir_composer = init(); + auto acir_composer = verifier_init(); auto vk_data = from_buffer(read_file(vk_path)); acir_composer.load_verification_key(std::move(vk_data)); auto data = acir_composer.serialize_verification_key_into_fields(); @@ -394,10 +454,12 @@ int main(int argc, char* argv[]) acvm_info(output_path); return 0; } - if (command == "prove_and_verify") { return proveAndVerify(bytecode_path, witness_path, recursive) ? 0 : 1; } + if (command == "prove_and_verify_goblin") { + return proveAndVerifyGoblin(bytecode_path, witness_path, recursive) ? 0 : 1; + } if (command == "prove") { std::string output_path = get_option(args, "-o", "./proofs/proof"); prove(bytecode_path, witness_path, recursive, output_path); diff --git a/barretenberg/cpp/src/barretenberg/commitment_schemes/commitment_key.hpp b/barretenberg/cpp/src/barretenberg/commitment_schemes/commitment_key.hpp index 2e9c65864a0..394ff93fdbe 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes/commitment_key.hpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/commitment_key.hpp @@ -16,6 +16,7 @@ #include "barretenberg/polynomials/polynomial_arithmetic.hpp" #include "barretenberg/srs/factories/crs_factory.hpp" #include "barretenberg/srs/factories/file_crs_factory.hpp" +#include "barretenberg/srs/global_crs.hpp" #include #include @@ -46,7 +47,9 @@ template class CommitmentKey { * @param path * */ - CommitmentKey(const size_t num_points, std::shared_ptr> crs_factory) + CommitmentKey(const size_t num_points, + std::shared_ptr> crs_factory = + barretenberg::srs::get_crs_factory()) : pippenger_runtime_state(num_points) , srs(crs_factory->get_prover_crs(num_points)) {} diff --git a/barretenberg/cpp/src/barretenberg/commitment_schemes/gemini/gemini.hpp b/barretenberg/cpp/src/barretenberg/commitment_schemes/gemini/gemini.hpp index de7a4d1eb75..b0ed17cdc19 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes/gemini/gemini.hpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/gemini/gemini.hpp @@ -264,6 +264,4 @@ template class GeminiVerifier_ { }; // namespace proof_system::honk::pcs::gemini -extern template class GeminiProver_; -extern template class GeminiProver_; } // namespace proof_system::honk::pcs::gemini diff --git a/barretenberg/cpp/src/barretenberg/common/wasm_export.hpp b/barretenberg/cpp/src/barretenberg/common/wasm_export.hpp index f30c5946489..b9ba4efc139 100644 --- a/barretenberg/cpp/src/barretenberg/common/wasm_export.hpp +++ b/barretenberg/cpp/src/barretenberg/common/wasm_export.hpp @@ -7,3 +7,10 @@ #define WASM_EXPORT extern "C" __attribute__((visibility("default"))) #define ASYNC_WASM_EXPORT extern "C" __attribute__((visibility("default"))) #endif + +#ifdef __wasm__ +// Allow linker to not link this +#define WASM_IMPORT(name) extern "C" __attribute__((import_module("env"), import_name(name))) +#else +#define WASM_IMPORT(name) extern "C" +#endif \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_format.cpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_format.cpp index 6d94ba7b766..64411b6b2d0 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_format.cpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_format.cpp @@ -1,19 +1,64 @@ #include "acir_format.hpp" #include "barretenberg/common/log.hpp" #include "barretenberg/dsl/acir_format/pedersen.hpp" +#include "barretenberg/proof_system/circuit_builder/ultra_circuit_builder.hpp" namespace acir_format { -void read_witness(Builder& builder, WitnessVector const& witness) +/** + * @brief Populate variables and public_inputs in builder given witness and constraint_system + * @details This method replaces consecutive calls to add_public_vars then read_witness. + * + * @tparam Builder + * @param builder + * @param witness + * @param constraint_system + */ +template +void populate_variables_and_public_inputs(Builder& builder, + WitnessVector const& witness, + acir_format const& constraint_system) { - builder.variables[0] = 0; + // TODO(https://github.com/AztecProtocol/barretenberg/issues/816): Decrement the indices in + // constraint_system.public_inputs by one to account for the +1 added by default to account for a const zero + // variable in noir. This entire block can be removed once the +1 is removed from noir. + const uint32_t pre_applied_noir_offset = 1; + std::vector corrected_public_inputs; + for (const auto& index : constraint_system.public_inputs) { + corrected_public_inputs.emplace_back(index - pre_applied_noir_offset); + } + + for (size_t idx = 0; idx < constraint_system.varnum; ++idx) { + // TODO(https://github.com/AztecProtocol/barretenberg/issues/815) why is this needed? + fr value = idx < witness.size() ? witness[idx] : 0; + if (std::find(corrected_public_inputs.begin(), corrected_public_inputs.end(), idx) != + corrected_public_inputs.end()) { + builder.add_public_variable(value); + } else { + builder.add_variable(value); + } + } +} + +template void read_witness(Builder& builder, WitnessVector const& witness) +{ + builder.variables[0] = + 0; // TODO(https://github.com/AztecProtocol/barretenberg/issues/816): This the constant 0 hacked in. Bad. for (size_t i = 0; i < witness.size(); ++i) { + // TODO(https://github.com/AztecProtocol/barretenberg/issues/816): The i+1 accounts for the fact that 0 is added + // as a constant in variables in the UCB constructor. "witness" only contains the values that came directly from + // acir. builder.variables[i + 1] = witness[i]; } } -void add_public_vars(Builder& builder, acir_format const& constraint_system) +// TODO(https://github.com/AztecProtocol/barretenberg/issues/815): This function does two things: 1) emplaces back +// varnum-many 0s into builder.variables (.. why), and (2) populates builder.public_inputs with the correct indices into +// the variables vector (which at this stage will be populated with zeros). The actual entries of the variables vector +// are populated in "read_witness" +template void add_public_vars(Builder& builder, acir_format const& constraint_system) { + // TODO(https://github.com/AztecProtocol/barretenberg/issues/816): i = 1 acounting for const 0 in first position? for (size_t i = 1; i < constraint_system.varnum; ++i) { // If the index is in the public inputs vector, then we add it as a public input @@ -28,6 +73,7 @@ void add_public_vars(Builder& builder, acir_format const& constraint_system) } } +template void build_constraints(Builder& builder, acir_format const& constraint_system, bool has_valid_witness_assignments) { // Add arithmetic gates @@ -104,22 +150,27 @@ void build_constraints(Builder& builder, acir_format const& constraint_system, b } // Add recursion constraints - for (size_t i = 0; i < constraint_system.recursion_constraints.size(); ++i) { - auto& constraint = constraint_system.recursion_constraints[i]; - create_recursion_constraints(builder, constraint, has_valid_witness_assignments); - - // make sure the verification key records the public input indices of the final recursion output - // (N.B. up to the ACIR description to make sure that the final output aggregation object wires are public - // inputs!) - if (i == constraint_system.recursion_constraints.size() - 1) { - std::vector proof_output_witness_indices(constraint.output_aggregation_object.begin(), - constraint.output_aggregation_object.end()); - builder.set_recursive_proof(proof_output_witness_indices); + // TODO(https://github.com/AztecProtocol/barretenberg/issues/817): disable these for UGH for now since we're not yet + // dealing with proper recursion + if constexpr (IsGoblinBuilder) { + info("WARNING: this circuit contains recursion_constraints!"); + } else { + for (size_t i = 0; i < constraint_system.recursion_constraints.size(); ++i) { + auto& constraint = constraint_system.recursion_constraints[i]; + create_recursion_constraints(builder, constraint, has_valid_witness_assignments); + + // make sure the verification key records the public input indices of the final recursion output (N.B. up to + // the ACIR description to make sure that the final output aggregation object wires are public inputs!) + if (i == constraint_system.recursion_constraints.size() - 1) { + std::vector proof_output_witness_indices(constraint.output_aggregation_object.begin(), + constraint.output_aggregation_object.end()); + builder.set_recursive_proof(proof_output_witness_indices); + } } } } -void create_circuit(Builder& builder, acir_format const& constraint_system) +template void create_circuit(Builder& builder, acir_format const& constraint_system) { if (constraint_system.public_inputs.size() > constraint_system.varnum) { info("create_circuit: too many public inputs!"); @@ -129,7 +180,7 @@ void create_circuit(Builder& builder, acir_format const& constraint_system) build_constraints(builder, constraint_system, false); } -Builder create_circuit(const acir_format& constraint_system, size_t size_hint) +template Builder create_circuit(const acir_format& constraint_system, size_t size_hint) { Builder builder(size_hint); create_circuit(builder, constraint_system); @@ -145,15 +196,57 @@ Builder create_circuit_with_witness(acir_format const& constraint_system, return builder; } +template void create_circuit_with_witness(Builder& builder, acir_format const& constraint_system, WitnessVector const& witness) { if (constraint_system.public_inputs.size() > constraint_system.varnum) { info("create_circuit_with_witness: too many public inputs!"); } - add_public_vars(builder, constraint_system); - read_witness(builder, witness); + // Populate builder.variables and buider.public_inputs + populate_variables_and_public_inputs(builder, witness, constraint_system); + build_constraints(builder, constraint_system, true); } +/** + * @brief Apply an offset to the indices stored in the wires + * @details This method is needed due to the following: Noir constructs "wires" as indices into a "witness" vector. This + * is analogous to the wires and variables vectors in bberg builders. Were it not for the addition of constant variables + * in the constructors of a builder (e.g. zero), we would simply have noir.wires = builder.wires and noir.witness = + * builder.variables. To account for k-many constant variables in the first entries of the variables array, we have + * something like variables = variables.append(noir.witness). Accordingly, the indices in noir.wires have to be + * incremented to account for the offset at which noir.wires was placed into variables. + * + * @tparam Builder + * @param builder + */ +template void apply_wire_index_offset(Builder& builder) +{ + // For now, noir has a hard coded witness index offset = 1. Once this is removed, this pre-applied offset goes away + const uint32_t pre_applied_noir_offset = 1; + auto offset = static_cast(builder.num_vars_added_in_constructor - pre_applied_noir_offset); + info("Applying offset = ", offset); + + // Apply the offset to the indices stored the wires that were generated from acir. (Do not apply the offset to those + // values that were added in the builder constructor). + size_t start_index = builder.num_vars_added_in_constructor; + for (auto& wire : builder.wires) { + for (size_t idx = start_index; idx < wire.size(); ++idx) { + wire[idx] += offset; + } + } +} + +template UltraCircuitBuilder create_circuit(const acir_format& constraint_system, + size_t size_hint); +template void create_circuit_with_witness(UltraCircuitBuilder& builder, + acir_format const& constraint_system, + WitnessVector const& witness); +template void create_circuit_with_witness(GoblinUltraCircuitBuilder& builder, + acir_format const& constraint_system, + WitnessVector const& witness); +template void apply_wire_index_offset(GoblinUltraCircuitBuilder& builder); +template void apply_wire_index_offset(UltraCircuitBuilder& builder); + } // namespace acir_format diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_format.hpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_format.hpp index 15f2ecbcdd8..c9c373ac339 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_format.hpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_format.hpp @@ -38,6 +38,7 @@ struct acir_format { std::vector hash_to_field_constraints; std::vector fixed_base_scalar_mul_constraints; std::vector recursion_constraints; + // A standard plonk arithmetic constraint, as defined in the poly_triple struct, consists of selector values // for q_M,q_L,q_R,q_O,q_C and indices of three variables taking the role of left, right and output wire // This could be a large vector so use slab allocator, we don't expect the blackbox implementations to be so large. @@ -71,16 +72,20 @@ struct acir_format { using WitnessVector = std::vector>; -void read_witness(Builder& builder, std::vector const& witness); +template void read_witness(Builder& builder, std::vector const& witness); -void create_circuit(Builder& builder, const acir_format& constraint_system); +template void create_circuit(Builder& builder, const acir_format& constraint_system); +template Builder create_circuit(const acir_format& constraint_system, size_t size_hint = 0); Builder create_circuit_with_witness(const acir_format& constraint_system, WitnessVector const& witness, size_t size_hint = 0); +template void create_circuit_with_witness(Builder& builder, const acir_format& constraint_system, WitnessVector const& witness); +template void apply_wire_index_offset(Builder& builder); + } // namespace acir_format diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_to_constraint_buf.hpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_to_constraint_buf.hpp index 0c2f63a1817..aaf4833b998 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_to_constraint_buf.hpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_to_constraint_buf.hpp @@ -265,6 +265,8 @@ acir_format circuit_buf_to_acir_format(std::vector const& buf) auto circuit = Circuit::Circuit::bincodeDeserialize(buf); acir_format af; + // TODO(https://github.com/AztecProtocol/barretenberg/issues/816): this +1 seems to be accounting for the const 0 at + // the first index in variables af.varnum = circuit.current_witness_index + 1; af.public_inputs = join({ map(circuit.public_parameters.value, [](auto e) { return e.value; }), map(circuit.return_values.value, [](auto e) { return e.value; }) }); @@ -306,7 +308,7 @@ WitnessVector witness_buf_to_witness_data(std::vector const& buf) size_t index = 1; for (auto& e : w.value) { while (index < e.first.value) { - wv.push_back(barretenberg::fr(0)); + wv.push_back(barretenberg::fr(0)); // TODO(https://github.com/AztecProtocol/barretenberg/issues/816)? index++; } wv.push_back(barretenberg::fr(uint256_t(e.second))); diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/blake2s_constraint.cpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/blake2s_constraint.cpp index e5fc04696ad..f36730658e0 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/blake2s_constraint.cpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/blake2s_constraint.cpp @@ -3,8 +3,10 @@ namespace acir_format { -void create_blake2s_constraints(Builder& builder, const Blake2sConstraint& constraint) +template void create_blake2s_constraints(Builder& builder, const Blake2sConstraint& constraint) { + using byte_array_ct = proof_system::plonk::stdlib::byte_array; + using field_ct = proof_system::plonk::stdlib::field_t; // Create byte array struct byte_array_ct arr(&builder); @@ -34,4 +36,9 @@ void create_blake2s_constraints(Builder& builder, const Blake2sConstraint& const } } +template void create_blake2s_constraints(UltraCircuitBuilder& builder, + const Blake2sConstraint& constraint); +template void create_blake2s_constraints(GoblinUltraCircuitBuilder& builder, + const Blake2sConstraint& constraint); + } // namespace acir_format diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/blake2s_constraint.hpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/blake2s_constraint.hpp index aec0516b271..a4bf7983e47 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/blake2s_constraint.hpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/blake2s_constraint.hpp @@ -24,6 +24,6 @@ struct Blake2sConstraint { friend bool operator==(Blake2sConstraint const& lhs, Blake2sConstraint const& rhs) = default; }; -void create_blake2s_constraints(Builder& builder, const Blake2sConstraint& constraint); +template void create_blake2s_constraints(Builder& builder, const Blake2sConstraint& constraint); } // namespace acir_format diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/block_constraint.cpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/block_constraint.cpp index f655826386b..8bdb99fb39a 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/block_constraint.cpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/block_constraint.cpp @@ -5,8 +5,12 @@ using namespace proof_system::plonk; namespace acir_format { -field_ct poly_to_field_ct(const poly_triple poly, Builder& builder) + +template +proof_system::plonk::stdlib::field_t poly_to_field_ct(const poly_triple poly, Builder& builder) { + using field_ct = proof_system::plonk::stdlib::field_t; + ASSERT(poly.q_m == 0); ASSERT(poly.q_r == 0); ASSERT(poly.q_o == 0); @@ -19,8 +23,13 @@ field_ct poly_to_field_ct(const poly_triple poly, Builder& builder) return x; } +template void create_block_constraints(Builder& builder, const BlockConstraint constraint, bool has_valid_witness_assignments) { + using field_ct = proof_system::plonk::stdlib::field_t; + using rom_table_ct = proof_system::plonk::stdlib::rom_table; + using ram_table_ct = proof_system::plonk::stdlib::ram_table; + std::vector init; for (auto i : constraint.init) { field_ct value = poly_to_field_ct(i, builder); @@ -75,4 +84,11 @@ void create_block_constraints(Builder& builder, const BlockConstraint constraint } } +template void create_block_constraints(UltraCircuitBuilder& builder, + const BlockConstraint constraint, + bool has_valid_witness_assignments); +template void create_block_constraints(GoblinUltraCircuitBuilder& builder, + const BlockConstraint constraint, + bool has_valid_witness_assignments); + } // namespace acir_format \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/block_constraint.hpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/block_constraint.hpp index 511ee83e1c6..f54eedc2234 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/block_constraint.hpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/block_constraint.hpp @@ -23,6 +23,7 @@ struct BlockConstraint { BlockType type; }; +template void create_block_constraints(Builder& builder, const BlockConstraint constraint, bool has_valid_witness_assignments = true); diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/ecdsa_secp256k1.cpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/ecdsa_secp256k1.cpp index 6cebc71c543..f629482d363 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/ecdsa_secp256k1.cpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/ecdsa_secp256k1.cpp @@ -5,6 +5,7 @@ namespace acir_format { using namespace proof_system::plonk; +template crypto::ecdsa::signature ecdsa_convert_signature(Builder& builder, std::vector signature) { @@ -42,6 +43,7 @@ crypto::ecdsa::signature ecdsa_convert_signature(Builder& builder, std::vector secp256k1_ct::g1_ct ecdsa_convert_inputs(Builder* ctx, const secp256k1::g1::affine_element& input) { uint256_t x_u256(input.x); @@ -61,8 +63,13 @@ secp256k1_ct::g1_ct ecdsa_convert_inputs(Builder* ctx, const secp256k1::g1::affi // vector of bytes here, assumes that the witness indices point to a field element which can be represented // with just a byte. // notice that this function truncates each field_element to a byte -byte_array_ct ecdsa_vector_of_bytes_to_byte_array(Builder& builder, std::vector vector_of_bytes) +template +proof_system::plonk::stdlib::byte_array ecdsa_vector_of_bytes_to_byte_array( + Builder& builder, std::vector vector_of_bytes) { + using byte_array_ct = proof_system::plonk::stdlib::byte_array; + using field_ct = proof_system::plonk::stdlib::field_t; + byte_array_ct arr(&builder); // Get the witness assignment for each witness index @@ -83,10 +90,15 @@ witness_ct ecdsa_index_to_witness(Builder& builder, uint32_t index) return { &builder, value }; } +template void create_ecdsa_k1_verify_constraints(Builder& builder, const EcdsaSecp256k1Constraint& input, bool has_valid_witness_assignments) { + using secp256k1_ct = proof_system::plonk::stdlib::secp256k1; + using field_ct = proof_system::plonk::stdlib::field_t; + using bool_ct = proof_system::plonk::stdlib::bool_t; + using byte_array_ct = proof_system::plonk::stdlib::byte_array; if (has_valid_witness_assignments == false) { dummy_ecdsa_constraint(builder, input); @@ -94,12 +106,12 @@ void create_ecdsa_k1_verify_constraints(Builder& builder, auto new_sig = ecdsa_convert_signature(builder, input.signature); - auto message = ecdsa_vector_of_bytes_to_byte_array(builder, input.hashed_message); + byte_array_ct message = ecdsa_vector_of_bytes_to_byte_array(builder, input.hashed_message); auto pub_key_x_byte_arr = ecdsa_vector_of_bytes_to_byte_array(builder, input.pub_x_indices); auto pub_key_y_byte_arr = ecdsa_vector_of_bytes_to_byte_array(builder, input.pub_y_indices); - auto pub_key_x_fq = secp256k1_ct::fq_ct(pub_key_x_byte_arr); - auto pub_key_y_fq = secp256k1_ct::fq_ct(pub_key_y_byte_arr); + auto pub_key_x_fq = typename secp256k1_ct::fq_ct(pub_key_x_byte_arr); + auto pub_key_y_fq = typename secp256k1_ct::fq_ct(pub_key_y_byte_arr); std::vector rr(new_sig.r.begin(), new_sig.r.end()); std::vector ss(new_sig.s.begin(), new_sig.s.end()); @@ -111,7 +123,7 @@ void create_ecdsa_k1_verify_constraints(Builder& builder, pub_key_x_fq.assert_is_in_field(); pub_key_y_fq.assert_is_in_field(); - secp256k1_ct::g1_bigfr_ct public_key = secp256k1_ct::g1_bigfr_ct(pub_key_x_fq, pub_key_y_fq); + typename secp256k1_ct::g1_bigfr_ct public_key = typename secp256k1_ct::g1_bigfr_ct(pub_key_x_fq, pub_key_y_fq); for (size_t i = 0; i < 32; ++i) { sig.r[i].assert_equal(field_ct::from_witness_index(&builder, input.signature[i])); sig.s[i].assert_equal(field_ct::from_witness_index(&builder, input.signature[i + 32])); @@ -125,9 +137,10 @@ void create_ecdsa_k1_verify_constraints(Builder& builder, bool_ct signature_result = stdlib::ecdsa::verify_signature_prehashed_message_noassert(message, public_key, sig); + typename secp256k1_ct::fq_ct, + typename secp256k1_ct::bigfr_ct, + typename secp256k1_ct::g1_bigfr_ct>( + message, public_key, sig); bool_ct signature_result_normalized = signature_result.normalize(); builder.assert_equal(signature_result_normalized.witness_index, input.result); } @@ -137,7 +150,7 @@ void create_ecdsa_k1_verify_constraints(Builder& builder, // // This does not work for ECDSA as the signature, r, s and public key need // to be valid. -void dummy_ecdsa_constraint(Builder& builder, EcdsaSecp256k1Constraint const& input) +template void dummy_ecdsa_constraint(Builder& builder, EcdsaSecp256k1Constraint const& input) { std::vector pub_x_indices_; @@ -188,4 +201,13 @@ void dummy_ecdsa_constraint(Builder& builder, EcdsaSecp256k1Constraint const& in } } +template void create_ecdsa_k1_verify_constraints(UltraCircuitBuilder& builder, + const EcdsaSecp256k1Constraint& input, + bool has_valid_witness_assignments); +template void create_ecdsa_k1_verify_constraints(GoblinUltraCircuitBuilder& builder, + const EcdsaSecp256k1Constraint& input, + bool has_valid_witness_assignments); +template void dummy_ecdsa_constraint(UltraCircuitBuilder& builder, + EcdsaSecp256k1Constraint const& input); + } // namespace acir_format diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/ecdsa_secp256k1.hpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/ecdsa_secp256k1.hpp index aaab033f884..287e9cccda1 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/ecdsa_secp256k1.hpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/ecdsa_secp256k1.hpp @@ -30,14 +30,18 @@ struct EcdsaSecp256k1Constraint { friend bool operator==(EcdsaSecp256k1Constraint const& lhs, EcdsaSecp256k1Constraint const& rhs) = default; }; +template void create_ecdsa_k1_verify_constraints(Builder& builder, const EcdsaSecp256k1Constraint& input, bool has_valid_witness_assignments = true); -void dummy_ecdsa_constraint(Builder& builder, EcdsaSecp256k1Constraint const& input); +template void dummy_ecdsa_constraint(Builder& builder, EcdsaSecp256k1Constraint const& input); +template crypto::ecdsa::signature ecdsa_convert_signature(Builder& builder, std::vector signature); witness_ct ecdsa_index_to_witness(Builder& builder, uint32_t index); -byte_array_ct ecdsa_vector_of_bytes_to_byte_array(Builder& builder, std::vector vector_of_bytes); +template +proof_system::plonk::stdlib::byte_array ecdsa_vector_of_bytes_to_byte_array( + Builder& builder, std::vector vector_of_bytes); } // namespace acir_format diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/ecdsa_secp256r1.cpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/ecdsa_secp256r1.cpp index 7d1feeecbfd..7cf9742b132 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/ecdsa_secp256r1.cpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/ecdsa_secp256r1.cpp @@ -23,10 +23,14 @@ secp256r1_ct::g1_ct ecdsa_convert_inputs(Builder* ctx, const secp256r1::g1::affi return { x, y }; } +template void create_ecdsa_r1_verify_constraints(Builder& builder, const EcdsaSecp256r1Constraint& input, bool has_valid_witness_assignments) { + using secp256r1_ct = proof_system::plonk::stdlib::secp256r1; + using bool_ct = proof_system::plonk::stdlib::bool_t; + using field_ct = proof_system::plonk::stdlib::field_t; if (has_valid_witness_assignments == false) { dummy_ecdsa_constraint(builder, input); @@ -38,8 +42,8 @@ void create_ecdsa_r1_verify_constraints(Builder& builder, auto pub_key_x_byte_arr = ecdsa_vector_of_bytes_to_byte_array(builder, input.pub_x_indices); auto pub_key_y_byte_arr = ecdsa_vector_of_bytes_to_byte_array(builder, input.pub_y_indices); - auto pub_key_x_fq = secp256r1_ct::fq_ct(pub_key_x_byte_arr); - auto pub_key_y_fq = secp256r1_ct::fq_ct(pub_key_y_byte_arr); + auto pub_key_x_fq = typename secp256r1_ct::fq_ct(pub_key_x_byte_arr); + auto pub_key_y_fq = typename secp256r1_ct::fq_ct(pub_key_y_byte_arr); std::vector rr(new_sig.r.begin(), new_sig.r.end()); std::vector ss(new_sig.s.begin(), new_sig.s.end()); @@ -51,7 +55,7 @@ void create_ecdsa_r1_verify_constraints(Builder& builder, pub_key_x_fq.assert_is_in_field(); pub_key_y_fq.assert_is_in_field(); - secp256r1_ct::g1_bigfr_ct public_key = secp256r1_ct::g1_bigfr_ct(pub_key_x_fq, pub_key_y_fq); + typename secp256r1_ct::g1_bigfr_ct public_key = typename secp256r1_ct::g1_bigfr_ct(pub_key_x_fq, pub_key_y_fq); for (size_t i = 0; i < 32; ++i) { sig.r[i].assert_equal(field_ct::from_witness_index(&builder, input.signature[i])); sig.s[i].assert_equal(field_ct::from_witness_index(&builder, input.signature[i + 32])); @@ -65,9 +69,10 @@ void create_ecdsa_r1_verify_constraints(Builder& builder, bool_ct signature_result = stdlib::ecdsa::verify_signature_prehashed_message_noassert(message, public_key, sig); + typename secp256r1_ct::fq_ct, + typename secp256r1_ct::bigfr_ct, + typename secp256r1_ct::g1_bigfr_ct>( + message, public_key, sig); bool_ct signature_result_normalized = signature_result.normalize(); builder.assert_equal(signature_result_normalized.witness_index, input.result); } @@ -77,7 +82,7 @@ void create_ecdsa_r1_verify_constraints(Builder& builder, // // This does not work for ECDSA as the signature, r, s and public key need // to be valid. -void dummy_ecdsa_constraint(Builder& builder, EcdsaSecp256r1Constraint const& input) +template void dummy_ecdsa_constraint(Builder& builder, EcdsaSecp256r1Constraint const& input) { std::vector pub_x_indices_; @@ -137,4 +142,13 @@ void dummy_ecdsa_constraint(Builder& builder, EcdsaSecp256r1Constraint const& in } } +template void create_ecdsa_r1_verify_constraints(UltraCircuitBuilder& builder, + const EcdsaSecp256r1Constraint& input, + bool has_valid_witness_assignments); +template void create_ecdsa_r1_verify_constraints(GoblinUltraCircuitBuilder& builder, + const EcdsaSecp256r1Constraint& input, + bool has_valid_witness_assignments); +template void dummy_ecdsa_constraint(UltraCircuitBuilder& builder, + EcdsaSecp256r1Constraint const& input); + } // namespace acir_format diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/ecdsa_secp256r1.hpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/ecdsa_secp256r1.hpp index a47cab2ea46..1f5972ba609 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/ecdsa_secp256r1.hpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/ecdsa_secp256r1.hpp @@ -26,11 +26,12 @@ struct EcdsaSecp256r1Constraint { friend bool operator==(EcdsaSecp256r1Constraint const& lhs, EcdsaSecp256r1Constraint const& rhs) = default; }; +template void create_ecdsa_r1_verify_constraints(Builder& builder, const EcdsaSecp256r1Constraint& input, bool has_valid_witness_assignments = true); -void dummy_ecdsa_constraint(Builder& builder, EcdsaSecp256r1Constraint const& input); +template void dummy_ecdsa_constraint(Builder& builder, EcdsaSecp256r1Constraint const& input); template inline void read(B& buf, EcdsaSecp256r1Constraint& constraint) { diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/fixed_base_scalar_mul.cpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/fixed_base_scalar_mul.cpp index 3ac6e1ef336..71e281e99b6 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/fixed_base_scalar_mul.cpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/fixed_base_scalar_mul.cpp @@ -6,8 +6,11 @@ namespace acir_format { -void create_fixed_base_constraint(Builder& builder, const FixedBaseScalarMul& input) +template void create_fixed_base_constraint(Builder& builder, const FixedBaseScalarMul& input) { + using cycle_group_ct = proof_system::plonk::stdlib::cycle_group; + using cycle_scalar_ct = typename proof_system::plonk::stdlib::cycle_group::cycle_scalar; + using field_ct = proof_system::plonk::stdlib::field_t; // Computes low * G + high * 2^128 * G // @@ -26,4 +29,9 @@ void create_fixed_base_constraint(Builder& builder, const FixedBaseScalarMul& in builder.assert_equal(result.y.get_witness_index(), input.pub_key_y); } +template void create_fixed_base_constraint(UltraCircuitBuilder& builder, + const FixedBaseScalarMul& input); +template void create_fixed_base_constraint(GoblinUltraCircuitBuilder& builder, + const FixedBaseScalarMul& input); + } // namespace acir_format diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/fixed_base_scalar_mul.hpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/fixed_base_scalar_mul.hpp index fe4917a8d2a..ef7d634870b 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/fixed_base_scalar_mul.hpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/fixed_base_scalar_mul.hpp @@ -16,6 +16,6 @@ struct FixedBaseScalarMul { friend bool operator==(FixedBaseScalarMul const& lhs, FixedBaseScalarMul const& rhs) = default; }; -void create_fixed_base_constraint(Builder& builder, const FixedBaseScalarMul& input); +template void create_fixed_base_constraint(Builder& builder, const FixedBaseScalarMul& input); } // namespace acir_format diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/hash_to_field.cpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/hash_to_field.cpp index ec29a2cec6c..b2315247e3e 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/hash_to_field.cpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/hash_to_field.cpp @@ -5,8 +5,11 @@ namespace acir_format { using namespace proof_system::plonk; +template void create_hash_to_field_constraints(Builder& builder, const HashToFieldConstraint constraint) { + using byte_array_ct = proof_system::plonk::stdlib::byte_array; + using field_ct = proof_system::plonk::stdlib::field_t; // Create byte array struct byte_array_ct arr(&builder); @@ -38,4 +41,9 @@ void create_hash_to_field_constraints(Builder& builder, const HashToFieldConstra builder.assert_equal(normalised_out.witness_index, constraint.result); } +template void create_hash_to_field_constraints(UltraCircuitBuilder& builder, + const HashToFieldConstraint constraint); +template void create_hash_to_field_constraints(GoblinUltraCircuitBuilder& builder, + const HashToFieldConstraint constraint); + } // namespace acir_format diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/hash_to_field.hpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/hash_to_field.hpp index 605326e4ddc..212232cc868 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/hash_to_field.hpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/hash_to_field.hpp @@ -24,6 +24,6 @@ struct HashToFieldConstraint { friend bool operator==(HashToFieldConstraint const& lhs, HashToFieldConstraint const& rhs) = default; }; -void create_hash_to_field_constraints(Builder& builder, HashToFieldConstraint constraint); +template void create_hash_to_field_constraints(Builder& builder, HashToFieldConstraint constraint); } // namespace acir_format diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/keccak_constraint.cpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/keccak_constraint.cpp index 748c3e927e1..46745de023c 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/keccak_constraint.cpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/keccak_constraint.cpp @@ -4,8 +4,10 @@ namespace acir_format { -void create_keccak_constraints(Builder& builder, const KeccakConstraint& constraint) +template void create_keccak_constraints(Builder& builder, const KeccakConstraint& constraint) { + using byte_array_ct = proof_system::plonk::stdlib::byte_array; + using field_ct = proof_system::plonk::stdlib::field_t; // Create byte array struct byte_array_ct arr(&builder); @@ -35,8 +37,11 @@ void create_keccak_constraints(Builder& builder, const KeccakConstraint& constra } } -void create_keccak_var_constraints(Builder& builder, const KeccakVarConstraint& constraint) +template void create_keccak_var_constraints(Builder& builder, const KeccakVarConstraint& constraint) { + using byte_array_ct = proof_system::plonk::stdlib::byte_array; + using field_ct = proof_system::plonk::stdlib::field_t; + using uint32_ct = proof_system::plonk::stdlib::uint32; // Create byte array struct byte_array_ct arr(&builder); @@ -68,4 +73,13 @@ void create_keccak_var_constraints(Builder& builder, const KeccakVarConstraint& } } +template void create_keccak_constraints(UltraCircuitBuilder& builder, + const KeccakConstraint& constraint); +template void create_keccak_var_constraints(UltraCircuitBuilder& builder, + const KeccakVarConstraint& constraint); +template void create_keccak_constraints(GoblinUltraCircuitBuilder& builder, + const KeccakConstraint& constraint); +template void create_keccak_var_constraints(GoblinUltraCircuitBuilder& builder, + const KeccakVarConstraint& constraint); + } // namespace acir_format diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/keccak_constraint.hpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/keccak_constraint.hpp index fa2af398678..25259e1e941 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/keccak_constraint.hpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/keccak_constraint.hpp @@ -34,7 +34,7 @@ struct KeccakVarConstraint { friend bool operator==(KeccakVarConstraint const& lhs, KeccakVarConstraint const& rhs) = default; }; -void create_keccak_constraints(Builder& builder, const KeccakConstraint& constraint); -void create_keccak_var_constraints(Builder& builder, const KeccakVarConstraint& constraint); +template void create_keccak_constraints(Builder& builder, const KeccakConstraint& constraint); +template void create_keccak_var_constraints(Builder& builder, const KeccakVarConstraint& constraint); } // namespace acir_format diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/logic_constraint.cpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/logic_constraint.cpp index 9b77101b89d..b9d501f354a 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/logic_constraint.cpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/logic_constraint.cpp @@ -5,6 +5,7 @@ namespace acir_format { using namespace proof_system::plonk; +template void create_logic_gate(Builder& builder, const uint32_t a, const uint32_t b, @@ -12,6 +13,7 @@ void create_logic_gate(Builder& builder, const size_t num_bits, const bool is_xor_gate) { + using field_ct = proof_system::plonk::stdlib::field_t; field_ct left = field_ct::from_witness_index(&builder, a); field_ct right = field_ct::from_witness_index(&builder, b); @@ -21,4 +23,17 @@ void create_logic_gate(Builder& builder, res.assert_equal(our_res); } +template void create_logic_gate(GoblinUltraCircuitBuilder& builder, + const uint32_t a, + const uint32_t b, + const uint32_t result, + const size_t num_bits, + const bool is_xor_gate); +template void create_logic_gate(UltraCircuitBuilder& builder, + const uint32_t a, + const uint32_t b, + const uint32_t result, + const size_t num_bits, + const bool is_xor_gate); + } // namespace acir_format diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/logic_constraint.hpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/logic_constraint.hpp index 37e3f30f175..acff8b4ada3 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/logic_constraint.hpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/logic_constraint.hpp @@ -18,6 +18,7 @@ struct LogicConstraint { MSGPACK_FIELDS(a, b, result, num_bits, is_xor_gate); }; +template void create_logic_gate(Builder& builder, uint32_t a, uint32_t b, uint32_t result, size_t num_bits, bool is_xor_gate); void xor_gate(Builder& builder, uint32_t a, uint32_t b, uint32_t result); diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/pedersen.cpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/pedersen.cpp index 73aad6b94de..a633420053c 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/pedersen.cpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/pedersen.cpp @@ -4,8 +4,10 @@ namespace acir_format { using namespace proof_system::plonk; -void create_pedersen_constraint(Builder& builder, const PedersenConstraint& input) +template void create_pedersen_constraint(Builder& builder, const PedersenConstraint& input) { + using field_ct = proof_system::plonk::stdlib::field_t; + std::vector scalars; for (const auto& scalar : input.scalars) { @@ -20,8 +22,10 @@ void create_pedersen_constraint(Builder& builder, const PedersenConstraint& inpu builder.assert_equal(point.y.witness_index, input.result_y); } -void create_pedersen_hash_constraint(Builder& builder, const PedersenHashConstraint& input) +template void create_pedersen_hash_constraint(Builder& builder, const PedersenHashConstraint& input) { + using field_ct = proof_system::plonk::stdlib::field_t; + std::vector scalars; for (const auto& scalar : input.scalars) { @@ -35,4 +39,13 @@ void create_pedersen_hash_constraint(Builder& builder, const PedersenHashConstra builder.assert_equal(result.witness_index, input.result); } +template void create_pedersen_constraint(UltraCircuitBuilder& builder, + const PedersenConstraint& input); +template void create_pedersen_hash_constraint(UltraCircuitBuilder& builder, + const PedersenHashConstraint& input); +template void create_pedersen_constraint(GoblinUltraCircuitBuilder& builder, + const PedersenConstraint& input); +template void create_pedersen_hash_constraint(GoblinUltraCircuitBuilder& builder, + const PedersenHashConstraint& input); + } // namespace acir_format diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/pedersen.hpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/pedersen.hpp index 9605c75472b..cddeb9ce5c3 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/pedersen.hpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/pedersen.hpp @@ -24,8 +24,8 @@ struct PedersenHashConstraint { friend bool operator==(PedersenHashConstraint const& lhs, PedersenHashConstraint const& rhs) = default; }; -void create_pedersen_constraint(Builder& builder, const PedersenConstraint& input); -void create_pedersen_hash_constraint(Builder& builder, const PedersenHashConstraint& input); +template void create_pedersen_constraint(Builder& builder, const PedersenConstraint& input); +template void create_pedersen_hash_constraint(Builder& builder, const PedersenHashConstraint& input); template inline void read(B& buf, PedersenConstraint& constraint) { diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/recursion_constraint.cpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/recursion_constraint.cpp index 0e69aab847e..4118c3307f5 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/recursion_constraint.cpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/recursion_constraint.cpp @@ -28,6 +28,7 @@ void generate_dummy_proof() {} * We would either need a separate ACIR opcode where inner_proof_contains_recursive_proof = true, * or we need non-witness data to be provided as metadata in the ACIR opcode */ +template void create_recursion_constraints(Builder& builder, const RecursionConstraint& input, bool has_valid_witness_assignments) @@ -349,4 +350,8 @@ G1AsFields export_g1_affine_element_as_fields(const barretenberg::g1::affine_ele return G1AsFields{ x_lo, x_hi, y_lo, y_hi }; } +template void create_recursion_constraints(UltraCircuitBuilder& builder, + const RecursionConstraint& input, + bool has_valid_witness_assignments); + } // namespace acir_format diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/recursion_constraint.hpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/recursion_constraint.hpp index 38a8fde5435..65574c68173 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/recursion_constraint.hpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/recursion_constraint.hpp @@ -60,6 +60,7 @@ struct RecursionConstraint { friend bool operator==(RecursionConstraint const& lhs, RecursionConstraint const& rhs) = default; }; +template void create_recursion_constraints(Builder& builder, const RecursionConstraint& input, bool has_valid_witness_assignments = false); diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/schnorr_verify.cpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/schnorr_verify.cpp index 92125b0dc61..5f31c2690ba 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/schnorr_verify.cpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/schnorr_verify.cpp @@ -6,6 +6,7 @@ namespace acir_format { using namespace proof_system::plonk::stdlib; +template crypto::schnorr::signature convert_signature(Builder& builder, std::vector signature) { @@ -43,8 +44,13 @@ crypto::schnorr::signature convert_signature(Builder& builder, std::vector vector_of_bytes) +template +proof_system::plonk::stdlib::byte_array vector_of_bytes_to_byte_array(Builder& builder, + std::vector vector_of_bytes) { + using byte_array_ct = proof_system::plonk::stdlib::byte_array; + using field_ct = proof_system::plonk::stdlib::field_t; + byte_array_ct arr(&builder); // Get the witness assignment for each witness index @@ -59,14 +65,20 @@ byte_array_ct vector_of_bytes_to_byte_array(Builder& builder, std::vector +proof_system::plonk::stdlib::witness_t index_to_witness(Builder& builder, uint32_t index) { fr value = builder.get_variable(index); return { &builder, value }; } -void create_schnorr_verify_constraints(Builder& builder, const SchnorrConstraint& input) +template void create_schnorr_verify_constraints(Builder& builder, const SchnorrConstraint& input) { + using witness_ct = proof_system::plonk::stdlib::witness_t; + using cycle_group_ct = proof_system::plonk::stdlib::cycle_group; + using schnorr_signature_bits_ct = proof_system::plonk::stdlib::schnorr::signature_bits; + using bool_ct = proof_system::plonk::stdlib::bool_t; auto new_sig = convert_signature(builder, input.signature); // From ignorance, you will see me convert a bunch of witnesses from ByteArray -> BitArray @@ -92,4 +104,9 @@ void create_schnorr_verify_constraints(Builder& builder, const SchnorrConstraint builder.assert_equal(signature_result_normalized.witness_index, input.result); } +template void create_schnorr_verify_constraints(UltraCircuitBuilder& builder, + const SchnorrConstraint& input); +template void create_schnorr_verify_constraints(GoblinUltraCircuitBuilder& builder, + const SchnorrConstraint& input); + } // namespace acir_format diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/schnorr_verify.hpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/schnorr_verify.hpp index ccbfca767a9..a22c2abb567 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/schnorr_verify.hpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/schnorr_verify.hpp @@ -25,7 +25,7 @@ struct SchnorrConstraint { friend bool operator==(SchnorrConstraint const& lhs, SchnorrConstraint const& rhs) = default; }; -void create_schnorr_verify_constraints(Builder& builder, const SchnorrConstraint& input); +template void create_schnorr_verify_constraints(Builder& builder, const SchnorrConstraint& input); template inline void read(B& buf, SchnorrConstraint& constraint) { diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/sha256_constraint.cpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/sha256_constraint.cpp index bc22dd87699..bfe814f3b58 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/sha256_constraint.cpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/sha256_constraint.cpp @@ -7,8 +7,10 @@ namespace acir_format { // This function does not work (properly) because the stdlib:sha256 function is not working correctly for 512 bits // pair -void create_sha256_constraints(Builder& builder, const Sha256Constraint& constraint) +template void create_sha256_constraints(Builder& builder, const Sha256Constraint& constraint) { + using byte_array_ct = proof_system::plonk::stdlib::byte_array; + using field_ct = proof_system::plonk::stdlib::field_t; // Create byte array struct byte_array_ct arr(&builder); @@ -39,4 +41,9 @@ void create_sha256_constraints(Builder& builder, const Sha256Constraint& constra } } +template void create_sha256_constraints(UltraCircuitBuilder& builder, + const Sha256Constraint& constraint); +template void create_sha256_constraints(GoblinUltraCircuitBuilder& builder, + const Sha256Constraint& constraint); + } // namespace acir_format diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/sha256_constraint.hpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/sha256_constraint.hpp index 3027a9e2cfc..d1e26a8aeb1 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/sha256_constraint.hpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/sha256_constraint.hpp @@ -26,5 +26,5 @@ struct Sha256Constraint { // This function does not work (properly) because the stdlib:sha256 function is not working correctly for 512 bits // pair -void create_sha256_constraints(Builder& builder, const Sha256Constraint& constraint); +template void create_sha256_constraints(Builder& builder, const Sha256Constraint& constraint); } // namespace acir_format diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_proofs/acir_composer.cpp b/barretenberg/cpp/src/barretenberg/dsl/acir_proofs/acir_composer.cpp index 0dc4a117735..e9b2753ca5f 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_proofs/acir_composer.cpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_proofs/acir_composer.cpp @@ -17,13 +17,15 @@ AcirComposer::AcirComposer(size_t size_hint, bool verbose) , verbose_(verbose) {} -void AcirComposer::create_circuit(acir_format::acir_format& constraint_system) +template void AcirComposer::create_circuit(acir_format::acir_format& constraint_system) { + // this seems to have made sense for plonk but no longer makes sense for Honk? if we return early then the + // sizes below never get set and that eventually causes too few srs points to be extracted if (builder_.get_num_gates() > 1) { return; } vinfo("building circuit..."); - builder_ = acir_format::create_circuit(constraint_system, size_hint_); + builder_ = acir_format::create_circuit(constraint_system, size_hint_); exact_circuit_size_ = builder_.get_num_gates(); total_circuit_size_ = builder_.get_total_circuit_size(); circuit_subgroup_size_ = builder_.get_circuit_subgroup_size(total_circuit_size_); @@ -75,6 +77,28 @@ std::vector AcirComposer::create_proof(acir_format::acir_format& constr return proof; } +void AcirComposer::create_goblin_circuit(acir_format::acir_format& constraint_system, + acir_format::WitnessVector& witness) +{ + // Provide the builder with the op queue owned by the goblin instance + goblin_builder_.op_queue = goblin.op_queue; + + create_circuit_with_witness(goblin_builder_, constraint_system, witness); + + info("after create_circuit_with_witness: num_gates = ", goblin_builder_.num_gates); + + // Correct for the addition of const variables in the builder constructor + acir_format::apply_wire_index_offset(goblin_builder_); + + // Add some arbitrary op gates to ensure the associated polynomials are non-zero + GoblinTestingUtils::construct_goblin_ecc_op_circuit(goblin_builder_); +} + +std::vector AcirComposer::create_goblin_proof() +{ + return goblin.construct_proof(goblin_builder_); +} + std::shared_ptr AcirComposer::init_verification_key() { if (!proving_key_) { @@ -115,6 +139,11 @@ bool AcirComposer::verify_proof(std::vector const& proof, bool is_recur } } +bool AcirComposer::verify_goblin_proof(std::vector const& proof) +{ + return goblin.verify_proof({ proof }); +} + std::string AcirComposer::get_solidity_verifier() { std::ostringstream stream; diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_proofs/acir_composer.hpp b/barretenberg/cpp/src/barretenberg/dsl/acir_proofs/acir_composer.hpp index db78f067a22..4cdf9d92fdc 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_proofs/acir_composer.hpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_proofs/acir_composer.hpp @@ -1,18 +1,21 @@ #pragma once #include -#include -#include -#include -#include -#include +#include +#include namespace acir_proofs { +/** + * @brief A class responsible for marshalling construction of keys and prover and verifier instances used to prove + * satisfiability of circuits written in ACIR. + * @todo: This reflects the design of Plonk. Perhaps we should author new classes to better reflect the + * structure of the newer code since there's much more of that code now? + */ class AcirComposer { public: AcirComposer(size_t size_hint = 0, bool verbose = true); - void create_circuit(acir_format::acir_format& constraint_system); + template void create_circuit(acir_format::acir_format& constraint_system); std::shared_ptr init_proving_key(acir_format::acir_format& constraint_system); @@ -36,8 +39,15 @@ class AcirComposer { std::vector serialize_verification_key_into_fields(); + // Goblin specific methods + void create_goblin_circuit(acir_format::acir_format& constraint_system, acir_format::WitnessVector& witness); + std::vector create_goblin_proof(); + bool verify_goblin_proof(std::vector const& proof); + private: acir_format::Builder builder_; + acir_format::GoblinBuilder goblin_builder_; + Goblin goblin; size_t size_hint_; size_t exact_circuit_size_; size_t total_circuit_size_; diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_proofs/c_bind.cpp b/barretenberg/cpp/src/barretenberg/dsl/acir_proofs/c_bind.cpp index b92213f9724..7301f3d673e 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_proofs/c_bind.cpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_proofs/c_bind.cpp @@ -53,6 +53,20 @@ WASM_EXPORT void acir_create_proof(in_ptr acir_composer_ptr, *out = to_heap_buffer(proof_data); } +WASM_EXPORT void acir_create_goblin_proof(in_ptr acir_composer_ptr, + uint8_t const* acir_vec, + uint8_t const* witness_vec, + uint8_t** out) +{ + auto acir_composer = reinterpret_cast(*acir_composer_ptr); + auto constraint_system = acir_format::circuit_buf_to_acir_format(from_buffer>(acir_vec)); + auto witness = acir_format::witness_buf_to_witness_data(from_buffer>(witness_vec)); + + acir_composer->create_goblin_circuit(constraint_system, witness); + auto proof_data = acir_composer->create_goblin_proof(); + *out = to_heap_buffer(proof_data); +} + WASM_EXPORT void acir_load_verification_key(in_ptr acir_composer_ptr, uint8_t const* vk_buf) { auto acir_composer = reinterpret_cast(*acir_composer_ptr); @@ -83,6 +97,13 @@ WASM_EXPORT void acir_get_proving_key(in_ptr acir_composer_ptr, uint8_t const* a *out = to_heap_buffer(to_buffer(*pk)); } +WASM_EXPORT void acir_verify_goblin_proof(in_ptr acir_composer_ptr, uint8_t const* proof_buf, bool* result) +{ + auto acir_composer = reinterpret_cast(*acir_composer_ptr); + auto proof = from_buffer>(proof_buf); + *result = acir_composer->verify_goblin_proof(proof); +} + WASM_EXPORT void acir_verify_proof(in_ptr acir_composer_ptr, uint8_t const* proof_buf, bool const* is_recursive, diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_proofs/c_bind.hpp b/barretenberg/cpp/src/barretenberg/dsl/acir_proofs/c_bind.hpp index 5ffa298b2fc..ea1ec4766f8 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_proofs/c_bind.hpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_proofs/c_bind.hpp @@ -32,6 +32,11 @@ WASM_EXPORT void acir_create_proof(in_ptr acir_composer_ptr, bool const* is_recursive, uint8_t** out); +WASM_EXPORT void acir_create_goblin_proof(in_ptr acir_composer_ptr, + uint8_t const* constraint_system_buf, + uint8_t const* witness_buf, + uint8_t** out); + WASM_EXPORT void acir_load_verification_key(in_ptr acir_composer_ptr, uint8_t const* vk_buf); WASM_EXPORT void acir_init_verification_key(in_ptr acir_composer_ptr); @@ -45,6 +50,8 @@ WASM_EXPORT void acir_verify_proof(in_ptr acir_composer_ptr, bool const* is_recursive, bool* result); +WASM_EXPORT void acir_verify_goblin_proof(in_ptr acir_composer_ptr, uint8_t const* proof_buf, bool* result); + WASM_EXPORT void acir_get_solidity_verifier(in_ptr acir_composer_ptr, out_str_buf out); WASM_EXPORT void acir_serialize_proof_into_fields(in_ptr acir_composer_ptr, diff --git a/barretenberg/cpp/src/barretenberg/dsl/types.hpp b/barretenberg/cpp/src/barretenberg/dsl/types.hpp index 34ad0a27f37..56ecb208121 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/types.hpp +++ b/barretenberg/cpp/src/barretenberg/dsl/types.hpp @@ -1,6 +1,7 @@ #pragma once #include "barretenberg/plonk/composer/ultra_composer.hpp" +#include "barretenberg/goblin/goblin.hpp" #include "barretenberg/plonk/proof_system/prover/prover.hpp" #include "barretenberg/stdlib/commitment/pedersen/pedersen.hpp" #include "barretenberg/stdlib/encryption/schnorr/schnorr.hpp" @@ -25,6 +26,7 @@ namespace acir_format { using Builder = proof_system::UltraCircuitBuilder; +using GoblinBuilder = barretenberg::Goblin::Builder; using Composer = plonk::UltraComposer; using Prover = diff --git a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_verifier.cpp b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_verifier.cpp index 76058a9c800..5de5a4a0343 100644 --- a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_verifier.cpp @@ -199,7 +199,7 @@ template bool ECCVMVerifier_::verify_proof(const plonk if (commitment.y != 0) { batched_commitment_unshifted += commitment * rhos[commitment_idx]; } else { - info("point at infinity (unshifted)"); + info("ECCVM Verifier: point at infinity (unshifted)"); } ++commitment_idx; } @@ -210,7 +210,7 @@ template bool ECCVMVerifier_::verify_proof(const plonk if (commitment.y != 0) { batched_commitment_to_be_shifted += commitment * rhos[commitment_idx]; } else { - info("point at infinity (to be shifted)"); + info("ECCVM Verifier: point at infinity (to be shifted)"); } ++commitment_idx; } diff --git a/barretenberg/cpp/src/barretenberg/env/data_store.hpp b/barretenberg/cpp/src/barretenberg/env/data_store.hpp index 2ddb0d8e9f1..641c3644b37 100644 --- a/barretenberg/cpp/src/barretenberg/env/data_store.hpp +++ b/barretenberg/cpp/src/barretenberg/env/data_store.hpp @@ -1,11 +1,12 @@ // To be provided by the environment. // For a WASM build, this is provided by the JavaScript environment. // For a native build, this is provided in this module. +#include "barretenberg/common/wasm_export.hpp" #include #include // Takes a copy of buf and saves it associated with key. -extern "C" void set_data(char const* key, uint8_t const* buf, size_t length); +WASM_IMPORT("set_data") void set_data(char const* key, uint8_t const* buf, size_t length); // Copies bytes of data associated with key into out_buf. -extern "C" void get_data(char const* key, uint8_t* out_buf); +WASM_IMPORT("get_data") void get_data(char const* key, uint8_t* out_buf); diff --git a/barretenberg/cpp/src/barretenberg/env/hardware_concurrency.hpp b/barretenberg/cpp/src/barretenberg/env/hardware_concurrency.hpp index fe530989d67..44124b452a1 100644 --- a/barretenberg/cpp/src/barretenberg/env/hardware_concurrency.hpp +++ b/barretenberg/cpp/src/barretenberg/env/hardware_concurrency.hpp @@ -1,4 +1,5 @@ #pragma once +#include "barretenberg/common/wasm_export.hpp" #include -extern "C" uint32_t env_hardware_concurrency(); \ No newline at end of file +WASM_IMPORT("env_hardware_concurrency") uint32_t env_hardware_concurrency(); \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/env/logstr.hpp b/barretenberg/cpp/src/barretenberg/env/logstr.hpp index 2d75688ca2b..ebe54baefe9 100644 --- a/barretenberg/cpp/src/barretenberg/env/logstr.hpp +++ b/barretenberg/cpp/src/barretenberg/env/logstr.hpp @@ -1,4 +1,6 @@ // To be provided by the environment. // For a WASM build, this is provided by the JavaScript environment. // For a native build, this is provided in this module. -extern "C" void logstr(char const*); +#include "barretenberg/common/wasm_export.hpp" + +WASM_IMPORT("logstr") void logstr(char const*); diff --git a/barretenberg/cpp/src/barretenberg/goblin/goblin.cpp b/barretenberg/cpp/src/barretenberg/goblin/goblin.cpp new file mode 100644 index 00000000000..a21aaa2ca06 --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/goblin/goblin.cpp @@ -0,0 +1 @@ +// NB: This file is here so that goblin_objects will be created \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/goblin/goblin.hpp b/barretenberg/cpp/src/barretenberg/goblin/goblin.hpp index 3c2588288df..7e74349529e 100644 --- a/barretenberg/cpp/src/barretenberg/goblin/goblin.hpp +++ b/barretenberg/cpp/src/barretenberg/goblin/goblin.hpp @@ -1,9 +1,11 @@ #pragma once #include "barretenberg/eccvm/eccvm_composer.hpp" +#include "barretenberg/goblin/mock_circuits.hpp" #include "barretenberg/proof_system/circuit_builder/eccvm/eccvm_circuit_builder.hpp" #include "barretenberg/proof_system/circuit_builder/goblin_translator_circuit_builder.hpp" #include "barretenberg/proof_system/circuit_builder/goblin_ultra_circuit_builder.hpp" +#include "barretenberg/proof_system/instance_inspector.hpp" #include "barretenberg/stdlib/recursion/honk/verifier/merge_recursive_verifier.hpp" #include "barretenberg/translator_vm/goblin_translator_composer.hpp" #include "barretenberg/ultra_honk/ultra_composer.hpp" @@ -13,15 +15,21 @@ namespace barretenberg { class Goblin { using HonkProof = proof_system::plonk::proof; + using GUHFlavor = proof_system::honk::flavor::GoblinUltra; + using GoblinUltraCircuitBuilder = proof_system::GoblinUltraCircuitBuilder; + + using GUHVerificationKey = GUHFlavor::VerificationKey; + using Commitment = GUHFlavor::Commitment; + using FF = GUHFlavor::FF; + public: /** * @brief Output of goblin::accumulate; an Ultra proof and the corresponding verification key * */ struct AccumulationOutput { - using NativeVerificationKey = proof_system::honk::flavor::GoblinUltra::VerificationKey; HonkProof proof; - std::shared_ptr verification_key; + std::shared_ptr verification_key; }; struct Proof { @@ -29,14 +37,28 @@ class Goblin { HonkProof eccvm_proof; HonkProof translator_proof; TranslationEvaluations translation_evaluations; - }; + std::vector to_buffer() + { + // ACIRHACK: so much copying and duplication added here and elsewhere + std::vector translation_evaluations_buf = translation_evaluations.to_buffer(); + size_t proof_size = merge_proof.proof_data.size() + eccvm_proof.proof_data.size() + + translator_proof.proof_data.size() + translation_evaluations_buf.size(); - using Fr = barretenberg::fr; - using Fq = barretenberg::fq; + std::vector result(proof_size); + const auto insert = [&result](const std::vector& buf) { + result.insert(result.end(), buf.begin(), buf.end()); + }; + insert(merge_proof.proof_data); + insert(eccvm_proof.proof_data); + insert(translator_proof.proof_data); + insert(translation_evaluations_buf); + return result; + } + }; - using Transcript = proof_system::honk::BaseTranscript; - using GoblinUltraComposer = proof_system::honk::GoblinUltraComposer; - using GoblinUltraCircuitBuilder = proof_system::GoblinUltraCircuitBuilder; + using GoblinUltraComposer = proof_system::honk::UltraComposer_; + using GoblinUltraVerifier = proof_system::honk::UltraVerifier_; + using Builder = GoblinUltraCircuitBuilder; using OpQueue = proof_system::ECCOpQueue; using ECCVMFlavor = proof_system::honk::flavor::ECCVM; using ECCVMBuilder = proof_system::ECCVMCircuitBuilder; @@ -45,7 +67,7 @@ class Goblin { using TranslatorComposer = proof_system::honk::GoblinTranslatorComposer; using RecursiveMergeVerifier = proof_system::plonk::stdlib::recursion::goblin::MergeRecursiveVerifier_; - using MergeVerifier = proof_system::honk::MergeVerifier_; + using MergeVerifier = proof_system::honk::MergeVerifier_; std::shared_ptr op_queue = std::make_shared(); @@ -61,9 +83,12 @@ class Goblin { std::unique_ptr eccvm_composer; std::unique_ptr translator_composer; + AccumulationOutput accumulator; // ACIRHACK + Proof proof_; // ACIRHACK + public: /** - * @brief + * @brief If there is a previous merge proof, recursively verify it. Generate next accmulated proof and merge proof. * * @param circuit_builder */ @@ -123,11 +148,124 @@ class Goblin { auto translator_verifier = translator_composer->create_verifier(*translator_builder, eccvm_verifier.transcript); bool accumulator_construction_verified = translator_verifier.verify_proof(proof.translator_proof); - // TODO(https://github.com/AztecProtocol/barretenberg/issues/799): - // Ensure translation_evaluations are passed correctly + // TODO(https://github.com/AztecProtocol/barretenberg/issues/799): Ensure translation_evaluations are passed + // correctly bool translation_verified = translator_verifier.verify_translation(proof.translation_evaluations); return merge_verified && eccvm_verified && accumulator_construction_verified && translation_verified; }; + + // ACIRHACK + AccumulationOutput accumulate_for_acir(GoblinUltraCircuitBuilder& circuit_builder) + { + // Complete the circuit logic by recursively verifying previous merge proof if it exists + if (merge_proof_exists) { + RecursiveMergeVerifier merge_verifier{ &circuit_builder }; + [[maybe_unused]] auto pairing_points = merge_verifier.verify_proof(merge_proof); + } + + // Construct a Honk proof for the main circuit + GoblinUltraComposer composer; + auto instance = composer.create_instance(circuit_builder); + auto prover = composer.create_prover(instance); + auto ultra_proof = prover.construct_proof(); + instance_inspector::inspect_instance(instance); + + // TODO(https://github.com/AztecProtocol/barretenberg/issues/811): no merge prover for now since we're not + // mocking the first set of ecc ops + // // Construct and store the merge proof to be recursively verified on the next call to accumulate + // info("create_merge_prover"); + // auto merge_prover = composer.create_merge_prover(op_queue); + // info("merge_prover.construct_proof()"); + // merge_proof = merge_prover.construct_proof(); + + // if (!merge_proof_exists) { + // merge_proof_exists = true; + // } + + accumulator = { ultra_proof, instance->verification_key }; + return accumulator; + }; + + // ACIRHACK + Proof prove_for_acir() + { + info("Goblin.prove(): op_queue size = ", op_queue->ultra_ops[0].size()); + Proof proof; + + proof.merge_proof = std::move(merge_proof); + + eccvm_builder = std::make_unique(op_queue); + eccvm_composer = std::make_unique(); + auto eccvm_prover = eccvm_composer->create_prover(*eccvm_builder); + proof.eccvm_proof = eccvm_prover.construct_proof(); + proof.translation_evaluations = eccvm_prover.translation_evaluations; + + translator_builder = std::make_unique( + eccvm_prover.translation_batching_challenge_v, eccvm_prover.evaluation_challenge_x, op_queue); + translator_composer = std::make_unique(); + auto translator_prover = translator_composer->create_prover(*translator_builder, eccvm_prover.transcript); + proof.translator_proof = translator_prover.construct_proof(); + + proof_ = proof; // ACIRHACK + return proof; + }; + + // ACIRHACK + bool verify_for_acir(const Proof& proof) const + { + // ACIRHACK + // MergeVerifier merge_verifier; + // info("constructed merge_verifier"); + // bool merge_verified = merge_verifier.verify_proof(proof.merge_proof); + // info("verified merge proof. result: ", merge_verified); + + auto eccvm_verifier = eccvm_composer->create_verifier(*eccvm_builder); + bool eccvm_verified = eccvm_verifier.verify_proof(proof.eccvm_proof); + + auto translator_verifier = translator_composer->create_verifier(*translator_builder, eccvm_verifier.transcript); + bool accumulator_construction_verified = translator_verifier.verify_proof(proof.translator_proof); + // TODO(https://github.com/AztecProtocol/barretenberg/issues/799): Ensure translation_evaluations are passed + // correctly + bool translation_verified = translator_verifier.verify_translation(proof.translation_evaluations); + + return /* merge_verified && */ eccvm_verified && accumulator_construction_verified && translation_verified; + }; + + // ACIRHACK + std::vector construct_proof(GoblinUltraCircuitBuilder& builder) + { + info("goblin: construct_proof"); + accumulate_for_acir(builder); + info("accumulate complete."); + std::vector goblin_proof = prove_for_acir().to_buffer(); + std::vector result(accumulator.proof.proof_data.size() + goblin_proof.size()); + + const auto insert = [&result](const std::vector& buf) { + result.insert(result.end(), buf.begin(), buf.end()); + }; + insert(accumulator.proof.proof_data); + insert(goblin_proof); + return result; + } + + // ACIRHACK + bool verify_proof([[maybe_unused]] const proof_system::plonk::proof& proof) const + { + // ACIRHACK: to do this properly, extract the proof correctly or maybe share transcripts. + const auto extract_final_kernel_proof = [&]([[maybe_unused]] auto& input_proof) { return accumulator.proof; }; + + GoblinUltraVerifier verifier{ accumulator.verification_key }; + info("constructed GUH verifier"); + bool verified = verifier.verify_proof(extract_final_kernel_proof(proof)); + info(" verified GUH proof; result: ", verified); + + const auto extract_goblin_proof = [&]([[maybe_unused]] auto& input_proof) { return proof_; }; + auto goblin_proof = extract_goblin_proof(proof); + info("extracted goblin proof"); + verified = verified && verify_for_acir(goblin_proof); + info("verified goblin proof"); + return verified; + } }; } // namespace barretenberg \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/goblin/mock_circuits.hpp b/barretenberg/cpp/src/barretenberg/goblin/mock_circuits.hpp index 5199a65ab63..545897eb09c 100644 --- a/barretenberg/cpp/src/barretenberg/goblin/mock_circuits.hpp +++ b/barretenberg/cpp/src/barretenberg/goblin/mock_circuits.hpp @@ -1,3 +1,5 @@ +#pragma once + #include "barretenberg/commitment_schemes/commitment_key.hpp" #include "barretenberg/flavor/goblin_ultra.hpp" #include "barretenberg/proof_system/circuit_builder/goblin_ultra_circuit_builder.hpp" @@ -33,6 +35,15 @@ class GoblinTestingUtils { } } + static void construct_goblin_ecc_op_circuit(GoblinUltraBuilder& builder) + { + // Add a mul accum op and an equality op + auto point = Point::one() * FF::random_element(); + auto scalar = FF::random_element(); + builder.queue_ecc_mul_accum(point, scalar); + builder.queue_ecc_eq(); + } + /** * @brief Mock the interactions of a simple curcuit with the op_queue * @todo The transcript aggregation protocol in the Goblin proof system can not yet support an empty "previous @@ -50,11 +61,8 @@ class GoblinTestingUtils { { proof_system::GoblinUltraCircuitBuilder builder{ op_queue }; - // Add a mul accum op and an equality op - auto point = Point::one() * FF::random_element(); - auto scalar = FF::random_element(); - builder.queue_ecc_mul_accum(point, scalar); - builder.queue_ecc_eq(); + // Add some goblinized ecc ops + construct_goblin_ecc_op_circuit(builder); op_queue->set_size_data(); diff --git a/barretenberg/cpp/src/barretenberg/goblin/translation_evaluations.hpp b/barretenberg/cpp/src/barretenberg/goblin/translation_evaluations.hpp index 4a0e6d5d835..5f5f70e2c75 100644 --- a/barretenberg/cpp/src/barretenberg/goblin/translation_evaluations.hpp +++ b/barretenberg/cpp/src/barretenberg/goblin/translation_evaluations.hpp @@ -4,5 +4,19 @@ namespace barretenberg { struct TranslationEvaluations { fq op, Px, Py, z1, z2; + std::vector to_buffer() + { + std::vector result(5 * sizeof(fq)); + const auto insert = [&result](const fq& elt) { + std::vector buf = elt.to_buffer(); + result.insert(result.end(), buf.begin(), buf.end()); + }; + insert(op); + insert(Px); + insert(Py); + insert(z1); + insert(z2); + return result; + } }; } // namespace barretenberg \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/polynomials/polynomial_arithmetic.hpp b/barretenberg/cpp/src/barretenberg/polynomials/polynomial_arithmetic.hpp index 8e4338ba251..6ebe2a2d474 100644 --- a/barretenberg/cpp/src/barretenberg/polynomials/polynomial_arithmetic.hpp +++ b/barretenberg/cpp/src/barretenberg/polynomials/polynomial_arithmetic.hpp @@ -360,107 +360,5 @@ template void factor_roots(std::span polynomial, std::span(const fr*, const fr&, const size_t); -extern template fr evaluate(const std::vector, const fr&, const size_t); -extern template void copy_polynomial(const fr*, fr*, size_t, size_t); -extern template void fft_inner_serial(std::vector, const size_t, const std::vector&); -extern template void fft_inner_parallel(std::vector, - const EvaluationDomain&, - const fr&, - const std::vector&); -extern template void fft(fr*, const EvaluationDomain&); -extern template void fft(fr*, fr*, const EvaluationDomain&); -extern template void fft(std::vector, const EvaluationDomain&); -extern template void fft_with_constant(fr*, const EvaluationDomain&, const fr&); -extern template void coset_fft(fr*, const EvaluationDomain&); -extern template void coset_fft(fr*, fr*, const EvaluationDomain&); -extern template void coset_fft(std::vector, const EvaluationDomain&); -extern template void coset_fft(fr*, const EvaluationDomain&, const EvaluationDomain&, const size_t); -extern template void coset_fft_with_constant(fr*, const EvaluationDomain&, const fr&); -extern template void coset_fft_with_generator_shift(fr*, const EvaluationDomain&, const fr&); -extern template void ifft(fr*, const EvaluationDomain&); -extern template void ifft(fr*, fr*, const EvaluationDomain&); -extern template void ifft(std::vector, const EvaluationDomain&); -extern template void ifft_with_constant(fr*, const EvaluationDomain&, const fr&); -extern template void coset_ifft(fr*, const EvaluationDomain&); -extern template void coset_ifft(std::vector, const EvaluationDomain&); -extern template void partial_fft_serial_inner(fr*, fr*, const EvaluationDomain&, const std::vector&); -extern template void partial_fft_parellel_inner( - fr*, const EvaluationDomain&, const std::vector&, fr, bool); -extern template void partial_fft_serial(fr*, fr*, const EvaluationDomain&); -extern template void partial_fft(fr*, const EvaluationDomain&, fr, bool); -extern template void add(const fr*, const fr*, fr*, const EvaluationDomain&); -extern template void sub(const fr*, const fr*, fr*, const EvaluationDomain&); -extern template void mul(const fr*, const fr*, fr*, const EvaluationDomain&); -extern template void compute_lagrange_polynomial_fft(fr*, const EvaluationDomain&, const EvaluationDomain&); -extern template void divide_by_pseudo_vanishing_polynomial(std::vector, - const EvaluationDomain&, - const EvaluationDomain&, - const size_t); -extern template fr compute_kate_opening_coefficients(const fr*, fr*, const fr&, const size_t); -extern template LagrangeEvaluations get_lagrange_evaluations(const fr&, - const EvaluationDomain&, - const size_t); -extern template fr compute_barycentric_evaluation(const fr*, const size_t, const fr&, const EvaluationDomain&); -extern template void compress_fft(const fr*, fr*, const size_t, const size_t); -extern template fr evaluate_from_fft(const fr*, - const EvaluationDomain&, - const fr&, - const EvaluationDomain&); -extern template fr compute_sum(const fr*, const size_t); -extern template void compute_linear_polynomial_product(const fr*, fr*, const size_t); -extern template fr compute_linear_polynomial_product_evaluation(const fr*, const fr, const size_t); -extern template void fft_linear_polynomial_product( - const fr* roots, fr*, const size_t n, const EvaluationDomain&, const bool); -extern template void compute_interpolation(const fr*, fr*, const fr*, const size_t); -extern template void compute_efficient_interpolation(const fr*, fr*, const fr*, const size_t); - -extern template grumpkin::fr evaluate(const grumpkin::fr*, const grumpkin::fr&, const size_t); -extern template grumpkin::fr evaluate(const std::vector, - const grumpkin::fr&, - const size_t); -extern template void copy_polynomial(const grumpkin::fr*, grumpkin::fr*, size_t, size_t); -extern template void add(const grumpkin::fr*, - const grumpkin::fr*, - grumpkin::fr*, - const EvaluationDomain&); -extern template void sub(const grumpkin::fr*, - const grumpkin::fr*, - grumpkin::fr*, - const EvaluationDomain&); -extern template void mul(const grumpkin::fr*, - const grumpkin::fr*, - grumpkin::fr*, - const EvaluationDomain&); -extern template grumpkin::fr compute_sum(const grumpkin::fr*, const size_t); -extern template void compute_linear_polynomial_product(const grumpkin::fr*, grumpkin::fr*, const size_t); -extern template grumpkin::fr compute_linear_polynomial_product_evaluation(const grumpkin::fr*, - const grumpkin::fr, - const size_t); -extern template void compute_interpolation(const grumpkin::fr*, - grumpkin::fr*, - const grumpkin::fr*, - const size_t); -extern template void compute_efficient_interpolation(const grumpkin::fr*, - grumpkin::fr*, - const grumpkin::fr*, - const size_t); - } // namespace polynomial_arithmetic } // namespace barretenberg diff --git a/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/goblin_ultra_circuit_builder.hpp b/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/goblin_ultra_circuit_builder.hpp index 8e5c6b14018..ed0e41d5ae9 100644 --- a/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/goblin_ultra_circuit_builder.hpp +++ b/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/goblin_ultra_circuit_builder.hpp @@ -20,6 +20,8 @@ template class GoblinUltraCircuitBuilder_ : public UltraCircuitBui static constexpr size_t DEFAULT_NON_NATIVE_FIELD_LIMB_BITS = UltraCircuitBuilder_>::DEFAULT_NON_NATIVE_FIELD_LIMB_BITS; + size_t num_vars_added_in_constructor = 0; // needed in constructing circuit from acir + size_t num_ecc_op_gates = 0; // number of ecc op "gates" (rows); these are placed at the start of the circuit // Stores record of ecc operations and performs corresponding native operations internally @@ -80,6 +82,7 @@ template class GoblinUltraCircuitBuilder_ : public UltraCircuitBui add_accum_op_idx = this->put_constant_variable(FF(EccOpCode::ADD_ACCUM)); mul_accum_op_idx = this->put_constant_variable(FF(EccOpCode::MUL_ACCUM)); equality_op_idx = this->put_constant_variable(FF(EccOpCode::EQUALITY)); + num_vars_added_in_constructor = this->variables.size(); }; GoblinUltraCircuitBuilder_(std::shared_ptr op_queue_in) : GoblinUltraCircuitBuilder_(0, op_queue_in) diff --git a/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/ultra_circuit_builder.hpp b/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/ultra_circuit_builder.hpp index 14c7f9cc2b9..86b13627e99 100644 --- a/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/ultra_circuit_builder.hpp +++ b/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/ultra_circuit_builder.hpp @@ -56,6 +56,8 @@ class UltraCircuitBuilder_ : public CircuitBuilderBasezero_idx = put_constant_variable(FF::zero()); this->tau.insert({ DUMMY_TAG, DUMMY_TAG }); // TODO(luke): explain this + num_vars_added_in_constructor = this->variables.size(); }; UltraCircuitBuilder_(const UltraCircuitBuilder_& other) = default; UltraCircuitBuilder_(UltraCircuitBuilder_&& other) diff --git a/barretenberg/cpp/src/barretenberg/proof_system/instance_inspector.hpp b/barretenberg/cpp/src/barretenberg/proof_system/instance_inspector.hpp new file mode 100644 index 00000000000..48216e97fbf --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/proof_system/instance_inspector.hpp @@ -0,0 +1,43 @@ +#pragma once + +#include "barretenberg/common/log.hpp" + +namespace instance_inspector { + +// Determine whether a polynomial has at least one non-zero coefficient +bool is_non_zero(auto& polynomial) +{ + for (auto& coeff : polynomial) { + if (!coeff.is_zero()) { + return true; + } + } + return false; +} + +/** + * @brief Utility for indicating which polynomials in a prover instance are identically zero + * + * @param prover_instance + */ +void inspect_instance(auto& prover_instance) +{ + auto& prover_polys = prover_instance->prover_polynomials; + std::vector zero_polys; + for (auto [label, poly] : zip_view(prover_polys.get_labels(), prover_polys.get_all())) { + if (!is_non_zero(poly)) { + zero_polys.emplace_back(label); + } + } + if (zero_polys.empty()) { + info("\nDebug Utility: All prover polynomials are non-zero."); + } else { + info("\nDebug Utility: The following prover polynomials are identically zero: "); + for (const std::string& label : zero_polys) { + info("\t", label); + } + } + info(); +} + +} // namespace instance_inspector \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/srs/c_bind.cpp b/barretenberg/cpp/src/barretenberg/srs/c_bind.cpp index fde3b61d3fc..ca42da6202a 100644 --- a/barretenberg/cpp/src/barretenberg/srs/c_bind.cpp +++ b/barretenberg/cpp/src/barretenberg/srs/c_bind.cpp @@ -21,4 +21,16 @@ WASM_EXPORT void srs_init_srs(uint8_t const* points_buf, uint32_t const* num_poi srs::IO::read_affine_elements_from_buffer(&g2_point, (char*)g2_point_buf, 128); barretenberg::srs::init_crs_factory(points, g2_point); +} + +/** + * WARNING: The SRS is not encoded the same way as all the read/write methods encode. + * Have to use the old school io functions to parse the buffers. + */ +WASM_EXPORT void srs_init_grumpkin_srs(uint8_t const* points_buf, uint32_t const* num_points) +{ + auto points = std::vector(ntohl(*num_points)); + srs::IO::read_affine_elements_from_buffer(points.data(), (char*)points_buf, points.size() * 64); + + barretenberg::srs::init_grumpkin_crs_factory(points); } \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/srs/c_bind.hpp b/barretenberg/cpp/src/barretenberg/srs/c_bind.hpp index fa496f1e295..cd33e478e05 100644 --- a/barretenberg/cpp/src/barretenberg/srs/c_bind.hpp +++ b/barretenberg/cpp/src/barretenberg/srs/c_bind.hpp @@ -1,4 +1,5 @@ #include #include -WASM_EXPORT void srs_init_srs(uint8_t const* points_buf, uint32_t const* num_points, uint8_t const* g2_point_buf); \ No newline at end of file +WASM_EXPORT void srs_init_srs(uint8_t const* points_buf, uint32_t const* num_points, uint8_t const* g2_point_buf); +WASM_EXPORT void srs_init_grumpkin_srs(uint8_t const* points_buf, uint32_t const* num_points); \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/srs/factories/mem_crs_factory.cpp b/barretenberg/cpp/src/barretenberg/srs/factories/mem_bn254_crs_factory.cpp similarity index 62% rename from barretenberg/cpp/src/barretenberg/srs/factories/mem_crs_factory.cpp rename to barretenberg/cpp/src/barretenberg/srs/factories/mem_bn254_crs_factory.cpp index 44315a8b7ca..a9161115af0 100644 --- a/barretenberg/cpp/src/barretenberg/srs/factories/mem_crs_factory.cpp +++ b/barretenberg/cpp/src/barretenberg/srs/factories/mem_bn254_crs_factory.cpp @@ -1,35 +1,16 @@ -#include "mem_crs_factory.hpp" +#include "mem_bn254_crs_factory.hpp" #include "barretenberg/ecc/curves/bn254/bn254.hpp" #include "barretenberg/ecc/curves/bn254/g1.hpp" #include "barretenberg/ecc/curves/bn254/pairing.hpp" #include "barretenberg/ecc/scalar_multiplication/point_table.hpp" #include "barretenberg/ecc/scalar_multiplication/scalar_multiplication.hpp" +#include "barretenberg/srs/factories/mem_prover_crs.hpp" namespace { using namespace barretenberg; using namespace barretenberg::srs::factories; -class MemProverCrs : public ProverCrs { - public: - MemProverCrs(std::vector const& points) - : num_points(points.size()) - { - monomials_ = scalar_multiplication::point_table_alloc(num_points); - std::copy(points.begin(), points.end(), monomials_.get()); - scalar_multiplication::generate_pippenger_point_table( - monomials_.get(), monomials_.get(), num_points); - } - - g1::affine_element* get_monomial_points() override { return monomials_.get(); } - - size_t get_monomial_size() const override { return num_points; } - - private: - size_t num_points; - std::shared_ptr monomials_; -}; - class MemVerifierCrs : public VerifierCrs { public: MemVerifierCrs(g2::affine_element const& g2_point) @@ -59,17 +40,18 @@ class MemVerifierCrs : public VerifierCrs { namespace barretenberg::srs::factories { -MemCrsFactory::MemCrsFactory(std::vector const& points, g2::affine_element const g2_point) - : prover_crs_(std::make_shared(points)) +MemBn254CrsFactory::MemBn254CrsFactory(std::vector const& points, + g2::affine_element const& g2_point) + : prover_crs_(std::make_shared>(points)) , verifier_crs_(std::make_shared(g2_point)) {} -std::shared_ptr> MemCrsFactory::get_prover_crs(size_t) +std::shared_ptr> MemBn254CrsFactory::get_prover_crs(size_t) { return prover_crs_; } -std::shared_ptr> MemCrsFactory::get_verifier_crs(size_t) +std::shared_ptr> MemBn254CrsFactory::get_verifier_crs(size_t) { return verifier_crs_; } diff --git a/barretenberg/cpp/src/barretenberg/srs/factories/mem_crs_factory.hpp b/barretenberg/cpp/src/barretenberg/srs/factories/mem_bn254_crs_factory.hpp similarity index 80% rename from barretenberg/cpp/src/barretenberg/srs/factories/mem_crs_factory.hpp rename to barretenberg/cpp/src/barretenberg/srs/factories/mem_bn254_crs_factory.hpp index a4e6b90db6d..9054a4a2812 100644 --- a/barretenberg/cpp/src/barretenberg/srs/factories/mem_crs_factory.hpp +++ b/barretenberg/cpp/src/barretenberg/srs/factories/mem_bn254_crs_factory.hpp @@ -13,10 +13,10 @@ namespace barretenberg::srs::factories { * * This class is currently only used with wasm and works exclusively with the BN254 CRS. */ -class MemCrsFactory : public CrsFactory { +class MemBn254CrsFactory : public CrsFactory { public: - MemCrsFactory(std::vector const& points, g2::affine_element const g2_point); - MemCrsFactory(MemCrsFactory&& other) = default; + MemBn254CrsFactory(std::vector const& points, g2::affine_element const& g2_point); + MemBn254CrsFactory(MemBn254CrsFactory&& other) = default; std::shared_ptr> get_prover_crs(size_t degree) override; diff --git a/barretenberg/cpp/src/barretenberg/srs/factories/mem_crs_factory.test.cpp b/barretenberg/cpp/src/barretenberg/srs/factories/mem_crs_factory.test.cpp index f933f15cd95..7477ebd63b9 100644 --- a/barretenberg/cpp/src/barretenberg/srs/factories/mem_crs_factory.test.cpp +++ b/barretenberg/cpp/src/barretenberg/srs/factories/mem_crs_factory.test.cpp @@ -1,30 +1,31 @@ -#include "mem_crs_factory.hpp" #include "../io.hpp" #include "barretenberg/ecc/curves/bn254/bn254.hpp" #include "barretenberg/ecc/curves/bn254/pairing.hpp" +#include "barretenberg/srs/factories/mem_bn254_crs_factory.hpp" +#include "barretenberg/srs/factories/mem_grumpkin_crs_factory.hpp" #include "file_crs_factory.hpp" #include #include using namespace barretenberg; using namespace barretenberg::srs::factories; +using namespace curve; -TEST(reference_string, mem_file_consistency) +TEST(reference_string, mem_bn254_file_consistency) { // Load 1024 from file. - auto file_crs = FileCrsFactory("../srs_db/ignition", 1024); + auto file_crs = FileCrsFactory("../srs_db/ignition", 1024); // Use low level io lib to read 1024 from file. std::vector points(1024); - ::srs::IO::read_transcript_g1(points.data(), 1024, "../srs_db/ignition"); + ::srs::IO::read_transcript_g1(points.data(), 1024, "../srs_db/ignition"); g2::affine_element g2_point; - ::srs::IO::read_transcript_g2(g2_point, "../srs_db/ignition"); + ::srs::IO::read_transcript_g2(g2_point, "../srs_db/ignition"); - MemCrsFactory mem_crs(points, g2_point); + MemBn254CrsFactory mem_crs(points, g2_point); auto file_prover_crs = file_crs.get_prover_crs(1024); auto mem_prover_crs = mem_crs.get_prover_crs(1024); - file_prover_crs->get_monomial_size(); EXPECT_EQ(mem_prover_crs->get_monomial_size(), file_prover_crs->get_monomial_size()); @@ -44,7 +45,32 @@ TEST(reference_string, mem_file_consistency) 0); } -TEST(reference_string, grumpkin) +TEST(reference_string, mem_grumpkin_file_consistency) { - auto file_crs = FileCrsFactory("../srs_db/grumpkin"); + // Load 1024 from file. + auto file_crs = FileCrsFactory("../srs_db/ignition", 1024); + + // Use low level io lib to read 1024 from file. + std::vector points(1024); + ::srs::IO::read_transcript_g1(points.data(), 1024, "../srs_db/ignition"); + + MemGrumpkinCrsFactory mem_crs(points); + auto file_prover_crs = file_crs.get_prover_crs(1024); + auto mem_prover_crs = mem_crs.get_prover_crs(1024); + + EXPECT_EQ(mem_prover_crs->get_monomial_size(), file_prover_crs->get_monomial_size()); + + EXPECT_EQ(memcmp(mem_prover_crs->get_monomial_points(), + file_prover_crs->get_monomial_points(), + sizeof(Grumpkin::AffineElement) * 1024 * 2), + 0); + + auto file_verifier_crs = file_crs.get_verifier_crs(); + auto mem_verifier_crs = file_crs.get_verifier_crs(); + + EXPECT_EQ(mem_verifier_crs->get_first_g1(), file_verifier_crs->get_first_g1()); + EXPECT_EQ(memcmp(file_verifier_crs->get_monomial_points(), + mem_verifier_crs->get_monomial_points(), + sizeof(Grumpkin::AffineElement) * 1024 * 2), + 0); } diff --git a/barretenberg/cpp/src/barretenberg/srs/factories/mem_grumpkin_crs_factory.cpp b/barretenberg/cpp/src/barretenberg/srs/factories/mem_grumpkin_crs_factory.cpp new file mode 100644 index 00000000000..253374e1d46 --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/srs/factories/mem_grumpkin_crs_factory.cpp @@ -0,0 +1,55 @@ +#include "mem_grumpkin_crs_factory.hpp" +#include "../io.hpp" +#include "barretenberg/ecc/curves/grumpkin/grumpkin.hpp" +#include "barretenberg/ecc/scalar_multiplication/point_table.hpp" +#include "barretenberg/ecc/scalar_multiplication/scalar_multiplication.hpp" +#include "barretenberg/srs/factories/mem_prover_crs.hpp" + +namespace { + +using namespace curve; +using namespace barretenberg; +using namespace barretenberg::srs::factories; + +using Curve = curve::Grumpkin; + +class MemVerifierCrs : public VerifierCrs { + public: + MemVerifierCrs(std::vector const& points) + : num_points(points.size()) + , monomials_(scalar_multiplication::point_table_alloc(points.size())) + { + std::copy(points.begin(), points.end(), monomials_.get()); + scalar_multiplication::generate_pippenger_point_table(monomials_.get(), monomials_.get(), num_points); + } + + virtual ~MemVerifierCrs() = default; + Grumpkin::AffineElement* get_monomial_points() const override { return monomials_.get(); } + size_t get_monomial_size() const override { return num_points; } + Grumpkin::AffineElement get_first_g1() const override { return monomials_[0]; }; + + private: + size_t num_points; + std::shared_ptr monomials_; +}; + +} // namespace + +namespace barretenberg::srs::factories { + +MemGrumpkinCrsFactory::MemGrumpkinCrsFactory(std::vector const& points) + : prover_crs_(std::make_shared>(points)) + , verifier_crs_(std::make_shared(points)) +{} + +std::shared_ptr> MemGrumpkinCrsFactory::get_prover_crs(size_t) +{ + return prover_crs_; +} + +std::shared_ptr> MemGrumpkinCrsFactory::get_verifier_crs(size_t) +{ + return verifier_crs_; +} + +} // namespace barretenberg::srs::factories \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/srs/factories/mem_grumpkin_crs_factory.hpp b/barretenberg/cpp/src/barretenberg/srs/factories/mem_grumpkin_crs_factory.hpp new file mode 100644 index 00000000000..f1fb942ef05 --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/srs/factories/mem_grumpkin_crs_factory.hpp @@ -0,0 +1,28 @@ +#pragma once +#include "crs_factory.hpp" +#include +#include + +namespace barretenberg::srs::factories { + +/** + * Create reference strings given pointers to in memory buffers. + * + * This class is currently only used with wasm and works exclusively with the Grumpkin CRS. + */ +class MemGrumpkinCrsFactory : public CrsFactory { + public: + MemGrumpkinCrsFactory(std::vector const& points); + MemGrumpkinCrsFactory(MemGrumpkinCrsFactory&& other) = default; + + std::shared_ptr> get_prover_crs(size_t degree) override; + + std::shared_ptr> get_verifier_crs( + size_t degree = 0) override; + + private: + std::shared_ptr> prover_crs_; + std::shared_ptr> verifier_crs_; +}; + +} // namespace barretenberg::srs::factories diff --git a/barretenberg/cpp/src/barretenberg/srs/factories/mem_prover_crs.hpp b/barretenberg/cpp/src/barretenberg/srs/factories/mem_prover_crs.hpp new file mode 100644 index 00000000000..b3a1bc79e56 --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/srs/factories/mem_prover_crs.hpp @@ -0,0 +1,28 @@ +#pragma once + +#include "barretenberg/ecc/scalar_multiplication/point_table.hpp" +#include "barretenberg/ecc/scalar_multiplication/scalar_multiplication.hpp" +#include "barretenberg/srs/factories/crs_factory.hpp" + +namespace barretenberg::srs::factories { +// Common to both Grumpkin and Bn254, and generally curves regardless of pairing-friendliness +template class MemProverCrs : public ProverCrs { + public: + MemProverCrs(std::vector const& points) + : num_points(points.size()) + , monomials_(scalar_multiplication::point_table_alloc(points.size())) + { + std::copy(points.begin(), points.end(), monomials_.get()); + scalar_multiplication::generate_pippenger_point_table(monomials_.get(), monomials_.get(), num_points); + } + + typename Curve::AffineElement* get_monomial_points() override { return monomials_.get(); } + + size_t get_monomial_size() const override { return num_points; } + + private: + size_t num_points; + std::shared_ptr monomials_; +}; + +} // namespace barretenberg::srs::factories \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/srs/global_crs.cpp b/barretenberg/cpp/src/barretenberg/srs/global_crs.cpp index db98a87597f..c156cae415e 100644 --- a/barretenberg/cpp/src/barretenberg/srs/global_crs.cpp +++ b/barretenberg/cpp/src/barretenberg/srs/global_crs.cpp @@ -1,7 +1,8 @@ #include "./global_crs.hpp" #include "./factories/file_crs_factory.hpp" -#include "./factories/mem_crs_factory.hpp" +#include "./factories/mem_bn254_crs_factory.hpp" #include "barretenberg/common/throw_or_abort.hpp" +#include "barretenberg/srs/factories/mem_grumpkin_crs_factory.hpp" namespace { // TODO(#637): As a PoC we have two global variables for the two CRS but this could be improved to avoid duplication. @@ -14,7 +15,7 @@ namespace barretenberg::srs { // Initializes the crs using the memory buffers void init_crs_factory(std::vector const& points, g2::affine_element const g2_point) { - crs_factory = std::make_shared(points, g2_point); + crs_factory = std::make_shared(points, g2_point); } // Initializes crs from a file path this we use in the entire codebase @@ -23,6 +24,12 @@ void init_crs_factory(std::string crs_path) crs_factory = std::make_shared>(crs_path); } +// Initializes the crs using the memory buffers +void init_grumpkin_crs_factory(std::vector const& points) +{ + grumpkin_crs_factory = std::make_shared(points); +} + void init_grumpkin_crs_factory(std::string crs_path) { grumpkin_crs_factory = std::make_shared>(crs_path); diff --git a/barretenberg/cpp/src/barretenberg/srs/global_crs.hpp b/barretenberg/cpp/src/barretenberg/srs/global_crs.hpp index 06ecd066d91..ef57171a449 100644 --- a/barretenberg/cpp/src/barretenberg/srs/global_crs.hpp +++ b/barretenberg/cpp/src/barretenberg/srs/global_crs.hpp @@ -3,12 +3,16 @@ #include "barretenberg/ecc/curves/grumpkin/grumpkin.hpp" namespace barretenberg::srs { -void init_crs_factory(std::vector const& points, - barretenberg::g2::affine_element const g2_point); +// Initializes the crs using files void init_crs_factory(std::string crs_path); void init_grumpkin_crs_factory(std::string crs_path); +// Initializes the crs using memory buffers +void init_grumpkin_crs_factory(std::vector const& points); +void init_crs_factory(std::vector const& points, + barretenberg::g2::affine_element const g2_point); + std::shared_ptr> get_crs_factory(); std::shared_ptr> get_grumpkin_crs_factory(); diff --git a/barretenberg/cpp/src/barretenberg/stdlib/primitives/biggroup/biggroup_impl.hpp b/barretenberg/cpp/src/barretenberg/stdlib/primitives/biggroup/biggroup_impl.hpp index 54374d047f3..a6503bf1285 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/primitives/biggroup/biggroup_impl.hpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/primitives/biggroup/biggroup_impl.hpp @@ -600,7 +600,8 @@ element element::batch_mul(const std::vector& scalars, const size_t max_num_bits) { - if constexpr (IsGoblinBuilder) { + // Perform goblinized batched mul if available; supported only for BN254 + if constexpr (IsGoblinBuilder && std::same_as) { return goblin_batch_mul(points, scalars); } diff --git a/barretenberg/cpp/src/barretenberg/stdlib/recursion/honk/verifier/merge_recursive_verifier.cpp b/barretenberg/cpp/src/barretenberg/stdlib/recursion/honk/verifier/merge_recursive_verifier.cpp index f04c32c9583..78444cd519e 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/recursion/honk/verifier/merge_recursive_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/recursion/honk/verifier/merge_recursive_verifier.cpp @@ -83,5 +83,6 @@ std::array::Element, 2> MergeRecursiveVerifier_; +template class MergeRecursiveVerifier_; } // namespace proof_system::plonk::stdlib::recursion::goblin diff --git a/barretenberg/cpp/src/barretenberg/stdlib/recursion/honk/verifier/merge_recursive_verifier.hpp b/barretenberg/cpp/src/barretenberg/stdlib/recursion/honk/verifier/merge_recursive_verifier.hpp index 341d91a1bd1..4c4c753d54d 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/recursion/honk/verifier/merge_recursive_verifier.hpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/recursion/honk/verifier/merge_recursive_verifier.hpp @@ -27,5 +27,6 @@ template class MergeRecursiveVerifier_ { }; extern template class MergeRecursiveVerifier_; +extern template class MergeRecursiveVerifier_; } // namespace proof_system::plonk::stdlib::recursion::goblin diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/ultra_composer.hpp b/barretenberg/cpp/src/barretenberg/ultra_honk/ultra_composer.hpp index 7daaab2e1d3..ee0e6a10825 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/ultra_composer.hpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/ultra_composer.hpp @@ -19,9 +19,11 @@ template class UltraComposer_ { using PCS = typename Flavor::PCS; using CommitmentKey = typename Flavor::CommitmentKey; using VerifierCommitmentKey = typename Flavor::VerifierCommitmentKey; - using Instance = ProverInstance_; + using ProverInstance = ProverInstance_; + using Instance = ProverInstance; using FF = typename Flavor::FF; using Transcript = typename Flavor::Transcript; + using CRSFactory = srs::factories::CrsFactory; static constexpr size_t NUM_FOLDING = 2; using ProverInstances = ProverInstances_; @@ -33,13 +35,13 @@ template class UltraComposer_ { static constexpr size_t NUM_WIRES = CircuitBuilder::NUM_WIRES; // The crs_factory holds the path to the srs and exposes methods to extract the srs elements - std::shared_ptr> crs_factory_; + std::shared_ptr crs_factory_; // The commitment key is passed to the prover but also used herein to compute the verfication key commitments std::shared_ptr commitment_key; UltraComposer_() { crs_factory_ = barretenberg::srs::get_crs_factory(); } - explicit UltraComposer_(std::shared_ptr> crs_factory) + explicit UltraComposer_(std::shared_ptr crs_factory) : crs_factory_(std::move(crs_factory)) {} @@ -51,7 +53,7 @@ template class UltraComposer_ { std::shared_ptr compute_commitment_key(size_t circuit_size) { - commitment_key = std::make_shared(circuit_size, crs_factory_); + commitment_key = std::make_shared(circuit_size + 1); return commitment_key; }; @@ -59,10 +61,15 @@ template class UltraComposer_ { UltraProver_ create_prover(const std::shared_ptr&, const std::shared_ptr& transcript = std::make_shared()); + UltraVerifier_ create_verifier( const std::shared_ptr&, const std::shared_ptr& transcript = std::make_shared()); + UltraVerifier_ create_verifier(CircuitBuilder& circuit); + + UltraVerifier_ create_ultra_with_keccak_verifier(CircuitBuilder& circuit); + /** * @brief Create Prover for Goblin ECC op queue merge protocol * @@ -106,7 +113,6 @@ template class UltraComposer_ { return output_state; }; - private: /** * @brief Compute the verification key of an Instance, produced from a finalised circuit. * @@ -114,6 +120,7 @@ template class UltraComposer_ { */ void compute_verification_key(const std::shared_ptr&); }; + extern template class UltraComposer_; extern template class UltraComposer_; // TODO(#532): this pattern is weird; is this not instantiating the templates? diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/ultra_prover.hpp b/barretenberg/cpp/src/barretenberg/ultra_honk/ultra_prover.hpp index dece05e520c..5817648097d 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/ultra_prover.hpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/ultra_prover.hpp @@ -14,7 +14,6 @@ template class UltraProver_ { using FF = typename Flavor::FF; using Commitment = typename Flavor::Commitment; using CommitmentKey = typename Flavor::CommitmentKey; - using ProvingKey = typename Flavor::ProvingKey; using Polynomial = typename Flavor::Polynomial; using ProverPolynomials = typename Flavor::ProverPolynomials; using CommitmentLabels = typename Flavor::CommitmentLabels; @@ -62,5 +61,6 @@ extern template class UltraProver_; extern template class UltraProver_; using UltraProver = UltraProver_; +using GoblinUltraProver = UltraProver_; } // namespace proof_system::honk diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/ultra_verifier.cpp b/barretenberg/cpp/src/barretenberg/ultra_honk/ultra_verifier.cpp index 2775b586c7e..21ca72be6d1 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/ultra_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/ultra_verifier.cpp @@ -138,6 +138,7 @@ template bool UltraVerifier_::verify_proof(const plonk // If Sumcheck did not verify, return false if (sumcheck_verified.has_value() && !sumcheck_verified.value()) { + info("UltraVerifier: Sumcheck failed."); return false; } diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/ultra_verifier.hpp b/barretenberg/cpp/src/barretenberg/ultra_honk/ultra_verifier.hpp index 8197e46a941..d5dc0dab1c4 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/ultra_verifier.hpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/ultra_verifier.hpp @@ -34,5 +34,6 @@ extern template class UltraVerifier_; extern template class UltraVerifier_; using UltraVerifier = UltraVerifier_; +using GoblinUltraVerifier = UltraVerifier_; } // namespace proof_system::honk diff --git a/barretenberg/cpp/srs_db/download_grumpkin.sh b/barretenberg/cpp/srs_db/download_grumpkin.sh new file mode 100755 index 00000000000..c2eefc6c56c --- /dev/null +++ b/barretenberg/cpp/srs_db/download_grumpkin.sh @@ -0,0 +1,11 @@ +#!/bin/sh +# TODO(https://github.com/AztecProtocol/barretenberg/issues/813) We don't *actually* download grumpkin yet. +# this just generates grumpkin points and puts in a place where run_acir_tests.sh expects it. +# The above issue tracks the final pieces here. +set -eu + +# Enter build directory sibling to our script folder. +cd $(dirname $0)/../build +./bin/grumpkin_srs_gen 1048576 +mkdir -p ~/.bb-crs +ln -s ../srs_db/grumpkin/monomial ~/.bb-crs/monomial \ No newline at end of file diff --git a/barretenberg/cpp/srs_db/download_ignition.sh b/barretenberg/cpp/srs_db/download_ignition.sh index 87c86a8f88b..4b0df0ee9fc 100755 --- a/barretenberg/cpp/srs_db/download_ignition.sh +++ b/barretenberg/cpp/srs_db/download_ignition.sh @@ -15,6 +15,9 @@ # whatever is requested but does not check the validity of the downloads. set -eu +# Enter script directory. +cd $(dirname $0) + mkdir -p ignition cd ignition mkdir -p monomial diff --git a/barretenberg/exports.json b/barretenberg/exports.json index 4491016c8f8..6a8bd360ccf 100644 --- a/barretenberg/exports.json +++ b/barretenberg/exports.json @@ -369,6 +369,21 @@ "outArgs": [], "isAsync": false }, + { + "functionName": "srs_init_grumpkin_srs", + "inArgs": [ + { + "name": "points_buf", + "type": "const uint8_t *" + }, + { + "name": "num_points", + "type": "const uint32_t *" + } + ], + "outArgs": [], + "isAsync": false + }, { "functionName": "examples_simple_create_and_verify_proof", "inArgs": [], @@ -524,6 +539,30 @@ ], "isAsync": false }, + { + "functionName": "acir_create_goblin_proof", + "inArgs": [ + { + "name": "acir_composer_ptr", + "type": "in_ptr" + }, + { + "name": "constraint_system_buf", + "type": "const uint8_t *" + }, + { + "name": "witness_buf", + "type": "const uint8_t *" + } + ], + "outArgs": [ + { + "name": "out", + "type": "uint8_t **" + } + ], + "isAsync": false + }, { "functionName": "acir_load_verification_key", "inArgs": [ @@ -566,6 +605,26 @@ ], "isAsync": false }, + { + "functionName": "acir_get_proving_key", + "inArgs": [ + { + "name": "acir_composer_ptr", + "type": "in_ptr" + }, + { + "name": "acir_vec", + "type": "const uint8_t *" + } + ], + "outArgs": [ + { + "name": "out", + "type": "uint8_t **" + } + ], + "isAsync": false + }, { "functionName": "acir_verify_proof", "inArgs": [ @@ -590,6 +649,26 @@ ], "isAsync": false }, + { + "functionName": "acir_verify_goblin_proof", + "inArgs": [ + { + "name": "acir_composer_ptr", + "type": "in_ptr" + }, + { + "name": "proof_buf", + "type": "const uint8_t *" + } + ], + "outArgs": [ + { + "name": "result", + "type": "bool *" + } + ], + "isAsync": false + }, { "functionName": "acir_get_solidity_verifier", "inArgs": [ diff --git a/barretenberg/ts/README.md b/barretenberg/ts/README.md index 4e3544af942..07101e7b726 100644 --- a/barretenberg/ts/README.md +++ b/barretenberg/ts/README.md @@ -62,7 +62,7 @@ Commands: contract [options] Output solidity verification key contract. write_vk [options] Output verification key. proof_as_fields [options] Return the proof as fields elements - vk_as_fields [options] Return the verifiation key represented as fields elements. Also return the verification key hash. + vk_as_fields [options] Return the verification key represented as field elements. Also return the verification key hash. help [command] display help for command ``` diff --git a/barretenberg/ts/src/barretenberg_api/index.ts b/barretenberg/ts/src/barretenberg_api/index.ts index ea1aac55dad..9ee50ba908b 100644 --- a/barretenberg/ts/src/barretenberg_api/index.ts +++ b/barretenberg/ts/src/barretenberg_api/index.ts @@ -232,6 +232,18 @@ export class BarretenbergApi { return; } + async srsInitGrumpkinSrs(pointsBuf: Uint8Array, numPoints: number): Promise { + const inArgs = [pointsBuf, numPoints].map(serializeBufferable); + const outTypes: OutputType[] = []; + const result = await this.wasm.callWasmExport( + 'srs_init_grumpkin_srs', + inArgs, + outTypes.map(t => t.SIZE_IN_BYTES), + ); + const out = result.map((r, i) => outTypes[i].fromBuffer(r)); + return; + } + async examplesSimpleCreateAndVerifyProof(): Promise { const inArgs = [].map(serializeBufferable); const outTypes: OutputType[] = [BoolDeserializer()]; @@ -345,6 +357,22 @@ export class BarretenbergApi { return out[0]; } + async acirCreateGoblinProof( + acirComposerPtr: Ptr, + constraintSystemBuf: Uint8Array, + witnessBuf: Uint8Array, + ): Promise { + const inArgs = [acirComposerPtr, constraintSystemBuf, witnessBuf].map(serializeBufferable); + const outTypes: OutputType[] = [BufferDeserializer()]; + const result = await this.wasm.callWasmExport( + 'acir_create_goblin_proof', + inArgs, + outTypes.map(t => t.SIZE_IN_BYTES), + ); + const out = result.map((r, i) => outTypes[i].fromBuffer(r)); + return out[0]; + } + async acirLoadVerificationKey(acirComposerPtr: Ptr, vkBuf: Uint8Array): Promise { const inArgs = [acirComposerPtr, vkBuf].map(serializeBufferable); const outTypes: OutputType[] = []; @@ -381,8 +409,8 @@ export class BarretenbergApi { return out[0]; } - async acirGetProvingKey(acirComposerPtr: Ptr, constraintSystemBuf: Uint8Array): Promise { - const inArgs = [acirComposerPtr, constraintSystemBuf].map(serializeBufferable); + async acirGetProvingKey(acirComposerPtr: Ptr, acirVec: Uint8Array): Promise { + const inArgs = [acirComposerPtr, acirVec].map(serializeBufferable); const outTypes: OutputType[] = [BufferDeserializer()]; const result = await this.wasm.callWasmExport( 'acir_get_proving_key', @@ -405,6 +433,18 @@ export class BarretenbergApi { return out[0]; } + async acirVerifyGoblinProof(acirComposerPtr: Ptr, proofBuf: Uint8Array): Promise { + const inArgs = [acirComposerPtr, proofBuf].map(serializeBufferable); + const outTypes: OutputType[] = [BoolDeserializer()]; + const result = await this.wasm.callWasmExport( + 'acir_verify_goblin_proof', + inArgs, + outTypes.map(t => t.SIZE_IN_BYTES), + ); + const out = result.map((r, i) => outTypes[i].fromBuffer(r)); + return out[0]; + } + async acirGetSolidityVerifier(acirComposerPtr: Ptr): Promise { const inArgs = [acirComposerPtr].map(serializeBufferable); const outTypes: OutputType[] = [StringDeserializer()]; @@ -665,6 +705,18 @@ export class BarretenbergApiSync { return; } + srsInitGrumpkinSrs(pointsBuf: Uint8Array, numPoints: number): void { + const inArgs = [pointsBuf, numPoints].map(serializeBufferable); + const outTypes: OutputType[] = []; + const result = this.wasm.callWasmExport( + 'srs_init_grumpkin_srs', + inArgs, + outTypes.map(t => t.SIZE_IN_BYTES), + ); + const out = result.map((r, i) => outTypes[i].fromBuffer(r)); + return; + } + examplesSimpleCreateAndVerifyProof(): boolean { const inArgs = [].map(serializeBufferable); const outTypes: OutputType[] = [BoolDeserializer()]; @@ -778,6 +830,18 @@ export class BarretenbergApiSync { return out[0]; } + acirCreateGoblinProof(acirComposerPtr: Ptr, constraintSystemBuf: Uint8Array, witnessBuf: Uint8Array): Uint8Array { + const inArgs = [acirComposerPtr, constraintSystemBuf, witnessBuf].map(serializeBufferable); + const outTypes: OutputType[] = [BufferDeserializer()]; + const result = this.wasm.callWasmExport( + 'acir_create_goblin_proof', + inArgs, + outTypes.map(t => t.SIZE_IN_BYTES), + ); + const out = result.map((r, i) => outTypes[i].fromBuffer(r)); + return out[0]; + } + acirLoadVerificationKey(acirComposerPtr: Ptr, vkBuf: Uint8Array): void { const inArgs = [acirComposerPtr, vkBuf].map(serializeBufferable); const outTypes: OutputType[] = []; @@ -814,6 +878,18 @@ export class BarretenbergApiSync { return out[0]; } + acirGetProvingKey(acirComposerPtr: Ptr, acirVec: Uint8Array): Uint8Array { + const inArgs = [acirComposerPtr, acirVec].map(serializeBufferable); + const outTypes: OutputType[] = [BufferDeserializer()]; + const result = this.wasm.callWasmExport( + 'acir_get_proving_key', + inArgs, + outTypes.map(t => t.SIZE_IN_BYTES), + ); + const out = result.map((r, i) => outTypes[i].fromBuffer(r)); + return out[0]; + } + acirVerifyProof(acirComposerPtr: Ptr, proofBuf: Uint8Array, isRecursive: boolean): boolean { const inArgs = [acirComposerPtr, proofBuf, isRecursive].map(serializeBufferable); const outTypes: OutputType[] = [BoolDeserializer()]; @@ -826,6 +902,18 @@ export class BarretenbergApiSync { return out[0]; } + acirVerifyGoblinProof(acirComposerPtr: Ptr, proofBuf: Uint8Array): boolean { + const inArgs = [acirComposerPtr, proofBuf].map(serializeBufferable); + const outTypes: OutputType[] = [BoolDeserializer()]; + const result = this.wasm.callWasmExport( + 'acir_verify_goblin_proof', + inArgs, + outTypes.map(t => t.SIZE_IN_BYTES), + ); + const out = result.map((r, i) => outTypes[i].fromBuffer(r)); + return out[0]; + } + acirGetSolidityVerifier(acirComposerPtr: Ptr): string { const inArgs = [acirComposerPtr].map(serializeBufferable); const outTypes: OutputType[] = [StringDeserializer()]; diff --git a/barretenberg/ts/src/crs/node/ignition_files_crs.ts b/barretenberg/ts/src/crs/node/ignition_files_crs.ts index ce565224b86..697f45ae01d 100644 --- a/barretenberg/ts/src/crs/node/ignition_files_crs.ts +++ b/barretenberg/ts/src/crs/node/ignition_files_crs.ts @@ -14,9 +14,10 @@ function getCurrentDir() { } /** - * The path to our SRS object, assuming that we are in barretenberg/ts folder. + * The path to our SRS object, assuming that we are in e.g. barretenberg/ts/dest/node/crs/node folder. */ -export const SRS_DEV_PATH = getCurrentDir() + '/../../../cpp/srs_db/ignition/monomial'; +export const SRS_DEV_PATH = getCurrentDir() + '/../../../../../cpp/srs_db/ignition/monomial'; +export const GRUMPKIN_SRS_DEV_PATH = getCurrentDir() + '/../../../../../cpp/srs_db/grumpkin/monomial'; /** * Downloader for CRS from a local file (for Node). @@ -33,8 +34,8 @@ export class IgnitionFilesCrs { private path = SRS_DEV_PATH, ) {} - static defaultExists() { - return existsSync(SRS_DEV_PATH); + pathExists() { + return existsSync(this.path); } /** @@ -49,7 +50,10 @@ export class IgnitionFilesCrs { const data = await readFile(this.path + '/transcript00.dat'); this.data = data.subarray(g1Start, g1End); - this.g2Data = await readFile(this.path + '/g2.dat'); + // TODO(https://github.com/AztecProtocol/barretenberg/issues/811): proper abstraction from Grumpkin which does not have g2 + if (existsSync(this.path + '/g2.dat')) { + this.g2Data = await readFile(this.path + '/g2.dat'); + } } /** diff --git a/barretenberg/ts/src/crs/node/index.ts b/barretenberg/ts/src/crs/node/index.ts index afcbb37e8e9..5552029ed7b 100644 --- a/barretenberg/ts/src/crs/node/index.ts +++ b/barretenberg/ts/src/crs/node/index.ts @@ -1,5 +1,5 @@ import { NetCrs } from '../net_crs.js'; -import { IgnitionFilesCrs } from './ignition_files_crs.js'; +import { GRUMPKIN_SRS_DEV_PATH, IgnitionFilesCrs } from './ignition_files_crs.js'; import { mkdirSync, readFileSync, writeFileSync } from 'fs'; import { readFile } from 'fs/promises'; import createDebug from 'debug'; @@ -26,7 +26,8 @@ export class Crs { return; } - const crs = IgnitionFilesCrs.defaultExists() ? new IgnitionFilesCrs(this.numPoints) : new NetCrs(this.numPoints); + const ignitionCrs = new IgnitionFilesCrs(this.numPoints); + const crs = ignitionCrs.pathExists() ? new IgnitionFilesCrs(this.numPoints) : new NetCrs(this.numPoints); if (crs instanceof NetCrs) { debug(`downloading crs of size: ${this.numPoints}`); } else { @@ -54,3 +55,58 @@ export class Crs { return readFileSync(this.path + '/g2.dat'); } } + +/** + * Generic Grumpkin CRS finder utility class. + */ +export class GrumpkinCrs { + constructor(public readonly numPoints: number, public readonly path: string) {} + + static async new(numPoints: number, crsPath = './crs') { + const crs = new GrumpkinCrs(numPoints, crsPath); + await crs.init(); + return crs; + } + + async downloadG1Data() { + const g1Start = 28; + const g1End = g1Start + this.numPoints * 64 - 1; + + const response = await fetch('https://aztec-ignition.s3.amazonaws.com/TEST%20GRUMPKIN/monomial/transcript00.dat', { + headers: { + Range: `bytes=${g1Start}-${g1End}`, + }, + cache: 'force-cache', + }); + + return new Uint8Array(await response.arrayBuffer()); + } + + async init() { + mkdirSync(this.path, { recursive: true }); + const size = await readFile(this.path + '/grumpkin_size', 'ascii').catch(() => undefined); + if (size && +size >= this.numPoints) { + debug(`using cached crs of size: ${size}`); + return; + } + + // TODO(https://github.com/AztecProtocol/barretenberg/issues/813): implement NetCrs for Grumpkin once SRS is uploaded. + const ignitionCrs = new IgnitionFilesCrs(this.numPoints, GRUMPKIN_SRS_DEV_PATH); + if (ignitionCrs.pathExists()) { + await ignitionCrs.init(); + } + const g1Data = ignitionCrs.pathExists() ? ignitionCrs.getG1Data() : await this.downloadG1Data(); + debug(`loading ignition file crs of size: ${this.numPoints}`); + // await crs.init(); + writeFileSync(this.path + '/grumpkin_size', this.numPoints.toString()); + writeFileSync(this.path + '/grumpkin_g1.dat', g1Data); + } + + /** + * G1 points data for prover key. + * @returns The points data. + */ + getG1Data(): Uint8Array { + return readFileSync(this.path + '/grumpkin_g1.dat'); + } +} diff --git a/barretenberg/ts/src/main.ts b/barretenberg/ts/src/main.ts index de4cf64631d..5c708347104 100755 --- a/barretenberg/ts/src/main.ts +++ b/barretenberg/ts/src/main.ts @@ -7,6 +7,7 @@ import { Command } from 'commander'; import { acvmInfoJson } from './info.js'; import { Timer, writeBenchmark } from './benchmark/index.js'; import path from 'path'; +import { GrumpkinCrs } from './crs/node/index.js'; createDebug.log = console.error.bind(console); const debug = createDebug('bb.js'); @@ -43,11 +44,12 @@ async function computeCircuitSize(bytecodePath: string, api: Barretenberg) { return { exact, total, subgroup }; } -async function init(bytecodePath: string, crsPath: string) { +async function init(bytecodePath: string, crsPath: string, subgroupSizeOverride = -1) { const api = await Barretenberg.new({ threads }); const circuitSize = await getGates(bytecodePath, api); - const subgroupSize = Math.pow(2, Math.ceil(Math.log2(circuitSize))); + // TODO(https://github.com/AztecProtocol/barretenberg/issues/811): remove subgroupSizeOverride hack for goblin + const subgroupSize = Math.max(subgroupSizeOverride, Math.pow(2, Math.ceil(Math.log2(circuitSize)))); if (subgroupSize > MAX_CIRCUIT_SIZE) { throw new Error(`Circuit size of ${subgroupSize} exceeds max supported of ${MAX_CIRCUIT_SIZE}`); } @@ -69,6 +71,20 @@ async function init(bytecodePath: string, crsPath: string) { return { api, acirComposer, circuitSize, subgroupSize }; } +async function initGoblin(bytecodePath: string, crsPath: string) { + // TODO(https://github.com/AztecProtocol/barretenberg/issues/811): remove this subgroup size hack + const hardcodedGrumpkinSubgroupSizeHack = 32768; + const initData = await init(bytecodePath, crsPath, hardcodedGrumpkinSubgroupSizeHack); + const { api } = initData; + + // Plus 1 needed! (Move +1 into Crs?) + // Need both grumpkin and bn254 SRS's currently + const grumpkinCrs = await GrumpkinCrs.new(hardcodedGrumpkinSubgroupSizeHack + 1, crsPath); + await api.srsInitGrumpkinSrs(new RawBuffer(grumpkinCrs.getG1Data()), grumpkinCrs.numPoints); + + return initData; +} + async function initLite() { const api = await Barretenberg.new({ threads: 1 }); @@ -112,6 +128,34 @@ export async function proveAndVerify(bytecodePath: string, witnessPath: string, /* eslint-enable camelcase */ } +export async function proveAndVerifyGoblin(bytecodePath: string, witnessPath: string, crsPath: string) { + /* eslint-disable camelcase */ + const acir_test = path.basename(process.cwd()); + + const { api, acirComposer, circuitSize, subgroupSize } = await initGoblin(bytecodePath, crsPath); + try { + debug(`creating proof...`); + const bytecode = getBytecode(bytecodePath); + const witness = getWitness(witnessPath); + + writeBenchmark('gate_count', circuitSize, { acir_test, threads }); + writeBenchmark('subgroup_size', subgroupSize, { acir_test, threads }); + + const proofTimer = new Timer(); + const proof = await api.acirCreateGoblinProof(acirComposer, bytecode, witness); + writeBenchmark('proof_construction_time', proofTimer.ms(), { acir_test, threads }); + + debug(`verifying...`); + const verified = await api.acirVerifyGoblinProof(acirComposer, proof); + debug(`verified: ${verified}`); + console.log({ verified }); + return verified; + } finally { + await api.destroy(); + } + /* eslint-enable camelcase */ +} + export async function prove( bytecodePath: string, witnessPath: string, @@ -312,6 +356,17 @@ program process.exit(result ? 0 : 1); }); +program + .command('prove_and_verify_goblin') + .description('Generate a proof and verify it. Process exits with success or failure code.') + .option('-b, --bytecode-path ', 'Specify the bytecode path', './target/acir.gz') + .option('-w, --witness-path ', 'Specify the witness path', './target/witness.gz') + .action(async ({ bytecodePath, witnessPath, crsPath }) => { + handleGlobalOptions(); + const result = await proveAndVerifyGoblin(bytecodePath, witnessPath, crsPath); + process.exit(result ? 0 : 1); + }); + program .command('prove') .description('Generate a proof and write it to a file.') diff --git a/circuits/cpp/.dockerignore b/circuits/cpp/.dockerignore deleted file mode 100644 index 0e0185269d2..00000000000 --- a/circuits/cpp/.dockerignore +++ /dev/null @@ -1,18 +0,0 @@ -build -build-wasm -docker* -.* -!.clang-format -!.clang-tidy -src/wasi-sdk* -barretenberg/cpp/build* -barretenberg/cpp/docker* -barretenberg/cpp/scripts -barretenberg/cpp/.* -barretenberg/cpp/src/wasi-sdk* -barretenberg/cpp/src/aztec/rollup/proofs/root_*/fixtures/account -barretenberg/cpp/src/aztec/rollup/proofs/root_*/fixtures/join_split -barretenberg/cpp/src/aztec/rollup/proofs/root_*/fixtures/**/proving_key -barretenberg/cpp/srs_db/* -!barretenberg/cpp/srs_db/download_ignition.sh -!barretenberg/cpp/scripts/install-wasi-sdk.sh \ No newline at end of file diff --git a/circuits/cpp/dockerfiles/Dockerfile.wasm-linux-clang b/circuits/cpp/dockerfiles/Dockerfile.wasm-linux-clang deleted file mode 100644 index eb623c554a6..00000000000 --- a/circuits/cpp/dockerfiles/Dockerfile.wasm-linux-clang +++ /dev/null @@ -1,14 +0,0 @@ -FROM 278380418400.dkr.ecr.eu-west-2.amazonaws.com/barretenberg-wasm-linux-clang as bb - -FROM ubuntu:lunar AS builder -RUN apt-get update && apt-get install -y build-essential wget git libssl-dev cmake ninja-build curl binaryen -COPY --from=bb /usr/src/barretenberg/cpp /usr/src/barretenberg/cpp -WORKDIR /usr/src/circuits/cpp -COPY . . -RUN cmake --preset wasm && cmake --build --preset wasm --target aztec3-circuits.wasm - -FROM scratch -COPY --from=builder /usr/src/barretenberg/cpp/build-wasm/bin/barretenberg.wasm /usr/src/barretenberg/cpp/build-wasm/bin/primitives.wasm -COPY --from=builder /usr/src/barretenberg/cpp/srs_db /usr/src/barretenberg/cpp/srs_db -COPY --from=builder /usr/src/circuits/cpp/build-wasm/bin/aztec3-circuits.wasm /usr/src/circuits/cpp/build-wasm/bin/aztec3-circuits.wasm -COPY --from=builder /usr/src/circuits/cpp/src/aztec3/circuits/kernel/private/fixtures /usr/src/circuits/cpp/src/aztec3/circuits/kernel/private/fixtures diff --git a/circuits/cpp/dockerfiles/Dockerfile.wasm-linux-clang-assert b/circuits/cpp/dockerfiles/Dockerfile.wasm-linux-clang-assert deleted file mode 100644 index 1c996f61594..00000000000 --- a/circuits/cpp/dockerfiles/Dockerfile.wasm-linux-clang-assert +++ /dev/null @@ -1,16 +0,0 @@ -FROM 278380418400.dkr.ecr.eu-west-2.amazonaws.com/barretenberg-wasm-linux-clang as bb - -FROM ubuntu:lunar AS builder -RUN apt-get update && apt-get install -y build-essential git libssl-dev cmake ninja-build curl binaryen -COPY --from=bb /usr/src/barretenberg/cpp /usr/src/barretenberg/cpp -WORKDIR /usr/src/circuits/cpp -COPY . . -RUN cmake --preset wasm && cmake --build --preset wasm - -FROM ubuntu:lunar -RUN apt-get update && apt-get install -y xz-utils curl -RUN curl https://wasmtime.dev/install.sh -sSf | bash /dev/stdin --version v3.0.1 -COPY --from=builder /usr/src/barretenberg/cpp/srs_db /usr/src/barretenberg/cpp/srs_db -COPY --from=builder /usr/src/circuits/cpp/src/aztec3/circuits/kernel/private/fixtures /usr/src/circuits/cpp/src/aztec3/circuits/kernel/private/fixtures -COPY --from=builder /usr/src/circuits/cpp/scripts /usr/src/circuits/cpp/scripts -COPY --from=builder /usr/src/circuits/cpp/build-wasm/bin/*_tests /usr/src/circuits/cpp/build-wasm/bin/ diff --git a/circuits/cpp/dockerfiles/Dockerfile.x86_64-linux-clang b/circuits/cpp/dockerfiles/Dockerfile.x86_64-linux-clang deleted file mode 100644 index c0eca292e40..00000000000 --- a/circuits/cpp/dockerfiles/Dockerfile.x86_64-linux-clang +++ /dev/null @@ -1,22 +0,0 @@ -FROM 278380418400.dkr.ecr.eu-west-2.amazonaws.com/barretenberg-x86_64-linux-clang as bb - -FROM alpine:3.17 AS builder -RUN apk update \ - && apk upgrade \ - && apk add --no-cache \ - build-base \ - clang15 \ - cmake \ - ninja \ - git \ - curl \ - perl -COPY --from=bb /usr/src/barretenberg/cpp /usr/src/barretenberg/cpp -WORKDIR /usr/src/circuits/cpp -COPY . . -# Build the entire project, as we want to check everything builds under clang -RUN cmake --preset default && cmake --build --preset default - -FROM alpine:3.17 -COPY --from=builder /usr/src/barretenberg/cpp/srs_db /usr/src/barretenberg/cpp/srs_db -COPY --from=builder /usr/src/circuits/cpp/src/aztec3/circuits/kernel/private/fixtures /usr/src/circuits/cpp/src/aztec3/circuits/kernel/private/fixtures \ No newline at end of file diff --git a/circuits/cpp/dockerfiles/Dockerfile.x86_64-linux-clang-assert b/circuits/cpp/dockerfiles/Dockerfile.x86_64-linux-clang-assert deleted file mode 100644 index 9095d9d056a..00000000000 --- a/circuits/cpp/dockerfiles/Dockerfile.x86_64-linux-clang-assert +++ /dev/null @@ -1,25 +0,0 @@ -FROM 278380418400.dkr.ecr.eu-west-2.amazonaws.com/barretenberg-x86_64-linux-clang as bb - -FROM alpine:3.17 AS builder -RUN apk update \ - && apk upgrade \ - && apk add --no-cache \ - build-base \ - clang15 \ - cmake \ - ninja \ - git \ - curl \ - perl -COPY --from=bb /usr/src/barretenberg/cpp /usr/src/barretenberg/cpp -WORKDIR /usr/src/circuits/cpp -COPY . . -# Build everything to ensure everything builds. All tests will be run from the result of this build. -RUN cmake --preset default -DCMAKE_BUILD_TYPE=RelWithAssert -DCI=ON && cmake --build --preset default - -FROM alpine:3.17 -RUN apk update && apk add curl bash libstdc++ -COPY --from=builder /usr/src/barretenberg/cpp/srs_db /usr/src/barretenberg/cpp/srs_db -COPY --from=builder /usr/src/circuits/cpp/src/aztec3/circuits/kernel/private/fixtures /usr/src/circuits/cpp/src/aztec3/circuits/kernel/private/fixtures -COPY --from=builder /usr/src/circuits/cpp/scripts /usr/src/circuits/cpp/scripts -COPY --from=builder /usr/src/circuits/cpp/build/bin/*_tests /usr/src/circuits/cpp/build/bin/ \ No newline at end of file diff --git a/circuits/cpp/dockerfiles/Dockerfile.x86_64-linux-clang-tidy b/circuits/cpp/dockerfiles/Dockerfile.x86_64-linux-clang-tidy deleted file mode 100644 index ca0adedbafe..00000000000 --- a/circuits/cpp/dockerfiles/Dockerfile.x86_64-linux-clang-tidy +++ /dev/null @@ -1,22 +0,0 @@ -FROM 278380418400.dkr.ecr.eu-west-2.amazonaws.com/barretenberg-x86_64-linux-clang as bb - -FROM alpine:3.17 AS builder -RUN apk update \ - && apk upgrade \ - && apk add --no-cache \ - build-base \ - clang15 \ - clang15-extra-tools \ - openmp-dev \ - cmake \ - ninja \ - git \ - curl \ - perl \ - bash \ - python3 -COPY --from=bb /usr/src/barretenberg/cpp /usr/src/barretenberg/cpp -WORKDIR /usr/src/circuits/cpp -COPY . . -# Configure cmake and check if code is tidy -RUN ./scripts/tidy.sh fix \ No newline at end of file