diff --git a/packages/evm/contracts/Enclave.sol b/packages/evm/contracts/Enclave.sol index 3e597e55..4d5bdebb 100644 --- a/packages/evm/contracts/Enclave.sol +++ b/packages/evm/contracts/Enclave.sol @@ -41,8 +41,8 @@ contract Enclave is IEnclave, OwnableUpgradeable { mapping(uint256 e3Id => uint256 inputCount) public inputCounts; // Mapping of enabled encryption schemes. - mapping(bytes32 encryptionSchemeId => bool enabled) - public encryptionSchemes; + mapping(bytes32 encryptionSchemeId => IDecryptionVerifier decryptionVerifier) + public decryptionVerifiers; //////////////////////////////////////////////////////////// // // @@ -62,10 +62,7 @@ contract Enclave is IEnclave, OwnableUpgradeable { error InvalidEncryptionScheme(bytes32 encryptionSchemeId); error InputDeadlinePassed(uint256 e3Id, uint256 expiration); error InputDeadlineNotPassed(uint256 e3Id, uint256 expiration); - error InvalidComputationRequest( - IInputValidator inputValidator, - IDecryptionVerifier decryptionVerifier - ); + error InvalidComputationRequest(IInputValidator inputValidator); error InvalidCiphernodeRegistry(ICiphernodeRegistry ciphernodeRegistry); error InvalidInput(); error InvalidDuration(uint256 duration); @@ -145,24 +142,19 @@ contract Enclave is IEnclave, OwnableUpgradeable { nexte3Id++; uint256 seed = uint256(keccak256(abi.encode(block.prevrandao, e3Id))); - ( - bytes32 encryptionSchemeId, - IInputValidator inputValidator, - IDecryptionVerifier decryptionVerifier - ) = e3Program.validate( - e3Id, - seed, - e3ProgramParams, - computeProviderParams - ); + (bytes32 encryptionSchemeId, IInputValidator inputValidator) = e3Program + .validate(e3Id, seed, e3ProgramParams, computeProviderParams); + IDecryptionVerifier decryptionVerifier = decryptionVerifiers[ + encryptionSchemeId + ]; require( - encryptionSchemes[encryptionSchemeId], + decryptionVerifiers[encryptionSchemeId] != + IDecryptionVerifier(address(0)), InvalidEncryptionScheme(encryptionSchemeId) ); require( - address(inputValidator) != address(0) && - address(decryptionVerifier) != address(0), - InvalidComputationRequest(inputValidator, decryptionVerifier) + address(inputValidator) != address(0), + InvalidComputationRequest(inputValidator) ); e3 = E3({ @@ -339,14 +331,16 @@ contract Enclave is IEnclave, OwnableUpgradeable { emit E3ProgramDisabled(e3Program); } - function enableEncryptionScheme( - bytes32 encryptionSchemeId + function setDecryptionVerifier( + bytes32 encryptionSchemeId, + IDecryptionVerifier decryptionVerifier ) public onlyOwner returns (bool success) { require( - !encryptionSchemes[encryptionSchemeId], + decryptionVerifier != IDecryptionVerifier(address(0)) && + decryptionVerifiers[encryptionSchemeId] != decryptionVerifier, InvalidEncryptionScheme(encryptionSchemeId) ); - encryptionSchemes[encryptionSchemeId] = true; + decryptionVerifiers[encryptionSchemeId] = decryptionVerifier; success = true; emit EncryptionSchemeEnabled(encryptionSchemeId); } @@ -355,11 +349,14 @@ contract Enclave is IEnclave, OwnableUpgradeable { bytes32 encryptionSchemeId ) public onlyOwner returns (bool success) { require( - encryptionSchemes[encryptionSchemeId], + decryptionVerifiers[encryptionSchemeId] != + IDecryptionVerifier(address(0)), InvalidEncryptionScheme(encryptionSchemeId) ); - encryptionSchemes[encryptionSchemeId] = false; - success = false; + decryptionVerifiers[encryptionSchemeId] = IDecryptionVerifier( + address(0) + ); + success = true; emit EncryptionSchemeDisabled(encryptionSchemeId); } @@ -382,9 +379,9 @@ contract Enclave is IEnclave, OwnableUpgradeable { return InternalLeanIMT._root(inputs[e3Id]); } - function isEncryptionSchemeEnabled( + function getDecryptionVerifier( bytes32 encryptionSchemeId - ) public view returns (bool) { - return encryptionSchemes[encryptionSchemeId]; + ) public view returns (IDecryptionVerifier) { + return decryptionVerifiers[encryptionSchemeId]; } } diff --git a/packages/evm/contracts/interfaces/IE3Program.sol b/packages/evm/contracts/interfaces/IE3Program.sol index 2116adc6..7e476a56 100644 --- a/packages/evm/contracts/interfaces/IE3Program.sol +++ b/packages/evm/contracts/interfaces/IE3Program.sol @@ -2,7 +2,6 @@ pragma solidity >=0.8.27; import { IInputValidator } from "./IInputValidator.sol"; -import { IDecryptionVerifier } from "./IDecryptionVerifier.sol"; interface IE3Program { /// @notice This function should be called by the Enclave contract to validate the computation parameters. @@ -12,7 +11,6 @@ interface IE3Program { /// @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. - /// @return decryptionVerifier The decryption verifier to be used for the computation. function validate( uint256 e3Id, uint256 seed, @@ -20,11 +18,7 @@ interface IE3Program { bytes calldata computeProviderParams ) external - returns ( - bytes32 encryptionSchemeId, - IInputValidator inputValidator, - IDecryptionVerifier decryptionVerifier - ); + returns (bytes32 encryptionSchemeId, IInputValidator inputValidator); /// @notice This function should be called by the Enclave contract to verify the decrypted output of an E3. /// @param e3Id ID of the E3. diff --git a/packages/evm/contracts/test/MockE3Program.sol b/packages/evm/contracts/test/MockE3Program.sol index 079ae9b0..d6531305 100644 --- a/packages/evm/contracts/test/MockE3Program.sol +++ b/packages/evm/contracts/test/MockE3Program.sol @@ -1,11 +1,7 @@ // SPDX-License-Identifier: LGPL-3.0-only pragma solidity >=0.8.27; -import { - IE3Program, - IInputValidator, - IDecryptionVerifier -} from "../interfaces/IE3Program.sol"; +import { IE3Program, IInputValidator } from "../interfaces/IE3Program.sol"; contract MockE3Program is IE3Program { error invalidParams(bytes e3ProgramParams, bytes computeProviderParams); @@ -18,11 +14,7 @@ contract MockE3Program is IE3Program { ) external pure - returns ( - bytes32 encryptionSchemeId, - IInputValidator inputValidator, - IDecryptionVerifier decryptionVerifier - ) + returns (bytes32 encryptionSchemeId, IInputValidator inputValidator) { require( e3ProgramParams.length == 32 && computeProviderParams.length == 32, @@ -31,7 +23,6 @@ contract MockE3Program is IE3Program { // solhint-disable no-inline-assembly assembly { inputValidator := mload(add(e3ProgramParams, 32)) - decryptionVerifier := mload(add(computeProviderParams, 32)) } encryptionSchemeId = 0x0000000000000000000000000000000000000000000000000000000000000001; } diff --git a/packages/evm/package.json b/packages/evm/package.json index 556f4a89..f62e920e 100644 --- a/packages/evm/package.json +++ b/packages/evm/package.json @@ -1,7 +1,7 @@ { "name": "@gnosis-guild/enclave", "description": "Enclave is an open-source protocol for Encrypted Execution Environments (E3).", - "version": "0.0.2", + "version": "0.0.3", "license": "LGPL-3.0-only", "author": { "name": "gnosisguild", diff --git a/packages/evm/test/Enclave.spec.ts b/packages/evm/test/Enclave.spec.ts index 47244ec0..9348802b 100644 --- a/packages/evm/test/Enclave.spec.ts +++ b/packages/evm/test/Enclave.spec.ts @@ -52,7 +52,10 @@ describe("Enclave", function () { await poseidon.getAddress(), ); - await enclave.enableEncryptionScheme(encryptionSchemeId); + await enclave.setDecryptionVerifier( + encryptionSchemeId, + await decryptionVerifier.getAddress(), + ); await enclave.enableE3Program(await e3Program.getAddress()); return { @@ -217,47 +220,79 @@ describe("Enclave", function () { }); }); - describe("isEncryptionSchemeEnabled()", function () { + describe("getDecryptionVerifier()", function () { it("returns true if encryption scheme is enabled", async function () { - const { enclave } = await loadFixture(setup); - expect(await enclave.isEncryptionSchemeEnabled(encryptionSchemeId)).to.be - .true; + const { enclave, mocks } = await loadFixture(setup); + expect(await enclave.getDecryptionVerifier(encryptionSchemeId)).to.equal( + await mocks.decryptionVerifier.getAddress(), + ); }); it("returns false if encryption scheme is not enabled", async function () { const { enclave } = await loadFixture(setup); - expect(await enclave.isEncryptionSchemeEnabled(newEncryptionSchemeId)).to - .be.false; + expect( + await enclave.getDecryptionVerifier(newEncryptionSchemeId), + ).to.equal(ethers.ZeroAddress); }); }); - describe("enableEncryptionScheme()", function () { + describe("setDecryptionVerifier()", function () { it("reverts if caller is not owner", async function () { - const { enclave, notTheOwner } = await loadFixture(setup); + const { enclave, notTheOwner, mocks } = await loadFixture(setup); await expect( - enclave.connect(notTheOwner).enableEncryptionScheme(encryptionSchemeId), + enclave + .connect(notTheOwner) + .setDecryptionVerifier( + encryptionSchemeId, + await mocks.decryptionVerifier.getAddress(), + ), ) .to.be.revertedWithCustomError(enclave, "OwnableUnauthorizedAccount") .withArgs(notTheOwner); }); it("reverts if encryption scheme is already enabled", async function () { - const { enclave } = await loadFixture(setup); + const { enclave, mocks } = await loadFixture(setup); - await expect(enclave.enableEncryptionScheme(encryptionSchemeId)) + await expect( + enclave.setDecryptionVerifier( + encryptionSchemeId, + await mocks.decryptionVerifier.getAddress(), + ), + ) .to.be.revertedWithCustomError(enclave, "InvalidEncryptionScheme") .withArgs(encryptionSchemeId); }); - it("enabled encryption scheme", async function () { - const { enclave } = await loadFixture(setup); + it("enabled decryption verifier", async function () { + const { enclave, mocks } = await loadFixture(setup); - expect(await enclave.enableEncryptionScheme(newEncryptionSchemeId)); - expect(await enclave.isEncryptionSchemeEnabled(newEncryptionSchemeId)).to - .be.true; + expect( + await enclave.setDecryptionVerifier( + newEncryptionSchemeId, + await mocks.decryptionVerifier.getAddress(), + ), + ); + expect( + await enclave.getDecryptionVerifier(newEncryptionSchemeId), + ).to.equal(await mocks.decryptionVerifier.getAddress()); + }); + it("returns true if decryption verifier is enabled successfully", async function () { + const { enclave, mocks } = await loadFixture(setup); + + const result = await enclave.setDecryptionVerifier.staticCall( + newEncryptionSchemeId, + await mocks.decryptionVerifier.getAddress(), + ); + expect(result).to.be.true; }); it("emits EncryptionSchemeEnabled", async function () { - const { enclave } = await loadFixture(setup); + const { enclave, mocks } = await loadFixture(setup); - await expect(await enclave.enableEncryptionScheme(newEncryptionSchemeId)) + await expect( + await enclave.setDecryptionVerifier( + newEncryptionSchemeId, + await mocks.decryptionVerifier.getAddress(), + ), + ) .to.emit(enclave, "EncryptionSchemeEnabled") .withArgs(newEncryptionSchemeId); }); @@ -286,8 +321,16 @@ describe("Enclave", function () { const { enclave } = await loadFixture(setup); expect(await enclave.disableEncryptionScheme(encryptionSchemeId)); - expect(await enclave.isEncryptionSchemeEnabled(encryptionSchemeId)).to.be - .false; + expect(await enclave.getDecryptionVerifier(encryptionSchemeId)).to.equal( + ethers.ZeroAddress, + ); + }); + it("returns true if encryption scheme is disabled successfully", async function () { + const { enclave } = await loadFixture(setup); + + const result = + await enclave.disableEncryptionScheme.staticCall(encryptionSchemeId); + expect(result).to.be.true; }); it("emits EncryptionSchemeDisabled", async function () { const { enclave } = await loadFixture(setup); @@ -514,21 +557,6 @@ describe("Enclave", function () { ), ).to.be.revertedWithCustomError(enclave, "InvalidComputationRequest"); }); - it("reverts if given compute provider does not return output verifier address", async function () { - const { enclave, request } = await loadFixture(setup); - await expect( - enclave.request( - request.filter, - request.threshold, - request.startTime, - request.duration, - request.e3Program, - request.e3ProgramParams, - ZeroHash, - { value: 10 }, - ), - ).to.be.revertedWithCustomError(enclave, "InvalidComputationRequest"); - }); it("reverts if committee selection fails", async function () { const { enclave, request } = await loadFixture(setup); await expect(