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-connectionjournalctl -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, который очень помог в написании данного гайда