Retour sur la conférence à l’INSA – Fonctionnement du réseau Bitcoin

Retour sur la conférence à l’INSA – Fonctionnement du réseau Bitcoin

Retour sur la conférence du 12 Juin

La présentation que j’ai faite sur le fonctionnement de Bitcoin Mardi à l’INSA a pu paraître un peu déstructurée. C’était le cas. L’objectif était de présenter le fonctionnement du réseau, sans être trop long. Être exhaustif et complet. Dans l’idée cela semblait plutôt une bonne chose, en situation réelle et sous forme de conférence, c’est devenu plus compliqué.
Je vais donc ici reprendre cette présentation slide par slide en expliquant de façon plus organisée chaque idée. J’aurai donc la possibilité de mettre des tartines d’explication sans vous forcer à les avaler, ceux avec le moins d’appétit pourront lire les grandes lignes, ou s’arrêter et revenir en manger dès qu’ils se sentiront. Pour les plus gourmands, ou simplement gourmets –ça dépend du point de vue-, je mettrai des liens pour permettre d’aller plus loin.

Lien vers les slides : https://sia.pixeldrain.com/u/A6AgTh

0) – Prérequis

Cet article s’adresse plutôt à des personnes ayant déjà utilisé Bitcoin (ou d’autres cryptos) et curieuses de savoir le fonctionnement des choses. Il est donc préférable d’être à l’aise avec les notions de cryptographie asymétrique (aïe deux gros mots l’un à côté de l’autre), ce qui représente tout simplement l’adresse (pour vous envoyer des fonds) et la clef privée (pour que vous puissiez les envoyer à votre tour). Il est aussi préférable d’avoir entendu parler de blocs, de chaînes de blocs, de mining, et si c’est le cas mais que c’est un peu le fouillis dans votre esprit : c’est parfait vous êtes pleine cible de cet article. Les autres ne partez pas tout de suite ! Bien que j’ai dit que ce soit préférable, ce n’est pas absolument nécessaire d’avoir déjà expérimenté. Donc si vous vous sentez tout simplement curieux, le cœur aventureux, ou que vous ne savez plus comment meubler votre temps libre dans ce gros moment de flottement entre la fin du championnat et le début de la coupe du monde, vous êtes aussi les bienvenus, et je vous conseille tout de même d’aller vous référer à notre lexique, afin de mieux pouvoir déguster.

Les moins préparés étant à présent armés, on peut y aller. Au passage si vous avez une question ou une remarque, n’hésitez pas à venir la poser sur le Discord, on vous répondra avec plaisir ! https://discord.gg/jcwHsT3

I) – Présentation

Qu’est-ce Bitcoin ? Ce n’est pas forcément la question finale de cet article, dans lequel on essaiera plutôt de comprendre son fonctionnement, mais on va tout de même y répondre pour que ça soit clair : c’est un programme. Vous allez me dire merci Serge, mais c’est vraiment ça. Le programme s’appelle bitcoin-core et ce que l’on va appeler « Bitcoin » c’est l’ensemble de plusieurs ordinateurs faisant tourner ce programme.
Ces ordinateurs participent au réseau et s’appellent des nodes.

A) Les nodes, fondation du réseau

Schéma nodes

Les nodes sont sur Bitcoin, comme sur tous les réseaux peer-to-peer la base du réseau. Ils font tourner le programme (principalement bitcoin-core) et permettent donc au réseau de fonctionner. Ils réalisent plusieurs actions majeures :

  • Synchroniser la blockchain Bitcoin. C’est-à-dire récupérer la liste des transactions effectuées sur Bitcoin depuis le 3 Janvier 2009, réparties en bloc.
  • Partager cette blockchain aux nouveaux arrivants.
  • Mettre à jour la blockchain, c’est-à-dire ajouter les blocs à la chaîne, au rythme où ils sont minés, soit toutes les 10 minutes environ sur Bitcoin.

En ayant cette blockchain, c’est-à-dire l’histoire ; les nœuds serviront de « témoins » et attesteront qu’une adresse donnée possède bel et bien un certain nombre de bitcoins. Ce qui nous amène à l’autre rôle principal des node :

  • Recevoir des nouvelles transactions
  • Les valider, c’est-à-dire vérifier que les bitcoins dépensés par telle adresse lui appartiennent bien et que le montant envoyé est inférieur à celui possédé. Pour prouver cette possession, le détenteur de l’adresse signe la transaction avec la clef privée correspondante. Pour vérifier que le montant envoyé par cette adresse est valide, le nœud va regarder dans la chaîne, qu’il possède maintenant qu’il est synchronisé, si le nombre de bitcoins dépensés dans cette transaction n’est pas supérieur à la somme des bitcoins reçus lors des précédentes transactions (+ les éventuels frais de transaction). C’est un peu difficile à visualiser, mais c’est essentiel à la compréhension du fonctionnement de Bitcoin : il n’y a pas vraiment de champs dans la blockchain Bitcoin où il est marqué « telle adresse a x bitcoin ». Tout est calculé en fonction des transactions précédentes, c’est pour cette raison que vous verrez parfois certaines personnes dire ce genre de phrases toutes faites « dans Bitcoin, tout est transaction ». Voici un lien pour plus de clarté (des schémas) et de détails (UTXOs).
  • Si une transaction est validée, le nœud la copie dans ce que l’on appelle la « memory pool », souvent abrégé « mempool ». C’est un moyen de garder en mémoire les transactions valides mais pas encore confirmées (== pas encore mise dans un bloc). Il va ensuite la transmettre à tous les nœuds qu’il connaît, qui vont eux-mêmes valider la transaction et si elle est valide, la transmettre aux nœuds qu’ils connaissent. De cette manière, la transaction sera en quelques secondes dans la mempool de la plupart des nœuds du réseau. Donc la plupart des nœuds sauront que cette transaction a été effectuée et qu’elle est valide. Il ne reste plus qu’à la confirmer, c’est-à-dire la mettre dans un bloc, et c’est le rôle du mineur, que l’on va voir à présent.

Ressources/liens utiles :

B) Pourquoi des blocs ? Pourquoi une chaîne ? Pourquoi une preuve de travail ?

Introduction au problème : Comme on l’a vu dans la partie précédente, n’importe qui peut devenir un nœud du réseau, il suffit d’avoir une connexion à internet, de lancer bitcoin-core et de synchroniser la chaîne (donc avoir, à l’heure où j’écris ces lignes ~230GO d’espace libre). Personne ne va vérifier l’identité de la personne qui souhaite se connecter et participer. Il est donc (fort) probable que quelqu’un de malintentionné tienne un node et possède donc la chaîne. Puisque la chaîne et les blocs ne sont au final que des données brutes il est aisé de modifier les informations présentes : les transactions, les dates, etc.. On ne peut donc faire confiance à aucun node.

Mesdames et messieurs voici… La blockchain !

Ensuite, il est nécessaire d’avoir un ordre ; étant donné que les transactions sont chaînées, chaque dépense provient d’un revenu, ce qui se matérialise sur Bitcoin par le fait que chaque transaction dépend d’une précédente (sauf celles minées, au moment de la création de nouveaux bitcoins). Par conséquent si on modifie l’ordre dans lequel elles sont chaînées, on modifie la quantité, en bout de chaîne, de bitcoins détenus par une adresse. Or, pour avoir de l’ordre, il nous faut un temps commun..

Le problème : Il faut donc, sans faire confiance à personne, ni donner plus de pouvoir à certains (ou utiliser un tiers), pouvoir certifier la véracité de l’information échangée sur le réseau. Dit simplement il faut être sûr que nos bitcoins peuvent passer de partout dans le monde dans n’importe quel ordinateur sans pouvoir être altérés (même si, si l’on veut être rigoureux, cette simplification est fausse).

Ensuite, il  faut trouver un moyen de trouver un accord sur tout le réseau sur le temps. On ne peut pas se reposer sur un organisme central donnant l’heure, et ni faire confiance à un noeud pour donner le temps (toujours pour les mêmes raisons).

Pour résumer il faut trouver un moyen de transmettre un information numérique non duplicable, et de trouver un moyen d’émettre un temps commun accepté par tout le monde.

La solution proposée par Satoshi : Concernant l’immutabilité des transactions, Satoshi utilise ce qui est appelé un “timestamp server” (pour faire simple une blockchain sans mining), inventé en 1993 par 3 chercheurs (cf https://bitcoin.org/bitcoin.pdf#page=9, ref n°4). Ce “timestamps server” permet de stocker les transactions dans des blocs de données, ordonnés les uns à la suite des autres. Ordonnés les uns à la suite des autres signifie que le bloc n+1 sera publié, dans le temps, après le bloc n. Ca parait évident mais c’est très important. Ces blocs, publiés les uns à la suite des autres, contiendront chacun l’empreinte du bloc précédent. Concrètement, en hashant deux fois l’ensemble des données du bloc précédent avec la fonction sha256 (vous pouvez voir un exemple de hash d’un bloc ici : https://anders.com/blockchain/hash.html). Ainsi, si le dernier bloc publié est le bloc n, et que l’on change le contenu du bloc n-5 par exemple, cela modifierait son hash, qui est présent dans le bloc n-4, donc il faudrait changer le hash dans le bloc n-4, mais donc ça changerait le contenu du bloc n-4, donc son hash, qu’il faudrait changer dans le bloc suivant, le n-3, etc.. etc.. Avec d’autres mots, si l’on veut changer le passé (une transaction effectuée où l’on changerait le montant), il faudrait réécrire l’histoire depuis ce moment. C’est une opération très coûteuse, comme on le verra par la suite avec le mining. Quand bien même on réussirait, il faudrait faire accepter notre version de l’histoire (notre blockchain modifiée) à tous les autres nœuds du réseau. On se doute bien qu’ils risquent de ne pas trop être d’accord…

meme - no

La deuxième partie de la solution au problème : la proof of work. Version détaillée : sur Bitcoin les blocs sont publiés toutes les 10 minutes (Pourquoi 10 ?), il faut donc que les blocs soient publiés sur le réseau environ toutes les 10 minutes, sans s’appuyer sur quelqu’un (un node, un tiers) donnant la valeur en laquelle on devrait avoir confiance. Il faut de plus, que n’importe quel nœud du réseau soit capable d’émettre (de miner) un bloc, car si ce n’est pas le cas Bitcoin ne serait pas réellement décentralisé. Pour ce faire, Satoshi a utilisé la preuve de travail (https://bitcoin.org/bitcoin.pdf#page=9 ref n°6 cette fois). Le principe est de hasher une partie du bloc (son header, mais pour comprendre ça reste un détail) et de trouver un nombre inférieur à celui donné par le réseau. Alors, pour visualiser je vous invite à retourner faire des tests de hash sur https://anders.com/blockchain/hash.html . Le hash étant un nombre hexadécimal, un nombre “petit” se traduit par un ou plusieurs zéro au début du nombre. Ces zéros sont facultatif mais, étant donné que le hash est toujours de la même taille (comme expliqué au début de l’article), on les rajoute à l’avant pour arriver à 64 caractères (ou chiffres). C’est comme si j’écris 00134 au lieu de simplement 134. A présent essayez de rentrer sur Anders des datas pour n’obtenir ne serait-ce que un seul “0” au début du hash, on se rend compte que c’est très difficile, donc il nous faut un certain temps avant d’y arriver….

meme - now I get it

C’est la base du truc. Plutôt que de se baser sur une donnée en laquelle on doit avoir confiance, on va exécuter une tâche qui nous prendra un certain temps => on ne peut qu’avoir confiance en ce temps puisqu’on l’expérience nous-même. Sur Bitcoin, c’est un peu comme sur Anders, en plus structuré : on ne va pas taper du texte random en espérant arriver à un nombre de zéros en début de chaîne, on va modifier un champ spécial appelé “nonce”. Sur Bitcoin le nombre, qui s’appelle la “target”, auquel notre hash doit être inférieur, est beaucoup plus petit (donc beaucoup moins de chance de trouver un nombre avec encore plus de zéros au début) et la puissance de calcul beaucoup plus grosse. Genre vraiment beaucoup plus grosse. Avec Anders vous faisiez difficilement 2hash/s, sur l’ensemble du réseau Bitcoin son calculés plus de 35 500 000 TH/s = 1 000 000 000 000 Hash/s. Pour comparaison une année-lumière vaut environ 9 500 téramètres (Tm). On calcule sur Bitcoin (3 fois) plus de Hash par seconde, qu’il n’y a de mètres parcourus en une année en allant à la vitesse de la lumière (Ce genre de stats).

Et si de nouveaux mineurs arrivent ? Cela créera plus de puissance de calcul et donc plus de Hash/s ? Et donc l’émission des blocs se fera plus rapidement ?

Habile Bill

Pour éviter ça, la target, le nombre auquel notre hash doit être inférieur, s’ajuste en fonction de la puissance de calcul totale du réseau. Concrètement tous les 2016 blocs, on calcule combien de temps ça a pris pour calculer tous ces blocs : si le nombre de minutes prises pour miner tous ces blocs est inférieur à 2016 * 10 = 20160 minutes, on baisse la target, donc on baisse les chances de trouver un hash inférieur, donc on augmente le temps de calcul nécessaire au mining d’un bloc, donc on augmente le temps moyen d’émission d’un bloc. Si le nombre de minutes  est inférieur à 20160 on augmente la target, donc on augmente les chances de trouver un hash inférieur, donc on baisse le temps de calcul nécessaire au mining d’un bloc, donc on baisse le temps moyen d’émission des blocs.

Pour résumer, à l’aide d’une blockchain (un registre distribué à tout le monde) et l’implémentation de la preuve de travail, on peut créer une information numérique non duplicable, utiliser un temps sans rien demander à personne, et laisser n’importe qui faire ce qu’il veut sans lui faire confiance sans que ça ait un impacte sur le réseau. Vous pouvez voir ça en action (et en anglais) ici .

(Res)sources :

 

C) Que fait donc concrètement un mineur lorsqu’il “mine” un bloc ?

Pour cette partie je vais reprendre le magnifique schéma que j’ai réalisé dans la slide pour la conférence.

Le mineur est aussi un noeud du réseau, il  ne faut pas penser à lui comme quelqu’un d’extérieur, agissant sur le système. Non. Il fait partie du réseau et contribue à son bon fonctionnement. Donc, comme tous les noeuds du réseau ils reçoivent des transactions qu’ils valident, copient dans leur memory pool, puis repartagent. Je vous avais bien dit qu’on reviendrait à cette memory pool !

Voici ce qu’un mineur va faire :
“Créer” un bloc appelé candidate bloc (concrètement il n’y a pas de “bloc” à créer, ce sont juste des données mise les unes à la suite des autres, mais cette abstraction permet de mieux comprendre), ensuite remplir ce bloc avec des transactions de sa/son memory pool en veillant à ne pas dépasser 1MO au total, ça revient à environ 3000 transactions. La toute première transaction est spéciale, et ne provient pas de la mempool : c’est ce qu’on appelle la coinbase transaction, elle est créée par le mineur qui se rémunère pour son travail, elle ne provient pas d’une transaction précédente : c’est comme ça que les bitcoins sont, à la base, créés. Quand on dit “si un mineur trouve un bloc, il gagne X bitcoins”, en fait c’est lui qui crée aussi cette transaction, en respectant évidemment le maximum autorisé (s’il essaye de se donner plus, son bloc sera rejeté par le réseau et il aura fait tout ça pour rien). Ce maximum était au début de 50 bitcoins, et est divisé par 2 tous les 210 000 blocs (environ tous les 4 ans) : ce procédé s’appelle le halving. Aujourd’hui le maximum est de 12.5BTC/bloc, vous pouvez voir le temps restant avant le prochain halving ici .

Le mineur va ensuite créer le header, contenant des métadonnées et d’autres informations comme le hash du bloc précédent (afin de créer un chaîne) pour que chaque bloc dépende du précédent (cf partie B).

Donc une fois qu’il a aussi son header, le mineur a son bloc. Pour vérifier s’il est valide il va hasher le header, en appliquant 2 fois la fonction sha256. Si le hash qu’il obtient est inférieur à la target (s’il commence avec assez de 0), il a trouvé un bloc valide. Donc il l’envoie à tout le réseau (il l’envoie aux noeuds qu’il connaît, qui le valident puis l’envoient eux-mêmes à ceux qu’ils connaissent etc..), et tous les noeuds appliquent ce bloc à la chaîne. Il peut à présent se mettre à essayer d’en trouver un nouveau.

Et si le hash n’est pas inférieur à la target ? Comme vous avez pu le constater dans la partie B en utilisant Anders, une petite modification en entrée dans la fonction de hash, provoque d’énormes modifications à la sortie, c’est à dire dans le hash : on appelle ce genre de fonction des fonctions chaotiques. Si son bloc n’est pas valide (si après avoir appliqué 2 sha256 sur le header du bloc, le hash n’est pas inférieur à la target), il va changer une partie du header, que l’on appelle le “nonce”. En  général on crée le header avec un nonce à 0, on hash (2*sha256), si le hash ne convient pas on incrémente le nonce (nonce = nonce+1), on hash, si le hash ne convient pas on incrémente le nonce, on hash, si -bref vous avez compris. Le nonce est un nombre codé sur 4 octets, sa valeur maximale est 2 147 483 647, on a donc 2 147 283 647 possibilités de hash différents. Malgré tout, il est possible que aucun des ces hash ne soit inférieur à la target et donc que le bloc ne puisse jamais être valide : il faut donc changer son contenu.

(Res)sources :

 

Les autres parties suivront sûrement dans des prochains articles, en attendant voici quelques liens.

Pour aller encore plus loin :

Related posts

2 Comments

Leave a Reply