cosmos-sdk/docs/cn/basics/accounts.md

10 KiB
Raw Blame History

原文路径:https://github.com/cosmos/cosmos-sdk/blob/master/docs/basics/accounts.md

账户系统

必备阅读 {hide}

账户定义

在 Cosmos SDK 中,一个账户是指定的一个公私钥对。公钥可以用于派生出 AddressesAddresses 可以在程序里面的各个模块间区分不同的用户。Addresses 同样可以和消息进行关联用于确定发消息的账户。私钥一般用于生成签名来证明一个消息是被一个 Addresses(和私钥关联的Addresses) 所发送。

Cosmos SDK 使用一套称之为 BIP32 的标准来生成公私钥。这个标准定义了怎么去创建一个 HD 钱包(钱包就是一批账户的集合)。每一个账户的核心,都有一个种子,每一个种子都有一个 12 或 24 个字的助记符。使用这个助记符,使用一种单向的加密方法可以派生出任意数量的私钥。公钥可以通过私钥推导出来。当然,助记符是最敏感的信息,因为可以不停通过助记符来重新生成私钥。

     Account 0                         Account 1                         Account 2

+------------------+              +------------------+               +------------------+
|                  |              |                  |               |                  |
|    Address 0     |              |    Address 1     |               |    Address 2     |
|        ^         |              |        ^         |               |        ^         |
|        |         |              |        |         |               |        |         |
|        |         |              |        |         |               |        |         |
|        |         |              |        |         |               |        |         |
|        +         |              |        +         |               |        +         |
|  Public key 0    |              |  Public key 1    |               |  Public key 2    |
|        ^         |              |        ^         |               |        ^         |
|        |         |              |        |         |               |        |         |
|        |         |              |        |         |               |        |         |
|        |         |              |        |         |               |        |         |
|        +         |              |        +         |               |        +         |
|  Private key 0   |              |  Private key 1   |               |  Private key 2   |
|        ^         |              |        ^         |               |        ^         |
+------------------+              +------------------+               +------------------+
         |                                 |                                  |
         |                                 |                                  |
         |                                 |                                  |
         +--------------------------------------------------------------------+
                                           |
                                           |
                                 +---------+---------+
                                 |                   |
                                 |  Master PrivKey   |
                                 |                   |
                                 +-------------------+
                                           |
                                           |
                                 +---------+---------+
                                 |                   |
                                 |  Mnemonic (Seed)  |
                                 |                   |
                                 +-------------------+

在 Cosmos SDK 中,账户可以在 Keybase 中作为一个对象来储存和管理。

Keybase

Keybase 是储存和管理账户的对象,在 Cosmos SDK 中,Keybase 要实现以下接口

+++ 7d7821b9af/crypto/keys/types.go (L13-L86)

在 Cosmos SDK 中,Keybase 接口的默认实现对象是 dbKeybase

+++ 7d7821b9af/crypto/keys/keybase.go

dbKeybase 上面对 Keybase 接口中方法实现的笔记:

  • Sign(name, passphrase string, msg []byte) ([]byte, crypto.PubKey, error)message 字节进行签名。需要做一些准备工作将 message 编码成 []byte 类型,可以参考 auth 模块 message 准备的例子。注意SDK 上面没有实现签名的验证,签名验证被推迟到anteHandler中进行

+++ 7d7821b9af/x/auth/types/txbuilder.go (L176-L209)

  • CreateMnemonic(name string, language Language, passwd string, algo SigningAlgo) (info Info, seed string, err error)创建一个新的助记符并打印在日志里,但是并不保存在磁盘上
  • CreateAccount(name, mnemonic, bip39Passwd, encryptPasswd string, account uint32, index uint32) (Info, error) 基于bip44 path创建一个新的账户并将其保存在磁盘上。注意私钥在保存前用密码加密,永远不会储存未加密的私钥.在这个方法的上下文中, accountaddress 参数指的是 BIP44 派生路径的段(例如0, 1, 2, ...)用于从助记符派生出私钥和公钥(注意:给相同的助记符和 account 将派生出相同的私钥,给相同的 accountaddress 也会派生出相同的公钥和 Address)。最后注意 CreateAccount 方法使用在 Tendermint library 中的 secp256k1 派生出公私钥和 Address。总之,这个方法是用来创建用户的钥匙和地址的,并不是共识秘钥,参见Addresses 获取更多信息

dbKeybase 的实现是最基本的,并没有根据需求提供锁定功能。锁定功能指如果一个dbKeybase实例被创建,底层的db就被锁定意味着除了实例化它的程序其他程序无法访问它。这就是 SDK 程序使用另外一套 Keybase 接口的实现 lazyKeybase 的原因

+++ 7d7821b9af/crypto/keys/lazy_keybase.go

lazyKeybasedbKeybase 的一个简单包装,它仅在要执行操作时锁定数据库,并在之后立即将其解锁。使用 lazyKeybase命令行界面 可以在 rest server运行时创建新的账户,它也可以同时传递多个 CLI 命令

地址和公钥

AddressesPubKey 在程序里面都是标识一个参与者的公共信息。Cosmos SDK 默认提供 3 种类型的 AddressesPubKey

  • 基于用户的 AddressesPubKey,用于指定用户(例如 message 的发送者)。它们通过 secp256k1 曲线推导出来
  • 基于验证节点的 AddressesPubKey 用于指定验证者的操作员,它们通过 secp256k1 曲线推导出来
  • 基于共识节点的 AddressesPubKey 用于指定参与共识的验证着节点,它们通过 ed25519 曲线推导出来
Address bech32 Prefix Pubkey bech32 Prefix Curve Address byte length Pubkey byte length
Accounts cosmos cosmospub secp256k1 20 33
Validator Operator cosmosvaloper cosmosvaloperpub secp256k1 20 33
Consensus Nodes cosmosvalcons cosmosvalconspub ed25519 20 32

公钥

在 Cosmos SDK 里面 PubKey 遵循在 tendermint 的 crypto 包中定义的 Pubkey 接口

+++ bc572217c0/crypto/crypto.go (L22-L27)

对于 secp256k1 类型的秘钥,具体的实现可以在这里找到。对于ed25519类型的密钥,具体实现可以在这里找到。

请注意,在 Cosmos SDK 中,Pubkeys 并非以其原始格式进行操作。它使用 Aminobech32 进行 2 次编码。在 SDK 里面,Pubkeys 首先调用 Bytes() 方法在原始的 Pubkey 中(这里面提供 amino 编码),然后使用 bech32ConvertAndEncode 方法

+++ 7d7821b9af/types/address.go (L579-L729)

地址

在 Cosmos SDK 默认提送 3 种类型的地址

  • AccAddress 用于账户
  • ValAddress 用于验证者操作员
  • ConsAddress 用于验证者节点

这些地址类型都是一种长度为 20 的十六进制编码的 []byte 数组的别名,这里有一种标准方法从Pubkey pub中获取到地址aa.

aa := sdk.AccAddress(pub.Address().Bytes())

这些地址实现了 Address 接口

+++ 7d7821b9af/types/address.go (L71-L80)

值得注意的是,Marhsal()Bytes() 方法都返回相同的 []byte 类型的地址,根据 protobuf 的兼容性要求我们需要前者。同样,String() 也被用来返回 bech32 编码类型的地址,这个应该是用户看到的最终编码形式。下面是一个例子:

+++ 7d7821b9af/types/address.go (L229-L243)

接下来 {hide}

学习gas and fees {hide}