Мы хотим написать карточную игру на Ethereum. Каковы эффективные и безопасные способы перетасовки колоды карт в контракте и раздачи их игрокам? Это должно быть сделано таким образом, чтобы никто не мог определить карты друг друга и то, что представляет собой перетасованная колода, путем изучения кода контракта с открытым исходным кодом и перетасовки транзакций, которые находятся в общедоступной цепочке блоков Ethereum.
Если это невозможно в контракте, какие подходы возможны?
Алиса и Боб хотят перетасовать колоду карт так, чтобы ни один из них не знал, что лежит в руке другого, но эти руки не пересекаются (т. е. только одна может иметь конкретную карту).
Протокол:
Алиса и Боб выбирают протокол шифрования со следующими функциями.
Теперь, когда у Алисы и Боба есть схема шифрования:
Аналогичным образом можно взять больше карт. После игры Алиса и Боб раскрывают A и B , чтобы убедиться, что ни один из игроков не обманул.
Схемы шифрования с перечисленными свойствами действительно существуют, включая метод, аналогичный RSA. Смотрите мой источник для более подробной информации.
Контракты можно использовать для управления обменом сообщениями между игроками и для распределения вознаграждений. Контракт не должен выполнять какую-либо логику, если только игроки не согласны с результатами. В случае разногласий претендент должен поставить достаточно эфира, чтобы покрыть расходы на газ для проверки игры. Затем другой игрок должен выполнить вызов, чтобы проверить результат игры. Бензин возвращается правдивому игроку, а мошенник отменяет раунд или лишает его права.
Поскольку исходный код контрактов Ethereum может быть проверен, это должно быть так же просто, как использование ГСЧ для случайного выбора карт из колоды. Любой, кто хочет убедиться, что колода правильно перемешана, может проверить исходный код контракта.
Поскольку генерация хорошей случайности рассматривается в другом месте , этот ответ предполагает, что контракт перетасовки карт имеет доступ к хорошим случайным числам.
Создать хорошо перетасованную колоду можно путем случайного выбора карт из неперетасованной колоды и создания новой колоды до тех пор, пока не будет исчерпана неперетасованная колода.
contract Deck {
uint8[52] deck;
function getRandomNumber() returns (uint) {
...;
}
function shuffle() {
uint8[52] memory unshuffled;
for (uint8 i=0; i < 52; i++) {
unshuffled[i] = i;
}
uint cardIndex;
for (i=0; i < 52; i++) {
cardIndex = getRandomNumber() % (52 - i);
deck[i] = unshuffled[cardIndex];
unshuffled[cardIndex] = unshuffled[52 - i - 1]
}
}
}
Этот контракт представляет каждую из 52 карт как целое число от 0 до 51 включительно. Вызов shuffle
функции заполнит deck
переменную хранилища колодой из 52 карт в случайном порядке.
Это предполагает, что случайность может быть безопасно запрошена, что не всегда возможно. Если это не так, и вместо этого в контракт нужно отправить случайность, то следующая общая концепция должна работать одинаково хорошо.
contract Deck {
uint8[52] deck;
function shuffle(bytes randomBytes) {
if (randomBytes.length < 52) throw;
uint8[52] memory unshuffled;
for (uint8 i=0; i < 52; i++) {
unshuffled[i] = i;
}
uint8 cardIndex;
for (i=0; i < 52; i++) {
cardIndex = uint8(randomBytes[i]) % (52 - i);
deck[i] = unshuffled[cardIndex];
unshuffled[cardIndex] = unshuffled[52 - i - 1];
}
}
}
Эта версия контракта требует включения не менее 52 байт случайности в вызов shuffle
.
Если вы хотите, чтобы карты не повторялись, то это довольно сложная задача. Более простая проблема заключается в том, что нам все равно, если одна и та же карта сдается несколько раз (например, у вас туз пик, а у меня туз пик).
Рассмотрим простую игру с двумя игроками. Каждому игроку раздается по 1 карте, и это нормально, что оба игрока могут получить одну и ту же карту. Это можно представить, как две карты раздаются из двух разных колод. Чтобы реализовать это, мы можем думать о каждой карте как об индексе от 0 до 51 (включительно). Вот как правильно сгенерировать карту игрока 1, чтобы только он знал, что это такое.
Тот же подход можно использовать для создания карты игрока 2.
Я думаю, что убедиться, что каждая карта появляется только один раз, довольно сложно. Мы могли бы сказать, что однажды
hcvst
Тьяден Хесс
Джимкберри
Тьяден Хесс
эт
христианин
эт
Джимкберри
эт
Тьяден Хесс