Auth

摘要

本文档定义了 Cosmos SDK 的 auth 模块。 auth 模块负责为应用指定基础的交易和账户类型,因为 SDK 本身对这些细节是无关的。该模块包含中间件,执行所有基本的交易有效性检查(签名、序列号、辅助字段),并暴露账户管理器(account keeper),允许其他模块读取、写入和修改账户。 此模块在 Cosmos Hub 中使用。

目录

概念

注意:auth模块与authz模块不同。 它们的区别如下:

  • auth - 用于Cosmos SDK应用的账户和交易认证,负责指定基础交易和账户类型。

  • authz - 用于授权账户代表其他账户执行操作,允许授权者(granter)授予被授权者(grantee)权限,使其能够代表授权者执行消息。

燃料 & 费用

费用对网络运营者有两个目的:

费用限制了每个全节点存储的状态的增长,并允许对经济价值较低的交易进行一般性审查。费用最适合作为反垃圾邮件机制,在这种机制下,验证者对网络的使用和用户身份不感兴趣。

费用由交易提供的 gas 限制和 gas 价格决定,其中费用 = ceil(gasLimit * gasPrices)。 交易在执行时会产生 gas 成本,包括所有状态读取/写入、签名验证以及与交易大小成比例的费用。 运营者在启动节点时应设置最低 gas 价格,并且必须为他们希望支持的每种代币面额设置 gas 单位成本:

simd start ... --minimum-gas-prices=0.00001stake;0.05photinos

当将交易添加到内存池或传播交易时,验证者检查交易的 gas 价格,这些 gas 价格由提供的费用决定,是否满足验证者的最低 gas 价格要求。换句话说,交易必须提供至少一个代币面额,其费用与验证者的最低 gas 价格匹配。

CometBFT 当前不提供基于费用的内存池优先级排序,且基于费用的内存池过滤是节点本地的,不属于共识的一部分。但在设置了最低 gas 价格的情况下,节点运营者可以实现此类机制。

由于代币的市场价值会波动,验证者预计会动态调整其最低 gas 价格,以鼓励网络的使用。

状态

Accounts

账户包含 SDK 区块链中唯一标识的外部用户的认证信息,包括公钥、地址、以及用于重放保护的账户号码/序列号。为了提高效率,账户结构还存储用户的余额(sdk.Coins),因为账户余额也必须在支付费用时被获取。

账户对外作为接口暴露,内部则存储为基础账户或归属账户。模块客户端如果希望添加更多账户类型,可以自行扩展。

  • 0x01 | Address -> ProtocolBuffer(account)

Account Interface

账户接口暴露了读取和写入标准账户信息的方法。请注意,所有这些方法都操作符合接口要求的账户结构体 - 为了将账户写入存储,必须使用账户管理器(account keeper)。

// AccountI is an interface used to store coins at a given address within state.
// It presumes a notion of sequence numbers for replay protection,
// a notion of account numbers for replay protection for previously pruned accounts,
// and a pubkey for authentication purposes.
//
// Many complex conditions can be used in the concrete struct which implements AccountI.
type AccountI interface {
	proto.Message

	GetAddress() sdk.AccAddress
	SetAddress(sdk.AccAddress) error // errors if already set.

	GetPubKey() crypto.PubKey // can return nil.
	SetPubKey(crypto.PubKey) error

	GetAccountNumber() uint64
	SetAccountNumber(uint64) error

	GetSequence() uint64
	SetSequence(uint64) error

	// Ensure that account implements stringer
	String() string
}

Base Account

基础账户(Base Account)是最简单和最常见的账户类型,它直接在结构体中存储所有必要的字段。

// BaseAccount defines a base account type. It contains all the necessary fields
// for basic account functionality. Any custom account type should extend this
// type for additional functionality (e.g. vesting).
message BaseAccount {
  string address = 1;
  google.protobuf.Any pub_key = 2;
  uint64 account_number = 3;
  uint64 sequence       = 4;
}

Vesting Account

请查阅 Vesting.

AnteHandlers

x/auth 模块目前没有自己的交易处理程序,但暴露了特殊的 AnteHandler,用于对交易执行基本的有效性检查,以便将无效交易从内存池中丢弃。AnteHandler 可以被视为一组装饰器,在当前上下文中检查交易,依据的是 ADR 010

需要注意的是,AnteHandler 会在 CheckTxDeliverTx 阶段都被调用,因为目前 CometBFT 提议者可以在其提议的区块中包含那些在 CheckTx 阶段失败的交易。

装饰器(Decorators)

auth 模块提供了多个 AnteDecorators,它们递归地链式连接成一个单一的 AnteHandler,按以下顺序执行:

  1. SetUpContextDecorator 设置 Context 中的 GasMeter,并使用 defer 子句包装下一个 AnteHandler,以便从任何下游的 OutOfGas panic 中恢复,返回包含提供的气体和已用气体信息的错误。

  2. RejectExtensionOptionsDecorator 拒绝所有可能包含在 protobuf 交易中的扩展选项。

  3. MempoolFeeDecoratorCheckTx 阶段检查交易费用是否高于本地内存池的 minFee 参数。

  4. ValidateBasicDecorator 调用 tx.ValidateBasic,并返回任何非空的错误。

  5. TxTimeoutHeightDecorator 检查交易的时间戳是否超时。

  6. ValidateMemoDecorator 根据应用程序参数验证交易备注,并返回任何非空的错误。

  7. ConsumeGasTxSizeDecorator 根据应用程序参数消耗与交易大小成比例的气体。

  8. DeductFeeDecorator 从交易的第一个签署者扣除费用。如果启用了 x/feegrant 模块并设置了费用授予者,则费用将从费用授予者账户中扣除。

  9. SetPubKeyDecorator 从交易的签署者中设置公钥,这些签署者的公钥尚未保存在状态机和当前上下文中。

  10. ValidateSigCountDecorator 根据应用程序参数验证交易中签名的数量。

  11. SigGasConsumeDecorator 根据每个签名消耗预定义的气体。此操作要求在 SetPubKeyDecorator 中为所有签署者在上下文中设置公钥。

  12. SigVerificationDecorator 验证所有签名是否有效。此操作要求在 SetPubKeyDecorator 中为所有签署者在上下文中设置公钥。

  13. IncrementSequenceDecorator 增加每个签署者的账户序列号,以防止重放攻击。

Keepers

auth模块仅暴露一个keeper,account keeper,可用于读取和写入账户。

Account Keeper

目前仅暴露一个完全权限的account keeper,该keeper具有读取和写入所有账户所有字段的能力,并能够遍历所有存储的账户。

// AccountKeeperI is the interface contract that x/auth's keeper implements.
type AccountKeeperI interface {
	// Return a new account with the next account number and the specified address. Does not save the new account to the store.
	NewAccountWithAddress(sdk.Context, sdk.AccAddress) types.AccountI

	// Return a new account with the next account number. Does not save the new account to the store.
	NewAccount(sdk.Context, types.AccountI) types.AccountI

	// Check if an account exists in the store.
	HasAccount(sdk.Context, sdk.AccAddress) bool

	// Retrieve an account from the store.
	GetAccount(sdk.Context, sdk.AccAddress) types.AccountI

	// Set an account in the store.
	SetAccount(sdk.Context, types.AccountI)

	// Remove an account from the store.
	RemoveAccount(sdk.Context, types.AccountI)

	// Iterate over all accounts, calling the provided function. Stop iteration when it returns true.
	IterateAccounts(sdk.Context, func(types.AccountI) bool)

	// Fetch the public key of an account at a specified address
	GetPubKey(sdk.Context, sdk.AccAddress) (crypto.PubKey, error)

	// Fetch the sequence of an account at a specified address.
	GetSequence(sdk.Context, sdk.AccAddress) (uint64, error)

	// Fetch the next account number, and increment the internal counter.
	NextAccountNumber(sdk.Context) uint64
}

参数

auth模块包含以下参数:

类型
示例

MaxMemoCharacters

uint64

256

TxSigLimit

uint64

7

TxSizeCostPerByte

uint64

10

SigVerifyCostED25519

uint64

590

SigVerifyCostSecp256k1

uint64

1000

Client

CLI

用户可以使用CLI查询和与auth模块交互。

Query

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

simd query auth --help

account

account命令允许用户通过地址查询账户。

simd query auth account [address] [flags]

示例:

simd query auth account cosmos1...

示例输出:

'@type': /cosmos.auth.v1beta1.BaseAccount
account_number: "0"
address: cosmos1zwg6tpl8aw4rawv8sgag9086lpw5hv33u5ctr2
pub_key:
  '@type': /cosmos.crypto.secp256k1.PubKey
  key: ApDrE38zZdd7wLmFS9YmqO684y5DG6fjZ4rVeihF/AQD
sequence: "1"

accounts

accounts命令允许用户查询所有可用的账户。

simd query auth accounts [flags]

示例:

simd query auth accounts

示例输出:

accounts:
- '@type': /cosmos.auth.v1beta1.BaseAccount
  account_number: "0"
  address: cosmos1zwg6tpl8aw4rawv8sgag9086lpw5hv33u5ctr2
  pub_key:
    '@type': /cosmos.crypto.secp256k1.PubKey
    key: ApDrE38zZdd7wLmFS9YmqO684y5DG6fjZ4rVeihF/AQD
  sequence: "1"
- '@type': /cosmos.auth.v1beta1.ModuleAccount
  base_account:
    account_number: "8"
    address: cosmos1yl6hdjhmkf37639730gffanpzndzdpmhwlkfhr
    pub_key: null
    sequence: "0"
  name: transfer
  permissions:
  - minter
  - burner
- '@type': /cosmos.auth.v1beta1.ModuleAccount
  base_account:
    account_number: "4"
    address: cosmos1fl48vsnmsdzcv85q5d2q4z5ajdha8yu34mf0eh
    pub_key: null
    sequence: "0"
  name: bonded_tokens_pool
  permissions:
  - burner
  - staking
- '@type': /cosmos.auth.v1beta1.ModuleAccount
  base_account:
    account_number: "5"
    address: cosmos1tygms3xhhs3yv487phx3dw4a95jn7t7lpm470r
    pub_key: null
    sequence: "0"
  name: not_bonded_tokens_pool
  permissions:
  - burner
  - staking
- '@type': /cosmos.auth.v1beta1.ModuleAccount
  base_account:
    account_number: "6"
    address: cosmos10d07y265gmmuvt4z0w9aw880jnsr700j6zn9kn
    pub_key: null
    sequence: "0"
  name: gov
  permissions:
  - burner
- '@type': /cosmos.auth.v1beta1.ModuleAccount
  base_account:
    account_number: "3"
    address: cosmos1jv65s3grqf6v6jl3dp4t6c9t9rk99cd88lyufl
    pub_key: null
    sequence: "0"
  name: distribution
  permissions: []
- '@type': /cosmos.auth.v1beta1.BaseAccount
  account_number: "1"
  address: cosmos147k3r7v2tvwqhcmaxcfql7j8rmkrlsemxshd3j
  pub_key: null
  sequence: "0"
- '@type': /cosmos.auth.v1beta1.ModuleAccount
  base_account:
    account_number: "7"
    address: cosmos1m3h30wlvsf8llruxtpukdvsy0km2kum8g38c8q
    pub_key: null
    sequence: "0"
  name: mint
  permissions:
  - minter
- '@type': /cosmos.auth.v1beta1.ModuleAccount
  base_account:
    account_number: "2"
    address: cosmos17xpfvakm2amg962yls6f84z3kell8c5lserqta
    pub_key: null
    sequence: "0"
  name: fee_collector
  permissions: []
pagination:
  next_key: null
  total: "0"

params

params命令允许用户查询当前的auth参数。

simd query auth params [flags]

示例:

simd query auth params

示例输出:

max_memo_characters: "256"
sig_verify_cost_ed25519: "590"
sig_verify_cost_secp256k1: "1000"
tx_sig_limit: "7"
tx_size_cost_per_byte: "10"

Transactions

auth模块支持交易命令,帮助您进行签名等操作。与其他模块相比,您可以直接使用tx命令访问auth模块的交易命令。 直接使用--help标志获取关于tx命令的更多信息。

simd tx --help

sign

sign命令允许用户签署离线生成的交易。

simd tx sign tx.json --from $ALICE > tx.signed.json

结果是一个已签名的交易,可以通过broadcast命令广播到网络。 有关sign命令的更多信息,请运行simd tx sign --help.

sign-batch

sign-batch命令允许用户签署多个离线生成的交易。这些交易可以在一个文件中,每行一个交易,或者在多个文件中。

simd tx sign txs.json --from $ALICE > tx.signed.json

或者

simd tx sign tx1.json tx2.json tx3.json --from $ALICE > tx.signed.json

结果是多个已签名的交易。要将已签名的交易合并为一个交易,请使用--append标志。 有关sign-batch命令的更多信息,请运行 simd tx sign-batch --help.

multi-sign

multi-sign命令允许用户签署由多签账户离线生成的交易。

simd tx multisign transaction.json k1k2k3 k1sig.json k2sig.json k3sig.json

其中,k1k2k3是多签账户地址,k1sig.json是第一个签署者的签名,k2sig.json是第二个签署者的签名,k3sig.json是第三个签署者的签名。

嵌套多签交易

为了允许由嵌套多签账户签署交易,即多签账户的参与者可以是另一个多签账户,必须使用--skip-signature-verification标志。

# First aggregate signatures of the multisig participant
simd tx multi-sign transaction.json ms1 ms1p1sig.json ms1p2sig.json --signature-only --skip-signature-verification > ms1sig.json

# Then use the aggregated signatures and the other signatures to sign the final transaction
simd tx multi-sign transaction.json k1ms1 k1sig.json ms1sig.json --skip-signature-verification

其中,ms1是嵌套多签账户地址,ms1p1sig.json是嵌套多签账户的第一个参与者的签名,ms1p2sig.json是嵌套多签账户的第二个参与者的签名,ms1sig.json是嵌套多签账户的聚合签名。 k1ms1是一个由个人签署者和另一个嵌套多签账户(ms1)组成的多签账户,k1sig.json是个人成员的第一个签署者的签名。

有关multi-sign命令的更多信息,请运行simd tx multi-sign --help.

multisign-batch

multisign-batchsign-batch的工作方式相同,但适用于多签账户。不同之处在于,multisign-batch命令要求所有交易都在一个文件中,并且不存在--append标志。

有关multisign-batch命令的更多信息,请运行

validate-signatures

validate-signatures命令允许用户验证已签名交易的签名。

$ simd tx validate-signatures tx.signed.json
Signers:
  0: cosmos1l6vsqhh7rnwsyr2kyz3jjg3qduaz8gwgyl8275

Signatures:
  0: cosmos1l6vsqhh7rnwsyr2kyz3jjg3qduaz8gwgyl8275                      [OK]

有关 validate-signatures 命令的更多信息,请运行以下命令查看帮助文档:

simd tx validate-signatures --help

broadcast

broadcast 命令允许用户将已签名的交易广播到网络。

simd tx broadcast tx.signed.json

有关 broadcast 命令的更多信息,请运行以下命令查看帮助文档:

simd tx broadcast --help

gRPC

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

Account

account 端点允许用户通过地址查询账户。

cosmos.auth.v1beta1.Query/Account

示例:

grpcurl -plaintext \
    -d '{"address":"cosmos1.."}' \
    localhost:9090 \
    cosmos.auth.v1beta1.Query/Account

示例输出:

{
  "account":{
    "@type":"/cosmos.auth.v1beta1.BaseAccount",
    "address":"cosmos1zwg6tpl8aw4rawv8sgag9086lpw5hv33u5ctr2",
    "pubKey":{
      "@type":"/cosmos.crypto.secp256k1.PubKey",
      "key":"ApDrE38zZdd7wLmFS9YmqO684y5DG6fjZ4rVeihF/AQD"
    },
    "sequence":"1"
  }
}

Accounts

accounts 端点允许用户查询所有可用账户。

cosmos.auth.v1beta1.Query/Accounts

示例:

grpcurl -plaintext \
    localhost:9090 \
    cosmos.auth.v1beta1.Query/Accounts

示例输出:

{
   "accounts":[
      {
         "@type":"/cosmos.auth.v1beta1.BaseAccount",
         "address":"cosmos1zwg6tpl8aw4rawv8sgag9086lpw5hv33u5ctr2",
         "pubKey":{
            "@type":"/cosmos.crypto.secp256k1.PubKey",
            "key":"ApDrE38zZdd7wLmFS9YmqO684y5DG6fjZ4rVeihF/AQD"
         },
         "sequence":"1"
      },
      {
         "@type":"/cosmos.auth.v1beta1.ModuleAccount",
         "baseAccount":{
            "address":"cosmos1yl6hdjhmkf37639730gffanpzndzdpmhwlkfhr",
            "accountNumber":"8"
         },
         "name":"transfer",
         "permissions":[
            "minter",
            "burner"
         ]
      },
      {
         "@type":"/cosmos.auth.v1beta1.ModuleAccount",
         "baseAccount":{
            "address":"cosmos1fl48vsnmsdzcv85q5d2q4z5ajdha8yu34mf0eh",
            "accountNumber":"4"
         },
         "name":"bonded_tokens_pool",
         "permissions":[
            "burner",
            "staking"
         ]
      },
      {
         "@type":"/cosmos.auth.v1beta1.ModuleAccount",
         "baseAccount":{
            "address":"cosmos1tygms3xhhs3yv487phx3dw4a95jn7t7lpm470r",
            "accountNumber":"5"
         },
         "name":"not_bonded_tokens_pool",
         "permissions":[
            "burner",
            "staking"
         ]
      },
      {
         "@type":"/cosmos.auth.v1beta1.ModuleAccount",
         "baseAccount":{
            "address":"cosmos10d07y265gmmuvt4z0w9aw880jnsr700j6zn9kn",
            "accountNumber":"6"
         },
         "name":"gov",
         "permissions":[
            "burner"
         ]
      },
      {
         "@type":"/cosmos.auth.v1beta1.ModuleAccount",
         "baseAccount":{
            "address":"cosmos1jv65s3grqf6v6jl3dp4t6c9t9rk99cd88lyufl",
            "accountNumber":"3"
         },
         "name":"distribution"
      },
      {
         "@type":"/cosmos.auth.v1beta1.BaseAccount",
         "accountNumber":"1",
         "address":"cosmos147k3r7v2tvwqhcmaxcfql7j8rmkrlsemxshd3j"
      },
      {
         "@type":"/cosmos.auth.v1beta1.ModuleAccount",
         "baseAccount":{
            "address":"cosmos1m3h30wlvsf8llruxtpukdvsy0km2kum8g38c8q",
            "accountNumber":"7"
         },
         "name":"mint",
         "permissions":[
            "minter"
         ]
      },
      {
         "@type":"/cosmos.auth.v1beta1.ModuleAccount",
         "baseAccount":{
            "address":"cosmos17xpfvakm2amg962yls6f84z3kell8c5lserqta",
            "accountNumber":"2"
         },
         "name":"fee_collector"
      }
   ],
   "pagination":{
      "total":"9"
   }
}

Params

params 端点允许用户查询当前的 auth 参数。

cosmos.auth.v1beta1.Query/Params

示例:

grpcurl -plaintext \
    localhost:9090 \
    cosmos.auth.v1beta1.Query/Params

示例输出:

{
  "params": {
    "maxMemoCharacters": "256",
    "txSigLimit": "7",
    "txSizeCostPerByte": "10",
    "sigVerifyCostEd25519": "590",
    "sigVerifyCostSecp256k1": "1000"
  }
}

REST

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

Account

account 端点允许用户通过地址查询账户。

/cosmos/auth/v1beta1/account?address={address}

Accounts

accounts 端点允许用户查询所有可用的账户。

/cosmos/auth/v1beta1/accounts

Params

params 端点允许用户查询当前的 auth 参数。

/cosmos/auth/v1beta1/params

Last updated