NXTER MAGAZINE

Loterie sur la Chaîne de Blocs Nxt à Golang

Dans mon premier article, j’ai introduit la théorie de la chaîne de blocs, ce qu’il peut faire pour votre projet de logiciel et les bases de l’interaction avec la chaîne de blocs Nxt en PHP.

Aujourd’hui, je vais présenter un petit programme de loterie écrit dans Go.

Pré-requis:
Golang (testé avec Go 1.6.2)
NRS 1.10.1 (https://bitbucket.org/JeanLucPicard/nxt/downloads/)
Le programme est entièrement fonctionnel et éxécute une loterie tous les Dimanches [1]. Il a été écrit à l’origine en PHP, les deux sources sont disponibles en téléchargement à partir du Nxt Data Cloud [2].

Logique d’Application

Le flux de données de cette application est constitué de «tickets» soumis par les utilisateurs dans les pièces jointes.

Un joueur de loterie envoie 10 NXT au compte de loterie et attache un message public non chiffré avec une chaîne de 5 numéros, allant de 0 à 30, séparés par des virgules. La pièce jointe doit être déchiffrée pour que les récompenses soient publiquement vérifiables à l’aide de la chaîne de blocs.

L’application demande au serveur NXT de récupérer toutes les transactions du compte de loterie, de les trier, de sélectionner uniquement les transactions valides et de créer une tranche de cartes (tableau multidimensionnel en PHP) des comptes des joueurs et de leurs chaînes de nombres. Il calcule également la somme totale de NXT payable aux joueurs à partir de la somme de tous les billets valides.

À la réception de toutes les données valides, l’application exécute trois tours de la loterie. Chaque tour reçoit une partie de la somme totale payable, répartie entre les gagnants en simultanés. Dans la ronde de 5, l’application trouve des utilisateurs qui ont correctement deviné 5 numéros et envoie des récompenses. Dans la ronde de 4, l’application fait la même chose pour les utilisateurs qui ont deviné 4 numéros, la tranche de billets participants est maintenant à court de gagnant (s) de la ronde de 5. Rincer et répéter pour la ronde de 3.

C’est l’essentiel.

Un peu sur les internes

Pour chacun des trois tours, la loterie génère des séquences de 5 numéros et les compare aux chaînes de nombres dans les billets jusqu’à ce qu’un ou plusieurs gagnants soient trouvés. On peut dire que la loterie « force » la séquence gagnante sur le/les ticket(s).

Avec un nombre limité d’utilisateurs, cela semble être la seule façon raisonnable de gérer une loterie et de ne pas avoir à collecter et à conserver un gros jackpot pendant des mois voir des années.

Jetons un coup d’oeil à la fonction qui génère des séquences de 5 nombres et renvoie un tableau de eux à la fonction appelante. En moyenne, cette fonction s’éxécute des centaines de milliers de fois pour trouver la séquence de 5 correspondant à l’un des billets, quand nous avons un nombre très limité de participants. Cela prend des fractions de seconde. En PHP il prend un peu plus longtemps (une seconde ou deux), bien que la performance de PHP 7 est vraiment bonne.

func genFive(seed string) [5]int {
   var r [5]int
   seedInt, _ := strconv.Atoi(seed)
   d := false
   for a := offset; a < offset+5; a++ { 
      rand.Seed(int64(seedInt + offset)) 
      var dup [31]int 
      d = false 
      r[0] = rand.Intn(31) 
      r[1] = rand.Intn(31) 
      r[2] = rand.Intn(31) 
      r[3] = rand.Intn(31) 
      r[4] = rand.Intn(31) 
      for _, v := range r { 
         dup[v]++ 
      } 
      for k, _ := range dup { 
         if dup[k] > 1 {
            d = true
         }
      }
      offset = offset + 5
      if d == false {
         return r
      }
   }
   return r
}

Une caractéristique importante d’une application de loterie d’une Chaîne de Blocs est: elle doit être complètement libre de toute confiance.
Tout le monde doit être en mesure de valider que les résultats de la loterie n’ont pas été joués. Une solution logique et simple à cela est de générer des séquences de nombres avec une graine déterministe.

Le problème des graines déterministes: si elles sont connues à l’avance, des séquences de nombres peuvent être prédites et la loterie peut être jouée. Pour résoudre ce problème, nous nous tournons de nouveau vers la chaîne de blocs Nxt, afin de trouver une source de graine avec une fonction getSeed ().

func getSeed() (string, string) {
 type BlockchainStatus struct {
    NumberOfBlocks int `json:"numberOfBlocks"`
 }
 var status BlockchainStatus
 if seedBlockOutput, b := 
sendQuery("requestType=getBlockchainStatus", 
true); 
b != false { if err := 
json.Unmarshal([]byte(seedBlockOutput), &status); 
err != nil {
     fmt.Println(err)
   }
  }
 seedBlockHeight := 
strconv.Itoa(status.NumberOfBlocks - 11)

 type BlockId struct {
  Block string `json:"block"`
 }
 var block BlockId
 if seedBlockId, b := 
sendQuery("requestType=getBlockId&height="
+seedBlockHeight, true); b != false {
if err := json.Unmarshal([]byte(seedBlockId), 
&block); err != nil {
         fmt.Println(err)
    }
  }
 seed := block.Block[len(block.Block)-5:]
 return seed, seedBlockHeight
}

L’application fonctionne à 18:00 UTC le dimanche.

La première chose qu’il fait dans la fonction getSeed () est de récupérer le bloc id du bloc qui a été généré 10 blocs avant le début de l’application (comme vu dans une copie locale du blockchain sur le noeud de la loterie) et prendre les 5 derniers chiffres du bloc id comme une graine. En raison de la latence du réseau et des réorganisations occasionnelles de la chaîne de blocs de 1-3 blocs, le nœud de loterie peut ne pas voir le même bloc que les autres nœuds. Le nombre 10 pour obtenir le bloc de la graine a été choisi pour être raisonnablement sûr que le bloc ne serait pas réorganisé.

On peut faire valoir qu’il existe une possibilité théorique que le bloc ID soit prévisible. Les chances de cela sont minuscules à mon avis, mais je vais laisser aux lecteurs de débattre et de décider.

Maintenant que l’application a ses gra

On peut faire valoir qu’il existe une possibilité théorique que le bloc ID soit prévisible. Les chances que cela se produise sont minuscules à mon avis, mais je vais laisser aux lecteurs la chance de débattre et de décider.

Maintenant que l’application a sa graine, il peut faire son travail d’une manière afin que les utilisateurs n’ont pas besoin de faire confiance à l’hôte de la loterie.

Le code source Go n’inclut pas la routine pour vérifier les résultats antérieurs.
Le code source PHP l’a, il est entièrement fonctionnel et peut être utilisé pour vérifier indépendamment tous les résultats passés avec les graines déterministes de la chaîne de blocs.

Pour Go, j’utilise cette fonction pour envoyer des requêtes au serveur Nxt et renvoyer les résultats.

func sendQuery(Query string, Active bool) 
(output string, b bool) {
   output = ""
   b = false
   if Active == false {
      output = "Function disabled"
      return
   }
   body := strings.NewReader(Query)
   req, err := http.NewRequest("POST", 
"http://127.0.0.1:7876/nxt", body)
   if err != nil {
      output = fmt.Sprintf("%s", err)
      return
   }
   req.Header.Set("Content-Type", 
"application/x-www-form-urlencoded")

   resp, err := http.DefaultClient.Do(req)
   if err != nil {
      output = fmt.Sprintf("%s", err)
      return
   }
   bo, err := ioutil.ReadAll(resp.Body)
   defer resp.Body.Close()
   output = fmt.Sprintf("%s", bo)
   match, _ := 
regexp.MatchString(".*errorDescription.*", 
output)
   if match == true {
      fileHandle, _ := 
os.OpenFile("./error.log", os.O_APPEND, 0666)
      writer := bufio.NewWriter(fileHandle)
      defer fileHandle.Close()
      fmt.Fprintln(writer, output)
      writer.Flush()
      return
   }
   b = true
   return
}

Les résultats sont retournés sous la forme d’une chaîne JSON et doivent être non assemblés dans des structures appropriées.

validPlayers := make([]map[string]string, 0)

lotteryAccount := "NXT-YXC4-RB92-F6MQ-2ZRA6"

type Attachment struct {
   Message       string `json:"message"`
   MessageIsText bool   `json:"messageIsText"`
}

type Transaction struct {
   Timestamp   int        `json:"timestamp"`
   AmountNQT   string     `json:"amountNQT"`
   ID          string     `json:"transaction"`
   SenderRS    string     `json:"senderRS"`
   RecipientRS string     `json:"recipientRS"`
   Attached    Attachment `json:"attachment"`
}

type Response struct {
   Transactions []Transaction 
`json:"transactions"`
}
Query := 
"requestType=getBlockchainTransactions&account=" +
lotteryAccount + 
"&type=0&subtype=0&executedOnly=true"

if v, a := sendQuery(Query, true); a == true {
   var transactions Response
   if err := json.Unmarshal([]byte(v), 
&transactions); err != nil {
      fmt.Println(err)
   }

 p := 0
 for k, _ := range transactions.Transactions {
    // code to check tickets for validity.
    // if transaction satisfies all criteria 
    // add it to the slice of valid tickets.
		
    validPlayers = append(validPlayers, 
make(map[string]string))
    validPlayers[p][txSender] = lotteryNumbers
    p++
			
   }
}

Maintenant que ‘validPlayers’ a tous les bons tickets, nous pouvons commencer le jeu.

Process() reçoit un entier (5, 4 ou 3) et d’autres paramètres, y compris validPlayers et exécute trois rounds de la loterie. Il fait un appel à la fonction getWinners(), que l’on appelle genFive() pour générer des séquences de nombres jusqu’à ce qu’au moins un gagnant soit trouvé. GetWinners() renvoie les résultats à process() qui envoie une récompense, supprime le ticket gagnant des tickets admissibles et retourne les billets restants dans main() pour les tours suivants. Il existe une fonction aidante preparePlayers() qui recrée les joueurs valides sans les espaces vides libérés par les tickets supprimés.

J’encourage tous les programmeurs à essayer de coder sur la Chaîne de Blocs Nxt. Il est très facile avec son API riche d’accrocher dans toutes les fonctionnalités du moteur de base. https://nxtwiki.org/wiki/The_Nxt_API

Ma prochaine application sera probablement une application de sondage, avec des enregistrements immuables des votes enregistrés dans la chaîne de blocs. Pensez-vous qu’une application comme celle-ci peut trouver une utilisation dans le monde moderne? Par ailleurs, Nxt a son propre vote intégré. Il est trop facile d’oublier ce que Nxt a, car il a tant de fonctionnalités et toutes ces fonctionnalités sont accessibles par l’API, aimablement programmé par les développeurs de base pour userland. Vous pouvez « détruire » vos premières pièces NXT pour envoyer des transactions dans le projet de noeud Lucky exécutant un nœud public, venez à nxtforum.org et vous découvrirez comment.

Veuillez laisser vos commentaires et suggestions.


 

1.
Lottery at nxtforum.org.

2.
Pour accéder au  »Nxt Data Cloud », télécharger et installer le  NRS (Nxt Reference Software 1.10.1) et rechercher par «loterie» mot-clé. Le code source peut également être téléchargé depuis n’importe quel serveur Open API Nxt public, par exemple:

Go: http://23.94.134.161:7876/nxt?requestType=downloadTaggedData&transaction=7872865106538381099&retrieve=true

PHP: http://23.94.134.161:7876/nxt?requestType=downloadTaggedData&transaction=13031806327722095646&retrieve=true
BACK TO POST.

View this in: English Русский Español

Laisser un commentaire

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur comment les données de vos commentaires sont utilisées.