Pull to refresh

Comments 46

Выпавшее число вычисляется путём взятия остатка от деления результата SHA-3 на 37.

Это не самый правильный способ. Во-первых, множество возможных значений хэша обычно является степенью двойки, что не может делиться на 37. Так что некоторые остатки будут выпадать чуть-чуть чаще других. Разница совсем ничтожна, но как-то неэстетично. Во-вторых, доказать, что значения данного хэша перемешаны равномерно — очень нетривиальная задача. Хотя обычно по построению хэш-функции «хорошо» перемешивают.


Предлагаю универсальный способ генерации случайного результата. Пусть каждый заинтересованный участник (в данном случае это игрок и казино) сгенерируют любым способом число от 0 до 36 (рекомендуемый способ — посредством своего автономного ГСЧ, хотя это не обязательно), затем вычислит от него хэш заданной хэш-функцией и вышлет его организатору. Собранные хэши должны быть помещены в блокчейн, чтобы все их видели. Затем каждый участник высылает свое сгенерированное число, что тоже помещается в блокчейн, чтобы все могли проверить, что хеши были получены именно из этих чисел. Результатом объявляется сумма этих чисел по модулю 37. Нужно только немного побороться с теми, кто вышлет хэш, но зажмет свое исходное число, заблокировав тем самым всю процедуру. Но лекарство довольно очевидно.

Если разница о которой вы говорите — меньше 2.7%, то это не проблема для рассматриваемого казино, а лишь маленький бонус для игрока, который о ней знает. :)

Если я правильно понял описанный вами алгоритм, на каждое пари придётся совершить две транзакции: одна для хэшей, другая для сгенерированных чисел. Это, во первых, увеличит стоимость ставки (которая = стоимости жетонов + плата за транзакцию). А во вторых, из-за того что время генерации блока в хотя и бывает, в среднем 15 секунд, зачастую доходит полуминуты. А одна из самых частых жалоб на рассмотренную реализацию, как я понимаю — именно низкая скорость. Обычно ставка проходит за 30-60 секунд. Если ждать лишний блок — станет до 90 секунд, это многих раздражает.

Разумеется, там и близко нет 2.7%. Например, для 256-битного хэша нетрудно посчитать. Применяя теорему Ферма, имеем: 2^256 = 16 (mod 37). То есть каждый из остатков с 0 по 16 будет попадаться с вероятностью (x+1)/2^256, а каждый из оставшихся остатков — с вероятностью x/2^256, где x = ⌊2^256/37⌋. Итоговый дисбаланс (отношение вероятностей) составляет порядка 2^{-251}.


Да, действительно, нужно ждать две транзакции. Впрочем, вместо блокчейна можно использовать более слабые механизмы для публикации. Но, с другой стороны, в изначальном алгоритме зачем-то нужно ждать BlockDelay блоков, в то время как предлагаемые мной две транзакции вполне могут попасть в соседние блоки, то есть ждать даже меньше.

BlockDelay в настоящее время равен 1. Если бы он был равен нулю, то майнер мог бы вместо изменения nonce блока менять свою ставку, и с определённой долей вероятности мог бы не только получить вознаграждение за блок, но и выиграть в рулетку.
При этом ставка гарантированно будет рассчитана в BlockDelay блоке после её принятия.


С вашем-же предложением — как сервер, так и игрок могут не присылать свои числа довольно долго.
Кстати, если игрок не прислал число — ок, его ставка проигрывает. А если число не прислал сервер? А если он его не прислал не потому, что увидел ставку игрока и понял что проиграл, а потому что DDoS?

И ещё один важный момент. В рассмотренной реализации у казино нет никакого сервера, с автономным ГСЧ. Всё что доступно смарт-контракту это блокчейн. Сервер, на котором лежит UI игры, никак не участвует в процессе принятия ставок.

Попытался найти информацию о пригодности SHA-3 в качестве ГСЧ, её на удивление очень мало.
Из самого полезного: Statistical Analysis of Reduced Round Compression Functions of SHA-3 Second Round Candidates, Why not SHA-3?, Sponge-based pseudo-random number generators.
Насколько я понял, она считается вполне подходящей, а код типа r = sha3(blockash, nonce) % max — общепринятая практика.

Во-первых, есть общие соображения (по фон Нейману):


Кто пытается арифметическими методами генерировать случайные числа, тот, конечно, живет во грехе.

Во-вторых, даже хорошие криптографические решения опираются на сложную математику, убедиться в практической применимости данных методов весьма непросто.


А для данной реализации рулетки я даже придумал атаку. Нужно быть майнером и пытаться сгенерировать несколько валидных блоков, которые будут служить в качестве источника результата. Должно повезти дважды: (1) просто сгенерировать валидный блок, (2) найденный блок должен быть «хорошим», то есть дающим выигрыш ставке атакующего. Тогда остается только впихивать в сеть найденный хороший блок, и если повезет, (3) сеть выберет именно этот блок, и выигрыш будет в кармане. Если найдется «плохой» блок, то в сеть его вбрасывать не надо. Поскольку деятельность обычных майнеров — результат везения (1) и (3), то по затратам здесь атакующий выходит в ноль (считаем, что комиссии майнеров примерно равны затратам на вычисления). Нужно лишь, чтобы ставка была достаточно высока, чтобы покрыть риски нахождения «плохих» блоков.

Согласен, анализ таких решений — задача непростая. Кстати, спасибо за пояснение про вероятности веткой выше.


Про атаку на данный алгоритм вы не совсем правы. Надо сгенерировать BlockDelay + 1 связанных блоков, таких что в первом — выигрышная ставка, которая рассчитывается на основе хэша последнего. При этом изменение ставки требует пересчета всей цепочки.


Пусть t — среднее время поиска блока в сети.
Пусть p — вероятность, что наш конкретный майнер найдет блок за время t.
Если я правильно понимаю, то вероятность того, что майнер за время t успеет найти BlockDelay + 1 взаимосвязанных блоков равняется p ^ (BlockDelay + 1).


И это ещё если он найдет способ одновременно создавать ставку и blockhash последнего блока… Не представляю как это сделать.

Нет, идея атаки не в том, чтобы менять ставку, а в том, чтобы попытаться найти тот блок, который определяет выигрыш. Нужно действовать в точности как настоящий майнер, но выбрасывать найденные блоки, если они проигрышные. Таким образом можно лишь немного сместить шансы на выигрыш в свою пользу. А расплачиваться нужно валидными найденными блоками, которые в нормальной ситуации принесли бы законную комиссию.

Ок, давайте считать. По данным Etherscan в день майнеры получают примерно 30000 ETH, которые достаются им за примерно 6000 блоков. То есть награда за блок — примерно 5 ETH.

Допустим, майнер делает одну из ставку, с наибольшей вероятностью выигрыша. Для примера «на красное». Надо, чтобы выигрыш принёс больше тех 5 ETH, которые он получит за найденный блок.
При ставке «на красное» сумма ставки должна быть не менее 2.5 ETH.

С другими типами ставок будет та же история — сумма меньше, но и вероятность что другой блок окажется «хорошим» тоже меньше.

Правда из-за Uncle-блоков майнер всё-таки может получить часть награды за неопубликованный блок. Так что действительно, его шанс выиграть окажется немного больше, чем у обычного игрока.

Но мне, всё же, кажется это весьма извращённый метод играть в казино…
Upd. Ошибся: награду за Uncle получит не тот, кто его нашел, а тот кто включил его в свой. Значит нашему игроку это ничем не поможет: не опубликовать блок = потерять 5 ETH.

Из этих выкладок можно сделать оценку снизу на то, какой должна быть ставка в казино, чтобы такая атака была оправданной. Правда, из-за того, что, во-первых, казино берет себе 1/37, и, во-вторых, невелики вероятности нахождения блока и включения его в цепочку, эта стратегия может потребовать очень много ресурсов: огромная ставка плюс огромные мощности.

В нашем случае максимальная ставка ограничена — 256 жетонов на пари. И 5 пари на блок, то есть 12.8 ETH на блок.
Самый легкий способ доказать честность: перед ставками и игрой отдавать запороленный архив, в котором результат. После ставок отдавать пароль. Почему так не делают?
Может быть кто-то делает, я точно не знаю. Но в той рулетке, о которой мы сейчас говорим — идея в том, что вся механика открыта игрокам, полностью доступна проверке и не может быть изменена по желанию казино. В этом преимущества блокчейна.
Если же вопрос о том, почему в блокчейне нельзя такой подход организовать — тут всё просто: смарт-контракты Ethereum ничего не знают о мире вне блокчейна.
А ещё вычисления в блокчейне довольно дорогие, разархивировать архив на каждую ставку — так и разориться можно.
Да архив тут как возможный способ. Основная идея в том, что бы отдавать секрет игроку с результатом, а после ставок отдавать ключ.

Такое очень много где есть. Например в казино Bitsler сервер генерирует случайное число (Seed server) и заранее показывает эго хэш. Так же клиент видит свой Client seed и может его перегенерировать. Плюс используется nonce — порядковый номер ставки игрока.


И далее, для игры в Multicolor рулетку:


$seed = $serverSeed.'-'.$clientSeed.'-'.$nonce;
do {
     $seed = sha1($seed);
     $lucky = hexdec(substr($seed,0,8));
} while ($lucky > 4294960000);

$luckyNumber = ($lucky % 100000) / 1000;

if ($luckyNumber < 0)
     $luckyNumber = -$luckyNumber;

echo $luckyNumber;
Кстати, если казино сделает запароленный архив с результатами игр, как вы узнаете, что эти результаты — случайные? Может быть они специально подобраны так, чтобы игроки — люди, чьё поведение не случайно, а может быть подвержено манипуляциям — чаще проигрывали?
Случайность (вернее — непредсказуемость) ставок нужна в первую очередь самому казино. Случайные результаты гарантируют (на сколь-либо продолжительном промежутке времени) казино прибыль в 2,7% от сделанных ставок. Для казино при этом рулетка — не азартная игра, а автомат по получению денег. Выигратьывать у казино при этом невозможно.
Если же казино будет подсовывать неслучайные результаты и делать это честным образом (т.е. 'манипулировать со случайностью' ДО сделанных ставок), то обманет казино в первую очередь само себя, т.к. те, чье поведение подвержено манипуляциям может быть и будут чаще проигрывать, но те, кто способен если не отгадать эти манипуляции, то хотя бы провести статистический анализ эн предыдущих игр, наверняка будут чаще выигрывать.

Вы абсолютно правы, что для владельцев казино это не азартная игра, а бизнес.
Вместе с тем, может так случиться что владелец решит увеличить свою прибыль сверх этих 2.7% за счёт своего понимания человеческой психологии. Разумеется, это риск. Но кто сказал, что владелец казино — не азартный человек?
Допустим, казино формирует серии псевдо-случайных результатов персонально для каждого игрока по 100 штук за раз. Изначально результаты формируются полностью случайно. Однако по мере того, как игрок делает ставки некий чёрный ящик в казино анализирует поведение игрока и, в случае если понимает что игрок следует определённой стратегии, следующую серию результатов может сформировать спецальным образом.

Конечно, игрок тоже может анализировать результаты и в случае неравномерного их распределения — воспользоваться этим. Но не все сообразят так сделать. А «черный ящик» может выдавать сдвинутые результаты только тем, кто своим поведением показал, что не занимается анализом. Не забывайте, казино знает про игрока всё — вплоть до того, как он двигает мышкой.
Представьте себе крайний случай — нет никаких алгоритмов и никакой рулетки. Играет два человека:
Первый загадывает (пишет на бумажке) число от 0 до 36
Второй делает ставку
Первый называет загаданное число
Ставки и выигрыши — по рулеточным правилам.
При загадывании числа первый может пользоваться чем угодно, от TRNG, до учебника психологии.

В каком случае вы бы предпочли сесть за игровой стол вторым номером? (варианта 'не садиться за стол' нет)

Я бы предпочёл сесть за стол с равномерным случайным распределением, т.к. считаю что это минимизирует преимущество первого игрока, сводит его к тем самым 2.7%.

А на месте первого игрока я бы сначала использовал TRNG и запустил бы нейронную сеть, тренируя её на ставках соперника в зависимости от N предыдущих чисел, чтобы она пыталась их предсказывать. И когда счёл бы, что сеть достаточно натренирована, попробовал бы с её помощью исключать числа которые, предположительно, дадут второму выигрыш.
Поздравляю, вы выбрали худший для себя вариант.

Играя вторым номером вы всегда сможете свести преимущество первого игрока к 2,7%. Просто сами используйте TRNG для ставок.
И можете точно так же, как первый номер анализирует ваши ставки, анализировать его 'результаты'. Если на каком-то этапе анализа захотите — перейдете к активным действиям. При этом у вас есть важное преимущество — размер ставки выбираете вы.
Я отвечал исходя из того, что сидя вторым номером не могу пользоваться техническими устройствами.
И я думаю, большая часть игроков именно так и поступает: им интересно проверить свою интуицию и везение, а не работать роботом. Особенно зная, что робот всегда проигрывает.

Впрочем, лично мне интересно роботов писать… А в случае этой рулетки — оно ещё и разрешено организаторами.
интересно проверить свою интуицию и везение
Вы всерьез собрались противопоставлять интуицию и везение TRNG?
Интуицию, везение и интеллект имеет смысл противопоставлять другому интеллекту (что есть вариант 2).

А в случае этой рулетки — оно ещё и разрешено организаторами.
Разговор-то не за эту рулетку, а за то, что самое глупое, что может сделать казино — вносить априорную неслучайность в результаты.
Нет, я как раз не собираюсь сидеть и играть с TRNG. Но именно так делает значительная часть игроков в рулетку, Dice и прочие игры с автоматами.

Разговор начался с вопроса о том, имеет ли смысл владельцу казино заменять TRNG на что-то другое. И моя позиция заключается в том, что если игрок — человек, то такая замена может быть выгодна.
если будете открывать казино — дайте знать
пароль может содержать зашифрованные результаты, нет?

Какой пароль вы имеет в виду?

Казино, даже онлайн, нет смысла обманывать игроков — математическая вероятность и психология игрока на их стороне. Обманите один раз — потеряете игрока, дадите ему честную вероятность выигрыша — он будет постоянно вам все свои деньги носить. Столбики и по 95% выигрыша выдавали, куда выше, чем в рулетке.
Согласен, обманывать смысла нету. Однако, не зря говорят: доверяй, но проверяй.
Лично для меня анализ этого смарт-контракта был ещё и способом разобраться в Solidity.
ага, то-то в России среди владельцев таких столбиков самыми популярными были те, которые вообще никакого выигрыша не выдавали, тупо забирая хозяину все 100% вкинутых денег. Заодно на диспенсере монет экономия…
Такое высказывание имеет смысл, если вы работали в конторе, поставлявшей эти аппараты по всей России и знаете кухню этого бизнеса. Если так — с удовольствием почитал бы вашу стать на гиктаймсе о том, как это было (без сарказма). Если нет — извините, у меня знакомый работал в обслуживании этих автоматов, его опыт, конечно, точечный и не дающий полной картины по всей стране, но он для меня имеет куда больший вес, чем высказывание анонимуса.
Столбики и по 95% выигрыша выдавали, куда выше, чем в рулетке.
Незаряженная 'европейская' (с одним zero) рулетка возвращает 36/37, т.е. ~97,3%
Да, был неправ относительно рулетки.
в один момент времени в сети может существовать одна игра? т.е. все транзакции по этому контракту идут как ставки, а на следующем победитель получает выигрыш? Или у игры есть идентификатор и где-то централизовано игроки собираются?

p.s. как можно потестировать игру, не загружая блокчейн ethereum (под текущим его ддос это проблематично) или где его можно загрузить в виде архива?
Протестировать игру можно на её сайте, используя Chrome с плагином MetaMask. Есть даже видеоинструкция.
После установки MetaMask он предложит создать кошелёк и выдаст на этот кошелёк 1 ETH в тестовой сети Ropsten. Вот на этот тестовый эфир и можно попробовать игру. Разумеется, это будут «фантики», т.к. ETH в тестовой сети никакой ценности не имеют.
В принципе, никто не может помешает вам взять код контракта, перезалить по новому адресу и тем самым получить новую копию игры, управлять которой будете вы сами.
Но конкретный сайт игры работает с конкретным экземпляром контракта. Сам контракт и входящие транзакции (ставки) исполняются майнерами последовательно во время формирования нового блока. Разумеется значение имеет только тот блок, который попадёт в блокчейн.
Я похоже продолжаю не понимать — что есть ethereum

Я ожидал что я запущу клиент, во встроенном в нем браузере открою 'страницу' по некому стартовому адресу контракта и смогу там играть. Без необходимости в существовании какого то стороннего сервиса.

Это все еще недостижимо?
Можно как вы говорите. Можно проще — никакого отдельного клиента, ваш обычный Chrome. Устанавливаете плагин MetaMask. Он делает для сайтов доступным объект web3, через который JavaScript может делать вызовы к Ethereum-кошельку встроенному в MetaMask.
Когда вы делаете ставку скрипт на странице рулетки через web3 просить кошелёк выполнить транзакцию. Тот через JSON-RPC обращается к какой-нибудь (прописанной авторами MetaMask или настроенной вами самостоятельно) Ethereum-node, которая публикует транзакцию в сети.
Дальше майнер, пожелав включить эту транзакцию в блок, исполняет её код. А в коде — обращения к методу placeBet() смарт-контракта рулетки.

Если вы принципиально нехотите никаких сторонних сервисов — только вы и сеть Ethereum, вам потребуется Mist в режиме полной ноды. В его встроенном броузере открываете сайт рулетки и всё то же самое, только нода — сразу ваша, а не какая-то сторонняя.
Или даже не открываете сайт рулетки, а просто в консоле вызываете нужные методы смарт-контракта.
Вы описываете технологии, которые позволят мне сделать игру и играть, я не сомневаюсь что они существуют и хороши.

Я говорю о том что разработчики контракта не предоставляют всего этого в готовом виде, хотя у них этот функционал уже есть, у них же это как то работает? или я опять что то не понимаю.

В блокчейне ethereum не хранится код с интерфейсам пользователя для контрактов принципиально? или это техническое ограничение? Почему нужно открывать какой то вебсайт?
В блокчейне не хранится UI. Именно по этой причине нужен веб-сайт, который даёт игроку красивую картинку.
С другой стороны, кто угодно может сделать UI к этому контракту. Вам не нравится их сайт — делайте свой.

Почему UI не хранится непосредственно в блокчейне — хороший вопрос. Интересно узнать, как вы себе это представляете. Например, в каком виде его хранить? И, главное, зачем это делать — какая могла бы быть от такого хранения польза?

Теоретически, вы можете взять, например, весь код HTML+CSS+JS своего приложения и записать вместе с контрактом в блокчейн. Это будет довольно дорого: если я правильно понял спецификацию, за a байт придется заплатить Cmem(a) = Gmemory*a + (a^2/512) единиц газа, где Gmemory = 3. А обычная цена газа сегодня 0.00000002 ETH. Таким образом, 1Мб обойдется ~ 0.1049 ETH. Но вы можете это сделать.
Только просматривать такой UI на сегодня момент будет нечем.
А можно контракт научить ходить на random.org?
Там плюшки всякие, маяки, проверяемость…
Это чтобы с ГПСЧ не морочиться и предотвратить возможность описанной потенциальной атаки?
Ну, и по-настоящему случайные числа.
В EVM, виртуальной машине Ethereum, нету операций, которые позволили бы исполняемому коду сделать вызов за пределы виртуальной машины. Так что смарт-контракт может оперировать исключительно теми данными, которые находятся внутри блокчейна.

В этом ключе интересен проект Aeternity, они собираются сделать блокчейн со встроенными оракулами. Идея в том, что автор контракта может сформулировать вопрос (человеческим языком) а пользователи сети будут, при желании, на него отвечать. Далее, методом консенсуса, схожим с PoS, будет определён верный ответ.
А Вас не затруднит объяснить вот этот момент?
Дальнейшая жизнь пари начинается с вызова функции ProcessGames(), который, после появления новой ставки, выполняется, в настоящее время, с адреса ...
Как этот адрес узнаёт о появлении новой ставки? И немного расширю вопрос (думаю, не одному мне нужно это понять). Контракт, при выполнении потребляет газ. Этот газ списывается с адреса отправителя, активировавшего контракт. Количество газа зависит от, грубо говоря, количества выполненного кода. Например:
Простой контракт лотереи. 10 игроков присылают по 1 ETH и происходит розыгрыш. Для девяти из них количество газа будет, например 0,002 (т.к. контракт только принимает платёж), а для последнего, который активировал розыгрыш, количество газа будет больше, ибо выполнится весь остальной код контракта.
Т.е. чтобы всё было честно, активироваться розыгрыш должен снаружи. Вот тут мы и возвращаемся к основному вопросу. Как 0xa92d36dc1ca4f505f1886503a0626c4aa8106497 узнал о появлении ставки и как он послал вызов функции ProcessGames()?
Sign up to leave a comment.

Articles