Horcrux.
С чем его едят?

Или разворачиваем валидатора тестнета HAQQ в кластере.

Салют!

Поскольку это моя первая статься/гайд на тематику развертывания нод, критика не принимается :D
На днях, коллега по цеху выкатил статью о развертывании нод по средствам kubernetes (в каком-то смысле - дублирование онных). После кучи вопросов и последующего продолжительного ликбеза, пришел к скромному выводу: что ж, если вы уже "серьезный дядя" в мире мэйннетов, такой подход имеет место быть. Однако, у данной технологии высокий порог входа, так же есть свои + и - .
Данная дискуссия напомнила мне о давно возникавшем желании реализовать нативную кластеризацию валидатора. Чем мы сегодня и займемся =)
На испытательном полигоне выступят Horcrux (сервис защищенных многосторонних вычислений для подписания нод Tendermint) и проект Islamic Coin .

Данный материал так же требует определенного понимания что такое ноды, блокчейны и все такое по этой кухне. Предполагается, что читателем давно пройдена стадия "друг соседа сказал шо там кнопка <БАБЛО>", и уровень сознания со скилами, как минимум, "энтузиаст+"   =)

Собственно, чем полезен данный сервис? Horcrux - это "мультиподписант" для нод Tendermint, который позволяет:
а) поднять кластер из 2+n нод для лучшего High Availability, за счет отказоустойчивости (единственный минус - аренда всего этого 2+n хозяйства)
б) защитить ключ, за счет разбиения его на части (скомпрометировав одну из частей, жулик соснет тунца)
Можно настраивать порог количества частей ключа, имеющих силу подписи: 2 из 3, 3 из 5, 4 из 7. В подробности углубляться не буду. Для пытливых умов.
Короче говоря, это уже следующий уровень инфраструктуры валидатора. 

Прежде чем приступить к переносу действующего валидатора в кластер, я подготовил 3 синхронизированные ноды на разных серверах. Можно было бы, конечно, заморочиться с построением приватной сети, как то предлагает оф.документация:

img

однако, это тестнет, а у нас задача познакомиться с данной технологией. Соответственно, позволю себе, в каком-то смысле, пренебречь безопасностью и каждую часть подписанта подселю к своей ноде на сервер. В мэйннете, конечно же, лучше действовать по фен-шую.
На каждом сервере устанавливаем сам Horcrux (проверить релиз):

cd $HOME
git clone https://github.com/strangelove-ventures/horcrux
cd horcrux
make install

Создаем сервис:

tee /etc/systemd/system/horcrux.service > /dev/null <<EOF
[Unit]
Description=MPC Signer node
After=network.target
[Service]
Type=simple
User=root
ExecStart=$HOME/go/bin/horcrux cosigner start
Restart=always
RestartSec=3
LimitNOFILE=4096
[Install]
WantedBy=multi-user.target
EOF

systemctl daemon-reload
systemctl enable horcrux

Инициализируем конфигурацию на каждом сервере для своей же ноды. Для каждого сервера своя команда:

# подписант-1 будет коннектиться к ноде c ID-1
horcrux config init haqq_53211-1 "tcp://127.0.0.1:1234" -c -p "tcp://10.168.1.2:2222|2,tcp://10.168.1.3:2222|3" -l "tcp://10.168.1.1:2222" -t 2 --timeout 1500ms

# подписант-2 будет коннектиться к ноде c ID-2
horcrux config init haqq_53211-1 "tcp://127.0.0.1:1234" -c -p "tcp://10.168.1.1:2222|1,tcp://10.168.1.3:2222|3" -l "tcp://10.168.1.2:2222" -t 2 --timeout 1500ms

# подписант-3 будет коннектиться к ноде c ID-3
horcrux config init haqq_53211-1 "tcp://127.0.0.1:1234" -c -p "tcp://10.168.1.1:2222|1,tcp://10.168.1.2:2222|2" -l "tcp://10.168.1.3:2222" -t 2 --timeout 1500ms

На каждой ноде включаем приемник валидатора:

sed -i 's#priv_validator_laddr = ""#priv_validator_laddr = "tcp://127.0.0.1:1234"#g' $HOME/.haqqd/config/config.toml

systemctl restart haqqd && journalctl -u haqqd -f 

Далее с действующего валидатора ручками скачиваем priv_validator_key.json, заливаем в $HOME/.horcrux/ на любой из серверов (для удобства на 1) и режем на 3 части:

cd .horcrux
horcrux create-shares priv_validator_key.json 2 3

На выходе 3 части:

ls
priv_validator_key.json
private_share_1.json
private_share_2.json
private_share_3.json

Первую часть переименовываем в share.json и оставляем на месте в $HOME/.horcrux/ , остальные две части скачиваем себе на компьютер, так же переименовываем в share.json и заливаем на каждый сервер, в такой же каталог, в соответствии с ID. То есть сопоставляем:
private_share_1.json = ID-1 => $HOME/.horcrux/share.json
private_share_2.json = ID-2 => $HOME/.horcrux/share.json
private_share_3.json = ID-3 => $HOME/.horcrux/share.json
На будущее, внутри каждой части ключа, в конце контекста присутствует ID.

Далее самое интересное. Что бы валидатор не попал в тюрьму, делать надо все внимательно и не считать мух. И все же, будьте готовы в любой момент апнуть валидатора, если что-то пойдет по стекловате..
Стопаем действующего валидатора, открываем файл $HOME/.haqqd/data/priv_validator_state.json , в нем содержится информация о последней подписи действовашим валидатором:

{
"height": "361402",
"round": 0,
"step": 3,
"signature": "IEOS7EJ8C6ZZxwwXiGeMhoO8mwtgTiq6VPR/F1cpLZuz0ZvUZdsgQjTt0GniAIgosfEjC5izKw4Nvvs3ZIceAw==",
"signbytes": "6B080211BA8305000000000022480A205D4E1F722F53A3FD9E0D28639D7CE7B588338570EBA5C340687C30609C47BCA41224080112208283B6E16BEA46797F8AD4EE0ACE424AC7A4827202446B2D56E7F4438541B7BD2A0C08E4ACE28B0610CCD0AC830232066A756E6F2D31"
}

Копируем поля:

  "height": "361402",
  "round": 0,                       (значение этого поля оборачиваем в кавычки ! )
  "step": 3,

и вставляем на каждой подготовленной ноде в оба файла (что бы валидатор завелся с того же места)
$HOME/.horcrux/state/haqq_53211-1_priv_validator_state.json
$HOME/.horcrux/state/haqq_53211-1_share_sign_state.json

Должно получиться:

{
"height": "361402",
"round": "0",
"step": 3,
"ephemeral_public": null
}

Сохраняем и:

systemctl start horcrux && journalctl -u horcrux -f 

Поздравляю! Господа мамкины хацкеры, у вас лэвэл ап =)
Не забудьте настроить fw, что бы ноды по порту 2222 общались только друг с другом.
Повторюсь, этот гайд для ознакомления с технологией. Хотя, как по мне, он получился более юзерфрэндли, нежели оф.документация. Но для более детального погружения покурить её все же стоит.

За сим откланиваюсь. Всегда ваш...