该提案 (ELIP-003) 介绍了 EigenLayer 中的用户访问管理 (UAM) 功能,旨在增强 Operator 和 AVS 开发者的密钥管理能力,例如实现安全的密钥轮换、撤销和恢复。UAM 通过分离 ServiceManager
的职责来简化 AVS 架构,允许管理员密钥将特定功能委派给新的地址或合约,从而增强 EigenLayer 生态系统的安全性、操作效率和可扩展性。
作者 | 创建时间 | 状态 | 引用 | 讨论 |
---|---|---|---|---|
Matt Nelson Zeyad Rajabi Yash Patil | 2024-11-20 | 已合并 |
论坛帖子 |
用户访问管理 (UAM) 是 EigenLayer 中的一项协议级功能,旨在增强 Operator 和 AVS 开发者的密钥管理,例如允许安全的密钥轮换、撤销和恢复。UAM 将在关键方面简化 AVS 架构,主要通过拆分 ServiceManager
的职责。该协议现在划分了 root 管理员密钥可以委派给新地址(EOA 或合约)的特定功能。类似地,管理员密钥本身也可以被委派或轮换。
Operator 在保护 EigenLayer 生态系统中发挥着至关重要的作用,他们允许质押者委托其资产,为 Actively Validated Services (AVS) 提供服务。为了有效地运营,Operator 和 AVS 开发者依赖于安全高效的密码密钥管理:
Operator 密钥:智能合约或 ECDSA 密钥,用于核心功能,例如注册、奖励领取、可罚没权益分配和费用管理,需要不频繁的使用。
AVS 操作密钥:频繁使用的智能合约钱包或 ECDSA 密钥,用于管理核心协议内的操作相关功能。
Operator AVS 签名密钥:智能合约钱包、ECDSA、BLS 或其他类型的密钥,与 Operator 关联用于证明,并用于 AVS 中的任务验证逻辑。
EigenLayer 当前密钥管理的局限性给 Operator 和 AVS 开发者带来了几个挑战:
用户访问管理在协议层面实现,采用安全第一和用户赋权的方法,确保强大的、去中心化的安全控制直接集成到核心基础设施中。用户访问管理允许管理员地址所有者(Operator 或 AVS 开发者)创建和管理他们所需的任意数量的被委派用户(非管理员)地址和管理员地址。
管理员地址所有者可以添加任意数量的用户地址,并自定义每个用户地址允许调用的协议函数。当不再需要访问权限时,管理员地址所有者可以撤销用户地址级别的一个或多个权限。下图突出了这些关键点:
使用此模型进行密钥轮换很简单。管理员地址所有者可以创建一个具有相同权限集的新用户地址,然后撤销对旧用户地址的访问权限。下图突出了密钥轮换设计:
为了在管理员地址所有者级别轮换密钥,管理员地址所有者可以创建一个新的管理员地址。然后,管理员地址所有者可以删除旧的管理员地址。此方法确保新的管理员地址具有相同的用户地址和权限集。下图突出了管理员地址所有者级别的密钥轮换:
以下列出了管理员地址所有者可以委派给特定地址的协议函数:
管理员密钥将始终能够委派子密钥或自行完成所有这些操作。
请注意,随着协议级别引入新函数(将来)以及 EigenLayer 协议之外的任何自定义智能合约函数,访问权限可以扩展到上面列出的函数列表之外。
UAM 将核心合约 PermissionController
作为 DelegationManager
、AllocationManager
和 RewardsCoordinator
的依赖项添加。我们为 AVS 和 Operator 启用此功能,但不为质押者启用。请注意,如果 Operator 也是质押者,则它不能为任何质押者操作添加被委任者,例如排队提款和存款。我们不打算支持 AVSDirectory
,因为我们计划在另一个 ELIP 中稍后弃用其功能。
Operator 和 AVS 可以为其帐户拥有多个管理员。这启用了管理员密钥轮换。Operator 的帐户地址通过 DelegationManager
中的 registerAsOperator
函数初始化。AVS 的帐户地址通过 AllocationManager
中的 updateAVSMetadataURI
函数初始化。
管理员通过两步握手配置。必须将管理员设置为待定。之后,待定的管理员必须接受对帐户的管理权。帐户必须始终至少有一个管理员。如果从未设置任何管理员,则最初的 Operator 地址将充当管理员。
Operator 不能为初始 Operator 注册添加被委任用户。换句话说,他们注册的地址是他们的帐户,然后他们可以在随后的交易中转移该帐户的管理权。类似地,AVS 的帐户是他们用于在 AllocationManager
中初始化状态的地址。当管理员密钥轮换时,原始公共地址仍然是关联的 Operator ID 或 AVS ID。
提供以下权限控制器接口:
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.27;
struct AccountPermissions {
/// @notice 帐户的待定管理员
EnumerableSet.AddressSet pendingAdmins;
/// @notice 帐户的管理员
EnumerableSet.AddressSet admins;
/// @notice 从被委任者到编码的目标和选择器的列表的映射
mapping(address appointee => EnumerableSet.Bytes32Set) appointeePermissions;
/// @notice 从编码的目标和选择器到被委任者的列表的映射
mapping(bytes32 targetSelector => EnumerableSet.AddressSet) permissionAppointees;
}
interface IPermissionControllerErrors {
/// @notice 当调用者不是管理员时抛出
error NotAdmin();
/// @notice 当要删除的管理员不是管理员时抛出
error AdminNotSet();
/// @notice 当帐户的功能已设置被委任者时抛出
error AppointeeAlreadySet();
/// @notice 当帐户的功能未设置被委任者时抛出
error AppointeeNotSet();
/// @notice 当帐户尝试删除唯一管理员时抛出
error CannotHaveZeroAdmins();
/// @notice 当已设置管理员时抛出
error AdminAlreadySet();
/// @notice 当管理员不是待定时抛出
error AdminNotPending();
/// @notice 当管理员已待定时抛出
error AdminAlreadyPending();
}
interface IPermissionControllerEvents {
/// @notice 当设置被委任者时发出
event AppointeeSet(address indexed account, address indexed appointee, address target, bytes4 selector);
/// @notice 当撤销被委任者时发出
event AppointeeRemoved(address indexed account, address indexed appointee, address target, bytes4 selector);
/// @notice 当将管理员设置为帐户的待定时发出
event PendingAdminAdded(address indexed account, address admin);
/// @notice 当删除帐户的待定管理员时发出
event PendingAdminRemoved(address indexed account, address admin);
/// @notice 当为给定帐户设置管理员时发出
event AdminSet(address indexed account, address admin);
/// @notice 当删除给定帐户的管理员时发出
event AdminRemoved(address indexed account, address admin);
}
interface IPermissionController is IPermissionControllerErrors, IPermissionControllerEvents {
/**
* @notice 设置帐户的待定管理员
* @param account 要设置待定管理员的帐户
* @param admin 要设置的管理员
* @dev 可以为帐户设置多个管理员
*/
function addPendingAdmin(address account, address admin) external;
/**
* @notice 删除帐户的待定管理员
* @param account 要删除待定管理员的帐户
* @param admin 要删除的管理员
* @dev 只有帐户的管理员才能删除待定管理员
*/
function removePendingAdmin(address account, address admin) external;
/**
* @notice 接受帐户的管理员角色
* @param account 要接受管理员的帐户
* @dev 只有帐户的待定管理员才能成为管理员
*/
function acceptAdmin(
address account
) external;
/**
* @notice 删除帐户的管理员
* @param account 要删除管理员的帐户
* @param admin 要删除的管理员
* @dev 只有帐户的管理员才能重新删除管理员
* @dev 当删除管理员以至于没有剩余管理员时,则恢复
*/
function removeAdmin(address account, address admin) external;
/**
* @notice 为给定帐户设置一个被委任者
* @param account 要设置被委任者的帐户
* @param appointee 要设置的被委任者
* @param target 要设置被委任者的目标
* @param selector 要设置被委任者的选择器
* @dev 只有帐户的管理员才能设置被委任者
*/
function setAppointee(address account, address appointee, address target, bytes4 selector) external;
/**
* 删除给定帐户的被委任者
* @param account 要删除被委任者的帐户
* @param appointee 要删除的被委任者
* @param target 要删除被委任者的目标
* @param selector 要删除被委任者的选择器
* @dev 只有帐户的管理员才能删除被委任者
*/
function removeAppointee(address account, address appointee, address target, bytes4 selector) external;
/**
* @notice 检查给定的调用者是否是帐户的管理员
* @dev 如果帐户没有管理员,则检查调用者是否是帐户本身
*/
function isAdmin(address account, address caller) external view returns (bool);
/**
* @notice 检查 `pendingAdmin` 是否是 `account` 的待定管理员
*/
function isPendingAdmin(address account, address pendingAdmin) external view returns (bool);
/**
* @notice 获取帐户的管理员
* @param account 要获取管理员的帐户
* @dev 如果帐户没有管理员,则返回帐户本身
*/
function getAdmins(
address account
) external view returns (address[] memory);
/**
* @notice 获取帐户的待定管理员
* @param account 要获取待定管理员的帐户
*/
function getPendingAdmins(
address account
) external view returns (address[] memory);
/**
* @notice 检查给定的调用者是否具有调用该函数的权限
* @param account 要检查的帐户
* @param caller 要检查权限的调用者
* @param target 要检查权限的目标
* @param selector 要检查权限的选择器
* @dev 如果管理员或被委任者是调用者,则返回 `true`
*/
function canCall(address account, address caller, address target, bytes4 selector) external returns (bool);
/**
* @notice 获取给定帐户的被委任者的权限列表
* @param account 要获取被委任者的权限
* @param appointee 要获取权限的被委任者
*/
function getAppointeePermissions(
address account,
address appointee
) external returns (address[] memory, bytes4[] memory);
/**
* @notice 返回给定帐户和函数的被委任者列表
* @param account 要获取被委任者的帐户
* @param target 要获取被委任者的目标
* @param selector 要获取被委任者的选择器
* @dev 不包括管理员作为被委任者,即使它可以调用
*/
function getAppointees(address account, address target, bytes4 selector) external returns (address[] memory);
}
此接口存在于核心合约中。底层 PermissionController
合约是可升级的。我们预计核心中可能会出现新的需求,这将需要将新的操作添加到 UAM 接口。这些可能是核心协议中尚未设计的功能,这些功能可以用于委派或授予权限。
管理员密钥的安全性在 UAM 中至关重要。Operator 和 AVS 应在设置管理员地址并确保管理员密钥的安全时采取预防措施。一旦管理员接受了管理权,除非还配置为管理员,否则 Operator ID 或 AVS ID 的原始 root 密钥不能用于对协议执行写入操作。无论密钥如何构造和管理,始终建议对管理员密钥保持谨慎。切勿暴露或将管理员密钥连接到 Web。当需要密钥时,请注意可以使用减少的权限进行 UAM 委派,或使用以后可以轮换或销毁的密钥。
此提案中没有强制执行的迁移设计。该协议将继续按预期工作,无需采取任何措施,但 Operator 将拥有强大的访问管理和权限控制功能。
通过允许为每个操作灵活设置地址,我们预计 Operator 将实施从简单(ECDSA 密钥轮换)到复杂(上游智能合约权限方案)的各种解决方案。这种灵活性旨在鼓励和支持强大的网络安全实践,无论它们是什么。
以下是一个重大更改。我们正在更新接口,以将 OperatorID 作为输入添加到多个函数。这包括 updateOperatorMetadataURI
和 modifyOperatorDetails
。
/**
* @notice 由 operator 调用以发出一个 `OperatorMetadataURIUpdated` 事件,表明信息已更新。
* @param operator 要更新元数据的 operator
* @param metadataURI 与 Operator 关联的元数据的 URI
* @dev 请注意,`metadataURI` *从不存储*,仅在 `OperatorMetadataURIUpdated` 事件中发出
*/
function updateOperatorMetadataURI(
address operator,
string calldata metadataURI
) external;
随着我们朝着发布罚没的方向发展,AVS 将需要强大的工具来确保密钥得到良好保护,因为它们很快就可以用于罚没用户资金并直接与分配的权益进行交互。相同的灵活解决方案提供给 AVS,并且还为更复杂的、基于治理的方案或简单但安全的解决方案(例如每个操作隔离的多重签名)打开了大门。我们预计生态系统中会出现专门填补其中一些空白的解决方案。该协议对这些解决方案保持不偏不倚的态度,使 AVS 开发者能够选择自己的方法。
此外,UAM 通过允许将协议的许多写入函数委派给新地址(智能合约),从而解锁了 AVS 设计中的更多模块化。这开启了新的设计,并消除了 Service Manager
作为进入 EigenLayer 的传递合约的需求。
此提案将纳入罚没版本。它不会有与其相关的自身升级,并且不需要团队进行任何额外的开销。
无
- 原文链接: github.com/eigenfoundati...
- 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!