fairness.gno
2.11 Kb · 61 lines
1package gnodice
2
3import (
4 "crypto/sha256"
5 "encoding/binary"
6 "encoding/hex"
7 "strconv"
8)
9
10// Équité du jeu : empreinte du chiffre caché et calcul du dé.
11// Tout est vérifiable par n'importe qui avec SHA-256 :
12//
13// empreinte = sha256("gnodice|v1|commit|" + adresse + "|" + chiffre + "|" + secret)
14// dé = 1 + (8 premiers octets de sha256("gnodice|v1|roll|" + graine + "|" + empreinte + "|" + numéro)) mod 6
15//
16// Le secret du joueur et la graine du croupier font 32 octets (64 caractères
17// hexadécimaux). Un secret plus court permettrait au croupier de retrouver le
18// chiffre en essayant les 6 possibilités : il est donc refusé.
19
20const hexLen = 64 // 32 octets écrits en hexadécimal
21
22// Commitment calcule l'empreinte d'un chiffre caché. Lecture seule : le site
23// et le croupier peuvent l'appeler pour vérifier leurs calculs.
24func Commitment(player address, guess int, salt string) string {
25 sum := sha256.Sum256([]byte("gnodice|v1|commit|" + player.String() + "|" + strconv.Itoa(guess) + "|" + salt))
26 return hex.EncodeToString(sum[:])
27}
28
29// rollFromSeed calcule le dé à partir de la graine du croupier, de l'empreinte
30// du joueur et du numéro de la partie.
31// Le modulo 6 sur 64 bits a un biais inférieur à 1 sur 3 milliards de milliards :
32// négligeable.
33func rollFromSeed(seed, commitment string, id int64) int {
34 sum := sha256.Sum256([]byte("gnodice|v1|roll|" + seed + "|" + commitment + "|" + itoa64(id)))
35 return int(binary.BigEndian.Uint64(sum[0:8])%DieFaces) + 1
36}
37
38// RollFor : version publique de rollFromSeed, pour que chacun puisse vérifier
39// un tirage passé (graine et empreinte sont publiques après le tirage).
40func RollFor(seed, commitment string, id int64) int {
41 if !isHex64(seed) || !isHex64(commitment) {
42 return 0
43 }
44 return rollFromSeed(seed, commitment, id)
45}
46
47// isHex64 : exactement 64 caractères hexadécimaux minuscules.
48func isHex64(s string) bool {
49 if len(s) != hexLen {
50 return false
51 }
52 for i := 0; i < len(s); i++ {
53 c := s[i]
54 if !(c >= '0' && c <= '9' || c >= 'a' && c <= 'f') {
55 return false
56 }
57 }
58 return true
59}
60
61func itoa64(v int64) string { return strconv.FormatInt(v, 10) }