Падение VIZ из-за clear-votes-before-block

Я отлично распланировал "отдохнуть" в пятницу, взяться за несколько постов и побыть дома, помочь супруге. Нет, так просто НЕ МОГЛО БЫТЬ :D В пятницу случилась интересная ситуация в VIZ.

Делегаты, вдруг, ушли в лес по левой цепочке.

Проблема обнаружилась Максимом, он первый среагировал, что нода ругается на непонятный блок. Я тут же подключился к своей сид ноде проверить в чем дело. Проблема была в блоке 354393, где возникала ошибка itr->vote_percent != o.weight: You have already voted in a similar way. Ссылка на код: https://github.com/VIZ-World/viz-world/blob/mainnet-dev/libraries/chain/chain_evaluator.cpp#L974-L975

Кто-то проголосовал так же, как уже голосовал (процент голосования не был изменен). И если моя нода и Максима тут же сообщили об ошибке, то большинство делегатов ушло вперед с невалидным блоком.

Пришлось долго искать в чем дело и, наконец, сверив настройки в config.ini — мы нашли расхождение.

У меня и у Максима стоял clear-votes-before-block = 0, а у большинства делегатов конфиг дублировал доставшийся в наследство от Голоса clear-votes-before-block = 4294967295.

Несмотря на расхождении во мнениях всех рассудил код. Блокчейн нода во время выплаты за контент смотрит наличие clear-votes-before-block и больше ли он чем текущий номер блока. Если больше, то все голоса за контент удаляются из базы данных.

Несмотря на то, что в VIZ существует механика голосовать за посты ПОСЛЕ выплаты, это никак не должно было коснуться цепочку. Если бы ни одно но.

В коде есть строки https://github.com/VIZ-World/viz-world/blob/mainnet-dev/libraries/chain/chain_evaluator.cpp#L877-L884 отвечающие за "ленивое" удаление голоса из базы. Если такой голос уже там был и он остался после выплаты (о чем говорит проверка itr->num_changes == -1). Там же стоит проверка, что если нода делегатская (_db.is_producing), то не позволять проходить такой операции. Получается что этот кусок кода вообще никогда не выполнится :) Ведь chain_evaluator срабатывает на всех нодах по подтвержденным блокам от делегатов!

Ошибка оказалась в другом месте — а именно: https://github.com/VIZ-World/viz-world/blob/mainnet-dev/libraries/chain/database.cpp#L2166-L2174

Данный метод cashout_content_helper вызывается для всех постов. Метод, который должен отработать при достижении времени выплаты у контента. И именно тут находится странная ошибка в логике:

Если время выплаты наступило (не равно -1), то каждое голосование как элемент становится неизменяемым -1 (num_changes работает не только как количество изменений голоса, но и -1 как статус для невозможности изменения).

А если не наступило, то там как раз и происходит проверка _clear_votes_block > head_block_num(), после чего все голосования удаляются из базы данных.

Именно поэтому все ноды с установленным параметром clear-votes-before-block = 4294967295 в файле настроек удалили голоса. К таким нодам отнеслись и распространенная на данный момент паблик нода и большинство делегатских. Которые посчитали, что голоса не существует (так как он был удален) и создали его вновь.

На данный момент проблема частично решена. Часть делегатов исправила ошибку и вернулась к правильной цепи. К ним постепенно подключаются другие делегаты. Ошибка с clear-votes-before-block в теории касается и цепочки Голос. Если большинство делегатов поставили рекомендуемый конфиг https://github.com/GolosChain/golos/blob/master/share/golosd/config/config_witness.ini#L71 то у них потенциальна возможна та же самая ситуация. Сейчас от этой ошибки защищают публичные ноды, которые, скорее всего, в конфиге держат clear-votes-before-block = 0, но любой злоумышленник может аналогичным образом нанести урон блокчейну Голос. Я рекомендую обновить данный параметр в конфиге делегатам как VIZ, так и Голос как можно скорее. И если для VIZ эта проблема уже решается сейчас, то Голосу необходимо время для того чтобы среагировать и закрыть дыру с повторным созданием голоса с аналогичным процентом силы.

vizголосошибкабаг
61
14.962 GOLOS
0
В избранное
Анатолий Пискунов
web-developer
61
0
Комментарии (5)
Сортировать по:
Сначала старые
Зарегистрируйтесь, чтобы проголосовать за пост или написать комментарий
Авторы получают вознаграждение, когда пользователи голосуют за их посты. Голосующие читатели также получают вознаграждение за свои голоса.