NOUVEAU : Helius acquiert Light Protocol
comparaison du cycle de vie des transactions de Solana et de Sui
Blog/Fondamentaux

Aux frontières du déterminisme : cycle de vie des transactions dans Solana Sealevel et le runtime objet de Sui

Chercheur et développeur full stack.Prince Israel sur XPrince Israel sur LinkedIn
29 min de lecture

Solana et Sui sont deux blockchains de couche 1 très performantes, capables de traiter un volume élevé de transactions à très faible coût sans sacrifier l'évolutivité, la vitesse ni la décentralisation.

Ces deux protocoles sont reconnus dans le secteur comme des blockchains de pointe qui répondent à de nombreuses limites des blockchains plus anciennes telles qu'Ethereum et Bitcoin.

Ces protocoles sont conçus pour traiter des dizaines de milliers de transactions en parallèle, ce qui leur confère un débit exceptionnellement élevé, tant en théorie qu'en pratique. Solana, par exemple, peut atteindre 65 000 transactions par seconde (TPS) dans des conditions idéales et maintient environ 4 000 TPS dans des scénarios réels.

Sui, de son côté, a démontré un maximum théorique de 297 000 TPS, mais n'a traité depuis son lancement qu'un maximum de 3 500 TPS, avec une moyenne quotidienne d'environ 400 TPS pour les transactions utilisateur et de 600 TPS pour les transactions système servant à construire les checkpoints.

Aujourd'hui, Solana atteint une confirmation optimiste en 400 ms et une finalité complète en ~12,8 secondes. La prochaine mise à niveau du consensus Alpenglow devrait ramener cette finalité complète à 100-130 ms. Grâce à sa robuste conception optimiste, Sui atteint une finalité inférieure à une seconde au 90e percentile (P90) de latence.

Dans cet article de recherche, nous étudions les mécanismes sous-jacents qui assurent les hautes performances transactionnelles en analysant le cycle de vie des transactions des deux chaînes. Nous proposons également une comparaison détaillée de la manière dont leurs différents modèles d'exécution permettent d'atteindre un débit élevé avec un faible délai de finalité.

Qu'est-ce que le cycle de vie d'une transaction blockchain ?

Les blockchains traitent des transactions. Les transactions modifient l'état, c'est-à-dire la vue actualisée des comptes sur une blockchain. Comprendre le cycle de vie d'une transaction est sans doute la meilleure manière de saisir la philosophie de conception d'une blockchain. Cela fournit aux parties prenantes techniques des informations importantes sur l'optimisation de la chaîne en matière de débit et de sécurité, ses garanties de déterminisme, ses coûts d'ingénierie relatifs et les éventuels points de friction en conditions réelles.

Dans les sections suivantes, nous examinerons les différentes étapes que traversent les transactions, de leur soumission à leur finalisation, ainsi que l'incidence de ce processus sur l'exécution aux différents niveaux de ces chaînes.

Cycle de vie d'une transaction Solana

La blockchain Solana repose sur une conception unique qui utilise la preuve d'enjeu (Proof-of-Stake ou PoS) comme mécanisme de consensus et la preuve d'historique (Proof-of-History ou PoH) comme mécanisme d'horodatage permettant d'ordonner efficacement les transactions.

Le modèle de conception de Solana est centré sur les comptes, ce qui revient à dire que « sur Solana, tout est un compte ».

Les comptes servent à stocker des données, notamment l'état et les binaires exécutables, c'est-à-dire le code des programmes. Les transactions contiennent des instructions qui modifient l'état des comptes. Les nœuds qui participent au consensus du réseau et au traitement des transactions sont appelés validateurs. Le processus par lequel les transactions sont traitées afin de modifier un compte est appelé pipeline, et les différents points du cycle de vie d'une transaction sont appelés des étapes.

Une transaction Solana

Sur Solana, une transaction est un ensemble de signatures de messages sérialisés, signés par la première clé parmi les clés de compte du Message.

Le message d'une transaction est une structure de données contenant un en-tête, des clés de compte, un blockhash récent et des instructions. L'en-tête contient le MessageHeader, qui décrit l'organisation des clés de compte du Message.

Chaque instruction définit explicitement les comptes auxquels elle peut accéder et les autorisations requises pour chacun. Ces autorisations indiquent si un compte est en lecture seule ou en lecture-écriture, et s'il doit avoir signé la transaction contenant l'instruction.

Code
pub struct Message {
pub header: MessageHeader,
pub account_keys: Vec<Pubkey>,
pub recent_blockhash: Hash,
pub instructions: Vec<CompiledInstruction>,
}

Chaque instruction contient la liste de tous les comptes auxquels elle peut accéder, ainsi que les autorisations requises pour chacun d'eux.

Un Message contient une seule liste plate et partagée de tous les comptes requis par l'ensemble des instructions de la transaction. Cette liste plate est créée lors de la construction d'un Message, et les instructions sont converties en un ensemble de CompiledInstructions. Ces CompiledInstructions référencent ensuite, par leur index, les comptes dont elles ont besoin dans la liste de comptes partagée.

La liste de comptes partagée est ordonnée selon les autorisations requises pour les comptes :

  • Comptes modifiables et signataires.
  • Comptes en lecture seule et signataires.
  • Comptes modifiables et non signataires.
  • Comptes en lecture seule et non signataires.

Compte tenu de cet ordre, les champs du MessageHeader indiquent les autorisations requises par chaque compte d'une transaction.

Code
pub struct MessageHeader { 
pub num_required_signatures: u8,
pub num_readonly_signed_accounts: u8,
pub num_readonly_unsigned_accounts: u8,
}

Lorsque plusieurs transactions accèdent aux mêmes comptes en lecture seule, le runtime peut les traiter en parallèle dans une seule entrée PoH. Les transactions qui accèdent aux mêmes comptes en lecture-écriture sont traitées séquentiellement.

Les transactions sont soumises au client via Gulf Stream, le protocole de transfert des transactions de Solana, puis traitées dans le validateur par deux processus en pipeline et à plusieurs étapes : la Transaction Processing Unit (TPU) et la Transaction Validation Unit (TVU).

Ces processus coopèrent avec le runtime pour que les transactions qui modifient des états de compte différents soient traitées en parallèle, tandis que celles qui modifient le même état de compte le sont séquentiellement.

La TPU fonctionne lorsque le validateur est en mode leader, c'est-à-dire lorsqu'il produit des blocs, et la TVU lorsqu'il est en mode validateur, c'est-à-dire lorsqu'il valide des blocs. Dans les deux cas, le matériel du pipeline est similaire : entrée réseau, écritures sur disque, sortie réseau, etc. Son utilisation diffère toutefois. En bref, la TPU sert à créer des entrées dans le registre, tandis que la TVU sert à les valider.

Dans les grandes lignes, les transactions sont soumises par un client et traitées par Gulf Stream via QUIC dans la TPU d'un leader. La transaction fait l'objet de contrôles, puis l'étape bancaire planifie son exécution. Les mises à jour d'état sont réécrites dans l'état en mémoire de la banque. Les validateurs votent sur les blocs via gossip, et les blocs sont finalisés avec Tower BFT, une variante de PBFT dotée de mécanismes de verrouillage pondérés par l'enjeu.

Gulf Stream

Dans la plupart des blockchains, les transactions soumises par les utilisateurs sont placées en file d'attente dans une mempool, littéralement un « pool de mémoire », jusqu'à leur traitement par le réseau. Les transactions signées peuvent y rester longtemps, voire indéfiniment, dans l'attente de leur exécution si le réseau n'est pas dans un état optimal ou si les conditions d'exécution ne sont pas réunies. Elles risquent alors de ne jamais être incluses dans un bloc.

Solana élimine le besoin d'une mempool globale en s'appuyant sur un calendrier déterministe des leaders influencé par un algorithme pondéré par l'enjeu, appelé Stake-Weighted Quality of Service (SWQoS), afin de donner la priorité aux messages de transaction acheminés par des validateurs ayant mis des fonds en staking.

Comme tous les nœuds actifs connaissent à l'avance le calendrier des leaders, les messages de transaction peuvent être distribués efficacement. Les prochains leaders disposent ainsi d'un nombre suffisant de transactions à traiter avant même le début de leur créneau de production de blocs. Ce mécanisme permet aux validateurs de prétraiter les transactions en vérifiant les signatures et en éliminant au préalable les doublons ou les transactions mal formées.

Gulf Stream présente un autre avantage par rapport aux chaînes traditionnelles utilisant une mempool : sur celles-ci, les producteurs de blocs doivent retransmettre les mêmes transactions dans un bloc, ce qui signifie que chaque transaction est propagée au moins deux fois sur le réseau. Solana n'a pas besoin de surcharger gossip pour synchroniser les transactions en attente, et les transactions n'ont pas à se disputer l'espace de bloc au moyen d'enchères de gas ; elles sont distribuées selon la planification.

Transaction Processing Unit (TPU)

La TPU constitue la logique centrale du validateur chargée de produire les blocs. Les transactions sont récupérées auprès du client et transférées sous forme de paquets de données via un composant appelé QUIC streamer, qui alloue la mémoire des paquets et lit les données du point de terminaison QUIC. Cette phase est appelée « Fetch Stage ». Chaque flux transmet un paquet selon une contrainte de transmission QUIC identifiée par le client (adresse IP, clé publique du nœud) et le serveur.

Les paquets sont ensuite transmis à la Sigverify Stage, où ils sont dédupliqués à l'aide d'un mécanisme spécial de délestage qui supprime les paquets excédentaires. Les paquets dédupliqués sont alors filtrés pour retirer ceux dont la signature est invalide, puis transférés à l'étape bancaire.

L'étape bancaire est un composant essentiel de l'exécution du runtime de Solana. Elle planifie les paquets entrants, les filtre davantage afin de détecter les conflits et détermine s'ils peuvent être traités, conservés ou transférés par lots. Si elle détecte que le nœud est le producteur du bloc, elle traite avec le composant Bank les paquets conservés et ceux nouvellement reçus. Le composant Bank est une représentation en mémoire de l'état complet du registre à un slot donné.

Dans l'étape bancaire et le composant de planification, la transaction est suivie dans deux états :

  • Un état non traité, dans lequel la transaction est disponible pour la planification
  • Un état en attente, dans lequel la transaction est en cours de planification ou de traitement

Une fois son traitement terminé, une transaction peut éventuellement être retentée. Si c'est le cas, elle repasse à l'état non traité ; sinon, son état doit être supprimé. Les transactions valides traitées sont regroupées en une « Entry » au moyen des ticks PoH, assemblées en blocs, puis diffusées sous forme de shreds aux pairs du réseau via Turbine, le protocole de propagation des blocs de Solana. Celui-ci génère des codes d'effacement pour « régénérer » les paquets de données perdus avant de transmettre les paquets au pair approprié lors de la Broadcast Stage.

Transaction Validation Unit (TVU)

La TVU est la logique des nœuds validateurs non leaders chargée de valider et de propager les blocs. Dans la TVU, les paquets de données sont traités par des étapes multithread avant leur finalisation. Celles-ci comprennent la récupération des shreds, la vérification des signatures, la retransmission et le rejeu.

Lors de la Shred Fetch Stage et de l'étape de vérification de la signature du leader sur les shreds, les non-leaders reçoivent les shreds des autres nœuds via UDP et vérifient les signatures par lots. Les shreds valides sont retransmis aux nœuds pairs durant la Retransmit Stage, puis chaque transaction est rejouée dans l'ordre lors de la Replay Stage.

Lors de l'étape de rejeu, le runtime est appelé pour réexécuter toutes les transactions de manière déterministe. Il vérifie ainsi que toutes les modifications d'état, les propriétés des programmes et les hash de la banque correspondent exactement à la sortie du leader.

Si un bloc est jugé valide, le validateur signe une transaction de vote et l'envoie au leader afin qu'elle soit incluse dans les blocs suivants.

Runtime

Le runtime est le processeur de transactions concurrentes de Solana, partagé entre la TPU et la TVU. Les transactions indiquent à l'avance leurs dépendances de données, c'est-à-dire les comptes qu'elles souhaitent lire et/ou modifier, afin de permettre une exécution explicite en mémoire dynamique. La lecture de l'état peut ainsi être correctement isolée de l'exécution des programmes, ce qui permet au runtime d'orchestrer les accès concurrents.

Le runtime de Solana utilise un moteur d'exécution appelé Sealevel pour exécuter en parallèle les transactions qui accèdent à des comptes en lecture seule. À l'inverse, les transactions qui accèdent à des comptes modifiables communs sont sérialisées et exécutées séquentiellement.

Dans le runtime, les transactions sont exécutées de façon atomique : toutes les instructions d'une transaction doivent s'exécuter correctement pour que celle-ci soit enregistrée dans la banque. Dans le cas contraire, la transaction échoue.

Le runtime interagit avec un programme donné par l'intermédiaire d'un point d'entrée doté d'une interface clairement définie. Ce point d'entrée est simplement une fonction Rust que tous les programmes on-chain exposent proprement comme point de départ de leur exécution. Il sert d'interface entre le runtime de Solana et les programmes. Le moteur d'exécution associe les clés publiques aux comptes et les achemine vers ce point d'entrée. Il impose toutefois plusieurs contraintes essentielles qui guident sa logique d'exécution et sont définies par l'architecture du jeu d'instructions de la machine virtuelle :

  • Seul le programme propriétaire peut modifier le contenu d'un compte.
  • Les soldes totaux de tous les comptes sont égaux avant et après l'exécution d'une transaction, mais cela ne s'applique qu'à leur valeur agrégée. Les lamports ne sont pas conservés lors des transferts système et des destructions.
  • Après l'exécution de la transaction, les soldes des comptes en lecture seule doivent être identiques à leurs soldes antérieurs.
  • Toutes les instructions de la transaction sont exécutées de manière atomique. Si l'une d'elles échoue, toutes les modifications apportées aux comptes sont annulées.

Les pipelines de la TPU et de la TVU suivent des parcours légèrement différents lorsqu'ils interagissent avec le runtime. Le runtime de la TPU veille à ce que les « entries » soient enregistrées au moyen des ticks PoH avant la validation de la mémoire, tandis que celui de la TVU veille à ce qu'elles soient vérifiées avant le traitement de toute transaction par le runtime.

Consensus

Le consensus est l'un des mécanismes les plus fondamentaux des systèmes informatiques distribués complexes. Dans le cycle de vie d'une transaction Solana, il intervient après l'exécution et la validation du bloc par la TVU, mais avant sa finalisation. Son principe central est un accord uniforme qui garantit que les participants du réseau s'accordent sur un même résultat et qu'une fois leur décision prise, ils ne peuvent plus en changer.

Formellement, un mécanisme de consensus tolérant aux pannes doit satisfaire les propriétés suivantes :

  • Accord uniforme : deux nœuds ne peuvent pas prendre des décisions différentes.
  • Intégrité : aucun nœud ne prend de décision plus d'une fois.
  • Validité : si un nœud choisit une valeur, cette valeur a été proposée par un autre nœud.
  • Terminaison : tout nœud qui ne tombe pas en panne finit par choisir une valeur.

En apparence, le consensus vise à amener les nœuds à s'accorder sur un point. Avec Solana, les nœuds doivent parvenir à un accord dans plusieurs situations, principalement dans les trois scénarios suivants :

Rotation des leaders

Tous les nœuds doivent s'accorder sur l'identité du leader, car les pannes réseau peuvent perturber les communications et provoquer un scénario de split-brain, dans lequel plusieurs nœuds pensent à tort être simultanément le leader.

Le calendrier des leaders est généré à partir d'une seed prédéfinie et de l'algorithme suivant : la hauteur des ticks PoH, c'est-à-dire un compteur augmentant de façon monotone, sert périodiquement à initialiser un algorithme pseudo-aléatoire stable.

À cette hauteur, la banque prélève un échantillon de tous les comptes ayant mis des fonds en staking dont les identités de leader ont voté au cours d'un nombre de ticks configuré pour le cluster. Cet échantillon, appelé ensemble actif, est trié selon le poids de l'enjeu. La seed aléatoire sert ensuite à sélectionner des nœuds pondérés par l'enjeu afin de créer un ordre lui-même pondéré par l'enjeu, qui devient valide après un nombre de ticks configuré pour le cluster.

Synchronisation

Sans horodatage fiable, un validateur ne peut pas déterminer l'ordre des blocs entrants. Solana utilise un mécanisme appelé Proof-of-History comme horloge cryptographique pour ordonner les transactions avant qu'elles ne passent par le consensus. Selon la documentation d'Anza sur la synchronisation :

« Les nœuds leaders "horodatent" les blocs à l'aide de preuves cryptographiques attestant qu'un certain temps s'est écoulé depuis la dernière preuve. Toutes les données intégrées par hash à la preuve ont nécessairement été produites avant la génération de celle-ci. Le nœud partage ensuite le nouveau bloc avec les nœuds validateurs, qui peuvent vérifier ces preuves. Les blocs peuvent parvenir aux validateurs dans n'importe quel ordre, voire être rejoués des années plus tard. Grâce à ces garanties de synchronisation fiables, Solana peut diviser les blocs en lots plus petits de transactions appelés entries. Les entries sont ensuite diffusées en temps réel aux validateurs, avant même toute notion de consensus sur le bloc ».

Il est important de garder à l'esprit que, même si Proof-of-History n'est pas un mécanisme de consensus, il influe fortement sur les performances du consensus Proof-of-Stake de Solana.

Validation atomique

Les validations atomiques constituent un autre processus sur lequel les nœuds doivent s'accorder. Dans un système performant comme Solana, une transaction peut échouer sur certains nœuds et réussir sur d'autres.

Pour éviter toute exécution partielle, Solana garantit l'atomicité au sein du runtime au sens ACID. Elle veille également à ce que tous les nœuds s'accordent sur le résultat d'une transaction : soit ils l'annulent en cas de problème, soit ils la valident si tout se passe correctement.

Sur Solana, le niveau d'engagement mesure la finalité d'un bloc (slot) d'après le nombre de validateurs ayant voté en sa faveur et la profondeur de leurs votes dans le mécanisme de verrouillage de Tower BFT. Il reflète le degré d'accord du réseau sur le slot concerné selon les votes exprimés par les validateurs. Chaque validateur vote sur des slots, et plus précisément sur des hauteurs de bloc, et s'engage à ne pas voter pour des forks en conflit. Les verrouillages de Tower BFT garantissent le respect de ce mécanisme.

Solana possède trois statuts d'engagement : traité, confirmé et finalisé. Un bloc est considéré comme confirmé lorsqu'une supermajorité de validateurs ayant mis des fonds en staking (≥66 %) vote en sa faveur. Il est finalisé lorsqu'au moins 32 blocs confirmés sont construits au-dessus de lui.

Conséquence directe de son exécution parallèle optimiste et de son calendrier asynchrone des leaders, Solana suit un modèle « exécuter d'abord, voter ensuite » : le protocole n'attend pas que tous les validateurs s'accordent sur un bloc nouvellement produit avant de produire le suivant. Cela peut aussi créer des forks, c'est-à-dire un scénario dans lequel au moins deux chaînes concurrentes coexistent. Lorsqu'un slot est finalisé, tous les forks concurrents sont abandonnés et ce fork devient la chaîne canonique.

Alpenglow

À la date de rédaction de cet article, Solana utilise Tower BFT et le registre PoH pour garantir que le réseau parvient à un consensus même lorsque certains participants échouent.

Récemment, l'équipe de recherche d'Anza a proposé une nouvelle conception de protocole de consensus, plus simple et plus performante, appelée Alpenglow. Alpenglow vise à remanier les composants historiques du consensus actuel, notamment Proof of History, Tower BFT et l'utilisation de gossip pour propager les votes.

Alpenglow s'appuie essentiellement sur Votor et Rotor pour accélérer le consensus de Solana :

Votor est un mécanisme de vote à deux niveaux conçu pour atteindre la finalité des blocs en un seul tour si 80 % de l'enjeu répond, et en deux tours si au moins 60 % de l'enjeu répond.

Rotor améliore le protocole Turbine existant en utilisant une couche unique de nœuds relais pour diffuser les shreds. Rotor exploite également la bande passante des nœuds participants proportionnellement à leur enjeu afin de réduire le nombre de sauts et d'optimiser le débit de Solana. 

Sui

Contrairement à Solana, dont le modèle est centré sur les comptes, la blockchain Sui utilise un modèle de données orienté objet qui représente les données d'état sous forme d'objets dotés d'identifiants uniques, de propriétés et de méthodes.

Sur Sui, un smart contract est lui aussi un objet, appelé package Sui Move, qui possède un identifiant unique et manipule des objets. Ces packages Sui Move comprennent un ensemble de modules de bytecode Move de Sui. Chaque module se distingue par son nom, et la combinaison de l'ID on-chain d'un package et du nom d'un module permet d'identifier ce dernier de manière unique.

Bien que les subtilités de la conception des objets et des métadonnées dépassent le cadre de cet article, il est essentiel de retenir que chaque objet possède un propriétaire qui détermine comment cet objet peut être utilisé dans les transactions.

Les objets peuvent suivre les modèles de propriété suivants :

  • Objets détenus par une adresse : un objet détenu par une adresse appartient à une adresse précise de 32 octets, qu'il s'agisse d'une adresse de compte ou de l'ID d'un objet. Seul son propriétaire peut y accéder.
  • Objets immuables : un objet immuable ne peut être ni modifié, ni transféré, ni supprimé. Il n'a pas de propriétaire et reste accessible à tous pour une utilisation globale.
  • Objets partagés : un objet partagé est mutualisé et accessible à tous.
  • Objets encapsulés : ce modèle consiste à encapsuler un objet dans un autre. Les objets encapsulés ne sont pas indépendants et ne sont accessibles que par l'intermédiaire de l'objet qui les encapsule.

Une transaction Sui

Sur Sui, les transactions se composent d'un groupe de commandes exécutées sur des entrées afin de définir le résultat de la transaction. Ces groupes de commandes sont appelés blocs de transactions programmables (PTB) et définissent toutes les transactions utilisateur sur Sui. Les PTB permettent à un utilisateur d'appeler plusieurs fonctions Move, de gérer ses objets et ses « coins » dans une seule transaction, sans devoir publier un nouveau package Move.

La structure d'un PTB est définie ainsi :

Code
{
    inputs: [Input],
    commands: [Command],
}

inputs est un vecteur d'arguments qui sont soit des objets, soit des valeurs pures. Ces objets peuvent appartenir à l'expéditeur, ou être partagés ou immuables. Le champ commands est un vecteur d'instructions de transaction de haut niveau.

Pendant l'exécution des PTB, le vecteur d'entrée est rempli avec les objets d'entrée ou les octets des valeurs pures. Les commandes de la transaction sont ensuite exécutées dans l'ordre, et les résultats sont stockés dans un vecteur de résultats. Il s'agit d'un tableau de valeurs dans lequel chaque valeur peut correspondre à n'importe quel type Move propre à chaque commande ; contrairement aux entrées, ces valeurs ne sont pas limitées aux objets ou aux valeurs pures. Enfin, les effets de la transaction sont appliqués de manière atomique. 

Nous n'aborderons pas le fonctionnement interne des PTB de Sui, car il s'agit d'un autre sujet complexe. Il faut toutefois noter qu'au début de l'exécution, le runtime du PTB prend les objets d'entrée déjà chargés et les place dans le tableau d'entrée. Le réseau a déjà vérifié ces objets, notamment leur existence et la validité de leur propriété. Les octets des valeurs pures sont eux aussi chargés dans le tableau, mais ils ne sont validés qu'au moment de leur utilisation.

À ce stade, les effets sur le coin servant au gas sont de la plus haute importance. Le budget maximal de gas est alors prélevé sur ce coin. Ce budget, généralement indiqué par l'expéditeur lors de la soumission de la transaction, représente la quantité maximale de gas que celle-ci peut consommer. Le gas inutilisé est restitué au coin à la fin de l'exécution, même si ce dernier a changé de propriétaire. Chaque commande de la transaction est ensuite exécutée dans l'ordre.

Après la soumission, le nœud complet certifie toutes les métadonnées fournies en envoyant la transaction à un nœud validateur lors de l'étape de certification. Le nœud validateur effectue tous les contrôles de validité nécessaires sur la transaction et la signe pour confirmer sa validité si elle les réussit. Pour qu'un nœud validateur considère la transaction comme valide, celle-ci doit :

  • Posséder une signature utilisateur valide.
  • Garantir que l'initiateur de la transaction a accès à tous les objets d'entrée détenus qu'elle utilise.
  • Garantir que les objets d'entrée partagés utilisés par la transaction existent.
  • Contenir au moins autant de gas que le montant indiqué dans le budget de gas de la transaction.

Si tous les contrôles réussissent, le validateur tente de verrouiller tous les objets inputs détenus au profit du « digest de transaction » concerné afin que chaque entrée détenue ne puisse être utilisée qu'une seule fois à la fois.

Si le verrouillage réussit, le validateur signe la transaction et renvoie la signature au nœud complet.

Un nœud complet Sui offre essentiellement une vue en lecture seule de l'état du réseau. Contrairement aux nœuds validateurs, les nœuds complets ne peuvent pas signer de transactions, bien qu'ils puissent valider l'intégrité de la chaîne en réexécutant les transactions précédemment validées par un quorum de validateurs. Le nœud complet ne collecte pas une seule signature de validateur, mais autant que possible en parallèle. Seule une supermajorité (⅔+ de l'enjeu) est toutefois nécessaire pour former un certificat de transaction.

Exécution et checkpoints

Une fois leur certificat émis, les transactions sont envoyées pour exécution à un comité de validateurs, c'est-à-dire un ensemble de validateurs indépendants défini pour chaque époque. Le validateur n'a pas besoin de vérifier à nouveau les transactions : il lui suffit de vérifier les signatures du certificat. Si la signature du certificat est valide, le validateur peut être certain que la transaction l'est également.

Pendant l'exécution, les transactions sont réparties en deux catégories : les transactions portant sur des objets détenus et celles portant sur des objets partagés :

Transactions portant sur des objets détenus

Les transactions portant sur des objets détenus n'accèdent à aucun objet d'entrée partagé et sont exécutées immédiatement. Elles sont également appelées transactions fast path : elles sont exécutées après validation, puis enregistrées dans la chaîne canonique. Ces transactions ne « passent » pas par le consensus. Elles finissent par y passer, mais uniquement afin d'établir un ordre canonique pour leur inclusion dans les checkpoints. Cela est techniquement possible en l'absence de risque d'écritures conflictuelles, puisque seul le propriétaire peut modifier l'objet. 

Transactions portant sur des objets partagés

Les transactions portant sur des objets partagés accèdent à des objets partagés. Elles doivent donc être ordonnées par le consensus par rapport aux autres transactions qui utilisent les mêmes objets partagés, puis exécutées. Elles sont aussi appelées transactions slow path. Elles doivent suivre l'intégralité du processus de consensus pour garantir la cohérence, car plusieurs utilisateurs peuvent accéder aux objets concernés et les modifier. 

Auparavant, la mempool de Sui, Narwhal, évitait la congestion habituelle en dissociant la diffusion des transactions de leur ordonnancement. Elle conservait les transactions certifiées et signées dans un graphe orienté acyclique (DAG) sans les ordonner elle-même. Bullshark établissait ensuite leur ordre par consensus.

Afin d'améliorer encore les performances et la résilience, le protocole HammerHead a été introduit comme une évolution de Bullshark. Il met en œuvre une sélection dynamique des leaders fondée sur un score. Cela réduit considérablement la latence et augmente le débit, en particulier en présence de leaders défaillants ou hors service.

S'appuyant sur ces avancées, Mysticeti remplace désormais Narwhal et Bullshark en réunissant la diffusion et l'ordonnancement des transactions dans un même protocole. Mysticeti séquence les transactions dans un ordre total, ce qui simplifie encore le processus tout en réduisant la latence et en augmentant le débit. En outre, grâce au modèle de propriété centré sur les objets de Sui, la plupart des transactions restent indépendantes et n'ont pas à se disputer une position dans un ordre global.

Après l'exécution des transactions, le validateur signe leurs effets et les renvoie au nœud complet. Les effets d'une transaction sont essentiellement la liste de toutes les actions qu'elle a effectuées, comme les objets modifiés, le gas dépensé et le statut d'exécution de la transaction.

Les signatures des effets forment un ensemble de certificats d'effets que le nœud complet collecte auprès d'une supermajorité de validateurs, ce qui garantit la finalisation d'une transaction.

Lorsqu'une transaction est incluse dans un checkpoint, marquant la dernière étape de son cycle de vie, les changements d'état qu'elle a produits sont déjà finalisés et appliqués au réseau.

Pour les transactions impliquant uniquement des objets d'entrée détenus, les validateurs exécutent et finalisent ces transactions avant de les soumettre à la couche de consensus pour leur ordonnancement.

À l'inverse, les transactions impliquant des objets d'entrée partagés sont soumises au consensus pour être ordonnées avant leur exécution, puis ne sont pas soumises à nouveau en vue de leur inclusion dans un checkpoint.

Le validateur collecte auprès de la couche de consensus des fragments complets de transactions ordonnées selon leur causalité, puis construit un checkpoint contenant à la fois la liste des digests de transaction et les digests correspondants des effets de chaque transaction. Les checkpoints constituent ainsi un registre immuable de toutes les transitions d'état finalisées sur le réseau.

Finalité

Une transaction sur Sui atteint la finalité dès qu'une supermajorité (2𝑓 + 1) de validateurs accepte et contresigne un certificat de transaction, avant même que le certificat ne soit séquencé par le consensus ou exécuté. À ce stade, aucune transaction conflictuelle ne peut survenir et la transaction ne peut plus être révoquée. Pour les transactions qui n'impliquent que des objets détenus, le résultat de l'exécution est connu dès la finalité. Pour celles portant sur des objets partagés, il n'est déterminé qu'après le séquençage du certificat par le consensus. La finalité de la transaction est atteinte en deux allers-retours réseau.

Le règlement intervient lorsque la transaction est exécutée par une supermajorité de validateurs et qu'un certificat d'effets est formé. Pour les transactions portant sur des objets détenus, cette exécution se produit immédiatement, sans attendre le consensus. Pour celles portant sur des objets partagés, l'exécution et le règlement ont lieu juste après l'ordonnancement du certificat par le consensus. Dans les deux cas, le règlement n'est pas retardé par la création des checkpoints, ce qui offre une latence inférieure à celle du processus de checkpoint.

Si un certificat de transaction constitue un solide indicateur de finalité, seuls un certificat d'effets ou l'inclusion dans un checkpoint certifié fournissent une garantie absolue. Ils exigent en effet qu'une supermajorité de validateurs exécute la transaction et enregistre ses effets.

Dans les grandes lignes, le cycle de vie d'une transaction Sui s'appuie sur un modèle centré sur les objets pour maximiser le parallélisme et l'efficacité. Lorsqu'une transaction est soumise pour certification, les validateurs tentent de verrouiller les versions précises des objets d'entrée qu'elle référence.

Pour les objets détenus, ces verrous sont acquis immédiatement pendant la certification, garantissant un accès exclusif et empêchant la double dépense. Pour les objets partagés, les verrous ne sont établis qu'après l'ordonnancement de la transaction par le protocole de consensus de Sui.

Une fois tous les verrous requis acquis, l'exécution de la transaction est planifiée. Cette conception permet d'exécuter indépendamment et en parallèle les transactions portant sur des ensembles d'objets disjoints. Elle réduit ainsi considérablement les conflits et la congestion entre les parties indépendantes de l'état.

Une fois l'exécution réussie, les validateurs signent les effets de la transaction. Dès qu'une supermajorité de signatures est recueillie, un certificat d'effets est formé. Ce certificat garantit la finalité du règlement : la transaction est désormais irréversible et ses effets sont permanents.

Les checkpoints ne font pas partie du chemin critique de l'exécution ou de la finalité des transactions. Ils sont construits après l'exécution afin de fournir un ordre canonique des transactions et de faciliter la synchronisation de l'état pour les nœuds qui n'ont pas directement participé à l'exécution.

Le modèle objet de Sui permet un suivi précis des dépendances au niveau des objets, ce qui élimine le besoin de synchroniser l'état global. Cette architecture prend en charge une exécution distribuée et évolutive sur du matériel standard, au lieu de dépendre des progrès matériels pour augmenter le débit.

Analyse de l'exécution, de l'évolutivité et des compromis de conception

Comme indiqué précédemment, comprendre le cycle de vie d'une transaction est sans doute la meilleure manière de saisir la philosophie de conception d'une blockchain. Les différences entre les cycles de vie des transactions de Solana et de Sui révèlent des philosophies profondes en matière de modèle d'exécution selon trois axes essentiels : l'efficacité de l'exécution, les limites d'évolutivité et les compromis de conception.

Exécution

En tant que chaîne centrée sur les comptes, Solana détecte dynamiquement les conflits de comptes au moyen de leur verrouillage pendant la Banking Stage. Elle garantit ainsi que les transactions ne modifiant pas le même compte sont traitées en parallèle, tandis que celles qui entrent en conflit sont traitées séquentiellement.

Même si ce type de mécanisme de détection des comptes peut entraîner des coûts d'exécution supplémentaires dans les scénarios DeFi intensifs, en particulier lorsque des programmes doivent exécuter une logique provenant d'autres programmes par un mécanisme appelé Cross-Program Invocation, le moteur d'exécution de Solana conserve un parallélisme considérable grâce à sa détection dynamique des conflits. La chaîne peut ainsi exécuter les transactions presque instantanément avec des frais extrêmement faibles.

Sui, en revanche, n'a pas à se préoccuper des transactions conflictuelles, car son parallélisme est déduit lors de la compilation grâce à son modèle de propriété centré sur les objets. Le modèle des objets partagés et détenus permet de déduire statiquement les conflits et d'atteindre un coût d'exécution presque nul pour les transactions portant sur des objets détenus.

Limites d'évolutivité

En matière de mise à l'échelle, Sui assure une évolutivité horizontale et peut évoluer linéairement avec les partitions d'objets en traitant les transactions portant sur des objets détenus sans consensus global. Cela permet une finalité presque instantanée, inférieure à une seconde, et un débit uniquement limité par le matériel disponible. Les transactions portant sur des objets partagés nécessitent un consensus, mais depuis la mise à niveau Mysticeti, elles atteignent elles aussi une finalité inférieure à une seconde et un débit élevé. L'architecture de Sui permet à la diffusion et à l'exécution des blocs d'évoluer de manière élastique par l'ajout de ressources. Le système peut ainsi gérer efficacement des charges de travail croissantes, même si le chemin du consensus n'est pas aussi illimité que le fast path des objets détenus.

En raison de son approche à leader unique et de la distribution de son exécution, limitée par les conflits entre comptes, Solana semble atteindre une certaine limite d'évolutivité horizontale du fait de son modèle d'état global à shard unique et de l'ingestion des transactions par un leader pour chaque slot. Elle mène cependant une optimisation poussée à l'intérieur de cette limite grâce à son pipeline clairement défini, complété par PoH. Les transactions peuvent être ordonnées avec précision, traitées en moins de 400 ms et obtenir une confirmation optimiste en moins d'une seconde. Sur le plan de l'évolutivité verticale, Solana évolue fortement avec le matériel des validateurs, notamment les cœurs CPU et la RAM, ce qui correspond parfaitement à sa conception intrinsèque.

Il est important de préciser que Solana privilégie l'évolutivité verticale à l'évolutivité horizontale et atteint un plafond en raison de compromis de conception, et non d'une défaillance architecturale. Certaines approches horizontales sont actuellement en développement, comme les marchés de frais locaux, les sous-réseaux virtuels et la réduction de l'état au moyen de CMT.

Compromis de conception

Solana garantit le déterminisme par des contraintes strictes du runtime, l'isolation des comptes et une planification déterministe des leaders. Sa résolution dynamique des conflits entre comptes et son pipeline clairement défini favorisent les interactions approfondies entre programmes, ce qui lui permet d'offrir une forte composabilité.

Sui garantit le déterminisme grâce à des chemins d'exécution intégrés, déterminés par l'analyse de la propriété des objets. Parallèlement, le modèle centré sur les objets de Sui favorise la composabilité grâce aux objets partagés et aux blocs de transactions programmables (PTB), qui permettent des interactions complexes et des opérations atomiques entre plusieurs contrats et utilisateurs. Cela est possible parce que le propriétaire d'un objet peut lui-même être un autre objet, ce qui permet une interopérabilité au niveau des objets et leur organisation en arborescences de propriété. Ces structures sont particulièrement utiles lorsque des objets sont fréquemment utilisés ensemble ou lorsque des recherches pendant l'exécution sont nécessaires pour déterminer l'objet sur lequel agir.

Résumé

Le mécanisme qui traite les transactions de leur soumission à leur finalité est au cœur des performances remarquables de Solana et de Sui. L'étude du cycle de vie des transactions permet de comprendre les pipelines soigneusement conçus qui garantissent une faible latence et un débit élevé sur les deux chaînes.

Solana repose sur un modèle centré sur les comptes, dans lequel les transactions passent par une série de processus et de pipelines multithread destinés à garantir leur validité. Les transactions sont soumises au leader, qui exécute le pipeline de la TPU afin de les vérifier et de les planifier correctement : en parallèle si elles n'entrent pas en conflit, et séquentiellement dans le cas contraire. Lorsqu'un validateur ne produit pas de blocs, il exécute le pipeline de la TVU afin de répliquer et de valider les transactions. La TPU et la TVU utilisent toutes deux le runtime. Solana traite ainsi des milliers de transactions en très peu de temps, car le runtime peut identifier à l'avance et de manière déterministe les comptes qui ne se chevauchent pas, puis exécuter en parallèle les transactions sans conflit. Solana convient donc parfaitement à des cas d'usage réels comme le trading haute fréquence, la DeFi profondément composable, les dApps nécessitant une infrastructure lourde et les dApps grand public à faible latence.

Sui utilise pour sa part un modèle centré sur les objets, dans lequel chaque objet est suivi par un identifiant unique. En déduisant la propriété des objets, Sui peut déterminer statiquement si une transaction portant sur des ensembles d'objets disjoints peut être exécutée en parallèle. Son modèle à double chemin d'exécution sépare les transactions portant sur des objets détenus de celles portant sur des objets partagés et utilise des checkpoints signés pour synchroniser les nœuds complets. Sui peut ainsi traiter les transactions légères sans surcharger la couche de consensus, tout en offrant une finalité fiable et rapide ainsi qu'une synchronisation efficace des nouveaux nœuds. Cette architecture lui permet d'évoluer horizontalement avec l'augmentation de la charge et se révèle très utile pour les applications impliquant des interactions massives entre objets, notamment la DeFi, les jeux, les plateformes d'échange centrées sur les actifs et les actifs programmables.

Références

Abonnez-vous à Helius

Suivez les dernières actualités du développement sur Solana et recevez une notification à chaque publication

Image agrandie