Miniscript

le 08/08/2022 par Thomas ZOUGHEBI
Tags: Cloud & Platform

Lorsque l’on parle de « smart contracts », que l’on soit connaisseur ou novice, on pense généralement à Ethereum. Or, ce concept date de bien avant et c’est la technologie Bitcoin qui l’implémente en production pour la première fois. Néanmoins, son langage bas-niveau « Bitcoin Script » n’est pas très alléchant. Pour remédier à cela et optimiser les smart contracts de Bitcoin, il y a Miniscript.

"Smart" Contracts

Soyons clairs dès le début :

Ce que l’on appelle les "Contrats intelligents" existait au début de Bitcoin, en 2009.

Les mots "Smart Contract(s)" et leurs définitions sont d'abord utilisés et détaillés par Nick Szabo (essais et papiers de Nick Szabo, blog de Nick Szabo), dans son article de 1995/96 "Contrats Intelligents : Blocs de Construction pour les Marchés Numériques" (voir aussi "L'idée des Smart Contracts" (1997)) pour le n°16 du magazine Extropy. Ainsi, les Contrats Intelligents existaient également avant même Bitcoin.

Aujourd'hui, nous ne pourrions débattre que sur le fait que les contrats intelligents sont plus "stupides" qu’ "intelligents", car ils ne sont pas auto-exécutables. D'où leurs frères moins adorés, les "Dumb Contracts" (ndlr. Contrats Stupides...).

Le Bitcoin est conçu comme une monnaie programmable depuis le début. Tout le monde peut alors élaborer différentes conditions de dépenses de cette monnaie.

Précisément, un contrat intelligent est utilisé pour toute transaction Bitcoin. Du transfert de bitcoins d’un seul pair à un seul pair le plus simple qui soit, au transfert dont les conditions imbriquées de dépenses donnent des céphalées. Selon la définition du Contrat Intelligent de Nick Szabo, pour exister, ce type de programme n'a ni besoin d'un langage Turing-complet, ni de capacités de références temporelles comme cela a pu être avancé (La gestion du temps est une partie délicate de l’écriture des contrats intelligents car le « temps » est au moins lié aux émissions de blocs de la blockchain).

Bitcoin Script

Pour écrire ces conditions dans Bitcoin, nous utilisons un langage basé sur une pile appelé "Script", qui, par extension, est généralement renommé Bitcoin Script. Ce langage est inspiré de Forth, inventé par Charles H. Moore pour faciliter son travail sur le calcul des trajectoires des satellites. Volontairement, Bitcoin Script n'est plus Turing-complet, pour limiter la surface d’attaques et les erreurs, mais dispose aujourd'hui de capacités de gestion "temporelle", grâce à des opérateurs précédemment désactivés pour assurer la sécurité, puis réactivés (cf BIP n°112).

Ci-dessous est un exemple de contrat intelligent en Bitcoin Script (P2PKH), utilisé pour transférer la propriété des bitcoins d'un pair à un autre pair avec des clés publiques et des adresses :

<sig> <pubKey> OP_DUP OP_HASH160 <pubKeyHash> OP_EQUALVERIFY OP_CHECKSIG

Les opérandes sont entre les signes « < » et « > », tandis que les opérateurs sont en majuscules et commencent par « OP_ ». La partie en rouge peut être considérée comme l’énigme à résoudre pour obtenir les bitcoins, tandis que la partie en vert est la solution à présenter.

Il s'agit d'un contrat intelligent assez simple qui libère des fonds lorsque la signature attendue est délivrée comme preuve de propriété de l’adresse publique.

Mais que faire si nous voulons un contrat plus intelligent entre plusieurs entités ? Par exemple, pourrions-nous développer un script qui permettrait de débloquer des fonds en bitcoins au bout de 90 jours avec deux signataires sur trois au lieu de trois sur trois ? Si Alice, Bob, et Carole contrôlent à parts égales un fond en bitcoins mais que Carole est bloquée ou injoignable, on peut alors accorder un délai pour valider la transaction par moins de signataires, c’est-à-dire Alice et Bob.

Nous finirions avec quelque chose comme ceci :

<key_1> OP_CHECKSIG OP_SWAP <key_2> OP_CHECKSIG OP_ADD OP_SWAP <key_3> OP_CHECKSIG OP_ADD OP_SWAP OP_DUP OP_IF <a032> OP_CHECKSEQUENCEVERIFY OP_VERIFY OP_ENDIF OP_ADD 3 OP_EQUAL

A noter qu’il est difficile avec ce script de clairement différencier l’énigme de la solution...

Est-ce facilement compréhensible ? Lisible ? Et cela fonctionne-t-il ? Est-ce trop cher (cela coûte-t-il trop de frais de transaction) pour être validé par le réseau ? Et cette syntaxe est-elle suffisamment attrayante pour embarquer plus de gens et démontrer les possibilités de Bitcoin ?

C'est le genre de questions que Pieter Wuille, Andrew Poelstra et Sanket Kanjalkar se sont posées à Blockstream Research, ainsi que plusieurs autres personnes ayant participé aux discussions.

Miniscript

Miniscript est une belle première réponse. Il s'agit d'une nouvelle couche d'abstraction qui n'a besoin d'aucune modification de Bitcoin, car elle utilise toujours pleinement Bitcoin Script. Précisément, il utilise (pour l'instant) uniquement Bitcoin Script post-SegWit. Miniscript est également volontairement limité à un sous-ensemble de scripts, les plus utilisés. Nous pourrions dire que Miniscript offre moins de possibilités que Bitcoin Script lui-même, mais ce ne serait pas vrai comme nous allons le voir.

Miniscript peut être vu comme une couche d'abstraction intermédiaire entre la couche "Policy" (détaillée ci-dessous) et la couche Bitcoin Script :

Policy compile en Miniscript. Miniscript et Bitcoin Script sont mappés entre eux un pour un.

Il s’agit bien d’un mapping. Cette correspondance est assurée par les implémentations de Miniscript.

La couche « Policy » est en fait la couche du langage Policy. Donc, oui, vous obtenez en fait deux langages pour le prix d'un. Le langage « Policy » est conçu pour faciliter la programmation humaine des conditions de dépenses, tandis que Miniscript lui-même est conçu pour faciliter l'Analyse Statique. Cela signifie en fait que vous ne devez pas utiliser directement Miniscript pour coder, mais utiliser Policy à la place, puis le compiler en Miniscript (Pieter Wuille sur Stack Exchange).

Voici à quoi cela ressemblerait avec le dernier exemple du contrat « multi-sig » présenté ci-dessus. Souvenez-vous, plus que 2 signatures sur 3 après un délai de 90 jours :

Policy

thresh(3,pk(key_1),pk(key_2),pk(key_3),older(12960))

Miniscript

thresh(3,pk(key_1),s:pk(key_2),s:pk(key_3),sdv:older(12960))

Bitcoin Script

<key_1> OP_CHECKSIG OP_SWAP <key_2> OP_CHECKSIG OP_ADD OP_SWAP <key_3> OP_CHECKSIG OP_ADD OP_SWAP OP_DUP OP_IF <a032> OP_CHECKSEQUENCEVERIFY OP_VERIFY OP_ENDIF OP_ADD 3 OP_EQUAL

Optimisations Miniscript

Nous pouvons immédiatement voir comment les mêmes conditions de dépenses sont écrites de manière plus courte que Bitcoin Script, en Policy ou en Miniscript. C'est du code plus “compressé”, plus compact. Mais un code plus “compressé” ne signifie pas nécessairement plus simple. Au moins pour les humains, comme d'autres avec moi l'ont fait remarquer. Ce n'est pas, de toute façon, le principal avantage de Miniscript.

Outre les raccourcis apportés par les opérateurs, nous pouvons voir que l’ordre des opérateurs et des opérandes est modifié par rapport à Bitcoin Script. La syntaxe polonaise est utilisée. C'est très intéressant pour l'analyse car il est plus facile pour les machines et les humains de mettre le code dans des graphes, ou… des arbres ! Et Bitcoin aime les arbres (ndlr. oui, c’est un calembour). Non seulement vous pouvez trouver de nombreux arbres de Merkle, par exemple dans des blocs, mais l'une des futures structures possibles pour les contrats intelligents dans Bitcoin est celle du "Merklized Abstract Syntax Tree" (MAST ; Arbre de Merkle de la Syntaxe Abstraite ; BIP#114). Il serait plus facile d'organiser le code avec des nœuds logiques dans un graphe comme celui ci-dessous :

Policy sous forme d'arbre avec pondération des branches selon les probabilités de résolution.

Avec ce type de graphe, vous obtenez un premier aperçu d'une réelle optimisation de la taille et de la confidentialité, car vous n'auriez tout simplement pas toujours à obtenir et à lire chaque morceau de l'arbre pour dépenser les mêmes bitcoins (ndlr. pour ces optimisations en particulier, voir le lien avec MAST).

La même structure fournit également un meilleur moyen de composer des scripts (par exemple un multi-sig à l'intérieur d'un multi-sig...) qui est l'un des autres avantages de Miniscript.

L'optimisation ne s'arrête pas là car, comme nous l'avons dit, Miniscript fournit une meilleure Analyse Statique. Vous disposez désormais d'outils puissants pour examiner un Bitcoin Script (ou une Policy) et, en plus, vous pouvez ajouter des indications pour que les outils affinent vos scripts. Concrètement, vous pouvez ajouter un poids à une branche de l'arborescence de script ! Dans l'exemple ci-dessus est codé le fait qu'il y a 99% de chances que "A" signe la transaction. Ainsi, le compilateur trouvera le meilleur miniscript pour remplir ces conditions. Et parce que le Miniscript obtenu est directement mappé à son équivalent Bitcoin Script, vous obtenez le meilleur Bitcoin Script possible, et tout le monde peut l’utiliser avec n'importe quel wallet ou autre logiciel. La compatibilité est assurée.

Avec les outils, vous obtenez également un dimensionnement précis des coûts tels que les frais de commissions ― nous devons nous rappeler que nous sommes également limités en nombre d'opérateurs ― et vous pouvez tester vos conditions de dépenses sans dépenser (cf. Proof-of-Reserves). Avec ces outils, vous pouvez aussi travailler d'une autre manière, en codant d'abord vos conditions de dépenses dans différents Bitcoin Scripts, puis en les mappant dans des miniscripts que vous étudiez avec les outils.

Avec le compilateur en ligne et le dernier script du graphe, nous pouvons obtenir les informations suivantes en Unités de Poids (WU ; Weight Units) :

Spending cost analysis

  • Script: 67 WU
  • Input: 73.350000 WU
  • Total: 140.350000 WU

Comme vous pouvez le voir, Miniscript est loin d'être plus limité que Bitcoin Script, et dire que son objectif principal est la lisibilité humaine est très subjectif.

Envie de manipuler des graphes Miniscript ?

Si vous êtes impatient de jouer avec ces graphes, rendez-vous dès maintenant sur ce "playground" Miniscript en ligne de Bitcoin Dev Kit :

https://bitcoindevkit.org/bdk-cli/playground/

Là-bas, vous pourrez construire interactivement des graphes Policy.

Voyez par vous-même avec le graphe précédent en exemple, tourné et collé sur l'image ci-dessous, pour une meilleure compréhension :

Bac à sable de manipulation de graphes Policy et Miniscript.

Notez que vous pouvez choisir entre les trois versions d'encodage du Bitcoin Script : P2WSH ; P2SH-P2WSH ; P2SH. Pour le Miniscript, cela conduit respectivement aux trois racines : wsh() ; sh(wsh()) ; sh().

Les graphes, très peu pour moi !

Si la notation polonaise et les graphes vous empêchent de penser correctement, vous pouvez désormais évoluer à un niveau légèrement plus élevé grâce à Minsc.

Minsc est un langage haut-niveau s’exprimant en Policy. Nous sommes donc sur une troisième couche au-dessus de Bitcoin Script.

La syntaxe et les notations sont tout à fait classiques, et on s’y retrouve très vite. Les apports sont dans les possibilités d’écriture de temps et durées, les définitions de variables, les listes, et bien sûr les fonctions.

Pour reprendre l’exemple précédent du graphe, nous devrions écrire le script Minsc suivant :

99@pk(A) || (1@(pk(B) && older(144)))

Vous pouvez le vérifier à l’adresse suivante :

https://min.sc/#c=99%40pk%28A%29%20%7C%7C%20%281%40%28pk%28B%29%20%26%26%20older%28144%29%29%29

Et après ?

Le Miniscript actuel est intégré dans Bitcoin Core et implémenté en C++ et Rust. Il est encore tôt, et Miniscript est toujours en cours de développement. Il y a encore du travail pour permettre aux gens d'utiliser facilement les fonctionnalités déjà présentes dans Bitcoin. Miniscript doit être inclus dans des logiciels couramment utilisés, comme les wallets.

Mais avant cela, des tâches complexes doivent être accomplies. Plus vous approchez d'une limite de Bitcoin Script, plus il devient difficile d'optimiser la Policy (e.g. nombre d’opérateurs OP max...). Les informations provenant des outils sur une transaction, comme les commissions, sont difficiles à évaluer en raison de la difficulté à deviner la taille des Witness (BIP#112). De plus, depuis Segwit, la nouvelle façon dont les "inputs" de transactions sont encodés dans la pile conduit à encore plus d'analyses.

Plus d'optimisations pourraient être réalisées avec Miniscript grâce à l'ajout d'opérateurs dans Bitcoin Script. Donc, bien sûr, cela signifie que l'évolution de Miniscript dépend également de celle de Bitcoin Script.

Pendant ce temps, les deux compilateurs peuvent être améliorés, et des tests randomisés à grande échelle sont nécessaires et fourniront des données précieuses.

Cela m'amène à ce que je considère comme les seuls vrais "défauts" de Miniscript. C’est bien sûr mon opinion personnelle, mais j’étais en fait assez surpris que différentes personnes de la communauté (au moins française) ait la même.

Le seul défaut que j'ai pu voir est que la manière et le moment de l’annonce et de la publication de Miniscript ne permettent pas de suivre la philosophie écrasante de Bitcoin du "Don’t Trust, Verify" ("Ne faites pas confiance, Vérifiez"). On ne peut pas vérifier la plupart des fonctionnalités de Miniscript, car la majorité du travail (incroyable) de Pieter Wuille, Andrew Poelstra, et Sanket Kanjalkar n'est pas du tout public (e.g. impossible de vérifier le 1-to-1 mapping entre Bitcoin Script et Miniscript...). Donc, pour l'instant seulement j'espère, nous devons leur faire confiance, et indirectement, à Blockstream. Cela pourrait bien sûr être une source d'attaque sociale et politique contre Bitcoin, comme nous l'avons déjà vu dans le passé, et encore aujourd'hui, lorsque certaines personnes soutiennent que Blockstream, ou Bitcoin Core, centralisent Bitcoin.

Enfin, quelques autres projets connexes

Les Output Descriptors sont un moyen de décrire tous les types d'adresses. Ils sont importants car ils aident à classer les modèles et adresses de scripts structurés. Creuser ce sujet permet de comprendre les défis qui se cachent derrière Miniscript.

PSBT (Partially Signed Bitcoin Transaction ; Transaction Bitcoin Partiellement Signée) a introduit une sorte de moyen de fractionner une validation de Bitcoin Script qui améliore vraiment la sécurité. Mais dans le même temps, qui divise également l'analyse du script, et donc le Miniscript associé.

Ivy est un langage de haut niveau qui se compile en Bitcoin Script et a été développé chez Chain. J'ai été surpris que si peu de gens le connaissent et j'ai découvert en écrivant cet article que la documentation et l’outil en ligne pour le tester ont disparus.

Simplicity est un langage bas niveau inventé par Russell O'Connor et visant à remplacer Bitcoin Script, permettant une efficacité extrême, une Analyse Statique extrême, et même les Méthodes Formelles pour une fiabilité extrême.

L’innovation est bien là du côté de Bitcoin ! Il suffit de chercher un peu.

Sources

Tous les liens contenus dans cet article.

Ateliers, meetups, présentations et questions pertinentes de la communauté pour la communauté sur ce sujet avec en particulier Sosthene et Marsu pour les présentations.