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

9.9 KiB
Raw Blame History

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

账户系统

必备阅读 {hide}

账户定义

在Cosmos SDK中,一个账户是指定的一个公私钥对.公钥可以用于派生出Addresses,Addresses可以在程序里面的各个模块间区分不同的用户.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类型的地址,根据protobuff的兼容性要求我们需要前者.同样,String()也被用来返回bech32编码类型的地址,这个应该是用户看到的最终编码形式.下面是一个例子:

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

接下来 {hide}

学习gas and fees {hide}