Skip to content

Commit

Permalink
Still broken wip, first crack at committee design
Browse files Browse the repository at this point in the history
  • Loading branch information
cristovaoth committed Jun 6, 2024
1 parent 7ae874a commit 5703b25
Show file tree
Hide file tree
Showing 8 changed files with 241 additions and 98 deletions.
8 changes: 4 additions & 4 deletions packages/evm/contracts/Enclave.sol
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ contract Enclave is IEnclave, OwnableUpgradeable {
////////////////////////////////////////////////////////////

function request(
address[] memory pools, // TODO: should we allow for multiple pools?
address filter,
uint32[2] calldata threshold,
// TODO: do we also need a start block/time? Would it be possible to have computations where inputs are
//published before the request is made? This kind of assumes the cypher nodes have already been selected
Expand Down Expand Up @@ -169,15 +169,15 @@ contract Enclave is IEnclave, OwnableUpgradeable {
e3s[e3Id] = e3;

require(
cyphernodeRegistry.selectCommittee(e3Id, pools, threshold),
cyphernodeRegistry.requestCommittee(e3Id, filter, threshold),
CommitteeSelectionFailed()
);
// TODO: validate that the selected pool accepts both the computation and execution modules.

emit E3Requested(
e3Id,
e3s[e3Id],
pools,
filter,
computationModule,
executionModule
);
Expand All @@ -190,7 +190,7 @@ contract Enclave is IEnclave, OwnableUpgradeable {
require(e3.expiration == 0, E3AlreadyActivated(e3Id));

bytes memory committeePublicKey = cyphernodeRegistry
.getCommitteePublicKey(e3Id);
.committeePublicKey(e3Id);
// Note: This check feels weird
require(committeePublicKey.length > 0, CommitteeSelectionFailed());

Expand Down
32 changes: 32 additions & 0 deletions packages/evm/contracts/interfaces/ICommitteeCoordinator.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// SPDX-License-Identifier: LGPL-3.0-only
pragma solidity >=0.8.26;

interface ICommitteeCoordinator {
/// @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 threshold The M/N threshold for the committee.
event CommitteeRequested(uint256 indexed e3Id, uint32[2] threshold);

/// @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 publicKey Public key of the committee.
event CommitteeAssembled(uint256 indexed e3Id, bytes publicKey);

/// @notice This function should be called by the Enclave contract to select a node committee.
/// @param e3Id ID of the E3 for which to select the committee.
/// @param threshold The M/N threshold for the committee.
/// @return success True if committee selection was successfully initiated.
function requestCommittee(
uint256 e3Id,
uint32[2] calldata threshold
) external returns (bool success);

/// @notice This function should be called by the Enclave contract to get the public key of a committee.
/// @dev This function MUST revert if no committee has been requested for the given E3.
/// @dev This function MUST revert if the committee has not yet published a public key.
/// @param e3Id ID of the E3 for which to get the committee public key.
/// @return publicKey The public key of the committee.
function committeePublicKey(
uint256 e3Id
) external view returns (bytes memory);
}
38 changes: 15 additions & 23 deletions packages/evm/contracts/interfaces/ICyphernodeRegistry.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,48 +4,40 @@ pragma solidity >=0.8.26;
interface ICyphernodeRegistry {
/// @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 pools Addresses of the pools of nodes from which the committee was selected.
/// @param filter Address of the contract that will coordinate committee selection.
/// @param threshold The M/N threshold for the committee.
event CommitteeRequested(
uint256 indexed e3Id,
address[] pools,
address filter,
uint32[2] threshold
);

/// @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 nodes Addresses of the nodes in the committee.
/// @param merkleRoots Merkle roots of the nodes in the committee.
/// @param publicKey Public key of the committee.
event CommitteeSelected(
uint256 indexed e3Id,
address[] nodes,
bytes32[] merkleRoots,
bytes publicKey
);
event CommitteeSelected(uint256 indexed e3Id, bytes publicKey);

/// @notice This event MUST be emitted when a node is added to the registry.
/// @param nodeId ID of the node.
/// @param node Address of the node.
event NodeAdded(uint256 indexed nodeId, address indexed node);
/// @notice This event MUST be emitted when a filter is added to the registry.
event FilterAdded(address indexed filter);

/// @notice This event MUST be emitted when a node is removed from the registry.
/// @param nodeId ID of the node.
/// @param node Address of the node.
event NodeRemoved(uint256 indexed nodeId, address indexed node);
/// @notice This event MUST be emitted when a filter is removed from the registry.
event FilterRemoved(address indexed filter);

/// @notice This event MUST be emitted when `encalve` is set.
/// @param enclave Address of the enclave contract.
event EnclaveSet(address indexed enclave);

function addFilter(address filter) external;

function removeFilter(address filter) external;

/// @notice This function should be called by the Enclave contract to select a node committee.
/// @param e3Id ID of the E3 for which to select the committee.
/// @param pools IDs of the pool of nodes from which to select the committee.
/// @param threshold The M/N threshold for the committee.
/// @return success True if committee selection was successfully initiated.
function selectCommittee(
function requestCommittee(
uint256 e3Id,
address[] memory pools,
address filter,
uint32[2] calldata threshold
) external returns (bool success);

Expand All @@ -54,7 +46,7 @@ interface ICyphernodeRegistry {
/// @dev This function MUST revert if the committee has not yet published a public key.
/// @param e3Id ID of the E3 for which to get the committee public key.
/// @return publicKey The public key of the committee.
function getCommitteePublicKey(
function committeePublicKey(
uint256 e3Id
) external view returns (bytes memory publicKey);
) external view returns (bytes memory);
}
8 changes: 4 additions & 4 deletions packages/evm/contracts/interfaces/IEnclave.sol
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,13 @@ 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 pool 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 Cypher Node committee was selected.
/// @param computationModule Address of the Computation module selected.
/// @param executionModule Address of the execution module selected.
event E3Requested(
uint256 e3Id,
E3 e3,
address[] pool,
address filter,
IComputationModule indexed computationModule,
IExecutionModule indexed executionModule
);
Expand Down Expand Up @@ -87,7 +87,7 @@ interface IEnclave {

/// @notice This function should be called to request a computation within an Encrypted Execution Environment (E3).
/// @dev This function MUST emit the E3Requested event.
/// @param pools IDs of the pool of nodes from which to select the committee.
/// @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.
Expand All @@ -97,7 +97,7 @@ interface IEnclave {
/// @return e3Id ID of the E3.
/// @return e3 The E3 struct.
function request(
address[] memory pools,
address filter,
uint32[2] calldata threshold,
uint256 duration,
IComputationModule computationModule,
Expand Down
7 changes: 0 additions & 7 deletions packages/evm/contracts/interfaces/INodePool.sol

This file was deleted.

78 changes: 28 additions & 50 deletions packages/evm/contracts/registry/CyphernodeRegistryOwnable.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,26 +2,12 @@
pragma solidity >=0.8.26;

import { ICyphernodeRegistry } from "../interfaces/ICyphernodeRegistry.sol";
import { ICommitteeCoordinator } from "../interfaces/ICommitteeCoordinator.sol";
import {
OwnableUpgradeable
} from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";

contract CyphernodeRegistryOwnable is ICyphernodeRegistry, OwnableUpgradeable {
struct Committee {
address[] nodes;
uint32[2] threshold;
address[] pools;
bytes32[] merkleRoots;
bytes publicKey;
}

struct Node {
bool eligible;
// Number of duties the node has not yet completed.
// Incremented each time a duty is added, decremented each time a duty is completed.
uint256 outstandingDuties;
}

////////////////////////////////////////////////////////////
// //
// Storage Variables //
Expand All @@ -30,15 +16,17 @@ contract CyphernodeRegistryOwnable is ICyphernodeRegistry, OwnableUpgradeable {

address public enclave;

mapping(uint256 e3 => Committee committee) public committees;
mapping(address nodeId => Node node) public nodes;
mapping(address filter => bool enabled) public filters;

mapping(uint256 e3 => ICommitteeCoordinator coordinator) public requests;

////////////////////////////////////////////////////////////
// //
// Errors //
// //
////////////////////////////////////////////////////////////

error CommitteeAlreadyRequested();
error CommitteeAlreadyExists();
error CommitteeAlreadyPublished();
error CommitteeDoesNotExist();
Expand Down Expand Up @@ -78,36 +66,21 @@ contract CyphernodeRegistryOwnable is ICyphernodeRegistry, OwnableUpgradeable {
// //
////////////////////////////////////////////////////////////

function selectCommittee(
function requestCommittee(
uint256 e3Id,
address[] memory pools,
address filter,
uint32[2] calldata threshold
) external onlyEnclave returns (bool success) {
Committee storage committee = committees[e3Id];
require(committee.threshold.length == 0, CommitteeAlreadyExists());
committee.threshold = threshold;
committee.pools = pools;
success = true;

emit CommitteeRequested(e3Id, pools, threshold);
}

function publishCommittee(
uint256 e3Id,
address[] memory _nodes,
bytes32[] memory merkleRoots,
bytes memory publicKey
) external onlyOwner {
Committee storage committee = committees[e3Id];
require(
keccak256(committee.publicKey) == keccak256(hex""),
CommitteeAlreadyPublished()
requests[e3Id] == ICommitteeCoordinator(address(0)),
CommitteeAlreadyRequested()
);
committee.nodes = _nodes;
committee.merkleRoots = merkleRoots;
committee.publicKey = publicKey;
requests[e3Id] = ICommitteeCoordinator(filter);

emit CommitteeSelected(e3Id, _nodes, merkleRoots, publicKey);
ICommitteeCoordinator(filter).requestCommittee(e3Id, threshold);

emit CommitteeRequested(e3Id, filter, threshold);
success = true;
}

////////////////////////////////////////////////////////////
Expand All @@ -121,23 +94,28 @@ contract CyphernodeRegistryOwnable is ICyphernodeRegistry, OwnableUpgradeable {
emit EnclaveSet(_enclave);
}

function addFilter(address filter) external {
filters[filter] = true;
emit FilterAdded(filter);
}

function removeFilter(address filter) external onlyOwner {
filters[filter] = false;
emit FilterRemoved(filter);
}

////////////////////////////////////////////////////////////
// //
// Get Functions //
// //
////////////////////////////////////////////////////////////

function getCommitteePublicKey(
function committeePublicKey(
uint256 e3Id
) external view returns (bytes memory publicKey) {
publicKey = committees[e3Id].publicKey;
require(publicKey.length > 0, NoPublicKeyPublished());
}
require(requests[e3Id] != ICommitteeCoordinator(address(0)));

function getCommittee(
uint256 e3Id
) external view returns (Committee memory committee) {
committee = committees[e3Id];
require(committees[e3Id].threshold.length > 0, CommitteeDoesNotExist());
publicKey = requests[e3Id].committeePublicKey(e3Id);
require(publicKey.length > 0, NoPublicKeyPublished());
}
}
Loading

0 comments on commit 5703b25

Please sign in to comment.