Bitcoin a été initialement conçu avec un langage de script entièrement étoffé, destiné à englober et à support tout cas d’utilisation sûr potentiel que les utilisateurs pourraient proposer à l’avenir. Comme Satoshi lui-même l’a dit avant de disparaître :
"La nature de Bitcoin est telle qu’une fois la version 0.1 publiée, la conception du noyau a été gravée dans la pierre pour le reste de sa durée de vie. Pour cette raison, je voulais le concevoir pour prendre en support tous les types de transactions possibles auxquels je pouvais penser. Le problème était que chaque chose nécessitait un code de support spécial et des champs de données, qu’elle soit utilisée ou non, et ne couvrait qu’un cas particulier à la fois. Cela aurait été une explosion de cas particuliers. La solution a été un script, qui généralise le problème afin que les parties à la transaction puissent décrire leur transaction comme un prédicat évalué par le réseau de nœuds. - Satoshi, 17 juin 2010.
L’objectif était de donner aux utilisateurs un langage suffisamment général pour qu’ils puissent composer leurs propres types de transactions comme bon leur semble, c’est-à-dire donner aux utilisateurs la possibilité de concevoir et d’expérimenter la façon dont ils programment leur propre monnaie.
Avant de disparaître, Satoshi a arraché 15 de ces opcodes, les désactivant entièrement et ajoutant une limite stricte à la taille d’un élément de données pouvant être manipulé sur la pile du moteur de script (520 octets). Cela a été fait parce qu’il s’est franchement planté et a laissé ouvertes un grand nombre de façons dont des scripts compliqués pourraient être utilisés pour attaquer l’ensemble du réseau par déni de service, créant des transactions énormes et coûteuses à valider qui feraient planter les nœuds.
Ces opcodes n’ont pas été supprimés parce que Satoshi pensait que la fonctionnalité était dangereuse, ou que les gens ne devraient pas être en mesure de construire les choses qu’ils pouvaient avec eux, mais uniquement (du moins apparemment) à cause du risque pour le réseau dans son ensemble de les utiliser sans contraintes de ressources pour limiter le pire des coûts de validation qu’ils pourraient imposer au réseau.
Chaque mise à niveau de Bitcoin depuis lors a finalement rationalisé la fonctionnalité laissée, corrigeant d’autres défauts moins graves que Satoshi nous a laissés, et étendant la fonctionnalité de ce sous-ensemble de script qui nous a été laissé.
Lors de Bitcoin++ à Austin au début du mois de mai, le développeur de Core Lightning, Rusty Russell, a fait une proposition assez radicale lors de la première présentation de la conférence. Il a essentiellement lancé l’idée de revenir sur la plupart des opcodes qui Satoshi désactivés en 2010 avant sa disparition.
Au cours des dernières années, depuis l’activation de Taproot en 2021, l’espace de développement a été franchement sans but. Nous savons tous que Bitcoin n’est pas assez évolutif pour vraiment servir une partie importante de la population mondiale d’une manière auto-souveraine, et probablement même pas d’une manière minimisée ou dépositaire de la confiance qui peut évoluer au-delà des très grands dépositaires et fournisseurs de services incapables d’échapper vraiment au bras long du gouvernement.
Quiconque comprend Bitcoin sur le plan technologique comprend cela, ce n’est pas un sujet de débat. Ce qui fait l’objet d’un débat, et qui est très controversé, c’est de savoir comment s’y prendre pour remédier à cette lacune. Depuis Taproot, tout le monde a avancé des propositions très étroites destinées à ne traiter que des cas d’utilisation très particuliers qui pourraient être activés.
ANYPREVOUT (APO), une proposition visant à permettre aux signatures d’être réutilisables sur différentes transactions aussi longues que le script et la quantité d’entrée étaient les mêmes, a été conçue spécifiquement pour optimiser Lightning et les versions multipartites de celui-ci. CHECKTEMPLATEVERIFY (CTV), une proposition visant à faire respecter les pièces de monnaie ne pouvant être dépensées que par une transaction qui correspond exactement à une transaction prédéfinie, a été conçue spécifiquement pour étendre la fonctionnalité des chaînes de transactions pré-signées en les rendant totalement fiables. OP_VAULT a été conçu spécifiquement pour permettre une « période de délai d’expiration » pour les schémas de stockage à froid, afin qu’un utilisateur puisse « annuler » un retrait du stockage à froid en l’envoyant à une configuration multisig encore plus froide si ses clés étaient compromises.
Il y a un tas d’autres propositions, mais je pense que vous avez compris. Plutôt que d’essayer d’aborder de manière exhaustive l’expressivité et la programmabilité nécessaires pour faire évoluer Bitcoin de manière fondamentale, chacune des propositions au cours des dernières années a été conçue pour donner une petite augmentation de l’évolutivité ou améliorer une seule fonctionnalité étroite jugée souhaitable. Je pense que c’est la raison pour laquelle aucune de ces conversations n’aboutit. Personne n’est satisfait d’une autre proposition parce qu’elle ne répond pas au cas d’utilisation qu’ils veulent voir construite.
Rien n’est assez complet pour que quiconque puisse penser, en dehors de l’auteur de la proposition, qu’il s’agit de la prochaine étape raisonnable à franchir.
C’est la logique qui sous-tend la Grande Restauration de l’Écriture. En poussant et en analysant une restauration complète du script tel que Satoshi l’a initialement conçu, nous pouvons réellement essayer d’explorer tout l’espace des fonctionnalités dont nous avons besoin, plutôt que de nous chamailler et de nous battre pour savoir quelle petite extension de fonctionnalité est assez bonne pour le moment.
Ceux ci-dessus sont les opcodes destinés à être restaurés. En plus de ceux-ci, Rusty en propose trois autres pour simplifier la composition des différents opcodes.
Les couches 2 sont intrinsèquement une extension de la couche de base de Bitcoin, elles sont par nature limitées en termes de fonctionnalité par la fonctionnalité de la couche de base. Lightning nécessitait trois softforks distincts, CHECKLOCKTIMEVERIFY (CLTV), CHECKSEQUENCEVERIFY (CSV) et Segregated Witness avant qu’il ne soit possible de l’implémenter.
Vous ne pouvez tout simplement pas construire des couches 2 plus flexibles sans une couche de base plus flexible. Le seul raccourci pour contourner ce problème est celui des tiers de confiance, purement et simplement. C’est quelque chose que j’espère que nous aspirons tous à supprimer de tous les aspects de l’interaction avec Bitcoin à grande échelle.
Il y a des choses que nous devons être en mesure de faire que nous ne pouvons tout simplement pas faire en ce moment dans l’ordre pour emballer en toute sécurité plus de deux personnes dans un seul UTXO d’une manière qui peut être appliquée sans confiance sur la couche de base, le script Bitcoin n’est tout simplement pas assez flexible. Au niveau le plus élémentaire, nous avons besoin de covenants, nous avons besoin de la capacité du script à appliquer des détails plus granulaires sur la transaction en les exécutant pour s’assurer que des choses comme un utilisateur quittant en toute sécurité un UTXO par lui-même ne mettent pas les fonds des autres utilisateurs en danger.
À vue d’ensemble, c’est le type de fonctionnalité dont nous avons besoin :
Introspection : Nous devons être en mesure d’inspecter des détails spécifiques sur une transaction de dépense elle-même sur la pile, tels que « cette somme d’argent va à cette clé publique dans une sortie ». Cela me permet de retirer mon argent par moi-même en utilisant une branche Taproot spécifique, tout en m’assurant que je ne peux pas prendre l’argent de quelqu’un d’autre. Le script en cours d’exécution imposerait par consensus que la quantité correcte que tout le monde possède est renvoyée à une adresse composée des clés publiques des autres utilisateurs si je suis parti.
Transfert de données : Disons que nous allons encore plus loin que l’idée d’un canal Lightning avec plus de deux personnes, nous construisons un seul UTXO avec une quantité massive de personnes où tout le monde peut aller et venir à sa guise. D’une manière ou d’une autre, presque toujours avec un merkle et sa racine, nous avons besoin d’un moyen de savoir qui a combien d’argent. Cela signifie que lorsque quelqu’un part, nous devons être en mesure de nous assurer que le « dossier » de qui a droit à quoi fait partie du changement UTXO de l’argent de tout le monde. Il s’agit essentiellement d’une utilisation spécifique pour l’introspection.
Modification des clés publiques : nous devons pouvoir nous assurer que les modifications apportées aux clés publiques agrégées peuvent être vérifiées sur la pile. L’objectif à atteindre dans les systèmes de partage UTXO est qu’il y ait une clé agrégée avec toutes les personnes impliquées permettant un mouvement de fonds coopératif et plus efficace. Chaque fois que quelqu’un quitte unilatéralement un UTXO partagé, nous devons supprimer sa clé individuelle de l’agrégat. Sans précalculer à l’avance toutes les combinaisons possibles, la seule option est de pouvoir vérifier que la soustraction d’une clé de l’agrégat crée une clé valide composée du reste des clés individuelles.
Comme je l’ai dit plus haut, la raison pour laquelle tous ces opcodes ont été désactivés était d’éliminer les risques d’attaques par déni de service qui pourraient littéralement faire planter les nœuds composant le réseau. Il y a un moyen de résoudre ce problème, de limiter la quantité de ressources que n’importe lequel de ces opcodes peut utiliser.
Nous avons déjà une telle solution en ce qui concerne la vérification des signatures, la partie la plus coûteuse de la vérification des scripts Bitcoin. C’est ce qu’on appelle le budget sigops. Chaque utilisation d’un opcode de vérification de signature consomme un certain « budget » d’opérations de signature autorisées par bloc. Cela impose une limite stricte au coût que les transactions peuvent imposer aux utilisateurs pour vérifier un bloc individuel.
Taproot a changé la façon dont cela fonctionne, au lieu d’utiliser une seule limite de bloc globale, chaque transaction a sa propre limite sigops proportionnelle à la taille de la transaction. Cela correspond essentiellement à la même limite globale, mais facilite le raisonnement en termes de nombre de sigops dont dispose une transaction individuelle.
Le changement dans la façon dont Taproot gère les limites sigops par rapport à chaque transaction offre un moyen de généraliser cela, ce que Rusty propose avec une limite varops. L’idée est d’attribuer un coût pour chacun des opcodes réactivés afin de prendre en compte le pire des cas, c’est-à-dire le coût de calcul le plus cher à valider, que chaque opcode pourrait créer. Avec cela, chacun de ces opcodes aurait sa propre limite de « sigops » pour limiter le nombre de ressources qu’il pourrait consommer en vérification. Il serait également basé sur la taille de toute transaction qui les utilise, ce qui permet de maintenir la facilité de raisonnement à ce sujet, tout en s’ajoutant à une limite globale implicite par bloc.
Cela résoudrait les risques de déni de service qui ont amené Satoshi à désactiver tous ces opcodes en premier lieu.
Je suis sûr que beaucoup d’entre vous pensent « c’est un changement beaucoup trop important ». Je peux comprendre cela, mais je pense qu’un aspect important de ce projet en tant que proposition à comprendre est que nous n’avons pas à tout faire. La valeur de cette proposition n’est pas nécessairement de réactiver tout cela dans son ensemble, c’est le fait que nous examinerions en fait de manière exhaustive une suite massive de primitives et que nous nous demanderions ce que nous attendons vraiment de cela en termes de fonctionnalité.
Il s’agirait d’une volte-face complète par rapport aux trois dernières années de chamailleries et de disputes sur de minuscules changements étroits qui n’aident que certaines fonctionnalités. C’est une tente qui pourrait rassembler tout le monde sous un même toit pour évaluer de manière vraiment complète ce qu’il faut faire à partir d’ici. Peut-être que nous finissons par réactiver tout cela, peut-être que nous finissons par activer quelques choses parce que le consensus est que c’est tout ce dont nous avons besoin pour activer les fonctionnalités dont tout le monde s’accorde à dire que nous avons besoin.
Quel que soit le résultat final, il peut s’agir d’un changement productif dans l’ensemble de la conversation sur la direction que nous prendrons à partir de maintenant. Nous pouvons en fait cartographier et obtenir une configuration complète du terrain, plutôt que de nous disputer sur le chemin trouble et à moitié éclairé à emprunter ensuite.
Ce n’est en aucun cas la voie à suivre que nous empruntons, mais je pense que c’est notre meilleure chance de décider laquelle nous ferons. Il est temps de recommencer à travailler ensemble de manière productive.
Bitcoin a été initialement conçu avec un langage de script entièrement étoffé, destiné à englober et à support tout cas d’utilisation sûr potentiel que les utilisateurs pourraient proposer à l’avenir. Comme Satoshi lui-même l’a dit avant de disparaître :
"La nature de Bitcoin est telle qu’une fois la version 0.1 publiée, la conception du noyau a été gravée dans la pierre pour le reste de sa durée de vie. Pour cette raison, je voulais le concevoir pour prendre en support tous les types de transactions possibles auxquels je pouvais penser. Le problème était que chaque chose nécessitait un code de support spécial et des champs de données, qu’elle soit utilisée ou non, et ne couvrait qu’un cas particulier à la fois. Cela aurait été une explosion de cas particuliers. La solution a été un script, qui généralise le problème afin que les parties à la transaction puissent décrire leur transaction comme un prédicat évalué par le réseau de nœuds. - Satoshi, 17 juin 2010.
L’objectif était de donner aux utilisateurs un langage suffisamment général pour qu’ils puissent composer leurs propres types de transactions comme bon leur semble, c’est-à-dire donner aux utilisateurs la possibilité de concevoir et d’expérimenter la façon dont ils programment leur propre monnaie.
Avant de disparaître, Satoshi a arraché 15 de ces opcodes, les désactivant entièrement et ajoutant une limite stricte à la taille d’un élément de données pouvant être manipulé sur la pile du moteur de script (520 octets). Cela a été fait parce qu’il s’est franchement planté et a laissé ouvertes un grand nombre de façons dont des scripts compliqués pourraient être utilisés pour attaquer l’ensemble du réseau par déni de service, créant des transactions énormes et coûteuses à valider qui feraient planter les nœuds.
Ces opcodes n’ont pas été supprimés parce que Satoshi pensait que la fonctionnalité était dangereuse, ou que les gens ne devraient pas être en mesure de construire les choses qu’ils pouvaient avec eux, mais uniquement (du moins apparemment) à cause du risque pour le réseau dans son ensemble de les utiliser sans contraintes de ressources pour limiter le pire des coûts de validation qu’ils pourraient imposer au réseau.
Chaque mise à niveau de Bitcoin depuis lors a finalement rationalisé la fonctionnalité laissée, corrigeant d’autres défauts moins graves que Satoshi nous a laissés, et étendant la fonctionnalité de ce sous-ensemble de script qui nous a été laissé.
Lors de Bitcoin++ à Austin au début du mois de mai, le développeur de Core Lightning, Rusty Russell, a fait une proposition assez radicale lors de la première présentation de la conférence. Il a essentiellement lancé l’idée de revenir sur la plupart des opcodes qui Satoshi désactivés en 2010 avant sa disparition.
Au cours des dernières années, depuis l’activation de Taproot en 2021, l’espace de développement a été franchement sans but. Nous savons tous que Bitcoin n’est pas assez évolutif pour vraiment servir une partie importante de la population mondiale d’une manière auto-souveraine, et probablement même pas d’une manière minimisée ou dépositaire de la confiance qui peut évoluer au-delà des très grands dépositaires et fournisseurs de services incapables d’échapper vraiment au bras long du gouvernement.
Quiconque comprend Bitcoin sur le plan technologique comprend cela, ce n’est pas un sujet de débat. Ce qui fait l’objet d’un débat, et qui est très controversé, c’est de savoir comment s’y prendre pour remédier à cette lacune. Depuis Taproot, tout le monde a avancé des propositions très étroites destinées à ne traiter que des cas d’utilisation très particuliers qui pourraient être activés.
ANYPREVOUT (APO), une proposition visant à permettre aux signatures d’être réutilisables sur différentes transactions aussi longues que le script et la quantité d’entrée étaient les mêmes, a été conçue spécifiquement pour optimiser Lightning et les versions multipartites de celui-ci. CHECKTEMPLATEVERIFY (CTV), une proposition visant à faire respecter les pièces de monnaie ne pouvant être dépensées que par une transaction qui correspond exactement à une transaction prédéfinie, a été conçue spécifiquement pour étendre la fonctionnalité des chaînes de transactions pré-signées en les rendant totalement fiables. OP_VAULT a été conçu spécifiquement pour permettre une « période de délai d’expiration » pour les schémas de stockage à froid, afin qu’un utilisateur puisse « annuler » un retrait du stockage à froid en l’envoyant à une configuration multisig encore plus froide si ses clés étaient compromises.
Il y a un tas d’autres propositions, mais je pense que vous avez compris. Plutôt que d’essayer d’aborder de manière exhaustive l’expressivité et la programmabilité nécessaires pour faire évoluer Bitcoin de manière fondamentale, chacune des propositions au cours des dernières années a été conçue pour donner une petite augmentation de l’évolutivité ou améliorer une seule fonctionnalité étroite jugée souhaitable. Je pense que c’est la raison pour laquelle aucune de ces conversations n’aboutit. Personne n’est satisfait d’une autre proposition parce qu’elle ne répond pas au cas d’utilisation qu’ils veulent voir construite.
Rien n’est assez complet pour que quiconque puisse penser, en dehors de l’auteur de la proposition, qu’il s’agit de la prochaine étape raisonnable à franchir.
C’est la logique qui sous-tend la Grande Restauration de l’Écriture. En poussant et en analysant une restauration complète du script tel que Satoshi l’a initialement conçu, nous pouvons réellement essayer d’explorer tout l’espace des fonctionnalités dont nous avons besoin, plutôt que de nous chamailler et de nous battre pour savoir quelle petite extension de fonctionnalité est assez bonne pour le moment.
Ceux ci-dessus sont les opcodes destinés à être restaurés. En plus de ceux-ci, Rusty en propose trois autres pour simplifier la composition des différents opcodes.
Les couches 2 sont intrinsèquement une extension de la couche de base de Bitcoin, elles sont par nature limitées en termes de fonctionnalité par la fonctionnalité de la couche de base. Lightning nécessitait trois softforks distincts, CHECKLOCKTIMEVERIFY (CLTV), CHECKSEQUENCEVERIFY (CSV) et Segregated Witness avant qu’il ne soit possible de l’implémenter.
Vous ne pouvez tout simplement pas construire des couches 2 plus flexibles sans une couche de base plus flexible. Le seul raccourci pour contourner ce problème est celui des tiers de confiance, purement et simplement. C’est quelque chose que j’espère que nous aspirons tous à supprimer de tous les aspects de l’interaction avec Bitcoin à grande échelle.
Il y a des choses que nous devons être en mesure de faire que nous ne pouvons tout simplement pas faire en ce moment dans l’ordre pour emballer en toute sécurité plus de deux personnes dans un seul UTXO d’une manière qui peut être appliquée sans confiance sur la couche de base, le script Bitcoin n’est tout simplement pas assez flexible. Au niveau le plus élémentaire, nous avons besoin de covenants, nous avons besoin de la capacité du script à appliquer des détails plus granulaires sur la transaction en les exécutant pour s’assurer que des choses comme un utilisateur quittant en toute sécurité un UTXO par lui-même ne mettent pas les fonds des autres utilisateurs en danger.
À vue d’ensemble, c’est le type de fonctionnalité dont nous avons besoin :
Introspection : Nous devons être en mesure d’inspecter des détails spécifiques sur une transaction de dépense elle-même sur la pile, tels que « cette somme d’argent va à cette clé publique dans une sortie ». Cela me permet de retirer mon argent par moi-même en utilisant une branche Taproot spécifique, tout en m’assurant que je ne peux pas prendre l’argent de quelqu’un d’autre. Le script en cours d’exécution imposerait par consensus que la quantité correcte que tout le monde possède est renvoyée à une adresse composée des clés publiques des autres utilisateurs si je suis parti.
Transfert de données : Disons que nous allons encore plus loin que l’idée d’un canal Lightning avec plus de deux personnes, nous construisons un seul UTXO avec une quantité massive de personnes où tout le monde peut aller et venir à sa guise. D’une manière ou d’une autre, presque toujours avec un merkle et sa racine, nous avons besoin d’un moyen de savoir qui a combien d’argent. Cela signifie que lorsque quelqu’un part, nous devons être en mesure de nous assurer que le « dossier » de qui a droit à quoi fait partie du changement UTXO de l’argent de tout le monde. Il s’agit essentiellement d’une utilisation spécifique pour l’introspection.
Modification des clés publiques : nous devons pouvoir nous assurer que les modifications apportées aux clés publiques agrégées peuvent être vérifiées sur la pile. L’objectif à atteindre dans les systèmes de partage UTXO est qu’il y ait une clé agrégée avec toutes les personnes impliquées permettant un mouvement de fonds coopératif et plus efficace. Chaque fois que quelqu’un quitte unilatéralement un UTXO partagé, nous devons supprimer sa clé individuelle de l’agrégat. Sans précalculer à l’avance toutes les combinaisons possibles, la seule option est de pouvoir vérifier que la soustraction d’une clé de l’agrégat crée une clé valide composée du reste des clés individuelles.
Comme je l’ai dit plus haut, la raison pour laquelle tous ces opcodes ont été désactivés était d’éliminer les risques d’attaques par déni de service qui pourraient littéralement faire planter les nœuds composant le réseau. Il y a un moyen de résoudre ce problème, de limiter la quantité de ressources que n’importe lequel de ces opcodes peut utiliser.
Nous avons déjà une telle solution en ce qui concerne la vérification des signatures, la partie la plus coûteuse de la vérification des scripts Bitcoin. C’est ce qu’on appelle le budget sigops. Chaque utilisation d’un opcode de vérification de signature consomme un certain « budget » d’opérations de signature autorisées par bloc. Cela impose une limite stricte au coût que les transactions peuvent imposer aux utilisateurs pour vérifier un bloc individuel.
Taproot a changé la façon dont cela fonctionne, au lieu d’utiliser une seule limite de bloc globale, chaque transaction a sa propre limite sigops proportionnelle à la taille de la transaction. Cela correspond essentiellement à la même limite globale, mais facilite le raisonnement en termes de nombre de sigops dont dispose une transaction individuelle.
Le changement dans la façon dont Taproot gère les limites sigops par rapport à chaque transaction offre un moyen de généraliser cela, ce que Rusty propose avec une limite varops. L’idée est d’attribuer un coût pour chacun des opcodes réactivés afin de prendre en compte le pire des cas, c’est-à-dire le coût de calcul le plus cher à valider, que chaque opcode pourrait créer. Avec cela, chacun de ces opcodes aurait sa propre limite de « sigops » pour limiter le nombre de ressources qu’il pourrait consommer en vérification. Il serait également basé sur la taille de toute transaction qui les utilise, ce qui permet de maintenir la facilité de raisonnement à ce sujet, tout en s’ajoutant à une limite globale implicite par bloc.
Cela résoudrait les risques de déni de service qui ont amené Satoshi à désactiver tous ces opcodes en premier lieu.
Je suis sûr que beaucoup d’entre vous pensent « c’est un changement beaucoup trop important ». Je peux comprendre cela, mais je pense qu’un aspect important de ce projet en tant que proposition à comprendre est que nous n’avons pas à tout faire. La valeur de cette proposition n’est pas nécessairement de réactiver tout cela dans son ensemble, c’est le fait que nous examinerions en fait de manière exhaustive une suite massive de primitives et que nous nous demanderions ce que nous attendons vraiment de cela en termes de fonctionnalité.
Il s’agirait d’une volte-face complète par rapport aux trois dernières années de chamailleries et de disputes sur de minuscules changements étroits qui n’aident que certaines fonctionnalités. C’est une tente qui pourrait rassembler tout le monde sous un même toit pour évaluer de manière vraiment complète ce qu’il faut faire à partir d’ici. Peut-être que nous finissons par réactiver tout cela, peut-être que nous finissons par activer quelques choses parce que le consensus est que c’est tout ce dont nous avons besoin pour activer les fonctionnalités dont tout le monde s’accorde à dire que nous avons besoin.
Quel que soit le résultat final, il peut s’agir d’un changement productif dans l’ensemble de la conversation sur la direction que nous prendrons à partir de maintenant. Nous pouvons en fait cartographier et obtenir une configuration complète du terrain, plutôt que de nous disputer sur le chemin trouble et à moitié éclairé à emprunter ensuite.
Ce n’est en aucun cas la voie à suivre que nous empruntons, mais je pense que c’est notre meilleure chance de décider laquelle nous ferons. Il est temps de recommencer à travailler ensemble de manière productive.