
Analyse des technologies de mise à l'échelle Bitcoin en couche 2 : preuves de validité et preuves de fraude
TechFlow SélectionTechFlow Sélection

Analyse des technologies de mise à l'échelle Bitcoin en couche 2 : preuves de validité et preuves de fraude
Il existe de nombreuses limitations dans le paradigme Bitcoin, mais il est possible de contourner ces restrictions grâce à diverses méthodes ingénieuses ou technologies.
1 Introduction
Pour un algorithme f donné, deux parties Alice et Bob qui ne se font pas confiance peuvent établir la confiance selon les méthodes suivantes :
-
Alice entre l'entrée x, exécute l'algorithme f et obtient le résultat y. Bob, avec la même entrée x, exécute également f et obtient y'. Si y = y', alors Bob accepte l'entrée x et le résultat y fournis par Alice. Il s'agit d'un mécanisme particulier de preuve de validité, souvent utilisé dans la consensus blockchain. Ici, Alice est un nœud proposant un bloc, et Bob un nœud participant au consensus.
-
Alice entre x, exécute le programme zk.prove sur l'algorithme f, et obtient le résultat y ainsi qu'une preuve (proof). Bob utilise ensuite f, y et proof pour exécuter le programme zk.verify. Si le résultat est vrai, Bob accepte le résultat y d'Alice ; sinon, il le rejette. C'est une preuve de validité. Bob peut être un contrat sur chaîne.
-
Alice entre x, exécute f et obtient y. Bob fait de même avec x, obtenant y'. Si y = y', rien n'est fait ; si y ≠ y', Bob lance un défi à Alice, dont le programme contesté est f. L'interaction entre Alice et Bob peut se faire en une ou plusieurs étapes, et l'arbitrage suit un protocole de défi-réponse. Il s'agit d'une preuve de fraude. Bob est ici un challenger, surveillant hors chaîne et lançant des défis sur chaîne.
-
Alice entre x, exécute zk.prove sur f, obtenant y et proof. Bob exécute zk.verify avec f, y et proof. Si le résultat est vrai, rien n'est fait ; sinon, Bob lance un défi à Alice, contestant cette fois le programme zk.verify. Le nombre d'interactions entre Alice et Bob peut être une ou plusieurs. L'arbitrage suit un protocole de défi-réponse. Il s'agit aussi d'une preuve de fraude. Bob est le challenger, surveillant hors chaîne et agissant sur chaîne.
Pour les cas 2, 3 et 4 ci-dessus, en posant que x représente les transactions et l’état initial de Layer2, f le programme de consensus de Layer2, et y l’état final après transaction, on obtient des solutions de mise à l’échelle blockchain pour Layer2. Plus précisément :
-
Preuve de validité (Validity Proof) : basée sur une hypothèse pessimiste, elle exige qu’un état soit prouvé valide avant d’être accepté, et prend effet immédiatement. Elle nécessite de fournir une preuve que la transition d’état L2 est correcte, reflétant une vision pessimiste du monde — un état n’est accepté que s’il est prouvé correct.
-
Preuve de fraude (Fraud Proof) : basée sur une hypothèse optimiste, elle suppose par défaut la validité sauf preuve du contraire, avec une période de challenge durant laquelle les états sont contestables. Elle prend effet après expiration de cette fenêtre. Elle nécessite de fournir une preuve que la transition d’état L2 est incorrecte, reflétant une vision optimiste du monde — un état est supposé correct sauf réfutation.
Tableau 1 : Méthodes d'établissement de la confiance
Remarques complémentaires :
-
La distinction clé entre preuve de fraude et preuve de validité ne réside pas dans l'utilisation ou non de systèmes de preuve ZK tels que SNARK/STARK. Ces derniers concernent la méthode de preuve utilisée, tandis que "fraude" ou "validité" concerne le contenu de la preuve. C’est pourquoi le scénario 1 du tableau 1 est considéré comme une preuve de validité.
-
Les preuves de validité offrent une meilleure rapidité, mais leur vérification sur chaîne est plus complexe. Les preuves de fraude ont une vérification sur chaîne moins coûteuse, mais une latence plus élevée.
-
Pour les cas 2 et 4 du tableau 1, grâce aux techniques de récursion et de composition ZK, on peut compresser les calculs de plusieurs instances de f, réduisant fortement le coût de vérification chaîne des calculs hors chaîne.
Actuellement, grâce aux contrats intelligents Turing-complets de Solidity, les technologies de preuve de validité et de preuve de fraude sont largement utilisées pour la mise à l’échelle Ethereum Layer2. Toutefois, dans le paradigme Bitcoin, limité par le faible nombre d’opcodes disponibles, la taille maximale de pile à 1000 éléments, etc., ces technologies restent en phase exploratoire. Cet article passe en revue les contraintes du paradigme Bitcoin et les voies de contournement, étudie les preuves de validité et de fraude, et présente la technique unique de découpage de script propre au paradigme Bitcoin.
2 Contraintes et contournements dans le paradigme Bitcoin
Le paradigme Bitcoin comporte de nombreuses limitations, mais diverses méthodes ingénieuses permettent de les contourner : les engagements de bits (bit commitment) pour pallier l’absence d’état des UTXO, Taproot pour étendre l’espace de script, les sorties connecteurs (connector output) pour enrichir les modes de dépense des UTXO, et les covenants pour dépasser les contraintes des pré-signatures.
2.1 Modèle UTXO et limites du script
Bitcoin utilise le modèle UTXO, chaque UTXO étant verrouillé par un script de verrouillage définissant les conditions de dépense. Le script Bitcoin présente les limitations suivantes :
-
Le script Bitcoin est sans état ;
-
Pour les sorties P2TR, une transaction peut contenir jusqu’à environ 4 millions d’opcodes (remplissant tout un bloc), contre seulement 10 000 pour les autres types ;
-
Les modes de dépense d’un seul UTXO sont limités, manquant d’exploration des combinaisons ;
-
Fonctionnalités de covenants peu flexibles ;
-
La pile est limitée à 1000 éléments (altstack + stack), chaque élément faisant au maximum 520 octets ;
-
Les opérations arithmétiques (addition, soustraction) sont limitées à des éléments de 4 octets. Impossible de manipuler des éléments plus longs (20 octets ou plus), nécessaires aux opérations cryptographiques ;
-
Des opcodes comme OP_MUL et OP_CAT sont désactivés. Leur simulation via d'autres opcodes est extrêmement coûteuse — par exemple, simuler un tour de hachage BLAKE3 occupe environ 75 Ko de script.
2.2 Engagement de bit : dépasser l’absence d’état des UTXO
Actuellement, les scripts Bitcoin sont totalement sans état : l’environnement d’exécution est réinitialisé après chaque script. Cela empêche nativement de lier deux scripts avec une même valeur x. Une solution consiste à signer cette valeur. En signant une valeur, on rend le script « étatique ». En vérifiant la signature de x dans deux scripts différents, on force l’utilisation de la même valeur x. Si deux signatures différentes existent pour x, une pénalité peut être appliquée. Cette approche est appelée bit commitment.
Le principe du bit commitment est simple : pour chaque bit du message à signer, on définit deux valeurs de hachage distinctes, hash0 et hash1. Si le bit vaut 0, on révèle l’antécédent preimage0 de hash0 ; s’il vaut 1, on révèle preimage1 de hash1.
Par exemple, pour un bit m ∈ {0,1}, le script de déblocage correspondant contient simplement l’antécédent : si m=0, le script est preimage0 (ex: « 0xfa7fa5b1dea37d71a0b841967f6a3b119dbea140 ») ; si m=1, c’est preimage1 (ex: « 0x47c31e611a3bd2f3a7a42207613046703fa27496 »). Ainsi, le bit commitment permet de créer des scripts Bitcoin « avec état », rendant possibles de nouvelles fonctionnalités.
OP_HASH160
OP_DUP
<0xf592e757267b7f307324f1e78b34472f8b6f46f3> // Ceci est hash1
OP_EQUAL
OP_DUP
OP_ROT
<0x100b9f19ebd537fdc371fa1367d7ccc802dc2524> // Ceci est hash0
OP_EQUAL
OP_BOOLOR
OP_VERIFY
// La valeur du bit commitment est maintenant sur la pile, soit "0", soit "1".
Il existe deux implémentations principales du bit commitment :
-
Signature Lamport à usage unique : simple, utilisant uniquement des fonctions de hachage, donc compatible Bitcoin. Pour chaque bit du message, deux hachés doivent être engagés, ce qui rend la signature volumineuse. Pour un message de v bits, la clé publique fait 2v bits et la signature v bits.
-
Signature Winternitz à usage unique : réduit significativement la taille de la signature et de la clé publique par rapport à Lamport, mais augmente la complexité de signature/vérification. On peut ajuster la longueur de la chaîne de hachage (paramètre d) pour équilibrer taille et complexité. Par exemple, avec d=15, la taille est divisée par ~4, mais la vérification devient 4 fois plus coûteuse — un compromis entre espace pile et taille de script. La signature Lamport est un cas particulier de Winternitz avec d=1.
Dans la bibliothèque BitVM2, une signature Winternitz basée sur Blake3 est utilisée, avec environ 26 octets par bit. Utiliser le bit commitment pour introduire de l’état a donc un coût élevé. Ainsi, dans BitVM2, on commence par hacher le message complet (256 bits), puis applique le bit commitment sur ce haché, réduisant drastiquement la charge plutôt que d’engager chaque bit du message brut.
2.3 Taproot : dépasser la limite d’espace de script
Depuis l’activation en novembre 2021 du fork doux Taproot, incluant Schnorr (BIP 340), Taproot (BIP 341) et TapScript (BIP 342), un nouveau type de transaction est disponible : Pay-to-Taproot (P2TR). Ce dernier combine Taproot, MAST (Merkle Abstract Syntax Tree) et les signatures Schnorr pour créer des transactions plus privées, flexibles et évolutives.
Un P2TR supporte deux modes de dépense : par chemin de clé (key path) ou par chemin de script (script path).
Selon BIP 341, lors d’une dépense par script path, la profondeur maximale du chemin Merkle est de 128, donc au plus 2¹²⁸ feuilles (tapleaf). Depuis SegWit (2017), la taille des blocs est mesurée en unités de poids, avec un maximum de 4 millions (environ 4 Mo). Lorsqu’un P2TR est dépensé via script path, seule la feuille tapleaf correspondante est révélée dans le bloc. Chaque tapleaf peut donc atteindre ~4 Mo. Toutefois, par stratégie par défaut, de nombreux nœuds ne relaient que les transactions inférieures à 400 Ko ; celles au-delà nécessitent une coordination avec les mineurs.
Cet espace étendu rend plus viable la simulation d’opérations cryptographiques (multiplication, hachage) avec les opcodes existants.
Lors de la construction d’un système de calcul vérifiable sur P2TR, la taille du script n’est plus limitée à 4 Mo : le calcul peut être découpé en sous-fonctions réparties sur plusieurs tapleaf, dépassant ainsi la limite. Par exemple, le vérificateur Groth16 dans BitVM2 atteint 2 Go. Grâce à Taproot, il peut être divisé sur environ 1000 tapleaf. Couplé au bit commitment, cela permet de garantir l’intégrité et la cohérence du calcul global.
2.4 Sortie connecteur (connector output) : dépasser la limite des modes de dépense UTXO
Actuellement, un UTXO Bitcoin peut être dépensé soit via un script, soit via une clé publique. Tant que la condition est remplie (signature ou script), le dépense est valide. Deux UTXO sont indépendants : on ne peut pas imposer de condition conjointe pour leur dépense simultanée.
Cependant, Burak, fondateur du protocole Ark, a conçu une solution astucieuse utilisant les indicateurs SIGHASH : la sortie connecteur. Alice crée une signature transférant ses BTC à Bob, mais cette signature engage plusieurs entrées. Elle peut la rendre conditionnelle : valide uniquement si la transaction consomme une deuxième entrée. Cette deuxième entrée est le connecteur, liant UTXO A et UTXO B. Ainsi, la transaction Take_tx n’est valide que si UTXO B n’a pas été dépensé par Challenge_tx. En détruisant le connecteur, on bloque donc Take_tx.
Figure 1 : illustration d’un connector output
Dans le protocole BitVM2, le connector output joue un rôle similaire à une instruction if...else. Une fois dépensé par une transaction, il ne peut plus l’être par une autre, assurant son exclusivité. En pratique, pour prévoir une période de réponse au défi, un UTXO avec timelock est ajouté. De plus, le connector output peut adopter différentes stratégies de dépense : la transaction de défi peut être dépensable par n’importe qui, tandis que la réponse peut être réservée à l’opérateur ou ouverte à tous après délai.
2.5 Covenants : dépasser la limite des pré-signatures
Actuellement, les scripts Bitcoin contrôlent principalement les conditions de déblocage, mais pas la manière dont l’UTXO sera dépensé ultérieurement. Cela vient de l’impossibilité du script de lire le contenu de la transaction elle-même (pas d’auto-inspection). Si le script pouvait inspecter toute la transaction (sorties incluses), des covenants seraient possibles.
Les implémentations actuelles de covenants se divisent en deux catégories :
-
Pré-signature : utilise les capacités existantes du script Bitcoin pour créer des covenants simples et prédéfinis. Toutes les transactions futures possibles sont conçues et signées à l’avance, liant les participants à des clés privées et tarifs spécifiques. Certaines solutions exigent même la génération de clés privées temporaires pour toutes les transactions pré-signées. Après validation, ces clés sont supprimées en sécurité, empêchant leur vol. Toutefois, chaque ajout ou mise à jour de participant requiert de recommencer tout le processus, rendant la maintenance lourde. Par exemple, Lightning Network utilise la pré-signature pour des covenants à 2 parties, combinés avec HTLC pour router plusieurs connexions, réalisant ainsi une extension à confiance minimale. Mais cela nécessite de pré-signer de nombreuses transactions, et reste limité à deux parties, ce qui est lourd. Dans BitVM1, des centaines de transactions doivent être pré-signées à l’initialisation ; même optimisé, BitVM2 en nécessite encore des dizaines. Seuls les opérateurs ayant participé à la pré-signature peuvent être remboursés. Si n participants pré-signent chacun m transactions, la complexité par participant est n × m.
-
Introduction d’opcodes covenants : ajouter de nouveaux opcodes permettrait de réduire radicalement la complexité de communication et de maintenance, offrant des covenants plus flexibles. Exemples :
- OP_CAT : concatène deux chaînes d’octets. Bien que simple, il est puissant et réduit fortement la complexité de BitVM.
- OP_TXHASH : permet un contrôle plus fin des actions dans un covenant. Dans BitVM, cela permettrait de supporter un ensemble plus grand d’opérateurs, améliorant l’hypothèse de sécurité et minimisant la confiance.
3 Mise à l’échelle Bitcoin Layer2 : preuves de validité et de fraude
Les preuves de validité et de fraude peuvent toutes deux servir à l’évolutivité Bitcoin L2. Leurs différences principales sont résumées dans le tableau 2.
Tableau 2 : Preuve de validité vs preuve de fraude
Grâce au bit commitment, Taproot, la pré-signature et les sorties connecteurs, on peut construire des preuves de fraude sur Bitcoin. Avec Taproot et l’introduction d’opcodes covenants comme OP_CAT, on peut construire des preuves de validité. En outre, selon que Bob a ou non un accès contrôlé, les preuves de fraude se divisent en preuves permises (permissioned) et non permises (permissionless). Dans le premier cas, seuls certains groupes peuvent lancer un défi ; dans le second, tout tiers peut agir comme challenger. La version non permise est plus sécurisée, réduisant le risque de collusion entre participants autorisés.
Selon le nombre d’interactions entre Alice et Bob lors du défi-réponse, les preuves de fraude se divisent en preuves à un tour et à plusieurs tours, comme illustré figure 2.
Figure 2 : Preuve de fraude à un tour vs à plusieurs tours
Comme montré dans le tableau 3, les preuves de fraude peuvent être réalisées selon différents modèles d’interaction : un tour ou plusieurs tours.
Tableau 3 : Interaction à un tour vs à plusieurs tours
Dans le paradigme Bitcoin Layer2, BitVM1 utilise une preuve de fraude à plusieurs tours, BitVM2 une preuve à un tour, et bitcoincircle stark utilise une preuve de validité. BitVM1 et BitVM2 peuvent être déployés sans modification du protocole Bitcoin, tandis que bitcoin-circle stark nécessite l’ajout de l’opcode OP_CAT.
Pour la plupart des tâches de calcul, signet, testnet et mainnet Bitcoin ne peuvent pas représenter entièrement le script dans 4 Mo. Une technique de découpage (script Split) est nécessaire : diviser le script représentant le calcul complet en fragments (chunks) inférieurs à 4 Mo, répartis sur différents tapleaf.
3.1 Preuve de fraude à plusieurs tours sur Bitcoin
Comme indiqué dans le tableau 3, la preuve de fraude à plusieurs tours convient aux cas où l’on souhaite réduire le volume de calcul d’arbitrage sur chaîne, ou quand on ne peut pas localiser immédiatement le fragment erroné. Comme son nom l’indique, elle nécessite plusieurs interactions entre le prouveur et le vérifieur pour identifier le fragment problématique, puis arbitrer à partir de là.
Le premier livre blanc BitVM de Robin Linus (appelé BitVM1) utilisait cette méthode. En supposant une période de défi hebdomadaire et une recherche dichotomique, le cycle d’arbitrage chaîne pour un vérificateur Groth16 atteint 30 semaines — très lent. Même si certaines équipes explorent des méthodes n-aires plus efficaces que la dichotomie, elles restent bien moins rapides que le cycle de 2 semaines d’une preuve à un tour.
Actuellement, les preuves de fraude à plusieurs tours dans le paradigme Bitcoin sont toutes permissioned, tandis que les versions à un tour atteignent le statut permissionless, réduisant le risque de collusion et offrant une meilleure sécurité. Robin Linus a donc optimisé BitVM1 en exploitant pleinement Taproot, réduisant les interactions à un tour et étendant l’accès à tous, au prix d’un calcul d’arbitrage chaîne accru.
3.2 Preuve de fraude à un tour sur Bitcoin
Une interaction unique entre prouveur et vérifieur suffit pour valider ou invalider la preuve. Le vérifieur lance un seul défi, le prouveur répond une fois, en fournissant une preuve de correction. Si le vérifieur détecte une incohérence, le défi réussit ; sinon, il échoue. Les caractéristiques de ce modèle sont résumées dans le tableau 3.
Figure 3 : Preuve de fraude à un tour
Le 15 août 2024, Robin Linus a publié le livre blanc « BitVM2 : Bridging Bitcoin to Second Layers », utilisant un modèle similaire à la figure 3 pour implémenter un pont BitVM2 via une preuve de fraude à un tour.
3.3 Preuve de validité sur Bitcoin + OP_CAT
OP_CAT faisait partie initiale du langage de script Bitcoin, mais a été désactivé en 2010 pour des raisons de sécurité. Depuis, la communauté discute de sa réactivation. OP_CAT porte désormais le numéro 347 et est activé sur signet.
OP_CAT concatène deux éléments de la pile et repousse le résultat. Cette fonctionnalité ouvre la voie aux covenants et au vérificateur STARK sur Bitcoin :
-
Covenants : Andrew Poelstra propose « CAT and Schnorr Tricks I », utilisant OP_CAT et des astuces Schnorr pour implémenter des covenants. Schnorr est la signature numérique pour les sorties P2TR ; pour d’autres types, des astuces ECDSA similaires sont possibles (« Covenants with CAT and ECDSA »). Ces covenants aident à diviser l’algorithme STARK Verifier en plusieurs transactions, vérifiant progressivement la preuve complète.
-
Vérificateur STARK : il consiste principalement à concaténer des données et à les hacher. Contrairement aux opérations algébriques, le hachage est natif au script Bitcoin, économisant énormément. Par exemple, OP_SHA256 coûte un opcode natif contre des centaines de milliers simulés. Les hachages principaux dans STARK sont la vérification des chemins Merkle et la transformation Fiat-Shamir. OP_CAT est donc très adapté au vérificateur STARK.
3.4 Technique de découpage de script Bitcoin
Bien que les preuves SNARK/STARK réduisent fortement la charge de vérification par rapport au calcul brut f, leur conversion en script Bitcoin reste très lourde. Actuellement, même optimisés, les scripts de vérification Groth16 et Fflonk dépassent 2 Go. Or, la taille d’un bloc Bitcoin est limitée à 4 Mo — impossible d’exécuter tout le script dans un seul bloc. Heureusement, depuis Taproot, les scripts peuvent s’exécuter par tapleaf. On peut donc découper le vérificateur en chunks, chaque chunk formant un tapleaf du taptree. La cohérence entre chunks est assurée via bit commitment.
Avec des covenants OP_CAT, le vérificateur STARK peut être divisé en plusieurs transactions standard inférieures à 400 Ko, permettant la vérification complète de la preuve STARK sans coordination avec les mineurs.
Cette section se concentre sur les techniques de découpage de script dans le cadre actuel, sans activation de nouveaux opcodes.
Lors du découpage, plusieurs dimensions doivent être équilibrées :
-
La taille d’un chunk ≤ 4 Mo, incluant espace pour bit commitment, signature, etc.
-
La pile d’un chunk ≤ 1000 éléments. Il faut donc limiter les éléments sur pile pour optimiser l’espace script. Les frais de transaction ne dépendent pas de la taille de pile.
-
Le bit commitment est coûteux : 1 bit ≈ 26 octets. Minimiser le nombre de bits échangés entre chunks adjacents.
-
Chaque chunk doit avoir une fonction claire pour faciliter l’audit.
Les méthodes de découpage se divisent actuellement en trois grandes catégories :
-
Découpage automatique : cherche une division avec script ~3 Mo et pile minimale. Avantages : indépendant de l’algorithme, extensible à tout calcul. Inconvénients : (1) les blocs logiques (ex: OP_IF) ne peuvent être coupés, sinon le résultat change ; (2) le résultat du chunk peut être plusieurs éléments sur pile, nécessitant une annotation manuelle pour le bit commitment ; (3) faible lisibilité, difficile à auditer ; (4) la pile peut contenir des éléments inutiles pour le chunk suivant, gaspillant l’espace.
-
Découpage fonctionnel : basé sur les sous-fonctions du calcul, avec entrées/sorties claires. Le découpage inclut directement les scripts de bit commitment. Objectif : taille totale < 4 Mo, pile < 1000. Avantages : fonctionnalité claire, logique lisible, facile à auditer. Inconvénients : l’optimalité au niveau calcul n’implique pas l’optimalité au niveau script.
-
Découpage manuel : les points de coupe sont fixés manuellement, utile quand une sous-fonction > 4 Mo. Avantages : permet de découper manuellement des sous-fonctions lourdes (ex: calculs Fq12) ; logique claire, lisible, auditable. Inconvénients : dépend de l’expertise humaine ; après optimisation globale, les anciens points de coupe peuvent ne plus être optimaux, nécessitant un réajustement.
Par exemple, après plusieurs optimisations, le script du vérificateur Groth16 est passé de ~7 Go à ~1,26 Go. En plus de cette optimisation globale, chaque chunk peut être optimisé séparément pour mieux utiliser l’espace pile. Par exemple, en utilisant des algorithmes basés sur des tables de recherche (lookup table), chargées/déchargées dynamiquement, on peut réduire davantage la taille de chaque chunk.
Les coûts et environnements d’exécution des langages web2 diffèrent fondamentalement de ceux du script Bitcoin. Traduire bêtement des implémentations existantes ne fonctionne pas. Des optimisations spécifiques sont donc nécessaires :
-
Choisir des algorithmes avec bonne localité mémoire, même au prix d’un peu plus de calcul, afin de réduire les bits échangés entre chunks, diminuant ainsi la quantité de données à engager dans les transactions assertTx de BitVM2.
-
Exploiter la commutativité des opérations (ex: x&y = y&x) pour réduire d’environ moitié la taille des tables de recherche.
-
Les calculs Fq12 occupent beaucoup de script. On peut envisager d’utiliser Fiat-Shamir, Schwartz-Zippel et des schémas de preuve polynomiale pour réduire drastiquement la complexité des calculs en extension de corps Fq12.
4 Conclusion
Cet article a d’abord présenté les limitations du script Bitcoin, puis les solutions pour les contourner : bit commitment pour surmonter l’absence d’état des UTXO, Taproot pour étendre l’espace de script, sorties connecteurs pour enrichir les modes de dépense, et covenants pour dépasser les contraintes de pré-signature. Ensuite, il a passé en revue de manière exhaustive les caractéristiques des preuves de validité et de fraude, des preuves de fraude permissioned et permissionless, des preuves à un tour et à plusieurs tours, ainsi que la technique de découpage de script Bitcoin.
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














