La vérification de paiement simplifiée dans Bitcoin (BTC)
Tout comprendre sur les SPV dans Bitcoin – Bitcoin est un système qui ne nécessite théoriquement pas de tiers de confiance pour vérifier qu’une transaction a eu lieu. Néanmoins, faire fonctionner un nœud complet peut être quelque chose de rebutant pour l’utilisateur moyen et celui-ci peut être tenté de se tourner vers un service qui s’en chargerait à sa place. Heureusement, il existe une solution intermédiaire : la vérification de paiement simplifiée implémentée dans certains portefeuilles légers.
Qu’est-ce que la vérification de paiement simplifiée ?
Le réseau Bitcoin est un réseau pair-à-pair, c’est-à-dire que tous ses participants (appelés « nœuds ») ont le même niveau de privilège.
Ces nœuds complets téléchargent toute la chaîne de blocs, valident les règles de consensus et se chargent de relayer les blocs et les transactions. C’est une charge : la chaîne de Bitcoin pèse aujourd’hui environ 330 Go de données et l’ensemble des UTXO plus de 4 Go, la zone mémoire des transactions représente environ 100 Mo, et la taille moyenne des blocs minés toutes les 10 minutes est de 1,3 Mo.
On en conviendra, un tel volume de données n’est pas adapté pour un utilisateur qui souhaiterait effectuer des paiements en personne, avec un téléphone portable par exemple. C’est pour cette raison qu’il existe des logiciels appelés » portefeuilles légers » qui permettent d’utiliser Bitcoin sans avoir à faire tourner un nœud complet. Ils sont parfaitement appropriés pour les appareils moins puissants. Ces portefeuilles peuvent se connecter aux nœuds du réseau, mais surtout ils peuvent le faire en conservant une relative indépendance vis-à-vis de ces nœuds grâce à une méthode appelée « vérification de paiement simplifiée ».
La vérification de paiement simplifiée, nommée Simplified Payment Verification ou SPV en anglais, a été décrite pour la première fois par Satoshi Nakamoto au sein du livre blanc de Bitcoin. Néanmoins, elle n’était pas codée dans le logiciel au lancement de la chaîne en 2009 et son implémentation a été confiée aux développeurs de portefeuilles légers.
C’est Mike Hearn, l’ingénieur de Google ayant contacté Satoshi en avril 2009, qui a contribué en premier au développement de la vérification de paiement simplifiée. En effet, celui-ci a été à la base de bitcoinj, une implémentation du protocole Bitcoin programmée en Java, qui permettait entre autres une meilleure compatibilité avec les applications sur Android (dont le Java est le langage natif). Mike Hearn avait d’ailleurs parlé de ce projet à Satoshi avant la disparition de ce dernier.
Le premier portefeuille a avoir implémenté la vérification de paiement simplifiée de manière fonctionnelle est le Bitcoin Wallet for Android, un portefeuille pour mobile développé initialement par Andreas Schildbach et dont la première version remonte à mars 2011. Plusieurs personnes ont apporté leur aide à ce projet, dont Mike Hearn lui-même, celui-ci étant disponible en licence libre et publiquement. Bien qu’il ait perdu en popularité, le Bitcoin Wallet for Android existe encore aujourd’hui et est toujours fonctionnel.
Par la suite, cette vérification a été intégrée de manière plus ou moins directe dans d’autres portefeuilles comme le Bread Wallet (BRD) ou Electrum.
Comment ça fonctionne ?
La vérification de paiement simplifiée fonctionne grâce à la structure des blocs et à la façon dont ils sont chaînés. Comme on l’a dit, elle a été conceptualisée dès 2008 au sein du livre blanc de Bitcoin, dans la section 8 pour être exact. Satoshi Nakamoto la décrivait comme suit :
« Il est possible de vérifier les paiements sans faire fonctionner un nœud complet du réseau. Un utilisateur a seulement besoin de conserver une copie des entêtes des blocs de la plus longue chaîne de preuve de travail, qu’il peut obtenir en interrogeant les nœuds du réseau jusqu’à ce qu’il soit convaincu qu’il possède la plus longue chaîne, et obtenir la branche de Merkle liant la transaction au bloc dans lequel elle est horodatée. Il ne peut pas vérifier la transaction par lui-même, mais en la reliant à un endroit de la chaîne, il peut voir qu’un nœud du réseau l’a acceptée, et les blocs ajoutés après le confirment. »
En guise d’illustration, ce schéma y était présent :
Dans Bitcoin, la chaîne de preuve de travail n’est pas à proprement parler une chaîne de blocs, mais une chaîne d’entêtes. Chaque entête contient les données essentielles du bloc qu’il représente : sa version, son horodatage, sa difficulté de minage, son nonce, l’identifiant du bloc précédent, et surtout une racine de Merkle qui lie cryptographiquement le reste du bloc à l’entête. Les clients légers conservent la chaîne des entêtes, ce qui leur permet de déterminer la chaîne possédant le plus de preuve de travail accumulée, et ainsi de connaître l’identifiant de tous les blocs valides. Puisque chaque entête pèse 80 octets, la taille des données à conserver reste modeste pour des appareils modernes : environ 4 Mio par an, ce qui représente un peu plus de 51 Mio en mars 2021.
La seconde partie du bloc est constituée des transactions en tant que telles. Celles-ci sont agencées dans un arbre de Merkle, aussi appelé arbre de hachage, qui est une structure de données permettant de vérifier l’intégrité d’un ensemble d’informations sans les avoir nécessairement toutes au moment de la vérification. Les transactions sont hachées un première fois, puis les empreintes résultantes sont concaténées et hachées à nouveau. Le procédé est répété jusqu’à ce qu’il ne reste qu’une seule empreinte, la racine de Merkle, qui est placée dans l’entête.
Plus spécifiquement, les transactions sont d’abord hachées grâce à la double application de la fonction SHA256 (dSHA256
) :
HA = dSHA256( txA )
Puis, les empreintes sont concaténées deux à deux et hachées une nouvelle fois par cette même fonction :
HAB = dSHA256( HA + HB )
Dans le cas où il y a un nombre impair d’empreintes, la dernière est combinée avec elle-même :
HEFEF = dSHA256( HEF + HEF )
Le procédé est itéré jusqu’à obtenir une empreinte unique, la fameuse racine.
Le fait que la racine soit placée dans l’entête interdit à quiconque de modifier l’ensemble des transactions : en effet, l’ajout, la modification ou la suppression d’une transaction modifierait la racine de Merkle et rendrait invalide le bloc en question. De plus, cette structure en arbre permet de vérifier efficacement la présence d’une transaction dans le bloc, grâce à la connaissance de la branche correspondante. Cette branche est obtenue auprès des nœuds du réseau.
Par exemple, si un utilisateur veut vérifier que la transaction txD
a été confirmée, il devra demander les empreintes HC
, HAB
et HEFEF
aux nœuds du réseau, procéder aux différents calculs et s’assurer que le résultat correspond à la racine de Merkle HABCDEFEF
. Cela lui épargnera de télécharger l’entièreté du bloc. Ainsi, pour un bloc de 1 Mo contenant 4096 transactions, l’utilisateur ne devra télécharger théoriquement que 12 empreintes représentant au total 768 octets de données.
Manque de fiabilité et confidentialité
Le mode léger utilisant la vérification de paiement simplifiée permet donc deux choses :
- connaître la plus longue chaîne de preuve de travail grâce à la chaîne des entêtes ;
- pouvoir s’assurer de la présence d’une transaction dans un bloc.
Néanmoins, ce mode de vérification n’est pas parfait et souffre de quelques défauts.
Le premier est le manque de fiabilité qui, sans être absolu, peut poser problème. Tout d’abord, en temps normal, les nœuds du réseau auxquels est connecté le portefeuille léger ne peuvent pas lui mentir en inventant une transaction qui n’existe pas, mais peuvent en revanche lui « mentir » par omission en refusant de lui transmettre les informations nécessaires. Cela est un problème, et rend les portefeuilles de ce type sensibles aux attaques Sybil. Néanmoins, il peut être partiellement contrebalancé en augmentant la diversité des connexions sur le réseau.
Ensuite, les nœuds SPV sont plus vulnérables si la chaîne est attaquée par une entité disposant de la puissance de calcul majoritaire. Ce cas a été décrit par Satoshi Nakamoto dans le livre blanc :
« De ce fait, la vérification est fiable tant que les nœuds honnêtes contrôlent le réseau, mais est plus vulnérable si le réseau est maîtrisé par un attaquant. Alors que les nœuds du réseau peuvent vérifier les transactions par eux-mêmes, la méthode simplifiée peut être trompée par des transactions forgées par l’attaquant aussi longtemps que celui-ci maîtrise le réseau. Une stratégie pour se protéger serait d’accepter les alertes des nœuds du réseau lorsqu’ils détectent un bloc invalide, invitant le logiciel de l’utilisateur à télécharger le bloc complet et les transactions suspectes pour confirmer l’incohérence. Les entreprises qui reçoivent fréquemment des paiements voudront probablement toujours faire fonctionner leurs propres nœuds afin d’obtenir une sécurité plus indépendante et une vérification plus rapide. »
Les alertes décrites par Satoshi sont aujourd’hui appelées preuves de fraude et sont toujours en phase de développement.
Ainsi, bien que moins fiables que les nœuds complets, les portefeuilles SPV sont tout de même utilisables dans une grande majorité des cas.
Le second défaut de la vérification de paiement simplifiée est le manque de confidentialité, qui constitue déjà un plus gros problème que le premier. En effet, ce type de vérification demande au portefeuille léger de faire des requêtes auprès des nœuds du réseau. Cela va, dans une implémentation naïve, révéler au réseau l’ensemble de ses adresses et de ses transactions. Pour remédier à ce problème, certains portefeuilles légers ont implémenté les filtres de Bloom décrits dans le BIP-37 : tout en requérant l’échange d’un plus grand nombre d’informations, ceux-ci offrent à l’utilisateur un plus grand niveau de confidentialité.
Une amélioration à ce système est Neutrino, décrit dans les BIP 157 et le 158, qui fait usage du codage de Golomb-Rice et demande une plus grande bande passante. En plus d’accroître la confidentialité, Neutrino améliore aussi la fiabilité et s’adapte donc mieux à la gestion de canaux du réseau Lightning.
Enfin, un troisième défaut, bien que plus subtil, est l’absence de validation du protocole. En passant par un portefeuille SPV, l’utilisateur ne vérifie en effet pas toutes les règles de consensus de Bitcoin. Concrètement, il ne s’assure pas que la politique monétaire est bien respectée et que les mineurs ne créent pas plus de bitcoins que prévu. En cela, il n’est pas totalement souverain, dépend partiellement d’un tiers de confiance et affaiblit la décentralisation de la validation. C’est pourquoi les détenteurs les plus fortunés et les marchands les plus actifs ont une tendance toute particulière à faire tourner un nœud.
Conclusion
La vérification de paiement simplifiée est donc une méthode astucieuse, conceptualisée dès les origines, qui contribue au succès de Bitcoin en permettant aux utilisateurs néophytes et occasionnels de pouvoir interagir facilement avec le protocole. Il s’agit essentiellement d’un compromis entre la gestion d’un nœud complet, chère aux puristes, et la confiance aveugle dans un tiers de confiance, comme c’est par exemple le cas dans les solutions custodiales.