From 848c682932c0902bdb8656f3c909f6fed195957f Mon Sep 17 00:00:00 2001 From: Maxim Vezenov Date: Wed, 19 Apr 2023 18:16:34 -0400 Subject: [PATCH 1/9] merge master in zw/noir-recursion --- cpp/CMakeLists.txt | 8 +- .../crypto/generators/generator_data.cpp | 10 +- .../dsl/acir_format/acir_format.cpp | 2 - .../dsl/acir_format/acir_format.hpp | 23 +- .../dsl/acir_format/acir_format.test.cpp | 12 +- .../dsl/acir_format/blake2s_constraint.cpp | 2 - .../dsl/acir_format/blake2s_constraint.hpp | 4 +- .../dsl/acir_format/ecdsa_secp256k1.cpp | 4 +- .../dsl/acir_format/ecdsa_secp256k1.hpp | 4 +- .../dsl/acir_format/fixed_base_scalar_mul.cpp | 2 - .../dsl/acir_format/fixed_base_scalar_mul.hpp | 4 +- .../dsl/acir_format/hash_to_field.cpp | 6 +- .../dsl/acir_format/hash_to_field.hpp | 4 +- .../dsl/acir_format/logic_constraint.cpp | 4 +- .../dsl/acir_format/logic_constraint.hpp | 13 +- .../merkle_membership_constraint.cpp | 7 +- .../merkle_membership_constraint.hpp | 5 +- .../barretenberg/dsl/acir_format/pedersen.cpp | 9 +- .../barretenberg/dsl/acir_format/pedersen.hpp | 4 +- .../dsl/acir_format/schnorr_verify.cpp | 9 +- .../dsl/acir_format/schnorr_verify.hpp | 4 +- .../dsl/acir_format/sha256_constraint.cpp | 3 +- .../dsl/acir_format/sha256_constraint.hpp | 4 +- .../dsl/acir_proofs/acir_proofs.cpp | 25 +- cpp/src/barretenberg/dsl/types.hpp | 72 ++ cpp/src/barretenberg/ecc/fields/field.hpp | 4 + .../standard_honk_composer_helper.cpp | 1 + .../ultra_honk_composer_helper.cpp | 356 ++++++ .../ultra_honk_composer_helper.hpp | 72 ++ .../composer/standard_honk_composer.test.cpp | 103 -- .../honk/composer/ultra_honk_composer.hpp | 470 ++++++++ .../composer/ultra_honk_composer.test.cpp | 1036 +++++++++++++++++ cpp/src/barretenberg/honk/flavor/flavor.hpp | 56 +- .../honk/proof_system/prover_library.cpp | 10 +- .../honk/proof_system/prover_library.test.cpp | 34 +- .../honk/proof_system/ultra_prover.cpp | 56 + .../honk/proof_system/ultra_prover.hpp | 63 + .../honk/proof_system/verifier.cpp | 1 - .../honk/proof_system/verifier.test.cpp | 1 - .../grand_product_computation_relation.hpp | 87 ++ .../grand_product_initialization_relation.hpp | 44 + .../honk/sumcheck/relations/relation.hpp | 1 - ...test.cpp => relation_consistency.test.cpp} | 232 +++- .../relations/relation_correctness.test.cpp | 258 ++++ .../relations/ultra_arithmetic_relation.hpp | 87 ++ .../ultra_arithmetic_relation_secondary.hpp | 67 ++ .../proofs/join_split/c_bind.cpp | 32 +- .../join_split/compute_circuit_data.cpp | 3 +- .../proofs/join_split/join_split.cpp | 16 +- .../proofs/join_split/join_split.hpp | 5 +- .../proofs/join_split/join_split.test.cpp | 22 +- .../proofs/join_split/join_split_circuit.cpp | 17 +- .../proofs/join_split/join_split_circuit.hpp | 13 +- .../proofs/join_split/join_split_tx.hpp | 8 +- .../proofs/mock/mock_circuit.test.cpp | 4 +- .../notes/circuit/account/account_note.hpp | 5 +- .../proofs/notes/circuit/account/commit.hpp | 6 +- .../proofs/notes/circuit/asset_id.cpp | 4 +- .../proofs/notes/circuit/asset_id.hpp | 4 +- .../proofs/notes/circuit/bridge_call_data.hpp | 4 +- .../proofs/notes/circuit/claim/claim_note.hpp | 5 +- .../claim/complete_partial_commitment.hpp | 5 +- .../notes/circuit/claim/compute_nullifier.hpp | 5 +- .../claim/create_partial_commitment.hpp | 4 +- .../notes/circuit/claim/witness_data.hpp | 5 +- .../value/complete_partial_commitment.hpp | 6 +- .../notes/circuit/value/compute_nullifier.cpp | 4 +- .../notes/circuit/value/compute_nullifier.hpp | 5 +- .../circuit/value/compute_nullifier.test.cpp | 6 +- .../value/create_partial_commitment.hpp | 6 +- .../proofs/notes/circuit/value/value_note.hpp | 4 +- .../notes/circuit/value/value_note.test.cpp | 8 +- .../notes/circuit/value/witness_data.hpp | 5 +- .../barretenberg/join_split_example/types.hpp | 50 + .../plonk/composer/ultra_composer.cpp | 58 + .../plonk/composer/ultra_composer.hpp | 3 + .../plonk/composer/ultra_composer.test.cpp | 256 ++-- .../kate_commitment_scheme.cpp | 1 + .../kate_commitment_scheme.hpp | 1 + .../plonk/proof_system/constants.hpp | 12 +- .../plonk/proof_system/prover/c_bind.cpp | 5 +- .../proof_system/prover/c_bind_unrolled.cpp | 110 -- .../plonk/proof_system/prover/prover.cpp | 2 + .../plonk/proof_system/prover/prover.hpp | 1 + .../types/polynomial_manifest.hpp | 2 +- .../proof_system/types/program_settings.hpp | 16 + .../proof_system/types/prover_settings.hpp | 8 + .../verification_key.test.cpp | 27 +- .../plonk/proof_system/verifier/verifier.cpp | 1 + .../plonk/proof_system/verifier/verifier.hpp | 3 +- .../composer/permutation_helper.hpp | 54 +- .../encryption/schnorr/schnorr.test.cpp | 45 +- .../stdlib/hash/blake2s/blake2s.test.cpp | 32 +- .../stdlib/hash/sha256/sha256.bench.cpp | 18 +- .../stdlib/hash/sha256/sha256.test.cpp | 88 +- .../barretenberg/stdlib/merkle_tree/hash.hpp | 24 +- .../stdlib/merkle_tree/hash.test.cpp | 30 +- .../stdlib/merkle_tree/membership.test.cpp | 42 +- .../stdlib/merkle_tree/merkle_tree.test.cpp | 12 +- .../primitives/biggroup/biggroup.test.cpp | 1 - .../primitives/byte_array/byte_array.test.cpp | 3 +- .../stdlib/primitives/group/group.test.cpp | 7 +- .../packed_byte_array.test.cpp | 11 +- .../primitives/safe_uint/safe_uint.test.cpp | 4 +- .../verification_key.test.cpp | 12 +- cpp/src/barretenberg/stdlib/types/types.hpp | 100 -- 106 files changed, 3591 insertions(+), 942 deletions(-) create mode 100644 cpp/src/barretenberg/dsl/types.hpp create mode 100644 cpp/src/barretenberg/honk/composer/composer_helper/ultra_honk_composer_helper.cpp create mode 100644 cpp/src/barretenberg/honk/composer/composer_helper/ultra_honk_composer_helper.hpp create mode 100644 cpp/src/barretenberg/honk/composer/ultra_honk_composer.hpp create mode 100644 cpp/src/barretenberg/honk/composer/ultra_honk_composer.test.cpp create mode 100644 cpp/src/barretenberg/honk/proof_system/ultra_prover.cpp create mode 100644 cpp/src/barretenberg/honk/proof_system/ultra_prover.hpp rename cpp/src/barretenberg/honk/sumcheck/relations/{relation.test.cpp => relation_consistency.test.cpp} (57%) create mode 100644 cpp/src/barretenberg/honk/sumcheck/relations/relation_correctness.test.cpp create mode 100644 cpp/src/barretenberg/honk/sumcheck/relations/ultra_arithmetic_relation.hpp create mode 100644 cpp/src/barretenberg/honk/sumcheck/relations/ultra_arithmetic_relation_secondary.hpp create mode 100644 cpp/src/barretenberg/join_split_example/types.hpp delete mode 100644 cpp/src/barretenberg/plonk/proof_system/prover/c_bind_unrolled.cpp delete mode 100644 cpp/src/barretenberg/stdlib/types/types.hpp diff --git a/cpp/CMakeLists.txt b/cpp/CMakeLists.txt index 582d728537..4f719a0335 100644 --- a/cpp/CMakeLists.txt +++ b/cpp/CMakeLists.txt @@ -22,14 +22,8 @@ option(SERIALIZE_CANARY "Build with serialize canary" OFF) option(ENABLE_ASAN "Address sanitizer for debugging tricky memory corruption" 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() +message(STATUS "Building barretenberg for UltraPlonk Composer.") if(CMAKE_SYSTEM_PROCESSOR MATCHES "aarch64" OR CMAKE_SYSTEM_PROCESSOR MATCHES "arm64") message(STATUS "Compiling for ARM.") diff --git a/cpp/src/barretenberg/crypto/generators/generator_data.cpp b/cpp/src/barretenberg/crypto/generators/generator_data.cpp index 7970dfe659..1ad6127923 100644 --- a/cpp/src/barretenberg/crypto/generators/generator_data.cpp +++ b/cpp/src/barretenberg/crypto/generators/generator_data.cpp @@ -6,18 +6,14 @@ namespace { // The number of unique base points with default main index with precomputed ladders #ifdef __wasm__ -constexpr size_t num_default_generators = 64; -constexpr size_t num_generators_per_hash_index = 16; -constexpr size_t num_hash_indices = 32; -// TODO need to resolve memory out of bounds when these are too high +constexpr size_t num_default_generators = 32; #else constexpr size_t num_default_generators = 2048; -constexpr size_t num_hash_indices = 32; -constexpr size_t num_generators_per_hash_index = 128; #endif constexpr size_t hash_indices_generator_offset = 2048; - +constexpr size_t num_hash_indices = 16; +constexpr size_t num_generators_per_hash_index = 8; constexpr size_t num_indexed_generators = num_hash_indices * num_generators_per_hash_index; constexpr size_t size_of_generator_data_array = hash_indices_generator_offset + num_indexed_generators; constexpr size_t num_generator_types = 3; diff --git a/cpp/src/barretenberg/dsl/acir_format/acir_format.cpp b/cpp/src/barretenberg/dsl/acir_format/acir_format.cpp index 65313934a6..d760ad10d9 100644 --- a/cpp/src/barretenberg/dsl/acir_format/acir_format.cpp +++ b/cpp/src/barretenberg/dsl/acir_format/acir_format.cpp @@ -1,8 +1,6 @@ #include "acir_format.hpp" #include "barretenberg/common/log.hpp" -using namespace proof_system::plonk::stdlib::types; - namespace acir_format { void read_witness(Composer& composer, std::vector witness) diff --git a/cpp/src/barretenberg/dsl/acir_format/acir_format.hpp b/cpp/src/barretenberg/dsl/acir_format/acir_format.hpp index 950de43460..39940e7f3a 100644 --- a/cpp/src/barretenberg/dsl/acir_format/acir_format.hpp +++ b/cpp/src/barretenberg/dsl/acir_format/acir_format.hpp @@ -10,7 +10,7 @@ #include "recursion_constraint.hpp" #include "pedersen.hpp" #include "hash_to_field.hpp" -#include "barretenberg/stdlib/types/types.hpp" +#include "barretenberg/dsl/types.hpp" namespace acir_format { @@ -39,23 +39,20 @@ struct acir_format { friend bool operator==(acir_format const& lhs, acir_format const& rhs) = default; }; -void read_witness(plonk::stdlib::types::Composer& composer, std::vector witness); +void read_witness(Composer& composer, std::vector witness); -void create_circuit(plonk::stdlib::types::Composer& composer, const acir_format& constraint_system); +void create_circuit(Composer& composer, const acir_format& constraint_system); -plonk::stdlib::types::Composer 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); -plonk::stdlib::types::Composer 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); -plonk::stdlib::types::Composer 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); -void create_circuit_with_witness(plonk::stdlib::types::Composer& composer, - const acir_format& constraint_system, - std::vector witness); +void create_circuit_with_witness(Composer& composer, const acir_format& constraint_system, std::vector witness); // Serialisation template inline void read(B& buf, acir_format& data) diff --git a/cpp/src/barretenberg/dsl/acir_format/acir_format.test.cpp b/cpp/src/barretenberg/dsl/acir_format/acir_format.test.cpp index ff957c6b9b..586a82b03d 100644 --- a/cpp/src/barretenberg/dsl/acir_format/acir_format.test.cpp +++ b/cpp/src/barretenberg/dsl/acir_format/acir_format.test.cpp @@ -105,10 +105,10 @@ TEST(acir_format, test_logic_gate_from_noir_circuit) std::cout << "made composer" << std::endl; - auto prover = composer.create_prover(); + auto prover = composer.create_ultra_with_keccak_prover(); auto proof = prover.construct_proof(); - auto verifier = composer.create_verifier(); + auto verifier = composer.create_ultra_with_keccak_verifier(); EXPECT_EQ(verifier.verify_proof(proof), true); } @@ -174,10 +174,10 @@ TEST(acir_format, test_schnorr_verify_pass) 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 prover = composer.create_ultra_with_keccak_prover(); auto proof = prover.construct_proof(); - auto verifier = composer.create_verifier(); + auto verifier = composer.create_ultra_with_keccak_verifier(); EXPECT_EQ(verifier.verify_proof(proof), true); } @@ -243,10 +243,10 @@ TEST(acir_format, test_schnorr_verify_small_range) 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 prover = composer.create_ultra_with_keccak_prover(); auto proof = prover.construct_proof(); - auto verifier = composer.create_verifier(); + auto verifier = composer.create_ultra_with_keccak_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 03deb176f6..8cd00269af 100644 --- a/cpp/src/barretenberg/dsl/acir_format/blake2s_constraint.cpp +++ b/cpp/src/barretenberg/dsl/acir_format/blake2s_constraint.cpp @@ -1,8 +1,6 @@ #include "blake2s_constraint.hpp" #include "round.hpp" -using namespace proof_system::plonk::stdlib::types; - namespace acir_format { void create_blake2s_constraints(Composer& composer, const Blake2sConstraint& constraint) diff --git a/cpp/src/barretenberg/dsl/acir_format/blake2s_constraint.hpp b/cpp/src/barretenberg/dsl/acir_format/blake2s_constraint.hpp index 643eb1e39b..f68bf2019a 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/stdlib/types/types.hpp" +#include "barretenberg/dsl/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::stdlib::types::Composer& composer, const Blake2sConstraint& constraint); +void create_blake2s_constraints(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 291245d3d5..87a873dc16 100644 --- a/cpp/src/barretenberg/dsl/acir_format/ecdsa_secp256k1.cpp +++ b/cpp/src/barretenberg/dsl/acir_format/ecdsa_secp256k1.cpp @@ -2,10 +2,10 @@ #include "barretenberg/crypto/ecdsa/ecdsa.hpp" #include "barretenberg/stdlib/encryption/ecdsa/ecdsa.hpp" -using namespace proof_system::plonk::stdlib::types; - namespace acir_format { +using namespace proof_system::plonk; + crypto::ecdsa::signature ecdsa_convert_signature(Composer& composer, std::vector signature) { diff --git a/cpp/src/barretenberg/dsl/acir_format/ecdsa_secp256k1.hpp b/cpp/src/barretenberg/dsl/acir_format/ecdsa_secp256k1.hpp index 9fee1b035a..55d8f6c16d 100644 --- a/cpp/src/barretenberg/dsl/acir_format/ecdsa_secp256k1.hpp +++ b/cpp/src/barretenberg/dsl/acir_format/ecdsa_secp256k1.hpp @@ -1,6 +1,6 @@ #pragma once #include -#include "barretenberg/stdlib/types/types.hpp" +#include "barretenberg/dsl/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::stdlib::types::Composer& composer, const EcdsaSecp256k1Constraint& input); +void create_ecdsa_verify_constraints(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 81251944e6..453ab56f47 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,7 +1,5 @@ #include "fixed_base_scalar_mul.hpp" -using namespace proof_system::plonk::stdlib::types; - namespace acir_format { void create_fixed_base_constraint(Composer& composer, const FixedBaseScalarMul& input) 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 2b61305a5c..80e52e03db 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/stdlib/types/types.hpp" +#include "barretenberg/dsl/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::stdlib::types::Composer& composer, const FixedBaseScalarMul& input); +void create_fixed_base_constraint(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 998b414cd4..afc3e2cf9f 100644 --- a/cpp/src/barretenberg/dsl/acir_format/hash_to_field.cpp +++ b/cpp/src/barretenberg/dsl/acir_format/hash_to_field.cpp @@ -1,10 +1,10 @@ #include "hash_to_field.hpp" #include "round.hpp" -using namespace proof_system::plonk::stdlib::types; - namespace acir_format { +using namespace proof_system::plonk; + void create_hash_to_field_constraints(Composer& composer, const HashToFieldConstraint constraint) { @@ -30,7 +30,7 @@ void create_hash_to_field_constraints(Composer& composer, const HashToFieldConst // Hash To Field using blake2s. // Note: It does not need to be blake2s in the future - byte_array_ct out_bytes = proof_system::plonk::stdlib::blake2s(arr); + byte_array_ct out_bytes = 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 275ce3fd0d..504493ce3e 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/stdlib/types/types.hpp" +#include "barretenberg/dsl/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::stdlib::types::Composer& composer, HashToFieldConstraint constraint); +void create_hash_to_field_constraints(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 ca14b7cbc4..09990fe04b 100644 --- a/cpp/src/barretenberg/dsl/acir_format/logic_constraint.cpp +++ b/cpp/src/barretenberg/dsl/acir_format/logic_constraint.cpp @@ -1,10 +1,10 @@ #include "logic_constraint.hpp" #include "barretenberg/stdlib/primitives/logic/logic.hpp" -using namespace proof_system::plonk::stdlib::types; - namespace acir_format { +using namespace proof_system::plonk; + void create_logic_gate(Composer& composer, const uint32_t a, const uint32_t b, diff --git a/cpp/src/barretenberg/dsl/acir_format/logic_constraint.hpp b/cpp/src/barretenberg/dsl/acir_format/logic_constraint.hpp index 0a194838ad..964f84f5af 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/stdlib/types/types.hpp" +#include "barretenberg/dsl/types.hpp" namespace acir_format { @@ -14,16 +14,11 @@ struct LogicConstraint { friend bool operator==(LogicConstraint const& lhs, LogicConstraint const& rhs) = default; }; -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 create_logic_gate(Composer& composer, uint32_t a, uint32_t b, uint32_t result, size_t num_bits, bool is_xor_gate); -void xor_gate(plonk::stdlib::types::Composer& composer, uint32_t a, uint32_t b, uint32_t result); +void xor_gate(Composer& composer, uint32_t a, uint32_t b, uint32_t result); -void and_gate(plonk::stdlib::types::Composer& composer, uint32_t a, uint32_t b, uint32_t result); +void and_gate(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 3f30a61fcb..780373f5be 100644 --- a/cpp/src/barretenberg/dsl/acir_format/merkle_membership_constraint.cpp +++ b/cpp/src/barretenberg/dsl/acir_format/merkle_membership_constraint.cpp @@ -1,9 +1,6 @@ #include "merkle_membership_constraint.hpp" #include "barretenberg/stdlib/merkle_tree/membership.hpp" -using namespace proof_system::plonk::stdlib::types; -using namespace proof_system::plonk::stdlib::merkle_tree; - namespace acir_format { void create_merkle_check_membership_constraint(Composer& composer, const MerkleMembershipConstraint& input) @@ -22,7 +19,7 @@ void create_merkle_check_membership_constraint(Composer& composer, const MerkleM // 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_ct 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 @@ -39,7 +36,7 @@ void create_merkle_check_membership_constraint(Composer& composer, const MerkleM } } - auto exists = check_subtree_membership(root, hash_path, leaf, index_bits, 0); + auto exists = plonk::stdlib::merkle_tree::check_subtree_membership(root, hash_path, leaf, index_bits, 0); composer.assert_equal_constant(exists.witness_index, fr::one()); } 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 1fa1481e88..25bfcd0404 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/stdlib/types/types.hpp" +#include "barretenberg/dsl/types.hpp" namespace acir_format { @@ -14,8 +14,7 @@ struct MerkleMembershipConstraint { friend bool operator==(MerkleMembershipConstraint const& lhs, MerkleMembershipConstraint const& rhs) = default; }; -void create_merkle_check_membership_constraint(plonk::stdlib::types::Composer& composer, - const MerkleMembershipConstraint& input); +void create_merkle_check_membership_constraint(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 3ac7951ec9..d272a3a8ed 100644 --- a/cpp/src/barretenberg/dsl/acir_format/pedersen.cpp +++ b/cpp/src/barretenberg/dsl/acir_format/pedersen.cpp @@ -1,9 +1,9 @@ #include "pedersen.hpp" -using namespace proof_system::plonk::stdlib::types; - namespace acir_format { +using namespace proof_system::plonk; + void create_pedersen_constraint(Composer& composer, const PedersenConstraint& input) { std::vector scalars; @@ -13,12 +13,9 @@ void create_pedersen_constraint(Composer& composer, const PedersenConstraint& in field_ct scalar_as_field = field_ct::from_witness_index(&composer, scalar); scalars.push_back(scalar_as_field); } -#ifdef USE_TURBO - auto point = pedersen_commitment::commit(scalars); -#else + // TODO: Does Noir need additive homomorphic Pedersen hash? If so, using plookup version won't help. auto point = stdlib::pedersen_plookup_commitment::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 b801d2a8f2..3144359b2f 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/stdlib/types/types.hpp" +#include "barretenberg/dsl/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::stdlib::types::Composer& composer, const PedersenConstraint& input); +void create_pedersen_constraint(Composer& composer, const PedersenConstraint& input); template inline void read(B& buf, PedersenConstraint& constraint) { diff --git a/cpp/src/barretenberg/dsl/acir_format/schnorr_verify.cpp b/cpp/src/barretenberg/dsl/acir_format/schnorr_verify.cpp index f92176bd08..cb717ed99a 100644 --- a/cpp/src/barretenberg/dsl/acir_format/schnorr_verify.cpp +++ b/cpp/src/barretenberg/dsl/acir_format/schnorr_verify.cpp @@ -1,10 +1,11 @@ #include "schnorr_verify.hpp" +#include "barretenberg/stdlib/encryption/schnorr/schnorr.hpp" #include "barretenberg/crypto/schnorr/schnorr.hpp" -using namespace proof_system::plonk::stdlib::types; - namespace acir_format { +using namespace proof_system::plonk::stdlib; + crypto::schnorr::signature convert_signature(Composer& composer, std::vector signature) { @@ -82,9 +83,9 @@ void create_schnorr_verify_constraints(Composer& composer, const SchnorrConstrai point_ct pub_key{ witness_ct(&composer, pubkey_value_x), witness_ct(&composer, pubkey_value_y) }; - schnorr::signature_bits sig = stdlib::schnorr::convert_signature(&composer, new_sig); + schnorr_signature_bits_ct sig = schnorr::convert_signature(&composer, new_sig); - bool_ct signature_result = stdlib::schnorr::signature_verification_result(message, pub_key, sig); + bool_ct signature_result = schnorr::signature_verification_result(message, pub_key, sig); bool_ct signature_result_normalized = signature_result.normalize(); diff --git a/cpp/src/barretenberg/dsl/acir_format/schnorr_verify.hpp b/cpp/src/barretenberg/dsl/acir_format/schnorr_verify.hpp index f8e6b9c53f..7b6b984294 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/stdlib/types/types.hpp" +#include "barretenberg/dsl/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::stdlib::types::Composer& composer, const SchnorrConstraint& input); +void create_schnorr_verify_constraints(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 e54697d4e7..07c8166bd1 100644 --- a/cpp/src/barretenberg/dsl/acir_format/sha256_constraint.cpp +++ b/cpp/src/barretenberg/dsl/acir_format/sha256_constraint.cpp @@ -1,8 +1,7 @@ #include "sha256_constraint.hpp" #include "round.hpp" #include "barretenberg/stdlib/hash/sha256/sha256.hpp" - -using namespace proof_system::plonk::stdlib::types; +#include "barretenberg/dsl/types.hpp" namespace acir_format { diff --git a/cpp/src/barretenberg/dsl/acir_format/sha256_constraint.hpp b/cpp/src/barretenberg/dsl/acir_format/sha256_constraint.hpp index dec3bca40a..eccb1521ab 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/stdlib/types/types.hpp" +#include "barretenberg/dsl/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::stdlib::types::Composer& composer, const Sha256Constraint& constraint); +void create_sha256_constraints(Composer& composer, const Sha256Constraint& constraint); template inline void read(B& buf, Sha256Input& constraint) { diff --git a/cpp/src/barretenberg/dsl/acir_proofs/acir_proofs.cpp b/cpp/src/barretenberg/dsl/acir_proofs/acir_proofs.cpp index 4d01512eca..8041ac8966 100644 --- a/cpp/src/barretenberg/dsl/acir_proofs/acir_proofs.cpp +++ b/cpp/src/barretenberg/dsl/acir_proofs/acir_proofs.cpp @@ -2,12 +2,10 @@ #include "acir_proofs.hpp" #include "barretenberg/plonk/proof_system/proving_key/serialize.hpp" #include "barretenberg/dsl/acir_format/acir_format.hpp" -#include "barretenberg/stdlib/types/types.hpp" +#include "barretenberg/dsl/types.hpp" #include "barretenberg/srs/reference_string/pippenger_reference_string.hpp" #include "barretenberg/plonk/proof_system/verification_key/sol_gen.hpp" -using namespace proof_system::plonk::stdlib::types; - namespace acir_proofs { size_t get_solidity_verifier(uint8_t const* g2x, uint8_t const* vk_buf, uint8_t** output_buf) @@ -79,9 +77,9 @@ size_t init_verification_key(void* pippenger, uint8_t const* g2x, uint8_t const* reinterpret_cast(pippenger), g2x); proving_key->reference_string = crs_factory->get_prover_crs(proving_key->circuit_size); - Composer composer(proving_key, nullptr); + acir_format::Composer composer(proving_key, nullptr); auto verification_key = - plonk::stdlib::types::Composer::compute_verification_key_base(proving_key, crs_factory->get_verifier_crs()); + acir_format::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 @@ -110,7 +108,7 @@ size_t serialize_proof_into_field_elements(uint8_t const* proof_data_buf, plonk::proof proof = { std::vector(proof_data_buf, &proof_data_buf[proof_data_length]) }; transcript::StandardTranscript transcript( - proof.proof_data, Composer::create_manifest(1), transcript::HashType::PlookupPedersenBlake3s, 16); + proof.proof_data, acir_format::Composer::create_manifest(1), transcript::HashType::PlookupPedersenBlake3s, 16); std::vector output = transcript.export_transcript_in_recursion_format(); @@ -199,13 +197,14 @@ size_t new_proof(void* pippenger, reinterpret_cast(pippenger), g2x); proving_key->reference_string = crs_factory->get_prover_crs(proving_key->circuit_size); - auto env_crs = std::make_unique(); + // auto env_crs = std::make_unique(); + acir_format::Composer composer(proving_key, nullptr); + + create_circuit_with_witness(composer, constraint_system, witness); - auto composer = acir_format::create_circuit_with_witness(constraint_system, witness); + auto prover = composer.create_ultra_with_keccak_prover(); - auto prover = composer.create_prover(); - auto verifier = composer.create_verifier(); - auto heapProver = new stdlib::types::Prover(std::move(prover)); + auto heapProver = new acir_format::Prover(std::move(prover)); auto& proof_data = heapProver->construct_proof().proof_data; *proof_data_buf = proof_data.data(); @@ -226,11 +225,11 @@ bool verify_proof( read(vk_buf, vk_data); auto verification_key = std::make_shared(std::move(vk_data), crs); - Composer composer(nullptr, verification_key); + acir_format::Composer composer(nullptr, verification_key); create_circuit(composer, constraint_system); plonk::proof pp = { std::vector(proof, proof + length) }; - auto verifier = composer.create_verifier(); + auto verifier = composer.create_ultra_with_keccak_verifier(); verified = verifier.verify_proof(pp); #ifndef __wasm__ diff --git a/cpp/src/barretenberg/dsl/types.hpp b/cpp/src/barretenberg/dsl/types.hpp new file mode 100644 index 0000000000..273734aa76 --- /dev/null +++ b/cpp/src/barretenberg/dsl/types.hpp @@ -0,0 +1,72 @@ +#pragma once +#include "barretenberg/plonk/composer/ultra_composer.hpp" + +#include "barretenberg/plonk/proof_system/prover/prover.hpp" +#include "barretenberg/stdlib/primitives/bigfield/bigfield.hpp" +#include "barretenberg/stdlib/primitives/biggroup/biggroup.hpp" +#include "barretenberg/stdlib/primitives/bit_array/bit_array.hpp" +#include "barretenberg/stdlib/primitives/bool/bool.hpp" +#include "barretenberg/stdlib/primitives/packed_byte_array/packed_byte_array.hpp" +#include "barretenberg/stdlib/primitives/byte_array/byte_array.hpp" +#include "barretenberg/stdlib/primitives/uint/uint.hpp" +#include "barretenberg/stdlib/primitives/witness/witness.hpp" +#include "barretenberg/stdlib/primitives/bigfield/bigfield.hpp" +#include "barretenberg/stdlib/primitives/biggroup/biggroup.hpp" +#include "barretenberg/stdlib/commitment/pedersen/pedersen.hpp" +#include "barretenberg/stdlib/commitment/pedersen/pedersen_plookup.hpp" +#include "barretenberg/stdlib/merkle_tree/hash_path.hpp" +#include "barretenberg/stdlib/encryption/schnorr/schnorr.hpp" +#include "barretenberg/stdlib/primitives/curves/bn254.hpp" +#include "barretenberg/stdlib/primitives/curves/secp256k1.hpp" +#include "barretenberg/stdlib/primitives/memory/rom_table.hpp" +#include "barretenberg/stdlib/recursion/verifier/program_settings.hpp" +#include "barretenberg/stdlib/recursion/verification_key/verification_key.hpp" +#include "barretenberg/stdlib/recursion/aggregation_state/aggregation_state.hpp" + +namespace acir_format { + +using Composer = plonk::UltraComposer; + +using Prover = std::conditional_t< + std::same_as, + plonk::UltraWithKeccakProver, + std::conditional_t, plonk::TurboProver, plonk::Prover>>; + +using Verifier = std::conditional_t< + std::same_as, + plonk::UltraWithKeccakVerifier, + std::conditional_t, plonk::TurboVerifier, plonk::Verifier>>; + +using witness_ct = proof_system::plonk::stdlib::witness_t; +using public_witness_ct = proof_system::plonk::stdlib::public_witness_t; +using bool_ct = proof_system::plonk::stdlib::bool_t; +using byte_array_ct = proof_system::plonk::stdlib::byte_array; +using packed_byte_array_ct = proof_system::plonk::stdlib::packed_byte_array; +using field_ct = proof_system::plonk::stdlib::field_t; +using suint_ct = proof_system::plonk::stdlib::safe_uint_t; +using uint8_ct = proof_system::plonk::stdlib::uint8; +using uint16_ct = proof_system::plonk::stdlib::uint16; +using uint32_ct = proof_system::plonk::stdlib::uint32; +using uint64_ct = proof_system::plonk::stdlib::uint64; +using bit_array_ct = proof_system::plonk::stdlib::bit_array; +using fq_ct = proof_system::plonk::stdlib::bigfield; +using biggroup_ct = proof_system::plonk::stdlib::element; +using point_ct = proof_system::plonk::stdlib::point; +using pedersen_commitment = proof_system::plonk::stdlib::pedersen_commitment; +using group_ct = proof_system::plonk::stdlib::group; +using bn254 = proof_system::plonk::stdlib::bn254; +using secp256k1_ct = proof_system::plonk::stdlib::secp256k1; + +using hash_path_ct = proof_system::plonk::stdlib::merkle_tree::hash_path; + +using schnorr_signature_bits_ct = proof_system::plonk::stdlib::schnorr::signature_bits; + +// Ultra-composer specific typesv +using rom_table_ct = proof_system::plonk::stdlib::rom_table; + +using verification_key_ct = proof_system::plonk::stdlib::recursion::verification_key; +using aggregation_state_ct = proof_system::plonk::stdlib::recursion::aggregation_state; +using noir_recursive_settings = proof_system::plonk::stdlib::recursion::recursive_ultra_verifier_settings; +using Transcript_ct = proof_system::plonk::stdlib::recursion::Transcript; + +} // namespace acir_format diff --git a/cpp/src/barretenberg/ecc/fields/field.hpp b/cpp/src/barretenberg/ecc/fields/field.hpp index 66c59ea0d2..80a87f46af 100644 --- a/cpp/src/barretenberg/ecc/fields/field.hpp +++ b/cpp/src/barretenberg/ecc/fields/field.hpp @@ -25,6 +25,10 @@ namespace barretenberg { template struct alignas(32) field { public: // We don't initialize data by default since we'd lose a lot of time on pointless initializations. + // Other alternatives have been noted, such as casting to get around constructors where they matter, + // however it is felt that sanitizer tools (e.g. MSAN) can detect garbage well, whereas doing + // hacky casts where needed would require rework to critical algos like MSM, FFT, Sumcheck. + // Instead, the recommended solution is use an explicit = 0 where initialization is important. field() noexcept {} constexpr field(const uint256_t& input) noexcept diff --git a/cpp/src/barretenberg/honk/composer/composer_helper/standard_honk_composer_helper.cpp b/cpp/src/barretenberg/honk/composer/composer_helper/standard_honk_composer_helper.cpp index 8c61e02a5d..6867d9af37 100644 --- a/cpp/src/barretenberg/honk/composer/composer_helper/standard_honk_composer_helper.cpp +++ b/cpp/src/barretenberg/honk/composer/composer_helper/standard_honk_composer_helper.cpp @@ -165,6 +165,7 @@ StandardProver StandardHonkComposerHelper::create_prover( compute_witness(circuit_constructor); size_t num_sumcheck_rounds(circuit_proving_key->log_circuit_size); + // TODO(luke): what is this manifest? Remove? auto manifest = Flavor::create_manifest(circuit_constructor.public_inputs.size(), num_sumcheck_rounds); StandardProver output_state(std::move(wire_polynomials), circuit_proving_key); diff --git a/cpp/src/barretenberg/honk/composer/composer_helper/ultra_honk_composer_helper.cpp b/cpp/src/barretenberg/honk/composer/composer_helper/ultra_honk_composer_helper.cpp new file mode 100644 index 0000000000..1ef6fdcba0 --- /dev/null +++ b/cpp/src/barretenberg/honk/composer/composer_helper/ultra_honk_composer_helper.cpp @@ -0,0 +1,356 @@ +#include "ultra_honk_composer_helper.hpp" +#include "barretenberg/honk/proof_system/ultra_prover.hpp" +#include "barretenberg/plonk/proof_system/types/program_settings.hpp" +#include "barretenberg/plonk/proof_system/types/prover_settings.hpp" +// #include "barretenberg/plonk/proof_system/verifier/verifier.hpp" +#include "barretenberg/proof_system/circuit_constructors/ultra_circuit_constructor.hpp" +#include "barretenberg/proof_system/composer/permutation_helper.hpp" +#include "barretenberg/plonk/proof_system/commitment_scheme/kate_commitment_scheme.hpp" + +#include +#include +#include +#include + +namespace proof_system::honk { + +/** + * @brief Compute witness polynomials + * + * TODO(luke): The wire polynomials are returned directly whereas the sorted list polys are added to the proving + * key. This should be made consistent once Cody's Flavor work is settled. + */ +template +void UltraHonkComposerHelper::compute_witness(CircuitConstructor& circuit_constructor) +{ + if (computed_witness) { + return; + } + + size_t tables_size = 0; + size_t lookups_size = 0; + for (const auto& table : circuit_constructor.lookup_tables) { + tables_size += table.size; + lookups_size += table.lookup_gates.size(); + } + + const size_t filled_gates = circuit_constructor.num_gates + circuit_constructor.public_inputs.size(); + const size_t total_num_gates = std::max(filled_gates, tables_size + lookups_size); + + const size_t subgroup_size = circuit_constructor.get_circuit_subgroup_size(total_num_gates + NUM_RESERVED_GATES); + + // Pad the wires (pointers to `witness_indices` of the `variables` vector). + // Note: the remaining NUM_RESERVED_GATES indices are padded with zeros within `compute_witness_base` (called + // next). + for (size_t i = filled_gates; i < total_num_gates; ++i) { + circuit_constructor.w_l.emplace_back(circuit_constructor.zero_idx); + circuit_constructor.w_r.emplace_back(circuit_constructor.zero_idx); + circuit_constructor.w_o.emplace_back(circuit_constructor.zero_idx); + circuit_constructor.w_4.emplace_back(circuit_constructor.zero_idx); + } + + // TODO(#340)(luke): within compute_witness_base, the 3rd argument is used in the calculation of the dyadic circuit + // size (subgroup_size). Here (and in other split composers) we're passing in NUM_RANDOMIZED_GATES, but elsewhere, + // e.g. directly above, we use NUM_RESERVED_GATES in a similar role. Therefore, these two constants must be equal + // for everything to be consistent. What we should do is compute the dyadic circuit size once and for all then pass + // that around rather than computing in multiple places. + wire_polynomials = compute_witness_base(circuit_constructor, total_num_gates, NUM_RANDOMIZED_GATES); + + polynomial s_1(subgroup_size); + polynomial s_2(subgroup_size); + polynomial s_3(subgroup_size); + polynomial s_4(subgroup_size); + polynomial z_lookup(subgroup_size + 1); // Only instantiated in this function; nothing assigned. + + // Save space for adding random scalars in the s polynomial later. The subtracted 1 allows us to insert a `1` at the + // end, to ensure the evaluations (and hence coefficients) aren't all 0. See ComposerBase::compute_proving_key_base + // for further explanation, as a similar trick is done there. + size_t count = subgroup_size - tables_size - lookups_size - s_randomness - 1; + for (size_t i = 0; i < count; ++i) { + s_1[i] = 0; + s_2[i] = 0; + s_3[i] = 0; + s_4[i] = 0; + } + + for (auto& table : circuit_constructor.lookup_tables) { + const fr table_index(table.table_index); + auto& lookup_gates = table.lookup_gates; + for (size_t i = 0; i < table.size; ++i) { + if (table.use_twin_keys) { + lookup_gates.push_back({ + { + table.column_1[i].from_montgomery_form().data[0], + table.column_2[i].from_montgomery_form().data[0], + }, + { + table.column_3[i], + 0, + }, + }); + } else { + lookup_gates.push_back({ + { + table.column_1[i].from_montgomery_form().data[0], + 0, + }, + { + table.column_2[i], + table.column_3[i], + }, + }); + } + } + +#ifdef NO_TBB + std::sort(lookup_gates.begin(), lookup_gates.end()); +#else + std::sort(std::execution::par_unseq, lookup_gates.begin(), lookup_gates.end()); +#endif + + for (const auto& entry : lookup_gates) { + const auto components = entry.to_sorted_list_components(table.use_twin_keys); + s_1[count] = components[0]; + s_2[count] = components[1]; + s_3[count] = components[2]; + s_4[count] = table_index; + ++count; + } + } + + // Initialise the `s_randomness` positions in the s polynomials with 0. + // These will be the positions where we will be adding random scalars to add zero knowledge + // to plookup (search for `Blinding` in plonk/proof_system/widgets/random_widgets/plookup_widget_impl.hpp + // ProverPlookupWidget::compute_sorted_list_polynomial()) + for (size_t i = 0; i < s_randomness; ++i) { + s_1[count] = 0; + s_2[count] = 0; + s_3[count] = 0; + s_4[count] = 0; + ++count; + } + + // TODO(luke): Adding these to the key for now but this is inconsistent since these are 'witness' polys. Need + // to see what becomes of the proving key before making a decision here. + circuit_proving_key->polynomial_store.put("s_1_lagrange", std::move(s_1)); + circuit_proving_key->polynomial_store.put("s_2_lagrange", std::move(s_2)); + circuit_proving_key->polynomial_store.put("s_3_lagrange", std::move(s_3)); + circuit_proving_key->polynomial_store.put("s_4_lagrange", std::move(s_4)); + + computed_witness = true; +} + +template +UltraProver UltraHonkComposerHelper::create_prover(CircuitConstructor& circuit_constructor) +{ + finalize_circuit(circuit_constructor); + + compute_proving_key(circuit_constructor); + compute_witness(circuit_constructor); + + UltraProver output_state(std::move(wire_polynomials), circuit_proving_key); + + return output_state; +} + +// /** +// * Create verifier: compute verification key, +// * initialize verifier with it and an initial manifest and initialize commitment_scheme. +// * +// * @return The verifier. +// * */ +// // TODO(Cody): This should go away altogether. +// template +// plonk::UltraVerifier UltraHonkComposerHelper::create_verifier( +// const CircuitConstructor& circuit_constructor) +// { +// auto verification_key = compute_verification_key(circuit_constructor); + +// plonk::UltraVerifier output_state(circuit_verification_key, +// create_manifest(circuit_constructor.public_inputs.size())); + +// std::unique_ptr> kate_commitment_scheme = +// std::make_unique>(); + +// output_state.commitment_scheme = std::move(kate_commitment_scheme); + +// return output_state; +// } + +template +std::shared_ptr UltraHonkComposerHelper::compute_proving_key( + const CircuitConstructor& circuit_constructor) +{ + if (circuit_proving_key) { + return circuit_proving_key; + } + + size_t tables_size = 0; + size_t lookups_size = 0; + for (const auto& table : circuit_constructor.lookup_tables) { + tables_size += table.size; + lookups_size += table.lookup_gates.size(); + } + + const size_t minimum_circuit_size = tables_size + lookups_size; + const size_t num_randomized_gates = NUM_RANDOMIZED_GATES; + // Initialize circuit_proving_key + // TODO(#229)(Kesha): replace composer types. + circuit_proving_key = initialize_proving_key( + circuit_constructor, crs_factory_.get(), minimum_circuit_size, num_randomized_gates, ComposerType::PLOOKUP); + + construct_lagrange_selector_forms(circuit_constructor, circuit_proving_key.get()); + + // TODO(#217)(luke): Naively enforcing non-zero selectors for Honk will result in some relations not being + // satisfied. + // enforce_nonzero_polynomial_selectors(circuit_constructor, circuit_proving_key.get()); + + compute_honk_generalized_sigma_permutations(circuit_constructor, + circuit_proving_key.get()); + + compute_first_and_last_lagrange_polynomials(circuit_proving_key.get()); + + const size_t subgroup_size = circuit_proving_key->circuit_size; + + polynomial poly_q_table_column_1(subgroup_size); + polynomial poly_q_table_column_2(subgroup_size); + polynomial poly_q_table_column_3(subgroup_size); + polynomial poly_q_table_column_4(subgroup_size); + + size_t offset = subgroup_size - tables_size - s_randomness - 1; + + // Create lookup selector polynomials which interpolate each table column. + // Our selector polys always need to interpolate the full subgroup size, so here we offset so as to + // put the table column's values at the end. (The first gates are for non-lookup constraints). + // [0, ..., 0, ...table, 0, 0, 0, x] + // ^^^^^^^^^ ^^^^^^^^ ^^^^^^^ ^nonzero to ensure uniqueness and to avoid infinity commitments + // | table randomness + // ignored, as used for regular constraints and padding to the next power of 2. + + for (size_t i = 0; i < offset; ++i) { + poly_q_table_column_1[i] = 0; + poly_q_table_column_2[i] = 0; + poly_q_table_column_3[i] = 0; + poly_q_table_column_4[i] = 0; + } + + for (const auto& table : circuit_constructor.lookup_tables) { + const fr table_index(table.table_index); + + for (size_t i = 0; i < table.size; ++i) { + poly_q_table_column_1[offset] = table.column_1[i]; + poly_q_table_column_2[offset] = table.column_2[i]; + poly_q_table_column_3[offset] = table.column_3[i]; + poly_q_table_column_4[offset] = table_index; + ++offset; + } + } + + // Initialise the last `s_randomness` positions in table polynomials with 0. We don't need to actually randomise + // the table polynomials. + for (size_t i = 0; i < s_randomness; ++i) { + poly_q_table_column_1[offset] = 0; + poly_q_table_column_2[offset] = 0; + poly_q_table_column_3[offset] = 0; + poly_q_table_column_4[offset] = 0; + ++offset; + } + + // // In the case of using UltraPlonkComposer for a circuit which does _not_ make use of any lookup tables, all + // four + // // table columns would be all zeros. This would result in these polys' commitments all being the point at + // infinity + // // (which is bad because our point arithmetic assumes we'll never operate on the point at infinity). To avoid + // this, + // // we set the last evaluation of each poly to be nonzero. The last `num_roots_cut_out_of_vanishing_poly = 4` + // // evaluations are ignored by constraint checks; we arbitrarily choose the very-last evaluation to be nonzero. + // See + // // ComposerBase::compute_proving_key_base for further explanation, as a similar trick is done there. We could + // // have chosen `1` for each such evaluation here, but that would have resulted in identical commitments for + // // all four columns. We don't want to have equal commitments, because biggroup operations assume no points are + // // equal, so if we tried to verify an ultra proof in a circuit, the biggroup operations would fail. To combat + // // this, we just choose distinct values: + size_t num_selectors = circuit_constructor.num_selectors; + ASSERT(offset == subgroup_size - 1); + auto unique_last_value = num_selectors + 1; // Note: in compute_proving_key_base, moments earlier, each selector + // vector was given a unique last value from 1..num_selectors. So we + // avoid those values and continue the count, to ensure uniqueness. + poly_q_table_column_1[subgroup_size - 1] = unique_last_value; + poly_q_table_column_2[subgroup_size - 1] = ++unique_last_value; + poly_q_table_column_3[subgroup_size - 1] = ++unique_last_value; + poly_q_table_column_4[subgroup_size - 1] = ++unique_last_value; + + circuit_proving_key->polynomial_store.put("table_value_1_lagrange", std::move(poly_q_table_column_1)); + circuit_proving_key->polynomial_store.put("table_value_2_lagrange", std::move(poly_q_table_column_2)); + circuit_proving_key->polynomial_store.put("table_value_3_lagrange", std::move(poly_q_table_column_3)); + circuit_proving_key->polynomial_store.put("table_value_4_lagrange", std::move(poly_q_table_column_4)); + + // Copy memory read/write record data into proving key. Prover needs to know which gates contain a read/write + // 'record' witness on the 4th wire. This wire value can only be fully computed once the first 3 wire polynomials + // have been committed to. The 4th wire on these gates will be a random linear combination of the first 3 wires, + // using the plookup challenge `eta` + std::copy(circuit_constructor.memory_read_records.begin(), + circuit_constructor.memory_read_records.end(), + std::back_inserter(circuit_proving_key->memory_read_records)); + std::copy(circuit_constructor.memory_write_records.begin(), + circuit_constructor.memory_write_records.end(), + std::back_inserter(circuit_proving_key->memory_write_records)); + + circuit_proving_key->recursive_proof_public_input_indices = + std::vector(recursive_proof_public_input_indices.begin(), recursive_proof_public_input_indices.end()); + + circuit_proving_key->contains_recursive_proof = contains_recursive_proof; + + return circuit_proving_key; +} + +// /** +// * Compute verification key consisting of selector precommitments. +// * +// * @return Pointer to created circuit verification key. +// * */ +// template +// std::shared_ptr UltraHonkComposerHelper::compute_verification_key( +// const CircuitConstructor& circuit_constructor) +// { +// if (circuit_verification_key) { +// return circuit_verification_key; +// } + +// if (!circuit_proving_key) { +// compute_proving_key(circuit_constructor); +// } +// circuit_verification_key = compute_verification_key_common(circuit_proving_key, +// crs_factory_->get_verifier_crs()); + +// circuit_verification_key->composer_type = type; // Invariably plookup for this class. + +// // See `add_recusrive_proof()` for how this recursive data is assigned. +// circuit_verification_key->recursive_proof_public_input_indices = +// std::vector(recursive_proof_public_input_indices.begin(), +// recursive_proof_public_input_indices.end()); + +// circuit_verification_key->contains_recursive_proof = contains_recursive_proof; + +// return circuit_verification_key; +// } + +// template +// void UltraHonkComposerHelper::add_table_column_selector_poly_to_proving_key( +// polynomial& selector_poly_lagrange_form, const std::string& tag) +// { +// polynomial selector_poly_lagrange_form_copy(selector_poly_lagrange_form, circuit_proving_key->small_domain.size); + +// selector_poly_lagrange_form.ifft(circuit_proving_key->small_domain); +// auto& selector_poly_coeff_form = selector_poly_lagrange_form; + +// polynomial selector_poly_coset_form(selector_poly_coeff_form, circuit_proving_key->circuit_size * 4); +// selector_poly_coset_form.coset_fft(circuit_proving_key->large_domain); + +// circuit_proving_key->polynomial_store.put(tag, std::move(selector_poly_coeff_form)); +// circuit_proving_key->polynomial_store.put(tag + "_lagrange", std::move(selector_poly_lagrange_form_copy)); +// circuit_proving_key->polynomial_store.put(tag + "_fft", std::move(selector_poly_coset_form)); +// } + +template class UltraHonkComposerHelper; +} // namespace proof_system::honk diff --git a/cpp/src/barretenberg/honk/composer/composer_helper/ultra_honk_composer_helper.hpp b/cpp/src/barretenberg/honk/composer/composer_helper/ultra_honk_composer_helper.hpp new file mode 100644 index 0000000000..de309735e6 --- /dev/null +++ b/cpp/src/barretenberg/honk/composer/composer_helper/ultra_honk_composer_helper.hpp @@ -0,0 +1,72 @@ +#pragma once + +#include "barretenberg/proof_system/composer/composer_helper_lib.hpp" +#include "barretenberg/plonk/composer/splitting_tmp/composer_helper/composer_helper_lib.hpp" +#include "barretenberg/srs/reference_string/file_reference_string.hpp" +#include "barretenberg/plonk/proof_system/proving_key/proving_key.hpp" +#include "barretenberg/honk/proof_system/ultra_prover.hpp" +// #include "barretenberg/plonk/proof_system/verifier/verifier.hpp" + +#include +#include +#include +#include + +namespace proof_system::honk { +// TODO(Kesha): change initializations to specify this parameter +// Cody: What does this mean? +template class UltraHonkComposerHelper { + public: + // TODO(#340)(luke): In the split composers, NUM_RANDOMIZED_GATES has replaced NUM_RESERVED_GATES (in some places) + // to determine the next-power-of-2 circuit size. (There are some places in this composer that still use + // NUM_RESERVED_GATES). Therefore for consistency within this composer itself, and consistency with the original + // Ultra Composer, this value must match that of NUM_RESERVED_GATES. This issue needs to be reconciled + // simultaneously here and in the other split composers. + static constexpr size_t NUM_RANDOMIZED_GATES = 4; // equal to the number of multilinear evaluations leaked + static constexpr size_t program_width = CircuitConstructor::program_width; + std::vector wire_polynomials; + std::shared_ptr circuit_proving_key; + std::shared_ptr circuit_verification_key; + // TODO(#218)(kesha): we need to put this into the commitment key, so that the composer doesn't have to handle srs + // at all + std::shared_ptr crs_factory_; + + std::vector recursive_proof_public_input_indices; + bool contains_recursive_proof = false; + bool computed_witness = false; + + // This variable controls the amount with which the lookup table and witness values need to be shifted + // above to make room for adding randomness into the permutation and witness polynomials in the plookup widget. + // This must be (num_roots_cut_out_of_the_vanishing_polynomial - 1), since the variable num_roots_cut_out_of_ + // vanishing_polynomial cannot be trivially fetched here, I am directly setting this to 4 - 1 = 3. + static constexpr size_t s_randomness = 3; + + explicit UltraHonkComposerHelper(std::shared_ptr crs_factory) + : crs_factory_(std::move(crs_factory)) + {} + + UltraHonkComposerHelper(std::shared_ptr p_key, std::shared_ptr v_key) + : circuit_proving_key(std::move(p_key)) + , circuit_verification_key(std::move(v_key)) + {} + + UltraHonkComposerHelper(UltraHonkComposerHelper&& other) noexcept = default; + UltraHonkComposerHelper(UltraHonkComposerHelper const& other) noexcept = default; + UltraHonkComposerHelper& operator=(UltraHonkComposerHelper&& other) noexcept = default; + UltraHonkComposerHelper& operator=(UltraHonkComposerHelper const& other) noexcept = default; + ~UltraHonkComposerHelper() = default; + + void finalize_circuit(CircuitConstructor& circuit_constructor) { circuit_constructor.finalize_circuit(); }; + + std::shared_ptr compute_proving_key(const CircuitConstructor& circuit_constructor); + // std::shared_ptr compute_verification_key(const CircuitConstructor& circuit_constructor); + + void compute_witness(CircuitConstructor& circuit_constructor); + + UltraProver create_prover(CircuitConstructor& circuit_constructor); + // UltraVerifier create_verifier(const CircuitConstructor& circuit_constructor); + + void add_table_column_selector_poly_to_proving_key(polynomial& small, const std::string& tag); +}; + +} // namespace proof_system::honk diff --git a/cpp/src/barretenberg/honk/composer/standard_honk_composer.test.cpp b/cpp/src/barretenberg/honk/composer/standard_honk_composer.test.cpp index 84717e21a4..8ab126ba01 100644 --- a/cpp/src/barretenberg/honk/composer/standard_honk_composer.test.cpp +++ b/cpp/src/barretenberg/honk/composer/standard_honk_composer.test.cpp @@ -304,109 +304,6 @@ TEST(StandardHonkComposer, VerificationKeyCreation) composer.circuit_constructor.selectors.size() + composer.num_wires * 2 + 2); } -/** - * @brief A test taking sumcheck relations and applying them to the witness and selector polynomials to ensure that the - * realtions are correct. - * - * TODO(Kesha): We'll have to update this function once we add zk, since the relation will be incorrect for he first few - * indices - * - */ -TEST(StandardHonkComposer, SumcheckRelationCorrectness) -{ - // Create a composer and a dummy circuit with a few gates - StandardHonkComposer composer = StandardHonkComposer(); - static const size_t num_wires = StandardHonkComposer::num_wires; - fr a = fr::one(); - // Using the public variable to check that public_input_delta is computed and added to the relation correctly - uint32_t a_idx = composer.add_public_variable(a); - fr b = fr::one(); - fr c = a + b; - fr d = a + c; - uint32_t b_idx = composer.add_variable(b); - uint32_t c_idx = composer.add_variable(c); - uint32_t d_idx = composer.add_variable(d); - for (size_t i = 0; i < 16; i++) { - composer.create_add_gate({ a_idx, b_idx, c_idx, fr::one(), fr::one(), fr::neg_one(), fr::zero() }); - composer.create_add_gate({ d_idx, c_idx, a_idx, fr::one(), fr::neg_one(), fr::neg_one(), fr::zero() }); - } - // Create a prover (it will compute proving key and witness) - auto prover = composer.create_prover(); - - // Generate beta and gamma - fr beta = fr::random_element(); - fr gamma = fr::random_element(); - - // Compute public input delta - const auto public_inputs = composer.circuit_constructor.get_public_inputs(); - auto public_input_delta = - honk::compute_public_input_delta(public_inputs, beta, gamma, prover.key->circuit_size); - - sumcheck::RelationParameters params{ - .beta = beta, - .gamma = gamma, - .public_input_delta = public_input_delta, - }; - - constexpr size_t num_polynomials = proof_system::honk::StandardArithmetization::NUM_POLYNOMIALS; - // Compute grand product polynomial - polynomial z_perm_poly = - prover_library::compute_permutation_grand_product(prover.key, prover.wire_polynomials, beta, gamma); - - // Create an array of spans to the underlying polynomials to more easily - // get the transposition. - // Ex: polynomial_spans[3][i] returns the i-th coefficient of the third polynomial - // in the list below - std::array, num_polynomials> evaluations_array; - - using POLYNOMIAL = proof_system::honk::StandardArithmetization::POLYNOMIAL; - evaluations_array[POLYNOMIAL::W_L] = prover.wire_polynomials[0]; - evaluations_array[POLYNOMIAL::W_R] = prover.wire_polynomials[1]; - evaluations_array[POLYNOMIAL::W_O] = prover.wire_polynomials[2]; - evaluations_array[POLYNOMIAL::Z_PERM] = z_perm_poly; - evaluations_array[POLYNOMIAL::Z_PERM_SHIFT] = z_perm_poly.shifted(); - evaluations_array[POLYNOMIAL::Q_M] = prover.key->polynomial_store.get("q_m_lagrange"); - evaluations_array[POLYNOMIAL::Q_L] = prover.key->polynomial_store.get("q_1_lagrange"); - evaluations_array[POLYNOMIAL::Q_R] = prover.key->polynomial_store.get("q_2_lagrange"); - evaluations_array[POLYNOMIAL::Q_O] = prover.key->polynomial_store.get("q_3_lagrange"); - evaluations_array[POLYNOMIAL::Q_C] = prover.key->polynomial_store.get("q_c_lagrange"); - evaluations_array[POLYNOMIAL::SIGMA_1] = prover.key->polynomial_store.get("sigma_1_lagrange"); - evaluations_array[POLYNOMIAL::SIGMA_2] = prover.key->polynomial_store.get("sigma_2_lagrange"); - evaluations_array[POLYNOMIAL::SIGMA_3] = prover.key->polynomial_store.get("sigma_3_lagrange"); - evaluations_array[POLYNOMIAL::ID_1] = prover.key->polynomial_store.get("id_1_lagrange"); - evaluations_array[POLYNOMIAL::ID_2] = prover.key->polynomial_store.get("id_2_lagrange"); - evaluations_array[POLYNOMIAL::ID_3] = prover.key->polynomial_store.get("id_3_lagrange"); - evaluations_array[POLYNOMIAL::LAGRANGE_FIRST] = prover.key->polynomial_store.get("L_first_lagrange"); - evaluations_array[POLYNOMIAL::LAGRANGE_LAST] = prover.key->polynomial_store.get("L_last_lagrange"); - - // Construct the round for applying sumcheck relations and results for storing computed results - auto relations = std::tuple(honk::sumcheck::ArithmeticRelation(), - honk::sumcheck::GrandProductComputationRelation(), - honk::sumcheck::GrandProductInitializationRelation()); - - fr result = 0; - for (size_t i = 0; i < prover.key->circuit_size; i++) { - // Compute an array containing all the evaluations at a given row i - std::array evaluations_at_index_i; - for (size_t j = 0; j < num_polynomials; ++j) { - evaluations_at_index_i[j] = evaluations_array[j][i]; - } - - // For each relation, call the `accumulate_relation_evaluation` over all witness/selector values at the - // i-th row/vertex of the hypercube. - // We use ASSERT_EQ instead of EXPECT_EQ so that the tests stops at the first index at which the result is not - // 0, since result = 0 + C(transposed), which we expect will equal 0. - std::get<0>(relations).add_full_relation_value_contribution(result, evaluations_at_index_i, params); - ASSERT_EQ(result, 0); - - std::get<1>(relations).add_full_relation_value_contribution(result, evaluations_at_index_i, params); - ASSERT_EQ(result, 0); - - std::get<2>(relations).add_full_relation_value_contribution(result, evaluations_at_index_i, params); - ASSERT_EQ(result, 0); - } -} - TEST(StandardHonkComposer, BaseCase) { auto composer = StandardHonkComposer(); diff --git a/cpp/src/barretenberg/honk/composer/ultra_honk_composer.hpp b/cpp/src/barretenberg/honk/composer/ultra_honk_composer.hpp new file mode 100644 index 0000000000..5fa40b4626 --- /dev/null +++ b/cpp/src/barretenberg/honk/composer/ultra_honk_composer.hpp @@ -0,0 +1,470 @@ +#pragma once +#include "barretenberg/plonk/composer/plookup_tables/plookup_tables.hpp" +#include "barretenberg/honk/proof_system/ultra_prover.hpp" +#include "barretenberg/proof_system/circuit_constructors/ultra_circuit_constructor.hpp" +#include "barretenberg/honk/composer/composer_helper/ultra_honk_composer_helper.hpp" +#include + +namespace proof_system::honk { + +class UltraHonkComposer { + + public: + // An instantiation of the circuit constructor that only depends on arithmetization, not on the proof system + UltraCircuitConstructor circuit_constructor; + // Composer helper contains all proof-related material that is separate from circuit creation such as: + // 1) Proving and verification keys + // 2) CRS + // 3) Converting variables to witness vectors/polynomials + UltraHonkComposerHelper composer_helper; + size_t& num_gates; + + UltraHonkComposer() + : UltraHonkComposer("../srs_db/ignition", 0){}; + + UltraHonkComposer(std::string const& crs_path, const size_t size_hint) + : UltraHonkComposer(std::unique_ptr(new FileReferenceStringFactory(crs_path)), + size_hint){}; + + UltraHonkComposer(std::shared_ptr const& crs_factory, const size_t size_hint) + : circuit_constructor(size_hint) + , composer_helper(crs_factory) + , num_gates(circuit_constructor.num_gates){}; + + UltraHonkComposer(std::shared_ptr const& p_key, + std::shared_ptr const& v_key, + size_t size_hint = 0); + UltraHonkComposer(UltraHonkComposer&& other) = default; + UltraHonkComposer& operator=(UltraHonkComposer&& other) = delete; + ~UltraHonkComposer() = default; + + uint32_t get_zero_idx() { return circuit_constructor.zero_idx; } + + uint32_t add_variable(const barretenberg::fr& in) { return circuit_constructor.add_variable(in); } + + barretenberg::fr get_variable(const uint32_t index) const { return circuit_constructor.get_variable(index); } + + void finalize_circuit() { circuit_constructor.finalize_circuit(); }; + + UltraProver create_prover() { return composer_helper.create_prover(circuit_constructor); }; + // UltraVerifier create_verifier() { return composer_helper.create_verifier(circuit_constructor); }; + + void create_add_gate(const add_triple& in) { circuit_constructor.create_add_gate(in); } + + void create_big_add_gate(const add_quad& in, const bool use_next_gate_w_4 = false) + { + circuit_constructor.create_big_add_gate(in, use_next_gate_w_4); + }; + + // void create_big_add_gate_with_bit_extraction(const add_quad& in); + // void create_big_mul_gate(const mul_quad& in); + // void create_balanced_add_gate(const add_quad& in); + + // void create_mul_gate(const mul_triple& in) override; + // void create_bool_gate(const uint32_t a) override; + // void create_poly_gate(const poly_triple& in) override; + void create_ecc_add_gate(const ecc_add_gate& in) { circuit_constructor.create_ecc_add_gate(in); }; + + // void fix_witness(const uint32_t witness_index, const barretenberg::fr& witness_value); + + // void add_recursive_proof(const std::vector& proof_output_witness_indices) + // { + // if (contains_recursive_proof) { + // failure("added recursive proof when one already exists"); + // } + // contains_recursive_proof = true; + + // for (const auto& idx : proof_output_witness_indices) { + // set_public_input(idx); + // recursive_proof_public_input_indices.push_back((uint32_t)(public_inputs.size() - 1)); + // } + // } + + void create_new_range_constraint(const uint32_t variable_index, + const uint64_t target_range, + std::string const msg = "create_new_range_constraint") + { + circuit_constructor.create_new_range_constraint(variable_index, target_range, msg); + }; + // void create_range_constraint(const uint32_t variable_index, const size_t num_bits, std::string const& msg) + // { + // if (num_bits <= DEFAULT_PLOOKUP_RANGE_BITNUM) { + // /** + // * N.B. if `variable_index` is not used in any arithmetic constraints, this will create an unsatisfiable + // * circuit! + // * this range constraint will increase the size of the 'sorted set' of range-constrained integers + // by 1. + // * The 'non-sorted set' of range-constrained integers is a subset of the wire indices of all + // arithmetic + // * 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. + // **/ + // create_new_range_constraint(variable_index, 1ULL << num_bits, msg); + // } else { + // decompose_into_default_range(variable_index, num_bits, DEFAULT_PLOOKUP_RANGE_BITNUM, msg); + // } + // } + + // accumulator_triple create_logic_constraint(const uint32_t a, + // const uint32_t b, + // const size_t num_bits, + // bool is_xor_gate); + // accumulator_triple create_and_constraint(const uint32_t a, const uint32_t b, const size_t num_bits); + // accumulator_triple create_xor_constraint(const uint32_t a, const uint32_t b, const size_t num_bits); + + // uint32_t put_constant_variable(const barretenberg::fr& variable); + + // size_t get_num_constant_gates() const override { return 0; } + + // /** + // * @brief Get the final number of gates in a circuit, which consists of the sum of: + // * 1) Current number number of actual gates + // * 2) Number of public inputs, as we'll need to add a gate for each of them + // * 3) Number of Rom array-associated gates + // * 4) NUmber of range-list associated gates + // * + // * + // * @param count return arument, number of existing gates + // * @param rangecount return argument, extra gates due to range checks + // * @param romcount return argument, extra gates due to rom reads + // * @param ramcount return argument, extra gates due to ram read/writes + // */ + // void get_num_gates_split_into_components(size_t& count, + // size_t& rangecount, + // size_t& romcount, + // size_t& ramcount) const + // { + // count = num_gates; + // // each ROM gate adds +1 extra gate due to the rom reads being copied to a sorted list set + // for (size_t i = 0; i < rom_arrays.size(); ++i) { + // for (size_t j = 0; j < rom_arrays[i].state.size(); ++j) { + // if (rom_arrays[i].state[j][0] == UNINITIALIZED_MEMORY_RECORD) { + // romcount += 2; + // } + // } + // romcount += (rom_arrays[i].records.size()); + // romcount += 1; // we add an addition gate after procesing a rom array + // } + + // constexpr size_t gate_width = ultra_settings::program_width; + // // each RAM gate adds +2 extra gates due to the ram reads being copied to a sorted list set, + // // as well as an extra gate to validate timestamps + // std::vector ram_timestamps; + // std::vector ram_range_sizes; + // std::vector ram_range_exists; + // for (size_t i = 0; i < ram_arrays.size(); ++i) { + // for (size_t j = 0; j < ram_arrays[i].state.size(); ++j) { + // if (ram_arrays[i].state[j] == UNINITIALIZED_MEMORY_RECORD) { + // ramcount += NUMBER_OF_GATES_PER_RAM_ACCESS; + // } + // } + // ramcount += (ram_arrays[i].records.size() * NUMBER_OF_GATES_PER_RAM_ACCESS); + // ramcount += NUMBER_OF_ARITHMETIC_GATES_PER_RAM_ARRAY; // we add an addition gate after procesing a ram + // array + + // // there will be 'max_timestamp' number of range checks, need to calculate. + // const auto max_timestamp = ram_arrays[i].access_count - 1; + + // // if a range check of length `max_timestamp` already exists, we are double counting. + // // We record `ram_timestamps` to detect and correct for this error when we process range lists. + // ram_timestamps.push_back(max_timestamp); + // size_t padding = (gate_width - (max_timestamp % gate_width)) % gate_width; + // if (max_timestamp == gate_width) + // padding += gate_width; + // const size_t ram_range_check_list_size = max_timestamp + padding; + + // size_t ram_range_check_gate_count = (ram_range_check_list_size / gate_width); + // ram_range_check_gate_count += 1; // we need to add 1 extra addition gates for every distinct range list + + // ram_range_sizes.push_back(ram_range_check_gate_count); + // ram_range_exists.push_back(false); + // // rangecount += ram_range_check_gate_count; + // } + // for (const auto& list : range_lists) { + // auto list_size = list.second.variable_indices.size(); + // size_t padding = (gate_width - (list.second.variable_indices.size() % gate_width)) % gate_width; + // if (list.second.variable_indices.size() == gate_width) + // padding += gate_width; + // list_size += padding; + + // for (size_t i = 0; i < ram_timestamps.size(); ++i) { + // if (list.second.target_range == ram_timestamps[i]) { + // ram_range_exists[i] = true; + // } + // } + // rangecount += (list_size / gate_width); + // rangecount += 1; // we need to add 1 extra addition gates for every distinct range list + // } + // // update rangecount to include the ram range checks the composer will eventually be creating + // for (size_t i = 0; i < ram_range_sizes.size(); ++i) { + // if (!ram_range_exists[i]) { + // rangecount += ram_range_sizes[i]; + // } + // } + // } + + // /** + // * @brief Get the final number of gates in a circuit, which consists of the sum of: + // * 1) Current number number of actual gates + // * 2) Number of public inputs, as we'll need to add a gate for each of them + // * 3) Number of Rom array-associated gates + // * 4) NUmber of range-list associated gates + // * + // * @return size_t + // */ + // virtual size_t get_num_gates() const override + // { + // // if circuit finalised already added extra gates + // if (circuit_finalised) { + // return num_gates; + // } + // size_t count = 0; + // size_t rangecount = 0; + // size_t romcount = 0; + // size_t ramcount = 0; + // get_num_gates_split_into_components(count, rangecount, romcount, ramcount); + // return count + romcount + ramcount + rangecount; + // } + + // virtual void print_num_gates() const override + // { + // size_t count = 0; + // size_t rangecount = 0; + // size_t romcount = 0; + // size_t ramcount = 0; + + // get_num_gates_split_into_components(count, rangecount, romcount, ramcount); + + // size_t total = count + romcount + ramcount + rangecount; + // std::cout << "gates = " << total << " (arith " << count << ", rom " << romcount << ", ram " << ramcount + // << ", range " << rangecount << "), pubinp = " << public_inputs.size() << std::endl; + // } + + void assert_equal(const uint32_t a_variable_idx, + const uint32_t b_variable_idx, + std::string const& msg = "assert_equal") + { + circuit_constructor.assert_equal(a_variable_idx, b_variable_idx, msg); + } + + // void assert_equal_constant(const uint32_t a_idx, + // const barretenberg::fr& b, + // std::string const& msg = "assert equal constant") + // { + // if (variables[a_idx] != b && !failed()) { + // failure(msg); + // } + // auto b_idx = put_constant_variable(b); + // assert_equal(a_idx, b_idx, msg); + // } + + // /** + // * Plookup Methods + // **/ + // void add_table_column_selector_poly_to_proving_key(polynomial& small, const std::string& tag); + // void initialize_precomputed_table( + // const plookup::BasicTableId id, + // bool (*generator)(std::vector&, + // std::vector&, + // std::vector&), + // std::array (*get_values_from_key)(const std::array)); + + // plookup::BasicTable& get_table(const plookup::BasicTableId id); + // plookup::MultiTable& create_table(const plookup::MultiTableId id); + + plookup::ReadData create_gates_from_plookup_accumulators( + const plookup::MultiTableId& id, + const plookup::ReadData& read_values, + const uint32_t key_a_index, + std::optional key_b_index = std::nullopt) + { + return circuit_constructor.create_gates_from_plookup_accumulators(id, read_values, key_a_index, key_b_index); + }; + + // /** + // * Generalized Permutation Methods + // **/ + std::vector decompose_into_default_range( + const uint32_t variable_index, + const uint64_t num_bits, + const uint64_t target_range_bitnum = DEFAULT_PLOOKUP_RANGE_BITNUM, + std::string const& msg = "decompose_into_default_range") + { + return circuit_constructor.decompose_into_default_range(variable_index, num_bits, target_range_bitnum, msg); + }; + // std::vector decompose_into_default_range_better_for_oddlimbnum( + // const uint32_t variable_index, + // const size_t num_bits, + // std::string const& msg = "decompose_into_default_range_better_for_oddlimbnum"); + void create_dummy_constraints(const std::vector& variable_index) + { + circuit_constructor.create_dummy_constraints(variable_index); + }; + void create_sort_constraint(const std::vector& variable_index) + { + circuit_constructor.create_sort_constraint(variable_index); + }; + void create_sort_constraint_with_edges(const std::vector& variable_index, + const barretenberg::fr& start, + const barretenberg::fr& end) + { + circuit_constructor.create_sort_constraint_with_edges(variable_index, start, end); + }; + + void assign_tag(const uint32_t variable_index, const uint32_t tag) + { + circuit_constructor.assign_tag(variable_index, tag); + } + + // void assign_tag(const uint32_t variable_index, const uint32_t tag) + // { + // ASSERT(tag <= current_tag); + // ASSERT(real_variable_tags[real_variable_index[variable_index]] == DUMMY_TAG); + // real_variable_tags[real_variable_index[variable_index]] = tag; + // } + + uint32_t create_tag(const uint32_t tag_index, const uint32_t tau_index) + { + return circuit_constructor.create_tag(tag_index, tau_index); + } + + // uint32_t get_new_tag() + // { + // current_tag++; + // return current_tag; + // } + + // RangeList create_range_list(const uint64_t target_range); + // void process_range_list(const RangeList& list); + // void process_range_lists(); + + // /** + // * Custom Gate Selectors + // **/ + // void apply_aux_selectors(const AUX_SELECTORS type); + + // /** + // * Non Native Field Arithmetic + // **/ + void range_constrain_two_limbs(const uint32_t lo_idx, + const uint32_t hi_idx, + const size_t lo_limb_bits = DEFAULT_NON_NATIVE_FIELD_LIMB_BITS, + const size_t hi_limb_bits = DEFAULT_NON_NATIVE_FIELD_LIMB_BITS) + { + circuit_constructor.range_constrain_two_limbs(lo_idx, hi_idx, lo_limb_bits, hi_limb_bits); + }; + // std::array decompose_non_native_field_double_width_limb( + // const uint32_t limb_idx, const size_t num_limb_bits = (2 * DEFAULT_NON_NATIVE_FIELD_LIMB_BITS)); + std::array evaluate_non_native_field_multiplication( + const non_native_field_witnesses& input, const bool range_constrain_quotient_and_remainder = true) + { + return circuit_constructor.evaluate_non_native_field_multiplication(input, + range_constrain_quotient_and_remainder); + }; + // std::array evaluate_partial_non_native_field_multiplication(const non_native_field_witnesses& + // input); typedef std::pair scaled_witness; typedef std::tuple add_simple; std::array evaluate_non_native_field_subtraction( + // add_simple limb0, + // add_simple limb1, + // add_simple limb2, + // add_simple limb3, + // std::tuple limbp); + // std::array evaluate_non_native_field_addition(add_simple limb0, + // add_simple limb1, + // add_simple limb2, + // add_simple limb3, + // std::tuple + // limbp); + + // /** + // * Memory + // **/ + + size_t create_RAM_array(const size_t array_size) { return circuit_constructor.create_RAM_array(array_size); }; + size_t create_ROM_array(const size_t array_size) { return circuit_constructor.create_ROM_array(array_size); }; + + void set_ROM_element(const size_t rom_id, const size_t index_value, const uint32_t value_witness) + { + circuit_constructor.set_ROM_element(rom_id, index_value, value_witness); + }; + // void set_ROM_element_pair(const size_t rom_id, + // const size_t index_value, + // const std::array& value_witnesses); + uint32_t read_ROM_array(const size_t rom_id, const uint32_t index_witness) + { + return circuit_constructor.read_ROM_array(rom_id, index_witness); + }; + // std::array read_ROM_array_pair(const size_t rom_id, const uint32_t index_witness); + // void create_ROM_gate(RomRecord& record); + // void create_sorted_ROM_gate(RomRecord& record); + // void process_ROM_array(const size_t rom_id, const size_t gate_offset_from_public_inputs); + // void process_ROM_arrays(const size_t gate_offset_from_public_inputs); + + // void create_RAM_gate(RamRecord& record); + // void create_sorted_RAM_gate(RamRecord& record); + // void create_final_sorted_RAM_gate(RamRecord& record, const size_t ram_array_size); + + // size_t create_RAM_array(const size_t array_size); + void init_RAM_element(const size_t ram_id, const size_t index_value, const uint32_t value_witness) + { + circuit_constructor.init_RAM_element(ram_id, index_value, value_witness); + }; + uint32_t read_RAM_array(const size_t ram_id, const uint32_t index_witness) + { + return circuit_constructor.read_RAM_array(ram_id, index_witness); + }; + void write_RAM_array(const size_t ram_id, const uint32_t index_witness, const uint32_t value_witness) + { + circuit_constructor.write_RAM_array(ram_id, index_witness, value_witness); + }; + // void process_RAM_array(const size_t ram_id, const size_t gate_offset_from_public_inputs); + // void process_RAM_arrays(const size_t gate_offset_from_public_inputs); + + // /** + // * Member Variables + // **/ + + // uint32_t zero_idx = 0; + bool circuit_finalised = false; + + // // This variable controls the amount with which the lookup table and witness values need to be shifted + // // above to make room for adding randomness into the permutation and witness polynomials in the plookup widget. + // // This must be (num_roots_cut_out_of_the_vanishing_polynomial - 1), since the variable num_roots_cut_out_of_ + // // vanishing_polynomial cannot be trivially fetched here, I am directly setting this to 4 - 1 = 3. + // static constexpr size_t s_randomness = 3; + + // // these are variables that we have used a gate on, to enforce that they are equal to a defined value + // std::map constant_variable_indices; + + // std::vector lookup_tables; + // std::vector lookup_multi_tables; + // std::map range_lists; // DOCTODO: explain this. + + // /** + // * @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 + // */ + // std::vector ram_arrays; + + // /** + // * @brief Each entry in ram_arrays represents an independent ROM table. + // * RomTranscript tracks the current table state, + // * as well as the 'records' produced by each read operation. + // * Used in `compute_proving_key` to generate consistency check gates required to validate the ROM read history + // */ + // std::vector rom_arrays; + + // // Stores gate index of ROM and RAM reads (required by proving key) + // std::vector memory_read_records; + // // Stores gate index of RAM writes (required by proving key) + // std::vector memory_write_records; + + // std::vector recursive_proof_public_input_indices; + // bool contains_recursive_proof = false; +}; +} // namespace proof_system::honk diff --git a/cpp/src/barretenberg/honk/composer/ultra_honk_composer.test.cpp b/cpp/src/barretenberg/honk/composer/ultra_honk_composer.test.cpp new file mode 100644 index 0000000000..0c8f1baefc --- /dev/null +++ b/cpp/src/barretenberg/honk/composer/ultra_honk_composer.test.cpp @@ -0,0 +1,1036 @@ +#include "ultra_honk_composer.hpp" +#include "barretenberg/common/log.hpp" +#include "barretenberg/honk/proof_system/ultra_prover.hpp" +#include "barretenberg/honk/sumcheck/relations/relation.hpp" +#include "barretenberg/numeric/uint256/uint256.hpp" +#include "barretenberg/honk/flavor/flavor.hpp" +#include +#include +#include "barretenberg/honk/proof_system/prover.hpp" +#include "barretenberg/honk/sumcheck/sumcheck_round.hpp" +#include "barretenberg/honk/sumcheck/relations/grand_product_computation_relation.hpp" +#include "barretenberg/honk/sumcheck/relations/grand_product_initialization_relation.hpp" +#include "barretenberg/honk/utils/public_inputs.hpp" + +// TODO(luke): TEMPORARY; for testing only (comparison with Ultra Plonk composers) +#include "barretenberg/plonk/composer/ultra_composer.hpp" +#include "barretenberg/plonk/composer/splitting_tmp/ultra_plonk_composer.hpp" +#include "barretenberg/plonk/proof_system/prover/prover.hpp" + +#include +#include + +using namespace proof_system::honk; + +namespace test_ultra_honk_composer { + +std::vector add_variables(auto& composer, std::vector variables) +{ + std::vector res; + for (size_t i = 0; i < variables.size(); i++) { + res.emplace_back(composer.add_variable(variables[i])); + } + return res; +} + +/** + * @brief TEMPORARY method for checking consistency of polynomials computed by Ultra Plonk/Honk composers + * + * @param honk_prover + * @param plonk_prover + */ +// NOTE: Currently checking exact consistency for witness polynomials (wires, sorted lists) and table polys. +// The permutation polys are computed differently between plonk and honk so we do not expect consistency. +// Equality is checked on all selectors but we ignore the final entry since we do not enforce non-zero selectors in +// Honk. +void verify_consistency(honk::UltraProver& honk_prover, plonk::UltraProver& plonk_prover) +{ + auto& honk_store = honk_prover.key->polynomial_store; + auto& plonk_store = plonk_prover.key->polynomial_store; + + // Check that all selectors agree (aside from the final element which will differ due to not enforcing non-zero + // selectors in Honk). + for (auto& entry : honk_store) { + std::string key = entry.first; + bool is_selector = (key.find("q_") != std::string::npos) || (key.find("table_type") != std::string::npos); + if (plonk_store.contains(key) && is_selector) { + // check equality for all but final entry + for (size_t i = 0; i < honk_store.get(key).size() - 1; ++i) { + ASSERT_EQ(honk_store.get(key)[i], plonk_store.get(key)[i]); + } + } + } + + // Check that sorted witness-table and table polys agree + for (auto& entry : honk_store) { + std::string key = entry.first; + bool is_sorted_table = (key.find("s_") != std::string::npos); + bool is_table = (key.find("table_value_") != std::string::npos); + if (plonk_store.contains(key) && (is_sorted_table || is_table)) { + ASSERT_EQ(honk_store.get(key), plonk_store.get(key)); + } + } + + // Check that all wires agree + // Note: for Honk, wires are owned directly by the prover. For Plonk they are stored in the key. + for (size_t i = 0; i < 4; ++i) { + std::string label = "w_" + std::to_string(i + 1) + "_lagrange"; + ASSERT_EQ(honk_prover.wire_polynomials[i], plonk_prover.key->polynomial_store.get(label)); + } +} + +/** + * @brief TEMPORARY (verbose) method for checking consistency of polynomials computed by Ultra Plonk/Honk composers + * + * @param honk_prover + * @param plonk_prover + */ +void check_consistency(honk::UltraProver& honk_prover, plonk::UltraProver& plonk_prover) +{ + auto& honk_store = honk_prover.key->polynomial_store; + auto& plonk_store = plonk_prover.key->polynomial_store; + for (auto& entry : honk_store) { + std::string key = entry.first; + if (plonk_store.contains(key)) { + + bool polys_equal = (honk_store.get(key) == plonk_store.get(key)); + if (polys_equal) { + info("Equal: ", key); + } + if (!polys_equal) { + info("UNEQUAL: ", key); + } + } + } + + for (size_t i = 0; i < 4; ++i) { + std::string label = "w_" + std::to_string(i + 1) + "_lagrange"; + bool wire_equal = (honk_prover.wire_polynomials[i] == plonk_prover.key->polynomial_store.get(label)); + if (wire_equal) { + info("Wire Equal: ", i); + } + if (!wire_equal) { + info("Wire UNEQUAL: ", i); + } + } + + // std::string label = "w_1_lagrange"; + // for (size_t i = 0; i < plonk_store.get(label).size(); ++i) { + // auto val_honk = honk_prover.wire_polynomials[0][i]; + // // auto val_honk = honk_store.get(label)[i]; + // auto val_plonk = plonk_store.get(label)[i]; + // if (val_honk != val_plonk) { + // info("UNEQUAL index = ", i); + // info("honk: ",val_honk); + // info("plonk: ", val_plonk); + // } + // } +} + +TEST(UltraHonkComposer, create_gates_from_plookup_accumulators) +{ + auto honk_composer = UltraHonkComposer(); + auto plonk_composer = proof_system::plonk::UltraComposer(); + + barretenberg::fr input_value = fr::random_element(); + { + + const fr input_hi = uint256_t(input_value).slice(126, 256); + const fr input_lo = uint256_t(input_value).slice(0, 126); + const auto input_hi_index = honk_composer.add_variable(input_hi); + const auto input_lo_index = honk_composer.add_variable(input_lo); + + const auto sequence_data_hi = + plookup::get_lookup_accumulators(plookup::MultiTableId::PEDERSEN_LEFT_HI, input_hi); + const auto sequence_data_lo = + plookup::get_lookup_accumulators(plookup::MultiTableId::PEDERSEN_LEFT_LO, input_lo); + + const auto lookup_witnesses_hi = honk_composer.create_gates_from_plookup_accumulators( + plookup::MultiTableId::PEDERSEN_LEFT_HI, sequence_data_hi, input_hi_index); + const auto lookup_witnesses_lo = honk_composer.create_gates_from_plookup_accumulators( + plookup::MultiTableId::PEDERSEN_LEFT_LO, sequence_data_lo, input_lo_index); + } + { + const fr input_hi = uint256_t(input_value).slice(126, 256); + const fr input_lo = uint256_t(input_value).slice(0, 126); + const auto input_hi_index = plonk_composer.add_variable(input_hi); + const auto input_lo_index = plonk_composer.add_variable(input_lo); + + const auto sequence_data_hi = + plookup::get_lookup_accumulators(plookup::MultiTableId::PEDERSEN_LEFT_HI, input_hi); + const auto sequence_data_lo = + plookup::get_lookup_accumulators(plookup::MultiTableId::PEDERSEN_LEFT_LO, input_lo); + + const auto lookup_witnesses_hi = plonk_composer.create_gates_from_plookup_accumulators( + plookup::MultiTableId::PEDERSEN_LEFT_HI, sequence_data_hi, input_hi_index); + const auto lookup_witnesses_lo = plonk_composer.create_gates_from_plookup_accumulators( + plookup::MultiTableId::PEDERSEN_LEFT_LO, sequence_data_lo, input_lo_index); + } + + auto honk_prover = honk_composer.create_prover(); + auto plonk_prover = plonk_composer.create_prover(); + + verify_consistency(honk_prover, plonk_prover); +} + +/** + * @brief Build UltraHonkComposer + * + */ +TEST(UltraHonkComposer, test_no_lookup_proof) +{ + auto honk_composer = UltraHonkComposer(); + auto plonk_composer = proof_system::plonk::UltraComposer(); + + size_t MM = 4; + for (size_t i = 0; i < MM; ++i) { + for (size_t j = 0; j < MM; ++j) { + uint64_t left = static_cast(j); + uint64_t right = static_cast(i); + uint32_t left_idx = honk_composer.add_variable(fr(left)); + uint32_t right_idx = honk_composer.add_variable(fr(right)); + uint32_t result_idx = honk_composer.add_variable(fr(left ^ right)); + + uint32_t add_idx = + honk_composer.add_variable(fr(left) + fr(right) + honk_composer.get_variable(result_idx)); + honk_composer.create_big_add_gate( + { left_idx, right_idx, result_idx, add_idx, fr(1), fr(1), fr(1), fr(-1), fr(0) }); + } + } + + for (size_t i = 0; i < MM; ++i) { + for (size_t j = 0; j < MM; ++j) { + uint64_t left = static_cast(j); + uint64_t right = static_cast(i); + uint32_t left_idx = plonk_composer.add_variable(fr(left)); + uint32_t right_idx = plonk_composer.add_variable(fr(right)); + uint32_t result_idx = plonk_composer.add_variable(fr(left ^ right)); + + uint32_t add_idx = + plonk_composer.add_variable(fr(left) + fr(right) + plonk_composer.get_variable(result_idx)); + plonk_composer.create_big_add_gate( + { left_idx, right_idx, result_idx, add_idx, fr(1), fr(1), fr(1), fr(-1), fr(0) }); + } + } + + auto honk_prover = honk_composer.create_prover(); + auto plonk_prover = plonk_composer.create_prover(); + + verify_consistency(honk_prover, plonk_prover); +} + +TEST(UltraHonkComposer, test_elliptic_gate) +{ + typedef grumpkin::g1::affine_element affine_element; + typedef grumpkin::g1::element element; + + auto honk_composer = UltraHonkComposer(); + auto plonk_composer = proof_system::plonk::UltraComposer(); + + { + affine_element p1 = crypto::generators::get_generator_data({ 0, 0 }).generator; + affine_element p2 = crypto::generators::get_generator_data({ 0, 1 }).generator; + affine_element p3(element(p1) + element(p2)); + + uint32_t x1 = honk_composer.add_variable(p1.x); + uint32_t y1 = honk_composer.add_variable(p1.y); + uint32_t x2 = honk_composer.add_variable(p2.x); + uint32_t y2 = honk_composer.add_variable(p2.y); + uint32_t x3 = honk_composer.add_variable(p3.x); + uint32_t y3 = honk_composer.add_variable(p3.y); + + ecc_add_gate gate{ x1, y1, x2, y2, x3, y3, 1, 1 }; + honk_composer.create_ecc_add_gate(gate); + + grumpkin::fq beta = grumpkin::fq::cube_root_of_unity(); + affine_element p2_endo = p2; + p2_endo.x *= beta; + p3 = affine_element(element(p1) + element(p2_endo)); + x3 = honk_composer.add_variable(p3.x); + y3 = honk_composer.add_variable(p3.y); + gate = ecc_add_gate{ x1, y1, x2, y2, x3, y3, beta, 1 }; + honk_composer.create_ecc_add_gate(gate); + + p2_endo.x *= beta; + p3 = affine_element(element(p1) - element(p2_endo)); + x3 = honk_composer.add_variable(p3.x); + y3 = honk_composer.add_variable(p3.y); + gate = ecc_add_gate{ x1, y1, x2, y2, x3, y3, beta.sqr(), -1 }; + honk_composer.create_ecc_add_gate(gate); + } + { + affine_element p1 = crypto::generators::get_generator_data({ 0, 0 }).generator; + affine_element p2 = crypto::generators::get_generator_data({ 0, 1 }).generator; + affine_element p3(element(p1) + element(p2)); + + uint32_t x1 = plonk_composer.add_variable(p1.x); + uint32_t y1 = plonk_composer.add_variable(p1.y); + uint32_t x2 = plonk_composer.add_variable(p2.x); + uint32_t y2 = plonk_composer.add_variable(p2.y); + uint32_t x3 = plonk_composer.add_variable(p3.x); + uint32_t y3 = plonk_composer.add_variable(p3.y); + + ecc_add_gate gate{ x1, y1, x2, y2, x3, y3, 1, 1 }; + plonk_composer.create_ecc_add_gate(gate); + + grumpkin::fq beta = grumpkin::fq::cube_root_of_unity(); + affine_element p2_endo = p2; + p2_endo.x *= beta; + p3 = affine_element(element(p1) + element(p2_endo)); + x3 = plonk_composer.add_variable(p3.x); + y3 = plonk_composer.add_variable(p3.y); + gate = ecc_add_gate{ x1, y1, x2, y2, x3, y3, beta, 1 }; + plonk_composer.create_ecc_add_gate(gate); + + p2_endo.x *= beta; + p3 = affine_element(element(p1) - element(p2_endo)); + x3 = plonk_composer.add_variable(p3.x); + y3 = plonk_composer.add_variable(p3.y); + gate = ecc_add_gate{ x1, y1, x2, y2, x3, y3, beta.sqr(), -1 }; + plonk_composer.create_ecc_add_gate(gate); + } + + auto honk_prover = honk_composer.create_prover(); + auto plonk_prover = plonk_composer.create_prover(); + + verify_consistency(honk_prover, plonk_prover); +} + +TEST(UltraHonkComposer, non_trivial_tag_permutation) +{ + auto honk_composer = UltraHonkComposer(); + auto plonk_composer = proof_system::plonk::UltraComposer(); + + fr a = fr::random_element(); + { + fr b = -a; + + auto a_idx = honk_composer.add_variable(a); + auto b_idx = honk_composer.add_variable(b); + auto c_idx = honk_composer.add_variable(b); + auto d_idx = honk_composer.add_variable(a); + + honk_composer.create_add_gate( + { a_idx, b_idx, honk_composer.get_zero_idx(), fr::one(), fr::one(), fr::zero(), fr::zero() }); + honk_composer.create_add_gate( + { c_idx, d_idx, honk_composer.get_zero_idx(), fr::one(), fr::one(), fr::zero(), fr::zero() }); + + honk_composer.create_tag(1, 2); + honk_composer.create_tag(2, 1); + + honk_composer.assign_tag(a_idx, 1); + honk_composer.assign_tag(b_idx, 1); + honk_composer.assign_tag(c_idx, 2); + honk_composer.assign_tag(d_idx, 2); + } + { + fr b = -a; + + auto a_idx = plonk_composer.add_variable(a); + auto b_idx = plonk_composer.add_variable(b); + auto c_idx = plonk_composer.add_variable(b); + auto d_idx = plonk_composer.add_variable(a); + + plonk_composer.create_add_gate( + { a_idx, b_idx, plonk_composer.zero_idx, fr::one(), fr::one(), fr::zero(), fr::zero() }); + plonk_composer.create_add_gate( + { c_idx, d_idx, plonk_composer.zero_idx, fr::one(), fr::one(), fr::zero(), fr::zero() }); + + plonk_composer.create_tag(1, 2); + plonk_composer.create_tag(2, 1); + + plonk_composer.assign_tag(a_idx, 1); + plonk_composer.assign_tag(b_idx, 1); + plonk_composer.assign_tag(c_idx, 2); + plonk_composer.assign_tag(d_idx, 2); + } + + auto honk_prover = honk_composer.create_prover(); + auto plonk_prover = plonk_composer.create_prover(); + + verify_consistency(honk_prover, plonk_prover); +} + +TEST(UltraHonkComposer, non_trivial_tag_permutation_and_cycles) +{ + auto honk_composer = UltraHonkComposer(); + auto plonk_composer = proof_system::plonk::UltraComposer(); + + fr a = fr::random_element(); + { + fr c = -a; + + auto a_idx = honk_composer.add_variable(a); + auto b_idx = honk_composer.add_variable(a); + honk_composer.assert_equal(a_idx, b_idx); + auto c_idx = honk_composer.add_variable(c); + auto d_idx = honk_composer.add_variable(c); + honk_composer.assert_equal(c_idx, d_idx); + auto e_idx = honk_composer.add_variable(a); + auto f_idx = honk_composer.add_variable(a); + honk_composer.assert_equal(e_idx, f_idx); + auto g_idx = honk_composer.add_variable(c); + auto h_idx = honk_composer.add_variable(c); + honk_composer.assert_equal(g_idx, h_idx); + + honk_composer.create_tag(1, 2); + honk_composer.create_tag(2, 1); + + honk_composer.assign_tag(a_idx, 1); + honk_composer.assign_tag(c_idx, 1); + honk_composer.assign_tag(e_idx, 2); + honk_composer.assign_tag(g_idx, 2); + + honk_composer.create_add_gate( + { b_idx, a_idx, honk_composer.get_zero_idx(), fr::one(), fr::neg_one(), fr::zero(), fr::zero() }); + honk_composer.create_add_gate( + { c_idx, g_idx, honk_composer.get_zero_idx(), fr::one(), -fr::one(), fr::zero(), fr::zero() }); + honk_composer.create_add_gate( + { e_idx, f_idx, honk_composer.get_zero_idx(), fr::one(), -fr::one(), fr::zero(), fr::zero() }); + } + { + fr c = -a; + + auto a_idx = plonk_composer.add_variable(a); + auto b_idx = plonk_composer.add_variable(a); + plonk_composer.assert_equal(a_idx, b_idx); + auto c_idx = plonk_composer.add_variable(c); + auto d_idx = plonk_composer.add_variable(c); + plonk_composer.assert_equal(c_idx, d_idx); + auto e_idx = plonk_composer.add_variable(a); + auto f_idx = plonk_composer.add_variable(a); + plonk_composer.assert_equal(e_idx, f_idx); + auto g_idx = plonk_composer.add_variable(c); + auto h_idx = plonk_composer.add_variable(c); + plonk_composer.assert_equal(g_idx, h_idx); + + plonk_composer.create_tag(1, 2); + plonk_composer.create_tag(2, 1); + + plonk_composer.assign_tag(a_idx, 1); + plonk_composer.assign_tag(c_idx, 1); + plonk_composer.assign_tag(e_idx, 2); + plonk_composer.assign_tag(g_idx, 2); + + plonk_composer.create_add_gate( + { b_idx, a_idx, plonk_composer.zero_idx, fr::one(), fr::neg_one(), fr::zero(), fr::zero() }); + plonk_composer.create_add_gate( + { c_idx, g_idx, plonk_composer.zero_idx, fr::one(), -fr::one(), fr::zero(), fr::zero() }); + plonk_composer.create_add_gate( + { e_idx, f_idx, plonk_composer.zero_idx, fr::one(), -fr::one(), fr::zero(), fr::zero() }); + } + + auto honk_prover = honk_composer.create_prover(); + auto plonk_prover = plonk_composer.create_prover(); + + verify_consistency(honk_prover, plonk_prover); +} + +TEST(UltraHonkComposer, bad_tag_permutation) +{ + auto honk_composer = UltraHonkComposer(); + auto plonk_composer = proof_system::plonk::UltraComposer(); + + fr a = fr::random_element(); + { + fr b = -a; + + auto a_idx = honk_composer.add_variable(a); + auto b_idx = honk_composer.add_variable(b); + auto c_idx = honk_composer.add_variable(b); + auto d_idx = honk_composer.add_variable(a + 1); + + honk_composer.create_add_gate({ a_idx, b_idx, honk_composer.get_zero_idx(), 1, 1, 0, 0 }); + honk_composer.create_add_gate({ c_idx, d_idx, honk_composer.get_zero_idx(), 1, 1, 0, -1 }); + + honk_composer.create_tag(1, 2); + honk_composer.create_tag(2, 1); + + honk_composer.assign_tag(a_idx, 1); + honk_composer.assign_tag(b_idx, 1); + honk_composer.assign_tag(c_idx, 2); + honk_composer.assign_tag(d_idx, 2); + } + { + fr b = -a; + + auto a_idx = plonk_composer.add_variable(a); + auto b_idx = plonk_composer.add_variable(b); + auto c_idx = plonk_composer.add_variable(b); + auto d_idx = plonk_composer.add_variable(a + 1); + + plonk_composer.create_add_gate({ a_idx, b_idx, plonk_composer.zero_idx, 1, 1, 0, 0 }); + plonk_composer.create_add_gate({ c_idx, d_idx, plonk_composer.zero_idx, 1, 1, 0, -1 }); + + plonk_composer.create_tag(1, 2); + plonk_composer.create_tag(2, 1); + + plonk_composer.assign_tag(a_idx, 1); + plonk_composer.assign_tag(b_idx, 1); + plonk_composer.assign_tag(c_idx, 2); + plonk_composer.assign_tag(d_idx, 2); + } + + auto honk_prover = honk_composer.create_prover(); + auto plonk_prover = plonk_composer.create_prover(); + + verify_consistency(honk_prover, plonk_prover); +} + +TEST(UltraHonkComposer, sort_widget) +{ + auto honk_composer = UltraHonkComposer(); + auto plonk_composer = proof_system::plonk::UltraComposer(); + + { + fr a = fr::one(); + fr b = fr(2); + fr c = fr(3); + fr d = fr(4); + + auto a_idx = honk_composer.add_variable(a); + auto b_idx = honk_composer.add_variable(b); + auto c_idx = honk_composer.add_variable(c); + auto d_idx = honk_composer.add_variable(d); + honk_composer.create_sort_constraint({ a_idx, b_idx, c_idx, d_idx }); + } + { + fr a = fr::one(); + fr b = fr(2); + fr c = fr(3); + fr d = fr(4); + + auto a_idx = plonk_composer.add_variable(a); + auto b_idx = plonk_composer.add_variable(b); + auto c_idx = plonk_composer.add_variable(c); + auto d_idx = plonk_composer.add_variable(d); + plonk_composer.create_sort_constraint({ a_idx, b_idx, c_idx, d_idx }); + } + + auto honk_prover = honk_composer.create_prover(); + auto plonk_prover = plonk_composer.create_prover(); + + verify_consistency(honk_prover, plonk_prover); +} + +TEST(UltraHonkComposer, sort_with_edges_gate) +{ + auto honk_composer = UltraHonkComposer(); + auto plonk_composer = proof_system::plonk::UltraComposer(); + + { + auto idx = add_variables(honk_composer, { 1, 2, 5, 6, 7, 10, 11, 13, 16, 17, 20, 22, 22, 25, + 26, 29, 29, 32, 32, 33, 35, 38, 39, 39, 42, 42, 43, 45 }); + + honk_composer.create_sort_constraint_with_edges(idx, 1, 29); + } + { + auto idx = add_variables(plonk_composer, { 1, 2, 5, 6, 7, 10, 11, 13, 16, 17, 20, 22, 22, 25, + 26, 29, 29, 32, 32, 33, 35, 38, 39, 39, 42, 42, 43, 45 }); + + plonk_composer.create_sort_constraint_with_edges(idx, 1, 29); + } + + auto honk_prover = honk_composer.create_prover(); + auto plonk_prover = plonk_composer.create_prover(); + + verify_consistency(honk_prover, plonk_prover); +} + +TEST(UltraHonkComposer, range_constraint) +{ + auto honk_composer = UltraHonkComposer(); + auto plonk_composer = proof_system::plonk::UltraComposer(); + + { + auto indices = + add_variables(honk_composer, { 1, 0, 3, 80, 5, 6, 29, 8, 15, 11, 32, 21, 42, 79, 16, 10, 3, 26, 13, 14 }); + for (size_t i = 0; i < indices.size(); i++) { + honk_composer.create_new_range_constraint(indices[i], 79); + } + honk_composer.create_dummy_constraints(indices); + } + { + auto indices = + add_variables(plonk_composer, { 1, 0, 3, 80, 5, 6, 29, 8, 15, 11, 32, 21, 42, 79, 16, 10, 3, 26, 13, 14 }); + for (size_t i = 0; i < indices.size(); i++) { + plonk_composer.create_new_range_constraint(indices[i], 79); + } + plonk_composer.create_dummy_constraints(indices); + } + + auto honk_prover = honk_composer.create_prover(); + auto plonk_prover = plonk_composer.create_prover(); + + verify_consistency(honk_prover, plonk_prover); +} + +TEST(UltraHonkComposer, range_with_gates) +{ + + auto honk_composer = UltraHonkComposer(); + auto plonk_composer = proof_system::plonk::UltraComposer(); + + { + auto idx = add_variables(honk_composer, { 1, 2, 3, 4, 5, 6, 7, 8 }); + for (size_t i = 0; i < idx.size(); i++) { + honk_composer.create_new_range_constraint(idx[i], 8); + } + + honk_composer.create_add_gate( + { idx[0], idx[1], honk_composer.get_zero_idx(), fr::one(), fr::one(), fr::zero(), -3 }); + honk_composer.create_add_gate( + { idx[2], idx[3], honk_composer.get_zero_idx(), fr::one(), fr::one(), fr::zero(), -7 }); + honk_composer.create_add_gate( + { idx[4], idx[5], honk_composer.get_zero_idx(), fr::one(), fr::one(), fr::zero(), -11 }); + honk_composer.create_add_gate( + { idx[6], idx[7], honk_composer.get_zero_idx(), fr::one(), fr::one(), fr::zero(), -15 }); + } + { + auto idx = add_variables(plonk_composer, { 1, 2, 3, 4, 5, 6, 7, 8 }); + for (size_t i = 0; i < idx.size(); i++) { + plonk_composer.create_new_range_constraint(idx[i], 8); + } + + plonk_composer.create_add_gate( + { idx[0], idx[1], plonk_composer.zero_idx, fr::one(), fr::one(), fr::zero(), -3 }); + plonk_composer.create_add_gate( + { idx[2], idx[3], plonk_composer.zero_idx, fr::one(), fr::one(), fr::zero(), -7 }); + plonk_composer.create_add_gate( + { idx[4], idx[5], plonk_composer.zero_idx, fr::one(), fr::one(), fr::zero(), -11 }); + plonk_composer.create_add_gate( + { idx[6], idx[7], plonk_composer.zero_idx, fr::one(), fr::one(), fr::zero(), -15 }); + } + + auto honk_prover = honk_composer.create_prover(); + auto plonk_prover = plonk_composer.create_prover(); + + verify_consistency(honk_prover, plonk_prover); +} + +TEST(UltraHonkComposer, range_with_gates_where_range_is_not_a_power_of_two) +{ + auto honk_composer = UltraHonkComposer(); + auto plonk_composer = proof_system::plonk::UltraComposer(); + + { + auto idx = add_variables(honk_composer, { 1, 2, 3, 4, 5, 6, 7, 8 }); + for (size_t i = 0; i < idx.size(); i++) { + honk_composer.create_new_range_constraint(idx[i], 12); + } + + honk_composer.create_add_gate( + { idx[0], idx[1], honk_composer.get_zero_idx(), fr::one(), fr::one(), fr::zero(), -3 }); + honk_composer.create_add_gate( + { idx[2], idx[3], honk_composer.get_zero_idx(), fr::one(), fr::one(), fr::zero(), -7 }); + honk_composer.create_add_gate( + { idx[4], idx[5], honk_composer.get_zero_idx(), fr::one(), fr::one(), fr::zero(), -11 }); + honk_composer.create_add_gate( + { idx[6], idx[7], honk_composer.get_zero_idx(), fr::one(), fr::one(), fr::zero(), -15 }); + } + { + auto idx = add_variables(plonk_composer, { 1, 2, 3, 4, 5, 6, 7, 8 }); + for (size_t i = 0; i < idx.size(); i++) { + plonk_composer.create_new_range_constraint(idx[i], 12); + } + + plonk_composer.create_add_gate( + { idx[0], idx[1], plonk_composer.zero_idx, fr::one(), fr::one(), fr::zero(), -3 }); + plonk_composer.create_add_gate( + { idx[2], idx[3], plonk_composer.zero_idx, fr::one(), fr::one(), fr::zero(), -7 }); + plonk_composer.create_add_gate( + { idx[4], idx[5], plonk_composer.zero_idx, fr::one(), fr::one(), fr::zero(), -11 }); + plonk_composer.create_add_gate( + { idx[6], idx[7], plonk_composer.zero_idx, fr::one(), fr::one(), fr::zero(), -15 }); + } + + auto honk_prover = honk_composer.create_prover(); + auto plonk_prover = plonk_composer.create_prover(); + + verify_consistency(honk_prover, plonk_prover); +} + +TEST(UltraHonkComposer, sort_widget_complex) +{ + auto honk_composer = UltraHonkComposer(); + auto plonk_composer = proof_system::plonk::UltraComposer(); + + { + std::vector a = { 1, 3, 4, 7, 7, 8, 16, 14, 15, 15, 18, 19, 21, 21, 24, 25, 26, 27, 30, 32 }; + std::vector ind; + for (size_t i = 0; i < a.size(); i++) + ind.emplace_back(honk_composer.add_variable(a[i])); + honk_composer.create_sort_constraint(ind); + } + { + std::vector a = { 1, 3, 4, 7, 7, 8, 16, 14, 15, 15, 18, 19, 21, 21, 24, 25, 26, 27, 30, 32 }; + std::vector ind; + for (size_t i = 0; i < a.size(); i++) + ind.emplace_back(plonk_composer.add_variable(a[i])); + plonk_composer.create_sort_constraint(ind); + } + + auto honk_prover = honk_composer.create_prover(); + auto plonk_prover = plonk_composer.create_prover(); + + verify_consistency(honk_prover, plonk_prover); +} + +TEST(UltraHonkComposer, composed_range_constraint) +{ + auto honk_composer = UltraHonkComposer(); + auto plonk_composer = proof_system::plonk::UltraComposer(); + + auto c = fr::random_element(); + { + auto d = uint256_t(c).slice(0, 133); + auto e = fr(d); + auto a_idx = honk_composer.add_variable(fr(e)); + honk_composer.create_add_gate( + { a_idx, honk_composer.get_zero_idx(), honk_composer.get_zero_idx(), 1, 0, 0, -fr(e) }); + honk_composer.decompose_into_default_range(a_idx, 134); + } + { + auto d = uint256_t(c).slice(0, 133); + auto e = fr(d); + auto a_idx = plonk_composer.add_variable(fr(e)); + plonk_composer.create_add_gate({ a_idx, plonk_composer.zero_idx, plonk_composer.zero_idx, 1, 0, 0, -fr(e) }); + plonk_composer.decompose_into_default_range(a_idx, 134); + } + + auto honk_prover = honk_composer.create_prover(); + auto plonk_prover = plonk_composer.create_prover(); + + verify_consistency(honk_prover, plonk_prover); +} + +TEST(UltraHonkComposer, non_native_field_multiplication) +{ + auto honk_composer = UltraHonkComposer(); + auto plonk_composer = proof_system::plonk::UltraComposer(); + + fq a = fq::random_element(); + fq b = fq::random_element(); + { + uint256_t modulus = fq::modulus; + + uint1024_t a_big = uint512_t(uint256_t(a)); + uint1024_t b_big = uint512_t(uint256_t(b)); + uint1024_t p_big = uint512_t(uint256_t(modulus)); + + uint1024_t q_big = (a_big * b_big) / p_big; + uint1024_t r_big = (a_big * b_big) % p_big; + + uint256_t q(q_big.lo.lo); + uint256_t r(r_big.lo.lo); + + const auto split_into_limbs = [&](const uint512_t& input) { + constexpr size_t NUM_BITS = 68; + std::array limbs; + limbs[0] = input.slice(0, NUM_BITS).lo; + limbs[1] = input.slice(NUM_BITS * 1, NUM_BITS * 2).lo; + limbs[2] = input.slice(NUM_BITS * 2, NUM_BITS * 3).lo; + limbs[3] = input.slice(NUM_BITS * 3, NUM_BITS * 4).lo; + limbs[4] = fr(input.lo); + return limbs; + }; + + const auto get_limb_witness_indices = [&](const std::array& limbs) { + std::array limb_indices; + limb_indices[0] = honk_composer.add_variable(limbs[0]); + limb_indices[1] = honk_composer.add_variable(limbs[1]); + limb_indices[2] = honk_composer.add_variable(limbs[2]); + limb_indices[3] = honk_composer.add_variable(limbs[3]); + limb_indices[4] = honk_composer.add_variable(limbs[4]); + return limb_indices; + }; + const uint512_t BINARY_BASIS_MODULUS = uint512_t(1) << (68 * 4); + auto modulus_limbs = split_into_limbs(BINARY_BASIS_MODULUS - uint512_t(modulus)); + + const auto a_indices = get_limb_witness_indices(split_into_limbs(uint256_t(a))); + const auto b_indices = get_limb_witness_indices(split_into_limbs(uint256_t(b))); + const auto q_indices = get_limb_witness_indices(split_into_limbs(uint256_t(q))); + const auto r_indices = get_limb_witness_indices(split_into_limbs(uint256_t(r))); + + proof_system::non_native_field_witnesses inputs{ + a_indices, b_indices, q_indices, r_indices, modulus_limbs, fr(uint256_t(modulus)), + }; + const auto [lo_1_idx, hi_1_idx] = honk_composer.evaluate_non_native_field_multiplication(inputs); + honk_composer.range_constrain_two_limbs(lo_1_idx, hi_1_idx, 70, 70); + } + { + uint256_t modulus = fq::modulus; + + uint1024_t a_big = uint512_t(uint256_t(a)); + uint1024_t b_big = uint512_t(uint256_t(b)); + uint1024_t p_big = uint512_t(uint256_t(modulus)); + + uint1024_t q_big = (a_big * b_big) / p_big; + uint1024_t r_big = (a_big * b_big) % p_big; + + uint256_t q(q_big.lo.lo); + uint256_t r(r_big.lo.lo); + + const auto split_into_limbs = [&](const uint512_t& input) { + constexpr size_t NUM_BITS = 68; + std::array limbs; + limbs[0] = input.slice(0, NUM_BITS).lo; + limbs[1] = input.slice(NUM_BITS * 1, NUM_BITS * 2).lo; + limbs[2] = input.slice(NUM_BITS * 2, NUM_BITS * 3).lo; + limbs[3] = input.slice(NUM_BITS * 3, NUM_BITS * 4).lo; + limbs[4] = fr(input.lo); + return limbs; + }; + + const auto get_limb_witness_indices = [&](const std::array& limbs) { + std::array limb_indices; + limb_indices[0] = plonk_composer.add_variable(limbs[0]); + limb_indices[1] = plonk_composer.add_variable(limbs[1]); + limb_indices[2] = plonk_composer.add_variable(limbs[2]); + limb_indices[3] = plonk_composer.add_variable(limbs[3]); + limb_indices[4] = plonk_composer.add_variable(limbs[4]); + return limb_indices; + }; + const uint512_t BINARY_BASIS_MODULUS = uint512_t(1) << (68 * 4); + auto modulus_limbs = split_into_limbs(BINARY_BASIS_MODULUS - uint512_t(modulus)); + + const auto a_indices = get_limb_witness_indices(split_into_limbs(uint256_t(a))); + const auto b_indices = get_limb_witness_indices(split_into_limbs(uint256_t(b))); + const auto q_indices = get_limb_witness_indices(split_into_limbs(uint256_t(q))); + const auto r_indices = get_limb_witness_indices(split_into_limbs(uint256_t(r))); + + proof_system::plonk::UltraComposer::non_native_field_witnesses inputs{ + a_indices, b_indices, q_indices, r_indices, modulus_limbs, fr(uint256_t(modulus)), + }; + const auto [lo_1_idx, hi_1_idx] = plonk_composer.evaluate_non_native_field_multiplication(inputs); + plonk_composer.range_constrain_two_limbs(lo_1_idx, hi_1_idx, 70, 70); + } + + auto honk_prover = honk_composer.create_prover(); + auto plonk_prover = plonk_composer.create_prover(); + + verify_consistency(honk_prover, plonk_prover); +} + +TEST(UltraHonkComposer, rom) +{ + auto honk_composer = UltraHonkComposer(); + auto plonk_composer = proof_system::plonk::UltraComposer(); + + auto a = fr::random_element(); + auto b = fr::random_element(); + auto c = fr::random_element(); + auto d = fr::random_element(); + auto e = fr::random_element(); + auto f = fr::random_element(); + auto g = fr::random_element(); + auto h = fr::random_element(); + { + uint32_t rom_values[8]{ + honk_composer.add_variable(a), honk_composer.add_variable(b), honk_composer.add_variable(c), + honk_composer.add_variable(d), honk_composer.add_variable(e), honk_composer.add_variable(f), + honk_composer.add_variable(g), honk_composer.add_variable(h), + }; + + size_t rom_id = honk_composer.create_ROM_array(8); + + for (size_t i = 0; i < 8; ++i) { + honk_composer.set_ROM_element(rom_id, i, rom_values[i]); + } + + uint32_t a_idx = honk_composer.read_ROM_array(rom_id, honk_composer.add_variable(5)); + EXPECT_EQ(a_idx != rom_values[5], true); + uint32_t b_idx = honk_composer.read_ROM_array(rom_id, honk_composer.add_variable(4)); + uint32_t c_idx = honk_composer.read_ROM_array(rom_id, honk_composer.add_variable(1)); + + const auto d_value = + honk_composer.get_variable(a_idx) + honk_composer.get_variable(b_idx) + honk_composer.get_variable(c_idx); + uint32_t d_idx = honk_composer.add_variable(d_value); + + honk_composer.create_big_add_gate({ + a_idx, + b_idx, + c_idx, + d_idx, + 1, + 1, + 1, + -1, + 0, + }); + } + { + uint32_t rom_values[8]{ + plonk_composer.add_variable(a), plonk_composer.add_variable(b), plonk_composer.add_variable(c), + plonk_composer.add_variable(d), plonk_composer.add_variable(e), plonk_composer.add_variable(f), + plonk_composer.add_variable(g), plonk_composer.add_variable(h), + }; + + size_t rom_id = plonk_composer.create_ROM_array(8); + + for (size_t i = 0; i < 8; ++i) { + plonk_composer.set_ROM_element(rom_id, i, rom_values[i]); + } + + uint32_t a_idx = plonk_composer.read_ROM_array(rom_id, plonk_composer.add_variable(5)); + EXPECT_EQ(a_idx != rom_values[5], true); + uint32_t b_idx = plonk_composer.read_ROM_array(rom_id, plonk_composer.add_variable(4)); + uint32_t c_idx = plonk_composer.read_ROM_array(rom_id, plonk_composer.add_variable(1)); + + const auto d_value = plonk_composer.get_variable(a_idx) + plonk_composer.get_variable(b_idx) + + plonk_composer.get_variable(c_idx); + uint32_t d_idx = plonk_composer.add_variable(d_value); + + plonk_composer.create_big_add_gate({ + a_idx, + b_idx, + c_idx, + d_idx, + 1, + 1, + 1, + -1, + 0, + }); + } + + auto honk_prover = honk_composer.create_prover(); + auto plonk_prover = plonk_composer.create_prover(); + + check_consistency(honk_prover, plonk_prover); + verify_consistency(honk_prover, plonk_prover); +} + +TEST(UltraHonkComposer, ram) +{ + auto honk_composer = UltraHonkComposer(); + auto plonk_composer = proof_system::plonk::UltraComposer(); + + auto a = fr::random_element(); + auto b = fr::random_element(); + auto c = fr::random_element(); + auto d = fr::random_element(); + auto e = fr::random_element(); + auto f = fr::random_element(); + auto g = fr::random_element(); + auto h = fr::random_element(); + { + uint32_t ram_values[8]{ + honk_composer.add_variable(a), honk_composer.add_variable(b), honk_composer.add_variable(c), + honk_composer.add_variable(d), honk_composer.add_variable(e), honk_composer.add_variable(f), + honk_composer.add_variable(g), honk_composer.add_variable(h), + }; + + size_t ram_id = honk_composer.create_RAM_array(8); + + for (size_t i = 0; i < 8; ++i) { + honk_composer.init_RAM_element(ram_id, i, ram_values[i]); + } + + uint32_t a_idx = honk_composer.read_RAM_array(ram_id, honk_composer.add_variable(5)); + EXPECT_EQ(a_idx != ram_values[5], true); + + uint32_t b_idx = honk_composer.read_RAM_array(ram_id, honk_composer.add_variable(4)); + uint32_t c_idx = honk_composer.read_RAM_array(ram_id, honk_composer.add_variable(1)); + + honk_composer.write_RAM_array(ram_id, honk_composer.add_variable(4), honk_composer.add_variable(500)); + uint32_t d_idx = honk_composer.read_RAM_array(ram_id, honk_composer.add_variable(4)); + + EXPECT_EQ(honk_composer.get_variable(d_idx), 500); + + // ensure these vars get used in another arithmetic gate + const auto e_value = honk_composer.get_variable(a_idx) + honk_composer.get_variable(b_idx) + + honk_composer.get_variable(c_idx) + honk_composer.get_variable(d_idx); + uint32_t e_idx = honk_composer.add_variable(e_value); + + honk_composer.create_big_add_gate( + { + a_idx, + b_idx, + c_idx, + d_idx, + -1, + -1, + -1, + -1, + 0, + }, + true); + honk_composer.create_big_add_gate( + { + honk_composer.get_zero_idx(), + honk_composer.get_zero_idx(), + honk_composer.get_zero_idx(), + e_idx, + 0, + 0, + 0, + 0, + 0, + }, + false); + } + { + uint32_t ram_values[8]{ + plonk_composer.add_variable(a), plonk_composer.add_variable(b), plonk_composer.add_variable(c), + plonk_composer.add_variable(d), plonk_composer.add_variable(e), plonk_composer.add_variable(f), + plonk_composer.add_variable(g), plonk_composer.add_variable(h), + }; + + size_t ram_id = plonk_composer.create_RAM_array(8); + + for (size_t i = 0; i < 8; ++i) { + plonk_composer.init_RAM_element(ram_id, i, ram_values[i]); + } + + uint32_t a_idx = plonk_composer.read_RAM_array(ram_id, plonk_composer.add_variable(5)); + EXPECT_EQ(a_idx != ram_values[5], true); + + uint32_t b_idx = plonk_composer.read_RAM_array(ram_id, plonk_composer.add_variable(4)); + uint32_t c_idx = plonk_composer.read_RAM_array(ram_id, plonk_composer.add_variable(1)); + + plonk_composer.write_RAM_array(ram_id, plonk_composer.add_variable(4), plonk_composer.add_variable(500)); + uint32_t d_idx = plonk_composer.read_RAM_array(ram_id, plonk_composer.add_variable(4)); + + EXPECT_EQ(plonk_composer.get_variable(d_idx), 500); + + // ensure these vars get used in another arithmetic gate + const auto e_value = plonk_composer.get_variable(a_idx) + plonk_composer.get_variable(b_idx) + + plonk_composer.get_variable(c_idx) + plonk_composer.get_variable(d_idx); + uint32_t e_idx = plonk_composer.add_variable(e_value); + + plonk_composer.create_big_add_gate( + { + a_idx, + b_idx, + c_idx, + d_idx, + -1, + -1, + -1, + -1, + 0, + }, + true); + plonk_composer.create_big_add_gate( + { + plonk_composer.zero_idx, + plonk_composer.zero_idx, + plonk_composer.zero_idx, + e_idx, + 0, + 0, + 0, + 0, + 0, + }, + false); + } + + auto honk_prover = honk_composer.create_prover(); + auto plonk_prover = plonk_composer.create_prover(); + + verify_consistency(honk_prover, plonk_prover); +} + +} // namespace test_ultra_honk_composer diff --git a/cpp/src/barretenberg/honk/flavor/flavor.hpp b/cpp/src/barretenberg/honk/flavor/flavor.hpp index ad47783e1d..c420ed64aa 100644 --- a/cpp/src/barretenberg/honk/flavor/flavor.hpp +++ b/cpp/src/barretenberg/honk/flavor/flavor.hpp @@ -14,7 +14,7 @@ struct StandardArithmetization { * This separation must be maintained to allow for programmatic access, but the ordering of the * polynomials can be permuted within each category if necessary. Polynomials can also be added * or removed (assuming consistency with the prover algorithm) but the constants describing the - * number of poynomials in each category must be manually updated. + * number of polynomials in each category must be manually updated. * */ enum POLYNOMIAL { @@ -187,4 +187,58 @@ struct StandardHonk { return output; } }; + +struct UltraArithmetization { + /** + * @brief All of the multivariate polynomials used by the Ultra Honk Prover. + * @details The polynomials are broken into three categories: precomputed, witness, and shifted. + * This separation must be maintained to allow for programmatic access, but the ordering of the + * polynomials can be permuted within each category if necessary. Polynomials can also be added + * or removed (assuming consistency with the prover algorithm) but the constants describing the + * number of polynomials in each category must be manually updated. + * + */ + enum POLYNOMIAL { + /* --- PRECOMPUTED POLYNOMIALS --- */ + Q_C, + Q_L, + Q_R, + Q_O, + Q_4, + Q_M, + QARITH, + QSORT, + QELLIPTIC, + QAUX, + QLOOKUPTYPE, + SIGMA_1, + SIGMA_2, + SIGMA_3, + SIGMA_4, + ID_1, + ID_2, + ID_3, + ID_4, + LAGRANGE_FIRST, + LAGRANGE_LAST, // = LAGRANGE_N-1 whithout ZK, but can be less + /* --- WITNESS POLYNOMIALS --- */ + W_L, + W_R, + W_O, + W_4, + S_1, + S_2, + S_3, + S_4, + Z_PERM, + Z_LOOKUP, + /* --- SHIFTED POLYNOMIALS --- */ + W_1_SHIFT, + W_4_SHIFT, + Z_PERM_SHIFT, + Z_LOOKUP_SHIFT, + /* --- --- */ + COUNT // for programmatic determination of NUM_POLYNOMIALS + }; +}; } // namespace proof_system::honk diff --git a/cpp/src/barretenberg/honk/proof_system/prover_library.cpp b/cpp/src/barretenberg/honk/proof_system/prover_library.cpp index d99a2947a4..753bee2b92 100644 --- a/cpp/src/barretenberg/honk/proof_system/prover_library.cpp +++ b/cpp/src/barretenberg/honk/proof_system/prover_library.cpp @@ -1,6 +1,7 @@ #include "prover_library.hpp" #include "barretenberg/plonk/proof_system/types/prover_settings.hpp" #include +#include namespace proof_system::honk::prover_library { @@ -55,19 +56,18 @@ Polynomial compute_permutation_grand_product(std::shared_ptr // Populate wire and permutation polynomials std::array, program_width> wires; std::array, program_width> sigmas; + std::array, program_width> ids; for (size_t i = 0; i < program_width; ++i) { - std::string sigma_id = "sigma_" + std::to_string(i + 1) + "_lagrange"; wires[i] = wire_polynomials[i]; - sigmas[i] = key->polynomial_store.get(sigma_id); + sigmas[i] = key->polynomial_store.get("sigma_" + std::to_string(i + 1) + "_lagrange"); + ids[i] = key->polynomial_store.get("id_" + std::to_string(i + 1) + "_lagrange"); } // Step (1) // TODO(#222)(kesha): Change the order to engage automatic prefetching and get rid of redundant computation for (size_t i = 0; i < key->circuit_size; ++i) { for (size_t k = 0; k < program_width; ++k) { - // Note(luke): this idx could be replaced by proper ID polys if desired - Fr idx = k * key->circuit_size + i; - numerator_accumulator[k][i] = wires[k][i] + (idx * beta) + gamma; // w_k(i) + β.(k*n+i) + γ + numerator_accumulator[k][i] = wires[k][i] + (ids[k][i] * beta) + gamma; // w_k(i) + β.id_k(i) + γ denominator_accumulator[k][i] = wires[k][i] + (sigmas[k][i] * beta) + gamma; // w_k(i) + β.σ_k(i) + γ } } diff --git a/cpp/src/barretenberg/honk/proof_system/prover_library.test.cpp b/cpp/src/barretenberg/honk/proof_system/prover_library.test.cpp index 0902129370..f62380ebc9 100644 --- a/cpp/src/barretenberg/honk/proof_system/prover_library.test.cpp +++ b/cpp/src/barretenberg/honk/proof_system/prover_library.test.cpp @@ -13,7 +13,6 @@ using namespace proof_system::honk; namespace prover_library_tests { -// field is named Fscalar here because of clash with the Fr template class ProverLibraryTests : public testing::Test { using Polynomial = barretenberg::Polynomial; @@ -60,13 +59,17 @@ template class ProverLibraryTests : public testing::Test { // can simply be random. We're not interested in the particular properties of the result. std::vector wires; std::vector sigmas; + std::vector ids; for (size_t i = 0; i < program_width; ++i) { wires.emplace_back(get_random_polynomial(num_gates)); sigmas.emplace_back(get_random_polynomial(num_gates)); + ids.emplace_back(get_random_polynomial(num_gates)); - // Add sigma polys to proving_key; to be used by the prover in constructing it's own z_perm - std::string sigma_id = "sigma_" + std::to_string(i + 1) + "_lagrange"; - proving_key->polynomial_store.put(sigma_id, Polynomial{ sigmas[i] }); + // Add sigma/ID polys to proving_key; to be used by the prover in constructing it's own z_perm + std::string sigma_label = "sigma_" + std::to_string(i + 1) + "_lagrange"; + proving_key->polynomial_store.put(sigma_label, Polynomial{ sigmas[i] }); + std::string id_label = "id_" + std::to_string(i + 1) + "_lagrange"; + proving_key->polynomial_store.put(id_label, Polynomial{ ids[i] }); } // Get random challenges @@ -109,8 +112,7 @@ template class ProverLibraryTests : public testing::Test { // Step (1) for (size_t i = 0; i < proving_key->circuit_size; ++i) { for (size_t k = 0; k < program_width; ++k) { - FF idx = k * proving_key->circuit_size + i; // id_k[i] - numererator_accum[k][i] = wires[k][i] + (idx * beta) + gamma; // w_k(i) + β.(k*n+i) + γ + numererator_accum[k][i] = wires[k][i] + (ids[k][i] * beta) + gamma; // w_k(i) + β.id_k(i) + γ denominator_accum[k][i] = wires[k][i] + (sigmas[k][i] * beta) + gamma; // w_k(i) + β.σ_k(i) + γ } } @@ -206,8 +208,8 @@ template class ProverLibraryTests : public testing::Test { // ∏(s_k + βs_{k+1} + γ(1 + β)) // // in a way that is simple to read (but inefficient). See prover library method for more details. - const Fr eta_sqr = eta.sqr(); - const Fr eta_cube = eta_sqr * eta; + const FF eta_sqr = eta.sqr(); + const FF eta_cube = eta_sqr * eta; std::array accumulators; for (size_t i = 0; i < 4; ++i) { @@ -219,12 +221,12 @@ template class ProverLibraryTests : public testing::Test { // Note: block_mask is used for efficient modulus, i.e. i % N := i & (N-1), for N = 2^k const size_t block_mask = circuit_size - 1; // Initialize 't(X)' to be used in an expression of the form t(X) + β*t(Xω) - Fr table_i = tables[0][0] + tables[1][0] * eta + tables[2][0] * eta_sqr + tables[3][0] * eta_cube; + FF table_i = tables[0][0] + tables[1][0] * eta + tables[2][0] * eta_sqr + tables[3][0] * eta_cube; for (size_t i = 0; i < circuit_size; ++i) { size_t shift_idx = (i + 1) & block_mask; // f = (w_1 + q_2*w_1(Xω)) + η(w_2 + q_m*w_2(Xω)) + η²(w_3 + q_c*w_3(Xω)) + η³q_index. - Fr f_i = (wires[0][i] + wires[0][shift_idx] * column_1_step_size[i]) + + FF f_i = (wires[0][i] + wires[0][shift_idx] * column_1_step_size[i]) + (wires[1][i] + wires[1][shift_idx] * column_2_step_size[i]) * eta + (wires[2][i] + wires[2][shift_idx] * column_3_step_size[i]) * eta_sqr + eta_cube * lookup_index_selector[i]; @@ -233,17 +235,17 @@ template class ProverLibraryTests : public testing::Test { accumulators[0][i] = lookup_selector[i] * f_i + gamma; // t = t_1 + ηt_2 + η²t_3 + η³t_4 - Fr table_i_plus_1 = tables[0][shift_idx] + eta * tables[1][shift_idx] + eta_sqr * tables[2][shift_idx] + + FF table_i_plus_1 = tables[0][shift_idx] + eta * tables[1][shift_idx] + eta_sqr * tables[2][shift_idx] + eta_cube * tables[3][shift_idx]; // t + βt(Xω) + γ(1 + β) - accumulators[1][i] = table_i + table_i_plus_1 * beta + gamma * (Fr::one() + beta); + accumulators[1][i] = table_i + table_i_plus_1 * beta + gamma * (FF::one() + beta); // (1 + β) - accumulators[2][i] = Fr::one() + beta; + accumulators[2][i] = FF::one() + beta; // s + βs(Xω) + γ(1 + β) - accumulators[3][i] = s_lagrange[i] + beta * s_lagrange[shift_idx] + gamma * (Fr::one() + beta); + accumulators[3][i] = s_lagrange[i] + beta * s_lagrange[shift_idx] + gamma * (FF::one() + beta); // Set t(X_i) for next iteration table_i = table_i_plus_1; @@ -303,8 +305,8 @@ template class ProverLibraryTests : public testing::Test { prover_library::compute_sorted_list_accumulator(proving_key, sorted_list_polynomials, eta); // Method 2: Compute local sorted list accumulator simply and inefficiently - const Fr eta_sqr = eta.sqr(); - const Fr eta_cube = eta_sqr * eta; + const FF eta_sqr = eta.sqr(); + const FF eta_cube = eta_sqr * eta; // Compute s = s_1 + η*s_2 + η²*s_3 + η³*s_4 Polynomial sorted_list_accumulator_expected{ sorted_list_polynomials[0] }; diff --git a/cpp/src/barretenberg/honk/proof_system/ultra_prover.cpp b/cpp/src/barretenberg/honk/proof_system/ultra_prover.cpp new file mode 100644 index 0000000000..769e744a6d --- /dev/null +++ b/cpp/src/barretenberg/honk/proof_system/ultra_prover.cpp @@ -0,0 +1,56 @@ +#include "ultra_prover.hpp" +#include +#include +#include "barretenberg/honk/proof_system/prover_library.hpp" +#include "barretenberg/honk/sumcheck/sumcheck.hpp" +#include +#include "barretenberg/honk/sumcheck/polynomials/univariate.hpp" // will go away +#include "barretenberg/honk/utils/power_polynomial.hpp" +#include "barretenberg/honk/pcs/commitment_key.hpp" +#include +#include +#include +#include +#include "barretenberg/ecc/curves/bn254/fr.hpp" +#include "barretenberg/ecc/curves/bn254/g1.hpp" +#include "barretenberg/honk/sumcheck/relations/arithmetic_relation.hpp" +#include "barretenberg/honk/sumcheck/relations/grand_product_computation_relation.hpp" +#include "barretenberg/honk/sumcheck/relations/grand_product_initialization_relation.hpp" +#include "barretenberg/polynomials/polynomial.hpp" +#include "barretenberg/honk/flavor/flavor.hpp" +#include "barretenberg/transcript/transcript_wrappers.hpp" +#include +#include "barretenberg/honk/pcs/claim.hpp" + +namespace proof_system::honk { + +/** + * Create UltraHonkProver from proving key, witness and manifest. + * + * @param input_key Proving key. + * @param input_manifest Input manifest + * + * @tparam settings Settings class. + * */ +template +UltraHonkProver::UltraHonkProver(std::vector&& wire_polys, + std::shared_ptr input_key) + : wire_polynomials(wire_polys) + , key(input_key) + , queue(key, transcript) +{} + +template plonk::proof& UltraHonkProver::export_proof() +{ + proof.proof_data = transcript.proof_data; + return proof; +} + +template plonk::proof& UltraHonkProver::construct_proof() +{ + return export_proof(); +} + +template class UltraHonkProver; + +} // namespace proof_system::honk diff --git a/cpp/src/barretenberg/honk/proof_system/ultra_prover.hpp b/cpp/src/barretenberg/honk/proof_system/ultra_prover.hpp new file mode 100644 index 0000000000..b645e5863f --- /dev/null +++ b/cpp/src/barretenberg/honk/proof_system/ultra_prover.hpp @@ -0,0 +1,63 @@ +#pragma once +#include "barretenberg/ecc/curves/bn254/fr.hpp" +#include "barretenberg/honk/pcs/shplonk/shplonk.hpp" +#include "barretenberg/polynomials/polynomial.hpp" +#include "barretenberg/honk/flavor/flavor.hpp" +#include +#include "barretenberg/plonk/proof_system/proving_key/proving_key.hpp" +#include "barretenberg/honk/pcs/commitment_key.hpp" +#include "barretenberg/plonk/proof_system/types/proof.hpp" +#include "barretenberg/plonk/proof_system/types/program_settings.hpp" +#include "barretenberg/honk/pcs/gemini/gemini.hpp" +#include "barretenberg/honk/pcs/shplonk/shplonk_single.hpp" +#include "barretenberg/honk/pcs/kzg/kzg.hpp" +#include "barretenberg/honk/transcript/transcript.hpp" +#include "barretenberg/honk/sumcheck/sumcheck.hpp" +#include "barretenberg/honk/sumcheck/sumcheck_output.hpp" +#include +#include +#include +#include +#include +#include +#include +#include +#include "barretenberg/honk/pcs/claim.hpp" +#include "barretenberg/honk/proof_system/prover_library.hpp" + +namespace proof_system::honk { + +// TODO(luke): The naming here is awkward. The Standard Honk prover is called "Prover" and aliased as StandardProver. To +// be consistent with that convention outside of the prover class itself, I've called this class UltraHonkProver and use +// the alias UltraProver externally. Resolve. +template class UltraHonkProver { + + using Fr = barretenberg::fr; + using Polynomial = barretenberg::Polynomial; + using Commitment = barretenberg::g1::affine_element; + using POLYNOMIAL = proof_system::honk::StandardArithmetization::POLYNOMIAL; + + public: + UltraHonkProver(std::vector&& wire_polys, + std::shared_ptr input_key = nullptr); + + plonk::proof& export_proof(); + plonk::proof& construct_proof(); + + ProverTranscript transcript; + + std::vector wire_polynomials; + + std::shared_ptr key; + + work_queue queue; + + private: + plonk::proof proof; +}; + +extern template class UltraHonkProver; + +using UltraProver = UltraHonkProver; + +} // namespace proof_system::honk diff --git a/cpp/src/barretenberg/honk/proof_system/verifier.cpp b/cpp/src/barretenberg/honk/proof_system/verifier.cpp index 26e4b7e033..b26f10fa47 100644 --- a/cpp/src/barretenberg/honk/proof_system/verifier.cpp +++ b/cpp/src/barretenberg/honk/proof_system/verifier.cpp @@ -3,7 +3,6 @@ #include #include #include "barretenberg/honk/transcript/transcript.hpp" -#include "barretenberg/plonk/proof_system/constants.hpp" #include "./verifier.hpp" #include "barretenberg/plonk/proof_system/public_inputs/public_inputs.hpp" #include "barretenberg/ecc/curves/bn254/fr.hpp" diff --git a/cpp/src/barretenberg/honk/proof_system/verifier.test.cpp b/cpp/src/barretenberg/honk/proof_system/verifier.test.cpp index b98d39e893..903ea36adb 100644 --- a/cpp/src/barretenberg/honk/proof_system/verifier.test.cpp +++ b/cpp/src/barretenberg/honk/proof_system/verifier.test.cpp @@ -1,5 +1,4 @@ #include "barretenberg/numeric/bitop/get_msb.hpp" -#include "barretenberg/plonk/proof_system/constants.hpp" #include "barretenberg/polynomials/polynomial.hpp" #include "barretenberg/honk/flavor/flavor.hpp" #include "prover.hpp" diff --git a/cpp/src/barretenberg/honk/sumcheck/relations/grand_product_computation_relation.hpp b/cpp/src/barretenberg/honk/sumcheck/relations/grand_product_computation_relation.hpp index 5ecdedf61d..61f799e030 100644 --- a/cpp/src/barretenberg/honk/sumcheck/relations/grand_product_computation_relation.hpp +++ b/cpp/src/barretenberg/honk/sumcheck/relations/grand_product_computation_relation.hpp @@ -90,4 +90,91 @@ template class GrandProductComputationRelation { (w_2 + beta * sigma_2 + gamma) * (w_3 + beta * sigma_3 + gamma)); }; }; + +// TODO(luke): With Cody's Flavor work it should be easier to create a simple templated relation +// for handling arbitrary width. For now I'm duplicating the width 3 logic for width 4. +template class UltraGrandProductComputationRelation { + public: + // 1 + polynomial degree of this relation + static constexpr size_t RELATION_LENGTH = 6; + using MULTIVARIATE = proof_system::honk::UltraArithmetization::POLYNOMIAL; + + /** + * @brief Compute contribution of the permutation relation for a given edge (internal function) + * + * @details This the relation confirms faithful calculation of the grand + * product polynomial Z_perm. + * + * @param evals transformed to `evals + C(extended_edges(X)...)*scaling_factor` + * @param extended_edges an std::array containing the fully extended Univariate edges. + * @param parameters contains beta, gamma, and public_input_delta, .... + * @param scaling_factor optional term to scale the evaluation before adding to evals. + */ + inline void add_edge_contribution(Univariate& evals, + const auto& extended_edges, + const RelationParameters& relation_parameters, + const FF& scaling_factor) const + { + const auto& beta = relation_parameters.beta; + const auto& gamma = relation_parameters.gamma; + const auto& public_input_delta = relation_parameters.public_input_delta; + + auto w_1 = UnivariateView(extended_edges[MULTIVARIATE::W_L]); + auto w_2 = UnivariateView(extended_edges[MULTIVARIATE::W_R]); + auto w_3 = UnivariateView(extended_edges[MULTIVARIATE::W_O]); + auto w_4 = UnivariateView(extended_edges[MULTIVARIATE::W_4]); + auto sigma_1 = UnivariateView(extended_edges[MULTIVARIATE::SIGMA_1]); + auto sigma_2 = UnivariateView(extended_edges[MULTIVARIATE::SIGMA_2]); + auto sigma_3 = UnivariateView(extended_edges[MULTIVARIATE::SIGMA_3]); + auto sigma_4 = UnivariateView(extended_edges[MULTIVARIATE::SIGMA_4]); + auto id_1 = UnivariateView(extended_edges[MULTIVARIATE::ID_1]); + auto id_2 = UnivariateView(extended_edges[MULTIVARIATE::ID_2]); + auto id_3 = UnivariateView(extended_edges[MULTIVARIATE::ID_3]); + auto id_4 = UnivariateView(extended_edges[MULTIVARIATE::ID_4]); + auto z_perm = UnivariateView(extended_edges[MULTIVARIATE::Z_PERM]); + auto z_perm_shift = UnivariateView(extended_edges[MULTIVARIATE::Z_PERM_SHIFT]); + auto lagrange_first = UnivariateView(extended_edges[MULTIVARIATE::LAGRANGE_FIRST]); + auto lagrange_last = UnivariateView(extended_edges[MULTIVARIATE::LAGRANGE_LAST]); + + // Contribution (1) + evals += (((z_perm + lagrange_first) * (w_1 + id_1 * beta + gamma) * (w_2 + id_2 * beta + gamma) * + (w_3 + id_3 * beta + gamma) * (w_4 + id_4 * beta + gamma)) - + ((z_perm_shift + lagrange_last * public_input_delta) * (w_1 + sigma_1 * beta + gamma) * + (w_2 + sigma_2 * beta + gamma) * (w_3 + sigma_3 * beta + gamma) * (w_4 + sigma_4 * beta + gamma))) * + scaling_factor; + }; + + void add_full_relation_value_contribution(FF& full_honk_relation_value, + auto& purported_evaluations, + const RelationParameters& relation_parameters) const + { + const auto& beta = relation_parameters.beta; + const auto& gamma = relation_parameters.gamma; + const auto& public_input_delta = relation_parameters.public_input_delta; + + auto w_1 = purported_evaluations[MULTIVARIATE::W_L]; + auto w_2 = purported_evaluations[MULTIVARIATE::W_R]; + auto w_3 = purported_evaluations[MULTIVARIATE::W_O]; + auto w_4 = purported_evaluations[MULTIVARIATE::W_4]; + auto sigma_1 = purported_evaluations[MULTIVARIATE::SIGMA_1]; + auto sigma_2 = purported_evaluations[MULTIVARIATE::SIGMA_2]; + auto sigma_3 = purported_evaluations[MULTIVARIATE::SIGMA_3]; + auto sigma_4 = purported_evaluations[MULTIVARIATE::SIGMA_4]; + auto id_1 = purported_evaluations[MULTIVARIATE::ID_1]; + auto id_2 = purported_evaluations[MULTIVARIATE::ID_2]; + auto id_3 = purported_evaluations[MULTIVARIATE::ID_3]; + auto id_4 = purported_evaluations[MULTIVARIATE::ID_4]; + auto z_perm = purported_evaluations[MULTIVARIATE::Z_PERM]; + auto z_perm_shift = purported_evaluations[MULTIVARIATE::Z_PERM_SHIFT]; + auto lagrange_first = purported_evaluations[MULTIVARIATE::LAGRANGE_FIRST]; + auto lagrange_last = purported_evaluations[MULTIVARIATE::LAGRANGE_LAST]; + + // Contribution (1) + full_honk_relation_value += + ((z_perm + lagrange_first) * (w_1 + beta * id_1 + gamma) * (w_2 + beta * id_2 + gamma) * + (w_3 + beta * id_3 + gamma) * (w_4 + beta * id_4 + gamma) - + (z_perm_shift + lagrange_last * public_input_delta) * (w_1 + beta * sigma_1 + gamma) * + (w_2 + beta * sigma_2 + gamma) * (w_3 + beta * sigma_3 + gamma) * (w_4 + beta * sigma_4 + gamma)); + }; +}; } // namespace proof_system::honk::sumcheck diff --git a/cpp/src/barretenberg/honk/sumcheck/relations/grand_product_initialization_relation.hpp b/cpp/src/barretenberg/honk/sumcheck/relations/grand_product_initialization_relation.hpp index 788cec7f52..6aa7d9f3b2 100644 --- a/cpp/src/barretenberg/honk/sumcheck/relations/grand_product_initialization_relation.hpp +++ b/cpp/src/barretenberg/honk/sumcheck/relations/grand_product_initialization_relation.hpp @@ -45,4 +45,48 @@ template class GrandProductInitializationRelation { full_honk_relation_value += lagrange_last * z_perm_shift; }; }; + +// TODO(luke): The only difference between the Ultra relation and the Standard version is the enum +// used to refer into the edge polynomials. Seems desireable to not duplicate the code here but +// leaving this as is until Codys Flavor work is settled. +template class UltraGrandProductInitializationRelation { + public: + // 1 + polynomial degree of this relation + static constexpr size_t RELATION_LENGTH = 3; + using MULTIVARIATE = UltraArithmetization::POLYNOMIAL; // could just get from StandardArithmetization + + /** + * @brief Add contribution of the permutation relation for a given edge + * + * @details There are 2 relations associated with enforcing the wire copy relations + * This file handles the relation Z_perm_shift(n_last) = 0 via the relation: + * + * C(X) = L_LAST(X) * Z_perm_shift(X) + * + * @param evals transformed to `evals + C(extended_edges(X)...)*scaling_factor` + * @param extended_edges an std::array containing the fully extended Univariate edges. + * @param parameters contains beta, gamma, and public_input_delta, .... + * @param scaling_factor optional term to scale the evaluation before adding to evals. + */ + void add_edge_contribution(Univariate& evals, + const auto& extended_edges, + const RelationParameters&, + const FF& scaling_factor) const + { + auto z_perm_shift = UnivariateView(extended_edges[MULTIVARIATE::Z_PERM_SHIFT]); + auto lagrange_last = UnivariateView(extended_edges[MULTIVARIATE::LAGRANGE_LAST]); + + evals += (lagrange_last * z_perm_shift) * scaling_factor; + }; + + void add_full_relation_value_contribution(FF& full_honk_relation_value, + auto& purported_evaluations, + const RelationParameters&) const + { + auto z_perm_shift = purported_evaluations[MULTIVARIATE::Z_PERM_SHIFT]; + auto lagrange_last = purported_evaluations[MULTIVARIATE::LAGRANGE_LAST]; + + full_honk_relation_value += lagrange_last * z_perm_shift; + }; +}; } // namespace proof_system::honk::sumcheck diff --git a/cpp/src/barretenberg/honk/sumcheck/relations/relation.hpp b/cpp/src/barretenberg/honk/sumcheck/relations/relation.hpp index a7860faeeb..e03f09f990 100644 --- a/cpp/src/barretenberg/honk/sumcheck/relations/relation.hpp +++ b/cpp/src/barretenberg/honk/sumcheck/relations/relation.hpp @@ -2,7 +2,6 @@ namespace proof_system::honk::sumcheck { -// TODO(#226)(Adrian): Remove zeta, alpha as they are not used by the relations. template struct RelationParameters { FF beta; FF gamma; diff --git a/cpp/src/barretenberg/honk/sumcheck/relations/relation.test.cpp b/cpp/src/barretenberg/honk/sumcheck/relations/relation_consistency.test.cpp similarity index 57% rename from cpp/src/barretenberg/honk/sumcheck/relations/relation.test.cpp rename to cpp/src/barretenberg/honk/sumcheck/relations/relation_consistency.test.cpp index 6b7e1ac521..5557d7d47c 100644 --- a/cpp/src/barretenberg/honk/sumcheck/relations/relation.test.cpp +++ b/cpp/src/barretenberg/honk/sumcheck/relations/relation_consistency.test.cpp @@ -1,3 +1,5 @@ +#include "barretenberg/honk/sumcheck/relations/ultra_arithmetic_relation.hpp" +#include "barretenberg/honk/sumcheck/relations/ultra_arithmetic_relation_secondary.hpp" #include "relation.hpp" #include "barretenberg/honk/flavor/flavor.hpp" #include "arithmetic_relation.hpp" @@ -9,6 +11,7 @@ #include "barretenberg/ecc/curves/bn254/fr.hpp" #include "barretenberg/numeric/random/engine.hpp" +#include #include using namespace proof_system::honk::sumcheck; /** @@ -21,13 +24,11 @@ using namespace proof_system::honk::sumcheck; points), * extends them (using barycentric formula) to six evaluation points, and stores them to an array of polynomials. */ -static const size_t input_univariate_length = 2; -static constexpr size_t FULL_RELATION_LENGTH = 5; -static const size_t NUM_POLYNOMIALS = proof_system::honk::StandardArithmetization::NUM_POLYNOMIALS; +static const size_t INPUT_UNIVARIATE_LENGTH = 2; namespace proof_system::honk_relation_tests { -template class SumcheckRelation : public testing::Test { +template class RelationConsistency : public testing::Test { public: template using Univariate = Univariate; template using UnivariateView = UnivariateView; @@ -35,11 +36,12 @@ template class SumcheckRelation : public testing::Test { // TODO(#225)(Adrian): Accept FULL_RELATION_LENGTH as a template parameter for this function only, so that the test // can decide to which degree the polynomials must be extended. Possible accept an existing list of "edges" and // extend them to the degree. + template static std::array, NUM_POLYNOMIALS> compute_mock_extended_edges( - std::array, NUM_POLYNOMIALS>& input_univariates) + std::array, NUM_POLYNOMIALS>& input_univariates) { - BarycentricData barycentric_2_to_max = - BarycentricData(); + BarycentricData barycentric_2_to_max = + BarycentricData(); std::array, NUM_POLYNOMIALS> extended_univariates; for (size_t i = 0; i < NUM_POLYNOMIALS; ++i) { extended_univariates[i] = barycentric_2_to_max.extend(input_univariates[i]); @@ -136,6 +138,7 @@ template class SumcheckRelation : public testing::Test { * @param extended_edges * @param relation_parameters */ + template static void validate_evaluations( const Univariate& expected_evals, const auto relation, @@ -166,31 +169,35 @@ template class SumcheckRelation : public testing::Test { }; }; using FieldTypes = testing::Types; -TYPED_TEST_SUITE(SumcheckRelation, FieldTypes); +TYPED_TEST_SUITE(RelationConsistency, FieldTypes); #define SUMCHECK_RELATION_TYPE_ALIASES using FF = TypeParam; -TYPED_TEST(SumcheckRelation, ArithmeticRelation) +TYPED_TEST(RelationConsistency, ArithmeticRelation) { SUMCHECK_RELATION_TYPE_ALIASES using MULTIVARIATE = honk::StandardArithmetization::POLYNOMIAL; + + static constexpr size_t FULL_RELATION_LENGTH = 5; + static const size_t NUM_POLYNOMIALS = proof_system::honk::StandardArithmetization::NUM_POLYNOMIALS; + const auto relation_parameters = TestFixture::compute_mock_relation_parameters(); auto run_test = [&relation_parameters](bool is_random_input) { std::array, NUM_POLYNOMIALS> extended_edges; - std::array, NUM_POLYNOMIALS> input_polynomials; + std::array, NUM_POLYNOMIALS> input_polynomials; if (!is_random_input) { // evaluation form, i.e. input_univariate(0) = 1, input_univariate(1) = 2,.. The polynomial is x+1. for (size_t i = 0; i < NUM_POLYNOMIALS; ++i) { - input_polynomials[i] = Univariate({ 1, 2 }); + input_polynomials[i] = Univariate({ 1, 2 }); } - extended_edges = TestFixture::compute_mock_extended_edges(input_polynomials); + extended_edges = TestFixture::template compute_mock_extended_edges(input_polynomials); } else { // input_univariates are random polynomials of degree one for (size_t i = 0; i < NUM_POLYNOMIALS; ++i) { input_polynomials[i] = - Univariate({ FF::random_element(), FF::random_element() }); + Univariate({ FF::random_element(), FF::random_element() }); } - extended_edges = TestFixture::compute_mock_extended_edges(input_polynomials); + extended_edges = TestFixture::template compute_mock_extended_edges(input_polynomials); }; auto relation = ArithmeticRelation(); // Manually compute the expected edge contribution @@ -207,33 +214,37 @@ TYPED_TEST(SumcheckRelation, ArithmeticRelation) // Ensure that expression changes are detected. // expected_evals, length 4, extends to { { 5, 22, 57, 116, 205} } for input polynomial {1, 2} auto expected_evals = (q_m * w_r * w_l) + (q_r * w_r) + (q_l * w_l) + (q_o * w_o) + (q_c); - TestFixture::validate_evaluations(expected_evals, relation, extended_edges, relation_parameters); + TestFixture::template validate_evaluations(expected_evals, relation, extended_edges, relation_parameters); }; run_test(/* is_random_input=*/true); run_test(/* is_random_input=*/false); }; -TYPED_TEST(SumcheckRelation, GrandProductComputationRelation) +TYPED_TEST(RelationConsistency, GrandProductComputationRelation) { SUMCHECK_RELATION_TYPE_ALIASES using MULTIVARIATE = honk::StandardArithmetization::POLYNOMIAL; + + static constexpr size_t FULL_RELATION_LENGTH = 5; + static const size_t NUM_POLYNOMIALS = proof_system::honk::StandardArithmetization::NUM_POLYNOMIALS; + const auto relation_parameters = TestFixture::compute_mock_relation_parameters(); auto run_test = [&relation_parameters](bool is_random_input) { std::array, NUM_POLYNOMIALS> extended_edges; - std::array, NUM_POLYNOMIALS> input_polynomials; + std::array, NUM_POLYNOMIALS> input_polynomials; if (!is_random_input) { // evaluation form, i.e. input_univariate(0) = 1, input_univariate(1) = 2,.. The polynomial is x+1. for (size_t i = 0; i < NUM_POLYNOMIALS; ++i) { - input_polynomials[i] = Univariate({ 1, 2 }); + input_polynomials[i] = Univariate({ 1, 2 }); } - extended_edges = TestFixture::compute_mock_extended_edges(input_polynomials); + extended_edges = TestFixture::template compute_mock_extended_edges(input_polynomials); } else { // input_univariates are random polynomials of degree one for (size_t i = 0; i < NUM_POLYNOMIALS; ++i) { input_polynomials[i] = - Univariate({ FF::random_element(), FF::random_element() }); + Univariate({ FF::random_element(), FF::random_element() }); } - extended_edges = TestFixture::compute_mock_extended_edges(input_polynomials); + extended_edges = TestFixture::template compute_mock_extended_edges(input_polynomials); }; auto relation = GrandProductComputationRelation(); @@ -269,33 +280,37 @@ TYPED_TEST(SumcheckRelation, GrandProductComputationRelation) (z_perm_shift + lagrange_last * public_input_delta) * (w_1 + sigma_1 * beta + gamma) * (w_2 + sigma_2 * beta + gamma) * (w_3 + sigma_3 * beta + gamma); - TestFixture::validate_evaluations(expected_evals, relation, extended_edges, relation_parameters); + TestFixture::template validate_evaluations(expected_evals, relation, extended_edges, relation_parameters); }; run_test(/* is_random_input=*/true); run_test(/* is_random_input=*/false); }; -TYPED_TEST(SumcheckRelation, GrandProductInitializationRelation) +TYPED_TEST(RelationConsistency, GrandProductInitializationRelation) { SUMCHECK_RELATION_TYPE_ALIASES using MULTIVARIATE = honk::StandardArithmetization::POLYNOMIAL; + + static constexpr size_t FULL_RELATION_LENGTH = 5; + static const size_t NUM_POLYNOMIALS = proof_system::honk::StandardArithmetization::NUM_POLYNOMIALS; + const auto relation_parameters = TestFixture::compute_mock_relation_parameters(); auto run_test = [&relation_parameters](bool is_random_input) { std::array, NUM_POLYNOMIALS> extended_edges; - std::array, NUM_POLYNOMIALS> input_polynomials; + std::array, NUM_POLYNOMIALS> input_polynomials; if (!is_random_input) { // evaluation form, i.e. input_univariate(0) = 1, input_univariate(1) = 2,.. The polynomial is x+1. for (size_t i = 0; i < NUM_POLYNOMIALS; ++i) { - input_polynomials[i] = Univariate({ 1, 2 }); + input_polynomials[i] = Univariate({ 1, 2 }); } - extended_edges = TestFixture::compute_mock_extended_edges(input_polynomials); + extended_edges = TestFixture::template compute_mock_extended_edges(input_polynomials); } else { // input_univariates are random polynomials of degree one for (size_t i = 0; i < NUM_POLYNOMIALS; ++i) { input_polynomials[i] = - Univariate({ FF::random_element(), FF::random_element() }); + Univariate({ FF::random_element(), FF::random_element() }); } - extended_edges = TestFixture::compute_mock_extended_edges(input_polynomials); + extended_edges = TestFixture::template compute_mock_extended_edges(input_polynomials); }; auto relation = GrandProductInitializationRelation(); const auto& z_perm_shift = extended_edges[MULTIVARIATE::Z_PERM_SHIFT]; @@ -305,10 +320,169 @@ TYPED_TEST(SumcheckRelation, GrandProductInitializationRelation) // expected_evals, lenght 3 (coeff form = x^2 + x), extends to { { 0, 2, 6, 12, 20 } } auto expected_evals = z_perm_shift * lagrange_last; - TestFixture::validate_evaluations(expected_evals, relation, extended_edges, relation_parameters); + TestFixture::template validate_evaluations(expected_evals, relation, extended_edges, relation_parameters); }; run_test(/* is_random_input=*/true); run_test(/* is_random_input=*/false); }; +TYPED_TEST(RelationConsistency, UltraArithmeticRelation) +{ + SUMCHECK_RELATION_TYPE_ALIASES + using MULTIVARIATE = honk::UltraArithmetization::POLYNOMIAL; + + static constexpr size_t FULL_RELATION_LENGTH = 6; + static const size_t NUM_POLYNOMIALS = proof_system::honk::UltraArithmetization::COUNT; + + const auto relation_parameters = TestFixture::compute_mock_relation_parameters(); + std::array, NUM_POLYNOMIALS> extended_edges; + std::array, NUM_POLYNOMIALS> input_polynomials; + + // input_univariates are random polynomials of degree one + for (size_t i = 0; i < NUM_POLYNOMIALS; ++i) { + input_polynomials[i] = Univariate({ FF::random_element(), FF::random_element() }); + } + extended_edges = TestFixture::template compute_mock_extended_edges(input_polynomials); + + auto relation = UltraArithmeticRelation(); + + // Extract the extended edges for manual computation of relation contribution + const auto& w_1 = extended_edges[MULTIVARIATE::W_L]; + const auto& w_2 = extended_edges[MULTIVARIATE::W_R]; + const auto& w_3 = extended_edges[MULTIVARIATE::W_O]; + const auto& w_4 = extended_edges[MULTIVARIATE::W_4]; + const auto& w_4_shift = extended_edges[MULTIVARIATE::W_4_SHIFT]; + const auto& q_m = extended_edges[MULTIVARIATE::Q_M]; + const auto& q_l = extended_edges[MULTIVARIATE::Q_L]; + const auto& q_r = extended_edges[MULTIVARIATE::Q_R]; + const auto& q_o = extended_edges[MULTIVARIATE::Q_O]; + const auto& q_4 = extended_edges[MULTIVARIATE::Q_4]; + const auto& q_c = extended_edges[MULTIVARIATE::Q_C]; + const auto& q_arith = extended_edges[MULTIVARIATE::QARITH]; + + static const FF neg_half = FF(-2).invert(); + + auto expected_evals = (q_arith - 3) * (q_m * w_2 * w_1) * neg_half; + expected_evals += (q_l * w_1) + (q_r * w_2) + (q_o * w_3) + (q_4 * w_4) + q_c; + expected_evals += (q_arith - 1) * w_4_shift; + expected_evals *= q_arith; + + TestFixture::template validate_evaluations(expected_evals, relation, extended_edges, relation_parameters); +}; + +TYPED_TEST(RelationConsistency, UltraArithmeticRelationSecondary) +{ + SUMCHECK_RELATION_TYPE_ALIASES + using MULTIVARIATE = honk::UltraArithmetization::POLYNOMIAL; + + static constexpr size_t FULL_RELATION_LENGTH = 6; + static const size_t NUM_POLYNOMIALS = proof_system::honk::UltraArithmetization::COUNT; + + const auto relation_parameters = TestFixture::compute_mock_relation_parameters(); + std::array, NUM_POLYNOMIALS> extended_edges; + std::array, NUM_POLYNOMIALS> input_polynomials; + + // input_univariates are random polynomials of degree one + for (size_t i = 0; i < NUM_POLYNOMIALS; ++i) { + input_polynomials[i] = Univariate({ FF::random_element(), FF::random_element() }); + } + extended_edges = TestFixture::template compute_mock_extended_edges(input_polynomials); + + auto relation = UltraArithmeticRelationSecondary(); + + // Extract the extended edges for manual computation of relation contribution + const auto& w_1 = extended_edges[MULTIVARIATE::W_L]; + const auto& w_4 = extended_edges[MULTIVARIATE::W_4]; + const auto& w_1_shift = extended_edges[MULTIVARIATE::W_1_SHIFT]; + const auto& q_m = extended_edges[MULTIVARIATE::Q_M]; + const auto& q_arith = extended_edges[MULTIVARIATE::QARITH]; + + auto expected_evals = (w_1 + w_4 - w_1_shift + q_m); + expected_evals *= (q_arith - 2) * (q_arith - 1) * q_arith; + + TestFixture::template validate_evaluations(expected_evals, relation, extended_edges, relation_parameters); +}; + +TYPED_TEST(RelationConsistency, UltraGrandProductInitializationRelation) +{ + SUMCHECK_RELATION_TYPE_ALIASES + using MULTIVARIATE = honk::UltraArithmetization::POLYNOMIAL; + + static constexpr size_t FULL_RELATION_LENGTH = 6; + static const size_t NUM_POLYNOMIALS = proof_system::honk::UltraArithmetization::COUNT; + + const auto relation_parameters = TestFixture::compute_mock_relation_parameters(); + std::array, NUM_POLYNOMIALS> extended_edges; + std::array, NUM_POLYNOMIALS> input_polynomials; + + // input_univariates are random polynomials of degree one + for (size_t i = 0; i < NUM_POLYNOMIALS; ++i) { + input_polynomials[i] = Univariate({ FF::random_element(), FF::random_element() }); + } + extended_edges = TestFixture::template compute_mock_extended_edges(input_polynomials); + + auto relation = UltraGrandProductInitializationRelation(); + + // Extract the extended edges for manual computation of relation contribution + const auto& z_perm_shift = extended_edges[MULTIVARIATE::Z_PERM_SHIFT]; + const auto& lagrange_last = extended_edges[MULTIVARIATE::LAGRANGE_LAST]; + + // Compute the expected result using a simple to read version of the relation expression + auto expected_evals = z_perm_shift * lagrange_last; + + TestFixture::template validate_evaluations(expected_evals, relation, extended_edges, relation_parameters); +}; + +TYPED_TEST(RelationConsistency, UltraGrandProductComputationRelation) +{ + SUMCHECK_RELATION_TYPE_ALIASES + using MULTIVARIATE = honk::UltraArithmetization::POLYNOMIAL; + + static constexpr size_t FULL_RELATION_LENGTH = 6; + static const size_t NUM_POLYNOMIALS = proof_system::honk::UltraArithmetization::COUNT; + + const auto relation_parameters = TestFixture::compute_mock_relation_parameters(); + std::array, NUM_POLYNOMIALS> extended_edges; + std::array, NUM_POLYNOMIALS> input_polynomials; + + // input_univariates are random polynomials of degree one + for (size_t i = 0; i < NUM_POLYNOMIALS; ++i) { + input_polynomials[i] = Univariate({ FF::random_element(), FF::random_element() }); + } + extended_edges = TestFixture::template compute_mock_extended_edges(input_polynomials); + + auto relation = UltraGrandProductComputationRelation(); + + const auto& beta = relation_parameters.beta; + const auto& gamma = relation_parameters.gamma; + const auto& public_input_delta = relation_parameters.public_input_delta; + + // Extract the extended edges for manual computation of relation contribution + const auto& w_1 = extended_edges[MULTIVARIATE::W_L]; + const auto& w_2 = extended_edges[MULTIVARIATE::W_R]; + const auto& w_3 = extended_edges[MULTIVARIATE::W_O]; + const auto& w_4 = extended_edges[MULTIVARIATE::W_4]; + const auto& sigma_1 = extended_edges[MULTIVARIATE::SIGMA_1]; + const auto& sigma_2 = extended_edges[MULTIVARIATE::SIGMA_2]; + const auto& sigma_3 = extended_edges[MULTIVARIATE::SIGMA_3]; + const auto& sigma_4 = extended_edges[MULTIVARIATE::SIGMA_4]; + const auto& id_1 = extended_edges[MULTIVARIATE::ID_1]; + const auto& id_2 = extended_edges[MULTIVARIATE::ID_2]; + const auto& id_3 = extended_edges[MULTIVARIATE::ID_3]; + const auto& id_4 = extended_edges[MULTIVARIATE::ID_4]; + const auto& z_perm = extended_edges[MULTIVARIATE::Z_PERM]; + const auto& z_perm_shift = extended_edges[MULTIVARIATE::Z_PERM_SHIFT]; + const auto& lagrange_first = extended_edges[MULTIVARIATE::LAGRANGE_FIRST]; + const auto& lagrange_last = extended_edges[MULTIVARIATE::LAGRANGE_LAST]; + + // Compute the expected result using a simple to read version of the relation expression + auto expected_evals = (z_perm + lagrange_first) * (w_1 + id_1 * beta + gamma) * (w_2 + id_2 * beta + gamma) * + (w_3 + id_3 * beta + gamma) * (w_4 + id_4 * beta + gamma) - + (z_perm_shift + lagrange_last * public_input_delta) * (w_1 + sigma_1 * beta + gamma) * + (w_2 + sigma_2 * beta + gamma) * (w_3 + sigma_3 * beta + gamma) * + (w_4 + sigma_4 * beta + gamma); + + TestFixture::template validate_evaluations(expected_evals, relation, extended_edges, relation_parameters); +}; + } // namespace proof_system::honk_relation_tests diff --git a/cpp/src/barretenberg/honk/sumcheck/relations/relation_correctness.test.cpp b/cpp/src/barretenberg/honk/sumcheck/relations/relation_correctness.test.cpp new file mode 100644 index 0000000000..f5556a31da --- /dev/null +++ b/cpp/src/barretenberg/honk/sumcheck/relations/relation_correctness.test.cpp @@ -0,0 +1,258 @@ +#include "barretenberg/honk/composer/ultra_honk_composer.hpp" +#include "barretenberg/honk/composer/standard_honk_composer.hpp" +#include "barretenberg/honk/sumcheck/relations/relation.hpp" +#include "barretenberg/honk/sumcheck/relations/ultra_arithmetic_relation.hpp" +#include "barretenberg/honk/sumcheck/relations/ultra_arithmetic_relation_secondary.hpp" +#include "barretenberg/numeric/uint256/uint256.hpp" +#include "barretenberg/honk/flavor/flavor.hpp" +#include +#include "barretenberg/honk/proof_system/prover.hpp" +#include "barretenberg/honk/sumcheck/sumcheck_round.hpp" +#include "barretenberg/honk/sumcheck/relations/grand_product_computation_relation.hpp" +#include "barretenberg/honk/sumcheck/relations/grand_product_initialization_relation.hpp" +#include "barretenberg/honk/utils/public_inputs.hpp" + +#include + +using namespace proof_system::honk; + +namespace test_honk_relations { + +/** + * @brief Test the correctness of the Standard Honk relations + * + * @details Check that the constraints encoded by the relations are satisfied by the polynomials produced by the + * Standard Honk Composer for a real circuit. + * + * TODO(Kesha): We'll have to update this function once we add zk, since the relation will be incorrect for he first few + * indices + * + */ +TEST(RelationCorrectness, StandardRelationCorrectness) +{ + // Create a composer and a dummy circuit with a few gates + auto composer = StandardHonkComposer(); + static const size_t num_wires = StandardHonkComposer::num_wires; + fr a = fr::one(); + // Using the public variable to check that public_input_delta is computed and added to the relation correctly + uint32_t a_idx = composer.add_public_variable(a); + fr b = fr::one(); + fr c = a + b; + fr d = a + c; + uint32_t b_idx = composer.add_variable(b); + uint32_t c_idx = composer.add_variable(c); + uint32_t d_idx = composer.add_variable(d); + for (size_t i = 0; i < 16; i++) { + composer.create_add_gate({ a_idx, b_idx, c_idx, fr::one(), fr::one(), fr::neg_one(), fr::zero() }); + composer.create_add_gate({ d_idx, c_idx, a_idx, fr::one(), fr::neg_one(), fr::neg_one(), fr::zero() }); + } + // Create a prover (it will compute proving key and witness) + auto prover = composer.create_prover(); + + // Generate beta and gamma + fr beta = fr::random_element(); + fr gamma = fr::random_element(); + + // Compute public input delta + const auto public_inputs = composer.circuit_constructor.get_public_inputs(); + auto public_input_delta = + honk::compute_public_input_delta(public_inputs, beta, gamma, prover.key->circuit_size); + + sumcheck::RelationParameters params{ + .beta = beta, + .gamma = gamma, + .public_input_delta = public_input_delta, + }; + + constexpr size_t num_polynomials = proof_system::honk::StandardArithmetization::NUM_POLYNOMIALS; + // Compute grand product polynomial + polynomial z_perm_poly = + prover_library::compute_permutation_grand_product(prover.key, prover.wire_polynomials, beta, gamma); + + // Create an array of spans to the underlying polynomials to more easily + // get the transposition. + // Ex: polynomial_spans[3][i] returns the i-th coefficient of the third polynomial + // in the list below + std::array, num_polynomials> evaluations_array; + + using POLYNOMIAL = proof_system::honk::StandardArithmetization::POLYNOMIAL; + evaluations_array[POLYNOMIAL::W_L] = prover.wire_polynomials[0]; + evaluations_array[POLYNOMIAL::W_R] = prover.wire_polynomials[1]; + evaluations_array[POLYNOMIAL::W_O] = prover.wire_polynomials[2]; + evaluations_array[POLYNOMIAL::Z_PERM] = z_perm_poly; + evaluations_array[POLYNOMIAL::Z_PERM_SHIFT] = z_perm_poly.shifted(); + evaluations_array[POLYNOMIAL::Q_M] = prover.key->polynomial_store.get("q_m_lagrange"); + evaluations_array[POLYNOMIAL::Q_L] = prover.key->polynomial_store.get("q_1_lagrange"); + evaluations_array[POLYNOMIAL::Q_R] = prover.key->polynomial_store.get("q_2_lagrange"); + evaluations_array[POLYNOMIAL::Q_O] = prover.key->polynomial_store.get("q_3_lagrange"); + evaluations_array[POLYNOMIAL::Q_C] = prover.key->polynomial_store.get("q_c_lagrange"); + evaluations_array[POLYNOMIAL::SIGMA_1] = prover.key->polynomial_store.get("sigma_1_lagrange"); + evaluations_array[POLYNOMIAL::SIGMA_2] = prover.key->polynomial_store.get("sigma_2_lagrange"); + evaluations_array[POLYNOMIAL::SIGMA_3] = prover.key->polynomial_store.get("sigma_3_lagrange"); + evaluations_array[POLYNOMIAL::ID_1] = prover.key->polynomial_store.get("id_1_lagrange"); + evaluations_array[POLYNOMIAL::ID_2] = prover.key->polynomial_store.get("id_2_lagrange"); + evaluations_array[POLYNOMIAL::ID_3] = prover.key->polynomial_store.get("id_3_lagrange"); + evaluations_array[POLYNOMIAL::LAGRANGE_FIRST] = prover.key->polynomial_store.get("L_first_lagrange"); + evaluations_array[POLYNOMIAL::LAGRANGE_LAST] = prover.key->polynomial_store.get("L_last_lagrange"); + + // Construct the round for applying sumcheck relations and results for storing computed results + auto relations = std::tuple(honk::sumcheck::ArithmeticRelation(), + honk::sumcheck::GrandProductComputationRelation(), + honk::sumcheck::GrandProductInitializationRelation()); + + fr result = 0; + for (size_t i = 0; i < prover.key->circuit_size; i++) { + // Compute an array containing all the evaluations at a given row i + std::array evaluations_at_index_i; + for (size_t j = 0; j < num_polynomials; ++j) { + evaluations_at_index_i[j] = evaluations_array[j][i]; + } + + // For each relation, call the `accumulate_relation_evaluation` over all witness/selector values at the + // i-th row/vertex of the hypercube. + // We use ASSERT_EQ instead of EXPECT_EQ so that the tests stops at the first index at which the result is not + // 0, since result = 0 + C(transposed), which we expect will equal 0. + std::get<0>(relations).add_full_relation_value_contribution(result, evaluations_at_index_i, params); + ASSERT_EQ(result, 0); + + std::get<1>(relations).add_full_relation_value_contribution(result, evaluations_at_index_i, params); + ASSERT_EQ(result, 0); + + std::get<2>(relations).add_full_relation_value_contribution(result, evaluations_at_index_i, params); + ASSERT_EQ(result, 0); + } +} + +/** + * @brief Test the correctness of the Ultra Honk relations + * + * @details Check that the constraints encoded by the relations are satisfied by the polynomials produced by the + * Ultra Honk Composer for a real circuit. + * + * TODO(Kesha): We'll have to update this function once we add zk, since the relation will be incorrect for he first few + * indices + * + */ +// TODO(luke): Increase variety of gates in the test circuit to fully stress the relations, e.g. create_big_add_gate. +// NOTE(luke): More relations will be added as they are implemented for Ultra Honk +TEST(RelationCorrectness, UltraRelationCorrectness) +{ + // Create a composer and a dummy circuit with a few gates + auto composer = UltraHonkComposer(); + static const size_t num_wires = 4; + fr a = fr::one(); + // Using the public variable to check that public_input_delta is computed and added to the relation correctly + // TODO(luke): add method "add_public_variable" to UH composer + // uint32_t a_idx = composer.add_public_variable(a); + uint32_t a_idx = composer.add_variable(a); + fr b = fr::one(); + fr c = a + b; + fr d = a + c; + uint32_t b_idx = composer.add_variable(b); + uint32_t c_idx = composer.add_variable(c); + uint32_t d_idx = composer.add_variable(d); + for (size_t i = 0; i < 1; i++) { + composer.create_add_gate({ a_idx, b_idx, c_idx, fr::one(), fr::one(), fr::neg_one(), fr::zero() }); + composer.create_add_gate({ d_idx, c_idx, a_idx, fr::one(), fr::neg_one(), fr::neg_one(), fr::zero() }); + } + // Create a prover (it will compute proving key and witness) + auto prover = composer.create_prover(); + + // Generate beta and gamma + fr beta = fr::random_element(); + fr gamma = fr::random_element(); + + // Compute public input delta + const auto public_inputs = composer.circuit_constructor.get_public_inputs(); + auto public_input_delta = + honk::compute_public_input_delta(public_inputs, beta, gamma, prover.key->circuit_size); + + info("public_input_delta = ", public_input_delta); + + sumcheck::RelationParameters params{ + .beta = beta, + .gamma = gamma, + .public_input_delta = public_input_delta, + }; + + constexpr size_t num_polynomials = proof_system::honk::UltraArithmetization::COUNT; + // Compute grand product polynomial + auto z_perm_poly = + prover_library::compute_permutation_grand_product(prover.key, prover.wire_polynomials, beta, gamma); + + // Create an array of spans to the underlying polynomials to more easily + // get the transposition. + // Ex: polynomial_spans[3][i] returns the i-th coefficient of the third polynomial + // in the list below + std::array, num_polynomials> evaluations_array; + + using POLYNOMIAL = proof_system::honk::UltraArithmetization::POLYNOMIAL; + evaluations_array[POLYNOMIAL::W_L] = prover.wire_polynomials[0]; + evaluations_array[POLYNOMIAL::W_R] = prover.wire_polynomials[1]; + evaluations_array[POLYNOMIAL::W_O] = prover.wire_polynomials[2]; + evaluations_array[POLYNOMIAL::W_4] = prover.wire_polynomials[3]; + evaluations_array[POLYNOMIAL::W_1_SHIFT] = prover.wire_polynomials[0].shifted(); + evaluations_array[POLYNOMIAL::W_4_SHIFT] = prover.wire_polynomials[3].shifted(); + evaluations_array[POLYNOMIAL::S_1] = prover.key->polynomial_store.get("s_1_lagrange"); + evaluations_array[POLYNOMIAL::S_2] = prover.key->polynomial_store.get("s_2_lagrange"); + evaluations_array[POLYNOMIAL::S_3] = prover.key->polynomial_store.get("s_3_lagrange"); + evaluations_array[POLYNOMIAL::S_4] = prover.key->polynomial_store.get("s_4_lagrange"); + evaluations_array[POLYNOMIAL::Z_PERM] = z_perm_poly; + evaluations_array[POLYNOMIAL::Z_PERM_SHIFT] = z_perm_poly.shifted(); + evaluations_array[POLYNOMIAL::Z_LOOKUP] = z_perm_poly; + evaluations_array[POLYNOMIAL::Z_LOOKUP_SHIFT] = z_perm_poly.shifted(); + evaluations_array[POLYNOMIAL::Q_M] = prover.key->polynomial_store.get("q_m_lagrange"); + evaluations_array[POLYNOMIAL::Q_L] = prover.key->polynomial_store.get("q_1_lagrange"); + evaluations_array[POLYNOMIAL::Q_R] = prover.key->polynomial_store.get("q_2_lagrange"); + evaluations_array[POLYNOMIAL::Q_O] = prover.key->polynomial_store.get("q_3_lagrange"); + evaluations_array[POLYNOMIAL::Q_C] = prover.key->polynomial_store.get("q_c_lagrange"); + evaluations_array[POLYNOMIAL::Q_4] = prover.key->polynomial_store.get("q_4_lagrange"); + evaluations_array[POLYNOMIAL::QARITH] = prover.key->polynomial_store.get("q_arith_lagrange"); + evaluations_array[POLYNOMIAL::QSORT] = prover.key->polynomial_store.get("q_sort_lagrange"); + evaluations_array[POLYNOMIAL::QELLIPTIC] = prover.key->polynomial_store.get("q_elliptic_lagrange"); + evaluations_array[POLYNOMIAL::QAUX] = prover.key->polynomial_store.get("q_aux_lagrange"); + evaluations_array[POLYNOMIAL::QLOOKUPTYPE] = prover.key->polynomial_store.get("table_type_lagrange"); + evaluations_array[POLYNOMIAL::SIGMA_1] = prover.key->polynomial_store.get("sigma_1_lagrange"); + evaluations_array[POLYNOMIAL::SIGMA_2] = prover.key->polynomial_store.get("sigma_2_lagrange"); + evaluations_array[POLYNOMIAL::SIGMA_3] = prover.key->polynomial_store.get("sigma_3_lagrange"); + evaluations_array[POLYNOMIAL::SIGMA_4] = prover.key->polynomial_store.get("sigma_4_lagrange"); + evaluations_array[POLYNOMIAL::ID_1] = prover.key->polynomial_store.get("id_1_lagrange"); + evaluations_array[POLYNOMIAL::ID_2] = prover.key->polynomial_store.get("id_2_lagrange"); + evaluations_array[POLYNOMIAL::ID_3] = prover.key->polynomial_store.get("id_3_lagrange"); + evaluations_array[POLYNOMIAL::ID_4] = prover.key->polynomial_store.get("id_4_lagrange"); + evaluations_array[POLYNOMIAL::LAGRANGE_FIRST] = prover.key->polynomial_store.get("L_first_lagrange"); + evaluations_array[POLYNOMIAL::LAGRANGE_LAST] = prover.key->polynomial_store.get("L_last_lagrange"); + + // Construct the round for applying sumcheck relations and results for storing computed results + auto relations = std::tuple(honk::sumcheck::UltraArithmeticRelation(), + honk::sumcheck::UltraArithmeticRelationSecondary(), + honk::sumcheck::UltraGrandProductInitializationRelation(), + honk::sumcheck::UltraGrandProductComputationRelation()); + + fr result = 0; + for (size_t i = 0; i < prover.key->circuit_size; i++) { + // Compute an array containing all the evaluations at a given row i + std::array evaluations_at_index_i; + for (size_t j = 0; j < num_polynomials; ++j) { + evaluations_at_index_i[j] = evaluations_array[j][i]; + } + + // For each relation, call the `accumulate_relation_evaluation` over all witness/selector values at the + // i-th row/vertex of the hypercube. We use ASSERT_EQ instead of EXPECT_EQ so that the tests stops at + // the first index at which the result is not 0, since result = 0 + C(transposed), which we expect will + // equal 0. + std::get<0>(relations).add_full_relation_value_contribution(result, evaluations_at_index_i, params); + ASSERT_EQ(result, 0); + + std::get<1>(relations).add_full_relation_value_contribution(result, evaluations_at_index_i, params); + ASSERT_EQ(result, 0); + + std::get<2>(relations).add_full_relation_value_contribution(result, evaluations_at_index_i, params); + ASSERT_EQ(result, 0); + + std::get<3>(relations).add_full_relation_value_contribution(result, evaluations_at_index_i, params); + ASSERT_EQ(result, 0); + } +} + +} // namespace test_honk_relations diff --git a/cpp/src/barretenberg/honk/sumcheck/relations/ultra_arithmetic_relation.hpp b/cpp/src/barretenberg/honk/sumcheck/relations/ultra_arithmetic_relation.hpp new file mode 100644 index 0000000000..2df6efc2c7 --- /dev/null +++ b/cpp/src/barretenberg/honk/sumcheck/relations/ultra_arithmetic_relation.hpp @@ -0,0 +1,87 @@ +#pragma once +#include +#include + +#include "barretenberg/honk/flavor/flavor.hpp" +#include "../polynomials/univariate.hpp" +#include "relation.hpp" + +namespace proof_system::honk::sumcheck { + +template class UltraArithmeticRelation { + public: + // 1 + polynomial degree of this relation + static constexpr size_t RELATION_LENGTH = 6; // degree(q_arith^2 * q_m * w_r * w_l) = 5 + using MULTIVARIATE = UltraArithmetization::POLYNOMIAL; + + /** + * @brief Expression for the Ultra Arithmetic gate. + * @details The relation is defined as C(extended_edges(X)...) = + * q_arith * + * [ -1/2(q_arith - 3)(q_m * w_r * w_l) + + * (q_l * w_l) + (q_r * w_r) + (q_o * w_o) + (q_4 * w_4) + q_c + + * (q_arith - 1)w_4_shift ] + * + * @param evals transformed to `evals + C(extended_edges(X)...)*scaling_factor` + * @param extended_edges an std::array containing the fully extended Univariate edges. + * @param parameters contains beta, gamma, and public_input_delta, .... + * @param scaling_factor optional term to scale the evaluation before adding to evals. + */ + void add_edge_contribution(Univariate& evals, + const auto& extended_edges, + const RelationParameters&, + const FF& scaling_factor) const + { + // OPTIMIZATION?: Karatsuba in general, at least for some degrees? + // See https://hackmd.io/xGLuj6biSsCjzQnYN-pEiA?both + + auto w_l = UnivariateView(extended_edges[MULTIVARIATE::W_L]); + auto w_r = UnivariateView(extended_edges[MULTIVARIATE::W_R]); + auto w_o = UnivariateView(extended_edges[MULTIVARIATE::W_O]); + auto w_4 = UnivariateView(extended_edges[MULTIVARIATE::W_4]); + auto w_4_shift = UnivariateView(extended_edges[MULTIVARIATE::W_4_SHIFT]); + auto q_m = UnivariateView(extended_edges[MULTIVARIATE::Q_M]); + auto q_l = UnivariateView(extended_edges[MULTIVARIATE::Q_L]); + auto q_r = UnivariateView(extended_edges[MULTIVARIATE::Q_R]); + auto q_o = UnivariateView(extended_edges[MULTIVARIATE::Q_O]); + auto q_4 = UnivariateView(extended_edges[MULTIVARIATE::Q_4]); + auto q_c = UnivariateView(extended_edges[MULTIVARIATE::Q_C]); + auto q_arith = UnivariateView(extended_edges[MULTIVARIATE::QARITH]); + + static const FF neg_half = FF(-2).invert(); + + auto tmp = (q_arith - 3) * (q_m * w_r * w_l) * neg_half; + tmp += (q_l * w_l) + (q_r * w_r) + (q_o * w_o) + (q_4 * w_4) + q_c; + tmp += (q_arith - 1) * w_4_shift; + tmp *= q_arith; + tmp *= scaling_factor; + evals += tmp; + }; + + void add_full_relation_value_contribution(FF& full_honk_relation_value, + const auto& purported_evaluations, + const RelationParameters&) const + { + auto w_l = purported_evaluations[MULTIVARIATE::W_L]; + auto w_r = purported_evaluations[MULTIVARIATE::W_R]; + auto w_o = purported_evaluations[MULTIVARIATE::W_O]; + auto w_4 = purported_evaluations[MULTIVARIATE::W_4]; + auto w_4_shift = purported_evaluations[MULTIVARIATE::W_4_SHIFT]; + auto q_m = purported_evaluations[MULTIVARIATE::Q_M]; + auto q_l = purported_evaluations[MULTIVARIATE::Q_L]; + auto q_r = purported_evaluations[MULTIVARIATE::Q_R]; + auto q_o = purported_evaluations[MULTIVARIATE::Q_O]; + auto q_4 = purported_evaluations[MULTIVARIATE::Q_4]; + auto q_c = purported_evaluations[MULTIVARIATE::Q_C]; + auto q_arith = purported_evaluations[MULTIVARIATE::QARITH]; + + static const FF neg_half = FF(-2).invert(); + + auto tmp = (q_arith - 3) * (q_m * w_r * w_l) * neg_half; + tmp += (q_l * w_l) + (q_r * w_r) + (q_o * w_o) + (q_4 * w_4) + q_c; + tmp += (q_arith - 1) * w_4_shift; + tmp *= q_arith; + full_honk_relation_value += tmp; + }; +}; +} // namespace proof_system::honk::sumcheck diff --git a/cpp/src/barretenberg/honk/sumcheck/relations/ultra_arithmetic_relation_secondary.hpp b/cpp/src/barretenberg/honk/sumcheck/relations/ultra_arithmetic_relation_secondary.hpp new file mode 100644 index 0000000000..78c01db356 --- /dev/null +++ b/cpp/src/barretenberg/honk/sumcheck/relations/ultra_arithmetic_relation_secondary.hpp @@ -0,0 +1,67 @@ +#pragma once +#include +#include + +#include "barretenberg/honk/flavor/flavor.hpp" +#include "../polynomials/univariate.hpp" +#include "relation.hpp" + +namespace proof_system::honk::sumcheck { + +template class UltraArithmeticRelationSecondary { + public: + // 1 + polynomial degree of this relation + static constexpr size_t RELATION_LENGTH = 5; // degree(q_arith^3 * w_l) = 4 + using MULTIVARIATE = UltraArithmetization::POLYNOMIAL; + + /** + * @brief Expression for the Ultra Arithmetic gate. + * @details The relation is defined as C(extended_edges(X)...) = + * q_arith * + * (q_arith - 2) * (q_arith - 1) * (w_l + w_4 - w_l_shift + q_m) + * + * @param evals transformed to `evals + C(extended_edges(X)...)*scaling_factor` + * @param extended_edges an std::array containing the fully extended Univariate edges. + * @param parameters contains beta, gamma, and public_input_delta, .... + * @param scaling_factor optional term to scale the evaluation before adding to evals. + */ + void add_edge_contribution(Univariate& evals, + const auto& extended_edges, + const RelationParameters&, + const FF& scaling_factor) const + { + // OPTIMIZATION?: Karatsuba in general, at least for some degrees? + // See https://hackmd.io/xGLuj6biSsCjzQnYN-pEiA?both + + auto w_l = UnivariateView(extended_edges[MULTIVARIATE::W_L]); + auto w_4 = UnivariateView(extended_edges[MULTIVARIATE::W_4]); + auto w_l_shift = UnivariateView(extended_edges[MULTIVARIATE::W_1_SHIFT]); + auto q_m = UnivariateView(extended_edges[MULTIVARIATE::Q_M]); + auto q_arith = UnivariateView(extended_edges[MULTIVARIATE::QARITH]); + + auto tmp = w_l + w_4 - w_l_shift + q_m; + tmp *= (q_arith - 2); + tmp *= (q_arith - 1); + tmp *= q_arith; + tmp *= scaling_factor; + evals += tmp; + }; + + void add_full_relation_value_contribution(FF& full_honk_relation_value, + const auto& purported_evaluations, + const RelationParameters&) const + { + auto w_l = purported_evaluations[MULTIVARIATE::W_L]; + auto w_4 = purported_evaluations[MULTIVARIATE::W_4]; + auto w_l_shift = purported_evaluations[MULTIVARIATE::W_1_SHIFT]; + auto q_m = purported_evaluations[MULTIVARIATE::Q_M]; + auto q_arith = purported_evaluations[MULTIVARIATE::QARITH]; + + auto tmp = w_l + w_4 - w_l_shift + q_m; + tmp *= (q_arith - 2); + tmp *= (q_arith - 1); + tmp *= q_arith; + full_honk_relation_value += tmp; + }; +}; +} // namespace proof_system::honk::sumcheck 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 cb35a19d27..5ee4b90fad 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 @@ -1,3 +1,6 @@ +#include +#include + #include "c_bind.h" #include "join_split.hpp" #include "compute_signing_data.hpp" @@ -5,14 +8,12 @@ #include "barretenberg/common/streams.hpp" #include "barretenberg/common/mem.hpp" #include "barretenberg/common/container.hpp" -#include #include "barretenberg/ecc/curves/grumpkin/grumpkin.hpp" #include "barretenberg/srs/reference_string/pippenger_reference_string.hpp" #include "barretenberg/plonk/proof_system/proving_key/serialize.hpp" -#include +#include "barretenberg/join_split_example/types.hpp" using namespace barretenberg; -using namespace proof_system::plonk::stdlib::types; using namespace join_split_example::proofs::join_split; #define WASM_EXPORT __attribute__((visibility("default"))) @@ -42,22 +43,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. -#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; - write(raw_buf_end, *get_proving_key()); - *output = raw_buf; - auto len = static_cast(raw_buf_end - raw_buf); - if (len > total_buf_len) { - info("Buffer overflow serializing proving key."); - std::abort(); - } - return len; -#else + // 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. + auto proving_key = get_proving_key(); auto buffer = to_buffer(*proving_key); auto raw_buf = (uint8_t*)malloc(buffer.size()); @@ -65,7 +54,6 @@ WASM_EXPORT uint32_t join_split__get_new_proving_key_data(uint8_t** output) *output = raw_buf; return static_cast(buffer.size()); -#endif } WASM_EXPORT void join_split__init_verification_key(void* pippenger, uint8_t const* g2x) @@ -103,13 +91,13 @@ 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 stdlib::types::Prover(std::move(prover)); + auto heapProver = new join_split_example::Prover(std::move(prover)); return heapProver; } WASM_EXPORT void join_split__delete_prover(void* prover) { - delete reinterpret_cast(prover); + delete reinterpret_cast(prover); } WASM_EXPORT bool join_split__verify_proof(uint8_t* proof, uint32_t length) diff --git a/cpp/src/barretenberg/join_split_example/proofs/join_split/compute_circuit_data.cpp b/cpp/src/barretenberg/join_split_example/proofs/join_split/compute_circuit_data.cpp index 47fc4deec2..037799660b 100644 --- a/cpp/src/barretenberg/join_split_example/proofs/join_split/compute_circuit_data.cpp +++ b/cpp/src/barretenberg/join_split_example/proofs/join_split/compute_circuit_data.cpp @@ -3,13 +3,14 @@ #include "sign_join_split_tx.hpp" #include "../notes/native/index.hpp" #include "barretenberg/stdlib/merkle_tree/hash_path.hpp" +#include "barretenberg/join_split_example/types.hpp" namespace join_split_example { namespace proofs { namespace join_split { using namespace join_split_example::proofs::join_split; -using namespace proof_system::plonk::stdlib::types; +using namespace proof_system::plonk::stdlib; using namespace join_split_example::proofs::notes::native; using namespace proof_system::plonk::stdlib::merkle_tree; 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 44567b5b26..95aee064e2 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 @@ -2,6 +2,7 @@ #include "join_split_circuit.hpp" #include "compute_circuit_data.hpp" #include "barretenberg/plonk/proof_system/commitment_scheme/kate_commitment_scheme.hpp" +#include "barretenberg/join_split_example/types.hpp" namespace join_split_example { namespace proofs { @@ -23,7 +24,7 @@ void init_proving_key(std::shared_ptr cons join_split_tx tx = noop_tx(); if (!mock) { - stdlib::types::Composer composer(crs_factory); + Composer composer(crs_factory); join_split_circuit(composer, tx); proving_key = composer.compute_proving_key(); } else { @@ -55,8 +56,7 @@ void init_verification_key(std::unique_ptr // Patch the 'nothing' reference string fed to init_proving_key. proving_key->reference_string = crs_factory->get_prover_crs(proving_key->circuit_size + 1); - verification_key = - plonk::stdlib::types::Composer::compute_verification_key_base(proving_key, crs_factory->get_verifier_crs()); + verification_key = Composer::compute_verification_key_base(proving_key, crs_factory->get_verifier_crs()); } void init_verification_key(std::shared_ptr const& crs, @@ -65,7 +65,7 @@ void init_verification_key(std::shared_ptr(std::move(vk_data), crs); } -stdlib::types::Prover new_join_split_prover(join_split_tx const& tx, bool mock) +Prover new_join_split_prover(join_split_tx const& tx, bool mock) { Composer composer(proving_key, nullptr); join_split_circuit(composer, tx); @@ -90,16 +90,10 @@ stdlib::types::Prover new_join_split_prover(join_split_tx const& tx, bool mock) bool verify_proof(plonk::proof const& proof) { - plonk::stdlib::types::Verifier verifier(verification_key, - Composer::create_manifest(verification_key->num_public_inputs)); + 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 6c9b4ac5ab..a6c103a4a0 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 @@ -1,14 +1,13 @@ #pragma once #include "join_split_tx.hpp" #include "barretenberg/srs/reference_string/mem_reference_string.hpp" -#include "barretenberg/stdlib/types/types.hpp" +#include "barretenberg/join_split_example/types.hpp" namespace join_split_example { namespace proofs { namespace join_split { using namespace proof_system::plonk::stdlib::merkle_tree; -using namespace proof_system::plonk::stdlib::types; void init_proving_key(std::shared_ptr const& crs_factory, bool mock); @@ -22,7 +21,7 @@ void init_verification_key(std::unique_ptr void init_verification_key(std::shared_ptr const& crs, plonk::verification_key_data&& vk_data); -stdlib::types::Prover new_join_split_prover(join_split_tx const& tx, bool mock); +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 c729f91434..25b802cd62 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 @@ -1,3 +1,5 @@ +#include + #include "../../constants.hpp" #include "../inner_proof_data/inner_proof_data.hpp" #include "index.hpp" @@ -5,9 +7,9 @@ #include "join_split_circuit.hpp" #include "barretenberg/common/streams.hpp" #include "barretenberg/common/test.hpp" -#include #include "barretenberg/plonk/proof_system/proving_key/serialize.hpp" #include "barretenberg/stdlib/merkle_tree/index.hpp" +#include "barretenberg/join_split_example/types.hpp" namespace join_split_example::proofs::join_split { @@ -122,7 +124,7 @@ constexpr bool CIRCUIT_CHANGE_EXPECTED = false; #endif using namespace barretenberg; -using namespace proof_system::plonk::stdlib::types; +using namespace proof_system::plonk::stdlib; using namespace proof_system::plonk::stdlib::merkle_tree; using namespace join_split_example::proofs::notes::native; using key_pair = join_split_example::fixtures::grumpkin_key_pair; @@ -800,17 +802,12 @@ 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 -#ifdef USE_TURBO - constexpr uint32_t CIRCUIT_GATE_COUNT = 59175; - constexpr uint32_t GATES_NEXT_POWER_OF_TWO = 65536; - const uint256_t VK_HASH("095cbe8f1b09690713d5161708b5ea77119575884e3cfab14f7364b9f1ba7faa"); -#else + // The below part detects any changes in the join-split circuit + constexpr uint32_t CIRCUIT_GATE_COUNT = 185573; constexpr uint32_t GATES_NEXT_POWER_OF_TWO = 524288; - const uint256_t VK_HASH("21389d5392ee23ffc96984689150b63d62113678b1ba127346a0ec72df842354"); + const uint256_t VK_HASH("13eb88883e80efb9bf306af2962cd1a49e9fa1b0bfb2d4b563b95217a17bcc74"); -#endif auto number_of_gates_js = result.number_of_gates; auto vk_hash_js = get_verification_key()->sha256_hash(); @@ -2623,11 +2620,8 @@ 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/join_split_example/proofs/join_split/join_split_circuit.cpp b/cpp/src/barretenberg/join_split_example/proofs/join_split/join_split_circuit.cpp index a0061cde88..c1ea2af1da 100644 --- a/cpp/src/barretenberg/join_split_example/proofs/join_split/join_split_circuit.cpp +++ b/cpp/src/barretenberg/join_split_example/proofs/join_split/join_split_circuit.cpp @@ -6,6 +6,7 @@ #include "../notes/circuit/claim/claim_note.hpp" #include "verify_signature.hpp" #include "barretenberg/stdlib/merkle_tree/membership.hpp" +#include "barretenberg/join_split_example/types.hpp" namespace join_split_example { namespace proofs { @@ -22,7 +23,7 @@ using namespace proof_system::plonk::stdlib::merkle_tree; */ field_ct process_input_note(field_ct const& account_private_key, field_ct const& merkle_root, - merkle_tree::hash_path const& hash_path, + hash_path_ct const& hash_path, suint_ct const& index, value::value_note const& note, bool_ct is_propagated, @@ -31,7 +32,7 @@ field_ct process_input_note(field_ct const& account_private_key, const bool_ct valid_value = note.value == 0 || is_note_in_use; valid_value.assert_equal(true, "padding note non zero"); - const bool_ct exists = merkle_tree::check_membership( + const bool_ct exists = proof_system::plonk::stdlib::merkle_tree::check_membership( merkle_root, hash_path, note.commitment, index.value.decompose_into_bits(DATA_TREE_DEPTH)); const bool_ct valid = exists || is_propagated || !is_note_in_use; valid.assert_equal(true, "input note not a member"); @@ -216,10 +217,10 @@ join_split_outputs join_split_circuit_component(join_split_inputs const& inputs) const auto account_alias_hash = inputs.alias_hash; const auto account_note_data = account::account_note(account_alias_hash.value, account_public_key, signer); const bool_ct signing_key_exists = - merkle_tree::check_membership(inputs.merkle_root, - inputs.account_note_path, - account_note_data.commitment, - inputs.account_note_index.value.decompose_into_bits(DATA_TREE_DEPTH)); + stdlib::merkle_tree::check_membership(inputs.merkle_root, + inputs.account_note_path, + account_note_data.commitment, + inputs.account_note_index.value.decompose_into_bits(DATA_TREE_DEPTH)); (signing_key_exists || !inputs.account_required).assert_equal(true, "account check_membership failed"); } @@ -287,8 +288,8 @@ void join_split_circuit(Composer& composer, join_split_tx const& tx) .signing_pub_key = stdlib::create_point_witness(composer, tx.signing_pub_key), .signature = stdlib::schnorr::convert_signature(&composer, tx.signature), .merkle_root = witness_ct(&composer, tx.old_data_root), - .input_path1 = merkle_tree::create_witness_hash_path(composer, tx.input_path[0]), - .input_path2 = merkle_tree::create_witness_hash_path(composer, tx.input_path[1]), + .input_path1 = stdlib::merkle_tree::create_witness_hash_path(composer, tx.input_path[0]), + .input_path2 = stdlib::merkle_tree::create_witness_hash_path(composer, tx.input_path[1]), .account_note_index = suint_ct(witness_ct(&composer, tx.account_note_index), DATA_TREE_DEPTH, "account_note_index"), .account_note_path = merkle_tree::create_witness_hash_path(composer, tx.account_note_path), diff --git a/cpp/src/barretenberg/join_split_example/proofs/join_split/join_split_circuit.hpp b/cpp/src/barretenberg/join_split_example/proofs/join_split/join_split_circuit.hpp index b8821989b4..bde45a710c 100644 --- a/cpp/src/barretenberg/join_split_example/proofs/join_split/join_split_circuit.hpp +++ b/cpp/src/barretenberg/join_split_example/proofs/join_split/join_split_circuit.hpp @@ -3,15 +3,14 @@ #include "../notes/circuit/value/witness_data.hpp" #include "../notes/circuit/claim/witness_data.hpp" #include "barretenberg/crypto/schnorr/schnorr.hpp" -#include "barretenberg/stdlib/types/types.hpp" +#include "barretenberg/join_split_example/types.hpp" namespace join_split_example { namespace proofs { namespace join_split { -using namespace proof_system::plonk::stdlib::types; - struct join_split_inputs { + field_ct proof_id; suint_ct public_value; field_ct public_owner; @@ -25,12 +24,12 @@ struct join_split_inputs { notes::circuit::value::witness_data output_note2; notes::circuit::claim::partial_claim_note_witness_data partial_claim_note; point_ct signing_pub_key; - stdlib::schnorr::signature_bits signature; + schnorr::signature_bits signature; field_ct merkle_root; - merkle_tree::hash_path input_path1; - merkle_tree::hash_path input_path2; + hash_path_ct input_path1; + hash_path_ct input_path2; suint_ct account_note_index; - merkle_tree::hash_path account_note_path; + hash_path_ct account_note_path; field_ct account_private_key; suint_ct alias_hash; bool_ct account_required; diff --git a/cpp/src/barretenberg/join_split_example/proofs/join_split/join_split_tx.hpp b/cpp/src/barretenberg/join_split_example/proofs/join_split/join_split_tx.hpp index 4dae8f30e3..fe309b8dac 100644 --- a/cpp/src/barretenberg/join_split_example/proofs/join_split/join_split_tx.hpp +++ b/cpp/src/barretenberg/join_split_example/proofs/join_split/join_split_tx.hpp @@ -3,14 +3,12 @@ #include "../notes/native/value/value_note.hpp" #include "barretenberg/crypto/schnorr/schnorr.hpp" #include "barretenberg/stdlib/merkle_tree/hash_path.hpp" -#include "barretenberg/stdlib/types/types.hpp" +#include "barretenberg/join_split_example/types.hpp" namespace join_split_example { namespace proofs { namespace join_split { -using namespace proof_system::plonk::stdlib::types; - struct join_split_tx { uint32_t proof_id; uint256_t public_value; @@ -19,7 +17,7 @@ struct join_split_tx { uint32_t num_input_notes; std::array input_index; barretenberg::fr old_data_root; - std::array input_path; + std::array input_path; std::array input_note; std::array output_note; @@ -29,7 +27,7 @@ struct join_split_tx { barretenberg::fr alias_hash; bool account_required; uint32_t account_note_index; - merkle_tree::fr_hash_path account_note_path; + proof_system::plonk::stdlib::merkle_tree::fr_hash_path account_note_path; grumpkin::g1::affine_element signing_pub_key; barretenberg::fr backward_link; // 0: no link, otherwise: any commitment. diff --git a/cpp/src/barretenberg/join_split_example/proofs/mock/mock_circuit.test.cpp b/cpp/src/barretenberg/join_split_example/proofs/mock/mock_circuit.test.cpp index 16004e9787..6960962095 100644 --- a/cpp/src/barretenberg/join_split_example/proofs/mock/mock_circuit.test.cpp +++ b/cpp/src/barretenberg/join_split_example/proofs/mock/mock_circuit.test.cpp @@ -1,9 +1,9 @@ #include "mock_circuit.hpp" #include "../join_split/join_split_tx.hpp" #include "barretenberg/common/test.hpp" -#include "barretenberg/stdlib/types/types.hpp" +#include "barretenberg/join_split_example/types.hpp" -using namespace proof_system::plonk::stdlib::types; +using namespace proof_system::plonk::stdlib; namespace rollup { namespace proofs { diff --git a/cpp/src/barretenberg/join_split_example/proofs/notes/circuit/account/account_note.hpp b/cpp/src/barretenberg/join_split_example/proofs/notes/circuit/account/account_note.hpp index 334b2edfc3..30390eb103 100644 --- a/cpp/src/barretenberg/join_split_example/proofs/notes/circuit/account/account_note.hpp +++ b/cpp/src/barretenberg/join_split_example/proofs/notes/circuit/account/account_note.hpp @@ -1,6 +1,7 @@ #pragma once -#include "barretenberg/stdlib/types/types.hpp" +#include "barretenberg/join_split_example/types.hpp" #include "commit.hpp" +#include "barretenberg/join_split_example/types.hpp" namespace join_split_example { namespace proofs { @@ -8,8 +9,6 @@ namespace notes { namespace circuit { namespace account { -using namespace proof_system::plonk::stdlib::types; - struct account_note { field_ct account_alias_hash; point_ct account_public_key; diff --git a/cpp/src/barretenberg/join_split_example/proofs/notes/circuit/account/commit.hpp b/cpp/src/barretenberg/join_split_example/proofs/notes/circuit/account/commit.hpp index 497644a951..dbe568197a 100644 --- a/cpp/src/barretenberg/join_split_example/proofs/notes/circuit/account/commit.hpp +++ b/cpp/src/barretenberg/join_split_example/proofs/notes/circuit/account/commit.hpp @@ -1,6 +1,8 @@ #pragma once -#include "barretenberg/stdlib/types/types.hpp" +#include "barretenberg/stdlib/commitment/pedersen/pedersen.hpp" +#include "barretenberg/stdlib/primitives/point/point.hpp" #include "../../constants.hpp" +#include "barretenberg/join_split_example/types.hpp" namespace join_split_example { namespace proofs { @@ -8,7 +10,7 @@ namespace notes { namespace circuit { namespace account { -using namespace proof_system::plonk::stdlib::types; +using namespace proof_system::plonk::stdlib; inline auto commit(field_ct const& account_alias_hash, point_ct const& account_public_key, diff --git a/cpp/src/barretenberg/join_split_example/proofs/notes/circuit/asset_id.cpp b/cpp/src/barretenberg/join_split_example/proofs/notes/circuit/asset_id.cpp index 5163231bc5..6a7a559b70 100644 --- a/cpp/src/barretenberg/join_split_example/proofs/notes/circuit/asset_id.cpp +++ b/cpp/src/barretenberg/join_split_example/proofs/notes/circuit/asset_id.cpp @@ -1,9 +1,9 @@ -#include "barretenberg/stdlib/types/types.hpp" +#include "barretenberg/join_split_example/types.hpp" #include "../constants.hpp" namespace join_split_example::proofs::notes::circuit { -using namespace proof_system::plonk::stdlib::types; +using namespace proof_system::plonk::stdlib; std::pair deflag_asset_id(suint_ct const& asset_id) { diff --git a/cpp/src/barretenberg/join_split_example/proofs/notes/circuit/asset_id.hpp b/cpp/src/barretenberg/join_split_example/proofs/notes/circuit/asset_id.hpp index 3c67f16695..89e244f39b 100644 --- a/cpp/src/barretenberg/join_split_example/proofs/notes/circuit/asset_id.hpp +++ b/cpp/src/barretenberg/join_split_example/proofs/notes/circuit/asset_id.hpp @@ -1,9 +1,9 @@ #pragma once -#include "barretenberg/stdlib/types/types.hpp" +#include "barretenberg/join_split_example/types.hpp" namespace join_split_example::proofs::notes::circuit { -using namespace proof_system::plonk::stdlib::types; +using namespace proof_system::plonk::stdlib; std::pair deflag_asset_id(suint_ct const& asset_id); diff --git a/cpp/src/barretenberg/join_split_example/proofs/notes/circuit/bridge_call_data.hpp b/cpp/src/barretenberg/join_split_example/proofs/notes/circuit/bridge_call_data.hpp index f5b1bbd319..f8ea941167 100644 --- a/cpp/src/barretenberg/join_split_example/proofs/notes/circuit/bridge_call_data.hpp +++ b/cpp/src/barretenberg/join_split_example/proofs/notes/circuit/bridge_call_data.hpp @@ -1,5 +1,5 @@ #pragma once -#include "barretenberg/stdlib/types/types.hpp" +#include "barretenberg/join_split_example/types.hpp" #include "../native/bridge_call_data.hpp" #include "./asset_id.hpp" #include "../constants.hpp" @@ -9,7 +9,7 @@ namespace proofs { namespace notes { namespace circuit { -using namespace proof_system::plonk::stdlib::types; +using namespace proof_system::plonk::stdlib; constexpr uint32_t input_asset_id_a_shift = DEFI_BRIDGE_ADDRESS_ID_LEN; constexpr uint32_t input_asset_id_b_shift = input_asset_id_a_shift + DEFI_BRIDGE_INPUT_A_ASSET_ID_LEN; diff --git a/cpp/src/barretenberg/join_split_example/proofs/notes/circuit/claim/claim_note.hpp b/cpp/src/barretenberg/join_split_example/proofs/notes/circuit/claim/claim_note.hpp index 8021265a43..8a23ff9f93 100644 --- a/cpp/src/barretenberg/join_split_example/proofs/notes/circuit/claim/claim_note.hpp +++ b/cpp/src/barretenberg/join_split_example/proofs/notes/circuit/claim/claim_note.hpp @@ -1,5 +1,6 @@ #pragma once -#include "barretenberg/stdlib/types/types.hpp" +#include "barretenberg/join_split_example/types.hpp" + #include "../bridge_call_data.hpp" #include "witness_data.hpp" #include "../value/create_partial_commitment.hpp" @@ -12,7 +13,7 @@ namespace notes { namespace circuit { namespace claim { -using namespace proof_system::plonk::stdlib::types; +using namespace proof_system::plonk::stdlib; struct partial_claim_note { suint_ct deposit_value; diff --git a/cpp/src/barretenberg/join_split_example/proofs/notes/circuit/claim/complete_partial_commitment.hpp b/cpp/src/barretenberg/join_split_example/proofs/notes/circuit/claim/complete_partial_commitment.hpp index 9b1010ab58..fb20d7fef9 100644 --- a/cpp/src/barretenberg/join_split_example/proofs/notes/circuit/claim/complete_partial_commitment.hpp +++ b/cpp/src/barretenberg/join_split_example/proofs/notes/circuit/claim/complete_partial_commitment.hpp @@ -1,6 +1,7 @@ #pragma once -#include "barretenberg/stdlib/types/types.hpp" +#include "barretenberg/join_split_example/types.hpp" #include "../../constants.hpp" +#include "barretenberg/stdlib/commitment/pedersen/pedersen.hpp" namespace join_split_example { namespace proofs { @@ -8,7 +9,7 @@ namespace notes { namespace circuit { namespace claim { -using namespace proof_system::plonk::stdlib::types; +using namespace proof_system::plonk::stdlib; inline auto complete_partial_commitment(field_ct const& partial_commitment, field_ct const& interaction_nonce, diff --git a/cpp/src/barretenberg/join_split_example/proofs/notes/circuit/claim/compute_nullifier.hpp b/cpp/src/barretenberg/join_split_example/proofs/notes/circuit/claim/compute_nullifier.hpp index 304f9f6205..2ffb181bb2 100644 --- a/cpp/src/barretenberg/join_split_example/proofs/notes/circuit/claim/compute_nullifier.hpp +++ b/cpp/src/barretenberg/join_split_example/proofs/notes/circuit/claim/compute_nullifier.hpp @@ -1,5 +1,6 @@ #pragma once -#include "barretenberg/stdlib/types/types.hpp" + +#include "barretenberg/join_split_example/types.hpp" #include "barretenberg/stdlib/hash/pedersen/pedersen.hpp" #include "../../constants.hpp" @@ -9,8 +10,6 @@ namespace notes { namespace circuit { namespace claim { -using namespace proof_system::plonk::stdlib::types; - inline field_ct compute_nullifier(field_ct const& note_commitment) { return pedersen_commitment::compress(std::vector{ note_commitment }, diff --git a/cpp/src/barretenberg/join_split_example/proofs/notes/circuit/claim/create_partial_commitment.hpp b/cpp/src/barretenberg/join_split_example/proofs/notes/circuit/claim/create_partial_commitment.hpp index 30eb7adb7a..36c37a8e78 100644 --- a/cpp/src/barretenberg/join_split_example/proofs/notes/circuit/claim/create_partial_commitment.hpp +++ b/cpp/src/barretenberg/join_split_example/proofs/notes/circuit/claim/create_partial_commitment.hpp @@ -1,5 +1,5 @@ #pragma once -#include "barretenberg/stdlib/types/types.hpp" +#include "barretenberg/join_split_example/types.hpp" #include "barretenberg/stdlib/hash/pedersen/pedersen.hpp" #include "../../constants.hpp" @@ -9,7 +9,7 @@ namespace notes { namespace circuit { namespace claim { -using namespace proof_system::plonk::stdlib::types; +using namespace proof_system::plonk::stdlib; inline auto create_partial_commitment(field_ct const& deposit_value, field_ct const& bridge_call_data, diff --git a/cpp/src/barretenberg/join_split_example/proofs/notes/circuit/claim/witness_data.hpp b/cpp/src/barretenberg/join_split_example/proofs/notes/circuit/claim/witness_data.hpp index b49bddd3bb..e5fc35fb39 100644 --- a/cpp/src/barretenberg/join_split_example/proofs/notes/circuit/claim/witness_data.hpp +++ b/cpp/src/barretenberg/join_split_example/proofs/notes/circuit/claim/witness_data.hpp @@ -1,5 +1,6 @@ #pragma once -#include "barretenberg/stdlib/types/types.hpp" + +#include "barretenberg/join_split_example/types.hpp" #include "../../native/claim/claim_note.hpp" #include "../../native/claim/claim_note_tx_data.hpp" #include "../../constants.hpp" @@ -11,7 +12,7 @@ namespace notes { namespace circuit { namespace claim { -using namespace proof_system::plonk::stdlib::types; +using namespace proof_system::plonk::stdlib; /** * Convert native claim note data into circuit witness data. diff --git a/cpp/src/barretenberg/join_split_example/proofs/notes/circuit/value/complete_partial_commitment.hpp b/cpp/src/barretenberg/join_split_example/proofs/notes/circuit/value/complete_partial_commitment.hpp index e5bc84b994..1ec344d17a 100644 --- a/cpp/src/barretenberg/join_split_example/proofs/notes/circuit/value/complete_partial_commitment.hpp +++ b/cpp/src/barretenberg/join_split_example/proofs/notes/circuit/value/complete_partial_commitment.hpp @@ -1,15 +1,15 @@ #pragma once -#include "barretenberg/stdlib/types/types.hpp" + +#include "barretenberg/join_split_example/types.hpp" #include "barretenberg/stdlib/commitment/pedersen/pedersen.hpp" #include "../../constants.hpp" - namespace join_split_example { namespace proofs { namespace notes { namespace circuit { namespace value { -using namespace proof_system::plonk::stdlib::types; +using namespace proof_system::plonk::stdlib; inline auto complete_partial_commitment(field_ct const& value_note_partial_commitment, suint_ct const& value, diff --git a/cpp/src/barretenberg/join_split_example/proofs/notes/circuit/value/compute_nullifier.cpp b/cpp/src/barretenberg/join_split_example/proofs/notes/circuit/value/compute_nullifier.cpp index 30dafca6b6..6f73dd418f 100644 --- a/cpp/src/barretenberg/join_split_example/proofs/notes/circuit/value/compute_nullifier.cpp +++ b/cpp/src/barretenberg/join_split_example/proofs/notes/circuit/value/compute_nullifier.cpp @@ -1,6 +1,6 @@ #include "compute_nullifier.hpp" #include "../../constants.hpp" -#include "barretenberg/stdlib/types/types.hpp" +#include "barretenberg/join_split_example/types.hpp" namespace join_split_example { namespace proofs { @@ -8,7 +8,7 @@ namespace notes { namespace circuit { using namespace barretenberg; -using namespace proof_system::plonk::stdlib::types; +using namespace proof_system::plonk::stdlib; field_ct compute_nullifier(field_ct const& note_commitment, field_ct const& account_private_key, diff --git a/cpp/src/barretenberg/join_split_example/proofs/notes/circuit/value/compute_nullifier.hpp b/cpp/src/barretenberg/join_split_example/proofs/notes/circuit/value/compute_nullifier.hpp index 3271035abb..85a14dd416 100644 --- a/cpp/src/barretenberg/join_split_example/proofs/notes/circuit/value/compute_nullifier.hpp +++ b/cpp/src/barretenberg/join_split_example/proofs/notes/circuit/value/compute_nullifier.hpp @@ -1,14 +1,11 @@ #pragma once -#include "barretenberg/stdlib/types/types.hpp" +#include "barretenberg/join_split_example/types.hpp" namespace join_split_example { namespace proofs { namespace notes { namespace circuit { -using namespace barretenberg; -using namespace proof_system::plonk::stdlib::types; - field_ct compute_nullifier(field_ct const& note_commitment, field_ct const& account_private_key, bool_ct const& is_note_in_use); diff --git a/cpp/src/barretenberg/join_split_example/proofs/notes/circuit/value/compute_nullifier.test.cpp b/cpp/src/barretenberg/join_split_example/proofs/notes/circuit/value/compute_nullifier.test.cpp index 063ef93edd..88198aa7c5 100644 --- a/cpp/src/barretenberg/join_split_example/proofs/notes/circuit/value/compute_nullifier.test.cpp +++ b/cpp/src/barretenberg/join_split_example/proofs/notes/circuit/value/compute_nullifier.test.cpp @@ -4,10 +4,10 @@ #include "./value_note.hpp" #include "../../native/value/compute_nullifier.hpp" #include "../../native/value/value_note.hpp" -#include "barretenberg/stdlib/types/types.hpp" +#include "barretenberg/join_split_example/types.hpp" +namespace join_split_example { using namespace join_split_example::proofs::notes; -using namespace proof_system::plonk::stdlib::types; TEST(compute_nullifier_circuit, native_consistency) { @@ -18,7 +18,6 @@ TEST(compute_nullifier_circuit, native_consistency) native::value::value_note{ 100, 0, 0, user.owner.public_key, user.note_secret, 0, fr::random_element() }; auto native_commitment = native_input_note.commit(); auto native_nullifier = native::compute_nullifier(native_commitment, priv_key, true); - Composer composer; auto circuit_witness_data = circuit::value::witness_data(composer, native_input_note); auto circuit_input_note = circuit::value::value_note(circuit_witness_data); @@ -27,3 +26,4 @@ TEST(compute_nullifier_circuit, native_consistency) EXPECT_EQ(circuit_nullifier.get_value(), native_nullifier); } +} // namespace join_split_example \ No newline at end of file diff --git a/cpp/src/barretenberg/join_split_example/proofs/notes/circuit/value/create_partial_commitment.hpp b/cpp/src/barretenberg/join_split_example/proofs/notes/circuit/value/create_partial_commitment.hpp index f01324ee34..ac6104c65a 100644 --- a/cpp/src/barretenberg/join_split_example/proofs/notes/circuit/value/create_partial_commitment.hpp +++ b/cpp/src/barretenberg/join_split_example/proofs/notes/circuit/value/create_partial_commitment.hpp @@ -1,6 +1,6 @@ #pragma once -#include "barretenberg/stdlib/types/types.hpp" -#include "barretenberg/stdlib/hash/pedersen/pedersen.hpp" +#include "barretenberg/stdlib/commitment/pedersen/pedersen.hpp" +#include "barretenberg/join_split_example/types.hpp" #include "../../constants.hpp" namespace join_split_example { @@ -9,8 +9,6 @@ namespace notes { namespace circuit { namespace value { -using namespace proof_system::plonk::stdlib::types; - inline auto create_partial_commitment(field_ct const& secret, point_ct const& owner, bool_ct const& account_required, diff --git a/cpp/src/barretenberg/join_split_example/proofs/notes/circuit/value/value_note.hpp b/cpp/src/barretenberg/join_split_example/proofs/notes/circuit/value/value_note.hpp index a4f8cc04c8..9f2d47a6c6 100644 --- a/cpp/src/barretenberg/join_split_example/proofs/notes/circuit/value/value_note.hpp +++ b/cpp/src/barretenberg/join_split_example/proofs/notes/circuit/value/value_note.hpp @@ -1,5 +1,5 @@ #pragma once -#include "barretenberg/stdlib/types/types.hpp" +#include "barretenberg/join_split_example/types.hpp" #include "witness_data.hpp" #include "commit.hpp" @@ -9,7 +9,7 @@ namespace notes { namespace circuit { namespace value { -using namespace proof_system::plonk::stdlib::types; +using namespace proof_system::plonk::stdlib; struct value_note { point_ct owner; diff --git a/cpp/src/barretenberg/join_split_example/proofs/notes/circuit/value/value_note.test.cpp b/cpp/src/barretenberg/join_split_example/proofs/notes/circuit/value/value_note.test.cpp index e243b35fb8..55b65c9949 100644 --- a/cpp/src/barretenberg/join_split_example/proofs/notes/circuit/value/value_note.test.cpp +++ b/cpp/src/barretenberg/join_split_example/proofs/notes/circuit/value/value_note.test.cpp @@ -2,13 +2,14 @@ #include "../../../../fixtures/user_context.hpp" #include "../../native/value/value_note.hpp" #include "../../constants.hpp" +#include "barretenberg/join_split_example/types.hpp" #include +namespace join_split_example { using namespace barretenberg; -using namespace proof_system::plonk::stdlib::types; +using namespace proof_system::plonk::stdlib; using namespace join_split_example::proofs::notes; using namespace join_split_example::proofs::notes::circuit::value; - TEST(value_note, commits) { auto user = join_split_example::fixtures::create_user_context(); @@ -106,4 +107,5 @@ TEST(value_note, commit_with_oversized_asset_id_fails) bool proof_result = verifier.verify_proof(proof); EXPECT_EQ(proof_result, false); -} \ No newline at end of file +} +} // namespace join_split_example \ No newline at end of file diff --git a/cpp/src/barretenberg/join_split_example/proofs/notes/circuit/value/witness_data.hpp b/cpp/src/barretenberg/join_split_example/proofs/notes/circuit/value/witness_data.hpp index ff0cbc0cc2..367f0e704e 100644 --- a/cpp/src/barretenberg/join_split_example/proofs/notes/circuit/value/witness_data.hpp +++ b/cpp/src/barretenberg/join_split_example/proofs/notes/circuit/value/witness_data.hpp @@ -1,7 +1,6 @@ #pragma once -#include "barretenberg/stdlib/types/types.hpp" #include "../../native/value/value_note.hpp" -#include "../../constants.hpp" +#include "barretenberg/join_split_example/types.hpp" namespace join_split_example { namespace proofs { @@ -9,7 +8,7 @@ namespace notes { namespace circuit { namespace value { -using namespace proof_system::plonk::stdlib::types; +using namespace proof_system::plonk::stdlib; struct witness_data { point_ct owner; diff --git a/cpp/src/barretenberg/join_split_example/types.hpp b/cpp/src/barretenberg/join_split_example/types.hpp new file mode 100644 index 0000000000..65b6cca423 --- /dev/null +++ b/cpp/src/barretenberg/join_split_example/types.hpp @@ -0,0 +1,50 @@ +#pragma once + +#include "barretenberg/plonk/composer/standard_composer.hpp" +#include "barretenberg/plonk/composer/turbo_composer.hpp" +#include "barretenberg/plonk/composer/ultra_composer.hpp" + +#include "barretenberg/plonk/proof_system/prover/prover.hpp" +#include "barretenberg/stdlib/primitives/bool/bool.hpp" +#include "barretenberg/stdlib/primitives/byte_array/byte_array.hpp" +#include "barretenberg/stdlib/primitives/uint/uint.hpp" +#include "barretenberg/stdlib/primitives/witness/witness.hpp" +#include "barretenberg/stdlib/commitment/pedersen/pedersen.hpp" +#include "barretenberg/stdlib/commitment/pedersen/pedersen_plookup.hpp" +#include "barretenberg/stdlib/merkle_tree/hash_path.hpp" +#include "barretenberg/stdlib/encryption/schnorr/schnorr.hpp" +#include "barretenberg/stdlib/primitives/curves/bn254.hpp" + +namespace join_split_example { + +using Composer = plonk::UltraComposer; + +using Prover = std::conditional_t< + std::same_as, + plonk::UltraProver, + std::conditional_t, plonk::TurboProver, plonk::Prover>>; + +using Verifier = std::conditional_t< + std::same_as, + plonk::UltraVerifier, + std::conditional_t, plonk::TurboVerifier, plonk::Verifier>>; + +using witness_ct = proof_system::plonk::stdlib::witness_t; +using public_witness_ct = proof_system::plonk::stdlib::public_witness_t; +using bool_ct = proof_system::plonk::stdlib::bool_t; +using byte_array_ct = proof_system::plonk::stdlib::byte_array; +using field_ct = proof_system::plonk::stdlib::field_t; +using suint_ct = proof_system::plonk::stdlib::safe_uint_t; +using uint32_ct = proof_system::plonk::stdlib::uint32; +using point_ct = proof_system::plonk::stdlib::point; +using pedersen_commitment = proof_system::plonk::stdlib::pedersen_commitment; +using group_ct = proof_system::plonk::stdlib::group; +using bn254 = proof_system::plonk::stdlib::bn254; + +using hash_path_ct = proof_system::plonk::stdlib::merkle_tree::hash_path; + +namespace schnorr { +using signature_bits = proof_system::plonk::stdlib::schnorr::signature_bits; +} // namespace schnorr + +} // namespace join_split_example \ No newline at end of file diff --git a/cpp/src/barretenberg/plonk/composer/ultra_composer.cpp b/cpp/src/barretenberg/plonk/composer/ultra_composer.cpp index 597b2ddea0..8782f6ab61 100644 --- a/cpp/src/barretenberg/plonk/composer/ultra_composer.cpp +++ b/cpp/src/barretenberg/plonk/composer/ultra_composer.cpp @@ -890,6 +890,50 @@ UltraToStandardProver UltraComposer::create_ultra_to_standard_prover() return output_state; } +/** + * @brief Uses slightly different settings from the UltraProver. + */ +UltraWithKeccakProver UltraComposer::create_ultra_with_keccak_prover() +{ + compute_proving_key(); + compute_witness(); + + UltraWithKeccakProver output_state(circuit_proving_key, create_manifest(public_inputs.size())); + + std::unique_ptr> permutation_widget = + std::make_unique>(circuit_proving_key.get()); + + std::unique_ptr> plookup_widget = + std::make_unique>(circuit_proving_key.get()); + + std::unique_ptr> arithmetic_widget = + std::make_unique>(circuit_proving_key.get()); + + std::unique_ptr> sort_widget = + std::make_unique>(circuit_proving_key.get()); + + std::unique_ptr> elliptic_widget = + std::make_unique>(circuit_proving_key.get()); + + std::unique_ptr> auxiliary_widget = + std::make_unique>(circuit_proving_key.get()); + + output_state.random_widgets.emplace_back(std::move(permutation_widget)); + output_state.random_widgets.emplace_back(std::move(plookup_widget)); + + output_state.transition_widgets.emplace_back(std::move(arithmetic_widget)); + output_state.transition_widgets.emplace_back(std::move(sort_widget)); + output_state.transition_widgets.emplace_back(std::move(elliptic_widget)); + output_state.transition_widgets.emplace_back(std::move(auxiliary_widget)); + + std::unique_ptr> kate_commitment_scheme = + std::make_unique>(); + + output_state.commitment_scheme = std::move(kate_commitment_scheme); + + return output_state; +} + UltraVerifier UltraComposer::create_verifier() { compute_verification_key(); @@ -918,6 +962,20 @@ UltraToStandardVerifier UltraComposer::create_ultra_to_standard_verifier() return output_state; } +UltraWithKeccakVerifier UltraComposer::create_ultra_with_keccak_verifier() +{ + compute_verification_key(); + + UltraWithKeccakVerifier output_state(circuit_verification_key, create_manifest(public_inputs.size())); + + std::unique_ptr> kate_commitment_scheme = + std::make_unique>(); + + output_state.commitment_scheme = std::move(kate_commitment_scheme); + + return output_state; +} + void UltraComposer::initialize_precomputed_table( const plookup::BasicTableId id, bool (*generator)(std::vector&, std ::vector&, std::vector&), diff --git a/cpp/src/barretenberg/plonk/composer/ultra_composer.hpp b/cpp/src/barretenberg/plonk/composer/ultra_composer.hpp index 6cdc969423..b3157639fd 100644 --- a/cpp/src/barretenberg/plonk/composer/ultra_composer.hpp +++ b/cpp/src/barretenberg/plonk/composer/ultra_composer.hpp @@ -160,6 +160,9 @@ class UltraComposer : public ComposerBase { UltraToStandardProver create_ultra_to_standard_prover(); UltraToStandardVerifier create_ultra_to_standard_verifier(); + UltraWithKeccakProver create_ultra_with_keccak_prover(); + UltraWithKeccakVerifier create_ultra_with_keccak_verifier(); + void create_add_gate(const add_triple& in) override; void create_big_add_gate(const add_quad& in, const bool use_next_gate_w_4 = false); diff --git a/cpp/src/barretenberg/plonk/composer/ultra_composer.test.cpp b/cpp/src/barretenberg/plonk/composer/ultra_composer.test.cpp index 8219f9183c..eef80fa56c 100644 --- a/cpp/src/barretenberg/plonk/composer/ultra_composer.test.cpp +++ b/cpp/src/barretenberg/plonk/composer/ultra_composer.test.cpp @@ -10,7 +10,7 @@ using namespace barretenberg; using namespace proof_system; -namespace proof_system::plonk { +namespace proof_system::plonk::test_ultra_composer { namespace { auto& engine = numeric::random::get_debug_engine(); @@ -27,7 +27,39 @@ std::vector add_variables(UltraComposer& composer, std::vector var } return res; } -TEST(ultra_composer, create_gates_from_plookup_accumulators) + +template class ultra_composer : public ::testing::Test { + public: + void prove_and_verify(UltraComposer& composer, bool expected_result) + { + if constexpr (T::use_keccak) { + auto prover = composer.create_ultra_with_keccak_prover(); + auto verifier = composer.create_ultra_with_keccak_verifier(); + auto proof = prover.construct_proof(); + bool verified = verifier.verify_proof(proof); + EXPECT_EQ(verified, expected_result); + } else { + auto prover = composer.create_prover(); + auto verifier = composer.create_verifier(); + auto proof = prover.construct_proof(); + bool verified = verifier.verify_proof(proof); + EXPECT_EQ(verified, expected_result); + } + }; +}; + +struct UseKeccak32Bytes { + static constexpr bool use_keccak = true; +}; + +struct UsePlookupPedersen16Bytes { + static constexpr bool use_keccak = false; +}; + +using BooleanTypes = ::testing::Types; +TYPED_TEST_SUITE(ultra_composer, BooleanTypes); + +TYPED_TEST(ultra_composer, create_gates_from_plookup_accumulators) { UltraComposer composer = UltraComposer(); @@ -106,16 +138,10 @@ TEST(ultra_composer, create_gates_from_plookup_accumulators) EXPECT_EQ(composer.get_variable(lookup_witnesses_hi[ColumnIdx::C3][i]), expected_y[i + num_lookups_lo]); } - auto prover = composer.create_prover(); - auto verifier = composer.create_verifier(); - auto proof = prover.construct_proof(); - - bool result = verifier.verify_proof(proof); - - EXPECT_EQ(result, true); + TestFixture::prove_and_verify(composer, /*expected_result=*/true); } -TEST(ultra_composer, test_no_lookup_proof) +TYPED_TEST(ultra_composer, test_no_lookup_proof) { UltraComposer composer = UltraComposer(); @@ -133,17 +159,10 @@ TEST(ultra_composer, test_no_lookup_proof) } } - auto prover = composer.create_prover(); - - auto verifier = composer.create_verifier(); - - auto proof = prover.construct_proof(); - - bool result = verifier.verify_proof(proof); // instance, prover.reference_string.SRS_T2); - EXPECT_EQ(result, true); + TestFixture::prove_and_verify(composer, /*expected_result=*/true); } -TEST(ultra_composer, test_elliptic_gate) +TYPED_TEST(ultra_composer, test_elliptic_gate) { typedef grumpkin::g1::affine_element affine_element; typedef grumpkin::g1::element element; @@ -180,17 +199,10 @@ TEST(ultra_composer, test_elliptic_gate) gate = ecc_add_gate{ x1, y1, x2, y2, x3, y3, beta.sqr(), -1 }; composer.create_ecc_add_gate(gate); - auto prover = composer.create_prover(); - - auto verifier = composer.create_verifier(); - - auto proof = prover.construct_proof(); - - bool result = verifier.verify_proof(proof); // instance, prover.reference_string.SRS_T2); - EXPECT_EQ(result, true); + TestFixture::prove_and_verify(composer, /*expected_result=*/true); } -TEST(ultra_composer, non_trivial_tag_permutation) +TYPED_TEST(ultra_composer, non_trivial_tag_permutation) { UltraComposer composer = UltraComposer(); fr a = fr::random_element(); @@ -215,15 +227,11 @@ TEST(ultra_composer, non_trivial_tag_permutation) // composer.create_add_gate({ a_idx, b_idx, composer.zero_idx, fr::one(), fr::neg_one(), fr::zero(), fr::zero() }); // composer.create_add_gate({ a_idx, b_idx, composer.zero_idx, fr::one(), fr::neg_one(), fr::zero(), fr::zero() }); // composer.create_add_gate({ a_idx, b_idx, composer.zero_idx, fr::one(), fr::neg_one(), fr::zero(), fr::zero() }); - auto prover = composer.create_prover(); - auto verifier = composer.create_verifier(); - - proof proof = prover.construct_proof(); - bool result = verifier.verify_proof(proof); // instance, prover.reference_string.SRS_T2); - EXPECT_EQ(result, true); + TestFixture::prove_and_verify(composer, /*expected_result=*/true); } -TEST(ultra_composer, non_trivial_tag_permutation_and_cycles) + +TYPED_TEST(ultra_composer, non_trivial_tag_permutation_and_cycles) { UltraComposer composer = UltraComposer(); fr a = fr::random_element(); @@ -257,17 +265,11 @@ TEST(ultra_composer, non_trivial_tag_permutation_and_cycles) // composer.create_add_gate({ a_idx, b_idx, composer.zero_idx, fr::one(), fr::neg_one(), fr::zero(), fr::zero() }); // composer.create_add_gate({ a_idx, b_idx, composer.zero_idx, fr::one(), fr::neg_one(), fr::zero(), fr::zero() }); // composer.create_add_gate({ a_idx, b_idx, composer.zero_idx, fr::one(), fr::neg_one(), fr::zero(), fr::zero() }); - auto prover = composer.create_prover(); - - auto verifier = composer.create_verifier(); - - proof proof = prover.construct_proof(); - bool result = verifier.verify_proof(proof); // instance, prover.reference_string.SRS_T2); - EXPECT_EQ(result, true); + TestFixture::prove_and_verify(composer, /*expected_result=*/true); } -TEST(ultra_composer, bad_tag_permutation) +TYPED_TEST(ultra_composer, bad_tag_permutation) { UltraComposer composer = UltraComposer(); fr a = fr::random_element(); @@ -288,16 +290,12 @@ TEST(ultra_composer, bad_tag_permutation) composer.assign_tag(b_idx, 1); composer.assign_tag(c_idx, 2); composer.assign_tag(d_idx, 2); - auto prover = composer.create_prover(); - auto verifier = composer.create_verifier(); - proof proof = prover.construct_proof(); - bool result = verifier.verify_proof(proof); // instance, prover.reference_string.SRS_T2); - EXPECT_EQ(result, false); + TestFixture::prove_and_verify(composer, /*expected_result=*/false); } // same as above but with turbocomposer to check reason of failue is really tag mismatch -TEST(ultra_composer, bad_tag_turbo_permutation) +TYPED_TEST(ultra_composer, bad_tag_turbo_permutation) { UltraComposer composer = UltraComposer(); fr a = fr::random_element(); @@ -317,13 +315,10 @@ TEST(ultra_composer, bad_tag_turbo_permutation) auto prover = composer.create_prover(); auto verifier = composer.create_verifier(); - proof proof = prover.construct_proof(); - - bool result = verifier.verify_proof(proof); // instance, prover.reference_string.SRS_T2); - EXPECT_EQ(result, true); + TestFixture::prove_and_verify(composer, /*expected_result=*/true); } -TEST(ultra_composer, sort_widget) +TYPED_TEST(ultra_composer, sort_widget) { UltraComposer composer = UltraComposer(); fr a = fr::one(); @@ -336,16 +331,11 @@ TEST(ultra_composer, sort_widget) auto c_idx = composer.add_variable(c); auto d_idx = composer.add_variable(d); composer.create_sort_constraint({ a_idx, b_idx, c_idx, d_idx }); - auto prover = composer.create_prover(); - auto verifier = composer.create_verifier(); - - proof proof = prover.construct_proof(); - bool result = verifier.verify_proof(proof); // instance, prover.reference_string.SRS_T2); - EXPECT_EQ(result, true); + TestFixture::prove_and_verify(composer, /*expected_result=*/true); } -TEST(ultra_composer, sort_with_edges_gate) +TYPED_TEST(ultra_composer, sort_with_edges_gate) { fr a = fr::one(); @@ -368,13 +358,8 @@ TEST(ultra_composer, sort_with_edges_gate) auto g_idx = composer.add_variable(g); auto h_idx = composer.add_variable(h); composer.create_sort_constraint_with_edges({ a_idx, b_idx, c_idx, d_idx, e_idx, f_idx, g_idx, h_idx }, a, h); - auto prover = composer.create_prover(); - auto verifier = composer.create_verifier(); - proof proof = prover.construct_proof(); - - bool result = verifier.verify_proof(proof); // instance, prover.reference_string.SRS_T2); - EXPECT_EQ(result, true); + TestFixture::prove_and_verify(composer, /*expected_result=*/true); } { @@ -407,13 +392,8 @@ TEST(ultra_composer, sort_with_edges_gate) auto g_idx = composer.add_variable(g); auto h_idx = composer.add_variable(h); composer.create_sort_constraint_with_edges({ a_idx, b_idx, c_idx, d_idx, e_idx, f_idx, g_idx, h_idx }, b, h); - auto prover = composer.create_prover(); - auto verifier = composer.create_verifier(); - - proof proof = prover.construct_proof(); - bool result = verifier.verify_proof(proof); // instance, prover.reference_string.SRS_T2); - EXPECT_EQ(result, false); + TestFixture::prove_and_verify(composer, /*expected_result=*/false); } { UltraComposer composer = UltraComposer(); @@ -426,26 +406,16 @@ TEST(ultra_composer, sort_with_edges_gate) auto h_idx = composer.add_variable(h); auto b2_idx = composer.add_variable(fr(15)); composer.create_sort_constraint_with_edges({ a_idx, b2_idx, c_idx, d_idx, e_idx, f_idx, g_idx, h_idx }, b, h); - auto prover = composer.create_prover(); - auto verifier = composer.create_verifier(); - - proof proof = prover.construct_proof(); - bool result = verifier.verify_proof(proof); // instance, prover.reference_string.SRS_T2); - EXPECT_EQ(result, false); + TestFixture::prove_and_verify(composer, /*expected_result=*/false); } { UltraComposer composer = UltraComposer(); auto idx = add_variables(composer, { 1, 2, 5, 6, 7, 10, 11, 13, 16, 17, 20, 22, 22, 25, 26, 29, 29, 32, 32, 33, 35, 38, 39, 39, 42, 42, 43, 45 }); composer.create_sort_constraint_with_edges(idx, 1, 45); - auto prover = composer.create_prover(); - auto verifier = composer.create_verifier(); - proof proof = prover.construct_proof(); - - bool result = verifier.verify_proof(proof); // instance, prover.reference_string.SRS_T2); - EXPECT_EQ(result, true); + TestFixture::prove_and_verify(composer, /*expected_result=*/true); } { UltraComposer composer = UltraComposer(); @@ -453,16 +423,12 @@ TEST(ultra_composer, sort_with_edges_gate) 26, 29, 29, 32, 32, 33, 35, 38, 39, 39, 42, 42, 43, 45 }); composer.create_sort_constraint_with_edges(idx, 1, 29); - auto prover = composer.create_prover(); - auto verifier = composer.create_verifier(); - proof proof = prover.construct_proof(); - bool result = verifier.verify_proof(proof); // instance, prover.reference_string.SRS_T2); - EXPECT_EQ(result, false); + TestFixture::prove_and_verify(composer, /*expected_result=*/false); } } -TEST(ultra_composer, range_constraint) +TYPED_TEST(ultra_composer, range_constraint) { { UltraComposer composer = UltraComposer(); @@ -488,13 +454,8 @@ TEST(ultra_composer, range_constraint) } // auto ind = {a_idx,b_idx,c_idx,d_idx,e_idx,f_idx,g_idx,h_idx}; composer.create_dummy_constraints(indices); - auto prover = composer.create_prover(); - auto verifier = composer.create_verifier(); - proof proof = prover.construct_proof(); - - bool result = verifier.verify_proof(proof); - EXPECT_EQ(result, true); + TestFixture::prove_and_verify(composer, /*expected_result=*/true); } { UltraComposer composer = UltraComposer(); @@ -503,13 +464,8 @@ TEST(ultra_composer, range_constraint) composer.create_new_range_constraint(indices[i], 8); } composer.create_sort_constraint(indices); - auto prover = composer.create_prover(); - auto verifier = composer.create_verifier(); - - proof proof = prover.construct_proof(); - bool result = verifier.verify_proof(proof); - EXPECT_EQ(result, false); + TestFixture::prove_and_verify(composer, /*expected_result=*/false); } { UltraComposer composer = UltraComposer(); @@ -519,13 +475,8 @@ TEST(ultra_composer, range_constraint) composer.create_new_range_constraint(indices[i], 128); } composer.create_dummy_constraints(indices); - auto prover = composer.create_prover(); - auto verifier = composer.create_verifier(); - proof proof = prover.construct_proof(); - - bool result = verifier.verify_proof(proof); - EXPECT_EQ(result, true); + TestFixture::prove_and_verify(composer, /*expected_result=*/true); } { UltraComposer composer = UltraComposer(); @@ -551,17 +502,12 @@ TEST(ultra_composer, range_constraint) composer.create_new_range_constraint(indices[i], 79); } composer.create_dummy_constraints(indices); - auto prover = composer.create_prover(); - auto verifier = composer.create_verifier(); - - proof proof = prover.construct_proof(); - bool result = verifier.verify_proof(proof); - EXPECT_EQ(result, false); + TestFixture::prove_and_verify(composer, /*expected_result=*/false); } } -TEST(ultra_composer, range_with_gates) +TYPED_TEST(ultra_composer, range_with_gates) { UltraComposer composer = UltraComposer(); @@ -574,15 +520,11 @@ TEST(ultra_composer, range_with_gates) composer.create_add_gate({ idx[2], idx[3], composer.zero_idx, fr::one(), fr::one(), fr::zero(), -7 }); composer.create_add_gate({ idx[4], idx[5], composer.zero_idx, fr::one(), fr::one(), fr::zero(), -11 }); composer.create_add_gate({ idx[6], idx[7], composer.zero_idx, fr::one(), fr::one(), fr::zero(), -15 }); - auto prover = composer.create_prover(); - auto verifier = composer.create_verifier(); - proof proof = prover.construct_proof(); - bool result = verifier.verify_proof(proof); - EXPECT_EQ(result, true); + TestFixture::prove_and_verify(composer, /*expected_result=*/true); } -TEST(ultra_composer, range_with_gates_where_range_is_not_a_power_of_two) +TYPED_TEST(ultra_composer, range_with_gates_where_range_is_not_a_power_of_two) { UltraComposer composer = UltraComposer(); auto idx = add_variables(composer, { 1, 2, 3, 4, 5, 6, 7, 8 }); @@ -594,15 +536,11 @@ TEST(ultra_composer, range_with_gates_where_range_is_not_a_power_of_two) composer.create_add_gate({ idx[2], idx[3], composer.zero_idx, fr::one(), fr::one(), fr::zero(), -7 }); composer.create_add_gate({ idx[4], idx[5], composer.zero_idx, fr::one(), fr::one(), fr::zero(), -11 }); composer.create_add_gate({ idx[6], idx[7], composer.zero_idx, fr::one(), fr::one(), fr::zero(), -15 }); - auto prover = composer.create_prover(); - auto verifier = composer.create_verifier(); - proof proof = prover.construct_proof(); - bool result = verifier.verify_proof(proof); - EXPECT_EQ(result, true); + TestFixture::prove_and_verify(composer, /*expected_result=*/true); } -TEST(ultra_composer, sort_widget_complex) +TYPED_TEST(ultra_composer, sort_widget_complex) { { @@ -628,16 +566,11 @@ TEST(ultra_composer, sort_widget_complex) for (size_t i = 0; i < a.size(); i++) ind.emplace_back(composer.add_variable(a[i])); composer.create_sort_constraint(ind); - auto prover = composer.create_prover(); - auto verifier = composer.create_verifier(); - - proof proof = prover.construct_proof(); - bool result = verifier.verify_proof(proof); // instance, prover.reference_string.SRS_T2); - EXPECT_EQ(result, false); + TestFixture::prove_and_verify(composer, /*expected_result=*/false); } } -TEST(ultra_composer, sort_widget_neg) +TYPED_TEST(ultra_composer, sort_widget_neg) { UltraComposer composer = UltraComposer(); fr a = fr::one(); @@ -650,15 +583,11 @@ TEST(ultra_composer, sort_widget_neg) auto c_idx = composer.add_variable(c); auto d_idx = composer.add_variable(d); composer.create_sort_constraint({ a_idx, b_idx, c_idx, d_idx }); - auto prover = composer.create_prover(); - auto verifier = composer.create_verifier(); - - proof proof = prover.construct_proof(); - bool result = verifier.verify_proof(proof); - EXPECT_EQ(result, false); + TestFixture::prove_and_verify(composer, /*expected_result=*/false); } -TEST(ultra_composer, composed_range_constraint) + +TYPED_TEST(ultra_composer, composed_range_constraint) { UltraComposer composer = UltraComposer(); auto c = fr::random_element(); @@ -667,16 +596,11 @@ TEST(ultra_composer, composed_range_constraint) auto a_idx = composer.add_variable(fr(e)); composer.create_add_gate({ a_idx, composer.zero_idx, composer.zero_idx, 1, 0, 0, -fr(e) }); composer.decompose_into_default_range(a_idx, 134); - auto prover = composer.create_prover(); - auto verifier = composer.create_verifier(); - proof proof = prover.construct_proof(); - - bool result = verifier.verify_proof(proof); - EXPECT_EQ(result, true); + TestFixture::prove_and_verify(composer, /*expected_result=*/true); } -TEST(ultra_composer, non_native_field_multiplication) +TYPED_TEST(ultra_composer, non_native_field_multiplication) { UltraComposer composer = UltraComposer(); @@ -728,16 +652,10 @@ TEST(ultra_composer, non_native_field_multiplication) const auto [lo_1_idx, hi_1_idx] = composer.evaluate_non_native_field_multiplication(inputs); composer.range_constrain_two_limbs(lo_1_idx, hi_1_idx, 70, 70); - auto prover = composer.create_prover(); - auto verifier = composer.create_verifier(); - - proof proof = prover.construct_proof(); - - bool result = verifier.verify_proof(proof); - EXPECT_EQ(result, true); + TestFixture::prove_and_verify(composer, /*expected_result=*/true); } -TEST(ultra_composer, rom) +TYPED_TEST(ultra_composer, rom) { UltraComposer composer = UltraComposer(); @@ -774,18 +692,10 @@ TEST(ultra_composer, rom) 0, }); - auto prover = composer.create_prover(); - info("composer.num_gates after constructing prover: ", composer.num_gates); - - auto verifier = composer.create_verifier(); - - proof proof = prover.construct_proof(); - - bool result = verifier.verify_proof(proof); - EXPECT_EQ(result, true); + TestFixture::prove_and_verify(composer, /*expected_result=*/true); } -TEST(ultra_composer, ram) +TYPED_TEST(ultra_composer, ram) { UltraComposer composer = UltraComposer(); @@ -845,15 +755,7 @@ TEST(ultra_composer, ram) }, false); - auto prover = composer.create_prover(); - std::cout << "prover num_gates = " << composer.num_gates << std::endl; - - auto verifier = composer.create_verifier(); - - proof proof = prover.construct_proof(); - - bool result = verifier.verify_proof(proof); - EXPECT_EQ(result, true); + TestFixture::prove_and_verify(composer, /*expected_result=*/true); } -} // namespace proof_system::plonk +} // namespace proof_system::plonk::test_ultra_composer diff --git a/cpp/src/barretenberg/plonk/proof_system/commitment_scheme/kate_commitment_scheme.cpp b/cpp/src/barretenberg/plonk/proof_system/commitment_scheme/kate_commitment_scheme.cpp index 9e1d5a9d02..f084d8ad34 100644 --- a/cpp/src/barretenberg/plonk/proof_system/commitment_scheme/kate_commitment_scheme.cpp +++ b/cpp/src/barretenberg/plonk/proof_system/commitment_scheme/kate_commitment_scheme.cpp @@ -392,4 +392,5 @@ template class KateCommitmentScheme; template class KateCommitmentScheme; template class KateCommitmentScheme; template class KateCommitmentScheme; +template class KateCommitmentScheme; } // namespace proof_system::plonk diff --git a/cpp/src/barretenberg/plonk/proof_system/commitment_scheme/kate_commitment_scheme.hpp b/cpp/src/barretenberg/plonk/proof_system/commitment_scheme/kate_commitment_scheme.hpp index 653340dbdf..741193d0d8 100644 --- a/cpp/src/barretenberg/plonk/proof_system/commitment_scheme/kate_commitment_scheme.hpp +++ b/cpp/src/barretenberg/plonk/proof_system/commitment_scheme/kate_commitment_scheme.hpp @@ -43,5 +43,6 @@ extern template class KateCommitmentScheme; extern template class KateCommitmentScheme; extern template class KateCommitmentScheme; extern template class KateCommitmentScheme; +extern template class KateCommitmentScheme; } // namespace proof_system::plonk \ No newline at end of file diff --git a/cpp/src/barretenberg/plonk/proof_system/constants.hpp b/cpp/src/barretenberg/plonk/proof_system/constants.hpp index b5de8c110a..ac2ee70fec 100644 --- a/cpp/src/barretenberg/plonk/proof_system/constants.hpp +++ b/cpp/src/barretenberg/plonk/proof_system/constants.hpp @@ -1,20 +1,10 @@ #pragma once #include -#include "barretenberg/proof_system/types/composer_type.hpp" -namespace proof_system::plonk { -// 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 +namespace proof_system::plonk { // limb size when simulating a non-native field using bigfield class // (needs to be a universal constant to be used by native verifier) static constexpr uint64_t NUM_LIMB_BITS_IN_FIELD_SIMULATION = 68; - static constexpr uint32_t NUM_QUOTIENT_PARTS = 4; } // namespace proof_system::plonk diff --git a/cpp/src/barretenberg/plonk/proof_system/prover/c_bind.cpp b/cpp/src/barretenberg/plonk/proof_system/prover/c_bind.cpp index 6cd4d4c7af..ef1d1c1392 100644 --- a/cpp/src/barretenberg/plonk/proof_system/prover/c_bind.cpp +++ b/cpp/src/barretenberg/plonk/proof_system/prover/c_bind.cpp @@ -1,7 +1,6 @@ #include "prover.hpp" #include "barretenberg/env/data_store.hpp" #include "barretenberg/env/crs.hpp" -#include "barretenberg/proof_system/types/composer_type.hpp" #define WASM_EXPORT __attribute__((visibility("default"))) @@ -48,8 +47,8 @@ WASM_EXPORT void* test_env_load_prover_crs(size_t num_points) { return env_load_prover_crs(num_points); } -typedef std::conditional_t - WasmProver; + +using WasmProver = plonk::UltraProver; WASM_EXPORT void prover_process_queue(WasmProver* prover) { diff --git a/cpp/src/barretenberg/plonk/proof_system/prover/c_bind_unrolled.cpp b/cpp/src/barretenberg/plonk/proof_system/prover/c_bind_unrolled.cpp deleted file mode 100644 index 66cfdc7496..0000000000 --- a/cpp/src/barretenberg/plonk/proof_system/prover/c_bind_unrolled.cpp +++ /dev/null @@ -1,110 +0,0 @@ -#include "prover.hpp" -#include "barretenberg/proof_system/types/composer_type.hpp" - -#define WASM_EXPORT __attribute__((visibility("default"))) - -using namespace barretenberg; - -extern "C" { - -// TODO(Cody): Removed "unrolled" here when the time comes, if it does. -typedef std::conditional_t - WasmUnrolledProver; - -WASM_EXPORT void unrolled_prover_process_queue(WasmUnrolledProver* prover) -{ - prover->queue.process_queue(); -} - -WASM_EXPORT size_t unrolled_prover_get_circuit_size(WasmUnrolledProver* prover) -{ - return prover->get_circuit_size(); -} - -WASM_EXPORT void unrolled_prover_get_work_queue_item_info(WasmUnrolledProver* prover, uint8_t* result) -{ - auto info = prover->get_queued_work_item_info(); - memcpy(result, &info, sizeof(info)); -} - -WASM_EXPORT fr* unrolled_prover_get_scalar_multiplication_data(WasmUnrolledProver* prover, size_t work_item_number) -{ - return prover->get_scalar_multiplication_data(work_item_number); -} - -WASM_EXPORT size_t unrolled_prover_get_scalar_multiplication_size(WasmUnrolledProver* prover, size_t work_item_number) -{ - return prover->get_scalar_multiplication_size(work_item_number); -} - -WASM_EXPORT void unrolled_prover_put_scalar_multiplication_data(WasmUnrolledProver* prover, - g1::element* result, - const size_t work_item_number) -{ - prover->put_scalar_multiplication_data(*result, work_item_number); -} - -WASM_EXPORT fr* unrolled_prover_get_fft_data(WasmUnrolledProver* prover, fr* shift_factor, size_t work_item_number) -{ - auto data = prover->get_fft_data(work_item_number); - *shift_factor = data.shift_factor; - return data.data; -} - -WASM_EXPORT void unrolled_prover_put_fft_data(WasmUnrolledProver* prover, fr* result, size_t work_item_number) -{ - prover->put_fft_data(result, work_item_number); -} - -WASM_EXPORT fr* unrolled_prover_get_ifft_data(WasmUnrolledProver* prover, size_t work_item_number) -{ - return prover->get_ifft_data(work_item_number); -} - -WASM_EXPORT void unrolled_prover_put_ifft_data(WasmUnrolledProver* prover, fr* result, size_t work_item_number) -{ - prover->put_ifft_data(result, work_item_number); -} - -WASM_EXPORT void unrolled_prover_execute_preamble_round(WasmUnrolledProver* prover) -{ - prover->execute_preamble_round(); -} - -WASM_EXPORT void unrolled_prover_execute_first_round(WasmUnrolledProver* prover) -{ - prover->execute_first_round(); -} - -WASM_EXPORT void unrolled_prover_execute_second_round(WasmUnrolledProver* prover) -{ - prover->execute_second_round(); -} - -WASM_EXPORT void unrolled_prover_execute_third_round(WasmUnrolledProver* prover) -{ - prover->execute_third_round(); -} - -WASM_EXPORT void unrolled_prover_execute_fourth_round(WasmUnrolledProver* prover) -{ - prover->execute_fourth_round(); -} - -WASM_EXPORT void unrolled_prover_execute_fifth_round(WasmUnrolledProver* prover) -{ - prover->execute_fifth_round(); -} - -WASM_EXPORT void unrolled_prover_execute_sixth_round(WasmUnrolledProver* prover) -{ - prover->execute_sixth_round(); -} - -WASM_EXPORT size_t unrolled_prover_export_proof(WasmUnrolledProver* prover, uint8_t** proof_data_buf) -{ - auto& proof_data = prover->export_proof().proof_data; - *proof_data_buf = proof_data.data(); - return proof_data.size(); -} -} diff --git a/cpp/src/barretenberg/plonk/proof_system/prover/prover.cpp b/cpp/src/barretenberg/plonk/proof_system/prover/prover.cpp index 5e91ef8ae4..b7730585e1 100644 --- a/cpp/src/barretenberg/plonk/proof_system/prover/prover.cpp +++ b/cpp/src/barretenberg/plonk/proof_system/prover/prover.cpp @@ -1,5 +1,6 @@ #include "prover.hpp" #include "../public_inputs/public_inputs.hpp" +#include "barretenberg/plonk/proof_system/types/prover_settings.hpp" #include "barretenberg/polynomials/polynomial.hpp" #include #include "barretenberg/ecc/curves/bn254/scalar_multiplication/scalar_multiplication.hpp" @@ -639,5 +640,6 @@ template class ProverBase; template class ProverBase; template class ProverBase; template class ProverBase; +template class ProverBase; } // namespace proof_system::plonk diff --git a/cpp/src/barretenberg/plonk/proof_system/prover/prover.hpp b/cpp/src/barretenberg/plonk/proof_system/prover/prover.hpp index d0476608e2..6b817e5c19 100644 --- a/cpp/src/barretenberg/plonk/proof_system/prover/prover.hpp +++ b/cpp/src/barretenberg/plonk/proof_system/prover/prover.hpp @@ -109,5 +109,6 @@ typedef ProverBase UltraProver; // TODO(Mike): maybe just return // need separate cases for ultra vs ultra_to_standard...??? // TODO(Cody): Make this into an issue? typedef ProverBase UltraToStandardProver; +typedef ProverBase UltraWithKeccakProver; } // namespace proof_system::plonk diff --git a/cpp/src/barretenberg/plonk/proof_system/types/polynomial_manifest.hpp b/cpp/src/barretenberg/plonk/proof_system/types/polynomial_manifest.hpp index 65911eba38..dfdc619606 100644 --- a/cpp/src/barretenberg/plonk/proof_system/types/polynomial_manifest.hpp +++ b/cpp/src/barretenberg/plonk/proof_system/types/polynomial_manifest.hpp @@ -3,7 +3,7 @@ #include #include #include -#include "barretenberg/plonk/proof_system/constants.hpp" +#include "barretenberg/proof_system/types/composer_type.hpp" namespace proof_system::plonk { diff --git a/cpp/src/barretenberg/plonk/proof_system/types/program_settings.hpp b/cpp/src/barretenberg/plonk/proof_system/types/program_settings.hpp index b4b9d5d753..39c98c2784 100644 --- a/cpp/src/barretenberg/plonk/proof_system/types/program_settings.hpp +++ b/cpp/src/barretenberg/plonk/proof_system/types/program_settings.hpp @@ -187,4 +187,20 @@ class ultra_to_standard_verifier_settings : public ultra_verifier_settings { static constexpr transcript::HashType hash_type = transcript::HashType::PedersenBlake3s; }; +// This is neededed for the Noir backend. The ultra verifier contract uses 32-byte challenges generated with Keccak256. +class ultra_with_keccak_verifier_settings : public ultra_verifier_settings { + public: + typedef VerifierPlookupArithmeticWidget + PlookupArithmeticWidget; + typedef VerifierGenPermSortWidget GenPermSortWidget; + typedef VerifierTurboLogicWidget TurboLogicWidget; + typedef VerifierPermutationWidget PermutationWidget; + typedef VerifierPlookupWidget PlookupWidget; + typedef VerifierEllipticWidget EllipticWidget; + typedef VerifierPlookupAuxiliaryWidget + PlookupAuxiliaryWidget; + + static constexpr size_t num_challenge_bytes = 32; + static constexpr transcript::HashType hash_type = transcript::HashType::Keccak256; +}; } // namespace proof_system::plonk diff --git a/cpp/src/barretenberg/plonk/proof_system/types/prover_settings.hpp b/cpp/src/barretenberg/plonk/proof_system/types/prover_settings.hpp index fd439df766..3fa0e35d38 100644 --- a/cpp/src/barretenberg/plonk/proof_system/types/prover_settings.hpp +++ b/cpp/src/barretenberg/plonk/proof_system/types/prover_settings.hpp @@ -57,4 +57,12 @@ class ultra_to_standard_settings : public ultra_settings { static constexpr transcript::HashType hash_type = transcript::HashType::PedersenBlake3s; }; +// Only needed because ultra-to-standard recursion requires us to use a Pedersen hash which is common to both Ultra & +// Standard plonk i.e. the non-ultra version. +class ultra_with_keccak_settings : public ultra_settings { + public: + static constexpr size_t num_challenge_bytes = 32; + static constexpr transcript::HashType hash_type = transcript::HashType::Keccak256; +}; + } // namespace proof_system::plonk diff --git a/cpp/src/barretenberg/plonk/proof_system/verification_key/verification_key.test.cpp b/cpp/src/barretenberg/plonk/proof_system/verification_key/verification_key.test.cpp index 1e2a83998e..1151bf27c0 100644 --- a/cpp/src/barretenberg/plonk/proof_system/verification_key/verification_key.test.cpp +++ b/cpp/src/barretenberg/plonk/proof_system/verification_key/verification_key.test.cpp @@ -17,7 +17,8 @@ namespace proof_system::plonk::test_verification_key { * * @return verification_key_data randomly generated */ -verification_key_data rand_vk_data() { +verification_key_data rand_vk_data() +{ verification_key_data vk_data; vk_data.composer_type = static_cast(proof_system::ComposerType::STANDARD); vk_data.circuit_size = 1024; // not random - must be power of 2 @@ -40,7 +41,7 @@ void expect_compressions_eq(verification_key_data vk0_data, verification_key_dat // 0 hash index EXPECT_EQ(vk0_data.compress_native(0), vk1_data.compress_native(0)); // nonzero hash index - EXPECT_EQ(vk0_data.compress_native(15), vk1_data.compress_native(15)); + // EXPECT_EQ(vk0_data.compress_native(15), vk1_data.compress_native(15)); } /** @@ -52,10 +53,10 @@ void expect_compressions_eq(verification_key_data vk0_data, verification_key_dat void expect_compressions_ne(verification_key_data vk0_data, verification_key_data vk1_data) { EXPECT_NE(vk0_data.compress_native(0), vk1_data.compress_native(0)); - EXPECT_NE(vk0_data.compress_native(15), vk1_data.compress_native(15)); + // EXPECT_NE(vk0_data.compress_native(15), vk1_data.compress_native(15)); // ne hash indices still lead to ne compressions - EXPECT_NE(vk0_data.compress_native(0), vk1_data.compress_native(15)); - EXPECT_NE(vk0_data.compress_native(14), vk1_data.compress_native(15)); + // EXPECT_NE(vk0_data.compress_native(0), vk1_data.compress_native(15)); + // EXPECT_NE(vk0_data.compress_native(14), vk1_data.compress_native(15)); } TEST(verification_key, buffer_serialization) @@ -93,8 +94,8 @@ TEST(verification_key, compression_inequality_index_mismatch) verification_key_data vk0_data = rand_vk_data(); verification_key_data vk1_data = vk0_data; // copy // inquality on hash index mismatch - EXPECT_NE(vk0_data.compress_native(0), vk1_data.compress_native(15)); - EXPECT_NE(vk0_data.compress_native(14), vk1_data.compress_native(15)); + // EXPECT_NE(vk0_data.compress_native(0), vk1_data.compress_native(15)); + // EXPECT_NE(vk0_data.compress_native(14), vk1_data.compress_native(15)); } TEST(verification_key, compression_inequality_composer_type) @@ -105,7 +106,7 @@ TEST(verification_key, compression_inequality_composer_type) expect_compressions_ne(vk0_data, vk1_data); } -TEST(verification_key, compression_inequality_different_circuit_size) \ +TEST(verification_key, compression_inequality_different_circuit_size) { verification_key_data vk0_data = rand_vk_data(); verification_key_data vk1_data = vk0_data; @@ -113,7 +114,7 @@ TEST(verification_key, compression_inequality_different_circuit_size) \ expect_compressions_ne(vk0_data, vk1_data); } -TEST(verification_key, compression_inequality_different_num_public_inputs) \ +TEST(verification_key, compression_inequality_different_num_public_inputs) { verification_key_data vk0_data = rand_vk_data(); verification_key_data vk1_data = vk0_data; @@ -121,7 +122,7 @@ TEST(verification_key, compression_inequality_different_num_public_inputs) \ expect_compressions_ne(vk0_data, vk1_data); } -TEST(verification_key, compression_inequality_different_commitments) \ +TEST(verification_key, compression_inequality_different_commitments) { verification_key_data vk0_data = rand_vk_data(); verification_key_data vk1_data = vk0_data; @@ -129,7 +130,7 @@ TEST(verification_key, compression_inequality_different_commitments) \ expect_compressions_ne(vk0_data, vk1_data); } -TEST(verification_key, compression_inequality_different_num_commitments) \ +TEST(verification_key, compression_inequality_different_num_commitments) { verification_key_data vk0_data = rand_vk_data(); verification_key_data vk1_data = vk0_data; @@ -137,7 +138,7 @@ TEST(verification_key, compression_inequality_different_num_commitments) \ expect_compressions_ne(vk0_data, vk1_data); } -TEST(verification_key, compression_equality_different_contains_recursive_proof) \ +TEST(verification_key, compression_equality_different_contains_recursive_proof) { verification_key_data vk0_data = rand_vk_data(); verification_key_data vk1_data = vk0_data; @@ -146,7 +147,7 @@ TEST(verification_key, compression_equality_different_contains_recursive_proof) expect_compressions_eq(vk0_data, vk1_data); } -TEST(verification_key, compression_equality_different_recursive_proof_public_input_indices) \ +TEST(verification_key, compression_equality_different_recursive_proof_public_input_indices) { verification_key_data vk0_data = rand_vk_data(); verification_key_data vk1_data = vk0_data; diff --git a/cpp/src/barretenberg/plonk/proof_system/verifier/verifier.cpp b/cpp/src/barretenberg/plonk/proof_system/verifier/verifier.cpp index 2a4681df5f..bee400fd36 100644 --- a/cpp/src/barretenberg/plonk/proof_system/verifier/verifier.cpp +++ b/cpp/src/barretenberg/plonk/proof_system/verifier/verifier.cpp @@ -241,5 +241,6 @@ template class VerifierBase; template class VerifierBase; template class VerifierBase; template class VerifierBase; +template class VerifierBase; } // namespace proof_system::plonk diff --git a/cpp/src/barretenberg/plonk/proof_system/verifier/verifier.hpp b/cpp/src/barretenberg/plonk/proof_system/verifier/verifier.hpp index 151117ba10..951cef26d6 100644 --- a/cpp/src/barretenberg/plonk/proof_system/verifier/verifier.hpp +++ b/cpp/src/barretenberg/plonk/proof_system/verifier/verifier.hpp @@ -32,10 +32,11 @@ extern template class VerifierBase; extern template class VerifierBase; extern template class VerifierBase; extern template class VerifierBase; +extern template class VerifierBase; typedef VerifierBase Verifier; typedef VerifierBase TurboVerifier; typedef VerifierBase UltraVerifier; typedef VerifierBase UltraToStandardVerifier; - +typedef VerifierBase UltraWithKeccakVerifier; } // namespace proof_system::plonk diff --git a/cpp/src/barretenberg/proof_system/composer/permutation_helper.hpp b/cpp/src/barretenberg/proof_system/composer/permutation_helper.hpp index 73039533fc..ef70eb9a18 100644 --- a/cpp/src/barretenberg/proof_system/composer/permutation_helper.hpp +++ b/cpp/src/barretenberg/proof_system/composer/permutation_helper.hpp @@ -222,29 +222,30 @@ PermutationMapping compute_permutation_mapping(const CircuitConst } /** - * @brief Compute Sigma polynomials for Honk from a mapping and put into polynomial cache + * @brief Compute Sigma/ID polynomials for Honk from a mapping and put into polynomial cache * - * @details Given a mapping (effectively at table pointing witnesses to other witnesses) compute Sigma polynomials in - * lagrange form and put them into the cache. This version distinguishes betweenr regular elements and public inputs, - * but ignores tags + * @details Given a mapping (effectively at table pointing witnesses to other witnesses) compute Sigma/ID polynomials in + * lagrange form and put them into the cache. This version is suitable for traditional and generalized permutations. * * @tparam program_width The number of wires - * @param sigma_mappings A table with information about permuting each element + * @param permutation_mappings A table with information about permuting each element * @param key Pointer to the proving key */ template -void compute_honk_style_sigma_lagrange_polynomials_from_mapping( - std::array, program_width>& sigma_mappings, plonk::proving_key* key) +void compute_honk_style_permutation_lagrange_polynomials_from_mapping( + std::string label, + std::array, program_width>& permutation_mappings, + plonk::proving_key* key) { const size_t num_gates = key->circuit_size; - std::array sigma; + std::array permutation_poly; // sigma or ID poly for (size_t wire_index = 0; wire_index < program_width; wire_index++) { - sigma[wire_index] = barretenberg::polynomial(num_gates); - auto& current_sigma_polynomial = sigma[wire_index]; + permutation_poly[wire_index] = barretenberg::polynomial(num_gates); + auto& current_permutation_poly = permutation_poly[wire_index]; ITERATE_OVER_DOMAIN_START(key->small_domain) - const auto& current_mapping = sigma_mappings[wire_index][i]; + const auto& current_mapping = permutation_mappings[wire_index][i]; if (current_mapping.is_public_input) { // We intentionally want to break the cycles of the public input variables. // During the witness generation, the left and right wire polynomials at index i contain the i-th public @@ -254,13 +255,15 @@ void compute_honk_style_sigma_lagrange_polynomials_from_mapping( // -(i+1) -> (n+i) // These indices are chosen so they can easily be computed by the verifier. They can expect the running // product to be equal to the "public input delta" that is computed in - current_sigma_polynomial[i] = + current_permutation_poly[i] = -barretenberg::fr(current_mapping.row_index + 1 + num_gates * current_mapping.column_index); + } else if (current_mapping.is_tag) { + // Set evaluations to (arbitrary) values disjoint from non-tag values + current_permutation_poly[i] = num_gates * program_width + current_mapping.row_index; } else { - ASSERT(!current_mapping.is_tag); // For the regular permutation we simply point to the next location by setting the evaluation to its // index - current_sigma_polynomial[i] = + current_permutation_poly[i] = barretenberg::fr(current_mapping.row_index + num_gates * current_mapping.column_index); } ITERATE_OVER_DOMAIN_END; @@ -268,7 +271,7 @@ void compute_honk_style_sigma_lagrange_polynomials_from_mapping( // Save to polynomial cache for (size_t j = 0; j < program_width; j++) { std::string index = std::to_string(j + 1); - key->polynomial_store.put("sigma_" + index + "_lagrange", std::move(sigma[j])); + key->polynomial_store.put(label + "_" + index + "_lagrange", std::move(permutation_poly[j])); } } @@ -447,7 +450,7 @@ void compute_standard_honk_sigma_permutations(CircuitConstructor& circuit_constr // Compute the permutation table specifying which element becomes which auto mapping = compute_permutation_mapping(circuit_constructor, key); // Compute Honk-style sigma polynomial fromt the permutation table - compute_honk_style_sigma_lagrange_polynomials_from_mapping(mapping.sigmas, key); + compute_honk_style_permutation_lagrange_polynomials_from_mapping("sigma", mapping.sigmas, key); } /** @@ -508,4 +511,23 @@ void compute_plonk_generalized_sigma_permutations(const CircuitConstructor& circ compute_monomial_and_coset_fft_polynomials_from_lagrange("id", key); } +/** + * @brief Compute generalized permutation sigmas and ids for ultra plonk + * + * @tparam program_width + * @tparam CircuitConstructor + * @param circuit_constructor + * @param key + * @return std::array, program_width> + */ +template +void compute_honk_generalized_sigma_permutations(const CircuitConstructor& circuit_constructor, plonk::proving_key* key) +{ + auto mapping = compute_permutation_mapping(circuit_constructor, key); + + // Compute Honk-style sigma and ID polynomials from the corresponding mappings + compute_honk_style_permutation_lagrange_polynomials_from_mapping("sigma", mapping.sigmas, key); + compute_honk_style_permutation_lagrange_polynomials_from_mapping("id", mapping.ids, key); +} + } // namespace proof_system diff --git a/cpp/src/barretenberg/stdlib/encryption/schnorr/schnorr.test.cpp b/cpp/src/barretenberg/stdlib/encryption/schnorr/schnorr.test.cpp index aa4457a72e..4a2ab39e8a 100644 --- a/cpp/src/barretenberg/stdlib/encryption/schnorr/schnorr.test.cpp +++ b/cpp/src/barretenberg/stdlib/encryption/schnorr/schnorr.test.cpp @@ -1,15 +1,28 @@ #include "schnorr.hpp" #include "barretenberg/crypto/pedersen_commitment/pedersen.hpp" #include "barretenberg/ecc/curves/grumpkin/grumpkin.hpp" +#include "barretenberg/plonk/composer/ultra_composer.hpp" +#include "barretenberg/stdlib/primitives/field/field.hpp" +#include "barretenberg/stdlib/primitives/bool/bool.hpp" +#include "barretenberg/stdlib/primitives/witness/witness.hpp" +#include "barretenberg/stdlib/primitives/point/point.hpp" #include -#include "barretenberg/stdlib/types/types.hpp" -namespace test_stdlib_schnorr { +namespace proof_system::test_stdlib_schnorr { using namespace barretenberg; -using namespace proof_system::plonk::stdlib::types; +using namespace proof_system::plonk::stdlib; using namespace proof_system::plonk::stdlib::schnorr; +using Composer = plonk::UltraComposer; +using Prover = plonk::UltraProver; +using Verifier = plonk::UltraVerifier; +using bool_ct = bool_t; +using byte_array_ct = byte_array; +using field_ct = field_t; +using point_ct = point; +using witness_ct = witness_t; + auto run_scalar_mul_test = [](grumpkin::fr scalar_mont, bool expect_verify) { Composer composer = Composer(); @@ -204,9 +217,9 @@ TEST(stdlib_schnorr, verify_signature) EXPECT_EQ(first_result, true); point_ct pub_key{ witness_ct(&composer, account.public_key.x), witness_ct(&composer, account.public_key.y) }; - stdlib::schnorr::signature_bits sig = stdlib::schnorr::convert_signature(&composer, signature); + signature_bits sig = convert_signature(&composer, signature); byte_array_ct message(&composer, message_string); - stdlib::schnorr::verify_signature(message, pub_key, sig); + verify_signature(message, pub_key, sig); auto prover = composer.create_prover(); info("composer gates = %zu\n", composer.get_num_gates()); @@ -248,9 +261,9 @@ TEST(stdlib_schnorr, verify_signature_failure) // check stdlib verification with account 2 public key fails point_ct pub_key2_ct{ witness_ct(&composer, account2.public_key.x), witness_ct(&composer, account2.public_key.y) }; - stdlib::schnorr::signature_bits sig = stdlib::schnorr::convert_signature(&composer, signature); + signature_bits sig = convert_signature(&composer, signature); byte_array_ct message(&composer, message_string); - stdlib::schnorr::verify_signature(message, pub_key2_ct, sig); + verify_signature(message, pub_key2_ct, sig); auto prover = composer.create_prover(); @@ -286,14 +299,14 @@ TEST(stdlib_schnorr, signature_verification_result) EXPECT_EQ(first_result, true); point_ct pub_key{ witness_ct(&composer, account.public_key.x), witness_ct(&composer, account.public_key.y) }; - stdlib::schnorr::signature_bits sig = stdlib::schnorr::convert_signature(&composer, signature); + signature_bits sig = convert_signature(&composer, signature); byte_array_ct message(&composer, longer_string); - bool_ct signature_result = stdlib::schnorr::signature_verification_result(message, pub_key, sig); + bool_ct signature_result = signature_verification_result(message, pub_key, sig); EXPECT_EQ(signature_result.witness_bool, true); - plonk::stdlib::types::Prover prover = composer.create_prover(); + Prover prover = composer.create_prover(); info("composer gates = %zu\n", composer.get_num_gates()); - plonk::stdlib::types::Verifier verifier = composer.create_verifier(); + Verifier verifier = composer.create_verifier(); plonk::proof proof = prover.construct_proof(); bool result = verifier.verify_proof(proof); EXPECT_EQ(result, true); @@ -330,17 +343,17 @@ TEST(stdlib_schnorr, signature_verification_result_failure) // check stdlib verification with account 2 public key fails point_ct pub_key2_ct{ witness_ct(&composer, account2.public_key.x), witness_ct(&composer, account2.public_key.y) }; - stdlib::schnorr::signature_bits sig = stdlib::schnorr::convert_signature(&composer, signature); + signature_bits sig = convert_signature(&composer, signature); byte_array_ct message(&composer, message_string); - bool_ct signature_result = stdlib::schnorr::signature_verification_result(message, pub_key2_ct, sig); + bool_ct signature_result = signature_verification_result(message, pub_key2_ct, sig); EXPECT_EQ(signature_result.witness_bool, false); - plonk::stdlib::types::Prover prover = composer.create_prover(); + Prover prover = composer.create_prover(); info("composer gates = %zu\n", composer.get_num_gates()); - plonk::stdlib::types::Verifier verifier = composer.create_verifier(); + Verifier verifier = composer.create_verifier(); plonk::proof proof = prover.construct_proof(); bool verification_result = verifier.verify_proof(proof); EXPECT_EQ(verification_result, true); } -} // namespace test_stdlib_schnorr +} // namespace proof_system::test_stdlib_schnorr diff --git a/cpp/src/barretenberg/stdlib/hash/blake2s/blake2s.test.cpp b/cpp/src/barretenberg/stdlib/hash/blake2s/blake2s.test.cpp index b61cbc305d..61e7ccc293 100644 --- a/cpp/src/barretenberg/stdlib/hash/blake2s/blake2s.test.cpp +++ b/cpp/src/barretenberg/stdlib/hash/blake2s/blake2s.test.cpp @@ -1,21 +1,27 @@ #include "blake2s.hpp" #include "blake2s_plookup.hpp" -#include "barretenberg/crypto/blake2s/blake2s.hpp" #include -#include "barretenberg/stdlib/types/types.hpp" +#include "barretenberg/crypto/blake2s/blake2s.hpp" using namespace barretenberg; using namespace proof_system::plonk; -using namespace proof_system::plonk::stdlib::types; -typedef stdlib::byte_array byte_array; -typedef stdlib::byte_array byte_array_plookup; -typedef stdlib::public_witness_t public_witness_t; -typedef stdlib::public_witness_t public_witness_t_plookup; +using namespace plonk::stdlib; + +using Composer = plonk::UltraComposer; +using Prover = plonk::UltraProver; +using Verifier = plonk::UltraVerifier; + +using field_ct = field_t; +using witness_ct = witness_t; +using byte_array_ct = stdlib::byte_array; +using byte_array_plookup = stdlib::byte_array; +using public_witness_t = stdlib::public_witness_t; +using public_witness_t_plookup = stdlib::public_witness_t; TEST(stdlib_blake2s, test_single_block) { - Composer composer = Composer(); + auto composer = Composer(); std::string input = "abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz01"; std::vector input_v(input.begin(), input.end()); @@ -28,7 +34,7 @@ TEST(stdlib_blake2s, test_single_block) auto prover = composer.create_prover(); - printf("composer gates = %zu\n", composer.get_num_gates()); + info("composer gates = %zu\n", composer.get_num_gates()); auto verifier = composer.create_verifier(); auto proof = prover.construct_proof(); @@ -52,7 +58,7 @@ TEST(stdlib_blake2s, test_single_block_plookup) auto prover = composer.create_prover(); std::cout << "prover gates = " << prover.circuit_size << std::endl; - printf("composer gates = %zu\n", composer.get_num_gates()); + info("composer gates = %zu\n", composer.get_num_gates()); auto verifier = composer.create_verifier(); auto proof = prover.construct_proof(); @@ -63,7 +69,7 @@ TEST(stdlib_blake2s, test_single_block_plookup) TEST(stdlib_blake2s, test_double_block) { - Composer composer = Composer(); + auto composer = Composer(); std::string input = "abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789"; std::vector input_v(input.begin(), input.end()); @@ -76,7 +82,7 @@ TEST(stdlib_blake2s, test_double_block) auto prover = composer.create_prover(); - printf("composer gates = %zu\n", composer.get_num_gates()); + info("composer gates = %zu\n", composer.get_num_gates()); auto verifier = composer.create_verifier(); auto proof = prover.construct_proof(); @@ -100,7 +106,7 @@ TEST(stdlib_blake2s, test_double_block_plookup) auto prover = composer.create_prover(); std::cout << "prover gates = " << prover.circuit_size << std::endl; - printf("composer gates = %zu\n", composer.get_num_gates()); + info("composer gates = %zu\n", composer.get_num_gates()); auto verifier = composer.create_verifier(); auto proof = prover.construct_proof(); diff --git a/cpp/src/barretenberg/stdlib/hash/sha256/sha256.bench.cpp b/cpp/src/barretenberg/stdlib/hash/sha256/sha256.bench.cpp index 1c5947c669..d912505c44 100644 --- a/cpp/src/barretenberg/stdlib/hash/sha256/sha256.bench.cpp +++ b/cpp/src/barretenberg/stdlib/hash/sha256/sha256.bench.cpp @@ -2,10 +2,14 @@ #include #include "barretenberg/ecc/curves/bn254/fr.hpp" #include "barretenberg/plonk/composer/ultra_composer.hpp" -#include "barretenberg/stdlib/types/types.hpp" +#include "barretenberg/plonk/proof_system/prover/prover.hpp" +#include "barretenberg/stdlib/primitives/packed_byte_array/packed_byte_array.hpp" using namespace benchmark; -using namespace proof_system::plonk::stdlib::types; + +using Composer = proof_system::plonk::UltraComposer; +using Prover = proof_system::plonk::UltraProver; +using Verifier = proof_system::plonk::UltraVerifier; constexpr size_t NUM_HASHES = 8; constexpr size_t BYTES_PER_CHUNK = 512; @@ -24,13 +28,13 @@ void generate_test_plonk_circuit(Composer& composer, size_t num_bytes) for (size_t i = 0; i < num_bytes; ++i) { in[i] = get_random_char(); } - packed_byte_array_ct input(&composer, in); - plonk::stdlib::sha256(input); + proof_system::plonk::stdlib::packed_byte_array input(&composer, in); + proof_system::plonk::stdlib::sha256(input); } -stdlib::types::Composer composers[NUM_HASHES]; -stdlib::types::Prover provers[NUM_HASHES]; -stdlib::types::Verifier verifiers[NUM_HASHES]; +Composer composers[NUM_HASHES]; +Prover provers[NUM_HASHES]; +Verifier verifiers[NUM_HASHES]; plonk::proof proofs[NUM_HASHES]; void construct_witnesses_bench(State& state) noexcept diff --git a/cpp/src/barretenberg/stdlib/hash/sha256/sha256.test.cpp b/cpp/src/barretenberg/stdlib/hash/sha256/sha256.test.cpp index 9379e2382a..8f9952da34 100644 --- a/cpp/src/barretenberg/stdlib/hash/sha256/sha256.test.cpp +++ b/cpp/src/barretenberg/stdlib/hash/sha256/sha256.test.cpp @@ -2,8 +2,9 @@ #include "barretenberg/common/test.hpp" #include "barretenberg/crypto/sha256/sha256.hpp" #include "barretenberg/plonk/composer/standard_composer.hpp" +#include "barretenberg/plonk/composer/turbo_composer.hpp" +#include "barretenberg/plonk/composer/ultra_composer.hpp" #include "barretenberg/plonk/composer/plookup_tables/plookup_tables.hpp" -#include "barretenberg/stdlib/types/types.hpp" #include "barretenberg/numeric/random/engine.hpp" #include "barretenberg/numeric/bitop/rotate.hpp" @@ -13,11 +14,18 @@ namespace { auto& engine = numeric::random::get_debug_engine(); } -namespace test_stdlib_sha256 { +namespace proof_system::test_stdlib_sha256 { using namespace barretenberg; -using namespace proof_system::plonk; -using namespace proof_system::plonk::stdlib::types; +using namespace proof_system::plonk::stdlib; + +using Composer = plonk::UltraComposer; +using Prover = plonk::UltraProver; +using Verifier = plonk::UltraVerifier; + +using byte_array_ct = byte_array; +using packed_byte_array_ct = packed_byte_array; +using field_ct = field_t; constexpr uint64_t ror(uint64_t val, uint64_t shift) { @@ -112,8 +120,9 @@ std::array inner_block(std::array& w) TEST(stdlib_sha256, test_duplicate_proving_key) { - plonk::StandardComposer first_composer = StandardComposer(); - stdlib::packed_byte_array input(&first_composer, "An 8 character password? Snow White and the 7 Dwarves.."); + auto first_composer = plonk::StandardComposer(); + plonk::stdlib::packed_byte_array input( + &first_composer, "An 8 character password? Snow White and the 7 Dwarves.."); plonk::stdlib::sha256(input); auto prover = first_composer.create_prover(); auto verifier = first_composer.create_verifier(); @@ -125,8 +134,9 @@ TEST(stdlib_sha256, test_duplicate_proving_key) auto circuit_size = prover.circuit_size; // Test a second time with same keys and different input. - plonk::StandardComposer second_composer = StandardComposer(proving_key, verification_key, circuit_size); - stdlib::packed_byte_array input2(&second_composer, "An 8 character password? Snow White and the 9 Dwarves.."); + auto second_composer = plonk::StandardComposer(proving_key, verification_key, circuit_size); + plonk::stdlib::packed_byte_array input2( + &second_composer, "An 8 character password? Snow White and the 9 Dwarves.."); plonk::stdlib::sha256(input2); auto second_prover = second_composer.create_prover(); auto second_verifier = second_composer.create_verifier(); @@ -138,14 +148,14 @@ TEST(stdlib_sha256, test_duplicate_proving_key) // TEST(stdlib_sha256_plookup, test_round) // { -// plonk::UltraComposer composer = UltraComposer(); +// auto composer = UltraComposer(); // std::array w_inputs; // std::array, 64> w_elements; // for (size_t i = 0; i < 64; ++i) { // w_inputs[i] = engine.get_random_uint32(); -// w_elements[i] = stdlib::witness_t(&composer, +// w_elements[i] = plonk::stdlib::witness_t(&composer, // barretenberg::fr(w_inputs[i])); // } @@ -169,15 +179,15 @@ TEST(stdlib_sha256, test_duplicate_proving_key) TEST(stdlib_sha256, test_plookup_55_bytes) { - typedef stdlib::field_t field_pt; - typedef stdlib::packed_byte_array packed_byte_array_pt; + typedef plonk::stdlib::field_t field_pt; + typedef plonk::stdlib::packed_byte_array packed_byte_array_pt; // 55 bytes is the largest number of bytes that can be hashed in a single block, // accounting for the single padding bit, and the 64 size bits required by the SHA-256 standard. - plonk::UltraComposer composer = UltraComposer(); + auto composer = plonk::UltraComposer(); packed_byte_array_pt input(&composer, "An 8 character password? Snow White and the 7 Dwarves.."); - packed_byte_array_pt output_bits = stdlib::sha256(input); + packed_byte_array_pt output_bits = plonk::stdlib::sha256(input); std::vector output = output_bits.to_unverified_byte_slices(4); @@ -205,10 +215,10 @@ TEST(stdlib_sha256, test_55_bytes) { // 55 bytes is the largest number of bytes that can be hashed in a single block, // accounting for the single padding bit, and the 64 size bits required by the SHA-256 standard. - Composer composer = Composer(); + auto composer = Composer(); packed_byte_array_ct input(&composer, "An 8 character password? Snow White and the 7 Dwarves.."); - packed_byte_array_ct output_bits = stdlib::sha256(input); + packed_byte_array_ct output_bits = plonk::stdlib::sha256(input); std::vector output = output_bits.to_unverified_byte_slices(4); @@ -234,13 +244,13 @@ TEST(stdlib_sha256, test_55_bytes) TEST(stdlib_sha256, test_NIST_vector_one_packed_byte_array) { - typedef stdlib::field_t field_pt; - typedef stdlib::packed_byte_array packed_byte_array_pt; + typedef plonk::stdlib::field_t field_pt; + typedef plonk::stdlib::packed_byte_array packed_byte_array_pt; - plonk::UltraComposer composer = UltraComposer(); + auto composer = plonk::UltraComposer(); packed_byte_array_pt input(&composer, "abc"); - packed_byte_array_pt output_bytes = stdlib::sha256(input); + packed_byte_array_pt output_bytes = plonk::stdlib::sha256(input); std::vector output = output_bytes.to_unverified_byte_slices(4); EXPECT_EQ(uint256_t(output[0].get_value()).data[0], (uint64_t)0xBA7816BFU); EXPECT_EQ(uint256_t(output[1].get_value()).data[0], (uint64_t)0x8F01CFEAU); @@ -265,14 +275,14 @@ TEST(stdlib_sha256, test_NIST_vector_one_packed_byte_array) TEST(stdlib_sha256, test_NIST_vector_one) { - typedef stdlib::field_t field_pt; - typedef stdlib::packed_byte_array packed_byte_array_pt; + typedef plonk::stdlib::field_t field_pt; + typedef plonk::stdlib::packed_byte_array packed_byte_array_pt; - plonk::UltraComposer composer = UltraComposer(); + auto composer = plonk::UltraComposer(); packed_byte_array_pt input(&composer, "abc"); - packed_byte_array_pt output_bits = stdlib::sha256(input); + packed_byte_array_pt output_bits = plonk::stdlib::sha256(input); std::vector output = output_bits.to_unverified_byte_slices(4); @@ -299,11 +309,11 @@ TEST(stdlib_sha256, test_NIST_vector_one) TEST(stdlib_sha256, test_NIST_vector_two) { - Composer composer = Composer(); + auto composer = Composer(); byte_array_ct input(&composer, "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"); - byte_array_ct output_bits = stdlib::sha256(input); + byte_array_ct output_bits = plonk::stdlib::sha256(input); std::vector output = packed_byte_array_ct(output_bits).to_unverified_byte_slices(4); @@ -330,12 +340,12 @@ TEST(stdlib_sha256, test_NIST_vector_two) TEST(stdlib_sha256, test_NIST_vector_three) { - Composer composer = Composer(); + auto composer = Composer(); // one byte, 0xbd byte_array_ct input(&composer, std::vector{ 0xbd }); - byte_array_ct output_bits = stdlib::sha256(input); + byte_array_ct output_bits = plonk::stdlib::sha256(input); std::vector output = packed_byte_array_ct(output_bits).to_unverified_byte_slices(4); @@ -361,12 +371,12 @@ TEST(stdlib_sha256, test_NIST_vector_three) TEST(stdlib_sha256, test_NIST_vector_four) { - Composer composer = Composer(); + auto composer = Composer(); // 4 bytes, 0xc98c8e55 byte_array_ct input(&composer, std::vector{ 0xc9, 0x8c, 0x8e, 0x55 }); - byte_array_ct output_bits = stdlib::sha256(input); + byte_array_ct output_bits = plonk::stdlib::sha256(input); std::vector output = packed_byte_array_ct(output_bits).to_unverified_byte_slices(4); @@ -392,10 +402,10 @@ TEST(stdlib_sha256, test_NIST_vector_four) HEAVY_TEST(stdlib_sha256, test_NIST_vector_five) { - typedef stdlib::field_t field_pt; - typedef stdlib::packed_byte_array packed_byte_array_pt; + typedef plonk::stdlib::field_t field_pt; + typedef plonk::stdlib::packed_byte_array packed_byte_array_pt; - plonk::UltraComposer composer = UltraComposer(); + auto composer = plonk::UltraComposer(); packed_byte_array_pt input( &composer, @@ -410,7 +420,7 @@ HEAVY_TEST(stdlib_sha256, test_NIST_vector_five) "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" "AAAAAAAAAA"); - packed_byte_array_pt output_bits = stdlib::sha256(input); + packed_byte_array_pt output_bits = plonk::stdlib::sha256(input); std::vector output = output_bits.to_unverified_byte_slices(4); @@ -436,7 +446,7 @@ HEAVY_TEST(stdlib_sha256, test_NIST_vector_five) TEST(stdlib_sha256, test_input_len_multiple) { - Composer composer = Composer(); + auto composer = Composer(); std::vector input_sizes = { 1, 7, 15, 16, 30, 32, 55, 64, 90, 128, 512, 700 }; @@ -444,7 +454,7 @@ TEST(stdlib_sha256, test_input_len_multiple) auto input_buf = std::vector(inp, 1); byte_array_ct input(&composer, input_buf); - byte_array_ct output_bits = stdlib::sha256(input); + byte_array_ct output_bits = plonk::stdlib::sha256(input); auto circuit_output = output_bits.get_value(); @@ -456,7 +466,7 @@ TEST(stdlib_sha256, test_input_len_multiple) TEST(stdlib_sha256, test_input_str_len_multiple) { - Composer composer = Composer(); + auto composer = Composer(); std::vector input_strings = { "y", // 1 @@ -488,7 +498,7 @@ TEST(stdlib_sha256, test_input_str_len_multiple) auto input_buf = std::vector(input_str.begin(), input_str.end()); byte_array_ct input(&composer, input_buf); - byte_array_ct output_bits = stdlib::sha256(input); + byte_array_ct output_bits = plonk::stdlib::sha256(input); auto circuit_output = output_bits.get_value(); @@ -498,4 +508,4 @@ TEST(stdlib_sha256, test_input_str_len_multiple) } } -} // namespace test_stdlib_sha256 +} // namespace proof_system::test_stdlib_sha256 diff --git a/cpp/src/barretenberg/stdlib/merkle_tree/hash.hpp b/cpp/src/barretenberg/stdlib/merkle_tree/hash.hpp index 32e6fb2d8d..63b647d7eb 100644 --- a/cpp/src/barretenberg/stdlib/merkle_tree/hash.hpp +++ b/cpp/src/barretenberg/stdlib/merkle_tree/hash.hpp @@ -15,20 +15,12 @@ namespace merkle_tree { inline barretenberg::fr hash_pair_native(barretenberg::fr const& lhs, barretenberg::fr const& rhs) { - if (plonk::SYSTEM_COMPOSER == ComposerType::PLOOKUP) { - return crypto::pedersen_hash::lookup::hash_multiple({ lhs, rhs }); // uses lookup tables - } else { - return crypto::pedersen_hash::hash_multiple({ lhs, rhs }); // uses fixed-base multiplication gate - } + return crypto::pedersen_hash::lookup::hash_multiple({ lhs, rhs }); // uses lookup tables } inline barretenberg::fr hash_multiple_native(std::vector const& inputs) { - if (plonk::SYSTEM_COMPOSER == ComposerType::PLOOKUP) { - return crypto::pedersen_hash::lookup::hash_multiple(inputs); // uses lookup tables - } else { - return crypto::pedersen_hash::hash_multiple(inputs); // uses fixed-base multiplication gate - } + return crypto::pedersen_hash::lookup::hash_multiple(inputs); // uses lookup tables } /** @@ -46,11 +38,7 @@ inline barretenberg::fr compute_tree_root_native(std::vector c while (layer.size() > 1) { std::vector next_layer(layer.size() / 2); for (size_t i = 0; i < next_layer.size(); ++i) { - if (plonk::SYSTEM_COMPOSER == ComposerType::PLOOKUP) { - next_layer[i] = crypto::pedersen_hash::lookup::hash_multiple({ layer[i * 2], layer[i * 2 + 1] }); - } else { - next_layer[i] = crypto::pedersen_hash::hash_multiple({ layer[i * 2], layer[i * 2 + 1] }); - } + next_layer[i] = crypto::pedersen_hash::lookup::hash_multiple({ layer[i * 2], layer[i * 2 + 1] }); } layer = std::move(next_layer); } @@ -69,11 +57,7 @@ inline std::vector compute_tree_native(std::vector 1) { std::vector next_layer(layer.size() / 2); for (size_t i = 0; i < next_layer.size(); ++i) { - if (plonk::SYSTEM_COMPOSER == ComposerType::PLOOKUP) { - next_layer[i] = crypto::pedersen_hash::lookup::hash_multiple({ layer[i * 2], layer[i * 2 + 1] }); - } else { - next_layer[i] = crypto::pedersen_hash::hash_multiple({ layer[i * 2], layer[i * 2 + 1] }); - } + next_layer[i] = crypto::pedersen_hash::lookup::hash_multiple({ layer[i * 2], layer[i * 2 + 1] }); tree.push_back(next_layer[i]); } layer = std::move(next_layer); diff --git a/cpp/src/barretenberg/stdlib/merkle_tree/hash.test.cpp b/cpp/src/barretenberg/stdlib/merkle_tree/hash.test.cpp index da60dfa799..5273c89677 100644 --- a/cpp/src/barretenberg/stdlib/merkle_tree/hash.test.cpp +++ b/cpp/src/barretenberg/stdlib/merkle_tree/hash.test.cpp @@ -1,20 +1,31 @@ #include "hash.hpp" #include "memory_tree.hpp" #include -#include "barretenberg/stdlib/hash/pedersen/pedersen.hpp" + +#include "barretenberg/plonk/composer/ultra_composer.hpp" +#include "barretenberg/stdlib/primitives/field/field.hpp" +#include "barretenberg/stdlib/primitives/witness/witness.hpp" #include "barretenberg/stdlib/merkle_tree/membership.hpp" -#include "barretenberg/stdlib/types/types.hpp" + +namespace proof_system::stdlib_merkle_tree_hash_test { using namespace barretenberg; -using namespace proof_system::plonk::stdlib::types; +using namespace plonk::stdlib; + +using Composer = plonk::UltraComposer; +using Prover = plonk::UltraProver; +using Verifier = plonk::UltraVerifier; + +using field_ct = field_t; +using witness_ct = witness_t; TEST(stdlib_merkle_tree_hash, compress_native_vs_circuit) { fr x = uint256_t(0x5ec473eb273a8011, 0x50160109385471ca, 0x2f3095267e02607d, 0x02586f4a39e69b86); Composer composer = Composer(); witness_ct y = witness_ct(&composer, x); - field_ct z = plonk::stdlib::pedersen_hash::hash_multiple({ y, y }); - auto zz = stdlib::merkle_tree::hash_pair_native(x, x); + field_ct z = pedersen_hash::hash_multiple({ y, y }); + auto zz = merkle_tree::hash_pair_native(x, x); EXPECT_EQ(z.get_value(), zz); } @@ -31,8 +42,8 @@ TEST(stdlib_merkle_tree_hash, compute_tree_root_native_vs_circuit) inputs_ct.push_back(input_ct); } - field_ct z = plonk::stdlib::merkle_tree::compute_tree_root(inputs_ct); - auto zz = plonk::stdlib::merkle_tree::compute_tree_root_native(inputs); + field_ct z = merkle_tree::compute_tree_root(inputs_ct); + auto zz = merkle_tree::compute_tree_root_native(inputs); EXPECT_EQ(z.get_value(), zz); } @@ -40,7 +51,7 @@ TEST(stdlib_merkle_tree_hash, compute_tree_root_native_vs_circuit) TEST(stdlib_merkle_tree_hash, compute_tree_native) { constexpr size_t depth = 2; - stdlib::merkle_tree::MemoryTree mem_tree(depth); + merkle_tree::MemoryTree mem_tree(depth); std::vector leaves; for (size_t i = 0; i < (size_t(1) << depth); i++) { @@ -49,7 +60,7 @@ TEST(stdlib_merkle_tree_hash, compute_tree_native) mem_tree.update_element(i, input); } - std::vector tree_vector = plonk::stdlib::merkle_tree::compute_tree_native(leaves); + std::vector tree_vector = merkle_tree::compute_tree_native(leaves); // Check if the tree vector matches the memory tree hashes for (size_t i = 0; i < tree_vector.size() - 1; i++) { @@ -57,3 +68,4 @@ TEST(stdlib_merkle_tree_hash, compute_tree_native) } EXPECT_EQ(tree_vector.back(), mem_tree.root()); } +} // namespace proof_system::stdlib_merkle_tree_hash_test \ No newline at end of file diff --git a/cpp/src/barretenberg/stdlib/merkle_tree/membership.test.cpp b/cpp/src/barretenberg/stdlib/merkle_tree/membership.test.cpp index 1fb8f216f6..506a363ba2 100644 --- a/cpp/src/barretenberg/stdlib/merkle_tree/membership.test.cpp +++ b/cpp/src/barretenberg/stdlib/merkle_tree/membership.test.cpp @@ -1,23 +1,38 @@ +#include + #include "merkle_tree.hpp" #include "membership.hpp" #include "memory_store.hpp" #include "memory_tree.hpp" -#include -#include "barretenberg/stdlib/types/types.hpp" -using namespace barretenberg; -using namespace proof_system::plonk::stdlib::types; -using namespace proof_system::plonk::stdlib::merkle_tree; +#include "barretenberg/plonk/composer/ultra_composer.hpp" +#include "barretenberg/stdlib/primitives/bool/bool.hpp" +#include "barretenberg/stdlib/primitives/field/field.hpp" +#include "barretenberg/stdlib/primitives/witness/witness.hpp" namespace { auto& engine = numeric::random::get_debug_engine(); } +namespace proof_system::stdlib_merkle_test { + +using namespace barretenberg; +using namespace proof_system::plonk::stdlib::merkle_tree; +using namespace plonk::stdlib; + +using Composer = plonk::UltraComposer; +using Prover = plonk::UltraProver; +using Verifier = plonk::UltraVerifier; + +using bool_ct = bool_t; +using field_ct = field_t; +using witness_ct = witness_t; + TEST(stdlib_merkle_tree, test_check_membership) { MemoryStore store; auto db = MerkleTree(store, 3); - Composer composer = Composer(); + auto composer = Composer(); // Check membership at index 0. auto zero = field_ct(witness_ct(&composer, fr::zero())).decompose_into_bits(); @@ -49,7 +64,7 @@ TEST(stdlib_merkle_tree, test_batch_update_membership) { MemoryStore store; MerkleTree db(store, 4); - Composer composer = Composer(); + auto composer = Composer(); // Fill in an arbitrary value at i = 2. db.update_element(2, fr::random_element()); // Define old state. @@ -78,7 +93,7 @@ TEST(stdlib_merkle_tree, test_assert_check_membership) { MemoryStore store; auto db = MerkleTree(store, 3); - Composer composer = Composer(); + auto composer = Composer(); auto zero = field_ct(witness_ct(&composer, fr::zero())).decompose_into_bits(); field_ct root = witness_ct(&composer, db.root()); @@ -101,7 +116,7 @@ TEST(stdlib_merkle_tree, test_assert_check_membership_fail) MemoryStore store; auto db = MerkleTree(store, 3); - Composer composer = Composer(); + auto composer = Composer(); auto zero = field_ct(witness_ct(&composer, fr::zero())).decompose_into_bits(); field_ct root = witness_ct(&composer, db.root()); @@ -125,7 +140,7 @@ TEST(stdlib_merkle_tree, test_update_members) MemoryStore store; auto db = MerkleTree(store, 3); - Composer composer = Composer(); + auto composer = Composer(); auto zero = field_ct(witness_ct(&composer, fr::zero())).decompose_into_bits(); @@ -154,7 +169,7 @@ TEST(stdlib_merkle_tree, test_update_members) MemoryStore store; auto db = MerkleTree(store, 3); - Composer composer = Composer(); + auto composer = Composer(); auto zero = field_ct(witness_ct(&composer, fr::zero())).decompose_into_bits(); @@ -189,7 +204,7 @@ TEST(stdlib_merkle_tree, test_tree) MerkleTree db(store, depth); MemoryTree mem_tree(depth); - Composer composer = Composer(); + auto composer = Composer(); auto zero_field = field_ct(witness_ct(&composer, fr::zero())); auto values = std::vector(num, zero_field); @@ -214,7 +229,7 @@ TEST(stdlib_merkle_tree, test_update_memberships) MemoryStore store; MerkleTree tree(store, depth); - Composer composer = Composer(); + auto composer = Composer(); constexpr size_t filled = (1UL << depth) / 2; std::vector filled_values; @@ -273,3 +288,4 @@ TEST(stdlib_merkle_tree, test_update_memberships) bool result = verifier.verify_proof(proof); EXPECT_EQ(result, true); } +} // namespace proof_system::stdlib_merkle_test \ No newline at end of file diff --git a/cpp/src/barretenberg/stdlib/merkle_tree/merkle_tree.test.cpp b/cpp/src/barretenberg/stdlib/merkle_tree/merkle_tree.test.cpp index a4b3607be9..ed42634b57 100644 --- a/cpp/src/barretenberg/stdlib/merkle_tree/merkle_tree.test.cpp +++ b/cpp/src/barretenberg/stdlib/merkle_tree/merkle_tree.test.cpp @@ -4,11 +4,18 @@ #include "barretenberg/common/streams.hpp" #include "barretenberg/common/test.hpp" #include "barretenberg/numeric/random/engine.hpp" -#include "barretenberg/stdlib/types/types.hpp" -using namespace barretenberg; +namespace proof_system::test_stdlib_merkle_tree { + +using namespace plonk::stdlib; using namespace proof_system::plonk::stdlib::merkle_tree; +using Composer = plonk::UltraComposer; +using Prover = plonk::UltraProver; +using Verifier = plonk::UltraVerifier; + +using field_ct = field_t; +using witness_ct = witness_t; namespace { auto& engine = numeric::random::get_debug_engine(); auto& random_engine = numeric::random::get_engine(); @@ -128,3 +135,4 @@ TEST(stdlib_merkle_tree, test_get_hash_path_layers) EXPECT_NE(before[2], after[2]); } } +} // namespace proof_system::test_stdlib_merkle_tree \ No newline at end of file diff --git a/cpp/src/barretenberg/stdlib/primitives/biggroup/biggroup.test.cpp b/cpp/src/barretenberg/stdlib/primitives/biggroup/biggroup.test.cpp index 32eb7d5b80..e3b6576e9f 100644 --- a/cpp/src/barretenberg/stdlib/primitives/biggroup/biggroup.test.cpp +++ b/cpp/src/barretenberg/stdlib/primitives/biggroup/biggroup.test.cpp @@ -19,7 +19,6 @@ namespace { auto& engine = numeric::random::get_debug_engine(); } -// using namespace barretenberg; using namespace proof_system::plonk; // One can only define a TYPED_TEST with a single template paramter. diff --git a/cpp/src/barretenberg/stdlib/primitives/byte_array/byte_array.test.cpp b/cpp/src/barretenberg/stdlib/primitives/byte_array/byte_array.test.cpp index 81fcd8139a..3e8d1b2430 100644 --- a/cpp/src/barretenberg/stdlib/primitives/byte_array/byte_array.test.cpp +++ b/cpp/src/barretenberg/stdlib/primitives/byte_array/byte_array.test.cpp @@ -1,7 +1,8 @@ #include "byte_array.hpp" #include -#include "../../types/types.hpp" #include "barretenberg/plonk/composer/standard_composer.hpp" +#include "barretenberg/plonk/composer/turbo_composer.hpp" +#include "barretenberg/plonk/composer/ultra_composer.hpp" #include "barretenberg/honk/composer/standard_honk_composer.hpp" #include "barretenberg/stdlib/primitives/bool/bool.hpp" #include "barretenberg/stdlib/primitives/field/field.hpp" diff --git a/cpp/src/barretenberg/stdlib/primitives/group/group.test.cpp b/cpp/src/barretenberg/stdlib/primitives/group/group.test.cpp index 1a71438a2e..07df473361 100644 --- a/cpp/src/barretenberg/stdlib/primitives/group/group.test.cpp +++ b/cpp/src/barretenberg/stdlib/primitives/group/group.test.cpp @@ -1,8 +1,13 @@ -#include "../../types/types.hpp" #include +#include "barretenberg/plonk/composer/standard_composer.hpp" +#include "barretenberg/plonk/composer/turbo_composer.hpp" +#include "barretenberg/plonk/composer/ultra_composer.hpp" #include "barretenberg/honk/composer/standard_honk_composer.hpp" #include "barretenberg/stdlib/primitives/witness/witness.hpp" +#include "barretenberg/stdlib/primitives/field/field.hpp" +#include "barretenberg/stdlib/primitives/group/group.hpp" #include "barretenberg/numeric/random/engine.hpp" + #define STDLIB_TYPE_ALIASES \ using Composer = TypeParam; \ using witness_ct = stdlib::witness_t; \ diff --git a/cpp/src/barretenberg/stdlib/primitives/packed_byte_array/packed_byte_array.test.cpp b/cpp/src/barretenberg/stdlib/primitives/packed_byte_array/packed_byte_array.test.cpp index 340d02a543..c194d0fead 100644 --- a/cpp/src/barretenberg/stdlib/primitives/packed_byte_array/packed_byte_array.test.cpp +++ b/cpp/src/barretenberg/stdlib/primitives/packed_byte_array/packed_byte_array.test.cpp @@ -1,8 +1,13 @@ -#include "packed_byte_array.hpp" -#include "../../types/types.hpp" -#include "../byte_array/byte_array.hpp" #include + +#include "packed_byte_array.hpp" +#include "barretenberg/stdlib/primitives/byte_array/byte_array.hpp" #include "barretenberg/numeric/random/engine.hpp" +#include "barretenberg/plonk/composer/standard_composer.hpp" +#include "barretenberg/plonk/composer/turbo_composer.hpp" +#include "barretenberg/plonk/composer/ultra_composer.hpp" +#include "barretenberg/honk/composer/standard_honk_composer.hpp" + #pragma GCC diagnostic ignored "-Wunused-local-typedefs" namespace test_stdlib_packed_byte_array { diff --git a/cpp/src/barretenberg/stdlib/primitives/safe_uint/safe_uint.test.cpp b/cpp/src/barretenberg/stdlib/primitives/safe_uint/safe_uint.test.cpp index 45657fb45f..3a315b1bd7 100644 --- a/cpp/src/barretenberg/stdlib/primitives/safe_uint/safe_uint.test.cpp +++ b/cpp/src/barretenberg/stdlib/primitives/safe_uint/safe_uint.test.cpp @@ -6,8 +6,10 @@ #include "safe_uint.hpp" #include "barretenberg/numeric/random/engine.hpp" #include "../byte_array/byte_array.hpp" +#include "barretenberg/plonk/composer/standard_composer.hpp" +#include "barretenberg/plonk/composer/turbo_composer.hpp" +#include "barretenberg/plonk/composer/ultra_composer.hpp" #include "barretenberg/honk/composer/standard_honk_composer.hpp" -#include "barretenberg/stdlib/types/types.hpp" #pragma GCC diagnostic ignored "-Wunused-local-typedefs" diff --git a/cpp/src/barretenberg/stdlib/recursion/verification_key/verification_key.test.cpp b/cpp/src/barretenberg/stdlib/recursion/verification_key/verification_key.test.cpp index 5be5ce87c9..b9cb01e079 100644 --- a/cpp/src/barretenberg/stdlib/recursion/verification_key/verification_key.test.cpp +++ b/cpp/src/barretenberg/stdlib/recursion/verification_key/verification_key.test.cpp @@ -63,10 +63,10 @@ TYPED_TEST(VerificationKeyFixture, vk_data_vs_recursion_compress_native) auto recurs_vk = RecursVk::from_witness(&composer, native_vk); EXPECT_EQ(vk_data.compress_native(0), RecursVk::compress_native(native_vk, 0)); - EXPECT_EQ(vk_data.compress_native(15), RecursVk::compress_native(native_vk, 15)); + // EXPECT_EQ(vk_data.compress_native(15), RecursVk::compress_native(native_vk, 15)); // ne hash indeces still lead to ne compressions - EXPECT_NE(vk_data.compress_native(0), RecursVk::compress_native(native_vk, 15)); - EXPECT_NE(vk_data.compress_native(14), RecursVk::compress_native(native_vk, 15)); + // EXPECT_NE(vk_data.compress_native(0), RecursVk::compress_native(native_vk, 15)); + // EXPECT_NE(vk_data.compress_native(14), RecursVk::compress_native(native_vk, 15)); } TYPED_TEST(VerificationKeyFixture, compress_vs_compress_native) @@ -83,8 +83,8 @@ TYPED_TEST(VerificationKeyFixture, compress_vs_compress_native) auto recurs_vk = RecursVk::from_witness(&composer, native_vk); EXPECT_EQ(recurs_vk->compress(0).get_value(), RecursVk::compress_native(native_vk, 0)); - EXPECT_EQ(recurs_vk->compress(15).get_value(), RecursVk::compress_native(native_vk, 15)); + // EXPECT_EQ(recurs_vk->compress(15).get_value(), RecursVk::compress_native(native_vk, 15)); // ne hash indeces still lead to ne compressions - EXPECT_NE(recurs_vk->compress(0).get_value(), RecursVk::compress_native(native_vk, 15)); - EXPECT_NE(recurs_vk->compress(14).get_value(), RecursVk::compress_native(native_vk, 15)); + // EXPECT_NE(recurs_vk->compress(0).get_value(), RecursVk::compress_native(native_vk, 15)); + // EXPECT_NE(recurs_vk->compress(14).get_value(), RecursVk::compress_native(native_vk, 15)); } diff --git a/cpp/src/barretenberg/stdlib/types/types.hpp b/cpp/src/barretenberg/stdlib/types/types.hpp deleted file mode 100644 index 706b160800..0000000000 --- a/cpp/src/barretenberg/stdlib/types/types.hpp +++ /dev/null @@ -1,100 +0,0 @@ -#pragma once -#include "barretenberg/plonk/proof_system/constants.hpp" -#include "barretenberg/plonk/composer/standard_composer.hpp" -#include "barretenberg/plonk/composer/turbo_composer.hpp" -#include "barretenberg/plonk/composer/ultra_composer.hpp" -#include "barretenberg/stdlib/primitives/bigfield/bigfield.hpp" -#include "barretenberg/stdlib/primitives/biggroup/biggroup.hpp" -#include "barretenberg/stdlib/primitives/bit_array/bit_array.hpp" -#include "barretenberg/stdlib/primitives/bool/bool.hpp" -#include "barretenberg/stdlib/primitives/packed_byte_array/packed_byte_array.hpp" -#include "barretenberg/stdlib/primitives/byte_array/byte_array.hpp" -#include "barretenberg/stdlib/primitives/uint/uint.hpp" -#include "barretenberg/stdlib/primitives/witness/witness.hpp" -#include "barretenberg/stdlib/primitives/bigfield/bigfield.hpp" -#include "barretenberg/stdlib/primitives/biggroup/biggroup.hpp" -#include "barretenberg/stdlib/commitment/pedersen/pedersen.hpp" -#include "barretenberg/stdlib/commitment/pedersen/pedersen_plookup.hpp" -#include "barretenberg/stdlib/merkle_tree/hash_path.hpp" -#include "barretenberg/stdlib/encryption/schnorr/schnorr.hpp" -#include "barretenberg/stdlib/primitives/curves/bn254.hpp" -#include "barretenberg/stdlib/primitives/curves/secp256k1.hpp" -#include "barretenberg/stdlib/primitives/memory/rom_table.hpp" -#include "barretenberg/stdlib/recursion/verifier/program_settings.hpp" -#include "barretenberg/stdlib/primitives/memory/ram_table.hpp" -#include "barretenberg/stdlib/primitives/memory/rom_table.hpp" -#include "barretenberg/stdlib/primitives/memory/dynamic_array.hpp" - -namespace proof_system::plonk::stdlib::types { - -using namespace proof_system::plonk; -static constexpr size_t SYSTEM_COMPOSER = proof_system::plonk::SYSTEM_COMPOSER; - -typedef std::conditional_t< - SYSTEM_COMPOSER == proof_system::STANDARD, - plonk::StandardComposer, - std::conditional_t> - Composer; - -typedef std::conditional_t< - SYSTEM_COMPOSER == proof_system::STANDARD, - plonk::Prover, - std::conditional_t> - Prover; - -typedef std::conditional_t< - SYSTEM_COMPOSER == proof_system::STANDARD, - plonk::Verifier, - std::conditional_t> - Verifier; - -typedef std::conditional_t< - SYSTEM_COMPOSER == proof_system::STANDARD, - plonk::Prover, - std::conditional_t> - Prover; - -typedef std::conditional_t< - SYSTEM_COMPOSER == proof_system::STANDARD, - plonk::Verifier, - std::conditional_t> - Verifier; - -typedef stdlib::witness_t witness_ct; -typedef stdlib::public_witness_t public_witness_ct; -typedef stdlib::bool_t bool_ct; -typedef stdlib::byte_array byte_array_ct; -typedef stdlib::packed_byte_array packed_byte_array_ct; -typedef stdlib::field_t field_ct; -typedef stdlib::safe_uint_t suint_ct; -typedef stdlib::uint8 uint8_ct; -typedef stdlib::uint16 uint16_ct; -typedef stdlib::uint32 uint32_ct; -typedef stdlib::uint64 uint64_ct; -typedef stdlib::bit_array bit_array_ct; -typedef stdlib::bigfield fq_ct; -typedef stdlib::element biggroup_ct; -typedef stdlib::point point_ct; -typedef stdlib::pedersen_commitment pedersen_commitment; -typedef stdlib::group group_ct; -typedef stdlib::bn254 bn254; -typedef stdlib::secp256k1 secp256k1_ct; - -namespace merkle_tree { -using namespace stdlib::merkle_tree; -typedef stdlib::merkle_tree::hash_path hash_path; -} // namespace merkle_tree - -namespace schnorr { -typedef stdlib::schnorr::signature_bits signature_bits; -} // namespace schnorr - -// Ultra-composer specific types -typedef stdlib::rom_table rom_table_ct; - -typedef std::conditional_t, - recursion::recursive_ultra_verifier_settings> - recursive_inner_verifier_settings; - -} // namespace proof_system::plonk::stdlib::types From 21f1eea28bc40ca455e7a02254d1bdf56a5d5e2a Mon Sep 17 00:00:00 2001 From: Maxim Vezenov Date: Wed, 19 Apr 2023 18:16:56 -0400 Subject: [PATCH 2/9] add dsl files to commit --- .../dsl/acir_format/ecdsa_secp256k1.test.cpp | 4 ++-- .../dsl/acir_format/recursion_constraint.cpp | 20 ++++++++--------- .../dsl/acir_format/recursion_constraint.hpp | 22 +++++++++---------- .../acir_format/recursion_constraint.test.cpp | 12 +++++----- .../dsl/acir_proofs/acir_proofs.test.cpp | 6 ++--- 5 files changed, 32 insertions(+), 32 deletions(-) diff --git a/cpp/src/barretenberg/dsl/acir_format/ecdsa_secp256k1.test.cpp b/cpp/src/barretenberg/dsl/acir_format/ecdsa_secp256k1.test.cpp index 57f9af0a1c..875fc4d589 100644 --- a/cpp/src/barretenberg/dsl/acir_format/ecdsa_secp256k1.test.cpp +++ b/cpp/src/barretenberg/dsl/acir_format/ecdsa_secp256k1.test.cpp @@ -7,8 +7,8 @@ #include #include -using namespace proof_system::plonk::stdlib::types; -using curve = stdlib::secp256k1; +using namespace proof_system::plonk; +using curve = stdlib::secp256k1; size_t generate_ecdsa_constraint(acir_format::EcdsaSecp256k1Constraint& ecdsa_constraint, std::vector& witness_values) diff --git a/cpp/src/barretenberg/dsl/acir_format/recursion_constraint.cpp b/cpp/src/barretenberg/dsl/acir_format/recursion_constraint.cpp index 895c27f99c..0c2a1d0614 100644 --- a/cpp/src/barretenberg/dsl/acir_format/recursion_constraint.cpp +++ b/cpp/src/barretenberg/dsl/acir_format/recursion_constraint.cpp @@ -4,14 +4,14 @@ #include "barretenberg/stdlib/recursion/verifier/verifier.hpp" #include "barretenberg/transcript/transcript_wrappers.hpp" -using namespace proof_system::plonk::stdlib::types; +namespace acir_format { -using verification_key_ct = proof_system::plonk::stdlib::recursion::verification_key; -using aggregation_state_ct = proof_system::plonk::stdlib::recursion::aggregation_state; -using noir_recursive_settings = proof_system::plonk::stdlib::recursion::recursive_ultra_verifier_settings; -using Transcript_ct = proof_system::plonk::stdlib::recursion::Transcript; +using namespace proof_system::plonk; -namespace acir_format { +// using verification_key_ct = proof_system::plonk::stdlib::recursion::verification_key; +// using aggregation_state_ct = proof_system::plonk::stdlib::recursion::aggregation_state; +// using noir_recursive_settings = proof_system::plonk::stdlib::recursion::recursive_ultra_verifier_settings; +// using Transcript_ct = proof_system::plonk::stdlib::recursion::Transcript; void generate_dummy_proof() {} /** @@ -135,9 +135,9 @@ void create_recursion_constraints(Composer& composer, const RecursionConstraint& } } -template void create_recursion_constraints(plonk::stdlib::types::Composer&, const RecursionConstraint&); -template void create_recursion_constraints(plonk::stdlib::types::Composer&, const RecursionConstraint&); -template void create_recursion_constraints(plonk::stdlib::types::Composer&, const RecursionConstraint&); -template void create_recursion_constraints(plonk::stdlib::types::Composer&, const RecursionConstraint&); +template void create_recursion_constraints(Composer&, const RecursionConstraint&); +template void create_recursion_constraints(Composer&, const RecursionConstraint&); +template void create_recursion_constraints(Composer&, const RecursionConstraint&); +template void create_recursion_constraints(Composer&, const RecursionConstraint&); } // namespace acir_format diff --git a/cpp/src/barretenberg/dsl/acir_format/recursion_constraint.hpp b/cpp/src/barretenberg/dsl/acir_format/recursion_constraint.hpp index 45abd037c2..cf760878bd 100644 --- a/cpp/src/barretenberg/dsl/acir_format/recursion_constraint.hpp +++ b/cpp/src/barretenberg/dsl/acir_format/recursion_constraint.hpp @@ -1,10 +1,13 @@ #pragma once #include -#include "barretenberg/stdlib/types/types.hpp" -#include "barretenberg/plonk/proof_system//verification_key/verification_key.hpp" +// #include "barretenberg/stdlib/types/types.hpp" +#include "barretenberg/dsl/types.hpp" +#include "barretenberg/plonk/proof_system/verification_key/verification_key.hpp" namespace acir_format { +static constexpr size_t AGGREGATION_OBJECT_SIZE = 16; // 16 field elements + /** * @brief RecursionConstraint struct contains information required to recursively verify a proof! * @@ -29,7 +32,6 @@ namespace acir_format { * NOT contain */ struct RecursionConstraint { - static constexpr size_t AGGREGATION_OBJECT_SIZE = 16; // 16 field elements std::vector key; std::vector proof; uint32_t public_input; @@ -41,16 +43,12 @@ struct RecursionConstraint { }; template -void create_recursion_constraints(plonk::stdlib::types::Composer& composer, const RecursionConstraint& input); +void create_recursion_constraints(Composer& composer, const RecursionConstraint& input); -extern template void create_recursion_constraints(plonk::stdlib::types::Composer&, - const RecursionConstraint&); -extern template void create_recursion_constraints(plonk::stdlib::types::Composer&, - const RecursionConstraint&); -extern template void create_recursion_constraints(plonk::stdlib::types::Composer&, - const RecursionConstraint&); -extern template void create_recursion_constraints(plonk::stdlib::types::Composer&, - const RecursionConstraint&); +extern template void create_recursion_constraints(Composer&, const RecursionConstraint&); +extern template void create_recursion_constraints(Composer&, const RecursionConstraint&); +extern template void create_recursion_constraints(Composer&, const RecursionConstraint&); +extern template void create_recursion_constraints(Composer&, const RecursionConstraint&); template inline void read(B& buf, RecursionConstraint& constraint) { diff --git a/cpp/src/barretenberg/dsl/acir_format/recursion_constraint.test.cpp b/cpp/src/barretenberg/dsl/acir_format/recursion_constraint.test.cpp index cfd564f7f6..782334f7d8 100644 --- a/cpp/src/barretenberg/dsl/acir_format/recursion_constraint.test.cpp +++ b/cpp/src/barretenberg/dsl/acir_format/recursion_constraint.test.cpp @@ -6,9 +6,9 @@ #include #include -using namespace proof_system::plonk::stdlib::types; +using namespace proof_system::plonk; -Composer create_inner_circuit() +acir_format::Composer create_inner_circuit() { /** * constraints produced by Noir program: @@ -120,15 +120,17 @@ TEST(RecursionConstraint, TestRecursionConstraint) // std::vector keybuf; // write(keybuf, *(inner_verifier.key)); - std::array output_vars; + std::array output_vars; for (size_t i = 0; i < 16; ++i) { // variable idx 1 = public input // variable idx 2-18 = output_vars output_vars[i] = (static_cast(i + 3)); } - transcript::StandardTranscript transcript( - inner_proof.proof_data, Composer::create_manifest(1), transcript::HashType::PlookupPedersenBlake3s, 16); + transcript::StandardTranscript transcript(inner_proof.proof_data, + acir_format::Composer::create_manifest(1), + transcript::HashType::PlookupPedersenBlake3s, + 16); const std::vector proof_witnesses = transcript.export_transcript_in_recursion_format(); const std::vector key_witnesses = inner_verifier.key->export_key_in_recursion_format(); diff --git a/cpp/src/barretenberg/dsl/acir_proofs/acir_proofs.test.cpp b/cpp/src/barretenberg/dsl/acir_proofs/acir_proofs.test.cpp index de011de21e..bd4e8fc91a 100644 --- a/cpp/src/barretenberg/dsl/acir_proofs/acir_proofs.test.cpp +++ b/cpp/src/barretenberg/dsl/acir_proofs/acir_proofs.test.cpp @@ -4,7 +4,7 @@ #include #include -using namespace proof_system::plonk::stdlib::types; +using namespace proof_system::plonk; void create_inner_circuit(acir_format::acir_format& constraint_system, std::vector& witness) { @@ -216,8 +216,8 @@ TEST(AcirProofs, TestSerializationWithRecursion) key_indices.emplace_back(static_cast(i + 19 + proof_size)); } - std::array output_vars; - for (size_t i = 0; i < acir_format::RecursionConstraint::AGGREGATION_OBJECT_SIZE; ++i) { + std::array output_vars; + for (size_t i = 0; i < acir_format::AGGREGATION_OBJECT_SIZE; ++i) { // variable idx 1 = public input // variable idx 2-18 = output_vars output_vars[i] = (static_cast(i + 3)); From 70c64ece3b74ac8d26bb38776df4ab3875c895f1 Mon Sep 17 00:00:00 2001 From: Maxim Vezenov Date: Wed, 19 Apr 2023 22:14:37 -0400 Subject: [PATCH 3/9] namespace stuff and debugging --- cpp/src/barretenberg/dsl/acir_format/recursion_constraint.hpp | 3 +-- .../dsl/acir_format/recursion_constraint.test.cpp | 2 +- cpp/src/barretenberg/dsl/acir_proofs/acir_proofs.test.cpp | 4 ++-- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/cpp/src/barretenberg/dsl/acir_format/recursion_constraint.hpp b/cpp/src/barretenberg/dsl/acir_format/recursion_constraint.hpp index cf760878bd..cfc0116349 100644 --- a/cpp/src/barretenberg/dsl/acir_format/recursion_constraint.hpp +++ b/cpp/src/barretenberg/dsl/acir_format/recursion_constraint.hpp @@ -6,8 +6,6 @@ namespace acir_format { -static constexpr size_t AGGREGATION_OBJECT_SIZE = 16; // 16 field elements - /** * @brief RecursionConstraint struct contains information required to recursively verify a proof! * @@ -32,6 +30,7 @@ static constexpr size_t AGGREGATION_OBJECT_SIZE = 16; // 16 field elements * NOT contain */ struct RecursionConstraint { + static constexpr size_t AGGREGATION_OBJECT_SIZE = 16; // 16 field elements std::vector key; std::vector proof; uint32_t public_input; diff --git a/cpp/src/barretenberg/dsl/acir_format/recursion_constraint.test.cpp b/cpp/src/barretenberg/dsl/acir_format/recursion_constraint.test.cpp index 782334f7d8..2b23dcfa07 100644 --- a/cpp/src/barretenberg/dsl/acir_format/recursion_constraint.test.cpp +++ b/cpp/src/barretenberg/dsl/acir_format/recursion_constraint.test.cpp @@ -120,7 +120,7 @@ TEST(RecursionConstraint, TestRecursionConstraint) // std::vector keybuf; // write(keybuf, *(inner_verifier.key)); - std::array output_vars; + std::array output_vars; for (size_t i = 0; i < 16; ++i) { // variable idx 1 = public input // variable idx 2-18 = output_vars diff --git a/cpp/src/barretenberg/dsl/acir_proofs/acir_proofs.test.cpp b/cpp/src/barretenberg/dsl/acir_proofs/acir_proofs.test.cpp index bd4e8fc91a..c3b5fef075 100644 --- a/cpp/src/barretenberg/dsl/acir_proofs/acir_proofs.test.cpp +++ b/cpp/src/barretenberg/dsl/acir_proofs/acir_proofs.test.cpp @@ -216,8 +216,8 @@ TEST(AcirProofs, TestSerializationWithRecursion) key_indices.emplace_back(static_cast(i + 19 + proof_size)); } - std::array output_vars; - for (size_t i = 0; i < acir_format::AGGREGATION_OBJECT_SIZE; ++i) { + std::array output_vars; + for (size_t i = 0; i < acir_format::RecursionConstraint::AGGREGATION_OBJECT_SIZE; ++i) { // variable idx 1 = public input // variable idx 2-18 = output_vars output_vars[i] = (static_cast(i + 3)); From 47bc3e3939d3489f2dca962f9d1695da050963e1 Mon Sep 17 00:00:00 2001 From: Maxim Vezenov Date: Wed, 19 Apr 2023 22:21:41 -0400 Subject: [PATCH 4/9] c bind functions --- cpp/src/barretenberg/dsl/acir_proofs/c_bind.cpp | 16 ++++++++++++++++ cpp/src/barretenberg/dsl/acir_proofs/c_bind.hpp | 7 +++++++ 2 files changed, 23 insertions(+) diff --git a/cpp/src/barretenberg/dsl/acir_proofs/c_bind.cpp b/cpp/src/barretenberg/dsl/acir_proofs/c_bind.cpp index 4051aada3a..41d6d0375f 100644 --- a/cpp/src/barretenberg/dsl/acir_proofs/c_bind.cpp +++ b/cpp/src/barretenberg/dsl/acir_proofs/c_bind.cpp @@ -35,6 +35,22 @@ WASM_EXPORT size_t acir_proofs_init_verification_key(void* pippenger, return acir_proofs::init_verification_key(pippenger, g2x, pk_buf, vk_buf); } +WASM_EXPORT size_t acir_serialize_verification_key_into_field_elements(uint8_t const* g2x, + uint8_t const* vk_buf, + uint8_t** serialized_vk_buf, + uint8_t** serialized_vk_hash_buf) +{ + return acir_proofs::serialize_verification_key_into_field_elements( + g2x, vk_buf, serialized_vk_buf, serialized_vk_hash_buf); +} +WASM_EXPORT size_t acir_serialize_proof_into_field_elements(uint8_t const* proof_data_buf, + uint8_t** serialized_proof_data_buf, + size_t proof_data_length) +{ + return acir_proofs::serialize_proof_into_field_elements( + proof_data_buf, serialized_proof_data_buf, proof_data_length); +} + WASM_EXPORT size_t acir_proofs_new_proof(void* pippenger, uint8_t const* g2x, uint8_t const* pk_buf, diff --git a/cpp/src/barretenberg/dsl/acir_proofs/c_bind.hpp b/cpp/src/barretenberg/dsl/acir_proofs/c_bind.hpp index a628c928cb..0deda83166 100644 --- a/cpp/src/barretenberg/dsl/acir_proofs/c_bind.hpp +++ b/cpp/src/barretenberg/dsl/acir_proofs/c_bind.hpp @@ -14,6 +14,13 @@ 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_serialize_verification_key_into_field_elements(uint8_t const* g2x, + uint8_t const* vk_buf, + uint8_t** serialized_vk_buf, + uint8_t** serialized_vk_hash_buf); +WASM_EXPORT size_t acir_serialize_proof_into_field_elements(uint8_t const* proof_data_buf, + uint8_t** serialized_proof_data_buf, + size_t proof_data_length); WASM_EXPORT size_t acir_proofs_new_proof(void* pippenger, uint8_t const* g2x, uint8_t const* pk_buf, From 773f117a35db7db95e3037dbf9b8e4896efa2aba Mon Sep 17 00:00:00 2001 From: Maxim Vezenov Date: Wed, 19 Apr 2023 23:00:03 -0400 Subject: [PATCH 5/9] constraint test and comment removal --- .../dsl/acir_format/acir_format.test.cpp | 40 +++++++++++++++++++ .../dsl/acir_format/recursion_constraint.cpp | 5 --- .../dsl/acir_format/recursion_constraint.hpp | 6 ++- .../acir_format/recursion_constraint.test.cpp | 3 +- .../dsl/acir_proofs/acir_proofs.test.cpp | 3 +- 5 files changed, 48 insertions(+), 9 deletions(-) diff --git a/cpp/src/barretenberg/dsl/acir_format/acir_format.test.cpp b/cpp/src/barretenberg/dsl/acir_format/acir_format.test.cpp index 586a82b03d..5c17c353c1 100644 --- a/cpp/src/barretenberg/dsl/acir_format/acir_format.test.cpp +++ b/cpp/src/barretenberg/dsl/acir_format/acir_format.test.cpp @@ -4,6 +4,46 @@ #include #include "barretenberg/common/streams.hpp" +TEST(acir_format, test_a_single_constraint_no_pub_inputs) +{ + + poly_triple constraint{ + .a = 1, + .b = 2, + .c = 3, + .q_m = 0, + .q_l = 1, + .q_r = 1, + .q_o = -1, + .q_c = 0, + }; + + acir_format::acir_format constraint_system{ + .varnum = 4, + .public_inputs = {}, + .fixed_base_scalar_mul_constraints = {}, + .logic_constraints = {}, + .range_constraints = {}, + .schnorr_constraints = {}, + .ecdsa_constraints = {}, + .sha256_constraints = {}, + .blake2s_constraints = {}, + .hash_to_field_constraints = {}, + .pedersen_constraints = {}, + .merkle_membership_constraints = {}, + .constraints = { constraint }, + }; + + auto composer = acir_format::create_circuit_with_witness(constraint_system, { 0, 0, 1 }); + + auto prover = composer.create_ultra_with_keccak_prover(); + auto proof = prover.construct_proof(); + + auto verifier = composer.create_ultra_with_keccak_verifier(); + + EXPECT_EQ(verifier.verify_proof(proof), false); +} + TEST(acir_format, test_logic_gate_from_noir_circuit) { /** diff --git a/cpp/src/barretenberg/dsl/acir_format/recursion_constraint.cpp b/cpp/src/barretenberg/dsl/acir_format/recursion_constraint.cpp index 0c2a1d0614..6b68663c92 100644 --- a/cpp/src/barretenberg/dsl/acir_format/recursion_constraint.cpp +++ b/cpp/src/barretenberg/dsl/acir_format/recursion_constraint.cpp @@ -8,11 +8,6 @@ namespace acir_format { using namespace proof_system::plonk; -// using verification_key_ct = proof_system::plonk::stdlib::recursion::verification_key; -// using aggregation_state_ct = proof_system::plonk::stdlib::recursion::aggregation_state; -// using noir_recursive_settings = proof_system::plonk::stdlib::recursion::recursive_ultra_verifier_settings; -// using Transcript_ct = proof_system::plonk::stdlib::recursion::Transcript; - void generate_dummy_proof() {} /** * @brief Add constraints required to recursively verify an UltraPlonk proof diff --git a/cpp/src/barretenberg/dsl/acir_format/recursion_constraint.hpp b/cpp/src/barretenberg/dsl/acir_format/recursion_constraint.hpp index cfc0116349..362bfd88a6 100644 --- a/cpp/src/barretenberg/dsl/acir_format/recursion_constraint.hpp +++ b/cpp/src/barretenberg/dsl/acir_format/recursion_constraint.hpp @@ -35,8 +35,10 @@ struct RecursionConstraint { std::vector proof; uint32_t public_input; uint32_t key_hash; - std::array input_aggregation_object; - std::array output_aggregation_object; + // std::array input_aggregation_object; + // std::array output_aggregation_object; + std::vector input_aggregation_object; + std::vector output_aggregation_object; friend bool operator==(RecursionConstraint const& lhs, RecursionConstraint const& rhs) = default; }; diff --git a/cpp/src/barretenberg/dsl/acir_format/recursion_constraint.test.cpp b/cpp/src/barretenberg/dsl/acir_format/recursion_constraint.test.cpp index 2b23dcfa07..6e9de47382 100644 --- a/cpp/src/barretenberg/dsl/acir_format/recursion_constraint.test.cpp +++ b/cpp/src/barretenberg/dsl/acir_format/recursion_constraint.test.cpp @@ -120,7 +120,8 @@ TEST(RecursionConstraint, TestRecursionConstraint) // std::vector keybuf; // write(keybuf, *(inner_verifier.key)); - std::array output_vars; + // std::array output_vars; + std::vector output_vars(acir_format::RecursionConstraint::AGGREGATION_OBJECT_SIZE); for (size_t i = 0; i < 16; ++i) { // variable idx 1 = public input // variable idx 2-18 = output_vars diff --git a/cpp/src/barretenberg/dsl/acir_proofs/acir_proofs.test.cpp b/cpp/src/barretenberg/dsl/acir_proofs/acir_proofs.test.cpp index c3b5fef075..888011e697 100644 --- a/cpp/src/barretenberg/dsl/acir_proofs/acir_proofs.test.cpp +++ b/cpp/src/barretenberg/dsl/acir_proofs/acir_proofs.test.cpp @@ -216,7 +216,8 @@ TEST(AcirProofs, TestSerializationWithRecursion) key_indices.emplace_back(static_cast(i + 19 + proof_size)); } - std::array output_vars; + // std::array output_vars; + std::vector output_vars(acir_format::RecursionConstraint::AGGREGATION_OBJECT_SIZE); for (size_t i = 0; i < acir_format::RecursionConstraint::AGGREGATION_OBJECT_SIZE; ++i) { // variable idx 1 = public input // variable idx 2-18 = output_vars From 3ecbc6f60b430e5981fe165e99c79f3793221a54 Mon Sep 17 00:00:00 2001 From: Maxim Vezenov Date: Wed, 19 Apr 2023 23:10:11 -0400 Subject: [PATCH 6/9] revert some changes to RecursionConstraint while debugging serialization issues --- .../barretenberg/dsl/acir_format/recursion_constraint.hpp | 6 ++---- .../dsl/acir_format/recursion_constraint.test.cpp | 3 +-- cpp/src/barretenberg/dsl/acir_proofs/acir_proofs.test.cpp | 3 +-- 3 files changed, 4 insertions(+), 8 deletions(-) diff --git a/cpp/src/barretenberg/dsl/acir_format/recursion_constraint.hpp b/cpp/src/barretenberg/dsl/acir_format/recursion_constraint.hpp index 362bfd88a6..cfc0116349 100644 --- a/cpp/src/barretenberg/dsl/acir_format/recursion_constraint.hpp +++ b/cpp/src/barretenberg/dsl/acir_format/recursion_constraint.hpp @@ -35,10 +35,8 @@ struct RecursionConstraint { std::vector proof; uint32_t public_input; uint32_t key_hash; - // std::array input_aggregation_object; - // std::array output_aggregation_object; - std::vector input_aggregation_object; - std::vector output_aggregation_object; + std::array input_aggregation_object; + std::array output_aggregation_object; friend bool operator==(RecursionConstraint const& lhs, RecursionConstraint const& rhs) = default; }; diff --git a/cpp/src/barretenberg/dsl/acir_format/recursion_constraint.test.cpp b/cpp/src/barretenberg/dsl/acir_format/recursion_constraint.test.cpp index 6e9de47382..2b23dcfa07 100644 --- a/cpp/src/barretenberg/dsl/acir_format/recursion_constraint.test.cpp +++ b/cpp/src/barretenberg/dsl/acir_format/recursion_constraint.test.cpp @@ -120,8 +120,7 @@ TEST(RecursionConstraint, TestRecursionConstraint) // std::vector keybuf; // write(keybuf, *(inner_verifier.key)); - // std::array output_vars; - std::vector output_vars(acir_format::RecursionConstraint::AGGREGATION_OBJECT_SIZE); + std::array output_vars; for (size_t i = 0; i < 16; ++i) { // variable idx 1 = public input // variable idx 2-18 = output_vars diff --git a/cpp/src/barretenberg/dsl/acir_proofs/acir_proofs.test.cpp b/cpp/src/barretenberg/dsl/acir_proofs/acir_proofs.test.cpp index 888011e697..c3b5fef075 100644 --- a/cpp/src/barretenberg/dsl/acir_proofs/acir_proofs.test.cpp +++ b/cpp/src/barretenberg/dsl/acir_proofs/acir_proofs.test.cpp @@ -216,8 +216,7 @@ TEST(AcirProofs, TestSerializationWithRecursion) key_indices.emplace_back(static_cast(i + 19 + proof_size)); } - // std::array output_vars; - std::vector output_vars(acir_format::RecursionConstraint::AGGREGATION_OBJECT_SIZE); + std::array output_vars; for (size_t i = 0; i < acir_format::RecursionConstraint::AGGREGATION_OBJECT_SIZE; ++i) { // variable idx 1 = public input // variable idx 2-18 = output_vars From 92181ecfc70a96ea1f204c5716567cc73aa4ddc6 Mon Sep 17 00:00:00 2001 From: Maxim Vezenov Date: Fri, 21 Apr 2023 10:41:13 -0400 Subject: [PATCH 7/9] dispaly error when trying to use create_circuit_with_witness --- .../barretenberg/dsl/acir_proofs/acir_proofs.cpp | 1 + .../dsl/acir_proofs/acir_proofs.test.cpp | 14 ++++++++++++++ 2 files changed, 15 insertions(+) diff --git a/cpp/src/barretenberg/dsl/acir_proofs/acir_proofs.cpp b/cpp/src/barretenberg/dsl/acir_proofs/acir_proofs.cpp index 8041ac8966..3b624afbcb 100644 --- a/cpp/src/barretenberg/dsl/acir_proofs/acir_proofs.cpp +++ b/cpp/src/barretenberg/dsl/acir_proofs/acir_proofs.cpp @@ -173,6 +173,7 @@ size_t serialize_verification_key_into_field_elements(uint8_t const* g2x, auto vk_hash_raw_buf = (uint8_t*)malloc(32); memcpy(vk_hash_raw_buf, (void*)&output[output.size() - 1], 32); *serialized_vk_hash_buf = vk_hash_raw_buf; + // *serialized_vk_hash_buf = &raw_buf[(output.size() - 1) * 32]; return output_size_bytes; } diff --git a/cpp/src/barretenberg/dsl/acir_proofs/acir_proofs.test.cpp b/cpp/src/barretenberg/dsl/acir_proofs/acir_proofs.test.cpp index c3b5fef075..7695ddff50 100644 --- a/cpp/src/barretenberg/dsl/acir_proofs/acir_proofs.test.cpp +++ b/cpp/src/barretenberg/dsl/acir_proofs/acir_proofs.test.cpp @@ -201,6 +201,13 @@ TEST(AcirProofs, TestSerializationWithRecursion) memcpy(proof_witnesses.data(), (void*)proof_data_fields, proof_fields_size); memcpy(&key_witnesses[0], (void*)vk_fields, vk_fields_size); memcpy(&vk_hash_value, (void*)vk_hash_buf, 32); + // for (size_t i = 0; i < proof_fields_size / 32; i++) { + // proof_witnesses[i] = barretenberg::fr::serialize_from_buffer(&proof_data_fields[i * 32]); + // } + // for (size_t i = 0; i < vk_fields_size / 32; i++) { + // key_witnesses[i] = barretenberg::fr::serialize_from_buffer(&vk_fields[i * 32]); + // } + // vk_hash_value = barretenberg::fr::serialize_from_buffer(vk_hash_buf); std::vector proof_indices; @@ -271,6 +278,13 @@ TEST(AcirProofs, TestSerializationWithRecursion) .constraints = { vk_equality_constraint }, }; + // auto composer = acir_format::create_circuit_with_witness(constraint_system, witness); + // auto prover = composer.create_prover(); + + // auto proof = prover.construct_proof(); + // auto verifier = composer.create_verifier(); + // EXPECT_EQ(verifier.verify_proof(proof), true); + std::vector witness_buf; std::vector constraint_system_buf; write(constraint_system_buf, constraint_system); From 255d61b3ecda408e00bf0445adfa55c571b1966b Mon Sep 17 00:00:00 2001 From: Maxim Vezenov Date: Mon, 24 Apr 2023 19:32:01 -0400 Subject: [PATCH 8/9] is_recursive flag as part of new_proof and verify_proof, new RecursiveProver type in dsl, and serialization changes for recursion acir_proofs methods --- .../dsl/acir_format/acir_format.cpp | 1 + .../dsl/acir_format/recursion_constraint.cpp | 2 - .../dsl/acir_proofs/acir_proofs.cpp | 88 ++++++++++--------- .../dsl/acir_proofs/acir_proofs.hpp | 11 ++- .../dsl/acir_proofs/acir_proofs.test.cpp | 79 ++++++++++++----- .../barretenberg/dsl/acir_proofs/c_bind.cpp | 16 ++-- .../barretenberg/dsl/acir_proofs/c_bind.hpp | 11 ++- cpp/src/barretenberg/dsl/types.hpp | 2 + 8 files changed, 132 insertions(+), 78 deletions(-) diff --git a/cpp/src/barretenberg/dsl/acir_format/acir_format.cpp b/cpp/src/barretenberg/dsl/acir_format/acir_format.cpp index d760ad10d9..e4f524869c 100644 --- a/cpp/src/barretenberg/dsl/acir_format/acir_format.cpp +++ b/cpp/src/barretenberg/dsl/acir_format/acir_format.cpp @@ -112,6 +112,7 @@ Composer create_circuit(const acir_format& constraint_system, composer.add_variable(0); } } + // Add arithmetic gates for (const auto& constraint : constraint_system.constraints) { composer.create_poly_gate(constraint); diff --git a/cpp/src/barretenberg/dsl/acir_format/recursion_constraint.cpp b/cpp/src/barretenberg/dsl/acir_format/recursion_constraint.cpp index 6b68663c92..441b47c2d8 100644 --- a/cpp/src/barretenberg/dsl/acir_format/recursion_constraint.cpp +++ b/cpp/src/barretenberg/dsl/acir_format/recursion_constraint.cpp @@ -56,8 +56,6 @@ void create_recursion_constraints(Composer& composer, const RecursionConstraint& composer.assert_equal(composer.add_variable(dummy_field), key_field_idx); } } - // The env_crs should be ok, we use this when generating the constraint system in dsl - auto env_crs = std::make_unique(); // Construct an in-circuit representation of the verification key. // For now, the v-key is a circuit constant and is fixed for the circuit. diff --git a/cpp/src/barretenberg/dsl/acir_proofs/acir_proofs.cpp b/cpp/src/barretenberg/dsl/acir_proofs/acir_proofs.cpp index 3b624afbcb..4580792808 100644 --- a/cpp/src/barretenberg/dsl/acir_proofs/acir_proofs.cpp +++ b/cpp/src/barretenberg/dsl/acir_proofs/acir_proofs.cpp @@ -115,18 +115,11 @@ size_t serialize_proof_into_field_elements(uint8_t const* proof_data_buf, // NOTE: this output buffer will always have a fixed size! Maybe just precompute? const size_t output_size_bytes = output.size() * sizeof(barretenberg::fr); auto raw_buf = (uint8_t*)malloc(output_size_bytes); - // NOTE: currently we dump the fr values into memory in Mongtomery form - // This is so we don't have to re-convert into Montgomery form when we read these back in. - // I think this makes it easier to handle the data in barretenberg-sys / aztec-backend. - // If this is not the case, the commented out serialize code will convert out of Montgomery form before writing to - // the buffer - // for (size_t i = 0; i < output.size(); ++i) { - // barretenberg::fr::serialize_to_buffer(output[i], &raw_buf[i * 32]); - // } - // for (size_t i = 0; i < output.size(); ++i) { - // barretenberg::fr::serialize_to_buffer(output[i], &raw_buf[i * 32]); - // } - memcpy(raw_buf, (void*)output.data(), output_size_bytes); + + // The serialization code below will convert out of Montgomery form before writing to the buffer + for (size_t i = 0; i < output.size(); ++i) { + barretenberg::fr::serialize_to_buffer(output[i], &raw_buf[i * 32]); + } *serialized_proof_data_buf = raw_buf; return output_size_bytes; @@ -156,24 +149,17 @@ size_t serialize_verification_key_into_field_elements(uint8_t const* g2x, // Cut off 32 bytes as last element is the verification key hash which is not part of the key :o const size_t output_size_bytes = output.size() * sizeof(barretenberg::fr) - 32; auto raw_buf = (uint8_t*)malloc(output_size_bytes); - // NOTE: currently we dump the fr values into memory in Mongtomery form - // This is so we don't have to re-convert into Montgomery form when we read these back in. - // I think this makes it easier to handle the data in barretenberg-sys / aztec-backend. - // If this is not the case, the commented out serialize code will convert out of Montgomery form before writing to - // the buffer - // for (size_t i = 0; i < output.size(); ++i) { - // barretenberg::fr::serialize_to_buffer(output[i], &raw_buf[i * 32]); - // } - - // copy all but the vkey hash into raw_buf - memcpy(raw_buf, (void*)output.data(), output_size_bytes); + + // The serialization code below will convert out of Montgomery form before writing to the buffer + for (size_t i = 0; i < output.size(); ++i) { + barretenberg::fr::serialize_to_buffer(output[i], &raw_buf[i * 32]); + } + + // copy the vkey into serialized_vk_buf *serialized_vk_buf = raw_buf; - // copy the vkey hash into vk_hash_raw_buf - auto vk_hash_raw_buf = (uint8_t*)malloc(32); - memcpy(vk_hash_raw_buf, (void*)&output[output.size() - 1], 32); - *serialized_vk_hash_buf = vk_hash_raw_buf; - // *serialized_vk_hash_buf = &raw_buf[(output.size() - 1) * 32]; + // copy the vkey hash into serialized_vk_hash_buf + *serialized_vk_hash_buf = &raw_buf[(output.size() - 1) * 32]; return output_size_bytes; } @@ -183,7 +169,8 @@ size_t new_proof(void* pippenger, uint8_t const* pk_buf, uint8_t const* constraint_system_buf, uint8_t const* witness_buf, - uint8_t** proof_data_buf) + uint8_t** proof_data_buf, + bool is_recursive) { auto constraint_system = from_buffer(constraint_system_buf); @@ -198,22 +185,33 @@ size_t new_proof(void* pippenger, reinterpret_cast(pippenger), g2x); proving_key->reference_string = crs_factory->get_prover_crs(proving_key->circuit_size); - // auto env_crs = std::make_unique(); + // TODO: either need a context flag for recursive proofs or a new_recursive_proof method that uses regular + // UltraProver acir_format::Composer composer(proving_key, nullptr); create_circuit_with_witness(composer, constraint_system, witness); - auto prover = composer.create_ultra_with_keccak_prover(); - - auto heapProver = new acir_format::Prover(std::move(prover)); - auto& proof_data = heapProver->construct_proof().proof_data; - *proof_data_buf = proof_data.data(); - - return proof_data.size(); + if (is_recursive) { + auto prover = composer.create_prover(); + auto heapProver = new acir_format::RecursiveProver(std::move(prover)); + auto& proof_data = heapProver->construct_proof().proof_data; + *proof_data_buf = proof_data.data(); + return proof_data.size(); + } else { + auto prover = composer.create_ultra_with_keccak_prover(); + auto heapProver = new acir_format::Prover(std::move(prover)); + auto& proof_data = heapProver->construct_proof().proof_data; + *proof_data_buf = proof_data.data(); + return proof_data.size(); + } } -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 verify_proof(uint8_t const* g2x, + uint8_t const* vk_buf, + uint8_t const* constraint_system_buf, + uint8_t* proof, + uint32_t length, + bool is_recursive) { bool verified = false; @@ -230,9 +228,17 @@ bool verify_proof( create_circuit(composer, constraint_system); plonk::proof pp = { std::vector(proof, proof + length) }; - auto verifier = composer.create_ultra_with_keccak_verifier(); + // for inner circuit use new prover and verifier method for outer circuit use the normal prover and verifier + // TODO: either need a context flag for recursive verify or a new_recursive_verify_proof method that uses + // regular UltraVerifier + if (is_recursive) { + auto verifier = composer.create_verifier(); + verified = verifier.verify_proof(pp); + } else { + auto verifier = composer.create_ultra_with_keccak_verifier(); + verified = verifier.verify_proof(pp); + } - verified = verifier.verify_proof(pp); #ifndef __wasm__ } catch (const std::exception& e) { verified = false; diff --git a/cpp/src/barretenberg/dsl/acir_proofs/acir_proofs.hpp b/cpp/src/barretenberg/dsl/acir_proofs/acir_proofs.hpp index ced41993c3..95556f11a7 100644 --- a/cpp/src/barretenberg/dsl/acir_proofs/acir_proofs.hpp +++ b/cpp/src/barretenberg/dsl/acir_proofs/acir_proofs.hpp @@ -20,8 +20,13 @@ size_t new_proof(void* pippenger, 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); + uint8_t** proof_data_buf, + bool is_recursive); +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 is_recursive); } // namespace acir_proofs diff --git a/cpp/src/barretenberg/dsl/acir_proofs/acir_proofs.test.cpp b/cpp/src/barretenberg/dsl/acir_proofs/acir_proofs.test.cpp index 7695ddff50..885c0c1ec3 100644 --- a/cpp/src/barretenberg/dsl/acir_proofs/acir_proofs.test.cpp +++ b/cpp/src/barretenberg/dsl/acir_proofs/acir_proofs.test.cpp @@ -131,10 +131,10 @@ TEST(AcirProofs, TestSerialization) uint8_t* proof_data_buf = nullptr; size_t proof_length = acir_proofs::new_proof( - pippenger_ptr, &g2x_buffer[0], pk_buf, &constraint_system_buf[0], &witness_buf[0], &proof_data_buf); + pippenger_ptr, &g2x_buffer[0], pk_buf, &constraint_system_buf[0], &witness_buf[0], &proof_data_buf, true); bool verified = acir_proofs::verify_proof( - &g2x_buffer[0], vk_buf, &constraint_system_buf[0], proof_data_buf, static_cast(proof_length)); + &g2x_buffer[0], vk_buf, &constraint_system_buf[0], proof_data_buf, static_cast(proof_length), true); EXPECT_EQ(verified, true); } @@ -178,14 +178,18 @@ TEST(AcirProofs, TestSerializationWithRecursion) uint8_t* proof_data_buf = nullptr; size_t proof_length = acir_proofs::new_proof( - pippenger_ptr, &g2x_buffer[0], pk_buf, &constraint_system_buf[0], &witness_buf[0], &proof_data_buf); + pippenger_ptr, &g2x_buffer[0], pk_buf, &constraint_system_buf[0], &witness_buf[0], &proof_data_buf, true); proof_fields_size = acir_proofs::serialize_proof_into_field_elements(proof_data_buf, &proof_data_fields, proof_length); vk_fields_size = acir_proofs::serialize_verification_key_into_field_elements( &g2x_buffer[0], vk_buf, &vk_fields, &vk_hash_buf); - bool verified = acir_proofs::verify_proof( - &g2x_buffer[0], vk_buf, &constraint_system_buf[0], proof_data_buf, static_cast(proof_length)); + bool verified = acir_proofs::verify_proof(&g2x_buffer[0], + vk_buf, + &constraint_system_buf[0], + proof_data_buf, + static_cast(proof_length), + true); EXPECT_EQ(verified, true); delete pippenger_ptr_base; @@ -198,27 +202,28 @@ TEST(AcirProofs, TestSerializationWithRecursion) fr vk_hash_value; std::vector proof_witnesses(proof_fields_size / 32); std::vector key_witnesses(vk_fields_size / 32); - memcpy(proof_witnesses.data(), (void*)proof_data_fields, proof_fields_size); - memcpy(&key_witnesses[0], (void*)vk_fields, vk_fields_size); - memcpy(&vk_hash_value, (void*)vk_hash_buf, 32); - // for (size_t i = 0; i < proof_fields_size / 32; i++) { - // proof_witnesses[i] = barretenberg::fr::serialize_from_buffer(&proof_data_fields[i * 32]); - // } - // for (size_t i = 0; i < vk_fields_size / 32; i++) { - // key_witnesses[i] = barretenberg::fr::serialize_from_buffer(&vk_fields[i * 32]); - // } - // vk_hash_value = barretenberg::fr::serialize_from_buffer(vk_hash_buf); + // memcpy(proof_witnesses.data(), (void*)proof_data_fields, proof_fields_size); + // memcpy(&key_witnesses[0], (void*)vk_fields, vk_fields_size); + // memcpy(&vk_hash_value, (void*)vk_hash_buf, 32); + for (size_t i = 0; i < proof_fields_size / 32; i++) { + proof_witnesses[i] = barretenberg::fr::serialize_from_buffer(&proof_data_fields[i * 32]); + } + for (size_t i = 0; i < vk_fields_size / 32; i++) { + key_witnesses[i] = barretenberg::fr::serialize_from_buffer(&vk_fields[i * 32]); + } + vk_hash_value = barretenberg::fr::serialize_from_buffer(vk_hash_buf); std::vector proof_indices; const size_t proof_size = proof_witnesses.size(); - + std::cout << "proof_size: " << proof_size << std::endl; for (size_t i = 0; i < proof_size; ++i) { proof_indices.emplace_back(static_cast(i + 19)); } std::vector key_indices; const size_t key_size = key_witnesses.size(); + std::cout << "key_size: " << key_size << std::endl; for (size_t i = 0; i < key_size; ++i) { key_indices.emplace_back(static_cast(i + 19 + proof_size)); } @@ -250,6 +255,8 @@ TEST(AcirProofs, TestSerializationWithRecursion) .q_c = -vk_hash_value, }; + std::cout << "vk_hash_value: " << vk_hash_value << std::endl; + std::vector witness; for (size_t i = 0; i < 18; ++i) { witness.emplace_back(0); @@ -261,6 +268,8 @@ TEST(AcirProofs, TestSerializationWithRecursion) witness.emplace_back(wit); } + std::cout << "witness.size(): " << witness.size() << std::endl; + acir_format::acir_format constraint_system{ .varnum = static_cast(witness.size() + 1), .public_inputs = { 1 }, @@ -278,11 +287,11 @@ TEST(AcirProofs, TestSerializationWithRecursion) .constraints = { vk_equality_constraint }, }; + // std::cout << "about to create_circuit_with_witness" << std::endl; // auto composer = acir_format::create_circuit_with_witness(constraint_system, witness); - // auto prover = composer.create_prover(); - + // auto prover = composer.create_ultra_with_keccak_prover(); // auto proof = prover.construct_proof(); - // auto verifier = composer.create_verifier(); + // auto verifier = composer.create_ultra_with_keccak_verifier(); // EXPECT_EQ(verifier.verify_proof(proof), true); std::vector witness_buf; @@ -291,8 +300,10 @@ TEST(AcirProofs, TestSerializationWithRecursion) write(witness_buf, witness); uint8_t const* pk_buf = nullptr; acir_proofs::init_proving_key(&constraint_system_buf[0], &pk_buf); + std::cout << "past init_proving_key" << std::endl; uint32_t total_circuit_size = acir_proofs::get_total_circuit_size(&constraint_system_buf[0]); + std::cout << "got total_circuit_size" << std::endl; uint32_t pow2_size = 1 << (numeric::get_msb(total_circuit_size) + 1); auto env_crs = std::make_unique(); auto verifier_crs = env_crs->get_verifier_crs(); @@ -307,21 +318,41 @@ TEST(AcirProofs, TestSerializationWithRecursion) uint8_t const* vk_buf = nullptr; acir_proofs::init_verification_key(pippenger_ptr, &g2x_buffer[0], pk_buf, &vk_buf); + std::cout << "past init_verification_key" << std::endl; uint8_t* proof_data_buf = nullptr; size_t proof_length = acir_proofs::new_proof( - pippenger_ptr, &g2x_buffer[0], pk_buf, &constraint_system_buf[0], &witness_buf[0], &proof_data_buf); - - bool verified = acir_proofs::verify_proof( - &g2x_buffer[0], vk_buf, &constraint_system_buf[0], proof_data_buf, static_cast(proof_length)); + pippenger_ptr, &g2x_buffer[0], pk_buf, &constraint_system_buf[0], &witness_buf[0], &proof_data_buf, false); + std::cout << "past new_proof" << std::endl; + + bool verified = acir_proofs::verify_proof(&g2x_buffer[0], + vk_buf, + &constraint_system_buf[0], + proof_data_buf, + static_cast(proof_length), + false); EXPECT_EQ(verified, true); + std::cout << "past verify_proof" << std::endl; delete pippenger_ptr_base; + std::cout << "past delete pippenger_ptr_base" << std::endl; + free((void*)vk_buf); + std::cout << "past free vk_buf" << std::endl; + free((void*)pk_buf); + std::cout << "past free pk_buf" << std::endl; + free((void*)proof_data_buf); + std::cout << "past free proof_data_buf" << std::endl; + free((void*)proof_data_fields); + std::cout << "past free proof_data_fields" << std::endl; + free((void*)vk_fields); - free((void*)vk_hash_buf); + std::cout << "past free vk_fields" << std::endl; + + // free((void*)vk_hash_buf); + std::cout << "past free vk_hash_buf" << std::endl; } } diff --git a/cpp/src/barretenberg/dsl/acir_proofs/c_bind.cpp b/cpp/src/barretenberg/dsl/acir_proofs/c_bind.cpp index 41d6d0375f..ac26be3fd7 100644 --- a/cpp/src/barretenberg/dsl/acir_proofs/c_bind.cpp +++ b/cpp/src/barretenberg/dsl/acir_proofs/c_bind.cpp @@ -56,14 +56,20 @@ WASM_EXPORT size_t acir_proofs_new_proof(void* pippenger, uint8_t const* pk_buf, uint8_t const* constraint_system_buf, uint8_t const* witness_buf, - uint8_t** proof_data_buf) + uint8_t** proof_data_buf, + bool is_recursive) { - return acir_proofs::new_proof(pippenger, g2x, pk_buf, constraint_system_buf, witness_buf, proof_data_buf); + return acir_proofs::new_proof( + pippenger, g2x, pk_buf, constraint_system_buf, witness_buf, proof_data_buf, is_recursive); } -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) +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, + bool is_recursive) { - return acir_proofs::verify_proof(g2x, vk_buf, constraint_system_buf, proof, length); + return acir_proofs::verify_proof(g2x, vk_buf, constraint_system_buf, proof, length, is_recursive); } } diff --git a/cpp/src/barretenberg/dsl/acir_proofs/c_bind.hpp b/cpp/src/barretenberg/dsl/acir_proofs/c_bind.hpp index 0deda83166..39591b37d1 100644 --- a/cpp/src/barretenberg/dsl/acir_proofs/c_bind.hpp +++ b/cpp/src/barretenberg/dsl/acir_proofs/c_bind.hpp @@ -26,7 +26,12 @@ WASM_EXPORT size_t acir_proofs_new_proof(void* pippenger, 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); + uint8_t** proof_data_buf, + bool is_recursive); +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, + bool is_recursive); } diff --git a/cpp/src/barretenberg/dsl/types.hpp b/cpp/src/barretenberg/dsl/types.hpp index 273734aa76..be741363f9 100644 --- a/cpp/src/barretenberg/dsl/types.hpp +++ b/cpp/src/barretenberg/dsl/types.hpp @@ -37,6 +37,8 @@ using Verifier = std::conditional_t< plonk::UltraWithKeccakVerifier, std::conditional_t, plonk::TurboVerifier, plonk::Verifier>>; +using RecursiveProver = plonk::UltraProver; + using witness_ct = proof_system::plonk::stdlib::witness_t; using public_witness_ct = proof_system::plonk::stdlib::public_witness_t; using bool_ct = proof_system::plonk::stdlib::bool_t; From 61278fb77653784252d61b2532ccc993ae40a576 Mon Sep 17 00:00:00 2001 From: Maxim Vezenov Date: Mon, 24 Apr 2023 19:41:37 -0400 Subject: [PATCH 9/9] remove debug output from TestSerializationWithRecursion --- .../dsl/acir_proofs/acir_proofs.test.cpp | 35 ------------------- 1 file changed, 35 deletions(-) diff --git a/cpp/src/barretenberg/dsl/acir_proofs/acir_proofs.test.cpp b/cpp/src/barretenberg/dsl/acir_proofs/acir_proofs.test.cpp index 885c0c1ec3..b344086ca3 100644 --- a/cpp/src/barretenberg/dsl/acir_proofs/acir_proofs.test.cpp +++ b/cpp/src/barretenberg/dsl/acir_proofs/acir_proofs.test.cpp @@ -202,9 +202,6 @@ TEST(AcirProofs, TestSerializationWithRecursion) fr vk_hash_value; std::vector proof_witnesses(proof_fields_size / 32); std::vector key_witnesses(vk_fields_size / 32); - // memcpy(proof_witnesses.data(), (void*)proof_data_fields, proof_fields_size); - // memcpy(&key_witnesses[0], (void*)vk_fields, vk_fields_size); - // memcpy(&vk_hash_value, (void*)vk_hash_buf, 32); for (size_t i = 0; i < proof_fields_size / 32; i++) { proof_witnesses[i] = barretenberg::fr::serialize_from_buffer(&proof_data_fields[i * 32]); } @@ -216,14 +213,12 @@ TEST(AcirProofs, TestSerializationWithRecursion) std::vector proof_indices; const size_t proof_size = proof_witnesses.size(); - std::cout << "proof_size: " << proof_size << std::endl; for (size_t i = 0; i < proof_size; ++i) { proof_indices.emplace_back(static_cast(i + 19)); } std::vector key_indices; const size_t key_size = key_witnesses.size(); - std::cout << "key_size: " << key_size << std::endl; for (size_t i = 0; i < key_size; ++i) { key_indices.emplace_back(static_cast(i + 19 + proof_size)); } @@ -255,8 +250,6 @@ TEST(AcirProofs, TestSerializationWithRecursion) .q_c = -vk_hash_value, }; - std::cout << "vk_hash_value: " << vk_hash_value << std::endl; - std::vector witness; for (size_t i = 0; i < 18; ++i) { witness.emplace_back(0); @@ -268,8 +261,6 @@ TEST(AcirProofs, TestSerializationWithRecursion) witness.emplace_back(wit); } - std::cout << "witness.size(): " << witness.size() << std::endl; - acir_format::acir_format constraint_system{ .varnum = static_cast(witness.size() + 1), .public_inputs = { 1 }, @@ -287,23 +278,14 @@ TEST(AcirProofs, TestSerializationWithRecursion) .constraints = { vk_equality_constraint }, }; - // std::cout << "about to create_circuit_with_witness" << std::endl; - // auto composer = acir_format::create_circuit_with_witness(constraint_system, witness); - // auto prover = composer.create_ultra_with_keccak_prover(); - // auto proof = prover.construct_proof(); - // auto verifier = composer.create_ultra_with_keccak_verifier(); - // EXPECT_EQ(verifier.verify_proof(proof), true); - std::vector witness_buf; std::vector constraint_system_buf; write(constraint_system_buf, constraint_system); write(witness_buf, witness); uint8_t const* pk_buf = nullptr; acir_proofs::init_proving_key(&constraint_system_buf[0], &pk_buf); - std::cout << "past init_proving_key" << std::endl; uint32_t total_circuit_size = acir_proofs::get_total_circuit_size(&constraint_system_buf[0]); - std::cout << "got total_circuit_size" << std::endl; uint32_t pow2_size = 1 << (numeric::get_msb(total_circuit_size) + 1); auto env_crs = std::make_unique(); auto verifier_crs = env_crs->get_verifier_crs(); @@ -318,12 +300,10 @@ TEST(AcirProofs, TestSerializationWithRecursion) uint8_t const* vk_buf = nullptr; acir_proofs::init_verification_key(pippenger_ptr, &g2x_buffer[0], pk_buf, &vk_buf); - std::cout << "past init_verification_key" << std::endl; uint8_t* proof_data_buf = nullptr; size_t proof_length = acir_proofs::new_proof( pippenger_ptr, &g2x_buffer[0], pk_buf, &constraint_system_buf[0], &witness_buf[0], &proof_data_buf, false); - std::cout << "past new_proof" << std::endl; bool verified = acir_proofs::verify_proof(&g2x_buffer[0], vk_buf, @@ -332,27 +312,12 @@ TEST(AcirProofs, TestSerializationWithRecursion) static_cast(proof_length), false); EXPECT_EQ(verified, true); - std::cout << "past verify_proof" << std::endl; delete pippenger_ptr_base; - std::cout << "past delete pippenger_ptr_base" << std::endl; - free((void*)vk_buf); - std::cout << "past free vk_buf" << std::endl; - free((void*)pk_buf); - std::cout << "past free pk_buf" << std::endl; - free((void*)proof_data_buf); - std::cout << "past free proof_data_buf" << std::endl; - free((void*)proof_data_fields); - std::cout << "past free proof_data_fields" << std::endl; - free((void*)vk_fields); - std::cout << "past free vk_fields" << std::endl; - - // free((void*)vk_hash_buf); - std::cout << "past free vk_hash_buf" << std::endl; } }