Comprendre le Bitcoin Script
Qu'est-ce que le Bitcoin Script ?
Chaque fois que tu envoies des Bitcoin, tu ne déplaces pas vraiment une pièce d'un endroit à un autre. Tu crées une sortie et tu y attaches un petit programme. Ce programme définit les conditions exactes dans lesquelles ces pièces pourront ensuite être dépensées. Le langage utilisé pour écrire ces programmes s'appelle Bitcoin Script.
Satoshi Nakamoto l'a très bien décrit en qualifiant un script de sorte de prédicat : une petite équation qui se résout en vrai ou faux. Si celui qui dépense parvient à rendre l'équation vraie, les pièces bougent. Sinon, elles restent verrouillées. C'est tout le travail de Script. C'est un mécanisme de verrouillage, pas un ordinateur généraliste.
Le Bitcoin Script est volontairement petit et limité. Il n'est pas Turing complet, ce qui signifie qu'il n'a pas de boucles, pas de récursion et aucun moyen d'exécuter un programme sans fin. Ce n'est pas une fonctionnalité manquante. C'est une décision de sécurité fondamentale. Un langage qui ne peut pas tourner indéfiniment peut toujours être vérifié rapidement et à faible coût par chaque nœud du réseau, et c'est en partie ce qui permet à des gens ordinaires de vérifier Bitcoin sur du matériel modeste.
Tout cela contraste volontairement avec les réseaux qui utilisent un langage de contrats Turing complet. Cette expressivité accrue a produit à plusieurs reprises des comportements inattendus, des fonds gelés et des exploits qui ont siphonné des centaines de millions d'Euro ou de Dollar de valeur. Sur ces plateformes, les jetons peuvent aussi être gelés ou saisis par l'émetteur ou par une organisation qui les contrôle. Bitcoin a choisi un langage plus petit et prévisible précisément pour que personne ne tienne ce genre d'interrupteur sur tes pièces.
Si tu n'as pas encore lu comment une transaction est vérifiée par le réseau, Comment les transactions Bitcoin sont vérifiées est un bon complément à cet article.
La pile : comment Script raisonne
Le Bitcoin Script est un langage basé sur une pile. Une pile est un simple tas de données où tu peux seulement ajouter un élément au sommet (un "push") ou retirer un élément du sommet (un "pop"). La dernière chose que tu poses est la première que tu retires. Les ordinateurs gèrent ce type de mémoire de façon très efficace, même si cela paraît un peu étrange pour nous.
À cause de la pile, Script ne s'écrit pas comme on écrit d'habitude un calcul. Au lieu d'écrire 9 plus 12, tu écris d'abord les deux nombres puis l'opération : 9 12 OP_ADD. Les deux nombres sont posés sur la pile, puis OP_ADD les retire tous les deux, les additionne et repose le résultat.
Les commandes comme OP_ADD s'appellent des opcodes, abréviation de operation code. Ce sont les verbes du langage. Il existe environ 80 opcodes actifs, couvrant les calculs simples, les comparaisons, le hachage cryptographique et la vérification des signatures. Chacun retire quelques éléments de la pile, fait son travail et peut reposer un résultat.
Voici un exemple complet, un peu absurde, d'un script fonctionnel :
9 12 OP_ADD 21 OP_EQUAL
En lisant de gauche à droite : pose 9, pose 12, puis OP_ADD les remplace par 21. Pose maintenant un autre 21. Enfin OP_EQUAL retire les deux valeurs, voit qu'elles correspondent et pose un 1. Il reste un seul 1 sur la pile, donc le script est valide. En clair, cette sortie est verrouillée derrière l'énigme "donne-moi deux nombres dont la somme fait 21", et quiconque sait faire un calcul de base pourrait la déverrouiller.
Le script qui bloque et le script qui ouvre
Dans Bitcoin, ce script unique est en réalité scindé en deux moitiés qui se trouvent à des endroits différents.
Le script de verrouillage, techniquement le scriptPubKey, est attaché à une sortie. Il fixe les conditions de dépense. Dans l'exemple ci-dessus, la partie de verrouillage est OP_ADD 21 OP_EQUAL, la règle à satisfaire.
Le script de déverrouillage, techniquement le scriptSig, est fourni plus tard par celui qui veut dépenser cette sortie. Il apporte les valeurs d'entrée qui satisfont la règle. Dans l'exemple, la partie de déverrouillage est 9 12, la réponse à l'énigme.
Envoyer des Bitcoin à quelqu'un signifie donc vraiment créer une sortie dont le script de verrouillage ne peut être satisfait que par cette personne. La version classique verrouille les pièces sur une clé, de sorte que seul le détenteur de la clé privée correspondante peut produire un script de déverrouillage valide.
Un détail trompe presque tout le monde. Même si le script de déverrouillage est fourni par celui qui dépense après que la sortie existe déjà, lorsqu'un nœud exécute la validation complète, il place d'abord le script de déverrouillage, puis le script de verrouillage. Le script de déverrouillage pose les données sur la pile, et le script de verrouillage les vérifie ensuite.
How Locking and Unlocking Fit Together
Unlocking Script
scriptSig
Provided by the spender.
Locking Script
scriptPubKey
Attached to the output.
During validation the unlocking script runs first, then the locking script.
If the combined script leaves a single TRUE on the stack, the output is unlocked.
Comment un script est validé
Un nœud valide une transaction en combinant les scripts de déverrouillage et de verrouillage et en les exécutant de gauche à droite. Le résultat est binaire.
Un script est valide si, une fois terminé, il reste exactement un élément non nul sur la pile. En pratique, cela signifie un seul OP_1, ou toute valeur qui compte comme "vrai".
Un script est invalide si la pile est vide à la fin, si la seule chose qui reste est un zéro, s'il reste plus d'un élément, ou si le script s'interrompt prématurément. Il n'y a pas de "peut-être". Soit les conditions sont remplies, soit les pièces ne bougent pas.
Cette clarté du type ça passe ou ça casse est ce qui rend Bitcoin vérifiable. Chaque nœud exécute les mêmes scripts et aboutit à la même réponse, sans ambiguïté et sans dépendre d'informations extérieures.
Pay-to-Public-Key : le verrou d'origine
Le premier type de script standard est Pay-to-Public-Key (P2PK). Le script de verrouillage contient simplement une clé publique suivie de l'opcode OP_CHECKSIG. Pour dépenser, le propriétaire fournit une signature dans le script de déverrouillage.
Verrouillage: <ClePublique> OP_CHECKSIG
Deverrouillage: <Signature>
OP_CHECKSIG retire la signature et la clé publique, vérifie que la signature a été produite par la clé privée correspondante et pose un 1 si tout concorde. P2PK apparaît dans beaucoup des tout premiers blocs, y compris les sorties coinbase du bloc de genèse.
Aujourd'hui presque personne n'utilise P2PK. Le problème est pratique : pour payer quelqu'un, il faudrait sa clé publique complète, qui est longue, illisible et facile à recopier de travers. Satoshi a résolu cela avec le motif suivant.
Pay-to-Public-Key-Hash : le cheval de bataille
Pay-to-Public-Key-Hash (P2PKH) stocke dans le script de verrouillage seulement un hash de la clé publique, et non la clé elle-même. Vois le hash comme une courte empreinte de la clé. La vraie clé publique n'est révélée que plus tard, dans le script de déverrouillage, au moment de dépenser les pièces.
Le hash est obtenu en exécutant SHA-256 puis RIPEMD-160, une combinaison que Bitcoin regroupe dans un seul opcode appelé OP_HASH160. Le résultat ne fait que 160 bits, bien plus court que la clé publique. À partir de ce hash, avec un encodage et une somme de contrôle, un portefeuille construit la fameuse adresse Bitcoin. Un détail qui mérite réflexion : les adresses n'existent pas vraiment à l'intérieur de la blockchain. Ce sont une commodité créée par les portefeuilles par-dessus ces hash. Ce que le protocole voit, c'est le hash.
Le compromis, c'est que la clé publique n'est plus visible dans la sortie, alors que OP_CHECKSIG en a besoin pour vérifier la signature. Celui qui dépense doit donc fournir à la fois la clé publique et la signature, et le script vérifie d'abord que la clé fournie produit bien le hash stocké dans le verrou.
Verrouillage: OP_DUP OP_HASH160 <HashClePublique> OP_EQUALVERIFY OP_CHECKSIG
Deverrouillage: <Signature> <ClePublique>
Pour en savoir plus sur l'étape de hachage elle-même, vois Qu'est-ce qu'un hash ?.
Suivre un script P2PKH
Voici le script P2PKH complet exécuté étape par étape. Le script de déverrouillage passe en premier.
- La signature et la clé publique sont posées sur la pile.
OP_DUPduplique l'élément du sommet, la clé publique, car le script a besoin d'une copie à hacher et d'une copie pour vérifier la signature plus tard.OP_HASH160prend la copie du sommet de la clé publique et la hache, laissant un nouveau hash de clé publique sur la pile.- Le hash attendu issu du script de verrouillage est posé, et
OP_EQUALVERIFYcompare les deux hash. S'ils diffèrent, le script échoue aussitôt. S'ils correspondent, les deux sont retirés et l'exécution continue. - Ce qui reste est désormais en fait un script P2PK : une signature et une clé publique.
OP_CHECKSIGvérifie la signature face à la clé et pose un 1.
Il reste un seul 1 sur la pile, donc la sortie est déverrouillée. La mécanique est identique que les pièces aient été verrouillées avec le P2PKH legacy ou avec son équivalent moderne SegWit, P2WPKH. Seul change l'endroit où sont stockées les données de signature.
P2PKH Script Execution
Step through how a node unlocks a Pay-to-Public-Key-Hash output.
Stack (top to bottom)
Operation
Initial State
The script is ready. The unlocking script runs first, then the locking script.
Les scripts multisignature
L'une des astuces les plus utiles de Script est d'exiger plus d'une signature pour dépenser. Un script multisig standard, de type P2MS, encode une règle "m parmi n" : sur n clés publiques listées, m signatures valides quelconques déverrouillent les fonds.
Un multisig 2 parmi 3, par exemple, exige 2 signatures issues d'un ensemble de 3 clés. C'est la base de la conservation partagée, où aucune clé seule ne peut déplacer l'argent. Cela sous-tend les configurations multisignature traitées dans nos articles de sécurité.
Verrouillage: OP_2 <ClePub1> <ClePub2> <ClePub3> OP_3 OP_CHECKMULTISIG
Deverrouillage: <Signature1> <Signature2>
OP_CHECKMULTISIG vérifie à la fois que le nombre requis de signatures valides est présent et que chacune appartient à l'une des clés listées. Écrit directement ainsi, cependant, le multisig a la même lourdeur que P2PK. Celui qui envoie doit connaître chaque clé publique et le script exact, la sortie devient grande et coûteuse, et ta configuration de sécurité est exposée on-chain à la vue de tous. Le motif suivant règle tout cela d'un coup.
Pay-to-Script-Hash : cacher la complexité
Pay-to-Script-Hash (P2SH) te permet de verrouiller les pièces sur le hash d'un script plutôt que sur le script lui-même. Ton script personnalisé complet, appelé redeem script, reste caché jusqu'à ce que tu dépenses.
Lors d'un envoi vers une sortie P2SH, le script de verrouillage ne contient que le hash. Celui qui envoie n'a pas besoin de connaître ta structure multisig ni tes conditions personnalisées. Il paie simplement vers une adresse courte qui commence par le chiffre 3. Ton redeem script, ainsi que les données qui le satisfont, n'est fourni que plus tard dans le script de déverrouillage.
Verrouillage: OP_HASH160 <HashScript> OP_EQUAL
Deverrouillage: <Signature1> <Signature2> <RedeemScript>
La validation se fait en deux étapes. D'abord le script extérieur confirme que le redeem script fourni produit le hash présent dans le verrou. Ensuite le redeem script est déballé et exécuté comme un script à part entière, face aux signatures fournies. Les pièces ne bougent que si les deux étapes réussissent. P2SH t'apporte trois gains à la fois : des sorties plus petites et moins coûteuses, une adresse standardisée et propre, et tes conditions gardées privées jusqu'au moment où tu dépenses.
Les principaux types de script
Même si tu peux construire presque n'importe quel script de verrouillage, la plupart des nœuds ne relaient qu'un petit ensemble de motifs standard. Le tableau ci-dessous présente les types de script qui ont façonné Bitcoin, de l'ère legacy jusqu'à SegWit et Taproot, avec leurs préfixes d'adresse et l'endroit où chacun stocke ses données de déverrouillage.
La distinction entre legacy et SegWit compte. Les scripts legacy (P2PK, P2PKH, P2MS, P2SH) placent leurs données de déverrouillage dans le scriptSig. Les scripts SegWit (P2WPKH, P2WSH, P2TR) les placent plutôt dans un champ séparé appelé témoin (witness), ce qui est précisément ce qui a corrigé la malléabilité des transactions et abaissé les frais.
Standard Script Types
| Type | Pattern | Address | Unlocking | Era |
|---|---|---|---|---|
P2PK Pay to Public Key | <PubKey> OP_CHECKSIG | none | scriptSig | Legacy |
P2PKH Pay to Public Key Hash | OP_DUP OP_HASH160 <PubKeyHash> OP_EQUALVERIFY OP_CHECKSIG | 1... | scriptSig | Legacy |
P2MS Bare Multisig | OP_m <PubKey> ... <PubKey> OP_n OP_CHECKMULTISIG | none | scriptSig | Legacy |
P2SH Pay to Script Hash | OP_HASH160 <ScriptHash> OP_EQUAL | 3... | scriptSig | Legacy |
P2WPKH Pay to Witness Public Key Hash | OP_0 <PubKeyHash> | bc1q... | witness | SegWit |
P2WSH Pay to Witness Script Hash | OP_0 <ScriptHash> | bc1q... | witness | SegWit |
P2TR Pay to Taproot | OP_1 <TaprootOutputKey> | bc1p... | witness | Taproot |
P2PK
Pay to Public Key
Pattern
<PubKey> OP_CHECKSIG
Address
noneUnlocking
scriptSigP2PKH
Pay to Public Key Hash
Pattern
OP_DUP OP_HASH160 <PubKeyHash> OP_EQUALVERIFY OP_CHECKSIG
Address
1...Unlocking
scriptSigP2MS
Bare Multisig
Pattern
OP_m <PubKey> ... <PubKey> OP_n OP_CHECKMULTISIG
Address
noneUnlocking
scriptSigP2SH
Pay to Script Hash
Pattern
OP_HASH160 <ScriptHash> OP_EQUAL
Address
3...Unlocking
scriptSigP2WPKH
Pay to Witness Public Key Hash
Pattern
OP_0 <PubKeyHash>
Address
bc1q...Unlocking
witnessP2WSH
Pay to Witness Script Hash
Pattern
OP_0 <ScriptHash>
Address
bc1q...Unlocking
witnessP2TR
Pay to Taproot
Pattern
OP_1 <TaprootOutputKey>
Address
bc1p...Unlocking
witnessP2PK and bare P2MS have no standard address format. Multisig is almost always wrapped in P2SH or P2WSH today.
SegWit et Taproot : au-delà du Script classique
La mise à niveau SegWit de 2017 a déplacé les données de signature hors du corps principal de la transaction, vers le champ témoin. Cela a résolu un problème de longue date appelé malléabilité des transactions, où la signature visible pouvait être modifiée pour changer l'identifiant d'une transaction sans en changer le sens, et cela a aussi rendu les données de signature moins coûteuses à inclure. P2WPKH et P2WSH sont simplement les versions SegWit de P2PKH et P2SH, et produisent des adresses qui commencent par bc1q.
Fait intéressant, ces nouveaux types de script n'utilisent presque pas du tout l'ensemble du langage Script. Chacun suit un motif interne fixe que les nœuds exécutent d'une manière prédéfinie, ce qui est exactement la simplification "il suffit de vérifier une clé et une signature" que le Script classique rendait possible sans l'imposer. Le langage complet continue de vivre à l'intérieur de P2WSH, où tu peux encapsuler n'importe quel script personnalisé dont tu as besoin.
Pay-to-Taproot (P2TR), activé en novembre 2021, est le standard le plus récent et produit des adresses commençant par bc1p. Il associe les signatures Schnorr à une structure appelée MAST (Merkelized Abstract Syntax Trees), qui permet d'encoder de nombreuses conditions de dépense alternatives dans un arbre. Élément crucial, seule la branche que tu utilises réellement est révélée au moment de dépenser. Un portefeuille doté de conditions élaborées de sauvegarde et de récupération peut ainsi dépenser d'une manière identique à un paiement ordinaire à clé unique, ce qui améliore à la fois la confidentialité et l'efficacité.
Au-delà des signatures : verrous temporels et énigmes
Script peut exprimer bien plus que "prouve que tu possèdes cette clé". Deux opcodes ajoutent la dimension du temps. OP_CHECKLOCKTIMEVERIFY (introduit par BIP 65) rend une sortie non dépensable jusqu'à une date ou une hauteur de bloc choisie. OP_CHECKSEQUENCEVERIFY (BIP 112) impose un délai relatif, mesuré à partir du moment où les pièces ont été reçues. Ensemble, ils rendent des conditions comme "ces fonds ne peuvent pas bouger pendant six mois" applicables par le protocole lui-même.
Ces verrous temporels sont les briques de constructions plus avancées. Un Hash Time Locked Contract (HTLC), par exemple, combine une énigme de hash avec un verrou temporel, de sorte qu'un paiement soit s'achève quand un secret est révélé, soit est remboursé après une échéance. C'est ce motif qui rend le Lightning Network possible.
Script autorise aussi des énigmes pures. Une énigme de hash verrouille les pièces derrière "fournis des données qui produisent ce hash". Il existe même une énigme de collision de hash qui paie quiconque parvient à fournir deux entrées différentes produisant le même hash, en pratique une prime publique sur une fonction de hachage cassée. Et l'opcode spécial OP_RETURN te permet d'attacher une petite donnée à une sortie en la marquant comme définitivement non dépensable, une manière propre d'ancrer de l'information dans la chaîne sans gonfler l'ensemble des pièces dépensables.
Les limites qui gardent Bitcoin en sécurité
Script s'accompagne de limites de taille strictes, et elles existent pour la même raison que le langage évite les boucles : garder la vérification rapide et empêcher quiconque d'en faire une arme contre le réseau.
Les limites dures de validité sont claires. Un script complet ne peut pas dépasser 10 000 octets. Il peut exécuter au plus 201 opcodes, sans compter les opérations qui se contentent de poser des données sur la pile. Aucun élément seul posé sur la pile ne peut dépasser 520 octets, et la pile elle-même ne peut pas contenir plus de 1 000 éléments à la fois. Enfreins l'une de ces règles et le script est invalide, point.
Il y a aussi une couche plus souple. Un script peut être parfaitement valide mais non standard, ce qui signifie que les nœuds refuseront de le relayer sur le réseau même si un mineur pourrait quand même l'inclure dans un bloc. C'est une mesure de sécurité : seuls les motifs standard bien testés circulent librement, de sorte qu'un attaquant ne peut pas inonder le réseau de scripts étranges et lents à vérifier. En pratique, une transaction non standard doit être remise directement à un mineur ou minée par toi-même.
Pourquoi cela compte
Il est tentant de voir les limites de Script comme un Bitcoin en retard sur des chaînes plus "programmables". C'est l'inverse qui est vrai. Chaque restriction ici est un échange délibéré d'expressivité contre prévisibilité, vérifiabilité et sécurité.
Comme aucun script ne peut tourner indéfiniment, chaque nœud peut confirmer la chaîne entière sans faire confiance à personne. Comme le langage est petit, la surface d'attaque est petite. Comme il n'existe pas d'état global partagé dans lequel des contrats pourraient intervenir, il n'y a pas de point unique où quelqu'un pourrait intervenir et geler tes pièces. La flexibilité même qui permet à d'autres réseaux de promettre davantage est aussi ce qui les a exposés à des exploits catastrophiques et ce qui permet aux parties qui les contrôlent de saisir ou de geler des soldes à volonté.
Bitcoin a fait un pari différent. Un langage modeste et prévisible, vérifié de la même façon par tous, protégeant un ensemble de règles fixe et neutre. C'est ce qui permet à un canoë d'avancer en eau libre sans demander la permission, et c'est précisément le but. Pour la vue d'ensemble de la façon dont ces règles sont appliquées sur tout le réseau, vois Le mécanisme de consensus de Bitcoin : une analyse approfondie, et pour la structure que les scripts protègent en fin de compte, Qu'est-ce qu'une blockchain ?.
Points Clés
Le Bitcoin Script n'est pas Turing complet, et c'est voulu. Il n'a ni boucles ni récursion, donc chaque script se termine en un nombre d'étapes borné et prévisible.
Chaque sortie porte un script de verrouillage (scriptPubKey). Pour la dépenser, la transaction doit fournir un script de déverrouillage correspondant (scriptSig, ou le champ témoin pour SegWit).
Un script est valide lorsque l'exécution laisse une seule valeur non nulle sur la pile. Tout le reste échoue.
Un script Bitcoin est limité à 10 000 octets et à 201 opcodes exécutés au maximum, sans aucun élément de données dépassant 520 octets.
P2WPKH (SegWit natif, 2017) et P2TR (Taproot, 2021) sont les types de script standard modernes, et ils se déverrouillent via le champ témoin plutôt que via le scriptSig.
Questions fréquentes
Non, et c'est intentionnel. Le Bitcoin Script n'est pas Turing complet, ce qui signifie qu'il ne peut pas exécuter de boucles ni de programmes arbitraires. Ce choix de conception élimine des catégories entières de bugs et rend chaque transaction rapide et peu coûteuse à vérifier, même sur du matériel modeste.
Le scriptPubKey est le script de verrouillage attaché à une sortie. Il fixe les conditions à remplir pour dépenser ces pièces. Le scriptSig est le script de déverrouillage fourni par celui qui dépense. Il apporte les données, généralement une signature et une clé publique, qui satisfont ces conditions.
Oui. Le Bitcoin Script prend en charge des énigmes, des verrous temporels et des conditions multisignature bien au-delà d'une simple vérification de signature. Les scripts personnalisés sont valides et peuvent être minés, mais la plupart des nœuds ne relaient qu'un petit ensemble de motifs standard, donc un script non standard est plus difficile à faire confirmer sauf s'il est encapsulé dans P2SH ou P2WSH.
Taproot a introduit Pay-to-Taproot (P2TR), qui associe les signatures Schnorr à un arbre de conditions de dépense possibles appelé MAST. Seule la branche réellement utilisée est révélée on-chain, donc un contrat complexe ressemble à un paiement simple, ce qui améliore à la fois la confidentialité et l'efficacité de l'espace dans les blocs.
Sources
- 1.Greg Walker: Bitcoin Script (learnmeabitcoin.com)
- 2.Antonopoulos: Mastering Bitcoin, Chapter 7, Authorization and Authentication
- 3.Bitcoin Wiki: Script and Opcode List
- 4.BIP 16: Pay to Script Hash
- 5.BIP 141: Segregated Witness
- 6.BIP 341 and BIP 342: Taproot and Tapscript
Pas de conseil financier. CanoeBit publie uniquement du contenu éducatif. Rien ici ne constitue une recommandation d'achat, de vente ou de détention d'un actif.