Les smart contracts avec Bitcoin (2/3) : Le langage de script
Acheter Bitcoin (BTC)
Partenaire Bitpanda
Dans le précédent article, nous avons vu que Bitcoin utilisait un langage de programmation pour la validation de ses transactions. Ce langage, baptisé de manière peu originale Script, permet un large éventail d'actions et c'est lui qui est utilisé pour écrire les fameux smart contracts. Nous allons voir dans cet article comment il fonctionne et comment il intervient dans les opérations les plus simples au sein de Bitcoin.
Pour rappel, l'entièreté du protocole est basé sur le concept de sortie transactionnelle non dépensée, désignée usuellement sous le nom d'UTXO (Unspent Transaction Output). Une transaction dans Bitcoin consiste à déverrouiller un ou plusieurs de ces UTXO en entrée pour en verrouiller un ou plusieurs en sortie.
Le verrouillage et le déverrouillage se font grâce aux scripts internes de Bitcoin.
Le script de verrouillage permet de bloquer un UTXO (le plus souvent à une adresse).
Le script de déverrouillage permet de le débloquer.
Les deux scripts sont exécutés l'un après l'autre lors du déverrouillage.
Un langage à pile
Le langage de script de Bitcoin fonctionne avec une pile (stack), à la manière de certains langages des années 60 comme Forth. Attention : on ne parle pas ici d'une pile électrique, mais d'une pile de données ! Les données sont placées sur la pile et des codes opératoires (opcodes) agissent sur ces données. Le langage est riche : il existe plus d'une centaine de codes opératoires, comme l'atteste la page wiki de Script.
Le défaut de Script est qu'il n'est, a priori, pas Turing-complet comme l'est Solidity, le langage de Ethereum. En effet, rien dans sa conception de base ne permet de faire des boucles. Mais ce défaut est aussi une qualité dans le sens où il permet d'économiser des ressources, ce qui est crucial dans le contexte d'un protocole décentralisé.
Les scripts sont transmis de manière brute au sein des transactions et sont interprétées par les noeuds du réseau. Il existe néanmoins une syntaxe qui s'est développée pour permettre aux êtres humains de les écrire et de les lire de manière facilement compréhensible. Les codes opératoires sont notés en majuscules et sont souvent précédés d'un OP_. Par exemple, OP_CHECKSIG qui permet de vérifier des signatures. S'il n'y a pas d'ambiguïté, ce préfixe est omis : on écrit alors simplement CHECKSIG. Enfin, on utilise des chevrons pour indiquer qu'un élément est placé sur le sommet de la pile : l'usage de la notation <signature>
signifie que la signature est poussée sur la pile.
Le script est valide si et seulement si la valeur TRUE (« vrai » en anglais) est présente en haut de la pile à la fin de l'exécution. Il est invalide si ce n'est pas le cas ou si son exécution s'est arrêtée avant la fin.
L'exemple typique de script est celui qui consiste à réaliser une addition, ou plutôt à vérifier que cette addition est correcte. Il est présenté par Andreas Antonopoulos dans son livre Mastering Bitcoin.
Le script de verrouillage fait partie d'une première transaction et est utilisé pour bloquer l'UTXO. Dans cet exemple, il est composé des 4 codes opératoires OP_3, OP_5, OP_EQUAL et OP_ADD, et s'écrit de la manière suivante :
3 ADD 5 EQUAL
Le script de déverrouillage est placé dans une seconde transaction qui dépense l'UTXO bloqué par le script ci-dessus. Il n'est, quant à lui, constitué que d'un seul code opératoire, OP_2 :
2
L'exécution de ces scripts a lieu lors du déverrouillage de l'UTXO. Le script de déverrouillage et le script de verrouillage sont exécutés l'un après l'autre. Le script total est donc :
2 3 ADD 5 EQUAL
L'exécution de ce script est un peu contre-intuitive. Elle consiste à évaluer si 5 = 3 + 2 : puisque c'est le cas, la transaction a lieu. Si, au lieu de 2, on fournit une « mauvaise réponse » (4 par exemple), la transaction est invalidée par les nœuds du réseau. Voyons ci-dessous comment cela se passe avec la pile.
Pile | Description du script |
---|---|
2 3 ADD 5 EQUAL OP_2 : la valeur 2 est poussée sur le haut de la pile. |
|
2 3 ADD 5 EQUAL OP_3 : la valeur 3 est poussée sur le haut de la pile. |
|
2 3 ADD 5 EQUAL Le code opératoire OP_ADD additionne les deux valeurs en haut de la pile. |
|
2 3 ADD 5 EQUAL OP_5 : la valeur 5 est poussée sur le haut de la pile. |
|
2 3 ADD 5 EQUAL Le code opératoire OP_EQUAL sort les deux valeurs en haut de la pile et les compare. |
Les paiements simples : le schéma Pay-to-Public-Key-Hash
Comme on l'a dit, les paiements simples dans Bitcoin font aussi intervenir des scripts. Il s'agit de débloquer un UTXO dont on a le contrôle pour en bloquer un autre sous le contrôle du destinataire.
Au début, 2 schémas de script étaient utilisés pour les paiements : le schéma Pay-to-Public-Key (P2PK), dirigé vers une clé publique, et le schéma Pay-to-Public-Key-Hash (P2PKH), dirigé vers une adresse.
Si les notions de clé publique et d'adresse vous échappent, vous pouvez vous référer à l'article « Clés privées, clés publiques et adresses dans Bitcoin » qui expliquent ces concepts en détail.
Le schéma P2PK consiste à réaliser un paiement vers une clé publique. Plus précisément, la clé publique du destinataire est utilisée pour verrouiller l'UTXO créé par le paiement. Le script de verrouillage prend donc la forme suivante :
<clé publique> CHECKSIG
Lorsque le destinataire souhaite dépenser ses fonds, il utilise le script de déverrouillage correspondant qui n'est constitué que de sa signature :
<signature>
Les deux scripts sont parfois appelés scriptPubKey et scriptSig en raison de leur utilité originelle dans ce type de schéma. Le script de verrouillage contenait la clé publique et le script de déverrouillage la signature.
L'exécution des deux scripts est assez simple. La signature est d'abord poussée sur la pile. C'est ensuite au tour de la clé publique. Enfin, le code opératoire OP_CHECKSIG vérifie que la signature correspond bien à la clé publique, ce qui rend le script valide.
Ce schéma était assez répandu aux débuts de Bitcoin. Il a notamment été utilisé lors de la première vraie transaction entre Satoshi Nakamoto et Hal Finney. Mais il a cependant été abandonné aux profits de son concurrent, le schéma P2PKH.
Comme son nom l'indique, le schéma Pay-to-Public-Key-Hash (P2PKH) consiste à diriger le paiement vers l'empreinte d'une clé publique, c'est à dire une adresse. Ce schéma à l'avantage de rajouter une sécurité supplémentaire car la clé clé publique n'est dévoilée qu'au moment où la transaction de sortie est réalisée. Les adresses P2PKH sont représentées par des chaînes de caractère commençant toujours par un 1.
Le script de verrouillage utilisé pour ce schéma est :
DUP HASH160 <adresse> EQUALVERIFY CHECKSIG
Et le script de déverrouillage correspondant est :
<signature> <clé publique>
L'exécution de ces scripts a lieu de la manière suivante.
Pile | Description du script |
---|---|
<signature> <clé publique> DUP HASH160 <adresse> EQUALVERIFY CHECKSIG La signature est poussée sur le haut de la pile. |
|
<signature> <clé publique> DUP HASH160 <adresse> EQUALVERIFY CHECKSIG La clé publique est poussée sur le haut de la pile. |
|
<signature> <clé publique> DUP HASH160 <adresse> EQUALVERIFY CHECKSIG Le code opératoire OP_DUP duplique l'élément en haut de la pile : ici la clé publique. |
|
<signature> <clé publique> DUP HASH160 <adresse> EQUALVERIFY CHECKSIG Le code opératoire OP_HASH160 hache la clé publique pour comparer son empreinte avec l'adresse. |
|
<signature> <clé publique> DUP HASH160 <adresse> EQUALVERIFY CHECKSIG L'adresse est poussée en haut de la pile. |
|
<signature> <clé publique> DUP HASH160 <adresse> EQUALVERIFY CHECKSIG Le code opératoire OP_EQUALVERIFY sort les deux adresses en haut de la pile et les compare. Si elles ne sont pas égales, l'exécution du script s'arrête et la transaction est invalidée. Ici c'est le cas, donc on continue. |
|
<signature> <clé publique> DUP HASH160 <adresse> EQUALVERIFY CHECKSIG Le code opératoire OP_CHECKSIG prend les 2 valeurs en haut de la pile et vérifie que la signature correspond bien à la clé publique. Comme c'est le cas, la valeur TRUE est poussée sur la pile. |
Les scripts avancés : le schéma Pay-to-Script-Hash
Ainsi, les paiements simples font intervenir des scripts, mais n'importe quel script à la place de ces schémas prédéfinis. C'est ce qui donne à Bitcoin sa nature programmable.
En réalité, la plupart des scripts bruts ne sont pas considérés comme standard, c'est-à-dire qu'ils ne sont, en général, pas acceptés par les mineurs. Et cela même s'ils sont tout à fait valides selon le protocole. L'usage veut qu'on passe par un schéma particulier appelé Pay-to-Script-Hash.
Ce dernier a été introduit en 2012 par un soft fork. Il consiste à envoyer les fonds à une adresse qui représente le script de verrouillage. Ces adresses P2SH sont reconnaissables car elles commencent toujours par un 3. Les comptes multi-signatures utilisent ce type d'adresse.
Le schéma P2SH simplifie grandement l'usage des scripts avancés en optimisant la gestion des données et en faisant passer le fardeau de la construction du script sur le récepteur. L'envoyeur n'a pas besoin de comprendre quel script est utilisé : il se contente d'envoyer des bitcoins à l'adresse correspondante.
Pour ce faire, le script de verrouillage est haché et son empreinte sert d'adresse. Ce script de verrouillage est dans ce cas renommé en script de règlement (redeem script) car il n'est dévoilé qu'au moment de la transaction de dépense à partir de cette adresse.
La nouveau script de verrouillage est alors :
HASH160 <empreinte du script de règlement> EQUAL
Et le nouveau script de déverrouillage est constitué de l'ancien script de déverrouillage auquel on a ajouté le script de règlement.
Si l'on prend l'exemple d'addition, le script de règlement est :
3 ADD 5 EQUAL
Ce script est haché pour être transformé en adresse : 3F7hj1tyUZgWU1VsB3gXACqDM1symZAZ4f. Ce qui nous donne le nouveau script de verrouillage :
HASH160 <adresse 3F7hj1tyUZgWU1VsB3gXACqDM1symZAZ4f> EQUAL
Le nouveau script de déverrouillage est :
2 <script de règlement>
Lors de l'exécution, l'empreinte du script de règlement fourni dans le script de déverrouillage est comparée à l'adresse. Si elles sont égales, alors le script de règlement est combiné à l'autre partie du script de déverrouillage pour qu'ils soient exécutés ensemble de manière classique.
Ainsi, nous avons vu comment fonctionne le langage de script de Bitcoin qui est, il faut le dire, un peu particulier. L'usage des scripts avancés passe généralement par le schéma Pay-to-Script-Hash. Nous verrons dans le prochain article comment ces scripts peuvent être utilisés pour programmer des smart contracts permettant de résoudre des problèmes concrets.
Note des lecteurs
Franchement, bravo et merci pour ces explications à la fois bien détaillées et abordables. En espérant continuer à en apprendre davantage sur bitcoin