-
Notifications
You must be signed in to change notification settings - Fork 41
feat: add v6.0.0-rc.1 verifier contracts #65
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Closed
Closed
Changes from all commits
Commits
Show all changes
7 commits
Select commit
Hold shift + click to select a range
f3baae5
works
4322f80
tweak groth
yuwen01 3f65183
cargo update
yuwen01 853880f
feat: use REGISTER_ROUTE env var for conditional gateway route regist…
fakedev9999 6cdd937
feat: add Safe Transaction Builder JSON generator (#62)
fakedev9999 dcbb40b
feat: add v6.0.0-rc.1 verifier contracts
fakedev9999 2ca2f6e
fix: truncate VK_ROOT to 32 bytes in rc.1 verifier contracts
fakedev9999 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -9,4 +9,7 @@ broadcast/ | |
| docs/ | ||
|
|
||
| # Dotenv file | ||
| .env | ||
| .env | ||
|
|
||
| # Safe Transaction Builder generated files | ||
| safe-batches/*.json | ||
567 changes: 567 additions & 0 deletions
567
contracts/contracts/src/v6.0.0-beta.1/Groth16Verifier.sol
Large diffs are not rendered by default.
Oops, something went wrong.
1,341 changes: 1,341 additions & 0 deletions
1,341
contracts/contracts/src/v6.0.0-beta.1/PlonkVerifier.sol
Large diffs are not rendered by default.
Oops, something went wrong.
83 changes: 83 additions & 0 deletions
83
contracts/contracts/src/v6.0.0-beta.1/SP1VerifierGroth16.sol
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,83 @@ | ||
| // SPDX-License-Identifier: MIT | ||
| pragma solidity ^0.8.20; | ||
|
|
||
| import {ISP1Verifier, ISP1VerifierWithHash} from "../ISP1Verifier.sol"; | ||
| import {Groth16Verifier} from "./Groth16Verifier.sol"; | ||
|
|
||
| /// @title SP1 Verifier | ||
| /// @author Succinct Labs | ||
| /// @notice This contracts implements a solidity verifier for SP1. | ||
| contract SP1Verifier is Groth16Verifier, 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); | ||
|
|
||
| /// @notice Thrown when the exit code is invalid. | ||
| error InvalidExitCode(); | ||
|
|
||
| /// @notice Thrown when the proof is invalid. | ||
| error InvalidProof(); | ||
|
|
||
| /// @notice Thrown when the vkRoot is invalid. | ||
| error InvalidVkRoot(); | ||
|
|
||
| /// @notice The version of the circuit. | ||
| function VERSION() external pure returns (string memory) { | ||
| return "v6.0.0-beta.1"; | ||
| } | ||
|
|
||
| /// @inheritdoc ISP1VerifierWithHash | ||
| function VERIFIER_HASH() public pure returns (bytes32) { | ||
| return 0x58b7a3c37d9f7b9310b07a730c4d914e0a28d1f8ef296b0aca2bac7765ce976f; | ||
| } | ||
|
|
||
| /// @notice The recursion vk root. | ||
| function VK_ROOT() public pure returns (bytes32) { | ||
| return 0x00410a5637e8b7b8c4b895991b4892efd0ff4da2b5e277d701f2f5c1f23d0c7b; | ||
| } | ||
|
|
||
| /// @notice Hashes the public values to a field elements inside Bn254. | ||
| /// @param publicValues The public values. | ||
| function hashPublicValues( | ||
| bytes calldata publicValues | ||
| ) public pure returns (bytes32) { | ||
| return sha256(publicValues) & bytes32(uint256((1 << 253) - 1)); | ||
| } | ||
|
|
||
| /// @notice Verifies a proof with given public values and vkey. | ||
| /// @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 programVKey, | ||
| bytes calldata publicValues, | ||
| bytes calldata proofBytes | ||
| ) external view { | ||
| bytes4 receivedSelector = bytes4(proofBytes[:4]); | ||
| bytes4 expectedSelector = bytes4(VERIFIER_HASH()); | ||
| if (receivedSelector != expectedSelector) { | ||
| revert WrongVerifierSelector(receivedSelector, expectedSelector); | ||
| } | ||
| uint256 expectedVkRoot = uint256(VK_ROOT()); | ||
|
|
||
| bytes32 publicValuesDigest = hashPublicValues(publicValues); | ||
| (uint256 exitCode, uint256 vkRoot, uint256 nonce, uint256[8] memory proof) = abi.decode(proofBytes[4:], (uint256, uint256, uint256, uint256[8])); | ||
|
|
||
| uint256[5] memory inputs; | ||
| inputs[0] = uint256(programVKey); | ||
| inputs[1] = uint256(publicValuesDigest); | ||
| inputs[2] = exitCode; | ||
| inputs[3] = vkRoot; | ||
| inputs[4] = nonce; | ||
|
|
||
| if (exitCode != 0) { | ||
| revert InvalidExitCode(); | ||
| } | ||
| if (vkRoot != expectedVkRoot) { | ||
| revert InvalidVkRoot(); | ||
| } | ||
| this.Verify(proof, inputs); | ||
| } | ||
| } | ||
88 changes: 88 additions & 0 deletions
88
contracts/contracts/src/v6.0.0-beta.1/SP1VerifierPlonk.sol
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,88 @@ | ||
| // SPDX-License-Identifier: MIT | ||
| pragma solidity ^0.8.20; | ||
|
|
||
| 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, 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); | ||
|
|
||
| /// @notice Thrown when the exit code is invalid. | ||
| error InvalidExitCode(); | ||
|
|
||
| /// @notice Thrown when the proof is invalid. | ||
| error InvalidProof(); | ||
|
|
||
| /// @notice Thrown when the vkRoot is invalid. | ||
| error InvalidVkRoot(); | ||
|
|
||
| /// @notice The version of the circuit. | ||
| function VERSION() external pure returns (string memory) { | ||
| return "v6.0.0-beta.1"; | ||
| } | ||
|
|
||
| /// @inheritdoc ISP1VerifierWithHash | ||
| function VERIFIER_HASH() public pure returns (bytes32) { | ||
| return 0x433cef0e1aaeaa7aacc52ba14efb620fa2fc92c946aeef3919c0f360943b6c2a; | ||
| } | ||
|
|
||
| /// @notice The recursion vk root. | ||
| function VK_ROOT() public pure returns (bytes32) { | ||
| return 0x00410a5637e8b7b8c4b895991b4892efd0ff4da2b5e277d701f2f5c1f23d0c7b; | ||
| } | ||
|
|
||
| /// @notice Hashes the public values to a field elements inside Bn254. | ||
| /// @param publicValues The public values. | ||
| function hashPublicValues( | ||
| bytes calldata publicValues | ||
| ) public pure returns (bytes32) { | ||
| return sha256(publicValues) & bytes32(uint256((1 << 253) - 1)); | ||
| } | ||
|
|
||
| /// @notice Verifies a proof with given public values and vkey. | ||
| /// @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 programVKey, | ||
| bytes calldata publicValues, | ||
| bytes calldata proofBytes | ||
| ) external view { | ||
| bytes4 receivedSelector = bytes4(proofBytes[:4]); | ||
| bytes4 expectedSelector = bytes4(VERIFIER_HASH()); | ||
| if (receivedSelector != expectedSelector) { | ||
| revert WrongVerifierSelector(receivedSelector, expectedSelector); | ||
| } | ||
|
|
||
| uint256 expectedVkRoot = uint256(VK_ROOT()); | ||
|
|
||
| bytes32 publicValuesDigest = hashPublicValues(publicValues); | ||
| uint256 exitCode = uint256(bytes32(proofBytes[4:36])); | ||
| uint256 vkRoot = uint256(bytes32(proofBytes[36:68])); | ||
| uint256 nonce = uint256(bytes32(proofBytes[68:100])); | ||
|
|
||
| uint256[] memory inputs = new uint256[](5); | ||
| inputs[0] = uint256(programVKey); | ||
| inputs[1] = uint256(publicValuesDigest); | ||
| inputs[2] = exitCode; | ||
| inputs[3] = vkRoot; | ||
| inputs[4] = nonce; | ||
| if (exitCode != 0) { | ||
| revert InvalidExitCode(); | ||
| } | ||
| if (vkRoot != expectedVkRoot) { | ||
| revert InvalidVkRoot(); | ||
| } | ||
| bool success = this.Verify(proofBytes[100:], inputs); | ||
| if (!success) { | ||
| revert InvalidProof(); | ||
| } | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,8 @@ | ||
| { | ||
| "lib/forge-std": { | ||
| "rev": "978ac6fadb62f5f0b723c996f64be52eddba6801" | ||
| }, | ||
| "lib/openzeppelin-contracts": { | ||
| "rev": "dbb6104ce834628e473d2173bbc9d47f81a9eec3" | ||
| } | ||
| } |
Empty file.
41 changes: 41 additions & 0 deletions
41
contracts/script/deploy/v6.0.0-beta.1/SP1VerifierGroth16.s.sol
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,41 @@ | ||
| // SPDX-License-Identifier: MIT | ||
| pragma solidity ^0.8.20; | ||
|
|
||
| import {BaseScript} from "../../utils/Base.s.sol"; | ||
| import {SP1Verifier} from "../../../src/v6.0.0-beta.1/SP1VerifierGroth16.sol"; | ||
| import {SP1VerifierGateway} from "../../../src/SP1VerifierGateway.sol"; | ||
| import {ISP1VerifierWithHash} from "../../../src/ISP1Verifier.sol"; | ||
|
|
||
| contract SP1VerifierScript is BaseScript { | ||
| string internal constant KEY = "V6_0_0_BETA_1_SP1_VERIFIER_GROTH16"; | ||
|
|
||
| function run() external multichain(KEY) broadcaster { | ||
| // Read config | ||
| bytes32 CREATE2_SALT = readBytes32("CREATE2_SALT"); | ||
|
|
||
| // Deploy contract | ||
| address verifier = address(new SP1Verifier{salt: CREATE2_SALT}()); | ||
|
|
||
| // Register route to gateway (default: false for multisig deployments) | ||
| // Set REGISTER_ROUTE=true when deployer is gateway owner | ||
| if (vm.envOr("REGISTER_ROUTE", false)) { | ||
| address SP1_VERIFIER_GATEWAY = readAddress("SP1_VERIFIER_GATEWAY_GROTH16"); | ||
| SP1VerifierGateway gateway = SP1VerifierGateway(SP1_VERIFIER_GATEWAY); | ||
| gateway.addRoute(verifier); | ||
| } | ||
|
|
||
| // Write address | ||
| writeAddress(KEY, verifier); | ||
| } | ||
|
|
||
| function freeze() external multichain(KEY) broadcaster { | ||
| // Read config | ||
| address SP1_VERIFIER_GATEWAY = readAddress("SP1_VERIFIER_GATEWAY_GROTH16"); | ||
| address SP1_VERIFIER = readAddress(KEY); | ||
|
|
||
| // Freeze the verifier on the gateway | ||
| SP1VerifierGateway gateway = SP1VerifierGateway(SP1_VERIFIER_GATEWAY); | ||
| bytes4 selector = bytes4(ISP1VerifierWithHash(SP1_VERIFIER).VERIFIER_HASH()); | ||
| gateway.freezeRoute(selector); | ||
| } | ||
| } |
41 changes: 41 additions & 0 deletions
41
contracts/script/deploy/v6.0.0-beta.1/SP1VerifierPlonk.s.sol
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,41 @@ | ||
| // SPDX-License-Identifier: MIT | ||
| pragma solidity ^0.8.20; | ||
|
|
||
| import {BaseScript} from "../../utils/Base.s.sol"; | ||
| import {SP1Verifier} from "../../../src/v6.0.0-beta.1/SP1VerifierPlonk.sol"; | ||
| import {SP1VerifierGateway} from "../../../src/SP1VerifierGateway.sol"; | ||
| import {ISP1VerifierWithHash} from "../../../src/ISP1Verifier.sol"; | ||
|
|
||
| contract SP1VerifierScript is BaseScript { | ||
| string internal constant KEY = "V6_0_0_BETA_1_SP1_VERIFIER_PLONK"; | ||
|
|
||
| function run() external multichain(KEY) broadcaster { | ||
| // Read config | ||
| bytes32 CREATE2_SALT = readBytes32("CREATE2_SALT"); | ||
|
|
||
| // Deploy contract | ||
| address verifier = address(new SP1Verifier{salt: CREATE2_SALT}()); | ||
|
|
||
| // Register route to gateway (default: false for multisig deployments) | ||
| // Set REGISTER_ROUTE=true when deployer is gateway owner | ||
| if (vm.envOr("REGISTER_ROUTE", false)) { | ||
| address SP1_VERIFIER_GATEWAY = readAddress("SP1_VERIFIER_GATEWAY_PLONK"); | ||
| SP1VerifierGateway gateway = SP1VerifierGateway(SP1_VERIFIER_GATEWAY); | ||
| gateway.addRoute(verifier); | ||
| } | ||
|
|
||
| // Write address | ||
| writeAddress(KEY, verifier); | ||
| } | ||
|
|
||
| function freeze() external multichain(KEY) broadcaster { | ||
| // Read config | ||
| address SP1_VERIFIER_GATEWAY = readAddress("SP1_VERIFIER_GATEWAY_PLONK"); | ||
| address SP1_VERIFIER = readAddress(KEY); | ||
|
|
||
| // Freeze the verifier on the gateway | ||
| SP1VerifierGateway gateway = SP1VerifierGateway(SP1_VERIFIER_GATEWAY); | ||
| bytes4 selector = bytes4(ISP1VerifierWithHash(SP1_VERIFIER).VERIFIER_HASH()); | ||
| gateway.freezeRoute(selector); | ||
| } | ||
| } |
38 changes: 38 additions & 0 deletions
38
contracts/script/deploy/v6.0.0-rc.1/SP1VerifierGroth16.s.sol
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,38 @@ | ||
| // SPDX-License-Identifier: MIT | ||
| pragma solidity ^0.8.20; | ||
|
|
||
| import {BaseScript} from "../../utils/Base.s.sol"; | ||
| import {SP1Verifier} from "../../../src/v6.0.0-rc.1/SP1VerifierGroth16.sol"; | ||
| import {SP1VerifierGateway} from "../../../src/SP1VerifierGateway.sol"; | ||
| import {ISP1VerifierWithHash} from "../../../src/ISP1Verifier.sol"; | ||
|
|
||
| contract SP1VerifierScript is BaseScript { | ||
| string internal constant KEY = "V6_0_0_RC_1_SP1_VERIFIER_GROTH16"; | ||
|
|
||
| function run() external multichain(KEY) broadcaster { | ||
| // Read config | ||
| bytes32 CREATE2_SALT = readBytes32("CREATE2_SALT"); | ||
| address SP1_VERIFIER_GATEWAY = readAddress("SP1_VERIFIER_GATEWAY_GROTH16"); | ||
|
|
||
| // Deploy contract | ||
| address verifier = address(new SP1Verifier{salt: CREATE2_SALT}()); | ||
|
|
||
| // Add the verifier to the gateway | ||
| SP1VerifierGateway gateway = SP1VerifierGateway(SP1_VERIFIER_GATEWAY); | ||
| gateway.addRoute(verifier); | ||
|
|
||
| // Write address | ||
| writeAddress(KEY, verifier); | ||
| } | ||
|
|
||
| function freeze() external multichain(KEY) broadcaster { | ||
| // Read config | ||
| address SP1_VERIFIER_GATEWAY = readAddress("SP1_VERIFIER_GATEWAY_GROTH16"); | ||
| address SP1_VERIFIER = readAddress(KEY); | ||
|
|
||
| // Freeze the verifier on the gateway | ||
| SP1VerifierGateway gateway = SP1VerifierGateway(SP1_VERIFIER_GATEWAY); | ||
| bytes4 selector = bytes4(ISP1VerifierWithHash(SP1_VERIFIER).VERIFIER_HASH()); | ||
| gateway.freezeRoute(selector); | ||
| } | ||
| } |
38 changes: 38 additions & 0 deletions
38
contracts/script/deploy/v6.0.0-rc.1/SP1VerifierPlonk.s.sol
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,38 @@ | ||
| // SPDX-License-Identifier: MIT | ||
| pragma solidity ^0.8.20; | ||
|
|
||
| import {BaseScript} from "../../utils/Base.s.sol"; | ||
| import {SP1Verifier} from "../../../src/v6.0.0-rc.1/SP1VerifierPlonk.sol"; | ||
| import {SP1VerifierGateway} from "../../../src/SP1VerifierGateway.sol"; | ||
| import {ISP1VerifierWithHash} from "../../../src/ISP1Verifier.sol"; | ||
|
|
||
| contract SP1VerifierScript is BaseScript { | ||
| string internal constant KEY = "V6_0_0_RC_1_SP1_VERIFIER_PLONK"; | ||
|
|
||
| function run() external multichain(KEY) broadcaster { | ||
| // Read config | ||
| bytes32 CREATE2_SALT = readBytes32("CREATE2_SALT"); | ||
| address SP1_VERIFIER_GATEWAY = readAddress("SP1_VERIFIER_GATEWAY_PLONK"); | ||
|
|
||
| // Deploy contract | ||
| address verifier = address(new SP1Verifier{salt: CREATE2_SALT}()); | ||
|
|
||
| // Add the verifier to the gateway | ||
| SP1VerifierGateway gateway = SP1VerifierGateway(SP1_VERIFIER_GATEWAY); | ||
| gateway.addRoute(verifier); | ||
|
|
||
| // Write address | ||
| writeAddress(KEY, verifier); | ||
| } | ||
|
|
||
| function freeze() external multichain(KEY) broadcaster { | ||
| // Read config | ||
| address SP1_VERIFIER_GATEWAY = readAddress("SP1_VERIFIER_GATEWAY_PLONK"); | ||
| address SP1_VERIFIER = readAddress(KEY); | ||
|
|
||
| // Freeze the verifier on the gateway | ||
| SP1VerifierGateway gateway = SP1VerifierGateway(SP1_VERIFIER_GATEWAY); | ||
| bytes4 selector = bytes4(ISP1VerifierWithHash(SP1_VERIFIER).VERIFIER_HASH()); | ||
| gateway.freezeRoute(selector); | ||
| } | ||
| } |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
matt says to move these checks before declaring the uint256[5] memory inputs;
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yep it's strictly better
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll move both the exit code, vkey validation checks before inputs array allocation in #70
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also updated sp1 side to avoid regression in the future succinctlabs/sp1@61330b6