AuthZ

摘要

x/authz 是一个基于 ADR 30 实现的 Cosmos SDK 模块,允许从一个账户(授予者)向另一个账户(被授权者)授予任意权限。授权必须针对特定的 Msg 服务方法逐个授予,使用 Authorization 接口的实现。

目录

概念

AuthorizationGrant

x/authz 模块定义了接口和消息,用于授予其他账户代表一个账户执行操作的授权。该设计在 ADR 030中进行了定义。

Grant 是一种授权,允许被授权者代表授予者执行一个 MsgAuthorization 是一个接口,必须由具体的授权逻辑实现,以验证和执行授权。授权是可扩展的,可以为任何 Msg 服务方法定义,即使该方法定义在模块之外。有关更多细节,请参见下一节中的 SendAuthorization 示例。

注意:authz 模块与 auth(身份验证)模块不同,后者负责指定基础的交易和账户类型。

https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/x/authz/authorizations.go#L11-L25

内建授权

Cosmos SDK x/authz 模块提供以下授权类型:

GenericAuthorization

GenericAuthorization 实现了 Authorization 接口,授予无限制的权限,允许代表授予者账户执行提供的 Msg

https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/proto/cosmos/authz/v1beta1/authz.proto#L14-L22
https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/x/authz/generic_authorization.go#L16-L29
  • msg 存储 Msg 类型的 URL。

SendAuthorization

SendAuthorization 实现了 Authorization 接口,用于 cosmos.bank.v1beta1.MsgSend 消息。

  • 它接受一个(正数)SpendLimit,指定被授权者可以花费的最大代币数量。随着代币的花费,SpendLimit 会更新。

  • 它还接受一个(可选的)AllowList,指定被授权者可以向哪些地址发送代币。

https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/proto/cosmos/bank/v1beta1/authz.proto#L11-L30
https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/x/bank/types/send_authorization.go#L29-L62
  • spend_limit 用于跟踪授权中剩余的代币数量。

  • allow_list 指定一个可选的地址列表,受权人可以代表授予者向这些地址发送代币。

StakeAuthorization

StakeAuthorization 实现了 Authorization 接口,用于质押模块中的消息。 它接受一个 AuthorizationType,指定是否授权委托、取消委托或重新委托(即这些操作必须分别授权)。 它还接受一个必需的 MaxTokens,用于跟踪可以委托/取消委托/重新委托的代币数量限制。如果留空,则数量没有限制。 此外,该消息还接受一个 AllowListDenyList,允许你选择授权或拒绝被授权者与哪些验证者进行质押。

https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/proto/cosmos/staking/v1beta1/authz.proto#L11-L35
https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/x/staking/types/authz.go#L15-L35

燃料

为了防止 DoS 攻击,授予 StakeAuthorization 使用 x/authz 模块会消耗 gas。StakeAuthorization 允许你授权另一个账户向验证者进行委托、取消委托或重新委托。授权者可以定义一个验证者列表,允许或拒绝向这些验证者进行委托。Cosmos SDK 会遍历这些列表,并对每个列表中的验证者收取 10 gas。

由于状态维护着具有相同过期时间的授予者和被授权者对列表,我们会遍历列表以移除授予(如果某个特定的 msgType 被撤销),每次迭代收取 20 gas。

状态

Grant

授权通过组合授予者地址(授予者的地址字节)、被授权者地址(被授权者的地址字节)和授权类型(其类型 URL)来标识。因此,我们只允许为(授予者、被授权者、授权类型)三元组设置一个授权。

  • Grant: 0x01 | granter_address_len (1 byte) | granter_address_bytes | grantee_address_len (1 byte) | grantee_address_bytes | msgType_bytes -> ProtocolBuffer(AuthorizationGrant)

grant 对象封装了一个授权类型和一个过期时间戳:

https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/proto/cosmos/authz/v1beta1/authz.proto#L24-L32

GrantQueue

我们正在维护一个用于 authz 剔除的队列。每当创建一个授权时,带有过期时间、授予者和被授权者的键将被添加到 GrantQueue 中。 在 EndBlock(每个区块都会执行)中,我们不断检查并剔除过期的授权,通过形成一个前缀键,使用当前区块时间与 GrantQueue 中存储的过期时间进行比较,遍历所有匹配的记录并从 GrantQueueGrants 存储中删除它们。

https://github.com/cosmos/cosmos-sdk/blob/5f4ddc6f80f9707320eec42182184207fff3833a/x/authz/keeper/keeper.go#L378-L403
  • GrantQueue: 0x02 | expiration_bytes | granter_address_len (1 byte) | granter_address_bytes | grantee_address_len (1 byte) | grantee_address_bytes -> ProtocalBuffer(GrantQueueItem)

expiration_bytes 是以 UTC 格式表示的过期日期,格式为 "2006-01-02T15:04:05.000000000"

https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/x/authz/keeper/keys.go#L77-L93

GrantQueueItem 对象包含在授予者和被授权者之间的类型 URL 列表,这些授权将在键中指示的时间过期。

消息

在本节中,我们描述了 authz 模块消息的处理过程。

MsgGrant

An authorization grant is created using the MsgGrant message. If there is already a grant for the (授予者、被授权者、授权类型)三元组,如果存在相同的三元组,则新的授权将覆盖之前的授权。要更新或扩展现有的授权,应创建一个具有相同(授予者、被授权者、授权类型)三元组的新授权。

https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/proto/cosmos/authz/v1beta1/tx.proto#L35-L45

如果出现以下情况,消息处理应失败:

  • 授予者和被授权者具有相同的地址。

  • 提供的过期时间小于当前的 Unix 时间戳(但如果未提供过期时间,则会创建授权,因为过期时间是可选的)。

  • 提供的 Grant.Authorization 未实现。

  • Authorization.MsgTypeURL() 在路由器中未定义(应用程序路由器中没有定义处理该消息类型的处理程序)。

MsgRevoke

授权可以通过 MsgRevoke 消息移除。

https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/proto/cosmos/authz/v1beta1/tx.proto#L69-L78

如果出现以下情况,消息处理应失败:

  • 授予者和被授权者具有相同的地址。

  • 提供的 MsgTypeUrl 为空。

注意:如果授权已过期,MsgExec 消息将移除该授权。

MsgExec

当被授权者希望代表授予者执行交易时,他们必须发送 MsgExec 消息。

https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/proto/cosmos/authz/v1beta1/tx.proto#L52-L63

如果出现以下情况,消息处理应失败:

  • 提供的授权未实现。

  • 被授权者没有权限执行该交易。

  • 授予的授权已过期。

事件

authz 模块会触发在 Protobuf 参考中定义的 proto 事件。

客户端

CLI

用户可以使用 CLI 查询和与 authz 模块进行交互。

Query

查询命令允许用户查询 authz 状态。

simd query authz --help

grants

grants 命令允许用户查询授予者和被授权者对的授权。如果设置了消息类型 URL,则仅选择该消息类型的授权。

simd query authz grants [granter-addr] [grantee-addr] [msg-type-url]? [flags]

示例:

simd query authz grants cosmos1.. cosmos1.. /cosmos.bank.v1beta1.MsgSend

示例输出:

grants:
- authorization:
    '@type': /cosmos.bank.v1beta1.SendAuthorization
    spend_limit:
    - amount: "100"
      denom: stake
  expiration: "2022-01-01T00:00:00Z"
pagination: null

Transactions

tx 命令允许用户与 authz 模块进行交互。

simd tx authz --help

exec

exec 命令允许被授权者代表授予者执行交易。

  simd tx authz exec [tx-json-file] --from [grantee] [flags]

示例:

simd tx authz exec tx.json --from=cosmos1..

grant

grant 命令允许授予者向被授权者授予授权。

simd tx authz grant <grantee> <authorization_type="send"|"generic"|"delegate"|"unbond"|"redelegate"> --from <granter> [flags]

示例:

simd tx authz grant cosmos1.. send --spend-limit=100stake --from=cosmos1..

revoke

revoke 命令允许授予者从被授权者那里撤销授权。

simd tx authz revoke [grantee] [msg-type-url] --from=[granter] [flags]

示例:

simd tx authz revoke cosmos1.. /cosmos.bank.v1beta1.MsgSend --from=cosmos1..

gRPC

用户可以使用 gRPC 端点查询 authz 模块。

Grants

Grants 端点允许用户查询授予者和被授权者对的授权。如果设置了消息类型 URL,则仅选择该消息类型的授权。

cosmos.authz.v1beta1.Query/Grants

示例:

grpcurl -plaintext \
    -d '{"granter":"cosmos1..","grantee":"cosmos1..","msg_type_url":"/cosmos.bank.v1beta1.MsgSend"}' \
    localhost:9090 \
    cosmos.authz.v1beta1.Query/Grants

示例输出:

{
  "grants": [
    {
      "authorization": {
        "@type": "/cosmos.bank.v1beta1.SendAuthorization",
        "spendLimit": [
          {
            "denom":"stake",
            "amount":"100"
          }
        ]
      },
      "expiration": "2022-01-01T00:00:00Z"
    }
  ]
}

REST

用户可以使用 REST 端点查询 authz 模块。

/cosmos/authz/v1beta1/grants

示例:

curl "localhost:1317/cosmos/authz/v1beta1/grants?granter=cosmos1..&grantee=cosmos1..&msg_type_url=/cosmos.bank.v1beta1.MsgSend"

示例输出:

{
  "grants": [
    {
      "authorization": {
        "@type": "/cosmos.bank.v1beta1.SendAuthorization",
        "spend_limit": [
          {
            "denom": "stake",
            "amount": "100"
          }
        ]
      },
      "expiration": "2022-01-01T00:00:00Z"
    }
  ],
  "pagination": null
}

Last updated