From caadfe402f06fdc8664d5c9d3a2449f221186330 Mon Sep 17 00:00:00 2001 From: TomAFrench Date: Tue, 6 Feb 2024 14:26:38 +0000 Subject: [PATCH 1/6] feat: verify points in verification key on contract deployment --- .../sol/src/ultra/BaseUltraVerifier.sol | 274 +++++++++++++++--- 1 file changed, 228 insertions(+), 46 deletions(-) diff --git a/barretenberg/sol/src/ultra/BaseUltraVerifier.sol b/barretenberg/sol/src/ultra/BaseUltraVerifier.sol index e00052d6a8e..3ac5638d844 100644 --- a/barretenberg/sol/src/ultra/BaseUltraVerifier.sol +++ b/barretenberg/sol/src/ultra/BaseUltraVerifier.sol @@ -260,6 +260,7 @@ abstract contract BaseUltraVerifier { uint256 internal constant NU_CHALLENGE_INPUT_LOC_B = 0x37c0; uint256 internal constant NU_CHALLENGE_INPUT_LOC_C = 0x37e0; + bytes4 internal constant INVALID_VERIFICATION_KEY_SELECTOR = 0x7e5769bf; bytes4 internal constant PUBLIC_INPUT_INVALID_BN128_G1_POINT_SELECTOR = 0xeba9f4a6; bytes4 internal constant PUBLIC_INPUT_GE_P_SELECTOR = 0x374a972f; bytes4 internal constant MOD_EXP_FAILURE_SELECTOR = 0xf894a7bc; @@ -289,6 +290,7 @@ abstract contract BaseUltraVerifier { // for Grumpkin, a = 0 and b = -17. We use b in a custom gate relation that evaluates elliptic curve arithmetic uint256 internal constant GRUMPKIN_CURVE_B_PARAMETER_NEGATED = 17; + error INVALID_VERIFICATION_KEY(); error PUBLIC_INPUT_COUNT_INVALID(uint256 expected, uint256 actual); error PUBLIC_INPUT_INVALID_BN128_G1_POINT(); error PUBLIC_INPUT_GE_P(); @@ -300,6 +302,209 @@ abstract contract BaseUltraVerifier { function loadVerificationKey(uint256 _vk, uint256 _omegaInverseLoc) internal pure virtual; + constructor() { + loadVerificationKey(N_LOC, OMEGA_INVERSE_LOC); + + // We verify that all of the EC points in the verification key lie on the bn254 curve. + assembly { + let q := 21888242871839275222246405745257275088696311157297823662689037894645226208583 // EC group order + + let success := 1 + + // VALIDATE Q1 + { + let x := mload(Q1_X_LOC) + let y := mload(Q1_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + } + // VALIDATE Q2 + { + let x := mload(Q2_X_LOC) + let y := mload(Q2_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + } + // VALIDATE Q3 + { + let x := mload(Q3_X_LOC) + let y := mload(Q3_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + } + // VALIDATE Q4 + { + let x := mload(Q4_X_LOC) + let y := mload(Q4_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + mstore(0x00, x) + mstore(0x20, y) + } + // VALIDATE QM + { + let x := mload(QM_X_LOC) + let y := mload(QM_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + } + // VALIDATE QC + { + let x := mload(QC_X_LOC) + let y := mload(QC_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + } + // VALIDATE QARITH + { + let x := mload(QARITH_X_LOC) + let y := mload(QARITH_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + } + // VALIDATE QSORT + { + let x := mload(QSORT_X_LOC) + let y := mload(QSORT_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + } + // VALIDATE QELLIPTIC + { + let x := mload(QELLIPTIC_X_LOC) + let y := mload(QELLIPTIC_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + } + // VALIDATE QAUX + { + let x := mload(QAUX_X_LOC) + let y := mload(QAUX_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + } + // VALIDATE SIGMA1 + { + let x := mload(SIGMA1_X_LOC) + let y := mload(SIGMA1_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + } + // VALIDATE SIGMA2 + { + let x := mload(SIGMA2_X_LOC) + let y := mload(SIGMA2_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + } + // VALIDATE SIGMA3 + { + let x := mload(SIGMA3_X_LOC) + let y := mload(SIGMA3_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + } + // VALIDATE SIGMA4 + { + let x := mload(SIGMA4_X_LOC) + let y := mload(SIGMA4_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + } + // VALIDATE TABLE1 + { + let x := mload(TABLE1_X_LOC) + let y := mload(TABLE1_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + } + // VALIDATE TABLE2 + { + let x := mload(TABLE2_X_LOC) + let y := mload(TABLE2_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + } + // VALIDATE TABLE3 + { + let x := mload(TABLE3_X_LOC) + let y := mload(TABLE3_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + } + // VALIDATE TABLE4 + { + let x := mload(TABLE4_X_LOC) + let y := mload(TABLE4_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + } + // VALIDATE TABLE_TYPE + { + let x := mload(TABLE_TYPE_X_LOC) + let y := mload(TABLE_TYPE_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + } + // VALIDATE ID1 + { + let x := mload(ID1_X_LOC) + let y := mload(ID1_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + } + // VALIDATE ID2 + { + let x := mload(ID2_X_LOC) + let y := mload(ID2_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + } + // VALIDATE ID3 + { + let x := mload(ID3_X_LOC) + let y := mload(ID3_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + } + // VALIDATE ID4 + { + let x := mload(ID4_X_LOC) + let y := mload(ID4_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + } + + if iszero(success) { + mstore(0x0, INVALID_VERIFICATION_KEY_SELECTOR) + revert(0x00, 0x04) + } + } + } + /** * @notice Verify a Ultra Plonk proof * @param _proof - The serialized proof @@ -1864,8 +2069,7 @@ abstract contract BaseUltraVerifier { let x := mload(Q1_X_LOC) let y := mload(Q1_Y_LOC) let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + // Verification key fields verified to be on curve at contract deployment mstore(0x00, x) mstore(0x20, y) } @@ -1880,8 +2084,7 @@ abstract contract BaseUltraVerifier { let x := mload(Q2_X_LOC) let y := mload(Q2_Y_LOC) let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + // Verification key fields verified to be on curve at contract deployment mstore(0x00, x) mstore(0x20, y) } @@ -1896,8 +2099,7 @@ abstract contract BaseUltraVerifier { let x := mload(Q3_X_LOC) let y := mload(Q3_Y_LOC) let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + // Verification key fields verified to be on curve at contract deployment mstore(0x00, x) mstore(0x20, y) } @@ -1912,8 +2114,7 @@ abstract contract BaseUltraVerifier { let x := mload(Q4_X_LOC) let y := mload(Q4_Y_LOC) let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + // Verification key fields verified to be on curve at contract deployment mstore(0x00, x) mstore(0x20, y) } @@ -1928,8 +2129,7 @@ abstract contract BaseUltraVerifier { let x := mload(QM_X_LOC) let y := mload(QM_Y_LOC) let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + // Verification key fields verified to be on curve at contract deployment mstore(0x00, x) mstore(0x20, y) } @@ -1944,8 +2144,7 @@ abstract contract BaseUltraVerifier { let x := mload(QC_X_LOC) let y := mload(QC_Y_LOC) let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + // Verification key fields verified to be on curve at contract deployment mstore(0x00, x) mstore(0x20, y) } @@ -1960,8 +2159,7 @@ abstract contract BaseUltraVerifier { let x := mload(QARITH_X_LOC) let y := mload(QARITH_Y_LOC) let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + // Verification key fields verified to be on curve at contract deployment mstore(0x00, x) mstore(0x20, y) } @@ -1976,8 +2174,7 @@ abstract contract BaseUltraVerifier { let x := mload(QSORT_X_LOC) let y := mload(QSORT_Y_LOC) let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + // Verification key fields verified to be on curve at contract deployment mstore(0x00, x) mstore(0x20, y) } @@ -1992,8 +2189,7 @@ abstract contract BaseUltraVerifier { let x := mload(QELLIPTIC_X_LOC) let y := mload(QELLIPTIC_Y_LOC) let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + // Verification key fields verified to be on curve at contract deployment mstore(0x00, x) mstore(0x20, y) } @@ -2008,8 +2204,7 @@ abstract contract BaseUltraVerifier { let x := mload(QAUX_X_LOC) let y := mload(QAUX_Y_LOC) let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + // Verification key fields verified to be on curve at contract deployment mstore(0x00, x) mstore(0x20, y) } @@ -2024,8 +2219,7 @@ abstract contract BaseUltraVerifier { let x := mload(SIGMA1_X_LOC) let y := mload(SIGMA1_Y_LOC) let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + // Verification key fields verified to be on curve at contract deployment mstore(0x00, x) mstore(0x20, y) } @@ -2040,8 +2234,7 @@ abstract contract BaseUltraVerifier { let x := mload(SIGMA2_X_LOC) let y := mload(SIGMA2_Y_LOC) let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + // Verification key fields verified to be on curve at contract deployment mstore(0x00, x) mstore(0x20, y) } @@ -2056,8 +2249,7 @@ abstract contract BaseUltraVerifier { let x := mload(SIGMA3_X_LOC) let y := mload(SIGMA3_Y_LOC) let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + // Verification key fields verified to be on curve at contract deployment mstore(0x00, x) mstore(0x20, y) } @@ -2072,8 +2264,7 @@ abstract contract BaseUltraVerifier { let x := mload(SIGMA4_X_LOC) let y := mload(SIGMA4_Y_LOC) let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + // Verification key fields verified to be on curve at contract deployment mstore(0x00, x) mstore(0x20, y) } @@ -2088,8 +2279,7 @@ abstract contract BaseUltraVerifier { let x := mload(TABLE1_X_LOC) let y := mload(TABLE1_Y_LOC) let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + // Verification key fields verified to be on curve at contract deployment mstore(0x00, x) mstore(0x20, y) } @@ -2104,8 +2294,7 @@ abstract contract BaseUltraVerifier { let x := mload(TABLE2_X_LOC) let y := mload(TABLE2_Y_LOC) let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + // Verification key fields verified to be on curve at contract deployment mstore(0x00, x) mstore(0x20, y) } @@ -2120,8 +2309,7 @@ abstract contract BaseUltraVerifier { let x := mload(TABLE3_X_LOC) let y := mload(TABLE3_Y_LOC) let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + // Verification key fields verified to be on curve at contract deployment mstore(0x00, x) mstore(0x20, y) } @@ -2136,8 +2324,7 @@ abstract contract BaseUltraVerifier { let x := mload(TABLE4_X_LOC) let y := mload(TABLE4_Y_LOC) let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + // Verification key fields verified to be on curve at contract deployment mstore(0x00, x) mstore(0x20, y) } @@ -2152,8 +2339,7 @@ abstract contract BaseUltraVerifier { let x := mload(TABLE_TYPE_X_LOC) let y := mload(TABLE_TYPE_Y_LOC) let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + // Verification key fields verified to be on curve at contract deployment mstore(0x00, x) mstore(0x20, y) } @@ -2168,8 +2354,7 @@ abstract contract BaseUltraVerifier { let x := mload(ID1_X_LOC) let y := mload(ID1_Y_LOC) let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + // Verification key fields verified to be on curve at contract deployment mstore(0x00, x) mstore(0x20, y) } @@ -2184,8 +2369,7 @@ abstract contract BaseUltraVerifier { let x := mload(ID2_X_LOC) let y := mload(ID2_Y_LOC) let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + // Verification key fields verified to be on curve at contract deployment mstore(0x00, x) mstore(0x20, y) } @@ -2200,8 +2384,7 @@ abstract contract BaseUltraVerifier { let x := mload(ID3_X_LOC) let y := mload(ID3_Y_LOC) let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + // Verification key fields verified to be on curve at contract deployment mstore(0x00, x) mstore(0x20, y) } @@ -2216,8 +2399,7 @@ abstract contract BaseUltraVerifier { let x := mload(ID4_X_LOC) let y := mload(ID4_Y_LOC) let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + // Verification key fields verified to be on curve at contract deployment mstore(0x00, x) mstore(0x20, y) } From c66cdf9299c94393fe767f05e18634ac35258b5e Mon Sep 17 00:00:00 2001 From: TomAFrench Date: Tue, 6 Feb 2024 14:28:58 +0000 Subject: [PATCH 2/6] chore: update contract source in cpp --- .../barretenberg/dsl/acir_proofs/contract.hpp | 275 +++++++++++++++--- 1 file changed, 229 insertions(+), 46 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_proofs/contract.hpp b/barretenberg/cpp/src/barretenberg/dsl/acir_proofs/contract.hpp index a40c775ab4d..19e1ba63048 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_proofs/contract.hpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_proofs/contract.hpp @@ -263,6 +263,7 @@ abstract contract BaseUltraVerifier { uint256 internal constant NU_CHALLENGE_INPUT_LOC_B = 0x37c0; uint256 internal constant NU_CHALLENGE_INPUT_LOC_C = 0x37e0; + bytes4 internal constant INVALID_VERIFICATION_KEY_SELECTOR = 0x7e5769bf; bytes4 internal constant PUBLIC_INPUT_INVALID_BN128_G1_POINT_SELECTOR = 0xeba9f4a6; bytes4 internal constant PUBLIC_INPUT_GE_P_SELECTOR = 0x374a972f; bytes4 internal constant MOD_EXP_FAILURE_SELECTOR = 0xf894a7bc; @@ -291,6 +292,8 @@ abstract contract BaseUltraVerifier { // y^2 = x^3 + ax + b // for Grumpkin, a = 0 and b = -17. We use b in a custom gate relation that evaluates elliptic curve arithmetic uint256 internal constant GRUMPKIN_CURVE_B_PARAMETER_NEGATED = 17; + + error INVALID_VERIFICATION_KEY(); error PUBLIC_INPUT_COUNT_INVALID(uint256 expected, uint256 actual); error PUBLIC_INPUT_INVALID_BN128_G1_POINT(); error PUBLIC_INPUT_GE_P(); @@ -302,6 +305,209 @@ abstract contract BaseUltraVerifier { function loadVerificationKey(uint256 _vk, uint256 _omegaInverseLoc) internal pure virtual; + constructor() { + loadVerificationKey(N_LOC, OMEGA_INVERSE_LOC); + + // We verify that all of the EC points in the verification key lie on the bn254 curve. + assembly { + let q := 21888242871839275222246405745257275088696311157297823662689037894645226208583 // EC group order + + let success := 1 + + // VALIDATE Q1 + { + let x := mload(Q1_X_LOC) + let y := mload(Q1_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + } + // VALIDATE Q2 + { + let x := mload(Q2_X_LOC) + let y := mload(Q2_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + } + // VALIDATE Q3 + { + let x := mload(Q3_X_LOC) + let y := mload(Q3_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + } + // VALIDATE Q4 + { + let x := mload(Q4_X_LOC) + let y := mload(Q4_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + mstore(0x00, x) + mstore(0x20, y) + } + // VALIDATE QM + { + let x := mload(QM_X_LOC) + let y := mload(QM_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + } + // VALIDATE QC + { + let x := mload(QC_X_LOC) + let y := mload(QC_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + } + // VALIDATE QARITH + { + let x := mload(QARITH_X_LOC) + let y := mload(QARITH_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + } + // VALIDATE QSORT + { + let x := mload(QSORT_X_LOC) + let y := mload(QSORT_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + } + // VALIDATE QELLIPTIC + { + let x := mload(QELLIPTIC_X_LOC) + let y := mload(QELLIPTIC_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + } + // VALIDATE QAUX + { + let x := mload(QAUX_X_LOC) + let y := mload(QAUX_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + } + // VALIDATE SIGMA1 + { + let x := mload(SIGMA1_X_LOC) + let y := mload(SIGMA1_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + } + // VALIDATE SIGMA2 + { + let x := mload(SIGMA2_X_LOC) + let y := mload(SIGMA2_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + } + // VALIDATE SIGMA3 + { + let x := mload(SIGMA3_X_LOC) + let y := mload(SIGMA3_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + } + // VALIDATE SIGMA4 + { + let x := mload(SIGMA4_X_LOC) + let y := mload(SIGMA4_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + } + // VALIDATE TABLE1 + { + let x := mload(TABLE1_X_LOC) + let y := mload(TABLE1_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + } + // VALIDATE TABLE2 + { + let x := mload(TABLE2_X_LOC) + let y := mload(TABLE2_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + } + // VALIDATE TABLE3 + { + let x := mload(TABLE3_X_LOC) + let y := mload(TABLE3_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + } + // VALIDATE TABLE4 + { + let x := mload(TABLE4_X_LOC) + let y := mload(TABLE4_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + } + // VALIDATE TABLE_TYPE + { + let x := mload(TABLE_TYPE_X_LOC) + let y := mload(TABLE_TYPE_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + } + // VALIDATE ID1 + { + let x := mload(ID1_X_LOC) + let y := mload(ID1_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + } + // VALIDATE ID2 + { + let x := mload(ID2_X_LOC) + let y := mload(ID2_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + } + // VALIDATE ID3 + { + let x := mload(ID3_X_LOC) + let y := mload(ID3_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + } + // VALIDATE ID4 + { + let x := mload(ID4_X_LOC) + let y := mload(ID4_Y_LOC) + let xx := mulmod(x, x, q) + // validate on curve + success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + } + + if iszero(success) { + mstore(0x0, INVALID_VERIFICATION_KEY_SELECTOR) + revert(0x00, 0x04) + } + } + } + /** * @notice Verify a Ultra Plonk proof * @param _proof - The serialized proof @@ -1889,8 +2095,7 @@ abstract contract BaseUltraVerifier { let x := mload(Q1_X_LOC) let y := mload(Q1_Y_LOC) let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + // Verification key fields verified to be on curve at contract deployment mstore(0x00, x) mstore(0x20, y) } @@ -1905,8 +2110,7 @@ abstract contract BaseUltraVerifier { let x := mload(Q2_X_LOC) let y := mload(Q2_Y_LOC) let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + // Verification key fields verified to be on curve at contract deployment mstore(0x00, x) mstore(0x20, y) } @@ -1921,8 +2125,7 @@ abstract contract BaseUltraVerifier { let x := mload(Q3_X_LOC) let y := mload(Q3_Y_LOC) let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + // Verification key fields verified to be on curve at contract deployment mstore(0x00, x) mstore(0x20, y) } @@ -1937,8 +2140,7 @@ abstract contract BaseUltraVerifier { let x := mload(Q4_X_LOC) let y := mload(Q4_Y_LOC) let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + // Verification key fields verified to be on curve at contract deployment mstore(0x00, x) mstore(0x20, y) } @@ -1953,8 +2155,7 @@ abstract contract BaseUltraVerifier { let x := mload(QM_X_LOC) let y := mload(QM_Y_LOC) let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + // Verification key fields verified to be on curve at contract deployment mstore(0x00, x) mstore(0x20, y) } @@ -1969,8 +2170,7 @@ abstract contract BaseUltraVerifier { let x := mload(QC_X_LOC) let y := mload(QC_Y_LOC) let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + // Verification key fields verified to be on curve at contract deployment mstore(0x00, x) mstore(0x20, y) } @@ -1985,8 +2185,7 @@ abstract contract BaseUltraVerifier { let x := mload(QARITH_X_LOC) let y := mload(QARITH_Y_LOC) let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + // Verification key fields verified to be on curve at contract deployment mstore(0x00, x) mstore(0x20, y) } @@ -2001,8 +2200,7 @@ abstract contract BaseUltraVerifier { let x := mload(QSORT_X_LOC) let y := mload(QSORT_Y_LOC) let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + // Verification key fields verified to be on curve at contract deployment mstore(0x00, x) mstore(0x20, y) } @@ -2017,8 +2215,7 @@ abstract contract BaseUltraVerifier { let x := mload(QELLIPTIC_X_LOC) let y := mload(QELLIPTIC_Y_LOC) let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + // Verification key fields verified to be on curve at contract deployment mstore(0x00, x) mstore(0x20, y) } @@ -2033,8 +2230,7 @@ abstract contract BaseUltraVerifier { let x := mload(QAUX_X_LOC) let y := mload(QAUX_Y_LOC) let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + // Verification key fields verified to be on curve at contract deployment mstore(0x00, x) mstore(0x20, y) } @@ -2049,8 +2245,7 @@ abstract contract BaseUltraVerifier { let x := mload(SIGMA1_X_LOC) let y := mload(SIGMA1_Y_LOC) let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + // Verification key fields verified to be on curve at contract deployment mstore(0x00, x) mstore(0x20, y) } @@ -2065,8 +2260,7 @@ abstract contract BaseUltraVerifier { let x := mload(SIGMA2_X_LOC) let y := mload(SIGMA2_Y_LOC) let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + // Verification key fields verified to be on curve at contract deployment mstore(0x00, x) mstore(0x20, y) } @@ -2081,8 +2275,7 @@ abstract contract BaseUltraVerifier { let x := mload(SIGMA3_X_LOC) let y := mload(SIGMA3_Y_LOC) let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + // Verification key fields verified to be on curve at contract deployment mstore(0x00, x) mstore(0x20, y) } @@ -2097,8 +2290,7 @@ abstract contract BaseUltraVerifier { let x := mload(SIGMA4_X_LOC) let y := mload(SIGMA4_Y_LOC) let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + // Verification key fields verified to be on curve at contract deployment mstore(0x00, x) mstore(0x20, y) } @@ -2113,8 +2305,7 @@ abstract contract BaseUltraVerifier { let x := mload(TABLE1_X_LOC) let y := mload(TABLE1_Y_LOC) let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + // Verification key fields verified to be on curve at contract deployment mstore(0x00, x) mstore(0x20, y) } @@ -2129,8 +2320,7 @@ abstract contract BaseUltraVerifier { let x := mload(TABLE2_X_LOC) let y := mload(TABLE2_Y_LOC) let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + // Verification key fields verified to be on curve at contract deployment mstore(0x00, x) mstore(0x20, y) } @@ -2145,8 +2335,7 @@ abstract contract BaseUltraVerifier { let x := mload(TABLE3_X_LOC) let y := mload(TABLE3_Y_LOC) let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + // Verification key fields verified to be on curve at contract deployment mstore(0x00, x) mstore(0x20, y) } @@ -2161,8 +2350,7 @@ abstract contract BaseUltraVerifier { let x := mload(TABLE4_X_LOC) let y := mload(TABLE4_Y_LOC) let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + // Verification key fields verified to be on curve at contract deployment mstore(0x00, x) mstore(0x20, y) } @@ -2177,8 +2365,7 @@ abstract contract BaseUltraVerifier { let x := mload(TABLE_TYPE_X_LOC) let y := mload(TABLE_TYPE_Y_LOC) let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + // Verification key fields verified to be on curve at contract deployment mstore(0x00, x) mstore(0x20, y) } @@ -2193,8 +2380,7 @@ abstract contract BaseUltraVerifier { let x := mload(ID1_X_LOC) let y := mload(ID1_Y_LOC) let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + // Verification key fields verified to be on curve at contract deployment mstore(0x00, x) mstore(0x20, y) } @@ -2209,8 +2395,7 @@ abstract contract BaseUltraVerifier { let x := mload(ID2_X_LOC) let y := mload(ID2_Y_LOC) let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + // Verification key fields verified to be on curve at contract deployment mstore(0x00, x) mstore(0x20, y) } @@ -2225,8 +2410,7 @@ abstract contract BaseUltraVerifier { let x := mload(ID3_X_LOC) let y := mload(ID3_Y_LOC) let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + // Verification key fields verified to be on curve at contract deployment mstore(0x00, x) mstore(0x20, y) } @@ -2241,8 +2425,7 @@ abstract contract BaseUltraVerifier { let x := mload(ID4_X_LOC) let y := mload(ID4_Y_LOC) let xx := mulmod(x, x, q) - // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + // Verification key fields verified to be on curve at contract deployment mstore(0x00, x) mstore(0x20, y) } From 1c746f176b60f0439637b2adf0c26d852c2f80e8 Mon Sep 17 00:00:00 2001 From: TomAFrench Date: Tue, 6 Feb 2024 14:32:34 +0000 Subject: [PATCH 3/6] chore: add comment with assumption on vk being constant --- barretenberg/cpp/src/barretenberg/dsl/acir_proofs/contract.hpp | 3 +++ barretenberg/sol/src/ultra/BaseUltraVerifier.sol | 3 +++ 2 files changed, 6 insertions(+) diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_proofs/contract.hpp b/barretenberg/cpp/src/barretenberg/dsl/acir_proofs/contract.hpp index 19e1ba63048..6c0a26b4ead 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_proofs/contract.hpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_proofs/contract.hpp @@ -303,6 +303,9 @@ abstract contract BaseUltraVerifier { function getVerificationKeyHash() public pure virtual returns (bytes32); + /** + * @dev We assume that the verification key loaded by this function is constant as we only verify it on deployment + */ function loadVerificationKey(uint256 _vk, uint256 _omegaInverseLoc) internal pure virtual; constructor() { diff --git a/barretenberg/sol/src/ultra/BaseUltraVerifier.sol b/barretenberg/sol/src/ultra/BaseUltraVerifier.sol index 3ac5638d844..5c06bc7c6f2 100644 --- a/barretenberg/sol/src/ultra/BaseUltraVerifier.sol +++ b/barretenberg/sol/src/ultra/BaseUltraVerifier.sol @@ -300,6 +300,9 @@ abstract contract BaseUltraVerifier { function getVerificationKeyHash() public pure virtual returns (bytes32); + /** + * @dev We assume that the verification key loaded by this function is constant as we only verify it on deployment + */ function loadVerificationKey(uint256 _vk, uint256 _omegaInverseLoc) internal pure virtual; constructor() { From fe5f3253e8d987727556cbe41507bf012f6ae654 Mon Sep 17 00:00:00 2001 From: Tom French <15848336+TomAFrench@users.noreply.github.com> Date: Tue, 6 Feb 2024 15:12:07 +0000 Subject: [PATCH 4/6] chore: use consistent naming for curve --- barretenberg/cpp/src/barretenberg/dsl/acir_proofs/contract.hpp | 2 +- barretenberg/sol/src/ultra/BaseUltraVerifier.sol | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_proofs/contract.hpp b/barretenberg/cpp/src/barretenberg/dsl/acir_proofs/contract.hpp index 6c0a26b4ead..2fe2ebe3c98 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_proofs/contract.hpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_proofs/contract.hpp @@ -311,7 +311,7 @@ abstract contract BaseUltraVerifier { constructor() { loadVerificationKey(N_LOC, OMEGA_INVERSE_LOC); - // We verify that all of the EC points in the verification key lie on the bn254 curve. + // We verify that all of the EC points in the verification key lie on the bn128 curve. assembly { let q := 21888242871839275222246405745257275088696311157297823662689037894645226208583 // EC group order diff --git a/barretenberg/sol/src/ultra/BaseUltraVerifier.sol b/barretenberg/sol/src/ultra/BaseUltraVerifier.sol index 5c06bc7c6f2..6e9a6e2836b 100644 --- a/barretenberg/sol/src/ultra/BaseUltraVerifier.sol +++ b/barretenberg/sol/src/ultra/BaseUltraVerifier.sol @@ -308,7 +308,7 @@ abstract contract BaseUltraVerifier { constructor() { loadVerificationKey(N_LOC, OMEGA_INVERSE_LOC); - // We verify that all of the EC points in the verification key lie on the bn254 curve. + // We verify that all of the EC points in the verification key lie on the bn128 curve. assembly { let q := 21888242871839275222246405745257275088696311157297823662689037894645226208583 // EC group order From fafa85d9ceb558704647d9f6d83d337e6832c32c Mon Sep 17 00:00:00 2001 From: TomAFrench Date: Tue, 6 Feb 2024 15:30:49 +0000 Subject: [PATCH 5/6] feat: revert early in verifier contract for malformed proof inputs --- .../barretenberg/dsl/acir_proofs/contract.hpp | 80 ++++++++++++++---- .../sol/src/ultra/BaseUltraVerifier.sol | 81 +++++++++++++++---- 2 files changed, 127 insertions(+), 34 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_proofs/contract.hpp b/barretenberg/cpp/src/barretenberg/dsl/acir_proofs/contract.hpp index 2fe2ebe3c98..2f92ddacea2 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_proofs/contract.hpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_proofs/contract.hpp @@ -294,6 +294,7 @@ abstract contract BaseUltraVerifier { uint256 internal constant GRUMPKIN_CURVE_B_PARAMETER_NEGATED = 17; error INVALID_VERIFICATION_KEY(); + error POINT_NOT_ON_CURVE(); error PUBLIC_INPUT_COUNT_INVALID(uint256 expected, uint256 actual); error PUBLIC_INPUT_INVALID_BN128_G1_POINT(); error PUBLIC_INPUT_GE_P(); @@ -1929,7 +1930,10 @@ abstract contract BaseUltraVerifier { let y := mload(T1_Y_LOC) let xx := mulmod(x, x, q) // validate on curve - success := eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q)) + if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { + mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) + revert(0x00, 0x04) + } mstore(ACCUMULATOR_X_LOC, x) mstore(add(ACCUMULATOR_X_LOC, 0x20), y) } @@ -1939,13 +1943,16 @@ abstract contract BaseUltraVerifier { let y := mload(T2_Y_LOC) // 0x1420 let xx := mulmod(x, x, q) // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { + mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) + revert(0x00, 0x04) + } mstore(0x00, x) mstore(0x20, y) } mstore(0x40, mload(ZETA_POW_N_LOC)) // accumulator_2 = [T2].zeta^n - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + success := staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40) // accumulator = [T1] + accumulator_2 success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) @@ -1955,7 +1962,10 @@ abstract contract BaseUltraVerifier { let y := mload(T3_Y_LOC) let xx := mulmod(x, x, q) // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { + mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) + revert(0x00, 0x04) + } mstore(0x00, x) mstore(0x20, y) } @@ -1971,7 +1981,10 @@ abstract contract BaseUltraVerifier { let y := mload(T4_Y_LOC) let xx := mulmod(x, x, q) // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { + mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) + revert(0x00, 0x04) + } mstore(0x00, x) mstore(0x20, y) } @@ -1987,7 +2000,10 @@ abstract contract BaseUltraVerifier { let y := mload(W1_Y_LOC) let xx := mulmod(x, x, q) // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { + mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) + revert(0x00, 0x04) + } mstore(0x00, x) mstore(0x20, y) } @@ -2003,7 +2019,10 @@ abstract contract BaseUltraVerifier { let y := mload(W2_Y_LOC) let xx := mulmod(x, x, q) // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { + mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) + revert(0x00, 0x04) + } mstore(0x00, x) mstore(0x20, y) } @@ -2019,7 +2038,10 @@ abstract contract BaseUltraVerifier { let y := mload(W3_Y_LOC) let xx := mulmod(x, x, q) // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { + mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) + revert(0x00, 0x04) + } mstore(0x00, x) mstore(0x20, y) } @@ -2035,7 +2057,10 @@ abstract contract BaseUltraVerifier { let y := mload(W4_Y_LOC) let xx := mulmod(x, x, q) // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { + mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) + revert(0x00, 0x04) + } mstore(0x00, x) mstore(0x20, y) } @@ -2051,7 +2076,10 @@ abstract contract BaseUltraVerifier { let y := mload(S_Y_LOC) let xx := mulmod(x, x, q) // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { + mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) + revert(0x00, 0x04) + } mstore(0x00, x) mstore(0x20, y) } @@ -2067,7 +2095,10 @@ abstract contract BaseUltraVerifier { let y := mload(Z_Y_LOC) let xx := mulmod(x, x, q) // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { + mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) + revert(0x00, 0x04) + } mstore(0x00, x) mstore(0x20, y) } @@ -2083,7 +2114,10 @@ abstract contract BaseUltraVerifier { let y := mload(Z_LOOKUP_Y_LOC) let xx := mulmod(x, x, q) // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { + mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) + revert(0x00, 0x04) + } mstore(0x00, x) mstore(0x20, y) } @@ -2631,13 +2665,16 @@ abstract contract BaseUltraVerifier { let y := mload(PI_Z_Y_LOC) let xx := mulmod(x, x, q) // validate on curve - success := eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q)) + if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { + mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) + revert(0x00, 0x04) + } mstore(0x00, x) mstore(0x20, y) } // compute zeta.[PI_Z] and add into accumulator mstore(0x40, zeta) - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + success := staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40) // accumulator = accumulator + accumulator_2 success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) @@ -2647,7 +2684,10 @@ abstract contract BaseUltraVerifier { let y := mload(PI_Z_OMEGA_Y_LOC) let xx := mulmod(x, x, q) // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { + mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) + revert(0x00, 0x04) + } mstore(0x00, x) mstore(0x20, y) } @@ -2675,7 +2715,10 @@ abstract contract BaseUltraVerifier { let y := mload(RECURSIVE_P1_Y_LOC) let xx := mulmod(x, x, q) // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { + mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) + revert(0x00, 0x04) + } mstore(0x00, x) mstore(0x20, y) } @@ -2689,7 +2732,10 @@ abstract contract BaseUltraVerifier { let y := mload(RECURSIVE_P2_Y_LOC) let xx := mulmod(x, x, q) // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { + mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) + revert(0x00, 0x04) + } mstore(0x00, x) mstore(0x20, y) } diff --git a/barretenberg/sol/src/ultra/BaseUltraVerifier.sol b/barretenberg/sol/src/ultra/BaseUltraVerifier.sol index 6e9a6e2836b..10f739f3894 100644 --- a/barretenberg/sol/src/ultra/BaseUltraVerifier.sol +++ b/barretenberg/sol/src/ultra/BaseUltraVerifier.sol @@ -261,6 +261,7 @@ abstract contract BaseUltraVerifier { uint256 internal constant NU_CHALLENGE_INPUT_LOC_C = 0x37e0; bytes4 internal constant INVALID_VERIFICATION_KEY_SELECTOR = 0x7e5769bf; + bytes4 internal constant POINT_NOT_ON_CURVE_SELECTOR = 0xa3dad654; bytes4 internal constant PUBLIC_INPUT_INVALID_BN128_G1_POINT_SELECTOR = 0xeba9f4a6; bytes4 internal constant PUBLIC_INPUT_GE_P_SELECTOR = 0x374a972f; bytes4 internal constant MOD_EXP_FAILURE_SELECTOR = 0xf894a7bc; @@ -291,6 +292,7 @@ abstract contract BaseUltraVerifier { uint256 internal constant GRUMPKIN_CURVE_B_PARAMETER_NEGATED = 17; error INVALID_VERIFICATION_KEY(); + error POINT_NOT_ON_CURVE(); error PUBLIC_INPUT_COUNT_INVALID(uint256 expected, uint256 actual); error PUBLIC_INPUT_INVALID_BN128_G1_POINT(); error PUBLIC_INPUT_GE_P(); @@ -1903,7 +1905,10 @@ abstract contract BaseUltraVerifier { let y := mload(T1_Y_LOC) let xx := mulmod(x, x, q) // validate on curve - success := eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q)) + if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { + mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) + revert(0x00, 0x04) + } mstore(ACCUMULATOR_X_LOC, x) mstore(add(ACCUMULATOR_X_LOC, 0x20), y) } @@ -1913,13 +1918,16 @@ abstract contract BaseUltraVerifier { let y := mload(T2_Y_LOC) // 0x1420 let xx := mulmod(x, x, q) // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { + mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) + revert(0x00, 0x04) + } mstore(0x00, x) mstore(0x20, y) } mstore(0x40, mload(ZETA_POW_N_LOC)) // accumulator_2 = [T2].zeta^n - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + success := staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40) // accumulator = [T1] + accumulator_2 success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) @@ -1929,7 +1937,10 @@ abstract contract BaseUltraVerifier { let y := mload(T3_Y_LOC) let xx := mulmod(x, x, q) // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { + mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) + revert(0x00, 0x04) + } mstore(0x00, x) mstore(0x20, y) } @@ -1945,7 +1956,10 @@ abstract contract BaseUltraVerifier { let y := mload(T4_Y_LOC) let xx := mulmod(x, x, q) // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { + mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) + revert(0x00, 0x04) + } mstore(0x00, x) mstore(0x20, y) } @@ -1961,7 +1975,10 @@ abstract contract BaseUltraVerifier { let y := mload(W1_Y_LOC) let xx := mulmod(x, x, q) // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { + mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) + revert(0x00, 0x04) + } mstore(0x00, x) mstore(0x20, y) } @@ -1977,7 +1994,10 @@ abstract contract BaseUltraVerifier { let y := mload(W2_Y_LOC) let xx := mulmod(x, x, q) // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { + mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) + revert(0x00, 0x04) + } mstore(0x00, x) mstore(0x20, y) } @@ -1993,7 +2013,10 @@ abstract contract BaseUltraVerifier { let y := mload(W3_Y_LOC) let xx := mulmod(x, x, q) // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { + mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) + revert(0x00, 0x04) + } mstore(0x00, x) mstore(0x20, y) } @@ -2009,7 +2032,10 @@ abstract contract BaseUltraVerifier { let y := mload(W4_Y_LOC) let xx := mulmod(x, x, q) // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { + mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) + revert(0x00, 0x04) + } mstore(0x00, x) mstore(0x20, y) } @@ -2025,7 +2051,10 @@ abstract contract BaseUltraVerifier { let y := mload(S_Y_LOC) let xx := mulmod(x, x, q) // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { + mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) + revert(0x00, 0x04) + } mstore(0x00, x) mstore(0x20, y) } @@ -2041,7 +2070,10 @@ abstract contract BaseUltraVerifier { let y := mload(Z_Y_LOC) let xx := mulmod(x, x, q) // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { + mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) + revert(0x00, 0x04) + } mstore(0x00, x) mstore(0x20, y) } @@ -2057,7 +2089,10 @@ abstract contract BaseUltraVerifier { let y := mload(Z_LOOKUP_Y_LOC) let xx := mulmod(x, x, q) // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { + mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) + revert(0x00, 0x04) + } mstore(0x00, x) mstore(0x20, y) } @@ -2605,13 +2640,16 @@ abstract contract BaseUltraVerifier { let y := mload(PI_Z_Y_LOC) let xx := mulmod(x, x, q) // validate on curve - success := eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q)) + if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { + mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) + revert(0x00, 0x04) + } mstore(0x00, x) mstore(0x20, y) } // compute zeta.[PI_Z] and add into accumulator mstore(0x40, zeta) - success := and(success, staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40)) + success := staticcall(gas(), 7, 0x00, 0x60, ACCUMULATOR2_X_LOC, 0x40) // accumulator = accumulator + accumulator_2 success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) @@ -2621,7 +2659,10 @@ abstract contract BaseUltraVerifier { let y := mload(PI_Z_OMEGA_Y_LOC) let xx := mulmod(x, x, q) // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { + mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) + revert(0x00, 0x04) + } mstore(0x00, x) mstore(0x20, y) } @@ -2649,7 +2690,10 @@ abstract contract BaseUltraVerifier { let y := mload(RECURSIVE_P1_Y_LOC) let xx := mulmod(x, x, q) // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { + mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) + revert(0x00, 0x04) + } mstore(0x00, x) mstore(0x20, y) } @@ -2663,7 +2707,10 @@ abstract contract BaseUltraVerifier { let y := mload(RECURSIVE_P2_Y_LOC) let xx := mulmod(x, x, q) // validate on curve - success := and(success, eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) + if iszero(eq(mulmod(y, y, q), addmod(mulmod(x, xx, q), 3, q))) { + mstore(0x0, POINT_NOT_ON_CURVE_SELECTOR) + revert(0x00, 0x04) + } mstore(0x00, x) mstore(0x20, y) } From f6098ee5ecf0846ec14474a9e6fa77c8801b254d Mon Sep 17 00:00:00 2001 From: TomAFrench Date: Tue, 6 Feb 2024 15:46:40 +0000 Subject: [PATCH 6/6] chore: add missing constant to cpp version of contract --- barretenberg/cpp/src/barretenberg/dsl/acir_proofs/contract.hpp | 1 + 1 file changed, 1 insertion(+) diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_proofs/contract.hpp b/barretenberg/cpp/src/barretenberg/dsl/acir_proofs/contract.hpp index 2f92ddacea2..4d60226ce46 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_proofs/contract.hpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_proofs/contract.hpp @@ -264,6 +264,7 @@ abstract contract BaseUltraVerifier { uint256 internal constant NU_CHALLENGE_INPUT_LOC_C = 0x37e0; bytes4 internal constant INVALID_VERIFICATION_KEY_SELECTOR = 0x7e5769bf; + bytes4 internal constant POINT_NOT_ON_CURVE_SELECTOR = 0xa3dad654; bytes4 internal constant PUBLIC_INPUT_INVALID_BN128_G1_POINT_SELECTOR = 0xeba9f4a6; bytes4 internal constant PUBLIC_INPUT_GE_P_SELECTOR = 0x374a972f; bytes4 internal constant MOD_EXP_FAILURE_SELECTOR = 0xf894a7bc;