Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: moves IDecryptionVerifier out of E3Program / IComputeProvider #106

Merged
merged 2 commits into from
Sep 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 27 additions & 30 deletions packages/evm/contracts/Enclave.sol
Original file line number Diff line number Diff line change
Expand Up @@ -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;

////////////////////////////////////////////////////////////
// //
Expand All @@ -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);
Expand Down Expand Up @@ -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({
Expand Down Expand Up @@ -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);
}
Expand All @@ -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);
}

Expand All @@ -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];
}
}
8 changes: 1 addition & 7 deletions packages/evm/contracts/interfaces/IE3Program.sol
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -12,19 +11,14 @@ 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,
bytes calldata e3ProgramParams,
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.
Expand Down
13 changes: 2 additions & 11 deletions packages/evm/contracts/test/MockE3Program.sol
Original file line number Diff line number Diff line change
@@ -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);
Expand All @@ -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,
Expand All @@ -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;
}
Expand Down
2 changes: 1 addition & 1 deletion packages/evm/package.json
Original file line number Diff line number Diff line change
@@ -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",
Expand Down
100 changes: 64 additions & 36 deletions packages/evm/test/Enclave.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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);
});
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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(
Expand Down
Loading