From 1a83cd26f7f8c4163d538f942677dcea7f2bc8dc Mon Sep 17 00:00:00 2001 From: maramihali Date: Wed, 5 Feb 2025 12:26:46 +0000 Subject: [PATCH] feat: report wrong proof length in the verifier contract (#11728) Make the error explicit when we test the deployed honk verifier contracts with the wrong proof length by looking at the length member of the calldata proof received as input. --- barretenberg/acir_tests/sol-test/src/index.js | 6 +++++- .../src/barretenberg/dsl/acir_proofs/honk_contract.hpp | 9 +++++++++ .../barretenberg/dsl/acir_proofs/honk_zk_contract.hpp | 8 ++++++++ barretenberg/sol/src/honk/BaseHonkVerifier.sol | 9 +++++++++ barretenberg/sol/src/honk/BaseZKHonkVerifier.sol | 9 +++++++++ 5 files changed, 40 insertions(+), 1 deletion(-) diff --git a/barretenberg/acir_tests/sol-test/src/index.js b/barretenberg/acir_tests/sol-test/src/index.js index 465b309042a..7800eeabe0b 100644 --- a/barretenberg/acir_tests/sol-test/src/index.js +++ b/barretenberg/acir_tests/sol-test/src/index.js @@ -9,6 +9,7 @@ const NUMBER_OF_FIELDS_IN_PLONK_PROOF = 93; const NUMBER_OF_FIELDS_IN_HONK_PROOF = 443; const NUMBER_OF_FIELDS_IN_HONK_ZK_PROOF = 494; +const WRONG_PROOF_LENGTH = "0xed74ac0a"; const WRONG_PUBLIC_INPUTS_LENGTH = "0xfa066593"; const SUMCHECK_FAILED = "0x9fc3a218"; const SHPLEMINI_FAILED = "0xa5d82e8a"; @@ -60,7 +61,6 @@ const testingHonk = getEnvVarCanBeUndefined("TESTING_HONK"); const hasZK = getEnvVarCanBeUndefined("HAS_ZK"); const verifierContract = hasZK ? "ZKVerifier.sol" : "Verifier.sol"; -console.log(verifierContract); export const compilationInput = { language: "Solidity", sources: { @@ -260,6 +260,10 @@ try { if (testingHonk) { var errorType = e.data; switch (errorType) { + case WRONG_PROOF_LENGTH: + throw new Error( + "Proof length wrong. Check the constant and the proof surgery." + ); case WRONG_PUBLIC_INPUTS_LENGTH: throw new Error("Number of inputs in the proof is wrong"); case SUMCHECK_FAILED: 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 5cc27bc8868..c18cf1f311a 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_proofs/honk_contract.hpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_proofs/honk_contract.hpp @@ -1430,13 +1430,22 @@ abstract contract BaseHonkVerifier is IVerifier { numPublicInputs = _numPublicInputs; } + error ProofLengthWrong(); error PublicInputsLengthWrong(); error SumcheckFailed(); error ShpleminiFailed(); + // Number of field elements in a ultra honk zero knowledge proof + uint256 constant PROOF_SIZE = 443; + function loadVerificationKey() internal pure virtual returns (Honk.VerificationKey memory); function verify(bytes calldata proof, bytes32[] calldata publicInputs) public view override returns (bool) { + // Check the received proof is the expected size where each field element is 32 bytes + if (proof.length != PROOF_SIZE * 32) { + revert ProofLengthWrong(); + } + Honk.VerificationKey memory vk = loadVerificationKey(); Honk.Proof memory p = TranscriptLib.loadProof(proof); 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 92a4cd944e0..4e5eef6c2c6 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 @@ -1489,13 +1489,21 @@ interface IVerifier { // Errors + error ProofLengthWrong(); error PublicInputsLengthWrong(); error SumcheckFailed(); error ShpleminiFailed(); error GeminiChallengeInSubgroup(); error ConsistencyCheckFailed(); + uint256 constant PROOF_SIZE = 494; + function verify(bytes calldata proof, bytes32[] calldata publicInputs) public view override returns (bool verified) { + // Check the received proof is the expected size where each field element is 32 bytes + if (proof.length != PROOF_SIZE * 32) { + revert ProofLengthWrong(); + } + Honk.VerificationKey memory vk = loadVerificationKey(); Honk.ZKProof memory p = ZKTranscriptLib.loadProof(proof); diff --git a/barretenberg/sol/src/honk/BaseHonkVerifier.sol b/barretenberg/sol/src/honk/BaseHonkVerifier.sol index fc20594bddd..d6ad628b1de 100644 --- a/barretenberg/sol/src/honk/BaseHonkVerifier.sol +++ b/barretenberg/sol/src/honk/BaseHonkVerifier.sol @@ -39,13 +39,22 @@ abstract contract BaseHonkVerifier is IVerifier { } // Errors + error ProofLengthWrong(); error PublicInputsLengthWrong(); error SumcheckFailed(); error ShpleminiFailed(); + // Number of field elements in a ultra honk proof + uint256 constant PROOF_SIZE = 443; + function loadVerificationKey() internal pure virtual returns (Honk.VerificationKey memory); function verify(bytes calldata proof, bytes32[] calldata publicInputs) public view override returns (bool) { + // Check the received proof is the expected size where each field element is 32 bytes + if (proof.length != PROOF_SIZE * 32) { + revert ProofLengthWrong(); + } + Honk.VerificationKey memory vk = loadVerificationKey(); Honk.Proof memory p = TranscriptLib.loadProof(proof); if (publicInputs.length != vk.publicInputsSize) { diff --git a/barretenberg/sol/src/honk/BaseZKHonkVerifier.sol b/barretenberg/sol/src/honk/BaseZKHonkVerifier.sol index fee12422171..b93f6711741 100644 --- a/barretenberg/sol/src/honk/BaseZKHonkVerifier.sol +++ b/barretenberg/sol/src/honk/BaseZKHonkVerifier.sol @@ -41,12 +41,16 @@ abstract contract BaseZKHonkVerifier is IVerifier { } // Errors + error ProofLengthWrong(); error PublicInputsLengthWrong(); error SumcheckFailed(); error ShpleminiFailed(); error GeminiChallengeInSubgroup(); error ConsistencyCheckFailed(); + // Number of field elements in a ultra honk zero knowledge proof + uint256 constant PROOF_SIZE = 494; + function loadVerificationKey() internal pure virtual returns (Honk.VerificationKey memory); function verify(bytes calldata proof, bytes32[] calldata publicInputs) @@ -55,6 +59,11 @@ abstract contract BaseZKHonkVerifier is IVerifier { override returns (bool verified) { + // Check the received proof is the expected size where each field element is 32 bytes + if (proof.length != PROOF_SIZE * 32) { + revert ProofLengthWrong(); + } + Honk.VerificationKey memory vk = loadVerificationKey(); Honk.ZKProof memory p = ZKTranscriptLib.loadProof(proof);