Wiki ZooBC
Proof of Participation

Le tirage : qui produit le bloc suivant

Dans la preuve de participation, personne ne fait la course pour produire un bloc. Pour chaque nouvelle hauteur, un tirage aléatoire sur le registre des nœuds désigne les producteurs dans l’ordre : le premier tirage désigne le producteur du tour 1, le deuxième celui du tour 2, et ainsi de suite. Chaque nœud effectue le même tirage sur les mêmes données et obtient la même liste : chaque nœud sait donc qui peut produire le bloc suivant et refuse un bloc venant de quiconque d’autre.

Une loterie que chacun peut refaire

Un tirage équitable exige un aléa que personne ne contrôle et que tout le monde peut reproduire. ZooBC le prend dans le bloc précédent. Chaque bloc porte une graine de 64 octets, une valeur que son producteur ne peut pas choisir (voir la graine du bloc). La graine initialise un générateur de nombres pseudo-aléatoires, et chaque nombre que fournit le générateur choisit une entrée dans la liste des nœuds qui peuvent être tirés.

Comme la graine d’un bloc n’existe qu’une fois ce bloc créé, personne ne connaît à l’avance l’ordre du bloc d’après : l’ordre n’est normalement connu qu’un bloc à l’avance. (Un attaquant qui détient de nombreux sièges peut parfois voir plus loin ; voir la graine du bloc.) Et comme chaque nœud détient le même bloc précédent et le même registre, chaque nœud calcule la même liste. Il n’y a ni casse-tête à résoudre, ni tableau de service publié, ni coordinateur.

La graine du bloc précédent est hachée avec l’étiquette zbc-blocksmith et alimente un générateur qui désigne le producteur de chaque tour ; chaque nœud calcule la même liste.
La graine du bloc précédent est hachée avec l’étiquette zbc-blocksmith et alimente un générateur qui désigne le producteur de chaque tour ; chaque nœud calcule la même liste.

La liste dans laquelle on tire

Le tirage s’effectue dans l’ensemble sélectionnable :

  • le registre actif tel qu’il était au bloc précédent, c’est-à-dire les nœuds admis (enregistrés) ; les nœuds en file d’attente n’en font pas partie ;
  • ordonné par identifiant de nœud, du plus petit au plus grand (l’identifiant d’un nœud est tiré des 8 premiers octets de sa clé de nœud) ;
  • moins tout nœud frappé d’une suspension en vigueur (voir les tours manqués). Si leur retrait ne laissait personne, c’est l’ensemble actif complet qui est utilisé.

Si tous les nœuds actifs sont suspendus, le meilleur nœud en file d’attente ayant maintenu son assiduité est ajouté comme candidat à la reprise (voir la file d’attente), afin que la chaîne puisse toujours redémarrer ; un bloc produit par ce nœud l’admet aussitôt.

Les blocs sont jugés strictement d’après le registre tel qu’il était au bloc précédent, sans repli sur aucune autre hauteur. Un bloc venant d’un nœud qui n’a pas été tiré pour son tour est refusé par tous les nœuds.

Le générateur

La recette exacte, que toute implémentation doit suivre bit pour bit :

h = SHA3-256("zbc-blocksmith" ‖ seed of the previous block)
v = bytes 24 to 31 of h, read as a big-endian 64-bit number
Splitmix64(v) seeds a xoroshiro128+ generator
each draw: r = the next non-negative 63-bit number
the draw names entry (r mod n) of the selectable set, n = its size

Le tirage 1 désigne le producteur du tour 1, le tirage 2 celui du tour 2, et ainsi de suite (voir les tours et leur cadence). Les tirages sont indépendants : le même nœud peut donc être désigné plusieurs fois dans une même liste.

L’étiquette zbc-blocksmith distingue ce tirage des autres choix aléatoires tirés des graines de bloc, chacun utilisant sa propre étiquette : zbc-coinbase pour la loterie coinbase, zbc-receipt et zbc-receipt-datum pour les reçus, zbc-topology-v2 pour la topologie des pairs et zbc-apps pour les applis.

Chaque siège a la même chance

Chaque tirage choisit chaque entrée de l’ensemble sélectionnable avec la même probabilité. Rien d’autre n’intervient : ni le matériel du nœud, ni le solde de son propriétaire, ni sa mise, ni son score de participation. Un opérateur qui détient 3 des 30 sièges actifs produit environ un bloc sur dix.

C’est le premier objectif de conception de la preuve de participation : un pouvoir de production de blocs uniforme. La seule voie vers plus de pouvoir passe par plus de sièges, et les sièges ne s’obtiennent que par la file d’attente, une admission à la fois, à un rythme fixé par le protocole (voir le rythme d’admission). Tenir le score à l’écart du tirage est délibéré : un nœud au score élevé gagne davantage, mais il ne produit pas plus de blocs, ne choisit pas plus de graines et n’a pas plus d’occasions de laisser des transactions de côté.

Deux raffinements

Voir aussi