diff --git a/docs/post.sh b/docs/post.sh index 9dbcb119ed1f..62264248e924 100755 --- a/docs/post.sh +++ b/docs/post.sh @@ -12,3 +12,4 @@ rm -rf build/spec rm -rf build/rfc rm -rf learn/advanced/17-autocli.md rm -rf build/migrations/02-upgrading.md +rm -rf user/run-node/04-rosetta.md \ No newline at end of file diff --git a/docs/pre.sh b/docs/pre.sh index 622c3cd6d363..3c12a9a67d06 100755 --- a/docs/pre.sh +++ b/docs/pre.sh @@ -36,6 +36,9 @@ cp ../depinject/README.md ./build/packages/01-depinject.md cp ../collections/README.md ./build/packages/02-collections.md cp ../orm/README.md ./build/packages/03-orm.md +## Update user docs with rosetta +wget -O "./user/run-node/04-rosetta.md" "https://raw.githubusercontent.com/cosmos/rosetta/main/README.md" + ## Add architecture documentation cp -r ./architecture ./build diff --git a/docs/user/run-node/00-keyring.md b/docs/user/run-node/00-keyring.md new file mode 100644 index 000000000000..b4a2020068fe --- /dev/null +++ b/docs/user/run-node/00-keyring.md @@ -0,0 +1,134 @@ +--- +sidebar_position: 1 +--- + +# Setting up the keyring + +:::note Synopsis +This document describes how to configure and use the keyring and its various backends for an [**application**](../../learn/beginner/00-app-anatomy.md). +::: + +The keyring holds the private/public keypairs used to interact with a node. For instance, a validator key needs to be set up before running the blockchain node, so that blocks can be correctly signed. The private key can be stored in different locations, called "backends", such as a file or the operating system's own key storage. + +## Available backends for the keyring + +Starting with the v0.38.0 release, Cosmos SDK comes with a new keyring implementation +that provides a set of commands to manage cryptographic keys in a secure fashion. The +new keyring supports multiple storage backends, some of which may not be available on +all operating systems. + +### The `os` backend + +The `os` backend relies on operating system-specific defaults to handle key storage +securely. Typically, an operating system's credential sub-system handles password prompts, +private keys storage, and user sessions according to the user's password policies. Here +is a list of the most popular operating systems and their respective passwords manager: + +* macOS: [Keychain](https://support.apple.com/en-gb/guide/keychain-access/welcome/mac) +* Windows: [Credentials Management API](https://docs.microsoft.com/en-us/windows/win32/secauthn/credentials-management) +* GNU/Linux: + * [libsecret](https://gitlab.gnome.org/GNOME/libsecret) + * [kwallet](https://api.kde.org/frameworks/kwallet/html/index.html) + +GNU/Linux distributions that use GNOME as default desktop environment typically come with +[Seahorse](https://wiki.gnome.org/Apps/Seahorse). Users of KDE based distributions are +commonly provided with [KDE Wallet Manager](https://userbase.kde.org/KDE_Wallet_Manager). +Whilst the former is in fact a `libsecret` convenient frontend, the latter is a `kwallet` +client. + +`os` is the default option since operating system's default credentials managers are +designed to meet users' most common needs and provide them with a comfortable +experience without compromising on security. + +The recommended backends for headless environments are `file` and `pass`. + +### The `file` backend + +The `file` backend more closely resembles the keybase implementation used prior to +v0.38.1. It stores the keyring encrypted within the app's configuration directory. This +keyring will request a password each time it is accessed, which may occur multiple +times in a single command resulting in repeated password prompts. If using bash scripts +to execute commands using the `file` option you may want to utilize the following format +for multiple prompts: + +```shell +# assuming that KEYPASSWD is set in the environment +$ gaiacli config keyring-backend file # use file backend +$ (echo $KEYPASSWD; echo $KEYPASSWD) | gaiacli keys add me # multiple prompts +$ echo $KEYPASSWD | gaiacli keys show me # single prompt +``` + +:::tip +The first time you add a key to an empty keyring, you will be prompted to type the password twice. +::: + +### The `pass` backend + +The `pass` backend uses the [pass](https://www.passwordstore.org/) utility to manage on-disk +encryption of keys' sensitive data and metadata. Keys are stored inside `gpg` encrypted files +within app-specific directories. `pass` is available for the most popular UNIX +operating systems as well as GNU/Linux distributions. Please refer to its manual page for +information on how to download and install it. + +:::tip +**pass** uses [GnuPG](https://gnupg.org/) for encryption. `gpg` automatically invokes the `gpg-agent` +daemon upon execution, which handles the caching of GnuPG credentials. Please refer to `gpg-agent` +man page for more information on how to configure cache parameters such as credentials TTL and +passphrase expiration. +::: + +The password store must be set up prior to first use: + +```shell +pass init +``` + +Replace `` with your GPG key ID. You can use your personal GPG key or an alternative +one you may want to use specifically to encrypt the password store. + +### The `kwallet` backend + +The `kwallet` backend uses `KDE Wallet Manager`, which comes installed by default on the +GNU/Linux distributions that ships KDE as default desktop environment. Please refer to +[KWallet Handbook](https://docs.kde.org/stable5/en/kdeutils/kwallet5/index.html) for more +information. + +### The `test` backend + +The `test` backend is a password-less variation of the `file` backend. Keys are stored +unencrypted on disk. + +**Provided for testing purposes only. The `test` backend is not recommended for use in production environments**. + +### The `memory` backend + +The `memory` backend stores keys in memory. The keys are immediately deleted after the program has exited. + +**Provided for testing purposes only. The `memory` backend is not recommended for use in production environments**. + +### Setting backend using the env variable + +You can set the keyring-backend using env variable: `BINNAME_KEYRING_BACKEND`. For example, if your binary name is `gaia-v5` then set: `export GAIA_V5_KEYRING_BACKEND=pass` + +## Adding keys to the keyring + +:::warning +Make sure you can build your own binary, and replace `simd` with the name of your binary in the snippets. +::: + +Applications developed using the Cosmos SDK come with the `keys` subcommand. For the purpose of this tutorial, we're running the `simd` CLI, which is an application built using the Cosmos SDK for testing and educational purposes. For more information, see [`simapp`](https://github.com/cosmos/cosmos-sdk/tree/main/simapp). + +You can use `simd keys` for help about the keys command and `simd keys [command] --help` for more information about a particular subcommand. + +To create a new key in the keyring, run the `add` subcommand with a `` argument. For the purpose of this tutorial, we will solely use the `test` backend, and call our new key `my_validator`. This key will be used in the next section. + +```bash +$ simd keys add my_validator --keyring-backend test + +# Put the generated address in a variable for later use. +MY_VALIDATOR_ADDRESS=$(simd keys show my_validator -a --keyring-backend test) +``` + +This command generates a new 24-word mnemonic phrase, persists it to the relevant backend, and outputs information about the keypair. If this keypair will be used to hold value-bearing tokens, be sure to write down the mnemonic phrase somewhere safe! + +By default, the keyring generates a `secp256k1` keypair. The keyring also supports `ed25519` keys, which may be created by passing the `--algo ed25519` flag. A keyring can of course hold both types of keys simultaneously, and the Cosmos SDK's `x/auth` module supports natively these two public key algorithms. diff --git a/docs/user/run-node/01-run-node.md b/docs/user/run-node/01-run-node.md new file mode 100644 index 000000000000..9b1dfb4ebd59 --- /dev/null +++ b/docs/user/run-node/01-run-node.md @@ -0,0 +1,228 @@ +--- +sidebar_position: 1 +--- + +# Running a Node + +:::note Synopsis +Now that the application is ready and the keyring populated, it's time to see how to run the blockchain node. In this section, the application we are running is called [`simapp`](https://github.com/cosmos/cosmos-sdk/tree/main/simapp), and its corresponding CLI binary `simd`. +::: + +:::note Pre-requisite Readings + +* [Anatomy of a Cosmos SDK Application](../../learn/beginner/00-app-anatomy.md) +* [Setting up the keyring](./00-keyring.md) + +::: + +## Initialize the Chain + +:::warning +Make sure you can build your own binary, and replace `simd` with the name of your binary in the snippets. +::: + +Before actually running the node, we need to initialize the chain, and most importantly its genesis file. This is done with the `init` subcommand: + +```bash +# The argument is the custom username of your node, it should be human-readable. +simd init --chain-id my-test-chain +``` + +The command above creates all the configuration files needed for your node to run, as well as a default genesis file, which defines the initial state of the network. + +:::tip +All these configuration files are in `~/.simapp` by default, but you can overwrite the location of this folder by passing the `--home` flag to each commands, +or set an `$APPD_HOME` environment variable (where `APPD` is the name of the binary). +::: + +The `~/.simapp` folder has the following structure: + +```bash +. # ~/.simapp + |- data # Contains the databases used by the node. + |- config/ + |- app.toml # Application-related configuration file. + |- config.toml # CometBFT-related configuration file. + |- genesis.json # The genesis file. + |- node_key.json # Private key to use for node authentication in the p2p protocol. + |- priv_validator_key.json # Private key to use as a validator in the consensus protocol. +``` + +## Updating Some Default Settings + +If you want to change any field values in configuration files (for ex: genesis.json) you can use `jq` ([installation](https://stedolan.github.io/jq/download/) & [docs](https://stedolan.github.io/jq/manual/#Assignment)) & `sed` commands to do that. Few examples are listed here. + +```bash +# to change the chain-id +jq '.chain_id = "testing"' genesis.json > temp.json && mv temp.json genesis.json + +# to enable the api server +sed -i '/\[api\]/,+3 s/enable = false/enable = true/' app.toml + +# to change the voting_period +jq '.app_state.gov.voting_params.voting_period = "600s"' genesis.json > temp.json && mv temp.json genesis.json + +# to change the inflation +jq '.app_state.mint.minter.inflation = "0.300000000000000000"' genesis.json > temp.json && mv temp.json genesis.json +``` + +### Client Interaction + +When instantiating a node, GRPC and REST are defaulted to localhost to avoid unknown exposure of your node to the public. It is recommended to not expose these endpoints without a proxy that can handle load balancing or authentication is setup between your node and the public. + +:::tip +A commonly used tool for this is [nginx](https://nginx.org). +::: + + +## Adding Genesis Accounts + +Before starting the chain, you need to populate the state with at least one account. To do so, first [create a new account in the keyring](./00-keyring.md#adding-keys-to-the-keyring) named `my_validator` under the `test` keyring backend (feel free to choose another name and another backend). + +Now that you have created a local account, go ahead and grant it some `stake` tokens in your chain's genesis file. Doing so will also make sure your chain is aware of this account's existence: + +```bash +simd genesis add-genesis-account $MY_VALIDATOR_ADDRESS 100000000000stake +``` + +Recall that `$MY_VALIDATOR_ADDRESS` is a variable that holds the address of the `my_validator` key in the [keyring](./00-keyring.md#adding-keys-to-the-keyring). Also note that the tokens in the Cosmos SDK have the `{amount}{denom}` format: `amount` is an 18-digit-precision decimal number, and `denom` is the unique token identifier with its denomination key (e.g. `atom` or `uatom`). Here, we are granting `stake` tokens, as `stake` is the token identifier used for staking in [`simapp`](https://github.com/cosmos/cosmos-sdk/tree/main/simapp). For your own chain with its own staking denom, that token identifier should be used instead. + +Now that your account has some tokens, you need to add a validator to your chain. Validators are special full-nodes that participate in the consensus process (implemented in the [underlying consensus engine](../../learn/intro/02-sdk-app-architecture.md#cometbft)) in order to add new blocks to the chain. Any account can declare its intention to become a validator operator, but only those with sufficient delegation get to enter the active set (for example, only the top 125 validator candidates with the most delegation get to be validators in the Cosmos Hub). For this guide, you will add your local node (created via the `init` command above) as a validator of your chain. Validators can be declared before a chain is first started via a special transaction included in the genesis file called a `gentx`: + +```bash +# Create a gentx. +simd genesis gentx my_validator 100000000stake --chain-id my-test-chain --keyring-backend test + +# Add the gentx to the genesis file. +simd genesis collect-gentxs +``` + +A `gentx` does three things: + +1. Registers the `validator` account you created as a validator operator account (i.e. the account that controls the validator). +2. Self-delegates the provided `amount` of staking tokens. +3. Link the operator account with a CometBFT node pubkey that will be used for signing blocks. If no `--pubkey` flag is provided, it defaults to the local node pubkey created via the `simd init` command above. + +For more information on `gentx`, use the following command: + +```bash +simd genesis gentx --help +``` + +## Configuring the Node Using `app.toml` and `config.toml` + +The Cosmos SDK automatically generates two configuration files inside `~/.simapp/config`: + +* `config.toml`: used to configure the CometBFT, learn more on [CometBFT's documentation](https://docs.cometbft.com/v0.37/core/configuration), +* `app.toml`: generated by the Cosmos SDK, and used to configure your app, such as state pruning strategies, telemetry, gRPC and REST servers configuration, state sync... + +Both files are heavily commented, please refer to them directly to tweak your node. + +One example config to tweak is the `minimum-gas-prices` field inside `app.toml`, which defines the minimum gas prices the validator node is willing to accept for processing a transaction. Depending on the chain, it might be an empty string or not. If it's empty, make sure to edit the field with some value, for example `10token`, or else the node will halt on startup. For the purpose of this tutorial, let's set the minimum gas price to 0: + +```toml + # The minimum gas prices a validator is willing to accept for processing a + # transaction. A transaction's fees must meet the minimum of any denomination + # specified in this config (e.g. 0.25token1;0.0001token2). + minimum-gas-prices = "0stake" +``` + +:::tip +When running a node (not a validator!) and not wanting to run the application mempool, set the `max-txs` field to `-1`. + +```toml +[mempool] +# Setting max-txs to 0 will allow for a unbounded amount of transactions in the mempool. +# Setting max_txs to negative 1 (-1) will disable transactions from being inserted into the mempool. +# Setting max_txs to a positive number (> 0) will limit the number of transactions in the mempool, by the specified amount. +# +# Note, this configuration only applies to SDK built-in app-side mempool +# implementations. +max-txs = "-1" +``` + +::: + +## Run a Localnet + +Now that everything is set up, you can finally start your node: + +```bash +simd start +``` + +You should see blocks come in. + +The previous command allow you to run a single node. This is enough for the next section on interacting with this node, but you may wish to run multiple nodes at the same time, and see how consensus happens between them. + +The naive way would be to run the same commands again in separate terminal windows. This is possible, however in the Cosmos SDK, we leverage the power of [Docker Compose](https://docs.docker.com/compose/) to run a localnet. If you need inspiration on how to set up your own localnet with Docker Compose, you can have a look at the Cosmos SDK's [`docker-compose.yml`](https://github.com/cosmos/cosmos-sdk/blob/v0.50.0-alpha.0/docker-compose.yml). + +### Standalone App/CometBFT + +By default, the Cosmos SDK runs CometBFT in-process with the application +If you want to run the application and CometBFT in separate processes, +start the application with the `--with-comet=false` flag +and set `rpc.laddr` in `config.toml` to the CometBFT node's RPC address. + +## Logging + +Logging provides a way to see what is going on with a node. By default the `info` level is set. This is a global level and all info logs will be outputted to the terminal. + +If you would like to filter specific logs to the terminal instead of all, then setting `:` is how this can work. +Example: + +In `config.toml`: + +```toml +log_level: "state:info,p2p:info,consensus:info,x/staking:info,x/ibc:info,*:error" +``` + +Or directly in the command line: + +```bash + start --log_level "state:info,p2p:info,consensus:info,x/staking:info,x/ibc:info,*:error" +``` + +The above will show info logs for the state, p2p, consensus, staking, and ibc modules, and error logs for all other modules. +When no log filtering is required, simply use one of the supported global log levels: `trace`, `debug`, `info`, `warn`, `error`, `fatal`, `panic` or `disabled`. + +## State Sync + +State sync is the act in which a node syncs the latest or close to the latest state of a blockchain. This is useful for users who don't want to sync all the blocks in history. Read more in [CometBFT documentation](https://docs.cometbft.com/v0.37/core/state-sync). + +State sync works thanks to snapshots. Read how the SDK handles snapshots [here](https://github.com/cosmos/cosmos-sdk/blob/825245d/store/snapshots/README.md). + +### Local State Sync + +Local state sync work similar to normal state sync except that it works off a local snapshot of state instead of one provided via the p2p network. The steps to start local state sync are similar to normal state sync with a few different designs. + +1. As mentioned in https://docs.cometbft.com/v0.37/core/state-sync, one must set a height and hash in the config.toml along with a few rpc servers (the afromentioned link has instructions on how to do this). +2. Run ` ` to restore a local snapshot (note: first load it from a file with the *load* command). +3. Bootsrapping Comet state in order to start the node after the snapshot has been ingested. This can be done with the bootstrap command ` comet bootstrap-state` + +### Snapshots Commands + +The Cosmos SDK provides commands for managing snapshots. +These commands can be added in an app with the following snippet in `cmd//root.go`: + +```go +import ( + "github.com/cosmos/cosmos-sdk/client/snapshot" +) + +func initRootCmd(/* ... */) { + // ... + rootCmd.AddCommand( + snapshot.Cmd(appCreator), + ) +} +``` + +Then following commands are available at ` snapshots [command]`: + +* **list**: list local snapshots +* **load**: Load a snapshot archive file into snapshot store +* **restore**: Restore app state from local snapshot +* **export**: Export app state to snapshot store +* **dump**: Dump the snapshot as portable archive format +* **delete**: Delete a local snapshot diff --git a/docs/user/run-node/02-interact-node.md b/docs/user/run-node/02-interact-node.md new file mode 100644 index 000000000000..a511aec41836 --- /dev/null +++ b/docs/user/run-node/02-interact-node.md @@ -0,0 +1,289 @@ +--- +sidebar_position: 1 +--- + +# Interacting with the Node + +:::note Synopsis +There are multiple ways to interact with a node: using the CLI, using gRPC or using the REST endpoints. +::: + +:::note Pre-requisite Readings + +* [gRPC, REST and CometBFT Endpoints](../../learn/advanced/06-grpc_rest.md) +* [Running a Node](./01-run-node.md) + +::: + +## Using the CLI + +Now that your chain is running, it is time to try sending tokens from the first account you created to a second account. In a new terminal window, start by running the following query command: + +```bash +simd query bank balances $MY_VALIDATOR_ADDRESS +``` + +You should see the current balance of the account you created, equal to the original balance of `stake` you granted it minus the amount you delegated via the `gentx`. Now, create a second account: + +```bash +simd keys add recipient --keyring-backend test + +# Put the generated address in a variable for later use. +RECIPIENT=$(simd keys show recipient -a --keyring-backend test) +``` + +The command above creates a local key-pair that is not yet registered on the chain. An account is created the first time it receives tokens from another account. Now, run the following command to send tokens to the `recipient` account: + +```bash +simd tx bank send $MY_VALIDATOR_ADDRESS $RECIPIENT 1000000stake --chain-id my-test-chain --keyring-backend test + +# Check that the recipient account did receive the tokens. +simd query bank balances $RECIPIENT +``` + +Finally, delegate some of the stake tokens sent to the `recipient` account to the validator: + +```bash +simd tx staking delegate $(simd keys show my_validator --bech val -a --keyring-backend test) 500stake --from recipient --chain-id my-test-chain --keyring-backend test + +# Query the total delegations to `validator`. +simd query staking delegations-to $(simd keys show my_validator --bech val -a --keyring-backend test) +``` + +You should see two delegations, the first one made from the `gentx`, and the second one you just performed from the `recipient` account. + +## Using gRPC + +The Protobuf ecosystem developed tools for different use cases, including code-generation from `*.proto` files into various languages. These tools allow the building of clients easily. Often, the client connection (i.e. the transport) can be plugged and replaced very easily. Let's explore one of the most popular transport: [gRPC](../../learn/advanced/06-grpc_rest.md). + +Since the code generation library largely depends on your own tech stack, we will only present three alternatives: + +* `grpcurl` for generic debugging and testing, +* programmatically via Go, +* CosmJS for JavaScript/TypeScript developers. + +### 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. + +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/01-run-node.md#configuring-the-node-using-apptoml-and-configtoml)): + +```bash +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 order to get a description of the service you can run the following command: + +```bash +grpcurl -plaintext \ + localhost:9090 \ + describe cosmos.bank.v1beta1.Query # Service we want to inspect +``` + +It's also possible to execute an RPC call to query the node for information: + +```bash +grpcurl \ + -plaintext \ + -d "{\"address\":\"$MY_VALIDATOR_ADDRESS\"}" \ + localhost:9090 \ + cosmos.bank.v1beta1.Query/AllBalances +``` + +The list of all available gRPC query endpoints is [coming soon](https://github.com/cosmos/cosmos-sdk/issues/7786). + +#### Query for historical state using grpcurl + +You may also query for historical data by passing some [gRPC metadata](https://github.com/grpc/grpc-go/blob/master/Documentation/grpc-metadata.md) to the query: the `x-cosmos-block-height` metadata should contain the block to query. Using grpcurl as above, the command looks like: + +```bash +grpcurl \ + -plaintext \ + -H "x-cosmos-block-height: 123" \ + -d "{\"address\":\"$MY_VALIDATOR_ADDRESS\"}" \ + localhost:9090 \ + cosmos.bank.v1beta1.Query/AllBalances +``` + +Assuming the state at that block has not yet been pruned by the node, this query should return a non-empty response. + +### Programmatically via Go + +The following snippet shows how to query the state using gRPC inside a Go program. The idea is to create a gRPC connection, and use the Protobuf-generated client code to query the gRPC server. + +#### Install Cosmos SDK + + +```bash +go get github.com/cosmos/cosmos-sdk@main +``` + +```go +package main + +import ( + "context" + "fmt" + + "google.golang.org/grpc" + + "github.com/cosmos/cosmos-sdk/codec" + sdk "github.com/cosmos/cosmos-sdk/types" + banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" +) + +func queryState() error { + myAddress, err := sdk.AccAddressFromBech32("cosmos1...") // the my_validator or recipient address. + if err != nil { + return err + } + + // Create a connection to the gRPC server. + grpcConn, err := grpc.Dial( + "127.0.0.1:9090", // your gRPC server address. + grpc.WithInsecure(), // The Cosmos SDK doesn't support any transport security mechanism. + // This instantiates a general gRPC codec which handles proto bytes. We pass in a nil interface registry + // if the request/response types contain interface instead of 'nil' you should pass the application specific codec. + grpc.WithDefaultCallOptions(grpc.ForceCodec(codec.NewProtoCodec(nil).GRPCCodec())), + ) + if err != nil { + return err + } + defer grpcConn.Close() + + // This creates a gRPC client to query the x/bank service. + bankClient := banktypes.NewQueryClient(grpcConn) + bankRes, err := bankClient.Balance( + context.Background(), + &banktypes.QueryBalanceRequest{Address: myAddress.String(), Denom: "stake"}, + ) + if err != nil { + return err + } + + fmt.Println(bankRes.GetBalance()) // Prints the account balance + + return nil +} + +func main() { + if err := queryState(); err != nil { + panic(err) + } +} +``` + +You can replace the query client (here we are using `x/bank`'s) with one generated from any other Protobuf service. The list of all available gRPC query endpoints is [coming soon](https://github.com/cosmos/cosmos-sdk/issues/7786). + +#### Query for historical state using Go + +Querying for historical blocks is done by adding the block height metadata in the gRPC request. + +```go +package main + +import ( + "context" + "fmt" + + "google.golang.org/grpc" + "google.golang.org/grpc/metadata" + + "github.com/cosmos/cosmos-sdk/codec" + sdk "github.com/cosmos/cosmos-sdk/types" + grpctypes "github.com/cosmos/cosmos-sdk/types/grpc" + banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" +) + +func queryState() error { + myAddress, err := sdk.AccAddressFromBech32("cosmos1yerherx4d43gj5wa3zl5vflj9d4pln42n7kuzu") // the my_validator or recipient address. + if err != nil { + return err + } + + // Create a connection to the gRPC server. + grpcConn, err := grpc.Dial( + "127.0.0.1:9090", // your gRPC server address. + grpc.WithInsecure(), // The Cosmos SDK doesn't support any transport security mechanism. + // This instantiates a general gRPC codec which handles proto bytes. We pass in a nil interface registry + // if the request/response types contain interface instead of 'nil' you should pass the application specific codec. + grpc.WithDefaultCallOptions(grpc.ForceCodec(codec.NewProtoCodec(nil).GRPCCodec())), + ) + if err != nil { + return err + } + defer grpcConn.Close() + + // This creates a gRPC client to query the x/bank service. + bankClient := banktypes.NewQueryClient(grpcConn) + + var header metadata.MD + _, err = bankClient.Balance( + metadata.AppendToOutgoingContext(context.Background(), grpctypes.GRPCBlockHeightHeader, "12"), // Add metadata to request + &banktypes.QueryBalanceRequest{Address: myAddress.String(), Denom: "stake"}, + grpc.Header(&header), // Retrieve header from response + ) + if err != nil { + return err + } + blockHeight := header.Get(grpctypes.GRPCBlockHeightHeader) + + fmt.Println(blockHeight) // Prints the block height (12) + + return nil +} + +func main() { + if err := queryState(); err != nil { + panic(err) + } +} +``` + +### CosmJS + +CosmJS documentation can be found at [https://cosmos.github.io/cosmjs](https://cosmos.github.io/cosmjs). As of January 2021, CosmJS documentation is still work in progress. + +## Using the REST Endpoints + +As described in the [gRPC guide](../../learn/advanced/06-grpc_rest.md), all gRPC services on the Cosmos SDK are made available for more convenient REST-based queries through gRPC-gateway. The format of the URL path is based on the Protobuf service method's full-qualified name, but may contain small customizations so that final URLs look more idiomatic. For example, the REST endpoint for the `cosmos.bank.v1beta1.Query/AllBalances` method is `GET /cosmos/bank/v1beta1/balances/{address}`. Request arguments are passed as query parameters. + +Note that the REST endpoints are not enabled by default. To enable them, edit the `api` section of your `~/.simapp/config/app.toml` file: + +```toml +# Enable defines if the API server should be enabled. +enable = true +``` + +As a concrete example, the `curl` command to make balances request is: + +```bash +curl \ + -X GET \ + -H "Content-Type: application/json" \ + http://localhost:1317/cosmos/bank/v1beta1/balances/$MY_VALIDATOR_ADDRESS +``` + +Make sure to replace `localhost:1317` with the REST endpoint of your node, configured under the `api.address` field. + +The list of all available REST endpoints is available as a Swagger specification file, it can be viewed at `localhost:1317/swagger`. Make sure that the `api.swagger` field is set to true in your [`app.toml`](../run-node/01-run-node.md#configuring-the-node-using-apptoml-and-configtoml) file. + +### Query for historical state using REST + +Querying for historical state is done using the HTTP header `x-cosmos-block-height`. For example, a curl command would look like: + +```bash +curl \ + -X GET \ + -H "Content-Type: application/json" \ + -H "x-cosmos-block-height: 123" \ + http://localhost:1317/cosmos/bank/v1beta1/balances/$MY_VALIDATOR_ADDRESS +``` + +Assuming the state at that block has not yet been pruned by the node, this query should return a non-empty response. + +### Cross-Origin Resource Sharing (CORS) + +[CORS policies](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS) are not enabled by default to help with security. If you would like to use the rest-server in a public environment we recommend you provide a reverse proxy, this can be done with [nginx](https://www.nginx.com/). For testing and development purposes there is an `enabled-unsafe-cors` field inside [`app.toml`](../run-node/01-run-node.md#configuring-the-node-using-apptoml-and-configtoml). diff --git a/docs/user/run-node/03-txs.md b/docs/user/run-node/03-txs.md new file mode 100644 index 000000000000..106f02e8e8e8 --- /dev/null +++ b/docs/user/run-node/03-txs.md @@ -0,0 +1,387 @@ +--- +sidebar_position: 1 +--- + +# Generating, Signing and Broadcasting Transactions + +:::note Synopsis +This document describes how to generate an (unsigned) transaction, signing it (with one or multiple keys), and broadcasting it to the network. +::: + +## Using the CLI + +The easiest way to send transactions is using the CLI, as we have seen in the previous page when [interacting with a node](./02-interact-node.md#using-the-cli). For example, running the following command + +```bash +simd tx bank send $MY_VALIDATOR_ADDRESS $RECIPIENT 1000stake --chain-id my-test-chain --keyring-backend test +``` + +will run the following steps: + +* generate a transaction with one `Msg` (`x/bank`'s `MsgSend`), and print the generated transaction to the console. +* ask the user for confirmation to send the transaction from the `$MY_VALIDATOR_ADDRESS` account. +* fetch `$MY_VALIDATOR_ADDRESS` from the keyring. This is possible because we have [set up the CLI's keyring](./00-keyring.md) in a previous step. +* sign the generated transaction with the keyring's account. +* broadcast the signed transaction to the network. This is possible because the CLI connects to the node's CometBFT RPC endpoint. + +The CLI bundles all the necessary steps into a simple-to-use user experience. However, it's possible to run all the steps individually too. + +### Generating a Transaction + +Generating a transaction can simply be done by appending the `--generate-only` flag on any `tx` command, e.g.: + +```bash +simd tx bank send $MY_VALIDATOR_ADDRESS $RECIPIENT 1000stake --chain-id my-test-chain --generate-only +``` + +This will output the unsigned transaction as JSON in the console. We can also save the unsigned transaction to a file (to be passed around between signers more easily) by appending `> unsigned_tx.json` to the above command. + +### Signing a Transaction + +Signing a transaction using the CLI requires the unsigned transaction to be saved in a file. Let's assume the unsigned transaction is in a file called `unsigned_tx.json` in the current directory (see previous paragraph on how to do that). Then, simply run the following command: + +```bash +simd tx sign unsigned_tx.json --chain-id my-test-chain --keyring-backend test --from $MY_VALIDATOR_ADDRESS +``` + +This command will decode the unsigned transaction and sign it with `SIGN_MODE_DIRECT` with `$MY_VALIDATOR_ADDRESS`'s key, which we already set up in the keyring. The signed transaction will be output as JSON to the console, and, as above, we can save it to a file by appending `--output-document signed_tx.json`. + +Some useful flags to consider in the `tx sign` command: + +* `--sign-mode`: you may use `amino-json` to sign the transaction using `SIGN_MODE_LEGACY_AMINO_JSON`, +* `--offline`: sign in offline mode. This means that the `tx sign` command doesn't connect to the node to retrieve the signer's account number and sequence, both needed for signing. In this case, you must manually supply the `--account-number` and `--sequence` flags. This is useful for offline signing, i.e. signing in a secure environment which doesn't have access to the internet. + +#### Signing with Multiple Signers + +:::warning +Please note that signing a transaction with multiple signers or with a multisig account, where at least one signer uses `SIGN_MODE_DIRECT`, is not yet possible. You may follow [this Github issue](https://github.com/cosmos/cosmos-sdk/issues/8141) for more info. +::: + +Signing with multiple signers is done with the `tx multisign` command. This command assumes that all signers use `SIGN_MODE_LEGACY_AMINO_JSON`. The flow is similar to the `tx sign` command flow, but instead of signing an unsigned transaction file, each signer signs the file signed by previous signer(s). The `tx multisign` command will append signatures to the existing transactions. It is important that signers sign the transaction **in the same order** as given by the transaction, which is retrievable using the `GetSigners()` method. + +For example, starting with the `unsigned_tx.json`, and assuming the transaction has 4 signers, we would run: + +```bash +# Let signer1 sign the unsigned tx. +simd tx multisign unsigned_tx.json signer_key_1 --chain-id my-test-chain --keyring-backend test > partial_tx_1.json +# Now signer1 will send the partial_tx_1.json to the signer2. +# Signer2 appends their signature: +simd tx multisign partial_tx_1.json signer_key_2 --chain-id my-test-chain --keyring-backend test > partial_tx_2.json +# Signer2 sends the partial_tx_2.json file to signer3, and signer3 can append his signature: +simd tx multisign partial_tx_2.json signer_key_3 --chain-id my-test-chain --keyring-backend test > partial_tx_3.json +``` + +### Broadcasting a Transaction + +Broadcasting a transaction is done using the following command: + +```bash +simd tx broadcast tx_signed.json +``` + +You may optionally pass the `--broadcast-mode` flag to specify which response to receive from the node: + +* `sync`: the CLI waits for a CheckTx execution response only. +* `async`: the CLI returns immediately (transaction might fail). + +### Encoding a Transaction + +In order to broadcast a transaction using the gRPC or REST endpoints, the transaction will need to be encoded first. This can be done using the CLI. + +Encoding a transaction is done using the following command: + +```bash +simd tx encode tx_signed.json +``` + +This will read the transaction from the file, serialize it using Protobuf, and output the transaction bytes as base64 in the console. + +### Decoding a Transaction + +The CLI can also be used to decode transaction bytes. + +Decoding a transaction is done using the following command: + +```bash +simd tx decode [protobuf-byte-string] +``` + +This will decode the transaction bytes and output the transaction as JSON in the console. You can also save the transaction to a file by appending `> tx.json` to the above command. + +## Programmatically with Go + +It is possible to manipulate transactions programmatically via Go using the Cosmos SDK's `TxBuilder` interface. + +### Generating a Transaction + +Before generating a transaction, a new instance of a `TxBuilder` needs to be created. Since the Cosmos SDK supports both Amino and Protobuf transactions, the first step would be to decide which encoding scheme to use. All the subsequent steps remain unchanged, whether you're using Amino or Protobuf, as `TxBuilder` abstracts the encoding mechanisms. In the following snippet, we will use Protobuf. + +```go +import ( + "github.com/cosmos/cosmos-sdk/simapp" +) + +func sendTx() error { + // Choose your codec: Amino or Protobuf. Here, we use Protobuf, given by the following function. + app := simapp.NewSimApp(...) + + // Create a new TxBuilder. + txBuilder := app.TxConfig().NewTxBuilder() + + // --snip-- +} +``` + +We can also set up some keys and addresses that will send and receive the transactions. Here, for the purpose of the tutorial, we will be using some dummy data to create keys. + +```go +import ( + "github.com/cosmos/cosmos-sdk/testutil/testdata" +) + +priv1, _, addr1 := testdata.KeyTestPubAddr() +priv2, _, addr2 := testdata.KeyTestPubAddr() +priv3, _, addr3 := testdata.KeyTestPubAddr() +``` + +Populating the `TxBuilder` can be done via its methods: + +```go reference +https://github.com/cosmos/cosmos-sdk/blob/v0.50.0-alpha.0/client/tx_config.go#L33-L50 +``` + +```go +import ( + banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" +) + +func sendTx() error { + // --snip-- + + // Define two x/bank MsgSend messages: + // - from addr1 to addr3, + // - from addr2 to addr3. + // This means that the transactions needs two signers: addr1 and addr2. + msg1 := banktypes.NewMsgSend(addr1, addr3, types.NewCoins(types.NewInt64Coin("atom", 12))) + msg2 := banktypes.NewMsgSend(addr2, addr3, types.NewCoins(types.NewInt64Coin("atom", 34))) + + err := txBuilder.SetMsgs(msg1, msg2) + if err != nil { + return err + } + + txBuilder.SetGasLimit(...) + txBuilder.SetFeeAmount(...) + txBuilder.SetMemo(...) + txBuilder.SetTimeoutHeight(...) +} +``` + +At this point, `TxBuilder`'s underlying transaction is ready to be signed. + +### Signing a Transaction + +We set encoding config to use Protobuf, which will use `SIGN_MODE_DIRECT` by default. As per [ADR-020](https://github.com/cosmos/cosmos-sdk/blob/main/docs/architecture/adr-020-protobuf-transaction-encoding.md), each signer needs to sign the `SignerInfo`s of all other signers. This means that we need to perform two steps sequentially: + +* for each signer, populate the signer's `SignerInfo` inside `TxBuilder`, +* once all `SignerInfo`s are populated, for each signer, sign the `SignDoc` (the payload to be signed). + +In the current `TxBuilder`'s API, both steps are done using the same method: `SetSignatures()`. The current API requires us to first perform a round of `SetSignatures()` _with empty signatures_, only to populate `SignerInfo`s, and a second round of `SetSignatures()` to actually sign the correct payload. + +```go +import ( + cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" + "github.com/cosmos/cosmos-sdk/types/tx/signing" + xauthsigning "github.com/cosmos/cosmos-sdk/x/auth/signing" +) + +func sendTx() error { + // --snip-- + + privs := []cryptotypes.PrivKey{priv1, priv2} + accNums:= []uint64{..., ...} // The accounts' account numbers + accSeqs:= []uint64{..., ...} // The accounts' sequence numbers + + // First round: we gather all the signer infos. We use the "set empty + // signature" hack to do that. + var sigsV2 []signing.SignatureV2 + for i, priv := range privs { + sigV2 := signing.SignatureV2{ + PubKey: priv.PubKey(), + Data: &signing.SingleSignatureData{ + SignMode: encCfg.TxConfig.SignModeHandler().DefaultMode(), + Signature: nil, + }, + Sequence: accSeqs[i], + } + + sigsV2 = append(sigsV2, sigV2) + } + err := txBuilder.SetSignatures(sigsV2...) + if err != nil { + return err + } + + // Second round: all signer infos are set, so each signer can sign. + sigsV2 = []signing.SignatureV2{} + for i, priv := range privs { + signerData := xauthsigning.SignerData{ + ChainID: chainID, + AccountNumber: accNums[i], + Sequence: accSeqs[i], + } + sigV2, err := tx.SignWithPrivKey( + encCfg.TxConfig.SignModeHandler().DefaultMode(), signerData, + txBuilder, priv, encCfg.TxConfig, accSeqs[i]) + if err != nil { + return nil, err + } + + sigsV2 = append(sigsV2, sigV2) + } + err = txBuilder.SetSignatures(sigsV2...) + if err != nil { + return err + } +} +``` + +The `TxBuilder` is now correctly populated. To print it, you can use the `TxConfig` interface from the initial encoding config `encCfg`: + +```go +func sendTx() error { + // --snip-- + + // Generated Protobuf-encoded bytes. + txBytes, err := encCfg.TxConfig.TxEncoder()(txBuilder.GetTx()) + if err != nil { + return err + } + + // Generate a JSON string. + txJSONBytes, err := encCfg.TxConfig.TxJSONEncoder()(txBuilder.GetTx()) + if err != nil { + return err + } + txJSON := string(txJSONBytes) +} +``` + +### Broadcasting a Transaction + +The preferred way to broadcast a transaction is to use gRPC, though using REST (via `gRPC-gateway`) or the CometBFT RPC is also posible. An overview of the differences between these methods is exposed [here](../../learn/advanced/06-grpc_rest.md). For this tutorial, we will only describe the gRPC method. + +```go +import ( + "context" + "fmt" + + "google.golang.org/grpc" + + "github.com/cosmos/cosmos-sdk/types/tx" +) + +func sendTx(ctx context.Context) error { + // --snip-- + + // Create a connection to the gRPC server. + grpcConn := grpc.Dial( + "127.0.0.1:9090", // Or your gRPC server address. + grpc.WithInsecure(), // The Cosmos SDK doesn't support any transport security mechanism. + ) + defer grpcConn.Close() + + // Broadcast 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. + grpcRes, err := txClient.BroadcastTx( + ctx, + &tx.BroadcastTxRequest{ + Mode: tx.BroadcastMode_BROADCAST_MODE_SYNC, + TxBytes: txBytes, // Proto-binary of the signed transaction, see previous step. + }, + ) + if err != nil { + return err + } + + fmt.Println(grpcRes.TxResponse.Code) // Should be `0` if the tx is successful + + return nil +} +``` + +#### Simulating a Transaction + +Before broadcasting a transaction, we sometimes may want to dry-run the transaction, to estimate some information about the transaction without actually committing it. This is called simulating a transaction, and can be done as follows: + +```go +import ( + "context" + "fmt" + "testing" + + "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/types/tx" + authtx "github.com/cosmos/cosmos-sdk/x/auth/tx" +) + +func simulateTx() error { + // --snip-- + + // Simulate the tx via gRPC. We create a new client for the Protobuf Tx + // service. + txClient := tx.NewServiceClient(grpcConn) + 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{ + TxBytes: txBytes, + }, + ) + if err != nil { + return err + } + + fmt.Println(grpcRes.GasInfo) // Prints estimated gas used. + + return nil +} +``` + +## Using gRPC + +It is not possible to generate or sign a transaction using gRPC, only to broadcast one. In order to broadcast a transaction using gRPC, you will need to generate, sign, and encode the transaction using either the CLI or programmatically with Go. + +### Broadcasting a Transaction + +Broadcasting a transaction using the gRPC endpoint can be done by sending a `BroadcastTx` request as follows, where the `txBytes` are the protobuf-encoded bytes of a signed transaction: + +```bash +grpcurl -plaintext \ + -d '{"tx_bytes":"{{txBytes}}","mode":"BROADCAST_MODE_SYNC"}' \ + localhost:9090 \ + cosmos.tx.v1beta1.Service/BroadcastTx +``` + +## Using REST + +It is not possible to generate or sign a transaction using REST, only to broadcast one. In order to broadcast a transaction using REST, you will need to generate, sign, and encode the transaction using either the CLI or programmatically with Go. + +### Broadcasting a Transaction + +Broadcasting a transaction using the REST endpoint (served by `gRPC-gateway`) can be done by sending a POST request as follows, where the `txBytes` are the protobuf-encoded bytes of a signed transaction: + +```bash +curl -X POST \ + -H "Content-Type: application/json" \ + -d'{"tx_bytes":"{{txBytes}}","mode":"BROADCAST_MODE_SYNC"}' \ + localhost:1317/cosmos/tx/v1beta1/txs +``` + +## Using CosmJS (JavaScript & TypeScript) + +CosmJS aims to build client libraries in JavaScript that can be embedded in web applications. Please see [https://cosmos.github.io/cosmjs](https://cosmos.github.io/cosmjs) for more information. As of January 2021, CosmJS documentation is still work in progress. diff --git a/docs/user/run-node/04-rosetta.md b/docs/user/run-node/04-rosetta.md new file mode 100644 index 000000000000..de74d9898b0c --- /dev/null +++ b/docs/user/run-node/04-rosetta.md @@ -0,0 +1,144 @@ +# Rosetta + +The `rosetta` project implements Coinbase's [Rosetta API](https://www.rosetta-api.org). This document provides instructions on how to use the Rosetta API integration. For information about the motivation and design choices, refer to [ADR 035](https://docs.cosmos.network/main/architecture/adr-035-rosetta-api-support). + +## Installing Rosetta + +The Rosetta API server is a stand-alone server that connects to a node of a chain developed with Cosmos SDK. + +Rosetta can be added to any cosmos chain node. standalone or natively. + +### Standalone + +Rosetta can be executed as a standalone service, it connects to the node endpoints and expose the required endpoints. + +Install Rosetta standalone server with the following command: + +```bash +go install github.com/cosmos/rosetta +``` + +Alternatively, for building from source, simply run `make build`. The binary will be located in the root folder. + +### Native - As a node command + +To enable Native Rosetta API support, it's required to add the `RosettaCommand` to your application's root command file (e.g. `simd/cmd/root.go`). + +Import the `rosettaCmd` package: + +```go +import "github.com/cosmos/rosetta/cmd" +``` + +Find the following line: + +```go +initRootCmd(rootCmd, encodingConfig) +``` + +After that line, add the following: + +```go +rootCmd.AddCommand( + rosettaCmd.RosettaCommand(encodingConfig.InterfaceRegistry, encodingConfig.Codec) +) +``` + +The `RosettaCommand` function builds the `rosetta` root command and is defined in the `rosettaCmd` package (`github.com/cosmos/rosetta/cmd`). + +Since we’ve updated the Cosmos SDK to work with the Rosetta API, updating the application's root command file is all you need to do. + +An implementation example can be found in `simapp` package. + +## Use Rosetta Command + +To run Rosetta in your application CLI, use the following command: + +> **Note:** if using the native approach, add your node name before any rosetta comand. + +```shell +rosetta --help +``` + +To test and run Rosetta API endpoints for applications that are running and exposed, use the following command: + +```shell +rosetta + --blockchain "your application name (ex: gaia)" + --network "your chain identifier (ex: testnet-1)" + --tendermint "tendermint endpoint (ex: localhost:26657)" + --grpc "gRPC endpoint (ex: localhost:9090)" + --addr "rosetta binding address (ex: :8080)" + --grpc-types-server (optional) "gRPC endpoint for message descriptor types" +``` + +## Plugins - Multi chain connections + +Rosetta will try to reflect the node types trough reflection over the node gRPC endpoints, there may be cases were this approach is not enough. It is possible to extend or implement the required types easily trough plugins. + +To use Rosetta over any chain, it is required to set up prefixes and registering zone specific interfaces through plugins. + +Each plugin is a minimalist implementation of `InitZone` and `RegisterInterfaces` which allow Rosetta to parse chain specific data. There is an example for cosmos-hub chain under `plugins/cosmos-hun/` folder +- **InitZone**: An empty method that is executed first and defines prefixes, parameters and other settings. +- **RegisterInterfaces**: This method receives an interface registry which is were the zone specific types and interfaces will be loaded + +In order to add a new plugin: +1. Create a folder over `plugins` folder with the name of the desired zone +2. Add a `main.go` file with the mentioned methods above. +3. Build the code binary through `go build -buildmode=plugin -o main.so main.go` + +The plugin folder is selected through the cli `--plugin` flag and loaded into the Rosetta server. + +## Extensions + +There are two ways in which you can customize and extend the implementation with your custom settings. + +### Message extension + +In order to make an `sdk.Msg` understandable by rosetta the only thing which is required is adding the methods to your messages that satisfy the `rosetta.Msg` interface. Examples on how to do so can be found in the staking types such as `MsgDelegate`, or in bank types such as `MsgSend`. + +### Client interface override + +In case more customization is required, it's possible to embed the Client type and override the methods which require customizations. + +Example: + +```go +package custom_client +import ( + +"context" +"github.com/coinbase/rosetta-sdk-go/types" +"github.com/cosmos/rosetta/lib" +) + +// CustomClient embeds the standard cosmos client +// which means that it implements the cosmos-rosetta-gateway Client +// interface while at the same time allowing to customize certain methods +type CustomClient struct { + *rosetta.Client +} + +func (c *CustomClient) ConstructionPayload(_ context.Context, request *types.ConstructionPayloadsRequest) (resp *types.ConstructionPayloadsResponse, err error) { + // provide custom signature bytes + panic("implement me") +} +``` + +NOTE: when using a customized client, the command cannot be used as the constructors required **may** differ, so it's required to create a new one. We intend to provide a way to init a customized client without writing extra code in the future. + +### Error extension + +Since rosetta requires to provide 'returned' errors to network options. In order to declare a new rosetta error, we use the `errors` package in cosmos-rosetta-gateway. + +Example: + +```go +package custom_errors +import crgerrs "github.com/cosmos/rosetta/lib/errors" + +var customErrRetriable = true +var CustomError = crgerrs.RegisterError(100, "custom message", customErrRetriable, "description") +``` + +Note: errors must be registered before cosmos-rosetta-gateway's `Server`.`Start` method is called. Otherwise the registration will be ignored. Errors with same code will be ignored too. diff --git a/docs/user/run-node/05-run-testnet.md b/docs/user/run-node/05-run-testnet.md new file mode 100644 index 000000000000..c2b5da598186 --- /dev/null +++ b/docs/user/run-node/05-run-testnet.md @@ -0,0 +1,101 @@ +--- +sidebar_position: 1 +--- + +# Running a Testnet + +:::note Synopsis +The `simd testnet` subcommand makes it easy to initialize and start a simulated test network for testing purposes. +::: + +In addition to the commands for [running a node](./01-run-node.md), the `simd` binary also includes a `testnet` command that allows you to start a simulated test network in-process or to initialize files for a simulated test network that runs in a separate process. + +## Initialize Files + +First, let's take a look at the `init-files` subcommand. + +This is similar to the `init` command when initializing a single node, but in this case we are initializing multiple nodes, generating the genesis transactions for each node, and then collecting those transactions. + +The `init-files` subcommand initializes the necessary files to run a test network in a separate process (i.e. using a Docker container). Running this command is not a prerequisite for the `start` subcommand ([see below](#start-testnet)). + +In order to initialize the files for a test network, run the following command: + +```bash +simd testnet init-files +``` + +You should see the following output in your terminal: + +```bash +Successfully initialized 4 node directories +``` + +The default output directory is a relative `.testnets` directory. Let's take a look at the files created within the `.testnets` directory. + +### gentxs + +The `gentxs` directory includes a genesis transaction for each validator node. Each file includes a JSON encoded genesis transaction used to register a validator node at the time of genesis. The genesis transactions are added to the `genesis.json` file within each node directory during the initilization process. + +### nodes + +A node directory is created for each validator node. Within each node directory is a `simd` directory. The `simd` directory is the home directory for each node, which includes the configuration and data files for that node (i.e. the same files included in the default `~/.simapp` directory when running a single node). + +## Start Testnet + +Now, let's take a look at the `start` subcommand. + +The `start` subcommand both initializes and starts an in-process test network. This is the fastest way to spin up a local test network for testing purposes. + +You can start the local test network by running the following command: + +```bash +simd testnet start +``` + +You should see something similar to the following: + +```bash +acquiring test network lock +preparing test network with chain-id "chain-mtoD9v" + + ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +++ THIS MNEMONIC IS FOR TESTING PURPOSES ONLY ++ +++ DO NOT USE IN PRODUCTION ++ +++ ++ +++ sustain know debris minute gate hybrid stereo custom ++ +++ divorce cross spoon machine latin vibrant term oblige ++ +++ moment beauty laundry repeat grab game bronze truly ++ ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + + +starting test network... +started test network +press the Enter Key to terminate +``` + +The first validator node is now running in-process, which means the test network will terminate once you either close the terminal window or you press the Enter key. In the output, the mnemonic phrase for the first validator node is provided for testing purposes. The validator node is using the same default addresses being used when initializing and starting a single node (no need to provide a `--node` flag). + +Check the status of the first validator node: + +```shell +simd status +``` + +Import the key from the provided mnemonic: + +```shell +simd keys add test --recover --keyring-backend test +``` + +Check the balance of the account address: + +```shell +simd q bank balances [address] +``` + +Use this test account to manually test against the test network. + +## Testnet Options + +You can customize the configuration of the test network with flags. In order to see all flag options, append the `--help` flag to each command. diff --git a/docs/user/run-node/06-run-production.md b/docs/user/run-node/06-run-production.md new file mode 100644 index 000000000000..807ceea56efc --- /dev/null +++ b/docs/user/run-node/06-run-production.md @@ -0,0 +1,269 @@ +--- +sidebar_position: 1 +--- + +# Running in Production + +:::note Synopsis +This section describes how to securely run a node in a public setting and/or on a mainnet on one of the many Cosmos SDK public blockchains. +::: + +When operating a node, full node or validator, in production it is important to set your server up securely. + +:::note +There are many different ways to secure a server and your node, the described steps here is one way. To see another way of setting up a server see the [run in production tutorial](https://tutorials.cosmos.network/hands-on-exercise/5-run-in-prod/1-overview.html). +::: + +:::note +This walkthrough assumes the underlying operating system is Ubuntu. +::: + +## Sever Setup + +### User + +When creating a server most times it is created as user `root`. This user has heightened privileges on the server. When operating a node, it is recommended to not run your node as the root user. + +1. Create a new user + +```bash +sudo adduser change_me +``` + +2. We want to allow this user to perform sudo tasks + +```bash +sudo usermod -aG sudo change_me +``` + +Now when logging into the server, the non `root` user can be used. + +### Go + +1. Install the [Go](https://go.dev/doc/install) version preconized by the application. + +:::warning +In the past, validators [have had issues](https://github.com/cosmos/cosmos-sdk/issues/13976) when using different versions of Go. It is recommended that the whole validator set uses the version of Go that is preconized by the application. +::: + +### Firewall + +Nodes should not have all ports open to the public, this is a simple way to get DDOS'd. Secondly it is recommended by [CometBFT](github.com/cometbft/cometbft) to never expose ports that are not required to operate a node. + +When setting up a firewall there are a few ports that can be open when operating a Cosmos SDK node. There is the CometBFT json-RPC, prometheus, p2p, remote signer and Cosmos SDK GRPC and REST. If the node is being operated as a node that does not offer endpoints to be used for submission or querying then a max of three endpoints are needed. + +Most, if not all servers come equipped with [ufw](https://help.ubuntu.com/community/UFW). Ufw will be used in this tutorial. + +1. Reset UFW to disallow all incoming connections and allow outgoing + +```bash +sudo ufw default deny incoming +sudo ufw default allow outgoing +``` + +2. Lets make sure that port 22 (ssh) stays open. + +```bash +sudo ufw allow ssh +``` + +or + +```bash +sudo ufw allow 22 +``` + +Both of the above commands are the same. + +3. Allow Port 26656 (cometbft p2p port). If the node has a modified p2p port then that port must be used here. + +```bash +sudo ufw allow 26656/tcp +``` + +4. Allow port 26660 (cometbft [prometheus](https://prometheus.io)). This acts as the applications monitoring port as well. + +```bash +sudo ufw allow 26660/tcp +``` + +5. IF the node which is being setup would like to expose CometBFTs jsonRPC and Cosmos SDK GRPC and REST then follow this step. (Optional) + +##### CometBFT JsonRPC + +```bash +sudo ufw allow 26657/tcp +``` + +##### Cosmos SDK GRPC + +```bash +sudo ufw allow 9090/tcp +``` + +##### Cosmos SDK REST + +```bash +sudo ufw allow 1317/tcp +``` + +6. Lastly, enable ufw + +```bash +sudo ufw enable +``` + +### Signing + +If the node that is being started is a validator there are multiple ways a validator could sign blocks. + +#### File + +File based signing is the simplest and default approach. This approach works by storing the consensus key, generated on initialization, to sign blocks. This approach is only as safe as your server setup as if the server is compromised so is your key. This key is located in the `config/priv_val_key.json` directory generated on initialization. + +A second file exists that user must be aware of, the file is located in the data directory `data/priv_val_state.json`. This file protects your node from double signing. It keeps track of the consensus keys last sign height, round and latest signature. If the node crashes and needs to be recovered this file must be kept in order to ensure that the consensus key will not be used for signing a block that was previously signed. + +#### Remote Signer + +A remote signer is a secondary server that is separate from the running node that signs blocks with the consensus key. This means that the consensus key does not live on the node itself. This increases security because your full node which is connected to the remote signer can be swapped without missing blocks. + +The two most used remote signers are [tmkms](https://github.com/iqlusioninc/tmkms) from [Iqlusion](https://www.iqlusion.io) and [horcrux](https://github.com/strangelove-ventures/horcrux) from [Strangelove](https://strange.love). + +##### TMKMS + +###### Dependencies + +1. Update server dependencies and install extras needed. + +```sh +sudo apt update -y && sudo apt install build-essential curl jq -y +``` + +2. Install Rust: + +```sh +curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh +``` + +3. Install Libusb: + +```sh +sudo apt install libusb-1.0-0-dev +``` + +###### Setup + +There are two ways to install tmkms, from source or `cargo install`. In the examples we will cover downloading or building from source and using softsign. Softsign stands for software signing, but you could use a [yubihsm](https://www.yubico.com/products/hardware-security-module/) as your signing key if you wish. + +1. Build: + +From source: + +```bash +cd $HOME +git clone https://github.com/iqlusioninc/tmkms.git +cd $HOME/tmkms +cargo install tmkms --features=softsign +tmkms init config +tmkms softsign keygen ./config/secrets/secret_connection_key +``` + +or + +Cargo install: + +```bash +cargo install tmkms --features=softsign +tmkms init config +tmkms softsign keygen ./config/secrets/secret_connection_key +``` + +:::note +To use tmkms with a yubikey install the binary with `--features=yubihsm`. +::: + +2. Migrate the validator key from the full node to the new tmkms instance. + +```bash +scp user@123.456.32.123:~/.simd/config/priv_validator_key.json ~/tmkms/config/secrets +``` + +3. Import the validator key into tmkms. + +```bash +tmkms softsign import $HOME/tmkms/config/secrets/priv_validator_key.json $HOME/tmkms/config/secrets/priv_validator_key +``` + +At this point, it is necessary to delete the `priv_validator_key.json` from the validator node and the tmkms node. Since the key has been imported into tmkms (above) it is no longer necessary on the nodes. The key can be safely stored offline. + +4. Modifiy the `tmkms.toml`. + +```bash +vim $HOME/tmkms/config/tmkms.toml +``` + +This example shows a configuration that could be used for soft signing. The example has an IP of `123.456.12.345` with a port of `26659` a chain_id of `test-chain-waSDSe`. These are items that most be modified for the usecase of tmkms and the network. + +```toml +# CometBFT KMS configuration file + +## Chain Configuration + +[[chain]] +id = "osmosis-1" +key_format = { type = "bech32", account_key_prefix = "cosmospub", consensus_key_prefix = "cosmosvalconspub" } +state_file = "/root/tmkms/config/state/priv_validator_state.json" + +## Signing Provider Configuration + +### Software-based Signer Configuration + +[[providers.softsign]] +chain_ids = ["test-chain-waSDSe"] +key_type = "consensus" +path = "/root/tmkms/config/secrets/priv_validator_key" + +## Validator Configuration + +[[validator]] +chain_id = "test-chain-waSDSe" +addr = "tcp://123.456.12.345:26659" +secret_key = "/root/tmkms/config/secrets/secret_connection_key" +protocol_version = "v0.34" +reconnect = true +``` + +5. Set the address of the tmkms instance. + +```bash +vim $HOME/.simd/config/config.toml + +priv_validator_laddr = "tcp://127.0.0.1:26659" +``` + +:::tip +The above address it set to `127.0.0.1` but it is recommended to set the tmkms server to secure the startup +::: + +:::tip +It is recommended to comment or delete the lines that specify the path of the validator key and validator: + +```toml +# Path to the JSON file containing the private key to use as a validator in the consensus protocol +# priv_validator_key_file = "config/priv_validator_key.json" + +# Path to the JSON file containing the last sign state of a validator +# priv_validator_state_file = "data/priv_validator_state.json" +``` + +::: + +6. Start the two processes. + +```bash +tmkms start -c $HOME/tmkms/config/tmkms.toml +``` + +```bash +simd start +``` diff --git a/docs/user/run-node/07-multisig-guide.md b/docs/user/run-node/07-multisig-guide.md new file mode 100644 index 000000000000..f7be5b1f4574 --- /dev/null +++ b/docs/user/run-node/07-multisig-guide.md @@ -0,0 +1,108 @@ +--- +sidebar_position: 1 +--- + +# Guide to Multisig transactions + +## Overview + +Multisignature accounts are accounts that are generated from multiple public keys. A multisig necessitates that any transaction made on its behalf must be signed by a specified threshold of its members. + +A common use case for multisigs is to increase security of a signing account, and/or enable multiple parties to agree on and authorize a transaction. + +The first step is to create a multisig signing key by using the public keys of all possible signers and the minimum threshold of addresses that are needed to sign any transaction from the account. The threshold can be the same amount as the total number of addresses comprising the multisig. + +Whatever machine is generating the multisig, it should at least have all of the public keys imported into the same keyring. + +When you want to create a multisig transaction, you would create the transaction as normal, but instead of signing it with a single account's private key, you would need to sign it with the private keys of the accounts that make up the multisig key. + +This is done by signing the transaction multiple times, once with each private key. The order of the signatures matters and must match the order of the public keys in the multisig key. + +Once you have a transaction with the necessary signatures, it can be broadcasted to the network. The network will verify that the transaction has the necessary signatures from the accounts in the multisig key before it is executed. + +## Step by step guide to multisig transactions + +This tutorial will use the test keyring which will store the keys in the default home directory `~/.simapp` unless otherwise specified. +Verify which keys are available in the test keyring by running `--keyring-backend test`. + +Prior to this tutorial set the keyring backend to "test" in `~/.simapp/client.toml` to always the test keyring which will specify a consistent keyring for the entirety of the tutorial. Additionally, set the default keyring by running `simd config set client keyring-backend test`. + +```shell +simd keys list +``` + +If you don't already have accounts listed create the accounts using the below. + +```shell +simd keys add alice +simd keys add bob +simd keys add recipient +``` + +Alternatively the public keys comprising the multisig can be imported into the keyring. + +```shell +simd keys add alice --pubkey --keyring backend test +``` + +Create the multisig account between bob and alice. + +```shell +simd keys add alice-bob-multisig --multisig alice,bob --multisig-threshold 2 +``` + +Before generating any transaction, verify the balance of each account and note the amount. This step is crucial to confirm that the transaction can be processed successfully. + +```shell +simd query bank balances my_validator +simd query bank balances alice-bob-multisig +``` + +Ensure that the alice-bob-multisig account is funded with a sufficient balance to complete the transaction (gas included). In our case, the genesis account, my_validator, holds our funds. Therefore, we will transfer funds from the `my_validator` account to the `alice-bob-multisig` account. +Fund the multisig by sending it `stake` from the genesis account. + +```shell + simd tx bank send my_validator alice-bob-multisig "10000stake" +``` + +Check both accounts again to see if the funds have transferred. + +```shell +simd query bank balances alice-bob-multisig +``` + +Initiate the transaction. This command will create a transaction from the multisignature account `alice-bob-multisig` to send 1000stake to the recipient account. The transaction will be generated but not broadcasted yet. + +```shell +simd tx bank send alice-bob-multisig recipient 1000stake --generate-only --chain-id my-test-chain > tx.json +``` + +Alice signs the transaction using their key and refers to the multisig address. Execute the command below to accomplish this: + +```shell +simd tx sign --from alice --multisig=cosmos1re6mg24kvzjzmwmly3dqrqzdkruxwvctw8wwds tx.json --chain-id my-test-chain > tx-signed-alice.json +``` + +Let's repeat for Bob. + +```shell +simd tx sign --from bob --multisig=cosmos1re6mg24kvzjzmwmly3dqrqzdkruxwvctw8wwds tx.json --chain-id my-test-chain > tx-signed-bob.json +``` + +Execute a multisign transaction by using the `simd tx multisign` command. This command requires the names and signed transactions of all the participants in the multisig account. Here, Alice and Bob are the participants: + +```shell +simd tx multisign tx.json alice-bob-multisig tx-signed-alice.json tx-signed-bob.json --chain-id my-test-chain > tx-signed.json +``` + +Once the multisigned transaction is generated, it needs to be broadcasted to the network. This is done using the simd tx broadcast command: + +```shell +simd tx broadcast tx-signed.json --chain-id my-test-chain --gas auto --fees 250stake +``` + +Once the transaction is broadcasted, it's a good practice to verify if the transaction was successful. You can query the recipient's account balance again to confirm if the funds were indeed transferred: + +```shell +simd query bank balances alice-bob-multisig +``` diff --git a/docs/user/run-node/08-onchain-multisig.md b/docs/user/run-node/08-onchain-multisig.md new file mode 100644 index 000000000000..a93e59620e54 --- /dev/null +++ b/docs/user/run-node/08-onchain-multisig.md @@ -0,0 +1,248 @@ +--- +sidebar_position: 1 +--- + +# Guide to On-Chain Multisig transactions + +## Overview + +Multisignature **on-chain** accounts are an improvement over the previous implementation as these introduce a new set of +features. + +### Threshold and quorums + +The previous implementation only allowed for m-of-n multisig accounts, where m is the number of signatures required to +authorize a transaction and n is the total number of signers. The new implementation allows for more flexibility by +introducing threshold and quorum values. The quorum is the minimum voting power to make a proposal valid, while the +threshol is the minimum of voting power of YES votes to pass a proposal. + +### Revote + +Multisigs can allow members to change their votes after the initial vote. This is useful when a member changes their mind +or when new information becomes available. + +### Early execution + +Multisigs can be configured to allow for early execution of proposals. This is useful when a proposal is time-sensitive or +when the proposer wants to execute the proposal as soon as it reaches the threshold. It can also be used to mimic the +behavior of the previous multisig implementation. + +### Voting period + +Multisigs can be configured to have a voting period. This is the time window during which members can vote on a proposal. +If the proposal does not reach the threshold within the voting period, it is considered failed. + +## Setup + +We'll create a multisig with 3 members with a 2/3 passing threshold. + +First create the 3 members, Alice, Bob and Carol: + +```bash! +simd keys add alice --keyring-backend test --home ./.testnets/node0/simd/ +simd keys add bob --keyring-backend test --home ./.testnets/node0/simd/ +simd keys add carol --keyring-backend test --home ./.testnets/node0/simd/ +``` + +And we initialize them with some tokens (sent from one of our nodes): + +```bash! +simd tx bank send $(simd keys show node0 --address --keyring-backend=test --home ./.testnets/node0/simd/) $(simd keys show alice --address --keyring-backend=test --home ./.testnets/node0/simd/) 100stake --fees 5stake --chain-id $CHAINID --keyring-backend test --home ./.testnets/node0/simd/ +simd tx bank send $(simd keys show node0 --address --keyring-backend=test --home ./.testnets/node0/simd/) $(simd keys show bob --address --keyring-backend=test --home ./.testnets/node0/simd/) 100stake --fees 5stake --chain-id $CHAINID --keyring-backend test --home ./.testnets/node0/simd/ +simd tx bank send $(simd keys show node0 --address --keyring-backend=test --home ./.testnets/node0/simd/) $(simd keys show carol --address --keyring-backend=test --home ./.testnets/node0/simd/) 100stake --fees 5stake --chain-id $CHAINID --keyring-backend test --home ./.testnets/node0/simd/ +``` + +Now we craft our initialization message, in it we'll include the members' addresses, their weights and the configuration of our multisig. + +```json +{ + "members": [ + { + "address": "cosmos1pr26h2vq9adq3acvh37pz6wtk65u3y8798scq0", + "weight": 1000 + }, + { + "address": "cosmos1j4p2xlg393rg4mma0058alzgvkrjdddd2f5fll", + "weight": 1000 + }, + { + "address": "cosmos1vaqh39cdex9sgr46ef0tdln5cn0hdyd3s0lx4l", + "weight": 1000 + } + ], + "config": { + "threshold": 2000, + "quorum": 2000, + "voting_period": 86400, + "revote": false, + "early_execution": true + } +} +``` + +In the configuration we set the threshold and quorum to the same, 2/3 of the members must vote yes to pass the proposal. Other configurations can set the quorum and threshold to different values to mimic how organizations work. + +We've also set `early_execution` to true, to allow executing as soon as the proposal passes. + +Voting period is in seconds, so we've set that to 24h. And finally `revote` was set to false, because we don't want to allow members to change their vote mid-way through. + +To initialize the multisig, we have to run the `accounts init` passing the account type and the json we created. + + +```bash! +initcontents=$(cat init.json) +simd tx accounts init multisig $initcontents --fees 5stake --chain-id $CHAINID --keyring-backend test --home ./.testnets/node0/simd/ --from alice +``` + +If everything goes well, we'll get back a tx hash, and we'll check the tx result to get our newly created multisig's address. + +```bash! +simd q tx 472B5B4E181D2F399C0ACE4DEEB26FE4351D13E593ED8E793B005C48BFD32621 --output json | jq -r '.events[] | select(.type == "account_creation") | .attributes[] | select(.key == "address") | .value' +``` + +In this case, the address is `cosmos1uds6tz96dxfllz7tz3s3tm8tlg6x95g0mc2987sx6psjz98qlpss89sheu`. We can now send tokens to it, just like to a normal account. + +```bash! +simd tx bank send $(simd keys show node0 --address --keyring-backend=test --home ./.testnets/node0/simd/) cosmos1uds6tz96dxfllz7tz3s3tm8tlg6x95g0mc2987sx6psjz98qlpss89sheu 10000stake --fees 5stake --chain-id $CHAINID --keyring-backend test --home ./.testnets/node0/simd/ +``` + +## Proposals + +#### Create proposal + +In this multisig, every action is a proposal. We'll do a simple proposal to send tokens from the multisig to Alice. + +```json +{ + "proposal": { + "title": "Send 1000 tokens to Alice", + "summary": "Alice is a great multisig member so let's pay her.", + "messages": [ + { + "@type": "/cosmos.bank.v1beta1.MsgSend", + "from_address": "cosmos1uds6tz96dxfllz7tz3s3tm8tlg6x95g0mc2987sx6psjz98qlpss89sheu", + "to_address": "cosmos1pr26h2vq9adq3acvh37pz6wtk65u3y8798scq0", + "amount": [ + { + "denom": "stake", + "amount": "1000" + } + ] + } + ] + } +} +``` + +> The content of messages was created using a simple `tx send` command and passing the flag `--generate-only` so we could copy the message. + +Now we send the tx that will create the proposal: + +```bash! +propcontents=$(cat createprop.json) +simd tx accounts execute cosmos1uds6tz96dxfllz7tz3s3tm8tlg6x95g0mc2987sx6psjz98qlpss89sheu cosmos.accounts.defaults.multisig.v1.MsgCreateProposal $propcontents --fees 5stake --chain-id $CHAINID --keyring-backend test --home ./.testnets/node0/simd/ --from alice +``` + +This will again return a tx hash that we can use to find out the newly created proposal. + +```bash! +simd q tx 5CA4420B67FB040B3DF2484CB875E030123662F43AE9958A9F8028C1281C8654 --output json | jq -r '.events[] | select(.type == "proposal_created") | .attributes[] | select(.key == "proposal_id") | .value' +``` + +In this case, because this is the first proposal, we'll get that the proposal ID is 0. We can use this to query it. + +```bash! +simd q accounts query cosmos1uds6tz96dxfllz7tz3s3tm8tlg6x95g0mc2987sx6psjz98qlpss89sheu cosmos.accounts.defaults.multisig.v1.QueryProposal '{"proposal_id":1}' +``` + +We get back all the details from the proposal, including the end of the voting period and the current status of the proposal. + +```yaml +response: + '@type': /cosmos.accounts.defaults.multisig.v1.QueryProposalResponse + proposal: + messages: + - '@type': /cosmos.bank.v1beta1.MsgSend + amount: + - amount: "1000" + denom: stake + from_address: cosmos1uds6tz96dxfllz7tz3s3tm8tlg6x95g0mc2987sx6psjz98qlpss89sheu + to_address: cosmos1pr26h2vq9adq3acvh37pz6wtk65u3y8798scq0 + status: PROPOSAL_STATUS_VOTING_PERIOD + summary: Alice is a great multisig member so let's pay her. + title: Send 1000 tokens to Alice + voting_period_end: "1717064354" +``` + +### Vote on the proposal + +Just like before, we'll use `tx accounts execute`, but this time to vote. As we have a 2/3 passing threshold, we have to vote with at least 2 members. + +```bash! +simd tx accounts execute cosmos1uds6tz96dxfllz7tz3s3tm8tlg6x95g0mc2987sx6psjz98qlpss89sheu cosmos.accounts.defaults.multisig.v1.MsgVote '{"proposal_id":0, "vote":"VOTE_OPTION_YES"}' --fees 5stake --chain-id $CHAINID --keyring-backend test --home ./.testnets/node0/simd/ --from alice --yes +simd tx accounts execute cosmos1uds6tz96dxfllz7tz3s3tm8tlg6x95g0mc2987sx6psjz98qlpss89sheu cosmos.accounts.defaults.multisig.v1.MsgVote '{"proposal_id":0, "vote":"VOTE_OPTION_YES"}' --fees 5stake --chain-id $CHAINID --keyring-backend test --home ./.testnets/node0/simd/ --from bob --yes +``` + +### Execute the proposal + +Once we got enough votes, we can execute the proposal. + +```bash! +simd tx accounts execute cosmos1uds6tz96dxfllz7tz3s3tm8tlg6x95g0mc2987sx6psjz98qlpss89sheu cosmos.accounts.defaults.multisig.v1.MsgExecuteProposal '{"proposal_id":0}' --fees 5stake --chain-id $CHAINID --keyring-backend test --home ./.testnets/node0/simd/ --from bob --yes +``` + +Querying the tx hash will get us information about the success or failure of the proposal execution. + +```yaml +- attributes: + - index: true + key: proposal_id + value: "0" + - index: true + key: yes_votes + value: "2000" + - index: true + key: no_votes + value: "0" + - index: true + key: abstain_votes + value: "0" + - index: true + key: status + value: PROPOSAL_STATUS_PASSED + - index: true + key: reject_err + value: + - index: true + key: exec_err + value: + - index: true + key: msg_index + value: "0" + type: proposal_tally +``` + +Now checking the multisig and Alice's balance, we'll see that the send was performed correctly. + +```bash! +simd q bank balances cosmos1uds6tz96dxfllz7tz3s3tm8tlg6x95g0mc2987sx6psjz98qlpss89sheu + +balances: +- amount: "9000" + denom: stake +pagination: + total: "1" +``` + +```bash! +simd q bank balances $(./build/simd keys show alice --address) + +balances: +- amount: "1080" + denom: stake +pagination: + total: "1" +``` + + + diff --git a/docs/user/run-node/_category_.json b/docs/user/run-node/_category_.json new file mode 100644 index 000000000000..7fcac509a58b --- /dev/null +++ b/docs/user/run-node/_category_.json @@ -0,0 +1,5 @@ +{ + "label": "Running a Node, API and CLI", + "position": 1, + "link": null +} \ No newline at end of file diff --git a/docs/user/user.md b/docs/user/user.md new file mode 100644 index 000000000000..5429e8ad6e29 --- /dev/null +++ b/docs/user/user.md @@ -0,0 +1,10 @@ +--- +sidebar_position: 0 +--- +# User Guides + +This section is designed for developers who are using the Cosmos SDK to build applications. It provides essential guides and references to effectively use the SDK's features. + +* [Setting up keys](./run-node/00-keyring.md) - Learn how to set up secure key management using the Cosmos SDK's keyring feature. This guide provides a streamlined approach to cryptographic key handling, which is crucial for securing your application. +* [Running a node](./run-node/01-run-node.md) - This guide provides step-by-step instructions to deploy and manage a node in the Cosmos network. It ensures a smooth and reliable operation of your blockchain application by covering all the necessary setup and maintenance steps. +* [CLI](./run-node/02-interact-node.md) - Discover how to navigate and interact with the Cosmos SDK using the Command Line Interface (CLI). This section covers efficient and powerful command-based operations that can help you manage your application effectively.