Skip to content

Commit

Permalink
icamauth docs (#1813)
Browse files Browse the repository at this point in the history
* docs: add icamauth docs

* docs: change uatom to stake

* chore: update docs

* docs: update icamuath.md according to review comments

* docs: rename icamauth.md to README.md

* docs: read mnemonic from file

* docs: add hermes download instruction

* update docs

* globalfee/README.md -> globalfee.md

* Update docs/modules/icamauth/hermes_setup.sh

Co-authored-by: Danilo Pantani <[email protected]>

* docs: fix dead link

* Update README.md

* Update README.md

* fixes

Co-authored-by: billy rennekamp <[email protected]>
Co-authored-by: Danilo Pantani <[email protected]>
  • Loading branch information
3 people authored Nov 16, 2022
1 parent 719b81d commit c565ff4
Show file tree
Hide file tree
Showing 10 changed files with 576 additions and 6 deletions.
2 changes: 2 additions & 0 deletions docs/modules/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,7 @@ Updated Modules in V8 Rho
- [Gov](./gov.md)

## New Modules in Rho V8
- [Global Fee](./globalfee.md)
- [Group](./group.md)
- [ICA-Mauth](./icamauth/)

Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Gaia Fee Ante-handler
# Gaia Fees and Fees Check

## Gaia Fees

Expand All @@ -12,7 +12,7 @@ Global fees are the fees that each transaction incurs—except [bypass fee messa

For [global fees](https://github.com/cosmos/gaia/blob/82c4353ab1b04cf656a8c95d226c30c7845f157b/x/globalfee/types/params.go#L54-L99) to be valid:
- fees have to be alphabetically sorted by denomination (denom)
- fees must to have non-negative amount, with a valid and unique denom (i.e no duplicate denoms are allowed).
- fees must have non-negative amount, with a valid and unique denom (i.e. no duplicate denoms are allowed).

Global fees allow denoms with zero coins or value.

Expand Down Expand Up @@ -64,7 +64,7 @@ Global fees, min_gas_prices and the paid fees all allow zero coins setup. After
Only global fees might contain zero coins, which is used to define the allowed denoms of paid fees.
The [Fee AnteHandle](../../../x/globalfee/ante/fee.go) will take global fees and min_gas_prices and merge them into one [combined `sdk.Deccoins`](https://github.com/cosmos/gaia/blob/f2be720353a969b6362feff369218eb9056a60b9/ante/fee.go#L79) according to the denoms and amounts of global fees and min_gas_prices.
The [Fee AnteHandle](../../x/globalfee/ante/fee.go) will take global fees and min_gas_prices and merge them into one [combined `sdk.Deccoins`](https://github.com/cosmos/gaia/blob/f2be720353a969b6362feff369218eb9056a60b9/ante/fee.go#L79) according to the denoms and amounts of global fees and min_gas_prices.
If the paid fee is a subset of the combined fees set and the paid fee amount is greater than or equal to the required fees amount, the transaction can pass the fee check, otherwise an error will occur.
Expand Down
247 changes: 247 additions & 0 deletions docs/modules/icamauth/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,247 @@
# icamauth module

## Introduction to Interchain Accounts
**Interchain Accounts** (ICA) is a standard that allows an account on a *controller* chain to create and securely control an address on a different *host* chain using the Inter Blockchain Protocol (IBC). Transactions native to the host chain are wrapped inside an IBC packet and sent from the Interchain Account Owner on the controller chain to be executed on the host chain.

The benefit of ICA is that there is no need to create a custom IBC implementation for each unique transaction that a sovereign blockchain might have (trading on a DEX, executing a specific smart contract, etc.). Instead, a **generic** implementation allows blockchains to speak to each other, much like contracts can interact on Ethereum or other smart contract platforms.

For example, let's say that you have an address on the Cosmos Hub (the controller) with OSMO tokens that you want to stake on Osmosis (the host). With Interchain Accounts, you can create and control a new address on Osmosis without requiring a new private key. After sending your tokens to your Interchain Account using a regular IBC token transfer, you can send a wrapped `delegate` transaction over IBC, which will then be unwrapped and executed natively on Osmosis.

## The icamauth module
Blockchains implementing Interchain Accounts can decide which messages they allow a controller chain to execute via a whitelist. The **icamuath (interchain account message authentication) module** whitelists most of the message types available to the Cosmos Hub, allowing any account on a controller chain to interact with the Cosmos Hub as if owning a native account on the chain itself.
The following command allows you to query all the allowed message types on a host chain:
```shell
gaiad q interchain-accounts host params
```

The following tutorial will demonstrate how to use Interchain Accounts through the [icamauth module](../../../x/icamauth).

## Setup preparation
We will run two Cosmos-SDK chains (controller chain: `test-0` and host chain: `test-1`) and a relayer to connect these two chains. We will create an account on chain `test-0` and call it `alice`, and register an Interchain Account (that we'll call `alice_ica`) on chain `test-1` for `alice` on chain `test-0`. We will also create a standard account, `bob` on chain `test-1`.

Through these 3 accounts, we can test if:
- `alice` on chain `test-0` can control its `alice_ica` to transfer tokens to account `bob` on chain `test-1`.
- `alice` can control its `alice_ica` to transfer `alice_ica`'s token back to `alice` using a regular IBC token transfer.

### Prepare to run two chains
We've simplified the setup process via several shell scripts. If you'd like to learn more about what's happening under the hood we suggest you inspect the files more closely.

Set up the two chains, create the keys for `alice` and `bob`, and start running both chains in different terminals:
```shell
source ./docs/modules/icamauth/init_chain_controller.sh
```
and ni another temrinal:
```shell
source ./docs/modules/icamauth/init_chain_host.sh
```

### Setting up a Hermes relayer
You can download or build the Hermes binary from the source code.
#### Download the Hermes binary
You can find the hermes download information for different os architectures [here](https://github.com/informalsystems/hermes/releases).
```shell
curl -OL https://github.com/informalsystems/hermes/releases/download/v1.0.0/hermes-v1.0.0-x86_64-apple-darwin.zip
mkdir -p $HOME/.hermes/bin
tar -C $HOME/.hermes/bin/ -vxzf hermes-v1.0.0-x86_64-apple-darwin.zip
export PATH="$HOME/.hermes/bin:$PATH"
```

#### Build the Hermes binary
Install Rust:
```shell
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
source $HOME/.cargo/env
```

Build the Hermes binary:
```shell
git clone https://github.com/informalsystems/ibc-rs.git
cd ibc-rs
git checkout v1.0.0
cargo build --release --no-default-features --bin hermes
# binary path: ./target/release/hermes
cp ./target/release/hermes $HOME/.cargo/bin
export PATH="$HOME/.hermes/bin:$PATH"
```

#### Create the IBC connection
Run the following command in `gaia/docs/modules/icamauth` directory to create an IBC connection:
```shell
cd ./docs/modules/icamauth
source hermes_setup.sh
```

## Testing the Interchain Accounts functionality
First of all, you need to register an Interchain Account on `test-1` for `alice` by sending an `icamauth register` command signed by `alice` on the `test-0` chain:

Open a new terminal and add the following variables.
```shell
export HOME0=$HOME/test-0
export HOME1=$HOME/test-1
```

```shell
gaiad tx icamauth register --from alice --connection-id connection-0 --gas-prices 0.4stake --home $HOME0
```
query alice's ica:
```shell
gaiad query icamauth interchainaccounts connection-0 $(gaiad keys show alice -a --home $HOME0) --home $HOME0
```
To make things easier during the next steps, export the account addresses to environment variables:
```shell
export ALICE_ICA=$(gaiad query icamauth interchainaccounts connection-0 $(gaiad keys show alice -a --home $HOME0) --home $HOME0 -o json | jq -r '.interchain_account_address')
export ALICE=$(gaiad keys show alice -a --home $HOME0)
export BOB=$(gaiad keys show bob -a --home $HOME1)
```

Let's make sure `alice_ica` has some `stake`:
```shell
gaiad q bank balances $ALICE_ICA --home $HOME1
gaiad tx bank send $BOB $ALICE_ICA 1000stake --from bob --gas-prices 0.025stake --home $HOME1
gaiad q bank balances $ALICE_ICA --home $HOME1
```

### Exercises
We would like to invite you to try to perform the actions below yourself. If you're having issues, you can find the solutions at the bottom of this tutorial.

> NOTE:
> * `alice` = account on `test-0`
> * `alice_ica` = account on `test-1` owned by `alice` on `test-0`
> * `bob` = account on `test-1`
Q1: Let `alice` send `stake` to `bob` (hint: using ICA)

Q2: Let `bob` send `stake` back to `alice_ica` (hint: via the Bank module)

Q3: Let `alice` send `stake` to `bob` (hint: via a regular IBC token transfer)

Q4: Let `bob` send `ibc/stake` to `alice_ica` (hint: via the Bank module)

Q5: Let `alice_ica` send `ibc/stake` to `alice` (hint: via ICA & IBC-Transfer)

### Solutions
#### Q1: `alice_ica` sends tokens to `bob`
Both `alice_ica` and `bob` are on chain `test-1`, however, we need `alice` from `test-0` to sign the transaction, because `alice` is the only account with access to `alice_ica` over `icamuath`.

Step 1: generate the transaction json:
```shell
gaiad tx bank send $ALICE_ICA $BOB --from alice 100stake --generate-only --home $HOME1 | jq '.body.messages[0]' > ./send-raw.json

cat send-raw.json
```

This will generate and display a JSON file similar to this following file:
```shell
{
"@type": "/cosmos.bank.v1beta1.MsgSend",
"from_address": "cosmos1g2c3l9m7zpvwsa2k4yx007zsnx9gme9qyw89uccxf7gkus6ehylsaklv2y",
"to_address": "cosmos1jl3p6e62ey4xad8c5x0vh4p26j5ml8ejxr936t",
"amount": [
{
"denom": "stake",
"amount": "100"
}
]
}
```

Step 2: Check the balance of Bob's account before the transfer, then send the generated transaction and let `alice` sign it:
```shell
gaiad q bank balances $BOB --home $HOME1

gaiad tx icamauth submit ./send-raw.json --connection-id connection-0 --from alice --gas-prices 0.025stake --home $HOME0
```

Step 3: check the balance of Bob's account after the transfer to make sure it went through:
```shell
gaiad q bank balances $BOB --home $HOME1
```

#### Q2: `bob` sends the tokens back to `alice_ica`
Note that this transaction is just a regular coin transfer using the Bank module because both accounts exist on `test-1` and you are interacting directly with that chain via the `--home` flag.

```shell
gaiad tx bank send $BOB $ALICE_ICA 100stake --gas-prices 0.025stake --home $HOME1
```

#### Q3: `alice` sends tokens to `bob` via IBC
Create a new IBC channel using Hermes:

```shell
hermes --config ./docs/modules/icamauth/rly-config.toml create channel --a-chain test-0 --a-connection connection-0 --a-port transfer --b-port transfer
```

Initiate the IBC token transfer:
```shell
gaiad tx ibc-transfer transfer transfer channel-1 $BOB 200stake --from alice --gas-prices 0.025stake --home $HOME0
```

IBC token transfers can take a while before they're confirmed. You can check the balance of `bob` on `test-1`:
```shell
gaiad q bank balances $BOB --home $HOME1
balances:
- amount: "200"
denom: ibc/C4CFF46FD6DE35CA4CF4CE031E643C8FDC9BA4B99AE598E9B0ED98FE3A2319F9
- amount: "99999999000"
denom: stake
pagination:
next_key: null
total: "0"
```

Note how the `200stake` received has changed its denom to `ibc/C4CFF46FD6DE35CA4CF4CE031E643C8FDC9BA4B99AE598E9B0ED98FE3A2319F9`. Tokens sending over IBC always are encoded with information about its origin in its denom.

#### Q4: Let `bob` send the `ibc/stake` it just received to `alice_ica`
Notice how this is just a regular token transfer using the Bank module. Also make sure the ibc denom is correct as it will be different for each chain.

```shell
export IBC_DENOM=ibc/C4CFF46FD6DE35CA4CF4CE031E643C8FDC9BA4B99AE598E9B0ED98FE3A2319F9
gaiad tx bank send $BOB $ALICE_ICA 200$IBC_DENOM --from bob --gas-prices 0.025stake --home $HOME1
```

#### Q5: `alice_ica` sends `100ibc/stake` to `alice`

we have already created the channel in the above [#Q3], we can just use this channel to send the token back from `alice_ica` to `alice`.

Step 1: prepare the transaction JSON file:

```shell
gaiad tx ibc-transfer transfer transfer channel-1 $ALICE 100$IBC_DENOM --from $ALICE_ICA --generate-only --home $HOME1 | jq '.body.messages[0]' > send-raw.json

cat send-raw.json
```

This will generate and display the following JSON file:
```shell
{
"@type": "/ibc.applications.transfer.v1.MsgTransfer",
"source_port": "transfer",
"source_channel": "channel-1",
"token": {
"denom": "ibc/C4CFF46FD6DE35CA4CF4CE031E643C8FDC9BA4B99AE598E9B0ED98FE3A2319F9",
"amount": "100"
},
"sender": "cosmos13ys0vw7uhw5c70lrgzz6nw77f95k2pm42rt33areg33k0kltn2zsdjsfvu",
"receiver": "cosmos1sjww7vhxhe5sfye44fex4fv9telmuakuahk9nh",
"timeout_height": {
"revision_number": "1",
"revision_height": "4130"
},
"timeout_timestamp": "1641572037493534000"
}
```

Step 2: use Interchain Accounts to execute the IBC transfer in the JSON file.
Don't forget to confirm Alice's balance before and after the transfer to see the IBC denom disappear (it may take a moment for the entire sequence to complete):

```shell
gaiad q bank balances $ALICE_ICA --home $HOME1
gaiad tx icamauth submit send-raw.json --connection-id connection-0 --from alice --home $HOME0 --gas-prices 0.025stake
gaiad q bank balances $ALICE_ICA --home $HOME1
```

The long denom we saw will be changed from `ibc/C4CFF46FD6DE35CA4CF4CE031E643C8FDC9BA4B99AE598E9B0ED98FE3A2319F9` back to `stake` when the token is back to a on chain `test-0`.

## References:
- [Hermes installation](https://hermes.informal.systems/quick-start/installation.html)
- [Interchain Accounts tutorial](https://github.com/cosmos/interchain-accounts/blob/master/README.md)
25 changes: 25 additions & 0 deletions docs/modules/icamauth/hermes_setup.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#!/bin/bash

HERMES_BINARY=$(which hermes)
CONFIG_DIR=./rly-config.toml

# Restore Keys
$HERMES_BINARY --config $CONFIG_DIR keys add --key-name hermes-rly0 --chain test-0 --mnemonic-file ./rly0-mnemonic.txt

echo "sleeping"
sleep 5

$HERMES_BINARY --config $CONFIG_DIR keys add --key-name hermes-rly1 --chain test-1 --mnemonic-file ./rly1-mnemonic.txt

echo "sleeping"
sleep 5

# Configure the clients and connection
echo "Initiating connection handshake..."
$HERMES_BINARY --config $CONFIG_DIR create connection --a-chain test-0 --b-chain test-1

echo "sleeping"
sleep 5

echo "Starting hermes relayer..."
$HERMES_BINARY --config $CONFIG_DIR start
73 changes: 73 additions & 0 deletions docs/modules/icamauth/init_chain_controller.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
#!/bin/bash

BINARY=$(which gaiad)
# please do not reveal your mnemonic in production !!!
MNEMONIC_RLY0=`cat docs/modules/icamauth/rly0-mnemonic.txt`
MNEMONIC_ALICE="captain six loyal advice caution cost orient large mimic spare radar excess quote orchard error biology choice shop dish master quantum dumb accident between"
CHAINID_0=test-0
HOME_0=$HOME/test-0
P2PPORT_0=16656
RPCPORT_0=16657
GRPCPORT_0=9095
GRPCWEBPORT_0=9081
RESTPORT_0=1316
ROSETTA_0=8080

# Stop if it is already running
if pgrep -x "$BINARY" >/dev/null; then
echo "Terminating $BINARY..."
killall gaiad
fi

echo "Removing previous data..."
rm -rf $HOME_0 &> /dev/null

# Add directories for both chains, exit if an error occurs
if ! mkdir -p $HOME_0 2>/dev/null; then
echo "Failed to create gaiad folder. Aborting..."
exit 1
fi

echo "Initializing $CHAINID_0..."
$BINARY init test0 --chain-id=$CHAINID_0 --home $HOME_0

$BINARY config chain-id $CHAIN_ID_0 --home $HOME_0
$BINARY config keyring-backend test --home $HOME_0
$BINARY config broadcast-mode block --home $HOME_0
$BINARY config node tcp://localhost:$RPCPORT_0 --home $HOME_0


echo "Adding genesis accounts..."
$BINARY keys add val0 --home=$HOME_0
echo $MNEMONIC_ALICE | $BINARY keys add alice --recover --home=$HOME_0
echo $MNEMONIC_RLY0 | $BINARY keys add rly0 --recover --home=$HOME_0
$BINARY add-genesis-account $($BINARY keys show val0 -a --home=$HOME_0) 100000000000stake --home=$HOME_0
$BINARY add-genesis-account $($BINARY keys show alice -a --home=$HOME_0) 100000000000stake --home=$HOME_0
$BINARY add-genesis-account $($BINARY keys show rly0 -a --home=$HOME_0) 100000000000stake --home=$HOME_0

echo "Creating and collecting gentx..."
$BINARY gentx val0 7000000000stake --chain-id $CHAINID_0 --home=$HOME_0
$BINARY collect-gentxs --home=$HOME_0

echo "Change setups in app.toml and config.toml files..."
sed -i -e 's#"tcp://0.0.0.0:26656"#"tcp://0.0.0.0:'"$P2PPORT_0"'"#g' $HOME_0/config/config.toml
sed -i -e 's#"tcp://127.0.0.1:26657"#"tcp://0.0.0.0:'"$RPCPORT_0"'"#g' $HOME_0/config/config.toml
sed -i -e 's/"0.0.0.0:9090"/"0.0.0.0:'"$GRPCPORT_0"'"/g' $HOME_0/config/app.toml
sed -i -e 's/"0.0.0.0:9091"/"0.0.0.0:'"$GRPCWEBPORT_0"'"/g' $HOME_0/config/app.toml
sed -i -e 's/timeout_commit = "5s"/timeout_commit = "1s"/g' $HOME_0/config/config.toml
sed -i -e 's/timeout_propose = "3s"/timeout_propose = "1s"/g' $HOME_0/config/config.toml
sed -i -e 's/index_all_keys = false/index_all_keys = true/g' $HOME_0/config/config.toml
sed -i -e 's/enable = false/enable = true/g' $HOME_0/config/app.toml
sed -i -e 's/swagger = false/swagger = true/g' $HOME_0/config/app.toml
sed -i -e 's#"tcp://0.0.0.0:1317"#"tcp://0.0.0.0:'"$RESTPORT_0"'"#g' $HOME_0/config/app.toml
sed -i -e 's#":8080"#":'"$ROSETTA_0"'"#g' $HOME_0/config/app.toml

#set min_gas_prices
sed -i '' 's/minimum-gas-prices = ""/minimum-gas-prices = "0.025stake"/g' $HOME_0/config/app.toml

# Update host chain genesis to allow all msg types
sed -i '' 's/\"allow_messages\": \[\]/\"allow_messages\": \["*"\]/g' $HOME_0/config/genesis.json

echo "Starting $CHAINID_0..."
echo "Creating log file at gaia0.log"
$BINARY start --home=$HOME_0 --log_level=trace --log_format=json --pruning=nothing
Loading

0 comments on commit c565ff4

Please sign in to comment.