# Installation Guides


# Install Cosmovisor

### Build Cosmovisor

<pre class="language-bash"><code class="lang-bash">cd ${HOME}
<strong>git clone https://github.com/cosmos/cosmos-sdk &#x26;&#x26; cd cosmos-sdk/tools/cosmovisor/
</strong>make
sudo cp cosmovisor /usr/local/bin
</code></pre>

#### For MultiNode set ups you can do the following&#x20;

```javascript
mkdir -p ${HOME}/.chain-folder(.juno)/cosmovisor/genesis/bin
```

```javascript
mkdir -p ${HOME}/.local/bin
cp cosmovisor ${HOME}/.local/bin

///check to see if cosmovisor binary is there 
ls ${HOME}/.local/bin

///move chain binary to cosmovisor dir
cp ${HOME}/go/bin/binary ${HOME}/.chain/cosmovisor/genesis/bin
```

### Service file template

```bash
[Unit]
Description=Chain Node Name
After=network-online.target

[Service]
User=<USER>
Group=<GROUP>
ExecStart=/usr/local/bin/cosmovisor run start
Restart=always
RestartSec=3
LimitNOFILE=4096
Environment="DAEMON_NAME=<NODE_BINARY_NAME>"
Environment="DAEMON_HOME=<NODE_HOME_FOLDER>"
Environment="DAEMON_ALLOW_DOWNLOAD_BINARIES=false"
Environment="DAEMON_RESTART_AFTER_UPGRADE=true"
Environment="DAEMON_LOG_BUFFER_SIZE=512"
Environment="UNSAFE_SKIP_BACKUP=true"

[Install]
WantedBy=multi-user.target
```

```javascript
systemctl daemon-reload

systemctl start <service>

journalctl -u <service> -f
```


# Install Hermes Relayer

Setup demonstrates how to setup Hermes relayer and configure it to relay assets between LumenX and Osmosis chains.

### Pre-requisites

All steps were executed and tested on:

* Ubuntu 22.04 LTS

#### Create user account

```bash
adduser relayer
```

#### Required packages

```bash
sudo apt install make clang pkg-config libssl-dev build-essential git jq llvm libudev-dev -y
```

#### Rust installation

```bash
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
source $HOME/.cargo/env
```

**NOTE:** Install Rust as ***relayer*** user created earlier

### Relayer build & installation

```bash
git clone https://github.com/informalsystems/ibc-rs.git && \
cd ibc-rs && \
git checkout v1.3.0 && \
cargo build --release --bin hermes
```

```bash
mkdir -p ${HOME}/.local/bin ; \
cp ${HOME}/ibc-rs/target/release/hermes ${HOME}/.local/bin
```

### Hermes configuration

Create folder for Hermes configuration

```bash
mkdir -p ${HOME}/.hermes
```

Then populate ***${HOME}/.hermes/config.toml*** with following content:

```toml
[[chains]]
id = 'osmosis-1'
rpc_addr = 'https://rpc.service.for.osmosis:443'
grpc_addr = 'https://grpc.service.for.osmosis:443'
websocket_addr = 'ws://rpc.service.for.osmosis:443/websocket'
rpc_timeout = '10s'
account_prefix = 'osmo'
key_name = 'osmo'
address_type = { derivation = 'cosmos' }
store_prefix = 'ibc'
default_gas = 3000000
max_gas = 10000000
gas_price = { price = 0.25, denom = 'uosmo' }
gas_adjustment = 0.1
max_msg_num = 30
max_tx_size = 180000
clock_drift = '15s'
max_block_time = '10s'
trusting_period = '14days'
memo_prefix = ''
trust_threshold = { numerator = '1', denominator = '3' }
[chains.packet_filter]
policy = 'allow'
list = [
 ['transfer', 'channel-286'], # LumenX
]


[[chains]]
id = 'LumenX'
rpc_addr = 'http://rpc.service.for.lumenx:26727'
grpc_addr = 'http://rpc.service.for.lumenx:9160'
websocket_addr = 'ws://rpc.service.for.lumenx:26727/websocket'
rpc_timeout = '10s'
account_prefix = 'lumen'
key_name = 'lumen'
address_type = { derivation = 'cosmos' }
store_prefix = 'ibc'
default_gas = 3000000
max_gas = 10000000
gas_price = { price = 0.25, denom = 'ulumen' }
gas_adjustment = 0.1
max_msg_num = 30
max_tx_size = 180000
clock_drift = '15s'
max_block_time = '10s'
trusting_period = '14days'
memo_prefix = ''
trust_threshold = { numerator = '1', denominator = '3' }
[chains.packet_filter]
policy = 'allow'
list = [
 ['transfer', 'channel-3'], # osmosis-1
]
```

**NOTE:** Please note that apropriate addresses and ports for RPC, gRPC and WebSocket services must be adjusted accordingly to point to nodes providing those services.

### Add relayer keys

```bash
hermes-keys add --chain LumenX --mnemonic-file lumenx.txt
hermes-keys add --chain osmosis-1 --mnemonic-file osmosis.txt
```

**NOTE:** files *lumenx.txt* and *osmosis.txt* contain mnemonic for wallet which will be used for relayer fees. Wallets for relayer must have some amount of coins prior to starting relayer. Otherwise relayer will not be able to relay any transactions

### Create and start Hermes service

Service file ***/etc/systemd/system/hermes.service*** should have at least following content:

```bash
[Unit]
Description=Hermes IBC Relayer

[Service]
User=relayer
Group=relayer
ExecStart=/home/relayer/.local/bin/hermes start
LimitNOFILE=180000
Restart=always
RestartSec=3

[Install]
WantedBy=multi-user.target
```

```bash
sudo systemctl daemon-reload && \
sudo systemctl enable hermes && \
sudo systemctl restart hermes
```


# Backup Server

Configuring backup server to run multiple nodes nodes

So from a dedicated service provider you can rent a rescue image and here is how you can set up ubuntu OS on to the system.

```javascript
installimage
```

1. once you select ubuntu there will be blue screen with some disk configs this is important .. we have to make some changes there
2. select ubuntu 2004 3rd one

![](https://4226186182-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FimXSSnZkS06jq5Lqf13A%2Fuploads%2Fx8a5aEHA18h7r3osjeSz%2Fubuntu.png?alt=media\&token=f0123d12-4edf-4d10-a299-dcf9fffafb8c)

```javascript
config files by commenting out DRIVE3 DRIVE4 by using # 

SWRAIDLEVEL1 

& HOSTNAME to whatever is suited to the build
```

{% hint style="info" %}
Touchbar on mac click on server window, fn then f2 save then f10 exit.
{% endhint %}

Continue with YES. Once system will be deployed you can see with

```javascript
lsblk

///then

mount

```

![](https://4226186182-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FimXSSnZkS06jq5Lqf13A%2Fuploads%2FX7GJfdmseulZf5RzsAuG%2Fmount.png?alt=media\&token=0654e7a2-4892-4c6d-bea9-5316898e3f7c)

```javascript
reboot
```

{% hint style="info" %}
If you need to re-do ssh key you need to remove the IP of server the known host from known\_hosts so it can write the server again

`nano /users/local/.ssh/known_hosts`

input SSH password again
{% endhint %}

Log back in to Service, should now see the hostname implemented

Update system

```javascript
sudo apt update && sudo apt upgrade -y && sudo apt autoremove -y

reboot
```

install Firewall

```javascript
sudo apt install ufw
```

Now configure some basic rules to allow only ssh and outgoing traffic.

```javascript
sudo ufw limit ssh/tcp comment 'Rate limit for openssh server' 
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw enable
```

{% hint style="info" %}
Enable must be the last one, so all rules will be added and firewall enabled.
{% endhint %}

```javascript
reboot
```

#### The set up for this server is as follows.&#x20;

2x 512GB - configured in RAID 1 (Mirror) - they contain operating system and if one fails second will handle OS operations&#x20;

2x 1.92TB - unconfigured. we are about to crate partitions on them and configure those disks for auto-mount

Our usual configured set up is to create /mnt folder so I would suggest we go with

`/mnt/vol1 /mnt/vol2`

but first let's partition them

```javascript
fdisk /dev/nvme2n1

n
P
1
ENTER
ENTER
w
```

{% hint style="info" %}
repeat steps for `fdisk /dev/nvme3n1`
{% endhint %}

What we did on those disks... partition defines amount of space on disk dedicated for single file system... we created partition that covers whole disk space on each of 2 disks

now it is time to make this space usable - format disk with file system

```javascript
mkfs.ext4 /dev/nvme2n1p1
mkfs.ext4 /dev/nvme3n1p1

df -k
```

> at the moment you will not see those 2TB disks yet

Once you have folders created then we can mount volumes

```javascript
mkdir /mnt/vol1
mkdir /mnt/vol2

mount /dev/nvme2n1p1 /mnt/vol1
mount /dev/nvme3n1p1 /mnt/vol2
```

Check they are mounted

```javascript
df -k 
```

We need to make sure that linux will mount them each time it will start

```javascript
sudo /etc/fstab
more /etc/fstab

blkid
```

Add few lines to etc/fstab

```javascript
nano /etc/fstab

# /dev/nvme2n1p1
UUID=8e274ead-a0c0-42bd-8cd2-3d7dc354f6be /mnt/vol1 ext4 defaults 0 0
# /dev/nvme3n1p1
UUID=6d999d6f-b033-4bd8-813a-284542fcff70 /mnt/vol2 ext4 defaults 0 0
mount -a
```

```
reboot
```

#### What we have did so far.

1. Installed custom ubuntu 20.04
2. Created RAID1 volume (Mirror) for operating system during installation (2x 512GB)
3. Once operating system ready partitions were created on 2TB disks (fdisk)
4. Partitions were formatted then with ext4 filesystem (mkfs.ext4)
5. Newly created partitions mounted in /mnt/volX
6. Both new partitions added to /etc/fstab, so they will be automatically mounted when system starts

once system is back you can check if partitions are mounted with

```javascript
//This should display 2x 2TB volumes
df -k
```

Update box.

```javascript
apt update && apt upgrade -y && apt autoremove -y
```

### Install GO

```bash
GOVER=$(curl <https://go.dev/VERSION?m=text>)
wget <https://golang.org/dl/${GOVER}.linux-amd64.tar.gz>
sudo rm -rf /usr/local/go && sudo tar -C /usr/local -xzf ${GOVER}.linux-amd64.tar.gz
```

<pre class="language-javascript"><code class="lang-javascript"><strong>adduser comdex 
</strong></code></pre>

```javascript
///add user to sudo
usermod -aG sudo <username>

su - comdex

nano .profile

///add these lines to the end of the .profile 

	# add environmental variables for Go
if [ -f "/usr/local/go/bin/go" ] ; then
    export GOROOT=/usr/local/go
    export GOPATH=${HOME}/go
    export GOBIN=$GOPATH/bin
    export PATH=${PATH}:${GOROOT}/bin:${GOBIN}
fi

///to save
cmd x 

enter
```

Lets see whats in home

```bash
ls -l /home
```

#### Prepare for Chain build

1. move /home/comdex folder to data volume
2. create link in /home to data volume
3. change context to comdex user
4. build cosmovisor
5. build comdex binaries

move folder

```javascript
///move folder to mount storage
mv /home/comdex /mnt/vol1

///create s-link
ln -s /mnt/vol1/comdex /home/comdex

///see if link was created 
ls -l /home

///log into user
su - comdex

///check to see if GO env variables are good
go version

///back to root
ctrl-d
```

#### Tooling

```javascript
apt install build-essential git gcc make

///log back in to user
```

### Deploy cosmovisor

1. **Cosmovisor build**

```javascript
cd ${HOME}
git clone <https://github.com/cosmos/cosmos-sdk> && cd cosmos-sdk/cosmovisor/
make

///we make the correct folders 
mkdir -p ${HOME}/.comdex/cosmovisor/genesis/bin
```

```bash
```

Get the binary in place

```bash
cd
git clone <https://github.com/comdex-official/comdex.git>
cd comdex
git fetch --tags
git checkout v0.0.3
make install
```

**2. Cosmovisor binaries**

mv `cosmovisor` to it's destination folder

```javascript
///find the visor binary
sudo find / -name cosmovisor

///make directory for visor to live
mkdir -p ${HOME}/.local/bin

///place visor binary in new location
cp cosmovisor ${HOME}/.local/bin

///check to see if its there 
ls ${HOME}/.local/bin

```

```javascript
///Check to see if its in bin..
ls ${HOME}/.local/bin
```

#### (FOR COMDEX ONLY)

follow repo and up grade to .4

```javascript
cd ${HOME}/comdex
git fetch --tags
git checkout v0.0.4
make install

///initialise the node
comdex init "{{NODE_NAME}}" --chain-id comdex-1
```

#### Cosmovisor prep

```javascript
///locate binary
ls -l ${HOME}/go/bin

///mv to cosmosvisor genesis dir
cp ${HOME}/go/bin/binary ${HOME}/.chain/cosmovisor/genesis/bin
```

Now it's time to place proper genesis in config folder, so node will be in proper chain

```bash
rm ${HOME}/.comdex/config/genesis.json
curl <https://raw.githubusercontent.com/comdex-official/networks/main/mainnet/comdex-1/genesis.json> > ${HOME}/.comdex/config/genesis.json
```

#### Peers & Seeds

add peers & seeds from instructions

```javascript
///Add to shell
PEERS="$(curl -s "<https://raw.githubusercontent.com/KiFoundation/ki-networks/v0.1/Testnet/kichain-t-4/peers.txt")">

///Run the command to impletment to config.toml
sed -i.bak -e "s/^persistent_peers *=.*/persistent_peers = \\"$PEERS\\"/" $HOME/.kid/config/config.tom
```

```bash
seeds = "08ab4552a74dd7e211fc79432918d35818a67189@52.69.58.231:26656,449a0f1b7dafc142cf23a1f6166bbbf035edfb10@13.232.85.66:26656,5b27a6d4cf33909c0e5b217789e7455e261941d1@15.222.29.207:26656"
```

#### Checkout our state-sync intructions by following [here.](https://app.gitbook.com/o/qY7noVnVnux1PDe9cG1g/s/imXSSnZkS06jq5Lqf13A/~/changes/jJ9yp3kmYk8lvH3kf2pl/chains/chain-services/statsync/comdex)

#### Ports

in this section we show you a way on running multiple nodes on one server. This not configured properly can cause some flakey behaviour between chains. We reccomened you have a port system for each of you nodes. Here is an example below.

```bash
cd ${HOME}/.comdex/config
```

At the moment we have default ports in configuration. We need to change this as there will be more nodes on same server. We will add and increment of 100 to each port value refer to an excell sheet and run config command by adding 10 to it .

So while you are in `./comdex/config` we can then roll all changes

```bash
sed -i "s/laddr = \\"tcp:\\/\\/127.0.0.1:26657\\"/laddr = \\"tcp:\\/\\/127.0.0.1:26757\\"/g" config.toml
sed -i "s/address = \\"0.0.0.0:9090\\"/address = \\"0.0.0.0:9190\\"/g" app.toml
sed -i "s/address = \\"0.0.0.0:9091\\"/address = \\"0.0.0.0:9191\\"/g" app.toml
sed -i "s/laddr = \\"tcp:\\/\\/0.0.0.0:26656\\"/laddr = \\"tcp:\\/\\/0.0.0.0:26756\\"/g" config.toml
sed -i "s/address = \\"tcp:\\/\\/0.0.0.0:1317\\"/address = \\"tcp:\\/\\/0.0.0.0:1417\\"/g" app.toml
sed -i "s/proxy_app = \\"tcp:\\/\\/127.0.0.1:26658\\"/proxy_app = \\"tcp:\\/\\/127.0.0.1:26758\\"/g" config.toml
sed -i "s/prometheus_listen_addr = \\":26660\\"/prometheus_listen_addr = \\":26760\\"/g" config.toml
sed -i "s/pprof_laddr = \\"localhost:6060\\"/pprof_laddr = \\"localhost:6160\\"/g" config.toml
```

<figure><img src="https://4226186182-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FimXSSnZkS06jq5Lqf13A%2Fuploads%2FxEOghYxil6DJvsrEB9Yn%2FScreenshot%202022-08-31%20at%2009.13.06.png?alt=media&amp;token=3038cb02-59ab-4725-8b2a-62cd9e20386f" alt=""><figcaption></figcaption></figure>

You can check all ports and which process uses which port

```bash
netstat -tlpn
```

#### Summary

1. home folder moved
2. cosmovisor built
3. binaries built and placed
4. config adjusted for statesync
5. config adusted with new port numbers

#### What's left?

1. define service
2. Spin this bitch !!!&#x20;

### Service file

```javascript
///back to root
cntl-d
```

and then we define service

```javascript
///define service
nano /lib/systemd/system/comdex.service
```

```javascript
Unit]
Description=Comdex Backup Node (Cosmovisor)
After=network-online.target

[Service]
User=comdex
Group=comdex
ExecStart=/home/user/.local/bin/cosmovisor run start
Restart=always
RestartSec=3
LimitNOFILE=4096
Environment="DAEMON_NAME=comdex"
Environment="DAEMON_HOME=/home/comdex/.comdex"
Environment="DAEMON_ALLOW_DOWNLOAD_BINARIES=false"
Environment="DAEMON_RESTART_AFTER_UPGRADE=true"
Environment="DAEMON_LOG_BUFFER_SIZE=512"
///we skip back ups on main validators just so we get back online faster. 
///When it comes to our back-up servers this is where we do take a snapshot 
///after any upgrades, incase we need to roll back.
Environment="UNSAFE_SKIP_BACKUP=false"

[Install]
WantedBy=multi-user.target
```

```javascript
systemctl daemon-reload

systemctl start comdex

journalctl -u comdex -f
```

{% hint style="info" %}
Once chain is syncd make sure storage is evenly spread
{% endhint %}

```bash
df -k 
```

{% hint style="info" %}
How to show running services
{% endhint %}

```javascript
systemctl list-units --type=service
```


# Install Golang

{% embed url="<https://odysee.com/@ChainToolsAcademy:b/GolangInstall:c>" %}
Video demonstrates steps described below.
{% endembed %}

### Download and extract repository

#### AMD and Intel compatible processors

```bash
GOVER=$(curl https://go.dev/VERSION?m=text | head -n 1)
wget https://golang.org/dl/${GOVER}.linux-amd64.tar.gz && \
sudo rm -rf /usr/local/go && sudo tar -C /usr/local -xzf ${GOVER}.linux-amd64.tar.gz
```

#### **ARM processors**

```bash
GOVER=$(curl https://go.dev/VERSION?m=text | head -n 1)
wget https://golang.org/dl/${GOVER}.linux-arm64.tar.gz
sudo rm -rf /usr/local/go && sudo tar -C /usr/local -xzf ${GOVER}.linux-arm64.tar.gz
```

**NOTE**: That will install latest version of Go

**Install previous version**

```json
GOVER=go1.20.3
wget https://golang.org/dl/${GOVER}.linux-amd64.tar.gz
sudo rm -rf /usr/local/go && sudo tar -C /usr/local -xzf ${GOVER}.linux-amd64.tar.gz
```

### Add Go environmental variables

Set of variables, which should be set for user(s) with need to build Go apps.

That can be placed in `${HOME}/.profile` or `${HOME}/.bashrc` or any other shell-specific file, whic sets variable during logon

```bash
# add environmental variables for Go
if [ -f "/usr/local/go/bin/go" ] ; then
    export GOROOT=/usr/local/go
    export GOPATH=${HOME}/go
    export GOBIN=${GOPATH}/bin
    export PATH=${PATH}:${GOROOT}/bin:${GOBIN}
fi
```

**NOTE:** To make sure that Go-specific environment will be added to new users profiles below code needs to be added to `/etc/skel/.profile`.

### Important

Once all changes are applied and files installed make sure all shell instances will be closed and then logoff and logon again to system.

That way all environmental variables will be set correctly.


# Install Rust

{% embed url="<https://odysee.com/@ChainToolsAcademy:b/RustInstall:e>" %}
Video demonstrates steps described below.
{% endembed %}

```bash
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
```

#### Environment

Once Rust is installed environment has to be modified, so binaries can be found.

```bash
source $HOME/.cargo/env
```

Content of $HOME/.cargo/env looks like:

```bash
#!/bin/sh
# rustup shell setup
# affix colons on either side of $PATH to simplify matching
case ":${PATH}:" in
    *:"$HOME/.cargo/bin":*)
        ;;
    *)
        # Prepending path in case a system-installed rustc needs to be overridden
        export PATH="$HOME/.cargo/bin:$PATH"
        ;;
esac
```

### Update Rust

```bash
rustup update nightly && rustup update stable
rustup target add wasm32-unknown-unknown --toolchain nightly
```

### Install wasm-pack

```bash
curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh
```


# Install Node.js

## Ubuntu and Debian (from nodesource.com)

It is an abstract from Node.js documentation to have installation repos and command handy.

### Node.js LTS <a href="#user-content-nodejs-lts" id="user-content-nodejs-lts"></a>

```
# Using Ubuntu
curl -fsSL https://deb.nodesource.com/setup_lts.x | sudo -E bash -
sudo apt-get install -y nodejs

# Using Debian, as root
curl -fsSL https://deb.nodesource.com/setup_lts.x | bash -
apt-get install -y nodejs
```

### Node.js Current <a href="#user-content-nodejs-current" id="user-content-nodejs-current"></a>

```
# Using Ubuntu
curl -fsSL https://deb.nodesource.com/setup_current.x | sudo -E bash -
sudo apt-get install -y nodejs

# Using Debian, as root
curl -fsSL https://deb.nodesource.com/setup_current.x | bash -
apt-get install -y nodejs
```

### Node.js v16.x <a href="#user-content-nodejs-v16x" id="user-content-nodejs-v16x"></a>

```
# Using Ubuntu
curl -fsSL https://deb.nodesource.com/setup_16.x | sudo -E bash -
sudo apt-get install -y nodejs

# Using Debian, as root
curl -fsSL https://deb.nodesource.com/setup_16.x | bash -
apt-get install -y nodejs
```

### Node.js v14.x <a href="#user-content-nodejs-v14x" id="user-content-nodejs-v14x"></a>

```
# Using Ubuntu
curl -fsSL https://deb.nodesource.com/setup_14.x | sudo -E bash -
sudo apt-get install -y nodejs

# Using Debian, as root
curl -fsSL https://deb.nodesource.com/setup_14.x | bash -
apt-get install -y nodejs
```

### Node.js v12.x <a href="#user-content-nodejs-v12x" id="user-content-nodejs-v12x"></a>

```
# Using Ubuntu
curl -fsSL https://deb.nodesource.com/setup_12.x | sudo -E bash -
sudo apt-get install -y nodejs

# Using Debian, as root
curl -fsSL https://deb.nodesource.com/setup_12.x | bash -
apt-get install -y nodejs
```

Source: [NodeSource Node.js Binary Distributions](https://github.com/nodesource/distributions/blob/master/README.md#debinstall)


# Install Yarn

## Yarn Package Manager installation

This set of command is noted from Node.js installation.\
It comes up as suggestion once node.js is isntalled.\
Just wrote this down to have it handy for deployments.

### To install the Yarn package manager, run: <a href="#user-content-to-install-the-yarn-package-manager-run" id="user-content-to-install-the-yarn-package-manager-run"></a>

```
curl -sL https://dl.yarnpkg.com/debian/pubkey.gpg | gpg --dearmor | sudo tee /usr/share/keyrings/yarnkey.gpg >/dev/null
echo "deb [signed-by=/usr/share/keyrings/yarnkey.gpg] https://dl.yarnpkg.com/debian stable main" | sudo tee /etc/apt/sources.list.d/yarn.list
sudo apt-get update && sudo apt-get install yarn
```


# Node Configuration

Configuration tips for nodes/validators.


# Pruning Cosmos SDK

**Understanding Pruning in Cosmos SDK Chains**

Pruning is a crucial mechanism in Cosmos SDK-based blockchain networks like Juno. It plays a significant role in managing the storage footprint of nodes while ensuring the integrity and efficiency of the blockchain. In this article, we'll explore the concept of pruning and its implications for network participants.

**What is Pruning?**

Pruning is the process of removing old and unnecessary data from the blockchain's internal state database. This includes transactions, blocks, and associated metadata that are no longer required for the consensus process or maintaining the current state of the network.

**How Does Pruning Work?**

In Cosmos SDK chains like Juno, pruning is typically configured through parameters in the `app.toml` configuration file. These parameters specify the pruning strategy, including:

* `pruning`: Specifies the pruning strategy, such as `"custom"` or `"nothing"`.
* `pruning-keep-recent`: Sets the number of recent blocks to retain.
* `pruning-keep-every`: Sets the interval of blocks to keep.
* `pruning-interval`: Sets the frequency of pruning operations.

For example, setting `pruning-interval = "100"` would instruct the node to perform pruning operations every 100 blocks.

**Impact on Storage**

The pruning strategy directly impacts the storage usage of the node. By removing old blocks and data, pruning helps to reduce the overall storage footprint of the blockchain. However, it's essential to strike a balance between storage efficiency and historical data retention.

A higher pruning interval means less frequent pruning operations, leading to temporary increases in storage usage between pruning intervals. Conversely, a lower interval results in more frequent pruning but ensures a leaner storage footprint.

**Optimizing Pruning Parameters**

Network operators should carefully adjust pruning parameters based on factors like storage constraints, network activity, and resource availability. By optimizing pruning settings, operators can achieve a balance between storage efficiency, performance, and historical data retention.

In conclusion, pruning is a critical aspect of managing the storage footprint of Cosmos SDK chains like Juno. By implementing an effective pruning strategy, network participants can ensure the scalability, integrity, and efficiency of the blockchain network.


# Indexer backend on PostgreSQL

Configuration in `config.toml`

```toml
#######################################################
###   Transaction Indexer Configuration Options     ###
#######################################################
[tx_index]

# What indexer to use for transactions
#
# The application will set which txs to index. In some cases a node operator will be able
# to decide which txs to index based on configuration set in the application.
#
# Options:
#   1) "null"
#   2) "kv" (default) - the simplest possible indexer, backed by key-value storage (defaults to levelDB; see DBBackend).
#               - When "kv" is chosen "tx.height" and "tx.hash" will always be indexed.
#   3) "psql" - the indexer services backed by PostgreSQL.
# When "kv" or "psql" is chosen "tx.height" and "tx.hash" will always be indexed.
indexer = "psql"

# The PostgreSQL connection configuration, the connection format:
#   postgresql://<user>:<password>@<host>:<port>/<db>?<opts>
psql-conn = "postgresql://db_user:password@localhost:5432/node_db"
```

Get Tendermint package:

```
go get github.com/tendermint/tendermint
```

Database schema location:

```
~/go/pkg/mod/github.com/cometbft/cometbft@v0.34.27/state/indexer/sink/psql/schema.sql
```

Content of `schema.sql`

```sql
/*
  This file defines the database schema for the PostgresQL ("psql") event sink
  implementation in CometBFT. The operator must create a database and install
  this schema before using the database to index events.
 */

-- The blocks table records metadata about each block.
-- The block record does not include its events or transactions (see tx_results).
CREATE TABLE blocks (
  rowid      BIGSERIAL PRIMARY KEY,

  height     BIGINT NOT NULL,
  chain_id   VARCHAR NOT NULL,

  -- When this block header was logged into the sink, in UTC.
  created_at TIMESTAMPTZ NOT NULL,

  UNIQUE (height, chain_id)
);

-- Index blocks by height and chain, since we need to resolve block IDs when
-- indexing transaction records and transaction events.
CREATE INDEX idx_blocks_height_chain ON blocks(height, chain_id);

-- The tx_results table records metadata about transaction results.  Note that
-- the events from a transaction are stored separately.
CREATE TABLE tx_results (
  rowid BIGSERIAL PRIMARY KEY,

  -- The block to which this transaction belongs.
  block_id BIGINT NOT NULL REFERENCES blocks(rowid),
  -- The sequential index of the transaction within the block.
  index INTEGER NOT NULL,
  -- When this result record was logged into the sink, in UTC.
  created_at TIMESTAMPTZ NOT NULL,
  -- The hex-encoded hash of the transaction.
  tx_hash VARCHAR NOT NULL,
  -- The protobuf wire encoding of the TxResult message.
  tx_result BYTEA NOT NULL,

  UNIQUE (block_id, index)
);

-- The events table records events. All events (both block and transaction) are
-- associated with a block ID; transaction events also have a transaction ID.
CREATE TABLE events (
  rowid BIGSERIAL PRIMARY KEY,

  -- The block and transaction this event belongs to.
  -- If tx_id is NULL, this is a block event.
  block_id BIGINT NOT NULL REFERENCES blocks(rowid),
  tx_id    BIGINT NULL REFERENCES tx_results(rowid),

  -- The application-defined type label for the event.
  type VARCHAR NOT NULL
);

-- The attributes table records event attributes.
CREATE TABLE attributes (
   event_id      BIGINT NOT NULL REFERENCES events(rowid),
   key           VARCHAR NOT NULL, -- bare key
   composite_key VARCHAR NOT NULL, -- composed type.key
   value         VARCHAR NULL,

   UNIQUE (event_id, key)
);

-- A joined view of events and their attributes. Events that do not have any
-- attributes are represented as a single row with empty key and value fields.
CREATE VIEW event_attributes AS
  SELECT block_id, tx_id, type, key, composite_key, value
  FROM events LEFT JOIN attributes ON (events.rowid = attributes.event_id);

-- A joined view of all block events (those having tx_id NULL).
CREATE VIEW block_events AS
  SELECT blocks.rowid as block_id, height, chain_id, type, key, composite_key, value
  FROM blocks JOIN event_attributes ON (blocks.rowid = event_attributes.block_id)
  WHERE event_attributes.tx_id IS NULL;

-- A joined view of all transaction events.
CREATE VIEW tx_events AS
  SELECT height, index, chain_id, type, key, composite_key, value, tx_results.created_at
  FROM blocks JOIN tx_results ON (blocks.rowid = tx_results.block_id)
  JOIN event_attributes ON (tx_results.rowid = event_attributes.tx_id)
  WHERE event_attributes.tx_id IS NOT NULL;

```


# Tooling Guides


# Node Monitoring

Installation of Prometheus and Node Exporter

The Prometheus [**Node Exporter**](https://github.com/prometheus/node_exporter) exposes a wide variety of hardware- and kernel-related metrics.

In this guide, you will:

* Start up a Node Exporter on `localhost`
* Start up a Prometheus instance on `localhost` that's configured to scrape metrics from the running Node Exporter

### Installing Prometheus & Node Exporter

#### Prometheus instance install

```javascript
wget https://github.com/prometheus/prometheus/releases/download/v*/prometheus-*.*-amd64.tar.gz
tar xvf prometheus-*.*-amd64.tar.gz
cd prometheus-*.*
```

Copy tmp config to etc

```javascript
/tmp/prometheus-2.31.1.linux-amd64# cp /tmp/prometheus-2.31.1.linux-amd64/prometheus.yml  /etc/prometheus
```

Create service file for Prometheus to run&#x20;

```javascript
[Unit]
Description=Prometheus
Wants=network-online.target
After=network-online.target

[Service]
User=prometheus
Group=prometheus
Type=simple
ExecStart=/usr/local/bin/prometheus \
    --config.file /etc/prometheus/prometheus.yml \
    --storage.tsdb.path /var/lib/prometheus/ \
    --web.console.templates=/etc/prometheus/consoles \
    --web.console.libraries=/etc/prometheus/console_libraries

[Install]
WantedBy=multi-user.target
```

```javascript
sudo systemctl daemon-reload
sudo systemctl restart prometheus.service
```

As you have dedicated monitoring system. It is wise to add rules to firewall which will only allow prometheus server to scrape data.

```javascript
sudo ufw allow from "ip-of-your-monitoring/32 proto tcp to any port 9100 comment "Prometheus Node Exporter"

sudo ufw allow from "ip-of-your-monitoring/32 proto tcp to any port 26660 comment "Prometheus Tendermint Exporter"
```

#### Configuring your Prometheus instances <a href="#configuring-your-prometheus-instances" id="configuring-your-prometheus-instances"></a>

```javascript
global:
  scrape_interval: 15s

scrape_configs:
- job_name: node
  static_configs:
  - targets: ['localhost:9100']
```

### Install Node\_Exporter

```javascript
wget https://github.com/prometheus/node_exporter/releases/download/v1.2.2/node_exporter-1.2.2.linux-amd64.tar.gz

/// see whats been downloaded
ls

/// tar the folder
tar xvfz node_exporter-.amd64.tar.gz

/// cd into the folder
cd node_exporter-.amd64

/// run the instance to make sure it is working
./node_exporter

/// check to see scrapes are working 
curl http://localhost:9100/metrics

/// check from another server 
curl http://"ip-of-server-with-node-exporter":9100/metrics

/// rename the folder correctly 
mv node_exporter-1.2.2.linux-amd64 node_exporter

/// if you need to find where the node_exporter binary is you can
sudo find / -name "node_exporter*”

/// set some UFW rules
sudo ufw allow from 134.209.186.97/32 proto tcp to any port 9100 comment "Prometheus Node Exporter"

sudo ufw allow from 134.209.186.97/32 proto tcp to any port 26660 comment "Prometheus Tendermint Exporter"
```

### Create a service file&#x20;

```javascript
sudo nano /lib/systemd/system/node_exporter.service

/// inside the file
[Unit]
Description=Node Exporter
Wants=network-online.target
After=network-online.target

[Service]
User=monitoring
Group=monitoring
Type=simple
ExecStart=/home/monitoring/node_exporter/node_exporter


[Install]
WantedBy=multi-user.target
```

```javascript
sudo systemctl daemon-reload

sudo systemctl start node_exporter.service
```

#### Troubleshooting&#x20;

Some useful commands

```javascript
  ps aux | grep prometheus
  
  ufw status numbered
  
  ufw delete RULE_NUMBER
```


# Panic Cosmos

This first section will show you how to set up panic\_cosmos to alert of any missing blocks and lose of peers. It uses RPC to query the server and pull data and alert a Telegram Account of your choice.

This first section will show you how to set up panic\_cosmos to alert of any missing blocks and lose of peers. It used RPC to query the server and pull data from it to be alerted to your TG bot.

In this tutorial we are using Linux cloud machine with user set up called `monitoring` and inside there we will place our working directories along with service file for running in background.

Follow the guide from [here](https://github.com/SimplyVC/panic_cosmos/blob/master/doc/INSTALL_AND_RUN.md) if you want to see the work from the builders at Simply\_VC

On your monitoring server if it is a fresh install.&#x20;

```javascript
sudo apt-get update
```

**Requirements**

* Python v3.5.2+ with pip package manager and pipenv packaging tool.
* **Optional**: Telegram account and bots, for Telegram alerts and commands.
* **Optional**: Twilio account, for highly effective phone call alerts.
* **Optional**: Redis server, to keep a backup of the alerter state and to have some control over the alerter, such as to snooze phone call alerts using Telegram commands.

#### Step 1: installing Python (with pip and pipenv)

```javascript
/// create a user
su - username
```

Install Python v3.5.2 or greater:

```javascript
sudo apt-get install python3.8 python3-pip
```

Once the installation is complete, you can run `Python 3.8` with the python3.8 command and pip with the `pip3` command.

```javascript
python3.8 --version
///Python 3.8.4
```

To run the test suite, type the following command:

```javascript
python3.8 -m test
```

To install pip package manager

```javascript
apt-get install python3-pip
```

To install pipenv packaging tool, run

```javascript
pip install pipenv
```

#### Step 2: Telegram: [Click here](https://github.com/SimplyVC/panic_cosmos/blob/master/doc/INSTALL_TELEGRAM.md) if you want to set up a Telegram account with bots.

#### Step 3: Setting up PANIC

PANIC requires its own setup process, involving three main parts, each of which generates its own respective config file:

* Linking up any of the optional features that you set up (`config/user_config_main.ini`)
* Providing a list of nodes that you wish to monitor (`config/user_config_nodes.ini`)
* Providing a list of GitHub repositories that you wish to monitor (`config/user_config_repos.ini`)

All of these steps are packaged into one setup process which is started up by running:

```javascript
su - username

pipenv sync

pipenv run python run_setup.py
```

{% hint style="info" %}
If multiple versions of Python are installed, the python executable may be 'python3.6', 'python3.7', etc.
{% endhint %}

Alternatively, you can take a look at the three `config/example_***.ini` files and perform the config file generation manually by copying the three example config files to the ones listed above and replacing the example pieces of information with actual ones.

The setup process is guided by instructions which we highly recommend that you read. The setup of any optional feature that was not set up in the previous section can be skipped. For convenience, any yes/no question can be answered with a *yes* just by pressing *ENTER*.

Lastly, note that if you wish to change some configurations and run the setup process again, it will detect the config files and will not simply overwrite the current configurations.

#### STEP 4: Advanced Configuration

Edit the user\_config\_main.ini\` file by using nano or vi what ever you prefer and add your TG bot config. for example:

```javascript
[telegram_alerts]
enabled = True
bot_token = <BOT-TOKEN>
bot_chat_id = <CHAT_ID> 
```

{% hint style="info" %}
The chat ID is took from the API that the guide showed you earlier on setting up TG bot.
{% endhint %}

Edit the `user_config_nodes.ini` file now.&#x20;

This is where you can add the node you wish to get alerts for. Multiple nodes can be added here. For example.

<figure><img src="https://4226186182-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FimXSSnZkS06jq5Lqf13A%2Fuploads%2FVMkk3IjW0DPffAHO1Epq%2FScreenshot%202022-08-31%20at%2015.01.11.png?alt=media&amp;token=f6ebe53f-b013-4813-b00c-6cdb40bb94cd" alt=""><figcaption></figcaption></figure>

{% hint style="info" %}
If you are not intending to run sentries for your validator nodes then you need to add the same \<NODE\_RPC\_IP> and set the other to `validator=false` so you have two nodes being queried.
{% endhint %}

On each NODE you wish to monitor set the RPC and add rule in `ufw status` to allow connection from monitoring server

```javascript
sudo ufw allow from <monitoring_node_ip>/32 proto tcp to any port 26657 comment "Panic_Cosmos"
```

#### Step 5: Running PANIC

After all of the setting-up, you will be glad to find out that running the alerter is a breeze. To start up PANIC simply run the following commands:

```javascript
pipenv sync
pipenv run python run_alerter.py
# If multiple versions of Python are installed, the python executable may be `python3.6`, `python3.7`, etc.
```

Set up service for your session to run.

```javascript
nano /etc/systemd/system/panic_alerter.service

[Unit]
Description=PANIC
After=network.target
StartLimitIntervalSec=0

[Service]
Type=simple
Restart=always
User=username
TimeoutStopSec=90s
WorkingDirectory=/home/username/panic_cosmos/
ExecStart=/usr/bin/pipenv run python /home/panic_cosmos/run_alerter.py

[Install]
WantedBy=multi-user.target
```

```javascript
systemctl daemon-reload

systemctl start panic_alerter

journalctl -u panic_alerter -f
```


# Systemd Service Template

### Service template with logging to file

```bash
[Unit]
Description=Service
After=network-online.target

[Service]
Type=simple
User=<USER>
Group=<GROUP>
ExecStart=/home/<USER>/.local/bin/<SERVICE>
LimitNOFILE=8192
Restart=on-failure
RestartSec=3
StandardOutput=append:/home/<USER>/.logs/output.log
StandardError=append:/home/<USER>/.logs/error.log

[Install]
WantedBy=multi-user.target
```

### Service template with logging to journal

```bash
[Unit]
Description=Service
After=network-online.target

[Service]
Type=simple
User=<USER>
Group=<GROUP>
ExecStart=/home/<USER>/.local/bin/<SERVICE>
LimitNOFILE=8192
Restart=on-failure
RestartSec=3
StandardOutput=journal
StandardError=journal
SyslogIdentifier=<SERVICE_NAME>

[Install]
WantedBy=multi-user.target
```


# Configure journalctl

### Check how much disk space is allocated for journalctl

```bash
sudo journalctl --disk-usage
```

### Adjust journalctl diskspace allocation

In file `/etc/systemd/journald.conf` locate and adjust line ***SystemMaxUse=50M***. Allocation of 50M is an example. By default this parameter might be commented in configuration file.

### Restart journal to apply new settings and clean up history

```bash
sudo systemctl kill --kill-who=main --signal=SIGUSR2 systemd-journald.service
sudo systemctl restart systemd-journald.service
```


# Caddy Web Server/Proxy

Install Caddy to a service

Most people use Caddy as a web server or proxy, but at its core, Caddy is a server of servers. With the [requisite modules](https://caddyserver.com/docs/modules/), it can take on the role of any long-running process!

Configuration is both dynamic and exportable with [Caddy's API](https://caddyserver.com/docs/api). Although no config files required, you can still use them; most people's favorite way of configuring Caddy is using the [Caddyfile](https://caddyserver.com/docs/caddyfile). The format of the config document takes many forms with [config adapters](https://caddyserver.com/docs/config-adapters), but Caddy's native config language is [JSON](https://caddyserver.com/docs/json/).

Caddy compiles for all major platforms and has no runtime dependencies.

### **Install Caddy on to Ubuntu system**

```bash
sudo apt install -y debian-keyring debian-archive-keyring apt-transport-https
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' | sudo gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' | sudo tee /etc/apt/sources.list.d/caddy-stable.list
sudo apt update
sudo apt install caddy
```

### **Configuring Caddyfile**

Edit the config file which will be installed in `/etc/caddy/Caddyfile`

{% hint style="info" %}
You can either comment all lines with #.

Or just wipe whole content and create your own
{% endhint %}

### **Example Configuration**

```json
https://rpc.juno.chaintools.tech { 
  reverse_proxy http://<RPC-SERVER-IP>:<PORT> { 
     header_down Access-Control-Allow-Origin * 
  } log { 
         output file /var/log/caddy/rpc.juno.chaintools.tech.log
         } 
} 
 
https://api.juno.chaintools.tech { 
   reverse_proxy http://<API-SERVER-IP>:<PORT> { 
      header_down Access-Control-Allow-Origin * 
  } log { 
         output file /var/log/caddy/api.juno.chaintools.tech.log 
         } 
}
  
https://grpc.juno.chaintools.tech {
   reverse_proxy {
      to h2c://<GRPC-SERVER-IP>:<PORT>
      transport http  {
         versions h2c 2
      }
   }
   log {
       output file /var/log/caddy/grpc.juno.chaintools.tech.log
   }
}
```

### **Create a service file for Caddy**

```
cat /lib/systemd/system/caddy.service

# caddy.service
#
# For using Caddy with a config file.
#
# Make sure the ExecStart and ExecReload commands are correct
# for your installation.
#
# See https://caddyserver.com/docs/install for instructions.
#
# WARNING: This service does not use the --resume flag, so if you
# use the API to make changes, they will be overwritten by the
# Caddyfile next time the service is restarted. If you intend to
# use Caddy's API to configure it, add the --resume flag to the
# `caddy run` command or use the caddy-api.service file instead.

[Unit]
Description=Caddy
Documentation=https://caddyserver.com/docs/
After=network.target network-online.target
Requires=network-online.target

[Service]
Type=notify
User=caddy
Group=caddy
ExecStart=/usr/bin/caddy run --environ --config /etc/caddy/Caddyfile
```

Once you are happy with the config and service file you can now start.

`sudo systemctl daemon-reload`

`sudo systemctl start caddy`


# General

| Name           | Chain ID         |
| -------------- | ---------------- |
| Acrechain      | acre\_9052-1     |
| Beezee         | beezee-1         |
| BitSong        | bitsong-2b       |
| Blit           | blit-1           |
| Bluzelle       | bluzelle-9       |
| Carbon         | carbon-1         |
| Cheqd          | cheqd-mainnet-1  |
| Chihuahua      | chihuahua-1      |
| Comdex         | comdex-1         |
| Decentr        | mainnet-3        |
| Desmos         | desmos-mainnet   |
| Dyson Protocol | dyson-mainnet-01 |
| e-Money        | emoney-3         |
| Evmos          | evmos\_9001-2    |
| Fetch.ai       | fetchhub-4       |
| FirmaChain     | colosseum-1      |
| Gitopia        | gitopia          |
| IXO            | ixo-5            |
| Jackal         | jackal-1         |
| Juno           | juno-1           |
| Kava           | kava\_2222-10    |
| KiChain        | kichain-2        |
| Konstellation  | darchub          |
| Kujira         | kaiyo-1          |
| Kyve           | kyve-1           |
| Lum Network    | lum-network-1    |
| Medibloc       | panacea-3        |
| Meme           | meme-1           |
| Nois           | nois-1           |
| OmniFlix       | omniflixhub-1    |
| Passage        | passage-2        |
| Provenance     | pio-mainnet-1    |
| Quasar         | quasar-1         |
| Rizon          | titan-1          |
| Sentinel       | sentinelhub-2    |
| SifChain       | sifchain-1       |
| Source         | source-1         |
| Teritori       | teritori-1       |
| Unification    | FUND-MainNet-2   |
| Vidulum        | vidulum-1        |
| XPLA           | dimension\_37-1  |


# Endpoints

#### ​

| Chain      | Services                                                                                                                                   |
| ---------- | ------------------------------------------------------------------------------------------------------------------------------------------ |
| BitSong    | [RPC](https://rpc.bitsong.chaintools.tech), GRPC, [API](https://api.bitsong.chaintools.tech)                                               |
| Comdex     | [RPC](https://rpc.comdex.chaintools.tech), [GRPC](https://grpc.comdex.chaintools.tech), [API](https://api.comdex.chaintools.tech)          |
| Cosmos     | [RPC](https://rpc.cosmos.chaintools.tech/), GRPC, [API](https://api.cosmos.chaintools.tech)                                                |
| Decentr    | [RPC](https://rpc.decentr.chaintools.tech), GRPC, [API](https://api.decentr.chaintools.tech)                                               |
| Evmos      | [RPC](https://rpc.evmos.chaintools.tech), [GRPC](https://evmos.grpcui.chaintools.host/), [API](https://api.evmos.chaintools.tech)          |
| FirmaChain | [RPC](https://rpc.firmachain.chaintools.tech), GRPC, [API](https://api.firmachain.chaintools.tech)                                         |
| Juno       | [RPC](https://rpc.juno.chaintools.tech),[ GRPC](https://evmos.grpcui.chaintools.host), [API](https://api.juno.chaintools.tech)             |
| KiChain    | [RPC](https://rpc.kichain.chaintools.tech), GRPC, [API](https://api.kichain.chaintools.tech/)                                              |
| Kujira     | [RPC](https://rpc.kujira.chaintools.tech), [GRPC](https://api.kichain.chaintools.tech/), [API](https://api.kujira.chaintools.tech)         |
| OmniFlix   | [RPC](https://rpc.omniflix.chaintools.tech), GRPC, [API](https://api.omniflix.chaintools.tech)                                             |
| Rizon      | [RPC](https://rpc.rizon.chaintools.tech), GRPC, [API](https://api.rizon.chaintools.tech)                                                   |
| Sentinel   | [RPC](https://rpc.sentinel.chaintools.tech), [GRPC](https://sentinel.grpcui.chaintools.host/), [API](https://api.sentinel.chaintools.tech) |
| SifChain   | [RPC](https://rpc.sifchain.chaintools.tech), GRPC, [API](https://api.sifchain.chaintools.tech)                                             |
| Nois       | [RPC](https://rpc.nois.chaintools.tech/), [GRPC](https://nois.grpcui.chaintools.host/), [API](https://api.nois.chaintools.tech/)           |


# Peers & Seeds

Here we will try our best to update peer and seeds list.

{% hint style="info" %}
Query your own PEER
{% endhint %}

{% hint style="info" %}
Set external P2P address
{% endhint %}

```bash
sed -i "/^external_address = .*/ s//external_address = \"${ADDRESS:="$(curl -fsSL https://ifconfig.me):${PORT:=26656}"}\"/" $HOME/.chaind/config/config.toml
```

```javascript
echo $(junod tendermint show-node-id)@$(curl -4 ifconfig.co):26656
```

{% hint style="info" %}
Add seeds with `sed`
{% endhint %}

```bash
SEEDS=<    >
```

```bash
sed -i "s/^\(seeds *= *\).*$/\1$SEEDS/" config.toml
```

{% hint style="info" %}
Query how many peers connected to your network
{% endhint %}

```bash
curl -s http://localhost:26657/net_info | jq '.result.n_peers'
```

{% hint style="info" %}
Query connected peers on your network&#x20;
{% endhint %}

```javascript
curl -s http://localhost:26657/net_info | jq '.result.peers[].node_info.id + "@" + .result.peers[].remote_ip'
```


# State-Sync

Cosmos SDK State Sync Guide The recent Tendermint Core 0.34 release includes support for state sync, which allows a new node to join a network by fetching a snapshot of the application state

#### Enable StateSync <a href="#enable-statesync" id="enable-statesync"></a>

To enable StateSync adjust following parameters in `app.toml:`

`pruning-keep-every = "1000"`\
`[state-sync]`\
`snapshot-interval = 1000`\
`snapshot-keep-recent = 3`

Once changes are done restart node.

That will create snapshot every 1000 blocks and will keep 3 snapshots.


# Validator bootstrap commands

Some useful quick commands to help bootstrapping validator nodes

#### config

<pre class="language-bash"><code class="lang-bash">homed config chain-id chain_name --home $NAME_HOME

# seeds and peers
seeds=""
sed -i "s/^seeds *=.*/seeds = \"$seeds\"/" $NAME_HOME/config/config.toml

peers=""
sed -i "s/^persistent_peers *=.*/persistent_peers = \"$peers\"/" $NAME_HOME/config/config.toml

# indexing off
indexer="null"
sed -i "s/^indexer *=.*/indexer = \"$indexer\"/" $NAME_HOME/config/config.toml

# min-gas
min_gas_price=""
<strong>sed -i "s/^minimum-gas-prices *=.*/minimum-gas-prices = \"$min_gas_price\"/" $NAME_HOME/config/app.toml
</strong>
# prunning
pruning="custom"
pruning_keep_recent="100"
pruning_keep_every="0"
pruning_interval="10"

sed -i "s/^pruning *=.*/pruning = \"$pruning\"/" $NAME_HOME/config/app.toml
sed -i "s/^pruning-keep-recent *=.*/pruning-keep-recent = \"$pruning_keep_recent\"/" $NAME_HOME/config/app.toml
<strong>sed -i "s/^pruning-keep-every *=.*/pruning-keep-every = \"$pruning_keep_every\"/" $NAME_HOME/config/app.toml
</strong>sed -i "s/^pruning-interval *=.*/pruning-interval = \"$pruning_interval\"/" $NAME_HOME/config/app.toml

# enable snapshots if needed.
sed -i 's/snapshot-interval *=.*/snapshot-interval = 5000/' $NAME_HOME/config/app.toml

</code></pre>


# Mainnets


# Asset Mantle


# Beezee


# BitCanna


# BitSong

Build and synchronize node from state-sync service

### Prerequisites

* Ubuntu 20.04 LTS or newer
* Go 1.18.x or newer - Installation guide [here](/home/readme/install-golang).
* JSON processor jq - `sudo apt install jq`
* Essential Build Tools - `sudo apt install build-essential`

{% embed url="<https://odysee.com/@ChainToolsAcademy:b/StateSyncBitSong:d>" %}
Video demonstrates steps described below.
{% endembed %}

### Build BitSong Node

```bash
git clone https://github.com/bitsongofficial/go-bitsong && cd go-bitsong
git checkout v0.14.0
make install
```

### Initialize BitSong Node

```bash
bitsongd init myNode --chain-id bitsong-2b
wget -O ${HOME}/.bitsongd/config/addrbook.json https://files.chaintools.tech/chains/bitsong/addrbook.json
wget -O ${HOME}/.bitsongd/config/genesis.json https://github.com/bitsongofficial/networks/raw/master/bitsong-2b/genesis.json
```

### Configure state-sync

```bash
SNAP_RPC="https://rpc.bitsong.chaintools.tech:443"
SNAP_RPC2="https://rpc.bitsong.chaintools.tech:443"

LATEST_HEIGHT=$(curl -s $SNAP_RPC/block | jq -r .result.block.header.height); \
BLOCK_HEIGHT=$((LATEST_HEIGHT - 2000)); \
TRUST_HASH=$(curl -s "$SNAP_RPC/block?height=$BLOCK_HEIGHT" | jq -r .result.block_id.hash)

echo $LATEST_HEIGHT $BLOCK_HEIGHT $TRUST_HASH

sed -i.bak -E "s|^(enable[[:space:]]+=[[:space:]]+).*$|\1true| ; \
s|^(rpc_servers[[:space:]]+=[[:space:]]+).*$|\1\"$SNAP_RPC,$SNAP_RPC2\"| ; \
s|^(trust_height[[:space:]]+=[[:space:]]+).*$|\1$BLOCK_HEIGHT| ; \
s|^(trust_hash[[:space:]]+=[[:space:]]+).*$|\1\"$TRUST_HASH\"| ; \
s|^(seeds[[:space:]]+=[[:space:]]+).*$|\1\"\"|" $HOME/.bitsongd/config/config.toml
```

### Start BitSong Node

```
bitsongd start
```

**NOTE:** It might take 5-10 minutes for node to catch-up with RPC and download state-sync snapshot.

Once snapshot will be identified and accepted you will see following information in node logs:

```bash
12:35PM INF Discovering snapshots for 15s module=statesync
12:35PM INF Discovered new snapshot format=1 hash="W.:�5��D\blW�X��cJ\x01�l�p��t�S��\t�6" height=7422600 module=statesync
12:35PM INF Discovered new snapshot format=1 hash="�N\x11��et��z>{\x1a�B��e�)��iF$���C�^�" height=7422000 module=statesync
12:35PM INF Discovered new snapshot format=1 hash="��յ�S���~\x18������t��\x12=\v!�������k" height=7420500 module=statesync
12:35PM INF Discovered new snapshot format=1 hash="�O�y�RշKF�\x02D\x7f��I\x04\x18���\x12jR�o�\u038bQB" height=7423000 module=statesync
12:35PM INF Discovered new snapshot format=1 hash="�����®\x0e���P\x1b𤶠�:y�'C;�U�Ջ#�s" height=7422500 module=statesync
12:35PM INF Discovered new snapshot format=1 hash="xq�\n\x0ef�\r\tlz�\x1f��\x1b�X㼋�\x06�\x00w�@h\x17J�" height=7420000 module=statesync
12:36PM INF VerifyHeader hash=0E24547577528B701DDC22D28A7C6F956A8712E48D0D74BD20D692FB4E83F375 height=7423001 module=light
12:36PM INF VerifyHeader hash=5DF0018BDD2DA1AFE21324850F743B3DF1407B4BD8ABA6E7AE4B29F0D2730514 height=7423002 module=light
12:36PM INF Offering snapshot to ABCI app format=1 hash="�O�y�RշKF�\x02D\x7f��I\x04\x18���\x12jR�o�\u038bQB" height=7423000 module=statesync
12:36PM INF Snapshot accepted, restoring format=1 hash="�O�y�RշKF�\x02D\x7f��I\x04\x18���\x12jR�o�\u038bQB" height=7423000 module=statesync
12:36PM INF Fetching snapshot chunk chunk=0 format=1 height=7423000 module=statesync total=20
12:36PM INF Fetching snapshot chunk chunk=1 format=1 height=7423000 module=statesync total=20
12:36PM INF Fetching snapshot chunk chunk=2 format=1 height=7423000 module=statesync total=20
12:36PM INF Fetching snapshot chunk chunk=3 format=1 height=7423000 module=statesync total=20
12:36PM INF VerifyHeader hash=336FD5DED5EBF0CF24DA5584A08EC052193409890AA6EC8DCC31060A402B3A0E height=7423000 module=light
12:36PM INF Header has already been verified hash=0E24547577528B701DDC22D28A7C6F956A8712E48D0D74BD20D692FB4E83F375 height=7423001 module=light
```


# Carbon


# Cheqd


# CNHO Stables


# Decentr

Build and synchronize node from state-sync service

### Prerequisites

* Ubuntu 20.04 LTS or newer
* Go 1.18.x or newer - Installation guide [here](/home/readme/install-golang).
* JSON processor jq - `sudo apt install jq`
* Essential Build Tools - `sudo apt install build-essential`

{% embed url="<https://odysee.com/@ChainToolsAcademy:b/StateSyncDecentr:6>" %}
Video demonstrates steps described below.
{% endembed %}

### Build Decentr Node

<pre class="language-bash"><code class="lang-bash"><strong>git clone https://github.com/Decentr-net/decentr &#x26;&#x26; cd decentr
</strong>git checkout v1.6.2
make install
</code></pre>

### Initialize Decentr Node

```bash
decentrd init myNode --chain-id mainnet-3
wget -O ${HOME}/.decentr/config/addrbook.json https://files.chaintools.tech/chains/decentr/addrbook.json
wget -O ${HOME}/.decentr/config/genesis.json https://raw.githubusercontent.com/Decentr-net/mainnets/master/3.0/genesis.json
```

### Add Seed Nodes to config

```
sed -E -i 's/seeds = \".*\"/seeds = \"7708addcfb9d4ff394b18fbc6c016b4aaa90a10a@ares.mainnet.decentr.xyz:26656,8a3485f940c3b2b9f0dd979a16ea28de154f14dd@calliope.mainnet.decentr.xyz:26656,87490fd832f3226ac5d090f6a438d402670881d0@euterpe.mainnet.decentr.xyz:26656,3261bff0b7c16dcf6b5b8e62dd54faafbfd75415@hera.mainnet.decentr.xyz:26656,5f3cfa2e3d5ed2c2ef699c8593a3d93c902406a9@hermes.mainnet.decentr.xyz:26656,a529801b5390f56d5c280eaff4ae95b7163e385f@melpomene.mainnet.decentr.xyz:26656,385129dbe71bceff982204afa11ed7fa0ee39430@poseidon.mainnet.decentr.xyz:26656,35a934228c32ad8329ac917613a25474cc79bc08@terpsichore.mainnet.decentr.xyz:26656,0fd62bcd1de6f2e3cfc15852cdde9f3f8a7987e4@thalia.mainnet.decentr.xyz:26656,bd99693d0dbc855b0367f781fb48bf1ca6a6a58b@zeus.mainnet.decentr.xyz:26656\"/' $HOME/.decentr/config/config.toml
```

### Configure state-sync

```bash
SNAP_RPC="http://75.119.157.167:28657"
SNAP_RPC2="http://75.119.157.167:28657"

LATEST_HEIGHT=$(curl -s $SNAP_RPC/block | jq -r .result.block.header.height); \
BLOCK_HEIGHT=$((LATEST_HEIGHT - 1000)); \
TRUST_HASH=$(curl -s "$SNAP_RPC/block?height=$BLOCK_HEIGHT" | jq -r .result.block_id.hash)

echo $LATEST_HEIGHT $BLOCK_HEIGHT $TRUST_HASH

sed -i.bak -E "s|^(enable[[:space:]]+=[[:space:]]+).*$|\1true| ; \
s|^(rpc_servers[[:space:]]+=[[:space:]]+).*$|\1\"$SNAP_RPC,$SNAP_RPC2\"| ; \
s|^(trust_height[[:space:]]+=[[:space:]]+).*$|\1$BLOCK_HEIGHT| ; \
s|^(trust_hash[[:space:]]+=[[:space:]]+).*$|\1\"$TRUST_HASH\"| ; \
s|^(seeds[[:space:]]+=[[:space:]]+).*$|\1\"\"|" $HOME/.decentr/config/config.toml
```

### Start Decentr Node

```
decentrd start
```

**NOTE:** It might take 5-10 minutes for node to catch-up with RPC and download state-sync snapshot.


# Fetch.ai


# FirmaChain


# Gitopia


# Testnets


# Python gRPC

Code snippet, which lists all services and methods using reflection of gRPC service.

```python
import grpc

from grpc_reflection.v1alpha.proto_reflection_descriptor_database import ProtoReflectionDescriptorDatabase
from google.protobuf.descriptor_pool import DescriptorPool


server_address = "grpc.juno.chaintools.tech:443"
creds = grpc.ssl_channel_credentials()
with grpc.secure_channel(server_address, creds) as channel:
    reflection_db = ProtoReflectionDescriptorDatabase(channel)

    desc_pool = DescriptorPool(reflection_db)

    services = reflection_db.get_services()

    for service in services:
        service_details = desc_pool.FindServiceByName(service)
        print(f'Service: {service}')
        for method in service_details.methods_by_name:
            print(f' - Method: {method}')
        del service_details
```


# Handy commands

### Global consensus state

```bash
curl http://localhost:26657/consensus_state | jq '.result.round_state.height_vote_set[0].prevotes_bit_array'
```

### Check to see if chain is sync

```bash
curl -s http://localhost:26657/status | jq '.result.sync_info.catching_up'
```

### Set pruning on node

```bash
sed -i 's/^pruning = .*/pruning = "custom"/; s/^pruning-keep-recent = .*/pruning-keep-recent = "100"/; s/^pruning-keep-every = .*/pruning-keep-every = "0"/; s/^pruning-interval = .*/pruning-interval = "10"/' /home/juno/.juno/config/app.toml
```

### Set Indexer "null"

```bash
sed -i 's/^indexer *=.*/indexer = "null"/' /home/nois/.noisd/config/config.toml
```

### Validator pre-voting status

```bash
curl -s http://localhost:26657/dump_consensus_state | jq '.result.round_state.votes[0].prevotes' | grep $(curl -s http://localhost:26657/status | jq -r '.result.validator_info.address[:12]')
```

### Validator list

```bash
gaiad q staking validators  --node http://localhost:26657 -o json --limit=1000 | jq '.validators[]' | jq -r '.tokens + " - " + .status + " - " +  .description.moniker + " - " + .operator_address' | sort -gr | nl
```

### Set External Address

```bash
ip addr
```

```bash
sed -i "/^external_address = .*/ s//external_address = \"${ADDRESS:="your_ip_here:${PORT:=26656}"}\"/" $HOME/.kujira/config/config.toml
```

### Number of connected peers

```bash
curl -s http://127.0.0.1:26677/metrics | grep '^tendermint_p2p_peers'
```

### Number of peers

```bash
curl -s 127.0.0.1:26657/net_info  | grep n_peers
```

### Validator voting power

```bash
curl -s localhost:26657/status | jq .result.validator_info.voting_power
```

### Peer list

```bash
curl -s http://127.0.0.1:26657/net_info | jq -r '.result.peers[] | "\(.node_info.id)@\(.remote_ip):\(.node_info.listen_addr | split(":")[2])"' | paste -sd,
```

### Check Chain ID via REST API

```bash
curl --location --request GET 'https://NODE_IP/node_info' -s | jq '.node_info.network' | tr -d '"'
```

### Download Genesis from RPC

```bash
curl https://NODE_IP/genesis | jq '.result.genesis' > genesis.json
```

### Export Chain Height

```bash
junod export --height 112358 > some_file.json
```

### Storage&#x20;

```json
du /home/folder/
```


# Drafts


# Dyson Protocol Node Deployment with Podman

Guide describing how to deploy Dyson Protocol node containers using rootless environment and Podman as containerization platform.

{% embed url="<https://odysee.com/@Drafts:9/ct_Academy_DysonNode_Podman:4>" %}

### Docker vs Podman

Docker and Podman are both containerization platforms that enable developers to build, package, and distribute applications in a consistent and reproducible manner. While they share many similarities, there are also notable differences between the two:

1. **Daemon vs. Daemonless**: Docker uses a client-server architecture, where a Docker daemon runs in the background and manages containers. In contrast, Podman is daemonless and runs containers directly, which can reduce complexity and security risks.
2. **Root vs. Rootless**: Docker typically requires root privileges for most operations, which can introduce security concerns. Podman, on the other hand, supports running containers without root privileges (rootless), which enhances security and allows non-privileged users to manage containers.
3. **CLI Compatibility**: Podman aims to be a drop-in replacement for Docker, and its CLI commands closely mirror Docker's. However, there might be some minor differences, so it is essential to consult the respective documentation when transitioning from one platform to another.
4. **Container Orchestration**: Docker has native support for Docker Swarm, a container orchestration platform. Podman, on the other hand, does not have built-in orchestration support but can work with Kubernetes through the CRI-O runtime.
5. **Image Storage**: Docker uses a centralized image storage mechanism, while Podman employs a distributed approach. This allows Podman to isolate image storage for different users, enhancing security and preventing potential conflicts.
6. **API Compatibility**: Docker has a well-documented REST API for interacting with the Docker daemon. Podman, being daemonless, does not provide a native REST API. However, Podman can be configured to support the Docker API through the podman-docker package or the Podman API service.
7. **Community and Support**: Docker has a larger community and more extensive commercial support, owing to its longer history and widespread adoption. Podman is a newer project with a growing community, primarily supported by Red Hat.

In summary, Docker and Podman are both powerful containerization tools, but they differ in their architecture, security features, and some aspects of their functionality. Podman is an appealing alternative for those who prioritize rootless container management and a daemonless architecture, while Docker remains popular for its extensive community, support, and integration with Docker Swarm.

### Podman deployment/configuration

#### Update system

```bash
sudo apt update && sudo apt upgrade -y && sudo apt autoremove -y
```

#### Required packages

```bash
sudo apt install entr jq make git ufw podman podman-docker docker-compose
```

#### Create Dyson node user

```bash
sudo adduser dyson
```

Once dedicated user is created access system using `dyson` user to continue deployment.

#### Enable and start podman.socket as a user

```bash
systemctl --user enable podman.socket
systemctl --user start podman.socket
systemctl --user status podman.socket
export DOCKER_HOST=unix:///run/user/$UID/podman/podman.sock
```

**NOTE:** Commands `su - <user>` or `sudo -u <user>` do not preserve environment variables like `$DBUS_SESSION_BUS_ADDRESS` and `$XDG_RUNTIME_DIR`. It is required to use ssh to login as **dyson** user to have environmental variables set correctly for Podman: `ssh <user>@localhost`

#### Prevent containers termination at logoff

By default container started in user environment will be terminated once user will log off. To avoid that enable linger state `loginctl enable-linger dyson`.

### Build Dyson Protocol components

#### Node installation

```
git clone --recurse-submodules https://gitlab.com/dysonproject/dyson-deploy.git
cd dyson-deploy
```

#### Configurartion adjustments

To build and run containers we will use `docker-compose`. As Podman does not support `docker compose` syntax it is required to adju **Changes to `Makefile`**

* replace `docker compose` with `docker-compose`

**Changes to `scripts/start.sh`**

* replace `docker compose` with `docker-compose`

**Changes to `docker-compose.yml`**

* replace `links` with `depends_on`
* change `443:443` to `8443:443`
* change `80:80` to `8080:80`

```
$ make reset # if you had already joined the testnet
$ make testnet # prepare .env file for testnet deployment
```

#### Run containers

```bash
TAG=v0.1.1 docker-compose up -d
```

That will run containers

### Managing Dyson Protocol components

#### Check container status

```bash
docker container logs --tail=100 --follow=true dyson-deploy_chain_1
```

#### Accessing the `dysond` service

Use `docker compose exec chain bash` to enter the running container. (Ignore the warnings about blank env vars) On the host computer enter the running container

```
$ docker-compose exec chain bash
```


