diff --git a/README.md b/README.md index d8dc7a8061..f043335230 100644 --- a/README.md +++ b/README.md @@ -148,12 +148,10 @@ sequenceDiagram participant CiphernodeRegistry participant E3Program participant ComputeProvider - participant InputValidator participant DecryptionVerifier Users->>Enclave: request(parameters) Enclave->>E3Program: validate(e3ProgramParams) - E3Program-->>Enclave: inputValidator Enclave->>ComputeProvider: validate(computeProviderParams) ComputeProvider-->>Enclave: decryptionVerifier Enclave->>CiphernodeRegistry: requestCommittee(e3Id, seed, threshold) @@ -167,8 +165,8 @@ sequenceDiagram Enclave-->>Users: success Users->>Enclave: publishInput(e3Id, data) - Enclave->>InputValidator: validate(msg.sender, data) - InputValidator-->>Enclave: input, success + Enclave->>E3Program: validateInput(msg.sender, data) + E3Program-->>Enclave: input, success Enclave->>Enclave: Store input Enclave-->>Users: success diff --git a/crates/evm-helpers/src/contracts.rs b/crates/evm-helpers/src/contracts.rs index db4b576879..e56eddd510 100644 --- a/crates/evm-helpers/src/contracts.rs +++ b/crates/evm-helpers/src/contracts.rs @@ -50,7 +50,6 @@ sol! { address e3Program; bytes e3ProgramParams; bytes customParams; - address inputValidator; address decryptionVerifier; bytes32 committeePublicKey; bytes32 ciphertextOutput; diff --git a/crates/evm-helpers/src/events.rs b/crates/evm-helpers/src/events.rs index 56566c8b71..adc4b82319 100644 --- a/crates/evm-helpers/src/events.rs +++ b/crates/evm-helpers/src/events.rs @@ -20,11 +20,6 @@ sol! { function e3Program() external view returns (address); } - #[derive(Debug)] - interface IInputValidator { - function validateInput(bytes data) external view returns (bool); - } - #[derive(Debug)] interface IDecryptionVerifier { function verifyDecryption(bytes data) external view returns (bool); @@ -42,7 +37,6 @@ sol! { IE3Program e3Program; bytes e3ProgramParams; bytes customParams; - IInputValidator inputValidator; IDecryptionVerifier decryptionVerifier; bytes32 committeePublicKey; bytes32 ciphertextOutput; diff --git a/crates/evm-helpers/tests/fixtures/fake_enclave.sol b/crates/evm-helpers/tests/fixtures/fake_enclave.sol index a6d8a7184c..fe4c06645c 100644 --- a/crates/evm-helpers/tests/fixtures/fake_enclave.sol +++ b/crates/evm-helpers/tests/fixtures/fake_enclave.sol @@ -78,7 +78,6 @@ contract FakeEnclave { expiration: block.timestamp + 1 days, encryptionSchemeId: bytes32(keccak256("AES-256-GCM")), e3Program: 0x7F3E4df648B8Cb96C1D343be976b91B97CaD5c21, - inputValidator: 0xA51D5E87c0C82dDEBfa4E7E515B2D8Eea8f3e4f2, decryptionVerifier: 0x4B0D8c2E5f7a6c832f8b16d3aB0e7F5d9E9B24b1, e3ProgramParams: abi.encode(42, "testParams"), customParams: abi.encode("custom_params"), @@ -100,7 +99,6 @@ struct E3 { address e3Program; bytes e3ProgramParams; bytes customParams; - address inputValidator; address decryptionVerifier; bytes32 committeePublicKey; bytes32 ciphertextOutput; diff --git a/crates/indexer/tests/fixtures/fake_enclave.sol b/crates/indexer/tests/fixtures/fake_enclave.sol index a6d8a7184c..fe4c06645c 100644 --- a/crates/indexer/tests/fixtures/fake_enclave.sol +++ b/crates/indexer/tests/fixtures/fake_enclave.sol @@ -78,7 +78,6 @@ contract FakeEnclave { expiration: block.timestamp + 1 days, encryptionSchemeId: bytes32(keccak256("AES-256-GCM")), e3Program: 0x7F3E4df648B8Cb96C1D343be976b91B97CaD5c21, - inputValidator: 0xA51D5E87c0C82dDEBfa4E7E515B2D8Eea8f3e4f2, decryptionVerifier: 0x4B0D8c2E5f7a6c832f8b16d3aB0e7F5d9E9B24b1, e3ProgramParams: abi.encode(42, "testParams"), customParams: abi.encode("custom_params"), @@ -100,7 +99,6 @@ struct E3 { address e3Program; bytes e3ProgramParams; bytes customParams; - address inputValidator; address decryptionVerifier; bytes32 committeePublicKey; bytes32 ciphertextOutput; diff --git a/docs/pages/CRISP/introduction.mdx b/docs/pages/CRISP/introduction.mdx index 769c4ad7fb..d54cd397c9 100644 --- a/docs/pages/CRISP/introduction.mdx +++ b/docs/pages/CRISP/introduction.mdx @@ -76,12 +76,10 @@ Solidity contracts implementing the E3 program interface: Main E3 program contract implementing the `IE3Program` interface: - `validate()`: Validates voting parameters and setup - `verify()`: Verifies zkVM proofs of computation - -#### **CRISPInputValidator.sol** -Handles vote validation and zero-knowledge proof verification: -- Validates encrypted vote format -- Verifies voter eligibility proofs -- Ensures vote uniqueness +- `validateInput()`: Handles vote validation and zero-knowledge proof verification: + - Validates encrypted vote format + - Verifies voter eligibility proofs + - Ensures vote uniqueness #### **CRISPVerifier.sol** Noir verifier for proof of correct encryption: diff --git a/docs/pages/CRISP/setup.mdx b/docs/pages/CRISP/setup.mdx index 8ec294db22..8bb806761a 100644 --- a/docs/pages/CRISP/setup.mdx +++ b/docs/pages/CRISP/setup.mdx @@ -115,9 +115,6 @@ will look like the following: [DEPLOY] Deployed Semaphore to 0x9A9f2CCfdE556A7E9Ff0848998Aa4a0CFD8863AE [DEPLOY] Deployed CRISPCheckerFactory to 0x68B1D87F95878fE05B998F19b66F4baba5De1aed [DEPLOY] Deployed CRISPPolicyFactory to 0x3Aa5ebB10DC797CAC828524e59A333d0A371443c -[DEPLOY] Using CRISPInputValidator -[DEPLOY] Deployed InputValidator to: 0xc6e7DF5E7b4f2A278906862b61205850344D4e7d -[DEPLOY] Deployed CRISPInputValidatorFactory to 0x59b670e9fA9D0A427751Af201D676719a970857b [DEPLOY] Deployed HonkVerifier to 0x4ed7c70F96B99c776995fB64377f0d4aB3B0e1C1 [DEPLOY] Deployed CRISPProgram to 0x322813Fd9A801c5507c9de605d63CEA4f2CE6c44 [DEPLOY] Enabled E3 Program on Enclave @@ -312,7 +309,6 @@ The following steps are optional. You can config chainId = 31337 riscZeroVerifierAddress = "0x0000000000000000000000000000000000000000" enclaveAddress = "0xe7f1725E7734CE288F8367e1Bb143E90bb3F0512" - inputValidatorAddress = "0xa513E6E4b8f2a923D98304ec87F64353C4D5C853" ``` 3. Export the ETH_WALLET_PRIVATE_KEY environment variable (Anvil's default private key): diff --git a/docs/pages/architecture-overview.mdx b/docs/pages/architecture-overview.mdx index 6d9f65fabd..dd83b94433 100644 --- a/docs/pages/architecture-overview.mdx +++ b/docs/pages/architecture-overview.mdx @@ -40,12 +40,9 @@ and workflows to help you implement it effectively. - Verifies computation proofs - Interfaces with the Enclave contract - Ensures correct execution of the E3P - -#### InputValidator Contract - -- Validates and sanitizes input data -- Verifies Zero-Knowledge Proofs (ZKPs) -- Prevents malicious input injection +- Validates and sanitizes input data + - this might involve verifying a Zero-Knowledge Proof (ZKP) to ensure data integrity and authenticity + - prevents malicious input injection that could compromise the computation #### Decryption Verifier Contract diff --git a/docs/pages/building-with-enclave.mdx b/docs/pages/building-with-enclave.mdx index c0f2113244..f39d19dcf5 100644 --- a/docs/pages/building-with-enclave.mdx +++ b/docs/pages/building-with-enclave.mdx @@ -56,7 +56,7 @@ function request( ``` 2. Contract validates request parameters -3. E3 Program contract is set and used to get the InputValidator contract & Encryption scheme. +3. E3 Program contract is set and used to get the Encryption scheme. 4. Request is submitted to the ciphernodeRegistry for committee selection. 5. `E3Requested` event is emitted @@ -117,14 +117,14 @@ As much as possible, you should aim to validate inputs via proofs generated by D rather than in your Secure Process. This pushed computation to the edges and allows you to reduce the complexity of your FHE computation. -Your E3 Program must include a contract that implements IInputValidator. When publishing an input, -the Enclave contracts will call the `validate()` function on your Input Validator contract. +Your E3 Program must include logic that validates user inputs. When publishing an input, +the Enclave contracts will call the `validateInput()` function on your Program contract. ```solidity -function validate( +function validateInput( address sender, bytes memory params - ) external returns (bytes memory input, bool success); + ) external returns (bytes memory input); ``` At a minimum, this function should validate a proof that the given ciphertext is a valid encryption @@ -218,9 +218,9 @@ higher cost to compromise the E3), but incurs a higher protocol fee. 2. **Input Validation** -Your InputValidator contract is critical to ensuring that inputs come from approved parties, are +Your Program contract is critical to ensuring that inputs come from approved parties, are sanitized for your computation, and truthfully correspond to any specific sources of truth. You can -use your InputValidator contract to push computation to the edges, reducing the complexity of your +use your Program contract to push computation to the edges, reducing the complexity of your FHE computation. 3. **Result Verification** diff --git a/docs/pages/computation-flow.mdx b/docs/pages/computation-flow.mdx index d2ee08a111..88e79e86c3 100644 --- a/docs/pages/computation-flow.mdx +++ b/docs/pages/computation-flow.mdx @@ -57,12 +57,12 @@ During this phase, Data Providers — who may include individual users, applicat ensure they are valid for the requested E3. Some of these proofs are generic (e.g., proof of valid encryption) while others will be specific to your application. 3. **Submit Inputs**: Both encrypted data and ZKPs are submitted to the Enclave contract, which will - call the `validate` function on your E3P InputValidator smart contract. The input hash is then + call the `validateInput` function on your E3P smart contract. The input hash is then added to a Merkle tree, the root of which can later be used to anchor proofs of correct execution of your E3 Program. ```solidity - function validate( + function validateInput( address sender, bytes memory data ) external returns (bytes memory input); diff --git a/docs/pages/putting-it-together.mdx b/docs/pages/putting-it-together.mdx index 00e0b3dcd8..83844e8a49 100644 --- a/docs/pages/putting-it-together.mdx +++ b/docs/pages/putting-it-together.mdx @@ -103,7 +103,7 @@ impl ComputeProvider for Risc0Provider { // or FITNESS FOR A PARTICULAR PURPOSE. pragma solidity >=0.8.27; -import {CRISPBase, IEnclave, IE3Program, IInputValidator} from "evm_base/contracts/CRISPBase.sol"; +import {CRISPBase, IEnclave, IE3Program} from "evm_base/contracts/CRISPBase.sol"; import {IRiscZeroVerifier} from "risc0/IRiscZeroVerifier.sol"; contract MyE3Program is CRISPBase { @@ -111,23 +111,19 @@ contract MyE3Program is CRISPBase { bytes32 public constant ENCRYPTION_SCHEME_ID = /* Your Encryption Scheme ID */; IRiscZeroVerifier public verifier; - IInputValidator public inputValidator; constructor( IEnclave _enclave, - IInputValidator _inputValidator, IRiscZeroVerifier _verifier ) { - initialize(_enclave, _inputValidator, _verifier); + initialize(_enclave, _verifier); } function initialize( IEnclave _enclave, - IInputValidator _inputValidator, IRiscZeroVerifier _verifier ) public { CRISPBase.initialize(_enclave); - inputValidator = _inputValidator; verifier = _verifier; } diff --git a/docs/pages/write-e3-contract.mdx b/docs/pages/write-e3-contract.mdx index ca0dd05175..101aca3837 100644 --- a/docs/pages/write-e3-contract.mdx +++ b/docs/pages/write-e3-contract.mdx @@ -30,7 +30,7 @@ parameters when a new E3 instance is created and another to verify the output of bytes calldata computeProviderParams ) external - returns (bytes32 encryptionSchemeId, IInputValidator inputValidator); + returns (bytes32 encryptionSchemeId); ``` When a new instance of your E3 Program is requested, the `validate` function is called to validate @@ -63,11 +63,10 @@ your chosen Compute Provider to assess the validity of the proof and ciphertext. example of this using [RISC Zero's Verifier in our CRISP E3 contract](https://github.com/gnosisguild/CRISP/blob/9ffc89aedf92e8f8eb8a21b03091b1f48b587fe4/packages/risc0/contracts/CRISPRisc0.sol#L45). -### Input Validator +### Input Validation -In order to ensure correct computation, we recommend creating or using an existing input verifier -contract to check that the encrypted data submitted to your E3 is properly structured. This will -most likely be used in tandem with a proof generated by your Data Provider. +In order to ensure correct computation, we should be checking that the encrypted data submitted to your E3 is properly structured. This will +most likely be used in tandem with a proof generated by your Data Provider. The function should be implemented in the E3 Program contract. **Responsibilities:** @@ -80,13 +79,10 @@ most likely be used in tandem with a proof generated by your Data Provider. ```solidity pragma solidity >=0.8.27; -import {IInputValidator} from "@enclave-e3/contracts/interfaces.sol"; - -contract MyInputValidator is IInputValidator { - function validate(address sender, bytes memory data) external override returns (bytes memory, bool) { - // Decode data - // Verify ZKP - // Return validated input - } +function validateInput(address sender, bytes memory data) external returns (bytes memory input) { + // Decode the input data + // Verify associated ZKPs + // Return the validated input + return data; // Placeholder: replace with actual validated input } ``` diff --git a/examples/CRISP/Readme.md b/examples/CRISP/Readme.md index 213bfa0220..ca51e67f96 100644 --- a/examples/CRISP/Readme.md +++ b/examples/CRISP/Readme.md @@ -99,8 +99,6 @@ Deployments: ---------------------------------------------------------------------- Enclave: 0x9fE46736679d2D9a65F0992F2272dE9f3c7fa6e0 Verifier: 0xA51c1fc2f0D1a1b8494Ed1FE312d7C3a78Ed91C0 -InputValidator: 0x610178dA211FEF7D417bC0e6FeD39F05609AD788 -CRISPInputValidatorFactory: 0x0DCd1Bf9A1b36cE34237eEaFef220932846BCD82 HonkVerifier: 0x9A676e781A523b5d0C0e43731313A708CB607508 CRISPProgram: 0x959922bE3CAee4b8Cd9a407cc3ac1C251C2007B1 ``` diff --git a/examples/CRISP/client/.env.example b/examples/CRISP/client/.env.example index abc74fa235..a17f4aedbb 100644 --- a/examples/CRISP/client/.env.example +++ b/examples/CRISP/client/.env.example @@ -1,4 +1,3 @@ VITE_ENCLAVE_API=http://127.0.0.1:4000 VITE_TWITTER_SERVERLESS_API= VITE_WALLETCONNECT_PROJECT_ID= -VITE_E3_PROGRAM_ADDRESS=0xc3e53F4d16Ae77Db1c982e75a937B9f60FE63690 # Default E3 program address from hardhat diff --git a/examples/CRISP/client/src/config/Enclave.abi.ts b/examples/CRISP/client/src/config/Enclave.abi.ts deleted file mode 100644 index 50a202ec18..0000000000 --- a/examples/CRISP/client/src/config/Enclave.abi.ts +++ /dev/null @@ -1,96 +0,0 @@ -// SPDX-License-Identifier: LGPL-3.0-only -// -// This file is provided WITHOUT ANY WARRANTY; -// without even the implied warranty of MERCHANTABILITY -// or FITNESS FOR A PARTICULAR PURPOSE. - -const E3_PROGRAM_ADDRESS_FROM_ENV = import.meta.env.VITE_E3_PROGRAM_ADDRESS; - -if (!E3_PROGRAM_ADDRESS_FROM_ENV) { - throw new Error("VITE_E3_PROGRAM_ADDRESS environment variable is not set."); -} - -export const E3_PROGRAM_ADDRESS = E3_PROGRAM_ADDRESS_FROM_ENV; - -export const E3_PROGRAM_ABI = [ - { - "inputs": [ - { - "internalType": "uint256", - "name": "e3Id", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "identityCommitment", - "type": "uint256" - } - ], - "name": "registerMember", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "e3Id", - "type": "uint256" - } - ], - "name": "groupIds", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "groupId", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "identityCommitment", - "type": "uint256" - } - ], - "name": "committed", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "groupId", - "type": "uint256" - } - ], - "name": "getGroupCommitments", - "outputs": [ - { - "internalType": "uint256[]", - "name": "", - "type": "uint256[]" - } - ], - "stateMutability": "view", - "type": "function" - } -] as const; diff --git a/examples/CRISP/enclave.config.yaml b/examples/CRISP/enclave.config.yaml index 43efad8587..96b92a1ac3 100644 --- a/examples/CRISP/enclave.config.yaml +++ b/examples/CRISP/enclave.config.yaml @@ -3,7 +3,7 @@ chains: rpc_url: "ws://localhost:8545" contracts: e3_program: - address: "0xc3e53F4d16Ae77Db1c982e75a937B9f60FE63690" + address: "0xc5a5C42992dECbae36851359345FE25997F5C42d" deploy_block: 1 # Set to actual deploy block enclave: address: "0xA51c1fc2f0D1a1b8494Ed1FE312d7C3a78Ed91C0" diff --git a/examples/CRISP/packages/crisp-contracts/contracts/CRISPInputValidator.sol b/examples/CRISP/packages/crisp-contracts/contracts/CRISPInputValidator.sol deleted file mode 100644 index 917879e62d..0000000000 --- a/examples/CRISP/packages/crisp-contracts/contracts/CRISPInputValidator.sol +++ /dev/null @@ -1,107 +0,0 @@ -// SPDX-License-Identifier: LGPL-3.0-only -// -// This file is provided WITHOUT ANY WARRANTY; -// without even the implied warranty of MERCHANTABILITY -// or FITNESS FOR A PARTICULAR PURPOSE. -pragma solidity >=0.8.27; - -import {IInputValidator} from "@enclave-e3/contracts/contracts/interfaces/IInputValidator.sol"; -import {Clone} from "@excubiae/contracts/proxy/Clone.sol"; -import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol"; - -import {IVerifier} from "./CRISPVerifier.sol"; - -/// @title CRISPInputValidator. -/// @notice Enclave Input Validator -contract CRISPInputValidator is IInputValidator, Clone, Ownable(msg.sender) { - /// @notice The verifier that will be used to validate the input. - IVerifier internal noirVerifier; - - /// @notice The governance token address. - address public token; - /// @notice The minimum balance required to pass the validation. - uint256 public balanceThreshold; - /// @notice The block number at which the balance will be checked. - uint256 public snapshotBlock; - /// @notice The Merkle root of the census. - uint256 public censusMerkleRoot; - - /// @notice Indicates if the the round data has been set. - bool public isDataSet; - - /// @notice Mapping to store votes. Each elegible voter has their own slot - /// to store their vote. - mapping (address => bytes) public voteSlots; - - /// @notice The error emitted when the input data is empty. - error EmptyInputData(); - /// @notice The error emitted when the input data is invalid. - error InvalidInputData(bytes reason); - /// @notice The error emitted when the Noir proof is invalid. - error InvalidNoirProof(); - /// @notice The error emitted when the round data is not set. - error RoundDataNotSet(); - /// @notice The error emitted when trying to set the round data more than once. - error RoundDataAlreadySet(); - - /// @notice Initializes the contract with appended bytes data for configuration. - function _initialize() internal virtual override(Clone) { - super._initialize(); - - (address _verifierAddr, address _owner) = abi.decode( - _getAppendedBytes(), - (address, address) - ); - - noirVerifier = IVerifier(_verifierAddr); - _transferOwnership(_owner); - } - - /// @notice Sets the Merkle root of the census. Can only be set once. - /// @param _root The Merkle root to set. - function setRoundData(uint256 _root, address _token, uint256 _balanceThreshold, uint256 _snapshotBlock) external onlyOwner { - if (isDataSet) revert RoundDataAlreadySet(); - - isDataSet = true; - token = _token; - balanceThreshold = _balanceThreshold; - snapshotBlock = _snapshotBlock; - censusMerkleRoot = _root; - } - - /// @notice Validates input - /// @param data The input to be verified. - /// @return input The decoded, policy-approved application payload. - function validate( - address, - bytes memory data - ) external returns (bytes memory input) { - // we need to ensure that the CRISP admin set the merkle root of the census - // @todo update this once we have all components working - // if (!isDataSet) revert RoundDataNotSet(); - - if (data.length == 0) revert EmptyInputData(); - - ( - bytes memory noirProof, - bytes32[] memory noirPublicInputs, - bytes memory vote, - address slot - ) = abi.decode(data, (bytes, bytes32[], bytes, address)); - - /// @notice we need to check whether the slot is empty. - /// if the slot is empty - /// @todo pass it to the verifier - // bool isFirstVote = voteSlots[slot].length == 0; - - // Check if the ciphertext was encrypted correctly - if (!noirVerifier.verify(noirProof, noirPublicInputs)) - revert InvalidNoirProof(); - - /// @notice Store the vote in the correct slot. - voteSlots[slot] = vote; - - // return the vote so that it can be stored in Enclave's input merkle tree - input = vote; - } -} diff --git a/examples/CRISP/packages/crisp-contracts/contracts/CRISPInputValidatorFactory.sol b/examples/CRISP/packages/crisp-contracts/contracts/CRISPInputValidatorFactory.sol deleted file mode 100644 index 92cff1bd5f..0000000000 --- a/examples/CRISP/packages/crisp-contracts/contracts/CRISPInputValidatorFactory.sol +++ /dev/null @@ -1,28 +0,0 @@ -// SPDX-License-Identifier: LGPL-3.0-only -// -// This file is provided WITHOUT ANY WARRANTY; -// without even the implied warranty of MERCHANTABILITY -// or FITNESS FOR A PARTICULAR PURPOSE. -pragma solidity >=0.8.27; - -import {Factory} from "@excubiae/contracts/proxy/Factory.sol"; -import {CRISPInputValidator} from "./CRISPInputValidator.sol"; - -/// @title CRISPInputValidatorFactory -/// @notice Factory for deploying minimal proxy instances of CRISPInputValidator. -contract CRISPInputValidatorFactory is Factory { - /// @notice Initializes the factory with the CRISPInputValidator implementation. - constructor(address inputValidator) Factory(inputValidator) {} - - /// @notice Deploys a new CRISPInputValidator clone. - /// @param _verifierAddr Address of the associated verifier contract. - function deploy( - address _verifierAddr, - address _owner - ) public returns (address clone) { - bytes memory data = abi.encode(_verifierAddr, _owner); - - clone = super._deploy(data); - CRISPInputValidator(clone).initialize(); - } -} diff --git a/examples/CRISP/packages/crisp-contracts/contracts/CRISPProgram.sol b/examples/CRISP/packages/crisp-contracts/contracts/CRISPProgram.sol index c43cf8898c..52326197f4 100644 --- a/examples/CRISP/packages/crisp-contracts/contracts/CRISPProgram.sol +++ b/examples/CRISP/packages/crisp-contracts/contracts/CRISPProgram.sol @@ -8,23 +8,39 @@ pragma solidity >=0.8.27; import {IRiscZeroVerifier} from "risc0/IRiscZeroVerifier.sol"; import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol"; import {IE3Program} from "@enclave-e3/contracts/contracts/interfaces/IE3Program.sol"; -import {IInputValidator} from "@enclave-e3/contracts/contracts/interfaces/IInputValidator.sol"; import {IEnclave} from "@enclave-e3/contracts/contracts/interfaces/IEnclave.sol"; import {E3} from "@enclave-e3/contracts/contracts/interfaces/IE3.sol"; -import {CRISPInputValidatorFactory} from "./CRISPInputValidatorFactory.sol"; import {HonkVerifier} from "./CRISPVerifier.sol"; contract CRISPProgram is IE3Program, Ownable { + /// @notice a structure that holds the round data + struct RoundData { + /// @notice The governance token address. + address token; + /// @notice The minimum balance required to pass the validation. + uint256 balanceThreshold; + /// @notice The Merkle root of the census. + uint256 censusMerkleRoot; + } + // Constants bytes32 public constant ENCRYPTION_SCHEME_ID = keccak256("fhe.rs:BFV"); // State variables IEnclave public enclave; IRiscZeroVerifier public verifier; - CRISPInputValidatorFactory private immutable INPUT_VALIDATOR_FACTORY; HonkVerifier private immutable HONK_VERIFIER; bytes32 public imageId; + /// @notice the round data + RoundData public roundData; + /// @notice whether the round data has been set + bool public isDataSet; + + /// @notice Mapping to store votes. Each elegible voter has their own slot + /// to store their vote. + mapping(address => bytes) public voteSlots; + /// @notice Half of the largest minimum degree used to fit votes /// inside the plaintext polynomial uint256 public constant HALF_LARGEST_MINIMUM_DEGREE = 28; @@ -33,44 +49,64 @@ contract CRISPProgram is IE3Program, Ownable { mapping(address => bool) public authorizedContracts; mapping(uint256 e3Id => bytes32 paramsHash) public paramsHashes; - // Events - event InputValidatorUpdated(address indexed newValidator); - // Errors error CallerNotAuthorized(); error E3AlreadyInitialized(); error E3DoesNotExist(); error EnclaveAddressZero(); error VerifierAddressZero(); - error InvalidInputValidatorFactory(); + + /// @notice The error emitted when the honk verifier address is invalid. error InvalidHonkVerifier(); + /// @notice The error emitted when the input data is empty. + error EmptyInputData(); + /// @notice The error emitted when the input data is invalid. + error InvalidInputData(bytes reason); + /// @notice The error emitted when the Noir proof is invalid. + error InvalidNoirProof(); + /// @notice The error emitted when the round data is not set. + error RoundDataNotSet(); + /// @notice The error emitted when trying to set the round data more than once. + error RoundDataAlreadySet(); /// @notice Initialize the contract, binding it to a specified RISC Zero verifier. /// @param _enclave The enclave address /// @param _verifier The RISC Zero verifier address - /// @param _inputValidatorFactory The input validator factory address /// @param _honkVerifier The honk verifier address /// @param _imageId The image ID for the guest program - constructor( - IEnclave _enclave, - IRiscZeroVerifier _verifier, - CRISPInputValidatorFactory _inputValidatorFactory, - HonkVerifier _honkVerifier, - bytes32 _imageId - ) Ownable(msg.sender) { + constructor(IEnclave _enclave, IRiscZeroVerifier _verifier, HonkVerifier _honkVerifier, bytes32 _imageId) + Ownable(msg.sender) + { require(address(_enclave) != address(0), EnclaveAddressZero()); require(address(_verifier) != address(0), VerifierAddressZero()); - require(address(_inputValidatorFactory) != address(0), InvalidInputValidatorFactory()); require(address(_honkVerifier) != address(0), InvalidHonkVerifier()); enclave = _enclave; verifier = _verifier; - INPUT_VALIDATOR_FACTORY = _inputValidatorFactory; HONK_VERIFIER = _honkVerifier; authorizedContracts[address(_enclave)] = true; imageId = _imageId; } + /// @notice Sets the Round data. Can only be set once. + /// @param _root The Merkle root to set. + /// @param _token The governance token address. + /// @param _balanceThreshold The minimum balance required. + function setRoundData(uint256 _root, address _token, uint256 _balanceThreshold) + external + onlyOwner + { + if (isDataSet) revert RoundDataAlreadySet(); + + isDataSet = true; + + roundData = RoundData({ + token: _token, + balanceThreshold: _balanceThreshold, + censusMerkleRoot: _root + }); + } + /// @notice Set the Image ID for the guest program /// @param _imageId The new image ID. function setImageId(bytes32 _imageId) external onlyOwner { @@ -80,6 +116,7 @@ contract CRISPProgram is IE3Program, Ownable { /// @notice Set the RISC Zero verifier address /// @param _verifier The new RISC Zero verifier address function setVerifier(IRiscZeroVerifier _verifier) external onlyOwner { + if (address(_verifier) == address(0)) revert VerifierAddressZero(); verifier = _verifier; } @@ -95,16 +132,42 @@ contract CRISPProgram is IE3Program, Ownable { /// @param e3ProgramParams The E3 program parameters function validate(uint256 e3Id, uint256, bytes calldata e3ProgramParams, bytes calldata) external - returns (bytes32, IInputValidator inputValidator) + returns (bytes32) { require(authorizedContracts[msg.sender] || msg.sender == owner(), CallerNotAuthorized()); require(paramsHashes[e3Id] == bytes32(0), E3AlreadyInitialized()); paramsHashes[e3Id] = keccak256(e3ProgramParams); - // Deploy a new input validator - inputValidator = IInputValidator(INPUT_VALIDATOR_FACTORY.deploy(address(HONK_VERIFIER), owner())); + return ENCRYPTION_SCHEME_ID; + } + + function validateInput(address, bytes memory data) external returns (bytes memory input) { + // it should only be called via Enclave for now + require(authorizedContracts[msg.sender] || msg.sender == owner(), CallerNotAuthorized()); + // we need to ensure that the CRISP admin set the merkle root of the census + // @todo update this once we have all components working + // if (!isDataSet) revert RoundDataNotSet(); + + if (data.length == 0) revert EmptyInputData(); + + (bytes memory noirProof, bytes32[] memory noirPublicInputs, bytes memory vote, address slot) = + abi.decode(data, (bytes, bytes32[], bytes, address)); + + /// @notice we need to check whether the slot is empty. + /// if the slot is empty + /// @todo pass it to the verifier + // bool isFirstVote = voteSlots[slot].length == 0; + + // Check if the ciphertext was encrypted correctly + if (!HONK_VERIFIER.verify(noirProof, noirPublicInputs)) { + revert InvalidNoirProof(); + } + + /// @notice Store the vote in the correct slot. + voteSlots[slot] = vote; - return (ENCRYPTION_SCHEME_ID, inputValidator); + // return the vote so that it can be stored in Enclave's input merkle tree + input = vote; } /// @notice Decode the tally from the plaintext output diff --git a/examples/CRISP/packages/crisp-contracts/contracts/CRISPVerifier.sol b/examples/CRISP/packages/crisp-contracts/contracts/CRISPVerifier.sol index c6b8d5b539..90aee997c2 100644 --- a/examples/CRISP/packages/crisp-contracts/contracts/CRISPVerifier.sol +++ b/examples/CRISP/packages/crisp-contracts/contracts/CRISPVerifier.sol @@ -1883,4 +1883,4 @@ contract HonkVerifier is BaseHonkVerifier(N, LOG_N, NUMBER_OF_PUBLIC_INPUTS) { function loadVerificationKey() internal pure override returns (Honk.VerificationKey memory) { return HonkVerificationKey.loadVerificationKey(); } -} +} \ No newline at end of file diff --git a/examples/CRISP/packages/crisp-contracts/contracts/ImageID.sol b/examples/CRISP/packages/crisp-contracts/contracts/ImageID.sol index 2522b6d98a..7bff45a61e 100755 --- a/examples/CRISP/packages/crisp-contracts/contracts/ImageID.sol +++ b/examples/CRISP/packages/crisp-contracts/contracts/ImageID.sol @@ -19,8 +19,5 @@ pragma solidity ^0.8.20; library ImageID { - bytes32 public constant PROGRAM_ID = - bytes32( - 0x23734b77b0f76e85623a88d7a82f24c34c94834f2501964ea123b7a2027013a2 - ); + bytes32 public constant PROGRAM_ID = bytes32(0x23734b77b0f76e85623a88d7a82f24c34c94834f2501964ea123b7a2027013a2); } diff --git a/examples/CRISP/packages/crisp-contracts/contracts/Mocks/MockCRISPInputValidator.sol b/examples/CRISP/packages/crisp-contracts/contracts/Mocks/MockCRISPInputValidator.sol deleted file mode 100644 index 636ae5e323..0000000000 --- a/examples/CRISP/packages/crisp-contracts/contracts/Mocks/MockCRISPInputValidator.sol +++ /dev/null @@ -1,35 +0,0 @@ -// SPDX-License-Identifier: LGPL-3.0-only -// -// This file is provided WITHOUT ANY WARRANTY; -// without even the implied warranty of MERCHANTABILITY -// or FITNESS FOR A PARTICULAR PURPOSE. -pragma solidity >=0.8.27; - -import {IInputValidator} from "@enclave-e3/contracts/contracts/interfaces/IInputValidator.sol"; -import {IBasePolicy} from "@excubiae/contracts/interfaces/IBasePolicy.sol"; -import {Clone} from "@excubiae/contracts/proxy/Clone.sol"; -import {IVerifier} from "../CRISPVerifier.sol"; - -/// @title MockCRISPInputValidator. -/// @notice Mock Enclave Input Validator -contract MockCRISPInputValidator is IInputValidator, Clone { - /// @notice The error emitted when the input data is empty. - error EmptyInputData(); - - /// @notice Initializes the contract with appended bytes data for configuration. - function _initialize() internal virtual override(Clone) { - super._initialize(); - } - - /// @notice Validates input - /// @param sender The account that is submitting the input. - /// @param data The input to be verified. - /// @return input The decoded, policy-approved application payload. - function validate(address sender, bytes memory data) external returns (bytes memory input) { - if (data.length == 0) revert EmptyInputData(); - - (,,bytes memory vote,) = abi.decode(data, (bytes, bytes32[], bytes, address)); - - input = vote; - } -} diff --git a/examples/CRISP/packages/crisp-contracts/contracts/Mocks/MockCRISPProgram.sol b/examples/CRISP/packages/crisp-contracts/contracts/Mocks/MockCRISPProgram.sol new file mode 100644 index 0000000000..452c4ec13a --- /dev/null +++ b/examples/CRISP/packages/crisp-contracts/contracts/Mocks/MockCRISPProgram.sol @@ -0,0 +1,223 @@ +// SPDX-License-Identifier: LGPL-3.0-only +// +// This file is provided WITHOUT ANY WARRANTY; +// without even the implied warranty of MERCHANTABILITY +// or FITNESS FOR A PARTICULAR PURPOSE. +pragma solidity >=0.8.27; + +import {IRiscZeroVerifier} from "risc0/IRiscZeroVerifier.sol"; +import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol"; +import {IE3Program} from "@enclave-e3/contracts/contracts/interfaces/IE3Program.sol"; +import {IEnclave} from "@enclave-e3/contracts/contracts/interfaces/IEnclave.sol"; +import {E3} from "@enclave-e3/contracts/contracts/interfaces/IE3.sol"; +import {HonkVerifier} from "../CRISPVerifier.sol"; + +contract MockCRISPProgram is IE3Program, Ownable { + /// @notice a structure that holds the round data + struct RoundData { + /// @notice The governance token address. + address token; + /// @notice The minimum balance required to pass the validation. + uint256 balanceThreshold; + /// @notice The block number at which the balance will be checked. + uint256 snapshotBlock; + /// @notice The Merkle root of the census. + uint256 censusMerkleRoot; + } + + // Constants + bytes32 public constant ENCRYPTION_SCHEME_ID = keccak256("fhe.rs:BFV"); + + // State variables + IEnclave public enclave; + IRiscZeroVerifier public verifier; + HonkVerifier private immutable HONK_VERIFIER; + bytes32 public imageId; + + /// @notice the round data + RoundData public roundData; + /// @notice whether the round data has been set + bool public isDataSet; + + /// @notice Mapping to store votes. Each elegible voter has their own slot + /// to store their vote. + mapping(address => bytes) public voteSlots; + + /// @notice Half of the largest minimum degree used to fit votes + /// inside the plaintext polynomial + uint256 public constant HALF_LARGEST_MINIMUM_DEGREE = 28; + + // Mappings + mapping(address => bool) public authorizedContracts; + mapping(uint256 e3Id => bytes32 paramsHash) public paramsHashes; + + // Errors + error CallerNotAuthorized(); + error E3AlreadyInitialized(); + error E3DoesNotExist(); + error EnclaveAddressZero(); + error VerifierAddressZero(); + + /// @notice The error emitted when the honk verifier address is invalid. + error InvalidHonkVerifier(); + /// @notice The error emitted when the input data is empty. + error EmptyInputData(); + /// @notice The error emitted when the input data is invalid. + error InvalidInputData(bytes reason); + /// @notice The error emitted when the Noir proof is invalid. + error InvalidNoirProof(); + /// @notice The error emitted when the round data is not set. + error RoundDataNotSet(); + /// @notice The error emitted when trying to set the round data more than once. + error RoundDataAlreadySet(); + + /// @notice Initialize the contract, binding it to a specified RISC Zero verifier. + /// @param _enclave The enclave address + /// @param _verifier The RISC Zero verifier address + /// @param _honkVerifier The honk verifier address + /// @param _imageId The image ID for the guest program + constructor(IEnclave _enclave, IRiscZeroVerifier _verifier, HonkVerifier _honkVerifier, bytes32 _imageId) + Ownable(msg.sender) + { + require(address(_enclave) != address(0), EnclaveAddressZero()); + require(address(_verifier) != address(0), VerifierAddressZero()); + require(address(_honkVerifier) != address(0), InvalidHonkVerifier()); + + enclave = _enclave; + verifier = _verifier; + HONK_VERIFIER = _honkVerifier; + authorizedContracts[address(_enclave)] = true; + imageId = _imageId; + } + + /// @notice Sets the Merkle root of the census. Can only be set once. + /// @param _root The Merkle root to set. + function setRoundData(uint256 _root, address _token, uint256 _balanceThreshold, uint256 _snapshotBlock) + external + onlyOwner + { + if (isDataSet) revert RoundDataAlreadySet(); + + isDataSet = true; + + roundData = RoundData({ + token: _token, + balanceThreshold: _balanceThreshold, + snapshotBlock: _snapshotBlock, + censusMerkleRoot: _root + }); + } + + /// @notice Set the Image ID for the guest program + /// @param _imageId The new image ID. + function setImageId(bytes32 _imageId) external onlyOwner { + imageId = _imageId; + } + + /// @notice Set the RISC Zero verifier address + /// @param _verifier The new RISC Zero verifier address + function setVerifier(IRiscZeroVerifier _verifier) external onlyOwner { + verifier = _verifier; + } + + /// @notice Get the params hash for an E3 program + /// @param e3Id The E3 program ID + /// @return The params hash + function getParamsHash(uint256 e3Id) public view returns (bytes32) { + return paramsHashes[e3Id]; + } + + /// @notice Validate the E3 program parameters + /// @param e3Id The E3 program ID + /// @param e3ProgramParams The E3 program parameters + function validate(uint256 e3Id, uint256, bytes calldata e3ProgramParams, bytes calldata) + external + returns (bytes32) + { + require(authorizedContracts[msg.sender] || msg.sender == owner(), CallerNotAuthorized()); + require(paramsHashes[e3Id] == bytes32(0), E3AlreadyInitialized()); + paramsHashes[e3Id] = keccak256(e3ProgramParams); + + return ENCRYPTION_SCHEME_ID; + } + + function validateInput(address, bytes memory data) external returns (bytes memory input) { + if (data.length == 0) revert EmptyInputData(); + + (,, bytes memory vote,) = abi.decode(data, (bytes, bytes32[], bytes, address)); + + input = vote; + } + + /// @notice Decode the tally from the plaintext output + /// @param e3Id The E3 program ID + /// @return yes The number of yes votes + /// @return no The number of no votes + function decodeTally(uint256 e3Id) public view returns (uint256 yes, uint256 no) { + // fetch from enclave + E3 memory e3 = enclave.getE3(e3Id); + + // abi decode it into an array of uint256 + uint256[] memory tally = abi.decode(e3.plaintextOutput, (uint256[])); + + /// @notice We want to completely ignore anything outside of the coefficients + /// we agreed to store out votes on. + uint256 halfD = tally.length / 2; + uint256 START_INDEX_Y = halfD - HALF_LARGEST_MINIMUM_DEGREE; + uint256 START_INDEX_N = tally.length - HALF_LARGEST_MINIMUM_DEGREE; + + // first weight (we are converting back from bits to integer) + uint256 weight = 2 ** (HALF_LARGEST_MINIMUM_DEGREE - 1); + + // Convert yes votes + for (uint256 i = START_INDEX_Y; i < halfD; i++) { + yes += tally[i] * weight; + weight /= 2; // Right shift equivalent + } + + // Reset weight for no votes + weight = 2 ** (HALF_LARGEST_MINIMUM_DEGREE - 1); + + // Convert no votes + for (uint256 i = START_INDEX_N; i < tally.length; i++) { + no += tally[i] * weight; + weight /= 2; + } + + return (yes, no); + } + + /// @notice Verify the proof + /// @param e3Id The E3 program ID + /// @param ciphertextOutputHash The hash of the ciphertext output + /// @param proof The proof to verify + function verify(uint256 e3Id, bytes32 ciphertextOutputHash, bytes memory proof) + external + view + override + returns (bool) + { + require(paramsHashes[e3Id] != bytes32(0), E3DoesNotExist()); + bytes32 inputRoot = bytes32(enclave.getInputRoot(e3Id)); + bytes memory journal = new bytes(396); // (32 + 1) * 4 * 3 + + encodeLengthPrefixAndHash(journal, 0, ciphertextOutputHash); + encodeLengthPrefixAndHash(journal, 132, paramsHashes[e3Id]); + encodeLengthPrefixAndHash(journal, 264, inputRoot); + + verifier.verify(proof, imageId, sha256(journal)); + return true; + } + + /// @notice Encode length prefix and hash + /// @param journal The journal to encode into + /// @param startIndex The start index in the journal + /// @param hashVal The hash value to encode + function encodeLengthPrefixAndHash(bytes memory journal, uint256 startIndex, bytes32 hashVal) internal pure { + journal[startIndex] = 0x20; + startIndex += 4; + for (uint256 i = 0; i < 32; i++) { + journal[startIndex + i * 4] = hashVal[i]; + } + } +} diff --git a/examples/CRISP/packages/crisp-contracts/contracts/Mocks/MockEnclave.sol b/examples/CRISP/packages/crisp-contracts/contracts/Mocks/MockEnclave.sol index 1cefce8b2e..2df0fb8d40 100644 --- a/examples/CRISP/packages/crisp-contracts/contracts/Mocks/MockEnclave.sol +++ b/examples/CRISP/packages/crisp-contracts/contracts/Mocks/MockEnclave.sol @@ -7,7 +7,6 @@ pragma solidity >=0.8.27; import {E3} from "@enclave-e3/contracts/contracts/interfaces/IE3.sol"; import {IE3Program} from "@enclave-e3/contracts/contracts/interfaces/IE3Program.sol"; -import {IInputValidator} from "@enclave-e3/contracts/contracts/interfaces/IInputValidator.sol"; import {IDecryptionVerifier} from "@enclave-e3/contracts/contracts/interfaces/IDecryptionVerifier.sol"; contract MockEnclave { @@ -29,7 +28,6 @@ contract MockEnclave { e3Program: IE3Program(address(0)), e3ProgramParams: bytes(""), customParams: bytes(""), - inputValidator: IInputValidator(address(0)), decryptionVerifier: IDecryptionVerifier(address(0)), committeePublicKey: bytes32(0), ciphertextOutput: bytes32(0), diff --git a/examples/CRISP/packages/crisp-contracts/contracts/Mocks/MockRISC0Verifier.sol b/examples/CRISP/packages/crisp-contracts/contracts/Mocks/MockRISC0Verifier.sol index df57d12125..7d0ca3cb8e 100644 --- a/examples/CRISP/packages/crisp-contracts/contracts/Mocks/MockRISC0Verifier.sol +++ b/examples/CRISP/packages/crisp-contracts/contracts/Mocks/MockRISC0Verifier.sol @@ -8,11 +8,7 @@ pragma solidity ^0.8.27; import {IRiscZeroVerifier, Receipt} from "risc0/IRiscZeroVerifier.sol"; contract MockRISC0Verifier is IRiscZeroVerifier { - function verify( - bytes calldata seal, - bytes32 imageId, - bytes32 journalDigest - ) public view override {} + function verify(bytes calldata seal, bytes32 imageId, bytes32 journalDigest) public view override {} function verifyIntegrity(Receipt calldata receipt) external view override {} } diff --git a/examples/CRISP/packages/crisp-contracts/contracts/Mocks/RiscZeroGroth16Verifier.sol b/examples/CRISP/packages/crisp-contracts/contracts/Mocks/RiscZeroGroth16Verifier.sol index e48247c71a..4fd5d0955f 100644 --- a/examples/CRISP/packages/crisp-contracts/contracts/Mocks/RiscZeroGroth16Verifier.sol +++ b/examples/CRISP/packages/crisp-contracts/contracts/Mocks/RiscZeroGroth16Verifier.sol @@ -9,8 +9,5 @@ import {RiscZeroGroth16Verifier as RiscZero} from "risc0/groth16/RiscZeroGroth16 import {ControlID} from "risc0/groth16/ControlID.sol"; contract RiscZeroGroth16Verifier is RiscZero { - constructor() RiscZero( - ControlID.CONTROL_ROOT, - ControlID.BN254_CONTROL_ID - ) {} -} \ No newline at end of file + constructor() RiscZero(ControlID.CONTROL_ROOT, ControlID.BN254_CONTROL_ID) {} +} diff --git a/examples/CRISP/packages/crisp-contracts/deploy/crisp.ts b/examples/CRISP/packages/crisp-contracts/deploy/crisp.ts index fcb2ef147b..c9be6098a7 100644 --- a/examples/CRISP/packages/crisp-contracts/deploy/crisp.ts +++ b/examples/CRISP/packages/crisp-contracts/deploy/crisp.ts @@ -10,6 +10,7 @@ import { } from "@enclave-e3/contracts/scripts"; import { Enclave__factory as EnclaveFactory } from "@enclave-e3/contracts/types"; +import { ContractFactory } from "ethers"; import hre from "hardhat"; const IMAGE_ID = @@ -29,7 +30,6 @@ export const deployCRISPContracts = async () => { const verifier = await deployVerifier(useMockVerifier); - const inputValidator = await deployInputValidator(useMockInputValidator); const enclaveAddress = readDeploymentArgs("Enclave", chain)?.address; if (!enclaveAddress) { @@ -37,28 +37,9 @@ export const deployCRISPContracts = async () => { } const enclave = EnclaveFactory.connect(enclaveAddress, owner); - const crispInputValidatorFactoryFactory = await ethers.getContractFactory( - "CRISPInputValidatorFactory" - ); - const crispInputValidatorFactory = - await crispInputValidatorFactoryFactory.deploy(inputValidator); - - const crispInputValidatorFactoryAddress = - await crispInputValidatorFactory.getAddress(); - storeDeploymentArgs( - { - address: crispInputValidatorFactoryAddress, - constructorArgs: { - inputValidator, - }, - }, - "CRISPInputValidatorFactory", - chain - ); - - const honkVerifierFactory = await ethers.getContractFactory("HonkVerifier"); - const honkVerifier = await honkVerifierFactory.deploy(); - const honkVerifierAddress = await honkVerifier.getAddress(); + const honkVerifierFactory = await ethers.getContractFactory("HonkVerifier"); + const honkVerifier = await honkVerifierFactory.deploy(); + const honkVerifierAddress = await honkVerifier.getAddress(); storeDeploymentArgs( { @@ -68,46 +49,45 @@ export const deployCRISPContracts = async () => { chain ); - const crispFactory = await ethers.getContractFactory("CRISPProgram"); - const crisp = await crispFactory.deploy( - enclaveAddress, - verifier, - crispInputValidatorFactory.getAddress(), - honkVerifierAddress, - IMAGE_ID - ); + let crispFactory: ContractFactory; - const crispAddress = await crisp.getAddress(); + if (useMockInputValidator) { + console.log("Using MockCRISPProgram"); + crispFactory = await ethers.getContractFactory("MockCRISPProgram"); + } else { + crispFactory = await ethers.getContractFactory("CRISPProgram"); + } - storeDeploymentArgs( - { + const crisp = await crispFactory.deploy( + enclaveAddress, + verifier, + honkVerifierAddress, + IMAGE_ID, + ) + + const crispAddress = await crisp.getAddress(); + storeDeploymentArgs({ address: crispAddress, constructorArgs: { - enclave: enclaveAddress, - verifierAddress: verifier, - inputValidatorAddress: inputValidator, - honkVerifierAddress, - imageId: IMAGE_ID, - }, - }, - "CRISPProgram", - chain - ); + enclave: enclaveAddress, + verifierAddress: verifier, + honkVerifierAddress, + imageId: IMAGE_ID + } + }, "CRISPProgram", chain); // enable the program on Enclave const tx = await enclave.enableE3Program(crispAddress); await tx.wait(); console.log(` - Deployments: - ---------------------------------------------------------------------- - Enclave: ${enclaveAddress} - Risc0Verifier: ${verifier} - InputValidator: ${inputValidator} - CRISPInputValidatorFactory: ${crispInputValidatorFactoryAddress} - HonkVerifier: ${honkVerifierAddress} - CRISPProgram: ${crispAddress} - `); + Deployments: + ---------------------------------------------------------------------- + Enclave: ${enclaveAddress} + Risc0Verifier: ${verifier} + HonkVerifier: ${honkVerifierAddress} + CRISPProgram: ${crispAddress} + `); }; /** @@ -122,132 +102,34 @@ export const deployVerifier = async ( const chain = hre.globalOptions.network; if (!useMockVerifier) { - const existingVerifier = readDeploymentArgs( - "RiscZeroGroth16Verifier", - chain - ); + const existingVerifier = readDeploymentArgs("RiscZeroGroth16Verifier", chain); if (existingVerifier?.address) { - console.log( - "RiscZeroGroth16Verifier already deployed at:", - existingVerifier.address - ); - return existingVerifier.address; + console.log("RiscZeroGroth16Verifier already deployed at:", existingVerifier.address); + return existingVerifier.address; } - - const verifierFactory = await ethers.getContractFactory( - "RiscZeroGroth16Verifier" - ); + const verifierFactory = await ethers.getContractFactory("RiscZeroGroth16Verifier"); const verifier = await verifierFactory.deploy(); await verifier.waitForDeployment(); - const address = await verifier.getAddress(); - - storeDeploymentArgs( - { + + storeDeploymentArgs({ address, - }, - "RiscZeroGroth16Verifier", - chain - ); - + }, "RiscZeroGroth16Verifier", chain); return address; - } - + } // Check if mock verifier already deployed const existingMockVerifier = readDeploymentArgs("MockRISC0Verifier", chain); if (existingMockVerifier?.address) { - console.log( - "MockRISC0Verifier already deployed at:", - existingMockVerifier.address - ); - return existingMockVerifier.address; + console.log("MockRISC0Verifier already deployed at:", existingMockVerifier.address); + return existingMockVerifier.address; } - - const mockVerifierFactory = await ethers.getContractFactory( - "MockRISC0Verifier" - ); + const mockVerifierFactory = await ethers.getContractFactory("MockRISC0Verifier"); const mockVerifier = await mockVerifierFactory.deploy(); - + await mockVerifier.waitForDeployment(); const mockVerifierAddress = await mockVerifier.getAddress(); - storeDeploymentArgs( - { + storeDeploymentArgs({ address: mockVerifierAddress, - }, - "MockRISC0Verifier", - hre.globalOptions.network - ); - - return mockVerifierAddress; -}; - -/** - * Deploys the input validator contract - * @param useMockInputValidator - whether to use a mock input validator - * @returns The address of the input validator - */ -export const deployInputValidator = async ( - useMockInputValidator: boolean -): Promise => { - const { ethers } = await hre.network.connect(); - const chain = hre.globalOptions.network; - - if (useMockInputValidator) { - // Check if mock input validator already deployed - const existingMockInputValidator = readDeploymentArgs( - "MockCRISPInputValidator", - chain - ); - if (existingMockInputValidator?.address) { - console.log( - "MockInputValidator already deployed at:", - existingMockInputValidator.address - ); - return existingMockInputValidator.address; - } - - const mockInputValidatorFactory = await ethers.getContractFactory( - "MockCRISPInputValidator" - ); - const mockInputValidator = await mockInputValidatorFactory.deploy(); - const address = await mockInputValidator.getAddress(); - - storeDeploymentArgs( - { - address, - }, - "MockCRISPInputValidator", - hre.globalOptions.network - ); + }, "MockRISC0Verifier", hre.globalOptions.network); - return address; - } - - // Check if input validator already deployed - const existingInputValidator = readDeploymentArgs( - "CRISPInputValidator", - chain - ); - if (existingInputValidator?.address) { - console.log( - "CRISPInputValidator already deployed at:", - existingInputValidator.address - ); - return existingInputValidator.address; - } - - const inputValidatorFactory = await ethers.getContractFactory( - "CRISPInputValidator" - ); - const inputValidator = await inputValidatorFactory.deploy(); - const address = await inputValidator.getAddress(); - - storeDeploymentArgs( - { - address, - }, - "CRISPInputValidator", - hre.globalOptions.network - ); - - return address; -}; + return mockVerifierAddress; +} diff --git a/examples/CRISP/packages/crisp-contracts/deployed_contracts.json b/examples/CRISP/packages/crisp-contracts/deployed_contracts.json index 746f27b392..9d3e9ce8e9 100644 --- a/examples/CRISP/packages/crisp-contracts/deployed_contracts.json +++ b/examples/CRISP/packages/crisp-contracts/deployed_contracts.json @@ -95,46 +95,29 @@ "address": "0x9e4b733ACa2b5af39185fc4C3A9bc65a60ac8C18" }, "MockComputeProvider": { - "blockNumber": 9621863, - "address": "0xCD1c93B0353DFb4f6f65aB9CF4f7Cb3e545359F8" + "blockNumber": 23, + "address": "0x59b670e9fA9D0A427751Af201D676719a970857b" }, "MockDecryptionVerifier": { - "blockNumber": 9621864, - "address": "0xf3260Bc8C6f2B94f7F7fD8f1C6A8972356432308" - }, - "MockInputValidator": { - "blockNumber": 9621865, - "address": "0xe0A4A8DEBb24Ec9b7d79A97a4Cd3e10Dd52989E5" + "blockNumber": 24, + "address": "0x4ed7c70F96B99c776995fB64377f0d4aB3B0e1C1" }, "MockE3Program": { - "constructorArgs": { - "mockInputValidator": "0xe0A4A8DEBb24Ec9b7d79A97a4Cd3e10Dd52989E5" - }, - "blockNumber": 9621866, - "address": "0x2103196DFA7817D262eEDB3B846E69Dd7Bd76f4C" + "blockNumber": 25, + "address": "0x322813Fd9A801c5507c9de605d63CEA4f2CE6c44" }, "MockRISC0Verifier": { - "address": "0x6c39658221603adBd02f956574efdb3c75822F0f" - }, - "MockCRISPInputValidator": { - "address": "0x1D396BC1334900c9B1b62672B34127A1A127c718" - }, - "CRISPInputValidatorFactory": { - "address": "0x2D71D33BaA1FBA9dd677FA31863aA619AF0488E9", - "constructorArgs": { - "inputValidator": "0x764364c0e4C3072A7DF777F4037907fdf2f1A89f" - } + "address": "0x7a2088a1bFc9d81c55368AE168C2C02570cB814F" }, "HonkVerifier": { - "address": "0x957857a5EBe9177F2573cB3356e4c5e3eC88f42a" + "address": "0x09635F643e140090A9A8Dcd712eD6285858ceBef" }, "CRISPProgram": { - "address": "0x029d937aFA153a6AF8CD1ff91B51b86Ca68fDa4b", + "address": "0xc5a5C42992dECbae36851359345FE25997F5C42d", "constructorArgs": { - "enclave": "0x9e4b733ACa2b5af39185fc4C3A9bc65a60ac8C18", - "verifierAddress": "0x6c39658221603adBd02f956574efdb3c75822F0f", - "inputValidatorAddress": "0x764364c0e4C3072A7DF777F4037907fdf2f1A89f", - "honkVerifierAddress": "0x957857a5EBe9177F2573cB3356e4c5e3eC88f42a", + "enclave": "0xA51c1fc2f0D1a1b8494Ed1FE312d7C3a78Ed91C0", + "verifierAddress": "0x7a2088a1bFc9d81c55368AE168C2C02570cB814F", + "honkVerifierAddress": "0x09635F643e140090A9A8Dcd712eD6285858ceBef", "imageId": "0x23734b77b0f76e85623a88d7a82f24c34c94834f2501964ea123b7a2027013a2" } }, diff --git a/examples/CRISP/packages/crisp-contracts/hardhat.config.ts b/examples/CRISP/packages/crisp-contracts/hardhat.config.ts index f7ea54a076..4dd0c0ec5e 100644 --- a/examples/CRISP/packages/crisp-contracts/hardhat.config.ts +++ b/examples/CRISP/packages/crisp-contracts/hardhat.config.ts @@ -156,7 +156,6 @@ const config: HardhatUserConfig = { "@enclave-e3/contracts/contracts/test/MockComputeProvider.sol", "@enclave-e3/contracts/contracts/test/MockDecryptionVerifier.sol", "@enclave-e3/contracts/contracts/test/MockE3Program.sol", - "@enclave-e3/contracts/contracts/test/MockInputValidator.sol", "@enclave-e3/contracts/contracts/test/MockSlashingVerifier.sol", "@enclave-e3/contracts/contracts/test/MockStableToken.sol", ], diff --git a/examples/CRISP/packages/crisp-contracts/tests/crisp.contracts.test.ts b/examples/CRISP/packages/crisp-contracts/tests/crisp.contracts.test.ts index e3e5e75b1d..02270032c4 100644 --- a/examples/CRISP/packages/crisp-contracts/tests/crisp.contracts.test.ts +++ b/examples/CRISP/packages/crisp-contracts/tests/crisp.contracts.test.ts @@ -36,21 +36,19 @@ describe("CRISP Contracts", function () { /* IEnclave _enclave, IRiscZeroVerifier _verifier, - CRISPInputValidatorFactory _inputValidatorFactory, HonkVerifier _honkVerifier, bytes32 _imageId */ - const program = await ethers.deployContract("CRISPProgram", [ - nonZeroAddress, - nonZeroAddress, - nonZeroAddress, - nonZeroAddress, - zeroHash, - ]); - - expect(await program.getAddress()).to.not.equal(zeroAddress); + const program = await ethers.deployContract("CRISPProgram", [ + nonZeroAddress, + nonZeroAddress, + nonZeroAddress, + zeroHash + ]) + + expect(await program.getAddress()).to.not.equal(zeroAddress) + }) }); - }); describe("decode tally", () => { it("should decode different tallies correctly", async () => { diff --git a/examples/CRISP/server/.env.example b/examples/CRISP/server/.env.example index 9dc272e761..a9776b1487 100644 --- a/examples/CRISP/server/.env.example +++ b/examples/CRISP/server/.env.example @@ -12,10 +12,10 @@ ETHERSCAN_API_KEY="" # Cron-job API key to trigger new rounds CRON_API_KEY=1234567890 -# Based on Default Anvil Deployments (Only for testing) +# Based on Default Hardhat Deployments (Only for testing) ENCLAVE_ADDRESS="0xA51c1fc2f0D1a1b8494Ed1FE312d7C3a78Ed91C0" CIPHERNODE_REGISTRY_ADDRESS="0x610178dA211FEF7D417bC0e6FeD39F05609AD788" -E3_PROGRAM_ADDRESS="0xc3e53F4d16Ae77Db1c982e75a937B9f60FE63690" # CRISPProgram Contract Address +E3_PROGRAM_ADDRESS="0xc5a5C42992dECbae36851359345FE25997F5C42d" # CRISPProgram Contract Address FEE_TOKEN_ADDRESS="0x9fE46736679d2D9a65F0992F2272dE9f3c7fa6e0" # E3 Config diff --git a/examples/CRISP/server/src/server/indexer.rs b/examples/CRISP/server/src/server/indexer.rs index 1a30097aab..89fad88d31 100644 --- a/examples/CRISP/server/src/server/indexer.rs +++ b/examples/CRISP/server/src/server/indexer.rs @@ -134,7 +134,7 @@ pub async fn register_e3_requested( info!("[e3_id={}] Merkle root: {}", e3_id, merkle_root); - // TODO: Publish merkle root on-chain (inputValidator contract). + // TODO: Publish merkle root on-chain (Program contract). Ok(()) } diff --git a/packages/enclave-contracts/artifacts/contracts/interfaces/IEnclave.sol/IEnclave.json b/packages/enclave-contracts/artifacts/contracts/interfaces/IEnclave.sol/IEnclave.json index 356cd34911..b6491bcf45 100644 --- a/packages/enclave-contracts/artifacts/contracts/interfaces/IEnclave.sol/IEnclave.json +++ b/packages/enclave-contracts/artifacts/contracts/interfaces/IEnclave.sol/IEnclave.json @@ -173,11 +173,6 @@ "name": "customParams", "type": "bytes" }, - { - "internalType": "contract IInputValidator", - "name": "inputValidator", - "type": "address" - }, { "internalType": "contract IDecryptionVerifier", "name": "decryptionVerifier", @@ -503,11 +498,6 @@ "name": "customParams", "type": "bytes" }, - { - "internalType": "contract IInputValidator", - "name": "inputValidator", - "type": "address" - }, { "internalType": "contract IDecryptionVerifier", "name": "decryptionVerifier", @@ -817,11 +807,6 @@ "name": "customParams", "type": "bytes" }, - { - "internalType": "contract IInputValidator", - "name": "inputValidator", - "type": "address" - }, { "internalType": "contract IDecryptionVerifier", "name": "decryptionVerifier", @@ -977,5 +962,5 @@ "deployedLinkReferences": {}, "immutableReferences": {}, "inputSourceName": "project/contracts/interfaces/IEnclave.sol", - "buildInfoId": "solc-0_8_28-47e0db0804e3f0de0bf2198d3ad75eb1054de690" + "buildInfoId": "solc-0_8_28-e5cbacc29cffac21a8890a9017b7aa0e2311220f" } \ No newline at end of file diff --git a/packages/enclave-contracts/contracts/Enclave.sol b/packages/enclave-contracts/contracts/Enclave.sol index c10f194f51..d69ed0c614 100644 --- a/packages/enclave-contracts/contracts/Enclave.sol +++ b/packages/enclave-contracts/contracts/Enclave.sol @@ -6,7 +6,6 @@ pragma solidity >=0.8.27; import { IEnclave, E3, IE3Program } from "./interfaces/IEnclave.sol"; -import { IInputValidator } from "./interfaces/IInputValidator.sol"; import { ICiphernodeRegistry } from "./interfaces/ICiphernodeRegistry.sol"; import { IBondingRegistry } from "./interfaces/IBondingRegistry.sol"; import { IDecryptionVerifier } from "./interfaces/IDecryptionVerifier.sol"; @@ -140,10 +139,6 @@ contract Enclave is IEnclave, OwnableUpgradeable { /// @param expiration The expiration timestamp that has not yet passed. error InputDeadlineNotPassed(uint256 e3Id, uint256 expiration); - /// @notice Thrown when the input validator in the computation request is invalid. - /// @param inputValidator The address of the invalid input validator. - error InvalidComputationRequest(IInputValidator inputValidator); - /// @notice Thrown when attempting to set an invalid ciphernode registry address. /// @param ciphernodeRegistry The invalid ciphernode registry address. error InvalidCiphernodeRegistry(ICiphernodeRegistry ciphernodeRegistry); @@ -277,15 +272,12 @@ contract Enclave is IEnclave, OwnableUpgradeable { e3.ciphertextOutput = hex""; e3.plaintextOutput = hex""; - ( - bytes32 encryptionSchemeId, - IInputValidator inputValidator - ) = requestParams.e3Program.validate( - e3Id, - seed, - requestParams.e3ProgramParams, - requestParams.computeProviderParams - ); + bytes32 encryptionSchemeId = requestParams.e3Program.validate( + e3Id, + seed, + requestParams.e3ProgramParams, + requestParams.computeProviderParams + ); IDecryptionVerifier decryptionVerifier = decryptionVerifiers[ encryptionSchemeId ]; @@ -295,13 +287,8 @@ contract Enclave is IEnclave, OwnableUpgradeable { IDecryptionVerifier(address(0)), InvalidEncryptionScheme(encryptionSchemeId) ); - require( - address(inputValidator) != address(0), - InvalidComputationRequest(inputValidator) - ); e3.encryptionSchemeId = encryptionSchemeId; - e3.inputValidator = inputValidator; e3.decryptionVerifier = decryptionVerifier; e3s[e3Id] = e3; @@ -365,7 +352,7 @@ contract Enclave is IEnclave, OwnableUpgradeable { uint256 inputIndex = inputCounts[e3Id]; inputCounts[e3Id] = inputIndex + 1; - bytes memory input = e3.inputValidator.validate(msg.sender, data); + bytes memory input = e3.e3Program.validateInput(msg.sender, data); uint256 inputHash = PoseidonT3.hash( [uint256(keccak256(input)), inputIndex] diff --git a/packages/enclave-contracts/contracts/interfaces/IE3.sol b/packages/enclave-contracts/contracts/interfaces/IE3.sol index dc36d39c05..e18023d8df 100644 --- a/packages/enclave-contracts/contracts/interfaces/IE3.sol +++ b/packages/enclave-contracts/contracts/interfaces/IE3.sol @@ -5,7 +5,6 @@ // or FITNESS FOR A PARTICULAR PURPOSE. pragma solidity >=0.8.27; -import { IInputValidator } from "./IInputValidator.sol"; import { IE3Program } from "./IE3Program.sol"; import { IDecryptionVerifier } from "./IDecryptionVerifier.sol"; @@ -24,7 +23,6 @@ import { IDecryptionVerifier } from "./IDecryptionVerifier.sol"; * @param e3Program Address of the E3 Program contract that validates and verifies the computation * @param e3ProgramParams ABI encoded computation parameters specific to the E3 program * @param customParams Arbitrary ABI-encoded application-defined parameters. - * @param inputValidator Address of the input validator contract for input verification * @param decryptionVerifier Address of the output verifier contract for decryption verification * @param committeePublicKey The public key of the selected committee for this computation * @param ciphertextOutput Hash of the encrypted output data produced by the computation @@ -41,7 +39,6 @@ struct E3 { IE3Program e3Program; bytes e3ProgramParams; bytes customParams; - IInputValidator inputValidator; IDecryptionVerifier decryptionVerifier; bytes32 committeePublicKey; bytes32 ciphertextOutput; diff --git a/packages/enclave-contracts/contracts/interfaces/IE3Program.sol b/packages/enclave-contracts/contracts/interfaces/IE3Program.sol index 0dd1f642c1..9bfd17396a 100644 --- a/packages/enclave-contracts/contracts/interfaces/IE3Program.sol +++ b/packages/enclave-contracts/contracts/interfaces/IE3Program.sol @@ -5,8 +5,6 @@ // or FITNESS FOR A PARTICULAR PURPOSE. pragma solidity >=0.8.27; -import { IInputValidator } from "./IInputValidator.sol"; - /** * @title IE3Program * @notice Interface for E3 program validation and verification @@ -20,15 +18,12 @@ interface IE3Program { /// @param e3ProgramParams ABI encoded E3 program parameters /// @param computeProviderParams ABI encoded compute provider parameters /// @return encryptionSchemeId ID of the encryption scheme to be used for the computation - /// @return inputValidator The input validator to be used for the computation function validate( uint256 e3Id, uint256 seed, bytes calldata e3ProgramParams, bytes calldata computeProviderParams - ) - external - returns (bytes32 encryptionSchemeId, IInputValidator inputValidator); + ) external returns (bytes32 encryptionSchemeId); /// @notice Verify the ciphertext output of an E3 computation /// @dev This function is called by the Enclave contract when ciphertext output is published @@ -41,4 +36,14 @@ interface IE3Program { bytes32 ciphertextOutputHash, bytes memory proof ) external returns (bool success); + + /// @notice Validate and process input data for a computation + /// @dev This function is called by the Enclave contract when input is published + /// @param sender The account that is submitting the input + /// @param data The input data to be validated + /// @return input The decoded, policy-approved application payload + function validateInput( + address sender, + bytes memory data + ) external returns (bytes memory input); } diff --git a/packages/enclave-contracts/contracts/interfaces/IInputValidator.sol b/packages/enclave-contracts/contracts/interfaces/IInputValidator.sol deleted file mode 100644 index 2c87a2ba05..0000000000 --- a/packages/enclave-contracts/contracts/interfaces/IInputValidator.sol +++ /dev/null @@ -1,23 +0,0 @@ -// SPDX-License-Identifier: LGPL-3.0-only -// -// This file is provided WITHOUT ANY WARRANTY; -// without even the implied warranty of MERCHANTABILITY -// or FITNESS FOR A PARTICULAR PURPOSE. -pragma solidity >=0.8.27; - -/** - * @title IInputValidator - * @notice Interface for validating computation inputs - * @dev Input validators enforce access control and validation rules for E3 computation inputs - */ -interface IInputValidator { - /// @notice Validate and process input data for a computation - /// @dev This function is called by the Enclave contract when input is published - /// @param sender The account that is submitting the input - /// @param data The input data to be validated - /// @return input The decoded, policy-approved application payload - function validate( - address sender, - bytes memory data - ) external returns (bytes memory input); -} diff --git a/packages/enclave-contracts/contracts/lib/ExitQueueLib.sol b/packages/enclave-contracts/contracts/lib/ExitQueueLib.sol index 12d250dcc1..05579c6f8b 100644 --- a/packages/enclave-contracts/contracts/lib/ExitQueueLib.sol +++ b/packages/enclave-contracts/contracts/lib/ExitQueueLib.sol @@ -143,8 +143,9 @@ library ExitQueueLib { ExitTranche storage lastTranche = operatorQueue[len - 1]; if (lastTranche.unlockTimestamp == unlockTimestamp) { if (ticketAmount != 0) lastTranche.ticketAmount += ticketAmount; - if (licenseAmount != 0) + if (licenseAmount != 0) { lastTranche.licenseAmount += licenseAmount; + } merged = true; } } @@ -375,15 +376,19 @@ library ExitQueueLib { PendingAmounts storage pending = state.pendingTotals[operator]; if (isIncrease) { - if (ticketAmountDelta != 0) + if (ticketAmountDelta != 0) { pending.ticketAmount += ticketAmountDelta; - if (licenseAmountDelta != 0) + } + if (licenseAmountDelta != 0) { pending.licenseAmount += licenseAmountDelta; + } } else { - if (ticketAmountDelta != 0) + if (ticketAmountDelta != 0) { pending.ticketAmount -= ticketAmountDelta; - if (licenseAmountDelta != 0) + } + if (licenseAmountDelta != 0) { pending.licenseAmount -= licenseAmountDelta; + } } } diff --git a/packages/enclave-contracts/contracts/registry/BondingRegistry.sol b/packages/enclave-contracts/contracts/registry/BondingRegistry.sol index c931ea7c32..f0633c064b 100644 --- a/packages/enclave-contracts/contracts/registry/BondingRegistry.sol +++ b/packages/enclave-contracts/contracts/registry/BondingRegistry.sol @@ -128,8 +128,9 @@ contract BondingRegistry is IBondingRegistry, OwnableUpgradeable { /// @param operator Address of the operator to check modifier noExitInProgress(address operator) { Operator memory op = operators[operator]; - if (op.exitRequested && block.timestamp < op.exitUnlocksAt) + if (op.exitRequested && block.timestamp < op.exitUnlocksAt) { revert ExitInProgress(); + } _; } @@ -439,8 +440,9 @@ contract BondingRegistry is IBondingRegistry, OwnableUpgradeable { require(ticketClaim > 0 || licenseClaim > 0, ExitNotReady()); if (ticketClaim > 0) ticketToken.payout(msg.sender, ticketClaim); - if (licenseClaim > 0) + if (licenseClaim > 0) { licenseToken.safeTransfer(msg.sender, licenseClaim); + } } // ====================== diff --git a/packages/enclave-contracts/contracts/test/MockComputeProvider.sol b/packages/enclave-contracts/contracts/test/MockComputeProvider.sol index 64c134382c..9a759b97e6 100644 --- a/packages/enclave-contracts/contracts/test/MockComputeProvider.sol +++ b/packages/enclave-contracts/contracts/test/MockComputeProvider.sol @@ -11,14 +11,14 @@ import { } from "../interfaces/IComputeProvider.sol"; contract MockComputeProvider is IComputeProvider { - error invalidParams(); + error InvalidParams(); function validate( uint256, uint256, bytes memory params ) external pure returns (IDecryptionVerifier decryptionVerifier) { - require(params.length == 32, invalidParams()); + require(params.length == 32, InvalidParams()); // solhint-disable no-inline-assembly assembly { decryptionVerifier := mload(add(params, 32)) diff --git a/packages/enclave-contracts/contracts/test/MockE3Program.sol b/packages/enclave-contracts/contracts/test/MockE3Program.sol index b7cb563188..533e7a4ae2 100644 --- a/packages/enclave-contracts/contracts/test/MockE3Program.sol +++ b/packages/enclave-contracts/contracts/test/MockE3Program.sol @@ -5,39 +5,43 @@ // or FITNESS FOR A PARTICULAR PURPOSE. pragma solidity >=0.8.27; -import { IE3Program, IInputValidator } from "../interfaces/IE3Program.sol"; +import { IE3Program } from "../interfaces/IE3Program.sol"; contract MockE3Program is IE3Program { - error invalidParams(bytes e3ProgramParams, bytes computeProviderParams); - error InvalidInputValidator(); + error InvalidParams(bytes e3ProgramParams, bytes computeProviderParams); error E3AlreadyInitialized(); + bytes32 public constant ENCRYPTION_SCHEME_ID = keccak256("fhe.rs:BFV"); - IInputValidator public inputValidator; mapping(uint256 e3Id => bytes32 paramsHash) public paramsHashes; - constructor(IInputValidator _inputValidator) { - if (address(_inputValidator) == address(0)) { - revert InvalidInputValidator(); - } - - inputValidator = _inputValidator; - } + error InvalidInput(); function validate( uint256 e3Id, uint256, bytes calldata e3ProgramParams, bytes calldata computeProviderParams - ) external returns (bytes32, IInputValidator) { + ) external returns (bytes32) { require( computeProviderParams.length == 32, - invalidParams(e3ProgramParams, computeProviderParams) + InvalidParams(e3ProgramParams, computeProviderParams) ); require(paramsHashes[e3Id] == bytes32(0), E3AlreadyInitialized()); paramsHashes[e3Id] = keccak256(e3ProgramParams); - return (ENCRYPTION_SCHEME_ID, inputValidator); + return ENCRYPTION_SCHEME_ID; + } + + function validateInput( + address sender, + bytes memory data + ) external pure returns (bytes memory input) { + if (data.length == 3 || sender == address(0)) { + revert InvalidInput(); + } + + input = data; } function verify( diff --git a/packages/enclave-contracts/contracts/test/MockInputValidator.sol b/packages/enclave-contracts/contracts/test/MockInputValidator.sol deleted file mode 100644 index d9dfc2341a..0000000000 --- a/packages/enclave-contracts/contracts/test/MockInputValidator.sol +++ /dev/null @@ -1,29 +0,0 @@ -// SPDX-License-Identifier: LGPL-3.0-only -// -// This file is provided WITHOUT ANY WARRANTY; -// without even the implied warranty of MERCHANTABILITY -// or FITNESS FOR A PARTICULAR PURPOSE. -pragma solidity >=0.8.27; - -import { IInputValidator } from "../interfaces/IInputValidator.sol"; - -/// @title MockInputValidator. -/// @notice Enclave Input Validator -contract MockInputValidator is IInputValidator { - error InvalidInput(); - - /// @notice Validates input - /// @param sender The account that is submitting the input. - /// @param data The input to be verified. - /// @return input The decoded, policy-approved application payload. - function validate( - address sender, - bytes memory data - ) external pure returns (bytes memory input) { - if (data.length == 3 || sender == address(0)) { - revert InvalidInput(); - } - - input = data; - } -} diff --git a/packages/enclave-contracts/contracts/token/EnclaveToken.sol b/packages/enclave-contracts/contracts/token/EnclaveToken.sol index 70699d23ac..f1e5534008 100644 --- a/packages/enclave-contracts/contracts/token/EnclaveToken.sol +++ b/packages/enclave-contracts/contracts/token/EnclaveToken.sol @@ -149,8 +149,9 @@ contract EnclaveToken is string[] calldata allocations ) external onlyRole(MINTER_ROLE) { uint256 len = recipients.length; - if (amounts.length != len || allocations.length != len) + if (amounts.length != len || allocations.length != len) { revert ArrayLengthMismatch(); + } uint256 minted = totalMinted; @@ -232,8 +233,9 @@ contract EnclaveToken is ) internal override(ERC20, ERC20Votes) { // When transfers are restricted, only whitelisted addresses can send or receive. if (from != address(0) && to != address(0) && transfersRestricted) { - if (!transferWhitelisted[from] && !transferWhitelisted[to]) + if (!transferWhitelisted[from] && !transferWhitelisted[to]) { revert TransferNotAllowed(); + } } super._update(from, to, value); } diff --git a/packages/enclave-contracts/deployed_contracts.json b/packages/enclave-contracts/deployed_contracts.json index 078e235afb..07db290da2 100644 --- a/packages/enclave-contracts/deployed_contracts.json +++ b/packages/enclave-contracts/deployed_contracts.json @@ -52,16 +52,9 @@ "blockNumber": 9615410, "address": "0x37007c28bCc6522Baf079B2D97F9f22ffe4b13b7" }, - "MockInputValidator": { - "blockNumber": 9615411, - "address": "0x3d7C302270a85F6e8798b607275B1fF265514b38" - }, "MockE3Program": { - "constructorArgs": { - "mockInputValidator": "0x3d7C302270a85F6e8798b607275B1fF265514b38" - }, - "blockNumber": 9615412, - "address": "0xeb3B7C06e7D327f377901356860D88AA50822a6b" + "blockNumber": 9479405, + "address": "0x5a196784e60A6A18b86Af7a9e564A969F6d2bC76" }, "MockUSDC": { "constructorArgs": { diff --git a/packages/enclave-contracts/ignition/modules/mockE3Program.ts b/packages/enclave-contracts/ignition/modules/mockE3Program.ts index c0734e6c5a..c3274db74e 100644 --- a/packages/enclave-contracts/ignition/modules/mockE3Program.ts +++ b/packages/enclave-contracts/ignition/modules/mockE3Program.ts @@ -8,9 +8,7 @@ import { buildModule } from "@nomicfoundation/hardhat-ignition/modules"; export default buildModule("MockE3Program", (m) => { - const mockInputValidator = m.getParameter("mockInputValidator"); - - const mockE3Program = m.contract("MockE3Program", [mockInputValidator]); + const mockE3Program = m.contract("MockE3Program", []); return { mockE3Program }; }) as any; diff --git a/packages/enclave-contracts/ignition/modules/mockInputValidator.ts b/packages/enclave-contracts/ignition/modules/mockInputValidator.ts deleted file mode 100644 index 21f33ffd8c..0000000000 --- a/packages/enclave-contracts/ignition/modules/mockInputValidator.ts +++ /dev/null @@ -1,14 +0,0 @@ -// SPDX-License-Identifier: LGPL-3.0-only -// -// This file is provided WITHOUT ANY WARRANTY; -// without even the implied warranty of MERCHANTABILITY -// or FITNESS FOR A PARTICULAR PURPOSE. - -/* eslint-disable @typescript-eslint/no-explicit-any */ -import { buildModule } from "@nomicfoundation/hardhat-ignition/modules"; - -export default buildModule("MockInputValidator", (m) => { - const mockInputValidator = m.contract("MockInputValidator"); - - return { mockInputValidator }; -}) as any; diff --git a/packages/enclave-contracts/scripts/deployAndSave/mockInputValidator.ts b/packages/enclave-contracts/scripts/deployAndSave/mockInputValidator.ts deleted file mode 100644 index 0c944b7364..0000000000 --- a/packages/enclave-contracts/scripts/deployAndSave/mockInputValidator.ts +++ /dev/null @@ -1,46 +0,0 @@ -// SPDX-License-Identifier: LGPL-3.0-only -// -// This file is provided WITHOUT ANY WARRANTY; -// without even the implied warranty of MERCHANTABILITY -// or FITNESS FOR A PARTICULAR PURPOSE. -import type { HardhatRuntimeEnvironment } from "hardhat/types/hre"; - -import { - MockInputValidator, - MockInputValidator__factory as MockInputValidatorFactory, -} from "../../types"; -import { storeDeploymentArgs } from "../utils"; - -export const deployAndSaveMockInputValidator = async ( - hre: HardhatRuntimeEnvironment, -): Promise<{ - inputValidator: MockInputValidator; -}> => { - const { ethers } = await hre.network.connect(); - const [signer] = await ethers.getSigners(); - - const mockInputValidatorFactory = - await ethers.getContractFactory("MockInputValidator"); - const inputValidator = await mockInputValidatorFactory.deploy(); - await inputValidator.waitForDeployment(); - const inputValidatorAddress = await inputValidator.getAddress(); - - const chain = hre.globalOptions.network; - const blockNumber = await ethers.provider.getBlockNumber(); - - storeDeploymentArgs( - { - blockNumber, - address: inputValidatorAddress, - }, - "MockInputValidator", - chain, - ); - - const inputValidatorContract = MockInputValidatorFactory.connect( - inputValidatorAddress, - signer, - ); - - return { inputValidator: inputValidatorContract }; -}; diff --git a/packages/enclave-contracts/scripts/deployAndSave/mockProgram.ts b/packages/enclave-contracts/scripts/deployAndSave/mockProgram.ts index 23a623b89a..c6a78ee004 100644 --- a/packages/enclave-contracts/scripts/deployAndSave/mockProgram.ts +++ b/packages/enclave-contracts/scripts/deployAndSave/mockProgram.ts @@ -9,15 +9,13 @@ import { MockE3Program, MockE3Program__factory as MockE3ProgramFactory, } from "../../types"; -import { readDeploymentArgs, storeDeploymentArgs } from "../utils"; +import { storeDeploymentArgs } from "../utils"; interface MockProgramArgs { - mockInputValidator: string; hre: HardhatRuntimeEnvironment; } export const deployAndSaveMockProgram = async ({ - mockInputValidator, hre, }: MockProgramArgs): Promise<{ e3Program: MockE3Program; @@ -26,20 +24,8 @@ export const deployAndSaveMockProgram = async ({ const [signer] = await ethers.getSigners(); const chain = (await signer.provider?.getNetwork())?.name ?? "localhost"; - const preDeployedArgs = readDeploymentArgs("MockE3Program", chain); - - if ( - preDeployedArgs?.constructorArgs?.mockInputValidator === mockInputValidator - ) { - const e3ProgramContract = MockE3ProgramFactory.connect( - preDeployedArgs.address, - signer, - ); - return { e3Program: e3ProgramContract }; - } - const e3ProgramFactory = await ethers.getContractFactory("MockE3Program"); - const e3Program = await e3ProgramFactory.deploy(mockInputValidator); + const e3Program = await e3ProgramFactory.deploy(); await e3Program.waitForDeployment(); @@ -48,7 +34,6 @@ export const deployAndSaveMockProgram = async ({ storeDeploymentArgs( { - constructorArgs: { mockInputValidator }, blockNumber, address: e3ProgramAddress, }, diff --git a/packages/enclave-contracts/scripts/deployMocks.ts b/packages/enclave-contracts/scripts/deployMocks.ts index f9155fbcb3..c7d6d6aae2 100644 --- a/packages/enclave-contracts/scripts/deployMocks.ts +++ b/packages/enclave-contracts/scripts/deployMocks.ts @@ -7,13 +7,11 @@ import hre from "hardhat"; import { deployAndSaveMockComputeProvider } from "./deployAndSave/mockComputeProvider"; import { deployAndSaveMockDecryptionVerifier } from "./deployAndSave/mockDecryptionVerifier"; -import { deployAndSaveMockInputValidator } from "./deployAndSave/mockInputValidator"; import { deployAndSaveMockProgram } from "./deployAndSave/mockProgram"; export interface MockDeployments { computeProviderAddress: string; decryptionVerifierAddress: string; - inputValidatorAddress: string; e3ProgramAddress: string; } @@ -33,14 +31,8 @@ export const deployMocks = async (): Promise => { const decryptionVerifierAddress = await decryptionVerifier.getAddress(); - console.log("Deploying Input Validator"); - const { inputValidator } = await deployAndSaveMockInputValidator(hre); - - const inputValidatorAddress = await inputValidator.getAddress(); - console.log("Deploying E3 Program"); const { e3Program } = await deployAndSaveMockProgram({ - mockInputValidator: inputValidatorAddress, hre, }); @@ -51,14 +43,12 @@ export const deployMocks = async (): Promise => { ---------------------------------------------------------------------- MockComputeProvider:${computeProviderAddress} MockDecryptionVerifier:${decryptionVerifierAddress} - MockInputValidator:${inputValidatorAddress} MockE3Program:${e3ProgramAddress} `); return { computeProviderAddress, decryptionVerifierAddress, - inputValidatorAddress, e3ProgramAddress, }; }; diff --git a/packages/enclave-contracts/scripts/index.ts b/packages/enclave-contracts/scripts/index.ts index c74699be1d..6ac68aed5d 100644 --- a/packages/enclave-contracts/scripts/index.ts +++ b/packages/enclave-contracts/scripts/index.ts @@ -17,6 +17,5 @@ export * from "./deployAndSave/mockStableToken"; export * from "./deployAndSave/slashingManager"; export * from "./deployAndSave/mockComputeProvider"; export * from "./deployAndSave/mockDecryptionVerifier"; -export * from "./deployAndSave/mockInputValidator"; export * from "./deployAndSave/mockProgram"; export * from "./verify"; diff --git a/packages/enclave-contracts/tasks/enclave.ts b/packages/enclave-contracts/tasks/enclave.ts index 6bb3d8ae78..cf37cc2e9a 100644 --- a/packages/enclave-contracts/tasks/enclave.ts +++ b/packages/enclave-contracts/tasks/enclave.ts @@ -141,16 +141,8 @@ export const requestCommittee = task( ); let e3ProgramParams = e3Params; - - const mockInputValidatorArgs = readDeploymentArgs( - "MockInputValidator", - hre.globalOptions.network, - ); if (e3ProgramParams === ZeroAddress) { - if (!mockInputValidatorArgs) { - throw new Error("MockInputValidator deployment arguments not found"); - } - e3ProgramParams = zeroPadValue(mockInputValidatorArgs.address, 32); + e3ProgramParams = zeroPadValue(e3ProgramParams, 32); } let computeProviderParams = computeParams; @@ -170,6 +162,11 @@ export const requestCommittee = task( ); } + console.log("Preparing request with the following parameters:", { + computeParams, + computeProviderParams, + }); + const requestParams = { threshold: [thresholdQuorum, thresholdTotal] as [number, number], startWindow: [windowStart, windowEnd] as [number, number], diff --git a/packages/enclave-contracts/test/Enclave.spec.ts b/packages/enclave-contracts/test/Enclave.spec.ts index 83efd94102..270d870b23 100644 --- a/packages/enclave-contracts/test/Enclave.spec.ts +++ b/packages/enclave-contracts/test/Enclave.spec.ts @@ -18,7 +18,6 @@ import MockCiphernodeRegistryEmptyKeyModule from "../ignition/modules/mockCipher import mockComputeProviderModule from "../ignition/modules/mockComputeProvider"; import MockDecryptionVerifierModule from "../ignition/modules/mockDecryptionVerifier"; import MockE3ProgramModule from "../ignition/modules/mockE3Program"; -import MockInputValidatorModule from "../ignition/modules/mockInputValidator"; import MockStableTokenModule from "../ignition/modules/mockStableToken"; import SlashingManagerModule from "../ignition/modules/slashingManager"; import { @@ -304,16 +303,7 @@ describe("Enclave", function () { MockDecryptionVerifierModule, ); - const inputValidator = await ignition.deploy(MockInputValidatorModule); - - const e3Program = await ignition.deploy(MockE3ProgramModule, { - parameters: { - MockE3Program: { - mockInputValidator: - await inputValidator.mockInputValidator.getAddress(), - }, - }, - }); + const e3Program = await ignition.deploy(MockE3ProgramModule); await enclave.enableE3Program(await e3Program.mockE3Program.getAddress()); await enclave.setE3ProgramsParams([encodedE3ProgramParams]); @@ -358,7 +348,6 @@ describe("Enclave", function () { tree, mocks: { decryptionVerifier: decryptionVerifier.mockDecryptionVerifier, - inputValidator: inputValidator.mockInputValidator, e3Program: e3Program.mockE3Program, mockComputeProvider: mockComputeProvider.mockComputeProvider, }, @@ -536,7 +525,7 @@ describe("Enclave", function () { }); it("returns correct E3 details", async function () { - const { enclave, request, mocks, usdcToken } = await loadFixture(setup); + const { enclave, request, usdcToken } = await loadFixture(setup); await makeRequest(enclave, usdcToken, { threshold: request.threshold, @@ -554,9 +543,6 @@ describe("Enclave", function () { expect(e3.expiration).to.equal(0n); expect(e3.e3Program).to.equal(request.e3Program); expect(e3.e3ProgramParams).to.equal(request.e3ProgramParams); - expect(e3.inputValidator).to.equal( - await mocks.inputValidator.getAddress(), - ); expect(e3.decryptionVerifier).to.equal( abiCoder.decode(["address"], request.computeProviderParams)[0], ); @@ -909,7 +895,7 @@ describe("Enclave", function () { .withArgs(encryptionSchemeId); }); it("instantiates a new E3", async function () { - const { enclave, request, mocks, usdcToken } = await loadFixture(setup); + const { enclave, request, usdcToken } = await loadFixture(setup); await makeRequest(enclave, usdcToken, { threshold: request.threshold, @@ -928,9 +914,6 @@ describe("Enclave", function () { expect(e3.expiration).to.equal(0n); expect(e3.e3Program).to.equal(request.e3Program); expect(e3.requestBlock).to.equal(block.number); - expect(e3.inputValidator).to.equal( - await mocks.inputValidator.getAddress(), - ); expect(e3.decryptionVerifier).to.equal( abiCoder.decode(["address"], request.computeProviderParams)[0], ); diff --git a/packages/enclave-sdk/src/types.ts b/packages/enclave-sdk/src/types.ts index e3d1195a3d..eb0f38cc8d 100644 --- a/packages/enclave-sdk/src/types.ts +++ b/packages/enclave-sdk/src/types.ts @@ -134,7 +134,6 @@ export interface E3 { encryptionSchemeId: string; e3Program: string; e3ProgramParams: string; - inputValidator: string; decryptionVerifier: string; committeePublicKey: string; ciphertextOutput: string; diff --git a/templates/default/contracts/InputValidator.sol b/templates/default/contracts/InputValidator.sol deleted file mode 100644 index 157ea2e386..0000000000 --- a/templates/default/contracts/InputValidator.sol +++ /dev/null @@ -1,28 +0,0 @@ -// SPDX-License-Identifier: LGPL-3.0-only -// -// This file is provided WITHOUT ANY WARRANTY; -// without even the implied warranty of MERCHANTABILITY -// or FITNESS FOR A PARTICULAR PURPOSE. -pragma solidity >=0.8.27; - -import {IInputValidator} from "@enclave-e3/contracts/contracts/interfaces/IInputValidator.sol"; - -contract InputValidator is IInputValidator { - error EmptyInputData(); - - /// @notice Validates input - /// @param sender The account that is submitting the input. - /// @param data The input to be verified. - /// @return input The input data. - function validate( - address sender, - bytes memory data - ) external returns (bytes memory input) { - if (data.length == 0) revert EmptyInputData(); - - // You can add your own validation logic here. - // EXAMPLE: https://github.com/gnosisguild/enclave/blob/main/examples/CRISP/contracts/CRISPInputValidator.sol - - input = data; - } -} diff --git a/templates/default/contracts/MyProgram.sol b/templates/default/contracts/MyProgram.sol index 14f461a926..9a80591156 100755 --- a/templates/default/contracts/MyProgram.sol +++ b/templates/default/contracts/MyProgram.sol @@ -7,7 +7,6 @@ pragma solidity >=0.8.27; import {IRiscZeroVerifier} from "@risc0/ethereum/contracts/IRiscZeroVerifier.sol"; import {IE3Program} from "@enclave-e3/contracts/contracts/interfaces/IE3Program.sol"; -import {IInputValidator} from "@enclave-e3/contracts/contracts/interfaces/IInputValidator.sol"; import {IEnclave} from "@enclave-e3/contracts/contracts/interfaces/IEnclave.sol"; import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol"; @@ -18,7 +17,6 @@ contract MyProgram is IE3Program, Ownable { // State variables IEnclave public enclave; IRiscZeroVerifier public verifier; - IInputValidator public inputValidator; bytes32 public imageId; // Mappings @@ -31,23 +29,21 @@ contract MyProgram is IE3Program, Ownable { error E3DoesNotExist(); error VerifierAddressZero(); error AlreadyRegistered(); + error EmptyInputData(); /// @notice Initialize the contract, binding it to a specified RISC Zero verifier. /// @param _enclave The Enclave contract address /// @param _verifier The RISC Zero verifier address /// @param _imageId The image ID for the guest program - /// @param _inputValidator The input validator address constructor( IEnclave _enclave, IRiscZeroVerifier _verifier, - bytes32 _imageId, - IInputValidator _inputValidator + bytes32 _imageId ) Ownable(msg.sender) { require(address(_verifier) != address(0), VerifierAddressZero()); enclave = _enclave; verifier = _verifier; - inputValidator = _inputValidator; imageId = _imageId; authorizedContracts[address(_enclave)] = true; } @@ -60,7 +56,7 @@ contract MyProgram is IE3Program, Ownable { uint256, bytes calldata e3ProgramParams, bytes calldata - ) external returns (bytes32, IInputValidator) { + ) external returns (bytes32) { require( authorizedContracts[msg.sender] || msg.sender == owner(), CallerNotAuthorized() @@ -68,7 +64,23 @@ contract MyProgram is IE3Program, Ownable { require(paramsHashes[e3Id] == bytes32(0), E3AlreadyInitialized()); paramsHashes[e3Id] = keccak256(e3ProgramParams); - return (ENCRYPTION_SCHEME_ID, IInputValidator(address(inputValidator))); + return ENCRYPTION_SCHEME_ID; + } + + /// @notice Validates input + /// @param sender The account that is submitting the input. + /// @param data The input to be verified. + /// @return input The input data. + function validateInput( + address sender, + bytes memory data + ) external returns (bytes memory input) { + if (data.length == 0) revert EmptyInputData(); + + // You can add your own validation logic here. + // EXAMPLE: https://github.com/gnosisguild/enclave/blob/main/examples/CRISP/packages/crisp-contracts/contracts/CRISPProgram.sol + + input = data; } /// @notice Verify the proof diff --git a/templates/default/deploy/default.ts b/templates/default/deploy/default.ts index 7e2eddc3a9..61deceb21d 100644 --- a/templates/default/deploy/default.ts +++ b/templates/default/deploy/default.ts @@ -36,14 +36,7 @@ export const deployTemplate = async () => { const programId = await imageId.PROGRAM_ID(); - const inputValidator = await ethers.deployContract("InputValidator"); - await inputValidator.waitForDeployment(); - - storeDeploymentArgs({ - address: await inputValidator.getAddress(), - }, "InputValidator", chain); - - const e3Program = await ethers.deployContract("MyProgram", [await enclave.getAddress(), await verifier.getAddress(), programId, await inputValidator.getAddress()]); + const e3Program = await ethers.deployContract("MyProgram", [await enclave.getAddress(), await verifier.getAddress(), programId]); await e3Program.waitForDeployment(); storeDeploymentArgs({ @@ -52,7 +45,6 @@ export const deployTemplate = async () => { enclave: await enclave.getAddress(), verifier: await verifier.getAddress(), programId, - inputValidator: await inputValidator.getAddress(), }, }, "MyProgram", chain); diff --git a/templates/default/deployed_contracts.json b/templates/default/deployed_contracts.json index 81a3fe1c00..385beea440 100644 --- a/templates/default/deployed_contracts.json +++ b/templates/default/deployed_contracts.json @@ -104,16 +104,15 @@ "blockNumber": 24, "address": "0x4ed7c70F96B99c776995fB64377f0d4aB3B0e1C1" }, - "MockInputValidator": { + "MockE3Program": { "blockNumber": 25, "address": "0x322813Fd9A801c5507c9de605d63CEA4f2CE6c44" }, - "MockE3Program": { - "constructorArgs": { - "mockInputValidator": "0x322813Fd9A801c5507c9de605d63CEA4f2CE6c44" - }, - "blockNumber": 26, - "address": "0xa85233C63b9Ee964Add6F2cffe00Fd84eb32338f" + "MockRISC0Verifier": { + "address": "0x7a2088a1bFc9d81c55368AE168C2C02570cB814F" + }, + "ImageID": { + "address": "0x09635F643e140090A9A8Dcd712eD6285858ceBef" }, "MockRISC0Verifier": { "address": "0x09635F643e140090A9A8Dcd712eD6285858ceBef" @@ -125,12 +124,11 @@ "address": "0x67d269191c92Caf3cD7723F116c85e6E9bf55933" }, "MyProgram": { - "address": "0xE6E340D132b5f46d1e472DebcD681B2aBc16e57E", + "address": "0xc5a5C42992dECbae36851359345FE25997F5C42d", "constructorArgs": { "enclave": "0xA51c1fc2f0D1a1b8494Ed1FE312d7C3a78Ed91C0", - "verifier": "0x09635F643e140090A9A8Dcd712eD6285858ceBef", - "programId": "0xaf928ebf39fec4696c3f41f473a1a9473b67d723c6373149c6ab99ba4c1a76ef", - "inputValidator": "0x67d269191c92Caf3cD7723F116c85e6E9bf55933" + "verifier": "0x7a2088a1bFc9d81c55368AE168C2C02570cB814F", + "programId": "0xaf928ebf39fec4696c3f41f473a1a9473b67d723c6373149c6ab99ba4c1a76ef" } } } diff --git a/templates/default/enclave.config.yaml b/templates/default/enclave.config.yaml index c1d111e3c4..5036ac2770 100644 --- a/templates/default/enclave.config.yaml +++ b/templates/default/enclave.config.yaml @@ -3,7 +3,7 @@ chains: rpc_url: "ws://localhost:8545" contracts: e3_program: - address: "0xe6e340d132b5f46d1e472debcd681b2abc16e57e" + address: "0xc5a5C42992dECbae36851359345FE25997F5C42d" deploy_block: 1 # Set to actual deploy block enclave: address: "0xA51c1fc2f0D1a1b8494Ed1FE312d7C3a78Ed91C0" diff --git a/templates/default/hardhat.config.ts b/templates/default/hardhat.config.ts index 4af36e8d96..14c51551b2 100644 --- a/templates/default/hardhat.config.ts +++ b/templates/default/hardhat.config.ts @@ -130,7 +130,6 @@ const config: HardhatUserConfig = { "@enclave-e3/contracts/contracts/test/MockComputeProvider.sol", "@enclave-e3/contracts/contracts/test/MockDecryptionVerifier.sol", "@enclave-e3/contracts/contracts/test/MockE3Program.sol", - "@enclave-e3/contracts/contracts/test/MockInputValidator.sol", "@enclave-e3/contracts/contracts/test/MockSlashingVerifier.sol", "@enclave-e3/contracts/contracts/test/MockStableToken.sol", ], diff --git a/tests/integration/enclave.config.yaml b/tests/integration/enclave.config.yaml index e8641d134e..4a5481c3a1 100644 --- a/tests/integration/enclave.config.yaml +++ b/tests/integration/enclave.config.yaml @@ -3,7 +3,7 @@ chains: rpc_url: "ws://localhost:8545" contracts: e3_program: - address: "0x09635F643e140090A9A8Dcd712eD6285858ceBef" + address: "0x322813Fd9A801c5507c9de605d63CEA4f2CE6c44" deploy_block: 1 # Set to actual deploy block enclave: address: "0xA51c1fc2f0D1a1b8494Ed1FE312d7C3a78Ed91C0"