IBC через Hermes
Hermes это ретранслятор (relayer) межсетевых сетей Cosmos, построенный на Rust. Простыми словами это протокол связи между блокчейнами. Ретранслятор является центральным элементом в сетевой архитектуре IBC и обеспечивает извелечение и сбор информации от сетей (блокчейнов) которые не могут напрямую отправлять сообщения друг другу. Подробнее о Hermes можно почитать здесь
Hermes является не единственной реализацией cosmos ретрансляторов, к примеру еще есть, ibc-go и ts-relayer, но именно Hermes завоевал популярность и является выбором большинства нодраннеров
В данном гайде будет настроен relayer между сетями Stride и Gaia, но можно использовать любые поддерживаемые сети. Команда Stride предложила не создавать отдельные каналы, а поддержать эти:
Команда Stride рекомендует подключать каналы ниже
Active STRIDE <> GAIA Channels:
CHANNEL_ID | PORT_ID -----------+------------------------------- channel-0 | transfer channel-1 | icacontroller-GAIA.DELEGATION channel-2 | icacontroller-GAIA.FEE channel-3 | icacontroller-GAIA.WITHDRAWAL channel-4 | icacontroller-GAIA.REDEMPTION
Подготовка
Любой ретранслятор можно установить как на 1 сервер вместе с необходимыми нодами, так и на отдельный сервер, при этом даже не обязательно поднимать собственные ноды, а достаточно знать открытые RPC рабочих нод. Но, поскольку успех ретрансляции сильно зависит от задержки и скорости ввода-вывода, то в настоящее время рекомендуется обслуживать узлы на том же компьютере, что и процесс ретрансляции
Поскольку процесс ретрансляции должен иметь возможность запрашивать сеть обратно по высоте в течение как минимум 2/3 unbonding period (trusting period = 2/3 от unbonding period), то рекомендуется использовать настройки прунинга, которые сохранят полное состояние цепочки в течение более длительного периода времени, чем период unbonding
То есть 14 дней от 21 или 10 дней от 14 или 1,3 дня от 2 дней
Необходимый прунинг можно посчитать по формуле 14 дней*24*60*60/ среднее время блока
- Для 14 дней pruning-keep-recent = 200000
- Для 10 дней pruning-keep-recent = 150000
- Для 1,3 дня pruning-keep-recent = 18720
- Для 1,5 часа pruning-keep-recent = 1000
Polkachu к примеру для relayer использует 40000/2000
В данном примере мы будем использовать 1 сервер, на котором установим как сами ноды, так и Hermes
- установить две необходимые ноды и полностью синхронизировать их. В данном примере устанавливаем Stride и Gaia
- minimum-gas-prices на нодах настраиваем на 0 (minimum-gas-prices = "0uatom" / minimum-gas-prices = "0ustrd")
- RPC должны быть открыты и доступны Hermes (как это сделать можно узнать здесь)
- индексация должна быть настроена в положение indexer = "kv"
(если, не меняли, то пропускаем этот пункт)
- проверить наличие токенов на кошельках. Лучше всего использовать одну и ту же мнемонику во всех сетях, не используйте свои адреса ретрансляции ни для чего другого, потому что это может привести к ошибкам в последовательности несогласованных учетных записей
- после этого желательно проверить поддерживается ли данными нодами сама ретрансляция
strided q ibc-transfer params # receive_enabled: true # send_enabled: true gaiad q ibc-transfer params # receive_enabled: true # send_enabled: true
Установка Hermes
mkdir -p $HOME/.hermes/bin wget https://github.com/informalsystems/ibc-rs/releases/download/v1.0.0-rc.1/hermes-v1.0.0-rc.1-x86_64-unknown-linux-gnu.tar.gz && \ tar -C $HOME/.hermes/bin/ -vxzf hermes-v1.0.0-rc.1-x86_64-unknown-linux-gnu.tar.gz && \ echo 'export PATH="$HOME/.hermes/bin:$PATH"' >> $HOME/.bash_profile && \ source $HOME/.bash_profile # проверяем версию hermes version # hermes 1.0.0-rc.1+54ae389
Настройка Hermes
Для начала задаем переменные. RPC_ADDR берем из config.toml - GRPC_ADDR берем из app.toml. Значение 127.0.0.1 заменяем на IP адрес сервера в случае установки Hermes отдельно от нод. Данные ниже даны для примера!!!
CHAIN_ID_1="STRIDE-TESTNET-4" RPC_ADDR_1="127.0.0.1:26657" GRPC_ADDR_1="127.0.0.1:9090" ACCOUNT_PREFIX_1="stride" TRUSTING_PERIOD_1="8hours" DENOM_1="ustrd" MNEMONIC_1="way festival bargain mass swear flat fish help dinosaur delay lemon dry another fiber belt year smoke glimpse extra fancy acquire method help universe" MEMO="lesnik_utsa#4480"
CHAIN_ID_2="GAIA" RPC_ADDR_2="127.0.0.1:36657" GRPC_ADDR_2="127.0.0.1:9190" ACCOUNT_PREFIX_2="cosmos" TRUSTING_PERIOD_2="8hours" DENOM_2="uatom" MNEMONIC_2="way festival bargain mass swear flat fish help dinosaur delay lemon dry another fiber belt year smoke glimpse extra fancy acquire method help universe"
В данном файле будут использоваться переменные указанные выше. За более детальной информацией по config с описанием переходим сюда
sudo tee $HOME/.hermes/config.toml > /dev/null <<EOF [global] # укажите уровень детализации вывода журнала ретранслятора Default: 'info' # допустимые варианты 'error','warn','info','debug','trace' log_level = 'info' [mode] [mode.clients] enabled = true refresh = true misbehaviour = true [mode.connections] enabled = false [mode.channels] enabled = false [mode.packets] enabled = true clear_interval = 100 clear_on_start = true tx_confirmation = true [rest] # Следует ли включать службу REST или нет. Значение по умолчанию: false enabled = true host = '0.0.0.0' port = 3000 [telemetry] # Следует ли включать службу телеметрии или нет. Значение по умолчанию: false enabled = true host = '0.0.0.0' port = 3001 [[chains]] ### CHAIN_A ### id = '${CHAIN_ID_1}' rpc_addr = 'http://${RPC_ADDR_1}' grpc_addr = 'http://${GRPC_ADDR_1}' websocket_addr = 'ws://${RPC_ADDR_1}/websocket' rpc_timeout = '10s' account_prefix = '${ACCOUNT_PREFIX_1}' key_name = 'wallet' address_type = { derivation = 'cosmos' } store_prefix = 'ibc' default_gas = 100000 max_gas = 2500000 gas_price = { price = 0.001, denom = '${DENOM_1}' } gas_multiplier = 1.1 max_msg_num = 30 max_tx_size = 2097152 clock_drift = '5s' max_block_time = '30s' trusting_period = '${TRUSTING_PERIOD_1}' trust_threshold = { numerator = '1', denominator = '3' } memo_prefix = '${MEMO} Relayer' [chains.packet_filter] policy = 'allow' list = [ ['transfer', 'channel-0'], ] [[chains]] ### CHAIN_2 ### id = '${CHAIN_ID_2}' rpc_addr = 'http://${RPC_ADDR_2}' grpc_addr = 'http://${GRPC_ADDR_2}' websocket_addr = 'ws://${RPC_ADDR_2}/websocket' rpc_timeout = '10s' account_prefix = '${ACCOUNT_PREFIX_2}' key_name = 'wallet' address_type = { derivation = 'cosmos' } store_prefix = 'ibc' default_gas = 100000 max_gas = 2500000 gas_price = { price = 0.001, denom = '${DENOM_2}' } gas_multiplier = 1.1 max_msg_num = 30 max_tx_size = 2097152 clock_drift = '5s' max_block_time = '30s' trusting_period = '${TRUSTING_PERIOD_2}' trust_threshold = { numerator = '1', denominator = '3' } memo_prefix = '${MEMO} Relayer' [chains.packet_filter] policy = 'allow' list = [ ['transfer', 'channel-0'], ] EOF
Хочу отдельно обратить внимание на config и его часть [chains.packet_filter]
Если не прописывать совсем эти параметры, то ретранслятор будет использовать все доступные каналы
[chains.packet_filter] policy = 'allow' list = [ ['ica*', '*'], # разрешить ретрансляцию по всем каналам, порт которых начинается с ica ['transfer', 'channel-0'], ]
[chains.packet_filter] policy = 'allow' list = [ ['transfer', 'channel-0'],# gaia ['icahost', 'channel-4'], ['icahost', 'channel-1'], ['icahost', 'channel-2'], ['icahost', 'channel-3'], ]
[chains.packet_filter] policy = 'allow' list = [ ['transfer', 'channel-0'], ]
Проверяем правильность конфигурации
hermes config validate # Success: "configuration is valid" hermes health-check # INFO ThreadId(01) using default configuration from '/root/.hermes/config.toml' # INFO ThreadId(01) [STRIDE-TESTNET-2] performing health check... # INFO ThreadId(01) chain is healthy chain=STRIDE-TESTNET-2 # INFO ThreadId(01) [GAIA] performing health check... # INFO ThreadId(01) chain is healthy chain=GAIA # SUCCESS performed health check for all chains in the config
Добавляем кошельки в Hermes. За подробной информацией обращаемся сюда
# создаем файлы с мнемноникой sudo tee $HOME/.hermes/${CHAIN_ID_1}.mnemonic > /dev/null <<EOF ${MNEMONIC_1} EOF sudo tee $HOME/.hermes/${CHAIN_ID_2}.mnemonic > /dev/null <<EOF ${MNEMONIC_2} EOF # восстанавливаем кошельки hermes keys add --chain ${CHAIN_ID_1} --mnemonic-file $HOME/.hermes/${CHAIN_ID_1}.mnemonic hermes keys add --chain ${CHAIN_ID_2} --mnemonic-file $HOME/.hermes/${CHAIN_ID_2}.mnemonic # Success: Restore key testkey ([ADDRESS]) on [CHAIN ID] chain # Success: Restore key testkey ([ADDRESS]) on [CHAIN ID] chain # посмотреть кошельки hermes keys list --chain ${CHAIN_ID_1} hermes keys list --chain ${CHAIN_ID_2} # посмотреть баланс hermes keys balance --chain ${CHAIN_ID_1} hermes keys balance --chain ${CHAIN_ID_2}
sudo tee /etc/systemd/system/hermesd.service > /dev/null <<EOF [Unit] Description=hermes After=network-online.target [Service] User=$USER ExecStart=$(which hermes) start Restart=on-failure RestartSec=3 LimitNOFILE=65535 [Install] WantedBy=multi-user.target EOF
sudo systemctl daemon-reload sudo systemctl enable hermesd sudo systemctl restart hermesd && journalctl -u hermesd -f -o cat
Если все прошло успешно, то видим примерно такое
2022-07-31T14:38:30.273575Z INFO ThreadId(01) Scanned chains: 2022-07-31T14:38:30.273579Z INFO ThreadId(01) # Chain: STRIDE-TESTNET-2 - Client: 07-tendermint-0 * Connection: connection-0 | State: OPEN | Counterparty state: OPEN + Channel: channel-0 | Port: transfer | State: OPEN | Counterparty: channel-0 # Chain: GAIA - Client: 07-tendermint-0 * Connection: connection-0 | State: OPEN | Counterparty state: OPEN + Channel: channel-0 | Port: transfer | State: OPEN | Counterparty: channel-0 2022-07-31T14:38:30.273595Z INFO ThreadId(01) connection is Open, state on destination chain is Open chain=STRIDE-TESTNET-2 connection=connection-0 counterparty_chain=GAIA 2022-07-31T14:38:30.273600Z INFO ThreadId(01) connection is already open, not spawning Connection worker chain=STRIDE-TESTNET-2 connection=connection-0 2022-07-31T14:38:30.273606Z INFO ThreadId(01) no connection workers were spawn chain=STRIDE-TESTNET-2 connection=connection-0 2022-07-31T14:38:30.273611Z INFO ThreadId(01) channel is OPEN, state on destination chain is OPEN chain=STRIDE-TESTNET-2 counterparty_chain=GAIA channel=channel-0 2022-07-31T14:38:30.276438Z INFO ThreadId(01) spawned client worker: client::GAIA->STRIDE-TESTNET-2:07-tendermint-0 2022-07-31T14:38:30.278403Z INFO ThreadId(01) spawned packet worker: packet::channel-0/transfer:STRIDE-TESTNET-2->GAIA 2022-07-31T14:38:30.278430Z INFO ThreadId(01) done spawning channel workers chain=STRIDE-TESTNET-2 channel=channel-0 2022-07-31T14:38:30.278484Z INFO ThreadId(01) spawning Wallet worker: wallet::STRIDE-TESTNET-2 2022-07-31T14:38:30.278501Z INFO ThreadId(01) connection is Open, state on destination chain is Open chain=GAIA connection=connection-0 counterparty_chain=STRIDE-TESTNET-2 2022-07-31T14:38:30.278506Z INFO ThreadId(01) connection is already open, not spawning Connection worker chain=GAIA connection=connection-0 2022-07-31T14:38:30.278510Z INFO ThreadId(01) no connection workers were spawn chain=GAIA connection=connection-0 2022-07-31T14:38:30.278513Z INFO ThreadId(01) channel is OPEN, state on destination chain is OPEN chain=GAIA counterparty_chain=STRIDE-TESTNET-2 channel=channel-0 2022-07-31T14:38:30.283017Z INFO ThreadId(01) spawned client worker: client::STRIDE-TESTNET-2->GAIA:07-tendermint-0 2022-07-31T14:38:30.286036Z INFO ThreadId(01) done spawning channel workers chain=GAIA channel=channel-0 2022-07-31T14:38:30.286132Z INFO ThreadId(01) spawning Wallet worker: wallet::GAIA 2022-07-31T14:38:30.290684Z INFO ThreadId(01) Hermes has started
Дальше должны пойти подобные логи с хешами транзакций и баланс кошельков должен начать уменьшаться. Транзакции также можно проверить в explorer. Если есть такие логи, значит все настроено и работает
Полезные команды
hermes create channel --a-chain ${CHAIN_ID_1} --b-chain ${CHAIN_ID_2} --a-port transfer --b-port transfer --order unordered --new-client-connection
journalctl -u hermesd -f -o cat journalctl -fn 100 -u hermesd | grep "Ok" journalctl -u hermesd | grep "Ok"
strided tx ibc-transfer transfer transfer channel-0 <cosmos1fzhv> 500ustrd --from <name_stride_wallet> --fees 500ustrd -y gaiad tx ibc-transfer transfer transfer channel-0 <stride1fz> 500uatom --from <name_gaia_wallet> --fees 500uatom -y # примеры # strided tx ibc-transfer transfer transfer channel-0 cosmos1fzhv743ve4nw99lqwr9f8x4vkngp7v5ma008df 100000ibc/27394FB092D2ECCD56123C74F36E4C1F926001CEADA9CA97EA622B25F41E5EB2 --from wallet -y # strided tx ibc-transfer transfer transfer channel-0 cosmos1fzhv743ve4nw99lqwr9f8x4vkngp7v5ma008df 100000ustrd --from wallet --fees 500ustrd -y
# команда просмотра порта RPC echo $(grep -A 3 "\[rpc\]" ~/.sei/config/config.toml | egrep -o ":[0-9]+")
systemctl stop hermesd && \ systemctl disable hermesd && \ rm /etc/systemd/system/hermesd.service && \ systemctl daemon-reload && \ cd $HOME && \ rm -rf .hermes && \ rm -rf $(which hermesd)
Выражаю благодарность: за гайд от kj89, который очень помог в написании данного гайда