Bulletproofs expliqués : comment vérifier des montants masqués

· 7 min de lecture

Les Bulletproofs sont des preuves d’intervalle à divulgation nulle de connaissance, courtes, qui permettent à une cryptomonnaie de masquer chaque montant de transaction tout en laissant chaque nœud vérifier qu’aucun coin n’a été créé. Ce guide explique les engagements de Pedersen, pourquoi les montants masqués ont besoin de preuves d’intervalle, comment les Bulletproofs gardent ces preuves compactes et comment Blocknet les utilise sur chaque sortie.

Que sont les Bulletproofs ?

Réponse courte

Les Bulletproofs sont des preuves courtes à divulgation nulle de connaissance, publiées par Bünz, Bootle, Boneh, Poelstra, Wuille et Maxwell en 2018. Dans les cryptomonnaies, elles prouvent qu’un montant masqué se situe dans un intervalle valide, par exemple de 0 à 2^64, sans le révéler. Elles ne nécessitent aucune configuration de confiance, et leur taille ne croît qu’avec le logarithme de l’intervalle.

L’article, Bulletproofs: Short Proofs for Confidential Transactions and More, a été présenté à l’IEEE Symposium on Security and Privacy en 2018. Ses auteurs les ont conçues pour les transactions confidentielles, où les montants d’une blockchain sont remplacés par des engagements. Pour comprendre pourquoi une telle preuve est nécessaire, il faut partir de l’engagement.

Qu’est-ce qu’un engagement de Pedersen ?

Un engagement (commitment) est la version cryptographique d’une enveloppe scellée. Vous mettez un nombre dedans, montrez l’enveloppe à tout le monde et pouvez plus tard prouver ce qu’elle contenait. Personne ne peut lire le nombre à travers l’enveloppe, et vous ne pouvez pas y glisser un autre nombre après coup.

Un engagement de Pedersen, décrit par Torben Pedersen en 1991, réalise cela avec des points d’une courbe elliptique. Pour s’engager sur un montant v, un portefeuille choisit un secret aléatoire r, appelé facteur d’aveuglement, et calcule :

C = v·G + r·H

G et H sont deux points publics fixes de la courbe, choisis pour que personne ne sache exprimer l’un comme un multiple de l’autre. Le résultat C est un seul point de 32 octets. Il a deux propriétés :

Comment les nœuds peuvent-ils vérifier une transaction qu’ils ne peuvent pas lire ?

Réponse courte

Les engagements de Pedersen peuvent s’additionner. La somme de deux engagements est un engagement sur la somme de leurs montants, les facteurs d’aveuglement s’additionnant eux aussi. Un nœud additionne les engagements d’entrée d’une transaction d’un côté, ses engagements de sortie plus les frais de l’autre, et vérifie que les deux totaux correspondent : il confirme ainsi l’équilibre sans voir aucun montant.

Additionner deux engagements donne (v1 + v2)·G + (r1 + r2)·H, qui est lui-même un engagement sur v1 + v2. L’expéditeur choisit les facteurs d’aveuglement de sorte que l’aveuglement total des entrées égale celui des sorties. Si les montants s’équilibrent aussi, la différence entre la somme des entrées et celle des sorties vaut exactement zéro, et n’importe quel nœud peut le vérifier.

Les frais de réseau sont le seul nombre public d’une transaction. Les nœuds les transforment en engagement avec un facteur d’aveuglement nul et l’ajoutent du côté des sorties, si bien que la vérification devient : entrées = sorties + frais.

Pourquoi les montants masqués ont-ils besoin de preuves d’intervalle ?

L’arithmétique des engagements fonctionne modulo un très grand nombre, l’ordre du groupe de la courbe, qui vaut environ 2^252. Dans cette arithmétique, un montant « négatif » n’est qu’un énorme montant positif. Quelqu’un pourrait dépenser une entrée valant 10 coins et créer deux sorties, l’une valant 11 et l’autre « moins 1 ». Les engagements s’équilibreraient parfaitement, et 1 coin apparaîtrait à partir de rien, à l’insu de tous les observateurs.

Une preuve d’intervalle comble cette faille. Elle prouve que le montant contenu dans un engagement se situe entre 0 et 2^64 sans dire lequel. Avec chaque sortie ainsi bornée, quelques sorties ne peuvent jamais totaliser un nombre assez grand pour dépasser l’ordre du groupe et revenir à zéro : des engagements équilibrés signifient donc des montants équilibrés.

Les conceptions antérieures de transactions confidentielles utilisaient des preuves d’intervalle dont la taille croissait linéairement avec le nombre de bits. Les Bulletproofs ne croissent qu’avec le logarithme, ce qui ramène une preuve de 64 bits à quelques centaines d’octets.

Comment fonctionnent les Bulletproofs ?

Un Bulletproof prouve un intervalle en trois étapes.

  1. Décomposer le montant en bits. Un montant de 64 bits devient un vecteur de 64 bits. Le prouveur s’engage sur ce vecteur et montre deux faits à son sujet : chaque entrée vaut 0 ou 1, et les bits, pondérés par les puissances de deux, totalisent le montant engagé.
  2. Transformer ces faits en un seul produit scalaire. À l’aide de défis aléatoires, le prouveur réunit toutes ces conditions en une seule affirmation sur le produit scalaire de deux vecteurs. Comme les défis sont aléatoires, une affirmation fausse ne passe qu’avec une probabilité négligeable.
  3. Prouver le produit scalaire par divisions successives. À chaque tour, le prouveur envoie deux points de la courbe, L et R, et les deux vecteurs sont repliés à la moitié de leur longueur. Après log2(64) = 6 tours, il ne reste qu’une seule paire de nombres.

C’est de ces divisions successives que vient la taille. Le résumé de l’article évalue une preuve d’intervalle à 2·log2(n) + 9 éléments de groupe et de corps pour un intervalle de n bits. Pour 64 bits, cela fait 12 points pour les six tours plus 9 autres, soit 21 éléments au total, ou 672 octets quand chaque élément fait 32 octets.

La preuve est non interactive. Au lieu d’un vérificateur qui envoie des défis en direct, les deux parties les dérivent en hachant la transcription de la preuve, une technique standard appelée heuristique de Fiat-Shamir. Les Bulletproofs ne nécessitent pas non plus de configuration de confiance : les générateurs sont publics et dérivés ouvertement, et la sécurité repose uniquement sur l’hypothèse du logarithme discret. Plusieurs preuves peuvent être agrégées en n’ajoutant qu’un nombre logarithmique d’éléments, et la vérification peut se faire par lots.

Qui utilise les Bulletproofs ?

Monero a activé les Bulletproofs lors de sa mise à niveau du réseau du 18 octobre 2018 (la version v0.13.0) pour réduire la taille des transactions. La bibliothèque Rust bulletproofs du projet dalek-cryptography les implémente sur le groupe Ristretto de Curve25519, et la bibliothèque cryptographique de Blocknet est construite sur elle.

Comment Blocknet masque-t-il chaque montant ?

Sur Blocknet, chaque sortie de chaque transaction contient un engagement de Pedersen à la place d’un montant, et chaque sortie porte son propre Bulletproof de 64 bits. La confidentialité fait partie du format des transactions, sans mode transparent : il n’existe aucun moyen d’envoyer un paiement avec un montant visible.

Voici ce qu’un nœud vérifie avant d’accepter une transaction :

Vous pouvez le constater sur l’explorateur Blocknet. La page d’une transaction indique ses montants comme « hidden · Pedersen commitments », et chaque sortie affiche son engagement, un mémo chiffré et une preuve d’intervalle de « 672 bytes · Bulletproof », la taille que prévoient les calculs ci-dessus.

Le destinataire voit quand même le vrai montant. Chaque sortie porte le montant chiffré avec le secret que partagent les portefeuilles de l’expéditeur et du destinataire, et le portefeuille du destinataire le déchiffre avec la clé de visualisation privée. Le montant est visible par les deux personnes concernées par le paiement, et par personne d’autre.

Les montants masqués fonctionnent avec les autres couches de Blocknet : les signatures de cercle sur 16 sorties masquent l’expéditeur, les adresses furtives à usage unique masquent le destinataire, et Dandelion++ masque le point d’entrée d’une transaction dans le réseau. Le guide des fonctions de confidentialité de Blocknet les passe toutes en revue.

Obtenez vos propres BNT confidentiels

Une façon simple d’obtenir des coins aux montants masqués est de les miner. Blocknet utilise une preuve de travail Argon2id gourmande en mémoire que vous pouvez miner sur un ordinateur ordinaire, et seine la mine sur votre CPU, avec vos éventuels GPU NVIDIA en parallèle, en s’optimisant tout seul sans configuration. Chaque paiement que bntpool.com vous envoie arrive sous forme de sortie confidentielle avec un engagement et un Bulletproof. Le guide de minage vous mène du téléchargement aux premiers shares acceptés en quelques minutes.

Questions fréquentes

Les Bulletproofs nécessitent-ils une configuration de confiance (trusted setup) ?

Non. Les Bulletproofs reposent uniquement sur l'hypothèse du logarithme discret, la même que celle des signatures sur courbes elliptiques, et utilisent des paramètres publics que chacun peut dériver. Il n'y a ni cérémonie de configuration ni secret que quelqu'un devrait détruire ensuite, et des cryptomonnaies de confidentialité comme Monero et Blocknet les utilisent pour leurs preuves d'intervalle.

Quelle est la taille d'une preuve d'intervalle Bulletproofs ?

Un seul Bulletproof de 64 bits contient 2 × log2(64) + 9 = 21 éléments. Sur le groupe Ristretto, chaque élément occupe 32 octets : chaque preuve fait donc 672 octets, et l'explorateur Blocknet affiche exactement cette taille pour chaque sortie. La taille croît avec le logarithme de l'intervalle, donc doubler le nombre de bits n'ajoute que deux éléments.

Qui peut voir le montant d'une transaction Blocknet ?

Seuls l'expéditeur et le destinataire. La chaîne stocke un engagement de Pedersen et une preuve d'intervalle pour chaque sortie, ainsi que le montant chiffré avec le secret que partagent les deux portefeuilles. Le portefeuille du destinataire le déchiffre avec la clé de visualisation privée. Les frais de réseau sont le seul nombre public, afin que les nœuds puissent les intégrer à la vérification de l'équilibre.

Comment les nœuds savent-ils qu'aucun coin n'a été créé si les montants sont masqués ?

Chaque nœud vérifie deux choses pour chaque transaction. Les engagements de Pedersen doivent s'additionner, de sorte que les entrées égalent les sorties plus les frais, et chaque sortie doit porter une preuve d'intervalle valide montrant que son montant se situe entre 0 et 2^64. Ensemble, ces vérifications excluent toute inflation cachée sans révéler un seul montant.