Les reçus et la topologie du réseau
Une blockchain vit de ses nœuds qui se transmettent blocs et transactions. La preuve de participation mesure précisément ce service. Lorsqu’un nœud enregistré reçoit des données d’un autre nœud enregistré, il répond par un reçu, une courte déclaration signée avec sa clé de nœud. La preuve du travail vient donc du pair qui l’a reçu, et non du nœud qui le revendique. Le choix des pairs qui comptent n’appartient pas non plus aux nœuds : tous les 40 blocs, le protocole mélange le registre à l’aide de la graine du bloc et attribue à chaque nœud ses pairs prioritaires.
Pairs prioritaires : la topologie
Le registre est remélangé une fois par période de 40 blocs (topology_period_blocks), soit environ 10 minutes. Au premier bloc d’une période, chaque nœud enregistré reçoit une clé de tri :
key = SHA3-256(seed of the period's first block (64 bytes)
‖ node id (8 bytes, little-endian)
‖ period height (8 bytes, little-endian)
‖ "zbc-topology-v2")
Trier le registre selon ces clés donne la liste mélangée. Chaque nœud se voit attribuer comme pairs prioritaires une fenêtre de P nœuds consécutifs de cette liste, P étant max_assigned_peers : 12 sur le mainnet et 8 sur le devnet. La fenêtre du nœud en position i commence à la position (i × P) mod L, L étant la longueur de la liste ; la fenêtre compte toujours P nœuds complets, et ses points de départ sont étalés lorsque P et L ont un facteur commun. La relation est à sens unique : que A soit un pair prioritaire de B ne fait pas de B un pair prioritaire de A.
Comme l’ordre dépend d’une graine qu’aucun d’eux ne contrôle, et qu’il change toutes les 10 minutes, un groupe de nœuds complices ne peut pas s’arranger pour être pairs les uns des autres et ne se porter garants que mutuellement. La vitesse de connexion n’y joue aucun rôle, et personne ne publie de liste de pairs.
Ce que dit un reçu
Un reçu fait 232 octets :
| Champ | Octets |
|---|---|
| clé de nœud de l’expéditeur (le nœud qui a poussé les données) | 32 |
| clé de nœud du destinataire (le nœud qui signe) | 32 |
| bloc de référence : dernier bloc du destinataire, hauteur | 4 |
| bloc de référence : hachage | 32 |
| type de donnée : 1 pour un bloc, 2 pour une transaction | 4 |
| hachage de la donnée : quel bloc ou quelle transaction a été reçu | 32 |
| dernière racine de lot de reçus du destinataire | 32 |
| signature Ed25519 du destinataire sur les 168 octets ci-dessus | 64 |
Seuls les nœuds enregistrés donnent et conservent des reçus, et uniquement pour des données poussées par un autre nœud enregistré. Un nœud non enregistré peut suivre et vérifier la chaîne, mais il ne donne ni ne gagne de reçus. Un reçu ne nomme aucune chaîne : contrairement aux transactions (voir les signatures liées à la chaîne), il ne porte aucune liaison à une chaîne.
Les reçus n’ont rien à voir avec les confirmations de portefeuille ou les remboursements de frais, qui sont des enregistrements ordinaires de transactions et de soldes.
Lots et publication
L’expéditeur conserve les reçus qu’il gagne. Pour chaque hauteur, il les regroupe en un lot de 1 000 au plus, triés par signature, sous une racine de Merkle. Lorsqu’il produit un bloc à lui, il y publie un échantillon de ses reçus, de deux sortes : des reçus non liés, présentés tels quels, et des reçus liés, présentés avec une preuve de Merkle par rapport à une racine de lot antérieure. Le logiciel de référence échantillonne des reçus datant d’environ 40 blocs ; c’est son comportement, pas une règle de validité.
Ce que vérifient les validateurs
Pour chaque reçu publié dans un bloc, chaque nœud vérifie les points suivants, où n est le nombre de nœuds enregistrés :
- la signature du destinataire ;
- que le hachage du bloc de référence est bien celui du bloc de cette chaîne à cette hauteur ;
- son âge : un reçu expire après max(max(100, 2 × n) + 1,
receipt_lifecycle) blocs, soit 518 400 blocs (environ 90 jours) sur le mainnet ; - à partir de la hauteur 40, que le signataire d’un reçu non lié était un pair prioritaire du producteur du bloc pendant la période d’où provient le reçu ;
- à partir de la hauteur 80, la preuve de Merkle de chaque reçu lié ;
- le nombre : au plus 2 × min(n − 1, P) reçus, et jamais plus de 200.
Certains points ne sont pas des règles de validité, et il ne faut pas les y voir : les validateurs ne vérifient pas que l’expéditeur du reçu est le producteur du bloc, que le reçu est nouveau, que sa donnée date d’environ 40 blocs, ni qu’une racine liée est déjà apparue sur la chaîne.
Des reçus au score
Relayer rapporte des reçus, pas du score. Le score ne bouge que lorsque le nœud publie ses reçus dans un bloc à lui : présenter plus qu’un pivot d’environ la moitié de ce qu’il pourrait présenter fait monter son score, en présenter moins le fait baisser. Aucun score ne bouge avant la hauteur 40. Voir le score de participation pour les détails, et la loterie coinbase pour la façon dont le score se transforme en revenu.