From 5fe19ff804caf5c9cd51595e977c03f9f499a15d Mon Sep 17 00:00:00 2001 From: Auryn Macmillan Date: Fri, 23 Aug 2024 15:52:40 -0400 Subject: [PATCH 01/32] feat: add incremental merkle tree --- packages/evm/contracts/Enclave.sol | 10 ++++++++-- packages/evm/package.json | 2 ++ packages/evm/test/fixtures/Enclave.fixture.ts | 18 +++++++++++++++++- packages/evm/yarn.lock | 17 +++++++++++++++++ 4 files changed, 44 insertions(+), 3 deletions(-) diff --git a/packages/evm/contracts/Enclave.sol b/packages/evm/contracts/Enclave.sol index fe1e810b..dd0eb0b5 100644 --- a/packages/evm/contracts/Enclave.sol +++ b/packages/evm/contracts/Enclave.sol @@ -13,6 +13,7 @@ import { IOutputVerifier } from "./interfaces/IOutputVerifier.sol"; import { OwnableUpgradeable } from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; +import { BinaryIMT, BinaryIMTData } from "@zk-kit/imt.sol/BinaryIMT.sol"; contract Enclave is IEnclave, OwnableUpgradeable { //////////////////////////////////////////////////////////// @@ -41,7 +42,10 @@ contract Enclave is IEnclave, OwnableUpgradeable { public executionModules; // Mapping of E3s. - mapping(uint256 id => E3 e3) public e3s; + mapping(uint256 e3Id => E3 e3) public e3s; + + // Mapping of input merkle trees + mapping(uint256 e3Id => BinaryIMTData imt) public inputs; //////////////////////////////////////////////////////////// // // @@ -175,6 +179,7 @@ contract Enclave is IEnclave, OwnableUpgradeable { plaintextOutput: hex"" }); e3s[e3Id] = e3; + BinaryIMT.init(inputs[e3Id], 32, 0); require( cyphernodeRegistry.requestCommittee(e3Id, filter, threshold), @@ -227,8 +232,9 @@ contract Enclave is IEnclave, OwnableUpgradeable { bytes memory input; (input, success) = e3.inputValidator.validate(msg.sender, data); require(success, InvalidInput()); - // TODO: probably better to accumulate inputs, rather than just dumping them in storage. e3s[e3Id].inputs.push(input); + BinaryIMT.insert(inputs[e3Id], uint256(keccak256(input))); + emit InputPublished(e3Id, input); } diff --git a/packages/evm/package.json b/packages/evm/package.json index f6b4db13..b8ea4b99 100644 --- a/packages/evm/package.json +++ b/packages/evm/package.json @@ -13,6 +13,7 @@ "@nomicfoundation/hardhat-network-helpers": "^1.0.10", "@nomicfoundation/hardhat-toolbox": "^4.0.0", "@nomicfoundation/hardhat-verify": "^2.0.2", + "@openzeppelin/contracts": "^5.0.2", "@openzeppelin/contracts-upgradeable": "^5.0.2", "@trivago/prettier-plugin-sort-imports": "^4.3.0", "@typechain/ethers-v6": "^0.5.1", @@ -23,6 +24,7 @@ "@types/node": "^20.10.4", "@typescript-eslint/eslint-plugin": "^7.11.0", "@typescript-eslint/parser": "^7.11.0", + "@zk-kit/imt.sol": "^2.0.0-beta.12", "chai": "^4.3.10", "cross-env": "^7.0.3", "eslint": "^8.56.0", diff --git a/packages/evm/test/fixtures/Enclave.fixture.ts b/packages/evm/test/fixtures/Enclave.fixture.ts index 539e7cc9..b23fbe45 100644 --- a/packages/evm/test/fixtures/Enclave.fixture.ts +++ b/packages/evm/test/fixtures/Enclave.fixture.ts @@ -12,8 +12,24 @@ export async function deployEnclaveFixture({ registry: string; maxDuration?: number; }) { + const poseidonDeployment = await ( + await ethers.getContractFactory("PoseidonT3") + ).deploy(); + + const imtDeployment = await ( + await ethers.getContractFactory("BinaryIMT", { + libraries: { + PoseidonT3: poseidonDeployment.getAddress(), + }, + }) + ).deploy(); + const deployment = await ( - await ethers.getContractFactory("Enclave") + await ethers.getContractFactory("Enclave", { + Libraries: { + BinaryIMT: imtDeployment.getAddress(), + }, + }) ).deploy(owner, registry, maxDuration); return Enclave__factory.connect(await deployment.getAddress(), owner); diff --git a/packages/evm/yarn.lock b/packages/evm/yarn.lock index c287ce52..eeb3daf2 100644 --- a/packages/evm/yarn.lock +++ b/packages/evm/yarn.lock @@ -874,6 +874,11 @@ resolved "https://registry.yarnpkg.com/@openzeppelin/contracts-upgradeable/-/contracts-upgradeable-5.0.2.tgz#3e5321a2ecdd0b206064356798c21225b6ec7105" integrity sha512-0MmkHSHiW2NRFiT9/r5Lu4eJq5UJ4/tzlOgYXNAIj/ONkQTVnz22pLxDvp4C4uZ9he7ZFvGn3Driptn1/iU7tQ== +"@openzeppelin/contracts@^5.0.2": + version "5.0.2" + resolved "https://registry.yarnpkg.com/@openzeppelin/contracts/-/contracts-5.0.2.tgz#b1d03075e49290d06570b2fd42154d76c2a5d210" + integrity sha512-ytPc6eLGcHHnapAZ9S+5qsdomhjo6QBHTDRRBFfTxXIpsicMhVPouPgmUPebZZZGX7vt9USA+Z+0M0dSVtSUEA== + "@pkgjs/parseargs@^0.11.0": version "0.11.0" resolved "https://registry.yarnpkg.com/@pkgjs/parseargs/-/parseargs-0.11.0.tgz#a77ea742fab25775145434eb1d2328cf5013ac33" @@ -1303,6 +1308,13 @@ resolved "https://registry.yarnpkg.com/@ungap/structured-clone/-/structured-clone-1.2.0.tgz#756641adb587851b5ccb3e095daf27ae581c8406" integrity sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ== +"@zk-kit/imt.sol@^2.0.0-beta.12": + version "2.0.0-beta.12" + resolved "https://registry.yarnpkg.com/@zk-kit/imt.sol/-/imt.sol-2.0.0-beta.12.tgz#9acd5fb64111b781a6cc614d3998a285fb48ab54" + integrity sha512-kKgopVO6zlfSiQgv3X9WykaCeyb8jGtthWGqdo1ZD7fY1bH8A7BWhhWxtoCuU5mPEgRbamw1cAoUynuLoEULsg== + dependencies: + poseidon-solidity "0.0.5" + abbrev@1: version "1.1.1" resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" @@ -3892,6 +3904,11 @@ pluralize@^8.0.0: resolved "https://registry.yarnpkg.com/pluralize/-/pluralize-8.0.0.tgz#1a6fa16a38d12a1901e0320fa017051c539ce3b1" integrity sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA== +poseidon-solidity@0.0.5: + version "0.0.5" + resolved "https://registry.yarnpkg.com/poseidon-solidity/-/poseidon-solidity-0.0.5.tgz#3f93e01cfe25f6d2f2fac49734fbb00961b84655" + integrity sha512-NzrvSwHzvZgT4hvg2GyGqeR+UOU/eLSEt4wAoXEua+VaR7NTKKwx1X9bPlh1VMBEVEno+IWvkRBbidFGzTeAqQ== + prelude-ls@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" From 7c2eadf1e8f24db8242848b204101689043b5f19 Mon Sep 17 00:00:00 2001 From: Auryn Macmillan Date: Mon, 26 Aug 2024 20:48:52 -0400 Subject: [PATCH 02/32] Feat: BinaryIMT First attempt at accumulating inputs in a binary incremental merkle tree. Currently failing with `Error: Transaction reverted without a reason string` when I try to insert an input into the tree `BinaryIMT.insert(inputs[e3Id], inputHash);`. --- packages/evm/contracts/Enclave.sol | 10 ++++-- .../evm/contracts/interfaces/IEnclave.sol | 2 +- packages/evm/hardhat.config.ts | 1 + packages/evm/package.json | 1 + packages/evm/test/Enclave.spec.ts | 6 ++-- packages/evm/test/fixtures/Enclave.fixture.ts | 33 +++++++++++++++---- packages/evm/yarn.lock | 2 +- 7 files changed, 40 insertions(+), 15 deletions(-) diff --git a/packages/evm/contracts/Enclave.sol b/packages/evm/contracts/Enclave.sol index dd0eb0b5..c5e3d258 100644 --- a/packages/evm/contracts/Enclave.sol +++ b/packages/evm/contracts/Enclave.sol @@ -158,6 +158,7 @@ contract Enclave is IEnclave, OwnableUpgradeable { require(address(inputValidator) != address(0), InvalidComputation()); // TODO: validate that the requested computation can be performed by the given execution module. + // Perhaps the execution module should be returned by the computation module? IOutputVerifier outputVerifier = executionModule.validate(emParams); require( address(outputVerifier) != address(0), @@ -179,7 +180,7 @@ contract Enclave is IEnclave, OwnableUpgradeable { plaintextOutput: hex"" }); e3s[e3Id] = e3; - BinaryIMT.init(inputs[e3Id], 32, 0); + BinaryIMT.initWithDefaultZeroes(inputs[e3Id], 32); require( cyphernodeRegistry.requestCommittee(e3Id, filter, threshold), @@ -233,9 +234,12 @@ contract Enclave is IEnclave, OwnableUpgradeable { (input, success) = e3.inputValidator.validate(msg.sender, data); require(success, InvalidInput()); e3s[e3Id].inputs.push(input); - BinaryIMT.insert(inputs[e3Id], uint256(keccak256(input))); + // note: hash is divided by ten to make the hash smaller than the snark scalar field. + // TODO: Not sure if this is a bad idea ¯\_(ツ)_/¯ + uint256 inputHash = uint256(keccak256(input)) / 10; + BinaryIMT.insert(inputs[e3Id], inputHash); - emit InputPublished(e3Id, input); + emit InputPublished(e3Id, input, inputHash); } function publishCiphertextOutput( diff --git a/packages/evm/contracts/interfaces/IEnclave.sol b/packages/evm/contracts/interfaces/IEnclave.sol index fb2ec6f8..2fb2acea 100644 --- a/packages/evm/contracts/interfaces/IEnclave.sol +++ b/packages/evm/contracts/interfaces/IEnclave.sol @@ -38,7 +38,7 @@ interface IEnclave { /// successfully published. /// @param e3Id ID of the E3. /// @param data ABI encoded input data. - event InputPublished(uint256 indexed e3Id, bytes data); + event InputPublished(uint256 indexed e3Id, bytes data, uint256 inputHash); /// @notice This event MUST be emitted when the plaintext output of an Encrypted Execution Environment (E3) /// is successfully published. diff --git a/packages/evm/hardhat.config.ts b/packages/evm/hardhat.config.ts index e07861b9..278ca063 100644 --- a/packages/evm/hardhat.config.ts +++ b/packages/evm/hardhat.config.ts @@ -77,6 +77,7 @@ const config: HardhatUserConfig = { mnemonic, }, chainId: chainIds.hardhat, + allowUnlimitedContractSize: true, }, ganache: { accounts: { diff --git a/packages/evm/package.json b/packages/evm/package.json index b8ea4b99..f3e99b31 100644 --- a/packages/evm/package.json +++ b/packages/evm/package.json @@ -36,6 +36,7 @@ "hardhat-gas-reporter": "^2.2.0", "lodash": "^4.17.21", "mocha": "^10.2.0", + "poseidon-solidity": "^0.0.5", "prettier": "^3.1.1", "prettier-plugin-solidity": "^1.2.0", "rimraf": "^5.0.5", diff --git a/packages/evm/test/Enclave.spec.ts b/packages/evm/test/Enclave.spec.ts index f23b8ddc..a71207df 100644 --- a/packages/evm/test/Enclave.spec.ts +++ b/packages/evm/test/Enclave.spec.ts @@ -887,8 +887,6 @@ describe("Enclave", function () { .withArgs(0); await enclave.activate(0); - - await expect(enclave.publishInput(0, inputData)).to.not.be.reverted; }); it("reverts if input is not valid", async function () { @@ -928,7 +926,6 @@ describe("Enclave", function () { ); await enclave.activate(0); - await expect(enclave.publishInput(0, ZeroHash)).to.not.be.reverted; await mine(2, { interval: request.duration }); @@ -1002,10 +999,11 @@ describe("Enclave", function () { const inputData = abiCoder.encode(["bytes"], ["0xaabbccddeeff"]); await enclave.activate(e3Id); + const expectedHash = BigInt(ethers.keccak256(inputData)) / BigInt(10); await expect(enclave.publishInput(e3Id, inputData)) .to.emit(enclave, "InputPublished") - .withArgs(e3Id, inputData); + .withArgs(e3Id, inputData, expectedHash); }); }); diff --git a/packages/evm/test/fixtures/Enclave.fixture.ts b/packages/evm/test/fixtures/Enclave.fixture.ts index b23fbe45..15121b44 100644 --- a/packages/evm/test/fixtures/Enclave.fixture.ts +++ b/packages/evm/test/fixtures/Enclave.fixture.ts @@ -1,5 +1,6 @@ import { SignerWithAddress } from "@nomicfoundation/hardhat-ethers/signers"; import { ethers } from "hardhat"; +import { PoseidonT3, proxy } from "poseidon-solidity"; import { Enclave__factory } from "../../types/factories/contracts/Enclave__factory"; @@ -12,22 +13,42 @@ export async function deployEnclaveFixture({ registry: string; maxDuration?: number; }) { - const poseidonDeployment = await ( - await ethers.getContractFactory("PoseidonT3") - ).deploy(); + if ((await ethers.provider.getCode(proxy.address)) === "0x") { + // fund the keyless account + await owner.sendTransaction({ + to: proxy.from, + value: proxy.gas, + }); + + // then send the presigned transaction deploying the proxy + await ethers.provider.broadcastTransaction(proxy.tx); + } + + // Then deploy the hasher, if needed + if ((await ethers.provider.getCode(PoseidonT3.address)) === "0x") { + await owner.sendTransaction({ + to: proxy.address, + data: PoseidonT3.data, + }); + } + + const poseidonDeployment = await await ethers.getContractAt( + "PoseidonT3", + proxy.address, + ); const imtDeployment = await ( await ethers.getContractFactory("BinaryIMT", { libraries: { - PoseidonT3: poseidonDeployment.getAddress(), + PoseidonT3: await poseidonDeployment.getAddress(), }, }) ).deploy(); const deployment = await ( await ethers.getContractFactory("Enclave", { - Libraries: { - BinaryIMT: imtDeployment.getAddress(), + libraries: { + BinaryIMT: await imtDeployment.getAddress(), }, }) ).deploy(owner, registry, maxDuration); diff --git a/packages/evm/yarn.lock b/packages/evm/yarn.lock index eeb3daf2..86f25e70 100644 --- a/packages/evm/yarn.lock +++ b/packages/evm/yarn.lock @@ -3904,7 +3904,7 @@ pluralize@^8.0.0: resolved "https://registry.yarnpkg.com/pluralize/-/pluralize-8.0.0.tgz#1a6fa16a38d12a1901e0320fa017051c539ce3b1" integrity sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA== -poseidon-solidity@0.0.5: +poseidon-solidity@0.0.5, poseidon-solidity@^0.0.5: version "0.0.5" resolved "https://registry.yarnpkg.com/poseidon-solidity/-/poseidon-solidity-0.0.5.tgz#3f93e01cfe25f6d2f2fac49734fbb00961b84655" integrity sha512-NzrvSwHzvZgT4hvg2GyGqeR+UOU/eLSEt4wAoXEua+VaR7NTKKwx1X9bPlh1VMBEVEno+IWvkRBbidFGzTeAqQ== From 456ff18fb1728bc4dbb33a05a3db6f759be95078 Mon Sep 17 00:00:00 2001 From: Auryn Macmillan Date: Tue, 27 Aug 2024 08:21:01 -0400 Subject: [PATCH 03/32] feat: use LeanIMT, rather than BinaryIMT. This commit replaces BinaryIMT with LeanIMT, which resolved the errors in the previous commit. I've also removed the inputs array from the E3 struct, so inputs are no longer stored on-chain. There seems to be some limit to how large items in the trees can be. A hack solution is to divide the inputHash by `10 ** 39`. --- packages/evm/contracts/Enclave.sol | 28 +++++++---- packages/evm/contracts/interfaces/IE3.sol | 1 - packages/evm/package.json | 2 +- packages/evm/test/Enclave.spec.ts | 48 +++++++++++++------ packages/evm/test/fixtures/Enclave.fixture.ts | 29 +++++++---- packages/evm/yarn.lock | 8 ++-- 6 files changed, 79 insertions(+), 37 deletions(-) diff --git a/packages/evm/contracts/Enclave.sol b/packages/evm/contracts/Enclave.sol index c5e3d258..4c1cd76f 100644 --- a/packages/evm/contracts/Enclave.sol +++ b/packages/evm/contracts/Enclave.sol @@ -13,9 +13,14 @@ import { IOutputVerifier } from "./interfaces/IOutputVerifier.sol"; import { OwnableUpgradeable } from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; -import { BinaryIMT, BinaryIMTData } from "@zk-kit/imt.sol/BinaryIMT.sol"; +import { + InternalLeanIMT, + LeanIMTData +} from "@zk-kit/lean-imt.sol/InternalLeanIMT.sol"; contract Enclave is IEnclave, OwnableUpgradeable { + using InternalLeanIMT for LeanIMTData; + //////////////////////////////////////////////////////////// // // // Storage Variables // @@ -45,7 +50,10 @@ contract Enclave is IEnclave, OwnableUpgradeable { mapping(uint256 e3Id => E3 e3) public e3s; // Mapping of input merkle trees - mapping(uint256 e3Id => BinaryIMTData imt) public inputs; + mapping(uint256 e3Id => LeanIMTData imt) public inputs; + + // Mapping counting the number of inputs for each E3. + mapping(uint256 e3Id => uint256) public inputCount; //////////////////////////////////////////////////////////// // // @@ -175,12 +183,10 @@ contract Enclave is IEnclave, OwnableUpgradeable { inputValidator: inputValidator, outputVerifier: outputVerifier, committeePublicKey: hex"", - inputs: new bytes[](0), ciphertextOutput: hex"", plaintextOutput: hex"" }); e3s[e3Id] = e3; - BinaryIMT.initWithDefaultZeroes(inputs[e3Id], 32); require( cyphernodeRegistry.requestCommittee(e3Id, filter, threshold), @@ -233,11 +239,13 @@ contract Enclave is IEnclave, OwnableUpgradeable { bytes memory input; (input, success) = e3.inputValidator.validate(msg.sender, data); require(success, InvalidInput()); - e3s[e3Id].inputs.push(input); - // note: hash is divided by ten to make the hash smaller than the snark scalar field. + // note: hash is divided by 10 ** 39 to make the hash smaller than the snark scalar field. // TODO: Not sure if this is a bad idea ¯\_(ツ)_/¯ - uint256 inputHash = uint256(keccak256(input)) / 10; - BinaryIMT.insert(inputs[e3Id], inputHash); + uint256 inputHash = uint256( + keccak256(abi.encode(input, inputCount[e3Id])) + ) / 10 ** 39; + inputCount[e3Id]++; + inputs[e3Id]._insert(inputHash); emit InputPublished(e3Id, input, inputHash); } @@ -378,4 +386,8 @@ contract Enclave is IEnclave, OwnableUpgradeable { E3DoesNotExist(e3Id) ); } + + function getInputRoot(uint256 e3Id) public view returns (uint256) { + return InternalLeanIMT._root(inputs[e3Id]); + } } diff --git a/packages/evm/contracts/interfaces/IE3.sol b/packages/evm/contracts/interfaces/IE3.sol index faa2cace..67660a5e 100644 --- a/packages/evm/contracts/interfaces/IE3.sol +++ b/packages/evm/contracts/interfaces/IE3.sol @@ -29,7 +29,6 @@ struct E3 { IInputValidator inputValidator; IOutputVerifier outputVerifier; bytes committeePublicKey; - bytes[] inputs; bytes ciphertextOutput; bytes plaintextOutput; } diff --git a/packages/evm/package.json b/packages/evm/package.json index f3e99b31..e68c7404 100644 --- a/packages/evm/package.json +++ b/packages/evm/package.json @@ -24,7 +24,7 @@ "@types/node": "^20.10.4", "@typescript-eslint/eslint-plugin": "^7.11.0", "@typescript-eslint/parser": "^7.11.0", - "@zk-kit/imt.sol": "^2.0.0-beta.12", + "@zk-kit/lean-imt.sol": "2.0.0", "chai": "^4.3.10", "cross-env": "^7.0.3", "eslint": "^8.56.0", diff --git a/packages/evm/test/Enclave.spec.ts b/packages/evm/test/Enclave.spec.ts index a71207df..06be798d 100644 --- a/packages/evm/test/Enclave.spec.ts +++ b/packages/evm/test/Enclave.spec.ts @@ -933,7 +933,7 @@ describe("Enclave", function () { enclave.publishInput(0, ZeroHash), ).to.be.revertedWithCustomError(enclave, "InputDeadlinePassed"); }); - it("sets ciphertextInput correctly", async function () { + it("returns true if input is published successfully", async function () { const { enclave, request } = await loadFixture(setup); const inputData = "0x12345678"; @@ -951,16 +951,13 @@ describe("Enclave", function () { await enclave.activate(0); - expect(await enclave.publishInput(0, inputData)).to.not.be.reverted; - let e3 = await enclave.getE3(0); - expect(e3.inputs[0]).to.equal(inputData); - expect(await enclave.publishInput(0, inputData)).to.not.be.reverted; - e3 = await enclave.getE3(0); - expect(e3.inputs[1]).to.equal(inputData); + expect(await enclave.publishInput.staticCall(0, inputData)).to.equal( + true, + ); }); - it("returns true if input is published successfully", async function () { + it.only("adds inputHash to merkle tree", async function () { const { enclave, request } = await loadFixture(setup); - const inputData = "0x12345678"; + const inputData = abiCoder.encode(["bytes"], ["0xaabbccddeeff"]); await enclave.request( request.filter, @@ -974,11 +971,26 @@ describe("Enclave", function () { { value: 10 }, ); - await enclave.activate(0); + const e3Id = 0; - expect(await enclave.publishInput.staticCall(0, inputData)).to.equal( - true, - ); + await enclave.activate(e3Id); + + const expectedHash = + BigInt( + ethers.keccak256( + ethers.AbiCoder.defaultAbiCoder().encode( + ["bytes", "uint256"], + [inputData, 0], + ), + ), + ) / BigInt(10n ** 39n); + + await enclave.publishInput(e3Id, inputData); + expect(await enclave.getInputRoot(e3Id)).to.equal(expectedHash); + + const secondInputData = abiCoder.encode(["bytes"], ["0x112233445566"]); + await enclave.publishInput(e3Id, secondInputData); + expect(await enclave.getInputRoot(e3Id)).to.equal(expectedHash); }); it("emits InputPublished event", async function () { const { enclave, request } = await loadFixture(setup); @@ -999,7 +1011,15 @@ describe("Enclave", function () { const inputData = abiCoder.encode(["bytes"], ["0xaabbccddeeff"]); await enclave.activate(e3Id); - const expectedHash = BigInt(ethers.keccak256(inputData)) / BigInt(10); + const expectedHash = + BigInt( + ethers.keccak256( + ethers.AbiCoder.defaultAbiCoder().encode( + ["bytes", "uint256"], + [inputData, 0], + ), + ), + ) / BigInt(10); await expect(enclave.publishInput(e3Id, inputData)) .to.emit(enclave, "InputPublished") diff --git a/packages/evm/test/fixtures/Enclave.fixture.ts b/packages/evm/test/fixtures/Enclave.fixture.ts index 15121b44..7582069e 100644 --- a/packages/evm/test/fixtures/Enclave.fixture.ts +++ b/packages/evm/test/fixtures/Enclave.fixture.ts @@ -38,19 +38,30 @@ export async function deployEnclaveFixture({ ); const imtDeployment = await ( - await ethers.getContractFactory("BinaryIMT", { - libraries: { - PoseidonT3: await poseidonDeployment.getAddress(), - }, - }) + await ethers.getContractFactory( + "InternalLeanIMT", + // , { + // libraries: { + // PoseidonT3: await poseidonDeployment.getAddress(), + // }, + // } + ) ).deploy(); const deployment = await ( - await ethers.getContractFactory("Enclave", { - libraries: { - BinaryIMT: await imtDeployment.getAddress(), + await ethers.getContractFactory( + "Enclave", + { + libraries: { + PoseidonT3: await poseidonDeployment.getAddress(), + }, }, - }) + // , { + // libraries: { + // InternalLeanIMT: await imtDeployment.getAddress(), + // }, + // } + ) ).deploy(owner, registry, maxDuration); return Enclave__factory.connect(await deployment.getAddress(), owner); diff --git a/packages/evm/yarn.lock b/packages/evm/yarn.lock index 86f25e70..5a860550 100644 --- a/packages/evm/yarn.lock +++ b/packages/evm/yarn.lock @@ -1308,10 +1308,10 @@ resolved "https://registry.yarnpkg.com/@ungap/structured-clone/-/structured-clone-1.2.0.tgz#756641adb587851b5ccb3e095daf27ae581c8406" integrity sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ== -"@zk-kit/imt.sol@^2.0.0-beta.12": - version "2.0.0-beta.12" - resolved "https://registry.yarnpkg.com/@zk-kit/imt.sol/-/imt.sol-2.0.0-beta.12.tgz#9acd5fb64111b781a6cc614d3998a285fb48ab54" - integrity sha512-kKgopVO6zlfSiQgv3X9WykaCeyb8jGtthWGqdo1ZD7fY1bH8A7BWhhWxtoCuU5mPEgRbamw1cAoUynuLoEULsg== +"@zk-kit/lean-imt.sol@2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@zk-kit/lean-imt.sol/-/lean-imt.sol-2.0.0.tgz#4b0aee47854b5844455f9361396062139416e12b" + integrity sha512-e9pAm+IXveLPy7b1h05ipIo6U44vp8g/2E+Ocx3PIloMu7lgTXFkIeZj/qZ/iLgEMsF74T0dsg7aVIT0B0nsDA== dependencies: poseidon-solidity "0.0.5" From b2c946e1291a48969a37ff3b3717f9b1871f618d Mon Sep 17 00:00:00 2001 From: Auryn Macmillan Date: Wed, 28 Aug 2024 20:48:02 -0400 Subject: [PATCH 04/32] fix: deploy Poseidon In previous commits, I was hitting errors with the Poseidon library. It seems to be an issue with the deterministic deployments and hardhat network, being tracked [here](https://github.com/privacy-scaling-explorations/zk-kit.solidity/issues/38). By deploying the Poseidon Lib directly, the issue was resolved. Note that this required adding an override to the compiler settings. --- packages/evm/contracts/Enclave.sol | 4 +- .../evm/contracts/interfaces/IEnclave.sol | 7 +- packages/evm/hardhat.config.ts | 10 + packages/evm/package.json | 4 +- packages/evm/test/Enclave.spec.ts | 31 ++- packages/evm/test/fixtures/Enclave.fixture.ts | 36 +--- packages/evm/yarn.lock | 185 +++++++++--------- 7 files changed, 142 insertions(+), 135 deletions(-) diff --git a/packages/evm/contracts/Enclave.sol b/packages/evm/contracts/Enclave.sol index 4c1cd76f..8094fef3 100644 --- a/packages/evm/contracts/Enclave.sol +++ b/packages/evm/contracts/Enclave.sol @@ -243,11 +243,11 @@ contract Enclave is IEnclave, OwnableUpgradeable { // TODO: Not sure if this is a bad idea ¯\_(ツ)_/¯ uint256 inputHash = uint256( keccak256(abi.encode(input, inputCount[e3Id])) - ) / 10 ** 39; + ) / 10; inputCount[e3Id]++; inputs[e3Id]._insert(inputHash); - emit InputPublished(e3Id, input, inputHash); + emit InputPublished(e3Id, input, inputHash, inputCount[e3Id] - 1); } function publishCiphertextOutput( diff --git a/packages/evm/contracts/interfaces/IEnclave.sol b/packages/evm/contracts/interfaces/IEnclave.sol index 2fb2acea..e454bd4f 100644 --- a/packages/evm/contracts/interfaces/IEnclave.sol +++ b/packages/evm/contracts/interfaces/IEnclave.sol @@ -38,7 +38,12 @@ interface IEnclave { /// successfully published. /// @param e3Id ID of the E3. /// @param data ABI encoded input data. - event InputPublished(uint256 indexed e3Id, bytes data, uint256 inputHash); + event InputPublished( + uint256 indexed e3Id, + bytes data, + uint256 inputHash, + uint256 index + ); /// @notice This event MUST be emitted when the plaintext output of an Encrypted Execution Environment (E3) /// is successfully published. diff --git a/packages/evm/hardhat.config.ts b/packages/evm/hardhat.config.ts index 278ca063..e9f357b3 100644 --- a/packages/evm/hardhat.config.ts +++ b/packages/evm/hardhat.config.ts @@ -117,6 +117,16 @@ const config: HardhatUserConfig = { }, viaIR: true, }, + overrides: { + "node_modules/poseidon-solidity/PoseidonT3.sol": { + settings: { + optimizer: { + enabled: true, + runs: 2 ** 32 - 1, + }, + }, + }, + }, }, typechain: { outDir: "types", diff --git a/packages/evm/package.json b/packages/evm/package.json index e68c7404..1bc79870 100644 --- a/packages/evm/package.json +++ b/packages/evm/package.json @@ -24,6 +24,7 @@ "@types/node": "^20.10.4", "@typescript-eslint/eslint-plugin": "^7.11.0", "@typescript-eslint/parser": "^7.11.0", + "@zk-kit/lean-imt": "^2.1.0", "@zk-kit/lean-imt.sol": "2.0.0", "chai": "^4.3.10", "cross-env": "^7.0.3", @@ -31,11 +32,12 @@ "eslint-config-prettier": "^9.1.0", "ethers": "^6.9.0", "fs-extra": "^11.2.0", - "hardhat": "^2.19.2", + "hardhat": "^2.22.0", "hardhat-deploy": "^0.12.1", "hardhat-gas-reporter": "^2.2.0", "lodash": "^4.17.21", "mocha": "^10.2.0", + "poseidon-lite": "^0.3.0", "poseidon-solidity": "^0.0.5", "prettier": "^3.1.1", "prettier-plugin-solidity": "^1.2.0", diff --git a/packages/evm/test/Enclave.spec.ts b/packages/evm/test/Enclave.spec.ts index 06be798d..798471c6 100644 --- a/packages/evm/test/Enclave.spec.ts +++ b/packages/evm/test/Enclave.spec.ts @@ -3,9 +3,11 @@ import { mine, time, } from "@nomicfoundation/hardhat-network-helpers"; +import { LeanIMT } from "@zk-kit/lean-imt"; import { expect } from "chai"; import { ZeroHash } from "ethers"; import { ethers } from "hardhat"; +import { poseidon2 } from "poseidon-lite"; import { deployEnclaveFixture } from "./fixtures/Enclave.fixture"; import { deployComputationModuleFixture } from "./fixtures/MockComputationModule.fixture"; @@ -955,10 +957,16 @@ describe("Enclave", function () { true, ); }); - it.only("adds inputHash to merkle tree", async function () { + it("adds inputHash to merkle tree", async function () { const { enclave, request } = await loadFixture(setup); const inputData = abiCoder.encode(["bytes"], ["0xaabbccddeeff"]); + // Hash function used to compute the tree nodes. + const hash = (a, b) => poseidon2([a, b]); + + // To create an instance of a LeanIMT, you must provide the hash function. + const tree = new LeanIMT(hash); + await enclave.request( request.filter, request.threshold, @@ -975,7 +983,7 @@ describe("Enclave", function () { await enclave.activate(e3Id); - const expectedHash = + tree.insert( BigInt( ethers.keccak256( ethers.AbiCoder.defaultAbiCoder().encode( @@ -983,14 +991,25 @@ describe("Enclave", function () { [inputData, 0], ), ), - ) / BigInt(10n ** 39n); + ) / BigInt(10), + ); await enclave.publishInput(e3Id, inputData); - expect(await enclave.getInputRoot(e3Id)).to.equal(expectedHash); + expect(await enclave.getInputRoot(e3Id)).to.equal(tree.root); const secondInputData = abiCoder.encode(["bytes"], ["0x112233445566"]); + tree.insert( + BigInt( + ethers.keccak256( + ethers.AbiCoder.defaultAbiCoder().encode( + ["bytes", "uint256"], + [secondInputData, 1], + ), + ), + ) / BigInt(10), + ); await enclave.publishInput(e3Id, secondInputData); - expect(await enclave.getInputRoot(e3Id)).to.equal(expectedHash); + expect(await enclave.getInputRoot(e3Id)).to.equal(tree.root); }); it("emits InputPublished event", async function () { const { enclave, request } = await loadFixture(setup); @@ -1023,7 +1042,7 @@ describe("Enclave", function () { await expect(enclave.publishInput(e3Id, inputData)) .to.emit(enclave, "InputPublished") - .withArgs(e3Id, inputData, expectedHash); + .withArgs(e3Id, inputData, expectedHash, 0); }); }); diff --git a/packages/evm/test/fixtures/Enclave.fixture.ts b/packages/evm/test/fixtures/Enclave.fixture.ts index 7582069e..fb0acb2d 100644 --- a/packages/evm/test/fixtures/Enclave.fixture.ts +++ b/packages/evm/test/fixtures/Enclave.fixture.ts @@ -13,40 +13,8 @@ export async function deployEnclaveFixture({ registry: string; maxDuration?: number; }) { - if ((await ethers.provider.getCode(proxy.address)) === "0x") { - // fund the keyless account - await owner.sendTransaction({ - to: proxy.from, - value: proxy.gas, - }); - - // then send the presigned transaction deploying the proxy - await ethers.provider.broadcastTransaction(proxy.tx); - } - - // Then deploy the hasher, if needed - if ((await ethers.provider.getCode(PoseidonT3.address)) === "0x") { - await owner.sendTransaction({ - to: proxy.address, - data: PoseidonT3.data, - }); - } - - const poseidonDeployment = await await ethers.getContractAt( - "PoseidonT3", - proxy.address, - ); - - const imtDeployment = await ( - await ethers.getContractFactory( - "InternalLeanIMT", - // , { - // libraries: { - // PoseidonT3: await poseidonDeployment.getAddress(), - // }, - // } - ) - ).deploy(); + const poseidonFactory = await ethers.getContractFactory("PoseidonT3"); + const poseidonDeployment = await poseidonFactory.deploy(); const deployment = await ( await ethers.getContractFactory( diff --git a/packages/evm/yarn.lock b/packages/evm/yarn.lock index 5a860550..5258f6f1 100644 --- a/packages/evm/yarn.lock +++ b/packages/evm/yarn.lock @@ -680,53 +680,53 @@ "@nodelib/fs.scandir" "2.1.5" fastq "^1.6.0" -"@nomicfoundation/edr-darwin-arm64@0.4.0": - version "0.4.0" - resolved "https://registry.yarnpkg.com/@nomicfoundation/edr-darwin-arm64/-/edr-darwin-arm64-0.4.0.tgz#bbb43f0e01f40839b0bd38c2c443cb6910ae955f" - integrity sha512-7+rraFk9tCqvfemv9Ita5vTlSBAeO/S5aDKOgGRgYt0JEKZlrX161nDW6UfzMPxWl9GOLEDUzCEaYuNmXseUlg== +"@nomicfoundation/edr-darwin-arm64@0.5.2": + version "0.5.2" + resolved "https://registry.yarnpkg.com/@nomicfoundation/edr-darwin-arm64/-/edr-darwin-arm64-0.5.2.tgz#72f7a826c9f0f2c91308edca562de3b9484ac079" + integrity sha512-Gm4wOPKhbDjGTIRyFA2QUAPfCXA1AHxYOKt3yLSGJkQkdy9a5WW+qtqKeEKHc/+4wpJSLtsGQfpzyIzggFfo/A== -"@nomicfoundation/edr-darwin-x64@0.4.0": - version "0.4.0" - resolved "https://registry.yarnpkg.com/@nomicfoundation/edr-darwin-x64/-/edr-darwin-x64-0.4.0.tgz#b1ffcd9142418fd8498de34a7336b3f977907c86" - integrity sha512-+Hrc0mP9L6vhICJSfyGo/2taOToy1AIzVZawO3lU8Lf7oDQXfhQ4UkZnkWAs9SVu1eUwHUGGGE0qB8644piYgg== +"@nomicfoundation/edr-darwin-x64@0.5.2": + version "0.5.2" + resolved "https://registry.yarnpkg.com/@nomicfoundation/edr-darwin-x64/-/edr-darwin-x64-0.5.2.tgz#6d0fedb219d664631c6feddc596ab8c3bbc36fa8" + integrity sha512-ClyABq2dFCsrYEED3/UIO0c7p4H1/4vvlswFlqUyBpOkJccr75qIYvahOSJRM62WgUFRhbSS0OJXFRwc/PwmVg== -"@nomicfoundation/edr-linux-arm64-gnu@0.4.0": - version "0.4.0" - resolved "https://registry.yarnpkg.com/@nomicfoundation/edr-linux-arm64-gnu/-/edr-linux-arm64-gnu-0.4.0.tgz#8173d16d4f6f2b3e82ba7096d2a1ea3619d8bfa7" - integrity sha512-4HUDMchNClQrVRfVTqBeSX92hM/3khCgpZkXP52qrnJPqgbdCxosOehlQYZ65wu0b/kaaZSyvACgvCLSQ5oSzQ== +"@nomicfoundation/edr-linux-arm64-gnu@0.5.2": + version "0.5.2" + resolved "https://registry.yarnpkg.com/@nomicfoundation/edr-linux-arm64-gnu/-/edr-linux-arm64-gnu-0.5.2.tgz#60e4d52d963141bc2bb4a02639dc590a7fbdda2f" + integrity sha512-HWMTVk1iOabfvU2RvrKLDgtFjJZTC42CpHiw2h6rfpsgRqMahvIlx2jdjWYzFNy1jZKPTN1AStQ/91MRrg5KnA== -"@nomicfoundation/edr-linux-arm64-musl@0.4.0": - version "0.4.0" - resolved "https://registry.yarnpkg.com/@nomicfoundation/edr-linux-arm64-musl/-/edr-linux-arm64-musl-0.4.0.tgz#b1ce293a7c3e0d9f70391e1aef1a82b83b997567" - integrity sha512-D4J935ZRL8xfnP3zIFlCI9jXInJ0loDUkCTLeCEbOf2uuDumWDghKNQlF1itUS+EHaR1pFVBbuwqq8hVK0dASg== +"@nomicfoundation/edr-linux-arm64-musl@0.5.2": + version "0.5.2" + resolved "https://registry.yarnpkg.com/@nomicfoundation/edr-linux-arm64-musl/-/edr-linux-arm64-musl-0.5.2.tgz#6676a09eab57c435a16ffc144658c896acca9baa" + integrity sha512-CwsQ10xFx/QAD5y3/g5alm9+jFVuhc7uYMhrZAu9UVF+KtVjeCvafj0PaVsZ8qyijjqVuVsJ8hD1x5ob7SMcGg== -"@nomicfoundation/edr-linux-x64-gnu@0.4.0": - version "0.4.0" - resolved "https://registry.yarnpkg.com/@nomicfoundation/edr-linux-x64-gnu/-/edr-linux-x64-gnu-0.4.0.tgz#4c12c4e4bfd3d837f5663ad7cbf7cb6d5634ef83" - integrity sha512-6x7HPy+uN5Cb9N77e2XMmT6+QSJ+7mRbHnhkGJ8jm4cZvWuj2Io7npOaeHQ3YHK+TiQpTnlbkjoOIpEwpY3XZA== +"@nomicfoundation/edr-linux-x64-gnu@0.5.2": + version "0.5.2" + resolved "https://registry.yarnpkg.com/@nomicfoundation/edr-linux-x64-gnu/-/edr-linux-x64-gnu-0.5.2.tgz#f558d9697ce961410e7a7468f9ab8c8a601b9df6" + integrity sha512-CWVCEdhWJ3fmUpzWHCRnC0/VLBDbqtqTGTR6yyY1Ep3S3BOrHEAvt7h5gx85r2vLcztisu2vlDq51auie4IU1A== -"@nomicfoundation/edr-linux-x64-musl@0.4.0": - version "0.4.0" - resolved "https://registry.yarnpkg.com/@nomicfoundation/edr-linux-x64-musl/-/edr-linux-x64-musl-0.4.0.tgz#8842004aa1a47c504f10863687da28b65dca7baa" - integrity sha512-3HFIJSXgyubOiaN4MWGXx2xhTnhwlJk0PiSYNf9+L/fjBtcRkb2nM910ZJHTvqCb6OT98cUnaKuAYdXIW2amgw== +"@nomicfoundation/edr-linux-x64-musl@0.5.2": + version "0.5.2" + resolved "https://registry.yarnpkg.com/@nomicfoundation/edr-linux-x64-musl/-/edr-linux-x64-musl-0.5.2.tgz#c9c9cbb2997499f75c1d022be724b0551d44569f" + integrity sha512-+aJDfwhkddy2pP5u1ISg3IZVAm0dO836tRlDTFWtvvSMQ5hRGqPcWwlsbobhDQsIxhPJyT7phL0orCg5W3WMeA== -"@nomicfoundation/edr-win32-x64-msvc@0.4.0": - version "0.4.0" - resolved "https://registry.yarnpkg.com/@nomicfoundation/edr-win32-x64-msvc/-/edr-win32-x64-msvc-0.4.0.tgz#29d8bbb2edf9912a95f5453855cf17cdcb269957" - integrity sha512-CP4GsllEfXEz+lidcGYxKe5rDJ60TM5/blB5z/04ELVvw6/CK9eLcYeku7HV0jvV7VE6dADYKSdQyUkvd0El+A== +"@nomicfoundation/edr-win32-x64-msvc@0.5.2": + version "0.5.2" + resolved "https://registry.yarnpkg.com/@nomicfoundation/edr-win32-x64-msvc/-/edr-win32-x64-msvc-0.5.2.tgz#f16db88bf4fe09a996af0a25096e09deecb72bfa" + integrity sha512-CcvvuA3sAv7liFNPsIR/68YlH6rrybKzYttLlMr80d4GKJjwJ5OKb3YgE6FdZZnOfP19HEHhsLcE0DPLtY3r0w== -"@nomicfoundation/edr@^0.4.0": - version "0.4.0" - resolved "https://registry.yarnpkg.com/@nomicfoundation/edr/-/edr-0.4.0.tgz#4895ecb6ef321136db837458949c37cce4a29459" - integrity sha512-T96DMSogO8TCdbKKctvxfsDljbhFOUKWc9fHJhSeUh71EEho2qR4951LKQF7t7UWEzguVYh/idQr5L/E3QeaMw== +"@nomicfoundation/edr@^0.5.2": + version "0.5.2" + resolved "https://registry.yarnpkg.com/@nomicfoundation/edr/-/edr-0.5.2.tgz#e8c7b3d3dd4a312432ab3930dec60f76dc5c4926" + integrity sha512-hW/iLvUQZNTVjFyX/I40rtKvvDOqUEyIi96T28YaLfmPL+3LW2lxmYLUXEJ6MI14HzqxDqrLyhf6IbjAa2r3Dw== dependencies: - "@nomicfoundation/edr-darwin-arm64" "0.4.0" - "@nomicfoundation/edr-darwin-x64" "0.4.0" - "@nomicfoundation/edr-linux-arm64-gnu" "0.4.0" - "@nomicfoundation/edr-linux-arm64-musl" "0.4.0" - "@nomicfoundation/edr-linux-x64-gnu" "0.4.0" - "@nomicfoundation/edr-linux-x64-musl" "0.4.0" - "@nomicfoundation/edr-win32-x64-msvc" "0.4.0" + "@nomicfoundation/edr-darwin-arm64" "0.5.2" + "@nomicfoundation/edr-darwin-x64" "0.5.2" + "@nomicfoundation/edr-linux-arm64-gnu" "0.5.2" + "@nomicfoundation/edr-linux-arm64-musl" "0.5.2" + "@nomicfoundation/edr-linux-x64-gnu" "0.5.2" + "@nomicfoundation/edr-linux-x64-musl" "0.5.2" + "@nomicfoundation/edr-win32-x64-msvc" "0.5.2" "@nomicfoundation/ethereumjs-common@4.0.4": version "4.0.4" @@ -1315,6 +1315,20 @@ dependencies: poseidon-solidity "0.0.5" +"@zk-kit/lean-imt@^2.1.0": + version "2.1.0" + resolved "https://registry.yarnpkg.com/@zk-kit/lean-imt/-/lean-imt-2.1.0.tgz#ca876463a0249fc3de76b2f8821c7af31f94998a" + integrity sha512-RbG6QmTrurken7HzrJQouKiXKyGTpcoD+czQ1jvExRIA83k9w+SEsRdB7anPE8WoMKWAandDe09BzDCk6AirSw== + dependencies: + "@zk-kit/utils" "1.2.0" + +"@zk-kit/utils@1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@zk-kit/utils/-/utils-1.2.0.tgz#7f5dfadb9512f1a090639c912395a6684b560ba2" + integrity sha512-Ut9zfnlBVpopZG/s600Ds/FPSWXiPhO4q8949kmXTzwDXytjnvFbDZIFdWqE/lA7/NZjvykiTnnVwmanMxv2+w== + dependencies: + buffer "^6.0.3" + abbrev@1: version "1.1.1" resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" @@ -1556,6 +1570,11 @@ base-x@^3.0.2: dependencies: safe-buffer "^5.0.1" +base64-js@^1.3.1: + version "1.5.1" + resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" + integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== + bech32@1.1.4: version "1.1.4" resolved "https://registry.yarnpkg.com/bech32/-/bech32-1.1.4.tgz#e38c9f37bf179b8eb16ae3a772b40c356d4832e9" @@ -1675,6 +1694,14 @@ buffer-xor@^1.0.3: resolved "https://registry.yarnpkg.com/buffer-xor/-/buffer-xor-1.0.3.tgz#26e61ed1422fb70dd42e6e36729ed51d855fe8d9" integrity sha512-571s0T7nZWK6vB67HI5dyUF7wXiNcfaPPPTl6zYCNApANjIvYJTg7hlud/+cJpdAhS7dVzqMLmfhfHR3rAcOjQ== +buffer@^6.0.3: + version "6.0.3" + resolved "https://registry.yarnpkg.com/buffer/-/buffer-6.0.3.tgz#2ace578459cc8fbe2a70aaa8f52ee63b6a74c6c6" + integrity sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA== + dependencies: + base64-js "^1.3.1" + ieee754 "^1.2.1" + bytes@3.1.2: version "3.1.2" resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.2.tgz#8b0beeb98605adf1b128fa4386403c009e0221a5" @@ -1902,16 +1929,16 @@ command-line-usage@^6.1.0: table-layout "^1.0.2" typical "^5.2.0" -commander@3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/commander/-/commander-3.0.2.tgz#6837c3fb677ad9933d1cfba42dd14d5117d6b39e" - integrity sha512-Gar0ASD4BDyKC4hl4DwHqDrmvjoxWKZigVnAbn5H1owvm4CxCPdb0HQDehwNYMJpla5+M2tPmPARzhtYuwpHow== - commander@^10.0.0: version "10.0.1" resolved "https://registry.yarnpkg.com/commander/-/commander-10.0.1.tgz#881ee46b4f77d1c1dccc5823433aa39b022cbe06" integrity sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug== +commander@^8.1.0: + version "8.3.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-8.3.0.tgz#4837ea1b2da67b9c616a67afbb0fafee567bca66" + integrity sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww== + concat-map@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" @@ -2597,17 +2624,6 @@ fp-ts@^1.0.0: resolved "https://registry.yarnpkg.com/fp-ts/-/fp-ts-1.19.5.tgz#3da865e585dfa1fdfd51785417357ac50afc520a" integrity sha512-wDNqTimnzs8QqpldiId9OavWK2NptormjXnRJTQecNjzwfyp6P/8s/zG8e4h3ja3oqkKaY72UlTjQYt/1yXf9A== -fs-extra@^0.30.0: - version "0.30.0" - resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-0.30.0.tgz#f233ffcc08d4da7d432daa449776989db1df93f0" - integrity sha512-UvSPKyhMn6LEd/WpUaV9C9t3zATuqoqfWc3QdPhPLb58prN9tqYPlPWi8Krxi44loBoUzlobqZ3+8tGpxxSzwA== - dependencies: - graceful-fs "^4.1.2" - jsonfile "^2.1.0" - klaw "^1.0.0" - path-is-absolute "^1.0.0" - rimraf "^2.2.8" - fs-extra@^10.0.0: version "10.1.0" resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-10.1.0.tgz#02873cfbc4084dde127eaa5f9905eef2325d1abf" @@ -2869,7 +2885,7 @@ graceful-fs@4.2.10: resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.10.tgz#147d3a006da4ca3ce14728c7aefc287c367d7a6c" integrity sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA== -graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.1.9, graceful-fs@^4.2.0: +graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0: version "4.2.11" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== @@ -2942,14 +2958,14 @@ hardhat-gas-reporter@^2.2.0: sha1 "^1.1.1" viem "2.7.14" -hardhat@^2.19.2: - version "2.22.5" - resolved "https://registry.yarnpkg.com/hardhat/-/hardhat-2.22.5.tgz#7e1a4311fa9e34a1cfe337784eae06706f6469a5" - integrity sha512-9Zq+HonbXCSy6/a13GY1cgHglQRfh4qkzmj1tpPlhxJDwNVnhxlReV6K7hCWFKlOrV13EQwsdcD0rjcaQKWRZw== +hardhat@^2.22.0: + version "2.22.9" + resolved "https://registry.yarnpkg.com/hardhat/-/hardhat-2.22.9.tgz#d8f2720561dc60f5cc0ee80c82f9b1907fd61c88" + integrity sha512-sWiuI/yRdFUPfndIvL+2H18Vs2Gav0XacCFYY5msT5dHOWkhLxESJySIk9j83mXL31aXL8+UMA9OgViFLexklg== dependencies: "@ethersproject/abi" "^5.1.2" "@metamask/eth-sig-util" "^4.0.0" - "@nomicfoundation/edr" "^0.4.0" + "@nomicfoundation/edr" "^0.5.2" "@nomicfoundation/ethereumjs-common" "4.0.4" "@nomicfoundation/ethereumjs-tx" "5.0.4" "@nomicfoundation/ethereumjs-util" "9.0.4" @@ -2983,7 +2999,7 @@ hardhat@^2.19.2: raw-body "^2.4.1" resolve "1.17.0" semver "^6.3.0" - solc "0.7.3" + solc "0.8.26" source-map-support "^0.5.13" stacktrace-parser "^0.1.10" tsort "0.0.1" @@ -3105,6 +3121,11 @@ iconv-lite@0.4.24: dependencies: safer-buffer ">= 2.1.2 < 3" +ieee754@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" + integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== + ignore@^5.1.1, ignore@^5.2.0, ignore@^5.2.4, ignore@^5.3.1: version "5.3.1" resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.3.1.tgz#5073e554cd42c5b33b394375f538b8593e34d4ef" @@ -3308,13 +3329,6 @@ json-stable-stringify-without-jsonify@^1.0.1: resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" integrity sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw== -jsonfile@^2.1.0: - version "2.4.0" - resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-2.4.0.tgz#3736a2b428b87bbda0cc83b53fa3d633a35c2ae8" - integrity sha512-PKllAqbgLgxHaj8TElYymKCAgrASebJrWpTnEkOaTowt23VKXXN0sUeriJ+eh7y6ufb/CC5ap11pz71/cM0hUw== - optionalDependencies: - graceful-fs "^4.1.6" - jsonfile@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb" @@ -3357,13 +3371,6 @@ kind-of@^6.0.2: resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd" integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw== -klaw@^1.0.0: - version "1.3.1" - resolved "https://registry.yarnpkg.com/klaw/-/klaw-1.3.1.tgz#4088433b46b3b1ba259d78785d8e96f73ba02439" - integrity sha512-TED5xi9gGQjGpNnvRWknrwAB1eL5GciPfVFOt3Vk1OJCVDQbzuSfrF3hkUQKlsgKrG1F+0t5W0m+Fje1jIt8rw== - optionalDependencies: - graceful-fs "^4.1.9" - latest-version@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/latest-version/-/latest-version-7.0.0.tgz#843201591ea81a4d404932eeb61240fe04e9e5da" @@ -3904,6 +3911,11 @@ pluralize@^8.0.0: resolved "https://registry.yarnpkg.com/pluralize/-/pluralize-8.0.0.tgz#1a6fa16a38d12a1901e0320fa017051c539ce3b1" integrity sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA== +poseidon-lite@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/poseidon-lite/-/poseidon-lite-0.3.0.tgz#93c42f6f9b870f154f2722dfd686b909c4285765" + integrity sha512-ilJj4MIve4uBEG7SrtPqUUNkvpJ/pLVbndxa0WvebcQqeIhe+h72JR4g0EvwchUzm9sOQDlOjiDNmRAgxNZl4A== + poseidon-solidity@0.0.5, poseidon-solidity@^0.0.5: version "0.0.5" resolved "https://registry.yarnpkg.com/poseidon-solidity/-/poseidon-solidity-0.0.5.tgz#3f93e01cfe25f6d2f2fac49734fbb00961b84655" @@ -4063,7 +4075,7 @@ require-directory@^2.1.1: resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" integrity sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q== -require-from-string@^2.0.0, require-from-string@^2.0.2: +require-from-string@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-2.0.2.tgz#89a7fdd938261267318eafe14f9c32e598c36909" integrity sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw== @@ -4111,13 +4123,6 @@ reusify@^1.0.4: resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== -rimraf@^2.2.8: - version "2.7.1" - resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec" - integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w== - dependencies: - glob "^7.1.3" - rimraf@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" @@ -4308,18 +4313,16 @@ slice-ansi@^4.0.0: astral-regex "^2.0.0" is-fullwidth-code-point "^3.0.0" -solc@0.7.3: - version "0.7.3" - resolved "https://registry.yarnpkg.com/solc/-/solc-0.7.3.tgz#04646961bd867a744f63d2b4e3c0701ffdc7d78a" - integrity sha512-GAsWNAjGzIDg7VxzP6mPjdurby3IkGCjQcM8GFYZT6RyaoUZKmMU6Y7YwG+tFGhv7dwZ8rmR4iwFDrrD99JwqA== +solc@0.8.26: + version "0.8.26" + resolved "https://registry.yarnpkg.com/solc/-/solc-0.8.26.tgz#afc78078953f6ab3e727c338a2fefcd80dd5b01a" + integrity sha512-yiPQNVf5rBFHwN6SIf3TUUvVAFKcQqmSUFeq+fb6pNRCo0ZCgpYOZDi3BVoezCPIAcKrVYd/qXlBLUP9wVrZ9g== dependencies: command-exists "^1.2.8" - commander "3.0.2" + commander "^8.1.0" follow-redirects "^1.12.1" - fs-extra "^0.30.0" js-sha3 "0.8.0" memorystream "^0.3.1" - require-from-string "^2.0.0" semver "^5.5.0" tmp "0.0.33" From f58cdd0a6af756162f4a716ec05fd7e6801b4d8f Mon Sep 17 00:00:00 2001 From: Auryn Macmillan Date: Wed, 28 Aug 2024 20:51:24 -0400 Subject: [PATCH 05/32] fix: update comment --- packages/evm/contracts/Enclave.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/evm/contracts/Enclave.sol b/packages/evm/contracts/Enclave.sol index 8094fef3..b847bdef 100644 --- a/packages/evm/contracts/Enclave.sol +++ b/packages/evm/contracts/Enclave.sol @@ -239,7 +239,7 @@ contract Enclave is IEnclave, OwnableUpgradeable { bytes memory input; (input, success) = e3.inputValidator.validate(msg.sender, data); require(success, InvalidInput()); - // note: hash is divided by 10 ** 39 to make the hash smaller than the snark scalar field. + // note: hash is divided by 10 to make the hash smaller than the snark scalar field. // TODO: Not sure if this is a bad idea ¯\_(ツ)_/¯ uint256 inputHash = uint256( keccak256(abi.encode(input, inputCount[e3Id])) From 2b62c35abbcda9518a7c29b8efce74bf360f545a Mon Sep 17 00:00:00 2001 From: Auryn Macmillan Date: Wed, 28 Aug 2024 20:55:01 -0400 Subject: [PATCH 06/32] fix: explicitly set types for hash inputs --- packages/evm/test/Enclave.spec.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/evm/test/Enclave.spec.ts b/packages/evm/test/Enclave.spec.ts index 798471c6..d8a401bb 100644 --- a/packages/evm/test/Enclave.spec.ts +++ b/packages/evm/test/Enclave.spec.ts @@ -962,7 +962,7 @@ describe("Enclave", function () { const inputData = abiCoder.encode(["bytes"], ["0xaabbccddeeff"]); // Hash function used to compute the tree nodes. - const hash = (a, b) => poseidon2([a, b]); + const hash = (a: bigint, b: bigint) => poseidon2([a, b]); // To create an instance of a LeanIMT, you must provide the hash function. const tree = new LeanIMT(hash); From 04f81164537a550ada96d627ecd48d00dc29a313 Mon Sep 17 00:00:00 2001 From: Auryn Macmillan Date: Wed, 28 Aug 2024 21:31:31 -0400 Subject: [PATCH 07/32] fix: delete commented out code --- packages/evm/test/fixtures/Enclave.fixture.ts | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/packages/evm/test/fixtures/Enclave.fixture.ts b/packages/evm/test/fixtures/Enclave.fixture.ts index fb0acb2d..d7ef45ec 100644 --- a/packages/evm/test/fixtures/Enclave.fixture.ts +++ b/packages/evm/test/fixtures/Enclave.fixture.ts @@ -17,19 +17,11 @@ export async function deployEnclaveFixture({ const poseidonDeployment = await poseidonFactory.deploy(); const deployment = await ( - await ethers.getContractFactory( - "Enclave", - { - libraries: { - PoseidonT3: await poseidonDeployment.getAddress(), - }, + await ethers.getContractFactory("Enclave", { + libraries: { + PoseidonT3: await poseidonDeployment.getAddress(), }, - // , { - // libraries: { - // InternalLeanIMT: await imtDeployment.getAddress(), - // }, - // } - ) + }) ).deploy(owner, registry, maxDuration); return Enclave__factory.connect(await deployment.getAddress(), owner); From 4b604238fafc3454d4d4e1d8c742035997dd7c44 Mon Sep 17 00:00:00 2001 From: Auryn Macmillan Date: Wed, 28 Aug 2024 22:01:37 -0400 Subject: [PATCH 08/32] feat: add `getInputRoot()` to `IEnclave.sol` --- packages/evm/contracts/Enclave.sol | 4 ++++ packages/evm/contracts/interfaces/IEnclave.sol | 6 ++++++ 2 files changed, 10 insertions(+) diff --git a/packages/evm/contracts/Enclave.sol b/packages/evm/contracts/Enclave.sol index b847bdef..77ee457a 100644 --- a/packages/evm/contracts/Enclave.sol +++ b/packages/evm/contracts/Enclave.sol @@ -388,6 +388,10 @@ contract Enclave is IEnclave, OwnableUpgradeable { } function getInputRoot(uint256 e3Id) public view returns (uint256) { + require( + e3s[e3Id].computationModule != IComputationModule(address(0)), + E3DoesNotExist(e3Id) + ); return InternalLeanIMT._root(inputs[e3Id]); } } diff --git a/packages/evm/contracts/interfaces/IEnclave.sol b/packages/evm/contracts/interfaces/IEnclave.sol index e454bd4f..aa4463d6 100644 --- a/packages/evm/contracts/interfaces/IEnclave.sol +++ b/packages/evm/contracts/interfaces/IEnclave.sol @@ -176,4 +176,10 @@ interface IEnclave { /// @param e3Id ID of the E3. /// @return e3 The struct representing the requested E3. function getE3(uint256 e3Id) external view returns (E3 memory e3); + + /// @notice This function returns root of the input merkle tree for a given E3. + /// @dev This function MUST revert if the E3 does not exist. + /// @param e3Id ID of the E3. + /// @return root The root of the input merkle tree. + function getInputRoot(uint256 e3Id) external view returns (uint256 root); } From 5bd660ac1f1fdf9724f73ca8435cb716c2a24c88 Mon Sep 17 00:00:00 2001 From: Auryn Macmillan Date: Wed, 28 Aug 2024 22:21:10 -0400 Subject: [PATCH 09/32] fix: swap computationModule for outputVerifier --- packages/evm/contracts/Enclave.sol | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/evm/contracts/Enclave.sol b/packages/evm/contracts/Enclave.sol index 77ee457a..b6e08aa3 100644 --- a/packages/evm/contracts/Enclave.sol +++ b/packages/evm/contracts/Enclave.sol @@ -268,7 +268,7 @@ contract Enclave is IEnclave, OwnableUpgradeable { CiphertextOutputAlreadyPublished(e3Id) ); bytes memory output; - (output, success) = e3.outputVerifier.verify(e3Id, data); + (output, success) = e3.computationModule.verify(e3Id, data); require(success, InvalidOutput(output)); e3s[e3Id].ciphertextOutput = output; @@ -291,7 +291,7 @@ contract Enclave is IEnclave, OwnableUpgradeable { PlaintextOutputAlreadyPublished(e3Id) ); bytes memory output; - (output, success) = e3.computationModule.verify(e3Id, data); + (output, success) = e3.outputVerifier.verify(e3Id, data); require(success, InvalidOutput(output)); e3s[e3Id].plaintextOutput = output; From 627d0f8bc1b99bc2a0389820a4b6f0901fdd7e15 Mon Sep 17 00:00:00 2001 From: Auryn Macmillan Date: Thu, 29 Aug 2024 08:40:17 -0400 Subject: [PATCH 10/32] feat: replace keccak256 with Poseidon hash --- packages/evm/contracts/Enclave.sol | 12 ++++---- packages/evm/test/Enclave.spec.ts | 44 ++++++++++++++++-------------- 2 files changed, 29 insertions(+), 27 deletions(-) diff --git a/packages/evm/contracts/Enclave.sol b/packages/evm/contracts/Enclave.sol index b6e08aa3..4e25a487 100644 --- a/packages/evm/contracts/Enclave.sol +++ b/packages/evm/contracts/Enclave.sol @@ -15,7 +15,8 @@ import { } from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; import { InternalLeanIMT, - LeanIMTData + LeanIMTData, + PoseidonT3 } from "@zk-kit/lean-imt.sol/InternalLeanIMT.sol"; contract Enclave is IEnclave, OwnableUpgradeable { @@ -239,11 +240,10 @@ contract Enclave is IEnclave, OwnableUpgradeable { bytes memory input; (input, success) = e3.inputValidator.validate(msg.sender, data); require(success, InvalidInput()); - // note: hash is divided by 10 to make the hash smaller than the snark scalar field. - // TODO: Not sure if this is a bad idea ¯\_(ツ)_/¯ - uint256 inputHash = uint256( - keccak256(abi.encode(input, inputCount[e3Id])) - ) / 10; + uint256 inputHash = PoseidonT3.hash( + [uint256(keccak256(abi.encode(input))), inputCount[e3Id]] + ); + inputCount[e3Id]++; inputs[e3Id]._insert(inputHash); diff --git a/packages/evm/test/Enclave.spec.ts b/packages/evm/test/Enclave.spec.ts index d8a401bb..783bdd2c 100644 --- a/packages/evm/test/Enclave.spec.ts +++ b/packages/evm/test/Enclave.spec.ts @@ -23,6 +23,9 @@ const AddressSix = "0x0000000000000000000000000000000000000006"; const FilterFail = AddressTwo; const FilterOkay = AddressSix; +// Hash function used to compute the tree nodes. +const hash = (a: bigint, b: bigint) => poseidon2([a, b]); + describe("Enclave", function () { async function setup() { const [owner, notTheOwner] = await ethers.getSigners(); @@ -961,9 +964,6 @@ describe("Enclave", function () { const { enclave, request } = await loadFixture(setup); const inputData = abiCoder.encode(["bytes"], ["0xaabbccddeeff"]); - // Hash function used to compute the tree nodes. - const hash = (a: bigint, b: bigint) => poseidon2([a, b]); - // To create an instance of a LeanIMT, you must provide the hash function. const tree = new LeanIMT(hash); @@ -984,14 +984,14 @@ describe("Enclave", function () { await enclave.activate(e3Id); tree.insert( - BigInt( - ethers.keccak256( - ethers.AbiCoder.defaultAbiCoder().encode( - ["bytes", "uint256"], - [inputData, 0], + hash( + BigInt( + ethers.keccak256( + ethers.AbiCoder.defaultAbiCoder().encode(["bytes"], [inputData]), ), ), - ) / BigInt(10), + BigInt(0), + ), ); await enclave.publishInput(e3Id, inputData); @@ -999,14 +999,17 @@ describe("Enclave", function () { const secondInputData = abiCoder.encode(["bytes"], ["0x112233445566"]); tree.insert( - BigInt( - ethers.keccak256( - ethers.AbiCoder.defaultAbiCoder().encode( - ["bytes", "uint256"], - [secondInputData, 1], + hash( + BigInt( + ethers.keccak256( + ethers.AbiCoder.defaultAbiCoder().encode( + ["bytes"], + [secondInputData], + ), ), ), - ) / BigInt(10), + BigInt(1), + ), ); await enclave.publishInput(e3Id, secondInputData); expect(await enclave.getInputRoot(e3Id)).to.equal(tree.root); @@ -1030,15 +1033,14 @@ describe("Enclave", function () { const inputData = abiCoder.encode(["bytes"], ["0xaabbccddeeff"]); await enclave.activate(e3Id); - const expectedHash = + const expectedHash = hash( BigInt( ethers.keccak256( - ethers.AbiCoder.defaultAbiCoder().encode( - ["bytes", "uint256"], - [inputData, 0], - ), + ethers.AbiCoder.defaultAbiCoder().encode(["bytes"], [inputData]), ), - ) / BigInt(10); + ), + BigInt(0), + ); await expect(enclave.publishInput(e3Id, inputData)) .to.emit(enclave, "InputPublished") From 490431660d62140b89fdf18565a49ad36910a46d Mon Sep 17 00:00:00 2001 From: Auryn Macmillan Date: Thu, 29 Aug 2024 18:15:08 -0400 Subject: [PATCH 11/32] fix: remove redundant abi encoding --- packages/evm/contracts/Enclave.sol | 2 +- packages/evm/test/Enclave.spec.ts | 25 ++----------------------- 2 files changed, 3 insertions(+), 24 deletions(-) diff --git a/packages/evm/contracts/Enclave.sol b/packages/evm/contracts/Enclave.sol index 4e25a487..20a2620d 100644 --- a/packages/evm/contracts/Enclave.sol +++ b/packages/evm/contracts/Enclave.sol @@ -241,7 +241,7 @@ contract Enclave is IEnclave, OwnableUpgradeable { (input, success) = e3.inputValidator.validate(msg.sender, data); require(success, InvalidInput()); uint256 inputHash = PoseidonT3.hash( - [uint256(keccak256(abi.encode(input))), inputCount[e3Id]] + [uint256(keccak256(input)), inputCount[e3Id]] ); inputCount[e3Id]++; diff --git a/packages/evm/test/Enclave.spec.ts b/packages/evm/test/Enclave.spec.ts index 783bdd2c..da574822 100644 --- a/packages/evm/test/Enclave.spec.ts +++ b/packages/evm/test/Enclave.spec.ts @@ -983,34 +983,13 @@ describe("Enclave", function () { await enclave.activate(e3Id); - tree.insert( - hash( - BigInt( - ethers.keccak256( - ethers.AbiCoder.defaultAbiCoder().encode(["bytes"], [inputData]), - ), - ), - BigInt(0), - ), - ); + tree.insert(hash(BigInt(ethers.keccak256(inputData)), BigInt(0))); await enclave.publishInput(e3Id, inputData); expect(await enclave.getInputRoot(e3Id)).to.equal(tree.root); const secondInputData = abiCoder.encode(["bytes"], ["0x112233445566"]); - tree.insert( - hash( - BigInt( - ethers.keccak256( - ethers.AbiCoder.defaultAbiCoder().encode( - ["bytes"], - [secondInputData], - ), - ), - ), - BigInt(1), - ), - ); + tree.insert(hash(BigInt(ethers.keccak256(secondInputData)), BigInt(1))); await enclave.publishInput(e3Id, secondInputData); expect(await enclave.getInputRoot(e3Id)).to.equal(tree.root); }); From e1bee1673ac2f48b673ceb46cd095a1212d007ee Mon Sep 17 00:00:00 2001 From: Auryn Macmillan Date: Thu, 29 Aug 2024 18:16:10 -0400 Subject: [PATCH 12/32] fix: test that I broke in the last commit. --- packages/evm/test/Enclave.spec.ts | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/packages/evm/test/Enclave.spec.ts b/packages/evm/test/Enclave.spec.ts index da574822..67a94184 100644 --- a/packages/evm/test/Enclave.spec.ts +++ b/packages/evm/test/Enclave.spec.ts @@ -1012,14 +1012,7 @@ describe("Enclave", function () { const inputData = abiCoder.encode(["bytes"], ["0xaabbccddeeff"]); await enclave.activate(e3Id); - const expectedHash = hash( - BigInt( - ethers.keccak256( - ethers.AbiCoder.defaultAbiCoder().encode(["bytes"], [inputData]), - ), - ), - BigInt(0), - ); + const expectedHash = hash(BigInt(ethers.keccak256(inputData)), BigInt(0)); await expect(enclave.publishInput(e3Id, inputData)) .to.emit(enclave, "InputPublished") From 457890551352e20a25b8aefb7ed87739fd334732 Mon Sep 17 00:00:00 2001 From: Auryn Macmillan Date: Mon, 2 Sep 2024 15:27:31 -0400 Subject: [PATCH 13/32] fix: broken test --- packages/evm/test/Enclave.spec.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/evm/test/Enclave.spec.ts b/packages/evm/test/Enclave.spec.ts index 67a94184..a54ebb3f 100644 --- a/packages/evm/test/Enclave.spec.ts +++ b/packages/evm/test/Enclave.spec.ts @@ -684,10 +684,10 @@ describe("Enclave", function () { }); it("reverts if E3 start has expired", async function () { const { enclave, request } = await loadFixture(setup); - const startTime = [await time.latest(), (await time.latest()) + 1] as [ - number, - number, - ]; + const startTime = [ + (await time.latest()) + 1, + (await time.latest()) + 1000, + ] as [number, number]; await enclave.request( request.filter, @@ -701,7 +701,7 @@ describe("Enclave", function () { { value: 10 }, ); - mine(1, { interval: 1000 }); + await mine(2, { interval: 2000 }); await expect(enclave.activate(0)).to.be.revertedWithCustomError( enclave, From 6d09a1b27c47fb970bb5dd2b60f44e8a58a759a5 Mon Sep 17 00:00:00 2001 From: Auryn Macmillan Date: Mon, 2 Sep 2024 15:52:35 -0400 Subject: [PATCH 14/32] fix: appease the linter --- packages/evm/contracts/Enclave.sol | 8 ++++---- packages/evm/contracts/test/MockCyphernodeRegistry.sol | 2 ++ packages/evm/test/Enclave.spec.ts | 8 ++++---- packages/evm/test/fixtures/Enclave.fixture.ts | 1 - 4 files changed, 10 insertions(+), 9 deletions(-) diff --git a/packages/evm/contracts/Enclave.sol b/packages/evm/contracts/Enclave.sol index 20a2620d..46fae64b 100644 --- a/packages/evm/contracts/Enclave.sol +++ b/packages/evm/contracts/Enclave.sol @@ -54,7 +54,7 @@ contract Enclave is IEnclave, OwnableUpgradeable { mapping(uint256 e3Id => LeanIMTData imt) public inputs; // Mapping counting the number of inputs for each E3. - mapping(uint256 e3Id => uint256) public inputCount; + mapping(uint256 e3Id => uint256 inputCount) public inputCounts; //////////////////////////////////////////////////////////// // // @@ -241,13 +241,13 @@ contract Enclave is IEnclave, OwnableUpgradeable { (input, success) = e3.inputValidator.validate(msg.sender, data); require(success, InvalidInput()); uint256 inputHash = PoseidonT3.hash( - [uint256(keccak256(input)), inputCount[e3Id]] + [uint256(keccak256(input)), inputCounts[e3Id]] ); - inputCount[e3Id]++; + inputCounts[e3Id]++; inputs[e3Id]._insert(inputHash); - emit InputPublished(e3Id, input, inputHash, inputCount[e3Id] - 1); + emit InputPublished(e3Id, input, inputHash, inputCounts[e3Id] - 1); } function publishCiphertextOutput( diff --git a/packages/evm/contracts/test/MockCyphernodeRegistry.sol b/packages/evm/contracts/test/MockCyphernodeRegistry.sol index de4e95f3..ad7d81b5 100644 --- a/packages/evm/contracts/test/MockCyphernodeRegistry.sol +++ b/packages/evm/contracts/test/MockCyphernodeRegistry.sol @@ -16,6 +16,7 @@ contract MockCyphernodeRegistry is ICyphernodeRegistry { } } + // solhint-disable no-empty-blocks function publishCommittee( uint256, bytes calldata, @@ -50,6 +51,7 @@ contract MockCyphernodeRegistryEmptyKey is ICyphernodeRegistry { } } + // solhint-disable no-empty-blocks function publishCommittee( uint256, bytes calldata, diff --git a/packages/evm/test/Enclave.spec.ts b/packages/evm/test/Enclave.spec.ts index a54ebb3f..fbd2b251 100644 --- a/packages/evm/test/Enclave.spec.ts +++ b/packages/evm/test/Enclave.spec.ts @@ -751,7 +751,7 @@ describe("Enclave", function () { { value: 10 }, ); - mine(1, { interval: 1000 }); + await mine(1, { interval: 1000 }); await expect(enclave.activate(0)).to.be.revertedWithCustomError( enclave, @@ -1022,7 +1022,7 @@ describe("Enclave", function () { describe("publishCiphertextOutput()", function () { it("reverts if E3 does not exist", async function () { - const { enclave, request } = await loadFixture(setup); + const { enclave } = await loadFixture(setup); await expect(enclave.publishCiphertextOutput(0, "0x")) .to.be.revertedWithCustomError(enclave, "E3DoesNotExist") @@ -1184,7 +1184,7 @@ describe("Enclave", function () { describe("publishPlaintextOutput()", function () { it("reverts if E3 does not exist", async function () { - const { enclave, request } = await loadFixture(setup); + const { enclave } = await loadFixture(setup); const e3Id = 0; await expect(enclave.publishPlaintextOutput(e3Id, "0x")) @@ -1341,7 +1341,7 @@ describe("Enclave", function () { await enclave.activate(e3Id); await mine(2, { interval: request.duration }); await enclave.publishCiphertextOutput(e3Id, "0x1337"); - expect(await enclave.publishPlaintextOutput(e3Id, "0x1337")) + await expect(enclave.publishPlaintextOutput(e3Id, "0x1337")) .to.emit(enclave, "PlaintextOutputPublished") .withArgs(e3Id, "0x1337"); }); diff --git a/packages/evm/test/fixtures/Enclave.fixture.ts b/packages/evm/test/fixtures/Enclave.fixture.ts index d7ef45ec..aee379e0 100644 --- a/packages/evm/test/fixtures/Enclave.fixture.ts +++ b/packages/evm/test/fixtures/Enclave.fixture.ts @@ -1,6 +1,5 @@ import { SignerWithAddress } from "@nomicfoundation/hardhat-ethers/signers"; import { ethers } from "hardhat"; -import { PoseidonT3, proxy } from "poseidon-solidity"; import { Enclave__factory } from "../../types/factories/contracts/Enclave__factory"; From f298486d19c93e38f118b7354bb718e5960d6ea7 Mon Sep 17 00:00:00 2001 From: Auryn Macmillan Date: Wed, 4 Sep 2024 12:26:38 -0400 Subject: [PATCH 15/32] add: first pass at renaming things --- README.md | 91 +++++- packages/evm/contracts/Enclave.sol | 116 ++++---- ...deRegistry.sol => ICiphernodeRegistry.sol} | 12 +- ...ecutionModule.sol => IComputeProvider.sol} | 6 +- packages/evm/contracts/interfaces/IE3.sol | 12 +- ...{IComputationModule.sol => IE3Program.sol} | 2 +- .../evm/contracts/interfaces/IEnclave.sol | 50 ++-- ...able.sol => CiphernodeRegistryOwnable.sol} | 24 +- .../registry/NaiveRegistryFilter.sol | 4 +- ...egistry.sol => MockCiphernodeRegistry.sol} | 10 +- ...tionModule.sol => MockComputeProvider.sol} | 6 +- ...omputationModule.sol => MockE3Program.sol} | 7 +- .../evm/contracts/test/MockRegistryFilter.sol | 2 +- packages/evm/tasks/enclave.ts | 2 +- packages/evm/test/Enclave.spec.ts | 281 +++++++++--------- .../MockCiphernodeRegistry.fixture.ts | 15 + .../fixtures/MockComputationModule.fixture.ts | 11 - .../fixtures/MockComputeProvider.fixture.ts | 11 + .../MockCyphernodeRegistry.fixture.ts | 15 - .../test/fixtures/MockE3Program.fixture.ts | 11 + .../fixtures/MockExecutionModule.fixture.ts | 11 - 21 files changed, 382 insertions(+), 317 deletions(-) rename packages/evm/contracts/interfaces/{ICyphernodeRegistry.sol => ICiphernodeRegistry.sol} (88%) rename packages/evm/contracts/interfaces/{IExecutionModule.sol => IComputeProvider.sol} (67%) rename packages/evm/contracts/interfaces/{IComputationModule.sol => IE3Program.sol} (96%) rename packages/evm/contracts/registry/{CyphernodeRegistryOwnable.sol => CiphernodeRegistryOwnable.sol} (87%) rename packages/evm/contracts/test/{MockCyphernodeRegistry.sol => MockCiphernodeRegistry.sol} (81%) rename packages/evm/contracts/test/{MockExecutionModule.sol => MockComputeProvider.sol} (80%) rename packages/evm/contracts/test/{MockComputationModule.sol => MockE3Program.sol} (80%) create mode 100644 packages/evm/test/fixtures/MockCiphernodeRegistry.fixture.ts delete mode 100644 packages/evm/test/fixtures/MockComputationModule.fixture.ts create mode 100644 packages/evm/test/fixtures/MockComputeProvider.fixture.ts delete mode 100644 packages/evm/test/fixtures/MockCyphernodeRegistry.fixture.ts create mode 100644 packages/evm/test/fixtures/MockE3Program.fixture.ts delete mode 100644 packages/evm/test/fixtures/MockExecutionModule.fixture.ts diff --git a/README.md b/README.md index f5c23b79..c7025823 100644 --- a/README.md +++ b/README.md @@ -22,8 +22,8 @@ sequenceDiagram participant Enclave participant Ciphernode Registry participant Ciphernodes - participant Computation Module - participant Execution Module + participant E3 Program + participant Compute Provider loop Each computation request Requester ->> Enclave: Request computation @@ -39,16 +39,16 @@ sequenceDiagram loop Each input Data Providers ->> Enclave: Publish inputs - Enclave ->> Computation Module: Validate inputs - activate Computation Module - Computation Module -->> Enclave: 👌 - deactivate Computation Module + Enclave ->> E3 Program: Validate inputs + activate E3 Program + E3 Program -->> Enclave: 👌 + deactivate E3 Program end - Enclave ->> Execution Module: Request execution - activate Execution Module - Execution Module -->> Enclave: Publish ciphertext output - deactivate Execution Module + Enclave ->> Compute Provider: Request execution + activate Compute Provider + Compute Provider -->> Enclave: Publish ciphertext output + deactivate Compute Provider Enclave -->> Ciphernodes: Request plaintext output activate Ciphernodes @@ -62,6 +62,77 @@ sequenceDiagram ``` +--- + +```mermaid +sequenceDiagram + participant Owner + participant Enclave + participant CiphernodeRegistry + participant E3Program + participant ComputeProvider + + Owner->>Enclave: deploy(owner, ciphernodeRegistry, maxDuration) + Enclave->>Enclave: initialize() + Owner->>Enclave: enableE3Program() + Owner->>Enclave: enableComputeProvider() + + User->>Enclave: request(parameters) + Enclave->>E3Program: validate(computationParams) + E3Program-->>Enclave: inputValidator + Enclave->>ComputeProvider: validate(emParams) + ComputeProvider-->>Enclave: outputVerifier + Enclave->>CiphernodeRegistry: requestCommittee(e3Id, filter, threshold) + CiphernodeRegistry-->>Enclave: success + Enclave-->>User: e3Id, E3 struct +``` + +--- + +```mermaid +sequenceDiagram + participant User + participant Enclave + participant CiphernodeRegistry + participant E3Program + participant ComputeProvider + participant InputValidator + participant OutputVerifier + + User->>Enclave: request(parameters) + Enclave->>E3Program: validate(computationParams) + E3Program-->>Enclave: inputValidator + Enclave->>ComputeProvider: validate(emParams) + ComputeProvider-->>Enclave: outputVerifier + Enclave->>CiphernodeRegistry: requestCommittee(e3Id, filter, threshold) + CiphernodeRegistry-->>Enclave: success + Enclave-->>User: e3Id, E3 struct + + User->>Enclave: activate(e3Id) + Enclave->>CiphernodeRegistry: committeePublicKey(e3Id) + CiphernodeRegistry-->>Enclave: publicKey + Enclave->>Enclave: Set expiration and committeePublicKey + Enclave-->>User: success + + User->>Enclave: publishInput(e3Id, data) + Enclave->>InputValidator: validate(msg.sender, data) + InputValidator-->>Enclave: input, success + Enclave->>Enclave: Store input + Enclave-->>User: success + + User->>Enclave: publishCiphertextOutput(e3Id, data) + Enclave->>OutputVerifier: verify(e3Id, data) + OutputVerifier-->>Enclave: output, success + Enclave->>Enclave: Store ciphertextOutput + Enclave-->>User: success + + User->>Enclave: publishPlaintextOutput(e3Id, data) + Enclave->>E3Program: verify(e3Id, data) + E3Program-->>Enclave: output, success + Enclave->>Enclave: Store plaintextOutput + Enclave-->>User: success +``` + ## Security and Liability This repo is provided WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. diff --git a/packages/evm/contracts/Enclave.sol b/packages/evm/contracts/Enclave.sol index 46fae64b..2036c16a 100644 --- a/packages/evm/contracts/Enclave.sol +++ b/packages/evm/contracts/Enclave.sol @@ -4,10 +4,10 @@ pragma solidity >=0.8.26; import { IEnclave, E3, - IComputationModule, - IExecutionModule + IE3Program, + IComputeProvider } from "./interfaces/IEnclave.sol"; -import { ICyphernodeRegistry } from "./interfaces/ICyphernodeRegistry.sol"; +import { ICiphernodeRegistry } from "./interfaces/ICiphernodeRegistry.sol"; import { IInputValidator } from "./interfaces/IInputValidator.sol"; import { IOutputVerifier } from "./interfaces/IOutputVerifier.sol"; import { @@ -28,24 +28,24 @@ contract Enclave is IEnclave, OwnableUpgradeable { // // //////////////////////////////////////////////////////////// - ICyphernodeRegistry public cyphernodeRegistry; // address of the Cyphernode registry. + ICiphernodeRegistry public ciphernodeRegistry; // address of the Ciphernode registry. uint256 public maxDuration; // maximum duration of a computation in seconds. uint256 public nexte3Id; // ID of the next E3. uint256 public requests; // total number of requests made to Enclave. - // TODO: should computation and execution modules be explicitly allowed? + // TODO: should computation and compute providers be explicitly allowed? // My intuition is that an allowlist is required since they impose slashing conditions. // But perhaps this is one place where node pools might be utilized, allowing nodes to // opt in to being selected for specific computations, along with the corresponding slashing conditions. // This would reduce the governance overhead for Enclave. - // Mapping of allowed computation modules. - mapping(IComputationModule computationModule => bool allowed) + // Mapping of allowed E3 Programs. + mapping(IE3Program computationModule => bool allowed) public computationModules; - // Mapping of allowed execution modules. - mapping(IExecutionModule executionModule => bool allowed) - public executionModules; + // Mapping of allowed compute providers. + mapping(IComputeProvider computeProvider => bool allowed) + public computeProviders; // Mapping of E3s. mapping(uint256 e3Id => E3 e3) public e3s; @@ -63,7 +63,7 @@ contract Enclave is IEnclave, OwnableUpgradeable { //////////////////////////////////////////////////////////// error CommitteeSelectionFailed(); - error ComputationModuleNotAllowed(IComputationModule computationModule); + error E3ProgramNotAllowed(IE3Program computationModule); error E3AlreadyActivated(uint256 e3Id); error E3Expired(); error E3NotActivated(uint256 e3Id); @@ -74,8 +74,8 @@ contract Enclave is IEnclave, OwnableUpgradeable { error InputDeadlinePassed(uint256 e3Id, uint256 expiration); error InputDeadlineNotPassed(uint256 e3Id, uint256 expiration); error InvalidComputation(); - error InvalidExecutionModuleSetup(); - error InvalidCyphernodeRegistry(ICyphernodeRegistry cyphernodeRegistry); + error InvalidComputeProviderSetup(); + error InvalidCiphernodeRegistry(ICiphernodeRegistry ciphernodeRegistry); error InvalidInput(); error InvalidDuration(uint256 duration); error InvalidOutput(bytes output); @@ -96,22 +96,22 @@ contract Enclave is IEnclave, OwnableUpgradeable { /// @param _maxDuration The maximum duration of a computation in seconds constructor( address _owner, - ICyphernodeRegistry _cyphernodeRegistry, + ICiphernodeRegistry _ciphernodeRegistry, uint256 _maxDuration ) { - initialize(_owner, _cyphernodeRegistry, _maxDuration); + initialize(_owner, _ciphernodeRegistry, _maxDuration); } /// @param _owner The owner of this contract /// @param _maxDuration The maximum duration of a computation in seconds function initialize( address _owner, - ICyphernodeRegistry _cyphernodeRegistry, + ICiphernodeRegistry _ciphernodeRegistry, uint256 _maxDuration ) public initializer { __Ownable_init(msg.sender); setMaxDuration(_maxDuration); - setCyphernodeRegistry(_cyphernodeRegistry); + setCiphernodeRegistry(_ciphernodeRegistry); if (_owner != owner()) transferOwnership(_owner); } @@ -126,13 +126,13 @@ contract Enclave is IEnclave, OwnableUpgradeable { uint32[2] calldata threshold, uint256[2] calldata startWindow, uint256 duration, - IComputationModule computationModule, + IE3Program computationModule, bytes memory computationParams, - IExecutionModule executionModule, + IComputeProvider computeProvider, bytes memory emParams ) external payable returns (uint256 e3Id, E3 memory e3) { // TODO: allow for other payment methods or only native tokens? - // TODO: should payment checks be somewhere else? Perhaps in the computation module or cyphernode registry? + // TODO: should payment checks be somewhere else? Perhaps in the E3 Program or ciphernode registry? require(msg.value > 0, PaymentRequired(msg.value)); require( threshold[1] >= threshold[0] && threshold[0] > 0, @@ -150,11 +150,11 @@ contract Enclave is IEnclave, OwnableUpgradeable { ); require( computationModules[computationModule], - ComputationModuleNotAllowed(computationModule) + E3ProgramNotAllowed(computationModule) ); require( - executionModules[executionModule], - ModuleNotEnabled(address(executionModule)) + computeProviders[computeProvider], + ModuleNotEnabled(address(computeProvider)) ); // TODO: should IDs be incremental or produced deterministically? @@ -166,12 +166,12 @@ contract Enclave is IEnclave, OwnableUpgradeable { ); require(address(inputValidator) != address(0), InvalidComputation()); - // TODO: validate that the requested computation can be performed by the given execution module. - // Perhaps the execution module should be returned by the computation module? - IOutputVerifier outputVerifier = executionModule.validate(emParams); + // TODO: validate that the requested computation can be performed by the given compute provider. + // Perhaps the compute provider should be returned by the E3 Program? + IOutputVerifier outputVerifier = computeProvider.validate(emParams); require( address(outputVerifier) != address(0), - InvalidExecutionModuleSetup() + InvalidComputeProviderSetup() ); e3 = E3({ @@ -180,7 +180,7 @@ contract Enclave is IEnclave, OwnableUpgradeable { duration: duration, expiration: 0, computationModule: computationModule, - executionModule: executionModule, + computeProvider: computeProvider, inputValidator: inputValidator, outputVerifier: outputVerifier, committeePublicKey: hex"", @@ -190,7 +190,7 @@ contract Enclave is IEnclave, OwnableUpgradeable { e3s[e3Id] = e3; require( - cyphernodeRegistry.requestCommittee(e3Id, filter, threshold), + ciphernodeRegistry.requestCommittee(e3Id, filter, threshold), CommitteeSelectionFailed() ); @@ -199,7 +199,7 @@ contract Enclave is IEnclave, OwnableUpgradeable { e3s[e3Id], filter, computationModule, - executionModule + computeProvider ); } @@ -212,7 +212,7 @@ contract Enclave is IEnclave, OwnableUpgradeable { // TODO: handle what happens to the payment if the start window has passed. require(e3.startWindow[1] >= block.timestamp, E3Expired()); - bytes memory publicKey = cyphernodeRegistry.committeePublicKey(e3Id); + bytes memory publicKey = ciphernodeRegistry.committeePublicKey(e3Id); // Note: This check feels weird require(publicKey.length > 0, CommitteeSelectionFailed()); @@ -312,21 +312,21 @@ contract Enclave is IEnclave, OwnableUpgradeable { emit MaxDurationSet(_maxDuration); } - function setCyphernodeRegistry( - ICyphernodeRegistry _cyphernodeRegistry + function setCiphernodeRegistry( + ICiphernodeRegistry _ciphernodeRegistry ) public onlyOwner returns (bool success) { require( - address(_cyphernodeRegistry) != address(0) && - _cyphernodeRegistry != cyphernodeRegistry, - InvalidCyphernodeRegistry(_cyphernodeRegistry) + address(_ciphernodeRegistry) != address(0) && + _ciphernodeRegistry != ciphernodeRegistry, + InvalidCiphernodeRegistry(_ciphernodeRegistry) ); - cyphernodeRegistry = _cyphernodeRegistry; + ciphernodeRegistry = _ciphernodeRegistry; success = true; - emit CyphernodeRegistrySet(address(_cyphernodeRegistry)); + emit CiphernodeRegistrySet(address(_ciphernodeRegistry)); } - function enableComputationModule( - IComputationModule computationModule + function enableE3Program( + IE3Program computationModule ) public onlyOwner returns (bool success) { require( !computationModules[computationModule], @@ -334,23 +334,23 @@ contract Enclave is IEnclave, OwnableUpgradeable { ); computationModules[computationModule] = true; success = true; - emit ComputationModuleEnabled(computationModule); + emit E3ProgramEnabled(computationModule); } - function enableExecutionModule( - IExecutionModule executionModule + function enableComputeProvider( + IComputeProvider computeProvider ) public onlyOwner returns (bool success) { require( - !executionModules[executionModule], - ModuleAlreadyEnabled(address(executionModule)) + !computeProviders[computeProvider], + ModuleAlreadyEnabled(address(computeProvider)) ); - executionModules[executionModule] = true; + computeProviders[computeProvider] = true; success = true; - emit ExecutionModuleEnabled(executionModule); + emit ComputeProviderEnabled(computeProvider); } - function disableComputationModule( - IComputationModule computationModule + function disableE3Program( + IE3Program computationModule ) public onlyOwner returns (bool success) { require( computationModules[computationModule], @@ -358,19 +358,19 @@ contract Enclave is IEnclave, OwnableUpgradeable { ); delete computationModules[computationModule]; success = true; - emit ComputationModuleDisabled(computationModule); + emit E3ProgramDisabled(computationModule); } - function disableExecutionModule( - IExecutionModule executionModule + function disableComputeProvider( + IComputeProvider computeProvider ) public onlyOwner returns (bool success) { require( - executionModules[executionModule], - ModuleNotEnabled(address(executionModule)) + computeProviders[computeProvider], + ModuleNotEnabled(address(computeProvider)) ); - delete executionModules[executionModule]; + delete computeProviders[computeProvider]; success = true; - emit ExecutionModuleDisabled(executionModule); + emit ComputeProviderDisabled(computeProvider); } //////////////////////////////////////////////////////////// @@ -382,14 +382,14 @@ contract Enclave is IEnclave, OwnableUpgradeable { function getE3(uint256 e3Id) public view returns (E3 memory e3) { e3 = e3s[e3Id]; require( - e3.computationModule != IComputationModule(address(0)), + e3.computationModule != IE3Program(address(0)), E3DoesNotExist(e3Id) ); } function getInputRoot(uint256 e3Id) public view returns (uint256) { require( - e3s[e3Id].computationModule != IComputationModule(address(0)), + e3s[e3Id].computationModule != IE3Program(address(0)), E3DoesNotExist(e3Id) ); return InternalLeanIMT._root(inputs[e3Id]); diff --git a/packages/evm/contracts/interfaces/ICyphernodeRegistry.sol b/packages/evm/contracts/interfaces/ICiphernodeRegistry.sol similarity index 88% rename from packages/evm/contracts/interfaces/ICyphernodeRegistry.sol rename to packages/evm/contracts/interfaces/ICiphernodeRegistry.sol index 444fff7c..c9aaf984 100644 --- a/packages/evm/contracts/interfaces/ICyphernodeRegistry.sol +++ b/packages/evm/contracts/interfaces/ICiphernodeRegistry.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: LGPL-3.0-only pragma solidity >=0.8.26; -interface ICyphernodeRegistry { +interface ICiphernodeRegistry { /// @notice This event MUST be emitted when a committee is selected for an E3. /// @param e3Id ID of the E3 for which the committee was selected. /// @param filter Address of the contract that will coordinate committee selection. @@ -21,13 +21,13 @@ interface ICyphernodeRegistry { /// @param enclave Address of the enclave contract. event EnclaveSet(address indexed enclave); - /// @notice This event MUST be emitted when a cyphernode is added to the registry. - event CyphernodeAdded(address indexed node); + /// @notice This event MUST be emitted when a ciphernode is added to the registry. + event CiphernodeAdded(address indexed node); - /// @notice This event MUST be emitted when a cyphernode is removed from the registry. - event CyphernodeRemoved(address indexed node); + /// @notice This event MUST be emitted when a ciphernode is removed from the registry. + event CiphernodeRemoved(address indexed node); - function isCyphernodeEligible(address cyphernode) external returns (bool); + function isCiphernodeEligible(address ciphernode) external returns (bool); /// @notice Initiates the committee selection process for a specified E3. /// @dev This function MUST revert when not called by the Enclave contract. diff --git a/packages/evm/contracts/interfaces/IExecutionModule.sol b/packages/evm/contracts/interfaces/IComputeProvider.sol similarity index 67% rename from packages/evm/contracts/interfaces/IExecutionModule.sol rename to packages/evm/contracts/interfaces/IComputeProvider.sol index e6d6e9cf..d55903a2 100644 --- a/packages/evm/contracts/interfaces/IExecutionModule.sol +++ b/packages/evm/contracts/interfaces/IComputeProvider.sol @@ -3,9 +3,9 @@ pragma solidity >=0.8.26; import { IOutputVerifier } from "./IOutputVerifier.sol"; -interface IExecutionModule { - /// @notice This function should be called by the Enclave contract to validate the execution module parameters. - /// @param params ABI encoded execution module parameters. +interface IComputeProvider { + /// @notice This function should be called by the Enclave contract to validate the compute provider parameters. + /// @param params ABI encoded compute provider parameters. function validate( bytes calldata params ) external returns (IOutputVerifier outputVerifier); diff --git a/packages/evm/contracts/interfaces/IE3.sol b/packages/evm/contracts/interfaces/IE3.sol index 67660a5e..06b1cbd6 100644 --- a/packages/evm/contracts/interfaces/IE3.sol +++ b/packages/evm/contracts/interfaces/IE3.sol @@ -2,8 +2,8 @@ pragma solidity >=0.8.26; import { IInputValidator } from "./IInputValidator.sol"; -import { IExecutionModule } from "./IExecutionModule.sol"; -import { IComputationModule } from "./IComputationModule.sol"; +import { IComputeProvider } from "./IComputeProvider.sol"; +import { IE3Program } from "./IE3Program.sol"; import { IOutputVerifier } from "./IOutputVerifier.sol"; /// @title E3 struct @@ -12,8 +12,8 @@ import { IOutputVerifier } from "./IOutputVerifier.sol"; /// @param startWindow Start window for the computation: index zero is minimum, index 1 is the maxium. /// @param duration Duration of the E3. /// @param expiration Timestamp when committee duties expire. -/// @param computationModule Address of the computation module contract. -/// @param executionModule Address of the execution module contract. +/// @param computationModule Address of the E3 Program contract. +/// @param computeProvider Address of the compute provider contract. /// @param inputValidator Address of the input validator contract. /// @param outputVerifier Address of the output verifier contract. /// @param committeeId ID of the selected committee. @@ -24,8 +24,8 @@ struct E3 { uint256[2] startWindow; uint256 duration; uint256 expiration; - IComputationModule computationModule; - IExecutionModule executionModule; + IE3Program computationModule; + IComputeProvider computeProvider; IInputValidator inputValidator; IOutputVerifier outputVerifier; bytes committeePublicKey; diff --git a/packages/evm/contracts/interfaces/IComputationModule.sol b/packages/evm/contracts/interfaces/IE3Program.sol similarity index 96% rename from packages/evm/contracts/interfaces/IComputationModule.sol rename to packages/evm/contracts/interfaces/IE3Program.sol index 3a48423a..6c50b74d 100644 --- a/packages/evm/contracts/interfaces/IComputationModule.sol +++ b/packages/evm/contracts/interfaces/IE3Program.sol @@ -3,7 +3,7 @@ pragma solidity >=0.8.26; import { IInputValidator } from "./IInputValidator.sol"; -interface IComputationModule { +interface IE3Program { /// @notice This function should be called by the Enclave contract to validate the computation parameters. /// @param params ABI encoded computation parameters. /// @return inputValidator The input validator to be used for the computation. diff --git a/packages/evm/contracts/interfaces/IEnclave.sol b/packages/evm/contracts/interfaces/IEnclave.sol index aa4463d6..c8802b61 100644 --- a/packages/evm/contracts/interfaces/IEnclave.sol +++ b/packages/evm/contracts/interfaces/IEnclave.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: LGPL-3.0-only pragma solidity >=0.8.26; -import { E3, IComputationModule, IExecutionModule } from "./IE3.sol"; +import { E3, IE3Program, IComputeProvider } from "./IE3.sol"; interface IEnclave { //////////////////////////////////////////////////////////// @@ -13,15 +13,15 @@ interface IEnclave { /// @notice This event MUST be emitted when an Encrypted Execution Environment (E3) is successfully requested. /// @param e3Id ID of the E3. /// @param e3 Details of the E3. - /// @param filter Address of the pool of nodes from which the Cypher Node committee was selected. + /// @param filter Address of the pool of nodes from which the Cipher Node committee was selected. /// @param computationModule Address of the Computation module selected. - /// @param executionModule Address of the execution module selected. + /// @param computeProvider Address of the compute provider selected. event E3Requested( uint256 e3Id, E3 e3, address filter, - IComputationModule indexed computationModule, - IExecutionModule indexed executionModule + IE3Program indexed computationModule, + IComputeProvider indexed computeProvider ); /// @notice This event MUST be emitted when an Encrypted Execution Environment (E3) is successfully activated. @@ -64,25 +64,25 @@ interface IEnclave { /// @param maxDuration The maximum duration of a computation in seconds. event MaxDurationSet(uint256 maxDuration); - /// @notice This event MUST be emitted any time the CyphernodeRegistry is set. - /// @param cyphernodeRegistry The address of the CyphernodeRegistry contract. - event CyphernodeRegistrySet(address cyphernodeRegistry); + /// @notice This event MUST be emitted any time the CiphernodeRegistry is set. + /// @param ciphernodeRegistry The address of the CiphernodeRegistry contract. + event CiphernodeRegistrySet(address ciphernodeRegistry); - /// @notice This event MUST be emitted any time a computation module is enabled. - /// @param computationModule The address of the computation module. - event ComputationModuleEnabled(IComputationModule computationModule); + /// @notice This event MUST be emitted any time a E3 Program is enabled. + /// @param computationModule The address of the E3 Program. + event E3ProgramEnabled(IE3Program computationModule); - /// @notice This event MUST be emitted any time a computation module is disabled. - /// @param computationModule The address of the computation module. - event ComputationModuleDisabled(IComputationModule computationModule); + /// @notice This event MUST be emitted any time a E3 Program is disabled. + /// @param computationModule The address of the E3 Program. + event E3ProgramDisabled(IE3Program computationModule); - /// @notice This event MUST be emitted any time an execution module is enabled. - /// @param executionModule The address of the execution module. - event ExecutionModuleEnabled(IExecutionModule executionModule); + /// @notice This event MUST be emitted any time an compute provider is enabled. + /// @param computeProvider The address of the compute provider. + event ComputeProviderEnabled(IComputeProvider computeProvider); - /// @notice This event MUST be emitted any time an execution module is disabled. - /// @param executionModule The address of the execution module. - event ExecutionModuleDisabled(IExecutionModule executionModule); + /// @notice This event MUST be emitted any time an compute provider is disabled. + /// @param computeProvider The address of the compute provider. + event ComputeProviderDisabled(IComputeProvider computeProvider); //////////////////////////////////////////////////////////// // // @@ -95,10 +95,10 @@ interface IEnclave { /// @param filter IDs of the pool of nodes from which to select the committee. /// @param threshold The M/N threshold for the committee. /// @param duration The duration of the computation in seconds. - /// @param computationModule Address of the computation module. + /// @param computationModule Address of the E3 Program. /// @param computationParams ABI encoded computation parameters. - /// @param executionModule Address of the execution module. - /// @param emParams ABI encoded execution module parameters. + /// @param computeProvider Address of the compute provider. + /// @param emParams ABI encoded compute provider parameters. /// @return e3Id ID of the E3. /// @return e3 The E3 struct. function request( @@ -106,9 +106,9 @@ interface IEnclave { uint32[2] calldata threshold, uint256[2] calldata startWindow, uint256 duration, - IComputationModule computationModule, + IE3Program computationModule, bytes memory computationParams, - IExecutionModule executionModule, + IComputeProvider computeProvider, bytes memory emParams ) external payable returns (uint256 e3Id, E3 memory e3); diff --git a/packages/evm/contracts/registry/CyphernodeRegistryOwnable.sol b/packages/evm/contracts/registry/CiphernodeRegistryOwnable.sol similarity index 87% rename from packages/evm/contracts/registry/CyphernodeRegistryOwnable.sol rename to packages/evm/contracts/registry/CiphernodeRegistryOwnable.sol index c9c17ca5..29eebdc2 100644 --- a/packages/evm/contracts/registry/CyphernodeRegistryOwnable.sol +++ b/packages/evm/contracts/registry/CiphernodeRegistryOwnable.sol @@ -1,13 +1,13 @@ // SPDX-License-Identifier: LGPL-3.0-only pragma solidity >=0.8.26; -import { ICyphernodeRegistry } from "../interfaces/ICyphernodeRegistry.sol"; +import { ICiphernodeRegistry } from "../interfaces/ICiphernodeRegistry.sol"; import { IRegistryFilter } from "../interfaces/IRegistryFilter.sol"; import { OwnableUpgradeable } from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; -contract CyphernodeRegistryOwnable is ICyphernodeRegistry, OwnableUpgradeable { +contract CiphernodeRegistryOwnable is ICiphernodeRegistry, OwnableUpgradeable { //////////////////////////////////////////////////////////// // // // Storage Variables // @@ -16,7 +16,7 @@ contract CyphernodeRegistryOwnable is ICyphernodeRegistry, OwnableUpgradeable { address public enclave; - mapping(address cyphernode => bool isEnabled) public isEnabled; + mapping(address ciphernode => bool isEnabled) public isEnabled; mapping(uint256 e3Id => IRegistryFilter filter) public requests; mapping(uint256 e3Id => bytes publicKey) public publicKeys; @@ -31,7 +31,7 @@ contract CyphernodeRegistryOwnable is ICyphernodeRegistry, OwnableUpgradeable { error CommitteeAlreadyPublished(); error CommitteeDoesNotExist(); error CommitteeNotPublished(); - error CyphernodeNotEnabled(address node); + error CiphernodeNotEnabled(address node); error OnlyEnclave(); //////////////////////////////////////////////////////////// @@ -91,10 +91,10 @@ contract CyphernodeRegistryOwnable is ICyphernodeRegistry, OwnableUpgradeable { // only to be published by the filter require(address(requests[e3Id]) == msg.sender, CommitteeDoesNotExist()); - // for (uint256 i = 0; i < cyphernodes.length; i++) { + // for (uint256 i = 0; i < ciphernodes.length; i++) { // require( - // isEnabled[cyphernodes[i]] == true, - // CyphernodeNotEnabled(cyphernodes[i]) + // isEnabled[ciphernodes[i]] == true, + // CiphernodeNotEnabled(ciphernodes[i]) // ); // } @@ -113,17 +113,17 @@ contract CyphernodeRegistryOwnable is ICyphernodeRegistry, OwnableUpgradeable { emit EnclaveSet(_enclave); } - function addCyphernode(address node) external onlyOwner { + function addCiphernode(address node) external onlyOwner { isEnabled[node] = true; - emit CyphernodeAdded(node); + emit CiphernodeAdded(node); } - function removeCyphernode(address node) external onlyOwner { + function removeCiphernode(address node) external onlyOwner { isEnabled[node] = false; - emit CyphernodeRemoved(node); + emit CiphernodeRemoved(node); } - function isCyphernodeEligible(address node) external view returns (bool) { + function isCiphernodeEligible(address node) external view returns (bool) { return isEnabled[node]; } diff --git a/packages/evm/contracts/registry/NaiveRegistryFilter.sol b/packages/evm/contracts/registry/NaiveRegistryFilter.sol index 5966c8ea..e6ee2154 100644 --- a/packages/evm/contracts/registry/NaiveRegistryFilter.sol +++ b/packages/evm/contracts/registry/NaiveRegistryFilter.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: LGPL-3.0-only pragma solidity >=0.8.26; -import { ICyphernodeRegistry } from "../interfaces/ICyphernodeRegistry.sol"; +import { ICiphernodeRegistry } from "../interfaces/ICiphernodeRegistry.sol"; import { IRegistryFilter } from "../interfaces/IRegistryFilter.sol"; import { OwnableUpgradeable @@ -91,7 +91,7 @@ contract NaiveRegistryFilter is IRegistryFilter, OwnableUpgradeable { ); committee.nodes = nodes; committee.publicKey = publicKey; - ICyphernodeRegistry(registry).publishCommittee( + ICiphernodeRegistry(registry).publishCommittee( e3Id, abi.encode(nodes), publicKey diff --git a/packages/evm/contracts/test/MockCyphernodeRegistry.sol b/packages/evm/contracts/test/MockCiphernodeRegistry.sol similarity index 81% rename from packages/evm/contracts/test/MockCyphernodeRegistry.sol rename to packages/evm/contracts/test/MockCiphernodeRegistry.sol index ad7d81b5..e7435068 100644 --- a/packages/evm/contracts/test/MockCyphernodeRegistry.sol +++ b/packages/evm/contracts/test/MockCiphernodeRegistry.sol @@ -1,9 +1,9 @@ // SPDX-License-Identifier: LGPL-3.0-only pragma solidity >=0.8.26; -import { ICyphernodeRegistry } from "../interfaces/ICyphernodeRegistry.sol"; +import { ICiphernodeRegistry } from "../interfaces/ICiphernodeRegistry.sol"; -contract MockCyphernodeRegistry is ICyphernodeRegistry { +contract MockCiphernodeRegistry is ICiphernodeRegistry { function requestCommittee( uint256, address filter, @@ -33,12 +33,12 @@ contract MockCyphernodeRegistry is ICyphernodeRegistry { } } - function isCyphernodeEligible(address) external pure returns (bool) { + function isCiphernodeEligible(address) external pure returns (bool) { return false; } } -contract MockCyphernodeRegistryEmptyKey is ICyphernodeRegistry { +contract MockCiphernodeRegistryEmptyKey is ICiphernodeRegistry { function requestCommittee( uint256, address filter, @@ -62,7 +62,7 @@ contract MockCyphernodeRegistryEmptyKey is ICyphernodeRegistry { return hex""; } - function isCyphernodeEligible(address) external pure returns (bool) { + function isCiphernodeEligible(address) external pure returns (bool) { return false; } } diff --git a/packages/evm/contracts/test/MockExecutionModule.sol b/packages/evm/contracts/test/MockComputeProvider.sol similarity index 80% rename from packages/evm/contracts/test/MockExecutionModule.sol rename to packages/evm/contracts/test/MockComputeProvider.sol index 87ce5c52..413aa3c8 100644 --- a/packages/evm/contracts/test/MockExecutionModule.sol +++ b/packages/evm/contracts/test/MockComputeProvider.sol @@ -2,11 +2,11 @@ pragma solidity >=0.8.26; import { - IExecutionModule, + IComputeProvider, IOutputVerifier -} from "../interfaces/IExecutionModule.sol"; +} from "../interfaces/IComputeProvider.sol"; -contract MockExecutionModule is IExecutionModule { +contract MockComputeProvider is IComputeProvider { error invalidParams(); function validate( diff --git a/packages/evm/contracts/test/MockComputationModule.sol b/packages/evm/contracts/test/MockE3Program.sol similarity index 80% rename from packages/evm/contracts/test/MockComputationModule.sol rename to packages/evm/contracts/test/MockE3Program.sol index a6492b1f..522f9763 100644 --- a/packages/evm/contracts/test/MockComputationModule.sol +++ b/packages/evm/contracts/test/MockE3Program.sol @@ -1,12 +1,9 @@ // SPDX-License-Identifier: LGPL-3.0-only pragma solidity >=0.8.26; -import { - IComputationModule, - IInputValidator -} from "../interfaces/IComputationModule.sol"; +import { IE3Program, IInputValidator } from "../interfaces/IE3Program.sol"; -contract MockComputationModule is IComputationModule { +contract MockE3Program is IE3Program { error invalidParams(bytes params); function validate( diff --git a/packages/evm/contracts/test/MockRegistryFilter.sol b/packages/evm/contracts/test/MockRegistryFilter.sol index d48bba7e..ba9910fe 100644 --- a/packages/evm/contracts/test/MockRegistryFilter.sol +++ b/packages/evm/contracts/test/MockRegistryFilter.sol @@ -9,7 +9,7 @@ import { interface IRegistry { function publishCommittee( uint256 e3Id, - address[] calldata cyphernodes, + address[] calldata ciphernodes, bytes calldata publicKey ) external; } diff --git a/packages/evm/tasks/enclave.ts b/packages/evm/tasks/enclave.ts index c0d2c62a..191dcd74 100644 --- a/packages/evm/tasks/enclave.ts +++ b/packages/evm/tasks/enclave.ts @@ -3,7 +3,7 @@ import type { TaskArguments } from "hardhat/types"; task("task:deployEnclave", "Deploys Enclave contract") .addParam("owner", "Account that will own this contract") - .addParam("registry", "Address of the cyphernode registry") + .addParam("registry", "Address of the ciphernode registry") .addParam("maxDuration", "The maximum duration of a computation in seconds") .setAction(async function (taskArguments: TaskArguments, { ethers }) { const signers = await ethers.getSigners(); diff --git a/packages/evm/test/Enclave.spec.ts b/packages/evm/test/Enclave.spec.ts index fbd2b251..00ef3656 100644 --- a/packages/evm/test/Enclave.spec.ts +++ b/packages/evm/test/Enclave.spec.ts @@ -10,9 +10,9 @@ import { ethers } from "hardhat"; import { poseidon2 } from "poseidon-lite"; import { deployEnclaveFixture } from "./fixtures/Enclave.fixture"; -import { deployComputationModuleFixture } from "./fixtures/MockComputationModule.fixture"; -import { deployCyphernodeRegistryFixture } from "./fixtures/MockCyphernodeRegistry.fixture"; -import { deployExecutionModuleFixture } from "./fixtures/MockExecutionModule.fixture"; +import { deployCiphernodeRegistryFixture } from "./fixtures/MockCiphernodeRegistry.fixture"; +import { deployComputeProviderFixture } from "./fixtures/MockComputeProvider.fixture"; +import { deployE3ProgramFixture } from "./fixtures/MockE3Program.fixture"; import { deployInputValidatorFixture } from "./fixtures/MockInputValidator.fixture"; import { deployOutputVerifierFixture } from "./fixtures/MockOutputVerifier.fixture"; @@ -30,10 +30,10 @@ describe("Enclave", function () { async function setup() { const [owner, notTheOwner] = await ethers.getSigners(); - const registry = await deployCyphernodeRegistryFixture(); - const computationModule = await deployComputationModuleFixture(); + const registry = await deployCiphernodeRegistryFixture(); + const computationModule = await deployE3ProgramFixture(); const outputVerifier = await deployOutputVerifierFixture(); - const executionModule = await deployExecutionModuleFixture(); + const computeProvider = await deployComputeProviderFixture(); const inputValidator = await deployInputValidatorFixture(); const enclave = await deployEnclaveFixture({ @@ -41,8 +41,8 @@ describe("Enclave", function () { registry: await registry.getAddress(), }); - await enclave.enableComputationModule(await computationModule.getAddress()); - await enclave.enableExecutionModule(await executionModule.getAddress()); + await enclave.enableE3Program(await computationModule.getAddress()); + await enclave.enableComputeProvider(await computeProvider.getAddress()); return { owner, @@ -51,7 +51,7 @@ describe("Enclave", function () { mocks: { computationModule, outputVerifier, - executionModule, + computeProvider, inputValidator, registry, }, @@ -68,7 +68,7 @@ describe("Enclave", function () { ["address"], [await inputValidator.getAddress()], ), - executionModule: await executionModule.getAddress(), + computeProvider: await computeProvider.getAddress(), eMParams: abiCoder.encode( ["address"], [await outputVerifier.getAddress()], @@ -84,16 +84,16 @@ describe("Enclave", function () { owner: someSigner, registry: AddressTwo, }); - expect(await enclave.cyphernodeRegistry()).to.equal(AddressTwo); + expect(await enclave.ciphernodeRegistry()).to.equal(AddressTwo); }); - it("correctly sets cyphernodeRegistry address", async function () { + it("correctly sets ciphernodeRegistry address", async function () { const [aSigner] = await ethers.getSigners(); const enclave = await deployEnclaveFixture({ owner: aSigner, registry: AddressTwo, }); - expect(await enclave.cyphernodeRegistry()).to.equal(AddressTwo); + expect(await enclave.ciphernodeRegistry()).to.equal(AddressTwo); }); it("correctly sets max duration", async function () { @@ -132,49 +132,49 @@ describe("Enclave", function () { }); }); - describe("setCyphernodeRegistry()", function () { + describe("setCiphernodeRegistry()", function () { it("reverts if not called by owner", async function () { const { enclave, notTheOwner } = await loadFixture(setup); await expect( - enclave.connect(notTheOwner).setCyphernodeRegistry(AddressTwo), + enclave.connect(notTheOwner).setCiphernodeRegistry(AddressTwo), ) .to.be.revertedWithCustomError(enclave, "OwnableUnauthorizedAccount") .withArgs(notTheOwner); }); it("reverts if given address(0)", async function () { const { enclave } = await loadFixture(setup); - await expect(enclave.setCyphernodeRegistry(ethers.ZeroAddress)) - .to.be.revertedWithCustomError(enclave, "InvalidCyphernodeRegistry") + await expect(enclave.setCiphernodeRegistry(ethers.ZeroAddress)) + .to.be.revertedWithCustomError(enclave, "InvalidCiphernodeRegistry") .withArgs(ethers.ZeroAddress); }); - it("reverts if given address is the same as the current cyphernodeRegistry", async function () { + it("reverts if given address is the same as the current ciphernodeRegistry", async function () { const { enclave, mocks: { registry }, } = await loadFixture(setup); - await expect(enclave.setCyphernodeRegistry(registry)) - .to.be.revertedWithCustomError(enclave, "InvalidCyphernodeRegistry") + await expect(enclave.setCiphernodeRegistry(registry)) + .to.be.revertedWithCustomError(enclave, "InvalidCiphernodeRegistry") .withArgs(registry); }); - it("sets cyphernodeRegistry correctly", async function () { + it("sets ciphernodeRegistry correctly", async function () { const { enclave } = await loadFixture(setup); - expect(await enclave.cyphernodeRegistry()).to.not.equal(AddressTwo); - await enclave.setCyphernodeRegistry(AddressTwo); - expect(await enclave.cyphernodeRegistry()).to.equal(AddressTwo); + expect(await enclave.ciphernodeRegistry()).to.not.equal(AddressTwo); + await enclave.setCiphernodeRegistry(AddressTwo); + expect(await enclave.ciphernodeRegistry()).to.equal(AddressTwo); }); - it("returns true if cyphernodeRegistry is set successfully", async function () { + it("returns true if ciphernodeRegistry is set successfully", async function () { const { enclave } = await loadFixture(setup); - const result = await enclave.setCyphernodeRegistry.staticCall(AddressTwo); + const result = await enclave.setCiphernodeRegistry.staticCall(AddressTwo); expect(result).to.be.true; }); - it("emits CyphernodeRegistrySet event", async function () { + it("emits CiphernodeRegistrySet event", async function () { const { enclave } = await loadFixture(setup); - await expect(enclave.setCyphernodeRegistry(AddressTwo)) - .to.emit(enclave, "CyphernodeRegistrySet") + await expect(enclave.setCiphernodeRegistry(AddressTwo)) + .to.emit(enclave, "CiphernodeRegistrySet") .withArgs(AddressTwo); }); }); @@ -196,7 +196,7 @@ describe("Enclave", function () { request.duration, request.computationModule, request.cMParams, - request.executionModule, + request.computeProvider, request.eMParams, { value: 10 }, ); @@ -208,7 +208,7 @@ describe("Enclave", function () { expect(e3.inputValidator).to.equal( abiCoder.decode(["address"], request.cMParams)[0], ); - expect(e3.executionModule).to.equal(request.executionModule); + expect(e3.computeProvider).to.equal(request.computeProvider); expect(e3.outputVerifier).to.equal( abiCoder.decode(["address"], request.eMParams)[0], ); @@ -218,7 +218,7 @@ describe("Enclave", function () { }); }); - describe("enableComputationModule()", function () { + describe("enableE3Program()", function () { it("reverts if not called by owner", async function () { const { notTheOwner, @@ -227,22 +227,22 @@ describe("Enclave", function () { } = await loadFixture(setup); await expect( - enclave.connect(notTheOwner).enableComputationModule(computationModule), + enclave.connect(notTheOwner).enableE3Program(computationModule), ) .to.be.revertedWithCustomError(enclave, "OwnableUnauthorizedAccount") .withArgs(notTheOwner); }); - it("reverts if computation module is already enabled", async function () { + it("reverts if E3 Program is already enabled", async function () { const { enclave, mocks: { computationModule }, } = await loadFixture(setup); - await expect(enclave.enableComputationModule(computationModule)) + await expect(enclave.enableE3Program(computationModule)) .to.be.revertedWithCustomError(enclave, "ModuleAlreadyEnabled") .withArgs(computationModule); }); - it("enables computation module correctly", async function () { + it("enables E3 Program correctly", async function () { const { enclave, mocks: { computationModule }, @@ -250,21 +250,20 @@ describe("Enclave", function () { const enabled = await enclave.computationModules(computationModule); expect(enabled).to.be.true; }); - it("returns true if computation module is enabled successfully", async function () { + it("returns true if E3 Program is enabled successfully", async function () { const { enclave } = await loadFixture(setup); - const result = - await enclave.enableComputationModule.staticCall(AddressTwo); + const result = await enclave.enableE3Program.staticCall(AddressTwo); expect(result).to.be.true; }); - it("emits ComputationModuleEnabled event", async function () { + it("emits E3ProgramEnabled event", async function () { const { enclave } = await loadFixture(setup); - await expect(enclave.enableComputationModule(AddressTwo)) - .to.emit(enclave, "ComputationModuleEnabled") + await expect(enclave.enableE3Program(AddressTwo)) + .to.emit(enclave, "E3ProgramEnabled") .withArgs(AddressTwo); }); }); - describe("disableComputationModule()", function () { + describe("disableE3Program()", function () { it("reverts if not called by owner", async function () { const { notTheOwner, @@ -272,139 +271,137 @@ describe("Enclave", function () { mocks: { computationModule }, } = await loadFixture(setup); await expect( - enclave - .connect(notTheOwner) - .disableComputationModule(computationModule), + enclave.connect(notTheOwner).disableE3Program(computationModule), ) .to.be.revertedWithCustomError(enclave, "OwnableUnauthorizedAccount") .withArgs(notTheOwner); }); - it("reverts if computation module is not enabled", async function () { + it("reverts if E3 Program is not enabled", async function () { const { enclave } = await loadFixture(setup); - await expect(enclave.disableComputationModule(AddressTwo)) + await expect(enclave.disableE3Program(AddressTwo)) .to.be.revertedWithCustomError(enclave, "ModuleNotEnabled") .withArgs(AddressTwo); }); - it("disables computation module correctly", async function () { + it("disables E3 Program correctly", async function () { const { enclave, mocks: { computationModule }, } = await loadFixture(setup); - await enclave.disableComputationModule(computationModule); + await enclave.disableE3Program(computationModule); const enabled = await enclave.computationModules(computationModule); expect(enabled).to.be.false; }); - it("returns true if computation module is disabled successfully", async function () { + it("returns true if E3 Program is disabled successfully", async function () { const { enclave, mocks: { computationModule }, } = await loadFixture(setup); const result = - await enclave.disableComputationModule.staticCall(computationModule); + await enclave.disableE3Program.staticCall(computationModule); expect(result).to.be.true; }); - it("emits ComputationModuleDisabled event", async function () { + it("emits E3ProgramDisabled event", async function () { const { enclave, mocks: { computationModule }, } = await loadFixture(setup); - await expect(enclave.disableComputationModule(computationModule)) - .to.emit(enclave, "ComputationModuleDisabled") + await expect(enclave.disableE3Program(computationModule)) + .to.emit(enclave, "E3ProgramDisabled") .withArgs(computationModule); }); }); - describe("enableExecutionModule()", function () { + describe("enableComputeProvider()", function () { it("reverts if not called by owner", async function () { const { notTheOwner, enclave } = await loadFixture(setup); await expect( - enclave.connect(notTheOwner).enableExecutionModule(AddressTwo), + enclave.connect(notTheOwner).enableComputeProvider(AddressTwo), ) .to.be.revertedWithCustomError(enclave, "OwnableUnauthorizedAccount") .withArgs(notTheOwner.address); }); - it("reverts if execution module is already enabled", async function () { + it("reverts if compute provider is already enabled", async function () { const { enclave, - mocks: { executionModule }, + mocks: { computeProvider }, } = await loadFixture(setup); - await expect(enclave.enableExecutionModule(executionModule)) + await expect(enclave.enableComputeProvider(computeProvider)) .to.be.revertedWithCustomError(enclave, "ModuleAlreadyEnabled") - .withArgs(executionModule); + .withArgs(computeProvider); }); - it("enables execution module correctly", async function () { + it("enables compute provider correctly", async function () { const { enclave, - mocks: { executionModule }, + mocks: { computeProvider }, } = await loadFixture(setup); - const enabled = await enclave.executionModules(executionModule); + const enabled = await enclave.computeProviders(computeProvider); expect(enabled).to.be.true; }); - it("returns true if execution module is enabled successfully", async function () { + it("returns true if compute provider is enabled successfully", async function () { const { enclave } = await loadFixture(setup); - const result = await enclave.enableExecutionModule.staticCall(AddressTwo); + const result = await enclave.enableComputeProvider.staticCall(AddressTwo); expect(result).to.be.true; }); - it("emits ExecutionModuleEnabled event", async function () { + it("emits ComputeProviderEnabled event", async function () { const { enclave } = await loadFixture(setup); - await expect(enclave.enableExecutionModule(AddressTwo)) - .to.emit(enclave, "ExecutionModuleEnabled") + await expect(enclave.enableComputeProvider(AddressTwo)) + .to.emit(enclave, "ComputeProviderEnabled") .withArgs(AddressTwo); }); }); - describe("disableExecutionModule()", function () { + describe("disableComputeProvider()", function () { it("reverts if not called by owner", async function () { const { notTheOwner, enclave, - mocks: { executionModule }, + mocks: { computeProvider }, } = await loadFixture(setup); await expect( - enclave.connect(notTheOwner).disableExecutionModule(executionModule), + enclave.connect(notTheOwner).disableComputeProvider(computeProvider), ) .to.be.revertedWithCustomError(enclave, "OwnableUnauthorizedAccount") .withArgs(notTheOwner); }); - it("reverts if execution module is not enabled", async function () { + it("reverts if compute provider is not enabled", async function () { const { enclave } = await loadFixture(setup); - await expect(enclave.disableExecutionModule(AddressTwo)) + await expect(enclave.disableComputeProvider(AddressTwo)) .to.be.revertedWithCustomError(enclave, "ModuleNotEnabled") .withArgs(AddressTwo); }); - it("disables execution module correctly", async function () { + it("disables compute provider correctly", async function () { const { enclave, - mocks: { executionModule }, + mocks: { computeProvider }, } = await loadFixture(setup); - expect(await enclave.executionModules(executionModule)).to.be.true; - await enclave.disableExecutionModule(executionModule); - expect(await enclave.executionModules(executionModule)).to.be.false; + expect(await enclave.computeProviders(computeProvider)).to.be.true; + await enclave.disableComputeProvider(computeProvider); + expect(await enclave.computeProviders(computeProvider)).to.be.false; }); - it("returns true if execution module is disabled successfully", async function () { + it("returns true if compute provider is disabled successfully", async function () { const { enclave, - mocks: { executionModule }, + mocks: { computeProvider }, } = await loadFixture(setup); const result = - await enclave.disableExecutionModule.staticCall(executionModule); + await enclave.disableComputeProvider.staticCall(computeProvider); expect(result).to.be.true; }); - it("emits ExecutionModuleDisabled event", async function () { + it("emits ComputeProviderDisabled event", async function () { const { enclave, - mocks: { executionModule }, + mocks: { computeProvider }, } = await loadFixture(setup); - await expect(enclave.disableExecutionModule(executionModule)) - .to.emit(enclave, "ExecutionModuleDisabled") - .withArgs(executionModule); + await expect(enclave.disableComputeProvider(computeProvider)) + .to.emit(enclave, "ComputeProviderDisabled") + .withArgs(computeProvider); }); }); @@ -419,7 +416,7 @@ describe("Enclave", function () { request.duration, request.computationModule, request.cMParams, - request.executionModule, + request.computeProvider, request.eMParams, ), ).to.be.revertedWithCustomError(enclave, "PaymentRequired"); @@ -434,7 +431,7 @@ describe("Enclave", function () { request.duration, request.computationModule, request.cMParams, - request.executionModule, + request.computeProvider, request.eMParams, { value: 10 }, ), @@ -450,7 +447,7 @@ describe("Enclave", function () { request.duration, request.computationModule, request.cMParams, - request.executionModule, + request.computeProvider, request.eMParams, { value: 10 }, ), @@ -466,7 +463,7 @@ describe("Enclave", function () { 0, request.computationModule, request.cMParams, - request.executionModule, + request.computeProvider, request.eMParams, { value: 10 }, ), @@ -482,13 +479,13 @@ describe("Enclave", function () { time.duration.days(31), request.computationModule, request.cMParams, - request.executionModule, + request.computeProvider, request.eMParams, { value: 10 }, ), ).to.be.revertedWithCustomError(enclave, "InvalidDuration"); }); - it("reverts if computation module is not enabled", async function () { + it("reverts if E3 Program is not enabled", async function () { const { enclave, request } = await loadFixture(setup); await expect( enclave.request( @@ -498,15 +495,15 @@ describe("Enclave", function () { request.duration, ethers.ZeroAddress, request.cMParams, - request.executionModule, + request.computeProvider, request.eMParams, { value: 10 }, ), ) - .to.be.revertedWithCustomError(enclave, "ComputationModuleNotAllowed") + .to.be.revertedWithCustomError(enclave, "E3ProgramNotAllowed") .withArgs(ethers.ZeroAddress); }); - it("reverts if execution module is not enabled", async function () { + it("reverts if compute provider is not enabled", async function () { const { enclave, request } = await loadFixture(setup); await expect( enclave.request( @@ -524,7 +521,7 @@ describe("Enclave", function () { .to.be.revertedWithCustomError(enclave, "ModuleNotEnabled") .withArgs(ethers.ZeroAddress); }); - it("reverts if input computation module does not return input validator address", async function () { + it("reverts if input E3 Program does not return input validator address", async function () { const { enclave, request } = await loadFixture(setup); await expect( @@ -535,13 +532,13 @@ describe("Enclave", function () { request.duration, request.computationModule, ZeroHash, - request.executionModule, + request.computeProvider, request.eMParams, { value: 10 }, ), ).to.be.revertedWithCustomError(enclave, "InvalidComputation"); }); - it("reverts if input execution module does not return output verifier address", async function () { + it("reverts if input compute provider does not return output verifier address", async function () { const { enclave, request } = await loadFixture(setup); await expect( enclave.request( @@ -551,11 +548,11 @@ describe("Enclave", function () { request.duration, request.computationModule, request.cMParams, - request.executionModule, + request.computeProvider, ZeroHash, { value: 10 }, ), - ).to.be.revertedWithCustomError(enclave, "InvalidExecutionModuleSetup"); + ).to.be.revertedWithCustomError(enclave, "InvalidComputeProviderSetup"); }); it("reverts if committee selection fails", async function () { const { enclave, request } = await loadFixture(setup); @@ -567,7 +564,7 @@ describe("Enclave", function () { request.duration, request.computationModule, request.cMParams, - request.executionModule, + request.computeProvider, request.eMParams, { value: 10 }, ), @@ -582,7 +579,7 @@ describe("Enclave", function () { request.duration, request.computationModule, request.cMParams, - request.executionModule, + request.computeProvider, request.eMParams, { value: 10 }, ); @@ -594,7 +591,7 @@ describe("Enclave", function () { expect(e3.inputValidator).to.equal( abiCoder.decode(["address"], request.cMParams)[0], ); - expect(e3.executionModule).to.equal(request.executionModule); + expect(e3.computeProvider).to.equal(request.computeProvider); expect(e3.outputVerifier).to.equal( abiCoder.decode(["address"], request.eMParams)[0], ); @@ -611,7 +608,7 @@ describe("Enclave", function () { request.duration, request.computationModule, request.cMParams, - request.executionModule, + request.computeProvider, request.eMParams, { value: 10 }, ); @@ -624,7 +621,7 @@ describe("Enclave", function () { e3, request.filter, request.computationModule, - request.executionModule, + request.computeProvider, ); }); }); @@ -647,7 +644,7 @@ describe("Enclave", function () { request.duration, request.computationModule, request.cMParams, - request.executionModule, + request.computeProvider, request.eMParams, { value: 10 }, ); @@ -672,7 +669,7 @@ describe("Enclave", function () { request.duration, request.computationModule, request.cMParams, - request.executionModule, + request.computeProvider, request.eMParams, { value: 10 }, ); @@ -696,7 +693,7 @@ describe("Enclave", function () { request.duration, request.computationModule, request.cMParams, - request.executionModule, + request.computeProvider, request.eMParams, { value: 10 }, ); @@ -708,7 +705,7 @@ describe("Enclave", function () { "E3Expired", ); }); - it("reverts if cyphernodeRegistry does not return a public key", async function () { + it("reverts if ciphernodeRegistry does not return a public key", async function () { const { enclave, request } = await loadFixture(setup); const startTime = [ (await time.latest()) + 1000, @@ -722,7 +719,7 @@ describe("Enclave", function () { request.duration, request.computationModule, request.cMParams, - request.executionModule, + request.computeProvider, request.eMParams, { value: 10 }, ); @@ -746,7 +743,7 @@ describe("Enclave", function () { request.duration, request.computationModule, request.cMParams, - request.executionModule, + request.computeProvider, request.eMParams, { value: 10 }, ); @@ -758,7 +755,7 @@ describe("Enclave", function () { "E3Expired", ); }); - it("reverts if cyphernodeRegistry does not return a public key", async function () { + it("reverts if ciphernodeRegistry does not return a public key", async function () { const { enclave, request } = await loadFixture(setup); await enclave.request( @@ -768,23 +765,23 @@ describe("Enclave", function () { request.duration, request.computationModule, request.cMParams, - request.executionModule, + request.computeProvider, request.eMParams, { value: 10 }, ); - const prevRegistry = await enclave.cyphernodeRegistry(); - const nextRegistry = await deployCyphernodeRegistryFixture( - "MockCyphernodeRegistryEmptyKey", + const prevRegistry = await enclave.ciphernodeRegistry(); + const nextRegistry = await deployCiphernodeRegistryFixture( + "MockCiphernodeRegistryEmptyKey", ); - await enclave.setCyphernodeRegistry(nextRegistry); + await enclave.setCiphernodeRegistry(nextRegistry); await expect(enclave.activate(0)).to.be.revertedWithCustomError( enclave, "CommitteeSelectionFailed", ); - await enclave.setCyphernodeRegistry(prevRegistry); + await enclave.setCiphernodeRegistry(prevRegistry); await expect(enclave.activate(0)).to.not.be.reverted; }); it("sets committeePublicKey correctly", async () => { @@ -801,7 +798,7 @@ describe("Enclave", function () { request.duration, request.computationModule, request.cMParams, - request.executionModule, + request.computeProvider, request.eMParams, { value: 10 }, ); @@ -827,7 +824,7 @@ describe("Enclave", function () { request.duration, request.computationModule, request.cMParams, - request.executionModule, + request.computeProvider, request.eMParams, { value: 10 }, ); @@ -846,7 +843,7 @@ describe("Enclave", function () { request.duration, request.computationModule, request.cMParams, - request.executionModule, + request.computeProvider, request.eMParams, { value: 10 }, ); @@ -879,7 +876,7 @@ describe("Enclave", function () { request.duration, request.computationModule, request.cMParams, - request.executionModule, + request.computeProvider, request.eMParams, { value: 10 }, ); @@ -904,7 +901,7 @@ describe("Enclave", function () { request.duration, request.computationModule, request.cMParams, - request.executionModule, + request.computeProvider, request.eMParams, { value: 10 }, ); @@ -925,7 +922,7 @@ describe("Enclave", function () { request.duration, request.computationModule, request.cMParams, - request.executionModule, + request.computeProvider, request.eMParams, { value: 10 }, ); @@ -949,7 +946,7 @@ describe("Enclave", function () { request.duration, request.computationModule, request.cMParams, - request.executionModule, + request.computeProvider, request.eMParams, { value: 10 }, ); @@ -974,7 +971,7 @@ describe("Enclave", function () { request.duration, request.computationModule, request.cMParams, - request.executionModule, + request.computeProvider, request.eMParams, { value: 10 }, ); @@ -1003,7 +1000,7 @@ describe("Enclave", function () { request.duration, request.computationModule, request.cMParams, - request.executionModule, + request.computeProvider, request.eMParams, { value: 10 }, ); @@ -1039,7 +1036,7 @@ describe("Enclave", function () { request.duration, request.computationModule, request.cMParams, - request.executionModule, + request.computeProvider, request.eMParams, { value: 10 }, ); @@ -1056,7 +1053,7 @@ describe("Enclave", function () { request.duration, request.computationModule, request.cMParams, - request.executionModule, + request.computeProvider, request.eMParams, { value: 10 }, ); @@ -1082,7 +1079,7 @@ describe("Enclave", function () { request.duration, request.computationModule, request.cMParams, - request.executionModule, + request.computeProvider, request.eMParams, { value: 10 }, ); @@ -1107,7 +1104,7 @@ describe("Enclave", function () { request.duration, request.computationModule, request.cMParams, - request.executionModule, + request.computeProvider, request.eMParams, { value: 10 }, ); @@ -1128,7 +1125,7 @@ describe("Enclave", function () { request.duration, request.computationModule, request.cMParams, - request.executionModule, + request.computeProvider, request.eMParams, { value: 10 }, ); @@ -1149,7 +1146,7 @@ describe("Enclave", function () { request.duration, request.computationModule, request.cMParams, - request.executionModule, + request.computeProvider, request.eMParams, { value: 10 }, ); @@ -1170,7 +1167,7 @@ describe("Enclave", function () { request.duration, request.computationModule, request.cMParams, - request.executionModule, + request.computeProvider, request.eMParams, { value: 10 }, ); @@ -1202,7 +1199,7 @@ describe("Enclave", function () { request.duration, request.computationModule, request.cMParams, - request.executionModule, + request.computeProvider, request.eMParams, { value: 10 }, ); @@ -1221,7 +1218,7 @@ describe("Enclave", function () { request.duration, request.computationModule, request.cMParams, - request.executionModule, + request.computeProvider, request.eMParams, { value: 10 }, ); @@ -1241,7 +1238,7 @@ describe("Enclave", function () { request.duration, request.computationModule, request.cMParams, - request.executionModule, + request.computeProvider, request.eMParams, { value: 10 }, ); @@ -1267,7 +1264,7 @@ describe("Enclave", function () { request.duration, request.computationModule, request.cMParams, - request.executionModule, + request.computeProvider, request.eMParams, { value: 10 }, ); @@ -1289,7 +1286,7 @@ describe("Enclave", function () { request.duration, request.computationModule, request.cMParams, - request.executionModule, + request.computeProvider, request.eMParams, { value: 10 }, ); @@ -1312,7 +1309,7 @@ describe("Enclave", function () { request.duration, request.computationModule, request.cMParams, - request.executionModule, + request.computeProvider, request.eMParams, { value: 10 }, ); @@ -1334,7 +1331,7 @@ describe("Enclave", function () { request.duration, request.computationModule, request.cMParams, - request.executionModule, + request.computeProvider, request.eMParams, { value: 10 }, ); diff --git a/packages/evm/test/fixtures/MockCiphernodeRegistry.fixture.ts b/packages/evm/test/fixtures/MockCiphernodeRegistry.fixture.ts new file mode 100644 index 00000000..4e960cbc --- /dev/null +++ b/packages/evm/test/fixtures/MockCiphernodeRegistry.fixture.ts @@ -0,0 +1,15 @@ +import { ethers } from "hardhat"; + +import { MockCiphernodeRegistry__factory } from "../../types"; + +export async function deployCiphernodeRegistryFixture(name?: string) { + const [signer] = await ethers.getSigners(); + const deployment = await ( + await ethers.getContractFactory(name || "MockCiphernodeRegistry") + ).deploy(); + + return MockCiphernodeRegistry__factory.connect( + await deployment.getAddress(), + signer.provider, + ); +} diff --git a/packages/evm/test/fixtures/MockComputationModule.fixture.ts b/packages/evm/test/fixtures/MockComputationModule.fixture.ts deleted file mode 100644 index 9eba3fb9..00000000 --- a/packages/evm/test/fixtures/MockComputationModule.fixture.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { ethers } from "hardhat"; - -import { MockComputationModule__factory } from "../../types/factories/contracts/test/MockComputationModule__factory"; - -export async function deployComputationModuleFixture() { - const deployment = await ( - await ethers.getContractFactory("MockComputationModule") - ).deploy(); - - return MockComputationModule__factory.connect(await deployment.getAddress()); -} diff --git a/packages/evm/test/fixtures/MockComputeProvider.fixture.ts b/packages/evm/test/fixtures/MockComputeProvider.fixture.ts new file mode 100644 index 00000000..bcb2f0ce --- /dev/null +++ b/packages/evm/test/fixtures/MockComputeProvider.fixture.ts @@ -0,0 +1,11 @@ +import { ethers } from "hardhat"; + +import { MockComputeProvider__factory } from "../../types/factories/contracts/test/MockComputeProvider__factory"; + +export async function deployComputeProviderFixture() { + const deployment = await ( + await ethers.getContractFactory("MockComputeProvider") + ).deploy(); + + return MockComputeProvider__factory.connect(await deployment.getAddress()); +} diff --git a/packages/evm/test/fixtures/MockCyphernodeRegistry.fixture.ts b/packages/evm/test/fixtures/MockCyphernodeRegistry.fixture.ts deleted file mode 100644 index eecc554c..00000000 --- a/packages/evm/test/fixtures/MockCyphernodeRegistry.fixture.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { ethers } from "hardhat"; - -import { MockCyphernodeRegistry__factory } from "../../types"; - -export async function deployCyphernodeRegistryFixture(name?: string) { - const [signer] = await ethers.getSigners(); - const deployment = await ( - await ethers.getContractFactory(name || "MockCyphernodeRegistry") - ).deploy(); - - return MockCyphernodeRegistry__factory.connect( - await deployment.getAddress(), - signer.provider, - ); -} diff --git a/packages/evm/test/fixtures/MockE3Program.fixture.ts b/packages/evm/test/fixtures/MockE3Program.fixture.ts new file mode 100644 index 00000000..353525b3 --- /dev/null +++ b/packages/evm/test/fixtures/MockE3Program.fixture.ts @@ -0,0 +1,11 @@ +import { ethers } from "hardhat"; + +import { MockE3Program__factory } from "../../types/factories/contracts/test/MockE3Program__factory"; + +export async function deployE3ProgramFixture() { + const deployment = await ( + await ethers.getContractFactory("MockE3Program") + ).deploy(); + + return MockE3Program__factory.connect(await deployment.getAddress()); +} diff --git a/packages/evm/test/fixtures/MockExecutionModule.fixture.ts b/packages/evm/test/fixtures/MockExecutionModule.fixture.ts deleted file mode 100644 index 0b8d6582..00000000 --- a/packages/evm/test/fixtures/MockExecutionModule.fixture.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { ethers } from "hardhat"; - -import { MockExecutionModule__factory } from "../../types/factories/contracts/test/MockExecutionModule__factory"; - -export async function deployExecutionModuleFixture() { - const deployment = await ( - await ethers.getContractFactory("MockExecutionModule") - ).deploy(); - - return MockExecutionModule__factory.connect(await deployment.getAddress()); -} From 48d593268d15c2131b4d49ab134265ed5210353b Mon Sep 17 00:00:00 2001 From: Auryn Macmillan Date: Wed, 4 Sep 2024 12:29:20 -0400 Subject: [PATCH 16/32] add: bump solhint verstion --- packages/evm/package.json | 2 +- packages/evm/yarn.lock | 39 ++++++++++++++++++++++++++++++++------- 2 files changed, 33 insertions(+), 8 deletions(-) diff --git a/packages/evm/package.json b/packages/evm/package.json index 1bc79870..d8cbaa58 100644 --- a/packages/evm/package.json +++ b/packages/evm/package.json @@ -42,7 +42,7 @@ "prettier": "^3.1.1", "prettier-plugin-solidity": "^1.2.0", "rimraf": "^5.0.5", - "solhint": "^5.0.1", + "solhint": "^5.0.3", "solhint-plugin-prettier": "^0.1.0", "solidity-coverage": "^0.8.5", "ts-generator": "^0.1.1", diff --git a/packages/evm/yarn.lock b/packages/evm/yarn.lock index 5258f6f1..0863d0d9 100644 --- a/packages/evm/yarn.lock +++ b/packages/evm/yarn.lock @@ -4334,10 +4334,10 @@ solhint-plugin-prettier@^0.1.0: "@prettier/sync" "^0.3.0" prettier-linter-helpers "^1.0.0" -solhint@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/solhint/-/solhint-5.0.1.tgz#f0f783bd9d945e5a27b102295a3f28edba241d6c" - integrity sha512-QeQLS9HGCnIiibt+xiOa/+MuP7BWz9N7C5+Mj9pLHshdkNhuo3AzCpWmjfWVZBUuwIUO3YyCRVIcYLR3YOKGfg== +solhint@^5.0.3: + version "5.0.3" + resolved "https://registry.yarnpkg.com/solhint/-/solhint-5.0.3.tgz#b57f6d2534fe09a60f9db1b92e834363edd1cbde" + integrity sha512-OLCH6qm/mZTCpplTXzXTJGId1zrtNuDYP5c2e6snIv/hdRVxPfBBz/bAlL91bY/Accavkayp2Zp2BaDSrLVXTQ== dependencies: "@solidity-parser/parser" "^0.18.0" ajv "^6.12.6" @@ -4437,7 +4437,16 @@ string-format@^2.0.0: resolved "https://registry.yarnpkg.com/string-format/-/string-format-2.0.0.tgz#f2df2e7097440d3b65de31b6d40d54c96eaffb9b" integrity sha512-bbEs3scLeYNXLecRRuk6uJxdXUSj6le/8rNPHChIJTn2V79aXVTR1EH2OH5zLKKoz0V02fOUKZZcw01pLUShZA== -"string-width-cjs@npm:string-width@^4.2.0", string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.2, string-width@^4.2.3: +"string-width-cjs@npm:string-width@^4.2.0": + version "4.2.3" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" + +string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.2, string-width@^4.2.3: version "4.2.3" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== @@ -4462,7 +4471,14 @@ string_decoder@^1.1.1: dependencies: safe-buffer "~5.2.0" -"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1: +"strip-ansi-cjs@npm:strip-ansi@^6.0.1": + version "6.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" + integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== + dependencies: + ansi-regex "^5.0.1" + +strip-ansi@^6.0.0, strip-ansi@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== @@ -4856,7 +4872,16 @@ workerpool@6.2.1: resolved "https://registry.yarnpkg.com/workerpool/-/workerpool-6.2.1.tgz#46fc150c17d826b86a008e5a4508656777e9c343" integrity sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw== -"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0: +"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0": + version "7.0.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" + integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + +wrap-ansi@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== From 075067735cf6ac1d18b83c3ecba7819013f53374 Mon Sep 17 00:00:00 2001 From: Auryn Macmillan Date: Wed, 4 Sep 2024 14:31:05 -0400 Subject: [PATCH 17/32] add: global `compile` and `test` commands --- package.json | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index c5e4450c..85fe8606 100644 --- a/package.json +++ b/package.json @@ -9,11 +9,13 @@ }, "scripts": { "clean": "cd packages/evm && yarn clean", - "compile": "yarn evm:compile", + "compile": "yarn evm:compile && yarn ciphernode:build", "lint": "yarn evm:lint", "typechain": "yarn evm:typechain", - "test": "yarn evm:test", + "test": "yarn evm:test && yarn ciphernode:test", "coverage": "yarn evm:coverage", + "ciphernode:test": "cd packages/ciphernode && cargo test", + "ciphernode:build": "cd packages/ciphernode && cargo build --release", "evm:install": "cd packages/evm && yarn install", "evm:compile": "cd packages/evm && yarn compile", "evm:lint": "cd packages/evm && yarn lint", From e46e58b49ae19b3c56bf430f03d24b3f1c51ee03 Mon Sep 17 00:00:00 2001 From: Auryn Macmillan Date: Wed, 4 Sep 2024 14:58:45 -0400 Subject: [PATCH 18/32] chore: bump solidity version --- packages/evm/.prettierrc.yml | 2 +- packages/evm/.solhint.json | 2 +- packages/evm/contracts/Enclave.sol | 2 +- packages/evm/contracts/interfaces/ICiphernodeRegistry.sol | 2 +- packages/evm/contracts/interfaces/IComputeProvider.sol | 2 +- packages/evm/contracts/interfaces/IE3.sol | 2 +- packages/evm/contracts/interfaces/IE3Program.sol | 2 +- packages/evm/contracts/interfaces/IEnclave.sol | 2 +- packages/evm/contracts/interfaces/IInputValidator.sol | 2 +- packages/evm/contracts/interfaces/IOutputVerifier.sol | 2 +- packages/evm/contracts/interfaces/IRegistryFilter.sol | 2 +- .../evm/contracts/registry/CiphernodeRegistryOwnable.sol | 2 +- packages/evm/contracts/registry/NaiveRegistryFilter.sol | 2 +- packages/evm/contracts/test/MockCiphernodeRegistry.sol | 2 +- packages/evm/contracts/test/MockComputeProvider.sol | 2 +- packages/evm/contracts/test/MockE3Program.sol | 2 +- packages/evm/contracts/test/MockInputValidator.sol | 2 +- packages/evm/contracts/test/MockOutputVerifier.sol | 2 +- packages/evm/contracts/test/MockRegistryFilter.sol | 2 +- packages/evm/hardhat.config.ts | 2 +- packages/evm/yarn.lock | 8 ++++---- 21 files changed, 24 insertions(+), 24 deletions(-) diff --git a/packages/evm/.prettierrc.yml b/packages/evm/.prettierrc.yml index 17aefc74..b5da85f6 100644 --- a/packages/evm/.prettierrc.yml +++ b/packages/evm/.prettierrc.yml @@ -10,7 +10,7 @@ trailingComma: "all" overrides: - files: "*.sol" options: - compiler: "0.8.26" + compiler: "0.8.27" parser: "solidity-parse" tabWidth: 4 - files: "*.ts" diff --git a/packages/evm/.solhint.json b/packages/evm/.solhint.json index 78d8b176..876663a7 100644 --- a/packages/evm/.solhint.json +++ b/packages/evm/.solhint.json @@ -3,7 +3,7 @@ "plugins": ["prettier"], "rules": { "code-complexity": ["error", 8], - "compiler-version": ["error", ">=0.8.26"], + "compiler-version": ["error", ">=0.8.27"], "func-visibility": ["error", { "ignoreConstructors": true }], "max-line-length": ["error", 120], "named-parameters-mapping": "warn", diff --git a/packages/evm/contracts/Enclave.sol b/packages/evm/contracts/Enclave.sol index 2036c16a..c5a6edb7 100644 --- a/packages/evm/contracts/Enclave.sol +++ b/packages/evm/contracts/Enclave.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: LGPL-3.0-only -pragma solidity >=0.8.26; +pragma solidity >=0.8.27; import { IEnclave, diff --git a/packages/evm/contracts/interfaces/ICiphernodeRegistry.sol b/packages/evm/contracts/interfaces/ICiphernodeRegistry.sol index c9aaf984..2a01199f 100644 --- a/packages/evm/contracts/interfaces/ICiphernodeRegistry.sol +++ b/packages/evm/contracts/interfaces/ICiphernodeRegistry.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: LGPL-3.0-only -pragma solidity >=0.8.26; +pragma solidity >=0.8.27; interface ICiphernodeRegistry { /// @notice This event MUST be emitted when a committee is selected for an E3. diff --git a/packages/evm/contracts/interfaces/IComputeProvider.sol b/packages/evm/contracts/interfaces/IComputeProvider.sol index d55903a2..6e993d33 100644 --- a/packages/evm/contracts/interfaces/IComputeProvider.sol +++ b/packages/evm/contracts/interfaces/IComputeProvider.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: LGPL-3.0-only -pragma solidity >=0.8.26; +pragma solidity >=0.8.27; import { IOutputVerifier } from "./IOutputVerifier.sol"; diff --git a/packages/evm/contracts/interfaces/IE3.sol b/packages/evm/contracts/interfaces/IE3.sol index 06b1cbd6..8a920e10 100644 --- a/packages/evm/contracts/interfaces/IE3.sol +++ b/packages/evm/contracts/interfaces/IE3.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: LGPL-3.0-only -pragma solidity >=0.8.26; +pragma solidity >=0.8.27; import { IInputValidator } from "./IInputValidator.sol"; import { IComputeProvider } from "./IComputeProvider.sol"; diff --git a/packages/evm/contracts/interfaces/IE3Program.sol b/packages/evm/contracts/interfaces/IE3Program.sol index 6c50b74d..7b32328e 100644 --- a/packages/evm/contracts/interfaces/IE3Program.sol +++ b/packages/evm/contracts/interfaces/IE3Program.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: LGPL-3.0-only -pragma solidity >=0.8.26; +pragma solidity >=0.8.27; import { IInputValidator } from "./IInputValidator.sol"; diff --git a/packages/evm/contracts/interfaces/IEnclave.sol b/packages/evm/contracts/interfaces/IEnclave.sol index c8802b61..33b72127 100644 --- a/packages/evm/contracts/interfaces/IEnclave.sol +++ b/packages/evm/contracts/interfaces/IEnclave.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: LGPL-3.0-only -pragma solidity >=0.8.26; +pragma solidity >=0.8.27; import { E3, IE3Program, IComputeProvider } from "./IE3.sol"; diff --git a/packages/evm/contracts/interfaces/IInputValidator.sol b/packages/evm/contracts/interfaces/IInputValidator.sol index 257af4da..1419472e 100644 --- a/packages/evm/contracts/interfaces/IInputValidator.sol +++ b/packages/evm/contracts/interfaces/IInputValidator.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: LGPL-3.0-only -pragma solidity >=0.8.26; +pragma solidity >=0.8.27; interface IInputValidator { /// @notice This function should be called by the Enclave contract to validate the input parameters. diff --git a/packages/evm/contracts/interfaces/IOutputVerifier.sol b/packages/evm/contracts/interfaces/IOutputVerifier.sol index 53203715..d2c77b16 100644 --- a/packages/evm/contracts/interfaces/IOutputVerifier.sol +++ b/packages/evm/contracts/interfaces/IOutputVerifier.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: LGPL-3.0-only -pragma solidity >=0.8.26; +pragma solidity >=0.8.27; interface IOutputVerifier { /// @notice This function should be called by the Enclave contract to verify the output of a computation. diff --git a/packages/evm/contracts/interfaces/IRegistryFilter.sol b/packages/evm/contracts/interfaces/IRegistryFilter.sol index c861d734..dbac5bf5 100644 --- a/packages/evm/contracts/interfaces/IRegistryFilter.sol +++ b/packages/evm/contracts/interfaces/IRegistryFilter.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: LGPL-3.0-only -pragma solidity >=0.8.26; +pragma solidity >=0.8.27; interface IRegistryFilter { function requestCommittee( diff --git a/packages/evm/contracts/registry/CiphernodeRegistryOwnable.sol b/packages/evm/contracts/registry/CiphernodeRegistryOwnable.sol index 29eebdc2..6793fdf2 100644 --- a/packages/evm/contracts/registry/CiphernodeRegistryOwnable.sol +++ b/packages/evm/contracts/registry/CiphernodeRegistryOwnable.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: LGPL-3.0-only -pragma solidity >=0.8.26; +pragma solidity >=0.8.27; import { ICiphernodeRegistry } from "../interfaces/ICiphernodeRegistry.sol"; import { IRegistryFilter } from "../interfaces/IRegistryFilter.sol"; diff --git a/packages/evm/contracts/registry/NaiveRegistryFilter.sol b/packages/evm/contracts/registry/NaiveRegistryFilter.sol index e6ee2154..1b10eb67 100644 --- a/packages/evm/contracts/registry/NaiveRegistryFilter.sol +++ b/packages/evm/contracts/registry/NaiveRegistryFilter.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: LGPL-3.0-only -pragma solidity >=0.8.26; +pragma solidity >=0.8.27; import { ICiphernodeRegistry } from "../interfaces/ICiphernodeRegistry.sol"; import { IRegistryFilter } from "../interfaces/IRegistryFilter.sol"; diff --git a/packages/evm/contracts/test/MockCiphernodeRegistry.sol b/packages/evm/contracts/test/MockCiphernodeRegistry.sol index e7435068..4704e50a 100644 --- a/packages/evm/contracts/test/MockCiphernodeRegistry.sol +++ b/packages/evm/contracts/test/MockCiphernodeRegistry.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: LGPL-3.0-only -pragma solidity >=0.8.26; +pragma solidity >=0.8.27; import { ICiphernodeRegistry } from "../interfaces/ICiphernodeRegistry.sol"; diff --git a/packages/evm/contracts/test/MockComputeProvider.sol b/packages/evm/contracts/test/MockComputeProvider.sol index 413aa3c8..fa7eee78 100644 --- a/packages/evm/contracts/test/MockComputeProvider.sol +++ b/packages/evm/contracts/test/MockComputeProvider.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: LGPL-3.0-only -pragma solidity >=0.8.26; +pragma solidity >=0.8.27; import { IComputeProvider, diff --git a/packages/evm/contracts/test/MockE3Program.sol b/packages/evm/contracts/test/MockE3Program.sol index 522f9763..6b13761b 100644 --- a/packages/evm/contracts/test/MockE3Program.sol +++ b/packages/evm/contracts/test/MockE3Program.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: LGPL-3.0-only -pragma solidity >=0.8.26; +pragma solidity >=0.8.27; import { IE3Program, IInputValidator } from "../interfaces/IE3Program.sol"; diff --git a/packages/evm/contracts/test/MockInputValidator.sol b/packages/evm/contracts/test/MockInputValidator.sol index 2dcb0c89..0c16adec 100644 --- a/packages/evm/contracts/test/MockInputValidator.sol +++ b/packages/evm/contracts/test/MockInputValidator.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: LGPL-3.0-only -pragma solidity >=0.8.26; +pragma solidity >=0.8.27; import { IInputValidator } from "../interfaces/IInputValidator.sol"; diff --git a/packages/evm/contracts/test/MockOutputVerifier.sol b/packages/evm/contracts/test/MockOutputVerifier.sol index 1b5a00fd..dfb740b0 100644 --- a/packages/evm/contracts/test/MockOutputVerifier.sol +++ b/packages/evm/contracts/test/MockOutputVerifier.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: LGPL-3.0-only -pragma solidity >=0.8.26; +pragma solidity >=0.8.27; import { IOutputVerifier } from "../interfaces/IOutputVerifier.sol"; diff --git a/packages/evm/contracts/test/MockRegistryFilter.sol b/packages/evm/contracts/test/MockRegistryFilter.sol index ba9910fe..734ab8c6 100644 --- a/packages/evm/contracts/test/MockRegistryFilter.sol +++ b/packages/evm/contracts/test/MockRegistryFilter.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: LGPL-3.0-only -pragma solidity >=0.8.26; +pragma solidity >=0.8.27; import { IRegistryFilter } from "../interfaces/IRegistryFilter.sol"; import { diff --git a/packages/evm/hardhat.config.ts b/packages/evm/hardhat.config.ts index e9f357b3..488a1be2 100644 --- a/packages/evm/hardhat.config.ts +++ b/packages/evm/hardhat.config.ts @@ -102,7 +102,7 @@ const config: HardhatUserConfig = { tests: "./test", }, solidity: { - version: "0.8.26", + version: "0.8.27", settings: { metadata: { // Not including the metadata hash diff --git a/packages/evm/yarn.lock b/packages/evm/yarn.lock index 0863d0d9..af5d5df7 100644 --- a/packages/evm/yarn.lock +++ b/packages/evm/yarn.lock @@ -2999,7 +2999,7 @@ hardhat@^2.22.0: raw-body "^2.4.1" resolve "1.17.0" semver "^6.3.0" - solc "0.8.26" + solc "0.8.27" source-map-support "^0.5.13" stacktrace-parser "^0.1.10" tsort "0.0.1" @@ -4313,9 +4313,9 @@ slice-ansi@^4.0.0: astral-regex "^2.0.0" is-fullwidth-code-point "^3.0.0" -solc@0.8.26: - version "0.8.26" - resolved "https://registry.yarnpkg.com/solc/-/solc-0.8.26.tgz#afc78078953f6ab3e727c338a2fefcd80dd5b01a" +solc@0.8.27: + version "0.8.27" + resolved "https://registry.yarnpkg.com/solc/-/solc-0.8.27.tgz#afc78078953f6ab3e727c338a2fefcd80dd5b01a" integrity sha512-yiPQNVf5rBFHwN6SIf3TUUvVAFKcQqmSUFeq+fb6pNRCo0ZCgpYOZDi3BVoezCPIAcKrVYd/qXlBLUP9wVrZ9g== dependencies: command-exists "^1.2.8" From 1ec49f6a2925b4daca125a0dbfd3423ee0d2d9db Mon Sep 17 00:00:00 2001 From: Auryn Macmillan Date: Wed, 4 Sep 2024 15:13:54 -0400 Subject: [PATCH 19/32] chore: rename OutputVerifier to DycryptionVerifier --- README.md | 10 +++++----- packages/evm/contracts/Enclave.sol | 12 +++++++----- .../evm/contracts/interfaces/IComputeProvider.sol | 4 ++-- .../{IOutputVerifier.sol => IDecryptionVerifier.sol} | 6 +++--- packages/evm/contracts/interfaces/IE3.sol | 6 +++--- packages/evm/contracts/test/MockComputeProvider.sol | 8 ++++---- ...OutputVerifier.sol => MockDecryptionVerifier.sol} | 4 ++-- packages/evm/test/Enclave.spec.ts | 12 ++++++------ .../test/fixtures/MockDecryptionVerifier.fixture.ts | 10 ++++++++++ .../evm/test/fixtures/MockOutputVerifier.fixture.ts | 10 ---------- 10 files changed, 42 insertions(+), 40 deletions(-) rename packages/evm/contracts/interfaces/{IOutputVerifier.sol => IDecryptionVerifier.sol} (69%) rename packages/evm/contracts/test/{MockOutputVerifier.sol => MockDecryptionVerifier.sol} (67%) create mode 100644 packages/evm/test/fixtures/MockDecryptionVerifier.fixture.ts delete mode 100644 packages/evm/test/fixtures/MockOutputVerifier.fixture.ts diff --git a/README.md b/README.md index c7025823..3baf0b33 100644 --- a/README.md +++ b/README.md @@ -81,7 +81,7 @@ sequenceDiagram Enclave->>E3Program: validate(computationParams) E3Program-->>Enclave: inputValidator Enclave->>ComputeProvider: validate(emParams) - ComputeProvider-->>Enclave: outputVerifier + ComputeProvider-->>Enclave: decryptionVerifier Enclave->>CiphernodeRegistry: requestCommittee(e3Id, filter, threshold) CiphernodeRegistry-->>Enclave: success Enclave-->>User: e3Id, E3 struct @@ -97,13 +97,13 @@ sequenceDiagram participant E3Program participant ComputeProvider participant InputValidator - participant OutputVerifier + participant DecryptionVerifier User->>Enclave: request(parameters) Enclave->>E3Program: validate(computationParams) E3Program-->>Enclave: inputValidator Enclave->>ComputeProvider: validate(emParams) - ComputeProvider-->>Enclave: outputVerifier + ComputeProvider-->>Enclave: decryptionVerifier Enclave->>CiphernodeRegistry: requestCommittee(e3Id, filter, threshold) CiphernodeRegistry-->>Enclave: success Enclave-->>User: e3Id, E3 struct @@ -121,8 +121,8 @@ sequenceDiagram Enclave-->>User: success User->>Enclave: publishCiphertextOutput(e3Id, data) - Enclave->>OutputVerifier: verify(e3Id, data) - OutputVerifier-->>Enclave: output, success + Enclave->>DecryptionVerifier: verify(e3Id, data) + DecryptionVerifier-->>Enclave: output, success Enclave->>Enclave: Store ciphertextOutput Enclave-->>User: success diff --git a/packages/evm/contracts/Enclave.sol b/packages/evm/contracts/Enclave.sol index c5a6edb7..9903b332 100644 --- a/packages/evm/contracts/Enclave.sol +++ b/packages/evm/contracts/Enclave.sol @@ -9,7 +9,7 @@ import { } from "./interfaces/IEnclave.sol"; import { ICiphernodeRegistry } from "./interfaces/ICiphernodeRegistry.sol"; import { IInputValidator } from "./interfaces/IInputValidator.sol"; -import { IOutputVerifier } from "./interfaces/IOutputVerifier.sol"; +import { IDecryptionVerifier } from "./interfaces/IDecryptionVerifier.sol"; import { OwnableUpgradeable } from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; @@ -168,9 +168,11 @@ contract Enclave is IEnclave, OwnableUpgradeable { // TODO: validate that the requested computation can be performed by the given compute provider. // Perhaps the compute provider should be returned by the E3 Program? - IOutputVerifier outputVerifier = computeProvider.validate(emParams); + IDecryptionVerifier decryptionVerifier = computeProvider.validate( + emParams + ); require( - address(outputVerifier) != address(0), + address(decryptionVerifier) != address(0), InvalidComputeProviderSetup() ); @@ -182,7 +184,7 @@ contract Enclave is IEnclave, OwnableUpgradeable { computationModule: computationModule, computeProvider: computeProvider, inputValidator: inputValidator, - outputVerifier: outputVerifier, + decryptionVerifier: decryptionVerifier, committeePublicKey: hex"", ciphertextOutput: hex"", plaintextOutput: hex"" @@ -291,7 +293,7 @@ contract Enclave is IEnclave, OwnableUpgradeable { PlaintextOutputAlreadyPublished(e3Id) ); bytes memory output; - (output, success) = e3.outputVerifier.verify(e3Id, data); + (output, success) = e3.decryptionVerifier.verify(e3Id, data); require(success, InvalidOutput(output)); e3s[e3Id].plaintextOutput = output; diff --git a/packages/evm/contracts/interfaces/IComputeProvider.sol b/packages/evm/contracts/interfaces/IComputeProvider.sol index 6e993d33..2668ee1b 100644 --- a/packages/evm/contracts/interfaces/IComputeProvider.sol +++ b/packages/evm/contracts/interfaces/IComputeProvider.sol @@ -1,12 +1,12 @@ // SPDX-License-Identifier: LGPL-3.0-only pragma solidity >=0.8.27; -import { IOutputVerifier } from "./IOutputVerifier.sol"; +import { IDecryptionVerifier } from "./IDecryptionVerifier.sol"; interface IComputeProvider { /// @notice This function should be called by the Enclave contract to validate the compute provider parameters. /// @param params ABI encoded compute provider parameters. function validate( bytes calldata params - ) external returns (IOutputVerifier outputVerifier); + ) external returns (IDecryptionVerifier decryptionVerifier); } diff --git a/packages/evm/contracts/interfaces/IOutputVerifier.sol b/packages/evm/contracts/interfaces/IDecryptionVerifier.sol similarity index 69% rename from packages/evm/contracts/interfaces/IOutputVerifier.sol rename to packages/evm/contracts/interfaces/IDecryptionVerifier.sol index d2c77b16..0b9ad1f5 100644 --- a/packages/evm/contracts/interfaces/IOutputVerifier.sol +++ b/packages/evm/contracts/interfaces/IDecryptionVerifier.sol @@ -1,11 +1,11 @@ // SPDX-License-Identifier: LGPL-3.0-only pragma solidity >=0.8.27; -interface IOutputVerifier { - /// @notice This function should be called by the Enclave contract to verify the output of a computation. +interface IDecryptionVerifier { + /// @notice This function should be called by the Enclave contract to verify the decryption of output of a computation. /// @param e3Id ID of the E3. /// @param data ABI encoded output data to be verified. - /// @return output Ciphertext output of the given computation. + /// @return output Plaintext output of the given computation. function verify( uint256 e3Id, bytes memory data diff --git a/packages/evm/contracts/interfaces/IE3.sol b/packages/evm/contracts/interfaces/IE3.sol index 8a920e10..64f47060 100644 --- a/packages/evm/contracts/interfaces/IE3.sol +++ b/packages/evm/contracts/interfaces/IE3.sol @@ -4,7 +4,7 @@ pragma solidity >=0.8.27; import { IInputValidator } from "./IInputValidator.sol"; import { IComputeProvider } from "./IComputeProvider.sol"; import { IE3Program } from "./IE3Program.sol"; -import { IOutputVerifier } from "./IOutputVerifier.sol"; +import { IDecryptionVerifier } from "./IDecryptionVerifier.sol"; /// @title E3 struct /// @notice This struct represents an E3 computation. @@ -15,7 +15,7 @@ import { IOutputVerifier } from "./IOutputVerifier.sol"; /// @param computationModule Address of the E3 Program contract. /// @param computeProvider Address of the compute provider contract. /// @param inputValidator Address of the input validator contract. -/// @param outputVerifier Address of the output verifier contract. +/// @param decryptionVerifier Address of the output verifier contract. /// @param committeeId ID of the selected committee. /// @param ciphertextOutput Encrypted output data. /// @param plaintextOutput Decrypted output data. @@ -27,7 +27,7 @@ struct E3 { IE3Program computationModule; IComputeProvider computeProvider; IInputValidator inputValidator; - IOutputVerifier outputVerifier; + IDecryptionVerifier decryptionVerifier; bytes committeePublicKey; bytes ciphertextOutput; bytes plaintextOutput; diff --git a/packages/evm/contracts/test/MockComputeProvider.sol b/packages/evm/contracts/test/MockComputeProvider.sol index fa7eee78..c846b951 100644 --- a/packages/evm/contracts/test/MockComputeProvider.sol +++ b/packages/evm/contracts/test/MockComputeProvider.sol @@ -3,7 +3,7 @@ pragma solidity >=0.8.27; import { IComputeProvider, - IOutputVerifier + IDecryptionVerifier } from "../interfaces/IComputeProvider.sol"; contract MockComputeProvider is IComputeProvider { @@ -11,12 +11,12 @@ contract MockComputeProvider is IComputeProvider { function validate( bytes memory params - ) external pure returns (IOutputVerifier outputVerifier) { + ) external pure returns (IDecryptionVerifier decryptionVerifier) { require(params.length == 32, invalidParams()); // solhint-disable no-inline-assembly assembly { - outputVerifier := mload(add(params, 32)) + decryptionVerifier := mload(add(params, 32)) } - (outputVerifier) = abi.decode(params, (IOutputVerifier)); + (decryptionVerifier) = abi.decode(params, (IDecryptionVerifier)); } } diff --git a/packages/evm/contracts/test/MockOutputVerifier.sol b/packages/evm/contracts/test/MockDecryptionVerifier.sol similarity index 67% rename from packages/evm/contracts/test/MockOutputVerifier.sol rename to packages/evm/contracts/test/MockDecryptionVerifier.sol index dfb740b0..d2977901 100644 --- a/packages/evm/contracts/test/MockOutputVerifier.sol +++ b/packages/evm/contracts/test/MockDecryptionVerifier.sol @@ -1,9 +1,9 @@ // SPDX-License-Identifier: LGPL-3.0-only pragma solidity >=0.8.27; -import { IOutputVerifier } from "../interfaces/IOutputVerifier.sol"; +import { IDecryptionVerifier } from "../interfaces/IDecryptionVerifier.sol"; -contract MockOutputVerifier is IOutputVerifier { +contract MockDecryptionVerifier is IDecryptionVerifier { function verify( uint256, bytes memory data diff --git a/packages/evm/test/Enclave.spec.ts b/packages/evm/test/Enclave.spec.ts index 00ef3656..57f1d622 100644 --- a/packages/evm/test/Enclave.spec.ts +++ b/packages/evm/test/Enclave.spec.ts @@ -12,9 +12,9 @@ import { poseidon2 } from "poseidon-lite"; import { deployEnclaveFixture } from "./fixtures/Enclave.fixture"; import { deployCiphernodeRegistryFixture } from "./fixtures/MockCiphernodeRegistry.fixture"; import { deployComputeProviderFixture } from "./fixtures/MockComputeProvider.fixture"; +import { deployDecryptionVerifierFixture } from "./fixtures/MockDecryptionVerifier.fixture"; import { deployE3ProgramFixture } from "./fixtures/MockE3Program.fixture"; import { deployInputValidatorFixture } from "./fixtures/MockInputValidator.fixture"; -import { deployOutputVerifierFixture } from "./fixtures/MockOutputVerifier.fixture"; const abiCoder = ethers.AbiCoder.defaultAbiCoder(); const AddressTwo = "0x0000000000000000000000000000000000000002"; @@ -32,7 +32,7 @@ describe("Enclave", function () { const registry = await deployCiphernodeRegistryFixture(); const computationModule = await deployE3ProgramFixture(); - const outputVerifier = await deployOutputVerifierFixture(); + const decryptionVerifier = await deployDecryptionVerifierFixture(); const computeProvider = await deployComputeProviderFixture(); const inputValidator = await deployInputValidatorFixture(); @@ -50,7 +50,7 @@ describe("Enclave", function () { enclave, mocks: { computationModule, - outputVerifier, + decryptionVerifier, computeProvider, inputValidator, registry, @@ -71,7 +71,7 @@ describe("Enclave", function () { computeProvider: await computeProvider.getAddress(), eMParams: abiCoder.encode( ["address"], - [await outputVerifier.getAddress()], + [await decryptionVerifier.getAddress()], ), }, }; @@ -209,7 +209,7 @@ describe("Enclave", function () { abiCoder.decode(["address"], request.cMParams)[0], ); expect(e3.computeProvider).to.equal(request.computeProvider); - expect(e3.outputVerifier).to.equal( + expect(e3.decryptionVerifier).to.equal( abiCoder.decode(["address"], request.eMParams)[0], ); expect(e3.committeePublicKey).to.equal("0x"); @@ -592,7 +592,7 @@ describe("Enclave", function () { abiCoder.decode(["address"], request.cMParams)[0], ); expect(e3.computeProvider).to.equal(request.computeProvider); - expect(e3.outputVerifier).to.equal( + expect(e3.decryptionVerifier).to.equal( abiCoder.decode(["address"], request.eMParams)[0], ); expect(e3.committeePublicKey).to.equal("0x"); diff --git a/packages/evm/test/fixtures/MockDecryptionVerifier.fixture.ts b/packages/evm/test/fixtures/MockDecryptionVerifier.fixture.ts new file mode 100644 index 00000000..415771be --- /dev/null +++ b/packages/evm/test/fixtures/MockDecryptionVerifier.fixture.ts @@ -0,0 +1,10 @@ +import { ethers } from "hardhat"; + +import { MockDecryptionVerifier__factory } from "../../types/factories/contracts/test/MockDecryptionVerifier__factory"; + +export async function deployDecryptionVerifierFixture() { + const deployment = await ( + await ethers.getContractFactory("MockDecryptionVerifier") + ).deploy(); + return MockDecryptionVerifier__factory.connect(await deployment.getAddress()); +} diff --git a/packages/evm/test/fixtures/MockOutputVerifier.fixture.ts b/packages/evm/test/fixtures/MockOutputVerifier.fixture.ts deleted file mode 100644 index b7a9c28a..00000000 --- a/packages/evm/test/fixtures/MockOutputVerifier.fixture.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { ethers } from "hardhat"; - -import { MockOutputVerifier__factory } from "../../types/factories/contracts/test/MockOutputVerifier__factory"; - -export async function deployOutputVerifierFixture() { - const deployment = await ( - await ethers.getContractFactory("MockOutputVerifier") - ).deploy(); - return MockOutputVerifier__factory.connect(await deployment.getAddress()); -} From fce85209a52e31306d4429f69f81cd335cad5894 Mon Sep 17 00:00:00 2001 From: Auryn Macmillan Date: Wed, 4 Sep 2024 15:22:10 -0400 Subject: [PATCH 20/32] feat: update sequence diagram --- README.md | 96 +++++++------------------------------------------------ 1 file changed, 11 insertions(+), 85 deletions(-) diff --git a/README.md b/README.md index 3baf0b33..46a52532 100644 --- a/README.md +++ b/README.md @@ -17,81 +17,7 @@ Enclave employs a modular architecture involving numerous actors and participant ```mermaid sequenceDiagram - actor Requester - actor Data Providers - participant Enclave - participant Ciphernode Registry - participant Ciphernodes - participant E3 Program - participant Compute Provider - - loop Each computation request - Requester ->> Enclave: Request computation - activate Enclave - Enclave ->> Ciphernode Registry: Select Committee - activate Ciphernode Registry - Ciphernode Registry -->> Ciphernodes: Key Setup - activate Ciphernodes - Ciphernodes -->> Ciphernode Registry: Publish shared keys - deactivate Ciphernodes - Ciphernode Registry -->> Enclave: Publish Committee - deactivate Ciphernode Registry - - loop Each input - Data Providers ->> Enclave: Publish inputs - Enclave ->> E3 Program: Validate inputs - activate E3 Program - E3 Program -->> Enclave: 👌 - deactivate E3 Program - end - - Enclave ->> Compute Provider: Request execution - activate Compute Provider - Compute Provider -->> Enclave: Publish ciphertext output - deactivate Compute Provider - - Enclave -->> Ciphernodes: Request plaintext output - activate Ciphernodes - Ciphernodes ->> Enclave: Publish plaintext output - deactivate Ciphernodes - - Requester -->> Enclave: Get plaintext - Enclave -->> Requester: Returns plaintext - deactivate Enclave - end - -``` - ---- - -```mermaid -sequenceDiagram - participant Owner - participant Enclave - participant CiphernodeRegistry - participant E3Program - participant ComputeProvider - - Owner->>Enclave: deploy(owner, ciphernodeRegistry, maxDuration) - Enclave->>Enclave: initialize() - Owner->>Enclave: enableE3Program() - Owner->>Enclave: enableComputeProvider() - - User->>Enclave: request(parameters) - Enclave->>E3Program: validate(computationParams) - E3Program-->>Enclave: inputValidator - Enclave->>ComputeProvider: validate(emParams) - ComputeProvider-->>Enclave: decryptionVerifier - Enclave->>CiphernodeRegistry: requestCommittee(e3Id, filter, threshold) - CiphernodeRegistry-->>Enclave: success - Enclave-->>User: e3Id, E3 struct -``` - ---- - -```mermaid -sequenceDiagram - participant User + participant Users participant Enclave participant CiphernodeRegistry participant E3Program @@ -99,38 +25,38 @@ sequenceDiagram participant InputValidator participant DecryptionVerifier - User->>Enclave: request(parameters) + Users->>Enclave: request(parameters) Enclave->>E3Program: validate(computationParams) E3Program-->>Enclave: inputValidator Enclave->>ComputeProvider: validate(emParams) ComputeProvider-->>Enclave: decryptionVerifier Enclave->>CiphernodeRegistry: requestCommittee(e3Id, filter, threshold) CiphernodeRegistry-->>Enclave: success - Enclave-->>User: e3Id, E3 struct + Enclave-->>Users: e3Id, E3 struct - User->>Enclave: activate(e3Id) + Users->>Enclave: activate(e3Id) Enclave->>CiphernodeRegistry: committeePublicKey(e3Id) CiphernodeRegistry-->>Enclave: publicKey Enclave->>Enclave: Set expiration and committeePublicKey - Enclave-->>User: success + Enclave-->>Users: success - User->>Enclave: publishInput(e3Id, data) + Users->>Enclave: publishInput(e3Id, data) Enclave->>InputValidator: validate(msg.sender, data) InputValidator-->>Enclave: input, success Enclave->>Enclave: Store input - Enclave-->>User: success + Enclave-->>Users: success - User->>Enclave: publishCiphertextOutput(e3Id, data) + Users->>Enclave: publishCiphertextOutput(e3Id, data) Enclave->>DecryptionVerifier: verify(e3Id, data) DecryptionVerifier-->>Enclave: output, success Enclave->>Enclave: Store ciphertextOutput - Enclave-->>User: success + Enclave-->>Users: success - User->>Enclave: publishPlaintextOutput(e3Id, data) + Users->>Enclave: publishPlaintextOutput(e3Id, data) Enclave->>E3Program: verify(e3Id, data) E3Program-->>Enclave: output, success Enclave->>Enclave: Store plaintextOutput - Enclave-->>User: success + Enclave-->>Users: success ``` ## Security and Liability From 14b6d4dbad528d6f04e10dcd07fa56baacc4071e Mon Sep 17 00:00:00 2001 From: Auryn Macmillan Date: Wed, 4 Sep 2024 15:47:33 -0400 Subject: [PATCH 21/32] fix: computationModule -> e3Program --- README.md | 2 +- packages/evm/contracts/Enclave.sol | 58 +++----- packages/evm/contracts/interfaces/IE3.sol | 4 +- .../evm/contracts/interfaces/IEnclave.sol | 20 +-- packages/evm/test/Enclave.spec.ts | 135 +++++++++--------- 5 files changed, 98 insertions(+), 121 deletions(-) diff --git a/README.md b/README.md index 46a52532..07519420 100644 --- a/README.md +++ b/README.md @@ -26,7 +26,7 @@ sequenceDiagram participant DecryptionVerifier Users->>Enclave: request(parameters) - Enclave->>E3Program: validate(computationParams) + Enclave->>E3Program: validate(e3ProgramParams) E3Program-->>Enclave: inputValidator Enclave->>ComputeProvider: validate(emParams) ComputeProvider-->>Enclave: decryptionVerifier diff --git a/packages/evm/contracts/Enclave.sol b/packages/evm/contracts/Enclave.sol index 9903b332..b8a41583 100644 --- a/packages/evm/contracts/Enclave.sol +++ b/packages/evm/contracts/Enclave.sol @@ -40,8 +40,7 @@ contract Enclave is IEnclave, OwnableUpgradeable { // This would reduce the governance overhead for Enclave. // Mapping of allowed E3 Programs. - mapping(IE3Program computationModule => bool allowed) - public computationModules; + mapping(IE3Program e3Program => bool allowed) public e3Programs; // Mapping of allowed compute providers. mapping(IComputeProvider computeProvider => bool allowed) @@ -63,7 +62,7 @@ contract Enclave is IEnclave, OwnableUpgradeable { //////////////////////////////////////////////////////////// error CommitteeSelectionFailed(); - error E3ProgramNotAllowed(IE3Program computationModule); + error E3ProgramNotAllowed(IE3Program e3Program); error E3AlreadyActivated(uint256 e3Id); error E3Expired(); error E3NotActivated(uint256 e3Id); @@ -126,8 +125,8 @@ contract Enclave is IEnclave, OwnableUpgradeable { uint32[2] calldata threshold, uint256[2] calldata startWindow, uint256 duration, - IE3Program computationModule, - bytes memory computationParams, + IE3Program e3Program, + bytes memory e3ProgramParams, IComputeProvider computeProvider, bytes memory emParams ) external payable returns (uint256 e3Id, E3 memory e3) { @@ -148,10 +147,7 @@ contract Enclave is IEnclave, OwnableUpgradeable { duration > 0 && duration <= maxDuration, InvalidDuration(duration) ); - require( - computationModules[computationModule], - E3ProgramNotAllowed(computationModule) - ); + require(e3Programs[e3Program], E3ProgramNotAllowed(e3Program)); require( computeProviders[computeProvider], ModuleNotEnabled(address(computeProvider)) @@ -161,9 +157,7 @@ contract Enclave is IEnclave, OwnableUpgradeable { e3Id = nexte3Id; nexte3Id++; - IInputValidator inputValidator = computationModule.validate( - computationParams - ); + IInputValidator inputValidator = e3Program.validate(e3ProgramParams); require(address(inputValidator) != address(0), InvalidComputation()); // TODO: validate that the requested computation can be performed by the given compute provider. @@ -181,7 +175,7 @@ contract Enclave is IEnclave, OwnableUpgradeable { startWindow: startWindow, duration: duration, expiration: 0, - computationModule: computationModule, + e3Program: e3Program, computeProvider: computeProvider, inputValidator: inputValidator, decryptionVerifier: decryptionVerifier, @@ -196,13 +190,7 @@ contract Enclave is IEnclave, OwnableUpgradeable { CommitteeSelectionFailed() ); - emit E3Requested( - e3Id, - e3s[e3Id], - filter, - computationModule, - computeProvider - ); + emit E3Requested(e3Id, e3s[e3Id], filter, e3Program, computeProvider); } function activate(uint256 e3Id) external returns (bool success) { @@ -270,7 +258,7 @@ contract Enclave is IEnclave, OwnableUpgradeable { CiphertextOutputAlreadyPublished(e3Id) ); bytes memory output; - (output, success) = e3.computationModule.verify(e3Id, data); + (output, success) = e3.e3Program.verify(e3Id, data); require(success, InvalidOutput(output)); e3s[e3Id].ciphertextOutput = output; @@ -328,15 +316,15 @@ contract Enclave is IEnclave, OwnableUpgradeable { } function enableE3Program( - IE3Program computationModule + IE3Program e3Program ) public onlyOwner returns (bool success) { require( - !computationModules[computationModule], - ModuleAlreadyEnabled(address(computationModule)) + !e3Programs[e3Program], + ModuleAlreadyEnabled(address(e3Program)) ); - computationModules[computationModule] = true; + e3Programs[e3Program] = true; success = true; - emit E3ProgramEnabled(computationModule); + emit E3ProgramEnabled(e3Program); } function enableComputeProvider( @@ -352,15 +340,12 @@ contract Enclave is IEnclave, OwnableUpgradeable { } function disableE3Program( - IE3Program computationModule + IE3Program e3Program ) public onlyOwner returns (bool success) { - require( - computationModules[computationModule], - ModuleNotEnabled(address(computationModule)) - ); - delete computationModules[computationModule]; + require(e3Programs[e3Program], ModuleNotEnabled(address(e3Program))); + delete e3Programs[e3Program]; success = true; - emit E3ProgramDisabled(computationModule); + emit E3ProgramDisabled(e3Program); } function disableComputeProvider( @@ -383,15 +368,12 @@ contract Enclave is IEnclave, OwnableUpgradeable { function getE3(uint256 e3Id) public view returns (E3 memory e3) { e3 = e3s[e3Id]; - require( - e3.computationModule != IE3Program(address(0)), - E3DoesNotExist(e3Id) - ); + require(e3.e3Program != IE3Program(address(0)), E3DoesNotExist(e3Id)); } function getInputRoot(uint256 e3Id) public view returns (uint256) { require( - e3s[e3Id].computationModule != IE3Program(address(0)), + e3s[e3Id].e3Program != IE3Program(address(0)), E3DoesNotExist(e3Id) ); return InternalLeanIMT._root(inputs[e3Id]); diff --git a/packages/evm/contracts/interfaces/IE3.sol b/packages/evm/contracts/interfaces/IE3.sol index 64f47060..dcd42c91 100644 --- a/packages/evm/contracts/interfaces/IE3.sol +++ b/packages/evm/contracts/interfaces/IE3.sol @@ -12,7 +12,7 @@ import { IDecryptionVerifier } from "./IDecryptionVerifier.sol"; /// @param startWindow Start window for the computation: index zero is minimum, index 1 is the maxium. /// @param duration Duration of the E3. /// @param expiration Timestamp when committee duties expire. -/// @param computationModule Address of the E3 Program contract. +/// @param e3Program Address of the E3 Program contract. /// @param computeProvider Address of the compute provider contract. /// @param inputValidator Address of the input validator contract. /// @param decryptionVerifier Address of the output verifier contract. @@ -24,7 +24,7 @@ struct E3 { uint256[2] startWindow; uint256 duration; uint256 expiration; - IE3Program computationModule; + IE3Program e3Program; IComputeProvider computeProvider; IInputValidator inputValidator; IDecryptionVerifier decryptionVerifier; diff --git a/packages/evm/contracts/interfaces/IEnclave.sol b/packages/evm/contracts/interfaces/IEnclave.sol index 33b72127..dc0e4b0b 100644 --- a/packages/evm/contracts/interfaces/IEnclave.sol +++ b/packages/evm/contracts/interfaces/IEnclave.sol @@ -14,13 +14,13 @@ interface IEnclave { /// @param e3Id ID of the E3. /// @param e3 Details of the E3. /// @param filter Address of the pool of nodes from which the Cipher Node committee was selected. - /// @param computationModule Address of the Computation module selected. + /// @param e3Program Address of the Computation module selected. /// @param computeProvider Address of the compute provider selected. event E3Requested( uint256 e3Id, E3 e3, address filter, - IE3Program indexed computationModule, + IE3Program indexed e3Program, IComputeProvider indexed computeProvider ); @@ -69,12 +69,12 @@ interface IEnclave { event CiphernodeRegistrySet(address ciphernodeRegistry); /// @notice This event MUST be emitted any time a E3 Program is enabled. - /// @param computationModule The address of the E3 Program. - event E3ProgramEnabled(IE3Program computationModule); + /// @param e3Program The address of the E3 Program. + event E3ProgramEnabled(IE3Program e3Program); /// @notice This event MUST be emitted any time a E3 Program is disabled. - /// @param computationModule The address of the E3 Program. - event E3ProgramDisabled(IE3Program computationModule); + /// @param e3Program The address of the E3 Program. + event E3ProgramDisabled(IE3Program e3Program); /// @notice This event MUST be emitted any time an compute provider is enabled. /// @param computeProvider The address of the compute provider. @@ -95,8 +95,8 @@ interface IEnclave { /// @param filter IDs of the pool of nodes from which to select the committee. /// @param threshold The M/N threshold for the committee. /// @param duration The duration of the computation in seconds. - /// @param computationModule Address of the E3 Program. - /// @param computationParams ABI encoded computation parameters. + /// @param e3Program Address of the E3 Program. + /// @param e3ProgramParams ABI encoded computation parameters. /// @param computeProvider Address of the compute provider. /// @param emParams ABI encoded compute provider parameters. /// @return e3Id ID of the E3. @@ -106,8 +106,8 @@ interface IEnclave { uint32[2] calldata threshold, uint256[2] calldata startWindow, uint256 duration, - IE3Program computationModule, - bytes memory computationParams, + IE3Program e3Program, + bytes memory e3ProgramParams, IComputeProvider computeProvider, bytes memory emParams ) external payable returns (uint256 e3Id, E3 memory e3); diff --git a/packages/evm/test/Enclave.spec.ts b/packages/evm/test/Enclave.spec.ts index 57f1d622..34bbc18d 100644 --- a/packages/evm/test/Enclave.spec.ts +++ b/packages/evm/test/Enclave.spec.ts @@ -31,7 +31,7 @@ describe("Enclave", function () { const [owner, notTheOwner] = await ethers.getSigners(); const registry = await deployCiphernodeRegistryFixture(); - const computationModule = await deployE3ProgramFixture(); + const e3Program = await deployE3ProgramFixture(); const decryptionVerifier = await deployDecryptionVerifierFixture(); const computeProvider = await deployComputeProviderFixture(); const inputValidator = await deployInputValidatorFixture(); @@ -41,7 +41,7 @@ describe("Enclave", function () { registry: await registry.getAddress(), }); - await enclave.enableE3Program(await computationModule.getAddress()); + await enclave.enableE3Program(await e3Program.getAddress()); await enclave.enableComputeProvider(await computeProvider.getAddress()); return { @@ -49,7 +49,7 @@ describe("Enclave", function () { notTheOwner, enclave, mocks: { - computationModule, + e3Program, decryptionVerifier, computeProvider, inputValidator, @@ -63,7 +63,7 @@ describe("Enclave", function () { number, ], duration: time.duration.days(30), - computationModule: await computationModule.getAddress(), + e3Program: await e3Program.getAddress(), cMParams: abiCoder.encode( ["address"], [await inputValidator.getAddress()], @@ -194,7 +194,7 @@ describe("Enclave", function () { request.threshold, request.startTime, request.duration, - request.computationModule, + request.e3Program, request.cMParams, request.computeProvider, request.eMParams, @@ -204,7 +204,7 @@ describe("Enclave", function () { expect(e3.threshold).to.deep.equal(request.threshold); expect(e3.expiration).to.equal(0n); - expect(e3.computationModule).to.equal(request.computationModule); + expect(e3.e3Program).to.equal(request.e3Program); expect(e3.inputValidator).to.equal( abiCoder.decode(["address"], request.cMParams)[0], ); @@ -223,31 +223,29 @@ describe("Enclave", function () { const { notTheOwner, enclave, - mocks: { computationModule }, + mocks: { e3Program }, } = await loadFixture(setup); - await expect( - enclave.connect(notTheOwner).enableE3Program(computationModule), - ) + await expect(enclave.connect(notTheOwner).enableE3Program(e3Program)) .to.be.revertedWithCustomError(enclave, "OwnableUnauthorizedAccount") .withArgs(notTheOwner); }); it("reverts if E3 Program is already enabled", async function () { const { enclave, - mocks: { computationModule }, + mocks: { e3Program }, } = await loadFixture(setup); - await expect(enclave.enableE3Program(computationModule)) + await expect(enclave.enableE3Program(e3Program)) .to.be.revertedWithCustomError(enclave, "ModuleAlreadyEnabled") - .withArgs(computationModule); + .withArgs(e3Program); }); it("enables E3 Program correctly", async function () { const { enclave, - mocks: { computationModule }, + mocks: { e3Program }, } = await loadFixture(setup); - const enabled = await enclave.computationModules(computationModule); + const enabled = await enclave.e3Programs(e3Program); expect(enabled).to.be.true; }); it("returns true if E3 Program is enabled successfully", async function () { @@ -268,11 +266,9 @@ describe("Enclave", function () { const { notTheOwner, enclave, - mocks: { computationModule }, + mocks: { e3Program }, } = await loadFixture(setup); - await expect( - enclave.connect(notTheOwner).disableE3Program(computationModule), - ) + await expect(enclave.connect(notTheOwner).disableE3Program(e3Program)) .to.be.revertedWithCustomError(enclave, "OwnableUnauthorizedAccount") .withArgs(notTheOwner); }); @@ -285,31 +281,30 @@ describe("Enclave", function () { it("disables E3 Program correctly", async function () { const { enclave, - mocks: { computationModule }, + mocks: { e3Program }, } = await loadFixture(setup); - await enclave.disableE3Program(computationModule); + await enclave.disableE3Program(e3Program); - const enabled = await enclave.computationModules(computationModule); + const enabled = await enclave.e3Programs(e3Program); expect(enabled).to.be.false; }); it("returns true if E3 Program is disabled successfully", async function () { const { enclave, - mocks: { computationModule }, + mocks: { e3Program }, } = await loadFixture(setup); - const result = - await enclave.disableE3Program.staticCall(computationModule); + const result = await enclave.disableE3Program.staticCall(e3Program); expect(result).to.be.true; }); it("emits E3ProgramDisabled event", async function () { const { enclave, - mocks: { computationModule }, + mocks: { e3Program }, } = await loadFixture(setup); - await expect(enclave.disableE3Program(computationModule)) + await expect(enclave.disableE3Program(e3Program)) .to.emit(enclave, "E3ProgramDisabled") - .withArgs(computationModule); + .withArgs(e3Program); }); }); @@ -414,7 +409,7 @@ describe("Enclave", function () { request.threshold, request.startTime, request.duration, - request.computationModule, + request.e3Program, request.cMParams, request.computeProvider, request.eMParams, @@ -429,7 +424,7 @@ describe("Enclave", function () { [0, 2], request.startTime, request.duration, - request.computationModule, + request.e3Program, request.cMParams, request.computeProvider, request.eMParams, @@ -445,7 +440,7 @@ describe("Enclave", function () { [3, 2], request.startTime, request.duration, - request.computationModule, + request.e3Program, request.cMParams, request.computeProvider, request.eMParams, @@ -461,7 +456,7 @@ describe("Enclave", function () { request.threshold, request.startTime, 0, - request.computationModule, + request.e3Program, request.cMParams, request.computeProvider, request.eMParams, @@ -477,7 +472,7 @@ describe("Enclave", function () { request.threshold, request.startTime, time.duration.days(31), - request.computationModule, + request.e3Program, request.cMParams, request.computeProvider, request.eMParams, @@ -511,7 +506,7 @@ describe("Enclave", function () { request.threshold, request.startTime, request.duration, - request.computationModule, + request.e3Program, request.cMParams, ethers.ZeroAddress, request.eMParams, @@ -530,7 +525,7 @@ describe("Enclave", function () { request.threshold, request.startTime, request.duration, - request.computationModule, + request.e3Program, ZeroHash, request.computeProvider, request.eMParams, @@ -546,7 +541,7 @@ describe("Enclave", function () { request.threshold, request.startTime, request.duration, - request.computationModule, + request.e3Program, request.cMParams, request.computeProvider, ZeroHash, @@ -562,7 +557,7 @@ describe("Enclave", function () { request.threshold, request.startTime, request.duration, - request.computationModule, + request.e3Program, request.cMParams, request.computeProvider, request.eMParams, @@ -577,7 +572,7 @@ describe("Enclave", function () { request.threshold, request.startTime, request.duration, - request.computationModule, + request.e3Program, request.cMParams, request.computeProvider, request.eMParams, @@ -587,7 +582,7 @@ describe("Enclave", function () { expect(e3.threshold).to.deep.equal(request.threshold); expect(e3.expiration).to.equal(0n); - expect(e3.computationModule).to.equal(request.computationModule); + expect(e3.e3Program).to.equal(request.e3Program); expect(e3.inputValidator).to.equal( abiCoder.decode(["address"], request.cMParams)[0], ); @@ -606,7 +601,7 @@ describe("Enclave", function () { request.threshold, request.startTime, request.duration, - request.computationModule, + request.e3Program, request.cMParams, request.computeProvider, request.eMParams, @@ -620,7 +615,7 @@ describe("Enclave", function () { 0, e3, request.filter, - request.computationModule, + request.e3Program, request.computeProvider, ); }); @@ -642,7 +637,7 @@ describe("Enclave", function () { request.threshold, request.startTime, request.duration, - request.computationModule, + request.e3Program, request.cMParams, request.computeProvider, request.eMParams, @@ -667,7 +662,7 @@ describe("Enclave", function () { request.threshold, startTime, request.duration, - request.computationModule, + request.e3Program, request.cMParams, request.computeProvider, request.eMParams, @@ -691,7 +686,7 @@ describe("Enclave", function () { request.threshold, startTime, request.duration, - request.computationModule, + request.e3Program, request.cMParams, request.computeProvider, request.eMParams, @@ -717,7 +712,7 @@ describe("Enclave", function () { request.threshold, startTime, request.duration, - request.computationModule, + request.e3Program, request.cMParams, request.computeProvider, request.eMParams, @@ -741,7 +736,7 @@ describe("Enclave", function () { request.threshold, startTime, request.duration, - request.computationModule, + request.e3Program, request.cMParams, request.computeProvider, request.eMParams, @@ -763,7 +758,7 @@ describe("Enclave", function () { request.threshold, request.startTime, request.duration, - request.computationModule, + request.e3Program, request.cMParams, request.computeProvider, request.eMParams, @@ -796,7 +791,7 @@ describe("Enclave", function () { request.threshold, request.startTime, request.duration, - request.computationModule, + request.e3Program, request.cMParams, request.computeProvider, request.eMParams, @@ -822,7 +817,7 @@ describe("Enclave", function () { request.threshold, request.startTime, request.duration, - request.computationModule, + request.e3Program, request.cMParams, request.computeProvider, request.eMParams, @@ -841,7 +836,7 @@ describe("Enclave", function () { request.threshold, request.startTime, request.duration, - request.computationModule, + request.e3Program, request.cMParams, request.computeProvider, request.eMParams, @@ -874,7 +869,7 @@ describe("Enclave", function () { request.threshold, request.startTime, request.duration, - request.computationModule, + request.e3Program, request.cMParams, request.computeProvider, request.eMParams, @@ -899,7 +894,7 @@ describe("Enclave", function () { request.threshold, request.startTime, request.duration, - request.computationModule, + request.e3Program, request.cMParams, request.computeProvider, request.eMParams, @@ -920,7 +915,7 @@ describe("Enclave", function () { request.threshold, request.startTime, request.duration, - request.computationModule, + request.e3Program, request.cMParams, request.computeProvider, request.eMParams, @@ -944,7 +939,7 @@ describe("Enclave", function () { request.threshold, request.startTime, request.duration, - request.computationModule, + request.e3Program, request.cMParams, request.computeProvider, request.eMParams, @@ -969,7 +964,7 @@ describe("Enclave", function () { request.threshold, request.startTime, request.duration, - request.computationModule, + request.e3Program, request.cMParams, request.computeProvider, request.eMParams, @@ -998,7 +993,7 @@ describe("Enclave", function () { request.threshold, request.startTime, request.duration, - request.computationModule, + request.e3Program, request.cMParams, request.computeProvider, request.eMParams, @@ -1034,7 +1029,7 @@ describe("Enclave", function () { request.threshold, request.startTime, request.duration, - request.computationModule, + request.e3Program, request.cMParams, request.computeProvider, request.eMParams, @@ -1051,7 +1046,7 @@ describe("Enclave", function () { request.threshold, [await time.latest(), (await time.latest()) + 100], request.duration, - request.computationModule, + request.e3Program, request.cMParams, request.computeProvider, request.eMParams, @@ -1077,7 +1072,7 @@ describe("Enclave", function () { request.threshold, [await time.latest(), (await time.latest()) + 100], request.duration, - request.computationModule, + request.e3Program, request.cMParams, request.computeProvider, request.eMParams, @@ -1102,7 +1097,7 @@ describe("Enclave", function () { request.threshold, [await time.latest(), (await time.latest()) + 100], request.duration, - request.computationModule, + request.e3Program, request.cMParams, request.computeProvider, request.eMParams, @@ -1123,7 +1118,7 @@ describe("Enclave", function () { request.threshold, [await time.latest(), (await time.latest()) + 100], request.duration, - request.computationModule, + request.e3Program, request.cMParams, request.computeProvider, request.eMParams, @@ -1144,7 +1139,7 @@ describe("Enclave", function () { request.threshold, [await time.latest(), (await time.latest()) + 100], request.duration, - request.computationModule, + request.e3Program, request.cMParams, request.computeProvider, request.eMParams, @@ -1165,7 +1160,7 @@ describe("Enclave", function () { request.threshold, [await time.latest(), (await time.latest()) + 100], request.duration, - request.computationModule, + request.e3Program, request.cMParams, request.computeProvider, request.eMParams, @@ -1197,7 +1192,7 @@ describe("Enclave", function () { request.threshold, [await time.latest(), (await time.latest()) + 100], request.duration, - request.computationModule, + request.e3Program, request.cMParams, request.computeProvider, request.eMParams, @@ -1216,7 +1211,7 @@ describe("Enclave", function () { request.threshold, [await time.latest(), (await time.latest()) + 100], request.duration, - request.computationModule, + request.e3Program, request.cMParams, request.computeProvider, request.eMParams, @@ -1236,7 +1231,7 @@ describe("Enclave", function () { request.threshold, [await time.latest(), (await time.latest()) + 100], request.duration, - request.computationModule, + request.e3Program, request.cMParams, request.computeProvider, request.eMParams, @@ -1262,7 +1257,7 @@ describe("Enclave", function () { request.threshold, [await time.latest(), (await time.latest()) + 100], request.duration, - request.computationModule, + request.e3Program, request.cMParams, request.computeProvider, request.eMParams, @@ -1284,7 +1279,7 @@ describe("Enclave", function () { request.threshold, [await time.latest(), (await time.latest()) + 100], request.duration, - request.computationModule, + request.e3Program, request.cMParams, request.computeProvider, request.eMParams, @@ -1307,7 +1302,7 @@ describe("Enclave", function () { request.threshold, [await time.latest(), (await time.latest()) + 100], request.duration, - request.computationModule, + request.e3Program, request.cMParams, request.computeProvider, request.eMParams, @@ -1329,7 +1324,7 @@ describe("Enclave", function () { request.threshold, [await time.latest(), (await time.latest()) + 100], request.duration, - request.computationModule, + request.e3Program, request.cMParams, request.computeProvider, request.eMParams, From bb088767dbd9b947e2e377da1a93e7915d8953de Mon Sep 17 00:00:00 2001 From: Auryn Macmillan Date: Wed, 4 Sep 2024 15:58:11 -0400 Subject: [PATCH 22/32] feat: emit seed and params --- packages/evm/contracts/Enclave.sol | 4 +- packages/evm/contracts/interfaces/IE3.sol | 4 +- packages/evm/test/Enclave.spec.ts | 177 +++++++++++----------- 3 files changed, 95 insertions(+), 90 deletions(-) diff --git a/packages/evm/contracts/Enclave.sol b/packages/evm/contracts/Enclave.sol index b8a41583..5acc4c47 100644 --- a/packages/evm/contracts/Enclave.sol +++ b/packages/evm/contracts/Enclave.sol @@ -171,13 +171,15 @@ contract Enclave is IEnclave, OwnableUpgradeable { ); e3 = E3({ + seed: keccak256(abi.encode(block.prevrandao, e3Id)), threshold: threshold, startWindow: startWindow, duration: duration, expiration: 0, e3Program: e3Program, - computeProvider: computeProvider, + e3ProgramParams: e3ProgramParams, inputValidator: inputValidator, + computeProvider: computeProvider, decryptionVerifier: decryptionVerifier, committeePublicKey: hex"", ciphertextOutput: hex"", diff --git a/packages/evm/contracts/interfaces/IE3.sol b/packages/evm/contracts/interfaces/IE3.sol index dcd42c91..6f4afcd1 100644 --- a/packages/evm/contracts/interfaces/IE3.sol +++ b/packages/evm/contracts/interfaces/IE3.sol @@ -20,13 +20,15 @@ import { IDecryptionVerifier } from "./IDecryptionVerifier.sol"; /// @param ciphertextOutput Encrypted output data. /// @param plaintextOutput Decrypted output data. struct E3 { + bytes32 seed; uint32[2] threshold; uint256[2] startWindow; uint256 duration; uint256 expiration; IE3Program e3Program; - IComputeProvider computeProvider; + bytes e3ProgramParams; IInputValidator inputValidator; + IComputeProvider computeProvider; IDecryptionVerifier decryptionVerifier; bytes committeePublicKey; bytes ciphertextOutput; diff --git a/packages/evm/test/Enclave.spec.ts b/packages/evm/test/Enclave.spec.ts index 34bbc18d..f2834ca1 100644 --- a/packages/evm/test/Enclave.spec.ts +++ b/packages/evm/test/Enclave.spec.ts @@ -64,12 +64,12 @@ describe("Enclave", function () { ], duration: time.duration.days(30), e3Program: await e3Program.getAddress(), - cMParams: abiCoder.encode( + e3ProgramParams: abiCoder.encode( ["address"], [await inputValidator.getAddress()], ), computeProvider: await computeProvider.getAddress(), - eMParams: abiCoder.encode( + computeProviderParams: abiCoder.encode( ["address"], [await decryptionVerifier.getAddress()], ), @@ -195,9 +195,9 @@ describe("Enclave", function () { request.startTime, request.duration, request.e3Program, - request.cMParams, + request.e3ProgramParams, request.computeProvider, - request.eMParams, + request.computeProviderParams, { value: 10 }, ); const e3 = await enclave.getE3(0); @@ -205,12 +205,13 @@ describe("Enclave", function () { expect(e3.threshold).to.deep.equal(request.threshold); 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( - abiCoder.decode(["address"], request.cMParams)[0], + abiCoder.decode(["address"], request.e3ProgramParams)[0], ); expect(e3.computeProvider).to.equal(request.computeProvider); expect(e3.decryptionVerifier).to.equal( - abiCoder.decode(["address"], request.eMParams)[0], + abiCoder.decode(["address"], request.computeProviderParams)[0], ); expect(e3.committeePublicKey).to.equal("0x"); expect(e3.ciphertextOutput).to.equal("0x"); @@ -410,9 +411,9 @@ describe("Enclave", function () { request.startTime, request.duration, request.e3Program, - request.cMParams, + request.e3ProgramParams, request.computeProvider, - request.eMParams, + request.computeProviderParams, ), ).to.be.revertedWithCustomError(enclave, "PaymentRequired"); }); @@ -425,9 +426,9 @@ describe("Enclave", function () { request.startTime, request.duration, request.e3Program, - request.cMParams, + request.e3ProgramParams, request.computeProvider, - request.eMParams, + request.computeProviderParams, { value: 10 }, ), ).to.be.revertedWithCustomError(enclave, "InvalidThreshold"); @@ -441,9 +442,9 @@ describe("Enclave", function () { request.startTime, request.duration, request.e3Program, - request.cMParams, + request.e3ProgramParams, request.computeProvider, - request.eMParams, + request.computeProviderParams, { value: 10 }, ), ).to.be.revertedWithCustomError(enclave, "InvalidThreshold"); @@ -457,9 +458,9 @@ describe("Enclave", function () { request.startTime, 0, request.e3Program, - request.cMParams, + request.e3ProgramParams, request.computeProvider, - request.eMParams, + request.computeProviderParams, { value: 10 }, ), ).to.be.revertedWithCustomError(enclave, "InvalidDuration"); @@ -473,9 +474,9 @@ describe("Enclave", function () { request.startTime, time.duration.days(31), request.e3Program, - request.cMParams, + request.e3ProgramParams, request.computeProvider, - request.eMParams, + request.computeProviderParams, { value: 10 }, ), ).to.be.revertedWithCustomError(enclave, "InvalidDuration"); @@ -489,9 +490,9 @@ describe("Enclave", function () { request.startTime, request.duration, ethers.ZeroAddress, - request.cMParams, + request.e3ProgramParams, request.computeProvider, - request.eMParams, + request.computeProviderParams, { value: 10 }, ), ) @@ -507,9 +508,9 @@ describe("Enclave", function () { request.startTime, request.duration, request.e3Program, - request.cMParams, + request.e3ProgramParams, ethers.ZeroAddress, - request.eMParams, + request.computeProviderParams, { value: 10 }, ), ) @@ -528,7 +529,7 @@ describe("Enclave", function () { request.e3Program, ZeroHash, request.computeProvider, - request.eMParams, + request.computeProviderParams, { value: 10 }, ), ).to.be.revertedWithCustomError(enclave, "InvalidComputation"); @@ -542,7 +543,7 @@ describe("Enclave", function () { request.startTime, request.duration, request.e3Program, - request.cMParams, + request.e3ProgramParams, request.computeProvider, ZeroHash, { value: 10 }, @@ -558,9 +559,9 @@ describe("Enclave", function () { request.startTime, request.duration, request.e3Program, - request.cMParams, + request.e3ProgramParams, request.computeProvider, - request.eMParams, + request.computeProviderParams, { value: 10 }, ), ).to.be.revertedWithCustomError(enclave, "CommitteeSelectionFailed"); @@ -573,9 +574,9 @@ describe("Enclave", function () { request.startTime, request.duration, request.e3Program, - request.cMParams, + request.e3ProgramParams, request.computeProvider, - request.eMParams, + request.computeProviderParams, { value: 10 }, ); const e3 = await enclave.getE3(0); @@ -584,11 +585,11 @@ describe("Enclave", function () { expect(e3.expiration).to.equal(0n); expect(e3.e3Program).to.equal(request.e3Program); expect(e3.inputValidator).to.equal( - abiCoder.decode(["address"], request.cMParams)[0], + abiCoder.decode(["address"], request.e3ProgramParams)[0], ); expect(e3.computeProvider).to.equal(request.computeProvider); expect(e3.decryptionVerifier).to.equal( - abiCoder.decode(["address"], request.eMParams)[0], + abiCoder.decode(["address"], request.computeProviderParams)[0], ); expect(e3.committeePublicKey).to.equal("0x"); expect(e3.ciphertextOutput).to.equal("0x"); @@ -602,9 +603,9 @@ describe("Enclave", function () { request.startTime, request.duration, request.e3Program, - request.cMParams, + request.e3ProgramParams, request.computeProvider, - request.eMParams, + request.computeProviderParams, { value: 10 }, ); const e3 = await enclave.getE3(0); @@ -638,9 +639,9 @@ describe("Enclave", function () { request.startTime, request.duration, request.e3Program, - request.cMParams, + request.e3ProgramParams, request.computeProvider, - request.eMParams, + request.computeProviderParams, { value: 10 }, ); @@ -663,9 +664,9 @@ describe("Enclave", function () { startTime, request.duration, request.e3Program, - request.cMParams, + request.e3ProgramParams, request.computeProvider, - request.eMParams, + request.computeProviderParams, { value: 10 }, ); @@ -687,9 +688,9 @@ describe("Enclave", function () { startTime, request.duration, request.e3Program, - request.cMParams, + request.e3ProgramParams, request.computeProvider, - request.eMParams, + request.computeProviderParams, { value: 10 }, ); @@ -713,9 +714,9 @@ describe("Enclave", function () { startTime, request.duration, request.e3Program, - request.cMParams, + request.e3ProgramParams, request.computeProvider, - request.eMParams, + request.computeProviderParams, { value: 10 }, ); @@ -737,9 +738,9 @@ describe("Enclave", function () { startTime, request.duration, request.e3Program, - request.cMParams, + request.e3ProgramParams, request.computeProvider, - request.eMParams, + request.computeProviderParams, { value: 10 }, ); @@ -759,9 +760,9 @@ describe("Enclave", function () { request.startTime, request.duration, request.e3Program, - request.cMParams, + request.e3ProgramParams, request.computeProvider, - request.eMParams, + request.computeProviderParams, { value: 10 }, ); @@ -792,9 +793,9 @@ describe("Enclave", function () { request.startTime, request.duration, request.e3Program, - request.cMParams, + request.e3ProgramParams, request.computeProvider, - request.eMParams, + request.computeProviderParams, { value: 10 }, ); @@ -818,9 +819,9 @@ describe("Enclave", function () { request.startTime, request.duration, request.e3Program, - request.cMParams, + request.e3ProgramParams, request.computeProvider, - request.eMParams, + request.computeProviderParams, { value: 10 }, ); @@ -837,9 +838,9 @@ describe("Enclave", function () { request.startTime, request.duration, request.e3Program, - request.cMParams, + request.e3ProgramParams, request.computeProvider, - request.eMParams, + request.computeProviderParams, { value: 10 }, ); @@ -870,9 +871,9 @@ describe("Enclave", function () { request.startTime, request.duration, request.e3Program, - request.cMParams, + request.e3ProgramParams, request.computeProvider, - request.eMParams, + request.computeProviderParams, { value: 10 }, ); @@ -895,9 +896,9 @@ describe("Enclave", function () { request.startTime, request.duration, request.e3Program, - request.cMParams, + request.e3ProgramParams, request.computeProvider, - request.eMParams, + request.computeProviderParams, { value: 10 }, ); @@ -916,9 +917,9 @@ describe("Enclave", function () { request.startTime, request.duration, request.e3Program, - request.cMParams, + request.e3ProgramParams, request.computeProvider, - request.eMParams, + request.computeProviderParams, { value: 10 }, ); @@ -940,9 +941,9 @@ describe("Enclave", function () { request.startTime, request.duration, request.e3Program, - request.cMParams, + request.e3ProgramParams, request.computeProvider, - request.eMParams, + request.computeProviderParams, { value: 10 }, ); @@ -965,9 +966,9 @@ describe("Enclave", function () { request.startTime, request.duration, request.e3Program, - request.cMParams, + request.e3ProgramParams, request.computeProvider, - request.eMParams, + request.computeProviderParams, { value: 10 }, ); @@ -994,9 +995,9 @@ describe("Enclave", function () { request.startTime, request.duration, request.e3Program, - request.cMParams, + request.e3ProgramParams, request.computeProvider, - request.eMParams, + request.computeProviderParams, { value: 10 }, ); @@ -1030,9 +1031,9 @@ describe("Enclave", function () { request.startTime, request.duration, request.e3Program, - request.cMParams, + request.e3ProgramParams, request.computeProvider, - request.eMParams, + request.computeProviderParams, { value: 10 }, ); await expect(enclave.publishCiphertextOutput(e3Id, "0x")) @@ -1047,9 +1048,9 @@ describe("Enclave", function () { [await time.latest(), (await time.latest()) + 100], request.duration, request.e3Program, - request.cMParams, + request.e3ProgramParams, request.computeProvider, - request.eMParams, + request.computeProviderParams, { value: 10 }, ); const block = await tx.getBlock(); @@ -1073,9 +1074,9 @@ describe("Enclave", function () { [await time.latest(), (await time.latest()) + 100], request.duration, request.e3Program, - request.cMParams, + request.e3ProgramParams, request.computeProvider, - request.eMParams, + request.computeProviderParams, { value: 10 }, ); await enclave.activate(e3Id); @@ -1098,9 +1099,9 @@ describe("Enclave", function () { [await time.latest(), (await time.latest()) + 100], request.duration, request.e3Program, - request.cMParams, + request.e3ProgramParams, request.computeProvider, - request.eMParams, + request.computeProviderParams, { value: 10 }, ); await enclave.activate(e3Id); @@ -1119,9 +1120,9 @@ describe("Enclave", function () { [await time.latest(), (await time.latest()) + 100], request.duration, request.e3Program, - request.cMParams, + request.e3ProgramParams, request.computeProvider, - request.eMParams, + request.computeProviderParams, { value: 10 }, ); await enclave.activate(e3Id); @@ -1140,9 +1141,9 @@ describe("Enclave", function () { [await time.latest(), (await time.latest()) + 100], request.duration, request.e3Program, - request.cMParams, + request.e3ProgramParams, request.computeProvider, - request.eMParams, + request.computeProviderParams, { value: 10 }, ); await enclave.activate(e3Id); @@ -1161,9 +1162,9 @@ describe("Enclave", function () { [await time.latest(), (await time.latest()) + 100], request.duration, request.e3Program, - request.cMParams, + request.e3ProgramParams, request.computeProvider, - request.eMParams, + request.computeProviderParams, { value: 10 }, ); await enclave.activate(e3Id); @@ -1193,9 +1194,9 @@ describe("Enclave", function () { [await time.latest(), (await time.latest()) + 100], request.duration, request.e3Program, - request.cMParams, + request.e3ProgramParams, request.computeProvider, - request.eMParams, + request.computeProviderParams, { value: 10 }, ); await expect(enclave.publishPlaintextOutput(e3Id, "0x")) @@ -1212,9 +1213,9 @@ describe("Enclave", function () { [await time.latest(), (await time.latest()) + 100], request.duration, request.e3Program, - request.cMParams, + request.e3ProgramParams, request.computeProvider, - request.eMParams, + request.computeProviderParams, { value: 10 }, ); await enclave.activate(e3Id); @@ -1232,9 +1233,9 @@ describe("Enclave", function () { [await time.latest(), (await time.latest()) + 100], request.duration, request.e3Program, - request.cMParams, + request.e3ProgramParams, request.computeProvider, - request.eMParams, + request.computeProviderParams, { value: 10 }, ); await enclave.activate(e3Id); @@ -1258,9 +1259,9 @@ describe("Enclave", function () { [await time.latest(), (await time.latest()) + 100], request.duration, request.e3Program, - request.cMParams, + request.e3ProgramParams, request.computeProvider, - request.eMParams, + request.computeProviderParams, { value: 10 }, ); await enclave.activate(e3Id); @@ -1280,9 +1281,9 @@ describe("Enclave", function () { [await time.latest(), (await time.latest()) + 100], request.duration, request.e3Program, - request.cMParams, + request.e3ProgramParams, request.computeProvider, - request.eMParams, + request.computeProviderParams, { value: 10 }, ); await enclave.activate(e3Id); @@ -1303,9 +1304,9 @@ describe("Enclave", function () { [await time.latest(), (await time.latest()) + 100], request.duration, request.e3Program, - request.cMParams, + request.e3ProgramParams, request.computeProvider, - request.eMParams, + request.computeProviderParams, { value: 10 }, ); await enclave.activate(e3Id); @@ -1325,9 +1326,9 @@ describe("Enclave", function () { [await time.latest(), (await time.latest()) + 100], request.duration, request.e3Program, - request.cMParams, + request.e3ProgramParams, request.computeProvider, - request.eMParams, + request.computeProviderParams, { value: 10 }, ); await enclave.activate(e3Id); From f6a01b20e69e4169afae79002e26cd47cc89f12d Mon Sep 17 00:00:00 2001 From: Auryn Macmillan Date: Thu, 5 Sep 2024 09:39:32 -0400 Subject: [PATCH 23/32] feat: add `e3Id` and `seed` to `validate()` calls to `IE3Program` and `IComputeProvider` --- README.md | 2 +- packages/evm/contracts/Enclave.sol | 15 +++++++++++---- .../evm/contracts/interfaces/IComputeProvider.sol | 2 ++ packages/evm/contracts/interfaces/IE3.sol | 2 +- packages/evm/contracts/interfaces/IE3Program.sol | 4 ++++ packages/evm/contracts/interfaces/IEnclave.sol | 4 ++-- .../evm/contracts/test/MockComputeProvider.sol | 2 ++ packages/evm/contracts/test/MockE3Program.sol | 2 ++ 8 files changed, 25 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 07519420..79f4da0d 100644 --- a/README.md +++ b/README.md @@ -28,7 +28,7 @@ sequenceDiagram Users->>Enclave: request(parameters) Enclave->>E3Program: validate(e3ProgramParams) E3Program-->>Enclave: inputValidator - Enclave->>ComputeProvider: validate(emParams) + Enclave->>ComputeProvider: validate(computeProviderParams) ComputeProvider-->>Enclave: decryptionVerifier Enclave->>CiphernodeRegistry: requestCommittee(e3Id, filter, threshold) CiphernodeRegistry-->>Enclave: success diff --git a/packages/evm/contracts/Enclave.sol b/packages/evm/contracts/Enclave.sol index 5acc4c47..609825a6 100644 --- a/packages/evm/contracts/Enclave.sol +++ b/packages/evm/contracts/Enclave.sol @@ -128,7 +128,7 @@ contract Enclave is IEnclave, OwnableUpgradeable { IE3Program e3Program, bytes memory e3ProgramParams, IComputeProvider computeProvider, - bytes memory emParams + bytes memory computeProviderParams ) external payable returns (uint256 e3Id, E3 memory e3) { // TODO: allow for other payment methods or only native tokens? // TODO: should payment checks be somewhere else? Perhaps in the E3 Program or ciphernode registry? @@ -156,14 +156,21 @@ contract Enclave is IEnclave, OwnableUpgradeable { // TODO: should IDs be incremental or produced deterministically? e3Id = nexte3Id; nexte3Id++; + uint256 seed = uint256(keccak256(abi.encode(block.prevrandao, e3Id))); - IInputValidator inputValidator = e3Program.validate(e3ProgramParams); + IInputValidator inputValidator = e3Program.validate( + e3Id, + seed, + e3ProgramParams + ); require(address(inputValidator) != address(0), InvalidComputation()); // TODO: validate that the requested computation can be performed by the given compute provider. // Perhaps the compute provider should be returned by the E3 Program? IDecryptionVerifier decryptionVerifier = computeProvider.validate( - emParams + e3Id, + seed, + computeProviderParams ); require( address(decryptionVerifier) != address(0), @@ -171,7 +178,7 @@ contract Enclave is IEnclave, OwnableUpgradeable { ); e3 = E3({ - seed: keccak256(abi.encode(block.prevrandao, e3Id)), + seed: seed, threshold: threshold, startWindow: startWindow, duration: duration, diff --git a/packages/evm/contracts/interfaces/IComputeProvider.sol b/packages/evm/contracts/interfaces/IComputeProvider.sol index 2668ee1b..e997b180 100644 --- a/packages/evm/contracts/interfaces/IComputeProvider.sol +++ b/packages/evm/contracts/interfaces/IComputeProvider.sol @@ -7,6 +7,8 @@ interface IComputeProvider { /// @notice This function should be called by the Enclave contract to validate the compute provider parameters. /// @param params ABI encoded compute provider parameters. function validate( + uint256 e3Id, + uint256 seed, bytes calldata params ) external returns (IDecryptionVerifier decryptionVerifier); } diff --git a/packages/evm/contracts/interfaces/IE3.sol b/packages/evm/contracts/interfaces/IE3.sol index 6f4afcd1..66a78385 100644 --- a/packages/evm/contracts/interfaces/IE3.sol +++ b/packages/evm/contracts/interfaces/IE3.sol @@ -20,7 +20,7 @@ import { IDecryptionVerifier } from "./IDecryptionVerifier.sol"; /// @param ciphertextOutput Encrypted output data. /// @param plaintextOutput Decrypted output data. struct E3 { - bytes32 seed; + uint256 seed; uint32[2] threshold; uint256[2] startWindow; uint256 duration; diff --git a/packages/evm/contracts/interfaces/IE3Program.sol b/packages/evm/contracts/interfaces/IE3Program.sol index 7b32328e..506e1e94 100644 --- a/packages/evm/contracts/interfaces/IE3Program.sol +++ b/packages/evm/contracts/interfaces/IE3Program.sol @@ -5,9 +5,13 @@ import { IInputValidator } from "./IInputValidator.sol"; interface IE3Program { /// @notice This function should be called by the Enclave contract to validate the computation parameters. + /// @param e3Id ID of the E3. + /// @param seed Seed for the computation. /// @param params ABI encoded computation parameters. /// @return inputValidator The input validator to be used for the computation. function validate( + uint256 e3Id, + uint256 seed, bytes calldata params ) external returns (IInputValidator inputValidator); diff --git a/packages/evm/contracts/interfaces/IEnclave.sol b/packages/evm/contracts/interfaces/IEnclave.sol index dc0e4b0b..b22f03ed 100644 --- a/packages/evm/contracts/interfaces/IEnclave.sol +++ b/packages/evm/contracts/interfaces/IEnclave.sol @@ -98,7 +98,7 @@ interface IEnclave { /// @param e3Program Address of the E3 Program. /// @param e3ProgramParams ABI encoded computation parameters. /// @param computeProvider Address of the compute provider. - /// @param emParams ABI encoded compute provider parameters. + /// @param computeProviderParams ABI encoded compute provider parameters. /// @return e3Id ID of the E3. /// @return e3 The E3 struct. function request( @@ -109,7 +109,7 @@ interface IEnclave { IE3Program e3Program, bytes memory e3ProgramParams, IComputeProvider computeProvider, - bytes memory emParams + bytes memory computeProviderParams ) external payable returns (uint256 e3Id, E3 memory e3); /// @notice This function should be called to activate an Encrypted Execution Environment (E3) once it has been diff --git a/packages/evm/contracts/test/MockComputeProvider.sol b/packages/evm/contracts/test/MockComputeProvider.sol index c846b951..9ddd2fba 100644 --- a/packages/evm/contracts/test/MockComputeProvider.sol +++ b/packages/evm/contracts/test/MockComputeProvider.sol @@ -10,6 +10,8 @@ contract MockComputeProvider is IComputeProvider { error invalidParams(); function validate( + uint256, + uint256, bytes memory params ) external pure returns (IDecryptionVerifier decryptionVerifier) { require(params.length == 32, invalidParams()); diff --git a/packages/evm/contracts/test/MockE3Program.sol b/packages/evm/contracts/test/MockE3Program.sol index 6b13761b..b92d6a84 100644 --- a/packages/evm/contracts/test/MockE3Program.sol +++ b/packages/evm/contracts/test/MockE3Program.sol @@ -7,6 +7,8 @@ contract MockE3Program is IE3Program { error invalidParams(bytes params); function validate( + uint256, + uint256, bytes memory params ) external pure returns (IInputValidator inputValidator) { require(params.length == 32, "invalid params"); From 6305380287992f5b088e9f4f5cc3c9e75ad69e49 Mon Sep 17 00:00:00 2001 From: Auryn Macmillan Date: Thu, 5 Sep 2024 12:22:40 -0400 Subject: [PATCH 24/32] feat: store ciphernode in an incremental merkle tree --- .../interfaces/ICiphernodeRegistry.sol | 22 +++++++- .../registry/CiphernodeRegistryOwnable.sol | 53 +++++++++++++------ 2 files changed, 58 insertions(+), 17 deletions(-) diff --git a/packages/evm/contracts/interfaces/ICiphernodeRegistry.sol b/packages/evm/contracts/interfaces/ICiphernodeRegistry.sol index 2a01199f..6a48f70a 100644 --- a/packages/evm/contracts/interfaces/ICiphernodeRegistry.sol +++ b/packages/evm/contracts/interfaces/ICiphernodeRegistry.sol @@ -22,10 +22,28 @@ interface ICiphernodeRegistry { event EnclaveSet(address indexed enclave); /// @notice This event MUST be emitted when a ciphernode is added to the registry. - event CiphernodeAdded(address indexed node); + /// @param node Address of the ciphernode. + /// @param index Index of the ciphernode in the registry. + /// @param numNodes Number of ciphernodes in the registry. + /// @param size Size of the registry. + event CiphernodeAdded( + address indexed node, + uint256 index, + uint256 numNodes, + uint256 size + ); /// @notice This event MUST be emitted when a ciphernode is removed from the registry. - event CiphernodeRemoved(address indexed node); + /// @param node Address of the ciphernode. + /// @param index Index of the ciphernode in the registry. + /// @param numNodes Number of ciphernodes in the registry. + /// @param size Size of the registry. + event CiphernodeRemoved( + address indexed node, + uint256 index, + uint256 numNodes, + uint256 size + ); function isCiphernodeEligible(address ciphernode) external returns (bool); diff --git a/packages/evm/contracts/registry/CiphernodeRegistryOwnable.sol b/packages/evm/contracts/registry/CiphernodeRegistryOwnable.sol index 6793fdf2..19a9b693 100644 --- a/packages/evm/contracts/registry/CiphernodeRegistryOwnable.sol +++ b/packages/evm/contracts/registry/CiphernodeRegistryOwnable.sol @@ -6,8 +6,15 @@ import { IRegistryFilter } from "../interfaces/IRegistryFilter.sol"; import { OwnableUpgradeable } from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; +import { + InternalLeanIMT, + LeanIMTData, + PoseidonT3 +} from "@zk-kit/lean-imt.sol/InternalLeanIMT.sol"; contract CiphernodeRegistryOwnable is ICiphernodeRegistry, OwnableUpgradeable { + using InternalLeanIMT for LeanIMTData; + //////////////////////////////////////////////////////////// // // // Storage Variables // @@ -15,8 +22,8 @@ contract CiphernodeRegistryOwnable is ICiphernodeRegistry, OwnableUpgradeable { //////////////////////////////////////////////////////////// address public enclave; - - mapping(address ciphernode => bool isEnabled) public isEnabled; + uint256 public numCiphernodes; + LeanIMTData public ciphernodes; mapping(uint256 e3Id => IRegistryFilter filter) public requests; mapping(uint256 e3Id => bytes publicKey) public publicKeys; @@ -91,13 +98,6 @@ contract CiphernodeRegistryOwnable is ICiphernodeRegistry, OwnableUpgradeable { // only to be published by the filter require(address(requests[e3Id]) == msg.sender, CommitteeDoesNotExist()); - // for (uint256 i = 0; i < ciphernodes.length; i++) { - // require( - // isEnabled[ciphernodes[i]] == true, - // CiphernodeNotEnabled(ciphernodes[i]) - // ); - // } - publicKeys[e3Id] = publicKey; emit CommitteePublished(e3Id, publicKey); } @@ -114,17 +114,36 @@ contract CiphernodeRegistryOwnable is ICiphernodeRegistry, OwnableUpgradeable { } function addCiphernode(address node) external onlyOwner { - isEnabled[node] = true; - emit CiphernodeAdded(node); + uint256 ciphernode = uint256(bytes32(bytes20(node))); + ciphernodes._insert(ciphernode); + numCiphernodes++; + emit CiphernodeAdded( + node, + ciphernodes._indexOf(ciphernode), + numCiphernodes, + ciphernodes.size + ); } - function removeCiphernode(address node) external onlyOwner { - isEnabled[node] = false; - emit CiphernodeRemoved(node); + function removeCiphernode( + address node, + uint256[] calldata siblingNodes + ) external onlyOwner { + uint256 ciphernode = uint256(bytes32(bytes20(node))); + ciphernodes._remove(ciphernode, siblingNodes); + uint256 index = ciphernodes._indexOf(ciphernode); + numCiphernodes--; + emit CiphernodeAdded( + node, + ciphernodes._indexOf(ciphernode), + numCiphernodes, + ciphernodes.size + ); + emit CiphernodeRemoved(node, index, numCiphernodes, ciphernodes.size); } function isCiphernodeEligible(address node) external view returns (bool) { - return isEnabled[node]; + return isEnabled(node); } //////////////////////////////////////////////////////////// @@ -139,4 +158,8 @@ contract CiphernodeRegistryOwnable is ICiphernodeRegistry, OwnableUpgradeable { publicKey = publicKeys[e3Id]; require(publicKey.length > 0, CommitteeNotPublished()); } + + function isEnabled(address node) public view returns (bool) { + return ciphernodes._has(uint256(bytes32(bytes20(node)))); + } } From 01a7b6b81b846639503d9ec8b8a215a15185b3cb Mon Sep 17 00:00:00 2001 From: Auryn Macmillan Date: Thu, 5 Sep 2024 12:58:49 -0400 Subject: [PATCH 25/32] feat: make roots easily accessible --- .../contracts/registry/CiphernodeRegistryOwnable.sol | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/packages/evm/contracts/registry/CiphernodeRegistryOwnable.sol b/packages/evm/contracts/registry/CiphernodeRegistryOwnable.sol index 19a9b693..96c4c54b 100644 --- a/packages/evm/contracts/registry/CiphernodeRegistryOwnable.sol +++ b/packages/evm/contracts/registry/CiphernodeRegistryOwnable.sol @@ -26,6 +26,7 @@ contract CiphernodeRegistryOwnable is ICiphernodeRegistry, OwnableUpgradeable { LeanIMTData public ciphernodes; mapping(uint256 e3Id => IRegistryFilter filter) public requests; + mapping(uint256 e3Id => uint256 root) public roots; mapping(uint256 e3Id => bytes publicKey) public publicKeys; //////////////////////////////////////////////////////////// @@ -84,6 +85,7 @@ contract CiphernodeRegistryOwnable is ICiphernodeRegistry, OwnableUpgradeable { CommitteeAlreadyRequested() ); requests[e3Id] = IRegistryFilter(filter); + roots[e3Id] = root(); IRegistryFilter(filter).requestCommittee(e3Id, threshold); emit CommitteeRequested(e3Id, filter, threshold); @@ -162,4 +164,12 @@ contract CiphernodeRegistryOwnable is ICiphernodeRegistry, OwnableUpgradeable { function isEnabled(address node) public view returns (bool) { return ciphernodes._has(uint256(bytes32(bytes20(node)))); } + + function root() public view returns (uint256) { + return (ciphernodes._root()); + } + + function rootAt(uint256 e3Id) public view returns (uint256) { + return roots[e3Id]; + } } From b930596d0073e3977cc36b35133c9be17bd8eb41 Mon Sep 17 00:00:00 2001 From: samepant Date: Tue, 10 Sep 2024 15:37:56 -0400 Subject: [PATCH 26/32] add deploy script for deploying contracts, and setting registry address --- packages/evm/.env.example | 4 ++++ packages/evm/deploy/deploy.ts | 33 ++++++++++++++++++++++++++++++++- packages/evm/hardhat.config.ts | 18 +++++++++++++----- packages/evm/package.json | 1 + packages/evm/yarn.lock | 5 +++++ 5 files changed, 55 insertions(+), 6 deletions(-) create mode 100644 packages/evm/.env.example diff --git a/packages/evm/.env.example b/packages/evm/.env.example new file mode 100644 index 00000000..1009952f --- /dev/null +++ b/packages/evm/.env.example @@ -0,0 +1,4 @@ +MNEMONIC= +INFURA_KEY= + +ETHERSCAN_API_KEY= \ No newline at end of file diff --git a/packages/evm/deploy/deploy.ts b/packages/evm/deploy/deploy.ts index 60c6f2bb..b298f928 100644 --- a/packages/evm/deploy/deploy.ts +++ b/packages/evm/deploy/deploy.ts @@ -2,6 +2,7 @@ import { DeployFunction } from "hardhat-deploy/types"; import { HardhatRuntimeEnvironment } from "hardhat/types"; const THIRTY_DAYS_IN_SECONDS = 60 * 60 * 24 * 30; +const addressOne = "0x0000000000000000000000000000000000000001"; const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { const { deployer } = await hre.getNamedAccounts(); @@ -9,11 +10,41 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { const enclave = await deploy("Enclave", { from: deployer, - args: [THIRTY_DAYS_IN_SECONDS], + args: [deployer, addressOne, THIRTY_DAYS_IN_SECONDS], log: true, }); console.log(`Enclave contract: `, enclave.address); + + const cypherNodeRegistry = await deploy("CyphernodeRegistryOwnable", { + from: deployer, + args: [deployer, enclave.address], + log: true, + }); + + console.log( + `CyphernodeRegistryOwnable contract: `, + cypherNodeRegistry.address, + ); + + // set registry in enclave + const enclaveContract = await hre.ethers.getContractAt( + "Enclave", + enclave.address, + ); + + const setRegistryAddress = await enclaveContract.cyphernodeRegistry(); + + if (setRegistryAddress === cypherNodeRegistry.address) { + console.log(`Enclave contract already has registry`); + return; + } + + const result = await enclaveContract.setCyphernodeRegistry( + cypherNodeRegistry.address, + ); + await result.wait(); + console.log(`Enclave contract updated with registry`); }; export default func; func.id = "deploy_enclave"; // id required to prevent reexecution diff --git a/packages/evm/hardhat.config.ts b/packages/evm/hardhat.config.ts index 488a1be2..03caebb0 100644 --- a/packages/evm/hardhat.config.ts +++ b/packages/evm/hardhat.config.ts @@ -1,4 +1,5 @@ import "@nomicfoundation/hardhat-toolbox"; +import dotenv from "dotenv"; import "hardhat-deploy"; import type { HardhatUserConfig } from "hardhat/config"; import { vars } from "hardhat/config"; @@ -7,10 +8,17 @@ import type { NetworkUserConfig } from "hardhat/types"; import "./tasks/accounts"; import "./tasks/enclave"; -// Run 'npx hardhat vars setup' to see the list of variables that need to be set +dotenv.config(); -const mnemonic: string = vars.get("MNEMONIC"); -const infuraApiKey: string = vars.get("INFURA_API_KEY"); +const { INFURA_KEY, MNEMONIC, ETHERSCAN_API_KEY } = process.env; +if (!INFURA_KEY || !MNEMONIC || !ETHERSCAN_API_KEY) { + console.error( + "Please set the INFURA_KEY, MNEMONIC, and ETHERSCAN_API_KEY environment variables", + ); + process.exit(1); +} +const mnemonic: string = MNEMONIC; +const infuraApiKey: string = INFURA_KEY; const chainIds = { "arbitrum-mainnet": 42161, @@ -58,11 +66,11 @@ const config: HardhatUserConfig = { arbitrumOne: vars.get("ARBISCAN_API_KEY", ""), avalanche: vars.get("SNOWTRACE_API_KEY", ""), bsc: vars.get("BSCSCAN_API_KEY", ""), - mainnet: vars.get("ETHERSCAN_API_KEY", ""), + mainnet: ETHERSCAN_API_KEY, optimisticEthereum: vars.get("OPTIMISM_API_KEY", ""), polygon: vars.get("POLYGONSCAN_API_KEY", ""), polygonMumbai: vars.get("POLYGONSCAN_API_KEY", ""), - sepolia: vars.get("ETHERSCAN_API_KEY", ""), + sepolia: ETHERSCAN_API_KEY, }, }, gasReporter: { diff --git a/packages/evm/package.json b/packages/evm/package.json index d8cbaa58..d899b070 100644 --- a/packages/evm/package.json +++ b/packages/evm/package.json @@ -28,6 +28,7 @@ "@zk-kit/lean-imt.sol": "2.0.0", "chai": "^4.3.10", "cross-env": "^7.0.3", + "dotenv": "^16.4.5", "eslint": "^8.56.0", "eslint-config-prettier": "^9.1.0", "ethers": "^6.9.0", diff --git a/packages/evm/yarn.lock b/packages/evm/yarn.lock index af5d5df7..747974ac 100644 --- a/packages/evm/yarn.lock +++ b/packages/evm/yarn.lock @@ -2119,6 +2119,11 @@ doctrine@^3.0.0: dependencies: esutils "^2.0.2" +dotenv@^16.4.5: + version "16.4.5" + resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-16.4.5.tgz#cdd3b3b604cb327e286b4762e13502f717cb099f" + integrity sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg== + eastasianwidth@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/eastasianwidth/-/eastasianwidth-0.2.0.tgz#696ce2ec0aa0e6ea93a397ffcf24aa7840c827cb" From cf0e93c7de59ed45f5d49078f6805e1fcad958be Mon Sep 17 00:00:00 2001 From: samepant Date: Tue, 10 Sep 2024 15:55:14 -0400 Subject: [PATCH 27/32] add filter contract to deploy script --- .../contracts/registry/NaiveRegistryFilter.sol | 4 ++-- .../evm/contracts/test/MockRegistryFilter.sol | 2 +- packages/evm/deploy/deploy.ts | 18 ++++++++++++++++-- 3 files changed, 19 insertions(+), 5 deletions(-) diff --git a/packages/evm/contracts/registry/NaiveRegistryFilter.sol b/packages/evm/contracts/registry/NaiveRegistryFilter.sol index 1b10eb67..7d122e9e 100644 --- a/packages/evm/contracts/registry/NaiveRegistryFilter.sol +++ b/packages/evm/contracts/registry/NaiveRegistryFilter.sol @@ -53,8 +53,8 @@ contract NaiveRegistryFilter is IRegistryFilter, OwnableUpgradeable { // // //////////////////////////////////////////////////////////// - constructor(address _owner, address _enclave) { - initialize(_owner, _enclave); + constructor(address _owner, address _registry) { + initialize(_owner, _registry); } function initialize(address _owner, address _registry) public initializer { diff --git a/packages/evm/contracts/test/MockRegistryFilter.sol b/packages/evm/contracts/test/MockRegistryFilter.sol index 734ab8c6..4899f574 100644 --- a/packages/evm/contracts/test/MockRegistryFilter.sol +++ b/packages/evm/contracts/test/MockRegistryFilter.sol @@ -14,7 +14,7 @@ interface IRegistry { ) external; } -contract NaiveRegistryFilter is IRegistryFilter, OwnableUpgradeable { +contract MockNaiveRegistryFilter is IRegistryFilter, OwnableUpgradeable { struct Committee { address[] nodes; uint32[2] threshold; diff --git a/packages/evm/deploy/deploy.ts b/packages/evm/deploy/deploy.ts index b298f928..35b99935 100644 --- a/packages/evm/deploy/deploy.ts +++ b/packages/evm/deploy/deploy.ts @@ -8,6 +8,8 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { const { deployer } = await hre.getNamedAccounts(); const { deploy } = hre.deployments; + // Deploy Enclave contract + const enclave = await deploy("Enclave", { from: deployer, args: [deployer, addressOne, THIRTY_DAYS_IN_SECONDS], @@ -16,6 +18,8 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { console.log(`Enclave contract: `, enclave.address); + // Deploy CyphernodeRegistryOwnable contract + const cypherNodeRegistry = await deploy("CyphernodeRegistryOwnable", { from: deployer, args: [deployer, enclave.address], @@ -27,15 +31,25 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { cypherNodeRegistry.address, ); + // Deploy NaiveRegistryFilter contract + + const naiveRegistryFilter = await deploy("NaiveRegistryFilter", { + from: deployer, + args: [deployer, cypherNodeRegistry.address], + log: true, + }); + + console.log(`NaiveRegistryFilter contract: `, naiveRegistryFilter.address); + // set registry in enclave const enclaveContract = await hre.ethers.getContractAt( "Enclave", enclave.address, ); - const setRegistryAddress = await enclaveContract.cyphernodeRegistry(); + const registryAddress = await enclaveContract.cyphernodeRegistry(); - if (setRegistryAddress === cypherNodeRegistry.address) { + if (registryAddress === cypherNodeRegistry.address) { console.log(`Enclave contract already has registry`); return; } From f1b1038a302cdc7cd41e28896d7a472c3408a13a Mon Sep 17 00:00:00 2001 From: samepant Date: Fri, 13 Sep 2024 10:12:59 -0400 Subject: [PATCH 28/32] remove vestigial deploy script --- packages/evm/tasks/enclave.ts | 21 --------------------- 1 file changed, 21 deletions(-) delete mode 100644 packages/evm/tasks/enclave.ts diff --git a/packages/evm/tasks/enclave.ts b/packages/evm/tasks/enclave.ts deleted file mode 100644 index 191dcd74..00000000 --- a/packages/evm/tasks/enclave.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { task } from "hardhat/config"; -import type { TaskArguments } from "hardhat/types"; - -task("task:deployEnclave", "Deploys Enclave contract") - .addParam("owner", "Account that will own this contract") - .addParam("registry", "Address of the ciphernode registry") - .addParam("maxDuration", "The maximum duration of a computation in seconds") - .setAction(async function (taskArguments: TaskArguments, { ethers }) { - const signers = await ethers.getSigners(); - const enclaveFactory = await ethers.getContractFactory("Enclave"); - console.log(`Deploying Enclave...`); - const enclave = await enclaveFactory - .connect(signers[0]) - .deploy( - taskArguments.owner, - taskArguments.registry, - taskArguments.maxDuration, - ); - await enclave.waitForDeployment(); - console.log("Enclave deployed to: ", await enclave.getAddress()); - }); From b3c87d1dda5b38ec23daafabeb958a80a0e3d0f1 Mon Sep 17 00:00:00 2001 From: samepant Date: Fri, 13 Sep 2024 13:43:30 -0400 Subject: [PATCH 29/32] keep deployments in git --- packages/evm/.gitignore | 1 - packages/evm/deployments/sepolia/.chainId | 1 + .../sepolia/CyphernodeRegistryOwnable.json | 726 +++++++ packages/evm/deployments/sepolia/Enclave.json | 1757 +++++++++++++++++ .../sepolia/NaiveRegistryFilter.json | 458 +++++ .../d0e6e4f19028714f394c36db62dff2be.json | 95 + 6 files changed, 3037 insertions(+), 1 deletion(-) create mode 100644 packages/evm/deployments/sepolia/.chainId create mode 100644 packages/evm/deployments/sepolia/CyphernodeRegistryOwnable.json create mode 100644 packages/evm/deployments/sepolia/Enclave.json create mode 100644 packages/evm/deployments/sepolia/NaiveRegistryFilter.json create mode 100644 packages/evm/deployments/sepolia/solcInputs/d0e6e4f19028714f394c36db62dff2be.json diff --git a/packages/evm/.gitignore b/packages/evm/.gitignore index ec7522bb..e812c153 100644 --- a/packages/evm/.gitignore +++ b/packages/evm/.gitignore @@ -9,7 +9,6 @@ coverage dist node_modules types -deployments # files *.env diff --git a/packages/evm/deployments/sepolia/.chainId b/packages/evm/deployments/sepolia/.chainId new file mode 100644 index 00000000..bd8d1cd4 --- /dev/null +++ b/packages/evm/deployments/sepolia/.chainId @@ -0,0 +1 @@ +11155111 \ No newline at end of file diff --git a/packages/evm/deployments/sepolia/CyphernodeRegistryOwnable.json b/packages/evm/deployments/sepolia/CyphernodeRegistryOwnable.json new file mode 100644 index 00000000..1dce7765 --- /dev/null +++ b/packages/evm/deployments/sepolia/CyphernodeRegistryOwnable.json @@ -0,0 +1,726 @@ +{ + "address": "0xF9E3aeB059D699Ac4541625DE81062d6D8ad7e85", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "_owner", + "type": "address" + }, + { + "internalType": "address", + "name": "_enclave", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "CommitteeAlreadyPublished", + "type": "error" + }, + { + "inputs": [], + "name": "CommitteeAlreadyRequested", + "type": "error" + }, + { + "inputs": [], + "name": "CommitteeDoesNotExist", + "type": "error" + }, + { + "inputs": [], + "name": "CommitteeNotPublished", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "node", + "type": "address" + } + ], + "name": "CyphernodeNotEnabled", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidInitialization", + "type": "error" + }, + { + "inputs": [], + "name": "NotInitializing", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyEnclave", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "OwnableInvalidOwner", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "OwnableUnauthorizedAccount", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "e3Id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "publicKey", + "type": "bytes" + } + ], + "name": "CommitteePublished", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "e3Id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "filter", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint32[2]", + "name": "threshold", + "type": "uint32[2]" + } + ], + "name": "CommitteeRequested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "node", + "type": "address" + } + ], + "name": "CyphernodeAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "node", + "type": "address" + } + ], + "name": "CyphernodeRemoved", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "enclave", + "type": "address" + } + ], + "name": "EnclaveSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint64", + "name": "version", + "type": "uint64" + } + ], + "name": "Initialized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "node", + "type": "address" + } + ], + "name": "addCyphernode", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "e3Id", + "type": "uint256" + } + ], + "name": "committeePublicKey", + "outputs": [ + { + "internalType": "bytes", + "name": "publicKey", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "enclave", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_owner", + "type": "address" + }, + { + "internalType": "address", + "name": "_enclave", + "type": "address" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "node", + "type": "address" + } + ], + "name": "isCyphernodeEligible", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "cyphernode", + "type": "address" + } + ], + "name": "isEnabled", + "outputs": [ + { + "internalType": "bool", + "name": "isEnabled", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "e3Id", + "type": "uint256" + } + ], + "name": "publicKeys", + "outputs": [ + { + "internalType": "bytes", + "name": "publicKey", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "e3Id", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "publicKey", + "type": "bytes" + } + ], + "name": "publishCommittee", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "node", + "type": "address" + } + ], + "name": "removeCyphernode", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "e3Id", + "type": "uint256" + }, + { + "internalType": "address", + "name": "filter", + "type": "address" + }, + { + "internalType": "uint32[2]", + "name": "threshold", + "type": "uint32[2]" + } + ], + "name": "requestCommittee", + "outputs": [ + { + "internalType": "bool", + "name": "success", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "e3Id", + "type": "uint256" + } + ], + "name": "requests", + "outputs": [ + { + "internalType": "contract IRegistryFilter", + "name": "filter", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_enclave", + "type": "address" + } + ], + "name": "setEnclave", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "transactionHash": "0x52c081e0009793b5db42f4b17258c27a2a11c40c46df6fad4d183de612d68b43", + "receipt": { + "to": null, + "from": "0x485E60C486671E932fd9C53d4110cdEab1E7F0eb", + "contractAddress": "0xF9E3aeB059D699Ac4541625DE81062d6D8ad7e85", + "transactionIndex": 9, + "gasUsed": "860580", + "logsBloom": "0x00000000000080000001000000000100000000000000000000800000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000001000000000000000000000000000000000000020000000000000000000800000000000000000000000000000000400000800000000000000800000000000000800000000080000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000002000000000004000000000000000020000000000000000000020000000000000000000000000000000001000000000000", + "blockHash": "0x8d6af7fa19913d7eb201f04a7307ee3844cdc4bda86b43ca3ab7e1522b577cab", + "transactionHash": "0x52c081e0009793b5db42f4b17258c27a2a11c40c46df6fad4d183de612d68b43", + "logs": [ + { + "transactionIndex": 9, + "blockNumber": 6668198, + "transactionHash": "0x52c081e0009793b5db42f4b17258c27a2a11c40c46df6fad4d183de612d68b43", + "address": "0xF9E3aeB059D699Ac4541625DE81062d6D8ad7e85", + "topics": [ + "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x000000000000000000000000485e60c486671e932fd9c53d4110cdeab1e7f0eb" + ], + "data": "0x", + "logIndex": 16, + "blockHash": "0x8d6af7fa19913d7eb201f04a7307ee3844cdc4bda86b43ca3ab7e1522b577cab" + }, + { + "transactionIndex": 9, + "blockNumber": 6668198, + "transactionHash": "0x52c081e0009793b5db42f4b17258c27a2a11c40c46df6fad4d183de612d68b43", + "address": "0xF9E3aeB059D699Ac4541625DE81062d6D8ad7e85", + "topics": [ + "0x2c8267accd82e977550ed2349c73311183cd22e306347be4453c8d130995e3c9", + "0x000000000000000000000000083b0ae25fd41469fd8857027b40e3f49a169375" + ], + "data": "0x", + "logIndex": 17, + "blockHash": "0x8d6af7fa19913d7eb201f04a7307ee3844cdc4bda86b43ca3ab7e1522b577cab" + }, + { + "transactionIndex": 9, + "blockNumber": 6668198, + "transactionHash": "0x52c081e0009793b5db42f4b17258c27a2a11c40c46df6fad4d183de612d68b43", + "address": "0xF9E3aeB059D699Ac4541625DE81062d6D8ad7e85", + "topics": [ + "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", + "0x000000000000000000000000485e60c486671e932fd9c53d4110cdeab1e7f0eb", + "0x000000000000000000000000485e60c486671e932fd9c53d4110cdeab1e7f0eb" + ], + "data": "0x", + "logIndex": 18, + "blockHash": "0x8d6af7fa19913d7eb201f04a7307ee3844cdc4bda86b43ca3ab7e1522b577cab" + }, + { + "transactionIndex": 9, + "blockNumber": 6668198, + "transactionHash": "0x52c081e0009793b5db42f4b17258c27a2a11c40c46df6fad4d183de612d68b43", + "address": "0xF9E3aeB059D699Ac4541625DE81062d6D8ad7e85", + "topics": [ + "0xc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d2" + ], + "data": "0x0000000000000000000000000000000000000000000000000000000000000001", + "logIndex": 19, + "blockHash": "0x8d6af7fa19913d7eb201f04a7307ee3844cdc4bda86b43ca3ab7e1522b577cab" + } + ], + "blockNumber": 6668198, + "cumulativeGasUsed": "2286050", + "status": 1, + "byzantium": true + }, + "args": [ + "0x485E60C486671E932fd9C53d4110cdEab1E7F0eb", + "0x083b0AE25fD41469Fd8857027B40e3f49A169375" + ], + "numDeployments": 1, + "solcInputHash": "d0e6e4f19028714f394c36db62dff2be", + "metadata": "{\"compiler\":{\"version\":\"0.8.26+commit.8a97fa7a\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_enclave\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"CommitteeAlreadyPublished\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CommitteeAlreadyRequested\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CommitteeDoesNotExist\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CommitteeNotPublished\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"node\",\"type\":\"address\"}],\"name\":\"CyphernodeNotEnabled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidInitialization\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NotInitializing\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyEnclave\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"OwnableInvalidOwner\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"OwnableUnauthorizedAccount\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"e3Id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"publicKey\",\"type\":\"bytes\"}],\"name\":\"CommitteePublished\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"e3Id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"filter\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint32[2]\",\"name\":\"threshold\",\"type\":\"uint32[2]\"}],\"name\":\"CommitteeRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"node\",\"type\":\"address\"}],\"name\":\"CyphernodeAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"node\",\"type\":\"address\"}],\"name\":\"CyphernodeRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"enclave\",\"type\":\"address\"}],\"name\":\"EnclaveSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"version\",\"type\":\"uint64\"}],\"name\":\"Initialized\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"node\",\"type\":\"address\"}],\"name\":\"addCyphernode\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"e3Id\",\"type\":\"uint256\"}],\"name\":\"committeePublicKey\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"publicKey\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"enclave\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_enclave\",\"type\":\"address\"}],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"node\",\"type\":\"address\"}],\"name\":\"isCyphernodeEligible\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"cyphernode\",\"type\":\"address\"}],\"name\":\"isEnabled\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"e3Id\",\"type\":\"uint256\"}],\"name\":\"publicKeys\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"publicKey\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"e3Id\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"publicKey\",\"type\":\"bytes\"}],\"name\":\"publishCommittee\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"node\",\"type\":\"address\"}],\"name\":\"removeCyphernode\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"e3Id\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"filter\",\"type\":\"address\"},{\"internalType\":\"uint32[2]\",\"name\":\"threshold\",\"type\":\"uint32[2]\"}],\"name\":\"requestCommittee\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"e3Id\",\"type\":\"uint256\"}],\"name\":\"requests\",\"outputs\":[{\"internalType\":\"contract IRegistryFilter\",\"name\":\"filter\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_enclave\",\"type\":\"address\"}],\"name\":\"setEnclave\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"errors\":{\"InvalidInitialization()\":[{\"details\":\"The contract is already initialized.\"}],\"NotInitializing()\":[{\"details\":\"The contract is not initializing.\"}],\"OwnableInvalidOwner(address)\":[{\"details\":\"The owner is not a valid owner account. (eg. `address(0)`)\"}],\"OwnableUnauthorizedAccount(address)\":[{\"details\":\"The caller account is not authorized to perform an operation.\"}]},\"events\":{\"CommitteePublished(uint256,bytes)\":{\"params\":{\"e3Id\":\"ID of the E3 for which the committee was selected.\",\"publicKey\":\"Public key of the committee.\"}},\"CommitteeRequested(uint256,address,uint32[2])\":{\"params\":{\"e3Id\":\"ID of the E3 for which the committee was selected.\",\"filter\":\"Address of the contract that will coordinate committee selection.\",\"threshold\":\"The M/N threshold for the committee.\"}},\"EnclaveSet(address)\":{\"params\":{\"enclave\":\"Address of the enclave contract.\"}},\"Initialized(uint64)\":{\"details\":\"Triggered when the contract has been initialized or reinitialized.\"}},\"kind\":\"dev\",\"methods\":{\"committeePublicKey(uint256)\":{\"details\":\"This function MUST revert if no committee has been requested for the given E3.This function MUST revert if the committee has not yet published a public key.\",\"params\":{\"e3Id\":\"ID of the E3 for which to get the committee public key.\"},\"returns\":{\"publicKey\":\"The public key of the committee.\"}},\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"renounceOwnership()\":{\"details\":\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby disabling any functionality that is only available to the owner.\"},\"requestCommittee(uint256,address,uint32[2])\":{\"details\":\"This function MUST revert when not called by the Enclave contract.\",\"params\":{\"e3Id\":\"ID of the E3 for which to select the committee.\",\"filter\":\"The address of the filter responsible for the committee selection process.\",\"threshold\":\"The M/N threshold for the committee.\"},\"returns\":{\"success\":\"True if committee selection was successfully initiated.\"}},\"transferOwnership(address)\":{\"details\":\"Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.\"}},\"version\":1},\"userdoc\":{\"events\":{\"CommitteePublished(uint256,bytes)\":{\"notice\":\"This event MUST be emitted when a committee is selected for an E3.\"},\"CommitteeRequested(uint256,address,uint32[2])\":{\"notice\":\"This event MUST be emitted when a committee is selected for an E3.\"},\"CyphernodeAdded(address)\":{\"notice\":\"This event MUST be emitted when a cyphernode is added to the registry.\"},\"CyphernodeRemoved(address)\":{\"notice\":\"This event MUST be emitted when a cyphernode is removed from the registry.\"},\"EnclaveSet(address)\":{\"notice\":\"This event MUST be emitted when `enclave` is set.\"}},\"kind\":\"user\",\"methods\":{\"committeePublicKey(uint256)\":{\"notice\":\"This function should be called by the Enclave contract to get the public key of a committee.\"},\"requestCommittee(uint256,address,uint32[2])\":{\"notice\":\"Initiates the committee selection process for a specified E3.\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/registry/CyphernodeRegistryOwnable.sol\":\"CyphernodeRegistryOwnable\"},\"evmVersion\":\"paris\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"none\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":800},\"remappings\":[],\"viaIR\":true},\"sources\":{\"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {ContextUpgradeable} from \\\"../utils/ContextUpgradeable.sol\\\";\\nimport {Initializable} from \\\"../proxy/utils/Initializable.sol\\\";\\n\\n/**\\n * @dev Contract module which provides a basic access control mechanism, where\\n * there is an account (an owner) that can be granted exclusive access to\\n * specific functions.\\n *\\n * The initial owner is set to the address provided by the deployer. This can\\n * later be changed with {transferOwnership}.\\n *\\n * This module is used through inheritance. It will make available the modifier\\n * `onlyOwner`, which can be applied to your functions to restrict their use to\\n * the owner.\\n */\\nabstract contract OwnableUpgradeable is Initializable, ContextUpgradeable {\\n /// @custom:storage-location erc7201:openzeppelin.storage.Ownable\\n struct OwnableStorage {\\n address _owner;\\n }\\n\\n // keccak256(abi.encode(uint256(keccak256(\\\"openzeppelin.storage.Ownable\\\")) - 1)) & ~bytes32(uint256(0xff))\\n bytes32 private constant OwnableStorageLocation = 0x9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300;\\n\\n function _getOwnableStorage() private pure returns (OwnableStorage storage $) {\\n assembly {\\n $.slot := OwnableStorageLocation\\n }\\n }\\n\\n /**\\n * @dev The caller account is not authorized to perform an operation.\\n */\\n error OwnableUnauthorizedAccount(address account);\\n\\n /**\\n * @dev The owner is not a valid owner account. (eg. `address(0)`)\\n */\\n error OwnableInvalidOwner(address owner);\\n\\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\\n\\n /**\\n * @dev Initializes the contract setting the address provided by the deployer as the initial owner.\\n */\\n function __Ownable_init(address initialOwner) internal onlyInitializing {\\n __Ownable_init_unchained(initialOwner);\\n }\\n\\n function __Ownable_init_unchained(address initialOwner) internal onlyInitializing {\\n if (initialOwner == address(0)) {\\n revert OwnableInvalidOwner(address(0));\\n }\\n _transferOwnership(initialOwner);\\n }\\n\\n /**\\n * @dev Throws if called by any account other than the owner.\\n */\\n modifier onlyOwner() {\\n _checkOwner();\\n _;\\n }\\n\\n /**\\n * @dev Returns the address of the current owner.\\n */\\n function owner() public view virtual returns (address) {\\n OwnableStorage storage $ = _getOwnableStorage();\\n return $._owner;\\n }\\n\\n /**\\n * @dev Throws if the sender is not the owner.\\n */\\n function _checkOwner() internal view virtual {\\n if (owner() != _msgSender()) {\\n revert OwnableUnauthorizedAccount(_msgSender());\\n }\\n }\\n\\n /**\\n * @dev Leaves the contract without owner. It will not be possible to call\\n * `onlyOwner` functions. Can only be called by the current owner.\\n *\\n * NOTE: Renouncing ownership will leave the contract without an owner,\\n * thereby disabling any functionality that is only available to the owner.\\n */\\n function renounceOwnership() public virtual onlyOwner {\\n _transferOwnership(address(0));\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Can only be called by the current owner.\\n */\\n function transferOwnership(address newOwner) public virtual onlyOwner {\\n if (newOwner == address(0)) {\\n revert OwnableInvalidOwner(address(0));\\n }\\n _transferOwnership(newOwner);\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Internal function without access restriction.\\n */\\n function _transferOwnership(address newOwner) internal virtual {\\n OwnableStorage storage $ = _getOwnableStorage();\\n address oldOwner = $._owner;\\n $._owner = newOwner;\\n emit OwnershipTransferred(oldOwner, newOwner);\\n }\\n}\\n\",\"keccak256\":\"0xc163fcf9bb10138631a9ba5564df1fa25db9adff73bd9ee868a8ae1858fe093a\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.0.0) (proxy/utils/Initializable.sol)\\n\\npragma solidity ^0.8.20;\\n\\n/**\\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\\n * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an\\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\\n *\\n * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be\\n * reused. This mechanism prevents re-execution of each \\\"step\\\" but allows the creation of new initialization steps in\\n * case an upgrade adds a module that needs to be initialized.\\n *\\n * For example:\\n *\\n * [.hljs-theme-light.nopadding]\\n * ```solidity\\n * contract MyToken is ERC20Upgradeable {\\n * function initialize() initializer public {\\n * __ERC20_init(\\\"MyToken\\\", \\\"MTK\\\");\\n * }\\n * }\\n *\\n * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {\\n * function initializeV2() reinitializer(2) public {\\n * __ERC20Permit_init(\\\"MyToken\\\");\\n * }\\n * }\\n * ```\\n *\\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\\n * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.\\n *\\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\\n *\\n * [CAUTION]\\n * ====\\n * Avoid leaving a contract uninitialized.\\n *\\n * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation\\n * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke\\n * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:\\n *\\n * [.hljs-theme-light.nopadding]\\n * ```\\n * /// @custom:oz-upgrades-unsafe-allow constructor\\n * constructor() {\\n * _disableInitializers();\\n * }\\n * ```\\n * ====\\n */\\nabstract contract Initializable {\\n /**\\n * @dev Storage of the initializable contract.\\n *\\n * It's implemented on a custom ERC-7201 namespace to reduce the risk of storage collisions\\n * when using with upgradeable contracts.\\n *\\n * @custom:storage-location erc7201:openzeppelin.storage.Initializable\\n */\\n struct InitializableStorage {\\n /**\\n * @dev Indicates that the contract has been initialized.\\n */\\n uint64 _initialized;\\n /**\\n * @dev Indicates that the contract is in the process of being initialized.\\n */\\n bool _initializing;\\n }\\n\\n // keccak256(abi.encode(uint256(keccak256(\\\"openzeppelin.storage.Initializable\\\")) - 1)) & ~bytes32(uint256(0xff))\\n bytes32 private constant INITIALIZABLE_STORAGE = 0xf0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00;\\n\\n /**\\n * @dev The contract is already initialized.\\n */\\n error InvalidInitialization();\\n\\n /**\\n * @dev The contract is not initializing.\\n */\\n error NotInitializing();\\n\\n /**\\n * @dev Triggered when the contract has been initialized or reinitialized.\\n */\\n event Initialized(uint64 version);\\n\\n /**\\n * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,\\n * `onlyInitializing` functions can be used to initialize parent contracts.\\n *\\n * Similar to `reinitializer(1)`, except that in the context of a constructor an `initializer` may be invoked any\\n * number of times. This behavior in the constructor can be useful during testing and is not expected to be used in\\n * production.\\n *\\n * Emits an {Initialized} event.\\n */\\n modifier initializer() {\\n // solhint-disable-next-line var-name-mixedcase\\n InitializableStorage storage $ = _getInitializableStorage();\\n\\n // Cache values to avoid duplicated sloads\\n bool isTopLevelCall = !$._initializing;\\n uint64 initialized = $._initialized;\\n\\n // Allowed calls:\\n // - initialSetup: the contract is not in the initializing state and no previous version was\\n // initialized\\n // - construction: the contract is initialized at version 1 (no reininitialization) and the\\n // current contract is just being deployed\\n bool initialSetup = initialized == 0 && isTopLevelCall;\\n bool construction = initialized == 1 && address(this).code.length == 0;\\n\\n if (!initialSetup && !construction) {\\n revert InvalidInitialization();\\n }\\n $._initialized = 1;\\n if (isTopLevelCall) {\\n $._initializing = true;\\n }\\n _;\\n if (isTopLevelCall) {\\n $._initializing = false;\\n emit Initialized(1);\\n }\\n }\\n\\n /**\\n * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the\\n * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be\\n * used to initialize parent contracts.\\n *\\n * A reinitializer may be used after the original initialization step. This is essential to configure modules that\\n * are added through upgrades and that require initialization.\\n *\\n * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`\\n * cannot be nested. If one is invoked in the context of another, execution will revert.\\n *\\n * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in\\n * a contract, executing them in the right order is up to the developer or operator.\\n *\\n * WARNING: Setting the version to 2**64 - 1 will prevent any future reinitialization.\\n *\\n * Emits an {Initialized} event.\\n */\\n modifier reinitializer(uint64 version) {\\n // solhint-disable-next-line var-name-mixedcase\\n InitializableStorage storage $ = _getInitializableStorage();\\n\\n if ($._initializing || $._initialized >= version) {\\n revert InvalidInitialization();\\n }\\n $._initialized = version;\\n $._initializing = true;\\n _;\\n $._initializing = false;\\n emit Initialized(version);\\n }\\n\\n /**\\n * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the\\n * {initializer} and {reinitializer} modifiers, directly or indirectly.\\n */\\n modifier onlyInitializing() {\\n _checkInitializing();\\n _;\\n }\\n\\n /**\\n * @dev Reverts if the contract is not in an initializing state. See {onlyInitializing}.\\n */\\n function _checkInitializing() internal view virtual {\\n if (!_isInitializing()) {\\n revert NotInitializing();\\n }\\n }\\n\\n /**\\n * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.\\n * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized\\n * to any version. It is recommended to use this to lock implementation contracts that are designed to be called\\n * through proxies.\\n *\\n * Emits an {Initialized} event the first time it is successfully executed.\\n */\\n function _disableInitializers() internal virtual {\\n // solhint-disable-next-line var-name-mixedcase\\n InitializableStorage storage $ = _getInitializableStorage();\\n\\n if ($._initializing) {\\n revert InvalidInitialization();\\n }\\n if ($._initialized != type(uint64).max) {\\n $._initialized = type(uint64).max;\\n emit Initialized(type(uint64).max);\\n }\\n }\\n\\n /**\\n * @dev Returns the highest version that has been initialized. See {reinitializer}.\\n */\\n function _getInitializedVersion() internal view returns (uint64) {\\n return _getInitializableStorage()._initialized;\\n }\\n\\n /**\\n * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.\\n */\\n function _isInitializing() internal view returns (bool) {\\n return _getInitializableStorage()._initializing;\\n }\\n\\n /**\\n * @dev Returns a pointer to the storage namespace.\\n */\\n // solhint-disable-next-line var-name-mixedcase\\n function _getInitializableStorage() private pure returns (InitializableStorage storage $) {\\n assembly {\\n $.slot := INITIALIZABLE_STORAGE\\n }\\n }\\n}\\n\",\"keccak256\":\"0x631188737069917d2f909d29ce62c4d48611d326686ba6683e26b72a23bfac0b\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)\\n\\npragma solidity ^0.8.20;\\nimport {Initializable} from \\\"../proxy/utils/Initializable.sol\\\";\\n\\n/**\\n * @dev Provides information about the current execution context, including the\\n * sender of the transaction and its data. While these are generally available\\n * via msg.sender and msg.data, they should not be accessed in such a direct\\n * manner, since when dealing with meta-transactions the account sending and\\n * paying for execution may not be the actual sender (as far as an application\\n * is concerned).\\n *\\n * This contract is only required for intermediate, library-like contracts.\\n */\\nabstract contract ContextUpgradeable is Initializable {\\n function __Context_init() internal onlyInitializing {\\n }\\n\\n function __Context_init_unchained() internal onlyInitializing {\\n }\\n function _msgSender() internal view virtual returns (address) {\\n return msg.sender;\\n }\\n\\n function _msgData() internal view virtual returns (bytes calldata) {\\n return msg.data;\\n }\\n\\n function _contextSuffixLength() internal view virtual returns (uint256) {\\n return 0;\\n }\\n}\\n\",\"keccak256\":\"0xdbef5f0c787055227243a7318ef74c8a5a1108ca3a07f2b3a00ef67769e1e397\",\"license\":\"MIT\"},\"contracts/interfaces/ICyphernodeRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: LGPL-3.0-only\\npragma solidity >=0.8.26;\\n\\ninterface ICyphernodeRegistry {\\n /// @notice This event MUST be emitted when a committee is selected for an E3.\\n /// @param e3Id ID of the E3 for which the committee was selected.\\n /// @param filter Address of the contract that will coordinate committee selection.\\n /// @param threshold The M/N threshold for the committee.\\n event CommitteeRequested(\\n uint256 indexed e3Id,\\n address filter,\\n uint32[2] threshold\\n );\\n\\n /// @notice This event MUST be emitted when a committee is selected for an E3.\\n /// @param e3Id ID of the E3 for which the committee was selected.\\n /// @param publicKey Public key of the committee.\\n event CommitteePublished(uint256 indexed e3Id, bytes publicKey);\\n\\n /// @notice This event MUST be emitted when `enclave` is set.\\n /// @param enclave Address of the enclave contract.\\n event EnclaveSet(address indexed enclave);\\n\\n /// @notice This event MUST be emitted when a cyphernode is added to the registry.\\n event CyphernodeAdded(address indexed node);\\n\\n /// @notice This event MUST be emitted when a cyphernode is removed from the registry.\\n event CyphernodeRemoved(address indexed node);\\n\\n function isCyphernodeEligible(address cyphernode) external returns (bool);\\n\\n /// @notice Initiates the committee selection process for a specified E3.\\n /// @dev This function MUST revert when not called by the Enclave contract.\\n /// @param e3Id ID of the E3 for which to select the committee.\\n /// @param filter The address of the filter responsible for the committee selection process.\\n /// @param threshold The M/N threshold for the committee.\\n /// @return success True if committee selection was successfully initiated.\\n function requestCommittee(\\n uint256 e3Id,\\n address filter,\\n uint32[2] calldata threshold\\n ) external returns (bool success);\\n\\n /// @notice Publishes the public key resulting from the committee selection process.\\n /// @dev This function MUST revert if not called by the previously selected filter.\\n /// @param e3Id ID of the E3 for which to select the committee.\\n /// @param publicKey The public key generated by the selected committee.\\n function publishCommittee(\\n uint256 e3Id,\\n bytes calldata proof,\\n bytes calldata publicKey\\n ) external;\\n\\n /// @notice This function should be called by the Enclave contract to get the public key of a committee.\\n /// @dev This function MUST revert if no committee has been requested for the given E3.\\n /// @dev This function MUST revert if the committee has not yet published a public key.\\n /// @param e3Id ID of the E3 for which to get the committee public key.\\n /// @return publicKey The public key of the committee.\\n function committeePublicKey(\\n uint256 e3Id\\n ) external view returns (bytes memory);\\n}\\n\",\"keccak256\":\"0x60af5d66db32528f5032fe083218f180ab83f3199bcf090bed7249c28bc18104\",\"license\":\"LGPL-3.0-only\"},\"contracts/interfaces/IRegistryFilter.sol\":{\"content\":\"// SPDX-License-Identifier: LGPL-3.0-only\\npragma solidity >=0.8.26;\\n\\ninterface IRegistryFilter {\\n function requestCommittee(\\n uint256 e3Id,\\n uint32[2] calldata threshold\\n ) external returns (bool success);\\n}\\n\",\"keccak256\":\"0xec67f88f2cbf46e28d4835669ef3dd2320afe5b0324423944037c16fc3f42195\",\"license\":\"LGPL-3.0-only\"},\"contracts/registry/CyphernodeRegistryOwnable.sol\":{\"content\":\"// SPDX-License-Identifier: LGPL-3.0-only\\npragma solidity >=0.8.26;\\n\\nimport { ICyphernodeRegistry } from \\\"../interfaces/ICyphernodeRegistry.sol\\\";\\nimport { IRegistryFilter } from \\\"../interfaces/IRegistryFilter.sol\\\";\\nimport {\\n OwnableUpgradeable\\n} from \\\"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\\\";\\n\\ncontract CyphernodeRegistryOwnable is ICyphernodeRegistry, OwnableUpgradeable {\\n ////////////////////////////////////////////////////////////\\n // //\\n // Storage Variables //\\n // //\\n ////////////////////////////////////////////////////////////\\n\\n address public enclave;\\n\\n mapping(address cyphernode => bool isEnabled) public isEnabled;\\n\\n mapping(uint256 e3Id => IRegistryFilter filter) public requests;\\n mapping(uint256 e3Id => bytes publicKey) public publicKeys;\\n\\n ////////////////////////////////////////////////////////////\\n // //\\n // Errors //\\n // //\\n ////////////////////////////////////////////////////////////\\n\\n error CommitteeAlreadyRequested();\\n error CommitteeAlreadyPublished();\\n error CommitteeDoesNotExist();\\n error CommitteeNotPublished();\\n error CyphernodeNotEnabled(address node);\\n error OnlyEnclave();\\n\\n ////////////////////////////////////////////////////////////\\n // //\\n // Modifiers //\\n // //\\n ////////////////////////////////////////////////////////////\\n\\n modifier onlyEnclave() {\\n require(msg.sender == enclave, OnlyEnclave());\\n _;\\n }\\n\\n ////////////////////////////////////////////////////////////\\n // //\\n // Initialization //\\n // //\\n ////////////////////////////////////////////////////////////\\n\\n constructor(address _owner, address _enclave) {\\n initialize(_owner, _enclave);\\n }\\n\\n function initialize(address _owner, address _enclave) public initializer {\\n __Ownable_init(msg.sender);\\n setEnclave(_enclave);\\n transferOwnership(_owner);\\n }\\n\\n ////////////////////////////////////////////////////////////\\n // //\\n // Core Entrypoints //\\n // //\\n ////////////////////////////////////////////////////////////\\n\\n function requestCommittee(\\n uint256 e3Id,\\n address filter,\\n uint32[2] calldata threshold\\n ) external onlyEnclave returns (bool success) {\\n require(\\n requests[e3Id] == IRegistryFilter(address(0)),\\n CommitteeAlreadyRequested()\\n );\\n requests[e3Id] = IRegistryFilter(filter);\\n\\n IRegistryFilter(filter).requestCommittee(e3Id, threshold);\\n emit CommitteeRequested(e3Id, filter, threshold);\\n success = true;\\n }\\n\\n function publishCommittee(\\n uint256 e3Id,\\n bytes calldata,\\n bytes calldata publicKey\\n ) external {\\n // only to be published by the filter\\n require(address(requests[e3Id]) == msg.sender, CommitteeDoesNotExist());\\n\\n // for (uint256 i = 0; i < cyphernodes.length; i++) {\\n // require(\\n // isEnabled[cyphernodes[i]] == true,\\n // CyphernodeNotEnabled(cyphernodes[i])\\n // );\\n // }\\n\\n publicKeys[e3Id] = publicKey;\\n emit CommitteePublished(e3Id, publicKey);\\n }\\n\\n ////////////////////////////////////////////////////////////\\n // //\\n // Set Functions //\\n // //\\n ////////////////////////////////////////////////////////////\\n\\n function setEnclave(address _enclave) public onlyOwner {\\n enclave = _enclave;\\n emit EnclaveSet(_enclave);\\n }\\n\\n function addCyphernode(address node) external onlyOwner {\\n isEnabled[node] = true;\\n emit CyphernodeAdded(node);\\n }\\n\\n function removeCyphernode(address node) external onlyOwner {\\n isEnabled[node] = false;\\n emit CyphernodeRemoved(node);\\n }\\n\\n function isCyphernodeEligible(address node) external view returns (bool) {\\n return isEnabled[node];\\n }\\n\\n ////////////////////////////////////////////////////////////\\n // //\\n // Get Functions //\\n // //\\n ////////////////////////////////////////////////////////////\\n\\n function committeePublicKey(\\n uint256 e3Id\\n ) external view returns (bytes memory publicKey) {\\n publicKey = publicKeys[e3Id];\\n require(publicKey.length > 0, CommitteeNotPublished());\\n }\\n}\\n\",\"keccak256\":\"0x4cfad952b8b65dba77a5adf39dba5d1f7ff8d0a3661793bf155fea39f9d3f8e6\",\"license\":\"LGPL-3.0-only\"}},\"version\":1}", + "bytecode": "0x6080346101f957601f61105238819003918201601f19168301916001600160401b038311848410176101fe5780849260409485528339810103126101f957610052602061004b83610214565b9201610214565b60008051602061103283398151915254604081901c60ff16159290916001600160401b038316801590816101f1575b60011490816101e7575b1590816101de575b506101cd576001600160401b031983166001176000805160206110328339815191525561013292846101a2575b506100c96102b0565b6100d16102b0565b6100da33610228565b6100e26102de565b600080546001600160a01b0319166001600160a01b039290921691821781557f2c8267accd82e977550ed2349c73311183cd22e306347be4453c8d130995e3c99080a261012d6102de565b610228565b610146575b604051610d0b90816103278239f35b68ff0000000000000000196000805160206110328339815191525416600080516020611032833981519152557fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d2602060405160018152a1610137565b6001600160481b031916680100000000000000011760008051602061103283398151915255386100c0565b63f92ee8a960e01b60005260046000fd5b90501538610093565b303b15915061008b565b859150610081565b600080fd5b634e487b7160e01b600052604160045260246000fd5b51906001600160a01b03821682036101f957565b6001600160a01b0316801561029a577f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c19930080546001600160a01b0319811683179091556001600160a01b03167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a3565b631e4fbdf760e01b600052600060045260246000fd5b60ff6000805160206110328339815191525460401c16156102cd57565b631afcd79f60e31b60005260046000fd5b7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300546001600160a01b0316330361031157565b63118cdaa760e01b6000523360045260246000fdfe608080604052600436101561001357600080fd5b60003560e01c9081632a8dc588146109b957508063476422f814610952578063485cc9551461074657806370e36bbe146106e3578063715018a61461064a578063770ad208146105e057806381d12c58146105ab5780638da5cb5b146105655780639015d371146105265780639ccb58d5146103cc578063c680f41014610394578063d9bbec9514610170578063dbb06c9314610149578063e82f3b70146100f45763f2fde38b146100c457600080fd5b346100ef5760203660031901126100ef576100ed6100e06109f4565b6100e8610c76565b610bd0565b005b600080fd5b346100ef5760203660031901126100ef57600435600052600360205261011d6040600020610a7c565b805115610138576101349060405191829182610b20565b0390f35b6322e679e360e11b60005260046000fd5b346100ef5760003660031901126100ef5760206001600160a01b0360005416604051908152f35b346100ef5760603660031901126100ef5760043560243567ffffffffffffffff81116100ef576101a4903690600401610b69565b505060443567ffffffffffffffff81116100ef576101c6903690600401610b69565b908260005260026020526001600160a01b0360406000205416330361038357826000526003602052604060002067ffffffffffffffff831161036d5761020c8154610a20565b601f8111610325575b506000601f841160011461029d5791604091847f8d0ca30515bbff1268ae5868080463444e5002373f7bc7d8d8869dca0a5ffc019594600091610292575b508460011b906000198660031b1c19161790555b82825193849260208452816020850152848401376000828201840152601f01601f19168101030190a2005b905082013587610253565b8181526020812090601f198516815b81811061030d57509160409391867f8d0ca30515bbff1268ae5868080463444e5002373f7bc7d8d8869dca0a5ffc01979694106102f3575b5050600184811b019055610267565b830135600019600387901b60f8161c1916905586806102e4565b919260206001819286890135815501940192016102ac565b816000526020600020601f850160051c81019160208610610363575b601f0160051c01905b8181106103575750610215565b6000815560010161034a565b9091508190610341565b634e487b7160e01b600052604160045260246000fd5b632a17a1f360e01b60005260046000fd5b346100ef5760203660031901126100ef5760043560005260036020526101346103c06040600020610a7c565b60405191829182610b20565b346100ef5760803660031901126100ef576004356103e8610a0a565b366084116100ef576001600160a01b03600054163303610515578160005260026020526001600160a01b0360406000205416610504576001600160a01b03168160005260026020526040600020816001600160a01b0319825416179055604051631590527b60e11b815282600482015261046460248201610b97565b6020816064816000865af180156104f8576104bd575b5060607fa17377d4a5c0ff5c67888a6b08d9bf3a8505b47e922b6186b259471ebf12738e916040519081526104b160208201610b97565ba2602060405160018152f35b6020813d6020116104f0575b816104d660209383610a5a565b810103126100ef575180151581036100ef5750606061047a565b3d91506104c9565b6040513d6000823e3d90fd5b6374ff462560e11b60005260046000fd5b63e4c2a7eb60e01b60005260046000fd5b346100ef5760203660031901126100ef576001600160a01b036105476109f4565b166000526001602052602060ff604060002054166040519015158152f35b346100ef5760003660031901126100ef5760206001600160a01b037f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c1993005416604051908152f35b346100ef5760203660031901126100ef57600435600052600260205260206001600160a01b0360406000205416604051908152f35b346100ef5760203660031901126100ef576001600160a01b036106016109f4565b610609610c76565b168060005260016020526040600020600160ff198254161790557f0fdc359cb937ddbe7734e324351ff282307ad333751a9e90f17e7330157ea579600080a2005b346100ef5760003660031901126100ef57610663610c76565b60006001600160a01b037f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300546001600160a01b031981167f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c19930055167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a3005b346100ef5760203660031901126100ef576001600160a01b036107046109f4565b61070c610c76565b16806001600160a01b031960005416176000557f2c8267accd82e977550ed2349c73311183cd22e306347be4453c8d130995e3c9600080a2005b346100ef5760403660031901126100ef5761075f6109f4565b610767610a0a565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00549160ff8360401c16159267ffffffffffffffff81168015908161094a575b6001149081610940575b159081610937575b506109265767ffffffffffffffff1981166001177ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a0055610864926001600160a01b0391856108e7575b5061080b610cbe565b610813610cbe565b61081c33610bd0565b610824610c76565b16806001600160a01b031960005416176000557f2c8267accd82e977550ed2349c73311183cd22e306347be4453c8d130995e3c9600080a26100e8610c76565b61086a57005b68ff0000000000000000197ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a0054167ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00557fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d2602060405160018152a1005b68ffffffffffffffffff191668010000000000000001177ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a005585610802565b63f92ee8a960e01b60005260046000fd5b905015856107b9565b303b1591506107b1565b8591506107a7565b346100ef5760203660031901126100ef576001600160a01b036109736109f4565b61097b610c76565b16806000526001602052604060002060ff1981541690557f07f3f62f2502752da9299b12b0a9966cb97ace5e3ce476d04649d5f588ec4491600080a2005b346100ef5760203660031901126100ef576020906001600160a01b036109dd6109f4565b166000526001825260ff6040600020541615158152f35b600435906001600160a01b03821682036100ef57565b602435906001600160a01b03821682036100ef57565b90600182811c92168015610a50575b6020831014610a3a57565b634e487b7160e01b600052602260045260246000fd5b91607f1691610a2f565b90601f8019910116810190811067ffffffffffffffff82111761036d57604052565b9060405191826000825492610a9084610a20565b8084529360018116908115610afe5750600114610ab7575b50610ab592500383610a5a565b565b90506000929192526020600020906000915b818310610ae2575050906020610ab59282010138610aa8565b6020919350806001915483858901015201910190918492610ac9565b905060209250610ab594915060ff191682840152151560051b82010138610aa8565b91909160208152825180602083015260005b818110610b53575060409293506000838284010152601f8019910116010190565b8060208092870101516040828601015201610b32565b9181601f840112156100ef5782359167ffffffffffffffff83116100ef57602083818601950101116100ef57565b60446000915b60028310610baa57505050565b81359063ffffffff82168092036100ef5760208160019382935201920192019190610b9d565b6001600160a01b03168015610c60576001600160a01b037f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c19930054826001600160a01b03198216177f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c19930055167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a3565b631e4fbdf760e01b600052600060045260246000fd5b6001600160a01b037f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c19930054163303610ca957565b63118cdaa760e01b6000523360045260246000fd5b60ff7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a005460401c1615610ced57565b631afcd79f60e31b60005260046000fdfea164736f6c634300081a000af0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00", + "deployedBytecode": "0x608080604052600436101561001357600080fd5b60003560e01c9081632a8dc588146109b957508063476422f814610952578063485cc9551461074657806370e36bbe146106e3578063715018a61461064a578063770ad208146105e057806381d12c58146105ab5780638da5cb5b146105655780639015d371146105265780639ccb58d5146103cc578063c680f41014610394578063d9bbec9514610170578063dbb06c9314610149578063e82f3b70146100f45763f2fde38b146100c457600080fd5b346100ef5760203660031901126100ef576100ed6100e06109f4565b6100e8610c76565b610bd0565b005b600080fd5b346100ef5760203660031901126100ef57600435600052600360205261011d6040600020610a7c565b805115610138576101349060405191829182610b20565b0390f35b6322e679e360e11b60005260046000fd5b346100ef5760003660031901126100ef5760206001600160a01b0360005416604051908152f35b346100ef5760603660031901126100ef5760043560243567ffffffffffffffff81116100ef576101a4903690600401610b69565b505060443567ffffffffffffffff81116100ef576101c6903690600401610b69565b908260005260026020526001600160a01b0360406000205416330361038357826000526003602052604060002067ffffffffffffffff831161036d5761020c8154610a20565b601f8111610325575b506000601f841160011461029d5791604091847f8d0ca30515bbff1268ae5868080463444e5002373f7bc7d8d8869dca0a5ffc019594600091610292575b508460011b906000198660031b1c19161790555b82825193849260208452816020850152848401376000828201840152601f01601f19168101030190a2005b905082013587610253565b8181526020812090601f198516815b81811061030d57509160409391867f8d0ca30515bbff1268ae5868080463444e5002373f7bc7d8d8869dca0a5ffc01979694106102f3575b5050600184811b019055610267565b830135600019600387901b60f8161c1916905586806102e4565b919260206001819286890135815501940192016102ac565b816000526020600020601f850160051c81019160208610610363575b601f0160051c01905b8181106103575750610215565b6000815560010161034a565b9091508190610341565b634e487b7160e01b600052604160045260246000fd5b632a17a1f360e01b60005260046000fd5b346100ef5760203660031901126100ef5760043560005260036020526101346103c06040600020610a7c565b60405191829182610b20565b346100ef5760803660031901126100ef576004356103e8610a0a565b366084116100ef576001600160a01b03600054163303610515578160005260026020526001600160a01b0360406000205416610504576001600160a01b03168160005260026020526040600020816001600160a01b0319825416179055604051631590527b60e11b815282600482015261046460248201610b97565b6020816064816000865af180156104f8576104bd575b5060607fa17377d4a5c0ff5c67888a6b08d9bf3a8505b47e922b6186b259471ebf12738e916040519081526104b160208201610b97565ba2602060405160018152f35b6020813d6020116104f0575b816104d660209383610a5a565b810103126100ef575180151581036100ef5750606061047a565b3d91506104c9565b6040513d6000823e3d90fd5b6374ff462560e11b60005260046000fd5b63e4c2a7eb60e01b60005260046000fd5b346100ef5760203660031901126100ef576001600160a01b036105476109f4565b166000526001602052602060ff604060002054166040519015158152f35b346100ef5760003660031901126100ef5760206001600160a01b037f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c1993005416604051908152f35b346100ef5760203660031901126100ef57600435600052600260205260206001600160a01b0360406000205416604051908152f35b346100ef5760203660031901126100ef576001600160a01b036106016109f4565b610609610c76565b168060005260016020526040600020600160ff198254161790557f0fdc359cb937ddbe7734e324351ff282307ad333751a9e90f17e7330157ea579600080a2005b346100ef5760003660031901126100ef57610663610c76565b60006001600160a01b037f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300546001600160a01b031981167f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c19930055167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a3005b346100ef5760203660031901126100ef576001600160a01b036107046109f4565b61070c610c76565b16806001600160a01b031960005416176000557f2c8267accd82e977550ed2349c73311183cd22e306347be4453c8d130995e3c9600080a2005b346100ef5760403660031901126100ef5761075f6109f4565b610767610a0a565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00549160ff8360401c16159267ffffffffffffffff81168015908161094a575b6001149081610940575b159081610937575b506109265767ffffffffffffffff1981166001177ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a0055610864926001600160a01b0391856108e7575b5061080b610cbe565b610813610cbe565b61081c33610bd0565b610824610c76565b16806001600160a01b031960005416176000557f2c8267accd82e977550ed2349c73311183cd22e306347be4453c8d130995e3c9600080a26100e8610c76565b61086a57005b68ff0000000000000000197ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a0054167ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00557fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d2602060405160018152a1005b68ffffffffffffffffff191668010000000000000001177ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a005585610802565b63f92ee8a960e01b60005260046000fd5b905015856107b9565b303b1591506107b1565b8591506107a7565b346100ef5760203660031901126100ef576001600160a01b036109736109f4565b61097b610c76565b16806000526001602052604060002060ff1981541690557f07f3f62f2502752da9299b12b0a9966cb97ace5e3ce476d04649d5f588ec4491600080a2005b346100ef5760203660031901126100ef576020906001600160a01b036109dd6109f4565b166000526001825260ff6040600020541615158152f35b600435906001600160a01b03821682036100ef57565b602435906001600160a01b03821682036100ef57565b90600182811c92168015610a50575b6020831014610a3a57565b634e487b7160e01b600052602260045260246000fd5b91607f1691610a2f565b90601f8019910116810190811067ffffffffffffffff82111761036d57604052565b9060405191826000825492610a9084610a20565b8084529360018116908115610afe5750600114610ab7575b50610ab592500383610a5a565b565b90506000929192526020600020906000915b818310610ae2575050906020610ab59282010138610aa8565b6020919350806001915483858901015201910190918492610ac9565b905060209250610ab594915060ff191682840152151560051b82010138610aa8565b91909160208152825180602083015260005b818110610b53575060409293506000838284010152601f8019910116010190565b8060208092870101516040828601015201610b32565b9181601f840112156100ef5782359167ffffffffffffffff83116100ef57602083818601950101116100ef57565b60446000915b60028310610baa57505050565b81359063ffffffff82168092036100ef5760208160019382935201920192019190610b9d565b6001600160a01b03168015610c60576001600160a01b037f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c19930054826001600160a01b03198216177f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c19930055167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a3565b631e4fbdf760e01b600052600060045260246000fd5b6001600160a01b037f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c19930054163303610ca957565b63118cdaa760e01b6000523360045260246000fd5b60ff7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a005460401c1615610ced57565b631afcd79f60e31b60005260046000fdfea164736f6c634300081a000a", + "devdoc": { + "errors": { + "InvalidInitialization()": [ + { + "details": "The contract is already initialized." + } + ], + "NotInitializing()": [ + { + "details": "The contract is not initializing." + } + ], + "OwnableInvalidOwner(address)": [ + { + "details": "The owner is not a valid owner account. (eg. `address(0)`)" + } + ], + "OwnableUnauthorizedAccount(address)": [ + { + "details": "The caller account is not authorized to perform an operation." + } + ] + }, + "events": { + "CommitteePublished(uint256,bytes)": { + "params": { + "e3Id": "ID of the E3 for which the committee was selected.", + "publicKey": "Public key of the committee." + } + }, + "CommitteeRequested(uint256,address,uint32[2])": { + "params": { + "e3Id": "ID of the E3 for which the committee was selected.", + "filter": "Address of the contract that will coordinate committee selection.", + "threshold": "The M/N threshold for the committee." + } + }, + "EnclaveSet(address)": { + "params": { + "enclave": "Address of the enclave contract." + } + }, + "Initialized(uint64)": { + "details": "Triggered when the contract has been initialized or reinitialized." + } + }, + "kind": "dev", + "methods": { + "committeePublicKey(uint256)": { + "details": "This function MUST revert if no committee has been requested for the given E3.This function MUST revert if the committee has not yet published a public key.", + "params": { + "e3Id": "ID of the E3 for which to get the committee public key." + }, + "returns": { + "publicKey": "The public key of the committee." + } + }, + "owner()": { + "details": "Returns the address of the current owner." + }, + "renounceOwnership()": { + "details": "Leaves the contract without owner. It will not be possible to call `onlyOwner` functions. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby disabling any functionality that is only available to the owner." + }, + "requestCommittee(uint256,address,uint32[2])": { + "details": "This function MUST revert when not called by the Enclave contract.", + "params": { + "e3Id": "ID of the E3 for which to select the committee.", + "filter": "The address of the filter responsible for the committee selection process.", + "threshold": "The M/N threshold for the committee." + }, + "returns": { + "success": "True if committee selection was successfully initiated." + } + }, + "transferOwnership(address)": { + "details": "Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner." + } + }, + "version": 1 + }, + "userdoc": { + "events": { + "CommitteePublished(uint256,bytes)": { + "notice": "This event MUST be emitted when a committee is selected for an E3." + }, + "CommitteeRequested(uint256,address,uint32[2])": { + "notice": "This event MUST be emitted when a committee is selected for an E3." + }, + "CyphernodeAdded(address)": { + "notice": "This event MUST be emitted when a cyphernode is added to the registry." + }, + "CyphernodeRemoved(address)": { + "notice": "This event MUST be emitted when a cyphernode is removed from the registry." + }, + "EnclaveSet(address)": { + "notice": "This event MUST be emitted when `enclave` is set." + } + }, + "kind": "user", + "methods": { + "committeePublicKey(uint256)": { + "notice": "This function should be called by the Enclave contract to get the public key of a committee." + }, + "requestCommittee(uint256,address,uint32[2])": { + "notice": "Initiates the committee selection process for a specified E3." + } + }, + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 1860, + "contract": "contracts/registry/CyphernodeRegistryOwnable.sol:CyphernodeRegistryOwnable", + "label": "enclave", + "offset": 0, + "slot": "0", + "type": "t_address" + }, + { + "astId": 1864, + "contract": "contracts/registry/CyphernodeRegistryOwnable.sol:CyphernodeRegistryOwnable", + "label": "isEnabled", + "offset": 0, + "slot": "1", + "type": "t_mapping(t_address,t_bool)" + }, + { + "astId": 1869, + "contract": "contracts/registry/CyphernodeRegistryOwnable.sol:CyphernodeRegistryOwnable", + "label": "requests", + "offset": 0, + "slot": "2", + "type": "t_mapping(t_uint256,t_contract(IRegistryFilter)1846)" + }, + { + "astId": 1873, + "contract": "contracts/registry/CyphernodeRegistryOwnable.sol:CyphernodeRegistryOwnable", + "label": "publicKeys", + "offset": 0, + "slot": "3", + "type": "t_mapping(t_uint256,t_bytes_storage)" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_bool": { + "encoding": "inplace", + "label": "bool", + "numberOfBytes": "1" + }, + "t_bytes_storage": { + "encoding": "bytes", + "label": "bytes", + "numberOfBytes": "32" + }, + "t_contract(IRegistryFilter)1846": { + "encoding": "inplace", + "label": "contract IRegistryFilter", + "numberOfBytes": "20" + }, + "t_mapping(t_address,t_bool)": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => bool)", + "numberOfBytes": "32", + "value": "t_bool" + }, + "t_mapping(t_uint256,t_bytes_storage)": { + "encoding": "mapping", + "key": "t_uint256", + "label": "mapping(uint256 => bytes)", + "numberOfBytes": "32", + "value": "t_bytes_storage" + }, + "t_mapping(t_uint256,t_contract(IRegistryFilter)1846)": { + "encoding": "mapping", + "key": "t_uint256", + "label": "mapping(uint256 => contract IRegistryFilter)", + "numberOfBytes": "32", + "value": "t_contract(IRegistryFilter)1846" + }, + "t_uint256": { + "encoding": "inplace", + "label": "uint256", + "numberOfBytes": "32" + } + } + } +} \ No newline at end of file diff --git a/packages/evm/deployments/sepolia/Enclave.json b/packages/evm/deployments/sepolia/Enclave.json new file mode 100644 index 00000000..0cd92d01 --- /dev/null +++ b/packages/evm/deployments/sepolia/Enclave.json @@ -0,0 +1,1757 @@ +{ + "address": "0x083b0AE25fD41469Fd8857027B40e3f49A169375", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "_owner", + "type": "address" + }, + { + "internalType": "contract ICyphernodeRegistry", + "name": "_cyphernodeRegistry", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_maxDuration", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "e3Id", + "type": "uint256" + } + ], + "name": "CiphertextOutputAlreadyPublished", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "e3Id", + "type": "uint256" + } + ], + "name": "CiphertextOutputNotPublished", + "type": "error" + }, + { + "inputs": [], + "name": "CommitteeSelectionFailed", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "contract IComputationModule", + "name": "computationModule", + "type": "address" + } + ], + "name": "ComputationModuleNotAllowed", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "e3Id", + "type": "uint256" + } + ], + "name": "E3AlreadyActivated", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "e3Id", + "type": "uint256" + } + ], + "name": "E3DoesNotExist", + "type": "error" + }, + { + "inputs": [], + "name": "E3Expired", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "e3Id", + "type": "uint256" + } + ], + "name": "E3NotActivated", + "type": "error" + }, + { + "inputs": [], + "name": "E3NotReady", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "e3Id", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "expiration", + "type": "uint256" + } + ], + "name": "InputDeadlineNotPassed", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "e3Id", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "expiration", + "type": "uint256" + } + ], + "name": "InputDeadlinePassed", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidComputation", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "contract ICyphernodeRegistry", + "name": "cyphernodeRegistry", + "type": "address" + } + ], + "name": "InvalidCyphernodeRegistry", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "duration", + "type": "uint256" + } + ], + "name": "InvalidDuration", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidExecutionModuleSetup", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidInitialization", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidInput", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "output", + "type": "bytes" + } + ], + "name": "InvalidOutput", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidStartWindow", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint32[2]", + "name": "threshold", + "type": "uint32[2]" + } + ], + "name": "InvalidThreshold", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "module", + "type": "address" + } + ], + "name": "ModuleAlreadyEnabled", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "module", + "type": "address" + } + ], + "name": "ModuleNotEnabled", + "type": "error" + }, + { + "inputs": [], + "name": "NotInitializing", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "OwnableInvalidOwner", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "OwnableUnauthorizedAccount", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "PaymentRequired", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "e3Id", + "type": "uint256" + } + ], + "name": "PlaintextOutputAlreadyPublished", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "e3Id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "ciphertextOutput", + "type": "bytes" + } + ], + "name": "CiphertextOutputPublished", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "contract IComputationModule", + "name": "computationModule", + "type": "address" + } + ], + "name": "ComputationModuleDisabled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "contract IComputationModule", + "name": "computationModule", + "type": "address" + } + ], + "name": "ComputationModuleEnabled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "cyphernodeRegistry", + "type": "address" + } + ], + "name": "CyphernodeRegistrySet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "e3Id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "expiration", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "committeePublicKey", + "type": "bytes" + } + ], + "name": "E3Activated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "e3Id", + "type": "uint256" + }, + { + "components": [ + { + "internalType": "uint32[2]", + "name": "threshold", + "type": "uint32[2]" + }, + { + "internalType": "uint256[2]", + "name": "startWindow", + "type": "uint256[2]" + }, + { + "internalType": "uint256", + "name": "duration", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "expiration", + "type": "uint256" + }, + { + "internalType": "contract IComputationModule", + "name": "computationModule", + "type": "address" + }, + { + "internalType": "contract IExecutionModule", + "name": "executionModule", + "type": "address" + }, + { + "internalType": "contract IInputValidator", + "name": "inputValidator", + "type": "address" + }, + { + "internalType": "contract IOutputVerifier", + "name": "outputVerifier", + "type": "address" + }, + { + "internalType": "bytes", + "name": "committeePublicKey", + "type": "bytes" + }, + { + "internalType": "bytes[]", + "name": "inputs", + "type": "bytes[]" + }, + { + "internalType": "bytes", + "name": "ciphertextOutput", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "plaintextOutput", + "type": "bytes" + } + ], + "indexed": false, + "internalType": "struct E3", + "name": "e3", + "type": "tuple" + }, + { + "indexed": false, + "internalType": "address", + "name": "filter", + "type": "address" + }, + { + "indexed": true, + "internalType": "contract IComputationModule", + "name": "computationModule", + "type": "address" + }, + { + "indexed": true, + "internalType": "contract IExecutionModule", + "name": "executionModule", + "type": "address" + } + ], + "name": "E3Requested", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "contract IExecutionModule", + "name": "executionModule", + "type": "address" + } + ], + "name": "ExecutionModuleDisabled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "contract IExecutionModule", + "name": "executionModule", + "type": "address" + } + ], + "name": "ExecutionModuleEnabled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint64", + "name": "version", + "type": "uint64" + } + ], + "name": "Initialized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "e3Id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "InputPublished", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "maxDuration", + "type": "uint256" + } + ], + "name": "MaxDurationSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "e3Id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "plaintextOutput", + "type": "bytes" + } + ], + "name": "PlaintextOutputPublished", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "e3Id", + "type": "uint256" + } + ], + "name": "activate", + "outputs": [ + { + "internalType": "bool", + "name": "success", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IComputationModule", + "name": "computationModule", + "type": "address" + } + ], + "name": "computationModules", + "outputs": [ + { + "internalType": "bool", + "name": "allowed", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "cyphernodeRegistry", + "outputs": [ + { + "internalType": "contract ICyphernodeRegistry", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IComputationModule", + "name": "computationModule", + "type": "address" + } + ], + "name": "disableComputationModule", + "outputs": [ + { + "internalType": "bool", + "name": "success", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IExecutionModule", + "name": "executionModule", + "type": "address" + } + ], + "name": "disableExecutionModule", + "outputs": [ + { + "internalType": "bool", + "name": "success", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "e3s", + "outputs": [ + { + "internalType": "uint256", + "name": "duration", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "expiration", + "type": "uint256" + }, + { + "internalType": "contract IComputationModule", + "name": "computationModule", + "type": "address" + }, + { + "internalType": "contract IExecutionModule", + "name": "executionModule", + "type": "address" + }, + { + "internalType": "contract IInputValidator", + "name": "inputValidator", + "type": "address" + }, + { + "internalType": "contract IOutputVerifier", + "name": "outputVerifier", + "type": "address" + }, + { + "internalType": "bytes", + "name": "committeePublicKey", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "ciphertextOutput", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "plaintextOutput", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IComputationModule", + "name": "computationModule", + "type": "address" + } + ], + "name": "enableComputationModule", + "outputs": [ + { + "internalType": "bool", + "name": "success", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IExecutionModule", + "name": "executionModule", + "type": "address" + } + ], + "name": "enableExecutionModule", + "outputs": [ + { + "internalType": "bool", + "name": "success", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IExecutionModule", + "name": "executionModule", + "type": "address" + } + ], + "name": "executionModules", + "outputs": [ + { + "internalType": "bool", + "name": "allowed", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "e3Id", + "type": "uint256" + } + ], + "name": "getE3", + "outputs": [ + { + "components": [ + { + "internalType": "uint32[2]", + "name": "threshold", + "type": "uint32[2]" + }, + { + "internalType": "uint256[2]", + "name": "startWindow", + "type": "uint256[2]" + }, + { + "internalType": "uint256", + "name": "duration", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "expiration", + "type": "uint256" + }, + { + "internalType": "contract IComputationModule", + "name": "computationModule", + "type": "address" + }, + { + "internalType": "contract IExecutionModule", + "name": "executionModule", + "type": "address" + }, + { + "internalType": "contract IInputValidator", + "name": "inputValidator", + "type": "address" + }, + { + "internalType": "contract IOutputVerifier", + "name": "outputVerifier", + "type": "address" + }, + { + "internalType": "bytes", + "name": "committeePublicKey", + "type": "bytes" + }, + { + "internalType": "bytes[]", + "name": "inputs", + "type": "bytes[]" + }, + { + "internalType": "bytes", + "name": "ciphertextOutput", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "plaintextOutput", + "type": "bytes" + } + ], + "internalType": "struct E3", + "name": "e3", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_owner", + "type": "address" + }, + { + "internalType": "contract ICyphernodeRegistry", + "name": "_cyphernodeRegistry", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_maxDuration", + "type": "uint256" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "maxDuration", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "nexte3Id", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "e3Id", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "publishCiphertextOutput", + "outputs": [ + { + "internalType": "bool", + "name": "success", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "e3Id", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "publishInput", + "outputs": [ + { + "internalType": "bool", + "name": "success", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "e3Id", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "publishPlaintextOutput", + "outputs": [ + { + "internalType": "bool", + "name": "success", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "filter", + "type": "address" + }, + { + "internalType": "uint32[2]", + "name": "threshold", + "type": "uint32[2]" + }, + { + "internalType": "uint256[2]", + "name": "startWindow", + "type": "uint256[2]" + }, + { + "internalType": "uint256", + "name": "duration", + "type": "uint256" + }, + { + "internalType": "contract IComputationModule", + "name": "computationModule", + "type": "address" + }, + { + "internalType": "bytes", + "name": "computationParams", + "type": "bytes" + }, + { + "internalType": "contract IExecutionModule", + "name": "executionModule", + "type": "address" + }, + { + "internalType": "bytes", + "name": "emParams", + "type": "bytes" + } + ], + "name": "request", + "outputs": [ + { + "internalType": "uint256", + "name": "e3Id", + "type": "uint256" + }, + { + "components": [ + { + "internalType": "uint32[2]", + "name": "threshold", + "type": "uint32[2]" + }, + { + "internalType": "uint256[2]", + "name": "startWindow", + "type": "uint256[2]" + }, + { + "internalType": "uint256", + "name": "duration", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "expiration", + "type": "uint256" + }, + { + "internalType": "contract IComputationModule", + "name": "computationModule", + "type": "address" + }, + { + "internalType": "contract IExecutionModule", + "name": "executionModule", + "type": "address" + }, + { + "internalType": "contract IInputValidator", + "name": "inputValidator", + "type": "address" + }, + { + "internalType": "contract IOutputVerifier", + "name": "outputVerifier", + "type": "address" + }, + { + "internalType": "bytes", + "name": "committeePublicKey", + "type": "bytes" + }, + { + "internalType": "bytes[]", + "name": "inputs", + "type": "bytes[]" + }, + { + "internalType": "bytes", + "name": "ciphertextOutput", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "plaintextOutput", + "type": "bytes" + } + ], + "internalType": "struct E3", + "name": "e3", + "type": "tuple" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [], + "name": "requests", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract ICyphernodeRegistry", + "name": "_cyphernodeRegistry", + "type": "address" + } + ], + "name": "setCyphernodeRegistry", + "outputs": [ + { + "internalType": "bool", + "name": "success", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_maxDuration", + "type": "uint256" + } + ], + "name": "setMaxDuration", + "outputs": [ + { + "internalType": "bool", + "name": "success", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "transactionHash": "0x2e2dae8a05e34e82484cfaec005240ec707a4c0c6b6a4f6bcf8fb0f45c0c5b6f", + "receipt": { + "to": null, + "from": "0x485E60C486671E932fd9C53d4110cdEab1E7F0eb", + "contractAddress": "0x083b0AE25fD41469Fd8857027B40e3f49A169375", + "transactionIndex": 286, + "gasUsed": "2071049", + "logsBloom": "0x00000000000000000000000000000100000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000100000000000000000020000000000000000000800000000000000200000000800000000400000000008000000000800000000000000000000000880000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002004000000000000000020000000000000000000020000000001200000000800000000000000000000000000", + "blockHash": "0x516557b80e512cc5ad78bd83f7668e4d4f1dc08eb95582806d98fb0569c0517b", + "transactionHash": "0x2e2dae8a05e34e82484cfaec005240ec707a4c0c6b6a4f6bcf8fb0f45c0c5b6f", + "logs": [ + { + "transactionIndex": 286, + "blockNumber": 6662691, + "transactionHash": "0x2e2dae8a05e34e82484cfaec005240ec707a4c0c6b6a4f6bcf8fb0f45c0c5b6f", + "address": "0x083b0AE25fD41469Fd8857027B40e3f49A169375", + "topics": [ + "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x000000000000000000000000485e60c486671e932fd9c53d4110cdeab1e7f0eb" + ], + "data": "0x", + "logIndex": 369, + "blockHash": "0x516557b80e512cc5ad78bd83f7668e4d4f1dc08eb95582806d98fb0569c0517b" + }, + { + "transactionIndex": 286, + "blockNumber": 6662691, + "transactionHash": "0x2e2dae8a05e34e82484cfaec005240ec707a4c0c6b6a4f6bcf8fb0f45c0c5b6f", + "address": "0x083b0AE25fD41469Fd8857027B40e3f49A169375", + "topics": [ + "0xba0716ba1ee2ea8ecc4c64119b4537cdb42a99d82acf92af5b87607b8b523552" + ], + "data": "0x0000000000000000000000000000000000000000000000000000000000278d00", + "logIndex": 370, + "blockHash": "0x516557b80e512cc5ad78bd83f7668e4d4f1dc08eb95582806d98fb0569c0517b" + }, + { + "transactionIndex": 286, + "blockNumber": 6662691, + "transactionHash": "0x2e2dae8a05e34e82484cfaec005240ec707a4c0c6b6a4f6bcf8fb0f45c0c5b6f", + "address": "0x083b0AE25fD41469Fd8857027B40e3f49A169375", + "topics": [ + "0x016ea868599173c3163f65dea5e4677b2be5f0ececb4ec15d1166a27de35a533" + ], + "data": "0x0000000000000000000000000000000000000000000000000000000000000001", + "logIndex": 371, + "blockHash": "0x516557b80e512cc5ad78bd83f7668e4d4f1dc08eb95582806d98fb0569c0517b" + }, + { + "transactionIndex": 286, + "blockNumber": 6662691, + "transactionHash": "0x2e2dae8a05e34e82484cfaec005240ec707a4c0c6b6a4f6bcf8fb0f45c0c5b6f", + "address": "0x083b0AE25fD41469Fd8857027B40e3f49A169375", + "topics": [ + "0xc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d2" + ], + "data": "0x0000000000000000000000000000000000000000000000000000000000000001", + "logIndex": 372, + "blockHash": "0x516557b80e512cc5ad78bd83f7668e4d4f1dc08eb95582806d98fb0569c0517b" + } + ], + "blockNumber": 6662691, + "cumulativeGasUsed": "25038564", + "status": 1, + "byzantium": true + }, + "args": [ + "0x485E60C486671E932fd9C53d4110cdEab1E7F0eb", + "0x0000000000000000000000000000000000000001", + 2592000 + ], + "numDeployments": 1, + "solcInputHash": "d0e6e4f19028714f394c36db62dff2be", + "metadata": "{\"compiler\":{\"version\":\"0.8.26+commit.8a97fa7a\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"},{\"internalType\":\"contract ICyphernodeRegistry\",\"name\":\"_cyphernodeRegistry\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_maxDuration\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"e3Id\",\"type\":\"uint256\"}],\"name\":\"CiphertextOutputAlreadyPublished\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"e3Id\",\"type\":\"uint256\"}],\"name\":\"CiphertextOutputNotPublished\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CommitteeSelectionFailed\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"contract IComputationModule\",\"name\":\"computationModule\",\"type\":\"address\"}],\"name\":\"ComputationModuleNotAllowed\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"e3Id\",\"type\":\"uint256\"}],\"name\":\"E3AlreadyActivated\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"e3Id\",\"type\":\"uint256\"}],\"name\":\"E3DoesNotExist\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"E3Expired\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"e3Id\",\"type\":\"uint256\"}],\"name\":\"E3NotActivated\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"E3NotReady\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"e3Id\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"expiration\",\"type\":\"uint256\"}],\"name\":\"InputDeadlineNotPassed\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"e3Id\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"expiration\",\"type\":\"uint256\"}],\"name\":\"InputDeadlinePassed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidComputation\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"contract ICyphernodeRegistry\",\"name\":\"cyphernodeRegistry\",\"type\":\"address\"}],\"name\":\"InvalidCyphernodeRegistry\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"duration\",\"type\":\"uint256\"}],\"name\":\"InvalidDuration\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidExecutionModuleSetup\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidInitialization\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidInput\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"output\",\"type\":\"bytes\"}],\"name\":\"InvalidOutput\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidStartWindow\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint32[2]\",\"name\":\"threshold\",\"type\":\"uint32[2]\"}],\"name\":\"InvalidThreshold\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"module\",\"type\":\"address\"}],\"name\":\"ModuleAlreadyEnabled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"module\",\"type\":\"address\"}],\"name\":\"ModuleNotEnabled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NotInitializing\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"OwnableInvalidOwner\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"OwnableUnauthorizedAccount\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"PaymentRequired\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"e3Id\",\"type\":\"uint256\"}],\"name\":\"PlaintextOutputAlreadyPublished\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"e3Id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"ciphertextOutput\",\"type\":\"bytes\"}],\"name\":\"CiphertextOutputPublished\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract IComputationModule\",\"name\":\"computationModule\",\"type\":\"address\"}],\"name\":\"ComputationModuleDisabled\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract IComputationModule\",\"name\":\"computationModule\",\"type\":\"address\"}],\"name\":\"ComputationModuleEnabled\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"cyphernodeRegistry\",\"type\":\"address\"}],\"name\":\"CyphernodeRegistrySet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"e3Id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"expiration\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"committeePublicKey\",\"type\":\"bytes\"}],\"name\":\"E3Activated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"e3Id\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"uint32[2]\",\"name\":\"threshold\",\"type\":\"uint32[2]\"},{\"internalType\":\"uint256[2]\",\"name\":\"startWindow\",\"type\":\"uint256[2]\"},{\"internalType\":\"uint256\",\"name\":\"duration\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"expiration\",\"type\":\"uint256\"},{\"internalType\":\"contract IComputationModule\",\"name\":\"computationModule\",\"type\":\"address\"},{\"internalType\":\"contract IExecutionModule\",\"name\":\"executionModule\",\"type\":\"address\"},{\"internalType\":\"contract IInputValidator\",\"name\":\"inputValidator\",\"type\":\"address\"},{\"internalType\":\"contract IOutputVerifier\",\"name\":\"outputVerifier\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"committeePublicKey\",\"type\":\"bytes\"},{\"internalType\":\"bytes[]\",\"name\":\"inputs\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes\",\"name\":\"ciphertextOutput\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"plaintextOutput\",\"type\":\"bytes\"}],\"indexed\":false,\"internalType\":\"struct E3\",\"name\":\"e3\",\"type\":\"tuple\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"filter\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"contract IComputationModule\",\"name\":\"computationModule\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"contract IExecutionModule\",\"name\":\"executionModule\",\"type\":\"address\"}],\"name\":\"E3Requested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract IExecutionModule\",\"name\":\"executionModule\",\"type\":\"address\"}],\"name\":\"ExecutionModuleDisabled\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract IExecutionModule\",\"name\":\"executionModule\",\"type\":\"address\"}],\"name\":\"ExecutionModuleEnabled\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"version\",\"type\":\"uint64\"}],\"name\":\"Initialized\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"e3Id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"InputPublished\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"maxDuration\",\"type\":\"uint256\"}],\"name\":\"MaxDurationSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"e3Id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"plaintextOutput\",\"type\":\"bytes\"}],\"name\":\"PlaintextOutputPublished\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"e3Id\",\"type\":\"uint256\"}],\"name\":\"activate\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract IComputationModule\",\"name\":\"computationModule\",\"type\":\"address\"}],\"name\":\"computationModules\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"allowed\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"cyphernodeRegistry\",\"outputs\":[{\"internalType\":\"contract ICyphernodeRegistry\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract IComputationModule\",\"name\":\"computationModule\",\"type\":\"address\"}],\"name\":\"disableComputationModule\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract IExecutionModule\",\"name\":\"executionModule\",\"type\":\"address\"}],\"name\":\"disableExecutionModule\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"e3s\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"duration\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"expiration\",\"type\":\"uint256\"},{\"internalType\":\"contract IComputationModule\",\"name\":\"computationModule\",\"type\":\"address\"},{\"internalType\":\"contract IExecutionModule\",\"name\":\"executionModule\",\"type\":\"address\"},{\"internalType\":\"contract IInputValidator\",\"name\":\"inputValidator\",\"type\":\"address\"},{\"internalType\":\"contract IOutputVerifier\",\"name\":\"outputVerifier\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"committeePublicKey\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"ciphertextOutput\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"plaintextOutput\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract IComputationModule\",\"name\":\"computationModule\",\"type\":\"address\"}],\"name\":\"enableComputationModule\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract IExecutionModule\",\"name\":\"executionModule\",\"type\":\"address\"}],\"name\":\"enableExecutionModule\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract IExecutionModule\",\"name\":\"executionModule\",\"type\":\"address\"}],\"name\":\"executionModules\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"allowed\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"e3Id\",\"type\":\"uint256\"}],\"name\":\"getE3\",\"outputs\":[{\"components\":[{\"internalType\":\"uint32[2]\",\"name\":\"threshold\",\"type\":\"uint32[2]\"},{\"internalType\":\"uint256[2]\",\"name\":\"startWindow\",\"type\":\"uint256[2]\"},{\"internalType\":\"uint256\",\"name\":\"duration\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"expiration\",\"type\":\"uint256\"},{\"internalType\":\"contract IComputationModule\",\"name\":\"computationModule\",\"type\":\"address\"},{\"internalType\":\"contract IExecutionModule\",\"name\":\"executionModule\",\"type\":\"address\"},{\"internalType\":\"contract IInputValidator\",\"name\":\"inputValidator\",\"type\":\"address\"},{\"internalType\":\"contract IOutputVerifier\",\"name\":\"outputVerifier\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"committeePublicKey\",\"type\":\"bytes\"},{\"internalType\":\"bytes[]\",\"name\":\"inputs\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes\",\"name\":\"ciphertextOutput\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"plaintextOutput\",\"type\":\"bytes\"}],\"internalType\":\"struct E3\",\"name\":\"e3\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"},{\"internalType\":\"contract ICyphernodeRegistry\",\"name\":\"_cyphernodeRegistry\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_maxDuration\",\"type\":\"uint256\"}],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"maxDuration\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"nexte3Id\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"e3Id\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"publishCiphertextOutput\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"e3Id\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"publishInput\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"e3Id\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"publishPlaintextOutput\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"filter\",\"type\":\"address\"},{\"internalType\":\"uint32[2]\",\"name\":\"threshold\",\"type\":\"uint32[2]\"},{\"internalType\":\"uint256[2]\",\"name\":\"startWindow\",\"type\":\"uint256[2]\"},{\"internalType\":\"uint256\",\"name\":\"duration\",\"type\":\"uint256\"},{\"internalType\":\"contract IComputationModule\",\"name\":\"computationModule\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"computationParams\",\"type\":\"bytes\"},{\"internalType\":\"contract IExecutionModule\",\"name\":\"executionModule\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"emParams\",\"type\":\"bytes\"}],\"name\":\"request\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"e3Id\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"uint32[2]\",\"name\":\"threshold\",\"type\":\"uint32[2]\"},{\"internalType\":\"uint256[2]\",\"name\":\"startWindow\",\"type\":\"uint256[2]\"},{\"internalType\":\"uint256\",\"name\":\"duration\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"expiration\",\"type\":\"uint256\"},{\"internalType\":\"contract IComputationModule\",\"name\":\"computationModule\",\"type\":\"address\"},{\"internalType\":\"contract IExecutionModule\",\"name\":\"executionModule\",\"type\":\"address\"},{\"internalType\":\"contract IInputValidator\",\"name\":\"inputValidator\",\"type\":\"address\"},{\"internalType\":\"contract IOutputVerifier\",\"name\":\"outputVerifier\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"committeePublicKey\",\"type\":\"bytes\"},{\"internalType\":\"bytes[]\",\"name\":\"inputs\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes\",\"name\":\"ciphertextOutput\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"plaintextOutput\",\"type\":\"bytes\"}],\"internalType\":\"struct E3\",\"name\":\"e3\",\"type\":\"tuple\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"requests\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract ICyphernodeRegistry\",\"name\":\"_cyphernodeRegistry\",\"type\":\"address\"}],\"name\":\"setCyphernodeRegistry\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_maxDuration\",\"type\":\"uint256\"}],\"name\":\"setMaxDuration\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"errors\":{\"InvalidInitialization()\":[{\"details\":\"The contract is already initialized.\"}],\"NotInitializing()\":[{\"details\":\"The contract is not initializing.\"}],\"OwnableInvalidOwner(address)\":[{\"details\":\"The owner is not a valid owner account. (eg. `address(0)`)\"}],\"OwnableUnauthorizedAccount(address)\":[{\"details\":\"The caller account is not authorized to perform an operation.\"}]},\"events\":{\"CiphertextOutputPublished(uint256,bytes)\":{\"params\":{\"ciphertextOutput\":\"ABI encoded ciphertext output.\",\"e3Id\":\"ID of the E3.\"}},\"ComputationModuleDisabled(address)\":{\"params\":{\"computationModule\":\"The address of the computation module.\"}},\"ComputationModuleEnabled(address)\":{\"params\":{\"computationModule\":\"The address of the computation module.\"}},\"CyphernodeRegistrySet(address)\":{\"params\":{\"cyphernodeRegistry\":\"The address of the CyphernodeRegistry contract.\"}},\"E3Activated(uint256,uint256,bytes)\":{\"params\":{\"committeePublicKey\":\"Public key of the committee.\",\"e3Id\":\"ID of the E3.\",\"expiration\":\"Timestamp when committee duties expire.\"}},\"E3Requested(uint256,(uint32[2],uint256[2],uint256,uint256,address,address,address,address,bytes,bytes[],bytes,bytes),address,address,address)\":{\"params\":{\"computationModule\":\"Address of the Computation module selected.\",\"e3\":\"Details of the E3.\",\"e3Id\":\"ID of the E3.\",\"executionModule\":\"Address of the execution module selected.\",\"filter\":\"Address of the pool of nodes from which the Cypher Node committee was selected.\"}},\"ExecutionModuleDisabled(address)\":{\"params\":{\"executionModule\":\"The address of the execution module.\"}},\"ExecutionModuleEnabled(address)\":{\"params\":{\"executionModule\":\"The address of the execution module.\"}},\"Initialized(uint64)\":{\"details\":\"Triggered when the contract has been initialized or reinitialized.\"},\"InputPublished(uint256,bytes)\":{\"params\":{\"data\":\"ABI encoded input data.\",\"e3Id\":\"ID of the E3.\"}},\"MaxDurationSet(uint256)\":{\"params\":{\"maxDuration\":\"The maximum duration of a computation in seconds.\"}},\"PlaintextOutputPublished(uint256,bytes)\":{\"params\":{\"e3Id\":\"ID of the E3.\",\"plaintextOutput\":\"ABI encoded plaintext output.\"}}},\"kind\":\"dev\",\"methods\":{\"activate(uint256)\":{\"details\":\"This function MUST emit the E3Activated event.This function MUST revert if the given E3 has not yet been requested.This function MUST revert if the selected node committee has not yet published a public key.\",\"params\":{\"e3Id\":\"ID of the E3.\"}},\"constructor\":{\"params\":{\"_maxDuration\":\"The maximum duration of a computation in seconds\",\"_owner\":\"The owner of this contract\"}},\"getE3(uint256)\":{\"details\":\"This function MUST revert if the E3 does not exist.\",\"params\":{\"e3Id\":\"ID of the E3.\"},\"returns\":{\"e3\":\"The struct representing the requested E3.\"}},\"initialize(address,address,uint256)\":{\"params\":{\"_maxDuration\":\"The maximum duration of a computation in seconds\",\"_owner\":\"The owner of this contract\"}},\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"publishCiphertextOutput(uint256,bytes)\":{\"details\":\"This function MUST emit the CiphertextOutputPublished event.\",\"params\":{\"data\":\"ABI encoded output data to verify.\",\"e3Id\":\"ID of the E3.\"},\"returns\":{\"success\":\"True if the output was successfully published.\"}},\"publishInput(uint256,bytes)\":{\"details\":\"This function MUST revert if the E3 is not yet activated.This function MUST emit the InputPublished event.\",\"params\":{\"data\":\"ABI encoded input data to publish.\",\"e3Id\":\"ID of the E3.\"},\"returns\":{\"success\":\"True if the input was successfully published.\"}},\"publishPlaintextOutput(uint256,bytes)\":{\"details\":\"This function MUST revert if the output has not been published.This function MUST emit the PlaintextOutputPublished event.\",\"params\":{\"data\":\"ABI encoded output data to decrypt.\",\"e3Id\":\"ID of the E3.\"},\"returns\":{\"success\":\"True if the output was successfully decrypted.\"}},\"renounceOwnership()\":{\"details\":\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby disabling any functionality that is only available to the owner.\"},\"request(address,uint32[2],uint256[2],uint256,address,bytes,address,bytes)\":{\"details\":\"This function MUST emit the E3Requested event.\",\"params\":{\"computationModule\":\"Address of the computation module.\",\"computationParams\":\"ABI encoded computation parameters.\",\"duration\":\"The duration of the computation in seconds.\",\"emParams\":\"ABI encoded execution module parameters.\",\"executionModule\":\"Address of the execution module.\",\"filter\":\"IDs of the pool of nodes from which to select the committee.\",\"threshold\":\"The M/N threshold for the committee.\"},\"returns\":{\"e3\":\"The E3 struct.\",\"e3Id\":\"ID of the E3.\"}},\"setMaxDuration(uint256)\":{\"params\":{\"_maxDuration\":\"The maximum duration of a computation in seconds.\"},\"returns\":{\"success\":\"True if the max duration was successfully set.\"}},\"transferOwnership(address)\":{\"details\":\"Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.\"}},\"version\":1},\"userdoc\":{\"events\":{\"CiphertextOutputPublished(uint256,bytes)\":{\"notice\":\"This event MUST be emitted when the ciphertext output of an Encrypted Execution Environment (E3) is successfully published.\"},\"ComputationModuleDisabled(address)\":{\"notice\":\"This event MUST be emitted any time a computation module is disabled.\"},\"ComputationModuleEnabled(address)\":{\"notice\":\"This event MUST be emitted any time a computation module is enabled.\"},\"CyphernodeRegistrySet(address)\":{\"notice\":\"This event MUST be emitted any time the CyphernodeRegistry is set.\"},\"E3Activated(uint256,uint256,bytes)\":{\"notice\":\"This event MUST be emitted when an Encrypted Execution Environment (E3) is successfully activated.\"},\"E3Requested(uint256,(uint32[2],uint256[2],uint256,uint256,address,address,address,address,bytes,bytes[],bytes,bytes),address,address,address)\":{\"notice\":\"This event MUST be emitted when an Encrypted Execution Environment (E3) is successfully requested.\"},\"ExecutionModuleDisabled(address)\":{\"notice\":\"This event MUST be emitted any time an execution module is disabled.\"},\"ExecutionModuleEnabled(address)\":{\"notice\":\"This event MUST be emitted any time an execution module is enabled.\"},\"InputPublished(uint256,bytes)\":{\"notice\":\"This event MUST be emitted when an input to an Encrypted Execution Environment (E3) is successfully published.\"},\"MaxDurationSet(uint256)\":{\"notice\":\"This event MUST be emitted any time the `maxDuration` is set.\"},\"PlaintextOutputPublished(uint256,bytes)\":{\"notice\":\"This event MUST be emitted when the plaintext output of an Encrypted Execution Environment (E3) is successfully published.\"}},\"kind\":\"user\",\"methods\":{\"activate(uint256)\":{\"notice\":\"This function should be called to activate an Encrypted Execution Environment (E3) once it has been initialized and is ready for input.\"},\"getE3(uint256)\":{\"notice\":\"This function should be called to retrieve the details of an Encrypted Execution Environment (E3).\"},\"publishCiphertextOutput(uint256,bytes)\":{\"notice\":\"This function should be called to publish output data for an Encrypted Execution Environment (E3).\"},\"publishInput(uint256,bytes)\":{\"notice\":\"This function should be called to publish input data for Encrypted Execution Environment (E3).\"},\"publishPlaintextOutput(uint256,bytes)\":{\"notice\":\"This function publishes the plaintext output of an Encrypted Execution Environment (E3).\"},\"request(address,uint32[2],uint256[2],uint256,address,bytes,address,bytes)\":{\"notice\":\"This function should be called to request a computation within an Encrypted Execution Environment (E3).\"},\"setMaxDuration(uint256)\":{\"notice\":\"This function should be called to set the maximum duration of requested computations.\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/Enclave.sol\":\"Enclave\"},\"evmVersion\":\"paris\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"none\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":800},\"remappings\":[],\"viaIR\":true},\"sources\":{\"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {ContextUpgradeable} from \\\"../utils/ContextUpgradeable.sol\\\";\\nimport {Initializable} from \\\"../proxy/utils/Initializable.sol\\\";\\n\\n/**\\n * @dev Contract module which provides a basic access control mechanism, where\\n * there is an account (an owner) that can be granted exclusive access to\\n * specific functions.\\n *\\n * The initial owner is set to the address provided by the deployer. This can\\n * later be changed with {transferOwnership}.\\n *\\n * This module is used through inheritance. It will make available the modifier\\n * `onlyOwner`, which can be applied to your functions to restrict their use to\\n * the owner.\\n */\\nabstract contract OwnableUpgradeable is Initializable, ContextUpgradeable {\\n /// @custom:storage-location erc7201:openzeppelin.storage.Ownable\\n struct OwnableStorage {\\n address _owner;\\n }\\n\\n // keccak256(abi.encode(uint256(keccak256(\\\"openzeppelin.storage.Ownable\\\")) - 1)) & ~bytes32(uint256(0xff))\\n bytes32 private constant OwnableStorageLocation = 0x9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300;\\n\\n function _getOwnableStorage() private pure returns (OwnableStorage storage $) {\\n assembly {\\n $.slot := OwnableStorageLocation\\n }\\n }\\n\\n /**\\n * @dev The caller account is not authorized to perform an operation.\\n */\\n error OwnableUnauthorizedAccount(address account);\\n\\n /**\\n * @dev The owner is not a valid owner account. (eg. `address(0)`)\\n */\\n error OwnableInvalidOwner(address owner);\\n\\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\\n\\n /**\\n * @dev Initializes the contract setting the address provided by the deployer as the initial owner.\\n */\\n function __Ownable_init(address initialOwner) internal onlyInitializing {\\n __Ownable_init_unchained(initialOwner);\\n }\\n\\n function __Ownable_init_unchained(address initialOwner) internal onlyInitializing {\\n if (initialOwner == address(0)) {\\n revert OwnableInvalidOwner(address(0));\\n }\\n _transferOwnership(initialOwner);\\n }\\n\\n /**\\n * @dev Throws if called by any account other than the owner.\\n */\\n modifier onlyOwner() {\\n _checkOwner();\\n _;\\n }\\n\\n /**\\n * @dev Returns the address of the current owner.\\n */\\n function owner() public view virtual returns (address) {\\n OwnableStorage storage $ = _getOwnableStorage();\\n return $._owner;\\n }\\n\\n /**\\n * @dev Throws if the sender is not the owner.\\n */\\n function _checkOwner() internal view virtual {\\n if (owner() != _msgSender()) {\\n revert OwnableUnauthorizedAccount(_msgSender());\\n }\\n }\\n\\n /**\\n * @dev Leaves the contract without owner. It will not be possible to call\\n * `onlyOwner` functions. Can only be called by the current owner.\\n *\\n * NOTE: Renouncing ownership will leave the contract without an owner,\\n * thereby disabling any functionality that is only available to the owner.\\n */\\n function renounceOwnership() public virtual onlyOwner {\\n _transferOwnership(address(0));\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Can only be called by the current owner.\\n */\\n function transferOwnership(address newOwner) public virtual onlyOwner {\\n if (newOwner == address(0)) {\\n revert OwnableInvalidOwner(address(0));\\n }\\n _transferOwnership(newOwner);\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Internal function without access restriction.\\n */\\n function _transferOwnership(address newOwner) internal virtual {\\n OwnableStorage storage $ = _getOwnableStorage();\\n address oldOwner = $._owner;\\n $._owner = newOwner;\\n emit OwnershipTransferred(oldOwner, newOwner);\\n }\\n}\\n\",\"keccak256\":\"0xc163fcf9bb10138631a9ba5564df1fa25db9adff73bd9ee868a8ae1858fe093a\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.0.0) (proxy/utils/Initializable.sol)\\n\\npragma solidity ^0.8.20;\\n\\n/**\\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\\n * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an\\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\\n *\\n * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be\\n * reused. This mechanism prevents re-execution of each \\\"step\\\" but allows the creation of new initialization steps in\\n * case an upgrade adds a module that needs to be initialized.\\n *\\n * For example:\\n *\\n * [.hljs-theme-light.nopadding]\\n * ```solidity\\n * contract MyToken is ERC20Upgradeable {\\n * function initialize() initializer public {\\n * __ERC20_init(\\\"MyToken\\\", \\\"MTK\\\");\\n * }\\n * }\\n *\\n * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {\\n * function initializeV2() reinitializer(2) public {\\n * __ERC20Permit_init(\\\"MyToken\\\");\\n * }\\n * }\\n * ```\\n *\\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\\n * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.\\n *\\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\\n *\\n * [CAUTION]\\n * ====\\n * Avoid leaving a contract uninitialized.\\n *\\n * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation\\n * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke\\n * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:\\n *\\n * [.hljs-theme-light.nopadding]\\n * ```\\n * /// @custom:oz-upgrades-unsafe-allow constructor\\n * constructor() {\\n * _disableInitializers();\\n * }\\n * ```\\n * ====\\n */\\nabstract contract Initializable {\\n /**\\n * @dev Storage of the initializable contract.\\n *\\n * It's implemented on a custom ERC-7201 namespace to reduce the risk of storage collisions\\n * when using with upgradeable contracts.\\n *\\n * @custom:storage-location erc7201:openzeppelin.storage.Initializable\\n */\\n struct InitializableStorage {\\n /**\\n * @dev Indicates that the contract has been initialized.\\n */\\n uint64 _initialized;\\n /**\\n * @dev Indicates that the contract is in the process of being initialized.\\n */\\n bool _initializing;\\n }\\n\\n // keccak256(abi.encode(uint256(keccak256(\\\"openzeppelin.storage.Initializable\\\")) - 1)) & ~bytes32(uint256(0xff))\\n bytes32 private constant INITIALIZABLE_STORAGE = 0xf0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00;\\n\\n /**\\n * @dev The contract is already initialized.\\n */\\n error InvalidInitialization();\\n\\n /**\\n * @dev The contract is not initializing.\\n */\\n error NotInitializing();\\n\\n /**\\n * @dev Triggered when the contract has been initialized or reinitialized.\\n */\\n event Initialized(uint64 version);\\n\\n /**\\n * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,\\n * `onlyInitializing` functions can be used to initialize parent contracts.\\n *\\n * Similar to `reinitializer(1)`, except that in the context of a constructor an `initializer` may be invoked any\\n * number of times. This behavior in the constructor can be useful during testing and is not expected to be used in\\n * production.\\n *\\n * Emits an {Initialized} event.\\n */\\n modifier initializer() {\\n // solhint-disable-next-line var-name-mixedcase\\n InitializableStorage storage $ = _getInitializableStorage();\\n\\n // Cache values to avoid duplicated sloads\\n bool isTopLevelCall = !$._initializing;\\n uint64 initialized = $._initialized;\\n\\n // Allowed calls:\\n // - initialSetup: the contract is not in the initializing state and no previous version was\\n // initialized\\n // - construction: the contract is initialized at version 1 (no reininitialization) and the\\n // current contract is just being deployed\\n bool initialSetup = initialized == 0 && isTopLevelCall;\\n bool construction = initialized == 1 && address(this).code.length == 0;\\n\\n if (!initialSetup && !construction) {\\n revert InvalidInitialization();\\n }\\n $._initialized = 1;\\n if (isTopLevelCall) {\\n $._initializing = true;\\n }\\n _;\\n if (isTopLevelCall) {\\n $._initializing = false;\\n emit Initialized(1);\\n }\\n }\\n\\n /**\\n * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the\\n * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be\\n * used to initialize parent contracts.\\n *\\n * A reinitializer may be used after the original initialization step. This is essential to configure modules that\\n * are added through upgrades and that require initialization.\\n *\\n * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`\\n * cannot be nested. If one is invoked in the context of another, execution will revert.\\n *\\n * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in\\n * a contract, executing them in the right order is up to the developer or operator.\\n *\\n * WARNING: Setting the version to 2**64 - 1 will prevent any future reinitialization.\\n *\\n * Emits an {Initialized} event.\\n */\\n modifier reinitializer(uint64 version) {\\n // solhint-disable-next-line var-name-mixedcase\\n InitializableStorage storage $ = _getInitializableStorage();\\n\\n if ($._initializing || $._initialized >= version) {\\n revert InvalidInitialization();\\n }\\n $._initialized = version;\\n $._initializing = true;\\n _;\\n $._initializing = false;\\n emit Initialized(version);\\n }\\n\\n /**\\n * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the\\n * {initializer} and {reinitializer} modifiers, directly or indirectly.\\n */\\n modifier onlyInitializing() {\\n _checkInitializing();\\n _;\\n }\\n\\n /**\\n * @dev Reverts if the contract is not in an initializing state. See {onlyInitializing}.\\n */\\n function _checkInitializing() internal view virtual {\\n if (!_isInitializing()) {\\n revert NotInitializing();\\n }\\n }\\n\\n /**\\n * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.\\n * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized\\n * to any version. It is recommended to use this to lock implementation contracts that are designed to be called\\n * through proxies.\\n *\\n * Emits an {Initialized} event the first time it is successfully executed.\\n */\\n function _disableInitializers() internal virtual {\\n // solhint-disable-next-line var-name-mixedcase\\n InitializableStorage storage $ = _getInitializableStorage();\\n\\n if ($._initializing) {\\n revert InvalidInitialization();\\n }\\n if ($._initialized != type(uint64).max) {\\n $._initialized = type(uint64).max;\\n emit Initialized(type(uint64).max);\\n }\\n }\\n\\n /**\\n * @dev Returns the highest version that has been initialized. See {reinitializer}.\\n */\\n function _getInitializedVersion() internal view returns (uint64) {\\n return _getInitializableStorage()._initialized;\\n }\\n\\n /**\\n * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.\\n */\\n function _isInitializing() internal view returns (bool) {\\n return _getInitializableStorage()._initializing;\\n }\\n\\n /**\\n * @dev Returns a pointer to the storage namespace.\\n */\\n // solhint-disable-next-line var-name-mixedcase\\n function _getInitializableStorage() private pure returns (InitializableStorage storage $) {\\n assembly {\\n $.slot := INITIALIZABLE_STORAGE\\n }\\n }\\n}\\n\",\"keccak256\":\"0x631188737069917d2f909d29ce62c4d48611d326686ba6683e26b72a23bfac0b\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)\\n\\npragma solidity ^0.8.20;\\nimport {Initializable} from \\\"../proxy/utils/Initializable.sol\\\";\\n\\n/**\\n * @dev Provides information about the current execution context, including the\\n * sender of the transaction and its data. While these are generally available\\n * via msg.sender and msg.data, they should not be accessed in such a direct\\n * manner, since when dealing with meta-transactions the account sending and\\n * paying for execution may not be the actual sender (as far as an application\\n * is concerned).\\n *\\n * This contract is only required for intermediate, library-like contracts.\\n */\\nabstract contract ContextUpgradeable is Initializable {\\n function __Context_init() internal onlyInitializing {\\n }\\n\\n function __Context_init_unchained() internal onlyInitializing {\\n }\\n function _msgSender() internal view virtual returns (address) {\\n return msg.sender;\\n }\\n\\n function _msgData() internal view virtual returns (bytes calldata) {\\n return msg.data;\\n }\\n\\n function _contextSuffixLength() internal view virtual returns (uint256) {\\n return 0;\\n }\\n}\\n\",\"keccak256\":\"0xdbef5f0c787055227243a7318ef74c8a5a1108ca3a07f2b3a00ef67769e1e397\",\"license\":\"MIT\"},\"contracts/Enclave.sol\":{\"content\":\"// SPDX-License-Identifier: LGPL-3.0-only\\npragma solidity >=0.8.26;\\n\\nimport {\\n IEnclave,\\n E3,\\n IComputationModule,\\n IExecutionModule\\n} from \\\"./interfaces/IEnclave.sol\\\";\\nimport { ICyphernodeRegistry } from \\\"./interfaces/ICyphernodeRegistry.sol\\\";\\nimport { IInputValidator } from \\\"./interfaces/IInputValidator.sol\\\";\\nimport { IOutputVerifier } from \\\"./interfaces/IOutputVerifier.sol\\\";\\nimport {\\n OwnableUpgradeable\\n} from \\\"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\\\";\\n\\ncontract Enclave is IEnclave, OwnableUpgradeable {\\n ////////////////////////////////////////////////////////////\\n // //\\n // Storage Variables //\\n // //\\n ////////////////////////////////////////////////////////////\\n\\n ICyphernodeRegistry public cyphernodeRegistry; // address of the Cyphernode registry.\\n uint256 public maxDuration; // maximum duration of a computation in seconds.\\n uint256 public nexte3Id; // ID of the next E3.\\n uint256 public requests; // total number of requests made to Enclave.\\n\\n // TODO: should computation and execution modules be explicitly allowed?\\n // My intuition is that an allowlist is required since they impose slashing conditions.\\n // But perhaps this is one place where node pools might be utilized, allowing nodes to\\n // opt in to being selected for specific computations, along with the corresponding slashing conditions.\\n // This would reduce the governance overhead for Enclave.\\n\\n // Mapping of allowed computation modules.\\n mapping(IComputationModule computationModule => bool allowed)\\n public computationModules;\\n\\n // Mapping of allowed execution modules.\\n mapping(IExecutionModule executionModule => bool allowed)\\n public executionModules;\\n\\n // Mapping of E3s.\\n mapping(uint256 id => E3 e3) public e3s;\\n\\n ////////////////////////////////////////////////////////////\\n // //\\n // Errors //\\n // //\\n ////////////////////////////////////////////////////////////\\n\\n error CommitteeSelectionFailed();\\n error ComputationModuleNotAllowed(IComputationModule computationModule);\\n error E3AlreadyActivated(uint256 e3Id);\\n error E3Expired();\\n error E3NotActivated(uint256 e3Id);\\n error E3NotReady();\\n error E3DoesNotExist(uint256 e3Id);\\n error ModuleAlreadyEnabled(address module);\\n error ModuleNotEnabled(address module);\\n error InputDeadlinePassed(uint256 e3Id, uint256 expiration);\\n error InputDeadlineNotPassed(uint256 e3Id, uint256 expiration);\\n error InvalidComputation();\\n error InvalidExecutionModuleSetup();\\n error InvalidCyphernodeRegistry(ICyphernodeRegistry cyphernodeRegistry);\\n error InvalidInput();\\n error InvalidDuration(uint256 duration);\\n error InvalidOutput(bytes output);\\n error InvalidStartWindow();\\n error InvalidThreshold(uint32[2] threshold);\\n error CiphertextOutputAlreadyPublished(uint256 e3Id);\\n error CiphertextOutputNotPublished(uint256 e3Id);\\n error PaymentRequired(uint256 value);\\n error PlaintextOutputAlreadyPublished(uint256 e3Id);\\n\\n ////////////////////////////////////////////////////////////\\n // //\\n // Initialization //\\n // //\\n ////////////////////////////////////////////////////////////\\n\\n /// @param _owner The owner of this contract\\n /// @param _maxDuration The maximum duration of a computation in seconds\\n constructor(\\n address _owner,\\n ICyphernodeRegistry _cyphernodeRegistry,\\n uint256 _maxDuration\\n ) {\\n initialize(_owner, _cyphernodeRegistry, _maxDuration);\\n }\\n\\n /// @param _owner The owner of this contract\\n /// @param _maxDuration The maximum duration of a computation in seconds\\n function initialize(\\n address _owner,\\n ICyphernodeRegistry _cyphernodeRegistry,\\n uint256 _maxDuration\\n ) public initializer {\\n __Ownable_init(msg.sender);\\n setMaxDuration(_maxDuration);\\n setCyphernodeRegistry(_cyphernodeRegistry);\\n if (_owner != owner()) transferOwnership(_owner);\\n }\\n\\n ////////////////////////////////////////////////////////////\\n // //\\n // Core Entrypoints //\\n // //\\n ////////////////////////////////////////////////////////////\\n\\n function request(\\n address filter,\\n uint32[2] calldata threshold,\\n uint256[2] calldata startWindow,\\n uint256 duration,\\n IComputationModule computationModule,\\n bytes memory computationParams,\\n IExecutionModule executionModule,\\n bytes memory emParams\\n ) external payable returns (uint256 e3Id, E3 memory e3) {\\n // TODO: allow for other payment methods or only native tokens?\\n // TODO: should payment checks be somewhere else? Perhaps in the computation module or cyphernode registry?\\n require(msg.value > 0, PaymentRequired(msg.value));\\n require(\\n threshold[1] >= threshold[0] && threshold[0] > 0,\\n InvalidThreshold(threshold)\\n );\\n require(\\n // TODO: do we need a minimum start window to allow time for committee selection?\\n startWindow[1] >= startWindow[0] &&\\n startWindow[1] >= block.timestamp,\\n InvalidStartWindow()\\n );\\n require(\\n duration > 0 && duration <= maxDuration,\\n InvalidDuration(duration)\\n );\\n require(\\n computationModules[computationModule],\\n ComputationModuleNotAllowed(computationModule)\\n );\\n require(\\n executionModules[executionModule],\\n ModuleNotEnabled(address(executionModule))\\n );\\n\\n // TODO: should IDs be incremental or produced deterministically?\\n e3Id = nexte3Id;\\n nexte3Id++;\\n\\n IInputValidator inputValidator = computationModule.validate(\\n computationParams\\n );\\n require(address(inputValidator) != address(0), InvalidComputation());\\n\\n // TODO: validate that the requested computation can be performed by the given execution module.\\n IOutputVerifier outputVerifier = executionModule.validate(emParams);\\n require(\\n address(outputVerifier) != address(0),\\n InvalidExecutionModuleSetup()\\n );\\n\\n e3 = E3({\\n threshold: threshold,\\n startWindow: startWindow,\\n duration: duration,\\n expiration: 0,\\n computationModule: computationModule,\\n executionModule: executionModule,\\n inputValidator: inputValidator,\\n outputVerifier: outputVerifier,\\n committeePublicKey: hex\\\"\\\",\\n inputs: new bytes[](0),\\n ciphertextOutput: hex\\\"\\\",\\n plaintextOutput: hex\\\"\\\"\\n });\\n e3s[e3Id] = e3;\\n\\n require(\\n cyphernodeRegistry.requestCommittee(e3Id, filter, threshold),\\n CommitteeSelectionFailed()\\n );\\n\\n emit E3Requested(\\n e3Id,\\n e3s[e3Id],\\n filter,\\n computationModule,\\n executionModule\\n );\\n }\\n\\n function activate(uint256 e3Id) external returns (bool success) {\\n // Note: we could load this into a storage pointer, and do the sets there\\n // Requires a mew internal _getter that returns storage\\n E3 memory e3 = getE3(e3Id);\\n require(e3.expiration == 0, E3AlreadyActivated(e3Id));\\n require(e3.startWindow[0] <= block.timestamp, E3NotReady());\\n // TODO: handle what happens to the payment if the start window has passed.\\n require(e3.startWindow[1] >= block.timestamp, E3Expired());\\n\\n bytes memory publicKey = cyphernodeRegistry.committeePublicKey(e3Id);\\n // Note: This check feels weird\\n require(publicKey.length > 0, CommitteeSelectionFailed());\\n\\n e3s[e3Id].expiration = block.timestamp + e3.duration;\\n e3s[e3Id].committeePublicKey = publicKey;\\n\\n emit E3Activated(e3Id, e3.expiration, e3.committeePublicKey);\\n\\n return true;\\n }\\n\\n function publishInput(\\n uint256 e3Id,\\n bytes memory data\\n ) external returns (bool success) {\\n E3 memory e3 = getE3(e3Id);\\n\\n // Note: if we make 0 a no expiration, this has to be refactored\\n require(e3.expiration > 0, E3NotActivated(e3Id));\\n // TODO: should we have an input window, including both a start and end timestamp?\\n require(\\n e3.expiration > block.timestamp,\\n InputDeadlinePassed(e3Id, e3.expiration)\\n );\\n bytes memory input;\\n (input, success) = e3.inputValidator.validate(msg.sender, data);\\n require(success, InvalidInput());\\n // TODO: probably better to accumulate inputs, rather than just dumping them in storage.\\n e3s[e3Id].inputs.push(input);\\n emit InputPublished(e3Id, input);\\n }\\n\\n function publishCiphertextOutput(\\n uint256 e3Id,\\n bytes memory data\\n ) external returns (bool success) {\\n E3 memory e3 = getE3(e3Id);\\n // Note: if we make 0 a no expiration, this has to be refactored\\n require(e3.expiration > 0, E3NotActivated(e3Id));\\n require(\\n e3.expiration <= block.timestamp,\\n InputDeadlineNotPassed(e3Id, e3.expiration)\\n );\\n // TODO: should the output verifier be able to change its mind?\\n //i.e. should we be able to call this multiple times?\\n require(\\n e3.ciphertextOutput.length == 0,\\n CiphertextOutputAlreadyPublished(e3Id)\\n );\\n bytes memory output;\\n (output, success) = e3.outputVerifier.verify(e3Id, data);\\n require(success, InvalidOutput(output));\\n e3s[e3Id].ciphertextOutput = output;\\n\\n emit CiphertextOutputPublished(e3Id, output);\\n }\\n\\n function publishPlaintextOutput(\\n uint256 e3Id,\\n bytes memory data\\n ) external returns (bool success) {\\n E3 memory e3 = getE3(e3Id);\\n // Note: if we make 0 a no expiration, this has to be refactored\\n require(e3.expiration > 0, E3NotActivated(e3Id));\\n require(\\n e3.ciphertextOutput.length > 0,\\n CiphertextOutputNotPublished(e3Id)\\n );\\n require(\\n e3.plaintextOutput.length == 0,\\n PlaintextOutputAlreadyPublished(e3Id)\\n );\\n bytes memory output;\\n (output, success) = e3.computationModule.verify(e3Id, data);\\n require(success, InvalidOutput(output));\\n e3s[e3Id].plaintextOutput = output;\\n\\n emit PlaintextOutputPublished(e3Id, output);\\n }\\n\\n ////////////////////////////////////////////////////////////\\n // //\\n // Set Functions //\\n // //\\n ////////////////////////////////////////////////////////////\\n\\n function setMaxDuration(\\n uint256 _maxDuration\\n ) public onlyOwner returns (bool success) {\\n maxDuration = _maxDuration;\\n success = true;\\n emit MaxDurationSet(_maxDuration);\\n }\\n\\n function setCyphernodeRegistry(\\n ICyphernodeRegistry _cyphernodeRegistry\\n ) public onlyOwner returns (bool success) {\\n require(\\n address(_cyphernodeRegistry) != address(0) &&\\n _cyphernodeRegistry != cyphernodeRegistry,\\n InvalidCyphernodeRegistry(_cyphernodeRegistry)\\n );\\n cyphernodeRegistry = _cyphernodeRegistry;\\n success = true;\\n emit CyphernodeRegistrySet(address(_cyphernodeRegistry));\\n }\\n\\n function enableComputationModule(\\n IComputationModule computationModule\\n ) public onlyOwner returns (bool success) {\\n require(\\n !computationModules[computationModule],\\n ModuleAlreadyEnabled(address(computationModule))\\n );\\n computationModules[computationModule] = true;\\n success = true;\\n emit ComputationModuleEnabled(computationModule);\\n }\\n\\n function enableExecutionModule(\\n IExecutionModule executionModule\\n ) public onlyOwner returns (bool success) {\\n require(\\n !executionModules[executionModule],\\n ModuleAlreadyEnabled(address(executionModule))\\n );\\n executionModules[executionModule] = true;\\n success = true;\\n emit ExecutionModuleEnabled(executionModule);\\n }\\n\\n function disableComputationModule(\\n IComputationModule computationModule\\n ) public onlyOwner returns (bool success) {\\n require(\\n computationModules[computationModule],\\n ModuleNotEnabled(address(computationModule))\\n );\\n delete computationModules[computationModule];\\n success = true;\\n emit ComputationModuleDisabled(computationModule);\\n }\\n\\n function disableExecutionModule(\\n IExecutionModule executionModule\\n ) public onlyOwner returns (bool success) {\\n require(\\n executionModules[executionModule],\\n ModuleNotEnabled(address(executionModule))\\n );\\n delete executionModules[executionModule];\\n success = true;\\n emit ExecutionModuleDisabled(executionModule);\\n }\\n\\n ////////////////////////////////////////////////////////////\\n // //\\n // Get Functions //\\n // //\\n ////////////////////////////////////////////////////////////\\n\\n function getE3(uint256 e3Id) public view returns (E3 memory e3) {\\n e3 = e3s[e3Id];\\n require(\\n e3.computationModule != IComputationModule(address(0)),\\n E3DoesNotExist(e3Id)\\n );\\n }\\n}\\n\",\"keccak256\":\"0xc37015e312c621b75b924d32d19b43682ffb94ef3319326b75ca1a4e36454700\",\"license\":\"LGPL-3.0-only\"},\"contracts/interfaces/IComputationModule.sol\":{\"content\":\"// SPDX-License-Identifier: LGPL-3.0-only\\npragma solidity >=0.8.26;\\n\\nimport { IInputValidator } from \\\"./IInputValidator.sol\\\";\\n\\ninterface IComputationModule {\\n /// @notice This function should be called by the Enclave contract to validate the computation parameters.\\n /// @param params ABI encoded computation parameters.\\n /// @return inputValidator The input validator to be used for the computation.\\n function validate(\\n bytes calldata params\\n ) external returns (IInputValidator inputValidator);\\n\\n /// @notice This function should be called by the Enclave contract to verify the decrypted output of an E3.\\n /// @param e3Id ID of the E3.\\n /// @param outputData ABI encoded output data to be verified.\\n /// @return output The output data to be published.\\n /// @return success Whether the output data is valid.\\n function verify(\\n uint256 e3Id,\\n bytes memory outputData\\n ) external returns (bytes memory output, bool success);\\n}\\n\",\"keccak256\":\"0x9e65874df81985a203a0f3bea12996cb66f9e57663beed3e93f849414a5c4d0d\",\"license\":\"LGPL-3.0-only\"},\"contracts/interfaces/ICyphernodeRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: LGPL-3.0-only\\npragma solidity >=0.8.26;\\n\\ninterface ICyphernodeRegistry {\\n /// @notice This event MUST be emitted when a committee is selected for an E3.\\n /// @param e3Id ID of the E3 for which the committee was selected.\\n /// @param filter Address of the contract that will coordinate committee selection.\\n /// @param threshold The M/N threshold for the committee.\\n event CommitteeRequested(\\n uint256 indexed e3Id,\\n address filter,\\n uint32[2] threshold\\n );\\n\\n /// @notice This event MUST be emitted when a committee is selected for an E3.\\n /// @param e3Id ID of the E3 for which the committee was selected.\\n /// @param publicKey Public key of the committee.\\n event CommitteePublished(uint256 indexed e3Id, bytes publicKey);\\n\\n /// @notice This event MUST be emitted when `enclave` is set.\\n /// @param enclave Address of the enclave contract.\\n event EnclaveSet(address indexed enclave);\\n\\n /// @notice This event MUST be emitted when a cyphernode is added to the registry.\\n event CyphernodeAdded(address indexed node);\\n\\n /// @notice This event MUST be emitted when a cyphernode is removed from the registry.\\n event CyphernodeRemoved(address indexed node);\\n\\n function isCyphernodeEligible(address cyphernode) external returns (bool);\\n\\n /// @notice Initiates the committee selection process for a specified E3.\\n /// @dev This function MUST revert when not called by the Enclave contract.\\n /// @param e3Id ID of the E3 for which to select the committee.\\n /// @param filter The address of the filter responsible for the committee selection process.\\n /// @param threshold The M/N threshold for the committee.\\n /// @return success True if committee selection was successfully initiated.\\n function requestCommittee(\\n uint256 e3Id,\\n address filter,\\n uint32[2] calldata threshold\\n ) external returns (bool success);\\n\\n /// @notice Publishes the public key resulting from the committee selection process.\\n /// @dev This function MUST revert if not called by the previously selected filter.\\n /// @param e3Id ID of the E3 for which to select the committee.\\n /// @param publicKey The public key generated by the selected committee.\\n function publishCommittee(\\n uint256 e3Id,\\n bytes calldata proof,\\n bytes calldata publicKey\\n ) external;\\n\\n /// @notice This function should be called by the Enclave contract to get the public key of a committee.\\n /// @dev This function MUST revert if no committee has been requested for the given E3.\\n /// @dev This function MUST revert if the committee has not yet published a public key.\\n /// @param e3Id ID of the E3 for which to get the committee public key.\\n /// @return publicKey The public key of the committee.\\n function committeePublicKey(\\n uint256 e3Id\\n ) external view returns (bytes memory);\\n}\\n\",\"keccak256\":\"0x60af5d66db32528f5032fe083218f180ab83f3199bcf090bed7249c28bc18104\",\"license\":\"LGPL-3.0-only\"},\"contracts/interfaces/IE3.sol\":{\"content\":\"// SPDX-License-Identifier: LGPL-3.0-only\\npragma solidity >=0.8.26;\\n\\nimport { IInputValidator } from \\\"./IInputValidator.sol\\\";\\nimport { IExecutionModule } from \\\"./IExecutionModule.sol\\\";\\nimport { IComputationModule } from \\\"./IComputationModule.sol\\\";\\nimport { IOutputVerifier } from \\\"./IOutputVerifier.sol\\\";\\n\\n/// @title E3 struct\\n/// @notice This struct represents an E3 computation.\\n/// @param threshold M/N threshold for the committee.\\n/// @param startWindow Start window for the computation: index zero is minimum, index 1 is the maxium.\\n/// @param duration Duration of the E3.\\n/// @param expiration Timestamp when committee duties expire.\\n/// @param computationModule Address of the computation module contract.\\n/// @param executionModule Address of the execution module contract.\\n/// @param inputValidator Address of the input validator contract.\\n/// @param outputVerifier Address of the output verifier contract.\\n/// @param committeeId ID of the selected committee.\\n/// @param ciphertextOutput Encrypted output data.\\n/// @param plaintextOutput Decrypted output data.\\nstruct E3 {\\n uint32[2] threshold;\\n uint256[2] startWindow;\\n uint256 duration;\\n uint256 expiration;\\n IComputationModule computationModule;\\n IExecutionModule executionModule;\\n IInputValidator inputValidator;\\n IOutputVerifier outputVerifier;\\n bytes committeePublicKey;\\n bytes[] inputs;\\n bytes ciphertextOutput;\\n bytes plaintextOutput;\\n}\\n\",\"keccak256\":\"0x6013398b086073328305a2f33edd3027ed82b3fb7e802627f88ac7781a2c1125\",\"license\":\"LGPL-3.0-only\"},\"contracts/interfaces/IEnclave.sol\":{\"content\":\"// SPDX-License-Identifier: LGPL-3.0-only\\npragma solidity >=0.8.26;\\n\\nimport { E3, IComputationModule, IExecutionModule } from \\\"./IE3.sol\\\";\\n\\ninterface IEnclave {\\n ////////////////////////////////////////////////////////////\\n // //\\n // Events //\\n // //\\n ////////////////////////////////////////////////////////////\\n\\n /// @notice This event MUST be emitted when an Encrypted Execution Environment (E3) is successfully requested.\\n /// @param e3Id ID of the E3.\\n /// @param e3 Details of the E3.\\n /// @param filter Address of the pool of nodes from which the Cypher Node committee was selected.\\n /// @param computationModule Address of the Computation module selected.\\n /// @param executionModule Address of the execution module selected.\\n event E3Requested(\\n uint256 e3Id,\\n E3 e3,\\n address filter,\\n IComputationModule indexed computationModule,\\n IExecutionModule indexed executionModule\\n );\\n\\n /// @notice This event MUST be emitted when an Encrypted Execution Environment (E3) is successfully activated.\\n /// @param e3Id ID of the E3.\\n /// @param expiration Timestamp when committee duties expire.\\n /// @param committeePublicKey Public key of the committee.\\n event E3Activated(\\n uint256 e3Id,\\n uint256 expiration,\\n bytes committeePublicKey\\n );\\n\\n /// @notice This event MUST be emitted when an input to an Encrypted Execution Environment (E3) is\\n /// successfully published.\\n /// @param e3Id ID of the E3.\\n /// @param data ABI encoded input data.\\n event InputPublished(uint256 indexed e3Id, bytes data);\\n\\n /// @notice This event MUST be emitted when the plaintext output of an Encrypted Execution Environment (E3)\\n /// is successfully published.\\n /// @param e3Id ID of the E3.\\n /// @param plaintextOutput ABI encoded plaintext output.\\n event PlaintextOutputPublished(uint256 indexed e3Id, bytes plaintextOutput);\\n\\n /// @notice This event MUST be emitted when the ciphertext output of an Encrypted Execution Environment (E3)\\n /// is successfully published.\\n /// @param e3Id ID of the E3.\\n /// @param ciphertextOutput ABI encoded ciphertext output.\\n event CiphertextOutputPublished(\\n uint256 indexed e3Id,\\n bytes ciphertextOutput\\n );\\n\\n /// @notice This event MUST be emitted any time the `maxDuration` is set.\\n /// @param maxDuration The maximum duration of a computation in seconds.\\n event MaxDurationSet(uint256 maxDuration);\\n\\n /// @notice This event MUST be emitted any time the CyphernodeRegistry is set.\\n /// @param cyphernodeRegistry The address of the CyphernodeRegistry contract.\\n event CyphernodeRegistrySet(address cyphernodeRegistry);\\n\\n /// @notice This event MUST be emitted any time a computation module is enabled.\\n /// @param computationModule The address of the computation module.\\n event ComputationModuleEnabled(IComputationModule computationModule);\\n\\n /// @notice This event MUST be emitted any time a computation module is disabled.\\n /// @param computationModule The address of the computation module.\\n event ComputationModuleDisabled(IComputationModule computationModule);\\n\\n /// @notice This event MUST be emitted any time an execution module is enabled.\\n /// @param executionModule The address of the execution module.\\n event ExecutionModuleEnabled(IExecutionModule executionModule);\\n\\n /// @notice This event MUST be emitted any time an execution module is disabled.\\n /// @param executionModule The address of the execution module.\\n event ExecutionModuleDisabled(IExecutionModule executionModule);\\n\\n ////////////////////////////////////////////////////////////\\n // //\\n // Core Entrypoints //\\n // //\\n ////////////////////////////////////////////////////////////\\n\\n /// @notice This function should be called to request a computation within an Encrypted Execution Environment (E3).\\n /// @dev This function MUST emit the E3Requested event.\\n /// @param filter IDs of the pool of nodes from which to select the committee.\\n /// @param threshold The M/N threshold for the committee.\\n /// @param duration The duration of the computation in seconds.\\n /// @param computationModule Address of the computation module.\\n /// @param computationParams ABI encoded computation parameters.\\n /// @param executionModule Address of the execution module.\\n /// @param emParams ABI encoded execution module parameters.\\n /// @return e3Id ID of the E3.\\n /// @return e3 The E3 struct.\\n function request(\\n address filter,\\n uint32[2] calldata threshold,\\n uint256[2] calldata startWindow,\\n uint256 duration,\\n IComputationModule computationModule,\\n bytes memory computationParams,\\n IExecutionModule executionModule,\\n bytes memory emParams\\n ) external payable returns (uint256 e3Id, E3 memory e3);\\n\\n /// @notice This function should be called to activate an Encrypted Execution Environment (E3) once it has been\\n /// initialized and is ready for input.\\n /// @dev This function MUST emit the E3Activated event.\\n /// @dev This function MUST revert if the given E3 has not yet been requested.\\n /// @dev This function MUST revert if the selected node committee has not yet published a public key.\\n /// @param e3Id ID of the E3.\\n function activate(uint256 e3Id) external returns (bool success);\\n\\n /// @notice This function should be called to publish input data for Encrypted Execution Environment (E3).\\n /// @dev This function MUST revert if the E3 is not yet activated.\\n /// @dev This function MUST emit the InputPublished event.\\n /// @param e3Id ID of the E3.\\n /// @param data ABI encoded input data to publish.\\n /// @return success True if the input was successfully published.\\n function publishInput(\\n uint256 e3Id,\\n bytes calldata data\\n ) external returns (bool success);\\n\\n /// @notice This function should be called to publish output data for an Encrypted Execution Environment (E3).\\n /// @dev This function MUST emit the CiphertextOutputPublished event.\\n /// @param e3Id ID of the E3.\\n /// @param data ABI encoded output data to verify.\\n /// @return success True if the output was successfully published.\\n function publishCiphertextOutput(\\n uint256 e3Id,\\n bytes memory data\\n ) external returns (bool success);\\n\\n /// @notice This function publishes the plaintext output of an Encrypted Execution Environment (E3).\\n /// @dev This function MUST revert if the output has not been published.\\n /// @dev This function MUST emit the PlaintextOutputPublished event.\\n /// @param e3Id ID of the E3.\\n /// @param data ABI encoded output data to decrypt.\\n /// @return success True if the output was successfully decrypted.\\n function publishPlaintextOutput(\\n uint256 e3Id,\\n bytes memory data\\n ) external returns (bool success);\\n\\n ////////////////////////////////////////////////////////////\\n // //\\n // Set Functions //\\n // //\\n ////////////////////////////////////////////////////////////\\n\\n /// @notice This function should be called to set the maximum duration of requested computations.\\n /// @param _maxDuration The maximum duration of a computation in seconds.\\n /// @return success True if the max duration was successfully set.\\n function setMaxDuration(\\n uint256 _maxDuration\\n ) external returns (bool success);\\n\\n ////////////////////////////////////////////////////////////\\n // //\\n // Get Functions //\\n // //\\n ////////////////////////////////////////////////////////////\\n\\n /// @notice This function should be called to retrieve the details of an Encrypted Execution Environment (E3).\\n /// @dev This function MUST revert if the E3 does not exist.\\n /// @param e3Id ID of the E3.\\n /// @return e3 The struct representing the requested E3.\\n function getE3(uint256 e3Id) external view returns (E3 memory e3);\\n}\\n\",\"keccak256\":\"0x706e77d517e9d275fa68844f902ac74ae5c508443732da519423018e75426bb4\",\"license\":\"LGPL-3.0-only\"},\"contracts/interfaces/IExecutionModule.sol\":{\"content\":\"// SPDX-License-Identifier: LGPL-3.0-only\\npragma solidity >=0.8.26;\\n\\nimport { IOutputVerifier } from \\\"./IOutputVerifier.sol\\\";\\n\\ninterface IExecutionModule {\\n /// @notice This function should be called by the Enclave contract to validate the execution module parameters.\\n /// @param params ABI encoded execution module parameters.\\n function validate(\\n bytes calldata params\\n ) external returns (IOutputVerifier outputVerifier);\\n}\\n\",\"keccak256\":\"0x6cd6024b4459f94dde07b70e4f784078cbd4ab71d28c3b41316d3590d7c9bcf8\",\"license\":\"LGPL-3.0-only\"},\"contracts/interfaces/IInputValidator.sol\":{\"content\":\"// SPDX-License-Identifier: LGPL-3.0-only\\npragma solidity >=0.8.26;\\n\\ninterface IInputValidator {\\n /// @notice This function should be called by the Enclave contract to validate the input parameters.\\n /// @param params ABI encoded input parameters.\\n /// @return input The input data to be published.\\n /// @return success Whether the input parameters are valid.\\n function validate(\\n address sender,\\n bytes memory params\\n ) external returns (bytes memory input, bool success);\\n}\\n\",\"keccak256\":\"0x8faeb82309f9a353636ef4ad1ca34a181a8161ccd287dd7c3150c0d6251cd656\",\"license\":\"LGPL-3.0-only\"},\"contracts/interfaces/IOutputVerifier.sol\":{\"content\":\"// SPDX-License-Identifier: LGPL-3.0-only\\npragma solidity >=0.8.26;\\n\\ninterface IOutputVerifier {\\n /// @notice This function should be called by the Enclave contract to verify the output of a computation.\\n /// @param e3Id ID of the E3.\\n /// @param data ABI encoded output data to be verified.\\n /// @return output Ciphertext output of the given computation.\\n function verify(\\n uint256 e3Id,\\n bytes memory data\\n ) external view returns (bytes memory output, bool success);\\n}\\n\",\"keccak256\":\"0x09648c77f96c17a0d4143a11feb5c6aec15c70029cb483335a0bd9d6224769e8\",\"license\":\"LGPL-3.0-only\"}},\"version\":1}", + "bytecode": "0x6080346102a457601f61265838819003918201601f19168301916001600160401b038311848410176102a9578084926060946040528339810103126102a45780516001600160a01b0381168082036102a45760208301516001600160a01b03811693908490036102a457604090810151600080516020612638833981519152549182901c60ff161594916001600160401b0381168015908161029c575b6001149081610292575b159081610289575b50610278576001600160401b03198116600117600080516020612638833981519152557fba0716ba1ee2ea8ecc4c64119b4537cdb42a99d82acf92af5b87607b8b523552916020918761024d575b50610105610335565b61010d610335565b610116336102bf565b61011e610363565b80600155604051908152a1610131610363565b80151580610238575b1561022457600080546001600160a01b031916821790556040519081527f016ea868599173c3163f65dea5e4677b2be5f0ececb4ec15d1166a27de35a53390602090a1600080516020612618833981519152546001600160a01b03160361020d575b506101b1575b60405161227e908161039a8239f35b68ff0000000000000000196000805160206126388339815191525416600080516020612638833981519152557fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d2602060405160018152a16101a2565b61021e90610219610363565b6102bf565b3861019c565b63157970a560e21b60005260045260246000fd5b506000546001600160a01b031681141561013a565b6001600160481b031916680100000000000000011760008051602061263883398151915255386100fc565b63f92ee8a960e01b60005260046000fd5b905015386100ae565b303b1591506100a6565b87915061009c565b600080fd5b634e487b7160e01b600052604160045260246000fd5b6001600160a01b0316801561031f5760008051602061261883398151915280546001600160a01b0319811683179091556001600160a01b03167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a3565b631e4fbdf760e01b600052600060045260246000fd5b60ff6000805160206126388339815191525460401c161561035257565b631afcd79f60e31b60005260046000fd5b600080516020612618833981519152546001600160a01b0316330361038457565b63118cdaa760e01b6000523360045260246000fdfe6080604052600436101561001257600080fd5b60003560e01c806309e098de146116c6578063115dfcbb146116875780631794bb3c146114615780632c27e1371461143a5780634017daf01461132e578063406ed35c146112fb578063594dfe61146109f95780636db5c8fd146109db578063715018a61461094257806376c932d514610903578063784b2830146107a657806378b41acd146107835780638da5cb5b1461073d578063a8873c6b146106ab578063af378f1014610619578063b260c42a14610469578063b74cb2db1461044b578063cb6496171461042d578063cf0f34c414610405578063d016b08d14610265578063d3c59355146101d7578063f14ea7b8146101495763f2fde38b1461011957600080fd5b34610144576020366003190112610144576101426101356118db565b61013d6121e9565b612143565b005b600080fd5b34610144576020366003190112610144577f39a3e67e141e4afa4c0f050632f57cfa9ccab94319143265fb278752551b0ca860206001600160a01b0361018d6118db565b6101956121e9565b1680600052600482526101b08160ff60406000205416612030565b8060005260048252604060002060ff198154169055604051908152a1602060405160018152f35b34610144576020366003190112610144577fe48e78a7419c5652baf40c86a4d7548a04ec3f569d4e6204e5a1e1890acbfaf460206001600160a01b0361021b6118db565b6102236121e9565b16806000526005825261023e8160ff60406000205416612030565b8060005260058252604060002060ff198154169055604051908152a1602060405160018152f35b3461014457610273366118a8565b61027c82611e0e565b6060810161028d8482511515611b69565b51428111156103ed57506102d76000926001600160a01b0360c085940151169060405194858094819363caf9278560e01b83523360048401526040602484015260448301906119d1565b03925af180156103e1576000916000916103bc575b50156103ab57816000526006602052600a60406000200180549168010000000000000000831015610395576001830180835583101561037f5761035d817fabf12c38379be7b560558cae3ceec83b3762653f7dd74e875af2ea6aeac7eaa89461037194600052602060002001611c69565b6040519182916020835260208301906119d1565b0390a2602060405160018152f35b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b63b4fa3fb360e01b60005260046000fd5b90506103db91503d806000833e6103d38183611823565b810190611bd4565b836102ec565b6040513d6000823e3d90fd5b8363142c294360e31b60005260045260245260446000fd5b34610144576020366003190112610144576020610423600435612107565b6040519015158152f35b34610144576000366003190112610144576020600254604051908152f35b34610144576000366003190112610144576020600354604051908152f35b346101445760203660031901126101445760043561048681611e0e565b60608101918251610605576020820180515142106105f45760204291510151106105e357602460006001600160a01b0381541660405192838092630e82f3b760e41b82528660048301525afa9081156103e15760009161059b575b5080511561058a57604083015142019081421161057457600083815260066020526040902060048101929092557f50df9e2c9fc5a7f4a07e403fa0300b88fcc8c6943bdff4b8ae71f55b7fd95f8994610566926101009261054491600901611c69565b51930151604051938493845260208401526060604084015260608301906119d1565b0390a1602060405160018152f35b634e487b7160e01b600052601160045260246000fd5b630d8dbe2560e01b60005260046000fd5b903d8082843e6105ab8184611823565b8201916020818403126105df5780519167ffffffffffffffff83116105dc57506105d6929101611b85565b846104e1565b80fd5b5080fd5b633d82a7cd60e11b60005260046000fd5b63a0750b5160e01b60005260046000fd5b633e26347b60e21b60005260045260246000fd5b34610144576020366003190112610144577fe5df1e46acc6e102c34b0f812f6557dba66de2e5fed10b64103b5d744083ee3160206001600160a01b0361065d6118db565b6106656121e9565b1680600052600482526106818160ff60406000205416156120e1565b80600052600482526040600020600160ff19825416179055604051908152a1602060405160018152f35b34610144576020366003190112610144577fcf75d44d74f911d2ec243ed8b390c2e4c69f2f2f372a197c0665e72843d49c0d60206001600160a01b036106ef6118db565b6106f76121e9565b1680600052600582526107138160ff60406000205416156120e1565b80600052600582526040600020600160ff19825416179055604051908152a1602060405160018152f35b346101445760003660031901126101445760206001600160a01b037f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c1993005416604051908152f35b346101445760203660031901126101445760206104236107a16118db565b612056565b34610144576107b4366118a8565b6107bd82611e0e565b606081016107ce8482511515611b69565b514281116108eb5750610140810151516108d65761081392916001600160a01b0360e060009301511660405180809681946321614b3960e21b83528760048401611c0a565b03915afa9081156103e1576020926000908193610893575b506108868161085b7f7cc27e4a5626cbc4f8ba1a927b0448de55e6a114bc87660331270c5109ade0719386611c21565b836000526006865261087481600b604060002001611c69565b604051918291878352878301906119d1565b0390a26040519015158152f35b61088693506108cd907f7cc27e4a5626cbc4f8ba1a927b0448de55e6a114bc87660331270c5109ade071923d8091833e6103d38183611823565b9390915061082b565b82637eb9cea960e11b60005260045260246000fd5b836370c05fb960e11b60005260045260245260446000fd5b34610144576020366003190112610144576001600160a01b036109246118db565b166000526004602052602060ff604060002054166040519015158152f35b346101445760003660031901126101445761095b6121e9565b60006001600160a01b037f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300546001600160a01b031981167f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c19930055167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a3005b34610144576000366003190112610144576020600154604051908152f35b61014036600319011261014457610a0e6118db565b36606411610144573660a4116101445760a4359060c4356001600160a01b03811681036101445760e43567ffffffffffffffff811161014457610a55903690600401611861565b9061010435936001600160a01b0385168503610144576101243567ffffffffffffffff811161014457610a8c903690600401611861565b91610a95611d6a565b5034156112e65760443563ffffffff811690818103610144575063ffffffff610abc611fd5565b161115806112d0575b156112b25760843560643581101590816112a7575b5015611296578115158061128a575b15611275576001600160a01b038116600052600460205260ff6040600020541615611257576001600160a01b0386166000526005602052610b3b6001600160a01b03871660ff60406000205416612030565b600254936000198514610574576020610b7691600187016002556040518093819263c16e50ef60e01b835284600484015260248301906119d1565b038160006001600160a01b0387165af19081156103e15760009161120e575b506001600160a01b03169283156111fd576020610bcd916040518093819263c16e50ef60e01b835284600484015260248301906119d1565b038160006001600160a01b038c165af19081156103e1576000916111b4575b506001600160a01b03169485156111a357604051602096610c0d8883611823565b6000825260405195610c1e87611806565b6040958651610c2d8882611823565b60248b825b6064831061118b5750505088528651610c4b8882611823565b60648b825b60a4831061117b5750905089015286880152600060608801526001600160a01b03851660808801526001600160a01b038a1660a088015260c087015260e08601528351610c9d8882611823565b600081526101008601526101208501528251610cb98782611823565b600081526101408501528251610ccf8782611823565b60008152610160850152846000526006865282600020845160009060005b89600282106111535750505081558685015160005b6002811061113e575050838501516003820155606085015160048201556001600160a01b036080860151166001600160a01b036005830191166001600160a01b03198254161790556001600160a01b0360a0860151166001600160a01b036006830191166001600160a01b03198254161790556001600160a01b0360c0860151166001600160a01b036007830191166001600160a01b03198254161790556001600160a01b0360e0860151166001600160a01b036008830191166001600160a01b0319825416179055610ddd61010086015160098301611c69565b610120850151805190680100000000000000008211610395578890600a84015483600a8601558084106110b5575b5001600a830160005288600020896000925b848410611097575050505050610e4e90610e3f610140870151600b8301611c69565b600c6101608701519101611c69565b6000866001600160a01b036084818454169487519485938492639ccb58d560e01b84528c60048501521696876024840152610e8b60448401611ff9565b5af190811561108c57600091611057575b501561058a57846000526006865282600020835190868252606088830152610ed8606083018263ffffffff602091548181168452821c16910152565b610ee860a0830160018301611de6565b600381015460e083015260048101546101008301526001600160a01b036005820154166101208301526001600160a01b036006820154166101408301526001600160a01b036007820154166101608301526001600160a01b036008820154166101808301526101c06101a0830152610f6761022083016009830161192b565b600a820190605f19848203016101c085015281548082528a8201918b8260051b820101936000528b600020926000915b83831061102c575050505050916001600160a01b0380611028999a9b6110098495600c610ff57fdb6ad92217850c3c041086cc44cbec591badf6afe93d864e7f4ea4ba1bcf604199605f19898203016101e08a0152600b840161192b565b878103605f1901610200890152910161192b565b9689850152169516930390a380805195869586528501528301906119f6565b0390f35b90919293948d60016110488193601f198682030187528961192b565b97019301930191939290610f97565b90508681813d8311611085575b61106e8183611823565b810103126101445761107f90611bc7565b88610e9c565b503d611064565b84513d6000823e3d90fd5b600191816110a784935186611c69565b019201920191908a90610e1d565b600a850160005282600020908482015b81830181106110d5575050610e0b565b6001919293946110e582546118f1565b806110f8575b505001908b9392916110c5565b601f81118414611110575050600081555b8c8f6110eb565b83601f61112c9385600052600020920160051c82019101611c52565b8060005260008d812081835555611109565b60019089835193019282828601015501610d02565b829363ffffffff6001939451169063ffffffff8560051b92831b921b19161793019101610ced565b82358152918101918d9101610c50565b819061119684611fe8565b8152019101908c90610c32565b63f72c404960e01b60005260046000fd5b6020813d6020116111f5575b816111cd60209383611823565b810103126105df5751906001600160a01b03821682036105dc57506001600160a01b03610bec565b3d91506111c0565b630fdfa71f60e31b60005260046000fd5b6020813d60201161124f575b8161122760209383611823565b810103126105df5751906001600160a01b03821682036105dc57506001600160a01b03610b95565b3d915061121a565b6001600160a01b0390631e505a8160e01b6000521660045260246000fd5b506313b783af60e21b60005260045260246000fd5b50600154821115610ae9565b6308594fb760e01b60005260046000fd5b905042111587610ada565b604051633744092160e21b81526044906112ce60048201611ff9565bfd5b5063ffffffff6112de611fd5565b161515610ac5565b638c4fcd9360e01b6000523460045260246000fd5b346101445760203660031901126101445761102861131a600435611e0e565b6040519182916020835260208301906119f6565b3461014457602036600319011261014457600435600052600660205260406000206003810154611028600c61142b60048501549461141d6001600160a01b036005830154166001600160a01b036006840154166001600160a01b036007850154166001600160a01b0360088601541691604051936113ba856113b38160098b0161192b565b0386611823565b6113e9604051976113d9896113d281600b850161192b565b038a611823565b6113d2604051809c81930161192b565b6040519b8c9b8c5260208c015260408b015260608a0152608089015260a088015261012060c08801526101208701906119d1565b9085820360e08701526119d1565b908382036101008501526119d1565b346101445760003660031901126101445760206001600160a01b0360005416604051908152f35b346101445760603660031901126101445761147a6118db565b602435906001600160a01b0382168203610144577ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a005460ff8160401c16159267ffffffffffffffff82168015908161167f575b6001149081611675575b15908161166c575b5061165b5767ffffffffffffffff1982166001177ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a005561154a918461161c575b50611528612231565b611530612231565b61153933612143565b611544604435612107565b50612056565b506001600160a01b037f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c19930054166001600160a01b0382160361160a575b5061158d57005b68ff0000000000000000197ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a0054167ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00557fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d2602060405160018152a1005b6116169061013d6121e9565b81611586565b68ffffffffffffffffff191668010000000000000001177ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00558461151f565b63f92ee8a960e01b60005260046000fd5b905015856114df565b303b1591506114d7565b8591506114cd565b34610144576020366003190112610144576001600160a01b036116a86118db565b166000526005602052602060ff604060002054166040519015158152f35b34610144576116d4366118a8565b6116dd82611e0e565b6116ed8360608301511515611b69565b61014081015151156117f157610160810151516117dc57611738600093926001600160a01b0360808694015116906040519586809481936321614b3960e21b83528860048401611c0a565b03925af19081156103e1576020926000908193611799575b50610886816117807f02a24c3402076671e129905ba4579d884b1f94ded1c07fc03d26d11b60bca1699386611c21565b836000526006865261087481600c604060002001611c69565b61088693506117d3907f02a24c3402076671e129905ba4579d884b1f94ded1c07fc03d26d11b60bca169923d8091833e6103d38183611823565b93909150611750565b826360ec327960e01b60005260045260246000fd5b8263032c20ef60e21b60005260045260246000fd5b610180810190811067ffffffffffffffff82111761039557604052565b90601f8019910116810190811067ffffffffffffffff82111761039557604052565b67ffffffffffffffff811161039557601f01601f191660200190565b81601f820112156101445780359061187882611845565b926118866040519485611823565b8284526020838301011161014457816000926020809301838601378301015290565b90604060031983011261014457600435916024359067ffffffffffffffff8211610144576118d891600401611861565b90565b600435906001600160a01b038216820361014457565b90600182811c92168015611921575b602083101461190b57565b634e487b7160e01b600052602260045260246000fd5b91607f1691611900565b6000929181549161193b836118f1565b8083529260018116908115611991575060011461195757505050565b60009081526020812093945091925b838310611977575060209250010190565b600181602092949394548385870101520191019190611966565b915050602093945060ff929192191683830152151560051b010190565b60005b8381106119c15750506000910152565b81810151838201526020016119b1565b906020916119ea815180928185528580860191016119ae565b601f01601f1916010190565b80519192916000845b60028210611b4d5750505060208101516000604085015b60028210611b375750505060408101516080840152606081015160a08401526001600160a01b0360808201511660c08401526001600160a01b0360a08201511660e08401526001600160a01b0360c0820151166101008401526001600160a01b0360e082015116610120840152611aa06101008201516101c06101408601526101c08501906119d1565b9261012082015193818103610160830152845180825260208201906020808260051b8501019701916000905b828210611b09575050505050610160611af76118d894956101408501518482036101808601526119d1565b920151906101a08184039101526119d1565b9091929397602080611b27600193601f198d820301865288516119d1565b9a96019493919091019101611acc565b6020806001928551815201930191019091611a16565b60208060019263ffffffff8651168152019301910190916119ff565b15611b715750565b63166b4d0360e01b60005260045260246000fd5b81601f82011215610144578051611b9b81611845565b92611ba96040519485611823565b81845260208284010111610144576118d891602080850191016119ae565b5190811515820361014457565b91906040838203126101445782519067ffffffffffffffff821161014457611c036020916118d8938601611b85565b9301611bc7565b6040906118d89392815281602082015201906119d1565b15611c295750565b604051632f9f8ab960e01b815260206004820152908190611c4e9060248301906119d1565b0390fd5b818110611c5d575050565b60008155600101611c52565b919091825167ffffffffffffffff811161039557611c8782546118f1565b601f8111611d2d575b506020601f8211600114611ccb5781929394600092611cc0575b50508160011b916000199060031b1c1916179055565b015190503880611caa565b601f1982169083600052806000209160005b818110611d1557509583600195969710611cfc575b505050811b019055565b015160001960f88460031b161c19169055388080611cf2565b9192602060018192868b015181550194019201611cdd565b611d5a90836000526020600020601f840160051c81019160208510611d60575b601f0160051c0190611c52565b38611c90565b9091508190611d4d565b60405190611d7782611806565b606061016083600060408051611d8d8282611823565b8136823783528051611d9f8282611823565b81368237602084015282015260008382015260006080820152600060a0820152600060c0820152600060e08201528261010082015282610120820152826101408201520152565b906000905b60028210611df857505050565b6001602081928554815201930191019091611deb565b90611e17611d6a565b50816000526006602052604060002091604051611e3381611806565b604051611e51818663ffffffff602091548181168452821c16910152565b611e5c604082611823565b8152604051611e6e8160018701611de6565b611e79604082611823565b602082015260038401546040820152600484015460608201526001600160a01b0360058501541693608082019485526001600160a01b0360068201541660a08301526001600160a01b0360078201541660c08301526001600160a01b0360088201541660e0830152604051611efc81611ef5816009860161192b565b0382611823565b610100830152600a8101805467ffffffffffffffff81116103955760208160051b0191611f2c6040519384611823565b818352602083019060005260206000206000915b838310611fb05750505050611f8b8392600c926101206001600160a01b03960152604051611f7581611ef581600b860161192b565b610140850152611ef5604051809481930161192b565b61016082015293511615611f9c5750565b63cd6f4a4f60e01b60005260045260246000fd5b600160208192604051611fc781611ef5818961192b565b815201920192019190611f40565b60243563ffffffff811681036101445790565b359063ffffffff8216820361014457565b6024906000905b6002821061200d57505050565b60208060019263ffffffff61202187611fe8565b16815201930191019091612000565b156120385750565b6001600160a01b03906321ac7c5f60e01b6000521660045260246000fd5b6001600160a01b03906120676121e9565b16801515806120cc575b156120b8576020817f016ea868599173c3163f65dea5e4677b2be5f0ececb4ec15d1166a27de35a533926001600160a01b03196000541617600055604051908152a1600190565b63157970a560e21b60005260045260246000fd5b506001600160a01b0360005416811415612071565b156120e95750565b6001600160a01b039063b29d459560e01b6000521660045260246000fd5b60207fba0716ba1ee2ea8ecc4c64119b4537cdb42a99d82acf92af5b87607b8b523552916121336121e9565b80600155604051908152a1600190565b6001600160a01b031680156121d3576001600160a01b037f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c19930054826001600160a01b03198216177f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c19930055167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a3565b631e4fbdf760e01b600052600060045260246000fd5b6001600160a01b037f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c1993005416330361221c57565b63118cdaa760e01b6000523360045260246000fd5b60ff7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a005460401c161561226057565b631afcd79f60e31b60005260046000fdfea164736f6c634300081a000a9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300f0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00", + "deployedBytecode": "0x6080604052600436101561001257600080fd5b60003560e01c806309e098de146116c6578063115dfcbb146116875780631794bb3c146114615780632c27e1371461143a5780634017daf01461132e578063406ed35c146112fb578063594dfe61146109f95780636db5c8fd146109db578063715018a61461094257806376c932d514610903578063784b2830146107a657806378b41acd146107835780638da5cb5b1461073d578063a8873c6b146106ab578063af378f1014610619578063b260c42a14610469578063b74cb2db1461044b578063cb6496171461042d578063cf0f34c414610405578063d016b08d14610265578063d3c59355146101d7578063f14ea7b8146101495763f2fde38b1461011957600080fd5b34610144576020366003190112610144576101426101356118db565b61013d6121e9565b612143565b005b600080fd5b34610144576020366003190112610144577f39a3e67e141e4afa4c0f050632f57cfa9ccab94319143265fb278752551b0ca860206001600160a01b0361018d6118db565b6101956121e9565b1680600052600482526101b08160ff60406000205416612030565b8060005260048252604060002060ff198154169055604051908152a1602060405160018152f35b34610144576020366003190112610144577fe48e78a7419c5652baf40c86a4d7548a04ec3f569d4e6204e5a1e1890acbfaf460206001600160a01b0361021b6118db565b6102236121e9565b16806000526005825261023e8160ff60406000205416612030565b8060005260058252604060002060ff198154169055604051908152a1602060405160018152f35b3461014457610273366118a8565b61027c82611e0e565b6060810161028d8482511515611b69565b51428111156103ed57506102d76000926001600160a01b0360c085940151169060405194858094819363caf9278560e01b83523360048401526040602484015260448301906119d1565b03925af180156103e1576000916000916103bc575b50156103ab57816000526006602052600a60406000200180549168010000000000000000831015610395576001830180835583101561037f5761035d817fabf12c38379be7b560558cae3ceec83b3762653f7dd74e875af2ea6aeac7eaa89461037194600052602060002001611c69565b6040519182916020835260208301906119d1565b0390a2602060405160018152f35b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b63b4fa3fb360e01b60005260046000fd5b90506103db91503d806000833e6103d38183611823565b810190611bd4565b836102ec565b6040513d6000823e3d90fd5b8363142c294360e31b60005260045260245260446000fd5b34610144576020366003190112610144576020610423600435612107565b6040519015158152f35b34610144576000366003190112610144576020600254604051908152f35b34610144576000366003190112610144576020600354604051908152f35b346101445760203660031901126101445760043561048681611e0e565b60608101918251610605576020820180515142106105f45760204291510151106105e357602460006001600160a01b0381541660405192838092630e82f3b760e41b82528660048301525afa9081156103e15760009161059b575b5080511561058a57604083015142019081421161057457600083815260066020526040902060048101929092557f50df9e2c9fc5a7f4a07e403fa0300b88fcc8c6943bdff4b8ae71f55b7fd95f8994610566926101009261054491600901611c69565b51930151604051938493845260208401526060604084015260608301906119d1565b0390a1602060405160018152f35b634e487b7160e01b600052601160045260246000fd5b630d8dbe2560e01b60005260046000fd5b903d8082843e6105ab8184611823565b8201916020818403126105df5780519167ffffffffffffffff83116105dc57506105d6929101611b85565b846104e1565b80fd5b5080fd5b633d82a7cd60e11b60005260046000fd5b63a0750b5160e01b60005260046000fd5b633e26347b60e21b60005260045260246000fd5b34610144576020366003190112610144577fe5df1e46acc6e102c34b0f812f6557dba66de2e5fed10b64103b5d744083ee3160206001600160a01b0361065d6118db565b6106656121e9565b1680600052600482526106818160ff60406000205416156120e1565b80600052600482526040600020600160ff19825416179055604051908152a1602060405160018152f35b34610144576020366003190112610144577fcf75d44d74f911d2ec243ed8b390c2e4c69f2f2f372a197c0665e72843d49c0d60206001600160a01b036106ef6118db565b6106f76121e9565b1680600052600582526107138160ff60406000205416156120e1565b80600052600582526040600020600160ff19825416179055604051908152a1602060405160018152f35b346101445760003660031901126101445760206001600160a01b037f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c1993005416604051908152f35b346101445760203660031901126101445760206104236107a16118db565b612056565b34610144576107b4366118a8565b6107bd82611e0e565b606081016107ce8482511515611b69565b514281116108eb5750610140810151516108d65761081392916001600160a01b0360e060009301511660405180809681946321614b3960e21b83528760048401611c0a565b03915afa9081156103e1576020926000908193610893575b506108868161085b7f7cc27e4a5626cbc4f8ba1a927b0448de55e6a114bc87660331270c5109ade0719386611c21565b836000526006865261087481600b604060002001611c69565b604051918291878352878301906119d1565b0390a26040519015158152f35b61088693506108cd907f7cc27e4a5626cbc4f8ba1a927b0448de55e6a114bc87660331270c5109ade071923d8091833e6103d38183611823565b9390915061082b565b82637eb9cea960e11b60005260045260246000fd5b836370c05fb960e11b60005260045260245260446000fd5b34610144576020366003190112610144576001600160a01b036109246118db565b166000526004602052602060ff604060002054166040519015158152f35b346101445760003660031901126101445761095b6121e9565b60006001600160a01b037f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300546001600160a01b031981167f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c19930055167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a3005b34610144576000366003190112610144576020600154604051908152f35b61014036600319011261014457610a0e6118db565b36606411610144573660a4116101445760a4359060c4356001600160a01b03811681036101445760e43567ffffffffffffffff811161014457610a55903690600401611861565b9061010435936001600160a01b0385168503610144576101243567ffffffffffffffff811161014457610a8c903690600401611861565b91610a95611d6a565b5034156112e65760443563ffffffff811690818103610144575063ffffffff610abc611fd5565b161115806112d0575b156112b25760843560643581101590816112a7575b5015611296578115158061128a575b15611275576001600160a01b038116600052600460205260ff6040600020541615611257576001600160a01b0386166000526005602052610b3b6001600160a01b03871660ff60406000205416612030565b600254936000198514610574576020610b7691600187016002556040518093819263c16e50ef60e01b835284600484015260248301906119d1565b038160006001600160a01b0387165af19081156103e15760009161120e575b506001600160a01b03169283156111fd576020610bcd916040518093819263c16e50ef60e01b835284600484015260248301906119d1565b038160006001600160a01b038c165af19081156103e1576000916111b4575b506001600160a01b03169485156111a357604051602096610c0d8883611823565b6000825260405195610c1e87611806565b6040958651610c2d8882611823565b60248b825b6064831061118b5750505088528651610c4b8882611823565b60648b825b60a4831061117b5750905089015286880152600060608801526001600160a01b03851660808801526001600160a01b038a1660a088015260c087015260e08601528351610c9d8882611823565b600081526101008601526101208501528251610cb98782611823565b600081526101408501528251610ccf8782611823565b60008152610160850152846000526006865282600020845160009060005b89600282106111535750505081558685015160005b6002811061113e575050838501516003820155606085015160048201556001600160a01b036080860151166001600160a01b036005830191166001600160a01b03198254161790556001600160a01b0360a0860151166001600160a01b036006830191166001600160a01b03198254161790556001600160a01b0360c0860151166001600160a01b036007830191166001600160a01b03198254161790556001600160a01b0360e0860151166001600160a01b036008830191166001600160a01b0319825416179055610ddd61010086015160098301611c69565b610120850151805190680100000000000000008211610395578890600a84015483600a8601558084106110b5575b5001600a830160005288600020896000925b848410611097575050505050610e4e90610e3f610140870151600b8301611c69565b600c6101608701519101611c69565b6000866001600160a01b036084818454169487519485938492639ccb58d560e01b84528c60048501521696876024840152610e8b60448401611ff9565b5af190811561108c57600091611057575b501561058a57846000526006865282600020835190868252606088830152610ed8606083018263ffffffff602091548181168452821c16910152565b610ee860a0830160018301611de6565b600381015460e083015260048101546101008301526001600160a01b036005820154166101208301526001600160a01b036006820154166101408301526001600160a01b036007820154166101608301526001600160a01b036008820154166101808301526101c06101a0830152610f6761022083016009830161192b565b600a820190605f19848203016101c085015281548082528a8201918b8260051b820101936000528b600020926000915b83831061102c575050505050916001600160a01b0380611028999a9b6110098495600c610ff57fdb6ad92217850c3c041086cc44cbec591badf6afe93d864e7f4ea4ba1bcf604199605f19898203016101e08a0152600b840161192b565b878103605f1901610200890152910161192b565b9689850152169516930390a380805195869586528501528301906119f6565b0390f35b90919293948d60016110488193601f198682030187528961192b565b97019301930191939290610f97565b90508681813d8311611085575b61106e8183611823565b810103126101445761107f90611bc7565b88610e9c565b503d611064565b84513d6000823e3d90fd5b600191816110a784935186611c69565b019201920191908a90610e1d565b600a850160005282600020908482015b81830181106110d5575050610e0b565b6001919293946110e582546118f1565b806110f8575b505001908b9392916110c5565b601f81118414611110575050600081555b8c8f6110eb565b83601f61112c9385600052600020920160051c82019101611c52565b8060005260008d812081835555611109565b60019089835193019282828601015501610d02565b829363ffffffff6001939451169063ffffffff8560051b92831b921b19161793019101610ced565b82358152918101918d9101610c50565b819061119684611fe8565b8152019101908c90610c32565b63f72c404960e01b60005260046000fd5b6020813d6020116111f5575b816111cd60209383611823565b810103126105df5751906001600160a01b03821682036105dc57506001600160a01b03610bec565b3d91506111c0565b630fdfa71f60e31b60005260046000fd5b6020813d60201161124f575b8161122760209383611823565b810103126105df5751906001600160a01b03821682036105dc57506001600160a01b03610b95565b3d915061121a565b6001600160a01b0390631e505a8160e01b6000521660045260246000fd5b506313b783af60e21b60005260045260246000fd5b50600154821115610ae9565b6308594fb760e01b60005260046000fd5b905042111587610ada565b604051633744092160e21b81526044906112ce60048201611ff9565bfd5b5063ffffffff6112de611fd5565b161515610ac5565b638c4fcd9360e01b6000523460045260246000fd5b346101445760203660031901126101445761102861131a600435611e0e565b6040519182916020835260208301906119f6565b3461014457602036600319011261014457600435600052600660205260406000206003810154611028600c61142b60048501549461141d6001600160a01b036005830154166001600160a01b036006840154166001600160a01b036007850154166001600160a01b0360088601541691604051936113ba856113b38160098b0161192b565b0386611823565b6113e9604051976113d9896113d281600b850161192b565b038a611823565b6113d2604051809c81930161192b565b6040519b8c9b8c5260208c015260408b015260608a0152608089015260a088015261012060c08801526101208701906119d1565b9085820360e08701526119d1565b908382036101008501526119d1565b346101445760003660031901126101445760206001600160a01b0360005416604051908152f35b346101445760603660031901126101445761147a6118db565b602435906001600160a01b0382168203610144577ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a005460ff8160401c16159267ffffffffffffffff82168015908161167f575b6001149081611675575b15908161166c575b5061165b5767ffffffffffffffff1982166001177ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a005561154a918461161c575b50611528612231565b611530612231565b61153933612143565b611544604435612107565b50612056565b506001600160a01b037f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c19930054166001600160a01b0382160361160a575b5061158d57005b68ff0000000000000000197ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a0054167ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00557fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d2602060405160018152a1005b6116169061013d6121e9565b81611586565b68ffffffffffffffffff191668010000000000000001177ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00558461151f565b63f92ee8a960e01b60005260046000fd5b905015856114df565b303b1591506114d7565b8591506114cd565b34610144576020366003190112610144576001600160a01b036116a86118db565b166000526005602052602060ff604060002054166040519015158152f35b34610144576116d4366118a8565b6116dd82611e0e565b6116ed8360608301511515611b69565b61014081015151156117f157610160810151516117dc57611738600093926001600160a01b0360808694015116906040519586809481936321614b3960e21b83528860048401611c0a565b03925af19081156103e1576020926000908193611799575b50610886816117807f02a24c3402076671e129905ba4579d884b1f94ded1c07fc03d26d11b60bca1699386611c21565b836000526006865261087481600c604060002001611c69565b61088693506117d3907f02a24c3402076671e129905ba4579d884b1f94ded1c07fc03d26d11b60bca169923d8091833e6103d38183611823565b93909150611750565b826360ec327960e01b60005260045260246000fd5b8263032c20ef60e21b60005260045260246000fd5b610180810190811067ffffffffffffffff82111761039557604052565b90601f8019910116810190811067ffffffffffffffff82111761039557604052565b67ffffffffffffffff811161039557601f01601f191660200190565b81601f820112156101445780359061187882611845565b926118866040519485611823565b8284526020838301011161014457816000926020809301838601378301015290565b90604060031983011261014457600435916024359067ffffffffffffffff8211610144576118d891600401611861565b90565b600435906001600160a01b038216820361014457565b90600182811c92168015611921575b602083101461190b57565b634e487b7160e01b600052602260045260246000fd5b91607f1691611900565b6000929181549161193b836118f1565b8083529260018116908115611991575060011461195757505050565b60009081526020812093945091925b838310611977575060209250010190565b600181602092949394548385870101520191019190611966565b915050602093945060ff929192191683830152151560051b010190565b60005b8381106119c15750506000910152565b81810151838201526020016119b1565b906020916119ea815180928185528580860191016119ae565b601f01601f1916010190565b80519192916000845b60028210611b4d5750505060208101516000604085015b60028210611b375750505060408101516080840152606081015160a08401526001600160a01b0360808201511660c08401526001600160a01b0360a08201511660e08401526001600160a01b0360c0820151166101008401526001600160a01b0360e082015116610120840152611aa06101008201516101c06101408601526101c08501906119d1565b9261012082015193818103610160830152845180825260208201906020808260051b8501019701916000905b828210611b09575050505050610160611af76118d894956101408501518482036101808601526119d1565b920151906101a08184039101526119d1565b9091929397602080611b27600193601f198d820301865288516119d1565b9a96019493919091019101611acc565b6020806001928551815201930191019091611a16565b60208060019263ffffffff8651168152019301910190916119ff565b15611b715750565b63166b4d0360e01b60005260045260246000fd5b81601f82011215610144578051611b9b81611845565b92611ba96040519485611823565b81845260208284010111610144576118d891602080850191016119ae565b5190811515820361014457565b91906040838203126101445782519067ffffffffffffffff821161014457611c036020916118d8938601611b85565b9301611bc7565b6040906118d89392815281602082015201906119d1565b15611c295750565b604051632f9f8ab960e01b815260206004820152908190611c4e9060248301906119d1565b0390fd5b818110611c5d575050565b60008155600101611c52565b919091825167ffffffffffffffff811161039557611c8782546118f1565b601f8111611d2d575b506020601f8211600114611ccb5781929394600092611cc0575b50508160011b916000199060031b1c1916179055565b015190503880611caa565b601f1982169083600052806000209160005b818110611d1557509583600195969710611cfc575b505050811b019055565b015160001960f88460031b161c19169055388080611cf2565b9192602060018192868b015181550194019201611cdd565b611d5a90836000526020600020601f840160051c81019160208510611d60575b601f0160051c0190611c52565b38611c90565b9091508190611d4d565b60405190611d7782611806565b606061016083600060408051611d8d8282611823565b8136823783528051611d9f8282611823565b81368237602084015282015260008382015260006080820152600060a0820152600060c0820152600060e08201528261010082015282610120820152826101408201520152565b906000905b60028210611df857505050565b6001602081928554815201930191019091611deb565b90611e17611d6a565b50816000526006602052604060002091604051611e3381611806565b604051611e51818663ffffffff602091548181168452821c16910152565b611e5c604082611823565b8152604051611e6e8160018701611de6565b611e79604082611823565b602082015260038401546040820152600484015460608201526001600160a01b0360058501541693608082019485526001600160a01b0360068201541660a08301526001600160a01b0360078201541660c08301526001600160a01b0360088201541660e0830152604051611efc81611ef5816009860161192b565b0382611823565b610100830152600a8101805467ffffffffffffffff81116103955760208160051b0191611f2c6040519384611823565b818352602083019060005260206000206000915b838310611fb05750505050611f8b8392600c926101206001600160a01b03960152604051611f7581611ef581600b860161192b565b610140850152611ef5604051809481930161192b565b61016082015293511615611f9c5750565b63cd6f4a4f60e01b60005260045260246000fd5b600160208192604051611fc781611ef5818961192b565b815201920192019190611f40565b60243563ffffffff811681036101445790565b359063ffffffff8216820361014457565b6024906000905b6002821061200d57505050565b60208060019263ffffffff61202187611fe8565b16815201930191019091612000565b156120385750565b6001600160a01b03906321ac7c5f60e01b6000521660045260246000fd5b6001600160a01b03906120676121e9565b16801515806120cc575b156120b8576020817f016ea868599173c3163f65dea5e4677b2be5f0ececb4ec15d1166a27de35a533926001600160a01b03196000541617600055604051908152a1600190565b63157970a560e21b60005260045260246000fd5b506001600160a01b0360005416811415612071565b156120e95750565b6001600160a01b039063b29d459560e01b6000521660045260246000fd5b60207fba0716ba1ee2ea8ecc4c64119b4537cdb42a99d82acf92af5b87607b8b523552916121336121e9565b80600155604051908152a1600190565b6001600160a01b031680156121d3576001600160a01b037f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c19930054826001600160a01b03198216177f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c19930055167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a3565b631e4fbdf760e01b600052600060045260246000fd5b6001600160a01b037f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c1993005416330361221c57565b63118cdaa760e01b6000523360045260246000fd5b60ff7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a005460401c161561226057565b631afcd79f60e31b60005260046000fdfea164736f6c634300081a000a", + "devdoc": { + "errors": { + "InvalidInitialization()": [ + { + "details": "The contract is already initialized." + } + ], + "NotInitializing()": [ + { + "details": "The contract is not initializing." + } + ], + "OwnableInvalidOwner(address)": [ + { + "details": "The owner is not a valid owner account. (eg. `address(0)`)" + } + ], + "OwnableUnauthorizedAccount(address)": [ + { + "details": "The caller account is not authorized to perform an operation." + } + ] + }, + "events": { + "CiphertextOutputPublished(uint256,bytes)": { + "params": { + "ciphertextOutput": "ABI encoded ciphertext output.", + "e3Id": "ID of the E3." + } + }, + "ComputationModuleDisabled(address)": { + "params": { + "computationModule": "The address of the computation module." + } + }, + "ComputationModuleEnabled(address)": { + "params": { + "computationModule": "The address of the computation module." + } + }, + "CyphernodeRegistrySet(address)": { + "params": { + "cyphernodeRegistry": "The address of the CyphernodeRegistry contract." + } + }, + "E3Activated(uint256,uint256,bytes)": { + "params": { + "committeePublicKey": "Public key of the committee.", + "e3Id": "ID of the E3.", + "expiration": "Timestamp when committee duties expire." + } + }, + "E3Requested(uint256,(uint32[2],uint256[2],uint256,uint256,address,address,address,address,bytes,bytes[],bytes,bytes),address,address,address)": { + "params": { + "computationModule": "Address of the Computation module selected.", + "e3": "Details of the E3.", + "e3Id": "ID of the E3.", + "executionModule": "Address of the execution module selected.", + "filter": "Address of the pool of nodes from which the Cypher Node committee was selected." + } + }, + "ExecutionModuleDisabled(address)": { + "params": { + "executionModule": "The address of the execution module." + } + }, + "ExecutionModuleEnabled(address)": { + "params": { + "executionModule": "The address of the execution module." + } + }, + "Initialized(uint64)": { + "details": "Triggered when the contract has been initialized or reinitialized." + }, + "InputPublished(uint256,bytes)": { + "params": { + "data": "ABI encoded input data.", + "e3Id": "ID of the E3." + } + }, + "MaxDurationSet(uint256)": { + "params": { + "maxDuration": "The maximum duration of a computation in seconds." + } + }, + "PlaintextOutputPublished(uint256,bytes)": { + "params": { + "e3Id": "ID of the E3.", + "plaintextOutput": "ABI encoded plaintext output." + } + } + }, + "kind": "dev", + "methods": { + "activate(uint256)": { + "details": "This function MUST emit the E3Activated event.This function MUST revert if the given E3 has not yet been requested.This function MUST revert if the selected node committee has not yet published a public key.", + "params": { + "e3Id": "ID of the E3." + } + }, + "constructor": { + "params": { + "_maxDuration": "The maximum duration of a computation in seconds", + "_owner": "The owner of this contract" + } + }, + "getE3(uint256)": { + "details": "This function MUST revert if the E3 does not exist.", + "params": { + "e3Id": "ID of the E3." + }, + "returns": { + "e3": "The struct representing the requested E3." + } + }, + "initialize(address,address,uint256)": { + "params": { + "_maxDuration": "The maximum duration of a computation in seconds", + "_owner": "The owner of this contract" + } + }, + "owner()": { + "details": "Returns the address of the current owner." + }, + "publishCiphertextOutput(uint256,bytes)": { + "details": "This function MUST emit the CiphertextOutputPublished event.", + "params": { + "data": "ABI encoded output data to verify.", + "e3Id": "ID of the E3." + }, + "returns": { + "success": "True if the output was successfully published." + } + }, + "publishInput(uint256,bytes)": { + "details": "This function MUST revert if the E3 is not yet activated.This function MUST emit the InputPublished event.", + "params": { + "data": "ABI encoded input data to publish.", + "e3Id": "ID of the E3." + }, + "returns": { + "success": "True if the input was successfully published." + } + }, + "publishPlaintextOutput(uint256,bytes)": { + "details": "This function MUST revert if the output has not been published.This function MUST emit the PlaintextOutputPublished event.", + "params": { + "data": "ABI encoded output data to decrypt.", + "e3Id": "ID of the E3." + }, + "returns": { + "success": "True if the output was successfully decrypted." + } + }, + "renounceOwnership()": { + "details": "Leaves the contract without owner. It will not be possible to call `onlyOwner` functions. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby disabling any functionality that is only available to the owner." + }, + "request(address,uint32[2],uint256[2],uint256,address,bytes,address,bytes)": { + "details": "This function MUST emit the E3Requested event.", + "params": { + "computationModule": "Address of the computation module.", + "computationParams": "ABI encoded computation parameters.", + "duration": "The duration of the computation in seconds.", + "emParams": "ABI encoded execution module parameters.", + "executionModule": "Address of the execution module.", + "filter": "IDs of the pool of nodes from which to select the committee.", + "threshold": "The M/N threshold for the committee." + }, + "returns": { + "e3": "The E3 struct.", + "e3Id": "ID of the E3." + } + }, + "setMaxDuration(uint256)": { + "params": { + "_maxDuration": "The maximum duration of a computation in seconds." + }, + "returns": { + "success": "True if the max duration was successfully set." + } + }, + "transferOwnership(address)": { + "details": "Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner." + } + }, + "version": 1 + }, + "userdoc": { + "events": { + "CiphertextOutputPublished(uint256,bytes)": { + "notice": "This event MUST be emitted when the ciphertext output of an Encrypted Execution Environment (E3) is successfully published." + }, + "ComputationModuleDisabled(address)": { + "notice": "This event MUST be emitted any time a computation module is disabled." + }, + "ComputationModuleEnabled(address)": { + "notice": "This event MUST be emitted any time a computation module is enabled." + }, + "CyphernodeRegistrySet(address)": { + "notice": "This event MUST be emitted any time the CyphernodeRegistry is set." + }, + "E3Activated(uint256,uint256,bytes)": { + "notice": "This event MUST be emitted when an Encrypted Execution Environment (E3) is successfully activated." + }, + "E3Requested(uint256,(uint32[2],uint256[2],uint256,uint256,address,address,address,address,bytes,bytes[],bytes,bytes),address,address,address)": { + "notice": "This event MUST be emitted when an Encrypted Execution Environment (E3) is successfully requested." + }, + "ExecutionModuleDisabled(address)": { + "notice": "This event MUST be emitted any time an execution module is disabled." + }, + "ExecutionModuleEnabled(address)": { + "notice": "This event MUST be emitted any time an execution module is enabled." + }, + "InputPublished(uint256,bytes)": { + "notice": "This event MUST be emitted when an input to an Encrypted Execution Environment (E3) is successfully published." + }, + "MaxDurationSet(uint256)": { + "notice": "This event MUST be emitted any time the `maxDuration` is set." + }, + "PlaintextOutputPublished(uint256,bytes)": { + "notice": "This event MUST be emitted when the plaintext output of an Encrypted Execution Environment (E3) is successfully published." + } + }, + "kind": "user", + "methods": { + "activate(uint256)": { + "notice": "This function should be called to activate an Encrypted Execution Environment (E3) once it has been initialized and is ready for input." + }, + "getE3(uint256)": { + "notice": "This function should be called to retrieve the details of an Encrypted Execution Environment (E3)." + }, + "publishCiphertextOutput(uint256,bytes)": { + "notice": "This function should be called to publish output data for an Encrypted Execution Environment (E3)." + }, + "publishInput(uint256,bytes)": { + "notice": "This function should be called to publish input data for Encrypted Execution Environment (E3)." + }, + "publishPlaintextOutput(uint256,bytes)": { + "notice": "This function publishes the plaintext output of an Encrypted Execution Environment (E3)." + }, + "request(address,uint32[2],uint256[2],uint256,address,bytes,address,bytes)": { + "notice": "This function should be called to request a computation within an Encrypted Execution Environment (E3)." + }, + "setMaxDuration(uint256)": { + "notice": "This function should be called to set the maximum duration of requested computations." + } + }, + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 516, + "contract": "contracts/Enclave.sol:Enclave", + "label": "cyphernodeRegistry", + "offset": 0, + "slot": "0", + "type": "t_contract(ICyphernodeRegistry)1570" + }, + { + "astId": 518, + "contract": "contracts/Enclave.sol:Enclave", + "label": "maxDuration", + "offset": 0, + "slot": "1", + "type": "t_uint256" + }, + { + "astId": 520, + "contract": "contracts/Enclave.sol:Enclave", + "label": "nexte3Id", + "offset": 0, + "slot": "2", + "type": "t_uint256" + }, + { + "astId": 522, + "contract": "contracts/Enclave.sol:Enclave", + "label": "requests", + "offset": 0, + "slot": "3", + "type": "t_uint256" + }, + { + "astId": 527, + "contract": "contracts/Enclave.sol:Enclave", + "label": "computationModules", + "offset": 0, + "slot": "4", + "type": "t_mapping(t_contract(IComputationModule)1495,t_bool)" + }, + { + "astId": 532, + "contract": "contracts/Enclave.sol:Enclave", + "label": "executionModules", + "offset": 0, + "slot": "5", + "type": "t_mapping(t_contract(IExecutionModule)1802,t_bool)" + }, + { + "astId": 537, + "contract": "contracts/Enclave.sol:Enclave", + "label": "e3s", + "offset": 0, + "slot": "6", + "type": "t_mapping(t_uint256,t_struct(E3)1615_storage)" + } + ], + "types": { + "t_array(t_bytes_storage)dyn_storage": { + "base": "t_bytes_storage", + "encoding": "dynamic_array", + "label": "bytes[]", + "numberOfBytes": "32" + }, + "t_array(t_uint256)2_storage": { + "base": "t_uint256", + "encoding": "inplace", + "label": "uint256[2]", + "numberOfBytes": "64" + }, + "t_array(t_uint32)2_storage": { + "base": "t_uint32", + "encoding": "inplace", + "label": "uint32[2]", + "numberOfBytes": "32" + }, + "t_bool": { + "encoding": "inplace", + "label": "bool", + "numberOfBytes": "1" + }, + "t_bytes_storage": { + "encoding": "bytes", + "label": "bytes", + "numberOfBytes": "32" + }, + "t_contract(IComputationModule)1495": { + "encoding": "inplace", + "label": "contract IComputationModule", + "numberOfBytes": "20" + }, + "t_contract(ICyphernodeRegistry)1570": { + "encoding": "inplace", + "label": "contract ICyphernodeRegistry", + "numberOfBytes": "20" + }, + "t_contract(IExecutionModule)1802": { + "encoding": "inplace", + "label": "contract IExecutionModule", + "numberOfBytes": "20" + }, + "t_contract(IInputValidator)1817": { + "encoding": "inplace", + "label": "contract IInputValidator", + "numberOfBytes": "20" + }, + "t_contract(IOutputVerifier)1832": { + "encoding": "inplace", + "label": "contract IOutputVerifier", + "numberOfBytes": "20" + }, + "t_mapping(t_contract(IComputationModule)1495,t_bool)": { + "encoding": "mapping", + "key": "t_contract(IComputationModule)1495", + "label": "mapping(contract IComputationModule => bool)", + "numberOfBytes": "32", + "value": "t_bool" + }, + "t_mapping(t_contract(IExecutionModule)1802,t_bool)": { + "encoding": "mapping", + "key": "t_contract(IExecutionModule)1802", + "label": "mapping(contract IExecutionModule => bool)", + "numberOfBytes": "32", + "value": "t_bool" + }, + "t_mapping(t_uint256,t_struct(E3)1615_storage)": { + "encoding": "mapping", + "key": "t_uint256", + "label": "mapping(uint256 => struct E3)", + "numberOfBytes": "32", + "value": "t_struct(E3)1615_storage" + }, + "t_struct(E3)1615_storage": { + "encoding": "inplace", + "label": "struct E3", + "members": [ + { + "astId": 1585, + "contract": "contracts/Enclave.sol:Enclave", + "label": "threshold", + "offset": 0, + "slot": "0", + "type": "t_array(t_uint32)2_storage" + }, + { + "astId": 1589, + "contract": "contracts/Enclave.sol:Enclave", + "label": "startWindow", + "offset": 0, + "slot": "1", + "type": "t_array(t_uint256)2_storage" + }, + { + "astId": 1591, + "contract": "contracts/Enclave.sol:Enclave", + "label": "duration", + "offset": 0, + "slot": "3", + "type": "t_uint256" + }, + { + "astId": 1593, + "contract": "contracts/Enclave.sol:Enclave", + "label": "expiration", + "offset": 0, + "slot": "4", + "type": "t_uint256" + }, + { + "astId": 1596, + "contract": "contracts/Enclave.sol:Enclave", + "label": "computationModule", + "offset": 0, + "slot": "5", + "type": "t_contract(IComputationModule)1495" + }, + { + "astId": 1599, + "contract": "contracts/Enclave.sol:Enclave", + "label": "executionModule", + "offset": 0, + "slot": "6", + "type": "t_contract(IExecutionModule)1802" + }, + { + "astId": 1602, + "contract": "contracts/Enclave.sol:Enclave", + "label": "inputValidator", + "offset": 0, + "slot": "7", + "type": "t_contract(IInputValidator)1817" + }, + { + "astId": 1605, + "contract": "contracts/Enclave.sol:Enclave", + "label": "outputVerifier", + "offset": 0, + "slot": "8", + "type": "t_contract(IOutputVerifier)1832" + }, + { + "astId": 1607, + "contract": "contracts/Enclave.sol:Enclave", + "label": "committeePublicKey", + "offset": 0, + "slot": "9", + "type": "t_bytes_storage" + }, + { + "astId": 1610, + "contract": "contracts/Enclave.sol:Enclave", + "label": "inputs", + "offset": 0, + "slot": "10", + "type": "t_array(t_bytes_storage)dyn_storage" + }, + { + "astId": 1612, + "contract": "contracts/Enclave.sol:Enclave", + "label": "ciphertextOutput", + "offset": 0, + "slot": "11", + "type": "t_bytes_storage" + }, + { + "astId": 1614, + "contract": "contracts/Enclave.sol:Enclave", + "label": "plaintextOutput", + "offset": 0, + "slot": "12", + "type": "t_bytes_storage" + } + ], + "numberOfBytes": "416" + }, + "t_uint256": { + "encoding": "inplace", + "label": "uint256", + "numberOfBytes": "32" + }, + "t_uint32": { + "encoding": "inplace", + "label": "uint32", + "numberOfBytes": "4" + } + } + } +} \ No newline at end of file diff --git a/packages/evm/deployments/sepolia/NaiveRegistryFilter.json b/packages/evm/deployments/sepolia/NaiveRegistryFilter.json new file mode 100644 index 00000000..bc51ef5b --- /dev/null +++ b/packages/evm/deployments/sepolia/NaiveRegistryFilter.json @@ -0,0 +1,458 @@ +{ + "address": "0x4c19b2b2cE63129B494Cb0b0eCa4a2f761C649D6", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "_owner", + "type": "address" + }, + { + "internalType": "address", + "name": "_enclave", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "CommitteeAlreadyExists", + "type": "error" + }, + { + "inputs": [], + "name": "CommitteeAlreadyPublished", + "type": "error" + }, + { + "inputs": [], + "name": "CommitteeDoesNotExist", + "type": "error" + }, + { + "inputs": [], + "name": "CommitteeNotPublished", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidInitialization", + "type": "error" + }, + { + "inputs": [], + "name": "NotInitializing", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyRegistry", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "OwnableInvalidOwner", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "OwnableUnauthorizedAccount", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint64", + "name": "version", + "type": "uint64" + } + ], + "name": "Initialized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "e3", + "type": "uint256" + } + ], + "name": "committees", + "outputs": [ + { + "internalType": "bytes", + "name": "publicKey", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_owner", + "type": "address" + }, + { + "internalType": "address", + "name": "_registry", + "type": "address" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "e3Id", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "nodes", + "type": "address[]" + }, + { + "internalType": "bytes", + "name": "publicKey", + "type": "bytes" + } + ], + "name": "publishCommittee", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "registry", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "e3Id", + "type": "uint256" + }, + { + "internalType": "uint32[2]", + "name": "threshold", + "type": "uint32[2]" + } + ], + "name": "requestCommittee", + "outputs": [ + { + "internalType": "bool", + "name": "success", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_registry", + "type": "address" + } + ], + "name": "setRegistry", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "transactionHash": "0x3e1cd2b9beba7d5ca0540a7dc817b897998eed25f69128ab8c18e72213a607bb", + "receipt": { + "to": null, + "from": "0x485E60C486671E932fd9C53d4110cdEab1E7F0eb", + "contractAddress": "0x4c19b2b2cE63129B494Cb0b0eCa4a2f761C649D6", + "transactionIndex": 103, + "gasUsed": "765625", + "logsBloom": "0x00000000000000000000000000000100000000000000000000800000000080000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000101000000000000000000000000000000000000020000000000000000000800000000000000000000000000000000400000000000000000000800000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000020000000000000000000020000000000000000000000000000000000000000000000", + "blockHash": "0x5f2631ec7ee97ddbc4d178d3d10e876979fcefde8efcb1e7be33f21c66013da9", + "transactionHash": "0x3e1cd2b9beba7d5ca0540a7dc817b897998eed25f69128ab8c18e72213a607bb", + "logs": [ + { + "transactionIndex": 103, + "blockNumber": 6668292, + "transactionHash": "0x3e1cd2b9beba7d5ca0540a7dc817b897998eed25f69128ab8c18e72213a607bb", + "address": "0x4c19b2b2cE63129B494Cb0b0eCa4a2f761C649D6", + "topics": [ + "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x000000000000000000000000485e60c486671e932fd9c53d4110cdeab1e7f0eb" + ], + "data": "0x", + "logIndex": 154, + "blockHash": "0x5f2631ec7ee97ddbc4d178d3d10e876979fcefde8efcb1e7be33f21c66013da9" + }, + { + "transactionIndex": 103, + "blockNumber": 6668292, + "transactionHash": "0x3e1cd2b9beba7d5ca0540a7dc817b897998eed25f69128ab8c18e72213a607bb", + "address": "0x4c19b2b2cE63129B494Cb0b0eCa4a2f761C649D6", + "topics": [ + "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", + "0x000000000000000000000000485e60c486671e932fd9c53d4110cdeab1e7f0eb", + "0x000000000000000000000000485e60c486671e932fd9c53d4110cdeab1e7f0eb" + ], + "data": "0x", + "logIndex": 155, + "blockHash": "0x5f2631ec7ee97ddbc4d178d3d10e876979fcefde8efcb1e7be33f21c66013da9" + }, + { + "transactionIndex": 103, + "blockNumber": 6668292, + "transactionHash": "0x3e1cd2b9beba7d5ca0540a7dc817b897998eed25f69128ab8c18e72213a607bb", + "address": "0x4c19b2b2cE63129B494Cb0b0eCa4a2f761C649D6", + "topics": [ + "0xc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d2" + ], + "data": "0x0000000000000000000000000000000000000000000000000000000000000001", + "logIndex": 156, + "blockHash": "0x5f2631ec7ee97ddbc4d178d3d10e876979fcefde8efcb1e7be33f21c66013da9" + } + ], + "blockNumber": 6668292, + "cumulativeGasUsed": "14723279", + "status": 1, + "byzantium": true + }, + "args": [ + "0x485E60C486671E932fd9C53d4110cdEab1E7F0eb", + "0xF9E3aeB059D699Ac4541625DE81062d6D8ad7e85" + ], + "numDeployments": 1, + "solcInputHash": "d0e6e4f19028714f394c36db62dff2be", + "metadata": "{\"compiler\":{\"version\":\"0.8.26+commit.8a97fa7a\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_enclave\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"CommitteeAlreadyExists\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CommitteeAlreadyPublished\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CommitteeDoesNotExist\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CommitteeNotPublished\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidInitialization\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NotInitializing\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyRegistry\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"OwnableInvalidOwner\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"OwnableUnauthorizedAccount\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"version\",\"type\":\"uint64\"}],\"name\":\"Initialized\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"e3\",\"type\":\"uint256\"}],\"name\":\"committees\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"publicKey\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_registry\",\"type\":\"address\"}],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"e3Id\",\"type\":\"uint256\"},{\"internalType\":\"address[]\",\"name\":\"nodes\",\"type\":\"address[]\"},{\"internalType\":\"bytes\",\"name\":\"publicKey\",\"type\":\"bytes\"}],\"name\":\"publishCommittee\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"registry\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"e3Id\",\"type\":\"uint256\"},{\"internalType\":\"uint32[2]\",\"name\":\"threshold\",\"type\":\"uint32[2]\"}],\"name\":\"requestCommittee\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_registry\",\"type\":\"address\"}],\"name\":\"setRegistry\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"errors\":{\"InvalidInitialization()\":[{\"details\":\"The contract is already initialized.\"}],\"NotInitializing()\":[{\"details\":\"The contract is not initializing.\"}],\"OwnableInvalidOwner(address)\":[{\"details\":\"The owner is not a valid owner account. (eg. `address(0)`)\"}],\"OwnableUnauthorizedAccount(address)\":[{\"details\":\"The caller account is not authorized to perform an operation.\"}]},\"events\":{\"Initialized(uint64)\":{\"details\":\"Triggered when the contract has been initialized or reinitialized.\"}},\"kind\":\"dev\",\"methods\":{\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"renounceOwnership()\":{\"details\":\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby disabling any functionality that is only available to the owner.\"},\"transferOwnership(address)\":{\"details\":\"Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/registry/NaiveRegistryFilter.sol\":\"NaiveRegistryFilter\"},\"evmVersion\":\"paris\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"none\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":800},\"remappings\":[],\"viaIR\":true},\"sources\":{\"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol)\\n\\npragma solidity ^0.8.20;\\n\\nimport {ContextUpgradeable} from \\\"../utils/ContextUpgradeable.sol\\\";\\nimport {Initializable} from \\\"../proxy/utils/Initializable.sol\\\";\\n\\n/**\\n * @dev Contract module which provides a basic access control mechanism, where\\n * there is an account (an owner) that can be granted exclusive access to\\n * specific functions.\\n *\\n * The initial owner is set to the address provided by the deployer. This can\\n * later be changed with {transferOwnership}.\\n *\\n * This module is used through inheritance. It will make available the modifier\\n * `onlyOwner`, which can be applied to your functions to restrict their use to\\n * the owner.\\n */\\nabstract contract OwnableUpgradeable is Initializable, ContextUpgradeable {\\n /// @custom:storage-location erc7201:openzeppelin.storage.Ownable\\n struct OwnableStorage {\\n address _owner;\\n }\\n\\n // keccak256(abi.encode(uint256(keccak256(\\\"openzeppelin.storage.Ownable\\\")) - 1)) & ~bytes32(uint256(0xff))\\n bytes32 private constant OwnableStorageLocation = 0x9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300;\\n\\n function _getOwnableStorage() private pure returns (OwnableStorage storage $) {\\n assembly {\\n $.slot := OwnableStorageLocation\\n }\\n }\\n\\n /**\\n * @dev The caller account is not authorized to perform an operation.\\n */\\n error OwnableUnauthorizedAccount(address account);\\n\\n /**\\n * @dev The owner is not a valid owner account. (eg. `address(0)`)\\n */\\n error OwnableInvalidOwner(address owner);\\n\\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\\n\\n /**\\n * @dev Initializes the contract setting the address provided by the deployer as the initial owner.\\n */\\n function __Ownable_init(address initialOwner) internal onlyInitializing {\\n __Ownable_init_unchained(initialOwner);\\n }\\n\\n function __Ownable_init_unchained(address initialOwner) internal onlyInitializing {\\n if (initialOwner == address(0)) {\\n revert OwnableInvalidOwner(address(0));\\n }\\n _transferOwnership(initialOwner);\\n }\\n\\n /**\\n * @dev Throws if called by any account other than the owner.\\n */\\n modifier onlyOwner() {\\n _checkOwner();\\n _;\\n }\\n\\n /**\\n * @dev Returns the address of the current owner.\\n */\\n function owner() public view virtual returns (address) {\\n OwnableStorage storage $ = _getOwnableStorage();\\n return $._owner;\\n }\\n\\n /**\\n * @dev Throws if the sender is not the owner.\\n */\\n function _checkOwner() internal view virtual {\\n if (owner() != _msgSender()) {\\n revert OwnableUnauthorizedAccount(_msgSender());\\n }\\n }\\n\\n /**\\n * @dev Leaves the contract without owner. It will not be possible to call\\n * `onlyOwner` functions. Can only be called by the current owner.\\n *\\n * NOTE: Renouncing ownership will leave the contract without an owner,\\n * thereby disabling any functionality that is only available to the owner.\\n */\\n function renounceOwnership() public virtual onlyOwner {\\n _transferOwnership(address(0));\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Can only be called by the current owner.\\n */\\n function transferOwnership(address newOwner) public virtual onlyOwner {\\n if (newOwner == address(0)) {\\n revert OwnableInvalidOwner(address(0));\\n }\\n _transferOwnership(newOwner);\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Internal function without access restriction.\\n */\\n function _transferOwnership(address newOwner) internal virtual {\\n OwnableStorage storage $ = _getOwnableStorage();\\n address oldOwner = $._owner;\\n $._owner = newOwner;\\n emit OwnershipTransferred(oldOwner, newOwner);\\n }\\n}\\n\",\"keccak256\":\"0xc163fcf9bb10138631a9ba5564df1fa25db9adff73bd9ee868a8ae1858fe093a\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.0.0) (proxy/utils/Initializable.sol)\\n\\npragma solidity ^0.8.20;\\n\\n/**\\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\\n * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an\\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\\n *\\n * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be\\n * reused. This mechanism prevents re-execution of each \\\"step\\\" but allows the creation of new initialization steps in\\n * case an upgrade adds a module that needs to be initialized.\\n *\\n * For example:\\n *\\n * [.hljs-theme-light.nopadding]\\n * ```solidity\\n * contract MyToken is ERC20Upgradeable {\\n * function initialize() initializer public {\\n * __ERC20_init(\\\"MyToken\\\", \\\"MTK\\\");\\n * }\\n * }\\n *\\n * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {\\n * function initializeV2() reinitializer(2) public {\\n * __ERC20Permit_init(\\\"MyToken\\\");\\n * }\\n * }\\n * ```\\n *\\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\\n * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.\\n *\\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\\n *\\n * [CAUTION]\\n * ====\\n * Avoid leaving a contract uninitialized.\\n *\\n * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation\\n * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke\\n * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:\\n *\\n * [.hljs-theme-light.nopadding]\\n * ```\\n * /// @custom:oz-upgrades-unsafe-allow constructor\\n * constructor() {\\n * _disableInitializers();\\n * }\\n * ```\\n * ====\\n */\\nabstract contract Initializable {\\n /**\\n * @dev Storage of the initializable contract.\\n *\\n * It's implemented on a custom ERC-7201 namespace to reduce the risk of storage collisions\\n * when using with upgradeable contracts.\\n *\\n * @custom:storage-location erc7201:openzeppelin.storage.Initializable\\n */\\n struct InitializableStorage {\\n /**\\n * @dev Indicates that the contract has been initialized.\\n */\\n uint64 _initialized;\\n /**\\n * @dev Indicates that the contract is in the process of being initialized.\\n */\\n bool _initializing;\\n }\\n\\n // keccak256(abi.encode(uint256(keccak256(\\\"openzeppelin.storage.Initializable\\\")) - 1)) & ~bytes32(uint256(0xff))\\n bytes32 private constant INITIALIZABLE_STORAGE = 0xf0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00;\\n\\n /**\\n * @dev The contract is already initialized.\\n */\\n error InvalidInitialization();\\n\\n /**\\n * @dev The contract is not initializing.\\n */\\n error NotInitializing();\\n\\n /**\\n * @dev Triggered when the contract has been initialized or reinitialized.\\n */\\n event Initialized(uint64 version);\\n\\n /**\\n * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,\\n * `onlyInitializing` functions can be used to initialize parent contracts.\\n *\\n * Similar to `reinitializer(1)`, except that in the context of a constructor an `initializer` may be invoked any\\n * number of times. This behavior in the constructor can be useful during testing and is not expected to be used in\\n * production.\\n *\\n * Emits an {Initialized} event.\\n */\\n modifier initializer() {\\n // solhint-disable-next-line var-name-mixedcase\\n InitializableStorage storage $ = _getInitializableStorage();\\n\\n // Cache values to avoid duplicated sloads\\n bool isTopLevelCall = !$._initializing;\\n uint64 initialized = $._initialized;\\n\\n // Allowed calls:\\n // - initialSetup: the contract is not in the initializing state and no previous version was\\n // initialized\\n // - construction: the contract is initialized at version 1 (no reininitialization) and the\\n // current contract is just being deployed\\n bool initialSetup = initialized == 0 && isTopLevelCall;\\n bool construction = initialized == 1 && address(this).code.length == 0;\\n\\n if (!initialSetup && !construction) {\\n revert InvalidInitialization();\\n }\\n $._initialized = 1;\\n if (isTopLevelCall) {\\n $._initializing = true;\\n }\\n _;\\n if (isTopLevelCall) {\\n $._initializing = false;\\n emit Initialized(1);\\n }\\n }\\n\\n /**\\n * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the\\n * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be\\n * used to initialize parent contracts.\\n *\\n * A reinitializer may be used after the original initialization step. This is essential to configure modules that\\n * are added through upgrades and that require initialization.\\n *\\n * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`\\n * cannot be nested. If one is invoked in the context of another, execution will revert.\\n *\\n * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in\\n * a contract, executing them in the right order is up to the developer or operator.\\n *\\n * WARNING: Setting the version to 2**64 - 1 will prevent any future reinitialization.\\n *\\n * Emits an {Initialized} event.\\n */\\n modifier reinitializer(uint64 version) {\\n // solhint-disable-next-line var-name-mixedcase\\n InitializableStorage storage $ = _getInitializableStorage();\\n\\n if ($._initializing || $._initialized >= version) {\\n revert InvalidInitialization();\\n }\\n $._initialized = version;\\n $._initializing = true;\\n _;\\n $._initializing = false;\\n emit Initialized(version);\\n }\\n\\n /**\\n * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the\\n * {initializer} and {reinitializer} modifiers, directly or indirectly.\\n */\\n modifier onlyInitializing() {\\n _checkInitializing();\\n _;\\n }\\n\\n /**\\n * @dev Reverts if the contract is not in an initializing state. See {onlyInitializing}.\\n */\\n function _checkInitializing() internal view virtual {\\n if (!_isInitializing()) {\\n revert NotInitializing();\\n }\\n }\\n\\n /**\\n * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.\\n * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized\\n * to any version. It is recommended to use this to lock implementation contracts that are designed to be called\\n * through proxies.\\n *\\n * Emits an {Initialized} event the first time it is successfully executed.\\n */\\n function _disableInitializers() internal virtual {\\n // solhint-disable-next-line var-name-mixedcase\\n InitializableStorage storage $ = _getInitializableStorage();\\n\\n if ($._initializing) {\\n revert InvalidInitialization();\\n }\\n if ($._initialized != type(uint64).max) {\\n $._initialized = type(uint64).max;\\n emit Initialized(type(uint64).max);\\n }\\n }\\n\\n /**\\n * @dev Returns the highest version that has been initialized. See {reinitializer}.\\n */\\n function _getInitializedVersion() internal view returns (uint64) {\\n return _getInitializableStorage()._initialized;\\n }\\n\\n /**\\n * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.\\n */\\n function _isInitializing() internal view returns (bool) {\\n return _getInitializableStorage()._initializing;\\n }\\n\\n /**\\n * @dev Returns a pointer to the storage namespace.\\n */\\n // solhint-disable-next-line var-name-mixedcase\\n function _getInitializableStorage() private pure returns (InitializableStorage storage $) {\\n assembly {\\n $.slot := INITIALIZABLE_STORAGE\\n }\\n }\\n}\\n\",\"keccak256\":\"0x631188737069917d2f909d29ce62c4d48611d326686ba6683e26b72a23bfac0b\",\"license\":\"MIT\"},\"@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)\\n\\npragma solidity ^0.8.20;\\nimport {Initializable} from \\\"../proxy/utils/Initializable.sol\\\";\\n\\n/**\\n * @dev Provides information about the current execution context, including the\\n * sender of the transaction and its data. While these are generally available\\n * via msg.sender and msg.data, they should not be accessed in such a direct\\n * manner, since when dealing with meta-transactions the account sending and\\n * paying for execution may not be the actual sender (as far as an application\\n * is concerned).\\n *\\n * This contract is only required for intermediate, library-like contracts.\\n */\\nabstract contract ContextUpgradeable is Initializable {\\n function __Context_init() internal onlyInitializing {\\n }\\n\\n function __Context_init_unchained() internal onlyInitializing {\\n }\\n function _msgSender() internal view virtual returns (address) {\\n return msg.sender;\\n }\\n\\n function _msgData() internal view virtual returns (bytes calldata) {\\n return msg.data;\\n }\\n\\n function _contextSuffixLength() internal view virtual returns (uint256) {\\n return 0;\\n }\\n}\\n\",\"keccak256\":\"0xdbef5f0c787055227243a7318ef74c8a5a1108ca3a07f2b3a00ef67769e1e397\",\"license\":\"MIT\"},\"contracts/interfaces/ICyphernodeRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: LGPL-3.0-only\\npragma solidity >=0.8.26;\\n\\ninterface ICyphernodeRegistry {\\n /// @notice This event MUST be emitted when a committee is selected for an E3.\\n /// @param e3Id ID of the E3 for which the committee was selected.\\n /// @param filter Address of the contract that will coordinate committee selection.\\n /// @param threshold The M/N threshold for the committee.\\n event CommitteeRequested(\\n uint256 indexed e3Id,\\n address filter,\\n uint32[2] threshold\\n );\\n\\n /// @notice This event MUST be emitted when a committee is selected for an E3.\\n /// @param e3Id ID of the E3 for which the committee was selected.\\n /// @param publicKey Public key of the committee.\\n event CommitteePublished(uint256 indexed e3Id, bytes publicKey);\\n\\n /// @notice This event MUST be emitted when `enclave` is set.\\n /// @param enclave Address of the enclave contract.\\n event EnclaveSet(address indexed enclave);\\n\\n /// @notice This event MUST be emitted when a cyphernode is added to the registry.\\n event CyphernodeAdded(address indexed node);\\n\\n /// @notice This event MUST be emitted when a cyphernode is removed from the registry.\\n event CyphernodeRemoved(address indexed node);\\n\\n function isCyphernodeEligible(address cyphernode) external returns (bool);\\n\\n /// @notice Initiates the committee selection process for a specified E3.\\n /// @dev This function MUST revert when not called by the Enclave contract.\\n /// @param e3Id ID of the E3 for which to select the committee.\\n /// @param filter The address of the filter responsible for the committee selection process.\\n /// @param threshold The M/N threshold for the committee.\\n /// @return success True if committee selection was successfully initiated.\\n function requestCommittee(\\n uint256 e3Id,\\n address filter,\\n uint32[2] calldata threshold\\n ) external returns (bool success);\\n\\n /// @notice Publishes the public key resulting from the committee selection process.\\n /// @dev This function MUST revert if not called by the previously selected filter.\\n /// @param e3Id ID of the E3 for which to select the committee.\\n /// @param publicKey The public key generated by the selected committee.\\n function publishCommittee(\\n uint256 e3Id,\\n bytes calldata proof,\\n bytes calldata publicKey\\n ) external;\\n\\n /// @notice This function should be called by the Enclave contract to get the public key of a committee.\\n /// @dev This function MUST revert if no committee has been requested for the given E3.\\n /// @dev This function MUST revert if the committee has not yet published a public key.\\n /// @param e3Id ID of the E3 for which to get the committee public key.\\n /// @return publicKey The public key of the committee.\\n function committeePublicKey(\\n uint256 e3Id\\n ) external view returns (bytes memory);\\n}\\n\",\"keccak256\":\"0x60af5d66db32528f5032fe083218f180ab83f3199bcf090bed7249c28bc18104\",\"license\":\"LGPL-3.0-only\"},\"contracts/interfaces/IRegistryFilter.sol\":{\"content\":\"// SPDX-License-Identifier: LGPL-3.0-only\\npragma solidity >=0.8.26;\\n\\ninterface IRegistryFilter {\\n function requestCommittee(\\n uint256 e3Id,\\n uint32[2] calldata threshold\\n ) external returns (bool success);\\n}\\n\",\"keccak256\":\"0xec67f88f2cbf46e28d4835669ef3dd2320afe5b0324423944037c16fc3f42195\",\"license\":\"LGPL-3.0-only\"},\"contracts/registry/NaiveRegistryFilter.sol\":{\"content\":\"// SPDX-License-Identifier: LGPL-3.0-only\\npragma solidity >=0.8.26;\\n\\nimport { ICyphernodeRegistry } from \\\"../interfaces/ICyphernodeRegistry.sol\\\";\\nimport { IRegistryFilter } from \\\"../interfaces/IRegistryFilter.sol\\\";\\nimport {\\n OwnableUpgradeable\\n} from \\\"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\\\";\\n\\ncontract NaiveRegistryFilter is IRegistryFilter, OwnableUpgradeable {\\n struct Committee {\\n address[] nodes;\\n uint32[2] threshold;\\n bytes publicKey;\\n }\\n\\n ////////////////////////////////////////////////////////////\\n // //\\n // Storage Variables //\\n // //\\n ////////////////////////////////////////////////////////////\\n\\n address public registry;\\n\\n mapping(uint256 e3 => Committee committee) public committees;\\n\\n ////////////////////////////////////////////////////////////\\n // //\\n // Errors //\\n // //\\n ////////////////////////////////////////////////////////////\\n\\n error CommitteeAlreadyExists();\\n error CommitteeAlreadyPublished();\\n error CommitteeDoesNotExist();\\n error CommitteeNotPublished();\\n error OnlyRegistry();\\n\\n ////////////////////////////////////////////////////////////\\n // //\\n // Modifiers //\\n // //\\n ////////////////////////////////////////////////////////////\\n\\n modifier onlyRegistry() {\\n require(msg.sender == registry, OnlyRegistry());\\n _;\\n }\\n\\n ////////////////////////////////////////////////////////////\\n // //\\n // Initialization //\\n // //\\n ////////////////////////////////////////////////////////////\\n\\n constructor(address _owner, address _enclave) {\\n initialize(_owner, _enclave);\\n }\\n\\n function initialize(address _owner, address _registry) public initializer {\\n __Ownable_init(msg.sender);\\n setRegistry(_registry);\\n transferOwnership(_owner);\\n }\\n\\n ////////////////////////////////////////////////////////////\\n // //\\n // Core Entrypoints //\\n // //\\n ////////////////////////////////////////////////////////////\\n\\n function requestCommittee(\\n uint256 e3Id,\\n uint32[2] calldata threshold\\n ) external onlyRegistry returns (bool success) {\\n Committee storage committee = committees[e3Id];\\n require(committee.threshold.length == 0, CommitteeAlreadyExists());\\n committee.threshold = threshold;\\n success = true;\\n }\\n\\n function publishCommittee(\\n uint256 e3Id,\\n address[] memory nodes,\\n bytes memory publicKey\\n ) external onlyOwner {\\n Committee storage committee = committees[e3Id];\\n require(\\n keccak256(committee.publicKey) == keccak256(hex\\\"\\\"),\\n CommitteeAlreadyPublished()\\n );\\n committee.nodes = nodes;\\n committee.publicKey = publicKey;\\n ICyphernodeRegistry(registry).publishCommittee(\\n e3Id,\\n abi.encode(nodes),\\n publicKey\\n );\\n }\\n\\n ////////////////////////////////////////////////////////////\\n // //\\n // Set Functions //\\n // //\\n ////////////////////////////////////////////////////////////\\n\\n function setRegistry(address _registry) public onlyOwner {\\n registry = _registry;\\n }\\n}\\n\",\"keccak256\":\"0x1f961c7313a6d24f0c1bfc4455a461eb25d329f85fea57e08a6fc159f9960a5a\",\"license\":\"LGPL-3.0-only\"}},\"version\":1}", + "bytecode": "0x6080346101d657601f610e7c38819003918201601f19168301916001600160401b038311848410176101db5780849260409485528339810103126101d657610052602061004b836101f1565b92016101f1565b600080516020610e5c83398151915254604081901c60ff16159290916001600160401b038316801590816101ce575b60011490816101c4575b1590816101bb575b506101aa576001600160401b03198316600117600080516020610e5c8339815191525561010f928461017f575b506100c961028d565b6100d161028d565b6100da33610205565b6100e26102bb565b600080546001600160a01b0319166001600160a01b039290921691909117905561010a6102bb565b610205565b610123575b604051610b5890816103048239f35b68ff000000000000000019600080516020610e5c8339815191525416600080516020610e5c833981519152557fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d2602060405160018152a1610114565b6001600160481b0319166801000000000000000117600080516020610e5c83398151915255386100c0565b63f92ee8a960e01b60005260046000fd5b90501538610093565b303b15915061008b565b859150610081565b600080fd5b634e487b7160e01b600052604160045260246000fd5b51906001600160a01b03821682036101d657565b6001600160a01b03168015610277577f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c19930080546001600160a01b0319811683179091556001600160a01b03167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a3565b631e4fbdf760e01b600052600060045260246000fd5b60ff600080516020610e5c8339815191525460401c16156102aa57565b631afcd79f60e31b60005260046000fd5b7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300546001600160a01b031633036102ee57565b63118cdaa760e01b6000523360045260246000fdfe608080604052600436101561001357600080fd5b600090813560e01c90816329f73b9c14610480575080632b20a4f614610435578063485cc9551461023d578063715018a6146101a45780637b1039991461017e5780638da5cb5b14610138578063a91ee0dc146100f9578063f2fde38b146100cc5763f5e820fd1461008457600080fd5b346100c95760203660031901126100c9576100b1600260406100c593600435815260016020522001610921565b6040519182916020835260208301906109c5565b0390f35b80fd5b50346100c95760203660031901126100c9576100f66100e96108cc565b6100f1610ac3565b610a1d565b80f35b50346100c95760203660031901126100c9576001600160a01b0361011b6108cc565b610123610ac3565b166001600160a01b0319600054161760005580f35b50346100c957806003193601126100c95760206001600160a01b037f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c1993005416604051908152f35b50346100c957806003193601126100c9576001600160a01b036020915416604051908152f35b50346100c957806003193601126100c9576101bd610ac3565b806001600160a01b037f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300546001600160a01b031981167f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c19930055167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a380f35b50346100c95760403660031901126100c9576102576108cc565b602435906001600160a01b0382168203610431577ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00549160ff8360401c16159267ffffffffffffffff811680159081610429575b600114908161041f575b159081610416575b506104075767ffffffffffffffff1981166001177ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a005561034392916001600160a01b0391856103c8575b50610310610b0b565b610318610b0b565b61032133610a1d565b610329610ac3565b166001600160a01b031960005416176000556100f1610ac3565b61034a5780f35b68ff0000000000000000197ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a0054167ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00557fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d2602060405160018152a180f35b68ffffffffffffffffff191668010000000000000001177ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a005538610307565b63f92ee8a960e01b8552600485fd5b905015386102bd565b303b1591506102b5565b8591506102ab565b8280fd5b50346100c95760603660031901126100c957366064116100c957806001600160a01b03600492541633036104745760016020526334c2a65d60e11b8152fd5b6310f5403960e31b8152fd5b82346100c95760603660031901126100c9576004356024359267ffffffffffffffff841161043157366023850112156104315783600401359367ffffffffffffffff8511610880578460051b946104da6020870184610894565b82526020820190602482968201019036821161084457602401915b81831061085c575050506044359167ffffffffffffffff831161070b573660238401121561070b57826004013567ffffffffffffffff81116108485760405193610549601f8301601f191660200186610894565b8185523660248383010111610844578186926024602093018388013785010152610571610ac3565b80845260016020526040842060028101907fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a4706105ac83610921565b60208151910120036108355783519067ffffffffffffffff821161082157680100000000000000008211610821578054828255808310610806575b508790875260208720875b8381106107e95750505050835167ffffffffffffffff81116107d55761061882546108e7565b601f811161079a575b50806020601f821160011461073957879161072e575b508160011b916000199060031b1c19161790555b6001600160a01b0384541660405192604084019060208086015251809152606084019690865b81811061070f5750505061069283869796959603601f198101855284610894565b803b1561070b578392836106cd936106df6040519889968795869463d9bbec9560e01b865260048601526060602486015260648501906109c5565b838103600319016044850152906109c5565b03925af180156106fe576106f05780f35b6106f991610894565b818180f35b50604051903d90823e3d90fd5b8380fd5b82516001600160a01b0316895260209889019890920191600101610671565b905085015188610637565b8388528088209150601f198316885b81811061078257509083600194939210610769575b5050811b01905561064b565b87015160001960f88460031b161c19169055888061075d565b9192602060018192868c015181550194019201610748565b6107c59083885260208820601f840160051c810191602085106107cb575b601f0160051c0190610a06565b87610621565b90915081906107b8565b634e487b7160e01b86526041600452602486fd5b60019060206001600160a01b0385511694019381840155016105f2565b8188526020882061081b918101908401610a06565b886105e7565b634e487b7160e01b87526041600452602487fd5b63632a22bb60e01b8652600486fd5b8580fd5b634e487b7160e01b85526041600452602485fd5b82356001600160a01b038116810361087c578152602092830192016104f5565b8680fd5b634e487b7160e01b84526041600452602484fd5b90601f8019910116810190811067ffffffffffffffff8211176108b657604052565b634e487b7160e01b600052604160045260246000fd5b600435906001600160a01b03821682036108e257565b600080fd5b90600182811c92168015610917575b602083101461090157565b634e487b7160e01b600052602260045260246000fd5b91607f16916108f6565b9060405191826000825492610935846108e7565b80845293600181169081156109a3575060011461095c575b5061095a92500383610894565b565b90506000929192526020600020906000915b81831061098757505090602061095a928201013861094d565b602091935080600191548385890101520191019091849261096e565b90506020925061095a94915060ff191682840152151560051b8201013861094d565b919082519283825260005b8481106109f1575050826000602080949584010152601f8019910116010190565b806020809284010151828286010152016109d0565b818110610a11575050565b60008155600101610a06565b6001600160a01b03168015610aad576001600160a01b037f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c19930054826001600160a01b03198216177f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c19930055167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a3565b631e4fbdf760e01b600052600060045260246000fd5b6001600160a01b037f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c19930054163303610af657565b63118cdaa760e01b6000523360045260246000fd5b60ff7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a005460401c1615610b3a57565b631afcd79f60e31b60005260046000fdfea164736f6c634300081a000af0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00", + "deployedBytecode": "0x608080604052600436101561001357600080fd5b600090813560e01c90816329f73b9c14610480575080632b20a4f614610435578063485cc9551461023d578063715018a6146101a45780637b1039991461017e5780638da5cb5b14610138578063a91ee0dc146100f9578063f2fde38b146100cc5763f5e820fd1461008457600080fd5b346100c95760203660031901126100c9576100b1600260406100c593600435815260016020522001610921565b6040519182916020835260208301906109c5565b0390f35b80fd5b50346100c95760203660031901126100c9576100f66100e96108cc565b6100f1610ac3565b610a1d565b80f35b50346100c95760203660031901126100c9576001600160a01b0361011b6108cc565b610123610ac3565b166001600160a01b0319600054161760005580f35b50346100c957806003193601126100c95760206001600160a01b037f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c1993005416604051908152f35b50346100c957806003193601126100c9576001600160a01b036020915416604051908152f35b50346100c957806003193601126100c9576101bd610ac3565b806001600160a01b037f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300546001600160a01b031981167f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c19930055167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a380f35b50346100c95760403660031901126100c9576102576108cc565b602435906001600160a01b0382168203610431577ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00549160ff8360401c16159267ffffffffffffffff811680159081610429575b600114908161041f575b159081610416575b506104075767ffffffffffffffff1981166001177ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a005561034392916001600160a01b0391856103c8575b50610310610b0b565b610318610b0b565b61032133610a1d565b610329610ac3565b166001600160a01b031960005416176000556100f1610ac3565b61034a5780f35b68ff0000000000000000197ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a0054167ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00557fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d2602060405160018152a180f35b68ffffffffffffffffff191668010000000000000001177ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a005538610307565b63f92ee8a960e01b8552600485fd5b905015386102bd565b303b1591506102b5565b8591506102ab565b8280fd5b50346100c95760603660031901126100c957366064116100c957806001600160a01b03600492541633036104745760016020526334c2a65d60e11b8152fd5b6310f5403960e31b8152fd5b82346100c95760603660031901126100c9576004356024359267ffffffffffffffff841161043157366023850112156104315783600401359367ffffffffffffffff8511610880578460051b946104da6020870184610894565b82526020820190602482968201019036821161084457602401915b81831061085c575050506044359167ffffffffffffffff831161070b573660238401121561070b57826004013567ffffffffffffffff81116108485760405193610549601f8301601f191660200186610894565b8185523660248383010111610844578186926024602093018388013785010152610571610ac3565b80845260016020526040842060028101907fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a4706105ac83610921565b60208151910120036108355783519067ffffffffffffffff821161082157680100000000000000008211610821578054828255808310610806575b508790875260208720875b8381106107e95750505050835167ffffffffffffffff81116107d55761061882546108e7565b601f811161079a575b50806020601f821160011461073957879161072e575b508160011b916000199060031b1c19161790555b6001600160a01b0384541660405192604084019060208086015251809152606084019690865b81811061070f5750505061069283869796959603601f198101855284610894565b803b1561070b578392836106cd936106df6040519889968795869463d9bbec9560e01b865260048601526060602486015260648501906109c5565b838103600319016044850152906109c5565b03925af180156106fe576106f05780f35b6106f991610894565b818180f35b50604051903d90823e3d90fd5b8380fd5b82516001600160a01b0316895260209889019890920191600101610671565b905085015188610637565b8388528088209150601f198316885b81811061078257509083600194939210610769575b5050811b01905561064b565b87015160001960f88460031b161c19169055888061075d565b9192602060018192868c015181550194019201610748565b6107c59083885260208820601f840160051c810191602085106107cb575b601f0160051c0190610a06565b87610621565b90915081906107b8565b634e487b7160e01b86526041600452602486fd5b60019060206001600160a01b0385511694019381840155016105f2565b8188526020882061081b918101908401610a06565b886105e7565b634e487b7160e01b87526041600452602487fd5b63632a22bb60e01b8652600486fd5b8580fd5b634e487b7160e01b85526041600452602485fd5b82356001600160a01b038116810361087c578152602092830192016104f5565b8680fd5b634e487b7160e01b84526041600452602484fd5b90601f8019910116810190811067ffffffffffffffff8211176108b657604052565b634e487b7160e01b600052604160045260246000fd5b600435906001600160a01b03821682036108e257565b600080fd5b90600182811c92168015610917575b602083101461090157565b634e487b7160e01b600052602260045260246000fd5b91607f16916108f6565b9060405191826000825492610935846108e7565b80845293600181169081156109a3575060011461095c575b5061095a92500383610894565b565b90506000929192526020600020906000915b81831061098757505090602061095a928201013861094d565b602091935080600191548385890101520191019091849261096e565b90506020925061095a94915060ff191682840152151560051b8201013861094d565b919082519283825260005b8481106109f1575050826000602080949584010152601f8019910116010190565b806020809284010151828286010152016109d0565b818110610a11575050565b60008155600101610a06565b6001600160a01b03168015610aad576001600160a01b037f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c19930054826001600160a01b03198216177f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c19930055167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a3565b631e4fbdf760e01b600052600060045260246000fd5b6001600160a01b037f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c19930054163303610af657565b63118cdaa760e01b6000523360045260246000fd5b60ff7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a005460401c1615610b3a57565b631afcd79f60e31b60005260046000fdfea164736f6c634300081a000a", + "devdoc": { + "errors": { + "InvalidInitialization()": [ + { + "details": "The contract is already initialized." + } + ], + "NotInitializing()": [ + { + "details": "The contract is not initializing." + } + ], + "OwnableInvalidOwner(address)": [ + { + "details": "The owner is not a valid owner account. (eg. `address(0)`)" + } + ], + "OwnableUnauthorizedAccount(address)": [ + { + "details": "The caller account is not authorized to perform an operation." + } + ] + }, + "events": { + "Initialized(uint64)": { + "details": "Triggered when the contract has been initialized or reinitialized." + } + }, + "kind": "dev", + "methods": { + "owner()": { + "details": "Returns the address of the current owner." + }, + "renounceOwnership()": { + "details": "Leaves the contract without owner. It will not be possible to call `onlyOwner` functions. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby disabling any functionality that is only available to the owner." + }, + "transferOwnership(address)": { + "details": "Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner." + } + }, + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": {}, + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 2140, + "contract": "contracts/registry/NaiveRegistryFilter.sol:NaiveRegistryFilter", + "label": "registry", + "offset": 0, + "slot": "0", + "type": "t_address" + }, + { + "astId": 2145, + "contract": "contracts/registry/NaiveRegistryFilter.sol:NaiveRegistryFilter", + "label": "committees", + "offset": 0, + "slot": "1", + "type": "t_mapping(t_uint256,t_struct(Committee)2138_storage)" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_address)dyn_storage": { + "base": "t_address", + "encoding": "dynamic_array", + "label": "address[]", + "numberOfBytes": "32" + }, + "t_array(t_uint32)2_storage": { + "base": "t_uint32", + "encoding": "inplace", + "label": "uint32[2]", + "numberOfBytes": "32" + }, + "t_bytes_storage": { + "encoding": "bytes", + "label": "bytes", + "numberOfBytes": "32" + }, + "t_mapping(t_uint256,t_struct(Committee)2138_storage)": { + "encoding": "mapping", + "key": "t_uint256", + "label": "mapping(uint256 => struct NaiveRegistryFilter.Committee)", + "numberOfBytes": "32", + "value": "t_struct(Committee)2138_storage" + }, + "t_struct(Committee)2138_storage": { + "encoding": "inplace", + "label": "struct NaiveRegistryFilter.Committee", + "members": [ + { + "astId": 2131, + "contract": "contracts/registry/NaiveRegistryFilter.sol:NaiveRegistryFilter", + "label": "nodes", + "offset": 0, + "slot": "0", + "type": "t_array(t_address)dyn_storage" + }, + { + "astId": 2135, + "contract": "contracts/registry/NaiveRegistryFilter.sol:NaiveRegistryFilter", + "label": "threshold", + "offset": 0, + "slot": "1", + "type": "t_array(t_uint32)2_storage" + }, + { + "astId": 2137, + "contract": "contracts/registry/NaiveRegistryFilter.sol:NaiveRegistryFilter", + "label": "publicKey", + "offset": 0, + "slot": "2", + "type": "t_bytes_storage" + } + ], + "numberOfBytes": "96" + }, + "t_uint256": { + "encoding": "inplace", + "label": "uint256", + "numberOfBytes": "32" + }, + "t_uint32": { + "encoding": "inplace", + "label": "uint32", + "numberOfBytes": "4" + } + } + } +} \ No newline at end of file diff --git a/packages/evm/deployments/sepolia/solcInputs/d0e6e4f19028714f394c36db62dff2be.json b/packages/evm/deployments/sepolia/solcInputs/d0e6e4f19028714f394c36db62dff2be.json new file mode 100644 index 00000000..5c8e6151 --- /dev/null +++ b/packages/evm/deployments/sepolia/solcInputs/d0e6e4f19028714f394c36db62dff2be.json @@ -0,0 +1,95 @@ +{ + "language": "Solidity", + "sources": { + "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol)\n\npragma solidity ^0.8.20;\n\nimport {ContextUpgradeable} from \"../utils/ContextUpgradeable.sol\";\nimport {Initializable} from \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * The initial owner is set to the address provided by the deployer. This can\n * later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract OwnableUpgradeable is Initializable, ContextUpgradeable {\n /// @custom:storage-location erc7201:openzeppelin.storage.Ownable\n struct OwnableStorage {\n address _owner;\n }\n\n // keccak256(abi.encode(uint256(keccak256(\"openzeppelin.storage.Ownable\")) - 1)) & ~bytes32(uint256(0xff))\n bytes32 private constant OwnableStorageLocation = 0x9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300;\n\n function _getOwnableStorage() private pure returns (OwnableStorage storage $) {\n assembly {\n $.slot := OwnableStorageLocation\n }\n }\n\n /**\n * @dev The caller account is not authorized to perform an operation.\n */\n error OwnableUnauthorizedAccount(address account);\n\n /**\n * @dev The owner is not a valid owner account. (eg. `address(0)`)\n */\n error OwnableInvalidOwner(address owner);\n\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Initializes the contract setting the address provided by the deployer as the initial owner.\n */\n function __Ownable_init(address initialOwner) internal onlyInitializing {\n __Ownable_init_unchained(initialOwner);\n }\n\n function __Ownable_init_unchained(address initialOwner) internal onlyInitializing {\n if (initialOwner == address(0)) {\n revert OwnableInvalidOwner(address(0));\n }\n _transferOwnership(initialOwner);\n }\n\n /**\n * @dev Throws if called by any account other than the owner.\n */\n modifier onlyOwner() {\n _checkOwner();\n _;\n }\n\n /**\n * @dev Returns the address of the current owner.\n */\n function owner() public view virtual returns (address) {\n OwnableStorage storage $ = _getOwnableStorage();\n return $._owner;\n }\n\n /**\n * @dev Throws if the sender is not the owner.\n */\n function _checkOwner() internal view virtual {\n if (owner() != _msgSender()) {\n revert OwnableUnauthorizedAccount(_msgSender());\n }\n }\n\n /**\n * @dev Leaves the contract without owner. It will not be possible to call\n * `onlyOwner` functions. Can only be called by the current owner.\n *\n * NOTE: Renouncing ownership will leave the contract without an owner,\n * thereby disabling any functionality that is only available to the owner.\n */\n function renounceOwnership() public virtual onlyOwner {\n _transferOwnership(address(0));\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Can only be called by the current owner.\n */\n function transferOwnership(address newOwner) public virtual onlyOwner {\n if (newOwner == address(0)) {\n revert OwnableInvalidOwner(address(0));\n }\n _transferOwnership(newOwner);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Internal function without access restriction.\n */\n function _transferOwnership(address newOwner) internal virtual {\n OwnableStorage storage $ = _getOwnableStorage();\n address oldOwner = $._owner;\n $._owner = newOwner;\n emit OwnershipTransferred(oldOwner, newOwner);\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (proxy/utils/Initializable.sol)\n\npragma solidity ^0.8.20;\n\n/**\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\n * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\n *\n * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be\n * reused. This mechanism prevents re-execution of each \"step\" but allows the creation of new initialization steps in\n * case an upgrade adds a module that needs to be initialized.\n *\n * For example:\n *\n * [.hljs-theme-light.nopadding]\n * ```solidity\n * contract MyToken is ERC20Upgradeable {\n * function initialize() initializer public {\n * __ERC20_init(\"MyToken\", \"MTK\");\n * }\n * }\n *\n * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {\n * function initializeV2() reinitializer(2) public {\n * __ERC20Permit_init(\"MyToken\");\n * }\n * }\n * ```\n *\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\n * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.\n *\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\n *\n * [CAUTION]\n * ====\n * Avoid leaving a contract uninitialized.\n *\n * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation\n * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke\n * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:\n *\n * [.hljs-theme-light.nopadding]\n * ```\n * /// @custom:oz-upgrades-unsafe-allow constructor\n * constructor() {\n * _disableInitializers();\n * }\n * ```\n * ====\n */\nabstract contract Initializable {\n /**\n * @dev Storage of the initializable contract.\n *\n * It's implemented on a custom ERC-7201 namespace to reduce the risk of storage collisions\n * when using with upgradeable contracts.\n *\n * @custom:storage-location erc7201:openzeppelin.storage.Initializable\n */\n struct InitializableStorage {\n /**\n * @dev Indicates that the contract has been initialized.\n */\n uint64 _initialized;\n /**\n * @dev Indicates that the contract is in the process of being initialized.\n */\n bool _initializing;\n }\n\n // keccak256(abi.encode(uint256(keccak256(\"openzeppelin.storage.Initializable\")) - 1)) & ~bytes32(uint256(0xff))\n bytes32 private constant INITIALIZABLE_STORAGE = 0xf0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00;\n\n /**\n * @dev The contract is already initialized.\n */\n error InvalidInitialization();\n\n /**\n * @dev The contract is not initializing.\n */\n error NotInitializing();\n\n /**\n * @dev Triggered when the contract has been initialized or reinitialized.\n */\n event Initialized(uint64 version);\n\n /**\n * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,\n * `onlyInitializing` functions can be used to initialize parent contracts.\n *\n * Similar to `reinitializer(1)`, except that in the context of a constructor an `initializer` may be invoked any\n * number of times. This behavior in the constructor can be useful during testing and is not expected to be used in\n * production.\n *\n * Emits an {Initialized} event.\n */\n modifier initializer() {\n // solhint-disable-next-line var-name-mixedcase\n InitializableStorage storage $ = _getInitializableStorage();\n\n // Cache values to avoid duplicated sloads\n bool isTopLevelCall = !$._initializing;\n uint64 initialized = $._initialized;\n\n // Allowed calls:\n // - initialSetup: the contract is not in the initializing state and no previous version was\n // initialized\n // - construction: the contract is initialized at version 1 (no reininitialization) and the\n // current contract is just being deployed\n bool initialSetup = initialized == 0 && isTopLevelCall;\n bool construction = initialized == 1 && address(this).code.length == 0;\n\n if (!initialSetup && !construction) {\n revert InvalidInitialization();\n }\n $._initialized = 1;\n if (isTopLevelCall) {\n $._initializing = true;\n }\n _;\n if (isTopLevelCall) {\n $._initializing = false;\n emit Initialized(1);\n }\n }\n\n /**\n * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the\n * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be\n * used to initialize parent contracts.\n *\n * A reinitializer may be used after the original initialization step. This is essential to configure modules that\n * are added through upgrades and that require initialization.\n *\n * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`\n * cannot be nested. If one is invoked in the context of another, execution will revert.\n *\n * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in\n * a contract, executing them in the right order is up to the developer or operator.\n *\n * WARNING: Setting the version to 2**64 - 1 will prevent any future reinitialization.\n *\n * Emits an {Initialized} event.\n */\n modifier reinitializer(uint64 version) {\n // solhint-disable-next-line var-name-mixedcase\n InitializableStorage storage $ = _getInitializableStorage();\n\n if ($._initializing || $._initialized >= version) {\n revert InvalidInitialization();\n }\n $._initialized = version;\n $._initializing = true;\n _;\n $._initializing = false;\n emit Initialized(version);\n }\n\n /**\n * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the\n * {initializer} and {reinitializer} modifiers, directly or indirectly.\n */\n modifier onlyInitializing() {\n _checkInitializing();\n _;\n }\n\n /**\n * @dev Reverts if the contract is not in an initializing state. See {onlyInitializing}.\n */\n function _checkInitializing() internal view virtual {\n if (!_isInitializing()) {\n revert NotInitializing();\n }\n }\n\n /**\n * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.\n * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized\n * to any version. It is recommended to use this to lock implementation contracts that are designed to be called\n * through proxies.\n *\n * Emits an {Initialized} event the first time it is successfully executed.\n */\n function _disableInitializers() internal virtual {\n // solhint-disable-next-line var-name-mixedcase\n InitializableStorage storage $ = _getInitializableStorage();\n\n if ($._initializing) {\n revert InvalidInitialization();\n }\n if ($._initialized != type(uint64).max) {\n $._initialized = type(uint64).max;\n emit Initialized(type(uint64).max);\n }\n }\n\n /**\n * @dev Returns the highest version that has been initialized. See {reinitializer}.\n */\n function _getInitializedVersion() internal view returns (uint64) {\n return _getInitializableStorage()._initialized;\n }\n\n /**\n * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.\n */\n function _isInitializing() internal view returns (bool) {\n return _getInitializableStorage()._initializing;\n }\n\n /**\n * @dev Returns a pointer to the storage namespace.\n */\n // solhint-disable-next-line var-name-mixedcase\n function _getInitializableStorage() private pure returns (InitializableStorage storage $) {\n assembly {\n $.slot := INITIALIZABLE_STORAGE\n }\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)\n\npragma solidity ^0.8.20;\nimport {Initializable} from \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract ContextUpgradeable is Initializable {\n function __Context_init() internal onlyInitializing {\n }\n\n function __Context_init_unchained() internal onlyInitializing {\n }\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n\n function _contextSuffixLength() internal view virtual returns (uint256) {\n return 0;\n }\n}\n" + }, + "contracts/Enclave.sol": { + "content": "// SPDX-License-Identifier: LGPL-3.0-only\npragma solidity >=0.8.26;\n\nimport {\n IEnclave,\n E3,\n IComputationModule,\n IExecutionModule\n} from \"./interfaces/IEnclave.sol\";\nimport { ICyphernodeRegistry } from \"./interfaces/ICyphernodeRegistry.sol\";\nimport { IInputValidator } from \"./interfaces/IInputValidator.sol\";\nimport { IOutputVerifier } from \"./interfaces/IOutputVerifier.sol\";\nimport {\n OwnableUpgradeable\n} from \"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\";\n\ncontract Enclave is IEnclave, OwnableUpgradeable {\n ////////////////////////////////////////////////////////////\n // //\n // Storage Variables //\n // //\n ////////////////////////////////////////////////////////////\n\n ICyphernodeRegistry public cyphernodeRegistry; // address of the Cyphernode registry.\n uint256 public maxDuration; // maximum duration of a computation in seconds.\n uint256 public nexte3Id; // ID of the next E3.\n uint256 public requests; // total number of requests made to Enclave.\n\n // TODO: should computation and execution modules be explicitly allowed?\n // My intuition is that an allowlist is required since they impose slashing conditions.\n // But perhaps this is one place where node pools might be utilized, allowing nodes to\n // opt in to being selected for specific computations, along with the corresponding slashing conditions.\n // This would reduce the governance overhead for Enclave.\n\n // Mapping of allowed computation modules.\n mapping(IComputationModule computationModule => bool allowed)\n public computationModules;\n\n // Mapping of allowed execution modules.\n mapping(IExecutionModule executionModule => bool allowed)\n public executionModules;\n\n // Mapping of E3s.\n mapping(uint256 id => E3 e3) public e3s;\n\n ////////////////////////////////////////////////////////////\n // //\n // Errors //\n // //\n ////////////////////////////////////////////////////////////\n\n error CommitteeSelectionFailed();\n error ComputationModuleNotAllowed(IComputationModule computationModule);\n error E3AlreadyActivated(uint256 e3Id);\n error E3Expired();\n error E3NotActivated(uint256 e3Id);\n error E3NotReady();\n error E3DoesNotExist(uint256 e3Id);\n error ModuleAlreadyEnabled(address module);\n error ModuleNotEnabled(address module);\n error InputDeadlinePassed(uint256 e3Id, uint256 expiration);\n error InputDeadlineNotPassed(uint256 e3Id, uint256 expiration);\n error InvalidComputation();\n error InvalidExecutionModuleSetup();\n error InvalidCyphernodeRegistry(ICyphernodeRegistry cyphernodeRegistry);\n error InvalidInput();\n error InvalidDuration(uint256 duration);\n error InvalidOutput(bytes output);\n error InvalidStartWindow();\n error InvalidThreshold(uint32[2] threshold);\n error CiphertextOutputAlreadyPublished(uint256 e3Id);\n error CiphertextOutputNotPublished(uint256 e3Id);\n error PaymentRequired(uint256 value);\n error PlaintextOutputAlreadyPublished(uint256 e3Id);\n\n ////////////////////////////////////////////////////////////\n // //\n // Initialization //\n // //\n ////////////////////////////////////////////////////////////\n\n /// @param _owner The owner of this contract\n /// @param _maxDuration The maximum duration of a computation in seconds\n constructor(\n address _owner,\n ICyphernodeRegistry _cyphernodeRegistry,\n uint256 _maxDuration\n ) {\n initialize(_owner, _cyphernodeRegistry, _maxDuration);\n }\n\n /// @param _owner The owner of this contract\n /// @param _maxDuration The maximum duration of a computation in seconds\n function initialize(\n address _owner,\n ICyphernodeRegistry _cyphernodeRegistry,\n uint256 _maxDuration\n ) public initializer {\n __Ownable_init(msg.sender);\n setMaxDuration(_maxDuration);\n setCyphernodeRegistry(_cyphernodeRegistry);\n if (_owner != owner()) transferOwnership(_owner);\n }\n\n ////////////////////////////////////////////////////////////\n // //\n // Core Entrypoints //\n // //\n ////////////////////////////////////////////////////////////\n\n function request(\n address filter,\n uint32[2] calldata threshold,\n uint256[2] calldata startWindow,\n uint256 duration,\n IComputationModule computationModule,\n bytes memory computationParams,\n IExecutionModule executionModule,\n bytes memory emParams\n ) external payable returns (uint256 e3Id, E3 memory e3) {\n // TODO: allow for other payment methods or only native tokens?\n // TODO: should payment checks be somewhere else? Perhaps in the computation module or cyphernode registry?\n require(msg.value > 0, PaymentRequired(msg.value));\n require(\n threshold[1] >= threshold[0] && threshold[0] > 0,\n InvalidThreshold(threshold)\n );\n require(\n // TODO: do we need a minimum start window to allow time for committee selection?\n startWindow[1] >= startWindow[0] &&\n startWindow[1] >= block.timestamp,\n InvalidStartWindow()\n );\n require(\n duration > 0 && duration <= maxDuration,\n InvalidDuration(duration)\n );\n require(\n computationModules[computationModule],\n ComputationModuleNotAllowed(computationModule)\n );\n require(\n executionModules[executionModule],\n ModuleNotEnabled(address(executionModule))\n );\n\n // TODO: should IDs be incremental or produced deterministically?\n e3Id = nexte3Id;\n nexte3Id++;\n\n IInputValidator inputValidator = computationModule.validate(\n computationParams\n );\n require(address(inputValidator) != address(0), InvalidComputation());\n\n // TODO: validate that the requested computation can be performed by the given execution module.\n IOutputVerifier outputVerifier = executionModule.validate(emParams);\n require(\n address(outputVerifier) != address(0),\n InvalidExecutionModuleSetup()\n );\n\n e3 = E3({\n threshold: threshold,\n startWindow: startWindow,\n duration: duration,\n expiration: 0,\n computationModule: computationModule,\n executionModule: executionModule,\n inputValidator: inputValidator,\n outputVerifier: outputVerifier,\n committeePublicKey: hex\"\",\n inputs: new bytes[](0),\n ciphertextOutput: hex\"\",\n plaintextOutput: hex\"\"\n });\n e3s[e3Id] = e3;\n\n require(\n cyphernodeRegistry.requestCommittee(e3Id, filter, threshold),\n CommitteeSelectionFailed()\n );\n\n emit E3Requested(\n e3Id,\n e3s[e3Id],\n filter,\n computationModule,\n executionModule\n );\n }\n\n function activate(uint256 e3Id) external returns (bool success) {\n // Note: we could load this into a storage pointer, and do the sets there\n // Requires a mew internal _getter that returns storage\n E3 memory e3 = getE3(e3Id);\n require(e3.expiration == 0, E3AlreadyActivated(e3Id));\n require(e3.startWindow[0] <= block.timestamp, E3NotReady());\n // TODO: handle what happens to the payment if the start window has passed.\n require(e3.startWindow[1] >= block.timestamp, E3Expired());\n\n bytes memory publicKey = cyphernodeRegistry.committeePublicKey(e3Id);\n // Note: This check feels weird\n require(publicKey.length > 0, CommitteeSelectionFailed());\n\n e3s[e3Id].expiration = block.timestamp + e3.duration;\n e3s[e3Id].committeePublicKey = publicKey;\n\n emit E3Activated(e3Id, e3.expiration, e3.committeePublicKey);\n\n return true;\n }\n\n function publishInput(\n uint256 e3Id,\n bytes memory data\n ) external returns (bool success) {\n E3 memory e3 = getE3(e3Id);\n\n // Note: if we make 0 a no expiration, this has to be refactored\n require(e3.expiration > 0, E3NotActivated(e3Id));\n // TODO: should we have an input window, including both a start and end timestamp?\n require(\n e3.expiration > block.timestamp,\n InputDeadlinePassed(e3Id, e3.expiration)\n );\n bytes memory input;\n (input, success) = e3.inputValidator.validate(msg.sender, data);\n require(success, InvalidInput());\n // TODO: probably better to accumulate inputs, rather than just dumping them in storage.\n e3s[e3Id].inputs.push(input);\n emit InputPublished(e3Id, input);\n }\n\n function publishCiphertextOutput(\n uint256 e3Id,\n bytes memory data\n ) external returns (bool success) {\n E3 memory e3 = getE3(e3Id);\n // Note: if we make 0 a no expiration, this has to be refactored\n require(e3.expiration > 0, E3NotActivated(e3Id));\n require(\n e3.expiration <= block.timestamp,\n InputDeadlineNotPassed(e3Id, e3.expiration)\n );\n // TODO: should the output verifier be able to change its mind?\n //i.e. should we be able to call this multiple times?\n require(\n e3.ciphertextOutput.length == 0,\n CiphertextOutputAlreadyPublished(e3Id)\n );\n bytes memory output;\n (output, success) = e3.outputVerifier.verify(e3Id, data);\n require(success, InvalidOutput(output));\n e3s[e3Id].ciphertextOutput = output;\n\n emit CiphertextOutputPublished(e3Id, output);\n }\n\n function publishPlaintextOutput(\n uint256 e3Id,\n bytes memory data\n ) external returns (bool success) {\n E3 memory e3 = getE3(e3Id);\n // Note: if we make 0 a no expiration, this has to be refactored\n require(e3.expiration > 0, E3NotActivated(e3Id));\n require(\n e3.ciphertextOutput.length > 0,\n CiphertextOutputNotPublished(e3Id)\n );\n require(\n e3.plaintextOutput.length == 0,\n PlaintextOutputAlreadyPublished(e3Id)\n );\n bytes memory output;\n (output, success) = e3.computationModule.verify(e3Id, data);\n require(success, InvalidOutput(output));\n e3s[e3Id].plaintextOutput = output;\n\n emit PlaintextOutputPublished(e3Id, output);\n }\n\n ////////////////////////////////////////////////////////////\n // //\n // Set Functions //\n // //\n ////////////////////////////////////////////////////////////\n\n function setMaxDuration(\n uint256 _maxDuration\n ) public onlyOwner returns (bool success) {\n maxDuration = _maxDuration;\n success = true;\n emit MaxDurationSet(_maxDuration);\n }\n\n function setCyphernodeRegistry(\n ICyphernodeRegistry _cyphernodeRegistry\n ) public onlyOwner returns (bool success) {\n require(\n address(_cyphernodeRegistry) != address(0) &&\n _cyphernodeRegistry != cyphernodeRegistry,\n InvalidCyphernodeRegistry(_cyphernodeRegistry)\n );\n cyphernodeRegistry = _cyphernodeRegistry;\n success = true;\n emit CyphernodeRegistrySet(address(_cyphernodeRegistry));\n }\n\n function enableComputationModule(\n IComputationModule computationModule\n ) public onlyOwner returns (bool success) {\n require(\n !computationModules[computationModule],\n ModuleAlreadyEnabled(address(computationModule))\n );\n computationModules[computationModule] = true;\n success = true;\n emit ComputationModuleEnabled(computationModule);\n }\n\n function enableExecutionModule(\n IExecutionModule executionModule\n ) public onlyOwner returns (bool success) {\n require(\n !executionModules[executionModule],\n ModuleAlreadyEnabled(address(executionModule))\n );\n executionModules[executionModule] = true;\n success = true;\n emit ExecutionModuleEnabled(executionModule);\n }\n\n function disableComputationModule(\n IComputationModule computationModule\n ) public onlyOwner returns (bool success) {\n require(\n computationModules[computationModule],\n ModuleNotEnabled(address(computationModule))\n );\n delete computationModules[computationModule];\n success = true;\n emit ComputationModuleDisabled(computationModule);\n }\n\n function disableExecutionModule(\n IExecutionModule executionModule\n ) public onlyOwner returns (bool success) {\n require(\n executionModules[executionModule],\n ModuleNotEnabled(address(executionModule))\n );\n delete executionModules[executionModule];\n success = true;\n emit ExecutionModuleDisabled(executionModule);\n }\n\n ////////////////////////////////////////////////////////////\n // //\n // Get Functions //\n // //\n ////////////////////////////////////////////////////////////\n\n function getE3(uint256 e3Id) public view returns (E3 memory e3) {\n e3 = e3s[e3Id];\n require(\n e3.computationModule != IComputationModule(address(0)),\n E3DoesNotExist(e3Id)\n );\n }\n}\n" + }, + "contracts/interfaces/IComputationModule.sol": { + "content": "// SPDX-License-Identifier: LGPL-3.0-only\npragma solidity >=0.8.26;\n\nimport { IInputValidator } from \"./IInputValidator.sol\";\n\ninterface IComputationModule {\n /// @notice This function should be called by the Enclave contract to validate the computation parameters.\n /// @param params ABI encoded computation parameters.\n /// @return inputValidator The input validator to be used for the computation.\n function validate(\n bytes calldata params\n ) external returns (IInputValidator inputValidator);\n\n /// @notice This function should be called by the Enclave contract to verify the decrypted output of an E3.\n /// @param e3Id ID of the E3.\n /// @param outputData ABI encoded output data to be verified.\n /// @return output The output data to be published.\n /// @return success Whether the output data is valid.\n function verify(\n uint256 e3Id,\n bytes memory outputData\n ) external returns (bytes memory output, bool success);\n}\n" + }, + "contracts/interfaces/ICyphernodeRegistry.sol": { + "content": "// SPDX-License-Identifier: LGPL-3.0-only\npragma solidity >=0.8.26;\n\ninterface ICyphernodeRegistry {\n /// @notice This event MUST be emitted when a committee is selected for an E3.\n /// @param e3Id ID of the E3 for which the committee was selected.\n /// @param filter Address of the contract that will coordinate committee selection.\n /// @param threshold The M/N threshold for the committee.\n event CommitteeRequested(\n uint256 indexed e3Id,\n address filter,\n uint32[2] threshold\n );\n\n /// @notice This event MUST be emitted when a committee is selected for an E3.\n /// @param e3Id ID of the E3 for which the committee was selected.\n /// @param publicKey Public key of the committee.\n event CommitteePublished(uint256 indexed e3Id, bytes publicKey);\n\n /// @notice This event MUST be emitted when `enclave` is set.\n /// @param enclave Address of the enclave contract.\n event EnclaveSet(address indexed enclave);\n\n /// @notice This event MUST be emitted when a cyphernode is added to the registry.\n event CyphernodeAdded(address indexed node);\n\n /// @notice This event MUST be emitted when a cyphernode is removed from the registry.\n event CyphernodeRemoved(address indexed node);\n\n function isCyphernodeEligible(address cyphernode) external returns (bool);\n\n /// @notice Initiates the committee selection process for a specified E3.\n /// @dev This function MUST revert when not called by the Enclave contract.\n /// @param e3Id ID of the E3 for which to select the committee.\n /// @param filter The address of the filter responsible for the committee selection process.\n /// @param threshold The M/N threshold for the committee.\n /// @return success True if committee selection was successfully initiated.\n function requestCommittee(\n uint256 e3Id,\n address filter,\n uint32[2] calldata threshold\n ) external returns (bool success);\n\n /// @notice Publishes the public key resulting from the committee selection process.\n /// @dev This function MUST revert if not called by the previously selected filter.\n /// @param e3Id ID of the E3 for which to select the committee.\n /// @param publicKey The public key generated by the selected committee.\n function publishCommittee(\n uint256 e3Id,\n bytes calldata proof,\n bytes calldata publicKey\n ) external;\n\n /// @notice This function should be called by the Enclave contract to get the public key of a committee.\n /// @dev This function MUST revert if no committee has been requested for the given E3.\n /// @dev This function MUST revert if the committee has not yet published a public key.\n /// @param e3Id ID of the E3 for which to get the committee public key.\n /// @return publicKey The public key of the committee.\n function committeePublicKey(\n uint256 e3Id\n ) external view returns (bytes memory);\n}\n" + }, + "contracts/interfaces/IE3.sol": { + "content": "// SPDX-License-Identifier: LGPL-3.0-only\npragma solidity >=0.8.26;\n\nimport { IInputValidator } from \"./IInputValidator.sol\";\nimport { IExecutionModule } from \"./IExecutionModule.sol\";\nimport { IComputationModule } from \"./IComputationModule.sol\";\nimport { IOutputVerifier } from \"./IOutputVerifier.sol\";\n\n/// @title E3 struct\n/// @notice This struct represents an E3 computation.\n/// @param threshold M/N threshold for the committee.\n/// @param startWindow Start window for the computation: index zero is minimum, index 1 is the maxium.\n/// @param duration Duration of the E3.\n/// @param expiration Timestamp when committee duties expire.\n/// @param computationModule Address of the computation module contract.\n/// @param executionModule Address of the execution module contract.\n/// @param inputValidator Address of the input validator contract.\n/// @param outputVerifier Address of the output verifier contract.\n/// @param committeeId ID of the selected committee.\n/// @param ciphertextOutput Encrypted output data.\n/// @param plaintextOutput Decrypted output data.\nstruct E3 {\n uint32[2] threshold;\n uint256[2] startWindow;\n uint256 duration;\n uint256 expiration;\n IComputationModule computationModule;\n IExecutionModule executionModule;\n IInputValidator inputValidator;\n IOutputVerifier outputVerifier;\n bytes committeePublicKey;\n bytes[] inputs;\n bytes ciphertextOutput;\n bytes plaintextOutput;\n}\n" + }, + "contracts/interfaces/IEnclave.sol": { + "content": "// SPDX-License-Identifier: LGPL-3.0-only\npragma solidity >=0.8.26;\n\nimport { E3, IComputationModule, IExecutionModule } from \"./IE3.sol\";\n\ninterface IEnclave {\n ////////////////////////////////////////////////////////////\n // //\n // Events //\n // //\n ////////////////////////////////////////////////////////////\n\n /// @notice This event MUST be emitted when an Encrypted Execution Environment (E3) is successfully requested.\n /// @param e3Id ID of the E3.\n /// @param e3 Details of the E3.\n /// @param filter Address of the pool of nodes from which the Cypher Node committee was selected.\n /// @param computationModule Address of the Computation module selected.\n /// @param executionModule Address of the execution module selected.\n event E3Requested(\n uint256 e3Id,\n E3 e3,\n address filter,\n IComputationModule indexed computationModule,\n IExecutionModule indexed executionModule\n );\n\n /// @notice This event MUST be emitted when an Encrypted Execution Environment (E3) is successfully activated.\n /// @param e3Id ID of the E3.\n /// @param expiration Timestamp when committee duties expire.\n /// @param committeePublicKey Public key of the committee.\n event E3Activated(\n uint256 e3Id,\n uint256 expiration,\n bytes committeePublicKey\n );\n\n /// @notice This event MUST be emitted when an input to an Encrypted Execution Environment (E3) is\n /// successfully published.\n /// @param e3Id ID of the E3.\n /// @param data ABI encoded input data.\n event InputPublished(uint256 indexed e3Id, bytes data);\n\n /// @notice This event MUST be emitted when the plaintext output of an Encrypted Execution Environment (E3)\n /// is successfully published.\n /// @param e3Id ID of the E3.\n /// @param plaintextOutput ABI encoded plaintext output.\n event PlaintextOutputPublished(uint256 indexed e3Id, bytes plaintextOutput);\n\n /// @notice This event MUST be emitted when the ciphertext output of an Encrypted Execution Environment (E3)\n /// is successfully published.\n /// @param e3Id ID of the E3.\n /// @param ciphertextOutput ABI encoded ciphertext output.\n event CiphertextOutputPublished(\n uint256 indexed e3Id,\n bytes ciphertextOutput\n );\n\n /// @notice This event MUST be emitted any time the `maxDuration` is set.\n /// @param maxDuration The maximum duration of a computation in seconds.\n event MaxDurationSet(uint256 maxDuration);\n\n /// @notice This event MUST be emitted any time the CyphernodeRegistry is set.\n /// @param cyphernodeRegistry The address of the CyphernodeRegistry contract.\n event CyphernodeRegistrySet(address cyphernodeRegistry);\n\n /// @notice This event MUST be emitted any time a computation module is enabled.\n /// @param computationModule The address of the computation module.\n event ComputationModuleEnabled(IComputationModule computationModule);\n\n /// @notice This event MUST be emitted any time a computation module is disabled.\n /// @param computationModule The address of the computation module.\n event ComputationModuleDisabled(IComputationModule computationModule);\n\n /// @notice This event MUST be emitted any time an execution module is enabled.\n /// @param executionModule The address of the execution module.\n event ExecutionModuleEnabled(IExecutionModule executionModule);\n\n /// @notice This event MUST be emitted any time an execution module is disabled.\n /// @param executionModule The address of the execution module.\n event ExecutionModuleDisabled(IExecutionModule executionModule);\n\n ////////////////////////////////////////////////////////////\n // //\n // Core Entrypoints //\n // //\n ////////////////////////////////////////////////////////////\n\n /// @notice This function should be called to request a computation within an Encrypted Execution Environment (E3).\n /// @dev This function MUST emit the E3Requested event.\n /// @param filter IDs of the pool of nodes from which to select the committee.\n /// @param threshold The M/N threshold for the committee.\n /// @param duration The duration of the computation in seconds.\n /// @param computationModule Address of the computation module.\n /// @param computationParams ABI encoded computation parameters.\n /// @param executionModule Address of the execution module.\n /// @param emParams ABI encoded execution module parameters.\n /// @return e3Id ID of the E3.\n /// @return e3 The E3 struct.\n function request(\n address filter,\n uint32[2] calldata threshold,\n uint256[2] calldata startWindow,\n uint256 duration,\n IComputationModule computationModule,\n bytes memory computationParams,\n IExecutionModule executionModule,\n bytes memory emParams\n ) external payable returns (uint256 e3Id, E3 memory e3);\n\n /// @notice This function should be called to activate an Encrypted Execution Environment (E3) once it has been\n /// initialized and is ready for input.\n /// @dev This function MUST emit the E3Activated event.\n /// @dev This function MUST revert if the given E3 has not yet been requested.\n /// @dev This function MUST revert if the selected node committee has not yet published a public key.\n /// @param e3Id ID of the E3.\n function activate(uint256 e3Id) external returns (bool success);\n\n /// @notice This function should be called to publish input data for Encrypted Execution Environment (E3).\n /// @dev This function MUST revert if the E3 is not yet activated.\n /// @dev This function MUST emit the InputPublished event.\n /// @param e3Id ID of the E3.\n /// @param data ABI encoded input data to publish.\n /// @return success True if the input was successfully published.\n function publishInput(\n uint256 e3Id,\n bytes calldata data\n ) external returns (bool success);\n\n /// @notice This function should be called to publish output data for an Encrypted Execution Environment (E3).\n /// @dev This function MUST emit the CiphertextOutputPublished event.\n /// @param e3Id ID of the E3.\n /// @param data ABI encoded output data to verify.\n /// @return success True if the output was successfully published.\n function publishCiphertextOutput(\n uint256 e3Id,\n bytes memory data\n ) external returns (bool success);\n\n /// @notice This function publishes the plaintext output of an Encrypted Execution Environment (E3).\n /// @dev This function MUST revert if the output has not been published.\n /// @dev This function MUST emit the PlaintextOutputPublished event.\n /// @param e3Id ID of the E3.\n /// @param data ABI encoded output data to decrypt.\n /// @return success True if the output was successfully decrypted.\n function publishPlaintextOutput(\n uint256 e3Id,\n bytes memory data\n ) external returns (bool success);\n\n ////////////////////////////////////////////////////////////\n // //\n // Set Functions //\n // //\n ////////////////////////////////////////////////////////////\n\n /// @notice This function should be called to set the maximum duration of requested computations.\n /// @param _maxDuration The maximum duration of a computation in seconds.\n /// @return success True if the max duration was successfully set.\n function setMaxDuration(\n uint256 _maxDuration\n ) external returns (bool success);\n\n ////////////////////////////////////////////////////////////\n // //\n // Get Functions //\n // //\n ////////////////////////////////////////////////////////////\n\n /// @notice This function should be called to retrieve the details of an Encrypted Execution Environment (E3).\n /// @dev This function MUST revert if the E3 does not exist.\n /// @param e3Id ID of the E3.\n /// @return e3 The struct representing the requested E3.\n function getE3(uint256 e3Id) external view returns (E3 memory e3);\n}\n" + }, + "contracts/interfaces/IExecutionModule.sol": { + "content": "// SPDX-License-Identifier: LGPL-3.0-only\npragma solidity >=0.8.26;\n\nimport { IOutputVerifier } from \"./IOutputVerifier.sol\";\n\ninterface IExecutionModule {\n /// @notice This function should be called by the Enclave contract to validate the execution module parameters.\n /// @param params ABI encoded execution module parameters.\n function validate(\n bytes calldata params\n ) external returns (IOutputVerifier outputVerifier);\n}\n" + }, + "contracts/interfaces/IInputValidator.sol": { + "content": "// SPDX-License-Identifier: LGPL-3.0-only\npragma solidity >=0.8.26;\n\ninterface IInputValidator {\n /// @notice This function should be called by the Enclave contract to validate the input parameters.\n /// @param params ABI encoded input parameters.\n /// @return input The input data to be published.\n /// @return success Whether the input parameters are valid.\n function validate(\n address sender,\n bytes memory params\n ) external returns (bytes memory input, bool success);\n}\n" + }, + "contracts/interfaces/IOutputVerifier.sol": { + "content": "// SPDX-License-Identifier: LGPL-3.0-only\npragma solidity >=0.8.26;\n\ninterface IOutputVerifier {\n /// @notice This function should be called by the Enclave contract to verify the output of a computation.\n /// @param e3Id ID of the E3.\n /// @param data ABI encoded output data to be verified.\n /// @return output Ciphertext output of the given computation.\n function verify(\n uint256 e3Id,\n bytes memory data\n ) external view returns (bytes memory output, bool success);\n}\n" + }, + "contracts/interfaces/IRegistryFilter.sol": { + "content": "// SPDX-License-Identifier: LGPL-3.0-only\npragma solidity >=0.8.26;\n\ninterface IRegistryFilter {\n function requestCommittee(\n uint256 e3Id,\n uint32[2] calldata threshold\n ) external returns (bool success);\n}\n" + }, + "contracts/registry/CyphernodeRegistryOwnable.sol": { + "content": "// SPDX-License-Identifier: LGPL-3.0-only\npragma solidity >=0.8.26;\n\nimport { ICyphernodeRegistry } from \"../interfaces/ICyphernodeRegistry.sol\";\nimport { IRegistryFilter } from \"../interfaces/IRegistryFilter.sol\";\nimport {\n OwnableUpgradeable\n} from \"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\";\n\ncontract CyphernodeRegistryOwnable is ICyphernodeRegistry, OwnableUpgradeable {\n ////////////////////////////////////////////////////////////\n // //\n // Storage Variables //\n // //\n ////////////////////////////////////////////////////////////\n\n address public enclave;\n\n mapping(address cyphernode => bool isEnabled) public isEnabled;\n\n mapping(uint256 e3Id => IRegistryFilter filter) public requests;\n mapping(uint256 e3Id => bytes publicKey) public publicKeys;\n\n ////////////////////////////////////////////////////////////\n // //\n // Errors //\n // //\n ////////////////////////////////////////////////////////////\n\n error CommitteeAlreadyRequested();\n error CommitteeAlreadyPublished();\n error CommitteeDoesNotExist();\n error CommitteeNotPublished();\n error CyphernodeNotEnabled(address node);\n error OnlyEnclave();\n\n ////////////////////////////////////////////////////////////\n // //\n // Modifiers //\n // //\n ////////////////////////////////////////////////////////////\n\n modifier onlyEnclave() {\n require(msg.sender == enclave, OnlyEnclave());\n _;\n }\n\n ////////////////////////////////////////////////////////////\n // //\n // Initialization //\n // //\n ////////////////////////////////////////////////////////////\n\n constructor(address _owner, address _enclave) {\n initialize(_owner, _enclave);\n }\n\n function initialize(address _owner, address _enclave) public initializer {\n __Ownable_init(msg.sender);\n setEnclave(_enclave);\n transferOwnership(_owner);\n }\n\n ////////////////////////////////////////////////////////////\n // //\n // Core Entrypoints //\n // //\n ////////////////////////////////////////////////////////////\n\n function requestCommittee(\n uint256 e3Id,\n address filter,\n uint32[2] calldata threshold\n ) external onlyEnclave returns (bool success) {\n require(\n requests[e3Id] == IRegistryFilter(address(0)),\n CommitteeAlreadyRequested()\n );\n requests[e3Id] = IRegistryFilter(filter);\n\n IRegistryFilter(filter).requestCommittee(e3Id, threshold);\n emit CommitteeRequested(e3Id, filter, threshold);\n success = true;\n }\n\n function publishCommittee(\n uint256 e3Id,\n bytes calldata,\n bytes calldata publicKey\n ) external {\n // only to be published by the filter\n require(address(requests[e3Id]) == msg.sender, CommitteeDoesNotExist());\n\n // for (uint256 i = 0; i < cyphernodes.length; i++) {\n // require(\n // isEnabled[cyphernodes[i]] == true,\n // CyphernodeNotEnabled(cyphernodes[i])\n // );\n // }\n\n publicKeys[e3Id] = publicKey;\n emit CommitteePublished(e3Id, publicKey);\n }\n\n ////////////////////////////////////////////////////////////\n // //\n // Set Functions //\n // //\n ////////////////////////////////////////////////////////////\n\n function setEnclave(address _enclave) public onlyOwner {\n enclave = _enclave;\n emit EnclaveSet(_enclave);\n }\n\n function addCyphernode(address node) external onlyOwner {\n isEnabled[node] = true;\n emit CyphernodeAdded(node);\n }\n\n function removeCyphernode(address node) external onlyOwner {\n isEnabled[node] = false;\n emit CyphernodeRemoved(node);\n }\n\n function isCyphernodeEligible(address node) external view returns (bool) {\n return isEnabled[node];\n }\n\n ////////////////////////////////////////////////////////////\n // //\n // Get Functions //\n // //\n ////////////////////////////////////////////////////////////\n\n function committeePublicKey(\n uint256 e3Id\n ) external view returns (bytes memory publicKey) {\n publicKey = publicKeys[e3Id];\n require(publicKey.length > 0, CommitteeNotPublished());\n }\n}\n" + }, + "contracts/registry/NaiveRegistryFilter.sol": { + "content": "// SPDX-License-Identifier: LGPL-3.0-only\npragma solidity >=0.8.26;\n\nimport { ICyphernodeRegistry } from \"../interfaces/ICyphernodeRegistry.sol\";\nimport { IRegistryFilter } from \"../interfaces/IRegistryFilter.sol\";\nimport {\n OwnableUpgradeable\n} from \"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\";\n\ncontract NaiveRegistryFilter is IRegistryFilter, OwnableUpgradeable {\n struct Committee {\n address[] nodes;\n uint32[2] threshold;\n bytes publicKey;\n }\n\n ////////////////////////////////////////////////////////////\n // //\n // Storage Variables //\n // //\n ////////////////////////////////////////////////////////////\n\n address public registry;\n\n mapping(uint256 e3 => Committee committee) public committees;\n\n ////////////////////////////////////////////////////////////\n // //\n // Errors //\n // //\n ////////////////////////////////////////////////////////////\n\n error CommitteeAlreadyExists();\n error CommitteeAlreadyPublished();\n error CommitteeDoesNotExist();\n error CommitteeNotPublished();\n error OnlyRegistry();\n\n ////////////////////////////////////////////////////////////\n // //\n // Modifiers //\n // //\n ////////////////////////////////////////////////////////////\n\n modifier onlyRegistry() {\n require(msg.sender == registry, OnlyRegistry());\n _;\n }\n\n ////////////////////////////////////////////////////////////\n // //\n // Initialization //\n // //\n ////////////////////////////////////////////////////////////\n\n constructor(address _owner, address _enclave) {\n initialize(_owner, _enclave);\n }\n\n function initialize(address _owner, address _registry) public initializer {\n __Ownable_init(msg.sender);\n setRegistry(_registry);\n transferOwnership(_owner);\n }\n\n ////////////////////////////////////////////////////////////\n // //\n // Core Entrypoints //\n // //\n ////////////////////////////////////////////////////////////\n\n function requestCommittee(\n uint256 e3Id,\n uint32[2] calldata threshold\n ) external onlyRegistry returns (bool success) {\n Committee storage committee = committees[e3Id];\n require(committee.threshold.length == 0, CommitteeAlreadyExists());\n committee.threshold = threshold;\n success = true;\n }\n\n function publishCommittee(\n uint256 e3Id,\n address[] memory nodes,\n bytes memory publicKey\n ) external onlyOwner {\n Committee storage committee = committees[e3Id];\n require(\n keccak256(committee.publicKey) == keccak256(hex\"\"),\n CommitteeAlreadyPublished()\n );\n committee.nodes = nodes;\n committee.publicKey = publicKey;\n ICyphernodeRegistry(registry).publishCommittee(\n e3Id,\n abi.encode(nodes),\n publicKey\n );\n }\n\n ////////////////////////////////////////////////////////////\n // //\n // Set Functions //\n // //\n ////////////////////////////////////////////////////////////\n\n function setRegistry(address _registry) public onlyOwner {\n registry = _registry;\n }\n}\n" + }, + "contracts/test/MockComputationModule.sol": { + "content": "// SPDX-License-Identifier: LGPL-3.0-only\npragma solidity >=0.8.26;\n\nimport {\n IComputationModule,\n IInputValidator\n} from \"../interfaces/IComputationModule.sol\";\n\ncontract MockComputationModule is IComputationModule {\n error invalidParams(bytes params);\n\n function validate(\n bytes memory params\n ) external pure returns (IInputValidator inputValidator) {\n require(params.length == 32, \"invalid params\");\n // solhint-disable no-inline-assembly\n assembly {\n inputValidator := mload(add(params, 32))\n }\n }\n\n function verify(\n uint256,\n bytes memory data\n ) external pure returns (bytes memory output, bool success) {\n output = data;\n if (output.length > 0) success = true;\n }\n}\n" + }, + "contracts/test/MockCyphernodeRegistry.sol": { + "content": "// SPDX-License-Identifier: LGPL-3.0-only\npragma solidity >=0.8.26;\n\nimport { ICyphernodeRegistry } from \"../interfaces/ICyphernodeRegistry.sol\";\n\ncontract MockCyphernodeRegistry is ICyphernodeRegistry {\n function requestCommittee(\n uint256,\n address filter,\n uint32[2] calldata\n ) external pure returns (bool success) {\n if (filter == address(2)) {\n success = false;\n } else {\n success = true;\n }\n }\n\n function publishCommittee(\n uint256,\n bytes calldata,\n bytes calldata\n ) external {} // solhint-disable-line no-empty-blocks\n\n function committeePublicKey(\n uint256 e3Id\n ) external pure returns (bytes memory) {\n if (e3Id == type(uint256).max) {\n return hex\"\";\n } else {\n return abi.encodePacked(keccak256(abi.encode(e3Id)));\n }\n }\n\n function isCyphernodeEligible(address) external pure returns (bool) {\n return false;\n }\n}\n\ncontract MockCyphernodeRegistryEmptyKey is ICyphernodeRegistry {\n function requestCommittee(\n uint256,\n address filter,\n uint32[2] calldata\n ) external pure returns (bool success) {\n if (filter == address(2)) {\n success = false;\n } else {\n success = true;\n }\n }\n\n function publishCommittee(\n uint256,\n bytes calldata,\n bytes calldata\n ) external {} // solhint-disable-line no-empty-blocks\n\n function committeePublicKey(uint256) external pure returns (bytes memory) {\n return hex\"\";\n }\n\n function isCyphernodeEligible(address) external pure returns (bool) {\n return false;\n }\n}\n" + }, + "contracts/test/MockExecutionModule.sol": { + "content": "// SPDX-License-Identifier: LGPL-3.0-only\npragma solidity >=0.8.26;\n\nimport {\n IExecutionModule,\n IOutputVerifier\n} from \"../interfaces/IExecutionModule.sol\";\n\ncontract MockExecutionModule is IExecutionModule {\n error invalidParams();\n\n function validate(\n bytes memory params\n ) external pure returns (IOutputVerifier outputVerifier) {\n require(params.length == 32, invalidParams());\n // solhint-disable no-inline-assembly\n assembly {\n outputVerifier := mload(add(params, 32))\n }\n (outputVerifier) = abi.decode(params, (IOutputVerifier));\n }\n}\n" + }, + "contracts/test/MockInputValidator.sol": { + "content": "// SPDX-License-Identifier: LGPL-3.0-only\npragma solidity >=0.8.26;\n\nimport { IInputValidator } from \"../interfaces/IInputValidator.sol\";\n\ncontract MockInputValidator is IInputValidator {\n function validate(\n address,\n bytes memory params\n ) external pure returns (bytes memory input, bool success) {\n input = params;\n\n if (input.length == 3) {\n success = false;\n } else {\n success = true;\n }\n }\n}\n" + }, + "contracts/test/MockOutputVerifier.sol": { + "content": "// SPDX-License-Identifier: LGPL-3.0-only\npragma solidity >=0.8.26;\n\nimport { IOutputVerifier } from \"../interfaces/IOutputVerifier.sol\";\n\ncontract MockOutputVerifier is IOutputVerifier {\n function verify(\n uint256,\n bytes memory data\n ) external pure returns (bytes memory output, bool success) {\n output = data;\n\n if (output.length > 0) success = true;\n }\n}\n" + }, + "contracts/test/MockRegistryFilter.sol": { + "content": "// SPDX-License-Identifier: LGPL-3.0-only\npragma solidity >=0.8.26;\n\nimport { IRegistryFilter } from \"../interfaces/IRegistryFilter.sol\";\nimport {\n OwnableUpgradeable\n} from \"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\";\n\ninterface IRegistry {\n function publishCommittee(\n uint256 e3Id,\n address[] calldata cyphernodes,\n bytes calldata publicKey\n ) external;\n}\n\ncontract NaiveRegistryFilter is IRegistryFilter, OwnableUpgradeable {\n struct Committee {\n address[] nodes;\n uint32[2] threshold;\n bytes publicKey;\n }\n\n ////////////////////////////////////////////////////////////\n // //\n // Storage Variables //\n // //\n ////////////////////////////////////////////////////////////\n\n address public registry;\n\n mapping(uint256 e3 => Committee committee) public committees;\n\n ////////////////////////////////////////////////////////////\n // //\n // Errors //\n // //\n ////////////////////////////////////////////////////////////\n\n error CommitteeAlreadyExists();\n error CommitteeAlreadyPublished();\n error CommitteeDoesNotExist();\n error CommitteeNotPublished();\n error OnlyRegistry();\n\n ////////////////////////////////////////////////////////////\n // //\n // Modifiers //\n // //\n ////////////////////////////////////////////////////////////\n\n modifier onlyRegistry() {\n require(msg.sender == registry, OnlyRegistry());\n _;\n }\n\n ////////////////////////////////////////////////////////////\n // //\n // Initialization //\n // //\n ////////////////////////////////////////////////////////////\n\n constructor(address _owner, address _enclave) {\n initialize(_owner, _enclave);\n }\n\n function initialize(address _owner, address _registry) public initializer {\n __Ownable_init(msg.sender);\n setRegistry(_registry);\n transferOwnership(_owner);\n }\n\n ////////////////////////////////////////////////////////////\n // //\n // Core Entrypoints //\n // //\n ////////////////////////////////////////////////////////////\n\n function requestCommittee(\n uint256 e3Id,\n uint32[2] calldata threshold\n ) external onlyRegistry returns (bool success) {\n Committee storage committee = committees[e3Id];\n require(committee.threshold.length == 0, CommitteeAlreadyExists());\n committee.threshold = threshold;\n success = true;\n }\n\n function publishCommittee(\n uint256 e3Id,\n address[] memory nodes,\n bytes memory publicKey\n ) external onlyOwner {\n Committee storage committee = committees[e3Id];\n require(\n keccak256(committee.publicKey) == keccak256(hex\"\"),\n CommitteeAlreadyPublished()\n );\n committee.nodes = nodes;\n committee.publicKey = publicKey;\n IRegistry(registry).publishCommittee(e3Id, nodes, publicKey);\n }\n\n ////////////////////////////////////////////////////////////\n // //\n // Set Functions //\n // //\n ////////////////////////////////////////////////////////////\n\n function setRegistry(address _registry) public onlyOwner {\n registry = _registry;\n }\n}\n" + } + }, + "settings": { + "metadata": { + "bytecodeHash": "none", + "useLiteralContent": true + }, + "optimizer": { + "enabled": true, + "runs": 800 + }, + "viaIR": true, + "evmVersion": "paris", + "outputSelection": { + "*": { + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata", + "devdoc", + "userdoc", + "storageLayout", + "evm.gasEstimates" + ], + "": [ + "ast" + ] + } + } + } +} \ No newline at end of file From ccce0317f46ee11b3d3c53df57a338a0ad843d3e Mon Sep 17 00:00:00 2001 From: samepant Date: Fri, 13 Sep 2024 13:46:47 -0400 Subject: [PATCH 30/32] update readme --- packages/evm/README.md | 12 ++++++++++++ packages/evm/package.json | 2 +- 2 files changed, 13 insertions(+), 1 deletion(-) create mode 100644 packages/evm/README.md diff --git a/packages/evm/README.md b/packages/evm/README.md new file mode 100644 index 00000000..86dbc875 --- /dev/null +++ b/packages/evm/README.md @@ -0,0 +1,12 @@ +# Enclave EVM + +## To deploy + +``` +yarn deploy --network [network] +``` + +This will add the deployment information to the `./deployments` directory. + +Be sure to configure your desired network in `hardhat.config.ts` before +deploying. diff --git a/packages/evm/package.json b/packages/evm/package.json index d899b070..d568a1ec 100644 --- a/packages/evm/package.json +++ b/packages/evm/package.json @@ -72,7 +72,7 @@ "clean": "rimraf ./artifacts ./cache ./coverage ./types ./coverage.json && yarn typechain", "compile": "cross-env TS_NODE_TRANSPILE_ONLY=true hardhat compile", "coverage": "hardhat coverage --solcoverjs ./.solcover.js --temp artifacts --testfiles \"test/**/*.ts\" && yarn typechain", - "deploy:contracts": "hardhat deploy", + "deploy": "hardhat deploy", "lint": "yarn lint:sol && yarn lint:ts && yarn prettier:check", "lint:sol": "solhint --max-warnings 0 \"contracts/**/*.sol\"", "lint:ts": "eslint --ignore-path ./.eslintignore --ext .js,.ts .", From 6df113f3e8dbc99ed80c297852710ec4b8ade4f0 Mon Sep 17 00:00:00 2001 From: samepant Date: Fri, 13 Sep 2024 13:48:59 -0400 Subject: [PATCH 31/32] ignore DS_STORE --- .gitignore | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 150e1e47..91fcc861 100644 --- a/.gitignore +++ b/.gitignore @@ -3,4 +3,6 @@ node_modules # ciphernode -target \ No newline at end of file +target + +*.DS_Store \ No newline at end of file From 2c5f314658601e033e4d5448df32237435a7ef85 Mon Sep 17 00:00:00 2001 From: samepant Date: Fri, 13 Sep 2024 15:44:27 -0400 Subject: [PATCH 32/32] update packages to fix yarn error --- packages/evm/yarn.lock | 37 ++++++------------------------------- 1 file changed, 6 insertions(+), 31 deletions(-) diff --git a/packages/evm/yarn.lock b/packages/evm/yarn.lock index 747974ac..f681baac 100644 --- a/packages/evm/yarn.lock +++ b/packages/evm/yarn.lock @@ -3004,7 +3004,7 @@ hardhat@^2.22.0: raw-body "^2.4.1" resolve "1.17.0" semver "^6.3.0" - solc "0.8.27" + solc "0.8.26" source-map-support "^0.5.13" stacktrace-parser "^0.1.10" tsort "0.0.1" @@ -4320,8 +4320,8 @@ slice-ansi@^4.0.0: solc@0.8.27: version "0.8.27" - resolved "https://registry.yarnpkg.com/solc/-/solc-0.8.27.tgz#afc78078953f6ab3e727c338a2fefcd80dd5b01a" - integrity sha512-yiPQNVf5rBFHwN6SIf3TUUvVAFKcQqmSUFeq+fb6pNRCo0ZCgpYOZDi3BVoezCPIAcKrVYd/qXlBLUP9wVrZ9g== + resolved "https://registry.yarnpkg.com/solc/-/solc-0.8.27.tgz#cb8e7246cceadad8df65ceccffe640e106106bb4" + integrity sha512-BNxMol2tUAbkH7HKlXBcBqrGi2aqgv+uMHz26mJyTtlVgWmBA4ktiw0qVKHfkjf2oaHbwtbtaSeE2dhn/gTAKw== dependencies: command-exists "^1.2.8" commander "^8.1.0" @@ -4442,16 +4442,7 @@ string-format@^2.0.0: resolved "https://registry.yarnpkg.com/string-format/-/string-format-2.0.0.tgz#f2df2e7097440d3b65de31b6d40d54c96eaffb9b" integrity sha512-bbEs3scLeYNXLecRRuk6uJxdXUSj6le/8rNPHChIJTn2V79aXVTR1EH2OH5zLKKoz0V02fOUKZZcw01pLUShZA== -"string-width-cjs@npm:string-width@^4.2.0": - version "4.2.3" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" - integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== - dependencies: - emoji-regex "^8.0.0" - is-fullwidth-code-point "^3.0.0" - strip-ansi "^6.0.1" - -string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.2, string-width@^4.2.3: +"string-width-cjs@npm:string-width@^4.2.0", string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.2, string-width@^4.2.3: version "4.2.3" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== @@ -4476,14 +4467,7 @@ string_decoder@^1.1.1: dependencies: safe-buffer "~5.2.0" -"strip-ansi-cjs@npm:strip-ansi@^6.0.1": - version "6.0.1" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" - integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== - dependencies: - ansi-regex "^5.0.1" - -strip-ansi@^6.0.0, strip-ansi@^6.0.1: +"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== @@ -4877,16 +4861,7 @@ workerpool@6.2.1: resolved "https://registry.yarnpkg.com/workerpool/-/workerpool-6.2.1.tgz#46fc150c17d826b86a008e5a4508656777e9c343" integrity sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw== -"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" - integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== - dependencies: - ansi-styles "^4.0.0" - string-width "^4.1.0" - strip-ansi "^6.0.0" - -wrap-ansi@^7.0.0: +"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==