merged in master

This commit is contained in:
Sunny Aggarwal 2021-04-06 19:19:59 -04:00
commit 05e2e45010
264 changed files with 8719 additions and 17032 deletions

20
.deepsource.toml Normal file
View File

@ -0,0 +1,20 @@
version = 1
test_patterns = [
"tests/**",
"**_test.go"
]
exclude_patterns = [
"third_party/proto/**",
"testutil/**",
"proto/cosmos/**",
"contrib/**"
]
[[analyzers]]
name = "go"
enabled = true
[analyzers.meta]
import_paths = ["github.com/cosmos/cosmos-sdk"]

View File

@ -24,7 +24,7 @@ jobs:
make build-docs LEDGER_ENABLED=false
- name: Deploy 🚀
uses: JamesIves/github-pages-deploy-action@4.1.0
uses: JamesIves/github-pages-deploy-action@4.1.1
with:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
BRANCH: gh-pages

16
.github/workflows/janitor.yml vendored Normal file
View File

@ -0,0 +1,16 @@
name: Janitor
# Janitor cleans up previous runs of various workflows
# Cancels Sims and Tests
on:
pull_request:
jobs:
cancel:
name: "Cancel Previous Runs"
runs-on: ubuntu-latest
timeout-minutes: 3
steps:
- uses: styfle/cancel-workflow-action@0.8.0
with:
workflow_id: 872925,1013614,1134055
access_token: ${{ github.token }}

View File

@ -23,7 +23,7 @@ jobs:
- uses: golangci/golangci-lint-action@master
with:
# Required: the version of golangci-lint is required and must be specified without patch version: we always use the latest patch version.
version: v1.37
version: v1.39
args: --timeout 10m
github-token: ${{ secrets.github_token }}
if: env.GIT_DIFF

View File

@ -7,14 +7,6 @@ on:
- "rc**"
jobs:
cleanup-runs:
runs-on: ubuntu-latest
steps:
- uses: rokroskar/workflow-run-cleanup-action@master
env:
GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
if: "!startsWith(github.ref, 'refs/tags/') && github.ref != 'refs/heads/master'"
build:
runs-on: ubuntu-latest
if: "!contains(github.event.head_commit.message, 'skip-sims')"

View File

@ -8,14 +8,6 @@ on:
- master
jobs:
cleanup-runs:
runs-on: ubuntu-latest
if: "!startsWith(github.ref, 'refs/tags/') && github.ref != 'refs/heads/master'"
steps:
- uses: rokroskar/workflow-run-cleanup-action@master
env:
GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
build:
runs-on: ubuntu-latest
if: "!contains(github.event.head_commit.message, 'skip-sims')"

View File

@ -7,14 +7,6 @@ on:
branches:
- master
jobs:
cleanup-runs:
runs-on: ubuntu-latest
steps:
- uses: rokroskar/workflow-run-cleanup-action@master
env:
GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
if: "!startsWith(github.ref, 'refs/tags/') && github.ref != 'refs/heads/master'"
install-tparse:
runs-on: ubuntu-latest
steps:
@ -172,7 +164,7 @@ jobs:
sed -i.bak "/$(echo $filename | sed 's/\//\\\//g')/d" coverage.txt
done
if: env.GIT_DIFF
- uses: codecov/codecov-action@v1.3.1
- uses: codecov/codecov-action@v1.3.2
with:
file: ./coverage.txt
if: env.GIT_DIFF

View File

@ -56,6 +56,11 @@ issues:
- text: "ST1016:"
linters:
- stylecheck
- path: "legacy"
text: "SA1019:"
linters:
- staticcheck
max-issues-per-linter: 10000
max-same-issues: 10000

View File

@ -41,14 +41,20 @@ Ref: https://keepachangelog.com/en/1.0.0/
* [\#8559](https://github.com/cosmos/cosmos-sdk/pull/8559) Added Protobuf compatible secp256r1 ECDSA signatures.
* [\#8786](https://github.com/cosmos/cosmos-sdk/pull/8786) Enabled secp256r1 in x/auth.
* (rosetta) [\#8729](https://github.com/cosmos/cosmos-sdk/pull/8729) Data API fully supports balance tracking. Construction API can now construct any message supported by the application.
* [\#8754](https://github.com/cosmos/cosmos-sdk/pull/8875) Added support for reverse iteration to pagination.
### Client Breaking Changes
* [\#8363](https://github.com/cosmos/cosmos-sdk/pull/8363) Addresses no longer have a fixed 20-byte length. From the SDK modules' point of view, any 1-255 bytes-long byte array is a valid address.
* [\#8346](https://github.com/cosmos/cosmos-sdk/pull/8346) All CLI `tx` commands generate ServiceMsgs by default. Graceful Amino support has been added to ServiceMsgs to support signing legacy Msgs.
* (crypto/ed25519) [\#8690] Adopt zip1215 ed2559 verification rules.
* [\#8849](https://github.com/cosmos/cosmos-sdk/pull/8849) Upgrade module no longer supports time based upgrades.
* [\#8849](https://github.com/cosmos/cosmos-sdk/pull/8849) Upgrade module no longer supports time based upgrades.
* [\#8880](https://github.com/cosmos/cosmos-sdk/pull/8880) The CLI `simd migrate v0.40 ...` command has been renamed to `simd migrate v0.42`.
* [\#7477](https://github.com/cosmos/cosmos-sdk/pull/7477) Changed Bech32 Public Key serialization in the client facing functionality (CLI, MsgServer, QueryServer):
* updated the keyring display structure (it uses protobuf JSON serialization) - the output is more verbose.
* Renamed `MarshalAny` and `UnmarshalAny` to `MarshalInterface` and `UnmarshalInterface` respectively. These functions must take an interface as parameter (not a concrete type nor `Any` object). Underneath they use `Any` wrapping for correct protobuf serialization.
* CLI: removed `--text` flag from `show-node-id` command; the text format for public keys is not used any more - instead we use ProtoJSON.
* [\#9026](https://github.com/cosmos/cosmos-sdk/pull/9026) The `tx sign` and `tx sign-batch` CLI commands use SIGN_MODE_DIRECT by default for local pubkeys. For multisigs and ledger keys, the default LEGACY_AMINO_JSON is kept.
### API Breaking Changes
@ -63,7 +69,18 @@ Ref: https://keepachangelog.com/en/1.0.0/
* (x/bank) [\#8517](https://github.com/cosmos/cosmos-sdk/pull/8517) `SupplyI` interface and `Supply` are removed and uses `sdk.Coins` for supply tracking
* (x/upgrade) [\#8743](https://github.com/cosmos/cosmos-sdk/pull/8743) `UpgradeHandler` includes a new argument `VersionMap` which helps facilitate in-place migrations.
* (x/auth) [\#8129](https://github.com/cosmos/cosmos-sdk/pull/8828) Updated `SigVerifiableTx.GetPubKeys` method signature to return error.
* (x/upgrade) [\7487](https://github.com/cosmos/cosmos-sdk/pull/8897) Upgrade `Keeper` takes new argument `ProtocolVersionSetter` which implements setting a protocol version on baseapp.
* (baseapp) [\7487](https://github.com/cosmos/cosmos-sdk/pull/8897) BaseApp's fields appVersion and version were swapped to match Tendermint's fields.
* [\#8682](https://github.com/cosmos/cosmos-sdk/pull/8682) `ante.NewAnteHandler` updated to receive all positional params as `ante.HandlerOptions` struct. If required fields aren't set, throws error accordingly.
* (x/staking/types) [\#7447](https://github.com/cosmos/cosmos-sdk/issues/7447) Remove bech32 PubKey support:
* `ValidatorI` interface update: `GetConsPubKey` renamed to `TmConsPubKey` (this is to clarify the return type: consensus public key must be a tendermint key); `TmConsPubKey`, `GetConsAddr` methods return error.
* `Validator` updated according to the `ValidatorI` changes described above.
* `ToTmValidator` function: added `error` to return values.
* `Validator.ConsensusPubkey` type changed from `string` to `codectypes.Any`.
* `MsgCreateValidator.Pubkey` type changed from `string` to `codectypes.Any`.
* (client) [\#8926](https://github.com/cosmos/cosmos-sdk/pull/8926) `client/tx.PrepareFactory` has been converted to a private function, as it's only used internally.
* (auth/tx) [\#8926](https://github.com/cosmos/cosmos-sdk/pull/8926) The `ProtoTxProvider` interface used as a workaround for transaction simulation has been removed.
* (x/bank) [\#8798](https://github.com/cosmos/cosmos-sdk/pull/8798) `GetTotalSupply` is removed in favour of `GetPaginatedTotalSupply`
### State Machine Breaking
@ -73,23 +90,52 @@ Ref: https://keepachangelog.com/en/1.0.0/
* (x/bank) [\#8656](https://github.com/cosmos/cosmos-sdk/pull/8656) balance and supply are now correctly tracked via `coin_spent`, `coin_received`, `coinbase` and `burn` events.
* (x/bank) [\#8517](https://github.com/cosmos/cosmos-sdk/pull/8517) Supply is now stored and tracked as `sdk.Coins`
* (store) [\#8790](https://github.com/cosmos/cosmos-sdk/pull/8790) Reduce gas costs by 10x for transient store operations.
<<<<<<< HEAD
* (x/staking) [\#8505](https://github.com/cosmos/cosmos-sdk/pull/8505) Convert staking power reduction into an on-chain parameter rather than a hardcoded in-code variable.
=======
* (x/bank) [\#9051](https://github.com/cosmos/cosmos-sdk/pull/9051) Supply value is stored as `sdk.Int` rather than `string`.
>>>>>>> master
### Improvements
* (x/bank) [\#8614](https://github.com/cosmos/cosmos-sdk/issues/8614) Add `Name` and `Symbol` fields to denom metadata
* (x/auth) [\#8522](https://github.com/cosmos/cosmos-sdk/pull/8522) Allow to query all stored accounts
* (crypto/types) [\#8600](https://github.com/cosmos/cosmos-sdk/pull/8600) `CompactBitArray`: optimize the `NumTrueBitsBefore` method and add an `Equal` method.
* (grpc) [\#8815](https://github.com/cosmos/cosmos-sdk/pull/8815) Add orderBy parameter to `TxsByEvents` endpoint.
* (x/upgrade) [\#8743](https://github.com/cosmos/cosmos-sdk/pull/8743) Add tracking module versions as per ADR-041
* (types) [\#8962](https://github.com/cosmos/cosmos-sdk/issues/8962) Add `Abs()` method to `sdk.Int`.
* (x/bank) [\#8950](https://github.com/cosmos/cosmos-sdk/pull/8950) Improve efficiency on supply updates.
* (store) [\#8012](https://github.com/cosmos/cosmos-sdk/pull/8012) Implementation of ADR-038 WriteListener and listen.KVStore
### Bug Fixes
* (gRPC) [\#9015](https://github.com/cosmos/cosmos-sdk/pull/9015) Fix invalid status code when accessing gRPC endpoints.
* (gRPC) [\#8945](https://github.com/cosmos/cosmos-sdk/pull/8945) gRPC reflection now works correctly.
* (keyring) [#\8635](https://github.com/cosmos/cosmos-sdk/issues/8635) Remove hardcoded default passphrase value on `NewMnemonic`
* (x/bank) [\#8434](https://github.com/cosmos/cosmos-sdk/pull/8434) Fix legacy REST API `GET /bank/total` and `GET /bank/total/{denom}` in swagger
* (x/slashing) [\#8427](https://github.com/cosmos/cosmos-sdk/pull/8427) Fix query signing infos command
* (server) [\#8399](https://github.com/cosmos/cosmos-sdk/pull/8399) fix gRPC-web flag default value
* [\#9026](https://github.com/cosmos/cosmos-sdk/pull/9026) Fix bug of `gentx` command not working with ledger keys.
## [v0.42.2](https://github.com/cosmos/cosmos-sdk/releases/tag/v0.42.2) - 2021-03-19
### Improvements
* (grpc) [\#8815](https://github.com/cosmos/cosmos-sdk/pull/8815) Add orderBy parameter to `TxsByEvents` endpoint.
* (cli) [\#8826](https://github.com/cosmos/cosmos-sdk/pull/8826) Add trust to macOS Keychain for caller app by default.
* (store) [\#8811](https://github.com/cosmos/cosmos-sdk/pull/8811) store/cachekv: use typed types/kv.List instead of container/list.List
### Bug Fixes
* (crypto) [\#8841](https://github.com/cosmos/cosmos-sdk/pull/8841) Fix legacy multisig amino marshaling, allowing migrations to work between v0.39 and v0.40+.
* (cli) [\#8873](https://github.com/cosmos/cosmos-sdk/pull/8873) add --output-document to multisign-batch.
## [v0.42.1](https://github.com/cosmos/cosmos-sdk/releases/tag/v0.42.1) - 2021-03-10
This release fixes security vulnerability identified in the simapp.
### Deprecated
* (grpc) [\#8926](https://github.com/cosmos/cosmos-sdk/pull/8926) The `tx` field in `SimulateRequest` has been deprecated, prefer to pass `tx_bytes` instead.
## [v0.42.0](https://github.com/cosmos/cosmos-sdk/releases/tag/v0.42.0) - 2021-03-08
@ -164,6 +210,7 @@ he Cosmos Hub) should not use this release or any release in the v0.41.x series.
* (x/ibc) [\#8266](https://github.com/cosmos/cosmos-sdk/issues/8266) Add amino JSON support for IBC MsgTransfer in order to support Ledger text signing transfer transactions.
* (x/ibc) [\#8404](https://github.com/cosmos/cosmos-sdk/pull/8404) Reorder IBC `ChanOpenAck` and `ChanOpenConfirm` handler execution to perform core handler first, followed by application callbacks.
### Bug Fixes
* (simapp) [\#8418](https://github.com/cosmos/cosmos-sdk/pull/8418) Add balance coin to supply when adding a new genesis account

View File

@ -109,6 +109,8 @@ func (app *BaseApp) Info(req abci.RequestInfo) abci.ResponseInfo {
return abci.ResponseInfo{
Data: app.name,
Version: app.version,
AppVersion: app.appVersion,
LastBlockHeight: lastCommitID.Version,
LastBlockAppHash: lastCommitID.Hash,
}
@ -755,7 +757,7 @@ func handleQueryApp(app *BaseApp, path []string, req abci.RequestQuery) abci.Res
return abci.ResponseQuery{
Codespace: sdkerrors.RootCodespace,
Height: req.Height,
Value: []byte(app.appVersion),
Value: []byte(app.version),
}
default:

View File

@ -117,7 +117,11 @@ type BaseApp struct { // nolint: maligned
minRetainBlocks uint64
// application's version string
appVersion string
version string
// application's protocol version that increments on every upgrade
// if BaseApp is passed to the upgrade keeper's NewKeeper method.
appVersion uint64
// recovery handler for app.runTx method
runTxRecoveryMiddleware recoveryMiddleware
@ -170,11 +174,16 @@ func (app *BaseApp) Name() string {
return app.name
}
// AppVersion returns the application's version string.
func (app *BaseApp) AppVersion() string {
// AppVersion returns the application's protocol version.
func (app *BaseApp) AppVersion() uint64 {
return app.appVersion
}
// Version returns the application's version string.
func (app *BaseApp) Version() string {
return app.version
}
// Logger returns the logger of the BaseApp.
func (app *BaseApp) Logger() log.Logger {
return app.logger

View File

@ -340,21 +340,21 @@ func TestSetLoader(t *testing.T) {
}
}
func TestAppVersionSetterGetter(t *testing.T) {
func TestVersionSetterGetter(t *testing.T) {
logger := defaultLogger()
pruningOpt := SetPruning(store.PruneDefault)
db := dbm.NewMemDB()
name := t.Name()
app := NewBaseApp(name, logger, db, nil, pruningOpt)
require.Equal(t, "", app.AppVersion())
require.Equal(t, "", app.Version())
res := app.Query(abci.RequestQuery{Path: "app/version"})
require.True(t, res.IsOK())
require.Equal(t, "", string(res.Value))
versionString := "1.0.0"
app.SetAppVersion(versionString)
require.Equal(t, versionString, app.AppVersion())
app.SetVersion(versionString)
require.Equal(t, versionString, app.Version())
res = app.Query(abci.RequestQuery{Path: "app/version"})
require.True(t, res.IsOK())
require.Equal(t, versionString, string(res.Value))
@ -498,7 +498,7 @@ func TestInfo(t *testing.T) {
assert.Equal(t, t.Name(), res.GetData())
assert.Equal(t, int64(0), res.LastBlockHeight)
require.Equal(t, []uint8(nil), res.LastBlockAppHash)
require.Equal(t, app.AppVersion(), res.AppVersion)
// ----- test a proper response -------
// TODO
}
@ -510,7 +510,7 @@ func TestBaseAppOptionSeal(t *testing.T) {
app.SetName("")
})
require.Panics(t, func() {
app.SetAppVersion("")
app.SetVersion("")
})
require.Panics(t, func() {
app.SetDB(nil)

View File

@ -95,12 +95,16 @@ func (app *BaseApp) SetParamStore(ps ParamStore) {
app.paramStore = ps
}
// SetAppVersion sets the application's version string.
func (app *BaseApp) SetAppVersion(v string) {
// SetVersion sets the application's version string.
func (app *BaseApp) SetVersion(v string) {
if app.sealed {
panic("SetAppVersion() on sealed BaseApp")
panic("SetVersion() on sealed BaseApp")
}
app.version = v
}
// SetProtocolVersion sets the application's protocol version
func (app *BaseApp) SetProtocolVersion(v uint64) {
app.appVersion = v
}

View File

@ -8,7 +8,6 @@ import (
"github.com/spf13/cobra"
"github.com/spf13/pflag"
"github.com/tendermint/tendermint/libs/cli"
rpchttp "github.com/tendermint/tendermint/rpc/client/http"
"github.com/cosmos/cosmos-sdk/client/flags"
"github.com/cosmos/cosmos-sdk/crypto/keyring"
@ -94,11 +93,6 @@ func ReadPersistentCommandFlags(clientCtx Context, flagSet *pflag.FlagSet) (Cont
clientCtx = clientCtx.WithOutputFormat(output)
}
if clientCtx.HomeDir == "" || flagSet.Changed(flags.FlagHome) {
homeDir, _ := flagSet.GetString(flags.FlagHome)
clientCtx = clientCtx.WithHomeDir(homeDir)
}
if !clientCtx.Simulate || flagSet.Changed(flags.FlagDryRun) {
dryRun, _ := flagSet.GetBool(flags.FlagDryRun)
clientCtx = clientCtx.WithSimulation(dryRun)
@ -125,7 +119,7 @@ func ReadPersistentCommandFlags(clientCtx Context, flagSet *pflag.FlagSet) (Cont
keyringBackend, _ := flagSet.GetString(flags.FlagKeyringBackend)
if keyringBackend != "" {
kr, err := newKeyringFromFlags(clientCtx, keyringBackend)
kr, err := NewKeyringFromBackend(clientCtx, keyringBackend)
if err != nil {
return clientCtx, err
}
@ -139,7 +133,7 @@ func ReadPersistentCommandFlags(clientCtx Context, flagSet *pflag.FlagSet) (Cont
if rpcURI != "" {
clientCtx = clientCtx.WithNodeURI(rpcURI)
client, err := rpchttp.New(rpcURI, "/websocket")
client, err := NewClientFromNode(rpcURI)
if err != nil {
return clientCtx, err
}
@ -255,6 +249,21 @@ func readTxCommandFlags(clientCtx Context, flagSet *pflag.FlagSet) (Context, err
return clientCtx, nil
}
// ReadHomeFlag checks if home flag is changed.
// If this is a case, we update HomeDir field of Client Context
/* Discovered a bug with Cory
./build/simd init andrei --home ./test
cd test/config there is no client.toml configuration file
*/
func ReadHomeFlag(clientCtx Context, cmd *cobra.Command) Context {
if cmd.Flags().Changed(flags.FlagHome) {
rootDir, _ := cmd.Flags().GetString(flags.FlagHome)
clientCtx = clientCtx.WithHomeDir(rootDir)
}
return clientCtx
}
// GetClientQueryContext returns a Context from a command with fields set based on flags
// defined in AddQueryFlagsToCmd. An error is returned if any flag query fails.
//

96
client/config/cmd.go Normal file
View File

@ -0,0 +1,96 @@
package config
import (
"encoding/json"
"fmt"
"path/filepath"
tmcli "github.com/tendermint/tendermint/libs/cli"
"github.com/spf13/cobra"
"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/client/flags"
)
// Cmd returns a CLI command to interactively create an application CLI
// config file.
func Cmd() *cobra.Command {
cmd := &cobra.Command{
Use: "config <key> [value]",
Short: "Create or query an application CLI configuration file",
RunE: runConfigCmd,
Args: cobra.RangeArgs(0, 2),
}
return cmd
}
func runConfigCmd(cmd *cobra.Command, args []string) error {
clientCtx := client.GetClientContextFromCmd(cmd)
configPath := filepath.Join(clientCtx.HomeDir, "config")
conf, err := getClientConfig(configPath, clientCtx.Viper)
if err != nil {
return fmt.Errorf("couldn't get client config: %v", err)
}
switch len(args) {
case 0:
// print all client config fields to sdt out
s, _ := json.MarshalIndent(conf, "", "\t")
cmd.Println(string(s))
case 1:
// it's a get
key := args[0]
switch key {
case flags.FlagChainID:
cmd.Println(conf.ChainID)
case flags.FlagKeyringBackend:
cmd.Println(conf.KeyringBackend)
case tmcli.OutputFlag:
cmd.Println(conf.Output)
case flags.FlagNode:
cmd.Println(conf.Node)
case flags.FlagBroadcastMode:
cmd.Println(conf.BroadcastMode)
default:
err := errUnknownConfigKey(key)
return fmt.Errorf("couldn't get the value for the key: %v, error: %v", key, err)
}
case 2:
// it's set
key, value := args[0], args[1]
switch key {
case flags.FlagChainID:
conf.SetChainID(value)
case flags.FlagKeyringBackend:
conf.SetKeyringBackend(value)
case tmcli.OutputFlag:
conf.SetOutput(value)
case flags.FlagNode:
conf.SetNode(value)
case flags.FlagBroadcastMode:
conf.SetBroadcastMode(value)
default:
return errUnknownConfigKey(key)
}
confFile := filepath.Join(configPath, "client.toml")
if err := writeConfigToFile(confFile, conf); err != nil {
return fmt.Errorf("could not write client config to the file: %v", err)
}
default:
panic("cound not execute config command")
}
return nil
}
func errUnknownConfigKey(key string) error {
return fmt.Errorf("unknown configuration key: %q", key)
}

96
client/config/config.go Normal file
View File

@ -0,0 +1,96 @@
package config
import (
"fmt"
"os"
"path/filepath"
"github.com/cosmos/cosmos-sdk/client"
)
// Default constants
const (
chainID = ""
keyringBackend = "os"
output = "text"
node = "tcp://localhost:26657"
broadcastMode = "sync"
)
type ClientConfig struct {
ChainID string `mapstructure:"chain-id" json:"chain-id"`
KeyringBackend string `mapstructure:"keyring-backend" json:"keyring-backend"`
Output string `mapstructure:"output" json:"output"`
Node string `mapstructure:"node" json:"node"`
BroadcastMode string `mapstructure:"broadcast-mode" json:"broadcast-mode"`
}
// defaultClientConfig returns the reference to ClientConfig with default values.
func defaultClientConfig() *ClientConfig {
return &ClientConfig{chainID, keyringBackend, output, node, broadcastMode}
}
func (c *ClientConfig) SetChainID(chainID string) {
c.ChainID = chainID
}
func (c *ClientConfig) SetKeyringBackend(keyringBackend string) {
c.KeyringBackend = keyringBackend
}
func (c *ClientConfig) SetOutput(output string) {
c.Output = output
}
func (c *ClientConfig) SetNode(node string) {
c.Node = node
}
func (c *ClientConfig) SetBroadcastMode(broadcastMode string) {
c.BroadcastMode = broadcastMode
}
// ReadFromClientConfig reads values from client.toml file and updates them in client Context
func ReadFromClientConfig(ctx client.Context) (client.Context, error) {
configPath := filepath.Join(ctx.HomeDir, "config")
configFilePath := filepath.Join(configPath, "client.toml")
conf := defaultClientConfig()
// if config.toml file does not exist we create it and write default ClientConfig values into it.
if _, err := os.Stat(configFilePath); os.IsNotExist(err) {
if err := ensureConfigPath(configPath); err != nil {
return ctx, fmt.Errorf("couldn't make client config: %v", err)
}
if err := writeConfigToFile(configFilePath, conf); err != nil {
return ctx, fmt.Errorf("could not write client config to the file: %v", err)
}
}
conf, err := getClientConfig(configPath, ctx.Viper)
if err != nil {
return ctx, fmt.Errorf("couldn't get client config: %v", err)
}
// we need to update KeyringDir field on Client Context first cause it is used in NewKeyringFromBackend
ctx = ctx.WithOutputFormat(conf.Output).
WithChainID(conf.ChainID)
keyring, err := client.NewKeyringFromBackend(ctx, conf.KeyringBackend)
if err != nil {
return ctx, fmt.Errorf("couldn't get key ring: %v", err)
}
ctx = ctx.WithKeyring(keyring)
// https://github.com/cosmos/cosmos-sdk/issues/8986
client, err := client.NewClientFromNode(conf.Node)
if err != nil {
return ctx, fmt.Errorf("couldn't get client from nodeURI: %v", err)
}
ctx = ctx.WithNodeURI(conf.Node).
WithClient(client).
WithBroadcastMode(conf.BroadcastMode)
return ctx, nil
}

70
client/config/toml.go Normal file
View File

@ -0,0 +1,70 @@
package config
import (
"bytes"
"io/ioutil"
"os"
"text/template"
"github.com/spf13/viper"
)
const defaultConfigTemplate = `# This is a TOML config file.
# For more information, see https://github.com/toml-lang/toml
###############################################################################
### Client Configuration ###
###############################################################################
# The network chain ID
chain-id = "{{ .ChainID }}"
# The keyring's backend, where the keys are stored (os|file|kwallet|pass|test|memory)
keyring-backend = "{{ .KeyringBackend }}"
# CLI output format (text|json)
output = "{{ .Output }}"
# <host>:<port> to Tendermint RPC interface for this chain
node = "{{ .Node }}"
# Transaction broadcasting mode (sync|async|block)
broadcast-mode = "{{ .BroadcastMode }}"
`
// writeConfigToFile parses defaultConfigTemplate, renders config using the template and writes it to
// configFilePath.
func writeConfigToFile(configFilePath string, config *ClientConfig) error {
var buffer bytes.Buffer
tmpl := template.New("clientConfigFileTemplate")
configTemplate, err := tmpl.Parse(defaultConfigTemplate)
if err != nil {
return err
}
if err := configTemplate.Execute(&buffer, config); err != nil {
return err
}
return ioutil.WriteFile(configFilePath, buffer.Bytes(), 0600)
}
// ensureConfigPath creates a directory configPath if it does not exist
func ensureConfigPath(configPath string) error {
return os.MkdirAll(configPath, os.ModePerm)
}
// getClientConfig reads values from client.toml file and unmarshalls them into ClientConfig
func getClientConfig(configPath string, v *viper.Viper) (*ClientConfig, error) {
v.AddConfigPath(configPath)
v.SetConfigName("client")
v.SetConfigType("toml")
if err := v.ReadInConfig(); err != nil {
return nil, err
}
conf := new(ClientConfig)
if err := v.Unmarshal(conf); err != nil {
return nil, err
}
return conf, nil
}

View File

@ -5,6 +5,8 @@ import (
"io"
"os"
"github.com/spf13/viper"
"gopkg.in/yaml.v2"
"github.com/gogo/protobuf/proto"
@ -46,6 +48,7 @@ type Context struct {
AccountRetriever AccountRetriever
NodeURI string
FeeGranter sdk.AccAddress
Viper *viper.Viper
// TODO: Deprecated (remove).
LegacyAmino *codec.LegacyAmino
@ -133,7 +136,9 @@ func (ctx Context) WithChainID(chainID string) Context {
// WithHomeDir returns a copy of the Context with HomeDir set.
func (ctx Context) WithHomeDir(dir string) Context {
ctx.HomeDir = dir
if dir != "" {
ctx.HomeDir = dir
}
return ctx
}
@ -220,6 +225,14 @@ func (ctx Context) WithInterfaceRegistry(interfaceRegistry codectypes.InterfaceR
return ctx
}
// WithViper returns the context with Viper field. This Viper instance is used to read
// client-side config from the config file.
func (ctx Context) WithViper() Context {
v := viper.New()
ctx.Viper = v
return ctx
}
// PrintString prints the raw string to ctx.Output if it's defined, otherwise to os.Stdout
func (ctx Context) PrintString(str string) error {
return ctx.PrintBytes([]byte(str))
@ -330,7 +343,8 @@ func GetFromFields(kr keyring.Keyring, from string, genOnly bool) (sdk.AccAddres
return info.GetAddress(), info.GetName(), info.GetType(), nil
}
func newKeyringFromFlags(ctx Context, backend string) (keyring.Keyring, error) {
// NewKeyringFromBackend gets a Keyring object from a backend
func NewKeyringFromBackend(ctx Context, backend string) (keyring.Keyring, error) {
if ctx.GenerateOnly || ctx.Simulate {
return keyring.New(sdk.KeyringServiceName(), keyring.BackendMemory, ctx.KeyringDir, ctx.Input, ctx.KeyringOptions...)
}

View File

@ -51,7 +51,7 @@ func TestContext_PrintObject(t *testing.T) {
require.NoError(t, err)
require.Equal(t,
`{"animal":{"@type":"/testdata.Dog","size":"big","name":"Spot"},"x":"10"}
`, string(buf.Bytes()))
`, buf.String())
// yaml
buf = &bytes.Buffer{}
@ -65,7 +65,7 @@ func TestContext_PrintObject(t *testing.T) {
name: Spot
size: big
x: "10"
`, string(buf.Bytes()))
`, buf.String())
//
// amino
@ -81,7 +81,7 @@ x: "10"
require.NoError(t, err)
require.Equal(t,
`{"type":"testdata/HasAnimal","value":{"animal":{"type":"testdata/Dog","value":{"size":"big","name":"Spot"}},"x":"10"}}
`, string(buf.Bytes()))
`, buf.String())
// yaml
buf = &bytes.Buffer{}
@ -98,7 +98,7 @@ value:
name: Spot
size: big
x: "10"
`, string(buf.Bytes()))
`, buf.String())
}
func TestCLIQueryConn(t *testing.T) {

View File

@ -1,7 +1,6 @@
package debug
import (
"encoding/base64"
"encoding/hex"
"fmt"
"strconv"
@ -10,13 +9,12 @@ import (
"github.com/spf13/cobra"
"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/crypto/keys/ed25519"
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/errors"
"github.com/cosmos/cosmos-sdk/version"
)
// Cmd creates a main CLI command
func Cmd() *cobra.Command {
cmd := &cobra.Command{
Use: "debug",
@ -31,90 +29,31 @@ func Cmd() *cobra.Command {
return cmd
}
// getPubKeyFromString returns a Tendermint PubKey (PubKeyEd25519) by attempting
// to decode the pubkey string from hex, base64, and finally bech32. If all
// encodings fail, an error is returned.
func getPubKeyFromString(pkstr string) (cryptotypes.PubKey, error) {
bz, err := hex.DecodeString(pkstr)
if err == nil {
if len(bz) == ed25519.PubKeySize {
return &ed25519.PubKey{Key: bz}, nil
}
}
bz, err = base64.StdEncoding.DecodeString(pkstr)
if err == nil {
if len(bz) == ed25519.PubKeySize {
return &ed25519.PubKey{Key: bz}, nil
}
}
pk, err := sdk.GetPubKeyFromBech32(sdk.Bech32PubKeyTypeAccPub, pkstr)
if err == nil {
return pk, nil
}
pk, err = sdk.GetPubKeyFromBech32(sdk.Bech32PubKeyTypeValPub, pkstr)
if err == nil {
return pk, nil
}
pk, err = sdk.GetPubKeyFromBech32(sdk.Bech32PubKeyTypeConsPub, pkstr)
if err == nil {
return pk, nil
}
return nil, fmt.Errorf("pubkey '%s' invalid; expected hex, base64, or bech32 of correct size", pkstr)
// getPubKeyFromString decodes SDK PubKey using JSON marshaler.
func getPubKeyFromString(ctx client.Context, pkstr string) (cryptotypes.PubKey, error) {
var pk cryptotypes.PubKey
err := ctx.JSONMarshaler.UnmarshalInterfaceJSON([]byte(pkstr), &pk)
return pk, err
}
func PubkeyCmd() *cobra.Command {
return &cobra.Command{
Use: "pubkey [pubkey]",
Short: "Decode a ED25519 pubkey from hex, base64, or bech32",
Long: fmt.Sprintf(`Decode a pubkey from hex, base64, or bech32.
Short: "Decode a pubkey from proto JSON",
Long: fmt.Sprintf(`Decode a pubkey from proto JSON and display it's address.
Example:
$ %s debug pubkey TWFuIGlzIGRpc3Rpbmd1aXNoZWQsIG5vdCBvbmx5IGJ5IGhpcyByZWFzb24sIGJ1dCBieSB0aGlz
$ %s debug pubkey cosmos1e0jnq2sun3dzjh8p2xq95kk0expwmd7shwjpfg
`, version.AppName, version.AppName),
$ %s debug pubkey '{"@type":"/cosmos.crypto.secp256k1.PubKey","key":"AurroA7jvfPd1AadmmOvWM2rJSwipXfRf8yD6pLbA2DJ"}'
`, version.AppName),
Args: cobra.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
clientCtx := client.GetClientContextFromCmd(cmd)
pk, err := getPubKeyFromString(args[0])
pk, err := getPubKeyFromString(clientCtx, args[0])
if err != nil {
return err
}
edPK, ok := pk.(*ed25519.PubKey)
if !ok {
return errors.Wrapf(errors.ErrInvalidType, "invalid pubkey type; expected ED25519")
}
pubKeyJSONBytes, err := clientCtx.LegacyAmino.MarshalJSON(edPK)
if err != nil {
return err
}
accPub, err := sdk.Bech32ifyPubKey(sdk.Bech32PubKeyTypeAccPub, edPK)
if err != nil {
return err
}
valPub, err := sdk.Bech32ifyPubKey(sdk.Bech32PubKeyTypeValPub, edPK)
if err != nil {
return err
}
consenusPub, err := sdk.Bech32ifyPubKey(sdk.Bech32PubKeyTypeConsPub, edPK)
if err != nil {
return err
}
cmd.Println("Address:", edPK.Address())
cmd.Printf("Hex: %X\n", edPK.Key)
cmd.Println("JSON (base64):", string(pubKeyJSONBytes))
cmd.Println("Bech32 Acc:", accPub)
cmd.Println("Bech32 Validator Operator:", valPub)
cmd.Println("Bech32 Validator Consensus:", consenusPub)
cmd.Println("Address:", pk.Address())
cmd.Println("PubKey Hex:", hex.EncodeToString(pk.Bytes()))
return nil
},
}
@ -125,7 +64,7 @@ func AddrCmd() *cobra.Command {
Use: "addr [address]",
Short: "Convert an address between hex and bech32",
Long: fmt.Sprintf(`Convert an address between hex encoding and bech32.
Example:
$ %s debug addr cosmos1e0jnq2sun3dzjh8p2xq95kk0expwmd7shwjpfg
`, version.AppName),
@ -152,13 +91,10 @@ $ %s debug addr cosmos1e0jnq2sun3dzjh8p2xq95kk0expwmd7shwjpfg
}
}
accAddr := sdk.AccAddress(addr)
valAddr := sdk.ValAddress(addr)
cmd.Println("Address:", addr)
cmd.Printf("Address (hex): %X\n", addr)
cmd.Printf("Bech32 Acc: %s\n", accAddr)
cmd.Printf("Bech32 Val: %s\n", valAddr)
cmd.Printf("Bech32 Acc: %s\n", sdk.AccAddress(addr))
cmd.Printf("Bech32 Val: %s\n", sdk.ValAddress(addr))
return nil
},
}
@ -169,7 +105,7 @@ func RawBytesCmd() *cobra.Command {
Use: "raw-bytes [raw-bytes]",
Short: "Convert raw bytes output (eg. [10 21 13 255]) to hex",
Long: fmt.Sprintf(`Convert raw-bytes to hex.
Example:
$ %s debug raw-bytes [72 101 108 108 111 44 32 112 108 97 121 103 114 111 117 110 100]
`, version.AppName),

View File

@ -106,38 +106,6 @@
"Params": "UpgradeParams"
}
}
},
{
"url": "./tmp-swagger-gen/ibc/core/channel/v1/query.swagger.json",
"operationIds": {
"rename": {
"Params": "IBCChannelParams"
}
}
},
{
"url": "./tmp-swagger-gen/ibc/core/client/v1/query.swagger.json",
"operationIds": {
"rename": {
"Params": "IBCClientParams"
}
}
},
{
"url": "./tmp-swagger-gen/ibc/core/connection/v1/query.swagger.json",
"operationIds": {
"rename": {
"Params": "IBCConnectionParams"
}
}
},
{
"url": "./tmp-swagger-gen/ibc/applications/transfer/v1/query.swagger.json",
"operationIds": {
"rename": {
"Params": "IBCTransferParams"
}
}
}
]
}

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

View File

@ -566,7 +566,7 @@ paths:
$ref: "#/definitions/Address"
validator_address:
$ref: "#/definitions/ValidatorAddress"
delegation:
amount:
$ref: "#/definitions/Coin"
tags:
- Staking
@ -656,9 +656,8 @@ paths:
$ref: "#/definitions/Address"
validator_address:
$ref: "#/definitions/ValidatorAddress"
shares:
type: string
example: "100"
amount:
$ref: "#/definitions/Coin"
tags:
- Staking
consumes:

View File

@ -71,6 +71,7 @@ const (
FlagTimeoutHeight = "timeout-height"
FlagKeyAlgorithm = "algo"
FlagFeeAccount = "fee-account"
FlagReverse = "reverse"
// Tendermint logging flags
FlagLogLevel = "log_level"
@ -131,6 +132,7 @@ func AddPaginationFlagsToCmd(cmd *cobra.Command, query string) {
cmd.Flags().Uint64(FlagOffset, 0, fmt.Sprintf("pagination offset of %s to query for", query))
cmd.Flags().Uint64(FlagLimit, 100, fmt.Sprintf("pagination limit of %s to query for", query))
cmd.Flags().Bool(FlagCountTotal, false, fmt.Sprintf("count total number of records in %s to query for", query))
cmd.Flags().Bool(FlagReverse, false, "results are sorted in descending order")
}
// GasSetting encapsulates the possible values passed through the --gas flag.

View File

@ -95,33 +95,7 @@ func (s queryServer) GetLatestValidatorSet(ctx context.Context, req *GetLatestVa
if err != nil {
return nil, err
}
validatorsRes, err := rpc.GetValidators(ctx, s.clientCtx, nil, &page, &limit)
if err != nil {
return nil, err
}
outputValidatorsRes := &GetLatestValidatorSetResponse{
BlockHeight: validatorsRes.BlockHeight,
Validators: make([]*Validator, len(validatorsRes.Validators)),
Pagination: &qtypes.PageResponse{
Total: validatorsRes.Total,
},
}
for i, validator := range validatorsRes.Validators {
anyPub, err := codectypes.NewAnyWithValue(validator.PubKey)
if err != nil {
return nil, err
}
outputValidatorsRes.Validators[i] = &Validator{
Address: validator.Address.String(),
ProposerPriority: validator.ProposerPriority,
PubKey: anyPub,
VotingPower: validator.VotingPower,
}
}
return outputValidatorsRes, nil
return validatorsOutput(ctx, s.clientCtx, nil, page, limit)
}
func (m *GetLatestValidatorSetResponse) UnpackInterfaces(unpacker codectypes.AnyUnpacker) error {
@ -149,32 +123,42 @@ func (s queryServer) GetValidatorSetByHeight(ctx context.Context, req *GetValida
if req.Height > chainHeight {
return nil, status.Error(codes.InvalidArgument, "requested block height is bigger then the chain length")
}
validatorsRes, err := rpc.GetValidators(ctx, s.clientCtx, &req.Height, &page, &limit)
r, err := validatorsOutput(ctx, s.clientCtx, &req.Height, page, limit)
if err != nil {
return nil, err
}
return &GetValidatorSetByHeightResponse{
BlockHeight: r.BlockHeight,
Validators: r.Validators,
Pagination: r.Pagination,
}, nil
}
outputValidatorsRes := &GetValidatorSetByHeightResponse{
BlockHeight: validatorsRes.BlockHeight,
Validators: make([]*Validator, len(validatorsRes.Validators)),
Pagination: &qtypes.PageResponse{Total: validatorsRes.Total},
func validatorsOutput(ctx context.Context, cctx client.Context, height *int64, page, limit int) (*GetLatestValidatorSetResponse, error) {
vs, err := rpc.GetValidators(ctx, cctx, height, &page, &limit)
if err != nil {
return nil, err
}
for i, validator := range validatorsRes.Validators {
anyPub, err := codectypes.NewAnyWithValue(validator.PubKey)
resp := GetLatestValidatorSetResponse{
BlockHeight: vs.BlockHeight,
Validators: make([]*Validator, len(vs.Validators)),
Pagination: &qtypes.PageResponse{
Total: vs.Total,
},
}
for i, v := range vs.Validators {
anyPub, err := codectypes.NewAnyWithValue(v.PubKey)
if err != nil {
return nil, err
}
outputValidatorsRes.Validators[i] = &Validator{
Address: validator.Address.String(),
ProposerPriority: validator.ProposerPriority,
resp.Validators[i] = &Validator{
Address: v.Address.String(),
ProposerPriority: v.ProposerPriority,
PubKey: anyPub,
VotingPower: validator.VotingPower,
VotingPower: v.VotingPower,
}
}
return outputValidatorsRes, nil
return &resp, nil
}
// GetNodeInfo implements ServiceServer.GetNodeInfo

View File

@ -40,7 +40,7 @@ const (
func AddKeyCommand() *cobra.Command {
cmd := &cobra.Command{
Use: "add <name>",
Short: "Add an encrypted private key (either newly generated or recovered), encrypt it, and save to disk",
Short: "Add an encrypted private key (either newly generated or recovered), encrypt it, and save to <name> file",
Long: `Derive a new private key and encrypt to disk.
Optionally specify a BIP39 mnemonic, a BIP39 passphrase to further secure the mnemonic,
and a bip32 HD path to derive a specific account. The key will be stored under the given name
@ -53,29 +53,31 @@ local keystore.
Use the --pubkey flag to add arbitrary public keys to the keystore for constructing
multisig transactions.
You can add a multisig key by passing the list of key names you want the public
key to be composed of to the --multisig flag and the minimum number of signatures
required through --multisig-threshold. The keys are sorted by address, unless
the flag --nosort is set.
You can create and store a multisig key by passing the list of key names stored in a keyring
and the minimum number of signatures required through --multisig-threshold. The keys are
sorted by address, unless the flag --nosort is set.
Example:
keys add mymultisig --multisig "keyname1,keyname2,keyname3" --multisig-threshold 2
`,
Args: cobra.ExactArgs(1),
RunE: runAddCmd,
RunE: runAddCmdPrepare,
}
cmd.Flags().StringSlice(flagMultisig, nil, "Construct and store a multisig public key (implies --pubkey)")
cmd.Flags().Int(flagMultiSigThreshold, 1, "K out of N required signatures. For use in conjunction with --multisig")
cmd.Flags().Bool(flagNoSort, false, "Keys passed to --multisig are taken in the order they're supplied")
cmd.Flags().String(FlagPublicKey, "", "Parse a public key in bech32 format and save it to disk")
cmd.Flags().BoolP(flagInteractive, "i", false, "Interactively prompt user for BIP39 passphrase and mnemonic")
cmd.Flags().Bool(flags.FlagUseLedger, false, "Store a local reference to a private key on a Ledger device")
cmd.Flags().Bool(flagRecover, false, "Provide seed phrase to recover existing key instead of creating")
cmd.Flags().Bool(flagNoBackup, false, "Don't print out seed phrase (if others are watching the terminal)")
cmd.Flags().Bool(flags.FlagDryRun, false, "Perform action, but don't add key to local keystore")
cmd.Flags().String(flagHDPath, "", "Manual HD Path derivation (overrides BIP44 config)")
cmd.Flags().Uint32(flagCoinType, sdk.GetConfig().GetCoinType(), "coin type number for HD derivation")
cmd.Flags().Uint32(flagAccount, 0, "Account number for HD derivation")
cmd.Flags().Uint32(flagIndex, 0, "Address index number for HD derivation")
cmd.Flags().String(flags.FlagKeyAlgorithm, string(hd.Secp256k1Type), "Key signing algorithm to generate keys for")
f := cmd.Flags()
f.StringSlice(flagMultisig, nil, "List of key names stored in keyring to construct a public legacy multisig key")
f.Int(flagMultiSigThreshold, 1, "K out of N required signatures. For use in conjunction with --multisig")
f.Bool(flagNoSort, false, "Keys passed to --multisig are taken in the order they're supplied")
f.String(FlagPublicKey, "", "Parse a public key in JSON format and saves key info to <name> file.")
f.BoolP(flagInteractive, "i", false, "Interactively prompt user for BIP39 passphrase and mnemonic")
f.Bool(flags.FlagUseLedger, false, "Store a local reference to a private key on a Ledger device")
f.Bool(flagRecover, false, "Provide seed phrase to recover existing key instead of creating")
f.Bool(flagNoBackup, false, "Don't print out seed phrase (if others are watching the terminal)")
f.Bool(flags.FlagDryRun, false, "Perform action, but don't add key to local keystore")
f.String(flagHDPath, "", "Manual HD Path derivation (overrides BIP44 config)")
f.Uint32(flagCoinType, sdk.GetConfig().GetCoinType(), "coin type number for HD derivation")
f.Uint32(flagAccount, 0, "Account number for HD derivation")
f.Uint32(flagIndex, 0, "Address index number for HD derivation")
f.String(flags.FlagKeyAlgorithm, string(hd.Secp256k1Type), "Key signing algorithm to generate keys for")
cmd.SetOut(cmd.OutOrStdout())
cmd.SetErr(cmd.ErrOrStderr())
@ -83,14 +85,14 @@ the flag --nosort is set.
return cmd
}
func runAddCmd(cmd *cobra.Command, args []string) error {
func runAddCmdPrepare(cmd *cobra.Command, args []string) error {
buf := bufio.NewReader(cmd.InOrStdin())
clientCtx, err := client.GetClientQueryContext(cmd)
if err != nil {
return err
}
return RunAddCmd(cmd, args, clientCtx.Keyring, buf)
return RunAddCmd(clientCtx, cmd, args, buf)
}
/*
@ -102,13 +104,15 @@ input
output
- armor encrypted private key (saved to file)
*/
func RunAddCmd(cmd *cobra.Command, args []string, kb keyring.Keyring, inBuf *bufio.Reader) error {
func RunAddCmd(ctx client.Context, cmd *cobra.Command, args []string, inBuf *bufio.Reader) error {
// func RunAddCmd(cmd *cobra.Command, args []string, kb keyring.Keyring, inBuf *bufio.Reader) error {
var err error
name := args[0]
interactive, _ := cmd.Flags().GetBool(flagInteractive)
noBackup, _ := cmd.Flags().GetBool(flagNoBackup)
showMnemonic := !noBackup
kb := ctx.Keyring
keyringAlgos, _ := kb.SupportedAlgorithms()
algoStr, _ := cmd.Flags().GetString(flags.FlagKeyAlgorithm)
@ -139,7 +143,6 @@ func RunAddCmd(cmd *cobra.Command, args []string, kb keyring.Keyring, inBuf *buf
multisigKeys, _ := cmd.Flags().GetStringSlice(flagMultisig)
if len(multisigKeys) != 0 {
var pks []cryptotypes.PubKey
multisigThreshold, _ := cmd.Flags().GetInt(flagMultiSigThreshold)
if err := validateMultisigThreshold(multisigThreshold, len(multisigKeys)); err != nil {
return err
@ -172,16 +175,13 @@ func RunAddCmd(cmd *cobra.Command, args []string, kb keyring.Keyring, inBuf *buf
pubKey, _ := cmd.Flags().GetString(FlagPublicKey)
if pubKey != "" {
pk, err := sdk.GetPubKeyFromBech32(sdk.Bech32PubKeyTypeAccPub, pubKey)
var pk cryptotypes.PubKey
err = ctx.JSONMarshaler.UnmarshalInterfaceJSON([]byte(pubKey), &pk)
if err != nil {
return err
}
if _, err := kb.SavePubKey(name, pk, algo.Name()); err != nil {
return err
}
return nil
_, err := kb.SavePubKey(name, pk, algo.Name())
return err
}
coinType, _ := cmd.Flags().GetUint32(flagCoinType)
@ -284,11 +284,10 @@ func RunAddCmd(cmd *cobra.Command, args []string, kb keyring.Keyring, inBuf *buf
func printCreate(cmd *cobra.Command, info keyring.Info, showMnemonic bool, mnemonic string) error {
output, _ := cmd.Flags().GetString(cli.OutputFlag)
switch output {
case OutputFormatText:
cmd.PrintErrln()
printKeyInfo(cmd.OutOrStdout(), info, keyring.Bech32KeyOutput, output)
printKeyInfo(cmd.OutOrStdout(), info, keyring.MkAccKeyOutput, output)
// print mnemonic unless requested not to.
if showMnemonic {
@ -298,7 +297,7 @@ func printCreate(cmd *cobra.Command, info keyring.Info, showMnemonic bool, mnemo
fmt.Fprintln(cmd.ErrOrStderr(), mnemonic)
}
case OutputFormatJSON:
out, err := keyring.Bech32KeyOutput(info)
out, err := keyring.MkAccKeyOutput(info)
if err != nil {
return err
}

View File

@ -8,7 +8,6 @@ import (
"testing"
"github.com/stretchr/testify/require"
"github.com/tendermint/tendermint/libs/cli"
"github.com/cosmos/cosmos-sdk/client"
@ -74,8 +73,8 @@ func Test_runAddCmdLedgerWithCustomCoinType(t *testing.T) {
require.Equal(t, "keyname1", key1.GetName())
require.Equal(t, keyring.TypeLedger, key1.GetType())
require.Equal(t,
"terrapub1addwnpepqvpg7r26nl2pvqqern00m6s9uaax3hauu2rzg8qpjzq9hy6xve7sw0d84m6",
sdk.MustBech32ifyPubKey(sdk.Bech32PubKeyTypeAccPub, key1.GetPubKey()))
"PubKeySecp256k1{03028F0D5A9FD41600191CDEFDEA05E77A68DFBCE286241C0190805B9346667D07}",
key1.GetPubKey().String())
config.SetPurpose(44)
config.SetCoinType(118)
@ -122,6 +121,6 @@ func Test_runAddCmdLedger(t *testing.T) {
require.Equal(t, "keyname1", key1.GetName())
require.Equal(t, keyring.TypeLedger, key1.GetType())
require.Equal(t,
"cosmospub1addwnpepqd87l8xhcnrrtzxnkql7k55ph8fr9jarf4hn6udwukfprlalu8lgw0urza0",
sdk.MustBech32ifyPubKey(sdk.Bech32PubKeyTypeAccPub, key1.GetPubKey()))
"PubKeySecp256k1{034FEF9CD7C4C63588D3B03FEB5281B9D232CBA34D6F3D71AEE59211FFBFE1FE87}",
key1.GetPubKey().String())
}

View File

@ -5,6 +5,8 @@ import (
cryptocodec "github.com/cosmos/cosmos-sdk/crypto/codec"
)
// TODO: remove this file https://github.com/cosmos/cosmos-sdk/issues/8047
// KeysCdc defines codec to be used with key operations
var KeysCdc *codec.LegacyAmino

View File

@ -20,10 +20,10 @@ func getTestCases() testCases {
return testCases{
// nolint:govet
[]keyring.KeyOutput{
{"A", "B", "C", "D", "E", 0, nil},
{"A", "B", "C", "D", "", 0, nil},
{"", "B", "C", "D", "", 0, nil},
{"", "", "", "", "", 0, nil},
{"A", "B", "C", "D", "E"},
{"A", "B", "C", "D", ""},
{"", "B", "C", "D", ""},
{"", "", "", "", ""},
},
make([]keyring.KeyOutput, 4),
[][]byte{

View File

@ -33,6 +33,7 @@ func Test_runDeleteCmd(t *testing.T) {
path := sdk.GetConfig().GetFullBIP44Path()
cmd.SetArgs([]string{"blah", fmt.Sprintf("--%s=%s", flags.FlagHome, kbHome)})
kb, err := keyring.New(sdk.KeyringServiceName(), keyring.BackendTest, kbHome, mockIn)
require.NoError(t, err)
@ -42,14 +43,15 @@ func Test_runDeleteCmd(t *testing.T) {
_, _, err = kb.NewMnemonic(fakeKeyName2, keyring.English, sdk.FullFundraiserPath, keyring.DefaultBIP39Passphrase, hd.Secp256k1)
require.NoError(t, err)
cmd.SetArgs([]string{"blah", fmt.Sprintf("--%s=%s", flags.FlagHome, kbHome)})
clientCtx := client.Context{}.
WithKeyringDir(kbHome).
WithKeyring(kb)
clientCtx := client.Context{}.WithKeyring(kb)
ctx := context.WithValue(context.Background(), client.ClientContextKey, &clientCtx)
err = cmd.ExecuteContext(ctx)
require.Error(t, err)
require.Equal(t, "The specified item could not be found in the keyring", err.Error())
require.EqualError(t, err, "blah.info: key not found")
// User confirmation missing
cmd.SetArgs([]string{

View File

@ -45,7 +45,9 @@ func Test_runExportCmd(t *testing.T) {
mockIn.Reset("123456789\n123456789\n")
cmd.SetArgs(args)
clientCtx := client.Context{}.WithKeyring(kb)
clientCtx := client.Context{}.
WithKeyringDir(kbHome).
WithKeyring(kb)
ctx := context.WithValue(context.Background(), client.ClientContextKey, &clientCtx)
require.NoError(t, cmd.ExecuteContext(ctx))

View File

@ -25,7 +25,9 @@ func Test_runImportCmd(t *testing.T) {
kbHome := t.TempDir()
kb, err := keyring.New(sdk.KeyringServiceName(), keyring.BackendTest, kbHome, mockIn)
clientCtx := client.Context{}.WithKeyring(kb)
clientCtx := client.Context{}.
WithKeyringDir(kbHome).
WithKeyring(kb)
ctx := context.WithValue(context.Background(), client.ClientContextKey, &clientCtx)
require.NoError(t, err)

View File

@ -2,7 +2,6 @@ package keys
import (
"github.com/spf13/cobra"
"github.com/tendermint/tendermint/libs/cli"
"github.com/cosmos/cosmos-sdk/client"
)
@ -37,8 +36,7 @@ func runListCmd(cmd *cobra.Command, _ []string) error {
cmd.SetOut(cmd.OutOrStdout())
if ok, _ := cmd.Flags().GetBool(flagListNames); !ok {
output, _ := cmd.Flags().GetString(cli.OutputFlag)
printInfos(cmd.OutOrStdout(), infos, output)
printInfos(cmd.OutOrStdout(), infos, clientCtx.OutputFormat)
return nil
}

View File

@ -13,6 +13,7 @@ import (
"github.com/cosmos/cosmos-sdk/crypto/ledger"
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerr "github.com/cosmos/cosmos-sdk/types/errors"
)
const (
@ -41,12 +42,12 @@ consisting of all the keys provided by name and multisig threshold.`,
Args: cobra.MinimumNArgs(1),
RunE: runShowCmd,
}
cmd.Flags().String(FlagBechPrefix, sdk.PrefixAccount, "The Bech32 prefix encoding for a key (acc|val|cons)")
cmd.Flags().BoolP(FlagAddress, "a", false, "Output the address only (overrides --output)")
cmd.Flags().BoolP(FlagPublicKey, "p", false, "Output the public key only (overrides --output)")
cmd.Flags().BoolP(FlagDevice, "d", false, "Output the address in a ledger device")
cmd.Flags().Int(flagMultiSigThreshold, 1, "K out of N required signatures")
f := cmd.Flags()
f.String(FlagBechPrefix, sdk.PrefixAccount, "The Bech32 prefix encoding for a key (acc|val|cons)")
f.BoolP(FlagAddress, "a", false, "Output the address only (overrides --output)")
f.BoolP(FlagPublicKey, "p", false, "Output the public key only (overrides --output)")
f.BoolP(FlagDevice, "d", false, "Output the address in a ledger device")
f.Int(flagMultiSigThreshold, 1, "K out of N required signatures")
return cmd
}
@ -81,7 +82,10 @@ func runShowCmd(cmd *cobra.Command, args []string) (err error) {
}
multikey := multisig.NewLegacyAminoPubKey(multisigThreshold, pks)
info = keyring.NewMultiInfo(defaultMultiSigKeyName, multikey)
info, err = keyring.NewMultiInfo(defaultMultiSigKeyName, multikey)
if err != nil {
return err
}
}
isShowAddr, _ := cmd.Flags().GetBool(FlagAddress)
@ -111,10 +115,16 @@ func runShowCmd(cmd *cobra.Command, args []string) (err error) {
output, _ := cmd.Flags().GetString(cli.OutputFlag)
switch {
case isShowAddr:
printKeyAddress(cmd.OutOrStdout(), info, bechKeyOut)
case isShowPubKey:
printPubKey(cmd.OutOrStdout(), info, bechKeyOut)
case isShowAddr, isShowPubKey:
ko, err := bechKeyOut(info)
if err != nil {
return err
}
out := ko.Address
if isShowPubKey {
out = ko.PubKey
}
fmt.Fprintln(cmd.OutOrStdout(), out)
default:
printKeyInfo(cmd.OutOrStdout(), info, bechKeyOut, output)
}
@ -144,19 +154,20 @@ func runShowCmd(cmd *cobra.Command, args []string) (err error) {
}
func fetchKey(kb keyring.Keyring, keyref string) (keyring.Info, error) {
// firstly check if the keyref is a key name of a key registered in a keyring.
info, err := kb.Key(keyref)
if err != nil {
accAddr, err := sdk.AccAddressFromBech32(keyref)
if err != nil {
return info, err
}
info, err = kb.KeyByAddress(accAddr)
if err != nil {
return info, errors.New("key not found")
}
// if the key is not there or if we have a problem with a keyring itself then we move to a
// fallback: searching for key by address.
if err == nil || !sdkerr.IsOf(err, sdkerr.ErrIO, sdkerr.ErrKeyNotFound) {
return info, err
}
return info, nil
accAddr, err := sdk.AccAddressFromBech32(keyref)
if err != nil {
return info, err
}
info, err = kb.KeyByAddress(accAddr)
return info, sdkerr.Wrap(err, "Invalid key")
}
func validateMultisigThreshold(k, nKeys int) error {
@ -173,11 +184,11 @@ func validateMultisigThreshold(k, nKeys int) error {
func getBechKeyOut(bechPrefix string) (bechKeyOutFn, error) {
switch bechPrefix {
case sdk.PrefixAccount:
return keyring.Bech32KeyOutput, nil
return keyring.MkAccKeyOutput, nil
case sdk.PrefixValidator:
return keyring.Bech32ValKeyOutput, nil
return keyring.MkValKeyOutput, nil
case sdk.PrefixConsensus:
return keyring.Bech32ConsKeyOutput, nil
return keyring.MkConsKeyOutput, nil
}
return nil, fmt.Errorf("invalid Bech32 prefix encoding provided: %s", bechPrefix)

View File

@ -24,8 +24,8 @@ func Test_multiSigKey_Properties(t *testing.T) {
1,
[]cryptotypes.PubKey{tmpKey1.PubKey()},
)
tmp := keyring.NewMultiInfo("myMultisig", pk)
tmp, err := keyring.NewMultiInfo("myMultisig", pk)
require.NoError(t, err)
require.Equal(t, "myMultisig", tmp.GetName())
require.Equal(t, keyring.TypeMulti, tmp.GetType())
require.Equal(t, "D3923267FA8A3DD367BB768FA8BDC8FF7F89DA3F", tmp.GetPubKey().Address().String())
@ -48,7 +48,9 @@ func Test_runShowCmd(t *testing.T) {
kb, err := keyring.New(sdk.KeyringServiceName(), keyring.BackendTest, kbHome, mockIn)
require.NoError(t, err)
clientCtx := client.Context{}.WithKeyring(kb)
clientCtx := client.Context{}.
WithKeyringDir(kbHome).
WithKeyring(kb)
ctx := context.WithValue(context.Background(), client.ClientContextKey, &clientCtx)
cmd.SetArgs([]string{"invalid"})
@ -194,28 +196,20 @@ func Test_getBechKeyOut(t *testing.T) {
}{
{"empty", args{""}, nil, true},
{"wrong", args{"???"}, nil, true},
{"acc", args{sdk.PrefixAccount}, keyring.Bech32KeyOutput, false},
{"val", args{sdk.PrefixValidator}, keyring.Bech32ValKeyOutput, false},
{"cons", args{sdk.PrefixConsensus}, keyring.Bech32ConsKeyOutput, false},
{"acc", args{sdk.PrefixAccount}, keyring.MkAccKeyOutput, false},
{"val", args{sdk.PrefixValidator}, keyring.MkValKeyOutput, false},
{"cons", args{sdk.PrefixConsensus}, keyring.MkConsKeyOutput, false},
}
for _, tt := range tests {
tt := tt
t.Run(tt.name, func(t *testing.T) {
got, err := getBechKeyOut(tt.args.bechPrefix)
if (err != nil) != tt.wantErr {
t.Errorf("getBechKeyOut() error = %v, wantErr %v", err, tt.wantErr)
return
}
if !tt.wantErr {
if tt.wantErr {
require.Error(t, err)
} else {
require.NoError(t, err)
require.NotNil(t, got)
}
// TODO: Still not possible to compare functions
// Maybe in next release: https://github.com/stretchr/testify/issues/182
//if &got != &tt.want {
// t.Errorf("getBechKeyOut() = %v, want %v", got, tt.want)
//}
})
}
}

View File

@ -52,7 +52,7 @@ func printKeyInfo(w io.Writer, keyInfo cryptokeyring.Info, bechKeyOut bechKeyOut
}
func printInfos(w io.Writer, infos []cryptokeyring.Info, output string) {
kos, err := cryptokeyring.Bech32KeysOutput(infos)
kos, err := cryptokeyring.MkAccKeysOutput(infos)
if err != nil {
panic(err)
}
@ -78,21 +78,3 @@ func printTextInfos(w io.Writer, kos []cryptokeyring.KeyOutput) {
}
fmt.Fprintln(w, string(out))
}
func printKeyAddress(w io.Writer, info cryptokeyring.Info, bechKeyOut bechKeyOutFn) {
ko, err := bechKeyOut(info)
if err != nil {
panic(err)
}
fmt.Fprintln(w, ko.Address)
}
func printPubKey(w io.Writer, info cryptokeyring.Info, bechKeyOut bechKeyOutFn) {
ko, err := bechKeyOut(info)
if err != nil {
panic(err)
}
fmt.Fprintln(w, ko.PubKey)
}

View File

@ -6,6 +6,8 @@ import (
"strings"
"github.com/pkg/errors"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
abci "github.com/tendermint/tendermint/abci/types"
tmbytes "github.com/tendermint/tendermint/libs/bytes"
@ -13,6 +15,7 @@ import (
"github.com/cosmos/cosmos-sdk/store/rootmulti"
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
)
// GetNode returns an RPC client. If the context's client is not defined, an
@ -84,7 +87,7 @@ func (ctx Context) queryABCI(req abci.RequestQuery) (abci.ResponseQuery, error)
}
if !result.Response.IsOK() {
return abci.ResponseQuery{}, errors.New(result.Response.Log)
return abci.ResponseQuery{}, sdkErrorToGRPCError(result.Response)
}
// data from trusted node or subspace query doesn't need verification
@ -95,6 +98,19 @@ func (ctx Context) queryABCI(req abci.RequestQuery) (abci.ResponseQuery, error)
return result.Response, nil
}
func sdkErrorToGRPCError(resp abci.ResponseQuery) error {
switch resp.Code {
case sdkerrors.ErrInvalidRequest.ABCICode():
return status.Error(codes.InvalidArgument, resp.Log)
case sdkerrors.ErrUnauthorized.ABCICode():
return status.Error(codes.Unauthenticated, resp.Log)
case sdkerrors.ErrKeyNotFound.ABCICode():
return status.Error(codes.NotFound, resp.Log)
default:
return status.Error(codes.Unknown, resp.Log)
}
}
// query performs a query to a Tendermint node with the provided store name
// and path. It returns the result and height of the query upon success
// or an error if the query fails.

View File

@ -9,7 +9,6 @@ import (
"github.com/gorilla/mux"
"github.com/spf13/cobra"
tmtypes "github.com/tendermint/tendermint/types"
"github.com/cosmos/cosmos-sdk/client"
@ -67,7 +66,7 @@ func ValidatorCommand() *cobra.Command {
return cmd
}
// Validator output in bech32 format
// Validator output
type ValidatorOutput struct {
Address sdk.ConsAddress `json:"address"`
PubKey cryptotypes.PubKey `json:"pub_key"`
@ -135,21 +134,19 @@ func GetValidators(ctx context.Context, clientCtx client.Context, height *int64,
if validatorsRes.Total < 0 {
total = 0
}
outputValidatorsRes := ResultValidatorsOutput{
out := ResultValidatorsOutput{
BlockHeight: validatorsRes.BlockHeight,
Validators: make([]ValidatorOutput, len(validatorsRes.Validators)),
Total: uint64(total),
}
for i := 0; i < len(validatorsRes.Validators); i++ {
outputValidatorsRes.Validators[i], err = validatorOutput(validatorsRes.Validators[i])
out.Validators[i], err = validatorOutput(validatorsRes.Validators[i])
if err != nil {
return ResultValidatorsOutput{}, err
return out, err
}
}
return outputValidatorsRes, nil
return out, nil
}
// REST

View File

@ -38,7 +38,7 @@ func NewFactoryCLI(clientCtx client.Context, flagSet *pflag.FlagSet) Factory {
case flags.SignModeDirect:
signMode = signing.SignMode_SIGN_MODE_DIRECT
case flags.SignModeLegacyAminoJSON:
signMode = signing.SignMode_SIGN_MODE_LEGACY_AMINO_JSON
signMode = signing.SignMode_SIGN_MODE_LEGACY_AMINO_JSON //nolint:staticcheck
}
accNum, _ := flagSet.GetUint64(flags.FlagAccountNumber)

View File

@ -2,11 +2,13 @@ package tx
import (
"bufio"
"context"
"errors"
"fmt"
"net/http"
"os"
gogogrpc "github.com/gogo/protobuf/grpc"
"github.com/spf13/pflag"
"github.com/cosmos/cosmos-sdk/client"
@ -20,7 +22,6 @@ import (
"github.com/cosmos/cosmos-sdk/types/tx"
"github.com/cosmos/cosmos-sdk/types/tx/signing"
authsigning "github.com/cosmos/cosmos-sdk/x/auth/signing"
authtx "github.com/cosmos/cosmos-sdk/x/auth/tx"
)
// GenerateOrBroadcastTxCLI will either generate and print and unsigned transaction
@ -50,7 +51,7 @@ func GenerateTx(clientCtx client.Context, txf Factory, msgs ...sdk.Msg) error {
return errors.New("cannot estimate gas in offline mode")
}
_, adjusted, err := CalculateGas(clientCtx.QueryWithData, txf, msgs...)
_, adjusted, err := CalculateGas(clientCtx, txf, msgs...)
if err != nil {
return err
}
@ -76,13 +77,13 @@ func GenerateTx(clientCtx client.Context, txf Factory, msgs ...sdk.Msg) error {
// given set of messages. It will also simulate gas requirements if necessary.
// It will return an error upon failure.
func BroadcastTx(clientCtx client.Context, txf Factory, msgs ...sdk.Msg) error {
txf, err := PrepareFactory(clientCtx, txf)
txf, err := prepareFactory(clientCtx, txf)
if err != nil {
return err
}
if txf.SimulateAndExecute() || clientCtx.Simulate {
_, adjusted, err := CalculateGas(clientCtx.QueryWithData, txf, msgs...)
_, adjusted, err := CalculateGas(clientCtx, txf, msgs...)
if err != nil {
return err
}
@ -142,8 +143,9 @@ func BroadcastTx(clientCtx client.Context, txf Factory, msgs ...sdk.Msg) error {
// BaseReq. Upon any error, the error will be written to the http.ResponseWriter.
// Note that this function returns the legacy StdTx Amino JSON format for compatibility
// with legacy clients.
// Deprecated: We are removing Amino soon.
func WriteGeneratedTxResponse(
ctx client.Context, w http.ResponseWriter, br rest.BaseReq, msgs ...sdk.Msg,
clientCtx client.Context, w http.ResponseWriter, br rest.BaseReq, msgs ...sdk.Msg,
) {
gasAdj, ok := rest.ParseFloat64OrReturnBadRequest(w, br.GasAdjustment, flags.DefaultGasAdjustment)
if !ok {
@ -163,7 +165,7 @@ func WriteGeneratedTxResponse(
WithMemo(br.Memo).
WithChainID(br.ChainID).
WithSimulateAndExecute(br.Simulate).
WithTxConfig(ctx.TxConfig).
WithTxConfig(clientCtx.TxConfig).
WithTimeoutHeight(br.TimeoutHeight)
if br.Simulate || gasSetting.Simulate {
@ -172,7 +174,7 @@ func WriteGeneratedTxResponse(
return
}
_, adjusted, err := CalculateGas(ctx.QueryWithData, txf, msgs...)
_, adjusted, err := CalculateGas(clientCtx, txf, msgs...)
if rest.CheckInternalServerError(w, err) {
return
}
@ -180,7 +182,7 @@ func WriteGeneratedTxResponse(
txf = txf.WithGas(adjusted)
if br.Simulate {
rest.WriteSimulationResponse(w, ctx.LegacyAmino, txf.Gas())
rest.WriteSimulationResponse(w, clientCtx.LegacyAmino, txf.Gas())
return
}
}
@ -190,12 +192,12 @@ func WriteGeneratedTxResponse(
return
}
stdTx, err := ConvertTxToStdTx(ctx.LegacyAmino, tx.GetTx())
stdTx, err := ConvertTxToStdTx(clientCtx.LegacyAmino, tx.GetTx())
if rest.CheckInternalServerError(w, err) {
return
}
output, err := ctx.LegacyAmino.MarshalJSON(stdTx)
output, err := clientCtx.LegacyAmino.MarshalJSON(stdTx)
if rest.CheckInternalServerError(w, err) {
return
}
@ -268,46 +270,35 @@ func BuildSimTx(txf Factory, msgs ...sdk.Msg) ([]byte, error) {
return nil, err
}
protoProvider, ok := txb.(authtx.ProtoTxProvider)
if !ok {
return nil, fmt.Errorf("cannot simulate amino tx")
}
simReq := tx.SimulateRequest{Tx: protoProvider.GetProtoTx()}
return simReq.Marshal()
return txf.txConfig.TxEncoder()(txb.GetTx())
}
// CalculateGas simulates the execution of a transaction and returns the
// simulation response obtained by the query and the adjusted gas amount.
func CalculateGas(
queryFunc func(string, []byte) ([]byte, int64, error), txf Factory, msgs ...sdk.Msg,
) (tx.SimulateResponse, uint64, error) {
clientCtx gogogrpc.ClientConn, txf Factory, msgs ...sdk.Msg,
) (*tx.SimulateResponse, uint64, error) {
txBytes, err := BuildSimTx(txf, msgs...)
if err != nil {
return tx.SimulateResponse{}, 0, err
return nil, 0, err
}
// TODO This should use the generated tx service Client.
// https://github.com/cosmos/cosmos-sdk/issues/7726
bz, _, err := queryFunc("/cosmos.tx.v1beta1.Service/Simulate", txBytes)
txSvcClient := tx.NewServiceClient(clientCtx)
simRes, err := txSvcClient.Simulate(context.Background(), &tx.SimulateRequest{
TxBytes: txBytes,
})
if err != nil {
return tx.SimulateResponse{}, 0, err
}
var simRes tx.SimulateResponse
if err := simRes.Unmarshal(bz); err != nil {
return tx.SimulateResponse{}, 0, err
return nil, 0, err
}
return simRes, uint64(txf.GasAdjustment() * float64(simRes.GasInfo.GasUsed)), nil
}
// PrepareFactory ensures the account defined by ctx.GetFromAddress() exists and
// prepareFactory ensures the account defined by ctx.GetFromAddress() exists and
// if the account number and/or the account sequence number are zero (not set),
// they will be queried for and set on the provided Factory. A new Factory with
// the updated fields will be returned.
func PrepareFactory(clientCtx client.Context, txf Factory) (Factory, error) {
func prepareFactory(clientCtx client.Context, txf Factory) (Factory, error) {
from := clientCtx.GetFromAddress()
if err := txf.accountRetriever.EnsureExists(clientCtx, from); err != nil {

View File

@ -1,10 +1,12 @@
package tx_test
import (
"errors"
gocontext "context"
"fmt"
"testing"
"github.com/stretchr/testify/require"
"google.golang.org/grpc"
"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/client/tx"
@ -24,30 +26,34 @@ func NewTestTxConfig() client.TxConfig {
return cfg.TxConfig
}
func TestCalculateGas(t *testing.T) {
makeQueryFunc := func(gasUsed uint64, wantErr bool) func(string, []byte) ([]byte, int64, error) {
return func(string, []byte) ([]byte, int64, error) {
if wantErr {
return nil, 0, errors.New("query failed")
}
simRes := &txtypes.SimulateResponse{
GasInfo: &sdk.GasInfo{GasUsed: gasUsed, GasWanted: gasUsed},
Result: &sdk.Result{Data: []byte("tx data"), Log: "log"},
}
// mockContext is a mock client.Context to return abitrary simulation response, used to
// unit test CalculateGas.
type mockContext struct {
gasUsed uint64
wantErr bool
}
bz, err := simRes.Marshal()
if err != nil {
return nil, 0, err
}
return bz, 0, nil
}
func (m mockContext) Invoke(grpcCtx gocontext.Context, method string, req, reply interface{}, opts ...grpc.CallOption) (err error) {
if m.wantErr {
return fmt.Errorf("mock err")
}
*(reply.(*txtypes.SimulateResponse)) = txtypes.SimulateResponse{
GasInfo: &sdk.GasInfo{GasUsed: m.gasUsed, GasWanted: m.gasUsed},
Result: &sdk.Result{Data: []byte("tx data"), Log: "log"},
}
return nil
}
func (mockContext) NewStream(gocontext.Context, *grpc.StreamDesc, string, ...grpc.CallOption) (grpc.ClientStream, error) {
panic("not implemented")
}
func TestCalculateGas(t *testing.T) {
type args struct {
queryFuncGasUsed uint64
queryFuncWantErr bool
adjustment float64
mockGasUsed uint64
mockWantErr bool
adjustment float64
}
testCases := []struct {
@ -70,8 +76,11 @@ func TestCalculateGas(t *testing.T) {
WithTxConfig(txCfg).WithSignMode(txCfg.SignModeHandler().DefaultMode())
t.Run(stc.name, func(t *testing.T) {
queryFunc := makeQueryFunc(stc.args.queryFuncGasUsed, stc.args.queryFuncWantErr)
simRes, gotAdjusted, err := tx.CalculateGas(queryFunc, txf.WithGasAdjustment(stc.args.adjustment))
mockClientCtx := mockContext{
gasUsed: tc.args.mockGasUsed,
wantErr: tc.args.mockWantErr,
}
simRes, gotAdjusted, err := tx.CalculateGas(mockClientCtx, txf.WithGasAdjustment(stc.args.adjustment))
if stc.expPass {
require.NoError(t, err)
require.Equal(t, simRes.GasInfo.GasUsed, stc.wantEstimate)
@ -79,7 +88,7 @@ func TestCalculateGas(t *testing.T) {
require.NotNil(t, simRes.Result)
} else {
require.Error(t, err)
require.Nil(t, simRes.Result)
require.Nil(t, simRes)
}
})
}

View File

@ -2,6 +2,7 @@ package client
import (
"github.com/spf13/pflag"
rpchttp "github.com/tendermint/tendermint/rpc/client/http"
"github.com/cosmos/cosmos-sdk/client/flags"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
@ -51,6 +52,7 @@ func ReadPageRequest(flagSet *pflag.FlagSet) (*query.PageRequest, error) {
limit, _ := flagSet.GetUint64(flags.FlagLimit)
countTotal, _ := flagSet.GetBool(flags.FlagCountTotal)
page, _ := flagSet.GetUint64(flags.FlagPage)
reverse, _ := flagSet.GetBool(flags.FlagReverse)
if page > 1 && offset > 0 {
return nil, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "page and offset cannot be used together")
@ -65,5 +67,14 @@ func ReadPageRequest(flagSet *pflag.FlagSet) (*query.PageRequest, error) {
Offset: offset,
Limit: limit,
CountTotal: countTotal,
Reverse: reverse,
}, nil
}
// NewClientFromNode sets up Client implementation that communicates with a Tendermint node over
// JSON RPC and WebSockets
// TODO: We might not need to manually append `/websocket`:
// https://github.com/cosmos/cosmos-sdk/issues/8986
func NewClientFromNode(nodeURI string) (*rpchttp.HTTP, error) {
return rpchttp.New(nodeURI, "/websocket")
}

View File

@ -7,6 +7,10 @@ import (
"github.com/cosmos/cosmos-sdk/codec"
"github.com/cosmos/cosmos-sdk/codec/types"
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
"github.com/cosmos/cosmos-sdk/crypto/keys/ed25519"
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
"github.com/cosmos/cosmos-sdk/simapp"
"github.com/cosmos/cosmos-sdk/testutil/testdata"
)
@ -53,3 +57,80 @@ func TestMarshalAny(t *testing.T) {
err = cdc.UnmarshalInterface(bz, nil)
require.Error(t, err)
}
func TestMarshalProtoPubKey(t *testing.T) {
require := require.New(t)
ccfg := simapp.MakeTestEncodingConfig()
privKey := ed25519.GenPrivKey()
pk := privKey.PubKey()
// **** test JSON serialization ****
pkAny, err := codectypes.NewAnyWithValue(pk)
require.NoError(err)
bz, err := ccfg.Marshaler.MarshalJSON(pkAny)
require.NoError(err)
var pkAny2 codectypes.Any
err = ccfg.Marshaler.UnmarshalJSON(bz, &pkAny2)
require.NoError(err)
// Before getting a cached value we need to unpack it.
// Normally this happens in types which implement UnpackInterfaces
var pkI cryptotypes.PubKey
err = ccfg.InterfaceRegistry.UnpackAny(&pkAny2, &pkI)
require.NoError(err)
var pk2 = pkAny2.GetCachedValue().(cryptotypes.PubKey)
require.True(pk2.Equals(pk))
// **** test binary serialization ****
bz, err = ccfg.Marshaler.MarshalBinaryBare(pkAny)
require.NoError(err)
var pkAny3 codectypes.Any
err = ccfg.Marshaler.UnmarshalBinaryBare(bz, &pkAny3)
require.NoError(err)
err = ccfg.InterfaceRegistry.UnpackAny(&pkAny3, &pkI)
require.NoError(err)
var pk3 = pkAny3.GetCachedValue().(cryptotypes.PubKey)
require.True(pk3.Equals(pk))
}
// TestMarshalProtoInterfacePubKey tests PubKey marshaling using (Un)marshalInterface
// helper functions
func TestMarshalProtoInterfacePubKey(t *testing.T) {
require := require.New(t)
ccfg := simapp.MakeTestEncodingConfig()
privKey := ed25519.GenPrivKey()
pk := privKey.PubKey()
// **** test JSON serialization ****
bz, err := ccfg.Marshaler.MarshalInterfaceJSON(pk)
require.NoError(err)
var pk3 cryptotypes.PubKey
err = ccfg.Marshaler.UnmarshalInterfaceJSON(bz, &pk3)
require.NoError(err)
require.True(pk3.Equals(pk))
// ** Check unmarshal using JSONMarshaler **
// Unpacking won't work straightforward s Any type
// Any can't implement UnpackInterfacesMessage interface. So Any is not
// automatically unpacked and we won't get a value.
var pkAny codectypes.Any
err = ccfg.Marshaler.UnmarshalJSON(bz, &pkAny)
require.NoError(err)
ifc := pkAny.GetCachedValue()
require.Nil(ifc)
// **** test binary serialization ****
bz, err = ccfg.Marshaler.MarshalInterface(pk)
require.NoError(err)
var pk2 cryptotypes.PubKey
err = ccfg.Marshaler.UnmarshalInterface(bz, &pk2)
require.NoError(err)
require.True(pk2.Equals(pk))
}

View File

@ -3,25 +3,29 @@ package codec
import (
"bytes"
"github.com/cosmos/cosmos-sdk/codec/types"
"github.com/gogo/protobuf/jsonpb"
"github.com/gogo/protobuf/proto"
"github.com/cosmos/cosmos-sdk/codec/types"
)
var defaultJM = &jsonpb.Marshaler{OrigName: true, EmitDefaults: true, AnyResolver: nil}
// ProtoMarshalJSON provides an auxiliary function to return Proto3 JSON encoded
// bytes of a message.
func ProtoMarshalJSON(msg proto.Message, resolver jsonpb.AnyResolver) ([]byte, error) {
// We use the OrigName because camel casing fields just doesn't make sense.
// EmitDefaults is also often the more expected behavior for CLI users
jm := &jsonpb.Marshaler{OrigName: true, EmitDefaults: true, AnyResolver: resolver}
jm := defaultJM
if resolver != nil {
jm = &jsonpb.Marshaler{OrigName: true, EmitDefaults: true, AnyResolver: resolver}
}
err := types.UnpackInterfaces(msg, types.ProtoJSONPacker{JSONPBMarshaler: jm})
if err != nil {
return nil, err
}
buf := new(bytes.Buffer)
if err := jm.Marshal(buf, msg); err != nil {
return nil, err
}

View File

@ -34,11 +34,15 @@ func NewProtoCodec(interfaceRegistry types.InterfaceRegistry) *ProtoCodec {
}
// MarshalBinaryBare implements BinaryMarshaler.MarshalBinaryBare method.
// NOTE: this function must be used with a concrete type which
// implements proto.Message. For interface please use the codec.MarshalInterface
func (pc *ProtoCodec) MarshalBinaryBare(o ProtoMarshaler) ([]byte, error) {
return o.Marshal()
}
// MustMarshalBinaryBare implements BinaryMarshaler.MustMarshalBinaryBare method.
// NOTE: this function must be used with a concrete type which
// implements proto.Message. For interface please use the codec.MarshalInterface
func (pc *ProtoCodec) MustMarshalBinaryBare(o ProtoMarshaler) []byte {
bz, err := pc.MarshalBinaryBare(o)
if err != nil {
@ -71,6 +75,8 @@ func (pc *ProtoCodec) MustMarshalBinaryLengthPrefixed(o ProtoMarshaler) []byte {
}
// UnmarshalBinaryBare implements BinaryMarshaler.UnmarshalBinaryBare method.
// NOTE: this function must be used with a concrete type which
// implements proto.Message. For interface please use the codec.UnmarshalInterface
func (pc *ProtoCodec) UnmarshalBinaryBare(bz []byte, ptr ProtoMarshaler) error {
err := ptr.Unmarshal(bz)
if err != nil {
@ -84,6 +90,8 @@ func (pc *ProtoCodec) UnmarshalBinaryBare(bz []byte, ptr ProtoMarshaler) error {
}
// MustUnmarshalBinaryBare implements BinaryMarshaler.MustUnmarshalBinaryBare method.
// NOTE: this function must be used with a concrete type which
// implements proto.Message. For interface please use the codec.UnmarshalInterface
func (pc *ProtoCodec) MustUnmarshalBinaryBare(bz []byte, ptr ProtoMarshaler) {
if err := pc.UnmarshalBinaryBare(bz, ptr); err != nil {
panic(err)
@ -116,6 +124,8 @@ func (pc *ProtoCodec) MustUnmarshalBinaryLengthPrefixed(bz []byte, ptr ProtoMars
// MarshalJSON implements JSONMarshaler.MarshalJSON method,
// it marshals to JSON using proto codec.
// NOTE: this function must be used with a concrete type which
// implements proto.Message. For interface please use the codec.MarshalInterfaceJSON
func (pc *ProtoCodec) MarshalJSON(o proto.Message) ([]byte, error) {
m, ok := o.(ProtoMarshaler)
if !ok {
@ -127,6 +137,8 @@ func (pc *ProtoCodec) MarshalJSON(o proto.Message) ([]byte, error) {
// MustMarshalJSON implements JSONMarshaler.MustMarshalJSON method,
// it executes MarshalJSON except it panics upon failure.
// NOTE: this function must be used with a concrete type which
// implements proto.Message. For interface please use the codec.MarshalInterfaceJSON
func (pc *ProtoCodec) MustMarshalJSON(o proto.Message) []byte {
bz, err := pc.MarshalJSON(o)
if err != nil {
@ -138,6 +150,8 @@ func (pc *ProtoCodec) MustMarshalJSON(o proto.Message) []byte {
// UnmarshalJSON implements JSONMarshaler.UnmarshalJSON method,
// it unmarshals from JSON using proto codec.
// NOTE: this function must be used with a concrete type which
// implements proto.Message. For interface please use the codec.UnmarshalInterfaceJSON
func (pc *ProtoCodec) UnmarshalJSON(bz []byte, ptr proto.Message) error {
m, ok := ptr.(ProtoMarshaler)
if !ok {
@ -155,6 +169,8 @@ func (pc *ProtoCodec) UnmarshalJSON(bz []byte, ptr proto.Message) error {
// MustUnmarshalJSON implements JSONMarshaler.MustUnmarshalJSON method,
// it executes UnmarshalJSON except it panics upon failure.
// NOTE: this function must be used with a concrete type which
// implements proto.Message. For interface please use the codec.UnmarshalInterfaceJSON
func (pc *ProtoCodec) MustUnmarshalJSON(bz []byte, ptr proto.Message) {
if err := pc.UnmarshalJSON(bz, ptr); err != nil {
panic(err)
@ -229,6 +245,7 @@ func (pc *ProtoCodec) UnpackAny(any *types.Any, iface interface{}) error {
return pc.interfaceRegistry.UnpackAny(any, iface)
}
// InterfaceRegistry returns InterfaceRegistry
func (pc *ProtoCodec) InterfaceRegistry() types.InterfaceRegistry {
return pc.interfaceRegistry
}

View File

@ -37,7 +37,7 @@ func anyCompatError(errType string, x interface{}) error {
func (any Any) MarshalAmino() ([]byte, error) {
ac := any.compat
if ac == nil {
return nil, anyCompatError("amino binary unmarshal", any)
return nil, anyCompatError("amino binary marshal", any)
}
return ac.aminoBz, ac.err
}

View File

@ -1,7 +1,7 @@
[
{
"account_identifier": {
"address":"cosmos1ujtnemf6jmfm995j000qdry064n5lq854gfe3j"
"address":"cosmos1trf09zvqeuc722zyeg34pra8qaqll9ddw0qy8q"
},
"currency":{
"symbol":"stake",

Binary file not shown.

View File

@ -177,6 +177,10 @@ func (i offlineInfo) GetPath() (*hd.BIP44Params, error) {
return nil, fmt.Errorf("BIP44 Paths are not available for this type")
}
// Deprecated: this structure is not used anymore and it's here only to allow
// decoding old multiInfo records from keyring.
// The problem with legacy.Cdc.UnmarshalBinaryLengthPrefixed - the legacy codec doesn't
// tolerate extensibility.
type multisigPubKeyInfo struct {
PubKey cryptotypes.PubKey `json:"pubkey"`
Weight uint `json:"weight"`
@ -191,21 +195,14 @@ type multiInfo struct {
}
// NewMultiInfo creates a new multiInfo instance
func NewMultiInfo(name string, pub cryptotypes.PubKey) Info {
multiPK := pub.(*multisig.LegacyAminoPubKey)
pubKeys := make([]multisigPubKeyInfo, len(multiPK.PubKeys))
for i, pk := range multiPK.GetPubKeys() {
// TODO: Recursively check pk for total weight?
pubKeys[i] = multisigPubKeyInfo{pk, 1}
func NewMultiInfo(name string, pub cryptotypes.PubKey) (Info, error) {
if _, ok := pub.(*multisig.LegacyAminoPubKey); !ok {
return nil, fmt.Errorf("MultiInfo supports only multisig.LegacyAminoPubKey, got %T", pub)
}
return &multiInfo{
Name: name,
PubKey: pub,
Threshold: uint(multiPK.Threshold),
PubKeys: pubKeys,
}
Name: name,
PubKey: pub,
}, nil
}
// GetType implements Info interface

View File

@ -437,7 +437,7 @@ func (ks keystore) Delete(uid string) error {
return err
}
err = ks.db.Remove(string(infoKey(uid)))
err = ks.db.Remove(infoKey(uid))
if err != nil {
return err
}
@ -448,19 +448,20 @@ func (ks keystore) Delete(uid string) error {
func (ks keystore) KeyByAddress(address sdk.Address) (Info, error) {
ik, err := ks.db.Get(addrHexKeyAsString(address))
if err != nil {
return nil, err
return nil, wrapKeyNotFound(err, fmt.Sprint("key with address", address, "not found"))
}
if len(ik.Data) == 0 {
return nil, fmt.Errorf("key with address %s not found", address)
return nil, wrapKeyNotFound(err, fmt.Sprint("key with address", address, "not found"))
}
return ks.key(string(ik.Data))
}
bs, err := ks.db.Get(string(ik.Data))
if err != nil {
return nil, err
func wrapKeyNotFound(err error, msg string) error {
if err == keyring.ErrKeyNotFound {
return sdkerrors.Wrap(sdkerrors.ErrKeyNotFound, msg)
}
return unmarshalInfo(bs.Data)
return err
}
func (ks keystore) List() ([]Info, error) {
@ -529,7 +530,7 @@ func (ks keystore) NewMnemonic(uid string, language Language, hdPath, bip39Passp
return info, mnemonic, nil
}
func (ks keystore) NewAccount(uid string, mnemonic string, bip39Passphrase string, hdPath string, algo SignatureAlgo) (Info, error) {
func (ks keystore) NewAccount(name string, mnemonic string, bip39Passphrase string, hdPath string, algo SignatureAlgo) (Info, error) {
if !ks.isSupportedSigningAlgo(algo) {
return nil, ErrUnsupportedSigningAlgo
}
@ -549,28 +550,28 @@ func (ks keystore) NewAccount(uid string, mnemonic string, bip39Passphrase strin
return nil, fmt.Errorf("account with address %s already exists in keyring, delete the key first if you want to recreate it", address)
}
return ks.writeLocalKey(uid, privKey, algo.Name())
return ks.writeLocalKey(name, privKey, algo.Name())
}
func (ks keystore) isSupportedSigningAlgo(algo SignatureAlgo) bool {
return ks.options.SupportedAlgos.Contains(algo)
}
func (ks keystore) Key(uid string) (Info, error) {
key := infoKey(uid)
bs, err := ks.db.Get(string(key))
func (ks keystore) key(infoKey string) (Info, error) {
bs, err := ks.db.Get(infoKey)
if err != nil {
return nil, err
return nil, wrapKeyNotFound(err, infoKey)
}
if len(bs.Data) == 0 {
return nil, sdkerrors.Wrap(sdkerrors.ErrKeyNotFound, uid)
return nil, sdkerrors.Wrap(sdkerrors.ErrKeyNotFound, infoKey)
}
return unmarshalInfo(bs.Data)
}
func (ks keystore) Key(uid string) (Info, error) {
return ks.key(infoKey(uid))
}
// SupportedAlgorithms returns the keystore Options' supported signing algorithm.
// for the keyring and Ledger.
func (ks keystore) SupportedAlgorithms() (SigningAlgoList, SigningAlgoList) {
@ -742,7 +743,6 @@ func newRealPrompt(dir string, buf io.Reader) func(string) (string, error) {
func (ks keystore) writeLocalKey(name string, priv types.PrivKey, algo hd.PubKeyType) (Info, error) {
// encrypt private key using keyring
pub := priv.PubKey()
info := newLocalInfo(name, pub, string(legacy.Cdc.MustMarshalBinaryBare(priv)), algo)
if err := ks.writeInfo(info); err != nil {
return nil, err
@ -752,18 +752,16 @@ func (ks keystore) writeLocalKey(name string, priv types.PrivKey, algo hd.PubKey
}
func (ks keystore) writeInfo(info Info) error {
// write the info by key
key := infoKey(info.GetName())
key := infoKeyBz(info.GetName())
serializedInfo := marshalInfo(info)
exists, err := ks.existsInDb(info)
if exists {
return errors.New("public key already exist in keybase")
}
if err != nil {
return err
}
if exists {
return errors.New("public key already exist in keybase")
}
err = ks.db.Set(keyring.Item{
Key: string(key),
@ -784,6 +782,8 @@ func (ks keystore) writeInfo(info Info) error {
return nil
}
// existsInDb returns true if key is in DB. Error is returned only when we have error
// different thant ErrKeyNotFound
func (ks keystore) existsInDb(info Info) (bool, error) {
if _, err := ks.db.Get(addrHexKeyAsString(info.GetAddress())); err == nil {
return true, nil // address lookup succeeds - info exists
@ -791,7 +791,7 @@ func (ks keystore) existsInDb(info Info) (bool, error) {
return false, err // received unexpected error - returns error
}
if _, err := ks.db.Get(string(infoKey(info.GetName()))); err == nil {
if _, err := ks.db.Get(infoKey(info.GetName())); err == nil {
return true, nil // uid lookup succeeds - info exists
} else if err != keyring.ErrKeyNotFound {
return false, err // received unexpected error - returns
@ -812,11 +812,13 @@ func (ks keystore) writeOfflineKey(name string, pub types.PubKey, algo hd.PubKey
}
func (ks keystore) writeMultisigKey(name string, pub types.PubKey) (Info, error) {
info := NewMultiInfo(name, pub)
err := ks.writeInfo(info)
info, err := NewMultiInfo(name, pub)
if err != nil {
return nil, err
}
if err = ks.writeInfo(info); err != nil {
return nil, err
}
return info, nil
}

View File

@ -10,7 +10,6 @@ import (
"github.com/cosmos/cosmos-sdk/crypto/hd"
"github.com/cosmos/cosmos-sdk/types"
sdk "github.com/cosmos/cosmos-sdk/types"
)
func TestInMemoryCreateLedger(t *testing.T) {
@ -28,9 +27,8 @@ func TestInMemoryCreateLedger(t *testing.T) {
// The mock is available, check that the address is correct
pubKey := ledger.GetPubKey()
pk, err := sdk.Bech32ifyPubKey(sdk.Bech32PubKeyTypeAccPub, pubKey)
require.NoError(t, err)
require.Equal(t, "cosmospub1addwnpepqdszcr95mrqqs8lw099aa9h8h906zmet22pmwe9vquzcgvnm93eqygufdlv", pk)
expectedPkStr := "PubKeySecp256k1{03602C0CB4D8C0081FEE794BDE96E7B95FA16F2B5283B764AC070584327B2C7202}"
require.Equal(t, expectedPkStr, pubKey.String())
// Check that restoring the key gets the same results
restoredKey, err := kb.Key("some_account")
@ -39,9 +37,7 @@ func TestInMemoryCreateLedger(t *testing.T) {
require.Equal(t, "some_account", restoredKey.GetName())
require.Equal(t, TypeLedger, restoredKey.GetType())
pubKey = restoredKey.GetPubKey()
pk, err = sdk.Bech32ifyPubKey(sdk.Bech32PubKeyTypeAccPub, pubKey)
require.NoError(t, err)
require.Equal(t, "cosmospub1addwnpepqdszcr95mrqqs8lw099aa9h8h906zmet22pmwe9vquzcgvnm93eqygufdlv", pk)
require.Equal(t, expectedPkStr, pubKey.String())
path, err := restoredKey.GetPath()
require.NoError(t, err)
@ -106,9 +102,8 @@ func TestAltKeyring_SaveLedgerKey(t *testing.T) {
// The mock is available, check that the address is correct
require.Equal(t, "some_account", ledger.GetName())
pubKey := ledger.GetPubKey()
pk, err := sdk.Bech32ifyPubKey(sdk.Bech32PubKeyTypeAccPub, pubKey)
require.NoError(t, err)
require.Equal(t, "cosmospub1addwnpepqdszcr95mrqqs8lw099aa9h8h906zmet22pmwe9vquzcgvnm93eqygufdlv", pk)
expectedPkStr := "PubKeySecp256k1{03602C0CB4D8C0081FEE794BDE96E7B95FA16F2B5283B764AC070584327B2C7202}"
require.Equal(t, expectedPkStr, pubKey.String())
// Check that restoring the key gets the same results
restoredKey, err := keyring.Key("some_account")
@ -117,9 +112,7 @@ func TestAltKeyring_SaveLedgerKey(t *testing.T) {
require.Equal(t, "some_account", restoredKey.GetName())
require.Equal(t, TypeLedger, restoredKey.GetType())
pubKey = restoredKey.GetPubKey()
pk, err = sdk.Bech32ifyPubKey(sdk.Bech32PubKeyTypeAccPub, pubKey)
require.NoError(t, err)
require.Equal(t, "cosmospub1addwnpepqdszcr95mrqqs8lw099aa9h8h906zmet22pmwe9vquzcgvnm93eqygufdlv", pk)
require.Equal(t, expectedPkStr, pubKey.String())
path, err := restoredKey.GetPath()
require.NoError(t, err)

View File

@ -367,7 +367,7 @@ func TestKeyringKeybaseExportImportPrivKey(t *testing.T) {
// try export non existing key
_, err = kb.ExportPrivKeyArmor("john3", "wrongpassword")
require.Equal(t, "The specified item could not be found in the keyring", err.Error())
require.EqualError(t, err, "john3.info: key not found")
}
func TestInMemoryLanguage(t *testing.T) {

View File

@ -85,7 +85,7 @@ func (kb dbKeybase) List() ([]Info, error) {
// Get returns the public information about one key.
func (kb dbKeybase) Get(name string) (Info, error) {
bs, err := kb.db.Get(infoKey(name))
bs, err := kb.db.Get(infoKeyBz(name))
if err != nil {
return nil, err
}
@ -129,7 +129,7 @@ func (kb dbKeybase) ExportPrivateKeyObject(name string, passphrase string) (type
}
func (kb dbKeybase) Export(name string) (armor string, err error) {
bz, err := kb.db.Get(infoKey(name))
bz, err := kb.db.Get(infoKeyBz(name))
if err != nil {
return "", err
}
@ -144,7 +144,7 @@ func (kb dbKeybase) Export(name string) (armor string, err error) {
// ExportPubKey returns public keys in ASCII armored format. It retrieves a Info
// object by its name and return the public key in a portable format.
func (kb dbKeybase) ExportPubKey(name string) (armor string, err error) {
bz, err := kb.db.Get(infoKey(name))
bz, err := kb.db.Get(infoKeyBz(name))
if err != nil {
return "", err
}
@ -182,7 +182,8 @@ func (kb dbKeybase) ExportPrivKey(name string, decryptPassphrase string,
// Close the underlying storage.
func (kb dbKeybase) Close() error { return kb.db.Close() }
func infoKey(name string) []byte { return []byte(fmt.Sprintf("%s.%s", name, infoSuffix)) }
func infoKey(name string) string { return fmt.Sprintf("%s.%s", name, infoSuffix) }
func infoKeyBz(name string) []byte { return []byte(infoKey(name)) }
// KeybaseOption overrides options for the db.
type KeybaseOption func(*kbOptions)

View File

@ -1,106 +1,78 @@
package keyring
import (
"github.com/cosmos/cosmos-sdk/codec"
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
sdk "github.com/cosmos/cosmos-sdk/types"
)
// TODO: Move this file to client/keys
// Use protobuf interface marshaler rather then generic JSON
// KeyOutput defines a structure wrapping around an Info object used for output
// functionality.
type KeyOutput struct {
Name string `json:"name" yaml:"name"`
Type string `json:"type" yaml:"type"`
Address string `json:"address" yaml:"address"`
PubKey string `json:"pubkey" yaml:"pubkey"`
Mnemonic string `json:"mnemonic,omitempty" yaml:"mnemonic"`
Threshold uint `json:"threshold,omitempty" yaml:"threshold"`
PubKeys []multisigPubKeyOutput `json:"pubkeys,omitempty" yaml:"pubkeys"`
Name string `json:"name" yaml:"name"`
Type string `json:"type" yaml:"type"`
Address string `json:"address" yaml:"address"`
PubKey string `json:"pubkey" yaml:"pubkey"`
Mnemonic string `json:"mnemonic,omitempty" yaml:"mnemonic"`
}
// NewKeyOutput creates a default KeyOutput instance without Mnemonic, Threshold and PubKeys
func NewKeyOutput(name, keyType, address, pubkey string) KeyOutput {
func NewKeyOutput(name string, keyType KeyType, a sdk.Address, pk cryptotypes.PubKey) (KeyOutput, error) { // nolint:interfacer
apk, err := codectypes.NewAnyWithValue(pk)
if err != nil {
return KeyOutput{}, err
}
bz, err := codec.ProtoMarshalJSON(apk, nil)
if err != nil {
return KeyOutput{}, err
}
return KeyOutput{
Name: name,
Type: keyType,
Address: address,
PubKey: pubkey,
}
Type: keyType.String(),
Address: a.String(),
PubKey: string(bz),
}, nil
}
type multisigPubKeyOutput struct {
Address string `json:"address" yaml:"address"`
PubKey string `json:"pubkey" yaml:"pubkey"`
Weight uint `json:"weight" yaml:"weight"`
// MkConsKeyOutput create a KeyOutput in with "cons" Bech32 prefixes.
func MkConsKeyOutput(keyInfo Info) (KeyOutput, error) {
pk := keyInfo.GetPubKey()
addr := sdk.ConsAddress(pk.Address())
return NewKeyOutput(keyInfo.GetName(), keyInfo.GetType(), addr, pk)
}
// Bech32KeysOutput returns a slice of KeyOutput objects, each with the "acc"
// MkValKeyOutput create a KeyOutput in with "val" Bech32 prefixes.
func MkValKeyOutput(keyInfo Info) (KeyOutput, error) {
pk := keyInfo.GetPubKey()
addr := sdk.ValAddress(pk.Address())
return NewKeyOutput(keyInfo.GetName(), keyInfo.GetType(), addr, pk)
}
// MkAccKeyOutput create a KeyOutput in with "acc" Bech32 prefixes. If the
// public key is a multisig public key, then the threshold and constituent
// public keys will be added.
func MkAccKeyOutput(keyInfo Info) (KeyOutput, error) {
pk := keyInfo.GetPubKey()
addr := sdk.AccAddress(pk.Address())
return NewKeyOutput(keyInfo.GetName(), keyInfo.GetType(), addr, pk)
}
// MkAccKeysOutput returns a slice of KeyOutput objects, each with the "acc"
// Bech32 prefixes, given a slice of Info objects. It returns an error if any
// call to Bech32KeyOutput fails.
func Bech32KeysOutput(infos []Info) ([]KeyOutput, error) {
// call to MkKeyOutput fails.
func MkAccKeysOutput(infos []Info) ([]KeyOutput, error) {
kos := make([]KeyOutput, len(infos))
var err error
for i, info := range infos {
ko, err := Bech32KeyOutput(info)
kos[i], err = MkAccKeyOutput(info)
if err != nil {
return nil, err
}
kos[i] = ko
}
return kos, nil
}
// Bech32ConsKeyOutput create a KeyOutput in with "cons" Bech32 prefixes.
func Bech32ConsKeyOutput(keyInfo Info) (KeyOutput, error) {
consAddr := sdk.ConsAddress(keyInfo.GetPubKey().Address().Bytes())
bechPubKey, err := sdk.Bech32ifyPubKey(sdk.Bech32PubKeyTypeConsPub, keyInfo.GetPubKey())
if err != nil {
return KeyOutput{}, err
}
return NewKeyOutput(keyInfo.GetName(), keyInfo.GetType().String(), consAddr.String(), bechPubKey), nil
}
// Bech32ValKeyOutput create a KeyOutput in with "val" Bech32 prefixes.
func Bech32ValKeyOutput(keyInfo Info) (KeyOutput, error) {
valAddr := sdk.ValAddress(keyInfo.GetPubKey().Address().Bytes())
bechPubKey, err := sdk.Bech32ifyPubKey(sdk.Bech32PubKeyTypeValPub, keyInfo.GetPubKey())
if err != nil {
return KeyOutput{}, err
}
return NewKeyOutput(keyInfo.GetName(), keyInfo.GetType().String(), valAddr.String(), bechPubKey), nil
}
// Bech32KeyOutput create a KeyOutput in with "acc" Bech32 prefixes. If the
// public key is a multisig public key, then the threshold and constituent
// public keys will be added.
func Bech32KeyOutput(keyInfo Info) (KeyOutput, error) {
accAddr := sdk.AccAddress(keyInfo.GetPubKey().Address().Bytes())
bechPubKey, err := sdk.Bech32ifyPubKey(sdk.Bech32PubKeyTypeAccPub, keyInfo.GetPubKey())
if err != nil {
return KeyOutput{}, err
}
ko := NewKeyOutput(keyInfo.GetName(), keyInfo.GetType().String(), accAddr.String(), bechPubKey)
if mInfo, ok := keyInfo.(*multiInfo); ok {
pubKeys := make([]multisigPubKeyOutput, len(mInfo.PubKeys))
for i, pk := range mInfo.PubKeys {
accAddr := sdk.AccAddress(pk.PubKey.Address().Bytes())
bechPubKey, err := sdk.Bech32ifyPubKey(sdk.Bech32PubKeyTypeAccPub, pk.PubKey)
if err != nil {
return KeyOutput{}, err
}
pubKeys[i] = multisigPubKeyOutput{accAddr.String(), bechPubKey, pk.Weight}
}
ko.Threshold = mInfo.Threshold
ko.PubKeys = pubKeys
}
return ko, nil
}

View File

@ -1,6 +1,7 @@
package keyring
import (
"fmt"
"testing"
"github.com/stretchr/testify/require"
@ -12,20 +13,18 @@ import (
)
func TestBech32KeysOutput(t *testing.T) {
tmpKey := secp256k1.GenPrivKey().PubKey()
bechTmpKey := sdk.MustBech32ifyPubKey(sdk.Bech32PubKeyTypeAccPub, tmpKey)
tmpAddr := sdk.AccAddress(tmpKey.Address().Bytes())
sk := secp256k1.PrivKey{Key: []byte{154, 49, 3, 117, 55, 232, 249, 20, 205, 216, 102, 7, 136, 72, 177, 2, 131, 202, 234, 81, 31, 208, 46, 244, 179, 192, 167, 163, 142, 117, 246, 13}}
tmpKey := sk.PubKey()
multisigPk := kmultisig.NewLegacyAminoPubKey(1, []types.PubKey{tmpKey})
multisigPks := kmultisig.NewLegacyAminoPubKey(1, []types.PubKey{tmpKey})
multiInfo := NewMultiInfo("multisig", multisigPks)
accAddr := sdk.AccAddress(multiInfo.GetPubKey().Address().Bytes())
bechPubKey := sdk.MustBech32ifyPubKey(sdk.Bech32PubKeyTypeAccPub, multiInfo.GetPubKey())
expectedOutput := NewKeyOutput(multiInfo.GetName(), multiInfo.GetType().String(), accAddr.String(), bechPubKey)
expectedOutput.Threshold = 1
expectedOutput.PubKeys = []multisigPubKeyOutput{{tmpAddr.String(), bechTmpKey, 1}}
outputs, err := Bech32KeysOutput([]Info{multiInfo})
info, err := NewMultiInfo("multisig", multisigPk)
require.NoError(t, err)
require.Equal(t, expectedOutput, outputs[0])
accAddr := sdk.AccAddress(info.GetPubKey().Address())
expectedOutput, err := NewKeyOutput(info.GetName(), info.GetType(), accAddr, multisigPk)
require.NoError(t, err)
out, err := MkAccKeyOutput(info)
require.NoError(t, err)
require.Equal(t, expectedOutput, out)
require.Equal(t, `{Name:multisig Type:multi Address:cosmos1nf8lf6n4wa43rzmdzwe6hkrnw5guekhqt595cw PubKey:{"@type":"/cosmos.crypto.multisig.LegacyAminoPubKey","threshold":1,"public_keys":[{"@type":"/cosmos.crypto.secp256k1.PubKey","key":"AurroA7jvfPd1AadmmOvWM2rJSwipXfRf8yD6pLbA2DJ"}]} Mnemonic:}`, fmt.Sprintf("%+v", out))
}

View File

@ -2,6 +2,7 @@ package keyring
import (
"encoding/hex"
"fmt"
"testing"
"github.com/stretchr/testify/require"
@ -13,7 +14,9 @@ import (
func Test_writeReadLedgerInfo(t *testing.T) {
tmpKey := make([]byte, secp256k1.PubKeySize)
bz, _ := hex.DecodeString("035AD6810A47F073553FF30D2FCC7E0D3B1C0B74B61A1AAA2582344037151E143A")
hexPK := "035AD6810A47F073553FF30D2FCC7E0D3B1C0B74B61A1AAA2582344037151E143A"
bz, err := hex.DecodeString(hexPK)
require.NoError(t, err)
copy(tmpKey[:], bz)
lInfo := newLedgerInfo("some_name", &secp256k1.PubKey{Key: tmpKey}, *hd.NewFundraiserParams(5, sdk.CoinType, 1), hd.Secp256k1Type)
@ -23,8 +26,8 @@ func Test_writeReadLedgerInfo(t *testing.T) {
require.NoError(t, err)
require.Equal(t, "m/44'/118'/5'/0/1", path.String())
require.Equal(t,
"cosmospub1addwnpepqddddqg2glc8x4fl7vxjlnr7p5a3czm5kcdp4239sg6yqdc4rc2r5wmxv8p",
sdk.MustBech32ifyPubKey(sdk.Bech32PubKeyTypeAccPub, lInfo.GetPubKey()))
fmt.Sprintf("PubKeySecp256k1{%s}", hexPK),
lInfo.GetPubKey().String())
// Serialize and restore
serialized := marshalInfo(lInfo)

View File

@ -180,6 +180,7 @@ func (pubKey *PubKey) VerifySignature(msg []byte, sig []byte) bool {
return ed25519consensus.Verify(pubKey.Key, msg, sig)
}
// String returns Hex representation of a pubkey with it's type
func (pubKey *PubKey) String() string {
return fmt.Sprintf("PubKeyEd25519{%X}", pubKey.Key)
}

View File

@ -11,7 +11,9 @@ import (
tmed25519 "github.com/tendermint/tendermint/crypto/ed25519"
"github.com/cosmos/cosmos-sdk/codec"
ed25519 "github.com/cosmos/cosmos-sdk/crypto/keys/ed25519"
"github.com/cosmos/cosmos-sdk/codec/types"
cryptocodec "github.com/cosmos/cosmos-sdk/crypto/codec"
"github.com/cosmos/cosmos-sdk/crypto/keys/ed25519"
"github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1"
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
)
@ -234,3 +236,21 @@ func TestMarshalAmino_BackwardsCompatibility(t *testing.T) {
})
}
}
func TestMarshalJSON(t *testing.T) {
require := require.New(t)
privKey := ed25519.GenPrivKey()
pk := privKey.PubKey()
registry := types.NewInterfaceRegistry()
cryptocodec.RegisterInterfaces(registry)
cdc := codec.NewProtoCodec(registry)
bz, err := cdc.MarshalInterfaceJSON(pk)
require.NoError(err)
var pk2 cryptotypes.PubKey
err = cdc.UnmarshalInterfaceJSON(bz, &pk2)
require.NoError(err)
require.True(pk2.Equals(pk))
}

View File

@ -18,18 +18,18 @@ var _ types.UnpackInterfacesMessage = &LegacyAminoPubKey{}
// Multisig can be constructed with multiple same keys - it will increase the power of
// the owner of that key (he will still need to add multiple signatures in the right order).
// Panics if len(pubKeys) < k or 0 >= k.
func NewLegacyAminoPubKey(k int, pubKeys []cryptotypes.PubKey) *LegacyAminoPubKey {
if k <= 0 {
func NewLegacyAminoPubKey(threshold int, pubKeys []cryptotypes.PubKey) *LegacyAminoPubKey {
if threshold <= 0 {
panic("threshold k of n multisignature: k <= 0")
}
if len(pubKeys) < k {
if len(pubKeys) < threshold {
panic("threshold k of n multisignature: len(pubKeys) < k")
}
anyPubKeys, err := packPubKeys(pubKeys)
if err != nil {
panic(err)
}
return &LegacyAminoPubKey{Threshold: uint32(k), PubKeys: anyPubKeys}
return &LegacyAminoPubKey{Threshold: uint32(threshold), PubKeys: anyPubKeys}
}
// Address implements cryptotypes.PubKey Address method

View File

@ -1,6 +1,7 @@
package multisig_test
import (
"strings"
"testing"
"github.com/stretchr/testify/require"
@ -9,10 +10,13 @@ import (
"github.com/cosmos/cosmos-sdk/codec/legacy"
"github.com/cosmos/cosmos-sdk/codec/types"
cryptocodec "github.com/cosmos/cosmos-sdk/crypto/codec"
"github.com/cosmos/cosmos-sdk/crypto/keyring"
kmultisig "github.com/cosmos/cosmos-sdk/crypto/keys/multisig"
"github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1"
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
"github.com/cosmos/cosmos-sdk/crypto/types/multisig"
"github.com/cosmos/cosmos-sdk/simapp"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/tx/signing"
"github.com/cosmos/cosmos-sdk/x/auth/legacy/legacytx"
)
@ -27,8 +31,7 @@ func TestNewMultiSig(t *testing.T) {
}
func TestAddress(t *testing.T) {
msg := []byte{1, 2, 3, 4}
pubKeys, _ := generatePubKeysAndSignatures(5, msg)
pubKeys := generatePubKeys(5)
multisigKey := kmultisig.NewLegacyAminoPubKey(2, pubKeys)
require.Len(t, multisigKey.Address().Bytes(), 20)
@ -110,7 +113,7 @@ func TestVerifyMultisignature(t *testing.T) {
}, {
"wrong size for sig bit array",
func(require *require.Assertions) {
pubKeys, _ := generatePubKeysAndSignatures(3, msg)
pubKeys := generatePubKeys(3)
pk = kmultisig.NewLegacyAminoPubKey(3, pubKeys)
sig = multisig.NewMultisig(1)
},
@ -201,7 +204,7 @@ func TestVerifyMultisignature(t *testing.T) {
}, {
"unable to verify signature",
func(require *require.Assertions) {
pubKeys, _ := generatePubKeysAndSignatures(2, msg)
pubKeys := generatePubKeys(2)
_, sigs := generatePubKeysAndSignatures(2, msg)
pk = kmultisig.NewLegacyAminoPubKey(2, pubKeys)
sig = multisig.NewMultisig(2)
@ -270,8 +273,7 @@ func TestMultiSigMigration(t *testing.T) {
}
func TestPubKeyMultisigThresholdAminoToIface(t *testing.T) {
msg := []byte{1, 2, 3, 4}
pubkeys, _ := generatePubKeysAndSignatures(5, msg)
pubkeys := generatePubKeys(5)
multisigKey := kmultisig.NewLegacyAminoPubKey(2, pubkeys)
ab, err := legacy.Cdc.MarshalBinaryLengthPrefixed(multisigKey)
@ -285,6 +287,14 @@ func TestPubKeyMultisigThresholdAminoToIface(t *testing.T) {
require.Equal(t, multisigKey.Equals(&pubKey), true)
}
func generatePubKeys(n int) []cryptotypes.PubKey {
pks := make([]cryptotypes.PubKey, n)
for i := 0; i < n; i++ {
pks[i] = secp256k1.GenPrivKey().PubKey()
}
return pks
}
func generatePubKeysAndSignatures(n int, msg []byte) (pubKeys []cryptotypes.PubKey, signatures []signing.SignatureData) {
pubKeys = make([]cryptotypes.PubKey, n)
signatures = make([]signing.SignatureData, n)
@ -332,25 +342,40 @@ func reorderPubKey(pk *kmultisig.LegacyAminoPubKey) (other *kmultisig.LegacyAmin
return
}
func TestDisplay(t *testing.T) {
require := require.New(t)
pubKeys := generatePubKeys(3)
msig := kmultisig.NewLegacyAminoPubKey(2, pubKeys)
// LegacyAminoPubKey wraps PubKeys into Amino (for serialization) and Any String method doesn't work.
require.PanicsWithValue("reflect.Value.Interface: cannot return value obtained from unexported field or method",
func() { require.Empty(msig.String()) },
)
ccfg := simapp.MakeTestEncodingConfig()
bz, err := ccfg.Marshaler.MarshalInterfaceJSON(msig)
require.NoError(err)
expectedPrefix := `{"@type":"/cosmos.crypto.multisig.LegacyAminoPubKey","threshold":2,"public_keys":[{"@type":"/cosmos.crypto.secp256k1.PubKey"`
require.True(strings.HasPrefix(string(bz), expectedPrefix))
// Example output:
// {"@type":"/cosmos.crypto.multisig.LegacyAminoPubKey","threshold":2,"public_keys":[{"@type":"/cosmos.crypto.secp256k1.PubKey","key":"AymUY3J2HKIyy9cbpGKcBFUTuDQsRH9NO/orKF/0WQ76"},{"@type":"/cosmos.crypto.secp256k1.PubKey","key":"AkvnCDzSYF+tQV/FoI217V7CDIRPzjJj7zBE2nw7x3xT"},{"@type":"/cosmos.crypto.secp256k1.PubKey","key":"A0yiqgcM5EB1i0h79+sQp+C0jLPFnT3+dFmdZmGa+H1s"}]}
}
func TestAminoBinary(t *testing.T) {
pubKey1 := secp256k1.GenPrivKey().PubKey()
pubKey2 := secp256k1.GenPrivKey().PubKey()
multisigKey := kmultisig.NewLegacyAminoPubKey(2, []cryptotypes.PubKey{pubKey1, pubKey2})
pubkeys := generatePubKeys(2)
msig := kmultisig.NewLegacyAminoPubKey(2, pubkeys)
// Do a round-trip key->bytes->key.
bz, err := legacy.Cdc.MarshalBinaryBare(multisigKey)
bz, err := legacy.Cdc.MarshalBinaryBare(msig)
require.NoError(t, err)
var newMultisigKey cryptotypes.PubKey
err = legacy.Cdc.UnmarshalBinaryBare(bz, &newMultisigKey)
var newMsig cryptotypes.PubKey
err = legacy.Cdc.UnmarshalBinaryBare(bz, &newMsig)
require.NoError(t, err)
require.Equal(t, multisigKey.Threshold, newMultisigKey.(*kmultisig.LegacyAminoPubKey).Threshold)
require.Equal(t, msig.Threshold, newMsig.(*kmultisig.LegacyAminoPubKey).Threshold)
}
func TestAminoMarshalJSON(t *testing.T) {
pubKey1 := secp256k1.GenPrivKey().PubKey()
pubKey2 := secp256k1.GenPrivKey().PubKey()
multisigKey := kmultisig.NewLegacyAminoPubKey(2, []cryptotypes.PubKey{pubKey1, pubKey2})
pubkeys := generatePubKeys(2)
multisigKey := kmultisig.NewLegacyAminoPubKey(2, pubkeys)
bz, err := legacy.Cdc.MarshalJSON(multisigKey)
require.NoError(t, err)
@ -401,5 +426,33 @@ func TestAminoUnmarshalJSON(t *testing.T) {
var pk cryptotypes.PubKey
err := cdc.UnmarshalJSON([]byte(pkJSON), &pk)
require.NoError(t, err)
require.Equal(t, uint32(3), pk.(*kmultisig.LegacyAminoPubKey).Threshold)
lpk := pk.(*kmultisig.LegacyAminoPubKey)
require.Equal(t, uint32(3), lpk.Threshold)
}
func TestProtoMarshalJSON(t *testing.T) {
require := require.New(t)
pubkeys := generatePubKeys(3)
msig := kmultisig.NewLegacyAminoPubKey(2, pubkeys)
registry := types.NewInterfaceRegistry()
cryptocodec.RegisterInterfaces(registry)
cdc := codec.NewProtoCodec(registry)
bz, err := cdc.MarshalInterfaceJSON(msig)
require.NoError(err)
var pk2 cryptotypes.PubKey
err = cdc.UnmarshalInterfaceJSON(bz, &pk2)
require.NoError(err)
require.True(pk2.Equals(msig))
// Test that we can correctly unmarshal key from keyring output
info, err := keyring.NewMultiInfo("my multisig", msig)
require.NoError(err)
ko, err := keyring.MkAccKeyOutput(info)
require.NoError(err)
require.Equal(ko.Address, sdk.AccAddress(pk2.Address()).String())
require.Equal(ko.PubKey, string(bz))
}

View File

@ -3,13 +3,13 @@ package secp256r1
import (
"testing"
proto "github.com/gogo/protobuf/proto"
"github.com/stretchr/testify/suite"
"github.com/tendermint/tendermint/crypto"
"github.com/cosmos/cosmos-sdk/codec"
"github.com/cosmos/cosmos-sdk/codec/types"
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
proto "github.com/gogo/protobuf/proto"
"github.com/stretchr/testify/suite"
)
var _ cryptotypes.PrivKey = &PrivKey{}

View File

@ -25,17 +25,16 @@ func TestPublicKeyUnsafe(t *testing.T) {
path := *hd.NewFundraiserParams(0, sdk.CoinType, 0)
priv, err := NewPrivKeySecp256k1Unsafe(path)
require.NoError(t, err)
require.NotNil(t, priv)
checkDefaultPubKey(t, priv)
}
func checkDefaultPubKey(t *testing.T, priv types.LedgerPrivKey) {
require.NotNil(t, priv)
expectedPkStr := "PubKeySecp256k1{034FEF9CD7C4C63588D3B03FEB5281B9D232CBA34D6F3D71AEE59211FFBFE1FE87}"
require.Equal(t, "eb5ae98721034fef9cd7c4c63588d3b03feb5281b9d232cba34d6f3d71aee59211ffbfe1fe87",
fmt.Sprintf("%x", cdc.Amino.MustMarshalBinaryBare(priv.PubKey())),
"Is your device using test mnemonic: %s ?", testutil.TestMnemonic)
pubKeyAddr, err := sdk.Bech32ifyPubKey(sdk.Bech32PubKeyTypeAccPub, priv.PubKey())
require.NoError(t, err)
require.Equal(t, "cosmospub1addwnpepqd87l8xhcnrrtzxnkql7k55ph8fr9jarf4hn6udwukfprlalu8lgw0urza0",
pubKeyAddr, "Is your device using test mnemonic: %s ?", testutil.TestMnemonic)
require.Equal(t, expectedPkStr, priv.PubKey().String())
addr := sdk.AccAddress(priv.PubKey().Address()).String()
require.Equal(t, "cosmos1w34k53py5v5xyluazqpq65agyajavep2rflq6h",
addr, "Is your device using test mnemonic: %s ?", testutil.TestMnemonic)
@ -43,16 +42,16 @@ func TestPublicKeyUnsafe(t *testing.T) {
func TestPublicKeyUnsafeHDPath(t *testing.T) {
expectedAnswers := []string{
"cosmospub1addwnpepqd87l8xhcnrrtzxnkql7k55ph8fr9jarf4hn6udwukfprlalu8lgw0urza0",
"cosmospub1addwnpepqfsdqjr68h7wjg5wacksmqaypasnra232fkgu5sxdlnlu8j22ztxvlqvd65",
"cosmospub1addwnpepqw3xwqun6q43vtgw6p4qspq7srvxhcmvq4jrx5j5ma6xy3r7k6dtxmrkh3d",
"cosmospub1addwnpepqvez9lrp09g8w7gkv42y4yr5p6826cu28ydrhrujv862yf4njmqyyjr4pjs",
"cosmospub1addwnpepq06hw3enfrtmq8n67teytcmtnrgcr0yntmyt25kdukfjkerdc7lqg32rcz7",
"cosmospub1addwnpepqg3trf2gd0s2940nckrxherwqhgmm6xd5h4pcnrh4x7y35h6yafmcpk5qns",
"cosmospub1addwnpepqdm6rjpx6wsref8wjn7ym6ntejet430j4szpngfgc20caz83lu545vuv8hp",
"cosmospub1addwnpepqvdhtjzy2wf44dm03jxsketxc07vzqwvt3vawqqtljgsr9s7jvydjmt66ew",
"cosmospub1addwnpepqwystfpyxwcava7v3t7ndps5xzu6s553wxcxzmmnxevlzvwrlqpzz695nw9",
"cosmospub1addwnpepqw970u6gjqkccg9u3rfj99857wupj2z9fqfzy2w7e5dd7xn7kzzgkgqch0r",
"PubKeySecp256k1{034FEF9CD7C4C63588D3B03FEB5281B9D232CBA34D6F3D71AEE59211FFBFE1FE87}",
"PubKeySecp256k1{0260D0487A3DFCE9228EEE2D0D83A40F6131F551526C8E52066FE7FE1E4A509666}",
"PubKeySecp256k1{03A2670393D02B162D0ED06A08041E80D86BE36C0564335254DF7462447EB69AB3}",
"PubKeySecp256k1{033222FC61795077791665544A90740E8EAD638A391A3B8F9261F4A226B396C042}",
"PubKeySecp256k1{03F577473348D7B01E7AF2F245E36B98D181BC935EC8B552CDE5932B646DC7BE04}",
"PubKeySecp256k1{0222B1A5486BE0A2D5F3C5866BE46E05D1BDE8CDA5EA1C4C77A9BC48D2FA2753BC}",
"PubKeySecp256k1{0377A1C826D3A03CA4EE94FC4DEA6BCCB2BAC5F2AC0419A128C29F8E88F1FF295A}",
"PubKeySecp256k1{031B75C84453935AB76F8C8D0B6566C3FCC101CC5C59D7000BFC9101961E9308D9}",
"PubKeySecp256k1{038905A42433B1D677CC8AFD36861430B9A8529171B0616F733659F131C3F80221}",
"PubKeySecp256k1{038BE7F348902D8C20BC88D32294F4F3B819284548122229DECD1ADF1A7EB0848B}",
}
const numIters = 10
@ -73,10 +72,8 @@ func TestPublicKeyUnsafeHDPath(t *testing.T) {
require.NoError(t, tmp.ValidateKey())
(&tmp).AssertIsPrivKeyInner()
pubKeyAddr, err := sdk.Bech32ifyPubKey(sdk.Bech32PubKeyTypeAccPub, priv.PubKey())
require.NoError(t, err)
require.Equal(t,
expectedAnswers[i], pubKeyAddr,
// in this test we are chekcking if the generated keys are correct.
require.Equal(t, expectedAnswers[i], priv.PubKey().String(),
"Is your device using test mnemonic: %s ?", testutil.TestMnemonic)
// Store and restore
@ -102,20 +99,8 @@ func TestPublicKeySafe(t *testing.T) {
require.NoError(t, err)
require.NotNil(t, priv)
require.Nil(t, ShowAddress(path, priv.PubKey(), sdk.GetConfig().GetBech32AccountAddrPrefix()))
require.Equal(t, "eb5ae98721034fef9cd7c4c63588d3b03feb5281b9d232cba34d6f3d71aee59211ffbfe1fe87",
fmt.Sprintf("%x", cdc.Amino.MustMarshalBinaryBare(priv.PubKey())),
"Is your device using test mnemonic: %s ?", testutil.TestMnemonic)
pubKeyAddr, err := sdk.Bech32ifyPubKey(sdk.Bech32PubKeyTypeAccPub, priv.PubKey())
require.NoError(t, err)
require.Equal(t, "cosmospub1addwnpepqd87l8xhcnrrtzxnkql7k55ph8fr9jarf4hn6udwukfprlalu8lgw0urza0",
pubKeyAddr, "Is your device using test mnemonic: %s ?", testutil.TestMnemonic)
require.Equal(t, "cosmos1w34k53py5v5xyluazqpq65agyajavep2rflq6h",
addr, "Is your device using test mnemonic: %s ?", testutil.TestMnemonic)
checkDefaultPubKey(t, priv)
addr2 := sdk.AccAddress(priv.PubKey().Address()).String()
require.Equal(t, addr, addr2)
@ -123,16 +108,16 @@ func TestPublicKeySafe(t *testing.T) {
func TestPublicKeyHDPath(t *testing.T) {
expectedPubKeys := []string{
"cosmospub1addwnpepqd87l8xhcnrrtzxnkql7k55ph8fr9jarf4hn6udwukfprlalu8lgw0urza0",
"cosmospub1addwnpepqfsdqjr68h7wjg5wacksmqaypasnra232fkgu5sxdlnlu8j22ztxvlqvd65",
"cosmospub1addwnpepqw3xwqun6q43vtgw6p4qspq7srvxhcmvq4jrx5j5ma6xy3r7k6dtxmrkh3d",
"cosmospub1addwnpepqvez9lrp09g8w7gkv42y4yr5p6826cu28ydrhrujv862yf4njmqyyjr4pjs",
"cosmospub1addwnpepq06hw3enfrtmq8n67teytcmtnrgcr0yntmyt25kdukfjkerdc7lqg32rcz7",
"cosmospub1addwnpepqg3trf2gd0s2940nckrxherwqhgmm6xd5h4pcnrh4x7y35h6yafmcpk5qns",
"cosmospub1addwnpepqdm6rjpx6wsref8wjn7ym6ntejet430j4szpngfgc20caz83lu545vuv8hp",
"cosmospub1addwnpepqvdhtjzy2wf44dm03jxsketxc07vzqwvt3vawqqtljgsr9s7jvydjmt66ew",
"cosmospub1addwnpepqwystfpyxwcava7v3t7ndps5xzu6s553wxcxzmmnxevlzvwrlqpzz695nw9",
"cosmospub1addwnpepqw970u6gjqkccg9u3rfj99857wupj2z9fqfzy2w7e5dd7xn7kzzgkgqch0r",
"PubKeySecp256k1{034FEF9CD7C4C63588D3B03FEB5281B9D232CBA34D6F3D71AEE59211FFBFE1FE87}",
"PubKeySecp256k1{0260D0487A3DFCE9228EEE2D0D83A40F6131F551526C8E52066FE7FE1E4A509666}",
"PubKeySecp256k1{03A2670393D02B162D0ED06A08041E80D86BE36C0564335254DF7462447EB69AB3}",
"PubKeySecp256k1{033222FC61795077791665544A90740E8EAD638A391A3B8F9261F4A226B396C042}",
"PubKeySecp256k1{03F577473348D7B01E7AF2F245E36B98D181BC935EC8B552CDE5932B646DC7BE04}",
"PubKeySecp256k1{0222B1A5486BE0A2D5F3C5866BE46E05D1BDE8CDA5EA1C4C77A9BC48D2FA2753BC}",
"PubKeySecp256k1{0377A1C826D3A03CA4EE94FC4DEA6BCCB2BAC5F2AC0419A128C29F8E88F1FF295A}",
"PubKeySecp256k1{031B75C84453935AB76F8C8D0B6566C3FCC101CC5C59D7000BFC9101961E9308D9}",
"PubKeySecp256k1{038905A42433B1D677CC8AFD36861430B9A8529171B0616F733659F131C3F80221}",
"PubKeySecp256k1{038BE7F348902D8C20BC88D32294F4F3B819284548122229DECD1ADF1A7EB0848B}",
}
expectedAddrs := []string{
@ -153,8 +138,8 @@ func TestPublicKeyHDPath(t *testing.T) {
privKeys := make([]types.LedgerPrivKey, numIters)
// Check with device
for i := uint32(0); i < 10; i++ {
path := *hd.NewFundraiserParams(0, sdk.CoinType, i)
for i := 0; i < len(expectedAddrs); i++ {
path := *hd.NewFundraiserParams(0, sdk.CoinType, uint32(i))
t.Logf("Checking keys at %s\n", path)
priv, addr, err := NewPrivKeySecp256k1(path, "cosmos")
@ -173,10 +158,9 @@ func TestPublicKeyHDPath(t *testing.T) {
require.NoError(t, tmp.ValidateKey())
(&tmp).AssertIsPrivKeyInner()
pubKeyAddr, err := sdk.Bech32ifyPubKey(sdk.Bech32PubKeyTypeAccPub, priv.PubKey())
require.NoError(t, err)
// in this test we are chekcking if the generated keys are correct and stored in a right path.
require.Equal(t,
expectedPubKeys[i], pubKeyAddr,
expectedPubKeys[i], priv.PubKey().String(),
"Is your device using test mnemonic: %s ?", testutil.TestMnemonic)
// Store and restore

View File

@ -15,10 +15,10 @@ The specification for IBC cross-chain fungible token transfers
([ICS20](https://github.com/cosmos/ics/tree/master/spec/ics-020-fungible-token-transfer)), needs to
be aware of the origin of any token denomination in order to relay a `Packet` which contains the sender
and recipient addressed in the
[`FungibleTokenPacketData`](https://github.com/cosmos/ics/tree/master/spec/ics-020-fungible-token-transfer#data-structures).
[`FungibleTokenPacketData`](https://github.com/cosmos/ibc/tree/master/spec/app/ics-020-fungible-token-transfer#data-structures).
The Packet relay sending works based in 2 cases (per
[specification](https://github.com/cosmos/ics/tree/master/spec/ics-020-fungible-token-transfer#packet-relay) and [Colin Axnér](https://github.com/colin-axner)'s description):
[specification](https://github.com/cosmos/ibc/tree/master/spec/app/ics-020-fungible-token-transfer#packet-relay) and [Colin Axnér](https://github.com/colin-axner)'s description):
1. Sender chain is acting as the source zone. The coins are transferred
to an escrow address (i.e locked) on the sender chain and then transferred
@ -96,7 +96,7 @@ of a coin's denom is performed according to a
where only lowercase alphanumeric characters are accepted. While this is desirable for native denominations
to keep a clean UX, it presents a challenge for IBC as ports and channels might be randomly
generated with special and uppercase characters as per the [ICS 024 - Host
Requirements](https://github.com/cosmos/ics/tree/master/spec/ics-024-host-requirements#paths-identifiers-separators)
Requirements](https://github.com/cosmos/ibc/tree/master/spec/core/ics-024-host-requirements#paths-identifiers-separators)
specification.
## Decision
@ -372,5 +372,5 @@ Additional validation logic, such as verifying the length of the hash, the may
## References
- [ICS 20 - Fungible token transfer](https://github.com/cosmos/ics/tree/master/spec/ics-020-fungible-token-transfer)
- [ICS 20 - Fungible token transfer](https://github.com/cosmos/ibc/tree/master/spec/app/ics-020-fungible-token-transfer)
- [Custom Coin Denomination validation](https://github.com/cosmos/cosmos-sdk/pull/6755)

View File

@ -7,8 +7,8 @@
## Context
Full implementation of the [IBC specification](https://github.com/cosmos/ics) requires the ability to create and authenticate object-capability keys at runtime (i.e., during transaction execution),
as described in [ICS 5](https://github.com/cosmos/ics/tree/master/spec/ics-005-port-allocation#technical-specification). In the IBC specification, capability keys are created for each newly initialised
Full implementation of the [IBC specification](https://github.com/cosmos/ibs) requires the ability to create and authenticate object-capability keys at runtime (i.e., during transaction execution),
as described in [ICS 5](https://github.com/cosmos/ibc/tree/master/spec/core/ics-005-port-allocation#technical-specification). In the IBC specification, capability keys are created for each newly initialised
port & channel, and are used to authenticate future usage of the port or channel. Since channels and potentially ports can be initialised during transaction execution, the state machine must be able to create
object-capability keys at this time.

View File

@ -6,7 +6,7 @@
## Context
[ICS 26 - Routing Module](https://github.com/cosmos/ics/tree/master/spec/ics-026-routing-module) defines a function [`handlePacketRecv`](https://github.com/cosmos/ics/tree/master/spec/ics-026-routing-module#packet-relay).
[ICS 26 - Routing Module](https://github.com/cosmos/ibc/tree/master/spec/core/ics-026-routing-module) defines a function [`handlePacketRecv`](https://github.com/cosmos/ibc/tree/master/spec/core/ics-026-routing-module#packet-relay).
In ICS 26, the routing module is defined as a layer above each application module
which verifies and routes messages to the destination modules. It is possible to

View File

@ -58,4 +58,4 @@ Implementation of this ADR will require changes to the Cosmos SDK. It will not r
## References
- [ICS 2: "Consensus state introspection"](https://github.com/cosmos/ics/tree/master/spec/ics-024-host-requirements#consensus-state-introspection)
- [ICS 2: "Consensus state introspection"](https://github.com/cosmos/ibc/tree/master/spec/core/ics-002-client-semantics#consensus-state-introspection)

View File

@ -54,7 +54,7 @@ We elect not to deal with chains which have actually halted, which is necessaril
Note that clients frozen due to misbehaviour must wait for the evidence to expire to avoid becoming refrozen.
This ADR does not address planned upgrades, which are handled separately as per the [specification](https://github.com/cosmos/ics/tree/master/spec/ics-007-tendermint-client#upgrades).
This ADR does not address planned upgrades, which are handled separately as per the [specification](https://github.com/cosmos/ibc/tree/master/spec/client/ics-007-tendermint-client#upgrades).
## Consequences

View File

@ -69,7 +69,7 @@ In the issue we discussed various modifications:
### Scope
This ADR only defines a process for the generation of address bytes. For end-user interactions with addresses (through the API, or CLI, etc.), we still use bech32 to format these addresses as strings. This ADR doesn't change that.
Using bech32 for string encoding gives us support for checksum error codes and handling of user typos.
Using Bech32 for string encoding gives us support for checksum error codes and handling of user typos.
## Decision

View File

@ -19,7 +19,7 @@ service definitions defined in [ADR 021](./adr-021-protobuf-query-encoding.md) a
## Context
In the current Cosmos SDK documentation on the [Object-Capability Model](../docs/core/ocap.md), it is stated that:
In the current Cosmos SDK documentation on the [Object-Capability Model](../core/ocap.md), it is stated that:
> We assume that a thriving ecosystem of Cosmos-SDK modules that are easy to compose into a blockchain application will contain faulty or malicious modules.

View File

@ -33,7 +33,7 @@ type WriteListener interface {
// if value is nil then it was deleted
// storeKey indicates the source KVStore, to facilitate using the the same WriteListener across separate KVStores
// set bool indicates if it was a set; true: set, false: delete
OnWrite(storeKey types.StoreKey, set bool, key []byte, value []byte)
OnWrite(storeKey StoreKey, key []byte, value []byte, delete bool) error
}
```
@ -72,15 +72,20 @@ func NewStoreKVPairWriteListener(w io.Writer, m codec.BinaryMarshaler) *StoreKVP
}
// OnWrite satisfies the WriteListener interface by writing length-prefixed protobuf encoded StoreKVPairs
func (wl *StoreKVPairWriteListener) OnWrite(storeKey types.StoreKey, set bool, key []byte, value []byte) {
func (wl *StoreKVPairWriteListener) OnWrite(storeKey types.StoreKey, key []byte, value []byte, delete bool) error error {
kvPair := new(types.StoreKVPair)
kvPair.StoreKey = storeKey.Name()
kvPair.Set = set
kvPair.Delete = Delete
kvPair.Key = key
kvPair.Value = value
if by, err := wl.marshaller.MarshalBinaryLengthPrefixed(kvPair); err == nil {
wl.writer.Write(by)
by, err := wl.marshaller.MarshalBinaryLengthPrefixed(kvPair)
if err != nil {
return err
}
if _, err := wl.writer.Write(by); err != nil {
return err
}
return nil
}
```
@ -110,20 +115,22 @@ func NewStore(parent types.KVStore, psk types.StoreKey, listeners []types.WriteL
func (s *Store) Set(key []byte, value []byte) {
types.AssertValidKey(key)
s.parent.Set(key, value)
s.onWrite(true, key, value)
s.onWrite(false, key, value)
}
// Delete implements the KVStore interface. It traces a write operation and
// delegates the Delete call to the parent KVStore.
func (s *Store) Delete(key []byte) {
s.parent.Delete(key)
s.onWrite(false, key, nil)
s.onWrite(true, key, nil)
}
// onWrite writes a KVStore operation to all of the WriteListeners
func (s *Store) onWrite(set bool, key, value []byte) {
func (s *Store) onWrite(delete bool, key, value []byte) {
for _, l := range s.listeners {
l.OnWrite(s.parentStoreKey, set, key, value)
if err := l.OnWrite(s.parentStoreKey, key, value, delete); err != nil {
// log error
}
}
}
```
@ -140,9 +147,9 @@ type MultiStore interface {
// ListeningEnabled returns if listening is enabled for the KVStore belonging the provided StoreKey
ListeningEnabled(key StoreKey) bool
// SetListeners sets the WriteListeners for the KVStore belonging to the provided StoreKey
// AddListeners adds WriteListeners for the KVStore belonging to the provided StoreKey
// It appends the listeners to a current set, if one already exists
SetListeners(key StoreKey, listeners []WriteListener)
AddListeners(key StoreKey, listeners []WriteListener)
}
```
@ -342,7 +349,7 @@ func (fss *FileStreamingService) Stream(wg *sync.WaitGroup, quitChan <-chan stru
case <-quitChan:
return
case by := <-fss.srcChan:
append(fss.stateCache, by)
fss.stateCache = append(fss.stateCache, by)
}
}
}()
@ -380,7 +387,7 @@ We will add a new method to the `BaseApp` to enable the registration of `Streami
func (app *BaseApp) RegisterHooks(s StreamingService) {
// set the listeners for each StoreKey
for key, lis := range s.Listeners() {
app.cms.SetListeners(key, lis)
app.cms.AddListeners(key, lis)
}
// register the streaming service hooks within the BaseApp
// BaseApp will pass BeginBlock, DeliverTx, and EndBlock requests and responses to the streaming services to update their ABCI context using these hooks
@ -398,7 +405,7 @@ func (app *BaseApp) BeginBlock(req abci.RequestBeginBlock) (res abci.ResponseBeg
...
// Call the streaming service hooks with the BeginBlock messages
for _ hook := range app.hooks {
for _, hook := range app.hooks {
hook.ListenBeginBlock(app.deliverState.ctx, req, res)
}
@ -445,7 +452,7 @@ func (app *BaseApp) DeliverTx(req abci.RequestDeliverTx) abci.ResponseDeliverTx
}
// Call the streaming service hooks with the DeliverTx messages
for _, hook := range app.hook {
for _, hook := range app.hooks {
hook.ListenDeliverTx(app.deliverState.ctx, req, res)
}

View File

@ -4,7 +4,7 @@ order: 4
# Accounts
This document describes the in-built accounts system of the Cosmos SDK. {synopsis}
This document describes the in-built account and public key system of the Cosmos SDK. {synopsis}
### Pre-requisite Readings
@ -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). 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.
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
@ -63,6 +63,8 @@ In the Cosmos SDK, keys are stored and managed by using an object called a [`Key
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).
In the node, all data is stored using Protocol Buffers serialization.
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).
@ -102,16 +104,16 @@ sdk.AccAddress(pub.Address().Bytes())
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. 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:
For user interaction, addresses 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#L230-L244
| | Address bech32 Prefix | Pubkey bech32 Prefix |
| ------------------ | --------------------- | -------------------- |
| Accounts | cosmos | cosmospub |
| Validator Operator | cosmosvaloper | cosmosvaloperpub |
| Consensus Nodes | cosmosvalcons | cosmosvalconspub |
| | Address Bech32 Prefix |
| ------------------ | --------------------- |
| Accounts | cosmos |
| Validator Operator | cosmosvaloper |
| Consensus Nodes | cosmosvalcons |
### Public Keys
@ -126,9 +128,10 @@ A compressed format is used for `secp256k1` and `secp256r1` serialization.
This prefix is followed by the `x`-coordinate.
Like `Address`, Bech32 is used to format `PubKey` and for all communication with a blockchain:
Public Keys are not used to reference accounts (or users) and in general are not used when composing transaction messages (with few exceptions: `MsgCreateValidator`, `Validator` and `Multisig` messages).
For user interactions, `PubKey` is formatted using Protobufs JSON ([ProtoMarshalJSON](https://github.com/cosmos/cosmos-sdk/blob/release/v0.42.x/codec/json.go#L12) function). Example:
+++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0-rc3/types/address.go#L579-L729
+++ https://github.com/cosmos/cosmos-sdk/blob/7568b66/crypto/keyring/output.go#L23-L39
## Keyring

View File

@ -54,6 +54,10 @@ This method takes care of marshaling the `res` parameter to protobuf and attachi
+++ https://github.com/cosmos/cosmos-sdk/blob/d55c1a26657a0af937fa2273b38dcfa1bb3cff9f/proto/cosmos/base/abci/v1beta1/abci.proto#L81-L95
This diagram shows a typical structure of an `Msg` Service, and how the message propagates through the module.
![](../uml/transaction_flow.svg)
## Legacy Amino `Msg`s
### `handler` type

View File

@ -5,6 +5,12 @@ parent:
# Cosmos SDK 文档
::: warning
**DEPRECATED**
This documentation is not complete and it's outdated. Please use the English version.
:::
## 开始
- **[SDK 介绍](./intro/README.md)**Cosmos SDK 的总体概览

View File

@ -1,5 +1,11 @@
# 基础文档
::: warning
**DEPRECATED**
This documentation is not complete and it's outdated. Please use the English version.
:::
此目录包含对 cosmos sdk 的基础概念介绍
1. [SDK 应用解析](./app-anatomy.md)

View File

@ -17,11 +17,11 @@ The full-node client of any SDK application is built by running a `main` functio
In general, developers will implement the `main.go` function with the following structure:
- First, an [`appCodec`](./encoding.md) is instantiated for the application.
- Then, the `config` is retrieved and config parameters are set. This mainly involves setting the bech32 prefixes for [addresses and pubkeys](../basics/accounts.md#addresses-and-pubkeys).
- Then, the `config` is retrieved and config parameters are set. This mainly involves setting the Bech32 prefixes for [addresses](../basics/accounts.md#addresses).
+++ https://github.com/cosmos/cosmos-sdk/blob/v0.40.0-rc3/types/config.go#L13-L24
- Using [cobra](https://github.com/spf13/cobra), the root command of the full-node client is created. After that, all the custom commands of the application are added using the `AddCommand()` method of `rootCmd`.
- Add default server commands to `rootCmd` using the `server.AddCommands()` method. These commands are separated from the ones added above since they are standard and defined at SDK level. They should be shared by all SDK-based applications. They include the most important command: the [`start` command](#start-command).
- Prepare and execute the `executor`.
- Prepare and execute the `executor`.
+++ https://github.com/tendermint/tendermint/blob/v0.34.0-rc6/libs/cli/setup.go#L74-L78
See an example of `main` function from the `simapp` application, the SDK's application for demo purposes:

View File

@ -70,6 +70,10 @@ gaia app.
+++ https://github.com/cosmos/cosmos-sdk/blob/v0.41.4/simapp/app.go#L249-L273
The following diagram shows the current dependencies between keepers.
![](../uml/keeper_dependencies.svg)
## Next {hide}
Learn about the [`runTx` middleware](./runtx_middleware.md) {hide}

View File

@ -133,6 +133,9 @@
- [CommitInfo](#cosmos.base.store.v1beta1.CommitInfo)
- [StoreInfo](#cosmos.base.store.v1beta1.StoreInfo)
- [cosmos/base/store/v1beta1/listening.proto](#cosmos/base/store/v1beta1/listening.proto)
- [StoreKVPair](#cosmos.base.store.v1beta1.StoreKVPair)
- [cosmos/base/store/v1beta1/snapshot.proto](#cosmos/base/store/v1beta1/snapshot.proto)
- [SnapshotIAVLItem](#cosmos.base.store.v1beta1.SnapshotIAVLItem)
- [SnapshotItem](#cosmos.base.store.v1beta1.SnapshotItem)
@ -680,6 +683,7 @@ pagination. Ex:
| `offset` | [uint64](#uint64) | | offset is a numeric offset that can be used when key is unavailable. It is less efficient than using key. Only one of offset or key should be set. |
| `limit` | [uint64](#uint64) | | limit is the total number of results to be returned in the result page. If left empty it will default to a value to be set by each app. |
| `count_total` | [bool](#bool) | | count_total is set to true to indicate that the result set should include a count of the total number of items available for pagination in UIs. count_total is only respected when offset is used. It is ignored when key is set. |
| `reverse` | [bool](#bool) | | reverse is set to true indicates that, results to be returned in the descending order. |
@ -1623,7 +1627,7 @@ GenesisState defines the bank module's genesis state.
| ----- | ---- | ----- | ----------- |
| `params` | [Params](#cosmos.bank.v1beta1.Params) | | params defines all the paramaters of the module. |
| `balances` | [Balance](#cosmos.bank.v1beta1.Balance) | repeated | balances is an array containing the balances of all the accounts. |
| `supply` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | supply represents the total supply. |
| `supply` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | supply represents the total supply. If it is left empty, then supply will be calculated based on the provided balances. Otherwise, it will be used to validate that the sum of the balances equals this amount. |
| `denom_metadata` | [Metadata](#cosmos.bank.v1beta1.Metadata) | repeated | denom_metadata defines the metadata of the differents coins. |
@ -1836,6 +1840,11 @@ QueryTotalSupplyRequest is the request type for the Query/TotalSupply RPC
method.
| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| `pagination` | [cosmos.base.query.v1beta1.PageRequest](#cosmos.base.query.v1beta1.PageRequest) | | pagination defines an optional pagination for the request. |
@ -1850,6 +1859,7 @@ method
| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| `supply` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | repeated | supply is the supply of the coins |
| `pagination` | [cosmos.base.query.v1beta1.PageResponse](#cosmos.base.query.v1beta1.PageResponse) | | pagination defines the pagination in the response. |
@ -2199,6 +2209,41 @@ between a store name and the commit ID.
<!-- end messages -->
<!-- end enums -->
<!-- end HasExtensions -->
<!-- end services -->
<a name="cosmos/base/store/v1beta1/listening.proto"></a>
<p align="right"><a href="#top">Top</a></p>
## cosmos/base/store/v1beta1/listening.proto
<a name="cosmos.base.store.v1beta1.StoreKVPair"></a>
### StoreKVPair
StoreKVPair is a KVStore KVPair used for listening to state changes (Sets and Deletes)
It optionally includes the StoreKey for the originating KVStore and a Boolean flag to distinguish between Sets and Deletes
| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| `store_key` | [string](#string) | | the store key for the KVStore this pair originates from |
| `delete` | [bool](#bool) | | true indicates a delete operation, false indicates a set operation |
| `key` | [bytes](#bytes) | | |
| `value` | [bytes](#bytes) | | |
<!-- end messages -->
<!-- end enums -->
@ -7257,7 +7302,8 @@ RPC method.
| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| `tx` | [Tx](#cosmos.tx.v1beta1.Tx) | | tx is the transaction to simulate. |
| `tx` | [Tx](#cosmos.tx.v1beta1.Tx) | | **Deprecated.** tx is the transaction to simulate. Deprecated. Send raw tx bytes instead. |
| `tx_bytes` | [bytes](#bytes) | | tx_bytes is the raw transaction. |

View File

@ -31,7 +31,7 @@ module correctly.
### Implement `IBCModule` Interface and callbacks
The Cosmos SDK expects all IBC modules to implement the [`IBCModule`
interface](https://github.com/cosmos/cosmos-sdk/tree/master/x/ibc/core/05-port/types/module.go). This
interface](https://github.com/cosmos/ibc-go/tree/main/modules/core/05-port/types/module.go). This
interface contains all of the callbacks IBC expects modules to implement. This section will describe
the callbacks that are called during channel handshake execution.
@ -209,7 +209,7 @@ channel, as well as how they will encode/decode it. This process is not specifie
to each application module to determine how to implement this agreement. However, for most
applications this will happen as a version negotiation during the channel handshake. While more
complex version negotiation is possible to implement inside the channel opening handshake, a very
simple version negotation is implemented in the [ibc-transfer module](https://github.com/cosmos/cosmos-sdk/tree/master/x/ibc-transfer/module.go).
simple version negotation is implemented in the [ibc-transfer module](https://github.com/cosmos/ibc-go/tree/main/modules/apps/transfer/module.go).
Thus, a module must define its a custom packet data structure, along with a well-defined way to
encode and decode it to and from `[]byte`.
@ -336,7 +336,7 @@ not want the packet processing to revert. Instead, we may want to encode this fa
acknowledgement and finish processing the packet. This will ensure the packet cannot be replayed,
and will also allow the sender module to potentially remediate the situation upon receiving the
acknowledgement. An example of this technique is in the `ibc-transfer` module's
[`OnRecvPacket`](https://github.com/cosmos/cosmos-sdk/tree/master/x/ibc-transfer/module.go).
[`OnRecvPacket`](https://github.com/cosmos/ibc-go/tree/main/modules/apps/transfer/module.go).
:::
### Acknowledgements
@ -358,9 +358,9 @@ Thus, modules must agree on how to encode/decode acknowledgements. The process o
acknowledgement struct along with encoding and decoding it, is very similar to the packet data
example above. [ICS 04](https://github.com/cosmos/ics/tree/master/spec/ics-004-channel-and-packet-semantics#acknowledgement-envelope)
specifies a recommended format for acknowledgements. This acknowledgement type can be imported from
[channel types](https://github.com/cosmos/cosmos-sdk/tree/master/x/ibc/core/04-channel/types).
[channel types](https://github.com/cosmos/ibc-go/tree/main/modules/core/04-channel/types).
While modules may choose arbitrary acknowledgement structs, a default acknowledgement types is provided by IBC [here](https://github.com/cosmos/cosmos-sdk/blob/master/proto/ibc/core/channel/v1/channel.proto):
While modules may choose arbitrary acknowledgement structs, a default acknowledgement types is provided by IBC [here](https://github.com/cosmos/ibc-go/blob/main/proto/ibc/core/channel/v1/channel.proto):
```proto
// Acknowledgement is the recommended acknowledgement format to be used by
@ -455,14 +455,14 @@ which implements everything discussed above.
Here are the useful parts of the module to look at:
[Binding to transfer
port](https://github.com/cosmos/cosmos-sdk/blob/master/x/ibc-transfer/genesis.go)
port](https://github.com/cosmos/ibc-go/blob/main/modules/apps/transfer/types/genesis.go)
[Sending transfer
packets](https://github.com/cosmos/cosmos-sdk/blob/master/x/ibc-transfer/keeper/relay.go)
packets](https://github.com/cosmos/ibc-go/blob/main/modules/apps/transfer/keeper/relay.go)
[Implementing IBC
callbacks](https://github.com/cosmos/cosmos-sdk/blob/master/x/ibc-transfer/module.go)
callbacks](https://github.com/cosmos/ibc-go/blob/main/modules/apps/transfer/module.go)
## Next {hide}
Learn about [building modules](../building-modules/intro.md) {hide}
Learn about [building modules](https://github.com/cosmos/cosmos-sdk/blob/master/docs/building-modules/intro.md) {hide}

View File

@ -7,7 +7,7 @@ order: 2
Learn how to integrate IBC to your application and send data packets to other chains. {synopsis}
This document outlines the required steps to integrate and configure the [IBC
module](https://github.com/cosmos/cosmos-sdk/tree/master/x/ibc) to your Cosmos SDK application and
module](https://github.com/cosmos/ibc-go/tree/main/modules/core) to your Cosmos SDK application and
send fungible token transfers to other chains.
## Integrating the IBC module
@ -120,13 +120,13 @@ IBC needs to know which module is bound to which port so that it can route packe
appropriate module and call the appropriate callbacks. The port to module name mapping is handled by
IBC's port `Keeper`. However, the mapping from module name to the relevant callbacks is accomplished
by the port
[`Router`](https://github.com/cosmos/cosmos-sdk/tree/master/x/ibc//core/05-port/types/router.go) on the
[`Router`](https://github.com/cosmos/ibc-go/blob/main/modules/core/05-port/types/router.go) on the
IBC module.
Adding the module routes allows the IBC handler to call the appropriate callback when processing a
channel handshake or a packet.
The second `Router` that is required is the evidence module router. This router handles general
The second `Router` that is required is the evidence module router. This router handles genenal
evidence submission and routes the business logic to each registered evidence handler. In the case
of IBC, it is required to submit evidence for [light client
misbehaviour](https://github.com/cosmos/ics/tree/master/spec/ics-002-client-semantics#misbehaviour)
@ -204,7 +204,7 @@ past historical info at any given height in order to verify the light client `Co
connection handhake.
The IBC module also has
[`BeginBlock`](https://github.com/cosmos/cosmos-sdk/blob/master/x/ibc/core/02-client/abci.go) logic as
[`BeginBlock`](https://github.com/cosmos/ibc-go/blob/main/modules/core/02-client/abci.go) logic as
well. This is optional as it is only required if your application uses the [localhost
client](https://github.com/cosmos/ics/blob/master/spec/ics-009-loopback-client) to connect two
different modules from the same chain.
@ -245,7 +245,7 @@ func NewApp(...args) *App {
That's it! You have now wired up the IBC module and are now able to send fungible tokens across
different chains. If you want to have a broader view of the changes take a look into the SDK's
[`SimApp`](https://github.com/cosmos/cosmos-sdk/blob/master/simapp/app.go).
[`SimApp`](https://github.com/cosmos/ibc-go/blob/main/testing/simapp/app.go).
## Next {hide}

View File

@ -1,180 +1,150 @@
<!--
order: 1
-->
<!-- order: 1 -->
# Overview
# IBC Overview
Learn what IBC is, its components and use cases. {synopsis}
Learn what IBC is, its components, and use cases. {synopsis}
## What is the Interblockchain Communication Protocol (IBC)?
## What is the Inter-Blockchain Communication Protocol (IBC)?
This document serves as a guide for developers who want to write their own Inter-blockchain
Communication Protocol (IBC) applications for custom [use-cases](https://github.com/cosmos/ics/blob/master/ibc/4_IBC_USECASES.md).
This document is a guide for developers who want to write their own IBC apps for custom use cases.
Due to the modular design of the IBC protocol, IBC
application developers do not need to concern themselves with the low-level details of clients,
connections, and proof verification. Nevertheless a brief explanation of the lower levels of the
stack is given so that application developers may have a high-level understanding of the IBC
protocol. Then the document goes into detail on the abstraction layer most relevant for application
developers (channels and ports), and describes how to define your own custom packets, and
`IBCModule` callbacks.
The modular design of the IBC protocol means that IBC app developers do not require in-depth knowledge of the low-level details of clients, connections, and proof verification. This brief explanation of the lower levels of the stack is provided so that app developers can gain a high-level understanding of the IBC protocol.
To have your module interact over IBC you must: bind to a port(s), define your own packet data (and
optionally acknowledgement) structs as well as how to encode/decode them, and implement the
`IBCModule` interface. Below is a more detailed explanation of how to write an IBC application
module correctly.
The abstraction layer details on channels and ports are relevant for app developers. You can define your own custom packets and IBCModule callbacks.
The following requirements must be met for a module to interact over IBC:
- Bind to one or more ports
- Define the packet data
- Define optional acknowledgement structures and methods to encode and decode them
- Implement the IBCModule interface
## Components Overview
### [Clients](https://github.com/cosmos/cosmos-sdk/tree/master/x/ibc/core/02-client)
This section describes the IBC components and links to the repos.
IBC Clients are light clients (identified by a unique client-id) that track the consensus states of
other blockchains, along with the proof spec necessary to properly verify proofs against the
client's consensus state. A client may be associated with any number of connections to multiple
chains. The supported IBC clients are:
### [Clients](https://github.com/cosmos/ibc-go/blob/main/modules/core/02-client)
* [Solo Machine light client](https://github.com/cosmos/cosmos-sdk/tree/master/x/ibc/light-clients/06-solomachine): devices such as phones, browsers, or laptops.
* [Tendermint light client](https://github.com/cosmos/cosmos-sdk/tree/master/x/ibc/light-clients/07-tendermint): The default for SDK-based chains,
* [Localhost (loopback) client](https://github.com/cosmos/cosmos-sdk/tree/master/x/ibc/light-clients/09-localhost): Useful for
testing, simulation and relaying packets to modules on the same application.
IBC clients are light clients that are identified by a unique client id. IBC clients track the consensus states of other blockchains and the proof specs of those blockchains that are required to properly verify proofs against the client's consensus state. A client can be associated with any number of connections to multiple chains. The supported IBC clients are:
### [Connections](https://github.com/cosmos/cosmos-sdk/tree/master/x/ibc/core/03-connection)
- [Solo Machine light client](https://github.com/cosmos/ibc-go/blob/main/modules/light-clients/06-solomachine): devices such as phones, browsers, or laptops.
- [Tendermint light client](https://github.com/cosmos/ibc-go/blob/main/modules/light-clients/07-tendermint): The default for Cosmos SDK-based chains.
- [Localhost (loopback) client](https://github.com/cosmos/ibc-go/blob/main/modules/light-clients/09-localhost): Useful for testing, simulation, and relaying packets to modules on the same application.
Connections encapsulate two `ConnectionEnd` objects on two seperate blockchains. Each
`ConnectionEnd` is associated with a client of the other blockchain (ie counterparty blockchain).
The connection handshake is responsible for verifying that the light clients on each chain are
correct for their respective counterparties. Connections, once established, are responsible for
facilitation all cross-chain verification of IBC state. A connection may be associated with any
number of channels.
### [Connections](https://github.com/cosmos/ibc-go/blob/main/modules/core/03-connection)
### [Proofs](https://github.com/cosmos/cosmos-sdk/tree/master/x/ibc/core/23-commitment) and [Paths](https://github.com/cosmos/cosmos-sdk/tree/master/x/ibc/core/24-host)
In IBC, blockchains do not directly pass messages to each other over the network. Instead, to
communicate, a blockchain will commit some state to a specifically defined path reserved for a
specific message type and a specific counterparty (perhaps storing a specific connectionEnd as part
of a handshake, or a packet intended to be relayed to a module on the counterparty chain). A relayer
process monitors for updates to these paths, and will relay messages, by submitting the data stored
under the path along with a proof to the counterparty chain. The paths that all IBC implementations
must use for committing IBC messages is defined in
[ICS-24](https://github.com/cosmos/ics/tree/master/spec/ics-024-host-requirements) and the proof
format that all implementations must be able to produce and verify is defined in this [ICS-23 implementation](https://github.com/confio/ics23).
Connections encapsulate two `ConnectionEnd` objects on two separate blockchains. Each `ConnectionEnd` is associated with a client of the other blockchain (the counterparty blockchain). The connection handshake is responsible for verifying that the light clients on each chain are correct for their respective counterparties. Connections, once established, are responsible for facilitating all cross-chain verification of IBC state. A connection can be associated with any number of channels.
### [Proofs](https://github.com/cosmos/ibc-go/blob/main/modules/core/23-commitment) and [Paths](https://github.com/cosmos/ibc-go/blob/main/modules/core/24-host)
In IBC, blockchains do not directly pass messages to each other over the network.
- To communicate, a blockchain commits some state to a precisely defined path reserved for a specific message type and a specific counterparty. For example, a blockchain that stores a specific connectionEnd as part of a handshake or a packet intended to be relayed to a module on the counterparty chain.
- A relayer process monitors for updates to these paths and relays messages by submitting the data stored under the path along with a proof of that data to the counterparty chain.
- The paths that all IBC implementations must support for committing IBC messages are defined in [ICS-24 host requirements](https://github.com/cosmos/ics/tree/master/spec/core/ics-024-host-requirements).
- The proof format that all implementations must produce and verify is defined in [ICS-23 implementation](https://github.com/confio/ics23).
### [Capabilities](./ocap.md)
IBC is intended to work in execution environements where modules do not necessarily trust each
other. Thus IBC must authenticate module actions on ports and channels so that only modules with the
appropriate permissions can use them. This is accomplished using [dynamic
capabilities](../architecture/adr-003-dynamic-capability-store.md). Upon binding to a port or
creating a channel for a module, IBC will return a dynamic capability that the module must claim in
order to use that port or channel. This prevents other modules from using that port or channel since
they will not own the appropriate capability.
IBC is intended to work in execution environments where modules do not necessarily trust each other. IBC must authenticate module actions on ports and channels so that only modules with the appropriate permissions can use the channels. This security is accomplished using [dynamic capabilities](../architecture/adr-003-dynamic-capability-store.md). Upon binding to a port or creating a channel for a module, IBC returns a dynamic capability that the module must claim to use that port or channel. This binding strategy prevents other modules from using that port or channel since those modules do not own the appropriate capability.
While the above is useful background information, IBC modules do not need to interact at all with
these lower-level abstractions. The relevant abstraction layer for IBC application developers is
that of channels and ports. IBC applications should be written as self-contained **modules**. A
module on one blockchain can thus communicate with other modules on other blockchains by sending,
receiving and acknowledging packets through channels, which are uniquely identified by the
`(channelID, portID)` tuple. A useful analogy is to consider IBC modules as internet applications on
a computer. A channel can then be conceptualized as an IP connection, with the IBC portID being
analogous to a IP port and the IBC channelID being analogous to an IP address. Thus, a single
instance of an IBC module may communicate on the same port with any number of other modules and and
IBC will correctly route all packets to the relevant module using the (channelID, portID tuple). An
IBC module may also communicate with another IBC module over multiple ports, with each
`(portID<->portID)` packet stream being sent on a different unique channel.
While this explanation is useful background information, IBC modules do not need to interact at all with these lower-level abstractions. The relevant abstraction layer for IBC application developers is that of channels and ports.
### [Ports](https://github.com/cosmos/cosmos-sdk/tree/master/x/ibc/core/05-port)
Write your IBC applications as self-contained **modules**. A module on one blockchain can communicate with other modules on other blockchains by sending, receiving, and acknowledging packets through channels that are uniquely identified by the `(channelID, portID)` tuple.
A useful analogy is to consider IBC modules as internet apps on a computer. A channel can then be conceptualized as an IP connection, with the IBC portID is like an IP port, and the IBC channelID is like an IP address. A single instance of an IBC module can communicate on the same port with any number of other modules and IBC correctly routes all packets to the relevant module using the `(channelID, portID)` tuple. An IBC module can also communicate with another IBC module over multiple ports by sending each `(portID<->portID)` packet stream on a different unique channel.
### [Ports](https://github.com/cosmos/ibc-go/blob/main/modules/core/05-port)
An IBC module can bind to any number of ports. Each port must be identified by a unique `portID`. Since IBC is designed to be secure with mutually-distrusted modules that operate on the same ledger, binding a port returns the dynamic object capability. To take action on a particular port, for example, to open a channel with its portID, a module must provide the dynamic object capability to the IBC handler. This requirement prevents a malicious module from opening channels with ports it does not own.
An IBC module may bind to any number of ports. Each port must be identified by a unique `portID`.
Since IBC is designed to be secure with mutually-distrusted modules operating on the same ledger,
binding a port will return a dynamic object capability. In order to take action on a particular port
(eg open a channel with its portID), a module must provide the dynamic object capability to the IBC
handler. This prevents a malicious module from opening channels with ports it does not own. Thus,
IBC modules are responsible for claiming the capability that is returned on `BindPort`.
### [Channels](https://github.com/cosmos/cosmos-sdk/tree/master/x/ibc/core/04-channel)
### [Channels](https://github.com/cosmos/ibc-go/blob/main/modules/core/04-channel)
An IBC channel can be established between 2 IBC ports. Currently, a port is exclusively owned by a
single module. IBC packets are sent over channels. Just as IP packets contain the destination IP
address and IP port as well as the source IP address and source IP port, IBC packets will contain
the destination portID and channelID as well as the source portID and channelID. This enables IBC to
correctly route packets to the destination module, while also allowing modules receiving packets to
know the sender module.
An IBC channel can be established between two IBC ports. A port is exclusively owned by a single module. IBC packets are sent over channels. Just as IP packets contain the destination IP address, IP port, the source IP address, and source IP port, IBC packets contain the destination portID, channelID, the source portID, and channelID. The IBC packets enable IBC to correctly route the packets to the destination module, while also allowing modules receiving packets to know the sender module.
A channel may be `ORDERED`, in which case, packets from a sending module must be processed by the
receiving module in the order they were sent. Or a channel may be `UNORDERED`, in which case packets
from a sending module are processed in the order they arrive (may not be the order they were sent).
- A channel can be `ORDERED` so that packets from a sending module must be processed by the receiving module in the order they were sent.
Modules may choose which channels they wish to communicate over with, thus IBC expects modules to
implement callbacks that are called during the channel handshake. These callbacks may do custom
channel initialization logic, if any return an error, the channel handshake will fail. Thus, by
returning errors on callbacks, modules can programatically reject and accept channels.
- Recommended, a channel may be `UNORDERED` so that packets from a sending module are processed in the order they arrive, which may not be the order the packets were sent.
The channel handshake is a 4 step handshake. Briefly, if a given chain A wants to open a channel with
chain B using an already established connection:
Modules may choose which channels they wish to communicate over with. IBC expects modules to implement callbacks that are called during the channel handshake. These callbacks may do custom channel initialization logic. If an error is returned, the channel handshake fails. By returning errors on callbacks, modules can programmatically reject and accept channels.
1. chain A sends a `ChanOpenInit` message to signal a channel initialization attempt with chain B.
2. chain B sends a `ChanOpenTry` message to try opening the channel on chain A.
3. chain A sends a `ChanOpenAck` message to mark its channel end status as open.
4. chain B sends a `ChanOpenConfirm` message to mark its channel end status as open.
The channel handshake is a 4-step handshake. Briefly, if a given chain A wants to open a channel with chain B using an already established connection:
If all this happens successfully, the channel will be open on both sides. At each step in the handshake, the module
associated with the `ChannelEnd` will have it's callback executed for that step of the handshake. So
on `ChanOpenInit`, the module on chain A will have its callback `OnChanOpenInit` executed.
1. Chain A sends a `ChanOpenInit` message to signal a channel initialization attempt with chain B.
2. Chain B sends a `ChanOpenTry` message to try opening the channel on chain A.
3. Chain A sends a `ChanOpenAck` message to mark its channel end status as open.
4. Chain B sends a `ChanOpenConfirm` message to mark its channel end status as open.
Just as ports came with dynamic capabilites, channel initialization will return a dynamic capability
that the module **must** claim so that they can pass in a capability to authenticate channel actions
like sending packets. The channel capability is passed into the callback on the first parts of the
handshake; either `OnChanOpenInit` on the initializing chain or `OnChanOpenTry` on the other chain.
If all of these actions happen successfully, the channel is open on both sides. At each step in the handshake, the module associated with the `ChannelEnd` executes its callback for that step of the handshake. So on `ChanOpenInit`, the module on chain A has its callback `OnChanOpenInit` executed.
### [Packets](https://github.com/cosmos/cosmos-sdk/tree/master/x/ibc/core/04-channel)
Just as ports came with dynamic capabilities, channel initialization returns a dynamic capability that the module **must** claim so that they can pass in a capability to authenticate channel actions like sending packets. The channel capability is passed into the callback on the first parts of the handshake: `OnChanOpenInit` on the initializing chain or `OnChanOpenTry` on the other chain.
Modules communicate with each other by sending packets over IBC channels. As mentioned above, all
IBC packets contain the destination `portID` and `channelID` along with the source `portID` and
`channelID`, this allows modules to know the sender module of a given packet. IBC packets also
contain a sequence to optionally enforce ordering. IBC packets also contain a `TimeoutTimestamp` and
`TimeoutHeight`, which when non-zero, will determine the deadline before which the receiving module
must process a packet. If the timeout passes without the packet being successfully received, the
sending module can timeout the packet and take appropriate actions.
### [Packets](https://github.com/cosmos/ibc-go/blob/main/modules/core/04-channel)
Modules send custom application data to each other inside the `Data []byte` field of the IBC packet.
Thus, packet data is completely opaque to IBC handlers. It is incumbent on a sender module to encode
their application-specific packet information into the `Data` field of packets, and the receiver
module to decode that `Data` back to the original application data.
Modules communicate with each other by sending packets over IBC channels. All IBC packets contain:
### [Receipts and Timeouts](https://github.com/cosmos/cosmos-sdk/tree/master/x/ibc/core/04-channel)
- Destination `portID`
Since IBC works over a distributed network and relies on potentially faulty relayers to relay messages between ledgers,
IBC must handle the case where a packet does not get sent to its destination in a timely manner or at all. Thus, packets must
specify a timeout height or timeout timestamp after which a packet can no longer be successfully received on the destination chain.
- Destination `channelID`
If the timeout does get reached, then a proof of packet timeout can be submitted to the original chain which can then perform
application-specific logic to timeout the packet, perhaps by rolling back the packet send changes (refunding senders any locked funds, etc).
- Source `portID`
In ORDERED channels, a timeout of a single packet in the channel will cause the channel to close. If packet sequence `n` times out,
then no packet at sequence `k > n` can be successfully received without violating the contract of ORDERED channels that packets are processed in the order that they are sent. Since ORDERED channels enforce this invariant, a proof that sequence `n` hasn't been received on the destination chain by packet `n`'s specified timeout is sufficient to timeout packet `n` and close the channel.
- Source `channelID`
In the UNORDERED case, packets may be received in any order. Thus, IBC will write a packet receipt for each sequence it has received in the UNORDERED channel. This receipt contains no information, it is simply a marker intended to signify that the UNORDERED channel has received a packet at the specified sequence. To timeout a packet on an UNORDERED channel, one must provide a proof that a packet receipt does not exist for the packet's sequence by the specified timeout. Of course, timing out a packet on an UNORDERED channel will simply trigger the application specific timeout logic for that packet, and will not close the channel.
These port and channels allow the modules to know the sender module of a given packet.
For this reason, most modules should use UNORDERED channels as they require less liveness guarantees to function effectively for users of that channel.
- A sequence to optionally enforce ordering
### [Acknowledgements](https://github.com/cosmos/cosmos-sdk/tree/master/x/ibc/core/04-channel)
- `TimeoutTimestamp` and `TimeoutHeight`
Modules may also choose to write application-specific acknowledgements upon processing a packet. This may either be done synchronously on `OnRecvPacket`, if the module processes packets as soon as they are received from IBC module. Or they may be done asynchronously if module processes packets at some later point after receiving the packet.
When non-zero, these timeout values determine the deadline before which the receiving module must process a packet.
Regardless, this acknowledgement data is opaque to IBC much like the packet `Data` and will be treated by IBC as a simple byte string `[]byte`. It is incumbent on receiver modules to encode their acknowledgemnet in such a way that the sender module can decode it correctly. This should be decided through version negotiation during the channel handshake.
If the timeout passes without the packet being successfully received, the sending module can timeout the packet and take appropriate actions.
The acknowledgement may encode whether the packet processing succeeded or failed, along with additional information that will allow the sender module to take appropriate action.
Modules send custom application data to each other inside the `Data []byte` field of the IBC packet. Packet data is completely opaque to IBC handlers. The sender module must encode their application-specific packet information into the `Data` field of packets. The receiver module must decode that `Data` back to the original application data.
Once the acknowledgement has been written by the receiving chain, a relayer will relay the acknowledgement back to the original sender module which will then execute application-specific acknowledgment logic using the contents of the acknowledgement. This may involve rolling back packet-send changes in the case of a failed acknowledgement (refunding senders).
### [Receipts and Timeouts](https://github.com/cosmos/ibc-go/blob/main/modules/core/04-channel)
Once an acknowledgement is received successfully on the original sender the chain, the IBC module deletes the corresponding packet commitment as it is no longer needed.
Since IBC works over a distributed network and relies on potentially faulty relayers to relay messages between ledgers, IBC must handle the case where a packet does not get sent to its destination in a timely manner or at all. Packets must specify a timeout height or timeout timestamp after which a packet can no longer be successfully received on the destination chain.
If the timeout is reached, then a proof-of-packet timeout can be submitted to the original chain which can then perform application-specific logic to timeout the packet, perhaps by rolling back the packet send changes (refunding senders any locked funds, and so on).
In ORDERED channels, a timeout of a single packet in the channel closes the channel. If packet sequence `n` times out, then no packet at sequence `k > n` can be successfully received without violating the contract of ORDERED channels that packets are processed in the order that they are sent. Since ORDERED channels enforce this invariant, a proof that sequence `n` hasn't been received on the destination chain by packet `n`'s specified timeout is sufficient to timeout packet `n` and close the channel.
In the UNORDERED case, packets can be received in any order. IBC writes a packet receipt for each sequence it has received in the UNORDERED channel. This receipt contains no information and is simply a marker intended to signify that the UNORDERED channel has received a packet at the specified sequence. To timeout a packet on an UNORDERED channel, proof that a packet receipt does not exist is required for the packet's sequence by the specified timeout. Of course, timing out a packet on an UNORDERED channel triggers the application specific timeout logic for that packet, and does not close the channel.
For this reason, most modules that use UNORDERED channels are recommended as they require less liveness guarantees to function effectively for users of that channel.
### [Acknowledgements](https://github.com/cosmos/ibc-go/blob/main/modules/core/04-channel)
Modules also write application-specific acknowledgements when processing a packet. Acknowledgements can be done:
- Synchronously on `OnRecvPacket` if the module processes packets as soon as they are received from IBC module.
- Asynchronously if module processes packets at some later point after receiving the packet.
This acknowledgement data is opaque to IBC much like the packet `Data` and is treated by IBC as a simple byte string `[]byte`. The receiver modules must encode their acknowledgement so that the sender module can decode it correctly. How the acknowledgement is encoded should be decided through version negotiation during the channel handshake.
The acknowledgement can encode whether the packet processing succeeded or failed, along with additional information that allows the sender module to take appropriate action.
After the acknowledgement has been written by the receiving chain, a relayer relays the acknowledgement back to the original sender module which then executes application-specific acknowledgment logic using the contents of the acknowledgement. This acknowledgement can involve rolling back packet-send changes in the case of a failed acknowledgement (refunding senders).
After an acknowledgement is received successfully on the original sender the chain, the IBC module deletes the corresponding packet commitment as it is no longer needed.
## Further Readings and Specs
If you want to learn more about IBC, check the following specifications:
To learn more about IBC, check out the following specifications:
* [IBC specification overview](https://github.com/cosmos/ics/blob/master/ibc/README.md)
* [IBC SDK specification](../../x/ibc/spec/README.md)
- [IBC specs](https://github.com/cosmos/ibc/tree/master/spec)
- [IBC protocol on the Cosmos SDK](https://github.com/cosmos/ibc-go/blob/main/docs/spec.md)
## Next {hide}

View File

@ -4,17 +4,17 @@ order: 4
# Relayer
## Pre-requisites Readings
## Prerequisites Readings
- [IBC Overview](./overview.md) {prereq}
- [Events](../core/events.md) {prereq}
- [Events](https://github.com/cosmos/cosmos-sdk/blob/master/docs/core/events.md) {prereq}
## Events
Events are emitted for every transaction processed by the base application to indicate the execution
of some logic clients may want to be aware of. This is extremely useful when relaying IBC packets.
Any message that uses IBC will emit events for the corresponding TAO logic executed as defined in
the [IBC events spec](https://github.com/cosmos/cosmos-sdk/tree/master/x/ibc/core/spec/06_events.md).
the [IBC events spec](https://github.com/cosmos/ibc-go/blob/main/modules/core/spec/06_events.md).
In the SDK, it can be assumed that for every message there is an event emitted with the type `message`,
attribute key `action`, and an attribute value representing the type of message sent
@ -43,3 +43,4 @@ piece of information needed to relay a packet.
## Example Implementations
- [Golang Relayer](https://github.com/iqlusioninc/relayer)
- [Hermes](https://github.com/informalsystems/ibc-rs/tree/master/relayer)

View File

@ -3,10 +3,15 @@ parent:
order: false
---
# 코스모스 SDK 문서에 오신 걸 환영합니다!
# 코스모스 SDK 문서에 오신 걸 환영합니다!
::: warning
번역된 문서는 **참고용**으로 번역되었습니다. 다수의 오타, 오류가 존재할 수 있으며, 영문 업데이트보다 번역이 느리게 진행될 수 있다는 점을 인지하시기 바랍니다.
**DEPRECATED**
This documentation is not complete and it's outdated. Please use the English version.
:::
::: warning
번역된 문서는 **참고용**으로 번역되었습니다. 다수의 오타, 오류가 존재할 수 있으며, 영문 업데이트보다 번역이 느리게 진행될 수 있다는 점을 인지하시기 바랍니다.
코스모스 관련 가장 정확한 정보를 확인하시기 위해서는 영어 원문을 참고하시기 바랍니다.
:::

View File

@ -25,7 +25,7 @@ Some important information concerning all legacy REST endpoints:
| `GET /txs/{hash}` | Query tx by hash | Endpoint will error when trying to output transactions that don't support Amino serialization (e.g. IBC txs)<sup>1</sup>. |
| `GET /txs` | Query tx by events | Endpoint will error when trying to output transactions that don't support Amino serialization (e.g. IBC txs)<sup>1</sup>. |
| `GET /gov/proposals/{id}/votes`, `GET /gov/proposals/{id}/votes/{voter}` | Gov endpoints for querying votes | All gov endpoints which return votes return int32 in the `option` field instead of string: `1=VOTE_OPTION_YES, 2=VOTE_OPTION_ABSTAIN, 3=VOTE_OPTION_NO, 4=VOTE_OPTION_NO_WITH_VETO`. |
| `GET /staking/*` | Staking query endpoints | All staking endpoints which return validators have two breaking changes. First, the validator's `consensus_pubkey` field returns an Amino-encoded struct representing an `Any` instead of a bech32-encoded string representing the pubkey. The `value` field of the `Any` is the pubkey's raw key as base64-encoded bytes. Second, the validator's `status` field now returns an int32 instead of string: `1=BOND_STATUS_UNBONDED`, `2=BOND_STATUS_UNBONDING`, `3=BOND_STATUS_BONDED`. |
| `GET /staking/*` | Staking query endpoints | All staking endpoints which return validators have two breaking changes. First, the validator's `consensus_pubkey` field returns an Amino-encoded struct representing an `Any` instead of a Bech32-encoded string representing the pubkey. The `value` field of the `Any` is the pubkey's raw key as base64-encoded bytes. Second, the validator's `status` field now returns an int32 instead of string: `1=BOND_STATUS_UNBONDED`, `2=BOND_STATUS_UNBONDING`, `3=BOND_STATUS_BONDED`. |
| `GET /staking/validators` | Get all validators | BondStatus is now a protobuf enum instead of an int32, and JSON serialized using its protobuf name, so expect query parameters like `?status=BOND_STATUS_{BONDED,UNBONDED,UNBONDING}` as opposed to `?status={bonded,unbonded,unbonding}`. |
<sup>1</sup>: Transactions that don't support Amino serialization are the ones that contain one or more `Msg`s that are not registered with the Amino codec. Currently in the SDK, only IBC `Msg`s fall into this case.

2400
docs/package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -14,6 +14,6 @@
"author": "",
"license": "ISC",
"dependencies": {
"vuepress-theme-cosmos": "^1.0.180"
"vuepress-theme-cosmos": "^1.0.181"
}
}

View File

@ -9,4 +9,6 @@ for D in ../x/*; do
fi
done
cat ../x/README.md | sed 's/\.\/x/\/modules/g' | sed 's/spec\/README.md//g' | sed 's/\.\.\/docs\/building-modules\/README\.md/\/building-modules\/intro\.html/g' > ./modules/README.md
cat ../x/README.md | sed 's/\.\/x/\/modules/g' | sed 's/spec\/README.md//g' | sed 's/\.\.\/docs\/building-modules\/README\.md/\/building-modules\/intro\.html/g' > ./modules/README.md
plantuml -tsvg uml/*.puml

View File

@ -4,3 +4,8 @@ parent:
---
# RU
::: warning
**DEPRECATED**
This documentation is not complete and it's outdated. Please use the English version.
:::

View File

@ -60,7 +60,7 @@ Since the code generation library largely depends on your own tech stack, we wil
### grpcurl
[grpcurl])https://github.com/fullstorydev/grpcurl is like `curl` but for gRPC. It is also available as a Go library, but we will use it only as a CLI command for debugging and testing purposes. Follow the instructions in the previous link to install it.
[grpcurl](https://github.com/fullstorydev/grpcurl) is like `curl` but for gRPC. It is also available as a Go library, but we will use it only as a CLI command for debugging and testing purposes. Follow the instructions in the previous link to install it.
Assuming you have a local node running (either a localnet, or connected a live network), you should be able to run the following command to list the Protobuf services available (you can replace `localhost:9000` by the gRPC server endpoint of another node, which is configured under the `grpc.address` field inside [`app.toml`](../run-node/run-node.md#configuring-the-node-using-apptoml)):
@ -70,27 +70,19 @@ grpcurl -plaintext localhost:9090 list
You should see a list of gRPC services, like `cosmos.bank.v1beta1.Query`. This is called reflection, which is a Protobuf endpoint returning a description of all available endpoints. Each of these represents a different Protobuf service, and each service exposes multiple RPC methods you can query against.
In the Cosmos SDK, we use [gogoprotobuf](https://github.com/gogo/protobuf) for code generation, and [grpc-go](https://github.com/grpc/grpc-go) for creating the gRPC server. Unfortunately, these two don't play well together, and more in-depth reflection (such as using grpcurl's `describe`) is not possible. See [this issue](https://github.com/grpc/grpc-go/issues/1873) for more info.
Instead, we need to manually pass the reference to relevant `.proto` files. For example:
In order to get a description of the service you can run the following command:
```bash
grpcurl \
-import-path ./proto \ # Import these proto files too
-import-path ./third_party/proto \ # Import these proto files too
-proto ./proto/cosmos/bank/v1beta1/query.proto \ # That's the proto file with the description of your service
localhost:9090 \
describe cosmos.bank.v1beta1.Query # Service we want to inspect
```
Once the Protobuf definitions are given, making a gRPC query is then straightforward, by calling the correct `Query` service RPC method, and by passing the request argument as data (`-d` flag):
It's also possible to execute an RPC call to query the node for information:
```bash
grpcurl \
-plaintext
-import-path ./proto \
-import-path ./third_party/proto \
-proto ./proto/cosmos/bank/v1beta1/query.proto \
-d '{"address":"$MY_VALIDATOR"}' \
localhost:9090 \
cosmos.bank.v1beta1.Query/AllBalances
@ -104,10 +96,7 @@ You may also query for historical data by passing some [gRPC metadata](https://g
```bash
grpcurl \
-plaintext
-import-path ./proto \
-import-path ./third_party/proto \
-proto ./proto/cosmos/bank/v1beta1/query.proto \
-plaintext \
-H "x-cosmos-block-height: 279256" \
-d '{"address":"$MY_VALIDATOR"}' \
localhost:9090 \

View File

@ -305,15 +305,13 @@ func simulateTx() error {
// Simulate the tx via gRPC. We create a new client for the Protobuf Tx
// service.
txClient := tx.NewServiceClient(grpcConn)
// We then call the BroadcastTx method on this client.
protoTx := txBuilderToProtoTx(txBuilder)
if err != nil {
return err
}
txBytes := /* Fill in with your signed transaction bytes. */
// We then call the Simulate method on this client.
grpcRes, err := txClient.Simulate(
context.Background(),
&tx.SimulateRequest{
Tx: protoTx,
TxBytes: txBytes,
},
)
if err != nil {
@ -324,16 +322,6 @@ func simulateTx() error {
return nil
}
// txBuilderToProtoTx converts a txBuilder into a proto tx.Tx.
func txBuilderToProtoTx(txBuilder client.TxBuilder) (*tx.Tx, error) { // nolint
protoProvider, ok := txBuilder.(authtx.ProtoTxProvider)
if !ok {
return nil, fmt.Errorf("expected proto tx builder, got %T", txBuilder)
}
return protoProvider.GetProtoTx(), nil
}
```
## Using REST

View File

@ -1,6 +1,6 @@
# Bech32 on Cosmos
The Cosmos network prefers to use the Bech32 address format wherever users must handle binary data. Bech32 encoding provides robust integrity checks on data and the human readable part(HRP) provides contextual hints that can assist UI developers with providing informative error messages.
The Cosmos network prefers to use the Bech32 address format wherever users must handle binary data. Bech32 encoding provides robust integrity checks on data and the human readable part (HRP) provides contextual hints that can assist UI developers with providing informative error messages.
In the Cosmos network, keys and addresses may refer to a number of different roles in the network like accounts, validators etc.
@ -9,16 +9,13 @@ In the Cosmos network, keys and addresses may refer to a number of different rol
| HRP | Definition |
| ---------------- | ------------------------------------- |
| cosmos | Cosmos Account Address |
| cosmospub | Cosmos Account Public Key |
| cosmosvalcons | Cosmos Validator Consensus Address |
| cosmosvalconspub | Cosmos Validator Consensus Public Key |
| cosmosvaloper | Cosmos Validator Operator Address |
| cosmosvaloperpub | Cosmos Validator Operator Public Key |
## Encoding
While all user facing interfaces to Cosmos software should exposed Bech32 interfaces, many internal interfaces encode binary value in hex or base64 encoded form.
To covert between other binary representation of addresses and keys, it is important to first apply the Amino encoding process before bech32 encoding.
To covert between other binary representation of addresses and keys, it is important to first apply the Amino encoding process before Bech32 encoding.
A complete implementation of the Amino serialization format is unnecessary in most cases. Simply prepending bytes from this [table](https://github.com/tendermint/spec/blob/master/spec/blockchain/encoding.md#public-key-cryptography) to the byte string payload before bech32 encoding will sufficient for compatible representation.
A complete implementation of the Amino serialization format is unnecessary in most cases. Simply prepending bytes from this [table](https://github.com/tendermint/spec/blob/master/spec/blockchain/encoding.md#public-key-cryptography) to the byte string payload before Bech32 encoding will sufficient for compatible representation.

View File

@ -0,0 +1,50 @@
@startuml
'https://plantuml.com/sequence-diagram
title: Redelegation
msgServer -> keeper : BeginRedelegation(delAddr, valSrcAddr, valDstAddr, sharesAmount)
participant "keeper (staking)" as keeper
keeper -> keeper : get number of sharew
note left: If the delegator has more shares than the total shares in the validator\n(due to rounding errors), then just withdraw the max number of shares.
keeper -> keeper : check the redelegation uses correct denom
alt valSrcAddr == valDstAddr
keeper --> msgServer : error
end
alt transitive redelegation
keeper --> msgServer : error
end
alt already has max redelegations
keeper --> msgServer : error
note left : this is the number of redelegations for a specific (del, valSrc, valDst) triple\ndefault : 7
end
keeper -> keeper : Unbond(del, valSrc) returns returnAmount
...
note left : See unbonding diagram
alt returnAmount is zero
keeper -> msgServer : error
end
keeper -> keeper : Delegate(del, returnAmount, status := valSrc.status, valDst, subtractAccount := false)
note left : See delegation diagram
...
alt validator is unbonded
keeper -> msgServer : current time
end
alt unbonding not complete, or just started
database store
keeper -> store : create redelegation object
keeper -> store : insert redelegation in queue, to be processed at the appropriate time
end
msgServer <-- keeper : completion time of the redelegation
msgServer -> msgServer : emit event: delegator, valSrc, valSrc,\nsharesAmount, completionTime
@enduml

View File

@ -0,0 +1,93 @@
@startuml
'https://plantuml.com/sequence-diagram
title: Delegating (currently undelegated funds delegator)
participant "msgServer (staking)"
participant "keeper (staking)" as keeper
participant validator
participant keeper.bankKeeper
participant vestingAccount
participant ctx.EventManager
database store
"msgServer (staking)" -> keeper : Delegate(Context, DelegatorAddress, Amount, Validator, tokenSrc := Unbonded)
alt exchange rate is invalid (tokens in validator is 0)
keeper --> "msgServer (staking)" : error
end
alt perform a new delegation
keeper -> keeper : delegation := create delegation object
keeper -> keeper : BeforeDelegationCreated hook
note left: Calls IncrementValidatorPeriod (Used to calculate distribution) in keeper/validator.go
else delegation exists, more tokens being added
keeper -> keeper : BeforeDelegationModified hook
note left: withdraw current delegation rewards (and increment period)
end
alt delegating from an account (subtractTokens == true)
keeper -> keeper.bankKeeper : DelegateCoinsFromAccountToModule
group DelegateCoinsFromAccountToModule function
keeper.bankKeeper -> keeper.bankKeeper : DelegateCoinsFromAccountToModule
keeper.bankKeeper -> keeper.bankKeeper : DelegateCoins
group DelegateCoins function
keeper.bankKeeper --> keeper.bankKeeper : Check the delegator has enough balances of all tokens delegated
keeper.bankKeeper --> keeper.bankKeeper : Track delegation (register that it exists to keep track of it)
alt validator is currently bonded
keeper.bankKeeper --> store : Transfer tokens from delegator to BondedTokensPool.
else validator is currently unbonded or unbonding
keeper.bankKeeper --> store : Transfer tokens from delegator to NotBondedTokensPool.
end
group trackDelegation function
keeper.bankKeeper -> keeper.bankKeeper : trackDelegation
alt delegator is a vesting account
keeper.bankKeeper -> vestingAccount : keep track of this delegation
end
end
end
end
keeper <-- keeper.bankKeeper : nil (success)
else moving tokens between pools (subtractTokens == false)
alt delegator tokens are not bonded but validator is bonded
keeper -> keeper.bankKeeper : SendCoinsFromModuleToModule(notBondedPool, bondedPool, coins)
else delegator tokens are bonded but validator is not bonded
keeper -> keeper.bankKeeper : SendCoinsFromModuleToModule(bondedPool, notBondedPool, coins)
end
group SendCoins function
keeper.bankKeeper -> keeper.bankKeeper : SendCoins
keeper.bankKeeper -> ctx.EventManager : Emit TransferEvent(to, from, amount)
alt amount of spendable (balance - locked) coins too low
keeper <-- keeper.bankKeeper : error
end
keeper.bankKeeper -> store : subtract balance from sender
keeper.bankKeeper -> store : add balance to recipient
end
end
keeper -> validator : AddTokensFromDel
validator -> validator : calculate number of shares to issue
note left: If there are no shares (validator being created) then 1 token = 1 share.\nIf there are already shares, then\nadded shares = (added tokens amount) * (current validator shares) / (current validator tokens)
validator -> validator : add delegated tokens to validator
keeper <-- validator : validator, addedShares
keeper -> store : update validator state
keeper -> keeper: calculate new validator's power
note left : Number of tokens divided by PowerReduction (default: 1,000,000,000,000,000,000 = 10^18)
alt validator is not jailed
keeper -> store : update validator's power in power index
note left : the power index has entries shaped as 35 || power || address.\nThis makes the validators sorted by power, high to low.
end
keeper -> keeper : AfterDelegationModified hook
note left: Calls initializeDelegation\nStore the previous period\nCalculate the number of tokens from shares\n(shares the delegator has) * (tokens in delegation object)/(total tokens delegated to the validator)\nStore delegation starting info.
"msgServer (staking)" <-- keeper : newShares (ignored by Delegate function)
"msgServer (staking)" -> "msgServer (staking)" : Emit event: Delegation(ValidatorAddress)
"msgServer (staking)" -> "msgServer (staking)" : Emit event: Message(DelegatorAddress)
"msgServer (staking)" -> "msgServer (staking)" : telemetry(Amount, Denom)
@enduml

View File

@ -0,0 +1,36 @@
@startuml
'https://plantuml.com/class-diagram
title: The dependencies between Keepers (Feb 2021)
abstract class Staking
abstract class Distribution
abstract class Slashing
abstract class Evidence
abstract class Bank
abstract class "Auth/Account" as Auth
abstract class Gov
abstract class Mint
Staking <|-- Mint
Bank <|-- Mint
Staking <|-- Gov
Bank <|-- Gov
Auth <|-- Gov
Auth <|-- Bank
Bank <|-- Distribution
Auth <|-- Distribution
Staking <|-- Distribution
Staking <|-- Evidence
Slashing <|-- Evidence
Staking <|-- Slashing
Auth <|-- Staking
Bank <|-- Staking
@enduml

View File

@ -0,0 +1,22 @@
What happens after a transaction is unmarshalled and is processed by the SDK?
@startuml
'https://plantuml.com/sequence-diagram
actor User
User -> baseApp : Transaction Type<Tx>
baseApp -> router : Route(ctx, msgRoute)
router --> baseApp : handler
baseApp -> handler: Msg<Tx>(Context, Msg(...))
handler -> msgServer : <Tx>(Context, Msg)
alt addresses invalid, denominations wrong, etc.
msgServer --> handler : error
end
msgServer -> keeper : perform action, update context
keeper --> msgServer : results, error code
msgServer -> Context.EventManager : Emit relevant events
msgServer -> msgServer : maybe wrap results in more structure
msgServer --> handler : result, error code
baseApp <-- handler : results, error code
@enduml

View File

@ -0,0 +1,51 @@
@startuml
'https://plantuml.com/sequence-diagram
title: Undelegate
msgServer -> keeper : Undelegate(delAddr, valAddr, tokenAmount)
keeper -> keeper : calculate number of shares the tokenAmount represents
alt wrong denom
msgServer <-- keeper : error
end
group Unbond(delAddr, valAddr, shares)
keeper -> keeper: BeforeDelegationSharesModified hook
alt no such delegation
keeper --> msgServer : error
end
alt not enough shares
keeper --> msgServer : error
end
alt delegator is the operator of the validator\nand validator is not already jailed\nand unbonding would put self-delegation under min threshold
keeper -> keeper : jail the validator, but proceed with unbonding
note left : Default min delegation threshold : 1 share
end
database store
alt complete unbonding, all shares removed
keeper -> store : remove delegation object
else there are still shares delegated (not a complete undbonding)
keeper -> store : update delegation object
keeper -> keeper : AfterDelegationModified hook
end
keeper -> store : update validator power index
keeper -> store : update validator information (including token amount)
alt validator status is "unbonded" and it has no more tokens
keeper -> store : delete the validator
note right : otherwise, do this in EndBlock once validator is unbonded
end
end
alt validator is bonded
keeper -> bankKeeper : send tokens from bonded pool to not bonded pool
end
msgServer -> msgServer : emit event : EventTypeUnbond(delAddr, valAddr, tokenAmount, completion time)
@enduml

15
go.mod
View File

@ -18,7 +18,7 @@ require (
github.com/gogo/gateway v1.1.0
github.com/gogo/protobuf v1.3.3
github.com/golang/mock v1.4.4
github.com/golang/protobuf v1.4.3
github.com/golang/protobuf v1.5.2
github.com/golang/snappy v0.0.2 // indirect
github.com/gorilla/handlers v1.5.1
github.com/gorilla/mux v1.8.0
@ -27,16 +27,17 @@ require (
github.com/hashicorp/golang-lru v0.5.4
github.com/hdevalence/ed25519consensus v0.0.0-20210204194344-59a8610d2b87
github.com/improbable-eng/grpc-web v0.14.0
github.com/magiconair/properties v1.8.4
github.com/jhump/protoreflect v1.8.2
github.com/magiconair/properties v1.8.5
github.com/mattn/go-isatty v0.0.12
github.com/otiai10/copy v1.5.0
github.com/pelletier/go-toml v1.8.1 // indirect
github.com/pkg/errors v0.9.1
github.com/prometheus/client_golang v1.9.0
github.com/prometheus/common v0.19.0
github.com/prometheus/client_golang v1.10.0
github.com/prometheus/common v0.20.0
github.com/rakyll/statik v0.1.7
github.com/regen-network/cosmos-proto v0.3.1
github.com/rs/zerolog v1.20.0
github.com/rs/zerolog v1.21.0
github.com/spf13/afero v1.3.4 // indirect
github.com/spf13/cast v1.3.1
github.com/spf13/cobra v1.1.3
@ -52,8 +53,8 @@ require (
github.com/tendermint/tm-db v0.6.4
golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad
google.golang.org/genproto v0.0.0-20210114201628-6edceaf6022f
google.golang.org/grpc v1.36.0
google.golang.org/protobuf v1.25.0
google.golang.org/grpc v1.36.1
google.golang.org/protobuf v1.26.0
gopkg.in/ini.v1 v1.61.0 // indirect
gopkg.in/yaml.v2 v2.4.0
nhooyr.io/websocket v1.8.6 // indirect

52
go.sum
View File

@ -258,8 +258,10 @@ github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:W
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/protobuf v1.4.3 h1:JjCZWpVbqXDqFVmTfYWEVTMIYrL/NPdPSCHPJ0T/raM=
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/golang/snappy v0.0.2-0.20200707131729-196ae77b8a26/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
@ -273,8 +275,10 @@ github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.2 h1:X2ev0eStA3AbceY54o37/0PQ/UWqKEiiO2dKL5OPaFM=
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/gofuzz v0.0.0-20170612174753-24818f796faf/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/gofuzz v1.1.1-0.20200604201612-c04b05f3adfa h1:Q75Upo5UN4JbPFURXZ8nLKYUvF85dyFRop/vQ0Rv+64=
@ -289,6 +293,7 @@ github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8=
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
github.com/gordonklaus/ineffassign v0.0.0-20200309095847-7953dde2c7bf/go.mod h1:cuNKsD1zp2v6XfE/orVX2QE1LC+i254ceGcVeDT3pTU=
github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg=
github.com/gorilla/handlers v1.5.1 h1:9lRY6j8DEeeBT10CvO9hGW0gmky0BprnvDI5vfhUHH4=
github.com/gorilla/handlers v1.5.1/go.mod h1:t8XrUpc4KVXb7HGyJ4/cEnwQiaxrX/hz1Zv/4g96P1Q=
@ -368,6 +373,8 @@ github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod
github.com/jackpal/go-nat-pmp v1.0.2-0.20160603034137-1fa385a6f458/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc=
github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
github.com/jhump/protoreflect v1.8.2 h1:k2xE7wcUomeqwY0LDCYA16y4WWfyTcMx5mKhk0d4ua0=
github.com/jhump/protoreflect v1.8.2/go.mod h1:7GcYQDdMU/O/BBrl/cX6PNHpXh6cenjd8pneu5yW7Tg=
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
github.com/jmhodges/levigo v1.0.0 h1:q5EC36kV79HWeTBWsod3mG11EgStG3qArTKcvlksN1U=
github.com/jmhodges/levigo v1.0.0/go.mod h1:Q6Qx+uH3RAqyK4rFQroq9RL7mdkABMcfhEI+nNuzMJQ=
@ -414,8 +421,8 @@ github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0U
github.com/lucasjones/reggen v0.0.0-20180717132126-cdb49ff09d77/go.mod h1:5ELEyG+X8f+meRWHuqUOewBOhvHkl7M76pdGEansxW4=
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
github.com/magiconair/properties v1.8.4 h1:8KGKTcQQGm0Kv7vEbKFErAoAOFyyacLStRtQSeYtvkY=
github.com/magiconair/properties v1.8.4/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60=
github.com/magiconair/properties v1.8.5 h1:b6kJs+EmPFMYGkow9GiUyCyOvIwYetYJ3fSaWak/Gls=
github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60=
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
github.com/mattn/go-colorable v0.1.0/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
@ -472,6 +479,7 @@ github.com/nats-io/nkeys v0.1.3/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxzi
github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
github.com/nishanths/predeclared v0.0.0-20200524104333-86fad755b4d3/go.mod h1:nt3d53pc1VYcphSCIaYAJtnPYnr3Zyn8fMq2wvPGPso=
github.com/nxadm/tail v1.4.4 h1:DQuhQpB1tVlglWS2hLQ5OV6B5r8aGxSrPc5Qo6uTN78=
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
github.com/oklog/oklog v0.3.2/go.mod h1:FCV+B7mhrz4o+ueLpx+KqkyXRGMWOYEvfiXtdGtbWGs=
@ -539,8 +547,8 @@ github.com/prometheus/client_golang v1.3.0/go.mod h1:hJaj2vgQTGQmVCsAACORcieXFeD
github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU=
github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M=
github.com/prometheus/client_golang v1.8.0/go.mod h1:O9VU6huf47PktckDQfMTX0Y8tY0/7TSWwj+ITvv0TnM=
github.com/prometheus/client_golang v1.9.0 h1:Rrch9mh17XcxvEu9D9DEpb4isxjGBtcevQjKvxPRQIU=
github.com/prometheus/client_golang v1.9.0/go.mod h1:FqZLKOZnGdFAhOK4nqGHa7D66IdsO+O441Eve7ptJDU=
github.com/prometheus/client_golang v1.10.0 h1:/o0BDeWzLWXNZ+4q5gXltUvaMpJqckTa+jTNoB+z4cg=
github.com/prometheus/client_golang v1.10.0/go.mod h1:WJM3cc3yu7XKBKa/I8WeZm+V3eltZnBwfENSU7mdogU=
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
@ -556,17 +564,18 @@ github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt2
github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4=
github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo=
github.com/prometheus/common v0.14.0/go.mod h1:U+gB1OBLb1lF3O42bTCL+FK18tX9Oar16Clt/msog/s=
github.com/prometheus/common v0.15.0/go.mod h1:U+gB1OBLb1lF3O42bTCL+FK18tX9Oar16Clt/msog/s=
github.com/prometheus/common v0.19.0 h1:Itb4+NjG9wRdkAWgVucbM/adyIXxEhbw0866e0uZE6A=
github.com/prometheus/common v0.19.0/go.mod h1:U+gB1OBLb1lF3O42bTCL+FK18tX9Oar16Clt/msog/s=
github.com/prometheus/common v0.18.0/go.mod h1:U+gB1OBLb1lF3O42bTCL+FK18tX9Oar16Clt/msog/s=
github.com/prometheus/common v0.20.0 h1:pfeDeUdQcIxOMutNjCejsEFp7qeP+/iltHSSmLpE+hU=
github.com/prometheus/common v0.20.0/go.mod h1:U+gB1OBLb1lF3O42bTCL+FK18tX9Oar16Clt/msog/s=
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A=
github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
github.com/prometheus/procfs v0.2.0 h1:wH4vA7pcjKuZzjF7lM8awk4fnuJO6idemZXoKnULUx4=
github.com/prometheus/procfs v0.2.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
github.com/prometheus/procfs v0.6.0 h1:mxy4L2jP6qMonqmq+aTtOx1ifVWUgG/TAmntgbh3xv4=
github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
github.com/prometheus/tsdb v0.6.2-0.20190402121629-4f204dcbc150/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
github.com/rakyll/statik v0.1.7 h1:OF3QCZUuyPxuGEP7B4ypUa7sB/iHtqOTDYZXGM8KOdQ=
@ -587,8 +596,8 @@ github.com/rs/cors v1.7.0 h1:+88SsELBHx5r+hZ8TCkggzSstaWNbDvThkVK8H6f9ik=
github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU=
github.com/rs/xhandler v0.0.0-20160618193221-ed27b6fd6521/go.mod h1:RvLn4FgxWubrpZHtQLnOf6EwhN2hEMusxZOhcW9H3UQ=
github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ=
github.com/rs/zerolog v1.20.0 h1:38k9hgtUBdxFwE34yS8rTHmHBa4eN16E4DJlv177LNs=
github.com/rs/zerolog v1.20.0/go.mod h1:IzD0RJ65iWH0w97OQQebJEvTZYvsCUm9WVLWBQrJRjo=
github.com/rs/zerolog v1.21.0 h1:Q3vdXlfLNT+OftyBHsU0Y445MD+8m8axjKgf2si0QcM=
github.com/rs/zerolog v1.21.0/go.mod h1:ZPhntP/xmq1nnND05hhpAh2QMhSsA4UN3MGZ6O2J3hM=
github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
@ -697,6 +706,7 @@ github.com/wsddn/go-ecdh v0.0.0-20161211032359-48726bab9208/go.mod h1:IotVbo4F+m
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/zondax/hid v0.9.0 h1:eiT3P6vNxAEVxXMw66eZUAAnU2zD33JBkfG/EnfAKl8=
github.com/zondax/hid v0.9.0/go.mod h1:l5wttcP0jwtdLjqjMMWFVEE7d1zO0jvSPA9OPZxWpEM=
@ -807,6 +817,7 @@ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@ -851,8 +862,10 @@ golang.org/x/sys v0.0.0-20200909081042-eff7692f9009/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20200922070232-aee5d888a860/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201015000850-e3ed0017c211/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201214210602-f9fddec55a1e h1:AyodaIpKjppX+cBfTASF2E1US3H2JFBj920Ot3rtDjs=
golang.org/x/sys v0.0.0-20201214210602-f9fddec55a1e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210309074719-68d13333faf2 h1:46ULzRKLh1CwgRq2dC5SlBzEqqNCi8rreOZnNrbqcIY=
golang.org/x/sys v0.0.0-20210309074719-68d13333faf2/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221 h1:/ZHdbVpdR/jk3g30/d4yUL0JU9kksj8+F/bnQUVLGDM=
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
@ -877,18 +890,21 @@ golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgw
golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20190828213141-aed303cbaa74/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191112195655-aa38f8e97acc/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20200103221440-774c71fcf114/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200117012304-6edc0a871e69/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200522201501-cb1345f3a375/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200717024301-6ddee64345a6/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
@ -935,8 +951,11 @@ google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4=
google.golang.org/protobuf v1.25.0 h1:Ejskq+SyPohKW+1uil0JJMtmHCgJPJ/qWTxr8qp+R4c=
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
google.golang.org/protobuf v1.25.1-0.20200805231151-a709e31e5d12/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.26.0 h1:bxAC2xTBsZGibn2RTntX0oH50xLsqy1OxA9tTL3p/lk=
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
@ -977,6 +996,7 @@ honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWh
honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
nhooyr.io/websocket v1.8.6 h1:s+C3xAMLwGmlI31Nyn/eAehUlZPwfYZu2JXM621Q5/k=
nhooyr.io/websocket v1.8.6/go.mod h1:B70DZP8IakI65RVQ51MsWP/8jndNma26DVA/nFSCgW0=
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=

View File

@ -15,7 +15,8 @@ message GenesisState {
// balances is an array containing the balances of all the accounts.
repeated Balance balances = 2 [(gogoproto.nullable) = false];
// supply represents the total supply.
// supply represents the total supply. If it is left empty, then supply will be calculated based on the provided
// balances. Otherwise, it will be used to validate that the sum of the balances equals this amount.
repeated cosmos.base.v1beta1.Coin supply = 3
[(gogoproto.castrepeated) = "github.com/cosmos/cosmos-sdk/types.Coins", (gogoproto.nullable) = false];

View File

@ -90,7 +90,13 @@ message QueryAllBalancesResponse {
// QueryTotalSupplyRequest is the request type for the Query/TotalSupply RPC
// method.
message QueryTotalSupplyRequest {}
message QueryTotalSupplyRequest {
option (gogoproto.equal) = false;
option (gogoproto.goproto_getters) = false;
// pagination defines an optional pagination for the request.
cosmos.base.query.v1beta1.PageRequest pagination = 1;
}
// QueryTotalSupplyResponse is the response type for the Query/TotalSupply RPC
// method
@ -98,6 +104,9 @@ message QueryTotalSupplyResponse {
// supply is the supply of the coins
repeated cosmos.base.v1beta1.Coin supply = 1
[(gogoproto.nullable) = false, (gogoproto.castrepeated) = "github.com/cosmos/cosmos-sdk/types.Coins"];
// pagination defines the pagination in the response.
cosmos.base.query.v1beta1.PageResponse pagination = 2;
}
// QuerySupplyOfRequest is the request type for the Query/SupplyOf RPC method.

Some files were not shown because too many files have changed in this diff Show More