- 区块链
【免费下载链接】eos
An open source smart contract platform
导读
在 EOSIO 区块链上,权限链接(permission link)机制允许账户为某个智能合约的具体 action 单独指定一个最低授权权限,从而把合约调用的鉴权从默认的active/owner权限中剥离出来。本文以 eos 仓库中的官方操作指南为基础,讲解如何通过cleos set action permission命令配合关键字NULL解除(unlink)一个已链接的权限级别,并深入仓库源码,揭示该命令在cleos客户端、链上unlinkauth原生动作与authorization_manager校验逻辑中的完整执行链路。读完本文,你将能独立完成"为指定合约动作解除权限绑定、恢复默认授权行为"的完整操作,并理解解除操作的底层原理与失败场景。
前置条件(Before you begin)
在动手解除权限链接之前,需要满足以下条件:
- 安装当前受支持的
cleos版本:cleos随 EOSIO 软件一同分发,安装 EOSIO 即会同时安装cleos与keosd两个命令行工具,安装指引见 docs/00_install/index.md。 - 理解以下基础概念:
- 账户(Account):EOSIO 上的身份实体,所有权限与合约动作都挂载在账户之下;
- 权限级别(Permission Level):账户内部的授权层级,最常用的是
owner、active,也可以自定义子权限(如customp); - 动作(Action):智能合约暴露的可调用操作,例如转账合约的
transfer动作。
核心概念:什么是"解除权限链接"
EOSIO 的权限链接是一张"动作 → 最低权限"的映射表。当你执行
cleos set action permission alice hodlcontract transfer customp -p alice@active时,链上实际产生的是一个eosio::linkauth动作,其数据为{"account":"alice","code":"hodlcontract","type":"transfer","requirement":"customp"},含义是:只有持有不低于customp权限的签名,才被允许以账户alice的身份调用hodlcontract合约的transfer动作。
"解除权限链接"就是把这张映射删除:此后该动作不再有专门的最低权限要求,恢复为 EOSIO 的默认行为——即由调用时使用的权限直接决定能否执行(通常对应账户的active权限)。
与之对应的操作是建立权限链接,完整的操作指南见 docs/02_cleos/02_how-to-guides/how-to-link-permission.md。链接与解除使用同一条命令,区别仅在于最后一个位置参数是权限名还是NULL。
命令总览与参数说明
解除权限链接使用的命令是cleos set action permission,完整命令格式如下:
cleos set action permission [OPTIONS] account code type requirement其中:
| 参数 | 类型 | 是否必填 | 说明 |
|---|---|---|---|
account | TEXT | 必填 | 要设置/删除权限动作链接的账户 |
code | TEXT | 必填 | 拥有该动作代码的合约账户(即合约部署所在的账户) |
type | TEXT | 必填 | 动作名称。注意权限必须按动作逐个设置 |
requirement | TEXT | 必填 | 传入NULL表示删除链接;传入权限名表示设置或更新该动作所需的最低权限 |
常用选项:
| 选项 | 说明 |
|---|---|
-h, --help | 打印帮助信息并退出 |
-x, --expiration | 设置交易过期时间(秒),默认 30 秒 |
-p, --permission | 授权本次操作所用的账户与权限级别,格式为account@permission,默认account@active |
-j, --json | 以 JSON 格式打印结果 |
-d, --dont-broadcast | 不广播交易到网络(仅打印到 stdout) |
--return-packed | 与--dont-broadcast配合使用,输出打包后的交易 |
-r, --ref-block | 设置用于 TAPOS 的参考区块号或区块 ID |
--max-cpu-usage-ms | 交易执行的 CPU 用量上限(毫秒),默认 0 表示不限制 |
--max-net-usage | 交易的网络用量上限(字节),默认 0 表示不限制 |
--delay-sec | 设置交易的延迟秒数,默认 0 秒 |
完整的官方命令参考文档见 docs/02_cleos/03_command-reference/set/set-action-permission.md。
解除权限链接的标准步骤
以下步骤演示如何解除账户alice对合约hodlcontract的transfer动作的权限链接:
cleos set action permission alice hodlcontract transfer NULL各参数含义:
alice= 持有被解除权限链接的账户名;hodlcontract= 拥有该智能合约代码的合约账户名;transfer= 要解除链接的动作名;NULL= 删除该动作上已有的权限链接。
如果不显式指定-p,命令默认以alice@active作为授权签名。更严谨的写法是显式声明授权权限:
cleos set action permission alice hodlcontract transfer NULL -p alice@active该命令执行成功后,会在终端打印类似如下的输出:
executed transaction: 50fe754760a1b8bd0e56f57570290a3f5daa509c090deb54c81a721ee7048201 120 bytes 242 us # eosio <= eosio::unlinkauth {"account":"alice","code":"hodlcontract","type":"transfer"}可以看到,链上实际执行的是eosio::unlinkauth原生动作,载荷中只有account、code、type三个字段,不再包含requirement字段——这正是"解除链接"与"建立链接"(linkauth带requirement字段)在链上数据层面的本质区别。
解除链接后发生了什么
解除成功后,transfer动作不再受自定义最低权限的约束,对合约动作的调用将回到默认授权流程:
- 若
alice是普通用户账户,调用时使用其active权限即可正常执行; - 若
alice是合约账户,且该动作是合约自己发起的(如内联动作),则不再需要链接到eosio.code权限,按常规授权处理。
底层原理:cleos 如何把NULL变成unlinkauth
cleos set action permission的实现在 programs/cleos/main.cpp 中,核心逻辑位于set_action_permission_subcommand结构体(programs/cleos/main.cpp#L959-L988):
permissions->callback([this] { name account = name(accountStr); name code = name(codeStr); name type = name(typeStr); bool is_delete = boost::iequals(requirementStr, "null"); if (is_delete) { send_actions({create_unlinkauth(account, code, type)}, signing_keys_opt.get_keys()); } else { name requirement = name(requirementStr); send_actions({create_linkauth(account, code, type, requirement)}, signing_keys_opt.get_keys()); } });这段代码揭示了几个关键细节:
NULL的判断是大小写不敏感的:客户端使用boost::iequals(requirementStr, "null")做忽略大小写的字符串比较,因此NULL、null、Null均被识别为删除操作,并据此构建unlinkauth动作;NULL不允许作为权限名使用:一旦命中删除分支,requirement字符串就不会再被解析为name类型,避免与真实权限名混淆;- 构建动作由辅助函数完成:
create_unlinkauth(programs/cleos/main.cpp#L768-L771)会构造一个chain::action,其authorization取自get_account_permissions(tx_permission, {account, config::active_name}),即默认使用目标账户的active权限作为本交易的授权声明。
链上校验:authorization_manager 如何验证解除操作
unlinkauth动作在链上由系统合约eosio处理。在 eos 仓库中,动作处理器通过宏注册于 libraries/chain/controller.cpp#L278-L279:
SET_APP_HANDLER( eosio, eosio, linkauth ); SET_APP_HANDLER( eosio, eosio, unlinkauth );对应的鉴权检查实现在 libraries/chain/authorization_manager.cpp 的check_unlinkauth_authorization(libraries/chain/authorization_manager.cpp#L412-L424)中:
void authorization_manager::check_unlinkauth_authorization( const unlinkauth& unlink, const vector<permission_level>& auths )const { EOS_ASSERT( auths.size() == 1, irrelevant_auth_exception, "unlink action should only have one declared authorization" ); const auto& auth = auths[0]; EOS_ASSERT( auth.actor == unlink.account, irrelevant_auth_exception, "the owner of the linked permission needs to be the actor of the declared authorization" ); const auto unlinked_permission_name = lookup_linked_permission(unlink.account, unlink.code, unlink.type); EOS_ASSERT( unlinked_permission_name, transaction_exception, "cannot unlink non-existent permission link of account '${account}' for actions matching '${code}::${action}'", ... ); }从中可以提炼出解除操作在链上必须满足的三条硬性规则:
- 只能有一个授权声明:
unlinkauth动作必须且只能带一个authorization; - 授权者必须是链接归属账户:授权声明的
actor必须等于unlink.account,即只有账户本人(或其授权的子权限签名)才能解除自己账户下的链接; - 链接必须真实存在:若该账户对该动作本就没有权限链接,交易会被
transaction_exception拒绝并报错cannot unlink non-existent permission link——这解释了为什么对从未链接过的动作重复执行NULL操作会失败,而不是静默成功。
此外,同文件中的check_linkauth_authorization(libraries/chain/authorization_manager.cpp#L375-L410)还对"建立链接"设置了限制:在fix_linkauth_restriction协议特性生效后,不能对eosio系统合约的updateauth、deleteauth、linkauth、unlinkauth、canceldelay等敏感系统动作设置最低权限链接。这也意味着这些系统动作同样不应(也不被允许)被随意链接后再解除,相关限制会直接影响你规划权限链接方案的边界。
常见场景与注意事项
- 解除后权限恢复默认:解除链接只删除"动作 → 最低权限"的映射,不会删除任何权限本身。若要删除自定义权限,应使用
cleos set account permission(见 docs/02_cleos/03_command-reference/set/set-account-permission.md)或cleos set account permission ... NULL的权限删除用法。 - 对未链接的动作执行解除会失败:正如链上校验规则所述,
cannot unlink non-existent permission link是正常防护,不属于命令执行错误。 - 区分"解除链接"与"删除权限":两者是不同层级的操作——前者只影响单个合约动作的鉴权映射,后者影响账户的整个权限结构,误删权限可能导致账户失去控制能力,操作前应谨慎核对账户与权限名。
- 大小写不敏感但建议规范书写:客户端按忽略大小写的方式识别
NULL,社区与官方文档统一使用大写NULL以保持可读性。 - 合约内联动作场景:如果某合约动作此前被链接到
eosio.code以便合约以自身身份发起内联动作,解除链接后该内联调用将不再被该最低权限放行,需改用其他授权方式(如直接使用active)。
相关资源
- 官方操作指南(本文主题文档):docs/02_cleos/02_how-to-guides/how-to-unlink-permission.md
- 建立权限链接指南:docs/02_cleos/02_how-to-guides/how-to-link-permission.md
- 命令参考:docs/02_cleos/03_command-reference/set/set-action-permission.md
- cleos 客户端实现:programs/cleos/main.cpp
- 链上鉴权校验:libraries/chain/authorization_manager.cpp
- 动作处理器注册:libraries/chain/controller.cpp
- 区块链
【免费下载链接】eos
An open source smart contract platform
相关推荐
notebooklm-py 的 Web batchexecute RPC 参考:混淆方法 ID、线格式 Payload 与 UI 选择器对照
notebooklm py 的 Web batchexecute RPC 参考:混淆方法 ID、线格式 Payload 与 UI 选择器对照 本文基于 docs
区块链EOS 多签账户配置实战:使用 cleos set account permission 构建多重签名权限
EOS 多签账户配置实战:使用 cleos set account permission 构建多重签名权限 导读 本指南讲解如何在 EOS 区块链上通过 cle
区块链EOSIO 账户密钥更新实战:使用 cleos 修改账户权限密钥
EOSIO 账户密钥更新实战:使用 cleos 修改账户权限密钥 本指南以 eos 仓库官方 How To 文档 how to update account k
区块链
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考