NXTER MAGAZINE

La bière, le pari et la Chaîne-de-Blocs NXT

Supposons que vous ayez un cercle d’amis que vous rencontrez dans un bar sportif pour boire de la bière, regarder des sports et faire des paris. Vous pouvez faire des paris sur la chaîne-de-blocs NXT et avoir une application Python de base l’automatiser pour vous.

Dans mon premier article j’ai présenté les bases d’une chaîne de blocs. Comme nous l’avons appris, la proposition de valeur la plus importante de la chaîne de blocs est l’immutabilité des données soumises dans les transactions enregistrées en blocs, à partir desquelles une chaîne de blocs est construite.

Aujourd’hui, je veux vous montrer comment construire une application de paris simple mais entièrement fonctionnel en python. Pour l’application de pari que je présente, l’immutabilité des données peut être nécessaire, mais dans le cas où un pari doit être annulé, l’application peut être modifiée pour tenir compte de cette fonctionnalité supplémentaire.

Conditions préalables:
NRS (logiciel de référence Nxt) 1.10.2:
https://bitbucket.org/JeanLucPicard/nxt/downloads/, Python 3 (ou Python 2 avec la moindre modification). Une bière ou deux (facultatif).

Logique d’Application

Un utilisateur soumet un pari (transfère tout montant de pièces de monnaie NXT) au compte de pari et ajoute un attachement public non chiffré. Dans la pièce jointe il doit écrire l’id de la mise, un deux-points et un nombre indiquant son choix dans le pari correspondant. Prenons un exemple: le bar des sports exécute un pari que l’équipe de football gagne. Ils attribuent un ID à ce jeu, disons «30».

Les choix sont les suivants:
« 1 » – équipe à domicile gagne. «2» – l’autre équipe gagne. « 3 » – cravate.

Pour parier sur la victoire de l’équipe locale, le joueur doit soumettre une transaction de n’importe quelle quantité de NXT, et joindre un message public non chiffré (pour  »auditabilité ») avec le contenu: 30: 1

Lorsque le moment est venu, l’hôte de pari exécute l’application pour trouver les gagnants et traiter les paiements. L’hôte peut prendre un petit supplément pour le service.

Implémentation

Le serveur Nxt écoute les requêtes sur le port 7876. Si vous l’exécutez sur la même machine que votre code python par défaut, vous devez soumettre des requêtes à http://127.0.0.1:7876/nxt

Pour notre application, nous devrons importer quelques modules et écrire la fonction pour soumettre des requêtes qui seront utilisées à plusieurs reprises dans l’application.

import sys, json, re
def sendQuery(Query):
  from urllib import parse, request
  params = parse.urlencode(Query)
  headers = {"Content-type": "application/x-www-form-urlencoded", 
"Accept": "text/plain"}
  req = request.Request("http://127.0.0.1:7876/nxt", 
params.encode('utf-8'))
  response = request.urlopen(req)
  return response.read()
	
myAccount = "NXT-AAAA-BBBB-CCCC-DDDDD"
totalAmount = 0
serviceFee = 0.05
players = []
secretPhrase = "bla bla bla''

La fonction renvoie une chaîne JSON à décoder, avec les transactions et les pièces jointes à analyser. De plus, quelques variables sont initialisées.

Ensuite, nous devons interroger le compte de pari pour récupérer toutes les transactions entrantes.
Il s’agit de la requête que vous pouvez envoyer au serveur NXT pour l’exécuter:

Query = {'requestType': 'getBlockchainTransactions', 
'account': myAccount, 'type': '0', 'subtype': '0', 'executedOnly': 'true'}

Décoder JSON et le charger sur une variable pour un traitement ultérieur.

output = sendQuery(Query)
data = json.loads(output.decode('utf-8'))

Comme nous avons maintenant toutes les données, nous parcourons la liste et rejetons certaines des transactions dont nous n’avons pas besoin. Par exemple, nous n’avons pas besoin de traiter les transactions sortantes, donc nous continuons la boucle de l’élément suivant.

for i in data['transactions']:
  txAmount = i['amountNQT']
  txSender = i['senderRS']
  if txSender == myAccount:
      continue
  txRecipient = i['recipientRS']
  if txRecipient != myAccount:
      continue

Ensuite, nous retirons la pièce jointe, vérifions si elle n’est pas chiffrée et dépouille les blancs.

line = i['attachment']['message']
  lineIsText = i['attachment']['messageIsText']
  if line.strip() != "" and lineIsText == True:
    line = line.strip()

L’étape suivante consiste à faire correspondre le message soumis à l’expression régulière. Il doit satisfaire au format «Number: Number», le premier nombre peut comporter jusqu’à 3 chiffres.

 matchLine = re.match(r'(d{1,3}:d{1})(.*)', line, re.M|re.I)

Si le message ci-joint est de format correct, nous le traitons plus loin …

L’application de pari accepte jusqu’à 3 arguments de ligne de commande: id du jeu, le numéro de choix qui a gagné, et le troisième paramètre optionnel entre guillemets pour nommer le choix du gagnant pour la verbosité dans le message de paiement.

Par exemple, l’hôte de pari doit l’exécuter comme ceci:
Python3 bet.py 30 1 « L’équipe locale gagne »

L’application traite les transactions avec l’ID de jeu 30 et récompense les joueurs qui ont choisi ‘1’.
Le troisième argument peut être omis: python3 bet.py 30 1

Ensuite, nous devons calculer la somme d’argent soumise pour notre jeu, faire une liste de dictionnaires de joueurs qui ont deviné le nombre correct, et calculer la somme totale pour la distribution après l’hôte de paris reçoit son service facultatif coupé.

  if matchLine:
      if matchLine.group(1).split(':')[0] == sys.argv[1]:
        totalAmount += int(txAmount)
        if matchLine.group(1).split(':')[1] == sys.argv[2]:
          d = {txSender: matchLine.group(1).split(':')[1], 
'amount': txAmount}
          players.append(dict(d))
afterFee = float(totalAmount - totalAmount * serviceFee)

Nous avons des gagnants dans la liste des joueurs de dictionnaires, nous avons de l’argent à distribuer dans ‘afterFee’, nous allons maintenant traiter les paiements.

sumCorrect = 0
for i in players:
  for key in i:
    if i[key] == sys.argv[2]:
      sumCorrect += float(i['amount'])
for i in players:
  for key in i:
    if i[key] == sys.argv[2]:
      t = float(i['amount']) * (afterFee / sumCorrect)
      if t > afterFee:
        strSendAmount = str(int(afterFee))
      else:
        strSendAmount = str(int(t))
      if len(sys.argv) > 3:
        reply = sys.argv[3]
      else:
        reply = sys.argv[2]
      message = "Payout for correct bet in poll " 
+ sys.argv[1] + "; your reply: " + reply
      Query = {'requestType': 'sendMoney', 'recipient': key, 
      'amountNQT': strSendAmount, 'secretPhrase': secretPhrase, 
      'feeNQT': '100000000', 'deadline': '1440', 'broadcast': 'true', 
'message': message, 'messageIsText': 'true', 'messageIsPrunable': 'true'}
      sendQuery(Query)

Inutile de dire que l’application peut être améliorée pour traiter les erreurs, annuler les paris ou éventuellement permettre d’autres paramètres dans les messages attachés. Les messages joints peuvent être soumis avec le Nxt Client (NRS) ou à partir d’un portefeuille Web qui permet l’envoi de pièces jointes.

Pour effectuer des transactions sur le Nxt Blockchain, vous avez besoin de pièces NXT, que vous pouvez acheter directement, en échangeant des Bitcoins pour des NXT ou en assistant au projet Lucky Node en exécutant un nœud public Nxt (serveur Nxt).

Pour savoir comment participer au projet de nœud Lucky, veuillez visiter https://nxtforum.org.

Il ya plus d’une centaine d’appels API que vous pouvez faire sur le serveur Nxt, une liste complète avec des paramètres obligatoires et facultatifs et des exemples sont disponibles à https://nxtwiki.org/wiki/The_Nxt_API.

À votre santé!

blockchain-betting

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.

Programmation de la Blockchain Nxt pour le plaisir et le profit

Les Blockchains peuvent être utiles dans diverses applications, en faisant face à l’audience mondiale et en soutenant l’infrastructure interne d’une entreprise. Une chaîne de blocs est une base de données distribuée, une copie de la chaîne de blocs est stockée sur chaque noeud dans un réseau pair à pair. Cette redondance extrême peut être considérée comme inefficace, mais s’il vous plaît rester avec moi pour quelques minutes de la théorie des blocs de chaîne.

Comme chaque nœud valide toutes les transactions enregistrées dans la chaîne de blocs et que les transactions passées ne peuvent pas être annulées ou falsifiées comme dans un  »RDBMS » traditionnel, cette redondance rend le bloc-chaîne * immuable *, et c’est une proposition de valeur très importante de chaîne de blocs. L’immutabilité des données est quelque chose que les bases de données traditionnelles ne peuvent pas fournir. Vous pouvez ou ne pas avoir besoin d’immutabilité des données et de la confiance sans confirmation que les données n’ont pas été modifiées.

Dans ce tutoriel je suppose que vous avez besoin de ceci;

L’une des blockchains les plus polyvalentes et flexibles est la Nxt Blockchain (https://nxt.org). Il a plus d’une centaine d’appels API https://nxtwiki.org/wiki/The_Nxt_API

Aujourd’hui, vous apprendrez les bases de la programmation de la chaîne de blocs Nxt. Je n’utiliserai que deux appels API dans ce didacticiel. Avec plus d’une centaine d’appels API, les possibilités pour les programmeurs sont illimitées.

Logique d’Application

Un client d’une entreprise ou un employé d’une organisation télécharge un fichier via un formulaire Web.
Le fichier est renommé en un nom unique et est enregistré dans un emplacement quelconque sur le serveur.

Un an plus tard, le client / employé doit vérifier, à l’aide de de la chaîne de blocs Nxt, que le fichier n’a pas été modifié. Par exemple, cela peut être requis à des fins légales. Il n’a pas besoin d’être des fichiers. Les mémoires d’entreprise internes peuvent être hachés et stockés dans la base de données, pour être vérifiés lors d’une vérification ultérieure.

Nxt nous permet d’envoyer et d’enregistrer des messages arbitraires (AM) dans sa chaîne de blocs.

Chaque transaction sur la chaîne de blocs est payante. Si la taille de la transaction est importante, elle peut être coûteuse; Heureusement Nxt a un sous-type de AM appelé messages pouvant être supprimés. Ceux-ci sont taillés après 90 jours qui les rendent bon marché, ils sont disponibles pour la récupération des noeuds d’archives après 90 jours.

La taille maximale d’un message arbitraire dans la chaîne de blocs  Nxt est d’environ 42 Ko, la taille d’un bloc. Un message pouvant être supprimé de 1 KB coûte 1 NXT (0,03 $). 1 Ko est suffisant pour stocker un hachage d’un fichier et c’est notre coût final pour enregistrer de façon permanente un hachage dans le bloc distribué immuable Nxt.

Lorsque le client télécharge un fichier, je crée un hachage SHA256 du fichier et stocke le hachage dans la base de données du serveur de l’organisation. Pour simplifier j’ai choisi SQlite, mais vous pouvez utiliser Mysql, Postgresql, Oracle. Je vais utiliser PDO pour accéder à la base de données SQlite en PHP.

Lorsque nous n’utilisons pas la base de données immuable (blockchain), le fichier peut être modifié, le nouveau hash du fichier modifié enregistré dans la base de données, ce qui rend difficile de prouver que le fichier était comme ça depuis le début.

La chaîne de blocs vient à la rescousse

Chaque message pouvant être supprimé peut être récupéré à partir des noeuds d’archivage. Chaque enregistrement dans la chaîne de blocs est immuable. Vous pouvez être sûr que le hachage du fichier que vous avez téléchargé il ya un an, quand il est extrait de la chaîne de blocs, est le même hachage. Tout ce que vous avez besoin maintenant est de le comparer avec le hachage dans le RDBMS interne de l’organisation.

Conditions préalables:
PHP avec curl, json et certaines extensions db (j’utilise sqlite3). Un serveur web est facultatif, vous pouvez utiliser php-cli. Java 8 (Oracle ou OpenJDK pour exécuter Nxt). Logiciel de référence Nxt: https://nxtforum.org/nrs-releases/nrs-v1-10-1/.

Installez le NRS (logiciel de référence Nxt (en fonction du contexte indistinctement appelé Nxt Client ou Nxt Server)) et créez un compte. Financer le avec quelques pièces de monnaie. Vous pouvez échanger des Bitcoin vers NXT à un service d’échange comme https://shapeshift.io ou échanger avec quelqu’un sur https://nxtforum.org. Il est également possible de « détruire » certains NXT gratuits comme récompense pour l’exécution d’un nœud; Http://nxter.org/the-forging-bounty-lottery-campaign-will-pay-5-million-in-rewards-to-forgers-and-nxt-nodes/ 
Tout d’abord, nous créons une table de base de données simple pour notre application, rien de fantaisiste, vous pouvez ajouter d’autres types de colonnes si vous devez stocker plus d’informations. J’aime utiliser DB Browser pour SQLite de http://sqlitebrowser.org.
Faisons une base de données vide ‘files.db’ et l’enregistrons dans /home/lurker10/phptutorial/files.db
À l’aide de DB Browser pour SQLite, créez le tableau suivant.
CREATE TABLE "files" (
`id` INTEGER PRIMARY KEY AUTOINCREMENT,
`txid` TEXT,
`hash` TEXT,
`uploadtime` TEXT,
`filename` TEXT
)

‘Txid’ est le champ pour stocker l’id d’une transaction que nous recevons des Nxt lorsque la transaction est acceptée. Il est unique. ‘Hash’ est le sha256 hash du fichier.

Dans ce didacticiel je saute la partie de téléchargement de fichier du code pour la garder concise.

Supposons que le fichier est déjà téléchargé et stocké sur le serveur Web. Nous définissons la variable d’emplacement du fichier dans le code.

$uploadDir = "/home/lurker10/phptutorial/tmp/";
$fileName = "copy12345.tar"; 

Par défaut, le serveur Nxt écoute les demandes d’API sur le port 7876. Si vous l’exécutez sur la même machine que votre code php, votre code doit envoyer des requêtes à http://127.0.0.1:7876/nxt

Les autres variables importantes sont la phrase de passe du compte Nxt que vous avez créé et financé et le compte du destinataire.

Vous pouvez envoyer le message à vous-même, le destinataire peut être votre propre compte.

$host = "http://127.0.0.1:7876/nxt";
$secretPhrase = "your passphrase";
$recipientID = "NXT-XXXX-XXXX-XXXX-XXXXX";

La partie suivante du code est la fonction qui soumet une requête en utilisant curl dans une requête POST.

Pour effectuer une requête, nous devons définir les variables $payload et $payload_string et les envoyer à sendRequest(). Il est possible d’exécuter le Nxt Server via HTTPS et d’utiliser une boucle pour vérifier le certificat SSL, mais pour cette application simple, nous avons désactivé la vérification SSL dans la connexion en boucle.

Un autre point d’intérêt est le $errorDescription, json-decoded à partir de la réponse du serveur.

S’il ya un problème avec la requête ( « Pas assez de fonds » dans votre compte lorsque votre solde est zéro),
Vous devez ajouter une routine de gestion des erreurs. Je l’omet aussi. Pour cette application, je suppose que le serveur a répondu correctement et renvoyer la réponse dans l’application pour un traitement ultérieur.

function sendRequest($host, $payload, $payload_string) {
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $host);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT_MS, 10000);
curl_setopt($ch, CURLOPT_TIMEOUT_MS, 10000);
curl_setopt($ch, CURLOPT_POST, count($payload));
curl_setopt($ch, CURLOPT_POSTFIELDS, $payload_string);
$output = curl_exec($ch);
$curl_error = curl_error($ch);
curl_close($ch);
$errorDescription = trim(@json_decode($output)->errorDescription);
if ($errorDescription != "") { // perform error handling; return false; }
return $output;
}

Comme le fichier est déjà téléchargé, je crée un hachage sha256 du fichier et de l’horodatage.

$fileHash = hash_file("sha256", $uploadDir.$fileName);
$txTime = time();

Je vais utiliser PDO pour travailler avec la base de données.

Ouvrez le DB et insérez un nouvel enregistrement.

Nous ne savons pas le txid jusqu’à ce que nous parlons au serveur Nxt qui peut nous le donner quand la transaction est acceptée sur le réseau NXT, donc pour l’instant, je vais insérer null pour le txid.

$pdo = new PDO('sqlite:/home/lurker10/phptutorial/files.db');
$sql = "INSERT INTO files (txid, hash, uploadtime, filename)
VALUES (null, '$fileHash', '$txTime', '$fileName')";
$result = $pdo->exec($sql);

Ensuite, nous créons une requête à envoyer au serveur NXT.

Cette requête particulière est « sendMessage », vous pouvez trouver beaucoup plus de requêtes pour interagir avec la blockchain et leurs paramètres obligatoires et facultatifs à https://nxtwiki.org/wiki/The_Nxt_API.

Comme je l’ai dit plus tôt, les frais de transaction sont de 1 NXT. 1 NXT = 100 000 000 NQT (nanoquants).
1 NQT est la plus petite unité de dénomination en NXT identique à 1 satoshi en Bitcoin.
Le Nxt Server accepte les frais en NQT, nous payons donc exactement 100 millions de NQT (0,03 $)

Le paramètre « broadcast » peut être changé en false, dans ce cas, vous recevrez ‘transactionBytes’ dans la réponse, qui peut être diffusée sur le réseau plus tard en utilisant la requête ‘broadcastTransaction’. Mais aujourd’hui, je l’ai mis à «vrai» pour diffuser la transaction instantanément.

N’oubliez pas d’urlencode() le message. J’insère le nom de fichier séparé du hachage avec un deux-points dans le message.

$payload = array(
"requestType" => "sendMessage",
"recipient" => $recipientID,
"secretPhrase" => urlencode($secretPhrase),
"feeNQT" => 100000000,
"deadline" => 1440,
"broadcast" => "true",
"message" => urlencode($fileName . ":" . $fileHash),
"messageIsPrunable" => "true"
);
$payload_string = "";
foreach ($payload as $key => $value) {
$payload_string .= $key . "=" . $value . "&";
}
rtrim($payload_string, "&");

Envoyez la requête au serveur NXT en utilisant la fonction sendRequest ():

$output = sendRequest($host, $payload, $payload_string);

Et décoder la réponse JSON du serveur pour obtenir l’id de transaction:

if ($output != false) {
$txId = json_decode($output)->transaction;
}

Maintenant qu’il ya une réponse positive sur la transaction acceptée et que son ID est connu, mettons à jour l’enregistrement dans le db interne.

$lastId = $pdo->lastInsertId();
$sql = "UPDATE files SET txid = '$txId' where id = '$lastId'";
$result = $pdo->exec($sql);

Nous pouvons éventuellement fournir ces liens au client pour des références futures et pour prouver que le hash a été téléchargé:

echo "NXT Transaction ID: " . $txId . ",
JSON response";
echo "

Utilisez ces liens pour vérifier le hash Sha256 de votre fichier enregistré dans notre base de données interne contre l’enregistrement permanent dans le bloc block NXT:

" . $fileHash;

En option, envoyez un e-mail au client, le $txId, qui pourra ensuite être utilisé pour vérifier le hachage ou, autrement, leur donner des informations de base sur la récupération du hachage à partir du db interne et le comparer au hachage stocké par la blockchain à l’avenir, par horodatage ou avec d’autres critères.

Cette application n’inclut pas l’authentification des utilisateurs. Normalement, le client ou l’utilisateur d’un service intranet pourrait voir ses fichiers après s’être authentifié sur le site.

Cette application suppose également que l’application de vérification est hors de portée du responsable de la base de données interne pour éviter de falsifier les résultats de la vérification.

Maintenant, l’enregistrement est enregistré dans la base de données de l’entreprise. Afficher l’enregistrement db pour confirmer qu’il est là.

$sth = $pdo->prepare("SELECT id, txid, hash, uploadtime, filename FROM files ORDER BY id DESC");
$sth->execute();
$result = $sth->fetch(PDO::FETCH_OBJ);
if ($result != false) {
var_dump($result);
}

L’Application de Vérification

Pour utiliser l’application de vérification de hachage, le client doit avoir l’ID de transaction dans la chaîne de blocs NXT
Transmis à la Nxt Blockchain.

Supposons que le client ne l’a, enregistré dans l’archive de courrier ou récupéré par d’autres moyens.

$txId = "111111111111111111";


Voyons ce que notre base de données interne a pour le hash du fichier. Fetch et l’enregistrer dans $ hashInDb.

$pdo = new PDO('sqlite:/home/lurker10/phptutorial/files.db');
$sth = $pdo->prepare("SELECT hash FROM files where txid = '$txId'");
$sth->execute();
$result = $sth->fetch(PDO::FETCH_OBJ);
if ($result != false) {
$hashInDb = $result->hash;
}

Envoyer une requête au serveur NXT et extraire toutes les informations stockées dans le bloc NXT pour la transaction avec l’ID donné.

$payload = array (
"requestType" => "getTransaction",
"transaction" => $txId
);
$payload_string = "";
foreach ($payload as $key => $value) {
$payload_string .= $key . "=" . $value . "&";
}
rtrim($payload_string, "&");

$output = sendRequest($host, $payload, $payload_string);

Décoder la réponse JSON et extraire le champ de la pièce jointe où le hachage est stocké.

Dans la première partie de l’application, nous avons enregistré le nom de fichier séparé du hachage avec un deux-points.
Maintenant, nous extrayons simplement la partie de hachage du message arbitraire.

$attachmentPlainData = json_decode($output)->attachment->message;
$hashInBlockchain = explode(":", $attachmentPlainData)[1];

Et comparer ce que nous avons dans la base de données de l’entreprise avec ce qui a été enregistré il ya un an dans la chaîne de blocs Nxt.

if ($hashInDb == $hashInBlockchain)
echo "Hashes are identical";
else
echo "Hashes are not identical";

NXT-crypto-developer