Skip to content

Commit

Permalink
evm: add support for per-chain enabled transceivers
Browse files Browse the repository at this point in the history
  • Loading branch information
kcsongor authored and bruce-riley committed Sep 13, 2024
1 parent 02160b8 commit 0c321bb
Show file tree
Hide file tree
Showing 3 changed files with 73 additions and 3 deletions.
37 changes: 34 additions & 3 deletions evm/src/NttManager/ManagerBase.sol
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,19 @@ abstract contract ManagerBase is
}
}

function _getThresholdStoragePerChain()
private
pure
returns (mapping(uint16 => _Threshold) storage $)
{
// TODO: this is safe (reusing the storage slot, because the mapping
// doesn't write into the slot itself) buy maybe we shouldn't?
uint256 slot = uint256(THRESHOLD_SLOT);
assembly ("memory-safe") {
$.slot := slot
}
}

function _getMessageAttestationsStorage()
internal
pure
Expand Down Expand Up @@ -122,6 +135,9 @@ abstract contract ManagerBase is
uint256 totalPriceQuote = 0;
for (uint256 i = 0; i < numEnabledTransceivers; i++) {
address transceiverAddr = enabledTransceivers[i];
if (!_isTransceiverEnabledForChain(transceiverAddr, recipientChain)) {
continue;
}
uint8 registeredTransceiverIndex = transceiverInfos[transceiverAddr].index;
uint256 transceiverPriceQuote = ITransceiver(transceiverAddr).quoteDeliveryPrice(
recipientChain, transceiverInstructions[registeredTransceiverIndex]
Expand Down Expand Up @@ -150,6 +166,7 @@ abstract contract ManagerBase is
) {
revert TransceiverAlreadyAttestedToMessage(nttManagerMessageHash);
}
_getMessageAttestationsStorage()[nttManagerMessageHash].sourceChainId = sourceChainId;
_setTransceiverAttestedToMessage(nttManagerMessageHash, msg.sender);

return nttManagerMessageHash;
Expand Down Expand Up @@ -200,6 +217,9 @@ abstract contract ManagerBase is
// call into transceiver contracts to send the message
for (uint256 i = 0; i < numEnabledTransceivers; i++) {
address transceiverAddr = enabledTransceivers[i];
if (!_isTransceiverEnabledForChain(transceiverAddr, recipientChain)) {
continue;
}

// send it to the recipient nttManager based on the chain
ITransceiver(transceiverAddr).sendMessage{value: priceQuotes[i]}(
Expand Down Expand Up @@ -284,11 +304,20 @@ abstract contract ManagerBase is
return _getThresholdStorage().num;
}

function getThreshold(uint16 chainId) public view returns (uint8) {
uint8 threshold = _getThresholdStoragePerChain()[chainId].num;
if (threshold == 0) {
return _getThresholdStorage().num;
}
return threshold;
}

/// @inheritdoc IManagerBase
function isMessageApproved(
bytes32 digest
) public view returns (bool) {
uint8 threshold = getThreshold();
uint16 sourceChainId = _getMessageAttestationsStorage()[digest].sourceChainId;
uint8 threshold = getThreshold(sourceChainId);
return messageAttestations(digest) >= threshold && threshold > 0;
}

Expand Down Expand Up @@ -432,8 +461,10 @@ abstract contract ManagerBase is
bytes32 digest
) internal view returns (uint64) {
uint64 enabledTransceiverBitmap = _getEnabledTransceiversBitmap();
return
_getMessageAttestationsStorage()[digest].attestedTransceivers & enabledTransceiverBitmap;
uint16 sourceChainId = _getMessageAttestationsStorage()[digest].sourceChainId;
uint64 enabledTransceiversForChain = _getEnabledTransceiversBitmapForChain(sourceChainId);
return _getMessageAttestationsStorage()[digest].attestedTransceivers
& enabledTransceiverBitmap & enabledTransceiversForChain;
}

function _getEnabledTransceiverAttestedToMessage(
Expand Down
36 changes: 36 additions & 0 deletions evm/src/NttManager/TransceiverRegistry.sol
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,19 @@ abstract contract TransceiverRegistry {
}
}

function _getPerChainTransceiverBitmapStorage()
private
pure
returns (mapping(uint16 => _EnabledTransceiverBitmap) storage $)
{
// TODO: this is safe (reusing the storage slot, because the mapping
// doesn't write into the slot itself) buy maybe we shouldn't?
uint256 slot = uint256(TRANSCEIVER_BITMAP_SLOT);
assembly ("memory-safe") {
$.slot := slot
}
}

function _getRegisteredTransceiversStorage() internal pure returns (address[] storage $) {
uint256 slot = uint256(REGISTERED_TRANSCEIVERS_SLOT);
assembly ("memory-safe") {
Expand All @@ -138,6 +151,15 @@ abstract contract TransceiverRegistry {

// =============== Storage Getters/Setters ========================================

function _isTransceiverEnabledForChain(
address transceiver,
uint16 chainId
) internal view returns (bool) {
uint64 bitmap = _getEnabledTransceiversBitmapForChain(chainId);
uint8 index = _getTransceiverInfosStorage()[transceiver].index;
return (bitmap & uint64(1 << index)) != 0;
}

function _setTransceiver(
address transceiver
) internal returns (uint8 index) {
Expand Down Expand Up @@ -234,6 +256,20 @@ abstract contract TransceiverRegistry {
return _getTransceiverBitmapStorage().bitmap;
}

function _getEnabledTransceiversBitmapForChain(uint16 chainId)
internal
view
virtual
returns (uint64 bitmap)
{
bitmap = _getPerChainTransceiverBitmapStorage()[chainId].bitmap;
if (bitmap == 0) {
// NOTE: this makes it backwards compatible -- if the bitmap is not
// set, it's assumed the corridor uses all transceivers.
return type(uint64).max;
}
}

/// @notice Returns the Transceiver contracts that have been enabled via governance.
function getTransceivers() external pure returns (address[] memory result) {
result = _getEnabledTransceiversStorage();
Expand Down
3 changes: 3 additions & 0 deletions evm/src/interfaces/IManagerBase.sol
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ interface IManagerBase {
struct AttestationInfo {
bool executed;
uint64 attestedTransceivers;
// TODO: think about potential migration issues here (this field was
// introduced later, so for older messages it will be 0).
uint16 sourceChainId;
}

struct _Sequence {
Expand Down

0 comments on commit 0c321bb

Please sign in to comment.