Queremos escribir un juego de cartas en Ethereum. ¿Cuáles son las formas efectivas y seguras de barajar una baraja de cartas en un contrato y repartirlas a los jugadores? Debe hacerse de manera que nadie pueda determinar las cartas de los demás y cuál es el mazo barajado, examinando el código de contrato de fuente abierta y barajando transacciones que están todas en la cadena de bloques pública de Ethereum.
Si esto no es posible en un contrato, ¿qué enfoques son posibles?
Alice y Bob quieren barajar una baraja de cartas, de modo que ninguno sepa lo que contiene la mano del otro, pero las manos están separadas (es decir, solo uno puede tener una carta en particular).
Protocolo:
Alice y Bob deciden un protocolo de encriptación con las siguientes características
Ahora que Alice y Bob tienen un esquema de cifrado:
Se pueden sacar más cartas usando un procedimiento similar. Después del juego, Alice y Bob revelan A y B para que puedan verificar que ninguno de los jugadores hizo trampa.
De hecho, existen esquemas de cifrado con las propiedades enumeradas, incluido un método similar a RSA. Ver mi Fuente para más detalles.
Los contratos se pueden usar para administrar los mensajes entre jugadores y distribuir recompensas. El contrato no necesita ejecutar ninguna lógica a menos que los jugadores no estén de acuerdo con los resultados. En caso de desacuerdo, el retador debe aportar suficiente Ether para cubrir los costos de gasolina para verificar el juego. Luego, el otro jugador debe ejecutar la llamada para verificar el resultado del juego. El combustible se reembolsa al jugador veraz, y el tramposo cancela o pierde la ronda.
Dado que los contratos de Ethereum pueden verificar su código fuente, esto debería ser tan simple como usar un RNG para elegir cartas al azar de una baraja. Cualquiera que desee verificar que la baraja está barajada adecuadamente puede verificar el código fuente del contrato.
Dado que la generación de buena aleatoriedad se aborda en otra parte , esta respuesta supone que el contrato de barajado de cartas tiene acceso a buenos números aleatorios.
Se puede producir un mazo bien barajado seleccionando cartas al azar de un mazo sin barajar y construyendo un nuevo mazo hasta que se agote el mazo sin barajar.
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]
}
}
}
Este contrato representa cada una de las 52 cartas como un número entero entre 0 y 51 inclusive. Una llamada a la shuffle
función llenará la deck
variable de almacenamiento con una baraja de 52 cartas con orden aleatorio.
Esto supone que la aleatoriedad se puede solicitar de forma segura, lo que no es necesariamente factible. Si este no es el caso y la aleatoriedad debe incluirse en el contrato, entonces el siguiente concepto general debería funcionar igualmente bien.
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];
}
}
}
Esta versión del contrato requiere que se incluyan al menos 52 bytes de aleatoriedad con la llamada a shuffle
.
Si desea que las tarjetas no se repitan, entonces en realidad es un problema bastante difícil. Un problema más simple es si no nos importa si la misma carta se reparte varias veces (por ejemplo, usted tiene un as de picas y yo tengo un as de picas).
Consideremos un juego simple con 2 jugadores. A cada jugador se le repartirá 1 carta y está bien que ambos jugadores reciban la misma carta. Se puede pensar que las dos cartas se reparten de dos barajas diferentes. Para implementar esto, podemos pensar en cada carta como un índice entre 0 y 51 (ambos inclusive). A continuación se explica cómo generar de manera justa la carta del jugador 1, para que solo él sepa cuál es.
El mismo enfoque se puede utilizar para generar la tarjeta del jugador 2.
Asegurarme de que cada tarjeta aparezca solo una vez creo que es bastante desafiante. Podríamos decir que una vez
hcvst
tjaden hess
jimkberry
tjaden hess
ética
cristiano
ética
jimkberry
ética
tjaden hess