Skip to content

Commit

Permalink
use single key to index
Browse files Browse the repository at this point in the history
  • Loading branch information
RensR committed Sep 23, 2024
1 parent d572c5c commit 488c5e6
Show file tree
Hide file tree
Showing 7 changed files with 140 additions and 224 deletions.
52 changes: 25 additions & 27 deletions contracts/gas-snapshots/ccip.gas-snapshot
Original file line number Diff line number Diff line change
Expand Up @@ -810,35 +810,33 @@ PingPong_plumbing:test_Pausing_Success() (gas: 17810)
PingPong_startPingPong:test_StartPingPong_With_OOO_Success() (gas: 162091)
PingPong_startPingPong:test_StartPingPong_With_Sequenced_Ordered_Success() (gas: 181509)
RMNHome_beforeCapabilityConfigSet:test_beforeCapabilityConfigSet_OnlyCapabilitiesRegistryCanCall_reverts() (gas: 9872)
RMNHome_beforeCapabilityConfigSet:test_beforeCapabilityConfigSet_OnlyCapabilitiesRegistryCanCall_reverts() (gas: 9901)
RMNHome_beforeCapabilityConfigSet:test_beforeCapabilityConfigSet_success() (gas: 275772)
RMNHome_beforeCapabilityConfigSet:test_beforeCapabilityConfigSet_success() (gas: 794676)
RMNHome_promoteSecondaryAndRevokePrimary:test_promoteSecondaryAndRevokePrimary_OnlyOwner_reverts() (gas: 11073)
RMNHome_promoteSecondaryAndRevokePrimary:test_promoteSecondaryAndRevokePrimary_OnlyOwner_reverts() (gas: 11119)
RMNHome_beforeCapabilityConfigSet:test_beforeCapabilityConfigSet_success() (gas: 275003)
RMNHome_promoteSecondaryAndRevokePrimary:test_promoteSecondaryAndRevokePrimary_OnlyOwner_reverts() (gas: 10907)
RMNHome_promoteSecondaryAndRevokePrimary:test_promoteSecondaryAndRevokePrimary_OnlyOwner_reverts() (gas: 10953)
RMNHome_promoteSecondaryAndRevokePrimary:test_promoteSecondaryAndRevokePrimary_success() (gas: 209)
RMNHome_promoteSecondaryAndRevokePrimary:test_promoteSecondaryAndRevokePrimary_success() (gas: 209)
RMNHome_revokeSecondary:test_revokeSecondary_ConfigDigestMismatch_reverts() (gas: 20060)
RMNHome_revokeSecondary:test_revokeSecondary_ConfigDigestMismatch_reverts() (gas: 20108)
RMNHome_revokeSecondary:test_revokeSecondary_OnlyOwner_reverts() (gas: 11085)
RMNHome_revokeSecondary:test_revokeSecondary_OnlyOwner_reverts() (gas: 11129)
RMNHome_revokeSecondary:test_revokeSecondary_success() (gas: 28514)
RMNHome_revokeSecondary:test_revokeSecondary_success() (gas: 30361)
RMNHome_setDynamicConfig:test_setDynamicConfig_DigestNotFound_reverts() (gas: 34065)
RMNHome_setDynamicConfig:test_setDynamicConfig_MinObserversTooHigh_reverts() (gas: 20901)
RMNHome_setDynamicConfig:test_setDynamicConfig_OnlyOwner_reverts() (gas: 11973)
RMNHome_setDynamicConfig:test_setDynamicConfig_OnlyOwner_reverts() (gas: 15786)
RMNHome_setDynamicConfig:test_setDynamicConfig_success() (gas: 135276)
RMNHome_setDynamicConfig:test_setDynamicConfig_success() (gas: 64750)
RMNHome_setSecondary:test_setSecondary_DuplicateOffchainPublicKey_reverts() (gas: 21062)
RMNHome_setSecondary:test_setSecondary_DuplicatePeerId_reverts() (gas: 20856)
RMNHome_setSecondary:test_setSecondary_DuplicateSourceChain_reverts() (gas: 24623)
RMNHome_setSecondary:test_setSecondary_MinObserversTooHigh_reverts() (gas: 25062)
RMNHome_setSecondary:test_setSecondary_OnlyOwner_reverts() (gas: 12873)
RMNHome_setSecondary:test_setSecondary_OnlyOwner_reverts() (gas: 18238)
RMNHome_setSecondary:test_setSecondary_OutOfBoundsNodesLength_reverts() (gas: 187001)
RMNHome_setSecondary:test_setSecondary_OutOfBoundsObserverNodeIndex_reverts() (gas: 24767)
RMNHome_setSecondary:test_setSecondary_success() (gas: 283462)
RMNHome_setSecondary:test_setSecondary_success() (gas: 821737)
RMNHome_revokeSecondary:test_revokeSecondary_ConfigDigestMismatch_reverts() (gas: 19344)
RMNHome_revokeSecondary:test_revokeSecondary_ConfigDigestMismatch_reverts() (gas: 19366)
RMNHome_revokeSecondary:test_revokeSecondary_OnlyOwner_reverts() (gas: 10912)
RMNHome_revokeSecondary:test_revokeSecondary_OnlyOwner_reverts() (gas: 10956)
RMNHome_revokeSecondary:test_revokeSecondary_success() (gas: 27066)
RMNHome_revokeSecondary:test_revokeSecondary_success() (gas: 28966)
RMNHome_setDynamicConfig:test_setDynamicConfig_DigestNotFound_reverts() (gas: 33266)
RMNHome_setDynamicConfig:test_setDynamicConfig_MinObserversTooHigh_reverts() (gas: 20422)
RMNHome_setDynamicConfig:test_setDynamicConfig_OnlyOwner_reverts() (gas: 11834)
RMNHome_setDynamicConfig:test_setDynamicConfig_OnlyOwner_reverts() (gas: 15457)
RMNHome_setDynamicConfig:test_setDynamicConfig_success() (gas: 133123)
RMNHome_setDynamicConfig:test_setDynamicConfig_success() (gas: 63135)
RMNHome_setSecondary:test_setSecondary_DuplicateOffchainPublicKey_reverts() (gas: 20894)
RMNHome_setSecondary:test_setSecondary_DuplicatePeerId_reverts() (gas: 20688)
RMNHome_setSecondary:test_setSecondary_DuplicateSourceChain_reverts() (gas: 24455)
RMNHome_setSecondary:test_setSecondary_MinObserversTooHigh_reverts() (gas: 24894)
RMNHome_setSecondary:test_setSecondary_OnlyOwner_reverts() (gas: 12661)
RMNHome_setSecondary:test_setSecondary_OnlyOwner_reverts() (gas: 18070)
RMNHome_setSecondary:test_setSecondary_OutOfBoundsNodesLength_reverts() (gas: 186826)
RMNHome_setSecondary:test_setSecondary_OutOfBoundsObserverNodeIndex_reverts() (gas: 24599)
RMNHome_setSecondary:test_setSecondary_success() (gas: 282478)
RMNHome_setSecondary:test_setSecondary_success() (gas: 820692)
RMNRemote_constructor:test_constructor_success() (gas: 8334)
RMNRemote_constructor:test_constructor_zeroChainSelector_reverts() (gas: 59165)
RMNRemote_curse:test_curse_AlreadyCursed_duplicateSubject_reverts() (gas: 154457)
Expand Down
12 changes: 5 additions & 7 deletions contracts/src/v0.8/ccip/capability/CCIPHome.sol
Original file line number Diff line number Diff line change
Expand Up @@ -106,11 +106,10 @@ contract CCIPHome is HomeBase {
/// @return versionedConfig The config and its version.
/// @return ok True if the config was found, false otherwise.
function getConfig(
uint32 donId,
uint8 pluginType,
bytes32 pluginKey,
bytes32 configDigest
) external view returns (VersionedConfig memory versionedConfig, bool ok) {
(StoredConfig memory storedConfig, bool configOK) = _getStoredConfig(donId, pluginType, configDigest);
(StoredConfig memory storedConfig, bool configOK) = _getStoredConfig(pluginKey, configDigest);
if (configOK) {
return (
VersionedConfig({
Expand All @@ -126,10 +125,9 @@ contract CCIPHome is HomeBase {
}

function getAllConfigs(
uint32 donId,
uint8 pluginType
bytes32 pluginKey
) external view returns (VersionedConfig memory primaryConfig, VersionedConfig memory secondaryConfig) {
(StoredConfig memory primaryStoredConfig, bool primaryOk) = _getPrimaryStoredConfig(donId, pluginType);
(StoredConfig memory primaryStoredConfig, bool primaryOk) = _getPrimaryStoredConfig(pluginKey);

if (primaryOk) {
primaryConfig = VersionedConfig({
Expand All @@ -139,7 +137,7 @@ contract CCIPHome is HomeBase {
});
}

(StoredConfig memory secondaryStoredConfig, bool secondaryOk) = _getSecondaryStoredConfig(donId, pluginType);
(StoredConfig memory secondaryStoredConfig, bool secondaryOk) = _getSecondaryStoredConfig(pluginKey);

if (secondaryOk) {
secondaryConfig = VersionedConfig({
Expand Down
84 changes: 37 additions & 47 deletions contracts/src/v0.8/ccip/capability/HomeBase.sol
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ abstract contract HomeBase is OwnerIsCreator, ITypeAndVersion, ICapabilityConfig

/// @notice This array holds the configs.
/// @dev Value i in this array is valid iff s_configs[i].configDigest != 0.
mapping(uint32 donId => mapping(uint8 pluginType => StoredConfig[MAX_CONCURRENT_CONFIGS])) private s_configs;
mapping(bytes32 pluginKey => StoredConfig[MAX_CONCURRENT_CONFIGS]) private s_configs;

/// @notice The total number of configs ever set, used for generating the version of the configs.
uint32 private s_configCount = 0;
Expand Down Expand Up @@ -108,60 +108,56 @@ abstract contract HomeBase is OwnerIsCreator, ITypeAndVersion, ICapabilityConfig
/// @return primaryConfigDigest The digest of the primary config.
/// @return secondaryConfigDigest The digest of the secondary config.
function getConfigDigests(
uint32 donId,
uint8 pluginType
bytes32 pluginKey
) external view returns (bytes32 primaryConfigDigest, bytes32 secondaryConfigDigest) {
return (
s_configs[donId][pluginType][s_primaryConfigIndex].configDigest,
s_configs[donId][pluginType][s_primaryConfigIndex ^ 1].configDigest
s_configs[pluginKey][s_primaryConfigIndex].configDigest,
s_configs[pluginKey][s_primaryConfigIndex ^ 1].configDigest
);
}

function getPrimaryDigest(uint32 donId, uint8 pluginType) public view returns (bytes32) {
return s_configs[donId][pluginType][s_primaryConfigIndex].configDigest;
function getPrimaryDigest(bytes32 pluginKey) public view returns (bytes32) {
return s_configs[pluginKey][s_primaryConfigIndex].configDigest;
}

function getSecondaryDigest(uint32 donId, uint8 pluginType) public view returns (bytes32) {
return s_configs[donId][pluginType][s_primaryConfigIndex ^ 1].configDigest;
function getSecondaryDigest(bytes32 pluginKey) public view returns (bytes32) {
return s_configs[pluginKey][s_primaryConfigIndex ^ 1].configDigest;
}

/// @notice Returns the stored config for a given digest. Will always return an empty config if the digest is the zero
/// digest. This is done to prevent exposing old config state that is invalid.
function _getStoredConfig(
uint32 donId,
uint8 pluginType,
bytes32 pluginKey,
bytes32 configDigest
) internal view returns (StoredConfig memory storedConfig, bool ok) {
for (uint256 i = 0; i < MAX_CONCURRENT_CONFIGS; ++i) {
// We never want to return true for a zero digest, even if the caller is asking for it, as this can expose old
// config state that is invalid.
if (s_configs[donId][pluginType][i].configDigest == configDigest && configDigest != ZERO_DIGEST) {
return (s_configs[donId][pluginType][i], true);
if (s_configs[pluginKey][i].configDigest == configDigest && configDigest != ZERO_DIGEST) {
return (s_configs[pluginKey][i], true);
}
}
return (storedConfig, false);
}

function _getPrimaryStoredConfig(
uint32 donId,
uint8 pluginType
bytes32 pluginKey
) internal view returns (StoredConfig memory primaryConfig, bool ok) {
if (s_configs[donId][pluginType][s_primaryConfigIndex].configDigest == ZERO_DIGEST) {
if (s_configs[pluginKey][s_primaryConfigIndex].configDigest == ZERO_DIGEST) {
return (StoredConfig(ZERO_DIGEST, 0, "", ""), false);
}

return (s_configs[donId][pluginType][s_primaryConfigIndex], true);
return (s_configs[pluginKey][s_primaryConfigIndex], true);
}

function _getSecondaryStoredConfig(
uint32 donId,
uint8 pluginType
bytes32 pluginKey
) internal view returns (StoredConfig memory secondaryConfig, bool ok) {
if (s_configs[donId][pluginType][s_primaryConfigIndex ^ 1].configDigest == ZERO_DIGEST) {
if (s_configs[pluginKey][s_primaryConfigIndex ^ 1].configDigest == ZERO_DIGEST) {
return (StoredConfig(ZERO_DIGEST, 0, "", ""), false);
}

return (s_configs[donId][pluginType][s_primaryConfigIndex ^ 1], true);
return (s_configs[pluginKey][s_primaryConfigIndex ^ 1], true);
}

// ================================================================
Expand All @@ -172,15 +168,14 @@ abstract contract HomeBase is OwnerIsCreator, ITypeAndVersion, ICapabilityConfig
/// @param digestToOverwrite The digest of the config to overwrite, or ZERO_DIGEST if no config is to be overwritten.
/// This is done to prevent accidental overwrites.
function setSecondary(
uint32 donId,
uint8 pluginType,
bytes32 pluginKey,
bytes calldata encodedStaticConfig,
bytes calldata encodedDynamicConfig,
bytes32 digestToOverwrite
) external OnlyOwnerOrSelfCall returns (bytes32 newConfigDigest) {
_validateStaticAndDynamicConfig(encodedStaticConfig, encodedDynamicConfig);

bytes32 existingDigest = getSecondaryDigest(donId, pluginType);
bytes32 existingDigest = getSecondaryDigest(pluginKey);

if (existingDigest != digestToOverwrite) {
revert ConfigDigestMismatch(existingDigest, digestToOverwrite);
Expand All @@ -192,7 +187,7 @@ abstract contract HomeBase is OwnerIsCreator, ITypeAndVersion, ICapabilityConfig
}

uint32 newVersion = ++s_configCount;
newConfigDigest = _calculateConfigDigest(donId, pluginType, encodedStaticConfig, newVersion);
newConfigDigest = _calculateConfigDigest(pluginKey, encodedStaticConfig, newVersion);

StoredConfig memory newConfig = StoredConfig({
configDigest: newConfigDigest,
Expand All @@ -201,7 +196,7 @@ abstract contract HomeBase is OwnerIsCreator, ITypeAndVersion, ICapabilityConfig
dynamicConfig: encodedDynamicConfig
});

s_configs[donId][pluginType][s_primaryConfigIndex ^ 1] = newConfig;
s_configs[pluginKey][s_primaryConfigIndex ^ 1] = newConfig;

emit ConfigSet(newConfig);

Expand All @@ -210,37 +205,36 @@ abstract contract HomeBase is OwnerIsCreator, ITypeAndVersion, ICapabilityConfig

/// @notice Revokes a specific config by digest.
/// @param configDigest The digest of the config to revoke. This is done to prevent accidental revokes.
function revokeSecondary(uint32 donId, uint8 pluginType, bytes32 configDigest) external OnlyOwnerOrSelfCall {
function revokeSecondary(bytes32 pluginKey, bytes32 configDigest) external OnlyOwnerOrSelfCall {
uint256 secondaryConfigIndex = s_primaryConfigIndex ^ 1;
if (s_configs[donId][pluginType][secondaryConfigIndex].configDigest != configDigest) {
revert ConfigDigestMismatch(s_configs[donId][pluginType][secondaryConfigIndex].configDigest, configDigest);
if (s_configs[pluginKey][secondaryConfigIndex].configDigest != configDigest) {
revert ConfigDigestMismatch(s_configs[pluginKey][secondaryConfigIndex].configDigest, configDigest);
}

emit ConfigRevoked(configDigest);
// Delete only the digest, as that's what's used to determine if a config is active. This means the actual
// config stays in storage which should significantly reduce the gas cost of overwriting that storage space in
// the future.
delete s_configs[donId][pluginType][secondaryConfigIndex].configDigest;
delete s_configs[pluginKey][secondaryConfigIndex].configDigest;
}

/// @notice Promotes the secondary config to the primary config and revokes the primary config.
function promoteSecondaryAndRevokePrimary(
uint32 donId,
uint8 pluginType,
bytes32 pluginKey,
bytes32 digestToPromote,
bytes32 digestToRevoke
) external OnlyOwnerOrSelfCall {
uint256 secondaryConfigIndex = s_primaryConfigIndex ^ 1;
if (s_configs[donId][pluginType][secondaryConfigIndex].configDigest != digestToPromote) {
revert ConfigDigestMismatch(s_configs[donId][pluginType][secondaryConfigIndex].configDigest, digestToPromote);
if (s_configs[pluginKey][secondaryConfigIndex].configDigest != digestToPromote) {
revert ConfigDigestMismatch(s_configs[pluginKey][secondaryConfigIndex].configDigest, digestToPromote);
}

uint256 primaryConfigIndex = s_primaryConfigIndex;
if (s_configs[donId][pluginType][primaryConfigIndex].configDigest != digestToRevoke) {
revert ConfigDigestMismatch(s_configs[donId][pluginType][primaryConfigIndex].configDigest, digestToRevoke);
if (s_configs[pluginKey][primaryConfigIndex].configDigest != digestToRevoke) {
revert ConfigDigestMismatch(s_configs[pluginKey][primaryConfigIndex].configDigest, digestToRevoke);
}

delete s_configs[donId][pluginType][primaryConfigIndex].configDigest;
delete s_configs[pluginKey][primaryConfigIndex].configDigest;

s_primaryConfigIndex ^= 1;
if (digestToRevoke != ZERO_DIGEST) {
Expand All @@ -250,17 +244,16 @@ abstract contract HomeBase is OwnerIsCreator, ITypeAndVersion, ICapabilityConfig
}

function setDynamicConfig(
uint32 donId,
uint8 pluginType,
bytes32 pluginKey,
bytes calldata newDynamicConfig,
bytes32 currentDigest
) external OnlyOwnerOrSelfCall {
for (uint256 i = 0; i < MAX_CONCURRENT_CONFIGS; ++i) {
if (s_configs[donId][pluginType][i].configDigest == currentDigest && currentDigest != ZERO_DIGEST) {
_validateDynamicConfig(s_configs[donId][pluginType][i].staticConfig, newDynamicConfig);
if (s_configs[pluginKey][i].configDigest == currentDigest && currentDigest != ZERO_DIGEST) {
_validateDynamicConfig(s_configs[pluginKey][i].staticConfig, newDynamicConfig);

// Since the static config doesn't change we don't have to update the digest or version.
s_configs[donId][pluginType][i].dynamicConfig = newDynamicConfig;
s_configs[pluginKey][i].dynamicConfig = newDynamicConfig;

emit DynamicConfigSet(currentDigest, newDynamicConfig);
return;
Expand All @@ -271,8 +264,7 @@ abstract contract HomeBase is OwnerIsCreator, ITypeAndVersion, ICapabilityConfig
}

function _calculateConfigDigest(
uint32 donId,
uint8 pluginType,
bytes32 pluginKey,
bytes memory staticConfig,
uint32 version
) internal view returns (bytes32) {
Expand All @@ -281,9 +273,7 @@ abstract contract HomeBase is OwnerIsCreator, ITypeAndVersion, ICapabilityConfig
| (
uint256(
keccak256(
bytes.concat(
abi.encode(bytes32("EVM"), block.chainid, address(this), donId, pluginType, version), staticConfig
)
bytes.concat(abi.encode(bytes32("EVM"), block.chainid, address(this), pluginKey, version), staticConfig)
)
) & ~PREFIX_MASK
)
Expand Down
12 changes: 5 additions & 7 deletions contracts/src/v0.8/ccip/capability/RMNHome.sol
Original file line number Diff line number Diff line change
Expand Up @@ -56,11 +56,10 @@ contract RMNHome is HomeBase {
/// @return versionedConfig The config and its version.
/// @return ok True if the config was found, false otherwise.
function getConfig(
uint32 donId,
uint8 pluginType,
bytes32 pluginKey,
bytes32 configDigest
) external view returns (VersionedConfig memory versionedConfig, bool ok) {
(StoredConfig memory storedConfig, bool configOK) = _getStoredConfig(donId, pluginType, configDigest);
(StoredConfig memory storedConfig, bool configOK) = _getStoredConfig(pluginKey, configDigest);
if (configOK) {
return (
VersionedConfig({
Expand All @@ -77,10 +76,9 @@ contract RMNHome is HomeBase {
}

function getAllConfigs(
uint32 donId,
uint8 pluginType
bytes32 pluginKey
) external view returns (VersionedConfig memory primaryConfig, VersionedConfig memory secondaryConfig) {
(StoredConfig memory primaryStoredConfig, bool primaryOk) = _getPrimaryStoredConfig(donId, pluginType);
(StoredConfig memory primaryStoredConfig, bool primaryOk) = _getPrimaryStoredConfig(pluginKey);

if (primaryOk) {
primaryConfig = VersionedConfig({
Expand All @@ -91,7 +89,7 @@ contract RMNHome is HomeBase {
});
}

(StoredConfig memory secondaryStoredConfig, bool secondaryOk) = _getSecondaryStoredConfig(donId, pluginType);
(StoredConfig memory secondaryStoredConfig, bool secondaryOk) = _getSecondaryStoredConfig(pluginKey);

if (secondaryOk) {
secondaryConfig = VersionedConfig({
Expand Down
Loading

0 comments on commit 488c5e6

Please sign in to comment.