From 617088c023a2fb8e75623527ff6781ea1485aa9c Mon Sep 17 00:00:00 2001 From: mattstam Date: Tue, 18 Jun 2024 13:35:52 -0700 Subject: [PATCH 1/3] feat: new verifier contracts --- recursion/gnark-ffi/assets/ISP1Verifier.txt | 19 +++++----- .../gnark-ffi/assets/SP1MockVerifier.txt | 14 ++------ recursion/gnark-ffi/assets/SP1Verifier.txt | 36 ++++++++++--------- recursion/gnark-ffi/src/plonk_bn254.rs | 2 +- 4 files changed, 34 insertions(+), 37 deletions(-) diff --git a/recursion/gnark-ffi/assets/ISP1Verifier.txt b/recursion/gnark-ffi/assets/ISP1Verifier.txt index 1ea8727937..21eb13d62d 100644 --- a/recursion/gnark-ffi/assets/ISP1Verifier.txt +++ b/recursion/gnark-ffi/assets/ISP1Verifier.txt @@ -1,23 +1,24 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.19; +pragma solidity ^0.8.20; /// @title SP1 Verifier Interface /// @author Succinct Labs /// @notice This contract is the interface for the SP1 Verifier. interface ISP1Verifier { - /// @notice Returns the version of SP1 this verifier corresponds to. - function VERSION() external pure returns (string memory); - - /// @notice Returns the hash of the verification key. - function VKEY_HASH() external pure returns (bytes32); - /// @notice Verifies a proof with given public values and vkey. - /// @param vkey The verification key for the RISC-V program. + /// @dev It is expected that the first 4 bytes of proofBytes must match the first 4 bytes of + /// target verifier's VERIFIER_HASH. + /// @param programVKey The verification key for the RISC-V program. /// @param publicValues The public values encoded as bytes. /// @param proofBytes The proof of the program execution the SP1 zkVM encoded as bytes. function verifyProof( - bytes32 vkey, + bytes32 programVKey, bytes calldata publicValues, bytes calldata proofBytes ) external view; } + +interface ISP1VerifierWithHash is ISP1Verifier { + /// @notice Returns the hash of the verifier. + function VERIFIER_HASH() external pure returns (bytes32); +} diff --git a/recursion/gnark-ffi/assets/SP1MockVerifier.txt b/recursion/gnark-ffi/assets/SP1MockVerifier.txt index 93ca40a8bd..c3f0afb13c 100644 --- a/recursion/gnark-ffi/assets/SP1MockVerifier.txt +++ b/recursion/gnark-ffi/assets/SP1MockVerifier.txt @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.19; +pragma solidity ^0.8.20; import {ISP1Verifier} from "./ISP1Verifier.sol"; @@ -7,20 +7,12 @@ import {ISP1Verifier} from "./ISP1Verifier.sol"; /// @author Succinct Labs /// @notice This contracts implements a Mock solidity verifier for SP1. contract SP1MockVerifier is ISP1Verifier { - function VERSION() external pure returns (string memory) { - return "{SP1_CIRCUIT_VERSION}"; - } - - function VKEY_HASH() external pure returns (bytes32) { - return bytes32(0); - } - /// @notice Verifies a mock proof with given public values and vkey. /// @param proofBytes The proof of the program execution the SP1 zkVM encoded as bytes. function verifyProof( bytes32, - bytes memory, - bytes memory proofBytes + bytes calldata, + bytes calldata proofBytes ) external pure { assert(proofBytes.length == 0); } diff --git a/recursion/gnark-ffi/assets/SP1Verifier.txt b/recursion/gnark-ffi/assets/SP1Verifier.txt index 2cc044bfb5..5dc8e82eae 100644 --- a/recursion/gnark-ffi/assets/SP1Verifier.txt +++ b/recursion/gnark-ffi/assets/SP1Verifier.txt @@ -1,21 +1,26 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.19; +pragma solidity ^0.8.20; -import {ISP1Verifier} from "./ISP1Verifier.sol"; +import {ISP1Verifier, ISP1VerifierWithHash} from "../ISP1Verifier.sol"; import {PlonkVerifier} from "./PlonkVerifier.sol"; /// @title SP1 Verifier /// @author Succinct Labs /// @notice This contracts implements a solidity verifier for SP1. -contract SP1Verifier is PlonkVerifier { - error WrongVersionProof(); +contract SP1Verifier is PlonkVerifier, ISP1VerifierWithHash { + /// @notice Thrown when the verifier selector from this proof does not match the one in this + /// verifier. This indicates that this proof was sent to the wrong verifier. + /// @param received The verifier selector from the first 4 bytes of the proof. + /// @param expected The verifier selector from the first 4 bytes of the VERIFIER_HASH(). + error WrongVerifierSelector(bytes4 received, bytes4 expected); function VERSION() external pure returns (string memory) { return "{SP1_CIRCUIT_VERSION}"; } - function VKEY_HASH() public pure returns (bytes32) { - return {VKEY_HASH}; + /// @inheritdoc ISP1VerifierWithHash + function VERIFIER_HASH() public pure returns (bytes32) { + return {VERIFIER_HASH}; } /// @notice Hashes the public values to a field elements inside Bn254. @@ -27,25 +32,24 @@ contract SP1Verifier is PlonkVerifier { } /// @notice Verifies a proof with given public values and vkey. - /// @param vkey The verification key for the RISC-V program. + /// @param programVKey The verification key for the RISC-V program. /// @param publicValues The public values encoded as bytes. /// @param proofBytes The proof of the program execution the SP1 zkVM encoded as bytes. function verifyProof( - bytes32 vkey, + bytes32 programVKey, bytes calldata publicValues, bytes calldata proofBytes - ) public view { - // To ensure the proof corresponds to this verifier, we check that the first 4 bytes of - // proofBytes match the first 4 bytes of VKEY_HASH. - bytes4 proofBytesPrefix = bytes4(proofBytes[:4]); - if (proofBytesPrefix != bytes4(VKEY_HASH())) { - revert WrongVersionProof(); + ) external view { + bytes4 recievedSelector = bytes4(proofBytes[:4]); + bytes4 expectedSelector = bytes4(VERIFIER_HASH()); + if (recievedSelector != expectedSelector) { + revert WrongVerifierSelector(recievedSelector, expectedSelector); } bytes32 publicValuesDigest = hashPublicValues(publicValues); uint256[] memory inputs = new uint256[](2); - inputs[0] = uint256(vkey); + inputs[0] = uint256(programVKey); inputs[1] = uint256(publicValuesDigest); this.Verify(proofBytes[4:], inputs); } -} \ No newline at end of file +} diff --git a/recursion/gnark-ffi/src/plonk_bn254.rs b/recursion/gnark-ffi/src/plonk_bn254.rs index 4f64587610..56284528f3 100644 --- a/recursion/gnark-ffi/src/plonk_bn254.rs +++ b/recursion/gnark-ffi/src/plonk_bn254.rs @@ -94,7 +94,7 @@ impl PlonkBn254Prover { let sp1_verifier_str = include_str!("../assets/SP1Verifier.txt") .replace("{SP1_CIRCUIT_VERSION}", SP1_CIRCUIT_VERSION) .replace( - "{VKEY_HASH}", + "{VERIFIER_HASH}", format!("0x{}", hex::encode(vkey_hash)).as_str(), ); let mut sp1_verifier_file = File::create(sp1_verifier_path).unwrap(); From 47278e43dcd7b37616511e4d9891a0b08309c22a Mon Sep 17 00:00:00 2001 From: mattstam Date: Tue, 18 Jun 2024 14:18:42 -0700 Subject: [PATCH 2/3] feat: new verifier contracts 2 --- book/developers/building-plonk-artifacts.md | 17 ++++++++++++++--- recursion/gnark-ffi/assets/ISP1Verifier.txt | 3 ++- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/book/developers/building-plonk-artifacts.md b/book/developers/building-plonk-artifacts.md index 9efd9127d0..d6999f3f82 100644 --- a/book/developers/building-plonk-artifacts.md +++ b/book/developers/building-plonk-artifacts.md @@ -1,7 +1,18 @@ # Building Plonk BN254 Artifacts -To build the Plonk Bn254 artifacts from scratch, you can use the `Makefile` inside the `prover` directory. +To build the production Plonk Bn254 artifacts from scratch, you can use the `Makefile` inside the `prover` directory. ```shell,noplayground -RUST_LOG=info make plonk-bn254 -``` \ No newline at end of file +cd prover +RUST_LOG=info make build-plonk-bn254 +``` + +## Non-production builds + +For quickly building the plonk artifacts, you can run `cargo test` with additional flags to speed up the build process. + +```shell,noplayground +SP1_DEV=true FRI_QUERIES=1 cargo test --release test_e2e_prove_plonk +``` + +The generated artifacts should only be used for development and testing purposes. diff --git a/recursion/gnark-ffi/assets/ISP1Verifier.txt b/recursion/gnark-ffi/assets/ISP1Verifier.txt index 21eb13d62d..7ceb2d6fb8 100644 --- a/recursion/gnark-ffi/assets/ISP1Verifier.txt +++ b/recursion/gnark-ffi/assets/ISP1Verifier.txt @@ -19,6 +19,7 @@ interface ISP1Verifier { } interface ISP1VerifierWithHash is ISP1Verifier { - /// @notice Returns the hash of the verifier. + /// @notice Returns the SHA-256 hash of the verifier. + /// @dev This is automatically generated by taking hash of the VKey file. function VERIFIER_HASH() external pure returns (bytes32); } From 6250dedce43572e4d0cd39d1b041395384de773d Mon Sep 17 00:00:00 2001 From: mattstam Date: Thu, 20 Jun 2024 15:10:02 -0700 Subject: [PATCH 3/3] received --- recursion/gnark-ffi/assets/SP1Verifier.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/recursion/gnark-ffi/assets/SP1Verifier.txt b/recursion/gnark-ffi/assets/SP1Verifier.txt index 5dc8e82eae..e116e8bd70 100644 --- a/recursion/gnark-ffi/assets/SP1Verifier.txt +++ b/recursion/gnark-ffi/assets/SP1Verifier.txt @@ -40,10 +40,10 @@ contract SP1Verifier is PlonkVerifier, ISP1VerifierWithHash { bytes calldata publicValues, bytes calldata proofBytes ) external view { - bytes4 recievedSelector = bytes4(proofBytes[:4]); + bytes4 receivedSelector = bytes4(proofBytes[:4]); bytes4 expectedSelector = bytes4(VERIFIER_HASH()); - if (recievedSelector != expectedSelector) { - revert WrongVerifierSelector(recievedSelector, expectedSelector); + if (receivedSelector != expectedSelector) { + revert WrongVerifierSelector(receivedSelector, expectedSelector); } bytes32 publicValuesDigest = hashPublicValues(publicValues);