From d56dfbdfd74b438b3c8652e1ae8740de99f93ae5 Mon Sep 17 00:00:00 2001 From: Blaine Bublitz Date: Tue, 4 Apr 2023 17:43:46 +0100 Subject: [PATCH] feat: Working UltraPlonk for Noir (#299) * Make dsl composer agnostic. * change SYSTEM_COMPOSER under stdlib::types to ultra composer type * use ultra logic constraints * in process of debugging, move to using ultra logic constraints * add get_total_circuit_size method * acir format tests showing failures with range constraints of different bit sizes * remove unnecessary comment * (fix) Temporarily add a redundant add-gate for variables that need range constraint < 8 bits. * rename functions * Implement get_solidity_verifier function * Fix no longer available properties * remove constraint system * logic gate changes using plookup * logic gate debugging * test for logic gates passing * last debug things XOR and AND returnign correct results, XOR still failing * cleanup * pedersen_plookup * plookup funcs * add to header * fixed error in pedersen hash when RHS is a circuit constant * added ACIR test for XOR gate pedersen hash test now checks y coordinate * temp disable wasm-opt * Making everything compile with any composer & add a cmake flag to switch on turbo * enable wasm-opt for asyncify but disable optimizations * remove using in header * fixed work queue bug with wasm wasm code path was not correctly storing fft outputs in proving key * added bitwise logic operations into stdlib stdlib method is utility method to provide Composer-agnostic interface due to the use of plookup tables if enabled * updated acir_format to use new stdlib logic class Updated ReadMe to include wasm example that supports gtest filtering * reenable tests * linting fixes * disable binaryen with comment * write instead of read * remove random * WIP * cleanup the debug logging * restore the randomness * only add a zero/one test instead of replacing * remove unused change * changes to make solgen work correctly in bindings * fix join_split_tests.test_deposit_construct_proof * working serialized proving key size and circuit change test for ultra (#307) * USE_TURBO for join_split * Empty-Commit * Don't default one function; tweak comments. * Empty-Commit --------- Co-authored-by: Suyash Bagad Co-authored-by: vezenovm Co-authored-by: Maxim Vezenov Co-authored-by: zac-williamson Co-authored-by: kevaundray Co-authored-by: codygunton --- README.md | 9 + cpp/CMakeLists.txt | 8 + cpp/src/CMakeLists.txt | 32 ++- .../barretenberg/crypto/pedersen/c_bind.cpp | 26 ++ .../barretenberg/crypto/pedersen/c_bind.hpp | 3 + cpp/src/barretenberg/dsl/CMakeLists.txt | 2 +- .../dsl/acir_format/acir_format.cpp | 36 +-- .../dsl/acir_format/acir_format.hpp | 20 +- .../dsl/acir_format/acir_format.test.cpp | 252 ++++++++++++++++++ .../dsl/acir_format/blake2s_constraint.cpp | 5 +- .../dsl/acir_format/blake2s_constraint.hpp | 4 +- .../dsl/acir_format/ecdsa_secp256k1.cpp | 17 +- .../dsl/acir_format/ecdsa_secp256k1.hpp | 4 +- .../dsl/acir_format/fixed_base_scalar_mul.cpp | 3 +- .../dsl/acir_format/fixed_base_scalar_mul.hpp | 4 +- .../dsl/acir_format/hash_to_field.cpp | 5 +- .../dsl/acir_format/hash_to_field.hpp | 4 +- .../dsl/acir_format/logic_constraint.cpp | 22 +- .../dsl/acir_format/logic_constraint.hpp | 14 +- .../merkle_membership_constraint.cpp | 5 +- .../merkle_membership_constraint.hpp | 5 +- .../barretenberg/dsl/acir_format/pedersen.cpp | 7 +- .../barretenberg/dsl/acir_format/pedersen.hpp | 8 +- .../dsl/acir_format/schnorr_verify.cpp | 9 +- .../dsl/acir_format/schnorr_verify.hpp | 4 +- .../dsl/acir_format/sha256_constraint.cpp | 5 +- .../dsl/acir_format/sha256_constraint.hpp | 4 +- .../CMakeLists.txt | 2 +- .../acir_proofs.cpp} | 69 +++-- .../dsl/acir_proofs/acir_proofs.hpp | 20 ++ .../barretenberg/dsl/acir_proofs/c_bind.cpp | 53 ++++ .../barretenberg/dsl/acir_proofs/c_bind.hpp | 25 ++ .../barretenberg/dsl/turbo_proofs/c_bind.cpp | 43 --- .../barretenberg/dsl/turbo_proofs/c_bind.hpp | 24 -- .../dsl/turbo_proofs/turbo_proofs.hpp | 18 -- .../proofs/join_split/c_bind.cpp | 18 +- .../proofs/join_split/join_split.cpp | 12 +- .../proofs/join_split/join_split.hpp | 2 +- .../proofs/join_split/join_split.test.cpp | 14 +- .../plonk/composer/composer_base.hpp | 1 + .../plonk/composer/plookup_tables/uint.hpp | 2 +- .../plonk/composer/standard_composer.hpp | 2 + .../plonk/composer/turbo_composer.hpp | 3 + .../plonk/composer/ultra_composer.hpp | 38 ++- .../plonk/proof_system/constants.hpp | 4 + .../plonk/proof_system/prover/prover.cpp | 1 - .../proof_system/verification_key/sol_gen.hpp | 54 ++-- .../proof_system/work_queue/work_queue.cpp | 19 +- .../stdlib/hash/pedersen/pedersen.test.cpp | 34 ++- .../stdlib/hash/pedersen/pedersen_plookup.cpp | 2 +- .../stdlib/hash/sha256/sha256.bench.cpp | 6 +- .../stdlib/primitives/logic/logic.cpp | 94 +++++++ .../stdlib/primitives/logic/logic.hpp | 20 ++ .../stdlib/primitives/logic/logic.test.cpp | 101 +++++++ .../stdlib/primitives/plookup/plookup.cpp | 2 +- .../barretenberg/transcript/transcript.cpp | 2 - 56 files changed, 934 insertions(+), 268 deletions(-) create mode 100644 cpp/src/barretenberg/dsl/acir_format/acir_format.test.cpp rename cpp/src/barretenberg/dsl/{turbo_proofs => acir_proofs}/CMakeLists.txt (74%) rename cpp/src/barretenberg/dsl/{turbo_proofs/turbo_proofs.cpp => acir_proofs/acir_proofs.cpp} (66%) create mode 100644 cpp/src/barretenberg/dsl/acir_proofs/acir_proofs.hpp create mode 100644 cpp/src/barretenberg/dsl/acir_proofs/c_bind.cpp create mode 100644 cpp/src/barretenberg/dsl/acir_proofs/c_bind.hpp delete mode 100644 cpp/src/barretenberg/dsl/turbo_proofs/c_bind.cpp delete mode 100644 cpp/src/barretenberg/dsl/turbo_proofs/c_bind.hpp delete mode 100644 cpp/src/barretenberg/dsl/turbo_proofs/turbo_proofs.hpp create mode 100644 cpp/src/barretenberg/stdlib/primitives/logic/logic.cpp create mode 100644 cpp/src/barretenberg/stdlib/primitives/logic/logic.hpp create mode 100644 cpp/src/barretenberg/stdlib/primitives/logic/logic.test.cpp diff --git a/README.md b/README.md index 2be12b4834..802392f5fc 100644 --- a/README.md +++ b/README.md @@ -132,6 +132,12 @@ cmake --build --preset wasm --target ecc_tests wasmtime --dir=.. ./bin/ecc_tests ``` +To add gtest filter parameters in a wasm context: + +``` +wasmtime --dir=.. ./bin/ecc_tests run --gtest_filter=filtertext +``` + ### Fuzzing build For detailed instructions look in cpp/docs/Fuzzing.md @@ -160,11 +166,13 @@ cmake --build --preset coverage ``` Then run tests (on the mainframe always use taskset and nice to limit your influence on the server. Profiling instrumentation is very heavy): + ``` taskset 0xffffff nice -n10 make test ``` And generate report: + ``` make create_full_coverage_report ``` @@ -174,4 +182,5 @@ The report will land in the build directory in the all_test_coverage_report dire Alternatively you can build separate test binaries, e.g. honk_tests or numeric_tests and run **make test** just for them or even just for a single test. Then the report will just show coverage for those binaries. ### VS Code configuration + A default configuration for VS Code is provided by the file [`barretenberg.code-workspace`](barretenberg.code-workspace). These settings can be overridden by placing configuration files in `.vscode/`. diff --git a/cpp/CMakeLists.txt b/cpp/CMakeLists.txt index 3b5d8dd016..b978b04d53 100644 --- a/cpp/CMakeLists.txt +++ b/cpp/CMakeLists.txt @@ -20,6 +20,14 @@ option(DISABLE_TBB "Intel Thread Building Blocks" ON) option(COVERAGE "Enable collecting coverage from tests" OFF) option(ENABLE_HEAVY_TESTS "Enable heavy tests when collecting coverage" OFF) option(INSTALL_BARRETENBERG "Enable installation of barretenberg. (Projects embedding barretenberg may want to turn this OFF.)" ON) +option(USE_TURBO "Enable the use of TurboPlonk in barretenberg." OFF) + +if(USE_TURBO) + message(STATUS "Building barretenberg for TurboPlonk Composer.") + add_definitions(-DUSE_TURBO) +else() + message(STATUS "Building barretenberg for UltraPlonk Composer.") +endif() if(CMAKE_SYSTEM_PROCESSOR MATCHES "aarch64" OR CMAKE_SYSTEM_PROCESSOR MATCHES "arm64") message(STATUS "Compiling for ARM.") diff --git a/cpp/src/CMakeLists.txt b/cpp/src/CMakeLists.txt index 6a91ddd47f..3a40b2a908 100644 --- a/cpp/src/CMakeLists.txt +++ b/cpp/src/CMakeLists.txt @@ -91,7 +91,7 @@ if(WASM) $ $ $ - $ + $ ) # With binaryen installed, it seems its wasm backend optimiser gets invoked automatically. @@ -105,18 +105,24 @@ if(WASM) -nostartfiles -O2 -Wl,--no-entry -Wl,--export-dynamic -Wl,--import-memory -Wl,--allow-undefined -Wl,--stack-first -Wl,-z,stack-size=1048576 ) - find_program(WASM_OPT wasm-opt) + # TODO(blaine): Figure out how to Asyncify the wasm output. + # Binaryen's Asyncify transform produces wasm that has too many local variables to run in a WebAssembly + # instance. This likely would be "solved" by enabling the optimizations to reduce the number of locals, + # but using any optimization level results in a wasm file that takes an unusable amount of time to solve the + # most simple prood. - if(NOT WASM_OPT) - message(FATAL_ERROR "wasm-opt executable not found. Please install binaryen.") - endif() + # find_program(WASM_OPT wasm-opt) - add_custom_command( - TARGET barretenberg.wasm - POST_BUILD - COMMAND wasm-opt "$" -O2 --asyncify -o "$" - VERBATIM - ) + # if(NOT WASM_OPT) + # message(FATAL_ERROR "wasm-opt executable not found. Please install binaryen.") + # endif() + + # add_custom_command( + # TARGET barretenberg.wasm + # POST_BUILD + # COMMAND wasm-opt "$" -O0 --asyncify -o "$" + # VERBATIM + # ) if(INSTALL_BARRETENBERG) install(TARGETS barretenberg.wasm DESTINATION ${CMAKE_INSTALL_BINDIR}) @@ -151,7 +157,7 @@ if(WASM) $ $ $ - $ + $ ) else() # For use when compiling dependent cpp projects @@ -183,7 +189,7 @@ else() $ $ $ - $ + $ $ ) diff --git a/cpp/src/barretenberg/crypto/pedersen/c_bind.cpp b/cpp/src/barretenberg/crypto/pedersen/c_bind.cpp index 8f8a9e6a74..320604d46b 100644 --- a/cpp/src/barretenberg/crypto/pedersen/c_bind.cpp +++ b/cpp/src/barretenberg/crypto/pedersen/c_bind.cpp @@ -1,5 +1,6 @@ #include "c_bind.hpp" #include "pedersen.hpp" +#include "pedersen_lookup.hpp" #include "barretenberg/common/serialize.hpp" #include "barretenberg/common/timer.hpp" #include "barretenberg/common/mem.hpp" @@ -21,6 +22,14 @@ WASM_EXPORT void pedersen__compress_fields(uint8_t const* left, uint8_t const* r barretenberg::fr::serialize_to_buffer(r, result); } +WASM_EXPORT void pedersen_plookup_compress_fields(uint8_t const* left, uint8_t const* right, uint8_t* result) +{ + auto lhs = barretenberg::fr::serialize_from_buffer(left); + auto rhs = barretenberg::fr::serialize_from_buffer(right); + auto r = crypto::pedersen::lookup::compress_native({ lhs, rhs }); + barretenberg::fr::serialize_to_buffer(r, result); +} + WASM_EXPORT void pedersen__compress(uint8_t const* inputs_buffer, uint8_t* output) { std::vector to_compress; @@ -29,6 +38,14 @@ WASM_EXPORT void pedersen__compress(uint8_t const* inputs_buffer, uint8_t* outpu barretenberg::fr::serialize_to_buffer(r, output); } +WASM_EXPORT void pedersen_plookup_compress(uint8_t const* inputs_buffer, uint8_t* output) +{ + std::vector to_compress; + read(inputs_buffer, to_compress); + auto r = crypto::pedersen::lookup::compress_native(to_compress); + barretenberg::fr::serialize_to_buffer(r, output); +} + WASM_EXPORT void pedersen__compress_with_hash_index(uint8_t const* inputs_buffer, uint8_t* output, uint32_t hash_index) { std::vector to_compress; @@ -46,6 +63,15 @@ WASM_EXPORT void pedersen__commit(uint8_t const* inputs_buffer, uint8_t* output) write(output, pedersen_hash); } +WASM_EXPORT void pedersen_plookup_commit(uint8_t const* inputs_buffer, uint8_t* output) +{ + std::vector to_compress; + read(inputs_buffer, to_compress); + grumpkin::g1::affine_element pedersen_hash = crypto::pedersen::lookup::commit_native(to_compress); + + write(output, pedersen_hash); +} + WASM_EXPORT void pedersen__buffer_to_field(uint8_t const* data, size_t length, uint8_t* r) { std::vector to_compress(data, data + length); diff --git a/cpp/src/barretenberg/crypto/pedersen/c_bind.hpp b/cpp/src/barretenberg/crypto/pedersen/c_bind.hpp index 8e61135b9d..9b170cdd0b 100644 --- a/cpp/src/barretenberg/crypto/pedersen/c_bind.hpp +++ b/cpp/src/barretenberg/crypto/pedersen/c_bind.hpp @@ -9,12 +9,15 @@ extern "C" { WASM_EXPORT void pedersen__init(); WASM_EXPORT void pedersen__compress_fields(uint8_t const* left, uint8_t const* right, uint8_t* result); +WASM_EXPORT void pedersen_plookup_compress_fields(uint8_t const* left, uint8_t const* right, uint8_t* result); WASM_EXPORT void pedersen__compress(uint8_t const* inputs_buffer, uint8_t* output); +WASM_EXPORT void pedersen_plookup_compress(uint8_t const* inputs_buffer, uint8_t* output); WASM_EXPORT void pedersen__compress_with_hash_index(uint8_t const* inputs_buffer, uint8_t* output, uint32_t hash_index); WASM_EXPORT void pedersen__commit(uint8_t const* inputs_buffer, uint8_t* output); +WASM_EXPORT void pedersen_plookup_commit(uint8_t const* inputs_buffer, uint8_t* output); WASM_EXPORT void pedersen__buffer_to_field(uint8_t const* data, size_t length, uint8_t* r); diff --git a/cpp/src/barretenberg/dsl/CMakeLists.txt b/cpp/src/barretenberg/dsl/CMakeLists.txt index 9e37be54e7..f4697905ea 100644 --- a/cpp/src/barretenberg/dsl/CMakeLists.txt +++ b/cpp/src/barretenberg/dsl/CMakeLists.txt @@ -1,2 +1,2 @@ add_subdirectory(acir_format) -add_subdirectory(turbo_proofs) +add_subdirectory(acir_proofs) diff --git a/cpp/src/barretenberg/dsl/acir_format/acir_format.cpp b/cpp/src/barretenberg/dsl/acir_format/acir_format.cpp index 4a411a1e32..30160837c7 100644 --- a/cpp/src/barretenberg/dsl/acir_format/acir_format.cpp +++ b/cpp/src/barretenberg/dsl/acir_format/acir_format.cpp @@ -1,8 +1,10 @@ #include "acir_format.hpp" +using namespace plonk::stdlib::types; + namespace acir_format { -void read_witness(TurboComposer& composer, std::vector witness) +void read_witness(Composer& composer, std::vector witness) { composer.variables[0] = 0; for (size_t i = 0; i < witness.size(); ++i) { @@ -10,7 +12,7 @@ void read_witness(TurboComposer& composer, std::vector witness } } -void create_circuit(TurboComposer& composer, const acir_format& constraint_system) +void create_circuit(Composer& composer, const acir_format& constraint_system) { if (constraint_system.public_inputs.size() > constraint_system.varnum) { std::cout << "too many public inputs!" << std::endl; @@ -41,7 +43,7 @@ void create_circuit(TurboComposer& composer, const acir_format& constraint_syste // Add range constraint for (const auto& constraint : constraint_system.range_constraints) { - composer.decompose_into_base4_accumulators(constraint.witness, constraint.num_bits, ""); + composer.create_range_constraint(constraint.witness, constraint.num_bits, ""); } // Add sha256 constraints @@ -85,14 +87,14 @@ void create_circuit(TurboComposer& composer, const acir_format& constraint_syste } } -TurboComposer create_circuit(const acir_format& constraint_system, - std::unique_ptr&& crs_factory) +Composer create_circuit(const acir_format& constraint_system, + std::unique_ptr&& crs_factory) { if (constraint_system.public_inputs.size() > constraint_system.varnum) { std::cout << "too many public inputs!" << std::endl; } - TurboComposer composer(std::move(crs_factory)); + Composer composer(std::move(crs_factory)); 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 @@ -119,7 +121,7 @@ TurboComposer create_circuit(const acir_format& constraint_system, // Add range constraint for (const auto& constraint : constraint_system.range_constraints) { - composer.decompose_into_base4_accumulators(constraint.witness, constraint.num_bits, ""); + composer.create_range_constraint(constraint.witness, constraint.num_bits, ""); } // Add sha256 constraints @@ -165,15 +167,15 @@ TurboComposer create_circuit(const acir_format& constraint_system, return composer; } -TurboComposer create_circuit_with_witness(const acir_format& constraint_system, - std::vector witness, - std::unique_ptr&& crs_factory) +Composer create_circuit_with_witness(const acir_format& constraint_system, + std::vector witness, + std::unique_ptr&& crs_factory) { if (constraint_system.public_inputs.size() > constraint_system.varnum) { std::cout << "too many public inputs!" << std::endl; } - TurboComposer composer(std::move(crs_factory)); + Composer composer(std::move(crs_factory)); 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 @@ -203,7 +205,7 @@ TurboComposer create_circuit_with_witness(const acir_format& constraint_system, // Add range constraint for (const auto& constraint : constraint_system.range_constraints) { - composer.decompose_into_base4_accumulators(constraint.witness, constraint.num_bits, ""); + composer.create_range_constraint(constraint.witness, constraint.num_bits, ""); } // Add sha256 constraints @@ -248,13 +250,13 @@ TurboComposer create_circuit_with_witness(const acir_format& constraint_system, return composer; } -TurboComposer create_circuit_with_witness(const acir_format& constraint_system, std::vector witness) +Composer create_circuit_with_witness(const acir_format& constraint_system, std::vector witness) { if (constraint_system.public_inputs.size() > constraint_system.varnum) { std::cout << "too many public inputs!" << std::endl; } - auto composer = TurboComposer(); + auto composer = Composer(); 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 @@ -284,7 +286,7 @@ TurboComposer create_circuit_with_witness(const acir_format& constraint_system, // Add range constraint for (const auto& constraint : constraint_system.range_constraints) { - composer.decompose_into_base4_accumulators(constraint.witness, constraint.num_bits, ""); + composer.create_range_constraint(constraint.witness, constraint.num_bits, ""); } // Add sha256 constraints @@ -329,7 +331,7 @@ TurboComposer create_circuit_with_witness(const acir_format& constraint_system, return composer; } -void create_circuit_with_witness(TurboComposer& composer, const acir_format& constraint_system, std::vector witness) +void create_circuit_with_witness(Composer& composer, const acir_format& constraint_system, std::vector witness) { if (constraint_system.public_inputs.size() > constraint_system.varnum) { std::cout << "too many public inputs!" << std::endl; @@ -363,7 +365,7 @@ void create_circuit_with_witness(TurboComposer& composer, const acir_format& con // Add range constraint for (const auto& constraint : constraint_system.range_constraints) { - composer.decompose_into_base4_accumulators(constraint.witness, constraint.num_bits, ""); + composer.create_range_constraint(constraint.witness, constraint.num_bits, ""); } // Add sha256 constraints diff --git a/cpp/src/barretenberg/dsl/acir_format/acir_format.hpp b/cpp/src/barretenberg/dsl/acir_format/acir_format.hpp index 17c40441d8..b6f2f2ae4b 100644 --- a/cpp/src/barretenberg/dsl/acir_format/acir_format.hpp +++ b/cpp/src/barretenberg/dsl/acir_format/acir_format.hpp @@ -9,6 +9,7 @@ #include "merkle_membership_constraint.hpp" #include "pedersen.hpp" #include "hash_to_field.hpp" +#include "barretenberg/stdlib/types/types.hpp" namespace acir_format { @@ -35,20 +36,21 @@ struct acir_format { friend bool operator==(acir_format const& lhs, acir_format const& rhs) = default; }; -void read_witness(TurboComposer& composer, std::vector witness); +void read_witness(plonk::stdlib::types::Composer& composer, std::vector witness); -void create_circuit(TurboComposer& composer, const acir_format& constraint_system); +void create_circuit(plonk::stdlib::types::Composer& composer, const acir_format& constraint_system); -TurboComposer create_circuit(const acir_format& constraint_system, - std::unique_ptr&& crs_factory); +plonk::stdlib::types::Composer create_circuit(const acir_format& constraint_system, + std::unique_ptr&& crs_factory); -TurboComposer create_circuit_with_witness(const acir_format& constraint_system, - std::vector witness, - std::unique_ptr&& crs_factory); +plonk::stdlib::types::Composer create_circuit_with_witness(const acir_format& constraint_system, + std::vector witness, + std::unique_ptr&& crs_factory); -TurboComposer create_circuit_with_witness(const acir_format& constraint_system, std::vector witness); +plonk::stdlib::types::Composer create_circuit_with_witness(const acir_format& constraint_system, + std::vector witness); -void create_circuit_with_witness(TurboComposer& composer, +void create_circuit_with_witness(plonk::stdlib::types::Composer& composer, const acir_format& constraint_system, std::vector witness); diff --git a/cpp/src/barretenberg/dsl/acir_format/acir_format.test.cpp b/cpp/src/barretenberg/dsl/acir_format/acir_format.test.cpp new file mode 100644 index 0000000000..ff957c6b9b --- /dev/null +++ b/cpp/src/barretenberg/dsl/acir_format/acir_format.test.cpp @@ -0,0 +1,252 @@ +#include "acir_format.hpp" +#include "barretenberg/plonk/proof_system/types/proof.hpp" +#include +#include +#include "barretenberg/common/streams.hpp" + +TEST(acir_format, test_logic_gate_from_noir_circuit) +{ + /** + * constraints produced by Noir program: + * fn main(x : u32, y : pub u32) { + * let z = x ^ y; + * + * constrain z != 10; + * } + **/ + acir_format::RangeConstraint range_a{ + .witness = 1, + .num_bits = 32, + }; + acir_format::RangeConstraint range_b{ + .witness = 2, + .num_bits = 32, + }; + + acir_format::LogicConstraint logic_constraint{ + .a = 1, + .b = 2, + .result = 3, + .num_bits = 32, + .is_xor_gate = 1, + }; + poly_triple expr_a{ + .a = 3, + .b = 4, + .c = 0, + .q_m = 0, + .q_l = 1, + .q_r = -1, + .q_o = 0, + .q_c = -10, + }; + poly_triple expr_b{ + .a = 4, + .b = 5, + .c = 6, + .q_m = 1, + .q_l = 0, + .q_r = 0, + .q_o = -1, + .q_c = 0, + }; + poly_triple expr_c{ + .a = 4, + .b = 6, + .c = 4, + .q_m = 1, + .q_l = 0, + .q_r = 0, + .q_o = -1, + .q_c = 0, + + }; + poly_triple expr_d{ + .a = 6, + .b = 0, + .c = 0, + .q_m = 0, + .q_l = -1, + .q_r = 0, + .q_o = 0, + .q_c = 1, + }; + // EXPR [ (1, _4, _5) (-1, _6) 0 ] + // EXPR [ (1, _4, _6) (-1, _4) 0 ] + // EXPR [ (-1, _6) 1 ] + std::cout << "made struct" << std::endl; + + acir_format::acir_format constraint_system{ + .varnum = 7, + .public_inputs = { 2 }, + .fixed_base_scalar_mul_constraints = {}, + .logic_constraints = { logic_constraint }, + .range_constraints = { range_a, range_b }, + .schnorr_constraints = {}, + .ecdsa_constraints = {}, + .sha256_constraints = {}, + .blake2s_constraints = {}, + .hash_to_field_constraints = {}, + .pedersen_constraints = {}, + .merkle_membership_constraints = {}, + .constraints = { expr_a, expr_b, expr_c, expr_d }, + }; + + uint256_t inverse_of_five = fr(5).invert(); + auto composer = acir_format::create_circuit_with_witness(constraint_system, + { + 5, + 10, + 15, + 5, + inverse_of_five, + 1, + }); + + std::cout << "made composer" << std::endl; + + auto prover = composer.create_prover(); + auto proof = prover.construct_proof(); + + auto verifier = composer.create_verifier(); + + EXPECT_EQ(verifier.verify_proof(proof), true); +} + +TEST(acir_format, test_schnorr_verify_pass) +{ + std::vector range_constraints; + for (uint32_t i = 0; i < 10; i++) { + range_constraints.push_back(acir_format::RangeConstraint{ + .witness = i + 1, + .num_bits = 15, + }); + } + + std::vector signature(64); + for (uint32_t i = 0, value = 13; i < 64; i++, value++) { + signature[i] = value; + range_constraints.push_back(acir_format::RangeConstraint{ + .witness = value, + .num_bits = 15, + }); + } + + acir_format::SchnorrConstraint schnorr_constraint{ + .message = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }, + .public_key_x = 11, + .public_key_y = 12, + .result = 77, + .signature = signature, + }; + + acir_format::acir_format constraint_system{ + .varnum = 82, + .public_inputs = {}, + .fixed_base_scalar_mul_constraints = {}, + .logic_constraints = {}, + .range_constraints = range_constraints, + .schnorr_constraints = { schnorr_constraint }, + .ecdsa_constraints = {}, + .sha256_constraints = {}, + .blake2s_constraints = {}, + .hash_to_field_constraints = {}, + .pedersen_constraints = {}, + .merkle_membership_constraints = {}, + .constraints = { poly_triple{ + .a = schnorr_constraint.result, + .b = schnorr_constraint.result, + .c = schnorr_constraint.result, + .q_m = 0, + .q_l = 0, + .q_r = 0, + .q_o = 1, + .q_c = fr::neg_one(), + } }, + }; + uint256_t pub_x = uint256_t("17cbd3ed3151ccfd170efe1d54280a6a4822640bf5c369908ad74ea21518a9c5"); + uint256_t pub_y = uint256_t("0e0456e3795c1a31f20035b741cd6158929eeccd320d299cfcac962865a6bc74"); + + auto composer = acir_format::create_circuit_with_witness( + constraint_system, + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, pub_x, pub_y, 5, 202, 31, 146, 81, 242, 246, 69, + 43, 107, 249, 153, 198, 44, 14, 111, 191, 121, 137, 166, 160, 103, 18, 181, 243, 233, 226, 95, + 67, 16, 37, 128, 85, 76, 19, 253, 30, 77, 192, 53, 138, 205, 69, 33, 236, 163, 83, 194, + 84, 137, 184, 221, 176, 121, 179, 27, 63, 70, 54, 16, 176, 250, 39, 239, 1, 0, 0, 0 }); + + auto prover = composer.create_prover(); + auto proof = prover.construct_proof(); + + auto verifier = composer.create_verifier(); + + EXPECT_EQ(verifier.verify_proof(proof), true); +} + +TEST(acir_format, test_schnorr_verify_small_range) +{ + std::vector range_constraints; + for (uint32_t i = 0; i < 10; i++) { + range_constraints.push_back(acir_format::RangeConstraint{ + .witness = i + 1, + .num_bits = 8, + }); + } + + std::vector signature(64); + for (uint32_t i = 0, value = 13; i < 64; i++, value++) { + signature[i] = value; + range_constraints.push_back(acir_format::RangeConstraint{ + .witness = value, + .num_bits = 8, + }); + } + + acir_format::SchnorrConstraint schnorr_constraint{ + .message = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }, + .public_key_x = 11, + .public_key_y = 12, + .result = 77, + .signature = signature, + }; + + acir_format::acir_format constraint_system{ + .varnum = 82, + .public_inputs = {}, + .fixed_base_scalar_mul_constraints = {}, + .logic_constraints = {}, + .range_constraints = range_constraints, + .schnorr_constraints = { schnorr_constraint }, + .ecdsa_constraints = {}, + .sha256_constraints = {}, + .blake2s_constraints = {}, + .hash_to_field_constraints = {}, + .pedersen_constraints = {}, + .merkle_membership_constraints = {}, + .constraints = { poly_triple{ + .a = schnorr_constraint.result, + .b = schnorr_constraint.result, + .c = schnorr_constraint.result, + .q_m = 0, + .q_l = 0, + .q_r = 0, + .q_o = 1, + .q_c = fr::neg_one(), + } }, + }; + uint256_t pub_x = uint256_t("17cbd3ed3151ccfd170efe1d54280a6a4822640bf5c369908ad74ea21518a9c5"); + uint256_t pub_y = uint256_t("0e0456e3795c1a31f20035b741cd6158929eeccd320d299cfcac962865a6bc74"); + + auto composer = acir_format::create_circuit_with_witness( + constraint_system, + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, pub_x, pub_y, 5, 202, 31, 146, 81, 242, 246, 69, + 43, 107, 249, 153, 198, 44, 14, 111, 191, 121, 137, 166, 160, 103, 18, 181, 243, 233, 226, 95, + 67, 16, 37, 128, 85, 76, 19, 253, 30, 77, 192, 53, 138, 205, 69, 33, 236, 163, 83, 194, + 84, 137, 184, 221, 176, 121, 179, 27, 63, 70, 54, 16, 176, 250, 39, 239, 1, 0, 0, 0 }); + + auto prover = composer.create_prover(); + auto proof = prover.construct_proof(); + + auto verifier = composer.create_verifier(); + + EXPECT_EQ(verifier.verify_proof(proof), true); +} \ No newline at end of file diff --git a/cpp/src/barretenberg/dsl/acir_format/blake2s_constraint.cpp b/cpp/src/barretenberg/dsl/acir_format/blake2s_constraint.cpp index 38876d0a5b..56fe6a521f 100644 --- a/cpp/src/barretenberg/dsl/acir_format/blake2s_constraint.cpp +++ b/cpp/src/barretenberg/dsl/acir_format/blake2s_constraint.cpp @@ -1,12 +1,11 @@ #include "blake2s_constraint.hpp" #include "round.hpp" -#include "barretenberg/stdlib/types/types.hpp" using namespace plonk::stdlib::types; namespace acir_format { -void create_blake2s_constraints(plonk::TurboComposer& composer, const Blake2sConstraint& constraint) +void create_blake2s_constraints(Composer& composer, const Blake2sConstraint& constraint) { // Create byte array struct @@ -27,7 +26,7 @@ void create_blake2s_constraints(plonk::TurboComposer& composer, const Blake2sCon arr.write(element_bytes); } - byte_array_ct output_bytes = plonk::stdlib::blake2s(arr); + byte_array_ct output_bytes = plonk::stdlib::blake2s(arr); // Convert byte array to vector of field_t auto bytes = output_bytes.bytes(); diff --git a/cpp/src/barretenberg/dsl/acir_format/blake2s_constraint.hpp b/cpp/src/barretenberg/dsl/acir_format/blake2s_constraint.hpp index e4ce915b5a..643eb1e39b 100644 --- a/cpp/src/barretenberg/dsl/acir_format/blake2s_constraint.hpp +++ b/cpp/src/barretenberg/dsl/acir_format/blake2s_constraint.hpp @@ -1,7 +1,7 @@ #pragma once #include #include -#include "barretenberg/plonk/composer/turbo_composer.hpp" +#include "barretenberg/stdlib/types/types.hpp" namespace acir_format { @@ -19,7 +19,7 @@ struct Blake2sConstraint { friend bool operator==(Blake2sConstraint const& lhs, Blake2sConstraint const& rhs) = default; }; -void create_blake2s_constraints(plonk::TurboComposer& composer, const Blake2sConstraint& constraint); +void create_blake2s_constraints(plonk::stdlib::types::Composer& composer, const Blake2sConstraint& constraint); template inline void read(B& buf, Blake2sInput& constraint) { diff --git a/cpp/src/barretenberg/dsl/acir_format/ecdsa_secp256k1.cpp b/cpp/src/barretenberg/dsl/acir_format/ecdsa_secp256k1.cpp index 5d495775d7..4287faf643 100644 --- a/cpp/src/barretenberg/dsl/acir_format/ecdsa_secp256k1.cpp +++ b/cpp/src/barretenberg/dsl/acir_format/ecdsa_secp256k1.cpp @@ -1,13 +1,12 @@ #include "ecdsa_secp256k1.hpp" #include "barretenberg/crypto/ecdsa/ecdsa.hpp" #include "barretenberg/stdlib/encryption/ecdsa/ecdsa.hpp" -#include "barretenberg/stdlib/types/types.hpp" using namespace plonk::stdlib::types; namespace acir_format { -crypto::ecdsa::signature ecdsa_convert_signature(plonk::TurboComposer& composer, std::vector signature) +crypto::ecdsa::signature ecdsa_convert_signature(Composer& composer, std::vector signature) { crypto::ecdsa::signature signature_cr; @@ -42,7 +41,7 @@ crypto::ecdsa::signature ecdsa_convert_signature(plonk::TurboComposer& composer, return signature_cr; } -secp256k1_ct::g1_ct ecdsa_convert_inputs(plonk::TurboComposer* ctx, const secp256k1::g1::affine_element& input) +secp256k1_ct::g1_ct ecdsa_convert_inputs(Composer* ctx, const secp256k1::g1::affine_element& input) { uint256_t x_u256(input.x); uint256_t y_u256(input.y); @@ -61,7 +60,7 @@ secp256k1_ct::g1_ct ecdsa_convert_inputs(plonk::TurboComposer* ctx, const secp25 // 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(plonk::TurboComposer& composer, std::vector vector_of_bytes) +byte_array_ct ecdsa_vector_of_bytes_to_byte_array(Composer& composer, std::vector vector_of_bytes) { byte_array_ct arr(&composer); @@ -77,13 +76,13 @@ byte_array_ct ecdsa_vector_of_bytes_to_byte_array(plonk::TurboComposer& composer } return arr; } -witness_ct ecdsa_index_to_witness(plonk::TurboComposer& composer, uint32_t index) +witness_ct ecdsa_index_to_witness(Composer& composer, uint32_t index) { fr value = composer.get_variable(index); return { &composer, value }; } -void create_ecdsa_verify_constraints(plonk::TurboComposer& composer, const EcdsaSecp256k1Constraint& input) +void create_ecdsa_verify_constraints(Composer& composer, const EcdsaSecp256k1Constraint& input) { auto new_sig = ecdsa_convert_signature(composer, input.signature); @@ -98,15 +97,15 @@ void create_ecdsa_verify_constraints(plonk::TurboComposer& composer, const Ecdsa std::vector rr(new_sig.r.begin(), new_sig.r.end()); std::vector ss(new_sig.s.begin(), new_sig.s.end()); - stdlib::ecdsa::signature sig{ stdlib::byte_array(&composer, rr), - stdlib::byte_array(&composer, ss) }; + stdlib::ecdsa::signature sig{ stdlib::byte_array(&composer, rr), + stdlib::byte_array(&composer, ss) }; 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); - bool_ct signature_result = stdlib::ecdsa::verify_signature -#include "barretenberg/plonk/composer/turbo_composer.hpp" +#include "barretenberg/stdlib/types/types.hpp" namespace acir_format { @@ -28,7 +28,7 @@ struct EcdsaSecp256k1Constraint { friend bool operator==(EcdsaSecp256k1Constraint const& lhs, EcdsaSecp256k1Constraint const& rhs) = default; }; -void create_ecdsa_verify_constraints(plonk::TurboComposer& composer, const EcdsaSecp256k1Constraint& input); +void create_ecdsa_verify_constraints(plonk::stdlib::types::Composer& composer, const EcdsaSecp256k1Constraint& input); template inline void read(B& buf, EcdsaSecp256k1Constraint& constraint) { diff --git a/cpp/src/barretenberg/dsl/acir_format/fixed_base_scalar_mul.cpp b/cpp/src/barretenberg/dsl/acir_format/fixed_base_scalar_mul.cpp index db5383927c..6e829a8a9a 100644 --- a/cpp/src/barretenberg/dsl/acir_format/fixed_base_scalar_mul.cpp +++ b/cpp/src/barretenberg/dsl/acir_format/fixed_base_scalar_mul.cpp @@ -1,11 +1,10 @@ #include "fixed_base_scalar_mul.hpp" -#include "barretenberg/stdlib/types/types.hpp" using namespace plonk::stdlib::types; namespace acir_format { -void create_fixed_base_constraint(plonk::TurboComposer& composer, const FixedBaseScalarMul& input) +void create_fixed_base_constraint(Composer& composer, const FixedBaseScalarMul& input) { field_ct scalar_as_field = field_ct::from_witness_index(&composer, input.scalar); diff --git a/cpp/src/barretenberg/dsl/acir_format/fixed_base_scalar_mul.hpp b/cpp/src/barretenberg/dsl/acir_format/fixed_base_scalar_mul.hpp index 672978bac6..2b61305a5c 100644 --- a/cpp/src/barretenberg/dsl/acir_format/fixed_base_scalar_mul.hpp +++ b/cpp/src/barretenberg/dsl/acir_format/fixed_base_scalar_mul.hpp @@ -1,6 +1,6 @@ #pragma once #include -#include "barretenberg/plonk/composer/turbo_composer.hpp" +#include "barretenberg/stdlib/types/types.hpp" namespace acir_format { @@ -12,7 +12,7 @@ struct FixedBaseScalarMul { friend bool operator==(FixedBaseScalarMul const& lhs, FixedBaseScalarMul const& rhs) = default; }; -void create_fixed_base_constraint(plonk::TurboComposer& composer, const FixedBaseScalarMul& input); +void create_fixed_base_constraint(plonk::stdlib::types::Composer& composer, const FixedBaseScalarMul& input); template inline void read(B& buf, FixedBaseScalarMul& constraint) { diff --git a/cpp/src/barretenberg/dsl/acir_format/hash_to_field.cpp b/cpp/src/barretenberg/dsl/acir_format/hash_to_field.cpp index 577c3b6bac..564cd13c2e 100644 --- a/cpp/src/barretenberg/dsl/acir_format/hash_to_field.cpp +++ b/cpp/src/barretenberg/dsl/acir_format/hash_to_field.cpp @@ -1,12 +1,11 @@ #include "hash_to_field.hpp" #include "round.hpp" -#include "barretenberg/stdlib/types/types.hpp" using namespace plonk::stdlib::types; namespace acir_format { -void create_hash_to_field_constraints(plonk::TurboComposer& composer, const HashToFieldConstraint constraint) +void create_hash_to_field_constraints(Composer& composer, const HashToFieldConstraint constraint) { // Create byte array struct @@ -31,7 +30,7 @@ void create_hash_to_field_constraints(plonk::TurboComposer& composer, const Hash // Hash To Field using blake2s. // Note: It does not need to be blake2s in the future - byte_array_ct out_bytes = plonk::stdlib::blake2s(arr); + byte_array_ct out_bytes = plonk::stdlib::blake2s(arr); field_ct out(out_bytes); field_ct normalised_out = out.normalize(); diff --git a/cpp/src/barretenberg/dsl/acir_format/hash_to_field.hpp b/cpp/src/barretenberg/dsl/acir_format/hash_to_field.hpp index 6f8b901b57..275ce3fd0d 100644 --- a/cpp/src/barretenberg/dsl/acir_format/hash_to_field.hpp +++ b/cpp/src/barretenberg/dsl/acir_format/hash_to_field.hpp @@ -1,7 +1,7 @@ #pragma once #include #include -#include "barretenberg/plonk/composer/turbo_composer.hpp" +#include "barretenberg/stdlib/types/types.hpp" namespace acir_format { @@ -19,7 +19,7 @@ struct HashToFieldConstraint { friend bool operator==(HashToFieldConstraint const& lhs, HashToFieldConstraint const& rhs) = default; }; -void create_hash_to_field_constraints(plonk::TurboComposer& composer, HashToFieldConstraint constraint); +void create_hash_to_field_constraints(plonk::stdlib::types::Composer& composer, HashToFieldConstraint constraint); template inline void read(B& buf, HashToFieldInput& constraint) { diff --git a/cpp/src/barretenberg/dsl/acir_format/logic_constraint.cpp b/cpp/src/barretenberg/dsl/acir_format/logic_constraint.cpp index 27d938fbf6..b25530fa80 100644 --- a/cpp/src/barretenberg/dsl/acir_format/logic_constraint.cpp +++ b/cpp/src/barretenberg/dsl/acir_format/logic_constraint.cpp @@ -1,24 +1,24 @@ #include "logic_constraint.hpp" +#include "barretenberg/stdlib/primitives/logic/logic.hpp" + +using namespace plonk::stdlib::types; namespace acir_format { -void create_logic_gate(TurboComposer& composer, +void create_logic_gate(Composer& composer, const uint32_t a, const uint32_t b, const uint32_t result, const size_t num_bits, const bool is_xor_gate) { - auto accumulators = composer.create_logic_constraint(a, b, num_bits, is_xor_gate); - composer.assert_equal(accumulators.out.back(), result); -} -void xor_gate(TurboComposer& composer, const uint32_t a, const uint32_t b, const uint32_t result, const size_t num_bits) -{ - create_logic_gate(composer, a, b, result, num_bits, true); -} -void and_gate(TurboComposer& composer, const uint32_t a, const uint32_t b, const uint32_t result, const size_t num_bits) -{ - create_logic_gate(composer, a, b, result, num_bits, false); + + field_ct left = field_ct::from_witness_index(&composer, a); + field_ct right = field_ct::from_witness_index(&composer, b); + + field_ct res = stdlib::logic::create_logic_constraint(left, right, num_bits, is_xor_gate); + field_ct our_res = field_ct::from_witness_index(&composer, result); + res.assert_equal(our_res); } } // namespace acir_format diff --git a/cpp/src/barretenberg/dsl/acir_format/logic_constraint.hpp b/cpp/src/barretenberg/dsl/acir_format/logic_constraint.hpp index 51dfb73db5..0a194838ad 100644 --- a/cpp/src/barretenberg/dsl/acir_format/logic_constraint.hpp +++ b/cpp/src/barretenberg/dsl/acir_format/logic_constraint.hpp @@ -1,6 +1,6 @@ #pragma once #include -#include "barretenberg/plonk/composer/turbo_composer.hpp" +#include "barretenberg/stdlib/types/types.hpp" namespace acir_format { @@ -14,12 +14,16 @@ struct LogicConstraint { friend bool operator==(LogicConstraint const& lhs, LogicConstraint const& rhs) = default; }; -void create_logic_gate( - TurboComposer& composer, uint32_t a, uint32_t b, uint32_t result, size_t num_bits, bool is_xor_gate); +void create_logic_gate(plonk::stdlib::types::Composer& composer, + uint32_t a, + uint32_t b, + uint32_t result, + size_t num_bits, + bool is_xor_gate); -void xor_gate(TurboComposer& composer, uint32_t a, uint32_t b, uint32_t result, size_t num_bits); +void xor_gate(plonk::stdlib::types::Composer& composer, uint32_t a, uint32_t b, uint32_t result); -void and_gate(TurboComposer& composer, uint32_t a, uint32_t b, uint32_t result, size_t num_bits); +void and_gate(plonk::stdlib::types::Composer& composer, uint32_t a, uint32_t b, uint32_t result); template inline void read(B& buf, LogicConstraint& constraint) { diff --git a/cpp/src/barretenberg/dsl/acir_format/merkle_membership_constraint.cpp b/cpp/src/barretenberg/dsl/acir_format/merkle_membership_constraint.cpp index 65b746abcf..8ff90de39d 100644 --- a/cpp/src/barretenberg/dsl/acir_format/merkle_membership_constraint.cpp +++ b/cpp/src/barretenberg/dsl/acir_format/merkle_membership_constraint.cpp @@ -1,13 +1,12 @@ #include "merkle_membership_constraint.hpp" #include "barretenberg/stdlib/merkle_tree/membership.hpp" -#include "barretenberg/stdlib/types/types.hpp" using namespace plonk::stdlib::types; using namespace plonk::stdlib::merkle_tree; namespace acir_format { -void create_merkle_check_membership_constraint(plonk::TurboComposer& composer, const MerkleMembershipConstraint& input) +void create_merkle_check_membership_constraint(Composer& composer, const MerkleMembershipConstraint& input) { // Convert value from a witness index into a field element. // This is the hash of the message. In Barretenberg, this would be input.value = hash_value(message) @@ -23,7 +22,7 @@ void create_merkle_check_membership_constraint(plonk::TurboComposer& composer, c // We are given the HashPath as a Vec // We want to first convert it into a Vec<(fr, fr)> then cast this to hash_path // struct which requires the method create_witness_hashpath - hash_path hash_path; + hash_path hash_path; // In Noir we accept a hash path that only contains one hash per tree level // It is ok to reuse the leaf as it will be overridden in check_subtree_membership when computing the current root diff --git a/cpp/src/barretenberg/dsl/acir_format/merkle_membership_constraint.hpp b/cpp/src/barretenberg/dsl/acir_format/merkle_membership_constraint.hpp index 6cf9a78dd6..1fa1481e88 100644 --- a/cpp/src/barretenberg/dsl/acir_format/merkle_membership_constraint.hpp +++ b/cpp/src/barretenberg/dsl/acir_format/merkle_membership_constraint.hpp @@ -1,6 +1,6 @@ #pragma once #include -#include "barretenberg/plonk/composer/turbo_composer.hpp" +#include "barretenberg/stdlib/types/types.hpp" namespace acir_format { @@ -14,7 +14,8 @@ struct MerkleMembershipConstraint { friend bool operator==(MerkleMembershipConstraint const& lhs, MerkleMembershipConstraint const& rhs) = default; }; -void create_merkle_check_membership_constraint(plonk::TurboComposer& composer, const MerkleMembershipConstraint& input); +void create_merkle_check_membership_constraint(plonk::stdlib::types::Composer& composer, + const MerkleMembershipConstraint& input); template inline void read(B& buf, MerkleMembershipConstraint& constraint) { diff --git a/cpp/src/barretenberg/dsl/acir_format/pedersen.cpp b/cpp/src/barretenberg/dsl/acir_format/pedersen.cpp index 6bb7b9de9b..466929df42 100644 --- a/cpp/src/barretenberg/dsl/acir_format/pedersen.cpp +++ b/cpp/src/barretenberg/dsl/acir_format/pedersen.cpp @@ -1,11 +1,10 @@ #include "pedersen.hpp" -#include "barretenberg/stdlib/types/types.hpp" using namespace plonk::stdlib::types; namespace acir_format { -void create_pedersen_constraint(plonk::TurboComposer& composer, const PedersenConstraint& input) +void create_pedersen_constraint(Composer& composer, const PedersenConstraint& input) { std::vector scalars; @@ -14,7 +13,11 @@ void create_pedersen_constraint(plonk::TurboComposer& composer, const PedersenCo field_ct scalar_as_field = field_ct::from_witness_index(&composer, scalar); scalars.push_back(scalar_as_field); } +#ifdef USE_TURBO auto point = pedersen::commit(scalars); +#else + auto point = stdlib::pedersen_plookup::commit(scalars); +#endif composer.assert_equal(point.x.witness_index, input.result_x); composer.assert_equal(point.y.witness_index, input.result_y); diff --git a/cpp/src/barretenberg/dsl/acir_format/pedersen.hpp b/cpp/src/barretenberg/dsl/acir_format/pedersen.hpp index e53c51fef0..b801d2a8f2 100644 --- a/cpp/src/barretenberg/dsl/acir_format/pedersen.hpp +++ b/cpp/src/barretenberg/dsl/acir_format/pedersen.hpp @@ -1,6 +1,6 @@ #pragma once #include -#include "barretenberg/plonk/composer/turbo_composer.hpp" +#include "barretenberg/stdlib/types/types.hpp" namespace acir_format { @@ -13,7 +13,7 @@ struct PedersenConstraint { friend bool operator==(PedersenConstraint const& lhs, PedersenConstraint const& rhs) = default; }; -void create_pedersen_constraint(plonk::TurboComposer& composer, const PedersenConstraint& input); +void create_pedersen_constraint(plonk::stdlib::types::Composer& composer, const PedersenConstraint& input); template inline void read(B& buf, PedersenConstraint& constraint) { @@ -27,8 +27,8 @@ template inline void write(B& buf, PedersenConstraint const& constr { using serialize::write; write(buf, constraint.scalars); - read(buf, constraint.result_x); - read(buf, constraint.result_y); + write(buf, constraint.result_x); + write(buf, constraint.result_y); } } // namespace acir_format diff --git a/cpp/src/barretenberg/dsl/acir_format/schnorr_verify.cpp b/cpp/src/barretenberg/dsl/acir_format/schnorr_verify.cpp index 497bda7f9a..7c80c4208c 100644 --- a/cpp/src/barretenberg/dsl/acir_format/schnorr_verify.cpp +++ b/cpp/src/barretenberg/dsl/acir_format/schnorr_verify.cpp @@ -1,12 +1,11 @@ #include "schnorr_verify.hpp" #include "barretenberg/crypto/schnorr/schnorr.hpp" -#include "barretenberg/stdlib/types/types.hpp" using namespace plonk::stdlib::types; namespace acir_format { -crypto::schnorr::signature convert_signature(plonk::TurboComposer& composer, std::vector signature) +crypto::schnorr::signature convert_signature(Composer& composer, std::vector signature) { crypto::schnorr::signature signature_cr; @@ -43,7 +42,7 @@ crypto::schnorr::signature convert_signature(plonk::TurboComposer& composer, std // 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 vector_of_bytes_to_byte_array(plonk::TurboComposer& composer, std::vector vector_of_bytes) +byte_array_ct vector_of_bytes_to_byte_array(Composer& composer, std::vector vector_of_bytes) { byte_array_ct arr(&composer); @@ -59,13 +58,13 @@ byte_array_ct vector_of_bytes_to_byte_array(plonk::TurboComposer& composer, std: } return arr; } -witness_ct index_to_witness(plonk::TurboComposer& composer, uint32_t index) +witness_ct index_to_witness(Composer& composer, uint32_t index) { fr value = composer.get_variable(index); return { &composer, value }; } -void create_schnorr_verify_constraints(plonk::TurboComposer& composer, const SchnorrConstraint& input) +void create_schnorr_verify_constraints(Composer& composer, const SchnorrConstraint& input) { auto new_sig = convert_signature(composer, input.signature); diff --git a/cpp/src/barretenberg/dsl/acir_format/schnorr_verify.hpp b/cpp/src/barretenberg/dsl/acir_format/schnorr_verify.hpp index 8f0eec2222..f8e6b9c53f 100644 --- a/cpp/src/barretenberg/dsl/acir_format/schnorr_verify.hpp +++ b/cpp/src/barretenberg/dsl/acir_format/schnorr_verify.hpp @@ -1,6 +1,6 @@ #pragma once #include -#include "barretenberg/plonk/composer/turbo_composer.hpp" +#include "barretenberg/stdlib/types/types.hpp" namespace acir_format { @@ -25,7 +25,7 @@ struct SchnorrConstraint { friend bool operator==(SchnorrConstraint const& lhs, SchnorrConstraint const& rhs) = default; }; -void create_schnorr_verify_constraints(plonk::TurboComposer& composer, const SchnorrConstraint& input); +void create_schnorr_verify_constraints(plonk::stdlib::types::Composer& composer, const SchnorrConstraint& input); template inline void read(B& buf, SchnorrConstraint& constraint) { diff --git a/cpp/src/barretenberg/dsl/acir_format/sha256_constraint.cpp b/cpp/src/barretenberg/dsl/acir_format/sha256_constraint.cpp index b1c2fbe2a8..4da8a53567 100644 --- a/cpp/src/barretenberg/dsl/acir_format/sha256_constraint.cpp +++ b/cpp/src/barretenberg/dsl/acir_format/sha256_constraint.cpp @@ -1,7 +1,6 @@ #include "sha256_constraint.hpp" #include "round.hpp" #include "barretenberg/stdlib/hash/sha256/sha256.hpp" -#include "barretenberg/stdlib/types/types.hpp" using namespace plonk::stdlib::types; @@ -9,7 +8,7 @@ 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(plonk::TurboComposer& composer, const Sha256Constraint& constraint) +void create_sha256_constraints(Composer& composer, const Sha256Constraint& constraint) { // Create byte array struct @@ -31,7 +30,7 @@ void create_sha256_constraints(plonk::TurboComposer& composer, const Sha256Const } // Compute sha256 - byte_array_ct output_bytes = plonk::stdlib::sha256(arr); + byte_array_ct output_bytes = plonk::stdlib::sha256(arr); // Convert byte array to vector of field_t auto bytes = output_bytes.bytes(); diff --git a/cpp/src/barretenberg/dsl/acir_format/sha256_constraint.hpp b/cpp/src/barretenberg/dsl/acir_format/sha256_constraint.hpp index 08b60e0bd1..dec3bca40a 100644 --- a/cpp/src/barretenberg/dsl/acir_format/sha256_constraint.hpp +++ b/cpp/src/barretenberg/dsl/acir_format/sha256_constraint.hpp @@ -1,7 +1,7 @@ #pragma once #include #include -#include "barretenberg/plonk/composer/turbo_composer.hpp" +#include "barretenberg/stdlib/types/types.hpp" namespace acir_format { @@ -21,7 +21,7 @@ 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(plonk::TurboComposer& composer, const Sha256Constraint& constraint); +void create_sha256_constraints(plonk::stdlib::types::Composer& composer, const Sha256Constraint& constraint); template inline void read(B& buf, Sha256Input& constraint) { diff --git a/cpp/src/barretenberg/dsl/turbo_proofs/CMakeLists.txt b/cpp/src/barretenberg/dsl/acir_proofs/CMakeLists.txt similarity index 74% rename from cpp/src/barretenberg/dsl/turbo_proofs/CMakeLists.txt rename to cpp/src/barretenberg/dsl/acir_proofs/CMakeLists.txt index 066449db4a..9bdf62b9b7 100644 --- a/cpp/src/barretenberg/dsl/turbo_proofs/CMakeLists.txt +++ b/cpp/src/barretenberg/dsl/acir_proofs/CMakeLists.txt @@ -1,5 +1,5 @@ barretenberg_module( - turbo_proofs + acir_proofs acir_format plonk ) diff --git a/cpp/src/barretenberg/dsl/turbo_proofs/turbo_proofs.cpp b/cpp/src/barretenberg/dsl/acir_proofs/acir_proofs.cpp similarity index 66% rename from cpp/src/barretenberg/dsl/turbo_proofs/turbo_proofs.cpp rename to cpp/src/barretenberg/dsl/acir_proofs/acir_proofs.cpp index 233170dee8..ef70c7af1e 100644 --- a/cpp/src/barretenberg/dsl/turbo_proofs/turbo_proofs.cpp +++ b/cpp/src/barretenberg/dsl/acir_proofs/acir_proofs.cpp @@ -1,15 +1,35 @@ -#include "turbo_proofs.hpp" +#include "acir_proofs.hpp" #include "barretenberg/proof_system/proving_key/serialize.hpp" #include "barretenberg/dsl/acir_format/acir_format.hpp" #include "barretenberg/stdlib/types/types.hpp" #include "barretenberg/srs/reference_string/pippenger_reference_string.hpp" +#include "barretenberg/proof_system/verification_key/sol_gen.hpp" using namespace plonk::stdlib::types; -namespace turbo_proofs { +namespace acir_proofs { -uint32_t turbo_get_exact_circuit_size(uint8_t const* constraint_system_buf) +size_t get_solidity_verifier(uint8_t const* g2x, uint8_t const* vk_buf, uint8_t** output_buf) +{ + auto crs = std::make_shared(g2x); + bonk::verification_key_data vk_data; + read(vk_buf, vk_data); + auto verification_key = std::make_shared(std::move(vk_data), crs); + + std::ostringstream stream; + // TODO(blaine): Should we just use "VerificationKey" generically? + output_vk_sol(stream, verification_key, "UltraVerificationKey"); + + auto content_str = stream.str(); + auto raw_buf = (uint8_t*)malloc(content_str.size()); + memcpy(raw_buf, (void*)content_str.data(), content_str.size()); + *output_buf = raw_buf; + + return content_str.size(); +} + +uint32_t get_exact_circuit_size(uint8_t const* constraint_system_buf) { auto constraint_system = from_buffer(constraint_system_buf); auto crs_factory = std::make_unique(); @@ -19,9 +39,19 @@ uint32_t turbo_get_exact_circuit_size(uint8_t const* constraint_system_buf) return static_cast(num_gates); } -size_t turbo_init_proving_key(uint8_t const* constraint_system_buf, uint8_t const** pk_buf) +uint32_t get_total_circuit_size(uint8_t const* constraint_system_buf) { auto constraint_system = from_buffer(constraint_system_buf); + auto crs_factory = std::make_unique(); + auto composer = create_circuit(constraint_system, std::move(crs_factory)); + + return static_cast(composer.get_total_circuit_size()); +} + +size_t init_proving_key(uint8_t const* constraint_system_buf, uint8_t const** pk_buf) +{ + auto constraint_system = from_buffer(constraint_system_buf); + // We know that we don't actually need any CRS to create a proving key, so just feed in a nothing. // Hacky, but, right now it needs *something*. auto crs_factory = std::make_unique(); @@ -36,7 +66,7 @@ size_t turbo_init_proving_key(uint8_t const* constraint_system_buf, uint8_t cons return buffer.size(); } -size_t turbo_init_verification_key(void* pippenger, uint8_t const* g2x, uint8_t const* pk_buf, uint8_t const** vk_buf) +size_t init_verification_key(void* pippenger, uint8_t const* g2x, uint8_t const* pk_buf, uint8_t const** vk_buf) { std::shared_ptr crs; bonk::proving_key_data pk_data; @@ -47,13 +77,13 @@ size_t turbo_init_verification_key(void* pippenger, uint8_t const* g2x, uint8_t reinterpret_cast(pippenger), g2x); proving_key->reference_string = crs_factory->get_prover_crs(proving_key->circuit_size); - TurboComposer composer(proving_key, nullptr); + Composer composer(proving_key, nullptr); auto verification_key = plonk::stdlib::types::Composer::compute_verification_key_base(proving_key, crs_factory->get_verifier_crs()); // The composer_type has not yet been set. We need to set the composer_type for when we later read in and // construct the verification key so that we have the correct polynomial manifest - verification_key->composer_type = ComposerType::TURBO; + verification_key->composer_type = ComposerType::PLOOKUP; auto buffer = to_buffer(*verification_key); auto raw_buf = (uint8_t*)malloc(buffer.size()); @@ -63,12 +93,12 @@ size_t turbo_init_verification_key(void* pippenger, uint8_t const* g2x, uint8_t return buffer.size(); } -size_t turbo_new_proof(void* pippenger, - uint8_t const* g2x, - uint8_t const* pk_buf, - uint8_t const* constraint_system_buf, - uint8_t const* witness_buf, - uint8_t** proof_data_buf) +size_t new_proof(void* pippenger, + uint8_t const* g2x, + uint8_t const* pk_buf, + uint8_t const* constraint_system_buf, + uint8_t const* witness_buf, + uint8_t** proof_data_buf) { auto constraint_system = from_buffer(constraint_system_buf); @@ -83,18 +113,20 @@ size_t turbo_new_proof(void* pippenger, reinterpret_cast(pippenger), g2x); proving_key->reference_string = crs_factory->get_prover_crs(proving_key->circuit_size); - TurboComposer composer(proving_key, nullptr); + Composer composer(proving_key, nullptr); + create_circuit_with_witness(composer, constraint_system, witness); auto prover = composer.create_prover(); - auto heapProver = new TurboProver(std::move(prover)); + + auto heapProver = new stdlib::types::Prover(std::move(prover)); auto& proof_data = heapProver->construct_proof().proof_data; *proof_data_buf = proof_data.data(); return proof_data.size(); } -bool turbo_verify_proof( +bool verify_proof( uint8_t const* g2x, uint8_t const* vk_buf, uint8_t const* constraint_system_buf, uint8_t* proof, uint32_t length) { bool verified = false; @@ -103,13 +135,12 @@ bool turbo_verify_proof( try { #endif auto constraint_system = from_buffer(constraint_system_buf); - auto crs = std::make_shared(g2x); bonk::verification_key_data vk_data; read(vk_buf, vk_data); auto verification_key = std::make_shared(std::move(vk_data), crs); - TurboComposer composer(nullptr, verification_key); + Composer composer(nullptr, verification_key); create_circuit(composer, constraint_system); plonk::proof pp = { std::vector(proof, proof + length) }; @@ -125,4 +156,4 @@ bool turbo_verify_proof( return verified; } -} // namespace turbo_proofs +} // namespace acir_proofs diff --git a/cpp/src/barretenberg/dsl/acir_proofs/acir_proofs.hpp b/cpp/src/barretenberg/dsl/acir_proofs/acir_proofs.hpp new file mode 100644 index 0000000000..4bd126aae9 --- /dev/null +++ b/cpp/src/barretenberg/dsl/acir_proofs/acir_proofs.hpp @@ -0,0 +1,20 @@ +#include +#include + +namespace acir_proofs { + +size_t get_solidity_verifier(uint8_t const* g2x, uint8_t const* vk_buf, uint8_t** output_buf); +uint32_t get_exact_circuit_size(uint8_t const* constraint_system_buf); +uint32_t get_total_circuit_size(uint8_t const* constraint_system_buf); +size_t init_proving_key(uint8_t const* constraint_system_buf, uint8_t const** pk_buf); +size_t init_verification_key(void* pippenger, uint8_t const* g2x, uint8_t const* pk_buf, uint8_t const** vk_buf); +size_t new_proof(void* pippenger, + uint8_t const* g2x, + uint8_t const* pk_buf, + uint8_t const* constraint_system_buf, + uint8_t const* witness_buf, + uint8_t** proof_data_buf); +bool verify_proof( + uint8_t const* g2x, uint8_t const* vk_buf, uint8_t const* constraint_system_buf, uint8_t* proof, uint32_t length); + +} // namespace acir_proofs diff --git a/cpp/src/barretenberg/dsl/acir_proofs/c_bind.cpp b/cpp/src/barretenberg/dsl/acir_proofs/c_bind.cpp new file mode 100644 index 0000000000..4051aada3a --- /dev/null +++ b/cpp/src/barretenberg/dsl/acir_proofs/c_bind.cpp @@ -0,0 +1,53 @@ +#include "c_bind.hpp" +#include "acir_proofs.hpp" +#include + +#define WASM_EXPORT __attribute__((visibility("default"))) + +extern "C" { + +WASM_EXPORT size_t acir_proofs_get_solidity_verifier(uint8_t const* g2x, uint8_t const* vk_buf, uint8_t** output_buf) +{ + return acir_proofs::get_solidity_verifier(g2x, vk_buf, output_buf); +} + +// Get the exact circuit size for the constraint system. +WASM_EXPORT uint32_t acir_proofs_get_exact_circuit_size(uint8_t const* constraint_system_buf) +{ + return acir_proofs::get_exact_circuit_size(constraint_system_buf); +} + +WASM_EXPORT uint32_t acir_proofs_get_total_circuit_size(uint8_t const* constraint_system_buf) +{ + return acir_proofs::get_total_circuit_size(constraint_system_buf); +} + +WASM_EXPORT size_t acir_proofs_init_proving_key(uint8_t const* constraint_system_buf, uint8_t const** pk_buf) +{ + return acir_proofs::init_proving_key(constraint_system_buf, pk_buf); +} + +WASM_EXPORT size_t acir_proofs_init_verification_key(void* pippenger, + uint8_t const* g2x, + uint8_t const* pk_buf, + uint8_t const** vk_buf) +{ + return acir_proofs::init_verification_key(pippenger, g2x, pk_buf, vk_buf); +} + +WASM_EXPORT size_t acir_proofs_new_proof(void* pippenger, + uint8_t const* g2x, + uint8_t const* pk_buf, + uint8_t const* constraint_system_buf, + uint8_t const* witness_buf, + uint8_t** proof_data_buf) +{ + return acir_proofs::new_proof(pippenger, g2x, pk_buf, constraint_system_buf, witness_buf, proof_data_buf); +} + +WASM_EXPORT bool acir_proofs_verify_proof( + uint8_t const* g2x, uint8_t const* vk_buf, uint8_t const* constraint_system_buf, uint8_t* proof, uint32_t length) +{ + return acir_proofs::verify_proof(g2x, vk_buf, constraint_system_buf, proof, length); +} +} diff --git a/cpp/src/barretenberg/dsl/acir_proofs/c_bind.hpp b/cpp/src/barretenberg/dsl/acir_proofs/c_bind.hpp new file mode 100644 index 0000000000..a628c928cb --- /dev/null +++ b/cpp/src/barretenberg/dsl/acir_proofs/c_bind.hpp @@ -0,0 +1,25 @@ +#include +#include + +#define WASM_EXPORT __attribute__((visibility("default"))) + +extern "C" { + +WASM_EXPORT size_t acir_proofs_get_solidity_verifier(uint8_t const* g2x, uint8_t const* vk_buf, uint8_t** output_buf); +WASM_EXPORT uint32_t acir_proofs_get_exact_circuit_size(uint8_t const* constraint_system_buf); +WASM_EXPORT uint32_t acir_proofs_get_total_circuit_size(uint8_t const* constraint_system_buf); +// Construct composer using prover and verifier key buffers +WASM_EXPORT size_t acir_proofs_init_proving_key(uint8_t const* constraint_system_buf, uint8_t const** pk_buf); +WASM_EXPORT size_t acir_proofs_init_verification_key(void* pippenger, + uint8_t const* g2x, + uint8_t const* pk_buf, + uint8_t const** vk_buf); +WASM_EXPORT size_t acir_proofs_new_proof(void* pippenger, + uint8_t const* g2x, + uint8_t const* pk_buf, + uint8_t const* constraint_system_buf, + uint8_t const* witness_buf, + uint8_t** proof_data_buf); +WASM_EXPORT bool acir_proofs_verify_proof( + uint8_t const* g2x, uint8_t const* vk_buf, uint8_t const* constraint_system_buf, uint8_t* proof, uint32_t length); +} diff --git a/cpp/src/barretenberg/dsl/turbo_proofs/c_bind.cpp b/cpp/src/barretenberg/dsl/turbo_proofs/c_bind.cpp deleted file mode 100644 index 1b4cd27d84..0000000000 --- a/cpp/src/barretenberg/dsl/turbo_proofs/c_bind.cpp +++ /dev/null @@ -1,43 +0,0 @@ -#include "c_bind.hpp" -#include "turbo_proofs.hpp" -#include - -#define WASM_EXPORT __attribute__((visibility("default"))) - -extern "C" { - -// Get the exact circuit size for the constraint system. -WASM_EXPORT uint32_t turbo_get_exact_circuit_size(uint8_t const* constraint_system_buf) -{ - return turbo_proofs::turbo_get_exact_circuit_size(constraint_system_buf); -} - -WASM_EXPORT size_t turbo_init_proving_key(uint8_t const* constraint_system_buf, uint8_t const** pk_buf) -{ - return turbo_proofs::turbo_init_proving_key(constraint_system_buf, pk_buf); -} - -WASM_EXPORT size_t turbo_init_verification_key(void* pippenger, - uint8_t const* g2x, - uint8_t const* pk_buf, - uint8_t const** vk_buf) -{ - return turbo_proofs::turbo_init_verification_key(pippenger, g2x, pk_buf, vk_buf); -} - -WASM_EXPORT size_t turbo_new_proof(void* pippenger, - uint8_t const* g2x, - uint8_t const* pk_buf, - uint8_t const* constraint_system_buf, - uint8_t const* witness_buf, - uint8_t** proof_data_buf) -{ - return turbo_proofs::turbo_new_proof(pippenger, g2x, pk_buf, constraint_system_buf, witness_buf, proof_data_buf); -} - -WASM_EXPORT bool turbo_verify_proof( - uint8_t const* g2x, uint8_t const* vk_buf, uint8_t const* constraint_system_buf, uint8_t* proof, uint32_t length) -{ - return turbo_proofs::turbo_verify_proof(g2x, vk_buf, constraint_system_buf, proof, length); -} -} diff --git a/cpp/src/barretenberg/dsl/turbo_proofs/c_bind.hpp b/cpp/src/barretenberg/dsl/turbo_proofs/c_bind.hpp deleted file mode 100644 index e9ba3c5402..0000000000 --- a/cpp/src/barretenberg/dsl/turbo_proofs/c_bind.hpp +++ /dev/null @@ -1,24 +0,0 @@ -#include -#include - -#define WASM_EXPORT __attribute__((visibility("default"))) - -extern "C" { - -WASM_EXPORT uint32_t turbo_get_exact_circuit_size(uint8_t const* constraint_system_buf); - -// Construct composer using prover and verifier key buffers -WASM_EXPORT size_t turbo_init_proving_key(uint8_t const* constraint_system_buf, uint8_t const** pk_buf); -WASM_EXPORT size_t turbo_init_verification_key(void* pippenger, - uint8_t const* g2x, - uint8_t const* pk_buf, - uint8_t const** vk_buf); -WASM_EXPORT size_t turbo_new_proof(void* pippenger, - uint8_t const* g2x, - uint8_t const* pk_buf, - uint8_t const* constraint_system_buf, - uint8_t const* witness_buf, - uint8_t** proof_data_buf); -WASM_EXPORT bool turbo_verify_proof( - uint8_t const* g2x, uint8_t const* vk_buf, uint8_t const* constraint_system_buf, uint8_t* proof, uint32_t length); -} diff --git a/cpp/src/barretenberg/dsl/turbo_proofs/turbo_proofs.hpp b/cpp/src/barretenberg/dsl/turbo_proofs/turbo_proofs.hpp deleted file mode 100644 index 486973e418..0000000000 --- a/cpp/src/barretenberg/dsl/turbo_proofs/turbo_proofs.hpp +++ /dev/null @@ -1,18 +0,0 @@ -#include -#include - -namespace turbo_proofs { - -uint32_t turbo_get_exact_circuit_size(uint8_t const* constraint_system_buf); -size_t turbo_init_proving_key(uint8_t const* constraint_system_buf, uint8_t const** pk_buf); -size_t turbo_init_verification_key(void* pippenger, uint8_t const* g2x, uint8_t const* pk_buf, uint8_t const** vk_buf); -size_t turbo_new_proof(void* pippenger, - uint8_t const* g2x, - uint8_t const* pk_buf, - uint8_t const* constraint_system_buf, - uint8_t const* witness_buf, - uint8_t** proof_data_buf); -bool turbo_verify_proof( - uint8_t const* g2x, uint8_t const* vk_buf, uint8_t const* constraint_system_buf, uint8_t* proof, uint32_t length); - -} // namespace turbo_proofs diff --git a/cpp/src/barretenberg/join_split_example/proofs/join_split/c_bind.cpp b/cpp/src/barretenberg/join_split_example/proofs/join_split/c_bind.cpp index 67983ccd08..88ffa3bf80 100644 --- a/cpp/src/barretenberg/join_split_example/proofs/join_split/c_bind.cpp +++ b/cpp/src/barretenberg/join_split_example/proofs/join_split/c_bind.cpp @@ -42,9 +42,10 @@ WASM_EXPORT void join_split__release_key() WASM_EXPORT uint32_t join_split__get_new_proving_key_data(uint8_t** output) { - // Computing the size of the serialized key is non trivial. We know it's ~331mb. - // Allocate a buffer large enough to hold it, and abort if we overflow. - // This is to keep memory usage down. +// Computing the size of the serialized key is non trivial. We know it's ~331mb. +// Allocate a buffer large enough to hold it, and abort if we overflow. +// This is to keep memory usage down. +#ifdef USE_TURBO size_t total_buf_len = 350 * 1024 * 1024; auto raw_buf = (uint8_t*)malloc(total_buf_len); auto raw_buf_end = raw_buf; @@ -56,6 +57,15 @@ WASM_EXPORT uint32_t join_split__get_new_proving_key_data(uint8_t** output) std::abort(); } return len; +#else + auto proving_key = get_proving_key(); + auto buffer = to_buffer(*proving_key); + auto raw_buf = (uint8_t*)malloc(buffer.size()); + memcpy(raw_buf, (void*)buffer.data(), buffer.size()); + *output = raw_buf; + + return static_cast(buffer.size()); +#endif } WASM_EXPORT void join_split__init_verification_key(void* pippenger, uint8_t const* g2x) @@ -93,7 +103,7 @@ WASM_EXPORT void* join_split__new_prover(uint8_t const* join_split_buf, bool moc { auto tx = from_buffer(join_split_buf); auto prover = new_join_split_prover(tx, mock); - auto heapProver = new plonk::TurboProver(std::move(prover)); + auto heapProver = new stdlib::types::Prover(std::move(prover)); return heapProver; } diff --git a/cpp/src/barretenberg/join_split_example/proofs/join_split/join_split.cpp b/cpp/src/barretenberg/join_split_example/proofs/join_split/join_split.cpp index 64af4cbd25..213628a18f 100644 --- a/cpp/src/barretenberg/join_split_example/proofs/join_split/join_split.cpp +++ b/cpp/src/barretenberg/join_split_example/proofs/join_split/join_split.cpp @@ -23,7 +23,7 @@ void init_proving_key(std::shared_ptr const& crs_f join_split_tx tx = noop_tx(); if (!mock) { - Composer composer(crs_factory); + stdlib::types::Composer composer(crs_factory); join_split_circuit(composer, tx); proving_key = composer.compute_proving_key(); } else { @@ -64,7 +64,7 @@ void init_verification_key(std::shared_ptr con verification_key = std::make_shared(std::move(vk_data), crs); } -plonk::TurboProver new_join_split_prover(join_split_tx const& tx, bool mock) +stdlib::types::Prover new_join_split_prover(join_split_tx const& tx, bool mock) { Composer composer(proving_key, nullptr); join_split_circuit(composer, tx); @@ -89,10 +89,16 @@ plonk::TurboProver new_join_split_prover(join_split_tx const& tx, bool mock) bool verify_proof(plonk::proof const& proof) { - plonk::TurboVerifier verifier(verification_key, Composer::create_manifest(verification_key->num_public_inputs)); + plonk::stdlib::types::Verifier verifier(verification_key, + Composer::create_manifest(verification_key->num_public_inputs)); +#ifdef USE_TURBO std::unique_ptr> kate_commitment_scheme = std::make_unique>(); +#else + std::unique_ptr> kate_commitment_scheme = + std::make_unique>(); +#endif verifier.commitment_scheme = std::move(kate_commitment_scheme); return verifier.verify_proof(proof); diff --git a/cpp/src/barretenberg/join_split_example/proofs/join_split/join_split.hpp b/cpp/src/barretenberg/join_split_example/proofs/join_split/join_split.hpp index 274983ec80..e4fe781700 100644 --- a/cpp/src/barretenberg/join_split_example/proofs/join_split/join_split.hpp +++ b/cpp/src/barretenberg/join_split_example/proofs/join_split/join_split.hpp @@ -21,7 +21,7 @@ void init_verification_key(std::unique_ptr&& crs_f void init_verification_key(std::shared_ptr const& crs, bonk::verification_key_data&& vk_data); -plonk::TurboProver new_join_split_prover(join_split_tx const& tx, bool mock); +stdlib::types::Prover new_join_split_prover(join_split_tx const& tx, bool mock); bool verify_proof(plonk::proof const& proof); diff --git a/cpp/src/barretenberg/join_split_example/proofs/join_split/join_split.test.cpp b/cpp/src/barretenberg/join_split_example/proofs/join_split/join_split.test.cpp index c023322bbe..e7564dc63a 100644 --- a/cpp/src/barretenberg/join_split_example/proofs/join_split/join_split.test.cpp +++ b/cpp/src/barretenberg/join_split_example/proofs/join_split/join_split.test.cpp @@ -800,11 +800,17 @@ TEST_F(join_split_tests, test_0_input_notes_and_detect_circuit_change) EXPECT_TRUE(result.valid); - // The below part detects any changes in the join-split circuit +// The below part detects any changes in the join-split circuit +#ifdef USE_TURBO constexpr uint32_t CIRCUIT_GATE_COUNT = 64000; constexpr uint32_t GATES_NEXT_POWER_OF_TWO = 65536; const uint256_t VK_HASH("bb2062d006d31d3234766277711eb28577d5f6082d0f484b87e8235628f8e864"); +#else + constexpr uint32_t CIRCUIT_GATE_COUNT = 522850; + constexpr uint32_t GATES_NEXT_POWER_OF_TWO = 524288; + const uint256_t VK_HASH("012959f86e485f3a8f0b06c900082fca1c34b535cdf4f1088f03154ea655b401"); +#endif auto number_of_gates_js = result.number_of_gates; auto vk_hash_js = get_verification_key()->sha256_hash(); @@ -2613,11 +2619,15 @@ TEST_F(join_split_tests, test_send_two_virtual_notes_full_proof) // Miscellaneous // ************************************************************************************************************* -TEST_F(join_split_tests, serialzed_proving_key_size) +TEST_F(join_split_tests, serialized_proving_key_size) { uint8_t* ptr; auto len = join_split__get_new_proving_key_data(&ptr); +#ifdef USE_TURBO EXPECT_LE(len, 2 * 170 * 1024 * 1024); +#else + EXPECT_LE(len, 2315258552); +#endif } } // namespace join_split_example::proofs::join_split diff --git a/cpp/src/barretenberg/plonk/composer/composer_base.hpp b/cpp/src/barretenberg/plonk/composer/composer_base.hpp index c781241322..6f2c356510 100644 --- a/cpp/src/barretenberg/plonk/composer/composer_base.hpp +++ b/cpp/src/barretenberg/plonk/composer/composer_base.hpp @@ -107,6 +107,7 @@ class ComposerBase { virtual ~ComposerBase(){}; virtual size_t get_num_gates() const { return num_gates; } + virtual size_t get_total_circuit_size() const = 0; virtual void print_num_gates() const { std::cout << num_gates << std::endl; } virtual size_t get_num_variables() const { return variables.size(); } virtual std::shared_ptr compute_proving_key_base(const ComposerType type = STANDARD, diff --git a/cpp/src/barretenberg/plonk/composer/plookup_tables/uint.hpp b/cpp/src/barretenberg/plonk/composer/plookup_tables/uint.hpp index 41446d150b..05ccb4275e 100644 --- a/cpp/src/barretenberg/plonk/composer/plookup_tables/uint.hpp +++ b/cpp/src/barretenberg/plonk/composer/plookup_tables/uint.hpp @@ -64,7 +64,7 @@ inline BasicTable generate_and_rotate_table(BasicTableId id, const size_t table_ } } - table.get_values_from_key = &get_xor_rotate_values_from_key; + table.get_values_from_key = &get_and_rotate_values_from_key; table.column_1_step_size = base; table.column_2_step_size = base; diff --git a/cpp/src/barretenberg/plonk/composer/standard_composer.hpp b/cpp/src/barretenberg/plonk/composer/standard_composer.hpp index 20f490e22c..0a7015767f 100644 --- a/cpp/src/barretenberg/plonk/composer/standard_composer.hpp +++ b/cpp/src/barretenberg/plonk/composer/standard_composer.hpp @@ -79,6 +79,8 @@ class StandardComposer : public ComposerBase { StandardComposer& operator=(StandardComposer&& other) = default; ~StandardComposer() {} + virtual size_t get_total_circuit_size() const override { return num_gates; }; + void assert_equal_constant(uint32_t const a_idx, barretenberg::fr const& b, std::string const& msg = "assert equal constant"); diff --git a/cpp/src/barretenberg/plonk/composer/turbo_composer.hpp b/cpp/src/barretenberg/plonk/composer/turbo_composer.hpp index b089a85429..ab71116a85 100644 --- a/cpp/src/barretenberg/plonk/composer/turbo_composer.hpp +++ b/cpp/src/barretenberg/plonk/composer/turbo_composer.hpp @@ -23,6 +23,9 @@ class TurboComposer : public ComposerBase { virtual std::shared_ptr compute_proving_key() override; std::shared_ptr compute_verification_key() override; + + virtual size_t get_total_circuit_size() const override { return num_gates; }; + void compute_witness() override; TurboProver create_prover(); diff --git a/cpp/src/barretenberg/plonk/composer/ultra_composer.hpp b/cpp/src/barretenberg/plonk/composer/ultra_composer.hpp index 599e9e921b..769ec09a34 100644 --- a/cpp/src/barretenberg/plonk/composer/ultra_composer.hpp +++ b/cpp/src/barretenberg/plonk/composer/ultra_composer.hpp @@ -200,7 +200,22 @@ class UltraComposer : public ComposerBase { * gates. No arithemtic gate => size imbalance between sorted and non-sorted sets. Checking for this * and throwing an error would require a refactor of the Composer to catelog all 'orphan' variables not * assigned to gates. + * + * TODO(Suyash): + * The following is a temporary fix to make sure the range constraints on numbers with + * num_bits <= DEFAULT_PLOOKUP_RANGE_BITNUM is correctly enforced in the circuit. + * Longer term, as Zac says, we would need to refactor the composer to fix this. **/ + create_poly_gate(poly_triple{ + .a = variable_index, + .b = variable_index, + .c = variable_index, + .q_m = 0, + .q_l = 1, + .q_r = -1, + .q_o = 0, + .q_c = 0, + }); create_new_range_constraint(variable_index, 1ULL << num_bits, msg); } else { decompose_into_default_range(variable_index, num_bits, DEFAULT_PLOOKUP_RANGE_BITNUM, msg); @@ -327,6 +342,20 @@ class UltraComposer : public ComposerBase { return count + romcount + ramcount + rangecount; } + virtual size_t get_total_circuit_size() const override + { + size_t tables_size = 0; + size_t lookups_size = 0; + for (const auto& table : lookup_tables) { + tables_size += table.size; + lookups_size += table.lookup_gates.size(); + } + + auto minimum_circuit_size = tables_size + lookups_size; + auto num_filled_gates = num_gates + public_inputs.size(); + return std::max(minimum_circuit_size, num_filled_gates); + } + virtual void print_num_gates() const override { size_t count = 0; @@ -497,7 +526,8 @@ class UltraComposer : public ComposerBase { * @brief Each entry in ram_arrays represents an independent RAM table. * RamTranscript tracks the current table state, * as well as the 'records' produced by each read and write operation. - * Used in `compute_proving_key` to generate consistency check gates required to validate the RAM read/write history + * Used in `compute_proving_key` to generate consistency check gates required to validate the RAM read/write + * history */ std::vector ram_arrays; @@ -647,9 +677,9 @@ class UltraComposer : public ComposerBase { /** * @brief Create a unrolled manifest object * - * @note UP rolled/unrolled manifests are the same. Difference between regulur && unrolled Prover/Verifier is that - * unrolled Prover/Verifier uses 16-byte challenges and a SNARK-friendly hash algorithm to generate challenges. - * (i.e. unrolled Prover/Verifier is used in recursive setting) + * @note UP rolled/unrolled manifests are the same. Difference between regulur && unrolled Prover/Verifier is + * that unrolled Prover/Verifier uses 16-byte challenges and a SNARK-friendly hash algorithm to generate + * challenges. (i.e. unrolled Prover/Verifier is used in recursive setting) * * TODO: remove linearisation trick entirely from barretenberg and relabel `unrolled` to `recursive`! * @param num_public_inputs diff --git a/cpp/src/barretenberg/plonk/proof_system/constants.hpp b/cpp/src/barretenberg/plonk/proof_system/constants.hpp index 9d6229b039..f919f636cf 100644 --- a/cpp/src/barretenberg/plonk/proof_system/constants.hpp +++ b/cpp/src/barretenberg/plonk/proof_system/constants.hpp @@ -13,7 +13,11 @@ enum ComposerType { // This variable sets the composer (TURBO or ULTRA) of the entire stdlib and rollup modules. // To switch to using a new composer, only changing this variable should activate the new composer // throughout the stdlib and circuits. +#ifdef USE_TURBO static constexpr uint32_t SYSTEM_COMPOSER = ComposerType::TURBO; +#else +static constexpr uint32_t SYSTEM_COMPOSER = ComposerType::PLOOKUP; +#endif enum MerkleHashType { FIXED_BASE_PEDERSEN, diff --git a/cpp/src/barretenberg/plonk/proof_system/prover/prover.cpp b/cpp/src/barretenberg/plonk/proof_system/prover/prover.cpp index 96c3eff40f..12c5a3b1ea 100644 --- a/cpp/src/barretenberg/plonk/proof_system/prover/prover.cpp +++ b/cpp/src/barretenberg/plonk/proof_system/prover/prover.cpp @@ -417,7 +417,6 @@ template void ProverBase::execute_fourth_round() for (auto& widget : transition_widgets) { alpha_base = widget->compute_quotient_contribution(alpha_base, transcript); } - #ifdef DEBUG_TIMING start = std::chrono::steady_clock::now(); #endif diff --git a/cpp/src/barretenberg/proof_system/verification_key/sol_gen.hpp b/cpp/src/barretenberg/proof_system/verification_key/sol_gen.hpp index 096085b577..29fd773f0b 100644 --- a/cpp/src/barretenberg/proof_system/verification_key/sol_gen.hpp +++ b/cpp/src/barretenberg/proof_system/verification_key/sol_gen.hpp @@ -96,29 +96,29 @@ inline void output_vk_sol_ultra(std::ostream& os, std::shared_ptrnum_public_inputs, "vk.num_inputs"); print_u256("0x40", key->domain.root, "vk.work_root"); print_u256("0x60", key->domain.domain_inverse, "vk.domain_inverse"); - print_g1("0x80", "0xa0", key->constraint_selectors.at("Q_1"), "vk.Q1"); - print_g1("0xc0", "0xe0", key->constraint_selectors.at("Q_2"), "vk.Q2"); - print_g1("0x100", "0x120", key->constraint_selectors.at("Q_3"), "vk.Q3"); - print_g1("0x140", "0x160", key->constraint_selectors.at("Q_4"), "vk.Q4"); - print_g1("0x180", "0x1a0", key->constraint_selectors.at("Q_M"), "vk.Q_M"); - print_g1("0x1c0", "0x1e0", key->constraint_selectors.at("Q_C"), "vk.Q_C"); - print_g1("0x200", "0x220", key->constraint_selectors.at("Q_ARITHMETIC"), "vk.Q_ARITHMETIC"); - print_g1("0x240", "0x260", key->constraint_selectors.at("Q_SORT"), "vk.QSORT"); - print_g1("0x280", "0x2a0", key->constraint_selectors.at("Q_ELLIPTIC"), "vk.Q_ELLIPTIC"); - print_g1("0x2c0", "0x2e0", key->constraint_selectors.at("Q_AUX"), "vk.Q_AUX"); - print_g1("0x300", "0x320", key->permutation_selectors.at("SIGMA_1"), "vk.SIGMA1"); - print_g1("0x340", "0x360", key->permutation_selectors.at("SIGMA_2"), "vk.SIGMA2"); - print_g1("0x380", "0x3a0", key->permutation_selectors.at("SIGMA_3"), "vk.SIGMA3"); - print_g1("0x3c0", "0x3e0", key->permutation_selectors.at("SIGMA_4"), "vk.SIGMA4"); - print_g1("0x400", "0x420", key->constraint_selectors.at("TABLE_1"), "vk.TABLE1"); - print_g1("0x440", "0x460", key->constraint_selectors.at("TABLE_2"), "vk.TABLE2"); - print_g1("0x480", "0x4a0", key->constraint_selectors.at("TABLE_3"), "vk.TABLE3"); - print_g1("0x4c0", "0x4e0", key->constraint_selectors.at("TABLE_4"), "vk.TABLE4"); - print_g1("0x500", "0x520", key->constraint_selectors.at("TABLE_TYPE"), "vk.TABLE_TYPE"); - print_g1("0x540", "0x560", key->permutation_selectors.at("ID_1"), "vk.ID1"); - print_g1("0x580", "0x5a0", key->permutation_selectors.at("ID_2"), "vk.ID2"); - print_g1("0x5c0", "0x5e0", key->permutation_selectors.at("ID_3"), "vk.ID3"); - print_g1("0x600", "0x620", key->permutation_selectors.at("ID_4"), "vk.ID4"); + print_g1("0x80", "0xa0", key->commitments.at("Q_1"), "vk.Q1"); + print_g1("0xc0", "0xe0", key->commitments.at("Q_2"), "vk.Q2"); + print_g1("0x100", "0x120", key->commitments.at("Q_3"), "vk.Q3"); + print_g1("0x140", "0x160", key->commitments.at("Q_4"), "vk.Q4"); + print_g1("0x180", "0x1a0", key->commitments.at("Q_M"), "vk.Q_M"); + print_g1("0x1c0", "0x1e0", key->commitments.at("Q_C"), "vk.Q_C"); + print_g1("0x200", "0x220", key->commitments.at("Q_ARITHMETIC"), "vk.Q_ARITHMETIC"); + print_g1("0x240", "0x260", key->commitments.at("Q_SORT"), "vk.QSORT"); + print_g1("0x280", "0x2a0", key->commitments.at("Q_ELLIPTIC"), "vk.Q_ELLIPTIC"); + print_g1("0x2c0", "0x2e0", key->commitments.at("Q_AUX"), "vk.Q_AUX"); + print_g1("0x300", "0x320", key->commitments.at("SIGMA_1"), "vk.SIGMA1"); + print_g1("0x340", "0x360", key->commitments.at("SIGMA_2"), "vk.SIGMA2"); + print_g1("0x380", "0x3a0", key->commitments.at("SIGMA_3"), "vk.SIGMA3"); + print_g1("0x3c0", "0x3e0", key->commitments.at("SIGMA_4"), "vk.SIGMA4"); + print_g1("0x400", "0x420", key->commitments.at("TABLE_1"), "vk.TABLE1"); + print_g1("0x440", "0x460", key->commitments.at("TABLE_2"), "vk.TABLE2"); + print_g1("0x480", "0x4a0", key->commitments.at("TABLE_3"), "vk.TABLE3"); + print_g1("0x4c0", "0x4e0", key->commitments.at("TABLE_4"), "vk.TABLE4"); + print_g1("0x500", "0x520", key->commitments.at("TABLE_TYPE"), "vk.TABLE_TYPE"); + print_g1("0x540", "0x560", key->commitments.at("ID_1"), "vk.ID1"); + print_g1("0x580", "0x5a0", key->commitments.at("ID_2"), "vk.ID2"); + print_g1("0x5c0", "0x5e0", key->commitments.at("ID_3"), "vk.ID3"); + print_g1("0x600", "0x620", key->commitments.at("ID_4"), "vk.ID4"); os << " mstore(add(_vk, 0x640), " << (key->contains_recursive_proof ? "0x01" : "0x00") << ") // vk.contains_recursive_proof\n" " mstore(add(_vk, 0x660), " << (key->contains_recursive_proof ? key->recursive_proof_public_input_indices[0] : 0) << ") // vk.recursive_proof_public_input_indices\n" @@ -136,10 +136,10 @@ inline void output_vk_sol_ultra(std::ostream& os, std::shared_ptr const& key, std::string const& class_name) { diff --git a/cpp/src/barretenberg/proof_system/work_queue/work_queue.cpp b/cpp/src/barretenberg/proof_system/work_queue/work_queue.cpp index a6e2569cd5..ef8e51616b 100644 --- a/cpp/src/barretenberg/proof_system/work_queue/work_queue.cpp +++ b/cpp/src/barretenberg/proof_system/work_queue/work_queue.cpp @@ -247,18 +247,23 @@ void work_queue::process_queue() using namespace barretenberg; const size_t n = key->circuit_size; polynomial& wire = key->polynomial_store.get(item.tag); - polynomial wire_fft(4 * n + 4); polynomial wire_copy(wire, n); wire_copy.coset_fft_with_generator_shift(key->small_domain, item.constant); - for (size_t i = 0; i < n; ++i) { - wire_fft[4 * i + item.index] = wire_copy[i]; + if (item.index != 0) { + polynomial& old_wire_fft = key->polynomial_store.get(item.tag + "_fft"); + for (size_t i = 0; i < n; ++i) { + old_wire_fft[4 * i + item.index] = wire_copy[i]; + } + old_wire_fft[4 * n + item.index] = wire_copy[0]; + } else { + polynomial wire_fft(4 * n + 4); + for (size_t i = 0; i < n; ++i) { + wire_fft[4 * i + item.index] = wire_copy[i]; + } + key->polynomial_store.put(item.tag + "_fft", std::move(wire_fft)); } - wire_fft[4 * n + item.index] = wire_copy[0]; - - key->polynomial_store.put(item.tag + "_fft", 4 * n + 4); - break; } case WorkType::FFT: { diff --git a/cpp/src/barretenberg/stdlib/hash/pedersen/pedersen.test.cpp b/cpp/src/barretenberg/stdlib/hash/pedersen/pedersen.test.cpp index 9dc474f3ad..725d09752f 100644 --- a/cpp/src/barretenberg/stdlib/hash/pedersen/pedersen.test.cpp +++ b/cpp/src/barretenberg/stdlib/hash/pedersen/pedersen.test.cpp @@ -525,11 +525,41 @@ TEST(stdlib_pedersen, test_merkle_damgard_compress_plookup) } field_ct iv = witness_ct(&composer, fr(10)); - field_ct result = stdlib::pedersen_plookup::merkle_damgard_compress(inputs, iv).x; + auto result = stdlib::pedersen_plookup::merkle_damgard_compress(inputs, iv); auto expected = crypto::pedersen::lookup::merkle_damgard_compress(input_values, 10); - EXPECT_EQ(result.get_value(), expected.normalize().x); + EXPECT_EQ(result.x.get_value(), expected.normalize().x); + EXPECT_EQ(result.y.get_value(), expected.normalize().y); + + auto prover = composer.create_prover(); + + printf("composer gates = %zu\n", composer.get_num_gates()); + auto verifier = composer.create_verifier(); + + plonk::proof proof = prover.construct_proof(); + + bool proof_result = verifier.verify_proof(proof); + EXPECT_EQ(proof_result, true); +} + +TEST(stdlib_pedersen, test_merkle_damgard_compress_plookup_zero_one) +{ + plonk::UltraComposer composer = plonk::UltraComposer(); + + std::vector input_values{ 0, 1 }; + std::vector inputs; + for (const auto& input : input_values) { + inputs.emplace_back(witness_ct(&composer, input)); + } + field_ct iv = witness_ct(&composer, fr(10)); + + auto result = stdlib::pedersen_plookup::merkle_damgard_compress(inputs, iv); + + auto expected = crypto::pedersen::lookup::merkle_damgard_compress(input_values, 10); + + EXPECT_EQ(result.x.get_value(), expected.normalize().x); + EXPECT_EQ(result.y.get_value(), expected.normalize().y); auto prover = composer.create_prover(); diff --git a/cpp/src/barretenberg/stdlib/hash/pedersen/pedersen_plookup.cpp b/cpp/src/barretenberg/stdlib/hash/pedersen/pedersen_plookup.cpp index 964f9e6371..f2f3d85148 100644 --- a/cpp/src/barretenberg/stdlib/hash/pedersen/pedersen_plookup.cpp +++ b/cpp/src/barretenberg/stdlib/hash/pedersen/pedersen_plookup.cpp @@ -54,7 +54,7 @@ template point pedersen_plookup::add_points(const point& p1, if (p1_constant || p2_constant) { field_t lambda = (p2.y - p1.y) / (p2.x - p1.x); field_t x_3 = lambda.madd(lambda, -(p2.x + p1.x)); - field_t y_3 = lambda.madd(p1.x - x_3, p1.y); + field_t y_3 = lambda.madd(p1.x - x_3, -p1.y); return point{ x_3, y_3 }; } diff --git a/cpp/src/barretenberg/stdlib/hash/sha256/sha256.bench.cpp b/cpp/src/barretenberg/stdlib/hash/sha256/sha256.bench.cpp index 11685b4188..00d00082e1 100644 --- a/cpp/src/barretenberg/stdlib/hash/sha256/sha256.bench.cpp +++ b/cpp/src/barretenberg/stdlib/hash/sha256/sha256.bench.cpp @@ -28,9 +28,9 @@ void generate_test_plonk_circuit(Composer& composer, size_t num_bytes) plonk::stdlib::sha256(input); } -Composer composers[NUM_HASHES]; -plonk::TurboProver provers[NUM_HASHES]; -plonk::TurboVerifier verifiers[NUM_HASHES]; +stdlib::types::Composer composers[NUM_HASHES]; +stdlib::types::Prover provers[NUM_HASHES]; +stdlib::types::Verifier verifiers[NUM_HASHES]; plonk::proof proofs[NUM_HASHES]; void construct_witnesses_bench(State& state) noexcept diff --git a/cpp/src/barretenberg/stdlib/primitives/logic/logic.cpp b/cpp/src/barretenberg/stdlib/primitives/logic/logic.cpp new file mode 100644 index 0000000000..d3ae520aa8 --- /dev/null +++ b/cpp/src/barretenberg/stdlib/primitives/logic/logic.cpp @@ -0,0 +1,94 @@ +#include "logic.hpp" + +#include "../composers/composers.hpp" +#include "../plookup/plookup.hpp" + +namespace plonk { +namespace stdlib { + +/** + * @brief A logical AND or XOR over a variable number of bits. + * + * @details Defaults to basic Composer method if not using plookup-compatible composer + * + * @tparam Composer + * @param a + * @param b + * @param num_bits + * @param is_xor_gate + * @return field_t + */ +template +field_t logic::create_logic_constraint(field_pt& a, field_pt& b, size_t num_bits, bool is_xor_gate) +{ + // can't extend past field size! + ASSERT(num_bits < 254); + if (a.is_constant() && b.is_constant()) { + uint256_t a_native(a.get_value()); + uint256_t b_native(b.get_value()); + uint256_t c_native = is_xor_gate ? (a_native ^ b_native) : (a_native & b_native); + return field_t(c_native); + } + if (a.is_constant() && !b.is_constant()) { + Composer* ctx = b.get_context(); + uint256_t a_native(a.get_value()); + field_t a_witness = field_pt::from_witness_index(ctx, ctx->put_constant_variable(a_native)); + return create_logic_constraint(a_witness, b, num_bits, is_xor_gate); + } + if (!a.is_constant() && b.is_constant()) { + Composer* ctx = a.get_context(); + uint256_t b_native(b.get_value()); + field_pt b_witness = field_pt::from_witness_index(ctx, ctx->put_constant_variable(b_native)); + return create_logic_constraint(a, b_witness, num_bits, is_xor_gate); + } + if constexpr (Composer::type == ComposerType::PLOOKUP) { + Composer* ctx = a.get_context(); + + const size_t num_chunks = (num_bits / 32) + ((num_bits % 32 == 0) ? 0 : 1); + uint256_t left(a.get_value()); + uint256_t right(b.get_value()); + + field_pt res(ctx, 0); + for (size_t i = 0; i < num_chunks; ++i) { + uint256_t left_chunk = left & ((uint256_t(1) << 32) - 1); + uint256_t right_chunk = right & ((uint256_t(1) << 32) - 1); + + const field_pt a_chunk = witness_pt(ctx, left_chunk); + const field_pt b_chunk = witness_pt(ctx, right_chunk); + + field_pt result_chunk = 0; + if (is_xor_gate) { + result_chunk = + stdlib::plookup_read::read_from_2_to_1_table(plookup::MultiTableId::UINT32_XOR, a_chunk, b_chunk); + } else { + result_chunk = + stdlib::plookup_read::read_from_2_to_1_table(plookup::MultiTableId::UINT32_AND, a_chunk, b_chunk); + } + + uint256_t scaling_factor = uint256_t(1) << (32 * i); + res += result_chunk * scaling_factor; + + if (i == num_chunks - 1) { + const size_t final_num_bits = num_bits - (i * 32); + if (final_num_bits != 32) { + ctx->create_range_constraint(a_chunk.witness_index, final_num_bits, "bad range on a"); + ctx->create_range_constraint(b_chunk.witness_index, final_num_bits, "bad range on b"); + } + } + + left = left >> 32; + right = right >> 32; + } + + return res; + } else { + Composer* ctx = a.get_context(); + auto accumulator_triple = ctx->create_logic_constraint( + a.normalize().get_witness_index(), b.normalize().get_witness_index(), num_bits, is_xor_gate); + auto out_idx = accumulator_triple.out[accumulator_triple.out.size() - 1]; + return field_t::from_witness_index(ctx, out_idx); + } +} +INSTANTIATE_STDLIB_TYPE(logic); +} // namespace stdlib +} // namespace plonk diff --git a/cpp/src/barretenberg/stdlib/primitives/logic/logic.hpp b/cpp/src/barretenberg/stdlib/primitives/logic/logic.hpp new file mode 100644 index 0000000000..16423d3188 --- /dev/null +++ b/cpp/src/barretenberg/stdlib/primitives/logic/logic.hpp @@ -0,0 +1,20 @@ +#pragma once +#include "../composers/composers_fwd.hpp" +#include "../field/field.hpp" + +namespace plonk { +namespace stdlib { + +template class logic { + private: + typedef field_t field_pt; + typedef witness_t witness_pt; + + public: + static field_pt create_logic_constraint(field_pt& a, field_pt& b, size_t num_bits, bool is_xor_gate); +}; + +EXTERN_STDLIB_TYPE(logic); + +} // namespace stdlib +} // namespace plonk \ No newline at end of file diff --git a/cpp/src/barretenberg/stdlib/primitives/logic/logic.test.cpp b/cpp/src/barretenberg/stdlib/primitives/logic/logic.test.cpp new file mode 100644 index 0000000000..36f0384d2d --- /dev/null +++ b/cpp/src/barretenberg/stdlib/primitives/logic/logic.test.cpp @@ -0,0 +1,101 @@ +#include "../bool/bool.hpp" +#include "logic.hpp" +#include "barretenberg/plonk/proof_system/constants.hpp" +#include +#include "barretenberg/honk/composer/standard_honk_composer.hpp" +#include "barretenberg/plonk/composer/standard_composer.hpp" +#include "barretenberg/plonk/composer/ultra_composer.hpp" +#include "barretenberg/plonk/composer/turbo_composer.hpp" +#include "barretenberg/numeric/random/engine.hpp" + +using namespace bonk; + +namespace test_stdlib_logic { + +namespace { +auto& engine = numeric::random::get_debug_engine(); +} + +template void ignore_unused(T&) {} // use to ignore unused variables in lambdas + +using namespace barretenberg; +using namespace plonk; + +template class stdlib_logic : public testing::Test { + typedef stdlib::bool_t bool_ct; + typedef stdlib::field_t field_ct; + typedef stdlib::witness_t witness_ct; + typedef stdlib::public_witness_t public_witness_ct; + + public: + /** + * @brief Test logic + */ + static void test_logic() + { + Composer composer; + auto run_test = [&](size_t num_bits) { + uint256_t mask = (uint256_t(1) << num_bits) - 1; + + uint256_t a = engine.get_random_uint256() & mask; + uint256_t b = engine.get_random_uint256() & mask; + + uint256_t and_expected = a & b; + uint256_t xor_expected = a ^ b; + + field_ct x = witness_ct(&composer, a); + field_ct y = witness_ct(&composer, b); + + field_ct x_const(&composer, a); + field_ct y_const(&composer, b); + field_ct and_result = stdlib::logic::create_logic_constraint(x, y, num_bits, false); + field_ct xor_result = stdlib::logic::create_logic_constraint(x, y, num_bits, true); + + field_ct and_result_left_constant = + stdlib::logic::create_logic_constraint(x_const, y, num_bits, false); + field_ct xor_result_left_constant = + stdlib::logic::create_logic_constraint(x_const, y, num_bits, true); + + field_ct and_result_right_constant = + stdlib::logic::create_logic_constraint(x, y_const, num_bits, false); + field_ct xor_result_right_constant = + stdlib::logic::create_logic_constraint(x, y_const, num_bits, true); + + field_ct and_result_both_constant = + stdlib::logic::create_logic_constraint(x_const, y_const, num_bits, false); + field_ct xor_result_both_constant = + stdlib::logic::create_logic_constraint(x_const, y_const, num_bits, true); + + EXPECT_EQ(uint256_t(and_result.get_value()), and_expected); + EXPECT_EQ(uint256_t(and_result_left_constant.get_value()), and_expected); + EXPECT_EQ(uint256_t(and_result_right_constant.get_value()), and_expected); + EXPECT_EQ(uint256_t(and_result_both_constant.get_value()), and_expected); + + EXPECT_EQ(uint256_t(xor_result.get_value()), xor_expected); + EXPECT_EQ(uint256_t(xor_result_left_constant.get_value()), xor_expected); + EXPECT_EQ(uint256_t(xor_result_right_constant.get_value()), xor_expected); + EXPECT_EQ(uint256_t(xor_result_both_constant.get_value()), xor_expected); + }; + + for (size_t i = 8; i < 248; i += 8) { + run_test(i); + } + auto prover = composer.create_prover(); + plonk::proof proof = prover.construct_proof(); + auto verifier = composer.create_verifier(); + bool result = verifier.verify_proof(proof); + + EXPECT_EQ(result, true); + } +}; + +typedef testing::Types + ComposerTypes; + +TYPED_TEST_SUITE(stdlib_logic, ComposerTypes); + +TYPED_TEST(stdlib_logic, test_logic) +{ + TestFixture::test_logic(); +} +} // namespace test_stdlib_logic \ No newline at end of file diff --git a/cpp/src/barretenberg/stdlib/primitives/plookup/plookup.cpp b/cpp/src/barretenberg/stdlib/primitives/plookup/plookup.cpp index 76905d0753..ca69c95150 100644 --- a/cpp/src/barretenberg/stdlib/primitives/plookup/plookup.cpp +++ b/cpp/src/barretenberg/stdlib/primitives/plookup/plookup.cpp @@ -78,7 +78,7 @@ field_t plookup_::read_from_2_to_1_table(const MultiTableId { const auto lookup = get_lookup_accumulators(id, key_a, key_b, true); - return lookup[ColumnIdx::C2][0]; + return lookup[ColumnIdx::C3][0]; } template diff --git a/cpp/src/barretenberg/transcript/transcript.cpp b/cpp/src/barretenberg/transcript/transcript.cpp index 2e5d5e9e02..57b9cfa410 100644 --- a/cpp/src/barretenberg/transcript/transcript.cpp +++ b/cpp/src/barretenberg/transcript/transcript.cpp @@ -377,7 +377,6 @@ std::array Transcript::get_challenge_from * */ size_t Transcript::get_num_challenges(const std::string& challenge_name) const { - // printf("getting challenge count for %s \n", challenge_name.c_str()); ASSERT(challenges.count(challenge_name) == 1); return challenges.at(challenge_name).size(); @@ -393,7 +392,6 @@ size_t Transcript::get_num_challenges(const std::string& challenge_name) const * */ std::vector Transcript::get_element(const std::string& element_name) const { - // printf("getting element %s \n", element_name.c_str()); ASSERT(elements.count(element_name) == 1); return elements.at(element_name); }