Skip to content

Commit

Permalink
Merge pull request #13242 from smartcontractkit/KS-129/implement-modi…
Browse files Browse the repository at this point in the history
…fy-DON-capability-registry

KS-129:  Implement modify DON
  • Loading branch information
cds95 authored May 20, 2024
2 parents f2854c5 + bb8684a commit 9e3d804
Show file tree
Hide file tree
Showing 8 changed files with 377 additions and 224 deletions.
5 changes: 5 additions & 0 deletions .changeset/cool-readers-try.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"chainlink": patch
---

#internal add modify DON function to capability registry
5 changes: 5 additions & 0 deletions contracts/.changeset/quiet-guests-march.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@chainlink/contracts": patch
---

Add update DON function to capability registry
129 changes: 83 additions & 46 deletions contracts/src/v0.8/keystone/CapabilityRegistry.sol
Original file line number Diff line number Diff line change
Expand Up @@ -177,14 +177,11 @@ contract CapabilityRegistry is OwnerIsCreator, TypeAndVersionInterface {
/// @param signer The node's signer address
event NodeUpdated(bytes32 p2pId, uint256 nodeOperatorId, bytes32 signer);

/// @notice This event is emitted when a new DON is created
/// @param donId The ID of the newly created DON
/// @param isPublic True if the newly created DON is public
event DONAdded(uint256 donId, bool isPublic);

/// @notice This event is emitted when a DON is removed
/// @param donId The ID of the removed DON
event DONRemoved(uint32 donId);
/// @notice This event is emitted when a DON's config is set
/// @param donId The ID of the DON the config was set for
/// @param configCount The number of times the DON has been
/// configured
event ConfigSet(uint32 donId, uint32 configCount);

/// @notice This error is emitted when a DON does not exist
/// @param donId The ID of the nonexistent DON
Expand Down Expand Up @@ -550,44 +547,29 @@ contract CapabilityRegistry is OwnerIsCreator, TypeAndVersionInterface {
bool isPublic
) external onlyOwner {
uint32 id = s_donId;

s_dons[id].id = id;
s_dons[id].isPublic = isPublic;

uint32 configCount = 1;

DONCapabilityConfig storage donCapabilityConfig = s_dons[id].config[configCount];

for (uint256 i; i < nodes.length; ++i) {
bytes32 nodeP2PId = nodes[i];
if (donCapabilityConfig.nodes.contains(nodeP2PId)) revert DuplicateDONNode(id, nodeP2PId);

donCapabilityConfig.nodes.add(nodeP2PId);
}

for (uint256 i; i < capabilityConfigurations.length; ++i) {
CapabilityConfiguration calldata configuration = capabilityConfigurations[i];
bytes32 capabilityId = configuration.capabilityId;

if (!s_hashedCapabilityIds.contains(capabilityId)) revert CapabilityDoesNotExist(capabilityId);
if (s_deprecatedHashedCapabilityIds.contains(capabilityId)) revert CapabilityIsDeprecated(capabilityId);

if (donCapabilityConfig.capabilityConfigs[capabilityId].length > 0)
revert DuplicateDONCapability(id, capabilityId);

for (uint256 j; j < nodes.length; ++j) {
bytes32 nodeP2PId = nodes[j];
if (!s_nodes[nodeP2PId].supportedCapabilityIds[s_nodes[nodeP2PId].configCount].contains(capabilityId))
revert NodeDoesNotSupportCapability(nodeP2PId, capabilityId);
}

donCapabilityConfig.capabilityIds.push(capabilityId);
donCapabilityConfig.capabilityConfigs[capabilityId] = configuration.config;
}
_setDONConfig(id, 1, nodes, capabilityConfigurations, isPublic);
++s_donId;
}

s_dons[id].configCount = configCount;
/// @notice Updates a DON's configuration. This allows
/// the admin to reconfigure the list of capabilities supported
/// by the DON, the list of nodes that make up the DON as well
/// as whether or not the DON can accept external workflows
/// @param nodes The nodes making up the DON
/// @param capabilityConfigurations The list of configurations for the
/// capabilities supported by the DON
/// @param isPublic True if the DON is can accept external workflows
function updateDON(
uint32 donId,
bytes32[] calldata nodes,
CapabilityConfiguration[] calldata capabilityConfigurations,
bool isPublic
) external onlyOwner {
uint32 configCount = s_dons[donId].configCount;
if (configCount == 0) revert DONDoesNotExist(donId);
_setDONConfig(donId, ++configCount, nodes, capabilityConfigurations, isPublic);
++s_donId;
emit DONAdded(id, isPublic);
}

/// @notice Removes DONs from the Capability Registry
Expand All @@ -600,19 +582,20 @@ contract CapabilityRegistry is OwnerIsCreator, TypeAndVersionInterface {
// DON config count starts at index 1
if (don.configCount == 0) revert DONDoesNotExist(donId);
delete s_dons[donId];
emit DONRemoved(donId);
emit ConfigSet(donId, 0);
}
}

/// @notice Gets DON's data
/// @param donId The DON ID
/// @return uint32 The DON ID
/// @return uint32 The DON's config count
/// @return bool True if the DON is public
/// @return bytes32[] The list of node P2P IDs that are in the DON
/// @return CapabilityConfiguration[] The list of capability configurations supported by the DON
function getDON(
uint32 donId
) external view returns (uint32, bool, bytes32[] memory, CapabilityConfiguration[] memory) {
) external view returns (uint32, uint32, bool, bytes32[] memory, CapabilityConfiguration[] memory) {
uint32 configCount = s_dons[donId].configCount;

DONCapabilityConfig storage donCapabilityConfig = s_dons[donId].config[configCount];
Expand All @@ -627,7 +610,13 @@ contract CapabilityRegistry is OwnerIsCreator, TypeAndVersionInterface {
});
}

return (s_dons[donId].id, s_dons[donId].isPublic, donCapabilityConfig.nodes.values(), capabilityConfigurations);
return (
s_dons[donId].id,
configCount,
s_dons[donId].isPublic,
donCapabilityConfig.nodes.values(),
capabilityConfigurations
);
}

/// @notice Returns the DON specific configuration for a capability
Expand All @@ -638,4 +627,52 @@ contract CapabilityRegistry is OwnerIsCreator, TypeAndVersionInterface {
uint32 configCount = s_dons[donId].configCount;
return s_dons[donId].config[configCount].capabilityConfigs[capabilityId];
}

/// @notice Sets the configuration for a DON
/// @param donId The ID of the DON to set the configuration for
/// @param configCount The number of times the DON has been configured
/// @param nodes The nodes making up the DON
/// @param capabilityConfigurations The list of configurations for the
/// capabilities supported by the DON
/// @param isPublic True if the DON is can accept external workflows
function _setDONConfig(
uint32 donId,
uint32 configCount,
bytes32[] calldata nodes,
CapabilityConfiguration[] calldata capabilityConfigurations,
bool isPublic
) internal {
s_dons[donId].isPublic = isPublic;

DONCapabilityConfig storage donCapabilityConfig = s_dons[donId].config[configCount];
for (uint256 i; i < nodes.length; ++i) {
bytes32 nodeP2PId = nodes[i];
if (donCapabilityConfig.nodes.contains(nodeP2PId)) revert DuplicateDONNode(donId, nodeP2PId);

donCapabilityConfig.nodes.add(nodeP2PId);
}

for (uint256 i; i < capabilityConfigurations.length; ++i) {
CapabilityConfiguration calldata configuration = capabilityConfigurations[i];
bytes32 capabilityId = configuration.capabilityId;

if (!s_hashedCapabilityIds.contains(capabilityId)) revert CapabilityDoesNotExist(capabilityId);
if (s_deprecatedHashedCapabilityIds.contains(capabilityId)) revert CapabilityIsDeprecated(capabilityId);

if (donCapabilityConfig.capabilityConfigs[capabilityId].length > 0)
revert DuplicateDONCapability(donId, capabilityId);

for (uint256 j; j < nodes.length; ++j) {
bytes32 nodeP2PId = nodes[j];
if (!s_nodes[nodeP2PId].supportedCapabilityIds[s_nodes[nodeP2PId].configCount].contains(capabilityId))
revert NodeDoesNotSupportCapability(nodeP2PId, capabilityId);
}

donCapabilityConfig.capabilityIds.push(capabilityId);
donCapabilityConfig.capabilityConfigs[capabilityId] = configuration.config;
}

s_dons[donId].configCount = configCount;
emit ConfigSet(donId, configCount);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@ import {BaseTest} from "./BaseTest.t.sol";
import {CapabilityRegistry} from "../CapabilityRegistry.sol";

contract CapabilityRegistry_AddDONTest is BaseTest {
event DONAdded(uint256 donId, bool isPublic);
event ConfigSet(uint32 donId, uint32 configCount);

uint32 private constant DON_ID = 1;
uint32 private constant TEST_NODE_OPERATOR_ONE_ID = 0;
uint256 private constant TEST_NODE_OPERATOR_TWO_ID = 1;
bytes32 private constant INVALID_P2P_ID = bytes32("fake-p2p");
Expand Down Expand Up @@ -158,22 +159,24 @@ contract CapabilityRegistry_AddDONTest is BaseTest {
});

vm.expectEmit(true, true, true, true, address(s_capabilityRegistry));
emit DONAdded(1, true);
emit ConfigSet(DON_ID, 1);
s_capabilityRegistry.addDON(nodes, capabilityConfigs, true);

(
uint32 id,
uint32 configCount,
bool isPublic,
bytes32[] memory donNodes,
CapabilityRegistry.CapabilityConfiguration[] memory donCapabilityConfigs
) = s_capabilityRegistry.getDON(1);
assertEq(id, 1);
) = s_capabilityRegistry.getDON(DON_ID);
assertEq(id, DON_ID);
assertEq(configCount, 1);
assertEq(isPublic, true);
assertEq(donCapabilityConfigs.length, 1);
assertEq(donCapabilityConfigs.length, capabilityConfigs.length);
assertEq(donCapabilityConfigs[0].capabilityId, s_basicHashedCapabilityId);
assertEq(s_capabilityRegistry.getDONCapabilityConfig(1, s_basicHashedCapabilityId), CONFIG);
assertEq(s_capabilityRegistry.getDONCapabilityConfig(DON_ID, s_basicHashedCapabilityId), CONFIG);

assertEq(donNodes.length, 1);
assertEq(donNodes.length, nodes.length);
assertEq(donNodes[0], P2P_ID);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import {BaseTest} from "./BaseTest.t.sol";
import {CapabilityRegistry} from "../CapabilityRegistry.sol";

contract CapabilityRegistry_RemoveDONsTest is BaseTest {
event DONRemoved(uint32 donId);
event ConfigSet(uint32 donId, uint32 configCount);

uint32 private constant DON_ID = 1;
uint32 private constant TEST_NODE_OPERATOR_ONE_ID = 0;
Expand Down Expand Up @@ -81,16 +81,18 @@ contract CapabilityRegistry_RemoveDONsTest is BaseTest {
uint32[] memory donIDs = new uint32[](1);
donIDs[0] = DON_ID;
vm.expectEmit(true, true, true, true, address(s_capabilityRegistry));
emit DONRemoved(DON_ID);
emit ConfigSet(DON_ID, 0);
s_capabilityRegistry.removeDONs(donIDs);

(
uint32 id,
uint32 configCount,
bool isPublic,
bytes32[] memory donNodes,
CapabilityRegistry.CapabilityConfiguration[] memory donCapabilityConfigs
) = s_capabilityRegistry.getDON(DON_ID);
assertEq(id, 0);
assertEq(configCount, 0);
assertEq(isPublic, false);
assertEq(donCapabilityConfigs.length, 0);
assertEq(s_capabilityRegistry.getDONCapabilityConfig(DON_ID, s_basicHashedCapabilityId), bytes(""));
Expand Down
Loading

0 comments on commit 9e3d804

Please sign in to comment.