Skip to content

Commit

Permalink
Merge pull request nucypher#307 from vzotova/coordinator-layout
Browse files Browse the repository at this point in the history
Coordinator: moves rituals from array to mapping
  • Loading branch information
derekpierre authored Aug 19, 2024
2 parents 8983231 + e173166 commit 852f66d
Show file tree
Hide file tree
Showing 3 changed files with 185 additions and 41 deletions.
81 changes: 52 additions & 29 deletions contracts/contracts/coordination/Coordinator.sol
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ contract Coordinator is Initializable, AccessControlDefaultAdminRulesUpgradeable
ITACoChildApplication public immutable application;
uint96 private immutable minAuthorization; // TODO use child app for checking eligibility

Ritual[] public rituals;
Ritual[] internal ritualsStub; // former rituals, "internal" for testing only
uint32 public timeout;
uint16 public maxDkgSize;
bool private stub1; // former isInitiationPublic
Expand All @@ -106,10 +106,13 @@ contract Coordinator is Initializable, AccessControlDefaultAdminRulesUpgradeable
mapping(address => ParticipantKey[]) internal participantKeysHistory;
mapping(bytes32 => uint32) internal ritualPublicKeyRegistry;
mapping(IFeeModel => bool) public feeModelsRegistry;

mapping(uint256 index => Ritual ritual) internal _rituals;
uint256 public numberOfRituals;
// Note: Adjust the __preSentinelGap size if more contract variables are added

// Storage area for sentinel values
uint256[19] internal __preSentinelGap;
uint256[17] internal __preSentinelGap;
Participant internal __sentinelParticipant;
uint256[20] internal __postSentinelGap;

Expand All @@ -128,35 +131,58 @@ contract Coordinator is Initializable, AccessControlDefaultAdminRulesUpgradeable
__AccessControlDefaultAdminRules_init(0, _admin);
}

/// @dev use `upgradeAndCall` for upgrading together with re-initialization
function initializeNumberOfRituals() external reinitializer(2) {
if (numberOfRituals == 0) {
numberOfRituals = ritualsStub.length;
}
}

function rituals(uint32 ritualId) public view returns (Ritual memory) {
return storageRitual(ritualId);
}

// for backward compatibility
function storageRitual(uint32 ritualId) internal view returns (Ritual storage) {
if (ritualId < ritualsStub.length) {
return ritualsStub[ritualId];
}
require(ritualId < numberOfRituals, "Ritual id out of bounds");
return _rituals[ritualId];
}

function getInitiator(uint32 ritualId) external view returns (address) {
return rituals[ritualId].initiator;
return rituals(ritualId).initiator;
}

function getTimestamps(
uint32 ritualId
) external view returns (uint32 initTimestamp, uint32 endTimestamp) {
initTimestamp = rituals[ritualId].initTimestamp;
endTimestamp = rituals[ritualId].endTimestamp;
Ritual storage ritual = storageRitual(ritualId);
initTimestamp = ritual.initTimestamp;
endTimestamp = ritual.endTimestamp;
}

function getAccessController(uint32 ritualId) external view returns (IEncryptionAuthorizer) {
return rituals[ritualId].accessController;
Ritual storage ritual = storageRitual(ritualId);
return ritual.accessController;
}

function getFeeModel(uint32 ritualId) external view returns (IFeeModel) {
return rituals[ritualId].feeModel;
Ritual storage ritual = storageRitual(ritualId);
return ritual.feeModel;
}

function getRitualState(uint32 ritualId) external view returns (RitualState) {
return getRitualState(rituals[ritualId]);
return getRitualState(storageRitual(ritualId));
}

function isRitualActive(Ritual storage ritual) internal view returns (bool) {
return getRitualState(ritual) == RitualState.ACTIVE;
}

function isRitualActive(uint32 ritualId) external view returns (bool) {
Ritual storage ritual = rituals[ritualId];
Ritual storage ritual = storageRitual(ritualId);
return isRitualActive(ritual);
}

Expand Down Expand Up @@ -194,7 +220,7 @@ contract Coordinator is Initializable, AccessControlDefaultAdminRulesUpgradeable
}

function setProviderPublicKey(BLS12381.G2Point calldata publicKey) external {
uint32 lastRitualId = uint32(rituals.length);
uint32 lastRitualId = uint32(numberOfRituals);
address stakingProvider = application.operatorToStakingProvider(msg.sender);
require(stakingProvider != address(0), "Operator has no bond with staking provider");

Expand Down Expand Up @@ -247,20 +273,16 @@ contract Coordinator is Initializable, AccessControlDefaultAdminRulesUpgradeable
}

function transferRitualAuthority(uint32 ritualId, address newAuthority) external {
Ritual storage ritual = rituals[ritualId];
Ritual storage ritual = storageRitual(ritualId);
require(isRitualActive(ritual), "Ritual is not active");
address previousAuthority = ritual.authority;
require(msg.sender == previousAuthority, "Sender not ritual authority");
ritual.authority = newAuthority;
emit RitualAuthorityTransferred(ritualId, previousAuthority, newAuthority);
}

function numberOfRituals() external view returns (uint256) {
return rituals.length;
}

function getParticipants(uint32 ritualId) external view returns (Participant[] memory) {
Ritual storage ritual = rituals[ritualId];
Ritual storage ritual = storageRitual(ritualId);
return ritual.participant;
}

Expand All @@ -283,8 +305,9 @@ contract Coordinator is Initializable, AccessControlDefaultAdminRulesUpgradeable
require(2 <= length && length <= maxDkgSize, "Invalid number of nodes");
require(duration >= 24 hours, "Invalid ritual duration"); // TODO: Define minimum duration #106

uint32 id = uint32(rituals.length);
Ritual storage ritual = rituals.push();
uint32 id = uint32(numberOfRituals);
Ritual storage ritual = _rituals[id];
numberOfRituals += 1;
ritual.initiator = msg.sender;
ritual.authority = authority;
ritual.dkgSize = length;
Expand Down Expand Up @@ -326,7 +349,7 @@ contract Coordinator is Initializable, AccessControlDefaultAdminRulesUpgradeable
function postTranscript(uint32 ritualId, bytes calldata transcript) external {
uint256 initialGasLeft = gasleft();

Ritual storage ritual = rituals[ritualId];
Ritual storage ritual = storageRitual(ritualId);
require(
getRitualState(ritual) == RitualState.DKG_AWAITING_TRANSCRIPTS,
"Not waiting for transcripts"
Expand Down Expand Up @@ -354,7 +377,7 @@ contract Coordinator is Initializable, AccessControlDefaultAdminRulesUpgradeable
}

function getAuthority(uint32 ritualId) external view returns (address) {
return rituals[ritualId].authority;
return rituals(ritualId).authority;
}

function postAggregation(
Expand All @@ -365,7 +388,7 @@ contract Coordinator is Initializable, AccessControlDefaultAdminRulesUpgradeable
) external {
uint256 initialGasLeft = gasleft();

Ritual storage ritual = rituals[ritualId];
Ritual storage ritual = storageRitual(ritualId);
require(
getRitualState(ritual) == RitualState.DKG_AWAITING_AGGREGATIONS,
"Not waiting for aggregations"
Expand Down Expand Up @@ -433,7 +456,7 @@ contract Coordinator is Initializable, AccessControlDefaultAdminRulesUpgradeable
function getPublicKeyFromRitualId(
uint32 ritualId
) external view returns (BLS12381.G1Point memory) {
Ritual storage ritual = rituals[ritualId];
Ritual storage ritual = storageRitual(ritualId);
RitualState state = getRitualState(ritual);
require(
state == RitualState.ACTIVE || state == RitualState.EXPIRED,
Expand Down Expand Up @@ -484,7 +507,7 @@ contract Coordinator is Initializable, AccessControlDefaultAdminRulesUpgradeable
address provider,
bool transcript
) external view returns (Participant memory) {
Ritual storage ritual = rituals[ritualId];
Ritual storage ritual = storageRitual(ritualId);
Participant memory participant = getParticipant(ritual, provider);
if (!transcript) {
participant.transcript = "";
Expand All @@ -496,7 +519,7 @@ contract Coordinator is Initializable, AccessControlDefaultAdminRulesUpgradeable
uint32 ritualId,
address provider
) external view returns (Participant memory) {
Ritual storage ritual = rituals[ritualId];
Ritual storage ritual = storageRitual(ritualId);
Participant memory participant = getParticipant(ritual, provider);
return participant;
}
Expand All @@ -507,7 +530,7 @@ contract Coordinator is Initializable, AccessControlDefaultAdminRulesUpgradeable
uint256 maxParticipants,
bool includeTranscript
) external view returns (Participant[] memory) {
Ritual storage ritual = rituals[ritualId];
Ritual storage ritual = storageRitual(ritualId);
uint256 endIndex = ritual.participant.length;
require(startIndex >= 0, "Invalid start index");
require(startIndex < endIndex, "Wrong start index");
Expand All @@ -529,7 +552,7 @@ contract Coordinator is Initializable, AccessControlDefaultAdminRulesUpgradeable
}

function getProviders(uint32 ritualId) external view returns (address[] memory) {
Ritual storage ritual = rituals[ritualId];
Ritual storage ritual = storageRitual(ritualId);
address[] memory providers = new address[](ritual.participant.length);
for (uint256 i = 0; i < ritual.participant.length; i++) {
providers[i] = ritual.participant[i].provider;
Expand All @@ -538,7 +561,7 @@ contract Coordinator is Initializable, AccessControlDefaultAdminRulesUpgradeable
}

function isParticipant(uint32 ritualId, address provider) external view returns (bool) {
Ritual storage ritual = rituals[ritualId];
Ritual storage ritual = storageRitual(ritualId);
(bool found, ) = findParticipant(ritual, provider);
return found;
}
Expand All @@ -549,7 +572,7 @@ contract Coordinator is Initializable, AccessControlDefaultAdminRulesUpgradeable
bytes memory evidence,
bytes memory ciphertextHeader
) external view returns (bool) {
Ritual storage ritual = rituals[ritualId];
Ritual storage ritual = storageRitual(ritualId);
require(getRitualState(ritual) == RitualState.ACTIVE, "Ritual not active");
return ritual.accessController.isAuthorized(ritualId, evidence, ciphertextHeader);
}
Expand All @@ -572,7 +595,7 @@ contract Coordinator is Initializable, AccessControlDefaultAdminRulesUpgradeable
}

function extendRitual(uint32 ritualId, uint32 duration) external {
Ritual storage ritual = rituals[ritualId];
Ritual storage ritual = storageRitual(ritualId);
require(msg.sender == ritual.initiator, "Only initiator can extend ritual");
require(getRitualState(ritual) == RitualState.ACTIVE, "Only active ritual can be extended");
ritual.endTimestamp += duration;
Expand Down
35 changes: 35 additions & 0 deletions contracts/test/CoordinatorTestSet.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
pragma solidity ^0.8.0;

import "../threshold/ITACoChildApplication.sol";
import "../contracts/coordination/Coordinator.sol";

/**
* @notice Contract for testing Coordinator contract
Expand Down Expand Up @@ -33,3 +34,37 @@ contract ChildApplicationForCoordinatorMock is ITACoChildApplication {
// solhint-disable-next-line no-empty-blocks
function penalize(address _stakingProvider) external {}
}

contract ExtendedCoordinator is Coordinator {
constructor(ITACoChildApplication _application) Coordinator(_application) {}

function initiateOldRitual(
IFeeModel feeModel,
address[] calldata providers,
address authority,
uint32 duration,
IEncryptionAuthorizer accessController
) external returns (uint32) {
uint16 length = uint16(providers.length);

uint32 id = uint32(ritualsStub.length);
Ritual storage ritual = ritualsStub.push();
ritual.initiator = msg.sender;
ritual.authority = authority;
ritual.dkgSize = length;
ritual.threshold = getThresholdForRitualSize(length);
ritual.initTimestamp = uint32(block.timestamp);
ritual.endTimestamp = ritual.initTimestamp + duration;
ritual.accessController = accessController;
ritual.feeModel = feeModel;

address previous = address(0);
for (uint256 i = 0; i < length; i++) {
Participant storage newParticipant = ritual.participant.push();
address current = providers[i];
newParticipant.provider = current;
previous = current;
}
return id;
}
}
Loading

0 comments on commit 852f66d

Please sign in to comment.