
Discussion sur les principes et les détails techniques du protocole d'inscription Ordinal
TechFlow SélectionTechFlow Sélection

Discussion sur les principes et les détails techniques du protocole d'inscription Ordinal
Comment les satoshis dans un UTXO sont-ils précisément suivis, où exactement dans le script est inscrit le contenu gravé, et pourquoi les transferts BRC20 nécessitent-ils deux opérations ?
Auteur : @hicaptainz
Ces deux dernières semaines, en étudiant l'écosystème BTC et divers projets d'inscription, j'ai remarqué qu'il existe peu d'articles capables d'expliquer clairement les principes et détails techniques : par exemple, comment une transaction est-elle initiée lors du minting d'une inscription, comment les satoshis (sats) dans les UTXO sont-ils réellement suivis, où exactement le contenu gravé est-il stocké dans le script, et pourquoi un transfert BRC20 nécessite-t-il deux opérations ? Je me suis rendu compte que sans comprendre ces détails techniques, il est difficile de distinguer clairement les différences entre les protocoles comme BRC20, BRC420, Atomicals, Stamps ou encore les Runes. Cet article plonge donc dans les bases de la blockchain Bitcoin afin de répondre à ces questions.
Structure des blocs Bitcoin
La blockchain est essentiellement une technologie de comptabilité multi-utilisateur. En termes informatiques, c’est une base de données distribuée. Les enregistrements (ou transactions) sur une période donnée forment un bloc, puis la chaîne s’étend chronologiquement.

Nous utilisons un tableau Excel pour illustrer le fonctionnement de la blockchain. Un fichier Excel représente une blockchain entière, chaque feuille correspondant à un bloc, numérotés séquentiellement de 560331 à 560336. Le bloc 560336 contient les transactions les plus récentes. La partie principale d’un bloc suit la méthode de comptabilité en partie double bien connue : d’un côté figurent les adresses « débitées » (inputs from), de l’autre celles « créditées » (outputs to). La valeur indique la quantité de BTC associée à chaque adresse. La somme des inputs excède généralement celle des outputs ; la différence constitue les frais de transaction perçus par les mineurs (les « comptables »). L’en-tête du bloc contient le numéro du bloc précédent, son hachage, l’horodatage (timestamp) et un nombre aléatoire (nonce). Dans ce système décentralisé, qui obtient le droit de valider le prochain bloc ? C’est déterminé par ce nonce et le hachage résultant. Les mineurs, disposant de puissance de calcul, effectuent des calculs de hachage sur le bloc actuel. Celui qui trouve le premier un hachage satisfaisant les critères requis obtient le droit de minage, ainsi que la récompense et les frais. Enfin, la zone de script permet des applications étendues, comme le champ « note » via l’opcode op_return. Il faut noter que, dans un bloc réel, cette zone n’existe pas physiquement séparément mais est intégrée aux informations d’entrée et de sortie. Par exemple, le script attaché à un input est un script de déblocage (ScriptSig), nécessitant une signature privée pour autoriser la sortie ; tandis que celui attaché à un output est un script de verrouillage (ScriptPubKey), définissant les conditions de dépense (généralement « seulement la personne possédant la clé privée peut dépenser »).


Les deux images ci-dessus montrent les structures brutes des données d’input et d’output. Au niveau exécution, les scripts apparaissent comme des paramètres annexes aux transactions. Le ScriptSig, nécessitant une signature privée, est aussi appelé « données de témoignage » (witness data).
SegWit et Taproot
Bien que le réseau Bitcoin fonctionne depuis plus de 10 ans sans incident majeur, les coûts de transaction ont parfois atteint des niveaux prohibitifs. Les développeurs discutent donc régulièrement des moyens d’évoluer pour supporter un volume croissant de transactions.
En 2017, ce débat a culminé, divisant la communauté des développeurs : d’un côté ceux favorables à une mise à jour en fourchette molle (soft fork) appelée SegWit, de l’autre ceux préconisant un simple agrandissement des blocs (« big block »).
Comme mentionné précédemment, le script de déblocage génère des « données de témoignage » nécessitant une signature privée. Ne pourrait-on pas extraire ces données du bloc pour augmenter artificiellement le nombre de transactions par bloc ? C’est précisément ce que fait Segregated Witness (SegWit), activé en août 2017. Son principe consiste à diviser les données de transaction en deux parties : les données de base (Transaction Data) et les signatures (Witness Data). Ces dernières sont stockées dans une structure de données séparée, nommée « witness », transmise indépendamment des transactions initiales.

Techniquement, SegWit signifie que les transactions n’ont plus besoin d’inclure les données de témoignage (qui ne consomment donc plus l’espace initial de 1 Mo réservé au bloc). À la place, un espace supplémentaire est ajouté à la fin du bloc pour accueillir ces données. Ce nouvel espace supporte tout type de transfert de données avec un poids de bloc (block weight) avantageux, permettant d’intégrer beaucoup plus de données tout en restant dans les limites de taille sans nécessiter de hard fork. Ainsi, la taille effective des transactions augmente, et les frais liés aux signatures diminuent. Avant SegWit, la capacité était limitée à 1 Mo. Après SegWit, bien que la limite des données de transaction reste à 1 Mo, l’espace witness peut atteindre 4 Mo.
Taproot, implémenté en novembre 2021, repose sur trois propositions d’amélioration du Bitcoin (BIP) : Taproot, Tapscript et un nouveau schéma de signature numérique appelé « Schnorr Signatures ». Taproot apporte plusieurs avantages aux utilisateurs : meilleure confidentialité, frais réduits, et possibilité d’exécuter des transactions plus complexes grâce à de nouveaux opcodes, élargissant ainsi les cas d’usage.
Ces mises à jour ont été cruciales pour les NFT Ordinals, qui stockent les données NFT dans le script de dépense du chemin Taproot (dans l’espace witness). Cette amélioration facilite le stockage structuré de données arbitraires, posant les bases du standard « ord ». En assouplissant les contraintes de données, une transaction pourrait désormais remplir un bloc entier — jusqu’à 4 Mo — ouvrant la voie à tous types de médias stockés en chaîne.
On pourrait se demander : si l’on insère simplement une chaîne de caractères dans un script, n’y a-t-il aucune restriction ? Que se passe-t-il si le script est exécuté ? Si l’on y met du contenu aléatoire, cela pourrait-il provoquer une erreur bloquant la validation du bloc ? Voici qu’intervient l’instruction OP_FALSE. OP_FALSE (aussi représenté par « 0 » dans les scripts Bitcoin) garantit que le chemin d’exécution n’entre jamais dans une branche OP_IF, restant inactif. Elle agit comme un espace réservé ou une opération nulle (No Operation), similaire à un « commentaire » dans un langage de programmation, assurant que le code suivant n’est pas exécuté.

Modèle de transfert UTXO
Tout ce qui précède concerne les fondamentaux techniques du BTC. Examinons maintenant le modèle financier basé sur les UTXO.
UTXO signifie « Unspent Transaction Output », soit en français « sortie de transaction non dépensée ». On peut le comprendre comme le solde restant après un transfert. Pourquoi Bitcoin utilise-t-il ce concept ? Cela remonte à la différence entre deux modèles comptables : le modèle basé sur les soldes de compte et celui basé sur les transactions.
Dans les systèmes centralisés, nous sommes habitués au modèle de solde. Quand l’utilisateur A envoie 100 unités à B, la banque vérifie si A dispose bien de 100 unités, les déduit de son compte, et les ajoute à celui de B. La transaction est terminée.
Mais Bitcoin n’a pas de notion de solde. Le grand livre distribué ne conserve que la liste des transactions, sans enregistrer directement le solde d’un compte (ce qui nécessiterait un serveur centralisé). Supposons que A ait un solde de 1000 unités et veuille envoyer 100 unités à B. Cette opération serait enregistrée comme :
Transaction 1 : A envoie 100 unités à B
Transaction 2 : A s’envoie 900 unités à lui-même (UTXO)

Cette deuxième transaction, bien qu’apparente, joue le rôle de solde : elle indique qu’après avoir envoyé 100 unités, A en possède encore 900.
Alors pourquoi créer cet UTXO ? Car sur la blockchain BTC, on ne peut enregistrer que des transactions, pas des soldes. Sans UTXO, calculer un solde impliquerait d’additionner toutes les entrées et sorties d’un compte — une opération très coûteuse en temps et en ressources. L’UTXO évite astucieusement ce problème.
Un UTXO a une particularité : comme une pièce de monnaie, il ne peut être divisé. Comment alors rassembler suffisamment d’inputs ou rendre la monnaie ? Prenons l’analogie de la monnaie physique (chaque fois que vous voyez « UTXO », pensez « pièce »).
Supposons que Ming envoie 1 BTC à Gang. Ming doit rassembler suffisamment d’inputs. S’il trouve un UTXO de 0,9 BTC, ce n’est pas assez. Heureusement, les transactions peuvent avoir plusieurs inputs. Il ajoute un autre UTXO de 0,2 BTC. La transaction aura donc deux inputs. En sortie, une va vers l’adresse de Gang (1 BTC), l’autre vers l’adresse de Ming (0,1 BTC), servant de monnaie rendue (l’exemple ignore les frais).
Autrement dit, Ming a deux pièces (0,9 et 0,2), veut payer 1 BTC, donc les donne ensemble à Gang, qui lui rend 0,1 BTC. Ce modèle comptable repose donc sur la « monnaie rendue » pour éviter le calcul explicite du solde.
Système de numérotation du protocole Ordinal
Le protocole Ordinal est à l’origine de l’essor actuel de l’écosystème BTC. Il décompose le BTC homogène en son unité minimale, le satoshi (sat), puis attribue un numéro à chaque sat. Comment cela fonctionne-t-il ?
On sait que l’offre totale de BTC est de 21 millions, chaque BTC étant divisible en 100 millions de sats. L’unité minimale est donc le sat. Tous deux sont des jetons fongibles (FT). Essayons maintenant d’attribuer un numéro ordinal à chaque sat.
Plus haut, nous avons vu que les transactions incluent les adresses et montants des inputs et outputs. Chaque bloc contient deux types de transactions : la récompense de minage et les frais de transaction. Les frais ont des inputs et outputs, mais la récompense, créée ex nihilo, n’a pas d’input. Ce champ « input from » est vide : c’est la « transaction coinbase ». Les 21 millions de BTC proviennent tous de ces transactions coinbase, toujours placées en tête de liste dans chaque bloc.
Le protocole Ordinal définit deux règles :
-
Numérotation : chaque sat est numéroté selon l’ordre de son extraction minière.
-
Transfert : selon la règle FIFO (premier entré, premier sorti), les sats passent des inputs aux outputs.
La première règle est simple : les numéros sont générés uniquement par les transactions coinbase. Par exemple, si le premier bloc rapporte 50 BTC, ses sats reçoivent les numéros [0; 1; 2; ... ; 4 999 999 999]. Si le second bloc rapporte aussi 50 BTC, ses sats auront les numéros [5 000 000 000; ... ; 9 999 999 999].

La difficulté vient du fait qu’un UTXO contient plusieurs sats, tous identiques en apparence. Comment les ordonner ? C’est la deuxième règle qui le permet. Prenons un exemple simplifié :
Imaginons que l’unité minimale soit 1, qu’il y ait 10 blocs, chacun récompensant 10 BTC (soit 100 BTC au total). On peut numéroter ces 100 BTC de 0 à 99. Sans aucune dépense, on sait que les 10 BTC du premier bloc portent les numéros 0-9, ceux du second 10-19, ..., jusqu’au dixième (90-99). Sans output, on ne peut attribuer qu’une plage de numéros à chaque groupe de 10 BTC.
Supposons maintenant que le second bloc contienne deux outputs : un de 3 BTC et un autre de 7 BTC (monnaie rendue). Dans la liste des transactions, supposons que les 7 BTC (numéros 10-16) soient listés en premier, et les 3 BTC (17-19) en second. Ainsi, l’ordre des outputs détermine la séquence des sats dans les UTXO.
Attention : il s’agit de chaque sat, pas de l’UTXO ! L’UTXO étant indivisible, les sats vivent à l’intérieur, formant une plage continue. Seule la dépense d’un UTXO permet de subdiviser cette plage dans les nouveaux outputs.
Ordinal supporte plusieurs formats pour exprimer ce numéro : entiers, décimaux, degrés, pourcentages, ou noms alphabétiques.

Une fois les sats numérotés, on peut passer à l’inscription. Comme vu plus haut, l’espace witness (jusqu’à 4 Mo) permet de téléverser tout type de fichier (texte, image, vidéo). Une fois uploadé, le fichier est converti en hexadécimal et stocké dans le script Taproot. Ainsi, un UTXO correspond à un script Taproot, qui contient plusieurs sats (une plage continue). Pour éviter les attaques par spam, un UTXO ne peut contenir moins de 546 sats. Pour simplifier l’enregistrement, Ordinal stipule que « le numéro du premier sat de la plage représente la relation d’attachement » (selon le whitepaper, « le numéro du premier sat du premier output »). Ainsi, un UTXO contenant les sats 17-19 sera symbolisé par le numéro 17, lié au contenu gravé.
Minting et transfert des actifs Ordinal
Un NFT Ordinal consiste clairement à téléverser un fichier dans le script witness et à le lier à une plage de sats, permettant ainsi d’émettre des NFT sur la chaîne BTC. Mais où est stocké ce contenu ? Le script witness contient à la fois le script de déblocage (input) et le script de verrouillage (output). La réponse correcte est : les deux. C’est ici qu’intervient le mécanisme commit-reveal.
Le mécanisme commit-reveal est un protocole garantissant l’équité et la transparence dans le traitement d’informations sensibles (votes, enchères). Il comporte deux phases : engagement (commit) et révélation (reveal).
1. Phase d’engagement (commit) : l’utilisateur soumet une information chiffrée, généralement sous forme de hachage (empreinte cryptographique). Ce hachage est envoyé sur la blockchain. Grâce aux propriétés des fonctions de hachage, l’information originale ne peut être retrouvée à partir du hachage, assurant la confidentialité.
2. Phase de révélation (reveal) : à un moment donné, l’utilisateur révèle l’information originale, prouvant qu’elle correspond au hachage soumis. Le réseau vérifie que le hachage de l’information révélée correspond bien à celui engagé. Si oui, l’information est validée.
Comme vu précédemment, le contenu gravé doit être lié à une plage de sats dans un UTXO (un output), donc attaché au script de verrouillage. Mais les nœuds complets doivent stocker localement et transmettre l’ensemble des UTXO du réseau. Imaginez 10 000 fichiers vidéo de 4 Mo directement dans 10 000 scripts de verrouillage : les nœuds auraient besoin d’une capacité de stockage et de bande passante énorme — la chaîne s’effondrerait. La seule solution est donc de placer le contenu dans le script de déblocage (input), puis de le « pointer » vers un output.
Ainsi, le minting d’un actif Ordinal nécessite deux étapes (les portefeuilles les fusionnent pour une meilleure expérience utilisateur, construisant simultanément les transactions commit et reveal, donnant l’impression d’une seule étape et économisant les frais).
Lors du minting, l’utilisateur téléverse d’abord le hachage du fichier dans le script de verrouillage d’un UTXO (transfert de A à B). Étant un hachage, cela occupe peu d’espace dans la base UTXO des nœuds complets. Ensuite, il crée une nouvelle transaction (de B à A), appelée transaction de révélation (reveal). L’input utilise l’UTXO contenant le hachage, et son script de déblocage doit inclure le fichier original gravé. Selon le whitepaper : « D’abord, dans le commit, créer une sortie Taproot engageant un script contenant le contenu de l’inscription. Ensuite, dans la transaction reveal, utiliser la sortie produite par le commit pour afficher le contenu de l’inscription en chaîne. »
Pour le transfert, les NFT Ordinal et les BRC20 diffèrent légèrement. Un NFT Ordinal est transféré intégralement : on envoie simplement l’UTXO lié au destinataire, comme un transfert BTC classique. Mais BRC20 impliquant des montants personnalisés, nécessite deux étapes : premièrement, une transaction d’inscription « TRANSFERT » (Inscribe "TRANSFER"), puis une transaction de transfert « TRANSFERT » (Transfer "TRANSFER"). La première équivaut au minting d’un NFT Ordinal (avec paire commit-reveal implicite), la seconde à un transfert NFT classique. Certains portefeuilles construisent même ces trois transactions (père, fils, petit-fils) simultanément, économisant temps et frais.

En résumé, la transaction commit lie le contenu gravé (via son hachage) à une plage de sats numérotés (UTXO), tandis que la transaction reveal expose le contenu original. Cette paire de transactions parent-enfant accomplit conjointement le minting du NFT.
P2TR et un exemple
La discussion technique sur le minting n’est pas terminée. On peut se demander : comment la transaction reveal valide-t-elle l’information du commit ? Pourquoi faut-il transférer entre deux adresses A et B du même utilisateur ? Pourtant, lors du gravage, on ne semble pas devoir préparer deux portefeuilles. Ici intervient une des grandes améliorations de Taproot : P2TR.
P2TR (Pay-to-Taproot) est un nouveau type de transaction introduit par Taproot. Il permet de dépenser des bitcoins via une seule clé publique ou des scripts complexes (portefeuilles multisignatures, contrats intelligents), offrant plus de confidentialité et de flexibilité. Cela est rendu possible grâce à MAST (Merkleized Abstract Syntax Trees) et aux signatures Schnorr, permettant d’encoder efficacement plusieurs conditions de dépense dans une même transaction.
-
Définir les conditions de dépense
L’utilisateur définit d’abord une condition de dépense (clé unique ou script complexe) spécifiant les exigences (ex : multisig ou contrat intelligent).
-
Générer la sortie Taproot
L’utilisateur crée ensuite une sortie Taproot contenant une clé publique (représentant la condition). Cette clé est dérivée de la combinaison de sa propre clé publique et du hachage du script, via un processus appelé « tweaking ». Cela fait apparaître la sortie comme une clé standard, la rendant indiscernable des autres transactions.
-
Dépenser les bitcoins
Quand l’utilisateur veut dépenser, il peut utiliser sa clé unique (si la condition est remplie) ou révéler le script d’origine et fournir les signatures ou données nécessaires. Cela se fait via Tapscript, permettant une exécution plus efficace et flexible.
-
Vérification de la transaction
Les mineurs et nœuds vérifient ensuite la signature Schnorr et les données contre les conditions de dépense. Si elles correspondent, la transaction est valide.
-
Confidentialité et flexibilité accrues
Puisque les conditions de dépense ne sont révélées qu’au moment de la dépense, P2TR assure un haut niveau de confidentialité. De plus, MAST et Schnorr permettent d’encoder efficacement plusieurs conditions, rendant les transactions plus complexes sans augmenter leur taille.
Voilà comment le mécanisme commit-reveal s’applique à P2TR. Illustrons avec un exemple concret.
Utilisons l’explorateur blockchain https://www.blockchain.com/ pour analyser le minting d’un NFT image Ordinal, incluant les deux phases commit et reveal.
D’abord, la transaction commit a pour Hash ID : (2ddf90ddf7c929c8038888fc2b7591fb999c3ba3c3c7b49d54d01f8db4af585c). On observe que la sortie ne contient pas les données d’inscription (en réalité, elle contient le hachage hexadécimal du fichier image), et aucun détail d’inscription n’apparaît sur la page. L’adresse (bc1p4mtc.....) est une adresse temporaire générée par le processus de « tweaking » (représentant la condition de déblocage du script), partageant une clé privée avec l’adresse Taproot principale (bc1pg2mp...). Le second UTXO correspond à la monnaie rendue. Ainsi, le contenu est lié au premier UTXO et à ses sats.

Ensuite, examinons la transaction reveal, dont le Hash ID est (e7454db518ca3910d2f17f41c7b215d6cba00f29bd186ae77d4fcd7f0ba7c0e1). On y voit les informations d’inscription Ordinals. L’input correspond à l’adresse temporaire générée par la transaction précédente (bc1p4mtc.....), et son script de déblocage contient le fichier image en hexadécimal. La sortie de 0,00000546 BTC (546 sats) envoie ce NFT à l’adresse Taproot principale (bc1pg2mp...). Selon la règle FIFO et « lié au premier sat du premier output », bien que la quantité de sats change, le numéro du sat lié reste inchangé. On peut donc trouver cette inscription au sat 1893640468329373.
(https://ordinals.com/sat/1893640468329373)

Ces deux transactions (parent-enfant) sont soumises simultanément par le portefeuille au mempool, ne coûtant ainsi qu’une seule transaction en frais, et ayant de fortes chances d’être incluses dans le même bloc (comme ici, dans le bloc 790468). Les mineurs et nœuds vérifient ensuite que le hachage hexadécimal de l’image dans le script de déblocage de la transaction reveal correspond bien à celui dans le script de verrouillage de la sortie du commit. Si les hachages concordent, la transaction est valide, les deux transactions sont gravées dans la blockchain BTC, et l’image NFT est conservée et affichée. Sinon, les deux transactions sont annulées, et l’inscription échoue.
Protocole BRC20 et indexeurs
Avec le protocole Ordinal, graver un texte donne un NFT texte (équivalent à Loot sur Ethereum), une image donne un NFT image (comme les PFP Ethereum), une musique donne un NFT audio. Et si l’on gravait un code, spécifiquement un code « d’émission de jeton fongible » ?
BRC20 exploite justement le protocole Ordinal pour déployer, miner et transférer des jetons via des inscriptions au format JSON. Ce JSON contient des fragments de code décrivant les propriétés du jeton : offre totale, taille maximale de mint, code unique. Comme expliqué précédemment, le jeton BRC20 est un jeton semi-fongible (SFT) : il peut être traité comme un NFT dans certains cas, comme un FT dans d’autres. Comment gérer cette dualité ? Grâce à l’indexeur.
Un indexeur est un comptable qui classe et enregistre les informations reçues dans une base de données. Dans le protocole Ordinal, l’indexeur suit les inputs et outputs pour tracer les sats numérotés entre adresses. Dans BRC20, il ajoute une fonction : enregistrer les soldes de jetons entre adresses.
On peut donc voir les formes d’existence des jetons à travers le prisme du comptable : les jetons BRC20 existent dans une base triple. Niveau 1 (Layer1) : le comptable est le mineur BTC, la base est une « base en chaîne », produisant des actifs FT. Niveau 2 (layer2) : le comptable est l’indexeur Ordinal, base relationnelle, produisant des sats numérotés (NFT). Niveau 3 (layer3) : le comptable est l’indexeur BRC20, base relationnelle, produisant des actifs BRC20 (FT). Quand on traite BRC20 par « unités », on adopte le point de vue de l’indexeur Ordinal (qui les enregistre) : ce sont des NFT. Quand on les traite par « morceaux » (notamment après dépôt sur exchange centralisé), on adopte le point de vue de l’indexeur BRC20 (ou du serveur de l’exchange) : ce sont des FT. On en conclut que l’existence du jeton semi-fongible (SFT) découle de la présence de comptables hiérarchisés.
La blockchain n’est-elle pas une base de données distribuée ? C’est pourquoi le groupe des mineurs maintient collectivement cette « base en chaîne » (seule capable de garantir une véritable décentralisation). Pourtant, après tout cela, on revient aux bases « relationnelles » centralisées. Voilà pourquoi, récemment, les créateurs du protocole Ordinal, de BRC20 et le portefeuille Unisat se sont disputés âprement sur la mise à jour de l’indexeur — désaccord entre comptables.
Mais après des années de développement, l’industrie a accumulé de l’expérience en « décentralisation ». Peut-on remplacer la base relationnelle de l’indexeur par une base en chaîne ? Peut-on utiliser des preuves de fraude (fraud proofs) ou des ZKP pour assurer sécurité et décentralisation ? La demande de DA (Data Availability) dans l’écosystème Bitcoin pourrait-elle déborder vers d’autres solutions, stimulant la prospérité et l’intégration des écosystèmes multi-chaînes ? Je pressens bien des possibilités.
Bienvenue dans la communauté officielle TechFlow
Groupe Telegram :https://t.me/TechFlowDaily
Compte Twitter officiel :https://x.com/TechFlowPost
Compte Twitter anglais :https://x.com/BlockFlow_News














