Pensez Blockchain

La référence en chaîne de blocs au Québec

 
Capture d’écran 2019-12-11 à 14.53.48.png
 

Dans la première partie, nous avons expliqué qu’une transaction est composée de deux éléments : les « inputs » qui font référence aux UTXO d’anciennes transactions et qui possèdent un script permettant de les déverrouiller et les « outputs » qui permettent de créer les nouveaux UTXO et le script qui les verrouille.

Ensuite, dans la deuxième partie, nous avons expliqué le fonctionnement du langage à base d’empilement utilisé pour les transactions Bitcoin. Nous avons également présenté la manière dont fonctionne le verrouillage et déverrouillage des UTXO dans ce langage avec l’exemple de transaction la plus courante : le P2PKH (Pay-To-Public-Key-Hash), c’est-à-dire, le paiement  au hash d’une clé publique (à une adresse).

Dans cette troisième partie, nous allons discuter des autres types de transactions : le multisignature et le P2SH. Nous allons ensuite présenter quelques opérateurs permettant d’effectuer des scripts de transactions plus poussées et grâces auxquels il est possible d’ajouter des couches de complexité comme le Lightning Network sur la chaîne de blocs Bitcoin. 

Multisignature

Comme son nom l’indique, le multisignature ou multisig est un type de transaction qui requiert plusieurs signatures pour déverrouiller un UTXO (pour dépenser des bitcoins). Par exemple, cela peut être utile dans une entreprise où plusieurs partenaires souhaiteraient se répartir des clés privées pour signer une transaction. Trois partenaires pourraient avoir chacun leurs clés privées associées à une adresse où au moins deux sont requises pour débloquer les fonds. Cela représente alors une multisignature 2-de-3.

De manière générale, une transaction multisignature s’écrit M-de-N où N est le nombre total de clés privées réparties entre différents utilisateurs et M est le nombre minimum de signatures nécessaires pour réaliser une transaction. Le maximum étant 15-de-15.

Dans le langage Script, le code permettant de verrouiller un UTXO avec une transaction multisignature 2-de-3 s’écrirait : 

         2    <Clé publique 1> <Clé publique 2> <Clé publique 3>   3   CHECKMULTISIG

Et le code permettant de le déverrouiller serait :

        0   <Signature 2> <Signature 3>

Ces scripts de verrouillage et de déverrouillage seront évalués comme TRUE si les deux signatures présentées correspondent à au moins deux des clés publiques.

L’élément « 0 » ajouté au début du script de déverrouillage est utilisé pour résoudre un bug de l’opérateur CHECKMULTISIG. En effet, quand il sera activé, ce dernier va enlever le « 3 » (le nombre total de clés publiques), puis les clés publiques (en vérifiant qu’il y en a bien 3), il va ensuite enlever le « 2 » (le nombre de clés publiques nécessaire pour déverrouiller l’UTXO) et les signatures (en vérifiant qu’il y en a suffisamment et qu’elles correspondent aux clés privées). Il va ensuite enlever un élément supplémentaire (à cause du bug). C’est pourquoi, par consensus, un « 0 » est ajouté au début du script de déverrouillage. Sans celui-ci, le programme renverrait un message d’erreur et la transaction serait considérée comme invalide.

Un point négatif de ce type de transaction est que le script de verrouillage prend plus de poids et, plus il y a de clés publiques, plus le poids de la transaction sera important. En prenant plus d’espace dans un bloc, les frais de transactions seront alors plus importants. Le problème est que ce surplus de frais doit être payé par l’émetteur et non le receveur qui fabrique son portefeuille de manière complexe. En d’autres termes, si une entreprise utilise un système 2-de-3 (ou autres systèmes plus complexes), ce sont les clients lui envoyant les bitcoins qui devront payer un surplus de frais. 

Pour résoudre ce problème, le Pay-To-Script-Hash (P2SH) a été introduit en 2012. 

Pay-To-Script-Hash 

 Le Pay-To-Script-Hash (P2SH) ou paiement au hash d’un script permet de transférer le surplus de frais de l’émetteur au bénéficiaire.

L’idée est simple : plutôt que de payer des frais importants pour une transaction qui possède un script complexe (i.e. qui prend beaucoup d’espace dans un bloc), l’émetteur va verrouiller l’UTXO avec le hash de ce script (le hash prend toujours le même espace, quel que soit le script). Le bénéficiaire, qui souhaite avoir un script complexe, devra présenter ce script (appelé script de rédemption) qui a été hashé pour déverrouiller l’UTXO (pour dépenser ses bitcoins). C’est donc lui qui payera le surplus de frais, car c’est sa transaction qui prendra plus de place.

Dans une transaction P2SH, il y a donc 3 scripts : le script de verrouillage, le script de déverrouillage et le script de rédemption. En reprenant l’exemple précédent avec une multisignature 2-de-3, voici à quoi ces scripts ressembleraient :

Script de Redemption :

       2    <Clé publique 1> <Clé publique 2> <Clé publique 3>   3   CHECKMULTISIG

Script de verrouillage :

     HASH160   <Hash du script de redemption>  EQUAL

Script de déverrouillage :

     0   <Signature 2> <Signature 3>  <Script de Redemption> 

Pour vérifier la validité de la transaction, un noeud du réseau va dans un premier temps compiler le script de rédemption et le script de verrouillage.  Il va ainsi regarder si le script de rédemption, une fois hashé, correspond au hash dans le script de verrouillage :

   <Script de Redemption>  HASH160   <Hash du script de redemption>  EQUAL

Si c’est le cas, il va ensuite compiler le script de déverrouillage (dans lequel le script de rédemption est inclus). Si le résultat est TRUE, la transaction sera valide.

Dans Bitcoin, les adresses P2SH commencent par un « 3 ». C’est généralement le cas pour celles des plateformes d’échanges.

Ainsi, le P2SH permet aux utilisateurs de Bitcoin de réaliser des scripts plus complexes en transférant le surplus de frais au bénéficiaire, c’est-à-dire, à la personne qui souhaite utiliser un script complexe.

 Il est possible de faire des scripts plus complexes que le multisignature en utilisant des clauses conditionnelles.

Clauses Conditionnelles (IF, ELSE,…)

Les clauses conditionnelles sont des éléments essentiels en programmation. Elles permettent de choisir un chemin d’exécution en fonction de certaines conditions données au préalable : si la condition est vraie, le script 1 est exécuté, sinon c’est le script 2.  Dans le langage Script, ceci s’écrit de la manière suivante :

<Condition>

IF

          <Code exécuté si la condition est vraie>

ELSE

          <Code exécuté si la condition est fausse>

ENDIF

<Code exécuté dans tous les cas>

À noter que la condition (qui est un booléen TRUE ou FALSE) est donnée avant le « IF » dans le langage Script. En effet, celle-ci doit arriver dans la pile avant puisque l’opérateur « IF »  va l’enlever pour continuer le programme.

Ces clauses conditionnelles permettent ainsi de réaliser des transactions plus complexes. En plus de cela, le langage Script permet également de réaliser des transactions verrouillées dans le temps.

Transaction verrouillée dans le temps

 Dans Bitcoin, il est possible de faire des transactions qui ne peuvent pas être dépensées tout de suite, des transactions qui sont verrouillées pendant une certaine période.

Pour cela, il est possible de modifier le champ « locktime » de la transaction (voir partie 1). Si ce champ est différent de 0, la transaction sera considérée comme postdatée et il faudra que la date soit atteinte pour qu’elle soit considérée comme valide par un noeud du réseau et ajoutée dans un bloc.

Si le nombre inscrit est plus petit que 500 millions, il représente le nombre du bloc à partir duquel la transaction sera considérée valide (si ce nombre est plus petit que le numéro de bloc actuel, alors la transaction pourra être validée directement). En revanche, si le nombre est supérieur à 500 millions, il représente le nombre de secondes dans l’époque Unix (le nombre de secondes écoulées depuis le 1er Janvier 1970). La transaction sera alors considérée comme valide si l’heure inscrite dans le bloc est supérieure à celle inscrite dans le champ « locktime » de la transaction.

Le défaut principal de ce type de verrouillage temporel est que la transaction est inscrite dans un bloc seulement lorsque le temps est atteint. En d’autres termes, la transaction (même signée) n’a aucune valeur tant que la période n’a pas été écoulée. En effet, l’émetteur peut tout à fait dépenser l’UTXO entre temps ce qui rendra la transaction invalide lorsque le temps sera atteint. Le bénéficiaire n’a aucune garantie.

 Pour remédier à ce problème, un opérateur a été introduit en 2015 pour que la transaction soit bloquée dans le temps directement dans le script de verrouillage : l’opérateur CHECKLOCKTIMEVERIFY (CLTV). Il est ainsi possible d’inscrire une transaction dans un bloc et qu’elle ne puisse pas être dépensée avant un certain temps en utilisant cet opérateur dans le script de verrouillage des outputs de cette transaction. À noter que le champ « locktime » s’applique à toute la transaction (toutes les outputs) tandis que CLTV peut être utilisé que sur une seule output.

L’opérateur CLTV prend en entrée un nombre dont le format est le même que « locktime » (un bloc ou un temps suivant qu’il soit inférieur ou non à 500 millions). Si ce nombre est supérieur ou égal au « locktime » de la transaction (la transaction qui veut dépenser les bitcoins, pas celle qui les a verrouillés) alors le temps a été écoulé et le programme continuera. Si ce n’est pas le cas, le programme s’arrêtera directement. La raison pour laquelle cet opérateur ne renvoie pas TRUE ou FALSE sur la pile est par ce qu’il se termine par VERIFY. Tous les opérateurs ayant ce suffixe arrêtent l’exécution du programme lorsque le résultat est FALSE ou continuent l’exécution s’il est TRUE.

Voici un exemple de script de verrouillage pour une transaction multisig bloquée pendant 111 blocs en imaginant que nous sommes au bloc n° 220 000  au moment du verrouillage:

220111   CHECKLOCKTIMEVERIFY   DROP   2   <Clé publique 1> <Clé publique 2> <Clé publique 3>   3   CHECKMULTISIG

Après l’exécution du CLTV, le temps de verrouillage restera sur le haut de la pile. C’est pourquoi l’opérateur DROP est utilisé. Comme son nom l’indique, il permet d’enlever l’item en haut de la pile.

 Ainsi, le champ « locktime » et l’opérateur CLTV permettent de verrouiller une transaction dans le temps pour une date ou pour un bloc dans le futur. Ce type de verrouillage est dit absolu, car la transaction n’est pas verrouillée pendant un certain nombre de blocs, mais jusqu’à ce qu’un certain bloc soit atteint.

En 2016, le protocole Bitcoin a été mis à jour pour permettre d’effectuer des transactions bloquées dans le temps de manière relative. Par exemple, il est possible de faire une transaction verrouillée pendant 10 blocs dont le décompte commence seulement quand elle a été validée.

Le fonctionnement du verrouillage dans le temps relatif est similaire au verrouillage dans le temps absolu. Il existe un champ « sequence » (que nous avions mentionné en partie 1) situé dans les inputs de la transaction (chaque input peut avoir un nombre « sequence » différent) et un opérateur, CHECKSEQUENCEVERIFY (CSV),  qui permet de comparer le temps de verrouillage donné dans un script au temps donné dans le champ « sequence ».

Ces transactions verrouillées dans le temps de manière relative sont utilisées dans le Lightning Network.

Nous avons ainsi présenté certains types de transactions qu’il est possible de réaliser dans Bitcoin. Montrons maintenant un exemple pour récapituler tout ce dont nous avons parlé jusqu’à présent.

Exemple de transaction complexe

 Nous allons désormais voir un exemple de transaction complexe. Comme de nombreux exemples présentés ici, celui-ci est également tiré du livre Mastering Bitcoin de Andreas Antonopoulos. Dans cet exemple 3 partenaires souhaitent utiliser un script multisignature 2-de-3. Cependant, ils souhaitent qu’en cas de problème, leur avocat puisse effectuer une transaction avec l’accord de seulement un des partenaires. Ils souhaitent enfin que, si aucun d’entre eux n’est disponible pendant un certain temps, leur avocat puisse effectuer une transaction tout seul. Voici à quoi ressemblerait ce script de verrouillage (ou script de rédemption) :

IF

    IF

        2

    ELSE

        <30 jours>  CHECKSEQUENCEVERIFY  DROP 

        <Clé Publique de l’Avocat> CHECKSIGVERIFY

        1

    ENDIF

    <Clé publique Partenaire 1> <Clé publique Partenaire 2>

    <Clé publique Partenaire 3> 3 CHECKMULTISIG

ELSE

   <90 jours> CHECKSEQUENCEVERIFY DROP

   <Clé Publique de l’Avocat> CHECKSIG

ENDIF

Dans ce script, il y a 3 chemins d’exécutions possibles (les 3 mentionnés plus tôt). Comme nous pouvons le voir, il n’y a pas de conditions dans ce script. Elles seront en effet données dans le script de déverrouillage.

Si les partenaires souhaitent effectuer une transaction multisig, ils utiliseront un script de déverrouillage similaire à celui-ci (les partenaires qui signent peuvent changer):

0 <Signature Partenaire 1> <Signature Partenaire 3> TRUE TRUE

Les deux conditions sont vraies, ainsi, seules les lignes 3, 9 et 10 de script de verrouillage seront ajoutées à la pile. Nous retrouvons donc le schéma d’une transaction multisignature standard présenté au début de l’article.

Si un partenaire veut effectuer une transaction avec l’avocat, le script de déverrouillage sera le suivant :

0 <Signature Partenaire 2> <Signature de l’Avocat> FALSE TRUE

La première condition du script de verrouillage sera vraie, la deuxième sera fausse. Ainsi, seules les lignes 5, 6, 7, 9 et 10 seront ajoutées dans la pile. Dans un premier temps, il sera vérifié que 30 jours se sont écoulés (ligne 5) puis la validité de la signature de l’avocat sera examinée (ligne 6). Si elle est correcte c’est celle d’un des partenaires qui sera ensuite vérifiée par un procédé multisignature 1-de-3 (ligne 7, 9 et 10).

Enfin, l’avocat peut effectuer une transaction après 90 jours en utilisant le script de déverrouillage suivant :

<Signature de l’Avocat> FALSE

Ici, la première condition est fausse (la deuxième n’est donc pas atteinte). Ainsi, seules les lignes 12 et 13 sont ajoutées à la pile. Dans un premier temps, il sera vérifié que 90 jours se sont bien écoulés depuis le verrouillage du script (ligne 12). Si c’est le cas, la signature de l’avocat sera vérifiée avant de valider la transaction.

Ainsi, nous avons vu dans cette troisième partie qu’il est possible de faire des transactions complexes avec la chaîne de blocs Bitcoin. À l’aide du multisignature, il est possible de séparer le pouvoir de la transaction entre plusieurs personnes. Il est aussi possible de faire des transactions qui sont verrouillées pendant une certaine période et il existe également des clauses conditionnelles qui permettent d’avoir un script avec plusieurs chemins d’exécutions. Enfin, avec le P2SH, le paiement peut être réalisé avec le hash du script plutôt qu’avec ce dernier pour transférer le surplus de frais de transactions au bénéficiaire qui souhaite utiliser un script complexe.

Les 3 articles sur les transactions ont été grandement inspirés du livre Mastering Bitcoin de Andreas Antonopoulos. Si vous souhaitez en apprendre plus sur ce sujet ou sur la chaîne de blocs Bitcoin en général, je vous conseille fortement de lire ce livre.