From d7552b7ac478b642d45607ab68750f2add18b16f Mon Sep 17 00:00:00 2001 From: Robert Zaremba Date: Thu, 11 Mar 2021 19:11:55 +0100 Subject: [PATCH 01/11] Update docs for things related to secp256r1 --- docs/architecture/adr-020-protobuf-transaction-encoding.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/architecture/adr-020-protobuf-transaction-encoding.md b/docs/architecture/adr-020-protobuf-transaction-encoding.md index 062dac13eb2b..9e6085444242 100644 --- a/docs/architecture/adr-020-protobuf-transaction-encoding.md +++ b/docs/architecture/adr-020-protobuf-transaction-encoding.md @@ -289,7 +289,7 @@ and `FileDescriptor`s and returns a boolean result. Public keys in the Cosmos SDK implement the `cryptotypes.PubKey` interface. We propose to use `Any` for protobuf encoding as we are doing with other interfaces (e.g. in `BaseAccount` `PubKey` or `SignerInfo` `PublicKey`). -Following public keys are implemented: secp256k1, ed25519 and multisignature. +Following public keys are implemented: secp256k1, secp256r1, ed25519 and multisignature. Ex: From bde9beb549640b77668f8afc097395c2a32b949a Mon Sep 17 00:00:00 2001 From: Robert Zaremba Date: Wed, 17 Mar 2021 00:07:37 +0100 Subject: [PATCH 02/11] docs: update accounts and pubkey documentation --- docs/basics/accounts.md | 102 +++++++++++++++++++++++----------------- 1 file changed, 58 insertions(+), 44 deletions(-) diff --git a/docs/basics/accounts.md b/docs/basics/accounts.md index 756545af4aad..d6dcd501d421 100644 --- a/docs/basics/accounts.md +++ b/docs/basics/accounts.md @@ -14,7 +14,7 @@ This document describes the in-built accounts system of the Cosmos SDK. {synopsi In the Cosmos SDK, an _account_ designates a pair of _public key_ `PubKey` and _private key_ `PrivKey`. The `PubKey` can be derived to generate various `Addresses`, which are used to identify users (among other parties) in the application. `Addresses` are also associated with [`message`s](../building-modules/messages-and-queries.md#messages) to identify the sender of the `message`. The `PrivKey` is used to generate [digital signatures](#signatures) to prove that an `Address` associated with the `PrivKey` approved of a given `message`. -To derive `PubKey`s and `PrivKey`s, the Cosmos SDK uses a standard called [BIP32](https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki). This standard defines how to build an HD wallet, where a wallet is a set of accounts. At the core of every account, there is a seed, which takes the form of a 12 or 24-words mnemonic. From this mnemonic, it is possible to derive any number of `PrivKey`s using one-way cryptographic function. Then, a `PubKey` can be derived from the `PrivKey`. Naturally, the mnemonic is the most sensitive information, as private keys can always be re-generated if the mnemonic is preserved. +For HD key derivation the Cosmos SDK uses a standard called [BIP32](https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki). This allows to create a HD wallet - a set of accounts derived from an initial secret seed. A seed is usually created form of a 12 or 24-words mnemonic. This single seed allows to derive any number of `PrivKey`s using one-way cryptographic function. Then, a `PubKey` can be derived from the `PrivKey`. Naturally, the mnemonic is the most sensitive information, as private keys can always be re-generated if the mnemonic is preserved. ``` Account 0 Account 1 Account 2 @@ -56,80 +56,94 @@ To derive `PubKey`s and `PrivKey`s, the Cosmos SDK uses a standard called [BIP32 +-------------------+ ``` -In the Cosmos SDK, accounts are stored and managed via an object called a [`Keyring`](#keyring). +In the Cosmos SDK, keys are stored and managed via an object called a [`Keyring`](#keyring). -## Keyring -A `Keyring` is an object that stores and manages accounts. In the Cosmos SDK, a `Keyring` implementation follows the `Keyring` interface: +## Keys, accounts, addresses and signatures -+++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0-rc3/crypto/keyring/keyring.go#L50-L88 +The principal way of authenticating a user is done through a [digital signatures](https://en.wikipedia.org/wiki/Digital_signature). User is signing transactions using his/her private key. Signature verification is done with the associated public key. For the on-chain signature verification purpose we store public key in an `Account` object (alongside other data required for a proper transaction validation). -The default implementation of `Keyring` comes from the third-party [`99designs/keyring`](https://github.com/99designs/keyring) library. +Currently, the SDK supports the following digital key schemes for creating digital signatures: -A few notes on the `Keyring` methods: +- `secp256k1`, as implemented in the [SDK's `crypto/keys/secp256k1` package](https://github.com/cosmos/cosmos-sdk/blob/v0.42.1/crypto/keys/secp256k1/secp256k1.go). +- `secp256r1`, as implemented in the [SDK's `crypto/keys/secp256r1` package](https://github.com/cosmos/cosmos-sdk/blob/master/crypto/keys/secp256r1/pubkey.go), +- `tm-ed25519`, as implemented in the [SDK's `crypto/keys/ed25519` package](https://github.com/cosmos/cosmos-sdk/blob/v0.42.1/crypto/keys/ed25519/ed25519.go). This scheme is only supported for the consensus validation, not user transaction. -- `Sign(uid string, payload []byte) ([]byte, tmcrypto.PubKey, error)` strictly deals with the signature of the `payload` bytes. Some preliminary work should be done beforehand to prepare and encode the transaction into a canonical `[]byte` form. Protobuf being not deterministic, it has been decided in [ADR-020](../architecture/adr-020-protobuf-transaction-encoding.md) that the canonical `payload` to sign is the `SignDoc` struct, deterministically encoded using [ADR-027](adr-027-deterministic-protobuf-serialization.md). Note that signature verification is not implemented in the SDK by default, it is deferred to the [`anteHandler`](../core/baseapp.md#antehandler). - +++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0-rc3/proto/cosmos/tx/v1beta1/tx.proto#L47-L64 +| | Address length in bytes | public key length in bytes | Used for transaction authentication | Used for consensus (tendermint) | +|--------------+-------------------------+----------------------------+-------------------------------------+---------------------------------| +| `secp256k1` | 20 | 33 | yes | no | +| `secp256k1` | 32 | 33 | yes | no | +| `tm-ed25519` | -- not used -- | 32 | no | yes | -- `NewAccount(uid, mnemonic, bip39Passwd, hdPath string, algo SignatureAlgo) (Info, error)` creates a new account based on the [`bip44 path`](https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki) and persists it on disk (note that the `PrivKey` is [encrypted with a passphrase before being persisted](https://github.com/cosmos/cosmos-sdk/blob/v0.40.0-rc3/crypto/armor.go), it is **never stored unencrypted**). In the context of this method, the `account` and `address` parameters refer to the segment of the BIP44 derivation path (e.g. `0`, `1`, `2`, ...) used to derive the `PrivKey` and `PubKey` from the mnemonic (note that given the same mnemonic and `account`, the same `PrivKey` will be generated, and given the same `account` and `address`, the same `PubKey` and `Address` will be generated). Finally, note that the `NewAccount` method derives keys and addresses using the algorithm specified in the last argument `algo`. Currently, the SDK supports two public key algorithms: - - `secp256k1`, as implemented in the [SDK's `crypto/keys/secp256k1` package](https://github.com/cosmos/cosmos-sdk/blob/v0.40.0-rc3/crypto/keys/secp256k1/secp256k1.go), - - `ed25519`, as implemented in the [SDK's `crypto/keys/ed25519` package](https://github.com/cosmos/cosmos-sdk/blob/v0.40.0-rc3/crypto/keys/ed25519/ed25519.go). +## Addresses -- `ExportPrivKeyArmor(uid, encryptPassphrase string) (armor string, err error)` exports a private key in ASCII-armored encrypted format, using the given passphrase. You can then either import it again into the keyring using the `ImportPrivKey(uid, armor, passphrase string)` function, or decrypt it into a raw private key using the `UnarmorDecryptPrivKey(armorStr string, passphrase string)` function. +`Addresses` and `PubKey`s are both public information that identify actors in the application. As we noted above, `Account` is used to store authentication information. The basic account implementation is provided by a `BaseAccount` object. + +Each account is identified using `Address` - a sequence of bytes derived from a public key. Moreover, in SDK, we define 3 types of addresses, which specify a context where an account is used: -Also see the [`Addresses`](#addresses) section for more information. +- `AccAddress` is used to identify users (e.g. the sender of a `message`). +- `ValAddress` is used to identify validator operators. +- `ConsAddress` is used to identify validator nodes participating in consensus. They are derived using the **`ed25519`** curve. -## Addresses and PubKeys +These types implement the `Address` interface: -`Addresses` and `PubKey`s are both public information that identify actors in the application. There are 3 main types of `Addresses`/`PubKeys` available by default in the Cosmos SDK: ++++ https://github.com/cosmos/cosmos-sdk/blob/v0.42.1/types/address.go#L104-L113 -- Addresses and Keys for **accounts**, which identify users (e.g. the sender of a `message`). They are derived using the **`secp256k1`** curve. -- Addresses and Keys for **validator operators**, which identify the operators of validators. They are derived using the **`secp256k1`** curve. -- Addresses and Keys for **consensus nodes**, which identify the validator nodes participating in consensus. They are derived using the **`ed25519`** curve. +Address construction algorithm is defined in [ADR-28](https://github.com/cosmos/cosmos-sdk/blob/master/docs/architecture/adr-028-public-key-addresses.md). +Here is the standard way to obtain an account address from a `pub` public key: -| | 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` | +```go +sdk.AccAddress(pub.Address().Bytes()) +``` -### PubKeys +Of note, the `Marshal()` and `Bytes()` method both return the same raw `[]byte` form of the address, the former being needed for Protobuf compatibility. -`PubKey`s used in the Cosmos SDK are Protobuf messages and have the following methods: +Addresses and public keys are formatted using [bech32](https://en.bitcoin.it/wiki/Bech32) and implemented by the `String` method. This is the only format a user should use when interacting with a blockchain. Bech32 human readable part (bech32 prefix) is used to denote an address type. Example: + ++++ https://github.com/cosmos/cosmos-sdk/blob/v0.42.1/types/address.go#L235-L249 + + +| | Address bech32 Prefix | Pubkey bech32 Prefix | +| ------------------ | --------------------- | -------------------- | +| Accounts | cosmos | cosmospub | +| Validator Operator | cosmosvaloper | cosmosvaloperpub | +| Consensus Nodes | cosmosvalcons | cosmosvalconspub | -+++ https://github.com/cosmos/cosmos-sdk/blob/master/crypto/types/types.go#L8-L17 -- For `secp256k1` keys, the actual implementation can be found [here](https://github.com/cosmos/cosmos-sdk/blob/v0.40.0-rc3/crypto/keys/secp256k1/secp256k1.go). -- For `ed25519` keys, it can be found [here](https://github.com/cosmos/cosmos-sdk/blob/v0.40.0-rc3/crypto/keys/ed25519/ed25519.go). +### Public Keys -In both case, the actual key (as raw bytes) is the compressed form of the pubkey. The first byte is a `0x02` byte if the `y`-coordinate is the lexicographically largest of the two associated with the `x`-coordinate. Otherwise the first byte is a `0x03`. This prefix is followed with the `x`-coordinate. +Public keys in Cosmos SDK are defined by `crypto/PubKey` interface. Since they are saved in a store, it extends the `proto.Message` interface: -Note that in the Cosmos SDK, `Pubkeys` are not manipulated in their raw bytes form. Instead, they are encoded to string using [`Amino`](../core/encoding.md#amino) and [`bech32`](https://en.bitcoin.it/wiki/Bech32). In the SDK, it is done by first calling the `Bytes()` method on the raw `Pubkey` (which applies amino encoding), and then the `ConvertAndEncode` method of `bech32`. ++++ https://github.com/cosmos/cosmos-sdk/blob/master/crypto/types/types.go#L8-L17 + +For `secp256k1` and `secp256r1` serialization, a compressed format is used. The first byte is a `0x02` byte if the `y`-coordinate is the lexicographically largest of the two associated with the `x`-coordinate. Otherwise the first byte is a `0x03`. This prefix is followed with the `x`-coordinate. + +Similarly to `Address`, bech32 is used to format `PubKey` and for all communication with a blockchain: +++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0-rc3/types/address.go#L579-L729 -### Addresses -The Cosmos SDK comes by default with 3 types of addresses: +## Keyring -- `AccAddress` for accounts. -- `ValAddress` for validator operators. -- `ConsAddress` for validator nodes. +A `Keyring` is an object that stores and manages accounts. In the Cosmos SDK, a `Keyring` implementation follows the `Keyring` interface: -Each of these address types are an alias for an hex-encoded `[]byte` array of length 20. Here is the standard way to obtain an address `aa` from a `Pubkey pub`: ++++ https://github.com/cosmos/cosmos-sdk/blob/v0.42.1/crypto/keyring/keyring.go#L51-L92 -```go -aa := sdk.AccAddress(pub.Address().Bytes()) -``` +The default implementation of `Keyring` comes from the third-party [`99designs/keyring`](https://github.com/99designs/keyring) library. + +A few notes on the `Keyring` methods: + +- `Sign(uid string, payload []byte) ([]byte, sdkcrypto.PubKey, error)` strictly deals with the signature of the `payload` bytes. Some preliminary work should be done beforehand to prepare and encode the transaction into a canonical `[]byte` form. Protobuf being not deterministic, it has been decided in [ADR-020](../architecture/adr-020-protobuf-transaction-encoding.md) that the canonical `payload` to sign is the `SignDoc` struct, deterministically encoded using [ADR-027](adr-027-deterministic-protobuf-serialization.md). Note that signature verification is not implemented in the SDK by default, it is deferred to the [`anteHandler`](../core/baseapp.md#antehandler). + +++ https://github.com/cosmos/cosmos-sdk/blob/v0.42.1/proto/cosmos/tx/v1beta1/tx.proto#L47-L64 -These addresses implement the `Address` interface: +- `NewAccount(uid, mnemonic, bip39Passwd, hdPath string, algo SignatureAlgo) (Info, error)` creates a new account based on the [`bip44 path`](https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki) and persists it on disk (note that the `PrivKey` is [encrypted with a passphrase before being persisted](https://github.com/cosmos/cosmos-sdk/blob/v0.40.0-rc3/crypto/armor.go), it is **never stored unencrypted**). In the context of this method, the `account` and `address` parameters refer to the segment of the BIP44 derivation path (e.g. `0`, `1`, `2`, ...) used to derive the `PrivKey` and `PubKey` from the mnemonic (note that given the same mnemonic and `account`, the same `PrivKey` will be generated, and given the same `account` and `address`, the same `PubKey` and `Address` will be generated). Finally, note that the `NewAccount` method derives keys and addresses using the algorithm specified in the last argument `--algo`. The following keys are supported by the keyring: -+++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0-rc3/types/address.go#L76-L85 +- `secp256k1` +- `ed25519` -Of note, the `Marshal()` and `Bytes()` method both return the same raw `[]byte` form of the address, the former being needed for Protobuf compatibility. Also, the `String()` method is used to return the `bech32` encoded form of the address, which should be the only address format with which end-user interract. Here is an example: +- `ExportPrivKeyArmor(uid, encryptPassphrase string) (armor string, err error)` exports a private key in ASCII-armored encrypted format, using the given passphrase. You can then either import it again into the keyring using the `ImportPrivKey(uid, armor, passphrase string)` function, or decrypt it into a raw private key using the `UnarmorDecryptPrivKey(armorStr string, passphrase string)` function. -+++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0-rc3/types/address.go#L235-L249 ## Next {hide} From e6ba6e7b01f46f717abaae39ea993cd7ee6ea1b6 Mon Sep 17 00:00:00 2001 From: Robert Zaremba Date: Wed, 17 Mar 2021 00:16:56 +0100 Subject: [PATCH 03/11] update table formatting --- docs/basics/accounts.md | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/docs/basics/accounts.md b/docs/basics/accounts.md index d6dcd501d421..d2d4903459b0 100644 --- a/docs/basics/accounts.md +++ b/docs/basics/accounts.md @@ -69,11 +69,14 @@ Currently, the SDK supports the following digital key schemes for creating digit - `secp256r1`, as implemented in the [SDK's `crypto/keys/secp256r1` package](https://github.com/cosmos/cosmos-sdk/blob/master/crypto/keys/secp256r1/pubkey.go), - `tm-ed25519`, as implemented in the [SDK's `crypto/keys/ed25519` package](https://github.com/cosmos/cosmos-sdk/blob/v0.42.1/crypto/keys/ed25519/ed25519.go). This scheme is only supported for the consensus validation, not user transaction. -| | Address length in bytes | public key length in bytes | Used for transaction authentication | Used for consensus (tendermint) | -|--------------+-------------------------+----------------------------+-------------------------------------+---------------------------------| -| `secp256k1` | 20 | 33 | yes | no | -| `secp256k1` | 32 | 33 | yes | no | -| `tm-ed25519` | -- not used -- | 32 | no | yes | + +| | Address length | Public key length | Used for transaction | Used for consensus | +| | in bytes | in bytes | authentication | (tendermint) | +|--------------+----------------+-------------------+----------------------+--------------------| +| `secp256k1` | 20 | 33 | yes | no | +| `secp256k1` | 32 | 33 | yes | no | +| `tm-ed25519` | -- not used -- | 32 | no | yes | + ## Addresses From 8e984a90e8cade32e03955388f0bf551486115c0 Mon Sep 17 00:00:00 2001 From: Robert Zaremba Date: Wed, 17 Mar 2021 00:39:46 +0100 Subject: [PATCH 04/11] Apply suggestions from code review Co-authored-by: Alessio Treglia --- docs/architecture/adr-020-protobuf-transaction-encoding.md | 2 +- docs/basics/accounts.md | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/architecture/adr-020-protobuf-transaction-encoding.md b/docs/architecture/adr-020-protobuf-transaction-encoding.md index 9e6085444242..10ffb49da77e 100644 --- a/docs/architecture/adr-020-protobuf-transaction-encoding.md +++ b/docs/architecture/adr-020-protobuf-transaction-encoding.md @@ -289,7 +289,7 @@ and `FileDescriptor`s and returns a boolean result. Public keys in the Cosmos SDK implement the `cryptotypes.PubKey` interface. We propose to use `Any` for protobuf encoding as we are doing with other interfaces (e.g. in `BaseAccount` `PubKey` or `SignerInfo` `PublicKey`). -Following public keys are implemented: secp256k1, secp256r1, ed25519 and multisignature. +The following public keys are implemented: secp256k1, secp256r1, ed25519 and legacy-multisignature. Ex: diff --git a/docs/basics/accounts.md b/docs/basics/accounts.md index d2d4903459b0..02257e46962b 100644 --- a/docs/basics/accounts.md +++ b/docs/basics/accounts.md @@ -14,7 +14,7 @@ This document describes the in-built accounts system of the Cosmos SDK. {synopsi In the Cosmos SDK, an _account_ designates a pair of _public key_ `PubKey` and _private key_ `PrivKey`. The `PubKey` can be derived to generate various `Addresses`, which are used to identify users (among other parties) in the application. `Addresses` are also associated with [`message`s](../building-modules/messages-and-queries.md#messages) to identify the sender of the `message`. The `PrivKey` is used to generate [digital signatures](#signatures) to prove that an `Address` associated with the `PrivKey` approved of a given `message`. -For HD key derivation the Cosmos SDK uses a standard called [BIP32](https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki). This allows to create a HD wallet - a set of accounts derived from an initial secret seed. A seed is usually created form of a 12 or 24-words mnemonic. This single seed allows to derive any number of `PrivKey`s using one-way cryptographic function. Then, a `PubKey` can be derived from the `PrivKey`. Naturally, the mnemonic is the most sensitive information, as private keys can always be re-generated if the mnemonic is preserved. +For HD key derivation the Cosmos SDK uses a standard called [BIP32](https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki). This allows users to create an HD wallet - a set of accounts derived from an initial secret seed. A seed is usually created from a 12- or 24-word mnemonic. This single seed allows one to derive any number of `PrivKey`s using a one-way cryptographic function. Then, a `PubKey` can be derived from the `PrivKey`. Naturally, the mnemonic is the most sensitive information, as private keys can always be re-generated if the mnemonic is preserved. ``` Account 0 Account 1 Account 2 @@ -61,9 +61,9 @@ In the Cosmos SDK, keys are stored and managed via an object called a [`Keyring` ## Keys, accounts, addresses and signatures -The principal way of authenticating a user is done through a [digital signatures](https://en.wikipedia.org/wiki/Digital_signature). User is signing transactions using his/her private key. Signature verification is done with the associated public key. For the on-chain signature verification purpose we store public key in an `Account` object (alongside other data required for a proper transaction validation). +The principal way of authenticating a user is done through [digital signatures](https://en.wikipedia.org/wiki/Digital_signature). Users signs transactions using their own private key. Signature verification is done with the associated public key. For on-chain signature verification purposes, we store the public key in an `Account` object (alongside other data required for a proper transaction validation). -Currently, the SDK supports the following digital key schemes for creating digital signatures: +Currently, the Cosmos SDK supports the following digital key schemes for creating digital signatures: - `secp256k1`, as implemented in the [SDK's `crypto/keys/secp256k1` package](https://github.com/cosmos/cosmos-sdk/blob/v0.42.1/crypto/keys/secp256k1/secp256k1.go). - `secp256r1`, as implemented in the [SDK's `crypto/keys/secp256r1` package](https://github.com/cosmos/cosmos-sdk/blob/master/crypto/keys/secp256r1/pubkey.go), From 4f97b8ba46d045e967c5bca5e2f2fa56975e8410 Mon Sep 17 00:00:00 2001 From: Robert Zaremba Date: Wed, 17 Mar 2021 10:20:52 +0100 Subject: [PATCH 05/11] Apply suggestions from code review Awesome grammar fixes and style improvements Co-authored-by: Barrie Byron --- docs/basics/accounts.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/basics/accounts.md b/docs/basics/accounts.md index 02257e46962b..efcb57dfd285 100644 --- a/docs/basics/accounts.md +++ b/docs/basics/accounts.md @@ -140,12 +140,12 @@ A few notes on the `Keyring` methods: - `Sign(uid string, payload []byte) ([]byte, sdkcrypto.PubKey, error)` strictly deals with the signature of the `payload` bytes. Some preliminary work should be done beforehand to prepare and encode the transaction into a canonical `[]byte` form. Protobuf being not deterministic, it has been decided in [ADR-020](../architecture/adr-020-protobuf-transaction-encoding.md) that the canonical `payload` to sign is the `SignDoc` struct, deterministically encoded using [ADR-027](adr-027-deterministic-protobuf-serialization.md). Note that signature verification is not implemented in the SDK by default, it is deferred to the [`anteHandler`](../core/baseapp.md#antehandler). +++ https://github.com/cosmos/cosmos-sdk/blob/v0.42.1/proto/cosmos/tx/v1beta1/tx.proto#L47-L64 -- `NewAccount(uid, mnemonic, bip39Passwd, hdPath string, algo SignatureAlgo) (Info, error)` creates a new account based on the [`bip44 path`](https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki) and persists it on disk (note that the `PrivKey` is [encrypted with a passphrase before being persisted](https://github.com/cosmos/cosmos-sdk/blob/v0.40.0-rc3/crypto/armor.go), it is **never stored unencrypted**). In the context of this method, the `account` and `address` parameters refer to the segment of the BIP44 derivation path (e.g. `0`, `1`, `2`, ...) used to derive the `PrivKey` and `PubKey` from the mnemonic (note that given the same mnemonic and `account`, the same `PrivKey` will be generated, and given the same `account` and `address`, the same `PubKey` and `Address` will be generated). Finally, note that the `NewAccount` method derives keys and addresses using the algorithm specified in the last argument `--algo`. The following keys are supported by the keyring: +- `NewAccount(uid, mnemonic, bip39Passwd, hdPath string, algo SignatureAlgo) (Info, error)` creates a new account based on the [`bip44 path`](https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki) and persists it on disk. The `PrivKey` is **never stored unencrypted**, instead it is [encrypted with a passphrase](https://github.com/cosmos/cosmos-sdk/blob/v0.40.0-rc3/crypto/armor.go) before being persisted. In the context of this method, the key type and sequence number refer to the segment of the BIP44 derivation path (for example, `0`, `1`, `2`, ...) that is used to derive a private and a public key from the mnemonic. Using the same mnemonic and derivation path, the same `PrivKey`, `PubKey` and `Address` is generated. The following keys are supported by the keyring: - `secp256k1` - `ed25519` -- `ExportPrivKeyArmor(uid, encryptPassphrase string) (armor string, err error)` exports a private key in ASCII-armored encrypted format, using the given passphrase. You can then either import it again into the keyring using the `ImportPrivKey(uid, armor, passphrase string)` function, or decrypt it into a raw private key using the `UnarmorDecryptPrivKey(armorStr string, passphrase string)` function. +- `ExportPrivKeyArmor(uid, encryptPassphrase string) (armor string, err error)` exports a private key in ASCII-armored encrypted format using the given passphrase. You can then either import the private key again into the keyring using the `ImportPrivKey(uid, armor, passphrase string)` function or decrypt it into a raw private key using the `UnarmorDecryptPrivKey(armorStr string, passphrase string)` function. ## Next {hide} From 5ce006a5f08c820c83858d46cee98c818c7541ca Mon Sep 17 00:00:00 2001 From: Robert Zaremba Date: Wed, 17 Mar 2021 10:24:22 +0100 Subject: [PATCH 06/11] Apply suggestions from code review Awesome grammar and style improvements. Co-authored-by: Barrie Byron Co-authored-by: Alessio Treglia --- docs/basics/accounts.md | 32 ++++++++++++++++++-------------- 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/docs/basics/accounts.md b/docs/basics/accounts.md index efcb57dfd285..074d13cdeb67 100644 --- a/docs/basics/accounts.md +++ b/docs/basics/accounts.md @@ -56,18 +56,18 @@ For HD key derivation the Cosmos SDK uses a standard called [BIP32](https://gith +-------------------+ ``` -In the Cosmos SDK, keys are stored and managed via an object called a [`Keyring`](#keyring). +In the Cosmos SDK, keys are stored and managed by using an object called a [`Keyring`](#keyring). -## Keys, accounts, addresses and signatures +## Keys, accounts, addresses, and signatures -The principal way of authenticating a user is done through [digital signatures](https://en.wikipedia.org/wiki/Digital_signature). Users signs transactions using their own private key. Signature verification is done with the associated public key. For on-chain signature verification purposes, we store the public key in an `Account` object (alongside other data required for a proper transaction validation). +The principal way of authenticating a user is done using [digital signatures](https://en.wikipedia.org/wiki/Digital_signature). Users sign transactions using their own private key. Signature verification is done with the associated public key. For on-chain signature verification purposes, we store the public key in an `Account` object (alongside other data required for a proper transaction validation). -Currently, the Cosmos SDK supports the following digital key schemes for creating digital signatures: +The Cosmos SDK supports the following digital key schemes for creating digital signatures: - `secp256k1`, as implemented in the [SDK's `crypto/keys/secp256k1` package](https://github.com/cosmos/cosmos-sdk/blob/v0.42.1/crypto/keys/secp256k1/secp256k1.go). - `secp256r1`, as implemented in the [SDK's `crypto/keys/secp256r1` package](https://github.com/cosmos/cosmos-sdk/blob/master/crypto/keys/secp256r1/pubkey.go), -- `tm-ed25519`, as implemented in the [SDK's `crypto/keys/ed25519` package](https://github.com/cosmos/cosmos-sdk/blob/v0.42.1/crypto/keys/ed25519/ed25519.go). This scheme is only supported for the consensus validation, not user transaction. +- `tm-ed25519`, as implemented in the [SDK `crypto/keys/ed25519` package](https://github.com/cosmos/cosmos-sdk/blob/v0.42.1/crypto/keys/ed25519/ed25519.go). This scheme is supported only for the consensus validation. | | Address length | Public key length | Used for transaction | Used for consensus | @@ -81,13 +81,13 @@ Currently, the Cosmos SDK supports the following digital key schemes for creatin ## Addresses -`Addresses` and `PubKey`s are both public information that identify actors in the application. As we noted above, `Account` is used to store authentication information. The basic account implementation is provided by a `BaseAccount` object. +`Addresses` and `PubKey`s are both public information that identifies actors in the application. `Account` is used to store authentication information. The basic account implementation is provided by a `BaseAccount` object. -Each account is identified using `Address` - a sequence of bytes derived from a public key. Moreover, in SDK, we define 3 types of addresses, which specify a context where an account is used: +Each account is identified using `Address` which is a sequence of bytes derived from a public key. In SDK, we define 3 types of addresses that specify a context where an account is used: -- `AccAddress` is used to identify users (e.g. the sender of a `message`). -- `ValAddress` is used to identify validator operators. -- `ConsAddress` is used to identify validator nodes participating in consensus. They are derived using the **`ed25519`** curve. +- `AccAddress` identifies users (the sender of a `message`). +- `ValAddress` identifies validator operators. +- `ConsAddress` identifies validator nodes that are participating in consensus. Validator nodes are derived using the **`ed25519`** curve. These types implement the `Address` interface: @@ -100,9 +100,9 @@ Here is the standard way to obtain an account address from a `pub` public key: sdk.AccAddress(pub.Address().Bytes()) ``` -Of note, the `Marshal()` and `Bytes()` method both return the same raw `[]byte` form of the address, the former being needed for Protobuf compatibility. +Of note, the `Marshal()` and `Bytes()` method both return the same raw `[]byte` form of the address. `Marshal()` is required for Protobuf compatibility. -Addresses and public keys are formatted using [bech32](https://en.bitcoin.it/wiki/Bech32) and implemented by the `String` method. This is the only format a user should use when interacting with a blockchain. Bech32 human readable part (bech32 prefix) is used to denote an address type. Example: +Addresses and public keys are formatted using [Bech32](https://en.bitcoin.it/wiki/Bech32) and implemented by the `String` method. The Bech32 method is the only supported format to use when interacting with a blockchain. The Bech32 human-readable part (Bech32 prefix) is used to denote an address type. Example: +++ https://github.com/cosmos/cosmos-sdk/blob/v0.42.1/types/address.go#L235-L249 @@ -120,7 +120,11 @@ Public keys in Cosmos SDK are defined by `crypto/PubKey` interface. Since they a +++ https://github.com/cosmos/cosmos-sdk/blob/master/crypto/types/types.go#L8-L17 -For `secp256k1` and `secp256r1` serialization, a compressed format is used. The first byte is a `0x02` byte if the `y`-coordinate is the lexicographically largest of the two associated with the `x`-coordinate. Otherwise the first byte is a `0x03`. This prefix is followed with the `x`-coordinate. +A compressed format is used for `secp256k1` and `secp256r1` serialization. +- The first byte is a `0x02` byte if the `y`-coordinate is the lexicographically largest of the two associated with the `x`-coordinate. +- Otherwise the first byte is a `0x03`. + +This prefix is followed by the `x`-coordinate. Similarly to `Address`, bech32 is used to format `PubKey` and for all communication with a blockchain: @@ -137,7 +141,7 @@ The default implementation of `Keyring` comes from the third-party [`99designs/k A few notes on the `Keyring` methods: -- `Sign(uid string, payload []byte) ([]byte, sdkcrypto.PubKey, error)` strictly deals with the signature of the `payload` bytes. Some preliminary work should be done beforehand to prepare and encode the transaction into a canonical `[]byte` form. Protobuf being not deterministic, it has been decided in [ADR-020](../architecture/adr-020-protobuf-transaction-encoding.md) that the canonical `payload` to sign is the `SignDoc` struct, deterministically encoded using [ADR-027](adr-027-deterministic-protobuf-serialization.md). Note that signature verification is not implemented in the SDK by default, it is deferred to the [`anteHandler`](../core/baseapp.md#antehandler). +- `Sign(uid string, payload []byte) ([]byte, sdkcrypto.PubKey, error)` strictly deals with the signature of the `payload` bytes. You must prepare and encode the transaction into a canonical `[]byte` form. Because protobuf is not deterministic, it has been decided in [ADR-020](../architecture/adr-020-protobuf-transaction-encoding.md) that the canonical `payload` to sign is the `SignDoc` struct, deterministically encoded using [ADR-027](adr-027-deterministic-protobuf-serialization.md). Note that signature verification is not implemented in the SDK by default, it is deferred to the [`anteHandler`](../core/baseapp.md#antehandler). +++ https://github.com/cosmos/cosmos-sdk/blob/v0.42.1/proto/cosmos/tx/v1beta1/tx.proto#L47-L64 - `NewAccount(uid, mnemonic, bip39Passwd, hdPath string, algo SignatureAlgo) (Info, error)` creates a new account based on the [`bip44 path`](https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki) and persists it on disk. The `PrivKey` is **never stored unencrypted**, instead it is [encrypted with a passphrase](https://github.com/cosmos/cosmos-sdk/blob/v0.40.0-rc3/crypto/armor.go) before being persisted. In the context of this method, the key type and sequence number refer to the segment of the BIP44 derivation path (for example, `0`, `1`, `2`, ...) that is used to derive a private and a public key from the mnemonic. Using the same mnemonic and derivation path, the same `PrivKey`, `PubKey` and `Address` is generated. The following keys are supported by the keyring: From ea10e585e640786374796315e4fe7066e51fd782 Mon Sep 17 00:00:00 2001 From: Robert Zaremba Date: Wed, 17 Mar 2021 10:34:52 +0100 Subject: [PATCH 07/11] hd wallet docs update --- docs/basics/accounts.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/basics/accounts.md b/docs/basics/accounts.md index 074d13cdeb67..dd03f1bd3e39 100644 --- a/docs/basics/accounts.md +++ b/docs/basics/accounts.md @@ -14,7 +14,7 @@ This document describes the in-built accounts system of the Cosmos SDK. {synopsi In the Cosmos SDK, an _account_ designates a pair of _public key_ `PubKey` and _private key_ `PrivKey`. The `PubKey` can be derived to generate various `Addresses`, which are used to identify users (among other parties) in the application. `Addresses` are also associated with [`message`s](../building-modules/messages-and-queries.md#messages) to identify the sender of the `message`. The `PrivKey` is used to generate [digital signatures](#signatures) to prove that an `Address` associated with the `PrivKey` approved of a given `message`. -For HD key derivation the Cosmos SDK uses a standard called [BIP32](https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki). This allows users to create an HD wallet - a set of accounts derived from an initial secret seed. A seed is usually created from a 12- or 24-word mnemonic. This single seed allows one to derive any number of `PrivKey`s using a one-way cryptographic function. Then, a `PubKey` can be derived from the `PrivKey`. Naturally, the mnemonic is the most sensitive information, as private keys can always be re-generated if the mnemonic is preserved. +For HD key derivation the Cosmos SDK uses a standard called [BIP32](https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki). The BIP32 allows users to create an HD wallet (as specified in [BIP44(https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki)]) - a set of accounts derived from an initial secret seed. A seed is usually created from a 12- or 24-word mnemonic. A single seed can derive any number of `PrivKey`s using a one-way cryptographic function. Then, a `PubKey` can be derived from the `PrivKey`. Naturally, the mnemonic is the most sensitive information, as private keys can always be re-generated if the mnemonic is preserved. ``` Account 0 Account 1 Account 2 @@ -120,9 +120,9 @@ Public keys in Cosmos SDK are defined by `crypto/PubKey` interface. Since they a +++ https://github.com/cosmos/cosmos-sdk/blob/master/crypto/types/types.go#L8-L17 -A compressed format is used for `secp256k1` and `secp256r1` serialization. -- The first byte is a `0x02` byte if the `y`-coordinate is the lexicographically largest of the two associated with the `x`-coordinate. -- Otherwise the first byte is a `0x03`. +A compressed format is used for `secp256k1` and `secp256r1` serialization. +- The first byte is a `0x02` byte if the `y`-coordinate is the lexicographically largest of the two associated with the `x`-coordinate. +- Otherwise the first byte is a `0x03`. This prefix is followed by the `x`-coordinate. From 72cc038064555887d092e9dff83f24a72a336d2e Mon Sep 17 00:00:00 2001 From: Robert Zaremba Date: Wed, 17 Mar 2021 10:36:26 +0100 Subject: [PATCH 08/11] Apply suggestions from code review Co-authored-by: Barrie Byron --- docs/basics/accounts.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/basics/accounts.md b/docs/basics/accounts.md index dd03f1bd3e39..96485fc87195 100644 --- a/docs/basics/accounts.md +++ b/docs/basics/accounts.md @@ -116,7 +116,7 @@ Addresses and public keys are formatted using [Bech32](https://en.bitcoin.it/wik ### Public Keys -Public keys in Cosmos SDK are defined by `crypto/PubKey` interface. Since they are saved in a store, it extends the `proto.Message` interface: +Public keys in Cosmos SDK are defined by `cryptotypes.PubKey` interface. Since public keys are saved in a store, `cryptotypes.PubKey` extends the `proto.Message` interface: +++ https://github.com/cosmos/cosmos-sdk/blob/master/crypto/types/types.go#L8-L17 @@ -126,7 +126,7 @@ A compressed format is used for `secp256k1` and `secp256r1` serialization. This prefix is followed by the `x`-coordinate. -Similarly to `Address`, bech32 is used to format `PubKey` and for all communication with a blockchain: +Like `Address`, Bech32 is used to format `PubKey` and for all communication with a blockchain: +++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0-rc3/types/address.go#L579-L729 From dbb3367b3ed2e17e9b0cbc3c7cf11446c43f027f Mon Sep 17 00:00:00 2001 From: Alessio Treglia Date: Wed, 17 Mar 2021 12:11:09 +0000 Subject: [PATCH 09/11] Update docs/basics/accounts.md Co-authored-by: Amaury <1293565+amaurym@users.noreply.github.com> --- docs/basics/accounts.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/basics/accounts.md b/docs/basics/accounts.md index 96485fc87195..5df40261ca45 100644 --- a/docs/basics/accounts.md +++ b/docs/basics/accounts.md @@ -74,7 +74,7 @@ The Cosmos SDK supports the following digital key schemes for creating digital s | | in bytes | in bytes | authentication | (tendermint) | |--------------+----------------+-------------------+----------------------+--------------------| | `secp256k1` | 20 | 33 | yes | no | -| `secp256k1` | 32 | 33 | yes | no | +| `secp256r1` | 32 | 33 | yes | no | | `tm-ed25519` | -- not used -- | 32 | no | yes | From 0029b19fd3b0ad26121322ff327fd0f4523a0662 Mon Sep 17 00:00:00 2001 From: Barrie Byron Date: Wed, 17 Mar 2021 09:11:34 -0400 Subject: [PATCH 10/11] Update docs/architecture/adr-020-protobuf-transaction-encoding.md I agree, let's use "and" --- docs/architecture/adr-020-protobuf-transaction-encoding.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/architecture/adr-020-protobuf-transaction-encoding.md b/docs/architecture/adr-020-protobuf-transaction-encoding.md index 10ffb49da77e..dde981f7e9ec 100644 --- a/docs/architecture/adr-020-protobuf-transaction-encoding.md +++ b/docs/architecture/adr-020-protobuf-transaction-encoding.md @@ -288,7 +288,7 @@ and `FileDescriptor`s and returns a boolean result. ### Public Key Encoding Public keys in the Cosmos SDK implement the `cryptotypes.PubKey` interface. -We propose to use `Any` for protobuf encoding as we are doing with other interfaces (e.g. in `BaseAccount` `PubKey` or `SignerInfo` `PublicKey`). +We propose to use `Any` for protobuf encoding as we are doing with other interfaces (for example, in `BaseAccount.PubKey` and `SignerInfo.PublicKey`). The following public keys are implemented: secp256k1, secp256r1, ed25519 and legacy-multisignature. Ex: From 74e995c57ee8ee07a498eede83aa9258fc4defe6 Mon Sep 17 00:00:00 2001 From: Robert Zaremba Date: Wed, 17 Mar 2021 18:27:12 +0100 Subject: [PATCH 11/11] update code snippet links --- docs/basics/accounts.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/basics/accounts.md b/docs/basics/accounts.md index 5df40261ca45..d0ce41b9eded 100644 --- a/docs/basics/accounts.md +++ b/docs/basics/accounts.md @@ -91,7 +91,7 @@ Each account is identified using `Address` which is a sequence of bytes derived These types implement the `Address` interface: -+++ https://github.com/cosmos/cosmos-sdk/blob/v0.42.1/types/address.go#L104-L113 ++++ https://github.com/cosmos/cosmos-sdk/blob/v0.42.1/types/address.go#L71-L90 Address construction algorithm is defined in [ADR-28](https://github.com/cosmos/cosmos-sdk/blob/master/docs/architecture/adr-028-public-key-addresses.md). Here is the standard way to obtain an account address from a `pub` public key: @@ -104,7 +104,7 @@ Of note, the `Marshal()` and `Bytes()` method both return the same raw `[]byte` Addresses and public keys are formatted using [Bech32](https://en.bitcoin.it/wiki/Bech32) and implemented by the `String` method. The Bech32 method is the only supported format to use when interacting with a blockchain. The Bech32 human-readable part (Bech32 prefix) is used to denote an address type. Example: -+++ https://github.com/cosmos/cosmos-sdk/blob/v0.42.1/types/address.go#L235-L249 ++++ https://github.com/cosmos/cosmos-sdk/blob/v0.42.1/types/address.go#L230-L244 | | Address bech32 Prefix | Pubkey bech32 Prefix | @@ -135,7 +135,7 @@ Like `Address`, Bech32 is used to format `PubKey` and for all communication with A `Keyring` is an object that stores and manages accounts. In the Cosmos SDK, a `Keyring` implementation follows the `Keyring` interface: -+++ https://github.com/cosmos/cosmos-sdk/blob/v0.42.1/crypto/keyring/keyring.go#L51-L92 ++++ https://github.com/cosmos/cosmos-sdk/blob/v0.42.1/crypto/keyring/keyring.go#L51-L89 The default implementation of `Keyring` comes from the third-party [`99designs/keyring`](https://github.com/99designs/keyring) library.