From ccef1ce19e3804e8025aa611d0a01643c37a9265 Mon Sep 17 00:00:00 2001 From: lucasxia01 Date: Tue, 8 Jul 2025 16:46:40 +0000 Subject: [PATCH 1/6] do the check --- .../stdlib/honk_verifier/oink_recursive_verifier.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/barretenberg/cpp/src/barretenberg/stdlib/honk_verifier/oink_recursive_verifier.cpp b/barretenberg/cpp/src/barretenberg/stdlib/honk_verifier/oink_recursive_verifier.cpp index 672b25d8ea54..18be9a7522ab 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/honk_verifier/oink_recursive_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/honk_verifier/oink_recursive_verifier.cpp @@ -53,6 +53,7 @@ template void OinkRecursiveVerifier_::verify() FF vkey_hash = decider_vk->vk_and_hash->vk->add_hash_to_transcript(domain_separator, *transcript); vinfo("vk hash in Oink recursive verifier: ", vkey_hash); vinfo("expected vk hash: ", decider_vk->vk_and_hash->hash); + decider_vk->vk_and_hash->hash.assert_equal(vkey_hash); size_t num_public_inputs = static_cast(static_cast(decider_vk->vk_and_hash->vk->num_public_inputs.get_value())); From faab2f9ee0b3913013763e436d0bc84fcabfd4b2 Mon Sep 17 00:00:00 2001 From: lucasxia01 Date: Tue, 8 Jul 2025 18:28:51 +0000 Subject: [PATCH 2/6] fix tests --- .../test_civc_standalone_vks_havent_changed.sh | 2 +- .../client_ivc/acir_bincode_mocks.hpp | 18 ++++++++++++++---- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/barretenberg/cpp/scripts/test_civc_standalone_vks_havent_changed.sh b/barretenberg/cpp/scripts/test_civc_standalone_vks_havent_changed.sh index a1e2b7df8fcb..136121a0253e 100755 --- a/barretenberg/cpp/scripts/test_civc_standalone_vks_havent_changed.sh +++ b/barretenberg/cpp/scripts/test_civc_standalone_vks_havent_changed.sh @@ -11,7 +11,7 @@ cd .. # - Generate a hash for versioning: sha256sum bb-civc-inputs.tar.gz # - Upload the compressed results: aws s3 cp bb-civc-inputs.tar.gz s3://aztec-ci-artifacts/protocol/bb-civc-inputs-[hash(0:8)].tar.gz # Note: In case of the "Test suite failed to run ... Unexpected token 'with' " error, need to run: docker pull aztecprotocol/build:3.0 -pinned_civc_inputs_url="https://aztec-ci-artifacts.s3.us-east-2.amazonaws.com/protocol/bb-civc-inputs-b2a1aa5e.tar.gz" +pinned_civc_inputs_url="https://aztec-ci-artifacts.s3.us-east-2.amazonaws.com/protocol/bb-civc-inputs-d61d4539.tar.gz" # For easily rerunning the inputs generation if [[ "${1:-}" == "--update_inputs" ]]; then diff --git a/barretenberg/cpp/src/barretenberg/client_ivc/acir_bincode_mocks.hpp b/barretenberg/cpp/src/barretenberg/client_ivc/acir_bincode_mocks.hpp index dfcc40daf7f9..db4c15188a8d 100644 --- a/barretenberg/cpp/src/barretenberg/client_ivc/acir_bincode_mocks.hpp +++ b/barretenberg/cpp/src/barretenberg/client_ivc/acir_bincode_mocks.hpp @@ -86,9 +86,9 @@ inline std::vector create_simple_kernel(size_t vk_size, bool is_init_ke .verification_key = vk_inputs, .proof = {}, .public_inputs = {}, - // NOTE: If this starts failing after key hash becomes required need to pass as witness! (possibly after the VK, - // adding +1 to witness index below) - .key_hash = Acir::FunctionInput{ { Acir::ConstantOrWitnessEnum::Witness{ Acir::Witness{ 0 } } }, BIT_COUNT }, + .key_hash = Acir::FunctionInput{ { Acir::ConstantOrWitnessEnum::Witness{ + Acir::Witness{ static_cast(vk_size) } } }, + BIT_COUNT }, .proof_type = is_init_kernel ? acir_format::PROOF_TYPE::OINK : acir_format::PROOF_TYPE::PG }; @@ -96,7 +96,7 @@ inline std::vector create_simple_kernel(size_t vk_size, bool is_init_ke black_box_call.value = recursion; circuit.opcodes.push_back(Acir::Opcode{ Acir::Opcode::BlackBoxFuncCall{ black_box_call } }); - circuit.current_witness_index = static_cast(vk_inputs.size()); + circuit.current_witness_index = static_cast(vk_inputs.size() + 1); circuit.expression_width = Acir::ExpressionWidth{ Acir::ExpressionWidth::Bounded{ 3 } }; // Create the program with the circuit @@ -120,6 +120,16 @@ inline std::vector create_kernel_witness(const std::vector& app ss << app_vk_fields[i]; kernel_witness.stack.back().witness.value[Witnesses::Witness{ i }] = ss.str(); } + std::stringstream ss; + fr challenge = crypto::Poseidon2::hash(app_vk_fields); + // match the parameter used in stdlib, which is derived from cycle_scalar (is 128) + static constexpr size_t LO_BITS = fr::Params::MAX_BITS_PER_ENDOMORPHISM_SCALAR; + auto converted = static_cast(challenge); + uint256_t lo = converted.slice(0, LO_BITS); + ss << lo; + kernel_witness.stack.back().witness.value[Witnesses::Witness{ static_cast(app_vk_fields.size()) }] = + ss.str(); + return kernel_witness.bincodeSerialize(); } From bcf6189845ad51585b0f0ddb75af6bcfe7a5cc7e Mon Sep 17 00:00:00 2001 From: lucasxia01 Date: Tue, 8 Jul 2025 19:26:09 +0000 Subject: [PATCH 3/6] update hash to full 254 bits --- .../client_ivc/acir_bincode_mocks.hpp | 7 +------ .../cpp/src/barretenberg/flavor/flavor.hpp | 17 ++++------------- .../flavor/native_verification_key.test.cpp | 8 ++++---- .../flavor/stdlib_verification_key.test.cpp | 8 ++++---- .../ultra_recursive_verifier.test.cpp | 2 +- .../src/barretenberg/transcript/transcript.hpp | 7 +++---- yarn-project/stdlib/src/hash/hash.ts | 4 +--- 7 files changed, 18 insertions(+), 35 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/client_ivc/acir_bincode_mocks.hpp b/barretenberg/cpp/src/barretenberg/client_ivc/acir_bincode_mocks.hpp index db4c15188a8d..3685df67d588 100644 --- a/barretenberg/cpp/src/barretenberg/client_ivc/acir_bincode_mocks.hpp +++ b/barretenberg/cpp/src/barretenberg/client_ivc/acir_bincode_mocks.hpp @@ -121,12 +121,7 @@ inline std::vector create_kernel_witness(const std::vector& app kernel_witness.stack.back().witness.value[Witnesses::Witness{ i }] = ss.str(); } std::stringstream ss; - fr challenge = crypto::Poseidon2::hash(app_vk_fields); - // match the parameter used in stdlib, which is derived from cycle_scalar (is 128) - static constexpr size_t LO_BITS = fr::Params::MAX_BITS_PER_ENDOMORPHISM_SCALAR; - auto converted = static_cast(challenge); - uint256_t lo = converted.slice(0, LO_BITS); - ss << lo; + ss << crypto::Poseidon2::hash(app_vk_fields); kernel_witness.stack.back().witness.value[Witnesses::Witness{ static_cast(app_vk_fields.size()) }] = ss.str(); diff --git a/barretenberg/cpp/src/barretenberg/flavor/flavor.hpp b/barretenberg/cpp/src/barretenberg/flavor/flavor.hpp index b588635eae02..566dbfdad7b4 100644 --- a/barretenberg/cpp/src/barretenberg/flavor/flavor.hpp +++ b/barretenberg/cpp/src/barretenberg/flavor/flavor.hpp @@ -184,13 +184,8 @@ class NativeVerificationKey_ : public PrecomputedCommitments { */ fr hash() { - fr challenge = crypto::Poseidon2::hash(this->to_field_elements()); - // match the parameter used in stdlib, which is derived from cycle_scalar (is 128) - static constexpr size_t LO_BITS = fr::Params::MAX_BITS_PER_ENDOMORPHISM_SCALAR; - - auto converted = static_cast(challenge); - uint256_t lo = converted.slice(0, LO_BITS); - return lo; + fr vk_hash = crypto::Poseidon2::hash(this->to_field_elements()); + return vk_hash; } /** @@ -253,12 +248,8 @@ class StdlibVerificationKey_ : public PrecomputedCommitments { */ FF hash(Builder& builder) { - // use existing field-splitting code in cycle_scalar - FF challenge = stdlib::poseidon2::hash(builder, to_field_elements()); - using cycle_scalar = typename stdlib::cycle_group::cycle_scalar; - const cycle_scalar scalar = cycle_scalar(challenge); - scalar.lo.create_range_constraint(cycle_scalar::LO_BITS); - return scalar.lo; + FF vk_hash = stdlib::poseidon2::hash(builder, to_field_elements()); + return vk_hash; } /** diff --git a/barretenberg/cpp/src/barretenberg/flavor/native_verification_key.test.cpp b/barretenberg/cpp/src/barretenberg/flavor/native_verification_key.test.cpp index 0df12eb8fff2..849cc386a150 100644 --- a/barretenberg/cpp/src/barretenberg/flavor/native_verification_key.test.cpp +++ b/barretenberg/cpp/src/barretenberg/flavor/native_verification_key.test.cpp @@ -35,8 +35,8 @@ using FlavorTypes = testing::Types vk_field_elements = vk.to_field_elements(); NativeTranscript transcript; for (const auto& field_element : vk_field_elements) { - transcript.add_to_hash_buffer("vk_element", field_element); + transcript.add_to_independent_hash_buffer("vk_element", field_element); } - fr vkey_hash_1 = transcript.get_challenge("vk_hash"); + fr vkey_hash_1 = transcript.hash_independent_buffer("vk_hash"); // Second method of hashing: using hash(). fr vkey_hash_2 = vk.hash(); EXPECT_EQ(vkey_hash_1, vkey_hash_2); diff --git a/barretenberg/cpp/src/barretenberg/flavor/stdlib_verification_key.test.cpp b/barretenberg/cpp/src/barretenberg/flavor/stdlib_verification_key.test.cpp index fb81f6dd3c8b..455b9b3d10ce 100644 --- a/barretenberg/cpp/src/barretenberg/flavor/stdlib_verification_key.test.cpp +++ b/barretenberg/cpp/src/barretenberg/flavor/stdlib_verification_key.test.cpp @@ -39,8 +39,8 @@ using FlavorTypes = testing::Types, TYPED_TEST_SUITE(StdlibVerificationKeyTests, FlavorTypes); /** - * @brief Checks that the hash produced from calling to_field_elements and then add_to_hash_buffer is the same as the - * hash() call and also the same as the add_hash_to_transcript. + * @brief Checks that the hash produced from calling to_field_elements and then add_to_independent_hash_buffer is the + * same as the hash() call and also the same as the add_hash_to_transcript. * */ TYPED_TEST(StdlibVerificationKeyTests, VKHashingConsistency) @@ -68,9 +68,9 @@ TYPED_TEST(StdlibVerificationKeyTests, VKHashingConsistency) std::vector vk_field_elements = vk.to_field_elements(); StdlibTranscript transcript; for (const auto& field_element : vk_field_elements) { - transcript.add_to_hash_buffer("vk_element", field_element); + transcript.add_to_independent_hash_buffer("vk_element", field_element); } - FF vkey_hash_1 = transcript.template get_challenge("vk_hash"); + FF vkey_hash_1 = transcript.hash_independent_buffer("vk_hash"); // Second method of hashing: using hash(). FF vkey_hash_2 = vk.hash(outer_builder); EXPECT_EQ(vkey_hash_1.get_value(), vkey_hash_2.get_value()); diff --git a/barretenberg/cpp/src/barretenberg/stdlib/honk_verifier/ultra_recursive_verifier.test.cpp b/barretenberg/cpp/src/barretenberg/stdlib/honk_verifier/ultra_recursive_verifier.test.cpp index 06d4bf15a171..4f2de57caee4 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/honk_verifier/ultra_recursive_verifier.test.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/honk_verifier/ultra_recursive_verifier.test.cpp @@ -268,7 +268,7 @@ template class RecursiveVerifierTest : public testing } // Check the size of the recursive verifier if constexpr (std::same_as>) { - uint32_t NUM_GATES_EXPECTED = 870572; + uint32_t NUM_GATES_EXPECTED = 870546; BB_ASSERT_EQ(static_cast(outer_circuit.get_num_finalized_gates()), NUM_GATES_EXPECTED, "MegaZKHonk Recursive verifier changed in Ultra gate count! Update this value if you " diff --git a/barretenberg/cpp/src/barretenberg/transcript/transcript.hpp b/barretenberg/cpp/src/barretenberg/transcript/transcript.hpp index 7a5f9fe67ad0..05cdd154de21 100644 --- a/barretenberg/cpp/src/barretenberg/transcript/transcript.hpp +++ b/barretenberg/cpp/src/barretenberg/transcript/transcript.hpp @@ -452,11 +452,10 @@ template class BaseTranscript { */ Fr hash_independent_buffer(const std::string& label) { - Fr new_challenge = TranscriptParams::hash(independent_hash_buffer); - std::array new_challenges = TranscriptParams::split_challenge(new_challenge); + Fr buffer_hash = TranscriptParams::hash(independent_hash_buffer); independent_hash_buffer.clear(); - add_to_hash_buffer(label, new_challenge); - return new_challenges[0]; + add_to_hash_buffer(label, buffer_hash); + return buffer_hash; } /** diff --git a/yarn-project/stdlib/src/hash/hash.ts b/yarn-project/stdlib/src/hash/hash.ts index 3091ba3ea7db..6e5fa058a168 100644 --- a/yarn-project/stdlib/src/hash/hash.ts +++ b/yarn-project/stdlib/src/hash/hash.ts @@ -13,9 +13,7 @@ import type { AztecAddress } from '../aztec-address/index.js'; */ export async function hashVK(keyAsFields: Fr[]): Promise { // Should match the implementation in barretenberg/cpp/src/barretenberg/flavor/flavor.hpp > hash() - const hash = (await poseidon2Hash(keyAsFields)).toBuffer(); - // Taking the last 16 bytes (128 bits) of the hash. - return new Fr(toBigIntBE(hash.subarray(Fr.SIZE_IN_BYTES - 16))); + return await poseidon2Hash(keyAsFields); } /** From 7e12e16f60eb6bbbb1a7237231f0640f028fe34d Mon Sep 17 00:00:00 2001 From: lucasxia01 Date: Tue, 8 Jul 2025 19:46:54 +0000 Subject: [PATCH 4/6] update civc test --- .../cpp/scripts/test_civc_standalone_vks_havent_changed.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/barretenberg/cpp/scripts/test_civc_standalone_vks_havent_changed.sh b/barretenberg/cpp/scripts/test_civc_standalone_vks_havent_changed.sh index bde36d5cce32..c102e9862c06 100755 --- a/barretenberg/cpp/scripts/test_civc_standalone_vks_havent_changed.sh +++ b/barretenberg/cpp/scripts/test_civc_standalone_vks_havent_changed.sh @@ -11,7 +11,7 @@ cd .. # - Generate a hash for versioning: sha256sum bb-civc-inputs.tar.gz # - Upload the compressed results: aws s3 cp bb-civc-inputs.tar.gz s3://aztec-ci-artifacts/protocol/bb-civc-inputs-[hash(0:8)].tar.gz # Note: In case of the "Test suite failed to run ... Unexpected token 'with' " error, need to run: docker pull aztecprotocol/build:3.0 -pinned_civc_inputs_url="https://aztec-ci-artifacts.s3.us-east-2.amazonaws.com/protocol/bb-civc-inputs-33fe085e.tar.gz" +pinned_civc_inputs_url="https://aztec-ci-artifacts.s3.us-east-2.amazonaws.com/protocol/bb-civc-inputs-1e546faa.tar.gz" # For easily rerunning the inputs generation if [[ "${1:-}" == "--update_inputs" ]]; then From d08045294f60a46fad02f5cc9fd234b814771d1c Mon Sep 17 00:00:00 2001 From: lucasxia01 Date: Tue, 8 Jul 2025 20:33:44 +0000 Subject: [PATCH 5/6] fix yp linter --- yarn-project/stdlib/src/hash/hash.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/yarn-project/stdlib/src/hash/hash.ts b/yarn-project/stdlib/src/hash/hash.ts index 6e5fa058a168..de5436c7e236 100644 --- a/yarn-project/stdlib/src/hash/hash.ts +++ b/yarn-project/stdlib/src/hash/hash.ts @@ -1,5 +1,4 @@ import { GeneratorIndex } from '@aztec/constants'; -import { toBigIntBE } from '@aztec/foundation/bigint-buffer'; import { poseidon2Hash, poseidon2HashWithSeparator, sha256ToField } from '@aztec/foundation/crypto'; import type { EthAddress } from '@aztec/foundation/eth-address'; import { Fr } from '@aztec/foundation/fields'; From 73b50a74a615fff244552771fa5773d568c4d829 Mon Sep 17 00:00:00 2001 From: lucasxia01 Date: Tue, 8 Jul 2025 23:23:37 +0000 Subject: [PATCH 6/6] address comments --- .../client_ivc/acir_bincode_mocks.hpp | 21 ++++++++++--------- .../honk_verifier/oink_recursive_verifier.cpp | 1 + 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/client_ivc/acir_bincode_mocks.hpp b/barretenberg/cpp/src/barretenberg/client_ivc/acir_bincode_mocks.hpp index 3685df67d588..c1b209c12d86 100644 --- a/barretenberg/cpp/src/barretenberg/client_ivc/acir_bincode_mocks.hpp +++ b/barretenberg/cpp/src/barretenberg/client_ivc/acir_bincode_mocks.hpp @@ -79,24 +79,25 @@ inline std::vector create_simple_kernel(size_t vk_size, bool is_init_ke Acir::FunctionInput input{ { Acir::ConstantOrWitnessEnum::Witness{ i } }, BIT_COUNT }; vk_inputs.push_back(input); } + Acir::FunctionInput key_hash{ { Acir::ConstantOrWitnessEnum::Witness{ static_cast(vk_size) } }, + BIT_COUNT }; + size_t total_num_witnesses = /* vk */ vk_size + /* key_hash */ 1; // Modeled after noir-projects/mock-protocol-circuits/crates/mock-private-kernel-init/src/main.nr // We mock the init or tail kernels using OINK or PG respectively. - Acir::BlackBoxFuncCall::RecursiveAggregation recursion{ - .verification_key = vk_inputs, - .proof = {}, - .public_inputs = {}, - .key_hash = Acir::FunctionInput{ { Acir::ConstantOrWitnessEnum::Witness{ - Acir::Witness{ static_cast(vk_size) } } }, - BIT_COUNT }, - .proof_type = is_init_kernel ? acir_format::PROOF_TYPE::OINK : acir_format::PROOF_TYPE::PG - }; + Acir::BlackBoxFuncCall::RecursiveAggregation recursion{ .verification_key = vk_inputs, + .proof = {}, + .public_inputs = {}, + .key_hash = key_hash, + .proof_type = is_init_kernel + ? acir_format::PROOF_TYPE::OINK + : acir_format::PROOF_TYPE::PG }; Acir::BlackBoxFuncCall black_box_call; black_box_call.value = recursion; circuit.opcodes.push_back(Acir::Opcode{ Acir::Opcode::BlackBoxFuncCall{ black_box_call } }); - circuit.current_witness_index = static_cast(vk_inputs.size() + 1); + circuit.current_witness_index = static_cast(total_num_witnesses); circuit.expression_width = Acir::ExpressionWidth{ Acir::ExpressionWidth::Bounded{ 3 } }; // Create the program with the circuit diff --git a/barretenberg/cpp/src/barretenberg/stdlib/honk_verifier/oink_recursive_verifier.cpp b/barretenberg/cpp/src/barretenberg/stdlib/honk_verifier/oink_recursive_verifier.cpp index 18be9a7522ab..1b095b261429 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/honk_verifier/oink_recursive_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/honk_verifier/oink_recursive_verifier.cpp @@ -53,6 +53,7 @@ template void OinkRecursiveVerifier_::verify() FF vkey_hash = decider_vk->vk_and_hash->vk->add_hash_to_transcript(domain_separator, *transcript); vinfo("vk hash in Oink recursive verifier: ", vkey_hash); vinfo("expected vk hash: ", decider_vk->vk_and_hash->hash); + // Check that the vk hash matches the hash of the verification key decider_vk->vk_and_hash->hash.assert_equal(vkey_hash); size_t num_public_inputs =