Сетапим массово ноды Elixir
Канал в тг: https://t.me/PastFinCoding
Предисловие
Результативности от моего решения пока нет, потому что то дашборд лагает, то сервера падают из-за перегруза. Хочу просто поделиться тем, какую работу проделал, а выводы будут сделаны потом.
- Сейчас у меня работает 110 нод. То есть 110 кошельков валидаторов и 110 кошельков делегаторов, суммарно 220 кошельков задействовано. Есть несколько опций:
- Серверы на мою последнюю не регнутую карту:
Концепция
Ноды проектов работают следующим образом:
- Есть минимальные требования к серверу
- Один сервер - одна нода
- Когда появляется работа, ваша нода случайным образом может попасть в пул воркеров. Соответственно, чем больше у вас нод, тем выше попасть в пул воркеров и заработать награду.
- В тестнетах обычно меньше нагрузка и могут выдать бейс дроп, даже если ваша нода не так много решила задач.
Моя задача заключалась в том, чтобы автоматизированным путем засетапить большое количество нод, не переходя к сильному ручному труду.
UPD: все равно приходится много вещей контролировать и долго писал код.
Верхнеуровнево логика моего кода следующая:
- Сетаплю сервер
- Устанавливаю на него Docker
- Создаю на нем Docker файл, в image которого прописано, чтобы контейнер содержал Docker. То есть концепция докер в докере.
- Внутри контейнера с докером я ставлю контейнер с нодой, которая не знает про существование других контейнеров.
Таким образом получается запустить сразу много нод внутри одного сервера.
Проблематика
- Когда внутри одного сервера запускается сразу множество нод, достаточно сложно посчитать оптимальную нагрузку, чтобы сервер не отрубился или не выдавал низкий uptime на Elixir. Всё проходится экспериментальным путем, но пересетапливать достаточно сложно. Если сервер перегружается, то это нарушает работу других нод. То есть условно при условии, когда у вас одновременно начнет работать n нод, то ваш сервер отлетит. Как это вычислить? Я вообще не представляю.
- Сайт Elixir я не понимаю как рассчитывает награды, потому что админы пишут, что это экспериментальный не конечный подсчет, хотя на моих на всех нодах ноль наград, но в чате я видел, что людям дают.
- Когда выходит новая версия ноды, приходится их всех перезапускать, это долго.
- Требуется неплохое знание программирования, чтобы самому такую логику построить.
Погружаемся в задачу
Сторона делегатора
- На кошельке делегатора должен лежать Sepoila ETH.
- Нужно зайти на сайт элексира, заминтить $MOCK (внутренний токен для делегация, PoS логика).
- Выбрать валидатора, то есть привязать кошелек ноды.
- Застейкать заминченный $MOCK, чтобы передать валидатору.
Для того, чтобы на кошельке делегатора появился Sepoila ETH я придумал следующую схему:
- Я создаю большое количество пустых кошельков
- Я распределяю кошельки как:
- Я наливаю Sepoila ETH через все возможные краны на один кошелек, это достаточно сложная задача. При этом кошелек я создал пустой и перевел на него 10$ ETH, потому что иначе сайты не дадут налить. После агрегации на одном кошельке Sepoila ETH, я последовательно перевожу с одного кошелька на Level 1 (на 110 кошельков в моем случае), далее на Level 2, далее на Level 3, далее на Final. Соответственно при повторной транзакции у меня в таблице все зафиксировано, то есть путь будет всегда одинаковый у раскида Sepoila ETH. Я это делаю для безопасности от бана по сибилу, хотя может тупо выглядеть, однако мне показало норм идеей. Лучше, чем с одного кошелька раскидывать на 110 пустых кошельков. Еще раз: первый кошелек из ряда Level 1 переводит средства первому кошельку из ряда Level 2, и так до Final. По итогу кошельки между собой никак не пересекаются.
Что касается интерактива с сайтом Elixir:
- С самим сайтом я никак не взаимодействую, я украл только код транзакций, которые надо отправлять в блокчейн. Было не так сложно, однако не с первого раза.
- Можно минтить за один раз только 1000 $MOCK, но я написал логику, которая циклом может минтить большое количество и необязательно делать это сразу в первый раз. Можно через неделю еще наминтить и делегировать.
- В дискорде писали, что количество MOCK не сильно влияет на выбор ноды и там применена логика нормализации. Но я знаю че такое нормализация, поэтому вес все равно имеет. Я бы сказал что 50-60к MOCK достаточно.
- Адекватно чтобы код работал и подписывал транзы только ночью. Нормальный gwei в сети Sepoila ETH ~0.3 gwei.
Сторона валидатора
Всё написано в разборке кода про валидатора, основная сложность найти баланс между потреблением ноды и сервера.
Разборка кода
Делегатор
Распределение кошельков
Изначально у вас должен быть Excel файлик с двумя колонками: public_key, private_key. Назовите его как "original_wallets.xlsx". Из этого файлика мы и будем генерить сплит.
Если вам надо 100 нод, то в файле должно быть 500 кошельков.
Также для следующего этапа в файле "original_wallets.xlsx" должен быть кошелек для агрегации Sepoila ETH, который не попадет в распределение. Сделайте не n кошельков, а n + 1, последним кошель агрегатор. Потому что в следующем этапе криво код написан и лень исправлять.
Вот здесь указывать сколько у вас в конечном итоге будет нод.
Код для разбивки кошельков: https://gist.github.com/Pastfin/ade7958193b442f3f8ff0ca0198c83ac
Наливаем Sepoila ETH на первый кошелек агрегатор
- https://cloud.google.com/application/web3/faucet/ethereum/sepolia
- https://www.alchemy.com/faucets/ethereum-sepolia
- https://faucets.chain.link/sepolia
- https://getblock.io/faucet/eth-sepolia/
Регаемся там и наливаем, на кошельке должно быть хотя бы 10$ в ETH, лучше 20$ в ETH сразу кинуть.
Раскид с первого кошелька до Final
Теперь задача в том, чтобы докинуть Sepoila до Final. Я советую, чтобы на конечном кошельке было хотя бы 0.01 ETH. Сами посчитаете сколько надо налить на ваше количество нод. Учитывайте газ.
Код для раскида: https://gist.github.com/Pastfin/dff526b1afe1d2ab33571175a616eb81
Вот тут выставляется сколько вы хотите отправлять на каждый кошель.
Раскид происходит долго, но думаю, что код можно улучшить.
Взаимодействие с контрактом для минтинга и делегации
- Минтинг, выставляется рендж сколько вы хотите. Если много Sepoila ETH, то ставьте 40-50, если мало, то 3-5 тоже норм, потом дольете (строка в коде 172).
- approve_mock_for_staking
- stake
- is_already_delegated проверка. Это чтобы потом доливать стейкинг
- delegate если в 4 пункте False.
Код: https://gist.github.com/Pastfin/f8f6b154416c897a4c7d777a385bb5bb
После выполнения кода работа со стороны валидатора окончена.
Валидатор
Настройка серверов
Вот такие сервера я беру на Digital Ocean:
Для работы с серверами я использую VSC и расширение Remote Explorer, удобнее ничего не существует. После добавления и подключения прописываем следующие команды:
sudo apt update sudo apt-get install ca-certificates curl sudo install -m 0755 -d /etc/apt/keyrings sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc sudo chmod a+r /etc/apt/keyrings/docker.asc echo \ "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu \ $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \ sudo tee /etc/apt/sources.list.d/docker.list > /dev/null sudo apt-get update sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin sudo apt install python3 python3-venv python3-pip python3 -m venv myenv source myenv/bin/activate pip install pandas pip install openpyxl
Во время установки на все соглашаемся. Выполнять команды последовательно построчно. Это установка докера + установка питона с созданием окружающей среды.
Далее обычно через VSC я переношу на сервер целую папку под названием elixir, которая состоит из следующих файлов:
- env_files папка, про нее немного позже
- Dockerfile
- enf_file_generator.py
- run_dockers.py
- wallets_splitted.xlsx
Начнем с питоновских скриптов:
enf_file_generator.py - необходим для того, чтобы создавать в папку env_files файлы, которые позволяют ноде Элексира получать информацию про валидатора и бенефициара. То есть в этом файле указывается публичный ключ бенефециара от фарма, приватный ключ валидатора и никнейм валидатора, генерируется у меня в коде автоматически
Все файлы создаются автоматически и потом автоматически переносятся в контейнер, пример файла:
Код enf_file_generator.py: https://gist.github.com/Pastfin/4006df549d287a450e4db5a3a060f062
В 49 строке необходимо указать количество сколько у вас кошельков, чтобы сгенерировать нужное количество файлов.
run_dockers.py - необходим для запуска последовательно контейнеров. Важно контролировать в 84 строке сколько нод вы запускаете. Например, если первые 20 и это ваш первый сервер, то for x in range(20). Если это второй сервер, то for x in range(20, 40). Файл wallets_splitted.xlsx должен быть статичен на всех серверах, чтобы не сбить последовательность.
Код run_dockers.py: https://gist.github.com/Pastfin/51a12b3679c1a75b778afd65837ee708
Теперь перейдем к Dockerfile, вот код: https://gist.github.com/Pastfin/63b182361c2d8f129d6953064a497b42
Этот докерфайл позволяет создавать докер в докере.
После того, как мы создали и заполнили папку всем необходим, должно получиться так:
Все, после этого контейнеры сами начнут создаваться, где автоматически будет устанавливаться нода Элексира и сразу подключаться валидатор. Спустя 5 мин вы сможете увидеть в дашборде результат.
Если вы перегрузите сервер, то он перестанет заходить и вам заблочат акк на Digital Ocean. 20 нод - норма (но еще тестирую).
Всякие последние команды на последок
docker stop $(docker ps -q) docker rm $(docker ps -a -q) docker rmi $(docker images -q) --force docker volume prune -f docker network prune -f docker system prune -a --volumes -f
Проверка ssd памяти на серваке:
df -h
Проверка потребления ресурсов на серваке:
htop
docker ps docker exec -it {container_id or container_name} /bin/bash docker elixir logs -f