Генерация случайного начального значения блока
Эта страница переведена сообществом на русский язык, но нуждается в улучшениях. Если вы хотите принять участие в переводе свяжитесь с @alexgton.
Эта информация актуальна на момент написания статьи. Она может измениться при любом обновлении сети.
Время от времени на TON создается лотерейный контракт. Обычно в нем используется небезопасный способ обработки случайности, так что сгенерированные значения могут быть предсказаны пользователем, и лотерея может быть сведена на нет.
Но эксплуатация слабых мест в генерации случайных чисел часто предполагает использование прокси-контракта, который пересылает сообщение, если случайное значение верно. Существуют предложения по контрактам кошельков, которые смогут выполнять произвольный код (указанный и подписанный пользователем, разумеется) onchain, но большинство популярных версий кошельков не поддерживают такую возможность. Так что, если лотерея проверяет участие игрока через контракт кошелька, является ли это безопасным?
Или этот вопрос можно сформулировать следующим образом. Можно ли включить внешнее сообщение в блок, в котором случайное значение будет точно таким, как нужно отправителю?
Конечно, отправитель никак не влияет на случайность. Но валидаторы, генерирующие блоки и включающие предложенные внешние сообщения, влияют.
Как валидаторы влияют на начальное значение
Об этом не так много информации даже в whitepapers, поэтому большинство разработчиков оказываются в затруднении. Вот единственное упоминание о случайности блока в TON Whitepaper:
Алгоритм, используемый для выбора групп задач валидаторов для каждого шарда (w, s), является детерминированным псевдослучайным. Он использует псевдослучайные числа, внедренные валидаторами в каждый блок мастерчейна (сгенерированные в результате консенсуса с использованием пороговых подписей), для создания случайного начального значения, а затем вычисляет, например, Hash(code(w). code(s).validator_id.rand_seed) для каждого валидатора.
Однако единственная вещь, которая гарантированно правдива и актуальна, - это код. Итак, давайте посмотрим на collator.cpp:
{
// generate rand seed
prng::rand_gen().strong_rand_bytes(rand_seed->data(), 32);
LOG(DEBUG) << "block random seed set to " << rand_seed->to_hex();
}
Это код, который генерирует случайное начальное значение для блока. Он находится в коде коллатора, потому что он необходим стороне, генерирующей блоки (и не требуется для lite-валидаторов).
Итак, как мы видим, начальные значения генерируются блоком с помощью одного валидатора или коллатора. Следующий вопрос: