diff --git a/recursion/.prettierrc b/recursion/.prettierrc index 23246c1..b55d249 100644 --- a/recursion/.prettierrc +++ b/recursion/.prettierrc @@ -1,7 +1,7 @@ { - "arrowParens": "avoid", - "singleQuote": true, - "trailingComma": "all", - "printWidth": 100, - "proseWrap": "always" + "arrowParens": "avoid", + "singleQuote": true, + "trailingComma": "all", + "printWidth": 100, + "proseWrap": "always" } diff --git a/recursion/.yarn/install-state.gz b/recursion/.yarn/install-state.gz index d62291f..814e65b 100644 Binary files a/recursion/.yarn/install-state.gz and b/recursion/.yarn/install-state.gz differ diff --git a/recursion/README.md b/recursion/README.md index 5c5e025..d54c14d 100644 --- a/recursion/README.md +++ b/recursion/README.md @@ -1,19 +1,23 @@ # Recursive proofs with Noir -Recursive proofs mean you prove that another proof is correct. A bit of a proofinception but bear with me: +Recursive proofs mean you prove that another proof is correct. A bit of a proofinception but bear +with me: - You prove that `x != y` - You pick that proof and send it to another circuit (the "outer" proof) - You generate the outer proof and verify it -Why is this useful? In this example, it doesn't do much. But you could verify two proofs within a proof, which can be incredibly useful. +Why is this useful? In this example, it doesn't do much. But you could verify two proofs within a +proof, which can be incredibly useful. -You could also avoid verifying stuff on-chain for turn-based games, for example. Check out the [Noir Docs](https://noir-lang.org/docs/explainers/explainer-recursion) for a high-level explanation. +You could also avoid verifying stuff on-chain for turn-based games, for example. Check out the +[Noir Docs](https://noir-lang.org/docs/explainers/explainer-recursion) for a high-level explanation. ## Getting Started 1. Install dependencies by running `yarn` -2. For on-chain verification, open another terminal, and run `cd packages/hardhat && npx hardhat node` +2. For on-chain verification, open another terminal, and run + `cd packages/hardhat && npx hardhat node` 3. Run `yarn dev` ## Testing diff --git a/recursion/package.json b/recursion/package.json index dc4869b..138adf9 100644 --- a/recursion/package.json +++ b/recursion/package.json @@ -1,23 +1,23 @@ { - "name": "recursion", - "private": true, - "packageManager": "yarn@4.1.0", - "workspaces": [ - "packages/hardhat", - "packages/noir", - "packages/next" - ], - "engines": { - "node": "^20.10.0" - }, - "scripts": { - "dev": "yarn workspace hardhat run deploy && yarn workspace next run dev", - "test": "yarn workspace hardhat run test", - "build": "yarn workspace next run build" - }, - "dependencies": { - "@noir-lang/backend_barretenberg": "^0.23.0", - "@noir-lang/noir_js": "^0.23.0", - "@noir-lang/noir_wasm": "^0.23.0" - } + "name": "recursion", + "private": true, + "packageManager": "yarn@4.1.0", + "workspaces": [ + "packages/hardhat", + "packages/noir", + "packages/next" + ], + "engines": { + "node": "^20.10.0" + }, + "scripts": { + "dev": "yarn workspace hardhat run deploy && yarn workspace next run dev", + "test": "yarn workspace hardhat run test", + "build": "yarn workspace next run build" + }, + "dependencies": { + "@noir-lang/backend_barretenberg": "^0.25.0", + "@noir-lang/noir_js": "^0.25.0", + "@noir-lang/noir_wasm": "^0.25.0" + } } diff --git a/recursion/packages/addresses.json b/recursion/packages/addresses.json index f3e3168..19d8496 100644 --- a/recursion/packages/addresses.json +++ b/recursion/packages/addresses.json @@ -1 +1 @@ -{"chainId":31337,"verifier":"0xdc64a140aa3e981100a9beca4e685f962f0cf6c9"} \ No newline at end of file +{"chainId":31337,"verifier":"0xe7f1725e7734ce288f8367e1bb143e90bb3f0512"} \ No newline at end of file diff --git a/recursion/packages/hardhat/test/index.test.ts b/recursion/packages/hardhat/test/index.test.ts index f22cd11..96631e7 100644 --- a/recursion/packages/hardhat/test/index.test.ts +++ b/recursion/packages/hardhat/test/index.test.ts @@ -55,17 +55,17 @@ describe('It compiles noir program code, receiving circuit bytes and abi object. describe.only('Proof generation', async () => { it('Should generate an intermediate proof', async () => { const { witness } = await noirs.main.execute(mainInput); - intermediateProof = await backends.main.generateIntermediateProof(witness); + intermediateProof = await backends.main.generateProof(witness); const { proof, publicInputs } = intermediateProof; expect(proof instanceof Uint8Array).to.be.true; - const verified = await backends.main.verifyIntermediateProof({ proof, publicInputs }); + const verified = await backends.main.verifyProof({ proof, publicInputs }); expect(verified).to.be.true; const numPublicInputs = 1; const { proofAsFields, vkAsFields, vkHash } = - await backends.main.generateIntermediateProofArtifacts( + await backends.main.generateRecursiveProofArtifacts( { publicInputs, proof }, numPublicInputs, ); @@ -81,7 +81,7 @@ describe('It compiles noir program code, receiving circuit bytes and abi object. }); it('Should generate a final proof with a recursive input', async () => { - finalProof = await noirs.recursive.generateFinalProof(recursiveInputs); + finalProof = await noirs.recursive.generateProof(recursiveInputs); expect(finalProof.proof instanceof Uint8Array).to.be.true; }); }); @@ -94,7 +94,7 @@ describe('It compiles noir program code, receiving circuit bytes and abi object. }); it('Should verify off-chain', async () => { - const verified = await noirs.recursive.verifyFinalProof(finalProof); + const verified = await noirs.recursive.verifyProof(finalProof); expect(verified).to.be.true; }); diff --git a/recursion/packages/next/hooks/useMainProofGeneration.tsx b/recursion/packages/next/hooks/useMainProofGeneration.tsx index a083cfe..acb1055 100644 --- a/recursion/packages/next/hooks/useMainProofGeneration.tsx +++ b/recursion/packages/next/hooks/useMainProofGeneration.tsx @@ -11,7 +11,9 @@ export function useMainProofGeneration(inputs?: { x: string; y: string }) { const [mainProofArtifacts, setMainProofArtifacts] = useState(); const proofGeneration = async () => { - if (!inputs) return; + if (!inputs) { + return; + } const circuit = await getCircuit('main'); const backend = new BarretenbergBackend(circuit, { threads: navigator.hardwareConcurrency }); @@ -19,22 +21,19 @@ export function useMainProofGeneration(inputs?: { x: string; y: string }) { const { witness } = await noir.execute(inputs); - const { publicInputs, proof } = await toast.promise( - backend.generateIntermediateProof(witness), - { - pending: 'Generating proof', - success: 'Proof generated', - error: 'Error generating proof', - }, - ); + const { publicInputs, proof } = await toast.promise(backend.generateProof(witness), { + pending: 'Generating proof', + success: 'Proof generated', + error: 'Error generating proof', + }); - toast.promise(backend.verifyIntermediateProof({ proof, publicInputs }), { + toast.promise(backend.verifyProof({ proof, publicInputs }), { pending: 'Verifying intermediate proof', success: 'Intermediate proof verified', error: 'Error verifying intermediate proof', }); - const mainProofArtifacts = await backend.generateIntermediateProofArtifacts( + const mainProofArtifacts = await backend.generateRecursiveProofArtifacts( { publicInputs, proof }, 1, // 1 public input ); diff --git a/recursion/packages/next/hooks/useOffChainVerification.tsx b/recursion/packages/next/hooks/useOffChainVerification.tsx index 197110c..7179b2c 100644 --- a/recursion/packages/next/hooks/useOffChainVerification.tsx +++ b/recursion/packages/next/hooks/useOffChainVerification.tsx @@ -5,17 +5,26 @@ import { useEffect } from 'react'; import { toast } from 'react-toastify'; import { BarretenbergBackend } from '@noir-lang/backend_barretenberg'; -export function useOffChainVerification(backend?: BarretenbergBackend, proofData?: ProofData) { +export function useOffChainVerification( + backend?: BarretenbergBackend, + proofData?: ProofData, + stopLoading?: () => void, +) { useEffect(() => { if (!proofData || !backend) return; const { proof, publicInputs } = proofData; - toast.promise(backend.verifyFinalProof({ proof, publicInputs }), { + const verificationPromise = backend.verifyProof({ proof, publicInputs }); + toast.promise(verificationPromise, { pending: 'Verifying recursive proof off-chain', success: 'Recursive proof verified off-chain', error: 'Error verifying recursive proof off-chain', }); + verificationPromise.then(() => { + stopLoading?.(); + }); + // return () => { // backend.destroy(); // }; diff --git a/recursion/packages/next/hooks/useRecursiveProofGeneration.tsx b/recursion/packages/next/hooks/useRecursiveProofGeneration.tsx index 7bf558f..0610523 100644 --- a/recursion/packages/next/hooks/useRecursiveProofGeneration.tsx +++ b/recursion/packages/next/hooks/useRecursiveProofGeneration.tsx @@ -30,7 +30,7 @@ export function useRecursiveProofGeneration( }; const { witness } = await noir.execute(recInput); - const proofData = await backend.generateFinalProof(witness); + const proofData = await backend.generateProof(witness); setRecursiveBackend(backend); setProofData(proofData); diff --git a/recursion/packages/next/package.json b/recursion/packages/next/package.json index c77855f..21d5592 100644 --- a/recursion/packages/next/package.json +++ b/recursion/packages/next/package.json @@ -12,7 +12,7 @@ "typescript": "5.0.4" }, "dependencies": { - "@noir-lang/types": "^0.23.0", + "@noir-lang/types": "^0.25.0", "react": "^18.2.0", "react-dom": "^18.2.0", "react-toastify": "^10.0.4", diff --git a/recursion/packages/next/pages/Page.module.css b/recursion/packages/next/pages/Page.module.css new file mode 100644 index 0000000..3f842f5 --- /dev/null +++ b/recursion/packages/next/pages/Page.module.css @@ -0,0 +1,70 @@ +/* Page.module.css */ +.container { + max-width: 600px; + margin: 2rem auto; + padding: 2rem; + background: #f9f9f9; + border-radius: 8px; + box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); +} + +.title { + color: #333; + text-align: center; +} + +.proofForm { + display: flex; + flex-direction: column; + gap: 1rem; +} + +.inputGroup { + display: flex; + flex-direction: column; + gap: 0.5rem; +} + +.inputLabel { + font-size: 1rem; + color: #666; +} + +.inputField { + padding: 0.5rem; + font-size: 1rem; + border: 1px solid #ddd; + border-radius: 4px; +} + +.submitButton { + padding: 0.5rem 1rem; + font-size: 1rem; + color: white; + background-color: #5c6bc0; + border: none; + border-radius: 4px; + cursor: pointer; + transition: background-color 0.3s ease; +} + +.submitButton:hover { + background-color: #3f51b5; +} + +.submitButton:disabled { + background-color: #9fa8da; + cursor: not-allowed; +} + +.errorMessage { + color: #b71c1c; + text-align: center; + margin-top: 1rem; +} + +.successMessage { + color: #2e7d32; + text-align: center; + margin-top: 1rem; +} diff --git a/recursion/packages/next/pages/index.tsx b/recursion/packages/next/pages/index.tsx index 26ef473..3bbba07 100644 --- a/recursion/packages/next/pages/index.tsx +++ b/recursion/packages/next/pages/index.tsx @@ -1,21 +1,31 @@ 'use client'; -import React, { useState } from 'react'; +import styles from './Page.module.css'; + +import React, { useState, useCallback } from 'react'; import { useOffChainVerification } from '../hooks/useOffChainVerification'; import { useOnChainVerification } from '../hooks/useOnChainVerification'; import { useMainProofGeneration } from '../hooks/useMainProofGeneration'; import { useRecursiveProofGeneration } from '../hooks/useRecursiveProofGeneration'; export default function Page() { + const [xValue, setXValue] = useState(''); + const [yValue, setYValue] = useState(''); + const [loading, setLoading] = useState(false); + const stopLoading = useCallback(() => { + setLoading(false); + }, []); + const [input, setInput] = useState<{ x: string; y: string } | undefined>(); const mainProofArtifacts = useMainProofGeneration(input); const { recursiveBackend, proofData } = useRecursiveProofGeneration(mainProofArtifacts, input); - useOffChainVerification(recursiveBackend, proofData); + useOffChainVerification(recursiveBackend, proofData, stopLoading); useOnChainVerification(proofData); const submit = (e: React.FormEvent) => { e.preventDefault(); + setLoading(true); const elements = e.currentTarget.elements; if (!elements) return; @@ -25,18 +35,48 @@ export default function Page() { setInput({ x: x.value, y: y.value }); }; + const inputsFilled = xValue.trim() !== '' && yValue.trim() !== ''; + const isDisabled = loading || !inputsFilled; + return ( -
-

Recursive!

-

This circuit proves that x and y are different (main proof)

+
+

Recursive!

+

This circuit proves that x and y are different (main proof).

Then it feeds that proof into another circuit, which then proves it verifies (recursive - proof) + proof).

-

Try it!

- - - - +
+
+ + setXValue(e.target.value)} + /> +
+
+ + setYValue(e.target.value)} + /> +
+ +
+
); } diff --git a/recursion/packages/next/utils/verifierAbi.json b/recursion/packages/next/utils/verifierAbi.json index 76ba13d..f12fdce 100644 --- a/recursion/packages/next/utils/verifierAbi.json +++ b/recursion/packages/next/utils/verifierAbi.json @@ -1,80 +1,80 @@ [ - { - "inputs": [], - "name": "EC_SCALAR_MUL_FAILURE", - "type": "error" - }, - { - "inputs": [], - "name": "MOD_EXP_FAILURE", - "type": "error" - }, - { - "inputs": [], - "name": "PROOF_FAILURE", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "expected", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "actual", - "type": "uint256" - } - ], - "name": "PUBLIC_INPUT_COUNT_INVALID", - "type": "error" - }, - { - "inputs": [], - "name": "PUBLIC_INPUT_GE_P", - "type": "error" - }, - { - "inputs": [], - "name": "PUBLIC_INPUT_INVALID_BN128_G1_POINT", - "type": "error" - }, - { - "inputs": [], - "name": "getVerificationKeyHash", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "_proof", - "type": "bytes" - }, - { - "internalType": "bytes32[]", - "name": "_publicInputs", - "type": "bytes32[]" - } - ], - "name": "verify", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - } + { + "inputs": [], + "name": "EC_SCALAR_MUL_FAILURE", + "type": "error" + }, + { + "inputs": [], + "name": "MOD_EXP_FAILURE", + "type": "error" + }, + { + "inputs": [], + "name": "PROOF_FAILURE", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "expected", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "actual", + "type": "uint256" + } + ], + "name": "PUBLIC_INPUT_COUNT_INVALID", + "type": "error" + }, + { + "inputs": [], + "name": "PUBLIC_INPUT_GE_P", + "type": "error" + }, + { + "inputs": [], + "name": "PUBLIC_INPUT_INVALID_BN128_G1_POINT", + "type": "error" + }, + { + "inputs": [], + "name": "getVerificationKeyHash", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "_proof", + "type": "bytes" + }, + { + "internalType": "bytes32[]", + "name": "_publicInputs", + "type": "bytes32[]" + } + ], + "name": "verify", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + } ] diff --git a/recursion/packages/noir/main/Nargo.toml b/recursion/packages/noir/main/Nargo.toml index 92c044b..9307ee9 100644 --- a/recursion/packages/noir/main/Nargo.toml +++ b/recursion/packages/noir/main/Nargo.toml @@ -2,5 +2,6 @@ name = "main" type = "bin" authors = [""] +compiler_version = ">=0.24.0" [dependencies] diff --git a/recursion/packages/noir/main/src/main.nr b/recursion/packages/noir/main/src/main.nr index 6e170de..de59dd9 100644 --- a/recursion/packages/noir/main/src/main.nr +++ b/recursion/packages/noir/main/src/main.nr @@ -1,3 +1,4 @@ +#[recursive] fn main(x : Field, y : pub Field) { assert(x != y); } diff --git a/recursion/packages/noir/recursion/Nargo.toml b/recursion/packages/noir/recursion/Nargo.toml index f057b6e..212af6f 100644 --- a/recursion/packages/noir/recursion/Nargo.toml +++ b/recursion/packages/noir/recursion/Nargo.toml @@ -2,5 +2,6 @@ name = "recursion" type = "bin" authors = [""] +compiler_version = ">=0.24.0" [dependencies] diff --git a/recursion/packages/noir/recursion/contract/recursion/plonk_vk.sol b/recursion/packages/noir/recursion/contract/recursion/plonk_vk.sol index c70f9b5..a446dff 100644 --- a/recursion/packages/noir/recursion/contract/recursion/plonk_vk.sol +++ b/recursion/packages/noir/recursion/contract/recursion/plonk_vk.sol @@ -284,56 +284,49 @@ abstract contract BaseUltraVerifier { uint256 internal constant PAIRING_RHS_X_LOC = 0x3220; uint256 internal constant PAIRING_RHS_Y_LOC = 0x3240; - // ### SUCCESS FLAG MEMORY LOCATIONS - uint256 internal constant GRAND_PRODUCT_SUCCESS_FLAG = 0x3300; - uint256 internal constant ARITHMETIC_TERM_SUCCESS_FLAG = 0x3020; - uint256 internal constant BATCH_OPENING_SUCCESS_FLAG = 0x3340; - uint256 internal constant OPENING_COMMITMENT_SUCCESS_FLAG = 0x3360; - uint256 internal constant PAIRING_PREAMBLE_SUCCESS_FLAG = 0x3380; - uint256 internal constant PAIRING_SUCCESS_FLAG = 0x33a0; - uint256 internal constant RESULT_FLAG = 0x33c0; - // misc stuff - uint256 internal constant OMEGA_INVERSE_LOC = 0x3400; - uint256 internal constant C_ALPHA_SQR_LOC = 0x3420; - uint256 internal constant C_ALPHA_CUBE_LOC = 0x3440; - uint256 internal constant C_ALPHA_QUAD_LOC = 0x3460; - uint256 internal constant C_ALPHA_BASE_LOC = 0x3480; + uint256 internal constant OMEGA_INVERSE_LOC = 0x3300; + uint256 internal constant C_ALPHA_SQR_LOC = 0x3320; + uint256 internal constant C_ALPHA_CUBE_LOC = 0x3340; + uint256 internal constant C_ALPHA_QUAD_LOC = 0x3360; + uint256 internal constant C_ALPHA_BASE_LOC = 0x3380; // ### RECURSION VARIABLE MEMORY LOCATIONS - uint256 internal constant RECURSIVE_P1_X_LOC = 0x3500; - uint256 internal constant RECURSIVE_P1_Y_LOC = 0x3520; - uint256 internal constant RECURSIVE_P2_X_LOC = 0x3540; - uint256 internal constant RECURSIVE_P2_Y_LOC = 0x3560; - - uint256 internal constant PUBLIC_INPUTS_HASH_LOCATION = 0x3580; + uint256 internal constant RECURSIVE_P1_X_LOC = 0x3400; + uint256 internal constant RECURSIVE_P1_Y_LOC = 0x3420; + uint256 internal constant RECURSIVE_P2_X_LOC = 0x3440; + uint256 internal constant RECURSIVE_P2_Y_LOC = 0x3460; + uint256 internal constant PUBLIC_INPUTS_HASH_LOCATION = 0x3480; // sub-identity storage - uint256 internal constant PERMUTATION_IDENTITY = 0x3600; - uint256 internal constant PLOOKUP_IDENTITY = 0x3620; - uint256 internal constant ARITHMETIC_IDENTITY = 0x3640; - uint256 internal constant SORT_IDENTITY = 0x3660; - uint256 internal constant ELLIPTIC_IDENTITY = 0x3680; - uint256 internal constant AUX_IDENTITY = 0x36a0; - uint256 internal constant AUX_NON_NATIVE_FIELD_EVALUATION = 0x36c0; - uint256 internal constant AUX_LIMB_ACCUMULATOR_EVALUATION = 0x36e0; - uint256 internal constant AUX_RAM_CONSISTENCY_EVALUATION = 0x3700; - uint256 internal constant AUX_ROM_CONSISTENCY_EVALUATION = 0x3720; - uint256 internal constant AUX_MEMORY_EVALUATION = 0x3740; - - uint256 internal constant QUOTIENT_EVAL_LOC = 0x3760; - uint256 internal constant ZERO_POLY_INVERSE_LOC = 0x3780; + uint256 internal constant PERMUTATION_IDENTITY = 0x3500; + uint256 internal constant PLOOKUP_IDENTITY = 0x3520; + uint256 internal constant ARITHMETIC_IDENTITY = 0x3540; + uint256 internal constant SORT_IDENTITY = 0x3560; + uint256 internal constant ELLIPTIC_IDENTITY = 0x3580; + uint256 internal constant AUX_IDENTITY = 0x35a0; + uint256 internal constant AUX_NON_NATIVE_FIELD_EVALUATION = 0x35c0; + uint256 internal constant AUX_LIMB_ACCUMULATOR_EVALUATION = 0x35e0; + uint256 internal constant AUX_RAM_CONSISTENCY_EVALUATION = 0x3600; + uint256 internal constant AUX_ROM_CONSISTENCY_EVALUATION = 0x3620; + uint256 internal constant AUX_MEMORY_EVALUATION = 0x3640; + + uint256 internal constant QUOTIENT_EVAL_LOC = 0x3660; + uint256 internal constant ZERO_POLY_INVERSE_LOC = 0x3680; // when hashing public inputs we use memory at NU_CHALLENGE_INPUT_LOC_A, as the hash input size is unknown at compile time - uint256 internal constant NU_CHALLENGE_INPUT_LOC_A = 0x37a0; - uint256 internal constant NU_CHALLENGE_INPUT_LOC_B = 0x37c0; - uint256 internal constant NU_CHALLENGE_INPUT_LOC_C = 0x37e0; + uint256 internal constant NU_CHALLENGE_INPUT_LOC_A = 0x36a0; + uint256 internal constant NU_CHALLENGE_INPUT_LOC_B = 0x36c0; + uint256 internal constant NU_CHALLENGE_INPUT_LOC_C = 0x36e0; + 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; - bytes4 internal constant EC_SCALAR_MUL_FAILURE_SELECTOR = 0xf755f369; - bytes4 internal constant PROOF_FAILURE_SELECTOR = 0x0711fcec; + bytes4 internal constant PAIRING_PREAMBLE_FAILED_SELECTOR = 0x01882d81; + bytes4 internal constant OPENING_COMMITMENT_FAILED_SELECTOR = 0x4e719763; + bytes4 internal constant PAIRING_FAILED_SELECTOR = 0xd71fd263; uint256 internal constant ETA_INPUT_LENGTH = 0xc0; // W1, W2, W3 = 6 * 0x20 bytes @@ -357,17 +350,227 @@ 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 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(); error MOD_EXP_FAILURE(); - error EC_SCALAR_MUL_FAILURE(); - error PROOF_FAILURE(); + error PAIRING_PREAMBLE_FAILED(); + error OPENING_COMMITMENT_FAILED(); + error PAIRING_FAILED(); 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() { + loadVerificationKey(N_LOC, OMEGA_INVERSE_LOC); + + // We verify that all of the EC points in the verification key lie on the bn128 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 @@ -1786,7 +1989,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) } @@ -1796,13 +2002,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)) @@ -1812,7 +2021,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) } @@ -1828,7 +2040,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) } @@ -1844,7 +2059,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) } @@ -1860,7 +2078,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) } @@ -1876,7 +2097,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) } @@ -1892,7 +2116,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) } @@ -1908,7 +2135,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) } @@ -1924,7 +2154,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) } @@ -1940,7 +2173,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) } @@ -1955,8 +2191,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) } @@ -1971,8 +2206,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) } @@ -1987,8 +2221,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) } @@ -2003,8 +2236,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) } @@ -2019,8 +2251,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) } @@ -2035,8 +2266,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) } @@ -2051,8 +2281,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) } @@ -2067,8 +2296,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) } @@ -2083,8 +2311,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) } @@ -2099,8 +2326,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) } @@ -2115,8 +2341,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) } @@ -2131,8 +2356,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) } @@ -2147,8 +2371,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) } @@ -2163,8 +2386,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) } @@ -2179,8 +2401,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) } @@ -2195,8 +2416,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) } @@ -2211,8 +2431,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) } @@ -2227,8 +2446,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) } @@ -2243,8 +2461,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) } @@ -2259,8 +2476,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) } @@ -2275,8 +2491,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) } @@ -2291,8 +2506,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) } @@ -2307,8 +2521,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) } @@ -2496,7 +2709,10 @@ abstract contract BaseUltraVerifier { // accumulator = accumulator + accumulator_2 success := and(success, staticcall(gas(), 6, ACCUMULATOR_X_LOC, 0x80, ACCUMULATOR_X_LOC, 0x40)) - mstore(OPENING_COMMITMENT_SUCCESS_FLAG, success) + if iszero(success) { + mstore(0x0, OPENING_COMMITMENT_FAILED_SELECTOR) + revert(0x00, 0x04) + } } /** @@ -2511,13 +2727,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)) @@ -2527,7 +2746,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) } @@ -2555,7 +2777,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) } @@ -2569,7 +2794,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) } @@ -2589,10 +2817,9 @@ abstract contract BaseUltraVerifier { } if iszero(success) { - mstore(0x0, EC_SCALAR_MUL_FAILURE_SELECTOR) + mstore(0x0, PAIRING_PREAMBLE_FAILED_SELECTOR) revert(0x00, 0x04) } - mstore(PAIRING_PREAMBLE_SUCCESS_FLAG, success) } /** @@ -2617,18 +2844,12 @@ abstract contract BaseUltraVerifier { mstore(0x160, mload(G2X_Y1_LOC)) success := staticcall(gas(), 8, 0x00, 0x180, 0x00, 0x20) - mstore(PAIRING_SUCCESS_FLAG, success) - mstore(RESULT_FLAG, mload(0x00)) - } - if iszero( - and( - and(and(mload(PAIRING_SUCCESS_FLAG), mload(RESULT_FLAG)), mload(PAIRING_PREAMBLE_SUCCESS_FLAG)), - mload(OPENING_COMMITMENT_SUCCESS_FLAG) - ) - ) { - mstore(0x0, PROOF_FAILURE_SELECTOR) - revert(0x00, 0x04) + if iszero(and(success, mload(0x00))) { + mstore(0x0, PAIRING_FAILED_SELECTOR) + revert(0x00, 0x04) + } } + { mstore(0x00, 0x01) return(0x00, 0x20) // Proof succeeded! diff --git a/recursion/yarn.lock b/recursion/yarn.lock index 956ca10..c78827d 100644 --- a/recursion/yarn.lock +++ b/recursion/yarn.lock @@ -26,9 +26,9 @@ __metadata: languageName: node linkType: hard -"@aztec/bb.js@npm:0.19.0": - version: 0.19.0 - resolution: "@aztec/bb.js@npm:0.19.0" +"@aztec/bb.js@npm:0.26.3": + version: 0.26.3 + resolution: "@aztec/bb.js@npm:0.26.3" dependencies: comlink: "npm:^4.4.1" commander: "npm:^10.0.1" @@ -36,7 +36,7 @@ __metadata: tslib: "npm:^2.4.0" bin: bb.js: dest/node/main.js - checksum: 10c0/7f0df00d5fcc9c7a027c8fa4d02aa9ad36cfeb69dcee91770f207816fa00c1f9744113cbdc0921c43b48793ae56f1269b8300a081aa336b5971b0337af459bcf + checksum: 10c0/40bdf890145dd79fb31f4474b78144aa00b5aa31569fa37d0f8c96c5477689bad34d1633aaddfa25ffa7132820882932fbd9dc263c39d925b52881a8e7f40f0d languageName: node linkType: hard @@ -940,57 +940,58 @@ __metadata: languageName: node linkType: hard -"@noir-lang/acvm_js@npm:0.39.0": - version: 0.39.0 - resolution: "@noir-lang/acvm_js@npm:0.39.0" - checksum: 10c0/0780b8abe6ab6d0c83b095877adfe9080f0cd4bedb97f709f146b26a53d5b8be2bce065c8f710b59e0a6e23506ade6cdf73aaf58868da5863d75bca5c40783ba +"@noir-lang/acvm_js@npm:0.41.0": + version: 0.41.0 + resolution: "@noir-lang/acvm_js@npm:0.41.0" + checksum: 10c0/e836ec305e35a3c57e7a8ad735ffa271ab8ca7c0ba1a4c6403673e882b08c92b3fc35fc089e005d0562982272889b431bd3061fa05c3c5c18d0365397c0e48b9 languageName: node linkType: hard -"@noir-lang/backend_barretenberg@npm:^0.23.0": - version: 0.23.0 - resolution: "@noir-lang/backend_barretenberg@npm:0.23.0" +"@noir-lang/backend_barretenberg@npm:^0.25.0": + version: 0.25.0 + resolution: "@noir-lang/backend_barretenberg@npm:0.25.0" dependencies: - "@aztec/bb.js": "npm:0.19.0" - "@noir-lang/types": "npm:0.23.0" + "@aztec/bb.js": "npm:0.26.3" + "@noir-lang/types": "npm:0.25.0" fflate: "npm:^0.8.0" - checksum: 10c0/52170513bae7e09df4bc88d6c020cddab47b91ab3c56c4dcb2183d2b091bcb95c557606e338daf22ee415fe61b8b218cdf6ec7971a5548804d11f83cd7795086 + checksum: 10c0/479e6c7b0182f9148e97cfe29501ce5e3012e1ad0a18e492638dfddef7a9f41b5033b6a0cda5ac5d2c10728d129561972962a7b35646802b5738bc1ed2af2843 languageName: node linkType: hard -"@noir-lang/noir_js@npm:^0.23.0": - version: 0.23.0 - resolution: "@noir-lang/noir_js@npm:0.23.0" +"@noir-lang/noir_js@npm:^0.25.0": + version: 0.25.0 + resolution: "@noir-lang/noir_js@npm:0.25.0" dependencies: - "@noir-lang/acvm_js": "npm:0.39.0" - "@noir-lang/noirc_abi": "npm:0.23.0" - "@noir-lang/types": "npm:0.23.0" - checksum: 10c0/1ccb04cf5990cc6b32c230a08e016def41bb8c002263eea226272c719d63aee06b012772d69fe5658f3fd26985f906ab30d53adf4804632d9c7b63c25b108eaf + "@noir-lang/acvm_js": "npm:0.41.0" + "@noir-lang/noirc_abi": "npm:0.25.0" + "@noir-lang/types": "npm:0.25.0" + checksum: 10c0/4b02b3e219565dffc5fa4d3a8b3f88328fdd3512fd7b30d9a3bd94c2a41cd1f3bcac38cd2e069361560b8d90ef6fabf10ff831c8ba50679514216d6a7783ed67 languageName: node linkType: hard -"@noir-lang/noir_wasm@npm:^0.23.0": - version: 0.23.0 - resolution: "@noir-lang/noir_wasm@npm:0.23.0" +"@noir-lang/noir_wasm@npm:^0.25.0": + version: 0.25.0 + resolution: "@noir-lang/noir_wasm@npm:0.25.0" dependencies: + "@noir-lang/types": "npm:0.25.0" pako: "npm:^2.1.0" - checksum: 10c0/c960ebd9eb859efab48f1e15b002d1d5edd278cafe71d61261cf0cfee2a5cd792953f9e8ffd2fe142c1be32a72ed4bb4b17a4561392d6a0359f4936eef1287f5 + checksum: 10c0/9e9633e9b44a280f4366b5149627aa6832fdeec2bf9fcab4d49c9290c9e2c72978f8524be15b72b1e032b6b9f10412fca6e093bba3433d79df0b3dd5bca0bf1f languageName: node linkType: hard -"@noir-lang/noirc_abi@npm:0.23.0": - version: 0.23.0 - resolution: "@noir-lang/noirc_abi@npm:0.23.0" - checksum: 10c0/a37a9b96e8690d766bee3f850f6a9913c2a070d99147e3672c9979c4740226b5e17fc033b520b53b79f997ca1d95aa5598f91ac8c303a5f1242c238ccbbc1587 +"@noir-lang/noirc_abi@npm:0.25.0": + version: 0.25.0 + resolution: "@noir-lang/noirc_abi@npm:0.25.0" + dependencies: + "@noir-lang/types": "npm:0.25.0" + checksum: 10c0/b75677d487c63b9c0464b403801ec4792eb9cea89fdeeaef752a764a5dd2e962fddc51a6a078530b65275924a46c348d73dd120660f6a7cc03c36c6e9025af77 languageName: node linkType: hard -"@noir-lang/types@npm:0.23.0, @noir-lang/types@npm:^0.23.0": - version: 0.23.0 - resolution: "@noir-lang/types@npm:0.23.0" - dependencies: - "@noir-lang/noirc_abi": "npm:0.23.0" - checksum: 10c0/f349a2c6649988f21aecf104a31cff476af0d69b3f7352d72ac2eb36cbe14aa12a524273cce2066fa0ac7f68e62c69870b860a80c73df4d662d7d94bf321f882 +"@noir-lang/types@npm:0.25.0, @noir-lang/types@npm:^0.25.0": + version: 0.25.0 + resolution: "@noir-lang/types@npm:0.25.0" + checksum: 10c0/066d7dd3bb06a000fb1d2dac74db2b4e052516a5a5a4bc1f9c9a3beb8442045e323db60b90ec342b3acd71e19948a9701a0b082eead7ab51e6e1aa6e4986f1e1 languageName: node linkType: hard @@ -6595,7 +6596,7 @@ __metadata: version: 0.0.0-use.local resolution: "next@workspace:packages/next" dependencies: - "@noir-lang/types": "npm:^0.23.0" + "@noir-lang/types": "npm:^0.25.0" "@types/react": "npm:^18.2.55" next: "npm:^14.1.0" react: "npm:^18.2.0" @@ -7387,9 +7388,9 @@ __metadata: version: 0.0.0-use.local resolution: "recursion@workspace:." dependencies: - "@noir-lang/backend_barretenberg": "npm:^0.23.0" - "@noir-lang/noir_js": "npm:^0.23.0" - "@noir-lang/noir_wasm": "npm:^0.23.0" + "@noir-lang/backend_barretenberg": "npm:^0.25.0" + "@noir-lang/noir_js": "npm:^0.25.0" + "@noir-lang/noir_wasm": "npm:^0.25.0" languageName: unknown linkType: soft