Программирование генератора случайных чисел на Ethereum

image


При разработке смарт-контрактов на Ethereum обычно считается что полагаться на хеш блока как источник рандомности ненадежно, так как майнер может влиять на результат, подбирая хеш блока (см. Private Information and Randomness, How do you get a random number in a contract?)


Насколько в действительности велика возможность для майнера увеличить свои шансы на выигрыш в игре в которой нужно угадать хеш блока c определенным номером (или некое число производимое от хеша блока)?


Вероятность угадать случайное число в диапазоне от 0 до 9 составляет 1/10


Предположим, для простоты, что хеш блока это тоже число от 0 до 9.


То есть, предположим мы получаем число от 0 до 9 в зависимости от хеша блока, или другими словами приводим хеш блока к числу от 0 до 9.
Например так:


function blockHashToNumberFrom0to9(uint blockNumber) public view returns (uint){
    uint random_number = uint(block.blockhash(blockNumber))%10;
    return random_number;
    }


Предположим, я — майнер, обладающий такой вычислительной мощностью, что каждый 5й блок в сети майниться мной, т.е. мои шансы что я замайню следующий блок 2/10.
Например, один из крупнейших пулов (см.https://etherscan.io/stat/miner? range=1&blocktype=blocks), нашел способ всем участникам пула договориться об общей ставке в лото, и постараться влиять на результат. При этом конечно надо пренебречь возможными потерями дохода от майнинга.


Скажем я сделал ставку, и хочу повлиять на результат.


Если я просто замайню блок со случайным хешем, это не влияет на результат, но, предположим, я, вычислив первый возможный блок, его отвергаю, и майню следующие блоки пока не найду нужный. Каковы мои шансы что я найду два валидных блока с разными хешами быстрее чем остальная сеть замайнит блок (один) для этого номера блока?


Мои шансы найти два блока подряд: 2/10×2/10 = 4/100


Какие шансы что второй мой блок будет именно тем который мне нужен?


Рассуждаем следующим образом:


Шансы что выпадет такое же число 1/10×1/10 = 1/100


Шансы что выпадет другое число 1–1/100 = 99/100


Шансы что это число окажется тем которое нужно 99/100: 9 = 11/100


Шансы что эти события совпадут, то есть что я найду два блока подряд раньше чем остальная сеть найдет один и мой второй блок будет тем который мне нужен: 4/100×11/100 = 44/10000


Итого, сам подбирая блок, я увеличиваю свои шансы в игре на 44/10000:


0.1 + 0.0044 = 0.1044


Другими словами, мой шанс на выигрыш вместо 10% будет 10.44%


Шансы что я найду третий валидный блок раньше чем остальная сеть найдет один и этот блок окажется тем который мне нужен, и т.п. рассчитываются подобным же образом: мы добавляем шансы в которых вероятность отображается дробью числитель которой будет больше на единицы, а знаменатель больше на десятки, т.е. это в сумме не увеличит вероятность больше чем на 1/10000, иными словами при округлении до двух знаков после запятой, это будет то же самое число: ~ 10.44%
Для игрока майнящего каждый 10 блок в сети: ~ 10.11%


Однако мы исходили из того, что: «Мои шансы что я найду два валидных блока с разными хешами быстрее чем остальная сеть замайнит блок (один) для этого номера блока? 2/10×2/10 = 4/100» Это вероятность того что вообще будет найдено два блока подряд этим майнером. Вероятность того что это будет сделано быстрее чем остальная сеть найдет один — еще меньше.


Соответственно если результат задается не хешем одного блока, а скажем хешами некоторого количества последовательных блоков (скажем мы реализуем лото »5 из 36», где 36 двузначных цифр получаются из хешей 72 последовательных блоков), то возможность майнера повлиять на результат еще меньше. Таким образом если мы в качестве источника рандомности берем хеши нескольких последовательных блоков, шансы отдельно взятого майнера повлиять на результат, настолько малы, что в большинстве случаев ними можно пренебречь, даже есть речь идет о розыгрыше денежных (ETH) призов.


Интересно было бы мнение сообщества насколько корректно такое рассуждение.

© Habrahabr.ru