From 8ea60d69c032d49bcfcb52392d817ecfdd92c2dd Mon Sep 17 00:00:00 2001 From: Maddiaa0 <47148561+Maddiaa0@users.noreply.github.com> Date: Sat, 26 Jul 2025 19:36:37 +0000 Subject: [PATCH 1/7] feat(sol): vk hashing --- .../cpp/src/barretenberg/flavor/flavor.hpp | 4 +- .../flavor/ultra_keccak_flavor.hpp | 13 ++--- .../barretenberg/honk/utils/honk_key_gen.hpp | 1 + .../barretenberg/transcript/transcript.hpp | 3 ++ .../sol/src/honk/BaseHonkVerifier.sol | 4 +- .../sol/src/honk/BaseZKHonkVerifier.sol | 2 +- barretenberg/sol/src/honk/HonkTypes.sol | 2 + barretenberg/sol/src/honk/Transcript.sol | 54 +++++++++---------- barretenberg/sol/src/honk/ZKTranscript.sol | 52 +++++++++--------- .../src/honk/keys/Add2HonkVerificationKey.sol | 5 +- .../honk/keys/BlakeHonkVerificationKey.sol | 5 +- .../honk/keys/EcdsaHonkVerificationKey.sol | 5 +- .../keys/RecursiveHonkVerificationKey.sol | 5 +- 13 files changed, 75 insertions(+), 80 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/flavor/flavor.hpp b/barretenberg/cpp/src/barretenberg/flavor/flavor.hpp index 85261fce212e..7d2adc636582 100644 --- a/barretenberg/cpp/src/barretenberg/flavor/flavor.hpp +++ b/barretenberg/cpp/src/barretenberg/flavor/flavor.hpp @@ -197,9 +197,9 @@ class NativeVerificationKey_ : public PrecomputedCommitments { * @details Currently only used in testing. * @return FF */ - fr hash() + fr hash() const { - fr vk_hash = crypto::Poseidon2::hash(this->to_field_elements()); + fr vk_hash = Transcript::hash(this->to_field_elements()); return vk_hash; } diff --git a/barretenberg/cpp/src/barretenberg/flavor/ultra_keccak_flavor.hpp b/barretenberg/cpp/src/barretenberg/flavor/ultra_keccak_flavor.hpp index 4ac708d94c3c..fe838b16dc12 100644 --- a/barretenberg/cpp/src/barretenberg/flavor/ultra_keccak_flavor.hpp +++ b/barretenberg/cpp/src/barretenberg/flavor/ultra_keccak_flavor.hpp @@ -76,14 +76,11 @@ class UltraKeccakFlavor : public bb::UltraFlavor { */ fr add_hash_to_transcript(const std::string& domain_separator, Transcript& transcript) const override { - // TODO(https://github.com/AztecProtocol/barretenberg/issues/1427): We need to update this function to look - // like UltraFlavor's add_hash_to_transcript. Alternatively, the VerificationKey class will go away when we - // add pairing point aggregation to the solidity verifier. - uint64_t circuit_size = 1 << this->log_circuit_size; - transcript.add_to_hash_buffer(domain_separator + "vk_log_circuit_size", circuit_size); - transcript.add_to_hash_buffer(domain_separator + "vk_num_public_inputs", this->num_public_inputs); - transcript.add_to_hash_buffer(domain_separator + "vk_pub_inputs_offset", this->pub_inputs_offset); - return 0; + // This hash contains a hash of the entire vk - including all of the elements + const fr hash = this->hash(); + + transcript.add_to_hash_buffer(domain_separator + "vk_hash", hash); + return hash; } // Don't statically check for object completeness. diff --git a/barretenberg/cpp/src/barretenberg/honk/utils/honk_key_gen.hpp b/barretenberg/cpp/src/barretenberg/honk/utils/honk_key_gen.hpp index a26c0576c496..98ac4428142e 100644 --- a/barretenberg/cpp/src/barretenberg/honk/utils/honk_key_gen.hpp +++ b/barretenberg/cpp/src/barretenberg/honk/utils/honk_key_gen.hpp @@ -74,6 +74,7 @@ inline void output_vk_sol_ultra_honk(std::ostream& os, print_u256(1 << key->log_circuit_size, "circuitSize"); print_u256(key->log_circuit_size, "logCircuitSize"); print_u256(key->num_public_inputs, "publicInputsSize"); + print_u256(key->hash(), "vkHash"); print_g1(key->q_l, "ql"); print_g1(key->q_r, "qr"); print_g1(key->q_o, "qo"); diff --git a/barretenberg/cpp/src/barretenberg/transcript/transcript.hpp b/barretenberg/cpp/src/barretenberg/transcript/transcript.hpp index 29cf828a63ca..b9a3f65cfe8b 100644 --- a/barretenberg/cpp/src/barretenberg/transcript/transcript.hpp +++ b/barretenberg/cpp/src/barretenberg/transcript/transcript.hpp @@ -330,6 +330,9 @@ template class BaseTranscript { */ void enable_manifest() { use_manifest = true; } + // TODO: doc + static Fr hash(const std::vector& data) { return TranscriptParams::hash(data); } + /** * @brief After all the prover messages have been sent, finalize the round by hashing all the data and then * create the number of requested challenges. diff --git a/barretenberg/sol/src/honk/BaseHonkVerifier.sol b/barretenberg/sol/src/honk/BaseHonkVerifier.sol index 825461e1e040..c3c722bd32fe 100644 --- a/barretenberg/sol/src/honk/BaseHonkVerifier.sol +++ b/barretenberg/sol/src/honk/BaseHonkVerifier.sol @@ -65,9 +65,7 @@ abstract contract BaseHonkVerifier is IVerifier { // Generate the fiat shamir challenges for the whole protocol // TODO(https://github.com/AztecProtocol/barretenberg/issues/1281): Add pubInputsOffset to VK or remove entirely. - Transcript memory t = TranscriptLib.generateTranscript( - p, publicInputs, vk.circuitSize, $NUM_PUBLIC_INPUTS, /*pubInputsOffset=*/ 1 - ); + Transcript memory t = TranscriptLib.generateTranscript(p, publicInputs, vk.vkHash, $NUM_PUBLIC_INPUTS); // Derive public input delta // TODO(https://github.com/AztecProtocol/barretenberg/issues/1281): Add pubInputsOffset to VK or remove entirely. diff --git a/barretenberg/sol/src/honk/BaseZKHonkVerifier.sol b/barretenberg/sol/src/honk/BaseZKHonkVerifier.sol index dc5c5d918de5..f89ad31fcdca 100644 --- a/barretenberg/sol/src/honk/BaseZKHonkVerifier.sol +++ b/barretenberg/sol/src/honk/BaseZKHonkVerifier.sol @@ -74,7 +74,7 @@ abstract contract BaseZKHonkVerifier is IVerifier { // Generate the fiat shamir challenges for the whole protocol // TODO(https://github.com/AztecProtocol/barretenberg/issues/1281): Add pubInputsOffset to VK or remove entirely. ZKTranscript memory t = ZKTranscriptLib.generateTranscript( - p, publicInputs, vk.circuitSize, $NUM_PUBLIC_INPUTS, /*pubInputsOffset=*/ 1 + p, publicInputs, vk.vkHash, $NUM_PUBLIC_INPUTS ); // Derive public input delta diff --git a/barretenberg/sol/src/honk/HonkTypes.sol b/barretenberg/sol/src/honk/HonkTypes.sol index fa89fc128068..7f108ab19ddd 100644 --- a/barretenberg/sol/src/honk/HonkTypes.sol +++ b/barretenberg/sol/src/honk/HonkTypes.sol @@ -76,6 +76,8 @@ library Honk { } struct VerificationKey { + // Hash of all of the field elements in the verification key + uint256 vkHash; // Misc Params uint256 circuitSize; uint256 logCircuitSize; diff --git a/barretenberg/sol/src/honk/Transcript.sol b/barretenberg/sol/src/honk/Transcript.sol index d2ae68337637..b2efd122bfa5 100644 --- a/barretenberg/sol/src/honk/Transcript.sol +++ b/barretenberg/sol/src/honk/Transcript.sol @@ -31,14 +31,12 @@ library TranscriptLib { function generateTranscript( Honk.Proof memory proof, bytes32[] calldata publicInputs, - uint256 circuitSize, - uint256 publicInputsSize, - uint256 pubInputsOffset + uint256 vkHash, + uint256 publicInputsSize ) internal pure returns (Transcript memory t) { Fr previousChallenge; - (t.relationParameters, previousChallenge) = generateRelationParametersChallenges( - proof, publicInputs, circuitSize, publicInputsSize, pubInputsOffset, previousChallenge - ); + (t.relationParameters, previousChallenge) = + generateRelationParametersChallenges(proof, publicInputs, vkHash, publicInputsSize, previousChallenge); (t.alphas, previousChallenge) = generateAlphaChallenges(previousChallenge, proof); @@ -68,13 +66,12 @@ library TranscriptLib { function generateRelationParametersChallenges( Honk.Proof memory proof, bytes32[] calldata publicInputs, - uint256 circuitSize, + uint256 vkHash, uint256 publicInputsSize, - uint256 pubInputsOffset, Fr previousChallenge ) internal pure returns (Honk.RelationParameters memory rp, Fr nextPreviousChallenge) { (rp.eta, rp.etaTwo, rp.etaThree, previousChallenge) = - generateEtaChallenge(proof, publicInputs, circuitSize, publicInputsSize, pubInputsOffset); + generateEtaChallenge(proof, publicInputs, vkHash, publicInputsSize); (rp.beta, rp.gamma, nextPreviousChallenge) = generateBetaAndGammaChallenges(previousChallenge, proof); } @@ -82,36 +79,33 @@ library TranscriptLib { function generateEtaChallenge( Honk.Proof memory proof, bytes32[] calldata publicInputs, - uint256 circuitSize, - uint256 publicInputsSize, - uint256 pubInputsOffset + uint256 vkHash, + uint256 publicInputsSize ) internal pure returns (Fr eta, Fr etaTwo, Fr etaThree, Fr previousChallenge) { - bytes32[] memory round0 = new bytes32[](3 + publicInputsSize + 12); - round0[0] = bytes32(circuitSize); - round0[1] = bytes32(publicInputsSize); - round0[2] = bytes32(pubInputsOffset); + bytes32[] memory round0 = new bytes32[](1 + publicInputsSize + 12); + round0[0] = bytes32(vkHash); for (uint256 i = 0; i < publicInputsSize - PAIRING_POINTS_SIZE; i++) { - round0[3 + i] = bytes32(publicInputs[i]); + round0[1 + i] = bytes32(publicInputs[i]); } for (uint256 i = 0; i < PAIRING_POINTS_SIZE; i++) { - round0[3 + publicInputsSize - PAIRING_POINTS_SIZE + i] = FrLib.toBytes32(proof.pairingPointObject[i]); + round0[1 + publicInputsSize - PAIRING_POINTS_SIZE + i] = FrLib.toBytes32(proof.pairingPointObject[i]); } // Create the first challenge // Note: w4 is added to the challenge later on - round0[3 + publicInputsSize] = bytes32(proof.w1.x_0); - round0[3 + publicInputsSize + 1] = bytes32(proof.w1.x_1); - round0[3 + publicInputsSize + 2] = bytes32(proof.w1.y_0); - round0[3 + publicInputsSize + 3] = bytes32(proof.w1.y_1); - round0[3 + publicInputsSize + 4] = bytes32(proof.w2.x_0); - round0[3 + publicInputsSize + 5] = bytes32(proof.w2.x_1); - round0[3 + publicInputsSize + 6] = bytes32(proof.w2.y_0); - round0[3 + publicInputsSize + 7] = bytes32(proof.w2.y_1); - round0[3 + publicInputsSize + 8] = bytes32(proof.w3.x_0); - round0[3 + publicInputsSize + 9] = bytes32(proof.w3.x_1); - round0[3 + publicInputsSize + 10] = bytes32(proof.w3.y_0); - round0[3 + publicInputsSize + 11] = bytes32(proof.w3.y_1); + round0[1 + publicInputsSize] = bytes32(proof.w1.x_0); + round0[1 + publicInputsSize + 1] = bytes32(proof.w1.x_1); + round0[1 + publicInputsSize + 2] = bytes32(proof.w1.y_0); + round0[1 + publicInputsSize + 3] = bytes32(proof.w1.y_1); + round0[1 + publicInputsSize + 4] = bytes32(proof.w2.x_0); + round0[1 + publicInputsSize + 5] = bytes32(proof.w2.x_1); + round0[1 + publicInputsSize + 6] = bytes32(proof.w2.y_0); + round0[1 + publicInputsSize + 7] = bytes32(proof.w2.y_1); + round0[1 + publicInputsSize + 8] = bytes32(proof.w3.x_0); + round0[1 + publicInputsSize + 9] = bytes32(proof.w3.x_1); + round0[1 + publicInputsSize + 10] = bytes32(proof.w3.y_0); + round0[1 + publicInputsSize + 11] = bytes32(proof.w3.y_1); previousChallenge = FrLib.fromBytes32(keccak256(abi.encodePacked(round0))); (eta, etaTwo) = splitChallenge(previousChallenge); diff --git a/barretenberg/sol/src/honk/ZKTranscript.sol b/barretenberg/sol/src/honk/ZKTranscript.sol index 3cb35deb8bee..70f16994e541 100644 --- a/barretenberg/sol/src/honk/ZKTranscript.sol +++ b/barretenberg/sol/src/honk/ZKTranscript.sol @@ -33,13 +33,12 @@ library ZKTranscriptLib { function generateTranscript( Honk.ZKProof memory proof, bytes32[] calldata publicInputs, - uint256 circuitSize, - uint256 publicInputsSize, - uint256 pubInputsOffset + uint256 vkHash, + uint256 publicInputsSize ) external pure returns (ZKTranscript memory t) { Fr previousChallenge; (t.relationParameters, previousChallenge) = generateRelationParametersChallenges( - proof, publicInputs, circuitSize, publicInputsSize, pubInputsOffset, previousChallenge + proof, publicInputs, vkHash, publicInputsSize, previousChallenge ); (t.alphas, previousChallenge) = generateAlphaChallenges(previousChallenge, proof); @@ -69,13 +68,12 @@ library ZKTranscriptLib { function generateRelationParametersChallenges( Honk.ZKProof memory proof, bytes32[] calldata publicInputs, - uint256 circuitSize, + uint256 vkHash, uint256 publicInputsSize, - uint256 pubInputsOffset, Fr previousChallenge ) internal pure returns (Honk.RelationParameters memory rp, Fr nextPreviousChallenge) { (rp.eta, rp.etaTwo, rp.etaThree, previousChallenge) = - generateEtaChallenge(proof, publicInputs, circuitSize, publicInputsSize, pubInputsOffset); + generateEtaChallenge(proof, publicInputs, vkHash, publicInputsSize); (rp.beta, rp.gamma, nextPreviousChallenge) = generateBetaAndGammaChallenges(previousChallenge, proof); } @@ -83,35 +81,33 @@ library ZKTranscriptLib { function generateEtaChallenge( Honk.ZKProof memory proof, bytes32[] calldata publicInputs, - uint256 circuitSize, - uint256 publicInputsSize, - uint256 pubInputsOffset + uint256 vkHash, + uint256 publicInputsSize ) internal pure returns (Fr eta, Fr etaTwo, Fr etaThree, Fr previousChallenge) { - bytes32[] memory round0 = new bytes32[](3 + publicInputsSize + 12); - round0[0] = bytes32(circuitSize); - round0[1] = bytes32(publicInputsSize); - round0[2] = bytes32(pubInputsOffset); + bytes32[] memory round0 = new bytes32[](1 + publicInputsSize + 12); + round0[0] = bytes32(vkHash); + for (uint256 i = 0; i < publicInputsSize - PAIRING_POINTS_SIZE; i++) { - round0[3 + i] = bytes32(publicInputs[i]); + round0[1 + i] = bytes32(publicInputs[i]); } for (uint256 i = 0; i < PAIRING_POINTS_SIZE; i++) { - round0[3 + publicInputsSize - PAIRING_POINTS_SIZE + i] = FrLib.toBytes32(proof.pairingPointObject[i]); + round0[1 + publicInputsSize - PAIRING_POINTS_SIZE + i] = FrLib.toBytes32(proof.pairingPointObject[i]); } // Create the first challenge // Note: w4 is added to the challenge later on - round0[3 + publicInputsSize] = bytes32(proof.w1.x_0); - round0[3 + publicInputsSize + 1] = bytes32(proof.w1.x_1); - round0[3 + publicInputsSize + 2] = bytes32(proof.w1.y_0); - round0[3 + publicInputsSize + 3] = bytes32(proof.w1.y_1); - round0[3 + publicInputsSize + 4] = bytes32(proof.w2.x_0); - round0[3 + publicInputsSize + 5] = bytes32(proof.w2.x_1); - round0[3 + publicInputsSize + 6] = bytes32(proof.w2.y_0); - round0[3 + publicInputsSize + 7] = bytes32(proof.w2.y_1); - round0[3 + publicInputsSize + 8] = bytes32(proof.w3.x_0); - round0[3 + publicInputsSize + 9] = bytes32(proof.w3.x_1); - round0[3 + publicInputsSize + 10] = bytes32(proof.w3.y_0); - round0[3 + publicInputsSize + 11] = bytes32(proof.w3.y_1); + round0[1 + publicInputsSize] = bytes32(proof.w1.x_0); + round0[1 + publicInputsSize + 1] = bytes32(proof.w1.x_1); + round0[1 + publicInputsSize + 2] = bytes32(proof.w1.y_0); + round0[1 + publicInputsSize + 3] = bytes32(proof.w1.y_1); + round0[1 + publicInputsSize + 4] = bytes32(proof.w2.x_0); + round0[1 + publicInputsSize + 5] = bytes32(proof.w2.x_1); + round0[1 + publicInputsSize + 6] = bytes32(proof.w2.y_0); + round0[1 + publicInputsSize + 7] = bytes32(proof.w2.y_1); + round0[1 + publicInputsSize + 8] = bytes32(proof.w3.x_0); + round0[1 + publicInputsSize + 9] = bytes32(proof.w3.x_1); + round0[1 + publicInputsSize + 10] = bytes32(proof.w3.y_0); + round0[1 + publicInputsSize + 11] = bytes32(proof.w3.y_1); previousChallenge = FrLib.fromBytes32(keccak256(abi.encodePacked(round0))); (eta, etaTwo) = splitChallenge(previousChallenge); diff --git a/barretenberg/sol/src/honk/keys/Add2HonkVerificationKey.sol b/barretenberg/sol/src/honk/keys/Add2HonkVerificationKey.sol index 3ea10080054c..1822bdd6c6d5 100644 --- a/barretenberg/sol/src/honk/keys/Add2HonkVerificationKey.sol +++ b/barretenberg/sol/src/honk/keys/Add2HonkVerificationKey.sol @@ -14,6 +14,7 @@ library Add2HonkVerificationKey { circuitSize: uint256(4096), logCircuitSize: uint256(12), publicInputsSize: uint256(19), + vkHash: uint256(0x00591ad8d756290e4d7691a3fc5969f55c517d7bfac3de61c53df98cb7597bb9), ql: Honk.G1Point({ x: uint256(0x0480a80b708d88511983399d7d454290cd7fc44f01efd7cd0adabac1da5209b7), y: uint256(0x2ae668b0ee73a123a9d90f5783ad3d938b72e3c7ff79fcccab796e842df5300e) @@ -95,8 +96,8 @@ library Add2HonkVerificationKey { y: uint256(0x233ecaca2ddbebb0484a44e6f55b8c8614c7b5e0ce31b51d59d6b21322a307a1) }), t3: Honk.G1Point({ - x: uint256(0x1466af934dc34b082708b0a26a61dae7d9d859cbd4661cfab6abf34e827d9d2a), - y: uint256(0x2666bf4c8a2aef1ab89aafded315580561c9d4a13f3ac4b255b478f544590eda) + x: uint256(0x046d00a14d5c2e99d48c85c441284b5dfef894fba87965c1c75b9a5a7cf0fdde), + y: uint256(0x2113297215872f507a7668059f801ac9877e73cb6dcab3703c5f68b404abeded) }), t4: Honk.G1Point({ x: uint256(0x0765bf6645e4cf63f05d9b0efd06acebce309c685a3b05e613574ccd7316677c), diff --git a/barretenberg/sol/src/honk/keys/BlakeHonkVerificationKey.sol b/barretenberg/sol/src/honk/keys/BlakeHonkVerificationKey.sol index 2612e10c4606..46cff1945257 100644 --- a/barretenberg/sol/src/honk/keys/BlakeHonkVerificationKey.sol +++ b/barretenberg/sol/src/honk/keys/BlakeHonkVerificationKey.sol @@ -14,6 +14,7 @@ library BlakeHonkVerificationKey { circuitSize: uint256(32768), logCircuitSize: uint256(15), publicInputsSize: uint256(20), + vkHash: uint256(0x09d9b101f113101f439ee2f61e38edd4f0b2bfc8e55e9f5a0df7fe2408c5d82e), ql: Honk.G1Point({ x: uint256(0x1dbc2d49981f1318140ca1106a52550e1c079613c92a2b23206d1504cfb2f86b), y: uint256(0x04d743fe1aa6c0e790573ff504c0b5068b8d630459835db49d24004e0f010ad3) @@ -95,8 +96,8 @@ library BlakeHonkVerificationKey { y: uint256(0x1ba438e74f962c1b769f452da854110d0635d48e4d74d282ad06ae0e2830ac91) }), t3: Honk.G1Point({ - x: uint256(0x21313b069a809e1ab2df2a959cfd9a407933547daf0af170b0e6851d5f4e1014), - y: uint256(0x11a24ca630551e13681edd34cb75746b12ee1806cc3c2c7e670f3a1bb4f30a1f) + x: uint256(0x20d80d8e50445042431974ff13f53c27c62c17d6d2100faac252917bc2666ac1), + y: uint256(0x04bffddce3617713d52791e3344987b29b7c3359a227a03ca26857e813a84278) }), t4: Honk.G1Point({ x: uint256(0x2a0724cfe33e0ee4b3f81929ef0cd1da5e113987c9aed1534cca51dae3d9bc2d), diff --git a/barretenberg/sol/src/honk/keys/EcdsaHonkVerificationKey.sol b/barretenberg/sol/src/honk/keys/EcdsaHonkVerificationKey.sol index 32416150e400..a07ea0070619 100644 --- a/barretenberg/sol/src/honk/keys/EcdsaHonkVerificationKey.sol +++ b/barretenberg/sol/src/honk/keys/EcdsaHonkVerificationKey.sol @@ -14,6 +14,7 @@ library EcdsaHonkVerificationKey { circuitSize: uint256(65536), logCircuitSize: uint256(16), publicInputsSize: uint256(22), + vkHash: uint256(0x2fd5131e0fbfe3b7cb170c7f389581fb5cf275d176716711e3ed8accc5bfe7e2), ql: Honk.G1Point({ x: uint256(0x222da11caac0ef8c8d024bcd3ce7ef9da65cba415dc078d6c1e99efb9d296476), y: uint256(0x06b0caa4e59eeea611e3d82aa4c1be032ea48d1ebe99a2120c6b1d34ad52cad2) @@ -95,8 +96,8 @@ library EcdsaHonkVerificationKey { y: uint256(0x0cd29f3121acf9430707827d9b0805f991402d944261e1d648d9c08c7cec5475) }), t3: Honk.G1Point({ - x: uint256(0x1df7f08d004e38c6cc24155081bf68c1a6444b526bd98beea00feabc8ea337f9), - y: uint256(0x0471714279ef8a51213c70cb4fa89e73caf1ad84fa8c1447f41f6eb6bb897491) + x: uint256(0x028e38bb3aa2e17472eeeb097c9d6a2fb1249523df2ff33ba582e218e9d5a526), + y: uint256(0x0407008880940dfdef132dbcb27acc00e914e1b375c4d57c08d27202f1d99198) }), t4: Honk.G1Point({ x: uint256(0x1d794f2aaa0524cb1d97c2ff125061a697ec693323edcff93f0e5a59bcd2101d), diff --git a/barretenberg/sol/src/honk/keys/RecursiveHonkVerificationKey.sol b/barretenberg/sol/src/honk/keys/RecursiveHonkVerificationKey.sol index a3e54d72417f..3898073b962a 100644 --- a/barretenberg/sol/src/honk/keys/RecursiveHonkVerificationKey.sol +++ b/barretenberg/sol/src/honk/keys/RecursiveHonkVerificationKey.sol @@ -14,6 +14,7 @@ library RecursiveHonkVerificationKey { circuitSize: uint256(1048576), logCircuitSize: uint256(20), publicInputsSize: uint256(16), + vkHash: uint256(0x0f71347a3acbefd3925c24fbe03c70d91a785109f77dc874c8cb7ab5c7da5ce0), ql: Honk.G1Point({ x: uint256(0x2d26dcedf30775b10b7b5d23a575efd46e95045fbcafedfb05e144c2aa7edf6d), y: uint256(0x189bf6c6697af3d3a2067f655f5216cd2e97938d4797a6bfba0691fc0277fada) @@ -95,8 +96,8 @@ library RecursiveHonkVerificationKey { y: uint256(0x19f38f8e7cf18f375d75db06fca92a0cbfc1214af084c189478e34dc04c77419) }), t3: Honk.G1Point({ - x: uint256(0x15642d62fc17d119ba4afb77ab424e0a771b5bbb501c75790a1a4e2906931045), - y: uint256(0x21cea98314ec6efc5f8f1f648f42a7a5c1396036397af54a729801cc1c37d4e2) + x: uint256(0x1800723660742a70c0cc9a984e30274444a587c93d9f4742a9b96cd3572365e1), + y: uint256(0x08a91d28a9c758fed327095e282375ce84640883f7755c7d95e7ccb31cdcfd4c) }), t4: Honk.G1Point({ x: uint256(0x1f3bd0ebf0709ac30745d0dafb183cdd5b4a42e59fe1e447cad24659049d13a7), From 740a92c25f2fe72b0f9d0050132ad878f28e85df Mon Sep 17 00:00:00 2001 From: Maddiaa0 <47148561+Maddiaa0@users.noreply.github.com> Date: Sat, 26 Jul 2025 19:42:03 +0000 Subject: [PATCH 2/7] chore: remove todo --- .../cpp/src/barretenberg/ultra_honk/oink_prover.cpp | 5 +---- .../cpp/src/barretenberg/ultra_honk/oink_verifier.cpp | 6 +----- 2 files changed, 2 insertions(+), 9 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/oink_prover.cpp b/barretenberg/cpp/src/barretenberg/ultra_honk/oink_prover.cpp index 12ae4e808540..095cd9968ca4 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/oink_prover.cpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/oink_prover.cpp @@ -86,10 +86,7 @@ template void OinkProver::execute_preamble_ro { PROFILE_THIS_NAME("OinkProver::execute_preamble_round"); fr vkey_hash = honk_vk->add_hash_to_transcript(domain_separator, *transcript); - // TODO(https://github.com/AztecProtocol/barretenberg/issues/1427): Add VK FS to solidity verifier. - if constexpr (!IsAnyOf) { - vinfo("vk hash in Oink prover: ", vkey_hash); - } + vinfo("vk hash in Oink prover: ", vkey_hash); for (size_t i = 0; i < proving_key->num_public_inputs(); ++i) { auto public_input_i = proving_key->public_inputs[i]; diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/oink_verifier.cpp b/barretenberg/cpp/src/barretenberg/ultra_honk/oink_verifier.cpp index 6f0b1d3b9524..d6dd06cc241e 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/oink_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/oink_verifier.cpp @@ -46,11 +46,7 @@ template void OinkVerifier::verify() template void OinkVerifier::execute_preamble_round() { FF vkey_hash = verification_key->vk->add_hash_to_transcript(domain_separator, *transcript); - // TODO(https://github.com/AztecProtocol/barretenberg/issues/1427): Update solidity contract to generate vkey hash - // from transcript. - if constexpr (!IsAnyOf) { - vinfo("vk hash in Oink verifier: ", vkey_hash); - } + vinfo("vk hash in Oink verifier: ", vkey_hash); for (size_t i = 0; i < verification_key->vk->num_public_inputs; ++i) { auto public_input_i = From 8fef71b82d59dee84e45343ac2fdce930e2be291 Mon Sep 17 00:00:00 2001 From: Maddiaa0 <47148561+Maddiaa0@users.noreply.github.com> Date: Sat, 26 Jul 2025 19:42:26 +0000 Subject: [PATCH 3/7] chore: add doc --- .../cpp/src/barretenberg/transcript/transcript.hpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/barretenberg/cpp/src/barretenberg/transcript/transcript.hpp b/barretenberg/cpp/src/barretenberg/transcript/transcript.hpp index b9a3f65cfe8b..d93c1277ae83 100644 --- a/barretenberg/cpp/src/barretenberg/transcript/transcript.hpp +++ b/barretenberg/cpp/src/barretenberg/transcript/transcript.hpp @@ -330,7 +330,14 @@ template class BaseTranscript { */ void enable_manifest() { use_manifest = true; } - // TODO: doc + /** + * @brief Static hash method that forwards to TranscriptParams hash. + * @details This method allows hash to be called on the Transcript class directly, + * which is needed for verification key hashing. + * + * @param data Vector of field elements to hash + * @return Fr Hash result + */ static Fr hash(const std::vector& data) { return TranscriptParams::hash(data); } /** From 18f5dd531d520feb4570bced6573ca50b9f19c1a Mon Sep 17 00:00:00 2001 From: Maddiaa0 <47148561+Maddiaa0@users.noreply.github.com> Date: Sat, 26 Jul 2025 19:43:59 +0000 Subject: [PATCH 4/7] chore: scripts/cop_to_cpp.sh --- .../dsl/acir_proofs/honk_contract.hpp | 60 +++++++++---------- .../dsl/acir_proofs/honk_zk_contract.hpp | 56 +++++++++-------- 2 files changed, 54 insertions(+), 62 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_proofs/honk_contract.hpp b/barretenberg/cpp/src/barretenberg/dsl/acir_proofs/honk_contract.hpp index acf4d249112d..4dff7e79fd83 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_proofs/honk_contract.hpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_proofs/honk_contract.hpp @@ -216,6 +216,8 @@ library Honk { } struct VerificationKey { + // Hash of all of the field elements in the verification key + uint256 vkHash; // Misc Params uint256 circuitSize; uint256 logCircuitSize; @@ -342,14 +344,12 @@ library TranscriptLib { function generateTranscript( Honk.Proof memory proof, bytes32[] calldata publicInputs, - uint256 circuitSize, - uint256 publicInputsSize, - uint256 pubInputsOffset + uint256 vkHash, + uint256 publicInputsSize ) internal pure returns (Transcript memory t) { Fr previousChallenge; - (t.relationParameters, previousChallenge) = generateRelationParametersChallenges( - proof, publicInputs, circuitSize, publicInputsSize, pubInputsOffset, previousChallenge - ); + (t.relationParameters, previousChallenge) = + generateRelationParametersChallenges(proof, publicInputs, vkHash, publicInputsSize, previousChallenge); (t.alphas, previousChallenge) = generateAlphaChallenges(previousChallenge, proof); @@ -379,13 +379,12 @@ library TranscriptLib { function generateRelationParametersChallenges( Honk.Proof memory proof, bytes32[] calldata publicInputs, - uint256 circuitSize, + uint256 vkHash, uint256 publicInputsSize, - uint256 pubInputsOffset, Fr previousChallenge ) internal pure returns (Honk.RelationParameters memory rp, Fr nextPreviousChallenge) { (rp.eta, rp.etaTwo, rp.etaThree, previousChallenge) = - generateEtaChallenge(proof, publicInputs, circuitSize, publicInputsSize, pubInputsOffset); + generateEtaChallenge(proof, publicInputs, vkHash, publicInputsSize); (rp.beta, rp.gamma, nextPreviousChallenge) = generateBetaAndGammaChallenges(previousChallenge, proof); } @@ -393,36 +392,33 @@ library TranscriptLib { function generateEtaChallenge( Honk.Proof memory proof, bytes32[] calldata publicInputs, - uint256 circuitSize, - uint256 publicInputsSize, - uint256 pubInputsOffset + uint256 vkHash, + uint256 publicInputsSize ) internal pure returns (Fr eta, Fr etaTwo, Fr etaThree, Fr previousChallenge) { - bytes32[] memory round0 = new bytes32[](3 + publicInputsSize + 12); - round0[0] = bytes32(circuitSize); - round0[1] = bytes32(publicInputsSize); - round0[2] = bytes32(pubInputsOffset); + bytes32[] memory round0 = new bytes32[](1 + publicInputsSize + 12); + round0[0] = bytes32(vkHash); for (uint256 i = 0; i < publicInputsSize - PAIRING_POINTS_SIZE; i++) { - round0[3 + i] = bytes32(publicInputs[i]); + round0[1 + i] = bytes32(publicInputs[i]); } for (uint256 i = 0; i < PAIRING_POINTS_SIZE; i++) { - round0[3 + publicInputsSize - PAIRING_POINTS_SIZE + i] = FrLib.toBytes32(proof.pairingPointObject[i]); + round0[1 + publicInputsSize - PAIRING_POINTS_SIZE + i] = FrLib.toBytes32(proof.pairingPointObject[i]); } // Create the first challenge // Note: w4 is added to the challenge later on - round0[3 + publicInputsSize] = bytes32(proof.w1.x_0); - round0[3 + publicInputsSize + 1] = bytes32(proof.w1.x_1); - round0[3 + publicInputsSize + 2] = bytes32(proof.w1.y_0); - round0[3 + publicInputsSize + 3] = bytes32(proof.w1.y_1); - round0[3 + publicInputsSize + 4] = bytes32(proof.w2.x_0); - round0[3 + publicInputsSize + 5] = bytes32(proof.w2.x_1); - round0[3 + publicInputsSize + 6] = bytes32(proof.w2.y_0); - round0[3 + publicInputsSize + 7] = bytes32(proof.w2.y_1); - round0[3 + publicInputsSize + 8] = bytes32(proof.w3.x_0); - round0[3 + publicInputsSize + 9] = bytes32(proof.w3.x_1); - round0[3 + publicInputsSize + 10] = bytes32(proof.w3.y_0); - round0[3 + publicInputsSize + 11] = bytes32(proof.w3.y_1); + round0[1 + publicInputsSize] = bytes32(proof.w1.x_0); + round0[1 + publicInputsSize + 1] = bytes32(proof.w1.x_1); + round0[1 + publicInputsSize + 2] = bytes32(proof.w1.y_0); + round0[1 + publicInputsSize + 3] = bytes32(proof.w1.y_1); + round0[1 + publicInputsSize + 4] = bytes32(proof.w2.x_0); + round0[1 + publicInputsSize + 5] = bytes32(proof.w2.x_1); + round0[1 + publicInputsSize + 6] = bytes32(proof.w2.y_0); + round0[1 + publicInputsSize + 7] = bytes32(proof.w2.y_1); + round0[1 + publicInputsSize + 8] = bytes32(proof.w3.x_0); + round0[1 + publicInputsSize + 9] = bytes32(proof.w3.x_1); + round0[1 + publicInputsSize + 10] = bytes32(proof.w3.y_0); + round0[1 + publicInputsSize + 11] = bytes32(proof.w3.y_1); previousChallenge = FrLib.fromBytes32(keccak256(abi.encodePacked(round0))); (eta, etaTwo) = splitChallenge(previousChallenge); @@ -1738,9 +1734,7 @@ abstract contract BaseHonkVerifier is IVerifier { } // Generate the fiat shamir challenges for the whole protocol - Transcript memory t = TranscriptLib.generateTranscript( - p, publicInputs, vk.circuitSize, $NUM_PUBLIC_INPUTS, /*pubInputsOffset=*/ 1 - ); + Transcript memory t = TranscriptLib.generateTranscript(p, publicInputs, vk.vkHash, $NUM_PUBLIC_INPUTS); // Derive public input delta t.relationParameters.publicInputsDelta = computePublicInputDelta( diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_proofs/honk_zk_contract.hpp b/barretenberg/cpp/src/barretenberg/dsl/acir_proofs/honk_zk_contract.hpp index d9718e061173..18be9f880439 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_proofs/honk_zk_contract.hpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_proofs/honk_zk_contract.hpp @@ -216,6 +216,8 @@ library Honk { } struct VerificationKey { + // Hash of all of the field elements in the verification key + uint256 vkHash; // Misc Params uint256 circuitSize; uint256 logCircuitSize; @@ -344,13 +346,12 @@ library ZKTranscriptLib { function generateTranscript( Honk.ZKProof memory proof, bytes32[] calldata publicInputs, - uint256 circuitSize, - uint256 publicInputsSize, - uint256 pubInputsOffset + uint256 vkHash, + uint256 publicInputsSize ) external pure returns (ZKTranscript memory t) { Fr previousChallenge; (t.relationParameters, previousChallenge) = generateRelationParametersChallenges( - proof, publicInputs, circuitSize, publicInputsSize, pubInputsOffset, previousChallenge + proof, publicInputs, vkHash, publicInputsSize, previousChallenge ); (t.alphas, previousChallenge) = generateAlphaChallenges(previousChallenge, proof); @@ -380,13 +381,12 @@ library ZKTranscriptLib { function generateRelationParametersChallenges( Honk.ZKProof memory proof, bytes32[] calldata publicInputs, - uint256 circuitSize, + uint256 vkHash, uint256 publicInputsSize, - uint256 pubInputsOffset, Fr previousChallenge ) internal pure returns (Honk.RelationParameters memory rp, Fr nextPreviousChallenge) { (rp.eta, rp.etaTwo, rp.etaThree, previousChallenge) = - generateEtaChallenge(proof, publicInputs, circuitSize, publicInputsSize, pubInputsOffset); + generateEtaChallenge(proof, publicInputs, vkHash, publicInputsSize); (rp.beta, rp.gamma, nextPreviousChallenge) = generateBetaAndGammaChallenges(previousChallenge, proof); } @@ -394,35 +394,33 @@ library ZKTranscriptLib { function generateEtaChallenge( Honk.ZKProof memory proof, bytes32[] calldata publicInputs, - uint256 circuitSize, - uint256 publicInputsSize, - uint256 pubInputsOffset + uint256 vkHash, + uint256 publicInputsSize ) internal pure returns (Fr eta, Fr etaTwo, Fr etaThree, Fr previousChallenge) { - bytes32[] memory round0 = new bytes32[](3 + publicInputsSize + 12); - round0[0] = bytes32(circuitSize); - round0[1] = bytes32(publicInputsSize); - round0[2] = bytes32(pubInputsOffset); + bytes32[] memory round0 = new bytes32[](1 + publicInputsSize + 12); + round0[0] = bytes32(vkHash); + for (uint256 i = 0; i < publicInputsSize - PAIRING_POINTS_SIZE; i++) { - round0[3 + i] = bytes32(publicInputs[i]); + round0[1 + i] = bytes32(publicInputs[i]); } for (uint256 i = 0; i < PAIRING_POINTS_SIZE; i++) { - round0[3 + publicInputsSize - PAIRING_POINTS_SIZE + i] = FrLib.toBytes32(proof.pairingPointObject[i]); + round0[1 + publicInputsSize - PAIRING_POINTS_SIZE + i] = FrLib.toBytes32(proof.pairingPointObject[i]); } // Create the first challenge // Note: w4 is added to the challenge later on - round0[3 + publicInputsSize] = bytes32(proof.w1.x_0); - round0[3 + publicInputsSize + 1] = bytes32(proof.w1.x_1); - round0[3 + publicInputsSize + 2] = bytes32(proof.w1.y_0); - round0[3 + publicInputsSize + 3] = bytes32(proof.w1.y_1); - round0[3 + publicInputsSize + 4] = bytes32(proof.w2.x_0); - round0[3 + publicInputsSize + 5] = bytes32(proof.w2.x_1); - round0[3 + publicInputsSize + 6] = bytes32(proof.w2.y_0); - round0[3 + publicInputsSize + 7] = bytes32(proof.w2.y_1); - round0[3 + publicInputsSize + 8] = bytes32(proof.w3.x_0); - round0[3 + publicInputsSize + 9] = bytes32(proof.w3.x_1); - round0[3 + publicInputsSize + 10] = bytes32(proof.w3.y_0); - round0[3 + publicInputsSize + 11] = bytes32(proof.w3.y_1); + round0[1 + publicInputsSize] = bytes32(proof.w1.x_0); + round0[1 + publicInputsSize + 1] = bytes32(proof.w1.x_1); + round0[1 + publicInputsSize + 2] = bytes32(proof.w1.y_0); + round0[1 + publicInputsSize + 3] = bytes32(proof.w1.y_1); + round0[1 + publicInputsSize + 4] = bytes32(proof.w2.x_0); + round0[1 + publicInputsSize + 5] = bytes32(proof.w2.x_1); + round0[1 + publicInputsSize + 6] = bytes32(proof.w2.y_0); + round0[1 + publicInputsSize + 7] = bytes32(proof.w2.y_1); + round0[1 + publicInputsSize + 8] = bytes32(proof.w3.x_0); + round0[1 + publicInputsSize + 9] = bytes32(proof.w3.x_1); + round0[1 + publicInputsSize + 10] = bytes32(proof.w3.y_0); + round0[1 + publicInputsSize + 11] = bytes32(proof.w3.y_1); previousChallenge = FrLib.fromBytes32(keccak256(abi.encodePacked(round0))); (eta, etaTwo) = splitChallenge(previousChallenge); @@ -1809,7 +1807,7 @@ abstract contract BaseZKHonkVerifier is IVerifier { // Generate the fiat shamir challenges for the whole protocol ZKTranscript memory t = ZKTranscriptLib.generateTranscript( - p, publicInputs, vk.circuitSize, $NUM_PUBLIC_INPUTS, /*pubInputsOffset=*/ 1 + p, publicInputs, vk.vkHash, $NUM_PUBLIC_INPUTS ); // Derive public input delta From b2430f03b2493e9a88f4ff28015a167bf60eadc3 Mon Sep 17 00:00:00 2001 From: Maddiaa0 <47148561+Maddiaa0@users.noreply.github.com> Date: Sat, 26 Jul 2025 22:44:50 +0000 Subject: [PATCH 5/7] fix: key consistency test --- .../barretenberg/flavor/native_verification_key.test.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) 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 0aa8110ddc1a..d008b67a1e8c 100644 --- a/barretenberg/cpp/src/barretenberg/flavor/native_verification_key.test.cpp +++ b/barretenberg/cpp/src/barretenberg/flavor/native_verification_key.test.cpp @@ -68,12 +68,13 @@ TYPED_TEST(NativeVerificationKeyTests, VKHashingConsistency) { using Flavor = TypeParam; using VerificationKey = typename Flavor::VerificationKey; + using Transcript = typename Flavor::Transcript; VerificationKey vk(TestFixture::create_vk()); // First method of hashing: using to_field_elements and add_to_hash_buffer. std::vector vk_field_elements = vk.to_field_elements(); - NativeTranscript transcript; + Transcript transcript; for (const auto& field_element : vk_field_elements) { transcript.add_to_independent_hash_buffer("vk_element", field_element); } @@ -81,9 +82,7 @@ TYPED_TEST(NativeVerificationKeyTests, VKHashingConsistency) // Second method of hashing: using hash(). fr vkey_hash_2 = vk.hash(); EXPECT_EQ(vkey_hash_1, vkey_hash_2); - // TODO(https://github.com/AztecProtocol/barretenberg/issues/1427): Solidity verifier does not fiat shamir the full - // verification key. This will be fixed in a followup PR. - if constexpr (!IsAnyOf) { + if constexpr (!IsAnyOf) { // Third method of hashing: using add_hash_to_transcript. typename Flavor::Transcript transcript_2; fr vkey_hash_3 = vk.add_hash_to_transcript("", transcript_2); From 04114b77c1a44eb1e1c6352d052cdfb2b5a809ea Mon Sep 17 00:00:00 2001 From: Maddiaa0 <47148561+Maddiaa0@users.noreply.github.com> Date: Sat, 26 Jul 2025 22:53:42 +0000 Subject: [PATCH 6/7] fix: ultra transcript test --- .../src/barretenberg/ultra_honk/ultra_transcript.test.cpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/ultra_transcript.test.cpp b/barretenberg/cpp/src/barretenberg/ultra_honk/ultra_transcript.test.cpp index 9a670c375fe3..c0ec90e28bf5 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/ultra_transcript.test.cpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/ultra_transcript.test.cpp @@ -67,10 +67,7 @@ template class UltraTranscriptTests : public ::testing::Test { if constexpr (!IsAnyOf) { manifest_expected.add_entry(round, "vk_hash", frs_per_Fr); } else { - size_t frs_per_uint32 = bb::field_conversion::calc_num_bn254_frs(); - manifest_expected.add_entry(round, "vk_log_circuit_size", frs_per_uint32); - manifest_expected.add_entry(round, "vk_num_public_inputs", frs_per_uint32); - manifest_expected.add_entry(round, "vk_pub_inputs_offset", frs_per_uint32); + manifest_expected.add_entry(round, "vk_hash", 1); } manifest_expected.add_entry(round, "public_input_0", frs_per_Fr); From c8fdc265bb3fa42d7128cb6c82de06fc370927d9 Mon Sep 17 00:00:00 2001 From: Maddiaa0 <47148561+Maddiaa0@users.noreply.github.com> Date: Sun, 27 Jul 2025 14:06:07 +0000 Subject: [PATCH 7/7] chore: apply vk hash to optimized contract --- .../dsl/acir_proofs/honk_optimized_contract.hpp | 16 ++++++++-------- .../sol/scripts/copy_optimized_to_cpp.sh | 13 +++++++------ .../sol/src/honk/optimised/blake-opt.sol | 15 +++++++-------- 3 files changed, 22 insertions(+), 22 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_proofs/honk_optimized_contract.hpp b/barretenberg/cpp/src/barretenberg/dsl/acir_proofs/honk_optimized_contract.hpp index 27124dbcbaf3..06b6cd527711 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_proofs/honk_optimized_contract.hpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_proofs/honk_optimized_contract.hpp @@ -34,6 +34,7 @@ uint256 constant NUMBER_UNSHIFTED = 36; uint256 constant NUMBER_TO_BE_SHIFTED = 5; uint256 constant PAIRING_POINTS_SIZE = 16; +uint256 constant VK_HASH = {{ VK_HASH }}; uint256 constant CIRCUIT_SIZE = {{ CIRCUIT_SIZE }}; uint256 constant LOG_N = {{ LOG_CIRCUIT_SIZE }}; uint256 constant NUMBER_PUBLIC_INPUTS = {{ NUM_PUBLIC_INPUTS }}; @@ -1343,21 +1344,19 @@ contract HonkVerifier is IVerifier { // Note: can be mcpyed from proof // TODO: work what memory can be used here - if we use 0 solidity at all we can get // away with ignoring free memory practices entirely - mstore(0x00, CIRCUIT_SIZE) - mstore(0x20, NUMBER_PUBLIC_INPUTS) - mstore(0x40, PUBLIC_INPUTS_OFFSET) + mstore(0x00, VK_HASH) let public_inputs_start := add(calldataload(0x24), 0x24) let public_inputs_size := mul(REAL_NUMBER_PUBLIC_INPUTS, 0x20) // Copy the public inputs into the eta buffer - calldatacopy(0x60, public_inputs_start, public_inputs_size) + calldatacopy(0x20, public_inputs_start, public_inputs_size) // Copy Pairing points into eta buffer - let public_inputs_end := add(0x60, public_inputs_size) + let public_inputs_end := add(0x20, public_inputs_size) mcopy(public_inputs_end, PAIRING_POINT_0, 0x200) - // 0x1e0 = 3 * 32 bytes + 4 * 96 bytes for (w1,w2,w3) + 0x200 for pairing points - let eta_input_length := add(0x3e0, public_inputs_size) + // 0x1e0 = 1 * 32 bytes + 4 * 96 bytes for (w1,w2,w3) + 0x200 for pairing points + let eta_input_length := add(0x3a0, public_inputs_size) ///////////////////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -1377,7 +1376,7 @@ contract HonkVerifier is IVerifier { // Note: size will change once proof points are made smaller for keccak flavor // Right now it is 0x20 * 16 - should be 8 // End of public inputs + pairing point - mcopy(add(0x260, public_inputs_size), W_L_X0_LOC, 0x1a0) + mcopy(add(0x220, public_inputs_size), W_L_X0_LOC, 0x1a0) let prev_challenge := mod(keccak256(0x00, eta_input_length), p) mstore(0x00, prev_challenge) @@ -4231,6 +4230,7 @@ inline std::string get_optimized_honk_solidity_verifier(auto const& verification } }; + set_template_param("VK_HASH", field_to_hex(verification_key->hash())); set_template_param("CIRCUIT_SIZE", std::to_string(1 << verification_key->log_circuit_size)); set_template_param("LOG_CIRCUIT_SIZE", std::to_string(verification_key->log_circuit_size)); set_template_param("NUM_PUBLIC_INPUTS", std::to_string(verification_key->num_public_inputs)); diff --git a/barretenberg/sol/scripts/copy_optimized_to_cpp.sh b/barretenberg/sol/scripts/copy_optimized_to_cpp.sh index f39397968399..0a372ae88261 100755 --- a/barretenberg/sol/scripts/copy_optimized_to_cpp.sh +++ b/barretenberg/sol/scripts/copy_optimized_to_cpp.sh @@ -60,11 +60,12 @@ trap "rm -f $TEMP_CPP $TEMP_SOL $TEMP_PROCESSED $FINAL_SOL" EXIT # First, copy blake-opt.sol to a temp file for processing cp "$SOL_SRC_FILE" "$TEMP_SOL" -# Replace the hardcoded constants with template placeholders -sed -i 's/uint256 constant CIRCUIT_SIZE = 32768;/uint256 constant CIRCUIT_SIZE = {{ CIRCUIT_SIZE }};/' "$TEMP_SOL" -sed -i 's/uint256 constant LOG_N = 15;/uint256 constant LOG_N = {{ LOG_CIRCUIT_SIZE }};/' "$TEMP_SOL" -sed -i 's/uint256 constant NUMBER_PUBLIC_INPUTS = 20;/uint256 constant NUMBER_PUBLIC_INPUTS = {{ NUM_PUBLIC_INPUTS }};/' "$TEMP_SOL" -sed -i 's/uint256 constant REAL_NUMBER_PUBLIC_INPUTS = 20 - 16;/uint256 constant REAL_NUMBER_PUBLIC_INPUTS = {{ NUM_PUBLIC_INPUTS }} - 16;/' "$TEMP_SOL" +# Replace the hardcoded constants with template placeholders using regex patterns +sed -i -E 's/(uint256 constant VK_HASH = )0x[0-9a-fA-F]+;/\1{{ VK_HASH }};/' "$TEMP_SOL" +sed -i -E 's/(uint256 constant CIRCUIT_SIZE = )[0-9]+;/\1{{ CIRCUIT_SIZE }};/' "$TEMP_SOL" +sed -i -E 's/(uint256 constant LOG_N = )[0-9]+;/\1{{ LOG_CIRCUIT_SIZE }};/' "$TEMP_SOL" +sed -i -E 's/(uint256 constant NUMBER_PUBLIC_INPUTS = )[0-9]+;/\1{{ NUM_PUBLIC_INPUTS }};/' "$TEMP_SOL" +sed -i -E 's/(uint256 constant REAL_NUMBER_PUBLIC_INPUTS = )[0-9]+ - [0-9]+;/\1{{ NUM_PUBLIC_INPUTS }} - 16;/' "$TEMP_SOL" # Replace the contract name sed -i 's/contract BlakeOptHonkVerifier/contract HonkVerifier/' "$TEMP_SOL" @@ -76,7 +77,7 @@ awk ' print next } - + # For all other lines, replace the _14 values with templates { gsub(/POWERS_OF_EVALUATION_CHALLENGE_14_LOC/, "POWERS_OF_EVALUATION_CHALLENGE_{{ LOG_N_MINUS_ONE }}_LOC") diff --git a/barretenberg/sol/src/honk/optimised/blake-opt.sol b/barretenberg/sol/src/honk/optimised/blake-opt.sol index d7c90b328404..66b2e53a58de 100644 --- a/barretenberg/sol/src/honk/optimised/blake-opt.sol +++ b/barretenberg/sol/src/honk/optimised/blake-opt.sol @@ -12,6 +12,7 @@ uint256 constant NUMBER_UNSHIFTED = 36; uint256 constant NUMBER_TO_BE_SHIFTED = 5; uint256 constant PAIRING_POINTS_SIZE = 16; +uint256 constant VK_HASH = 0x09d9b101f113101f439ee2f61e38edd4f0b2bfc8e55e9f5a0df7fe2408c5d82e; uint256 constant CIRCUIT_SIZE = 32768; uint256 constant LOG_N = 15; uint256 constant NUMBER_PUBLIC_INPUTS = 20; @@ -1321,21 +1322,19 @@ contract BlakeOptHonkVerifier is IVerifier { // Note: can be mcpyed from proof // TODO: work what memory can be used here - if we use 0 solidity at all we can get // away with ignoring free memory practices entirely - mstore(0x00, CIRCUIT_SIZE) - mstore(0x20, NUMBER_PUBLIC_INPUTS) - mstore(0x40, PUBLIC_INPUTS_OFFSET) + mstore(0x00, VK_HASH) let public_inputs_start := add(calldataload(0x24), 0x24) let public_inputs_size := mul(REAL_NUMBER_PUBLIC_INPUTS, 0x20) // Copy the public inputs into the eta buffer - calldatacopy(0x60, public_inputs_start, public_inputs_size) + calldatacopy(0x20, public_inputs_start, public_inputs_size) // Copy Pairing points into eta buffer - let public_inputs_end := add(0x60, public_inputs_size) + let public_inputs_end := add(0x20, public_inputs_size) mcopy(public_inputs_end, PAIRING_POINT_0, 0x200) - // 0x1e0 = 3 * 32 bytes + 4 * 96 bytes for (w1,w2,w3) + 0x200 for pairing points - let eta_input_length := add(0x3e0, public_inputs_size) + // 0x1e0 = 1 * 32 bytes + 4 * 96 bytes for (w1,w2,w3) + 0x200 for pairing points + let eta_input_length := add(0x3a0, public_inputs_size) ///////////////////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -1355,7 +1354,7 @@ contract BlakeOptHonkVerifier is IVerifier { // Note: size will change once proof points are made smaller for keccak flavor // Right now it is 0x20 * 16 - should be 8 // End of public inputs + pairing point - mcopy(add(0x260, public_inputs_size), W_L_X0_LOC, 0x1a0) + mcopy(add(0x220, public_inputs_size), W_L_X0_LOC, 0x1a0) let prev_challenge := mod(keccak256(0x00, eta_input_length), p) mstore(0x00, prev_challenge)