L'ancien ambassadeur technique d'Arbitrum explique la structure des composants d'Arbitrum (partie 1)

ForesightNews

Cet article est l’interprétation technique d’Arbitrum One par Luo Benben, ancien ambassadeur technique d’Arbitrum et ancien co-fondateur de la société d’audit d’automatisation des contrats intelligents Goplus Security.

Écrit par : Luo Benben, ancien ambassadeur technique d’Arbitrum et contributeur geek web3

**Cet article est l’interprétation technique d’Arbitrum One par Luo Benben, ancien ambassadeur technique d’Arbitrum et ancien co-fondateur de la société d’audit d’automatisation des contrats intelligents Goplus Security. **

Parce qu’il y a un manque d’interprétation professionnelle d’Arbitrum et même d’OP Rollup dans les articles ou documents liés à la couche 2 dans le cercle chinois, cet article tente de combler le vide dans ce domaine en vulgarisant le mécanisme de fonctionnement d’Arbitrum. La structure d’Arbitrum elle-même étant trop complexe, le texte intégral dépasse tout de même les 10 000 mots bien qu’il soit simplifié au maximum, il est donc divisé en deux parties. Il est recommandé de le collecter et de le transmettre comme référence ! **

Brève description du trieur Rollup

Le principe de l’expansion du Rollup peut se résumer en deux points :

**Optimisation des coûts : transférez la plupart des tâches de calcul et de stockage vers la chaîne L1, c’est-à-dire L2. **L2 est principalement une chaîne fonctionnant sur un seul serveur, c’est-à-dire le séquenceur/opérateur.

Le trieur ressemble et se sent proche d’un serveur centralisé. Dans les « trois aspects impossibles de la blockchain », la « décentralisation » est abandonnée en échange de TPS et d’avantages en termes de coûts. Les utilisateurs peuvent laisser L2 traiter les instructions de transaction au lieu d’Ethereum, et le coût est bien inférieur à celui du trading sur Ethereum.

(Source : chaîne BNB)

Garantie de sécurité : **Le contenu de la transaction et le statut post-transaction sur L2 seront synchronisés avec Ethereum L1, et la validité de la transition de statut sera vérifiée via le contrat. **Dans le même temps, les enregistrements historiques de L2 seront conservés sur Ethereum. Même si le séquenceur est définitivement en panne, d’autres peuvent restaurer l’intégralité de l’état L2 via les enregistrements sur Ethereum.

**Fondamentalement, la sécurité de Rollup est basée sur Ethereum. **Si le séquenceur ne connaît pas la clé privée d’un compte, il ne peut pas initier de transactions au nom du compte, ni altérer le solde des actifs du compte (même s’il le sait, il sera rapidement découvert).

Bien que le trieur soit centralisé en tant que hub du système**, dans la solution Rollup relativement mature, le trieur centralisé ne peut mettre en œuvre que des comportements malveillants tels que l’examen des transactions ou les temps d’arrêt malveillants**, mais dans une solution de rollup idéale, il existe des moyens correspondants pour le confinement (comme des mécanismes résistant à la censure comme les retraits forcés ou le tri des preuves).

(Le protocole Loopring définit la fonction de retrait forcé dans le code source du contrat sur L1 pour que les utilisateurs puissent l’appeler)

Les méthodes de vérification d’état pour empêcher le séquenceur Rollup de faire du mal sont divisées en deux catégories : Preuve de fraude et Preuve de validité. Le système Rollup utilisant la preuve de fraude est appelé OP Rollup (Optimistic Rollup, OPR), tandis qu’en raison de certains bagages historiques, le système Rollup utilisant la preuve de validité est souvent appelé ZK Rollup** (Zero-knowledge Proof Rollup, ZKR) au lieu de Validity Rollup. .

Arbitrum One est un OPR typique. Il déploie des contrats sur L1 et ne vérifie pas activement les données soumises. Il est optimiste qu’il n’y a pas de problème avec les données. Si les données soumises sont incorrectes, le nœud de vérification L2 lancera activement une contestation.

Par conséquent, **OPR implique également une hypothèse de confiance : il existe à tout moment au moins un nœud vérificateur L2 honnête. **Le contrat de ZKR utilise des calculs cryptographiques pour vérifier activement mais de manière rentable les données soumises par le séquenceur.

(Méthode d’opération de cumul optimiste)

(Mode de fonctionnement ZK Rollup)

Cet article donnera une introduction approfondie à Arbitrum One, le projet leader en matière de rollup optimiste, couvrant tous les aspects de l’ensemble du système. Après l’avoir lu attentivement, vous aurez une compréhension approfondie d’Arbitrum et du rollup optimiste/OPR.

Composants principaux et flux de travail d’Arbitrum

Contrat principal :

Les contrats les plus importants d’Arbitrum incluent **SequencerInbox, DelayedInbox, L1 Gateways, L2 Gateways, Outbox, RollupCore, Bridge, etc. **Les détails seront présentés plus tard.

Séquenceur :

Recevez et triez les transactions des utilisateurs, calculez les résultats des transactions et renvoyez rapidement les reçus aux utilisateurs (généralement <1s). Les utilisateurs peuvent souvent voir leurs transactions répertoriées sur L2 en quelques secondes, et l’expérience est identique à celle de la plateforme Web2.

Dans le même temps, le séquenceur diffusera également le dernier bloc L2 immédiatement sous la chaîne Ethereum, et n’importe quel nœud Layer2 pourra le recevoir de manière asynchrone. Mais pour le moment, ces blocs L2 ne sont pas définitifs et peuvent être annulés par le séquenceur.

Toutes les quelques minutes, le séquenceur compressera les données de transaction L2 triées, les regroupera en lots et les soumettra au contrat de boîte de réception SequencerInbox sur la couche 1 pour garantir la disponibilité des données et le fonctionnement du protocole Rollup. De manière générale, les données L2 soumises à Layer1 ne peuvent pas être annulées et peuvent être définitives.

À partir du processus ci-dessus, nous pouvons résumer : **La couche 2 possède son propre réseau de nœuds, mais le nombre de ces nœuds est faible et il n’existe généralement pas de protocole de consensus couramment utilisé par les chaînes publiques, la sécurité est donc très faible et doit être garantie. en s’appuyant sur Ethereum.Fiabilité de la diffusion des données et efficacité des transitions d’état. **

Protocole de cumul d’arbitrage :

Une série de contrats qui définissent la structure du bloc RBlock de la chaîne Rollup, la méthode de continuation de la chaîne, la sortie de RBlock et le processus du mode challenge. ** Notez que la chaîne Rollup mentionnée ici n’est pas le grand livre de couche 2 que tout le monde comprend, mais une « structure de données de type chaîne » abstraite mise en place indépendamment par Arbitrum One afin de mettre en œuvre le mécanisme de preuve de fraude. **

Un RBlock peut contenir les résultats de plusieurs blocs L2, et les données sont également très différentes. Son entité de données RBlock est stockée dans une série de contrats dans RollupCore. S’il y a un problème avec un RBlock, le validateur contestera l’auteur du RBlock.

Validateur :

Les nœuds de validation d’Arbitrum sont en fait un sous-ensemble spécial de nœuds complets de couche 2 et ont actuellement accès à la liste blanche.

Validator crée un nouveau RBlock (bloc Rollup, également appelé assertion) basé sur le lot de transactions soumis par le séquenceur au contrat SequencerInbox,** et surveille l’état de la chaîne Rollup actuelle et évalue les transactions soumises par le séquenceur. Défi avec des données incorrectes. **

Le validateur actif doit engager à l’avance les actifs sur la chaîne ETH, parfois nous l’appelons aussi Staker. Bien que les nœuds de couche 2 qui ne s’engagent pas puissent également surveiller la dynamique de fonctionnement de Rollup et envoyer des alarmes anormales aux utilisateurs, ils ne peuvent pas intervenir directement sur les données d’erreur soumises par le séquenceur sur la chaîne ETH.

défi:

Les étapes de base peuvent être résumées sous forme de plusieurs cycles de segmentation interactive et de preuve en une seule étape. Dans le processus de segmentation, les parties contestataires effectuent d’abord plusieurs cycles de segmentation sur les données de transaction problématiques jusqu’à ce qu’elles décomposent les instructions du code d’opération problématique et effectuent une vérification. Le paradigme de « ** Preuve de subdivision à plusieurs tours et en une seule étape » est considéré par les développeurs d’Arbitrum comme la mise en œuvre la plus économe en gaz de la preuve de fraude. **Tous les aspects sont sous contrôle contractuel et aucune partie ne peut tricher.

Période du défi :

En raison de la nature optimiste de l’OP Rollup, après que chaque RBlock est soumis à la chaîne, le contrat n’est pas activement vérifié, ce qui laisse une période fenêtre au vérificateur pour falsifier. **Cette fenêtre horaire est la période de challenge, qui est d’une semaine sur le réseau principal Arbitrum One. Une fois la période de défi terminée, le RBlock sera finalement confirmé et les messages correspondants passés de L2 à L1 dans le bloc ** (tels que les opérations de retrait effectuées via le pont officiel) pourront être publiés.

ArbOS, Geth, WAVM:

La machine virtuelle utilisée par Arbitrum s’appelle AVM, qui comprend Geth et ArbOS. **Geth est le logiciel client le plus couramment utilisé dans Ethereum, et Arbitrum y a apporté de légères modifications. **ArbOS est responsable de toutes les fonctions spéciales liées à L2, telles que la gestion des ressources réseau, la génération de blocs L2, l’utilisation d’EVM, etc. Nous considérons la combinaison des deux comme un AVM natif, qui est la machine virtuelle utilisée par Arbitrum. WAVM est le résultat de la compilation du code AVM dans Wasm. **Dans le processus de contestation Arbitrum, la dernière « preuve en une seule étape » vérifie l’instruction WAVM. **

Ici, nous pouvons utiliser la figure suivante pour représenter la relation et le flux de travail entre les composants ci-dessus :

Cycle de vie des transactions L2

Le flux de traitement d’une transaction L2 est le suivant :

1. L’utilisateur envoie des instructions de trading au séquenceur.

2. Le trieur vérifie d’abord les transactions à traiter en signatures numériques et autres données, élimine les transactions invalides et effectue le tri et les calculs.

3. Le séquenceur envoie le reçu de transaction à l’utilisateur (généralement très rapidement), ** mais il ne s’agit que du “prétraitement” effectué par le séquenceur sous la chaîne ETH, qui est dans l’état de Soft Finality et est pas fiable. **. Mais pour les utilisateurs qui font confiance au séquenceur (la plupart des utilisateurs), ils peuvent être optimistes que la transaction est terminée et ne sera pas annulée.

4. Le trieur compresse fortement les données de transaction originales prétraitées et les encapsule dans un lot.

**5. De temps en temps (affecté par des facteurs tels que le volume de données et la congestion ETH), le séquenceur publiera des lots de transactions dans le contrat Sequencer Inbox sur L1. **À ce stade, on peut considérer que la transaction a une finalité ferme.

Contrat de boîte de réception du séquenceur

Le contrat recevra le lot de transactions soumis par le séquenceur pour garantir la disponibilité des données. En regardant plus en profondeur, les données par lots dans SequencerInbox enregistrent complètement les informations d’entrée de transaction de la couche 2. ** Même si le séquenceur est définitivement arrêté, n’importe qui peut restaurer l’état actuel de la couche 2 en fonction de l’enregistrement par lots et remplacer le séquenceur défaillant/en cours d’exécution. . **

Pour le comprendre d’une manière physique, le L2 que nous voyons n’est que la projection du lot dans SequencerInbox, et la source de lumière est STF. Étant donné que la source lumineuse STF ne change pas facilement, la forme de l’ombre est uniquement déterminée par le lot agissant comme objet.

**Le contrat Sequencer Inbox est également appelé fast box. Le séquenceur lui soumet spécifiquement des transactions prétraitées, et seul le séquenceur peut lui soumettre des données. **La fast box correspondante est la slow box Delayer Inbox, sa fonction sera décrite dans le processus ultérieur.

Le validateur surveillera toujours le contrat SequencerInbox. ** Chaque fois que le séquenceur libère un lot dans le contrat, un événement en chaîne sera lancé. Une fois que le validateur aura écouté l’occurrence de cet événement, il téléchargera les données du lot et l’exécutera. localement. Enfin, émettez RBlock au contrat de protocole Rollup sur la chaîne ETH.

Il existe un paramètre appelé accumulateur dans le contrat relais d’Arbitrum, qui enregistre le lot L2 nouvellement soumis, ainsi que le nombre et les informations des transactions nouvellement reçues sur la boîte de réception lente.

(Le séquenceur soumet continuellement des lots à SequencerInbox)

  • *

(Informations spécifiques au lot, le champ de données correspond aux données du lot, cette partie des données est très volumineuse et la capture d’écran n’est pas entièrement affichée)

Le contrat SequencerInbox a deux fonctions principales :

ajoutez Sequencer L2Batch From Origin(), le séquenceur appellera cette fonction à chaque fois pour soumettre des données Batch au contrat Sequencer Inox.

force Inclusion(), Cette fonction peut être appelée par n’importe qui et est utilisée pour mettre en œuvre des transactions résistantes à la censure. La manière dont cette fonction prend effet sera expliquée en détail plus tard lorsque nous parlerons du contrat Delayed Inbox.

Les deux fonctions ci-dessus appelleront bridge.enqueueSequencerMessage() pour mettre à jour le paramètre accumulateur accumulateur dans le contrat de pont.

Prix du gaz

Évidemment, les transactions L2 ne peuvent pas être gratuites, car cela entraînerait des attaques DoS. À cela s’ajoutent des coûts de fonctionnement pour le trieur L2 lui-même et des frais généraux pour la soumission des données sur L1. Lorsque les utilisateurs lancent des transactions au sein du réseau de couche 2, la structure des frais de gaz est la suivante :

Le coût de publication des données induit par l’occupation des ressources de la couche 1 provient principalement du lot soumis par le trieur (chaque lot comporte de nombreuses transactions utilisateur), et le coût est finalement partagé à parts égales par les initiateurs de la transaction. L’algorithme de tarification des frais généré par la publication des données est dynamique et le trieur établira le prix en fonction de l’état récent des profits et des pertes, de la taille du lot et du prix actuel du gaz Ethereum.

Le coût supporté par les utilisateurs en raison de l’occupation des ressources de couche 2 fixe une limite de gaz pouvant être traité par seconde pour garantir le fonctionnement stable du système (actuellement Arbitrum One est de 7 millions). Les prix indicatifs du gaz de L1 et L2 sont suivis et ajustés par ArbOS, et les formules ne seront pas décrites ici pour le moment.

Bien que le processus spécifique de calcul du prix du gaz soit relativement compliqué, les utilisateurs n’ont pas besoin de connaître ces détails et peuvent clairement sentir que les frais de transaction Rollup sont beaucoup moins chers que ceux du réseau principal ETH.

Preuve de fraude optimiste

Rappelant ce qui précède, L2 n’est en fait que la projection du lot d’entrée de transaction soumis par le trieur dans la boîte rapide, c’est-à-dire :

Entrées de transaction -> STF -> Sorties d’état. L’entrée a été déterminée et le STF est inchangé, donc le résultat de sortie est également déterminé. ** Le système de preuve de fraude et le protocole Arbitrum Rollup publie la racine de l’état de sortie sur L1 sous la forme de RBlock (alias assertion) et c’est un système de preuve optimiste. **

Sur L1, il y a les données d’entrée publiées par le séquenceur et l’état de sortie publié par le vérificateur. Réfléchissons bien, est-il nécessaire de publier le statut de la couche 2 à la chaîne ?

Étant donné que l’entrée détermine déjà complètement la sortie et que les données d’entrée sont visibles publiquement, la soumission du résultat de sortie - l’état semble redondante ? Mais cette idée ignore la nécessité réelle d’un règlement d’État entre les deux systèmes L1-L2, c’est-à-dire que le comportement de retrait de L2 vers L1 nécessite une preuve de l’État.

Lors de la création du Rollup, l’une des idées principales est de placer la majeure partie du calcul et du stockage sur L2 pour éviter le coût élevé de L1. Cela signifie que L1 ne connaît pas l’état de L2, cela n’aide que L2 Le séquenceur publie les données d’entrée de toutes les transactions, mais n’est pas responsable du calcul de l’état de L2.

**Le comportement de retrait consiste essentiellement à suivre le message cross-chain donné par L2, à débloquer les fonds correspondants du contrat L1, à les transférer sur le compte L1 de l’utilisateur ou à effectuer d’autres tâches. **

À ce stade, le contrat de Layer1 demandera : **Quel est votre statut sur Layer2 et comment prouver que vous possédez réellement les actifs que vous déclarez transférer. À ce stade, l’utilisateur doit fournir la preuve Merkle correspondante, etc. **

Par conséquent, si nous construisons un Rollup sans fonction de retrait, il est théoriquement possible de ne pas synchroniser l’état avec L1, et il n’est pas nécessaire d’avoir un système de preuve d’état tel que la preuve de fraude (bien que cela puisse causer d’autres problèmes). Mais dans des applications réelles, cela n’est évidemment pas réalisable.

Dans la preuve dite optimiste, le contrat ne vérifie pas si l’état de sortie soumis à L1 est correct et croit avec optimisme que tout est exact. **Le système de preuve optimiste supposera qu’il y a au moins un validateur honnête à tout moment. Si un état incorrect se produit, il sera contesté via une preuve de fraude. **

L’avantage de cette conception est qu’il n’est pas nécessaire de vérifier activement chaque RBlock émis à L1 pour éviter de gaspiller du gaz. En fait, pour OPR, il est irréaliste de vérifier chaque assertion, car chaque Rblock contient un ou plusieurs blocs L2, et chaque transaction doit être réexécutée sur L1. Ce n’est pas différent d’exécuter des transactions L2 directement sur L1, ce qui perd la signification de l’expansion de la couche 2.

ZKR n’a pas ce problème, car ZK Proof est simple et n’a besoin de vérifier qu’une très petite preuve. Il n’est pas nécessaire d’exécuter réellement de nombreuses transactions correspondant à la preuve. Par conséquent, ZKR ne fonctionne pas de manière optimiste : chaque fois que le statut est publié, il y aura un contrat Verfier pour la vérification mathématique.

** Bien que la preuve de fraude ne puisse pas être aussi concise qu’une preuve sans connaissance, Arbitrum utilise un processus interactif au tour par tour de « preuve multi-tours en une seule étape ». En fin de compte, ce qui doit être prouvé n’est qu’une seule machine virtuelle. code d’opération, le coût est relativement faible. **

Protocole de cumul

Voyons d’abord comment fonctionne le protocole Rollup, qui est le point d’entrée pour lancer des défis et lancer des preuves.

**Le contrat principal du protocole Rollup est RollupProxy.sol. **Sous réserve d’assurer une structure de données cohérente, une structure à double agent rare est utilisée. Un agent correspond à deux implémentations de RollupUserLogic.sol et RollupAdminLogic.sol. Dans les outils tels que Scan It ne peuvent pas encore être bien analysés.

Il existe également le contrat **ChallengeManager.sol chargé de gérer les défis, et la série de contrats OneStepProver pour déterminer les preuves de fraude. **

(Source photo : site officiel de L2BEAT)

Dans RollupProxy, une série de RBlocks (alias assertions) soumis par différents validateurs sont enregistrés, qui sont les cases de la figure ci-dessous : vert - confirmé, bleu - non confirmé, jaune - falsifié.

**RBlock contient l’état final après l’exécution d’un ou plusieurs blocs L2 depuis le dernier RBlock. **Ces RBlocks forment une chaîne de cumul formelle (notez que le grand livre L2 lui-même est différent). Dans des circonstances optimistes, cette chaîne de cumul ne devrait avoir aucun fork, car un fork signifie qu’un validateur a soumis des blocs de cumul en conflit.

Pour proposer ou accepter une assertion, le vérificateur doit d’abord miser une certaine quantité d’ETH pour l’assertion et devenir un Staker. De cette manière, en cas de contestation ou de preuve de fraude, la garantie du perdant sera perdue, ce qui constitue la base économique permettant de garantir le comportement honnête du vérificateur.

Le bloc bleu n°111 dans le coin inférieur droit de la figure finira par être falsifié car son bloc parent n°104 est erroné (jaune).

**De plus, le vérificateur A a proposé le bloc cumulatif n° 106, mais B n’était pas d’accord et l’a contesté. **

Une fois que B a lancé le défi, le contrat ChallengeManager est chargé de vérifier la répartition des étapes du défi :

  1. La segmentation est un processus dans lequel les deux parties interagissent à tour de rôle. Une partie segmente les données historiques contenues dans un certain bloc de cumul et l’autre partie indique quelle partie du fragment de données pose problème. Un processus similaire à la dichotomie (en fait N/K) qui rétrécit continuellement et progressivement la portée.

  2. Après cela, vous pouvez continuer à localiser la transaction et le résultat qui posent problème, puis la subdiviser en une instruction machine contestée dans la transaction.

  3. Le contrat ChallengeManager vérifie uniquement si les « fragments de données » générés après segmentation des données d’origine sont valides.

  4. Une fois que le challenger et la personne contestée ont localisé l’instruction machine à contester, le challenger appelle oneStepProveution() et envoie une preuve de fraude en une seule étape pour prouver qu’il y a un problème avec le résultat d’exécution de cette instruction machine. **

Preuve en une seule étape

La preuve en une seule étape est au cœur de la preuve de fraude d’Arbitrum. Jetons un coup d’œil à ce que prouve spécifiquement la preuve en une seule étape.

Cela nécessite d’abord de comprendre WAVM, **Wasm Arbitrum Virtual Machine, qui est une machine virtuelle compilée par le module ArbOS et le module principal Geth (client Ethereum). **Étant donné que L2 est complètement différent de L1, le noyau Geth d’origine doit être légèrement modifié et fonctionner avec ArbOS.

Par conséquent, la transition d’état sur L2 est en fait le travail conjoint d’ArbOS+Geth Core.

Le client de nœud d’Arbitrum (séquenceur, validateur, nœud complet, etc.) compile le programme de traitement ArbOS+Geth Core mentionné ci-dessus en code machine natif que l’hôte du nœud peut traiter directement (pour x86/ARM/PC/Mac/etc.).

Si vous modifiez la langue cible obtenue après la compilation en Wasm, vous obtiendrez le WAVM utilisé par le vérificateur lors de la génération des preuves de fraude, et le contrat pour vérifier la preuve en une seule étape simule également les fonctions de la machine virtuelle WAVM.

**Alors pourquoi doit-il être compilé dans le bytecode Wasm lors de la génération de preuves de fraude ? **La raison principale est que pour vérifier le contrat de preuve de fraude en une seule étape, il est nécessaire d’utiliser le contrat intelligent Ethereum pour simuler une machine virtuelle VM capable de traiter un certain ensemble de jeux d’instructions, et WASM est facile à mettre en œuvre. sur le contrat.

Cependant, WASM s’exécute légèrement plus lentement que le code machine natif, de sorte que les nœuds/contrats d’Arbitrum utiliseront WAVM uniquement lors de la génération et de la vérification des preuves de fraude.

**Après les séries précédentes de subdivisions interactives, la preuve en une seule étape prouve enfin l’instruction en une seule étape dans le jeu d’instructions WAVM. **

Comme on peut le voir dans le code ci-dessous, OneStepProofEntry doit d’abord déterminer à quelle catégorie appartient le code d’opération de l’instruction à prouver, puis appeler le prouveur correspondant tel que Mem, Math, etc., pour passer l’instruction en une seule étape dans le contrat du prouveur.

Le résultat final afterHash sera renvoyé au ChallengeManager.Si le hachage est incohérent avec le hachage après l’opération d’instruction enregistrée sur le bloc Rollup, le défi est réussi. S’ils sont cohérents, cela signifie qu’il n’y a aucun problème avec le résultat d’exécution de cette commande enregistré sur le bloc Rollup et que le défi a échoué.

Dans le prochain article, nous analyserons Arbitrum et même le module de contrat qui gère les messages inter-chaînes/fonctions de pontage entre Layer2 et Layer1, et clarifierons davantage comment un véritable Layer2 devrait atteindre la résistance à la censure.

Voir l'original
Avertissement : Les informations contenues dans cette page peuvent provenir de tiers et ne représentent pas les points de vue ou les opinions de Gate. Le contenu de cette page est fourni à titre de référence uniquement et ne constitue pas un conseil financier, d'investissement ou juridique. Gate ne garantit pas l'exactitude ou l'exhaustivité des informations et n'est pas responsable des pertes résultant de l'utilisation de ces informations. Les investissements en actifs virtuels comportent des risques élevés et sont soumis à une forte volatilité des prix. Vous pouvez perdre la totalité du capital investi. Veuillez comprendre pleinement les risques pertinents et prendre des décisions prudentes en fonction de votre propre situation financière et de votre tolérance au risque. Pour plus de détails, veuillez consulter l'avertissement.
Commentaire
0/400
Aucun commentaire