Wir wollen ein Kartenspiel in Ethereum schreiben. Was sind effektive und sichere Methoden, um ein Kartenspiel in einem Vertrag zu mischen und an die Spieler zu verteilen? Es muss so geschehen, dass niemand die Karten des anderen und das gemischte Deck bestimmen kann, indem der Open-Source-Vertragscode untersucht und Transaktionen gemischt werden, die sich alle auf der öffentlichen Ethereum-Blockchain befinden.
Wenn dies vertraglich nicht möglich ist, welche Vorgehensweisen sind möglich?
Alice und Bob wollen ein Kartenspiel so mischen, dass keiner weiß, was die Hand des anderen enthält, aber die Hände disjunkt sind (dh nur einer darf eine bestimmte Karte haben).
Protokoll:
Alice und Bob entscheiden sich für ein Verschlüsselungsprotokoll mit folgenden Merkmalen
Nun, da Alice und Bob ein Verschlüsselungsschema haben:
Weitere Karten können mit einem ähnlichen Verfahren gezogen werden. Nach dem Spiel zeigen Alice und Bob A und B , damit sie überprüfen können, dass keiner der Spieler geschummelt hat.
Tatsächlich existieren Verschlüsselungsverfahren mit den aufgeführten Eigenschaften, darunter auch ein RSA-ähnliches Verfahren. Siehe meine Quelle für weitere Details.
Verträge können verwendet werden, um die Nachrichten zwischen Spielern zu verwalten und Belohnungen zu verteilen. Der Vertrag muss keine Logik ausführen, es sei denn, die Spieler sind sich über die Ergebnisse nicht einig. Im Falle einer Meinungsverschiedenheit muss der Herausforderer genügend Ether aufbringen, um die Gaskosten für die Verifizierung des Spiels zu decken. Dann muss der andere Spieler den Anruf ausführen, um das Spielergebnis zu überprüfen. Das Gas wird dem wahrheitsgemäßen Spieler zurückerstattet und die Runde wird vom Betrüger abgebrochen oder verwirkt.
Da der Quellcode von Ethereum-Verträgen verifiziert werden kann, sollte dies so einfach sein wie die Verwendung eines RNG, um zufällig Karten aus einem Stapel auszuwählen. Jeder, der überprüfen möchte, ob das Deck angemessen gemischt ist, kann den Vertragsquellcode überprüfen.
Da die Erzeugung einer guten Zufälligkeit an anderer Stelle angesprochen wird , geht diese Antwort davon aus, dass der Kartenmischvertrag Zugriff auf gute Zufallszahlen hat.
Die Herstellung eines gut gemischten Decks kann durch zufälliges Auswählen von Karten aus einem nicht gemischten Deck und das Erstellen eines neuen Decks erfolgen, bis das nicht gemischte Deck aufgebraucht ist.
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]
}
}
}
Dieser Kontrakt repräsentiert jede der 52 Karten als ganze Zahl zwischen 0 und 51 einschließlich. Ein Aufruf der shuffle
Funktion füllt die deck
Speichervariable mit einem Kartenspiel mit 52 Karten in zufälliger Reihenfolge.
Dies setzt voraus, dass die Zufälligkeit sicher angefordert werden kann, was nicht unbedingt möglich ist. Wenn dies nicht der Fall ist und stattdessen Zufälligkeit in den Vertrag geschickt werden muss, sollte das folgende allgemeine Konzept genauso gut funktionieren.
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];
}
}
}
Diese Version des Vertrags erfordert mindestens 52 Zufallsbytes, die in den Aufruf von aufgenommen werden müssen shuffle
.
Wenn Sie wollen, dass sich Karten nicht wiederholen, dann ist das eigentlich ein ziemlich schwieriges Problem. Ein einfacheres Problem ist, wenn es uns egal ist, ob dieselbe Karte mehrmals ausgeteilt wird (z. B. Sie haben ein Pik-Ass und ich ein Pik-Ass).
Betrachten wir ein einfaches Spiel mit 2 Spielern. Jeder Spieler erhält 1 Karte und es ist in Ordnung, dass beide Spieler die gleiche Karte bekommen. Man kann sich das so vorstellen, als würden die beiden Karten von zwei verschiedenen Decks ausgeteilt. Um dies zu implementieren, können wir uns jede Karte als einen Index zwischen 0 und 51 (einschließlich) vorstellen. Hier erfahren Sie, wie Sie die Karte von Spieler 1 fair generieren, sodass nur er weiß, was es ist.
Derselbe Ansatz kann zum Erzeugen der Karte von Spieler 2 verwendet werden.
Sicherzustellen, dass jede Karte nur einmal erscheint, finde ich ziemlich herausfordernd. Das könnten wir einmal sagen
hcvst
Tjaden Hess
Himbeere
Tjaden Hess
eth
Christian
eth
Himbeere
eth
Tjaden Hess