En Ethereum, les ressources étaient jusqu'à récemment limitées et tarifées à l'aide d'une seule ressource appelée "gas". Le gas est une mesure de la quantité d'"effort de calcul" nécessaire pour traiter une transaction ou un bloc donné. Le gas regroupe plusieurs types d'"effort", notamment :
Par exemple, cette transactionque j'ai envoyé a coûté un total de 47 085 d'essence. Cela est réparti entre (i) un coût de base de 21000 d'essence, (ii) 1556 d'essence pour les octets dans les données d'appel incluses dans la transaction (iii) 16500 d'essence pour la lecture et l'écriture dans le stockage, (iv) 2149 d'essence pour en fairejournal, et le reste pour l'exécution EVM. Les frais de transaction qu'un utilisateur doit payer sont proportionnels au gas consommé par la transaction. Un bloc peut contenir jusqu'à un maximum de 30 millions de gas, et les prix du gas sont constamment ajustés via le @vbuterin/eip-1559-faq">Mécanisme de ciblage EIP-1559, garantissant qu'en moyenne, les blocs contiennent 15 millions de gaz.
Cette approche a une efficacité majeure : parce que tout est fusionné en une ressource virtuelle, elle conduit à une conception de marché très simple. Optimiser une transaction pour minimiser les coûts est facile, optimiser un bloc pour collecter les frais les plus élevés possibles est relativement facile (à l'exceptionMEV) et il n'y a pas d'incitations étranges qui encouragent certaines transactions à se regrouper avec d'autres transactions pour économiser sur les frais.
Mais cette approche comporte également une inefficacité majeure : elle considère que les différentes ressources sont mutuellement convertibles, alors que les limites sous-jacentes réelles de ce que le réseau peut gérer ne le sont pas. Une façon de comprendre ce problème est d'examiner ce diagramme :
La limite de gaz impose une contrainte de
𝑥1∗𝑑𝑎𝑡𝑎+𝑥2∗𝑐𝑜𝑚𝑝𝑢𝑡𝑎𝑡𝑖𝑜𝑛<𝑁
. La contrainte de sécurité sous-jacente réelle est souvent plus proche de
max(x1*data, x2*compotation) . Cette disparité conduit à ce que la limite de gaz exclue inutilement des blocs réellement sûrs, ou accepte des blocs réellement dangereux, ou une combinaison des deux. S'il y a n les ressources qui ont des limites de sécurité distinctes, alors le gaz unidimensionnel réduit vraisemblablement le débit jusqu'à un facteur de n Pour cette raison, il existe depuis longtemps un intérêt pour le concept de gaz multidimensionnel, et avec EIP-4844nous avons en fait un système de tarification multi-dimensionnel qui fonctionne sur Ethereum aujourd'hui. Ce post explore les avantages de cette approche et les perspectives de son extension. Au début de cette année, le bloc moyen était 150 ko en taille. Une grande partie de cette taille est constituée de données de rollup : protocoles de couche 2stocker des données sur la chaîne pour la sécurité. Ces données étaient coûteuses : même si les transactions sur les rollups coûteraient environ 5 à 10 fois moins que les transactions correspondantes sur l'Ethereum L1, même ce coût était trop élevé pour de nombreux cas d'utilisation. Pourquoi ne pas réduire le coût en gaz des données d'appel (actuellement 16 gaz par octet non nul et 4 gaz par octet nul), pour rendre les rollups moins chers ? Nousavons-nous fait cela avant, nous pourrions le refaire. La réponse ici est : la taille maximale d'un bloc était 30,000,00016=1,875,000 des octets non nuls, et le réseau peut déjà à peine gérer des blocs de cette taille. Réduire les coûts de 4x supplémentaires porterait le maximum à 7,5 Mo, ce qui serait un énorme risque pour la sécurité. Ce problème a fini par être résolu en introduisant un espace de données compatible avec le rollup appelé « blobs » dans chaque bloc. Les deux ressources ont des prix et des limites séparés : après le hard fork de Dencun, un bloc Ethereum peut contenir au maximum (i) 30 millions de gas, et (ii) 6 blobs, pouvant contenir environ 125 ko de données d'appel chacun. Les deux ressources ont des prix séparés, ajustés parmécanismes de tarification similaires à l'EIP-1559, ciblant une utilisation moyenne de 15 millions de gas et 3 blobs par bloc. En conséquence, les rollups sont devenus 100 fois moins chers, le volume des transactions sur les rollups a augmenté de plus de 3 fois, et la taille de bloc maximale théorique n'a été augmentée que légèrement : passant d'environ 1,9 Mo à environ 2,6 Mo. Frais de transaction sur les rollups, grâce à growthepie.xyz. La fourchette Dencun, qui a introduit des blobs avec une tarification multidimensionnelle, a eu lieu le 13 mars 2024. Dans un avenir proche, un problème similaire se posera concernant les preuves de stockage pour les clients sans état. Les clients sans état sont un nouveau type de client qui pourra vérifier la chaîne sans stocker beaucoup ou aucune donnée localement. Les clients sans état le font en acceptant des preuves des parties spécifiques de l'état d'Ethereum que les transactions dans ce bloc doivent toucher. Un client sans état reçoit un bloc, accompagné de preuves prouvant les valeurs actuelles dans les parties spécifiques de l'état (par exemple, soldes des comptes, code, stockage) touchées par l'exécution du bloc. Cela permet à un nœud de vérifier un bloc sans avoir de stockage en lui-même. Le coût de lecture de stockage est de 2100-2600 gaz selon le type de lecture, et les écritures de stockage coûtent plus cher. En moyenne, un bloc effectue environ 1000 lectures et écritures de stockage (y compris les vérifications de solde ETH, les appels SSTORE et SLOAD, la lecture de code de contrat et d'autres opérations). Le maximum théorique, cependant, est 30,000,0002,100=14,285 lit. Un client sans état charge directement proportionnel à ce nombre. Aujourd'hui, le plan est de soutenir les clients sans état en déplaçant la conception de l'arbre d'état d'Ethereum dearbres de Merkle PatriciaàArbres VerkleCependant, les arbres Verkle ne sont pas résistants aux attaques quantiques et ne sont pas optimaux pour les nouvelles vagues de systèmes de démonstration STARK. Par conséquence, de nombreuses personnes s'intéressent à soutenir les clients sans état grâce aux arbres de Merkle binaires et STARKsau lieu de - soit en sautant complètement Verkle, soit en effectuant une mise à niveau quelques années après la transition vers Verkle une fois que les STARKs seront plus matures. Les preuves STARK des branches d'arbre de hachage binaire ont de nombreux avantages, mais elles ont le point faible clé que les preuves prennent beaucoup de temps à générer: tandis que arbres Verklepeut prouverplus de cent mille valeurs par seconde, les STARK basés sur le hash peuvent généralement prouver seulement quelques milliers de hachages par seconde, et prouver chaque valeur nécessite une “branche” contenant de nombreux hachages. Étant donné les chiffres qui sont projetés aujourd'hui à partir de systèmes de preuve hyper-optimisés tels que BiniusetPlonky3et des hachages spécialisés commeVision-Mark-32, il semble probable que nous serons pendant un certain temps dans un régime où il est pratique de prouver 1 000 valeurs en moins d'une seconde, mais pas 14 285 valeurs. Les blocs moyens seraient acceptables, mais les blocs du pire des cas, potentiellement publiés par un attaquant, pourraient rompre le réseau. La façon "par défaut" dont nous avons géré un tel scénario est la revalorisation : rendre la lecture du stockage plus coûteuse pour réduire le maximum par bloc à quelque chose de plus sûr. Cependant, nous avonsdéjàfaitceci beaucoup fois, et cela rendrait trop d'applications trop coûteuses pour refaire cela. Une meilleure approche serait le gaz multidimensionnel : limiter et facturer l'accès au stockage séparément, en maintenant l'utilisation moyenne à 1 000 accès au stockage par bloc, mais en fixant une limite par bloc de par exemple 2 000. Une autre ressource qui vaut la peine d'être prise en compte est la croissance de la taille de l'état : les opérations qui augmentent la taille de l'état d'Ethereum, que les nœuds complets devront conserver à partir de ce moment-là. La propriété unique de la croissance de la taille de l'état est que la justification de sa limitation provient entièrement d'une utilisation soutenue à long terme, et non de pics. Par conséquent, il peut être utile d'ajouter une dimension de gaz distincte pour les opérations augmentant la taille de l'état (par exemple, SSTORE de zéro à non nul, création de contrat), mais avec un objectif différent : nous pourrions fixer un prix flottant pour cibler une utilisation moyenne spécifique, mais ne fixer aucune limite par bloc du tout. Cela montre l'une des propriétés puissantes du gaz multidimensionnel : il nous permet de poser séparément les questions de (i) quel est l'usage moyen idéal, et (ii) quel est l'usage maximal par bloc sûr, pour chaque ressource. Au lieu de fixer les prix du gaz en fonction des maximums par bloc, et de laisser l'usage moyen suivre, nous avons 2𝑛 degrés de liberté à définir 2𝑛 paramètres, ajustant chacun en fonction de ce qui est sûr pour le réseau. Des situations plus complexes, comme celles où deux ressources présentent des considérations de sécurité partiellement additives, pourraient être gérées en faisant en sorte qu'un opcode ou un coût de ressource nécessite une certaine quantité de plusieurs types de gaz (par exemple, un SSTORE de zéro à non nul pourrait coûter 5000 gaz de preuve de client sans état et 20000 gaz d'expansion de stockage). Laissez 𝑥1 être le coût en gaz des données et 𝑥2 être le coût en gaz de la computation, donc dans un système de gaz unidimensionnel, nous pouvons écrire le coût en gaz d'une transaction: 𝑔𝑎𝑠=𝑥1∗𝑑𝑎𝑡𝑎+𝑥2∗𝑐𝑜𝑚𝑝𝑢𝑡𝑎𝑡𝑖𝑜𝑛 Dans ce schéma, nous définissons plutôt le coût en gaz d'une transaction comme suit : 𝑔𝑎𝑠=𝑚𝑎𝑥(𝑥1∗𝑑𝑎𝑡𝑎,𝑥2∗𝑐𝑜𝑚𝑝𝑢𝑡𝑎𝑡𝑖𝑜𝑛) C'est-à-dire, au lieu qu'une transaction soit facturée pour les données plus la computation, la transaction est facturée en fonction de la ressource des deux qu'elle consomme le plus. Cela peut facilement être étendu pour couvrir plus de dimensions (par ex. max(…,x3*stockage_acces) ). Il devrait être facile de voir comment cela améliore le débit tout en préservant la sécurité. La quantité maximale théorique de données dans un bloc est toujours 𝐺𝐴𝑆𝐿𝐼𝑀𝐼𝑇𝑥1 , exactement la même que dans le schéma de gaz unidimensionnel. De même, la quantité maximale théorique de calcul est 𝐺𝐴𝑆𝐿𝐼𝑀𝐼𝑇𝑥2 , à nouveau exactement la même que dans le schéma de gaz unidimensionnel. Cependant, le coût en gaz de toute transaction qui consomme à la fois des données et des calculs diminue. C'est approximativement le schéma utilisé dans la propositionEIP-7623, pour réduire la taille maximale du bloc tout en augmentant davantage le nombre de blocs. Le mécanisme précis dans l'EIP-7623 est légèrement plus compliqué : il conserve le prix actuel des données d'appel à 16 gaz par octet, mais il ajoute un « prix plancher » de 48 gaz par octet ; une transaction paie le montant le plus élevé entre (16 bytes + execution_gas) et (48 bytes). En conséquence, l'EIP-7623 réduit la charge utile théorique maximale des transactions dans un bloc de ~1,9 Mo à ~0,6 Mo, tout en laissant les coûts de la plupart des applications inchangés. L'avantage de cette approche est qu'il s'agit d'un changement très mineur par rapport au schéma de gaz unidimensionnel actuel, il est donc très facile à mettre en œuvre. Il y a deux inconvénients: Je soutiendrais qu'une règle de style EIP-7623, à la fois pour les données d'appel de transaction et pour d'autres ressources, peut apporter des avantages suffisamment importants pour en valoir la peine malgré ces inconvénients. Cependant, si et quand nous sommes prêts à fournir l'effort de développement (nettement plus élevé), il existe une approche plus idéale. Commençons par rappeler comment fonctionne le EIP-1559 “classique”. Nous nous concentrerons sur la version introduite dans le EIP-4844 pour les blobs, car elle est mathématiquement plus élégante. Nous suivons un paramètre, excess_blobs. Pendant chaque bloc, nous définissons : excès_blobs <— max(excès_blobs + len(block.blobs) - TARGET, 0) Où TARGET = 3. C'est-à-dire, si un bloc a plus de blobs que la cible, excess_blobs augmente, et si un bloc a moins que la cible, il diminue. Nous définissons ensuite blob_basefee = exp(excess_blobs / 25.47), où exp est une approximation de la fonction exponentielle. 𝑒𝑥𝑝(𝑥)=2.71828𝑥 . C'est-à-dire que chaque fois que excess_blobs augmente d'environ 25, le basefee des blobs augmente d'un facteur d'environ 2,7. Si les blobs deviennent trop chers, l'utilisation moyenne diminue et excess_blobs commence à diminuer, faisant automatiquement baisser le prix à nouveau. Le prix d'un blob s'ajuste constamment pour s'assurer qu'en moyenne, les blocs sont à moitié pleins - c'est-à-dire qu'ils contiennent en moyenne 3 blobs chacun. S'il y a une augmentation à court terme de l'utilisation, alors la limite entre en jeu : chaque bloc ne peut contenir qu'un maximum de 6 blobs, et dans de telles circonstances, les transactions peuvent rivaliser entre elles en surenchérissant sur leurs frais de priorité. Dans le cas normal, cependant, chaque blob doit seulement payer le blob_basefee plus des frais de priorité supplémentaires minimes comme incitation pour être inclus. Ce type de tarification existait dans Ethereum pour le gaz depuis des années : un mécanisme très similaire a été introduit avec@vbuterin/eip-1559-faq">EIP-1559 de retour en 2020. Avec l'EIP-4844, nous avons maintenant deux prix flottants séparés pour le gas et pour les blobs. Frais de base de gaz sur une heure le 08-05-2024, en gwei. Source : ultrasound.money. En principe, nous pourrions ajouter des frais supplémentaires de stockage en lecture, et d'autres types d'opérations indépendantes, bien que avec une réserve que je développerai dans la section suivante. Pour les utilisateurs, l’expérience est remarquablement similaire à celle d’aujourd’hui : au lieu de payer un seul frais de base, vous en payez deux, mais votre portefeuille peut vous en faire abstraction et vous montrer simplement les frais attendus et les frais maximums que vous pouvez vous attendre à payer. Pour les constructeurs de blocs, la plupart du temps, la stratégie optimale est la même qu'aujourd'hui : inclure tout ce qui est valide. La plupart des blocs ne sont pas pleins - nidans le gaznidans les blobsLe cas difficile est lorsque le gaz ou les blobs sont suffisants pour dépasser la limite de bloc, et que le constructeur doit potentiellement résoudre unProblème de sac à dos multidimensionnelpour maximiser son profit. Cependant, même s'il existe de très bons algorithmes d'approximation, les gains de la création d'algorithmes propriétaires pour optimiser les profits dans ce cas sont bien inférieurs aux gains obtenus en faisant de même avec MEV. Pour les développeurs, le principal défi est la nécessité de repenser les fonctionnalités de l'EVM et de son infrastructure environnante, conçues autour d'un prix et d'une limite uniques aujourd'hui, en une conception qui prend en compte plusieurs prix et plusieurs limites. Un problème pour les développeurs d'applications est que l'optimisation devient légèrement plus difficile : dans certains cas, vous ne pouvez plus dire de manière non équivoque que A est plus efficace que B, car si A utilise plus de calldata mais que B utilise plus d'exécution, alors A pourrait être moins cher lorsque calldata est bon marché et plus cher lorsque calldata est cher. Cependant, les développeurs pourraient tout de même obtenir des résultats raisonnablement bons en optimisant en fonction des prix moyens historiques à long terme. Il y a un problème qui n'est pas apparu avec les blobs, et n'apparaîtra pas avec EIP-7623 ou même une implémentation de tarification multidimensionnelle "complète" pour calldata, mais apparaîtra si nous essayons de tarifer séparément les accès à l'état, ou toute autre ressource: les limites de gaz dans les sous-appels. Les limites de gaz dans l'EVM existent en deux endroits. Premièrement, chaque transaction définit une limite de gaz, qui limite le montant total de gaz pouvant être utilisé dans cette transaction. Deuxièmement, lorsqu'un contrat appelle un autre contrat, l'appel peut définir sa propre limite de gaz. Cela permet aux contrats d'appeler d'autres contrats en lesquels ils n'ont pas confiance, tout en garantissant qu'ils auront encore du gaz pour effectuer d'autres calculs après cet appel. Une trace d'une transaction d'abstraction de compte, où un compte appelle un autre compte et ne donne au destinataire qu'une quantité limitée de gaz, pour s'assurer que l'appel externe puisse continuer à s'exécuter même si le destinataire consomme tout le gaz qui lui a été attribué. Le défi est le suivant : rendre le gaz multidimensionnel entre différents types d'exécution semble nécessiter des sous-appels pour fournir plusieurs limites pour chaque type de gaz, ce qui nécessiterait un changement vraiment profond de l'EVM et ne serait pas compatible avec les applications existantes. C'est une des raisons pour lesquelles les propositions de gaz multidimensionnel s'arrêtent souvent à deux dimensions : les données et l'exécution. Les données (qu'il s'agisse de l'appel de transaction ou des blocs) ne sont attribuées qu'en dehors de l'EVM, de sorte que rien à l'intérieur de l'EVM n'a besoin de changer pour que l'appel de transaction ou les blocs soient tarifés séparément. Nous pouvons envisager une solution de style “EIP-7623” à ce problème. Voici une mise en œuvre simple : pendant l'exécution, facturer 4 fois plus pour les opérations de stockage ; pour simplifier l'analyse, disons 10000 gas par opération de stockage. À la fin de la transaction, rembourser min(7500 * opérations_de_stockage, gas_d_execution). Le résultat serait qu'après déduction du remboursement, un utilisateur est facturé : execution_gas + 10000 opérations de stockage - min(7500 opérations de stockage, gas d'exécution) Ce qui équivaut à : max(execution_gas + 2500 opérations de stockage, 10000storage_operations) Cela reflète la structure de l'EIP-7623. Une autre façon de le faire est de suivre les opérations de stockage et le gaz d'exécution en temps réel, et de facturer soit 2500, soit 10000 en fonction de la quantité maximale (gaz d'exécution + 2500)opérations de stockage, 10000Le coût en gaz des opérations de stockage) augmente au moment où l'opcode est appelé. Cela évite le besoin pour les transactions de sur-allouer du gaz qu'elles récupéreront principalement via des remboursements. Nous n'obtenons pas d'autorisation détaillée pour les sous-appels : un sous-appel pourrait consommer toute l'"allocation" d'une transaction pour des opérations de stockage bon marché. Mais nous obtenons quelque chose de suffisamment bon, où un contrat effectuant un sous-appel peut définir une limite et s'assurer qu'une fois l'exécution du sous-appel terminée, l'appel principal a toujours suffisamment de gaz pour effectuer tout post-traitement nécessaire. La solution de tarification la plus simple et complète que je puisse imaginer est la suivante : nous considérons les limites de gaz des sous-appels comme étant proportionnelles. C'est-à-dire, supposons qu'il y en ait 𝑘 différents types d'exécution, et chaque transaction définit une limite multidimensionnelle 𝐿1…𝐿𝑘 . Suppose that, at the current point in execution, the remaining gas is 𝑔1…𝑔𝑘 Supposons qu'un opcode CALL soit appelé, avec une limite de gas de sous-appel 𝑆 . Laissez 𝑠1=𝑆 , et ensuite 𝑠2=𝑠1𝑔1∗𝑔2 , 𝑠3=𝑠1𝑔1∗𝑔3 , et ainsi de suite. C’est-à-dire que nous traitons le premier type de gaz (de manière réaliste, l’exécution de la machine virtuelle) comme étant une sorte d'« unité de compte » privilégiée, puis nous affectons les autres types de gaz afin que le sous-appel obtienne le même pourcentage de gaz disponible pour chaque type. C’est un peu moche, mais cela maximise la rétrocompatibilité. Si nous voulons rendre le schéma plus « neutre » entre les différents types de gaz, au prix de sacrifier la rétrocompatibilité, nous pourrions simplement faire en sorte que le paramètre limite de gaz sous-call représente une fraction (par exemple. [1… 63] / 64) du gaz restant dans le contexte actuel). Dans l'un ou l'autre cas, il convient cependant de souligner que dès que vous commencez à introduire un gaz d'exécution multidimensionnel, le niveau inhérent de la laideur augmente, et il semble difficile d'éviter cela. Ainsi, notre tâche est de faire un compromis compliqué : acceptons-nous une certaine laideur au niveau de l'EVM, afin de débloquer en toute sécurité des gains significatifs de scalabilité L1, et si c'est le cas, quelle proposition spécifique fonctionne le mieux pour l'économie du protocole et les développeurs d'applications ? Il est fort probable que ce ne soit ni l'un ni l'autre des propositions que j'ai mentionnées ci-dessus, et il reste encore de la place pour trouver quelque chose de plus élégant et de meilleur.Blobs: gaz multidimensionnel dans Dencun
Clients multi-dimensionnels de gaz et sans état
Gaz multidimensionnel plus généralement
Par transaction max : le moyen plus faible mais plus simple d'obtenir du gaz multidimensionnel
Multidimensionnel EIP-1559: la stratégie plus difficile mais idéale
Tarification multidimensionnelle, l'EVM et les sous-appels
Avertissement:
Partilhar
Conteúdos
En Ethereum, les ressources étaient jusqu'à récemment limitées et tarifées à l'aide d'une seule ressource appelée "gas". Le gas est une mesure de la quantité d'"effort de calcul" nécessaire pour traiter une transaction ou un bloc donné. Le gas regroupe plusieurs types d'"effort", notamment :
Par exemple, cette transactionque j'ai envoyé a coûté un total de 47 085 d'essence. Cela est réparti entre (i) un coût de base de 21000 d'essence, (ii) 1556 d'essence pour les octets dans les données d'appel incluses dans la transaction (iii) 16500 d'essence pour la lecture et l'écriture dans le stockage, (iv) 2149 d'essence pour en fairejournal, et le reste pour l'exécution EVM. Les frais de transaction qu'un utilisateur doit payer sont proportionnels au gas consommé par la transaction. Un bloc peut contenir jusqu'à un maximum de 30 millions de gas, et les prix du gas sont constamment ajustés via le @vbuterin/eip-1559-faq">Mécanisme de ciblage EIP-1559, garantissant qu'en moyenne, les blocs contiennent 15 millions de gaz.
Cette approche a une efficacité majeure : parce que tout est fusionné en une ressource virtuelle, elle conduit à une conception de marché très simple. Optimiser une transaction pour minimiser les coûts est facile, optimiser un bloc pour collecter les frais les plus élevés possibles est relativement facile (à l'exceptionMEV) et il n'y a pas d'incitations étranges qui encouragent certaines transactions à se regrouper avec d'autres transactions pour économiser sur les frais.
Mais cette approche comporte également une inefficacité majeure : elle considère que les différentes ressources sont mutuellement convertibles, alors que les limites sous-jacentes réelles de ce que le réseau peut gérer ne le sont pas. Une façon de comprendre ce problème est d'examiner ce diagramme :
La limite de gaz impose une contrainte de
𝑥1∗𝑑𝑎𝑡𝑎+𝑥2∗𝑐𝑜𝑚𝑝𝑢𝑡𝑎𝑡𝑖𝑜𝑛<𝑁
. La contrainte de sécurité sous-jacente réelle est souvent plus proche de
max(x1*data, x2*compotation) . Cette disparité conduit à ce que la limite de gaz exclue inutilement des blocs réellement sûrs, ou accepte des blocs réellement dangereux, ou une combinaison des deux. S'il y a n les ressources qui ont des limites de sécurité distinctes, alors le gaz unidimensionnel réduit vraisemblablement le débit jusqu'à un facteur de n Pour cette raison, il existe depuis longtemps un intérêt pour le concept de gaz multidimensionnel, et avec EIP-4844nous avons en fait un système de tarification multi-dimensionnel qui fonctionne sur Ethereum aujourd'hui. Ce post explore les avantages de cette approche et les perspectives de son extension. Au début de cette année, le bloc moyen était 150 ko en taille. Une grande partie de cette taille est constituée de données de rollup : protocoles de couche 2stocker des données sur la chaîne pour la sécurité. Ces données étaient coûteuses : même si les transactions sur les rollups coûteraient environ 5 à 10 fois moins que les transactions correspondantes sur l'Ethereum L1, même ce coût était trop élevé pour de nombreux cas d'utilisation. Pourquoi ne pas réduire le coût en gaz des données d'appel (actuellement 16 gaz par octet non nul et 4 gaz par octet nul), pour rendre les rollups moins chers ? Nousavons-nous fait cela avant, nous pourrions le refaire. La réponse ici est : la taille maximale d'un bloc était 30,000,00016=1,875,000 des octets non nuls, et le réseau peut déjà à peine gérer des blocs de cette taille. Réduire les coûts de 4x supplémentaires porterait le maximum à 7,5 Mo, ce qui serait un énorme risque pour la sécurité. Ce problème a fini par être résolu en introduisant un espace de données compatible avec le rollup appelé « blobs » dans chaque bloc. Les deux ressources ont des prix et des limites séparés : après le hard fork de Dencun, un bloc Ethereum peut contenir au maximum (i) 30 millions de gas, et (ii) 6 blobs, pouvant contenir environ 125 ko de données d'appel chacun. Les deux ressources ont des prix séparés, ajustés parmécanismes de tarification similaires à l'EIP-1559, ciblant une utilisation moyenne de 15 millions de gas et 3 blobs par bloc. En conséquence, les rollups sont devenus 100 fois moins chers, le volume des transactions sur les rollups a augmenté de plus de 3 fois, et la taille de bloc maximale théorique n'a été augmentée que légèrement : passant d'environ 1,9 Mo à environ 2,6 Mo. Frais de transaction sur les rollups, grâce à growthepie.xyz. La fourchette Dencun, qui a introduit des blobs avec une tarification multidimensionnelle, a eu lieu le 13 mars 2024. Dans un avenir proche, un problème similaire se posera concernant les preuves de stockage pour les clients sans état. Les clients sans état sont un nouveau type de client qui pourra vérifier la chaîne sans stocker beaucoup ou aucune donnée localement. Les clients sans état le font en acceptant des preuves des parties spécifiques de l'état d'Ethereum que les transactions dans ce bloc doivent toucher. Un client sans état reçoit un bloc, accompagné de preuves prouvant les valeurs actuelles dans les parties spécifiques de l'état (par exemple, soldes des comptes, code, stockage) touchées par l'exécution du bloc. Cela permet à un nœud de vérifier un bloc sans avoir de stockage en lui-même. Le coût de lecture de stockage est de 2100-2600 gaz selon le type de lecture, et les écritures de stockage coûtent plus cher. En moyenne, un bloc effectue environ 1000 lectures et écritures de stockage (y compris les vérifications de solde ETH, les appels SSTORE et SLOAD, la lecture de code de contrat et d'autres opérations). Le maximum théorique, cependant, est 30,000,0002,100=14,285 lit. Un client sans état charge directement proportionnel à ce nombre. Aujourd'hui, le plan est de soutenir les clients sans état en déplaçant la conception de l'arbre d'état d'Ethereum dearbres de Merkle PatriciaàArbres VerkleCependant, les arbres Verkle ne sont pas résistants aux attaques quantiques et ne sont pas optimaux pour les nouvelles vagues de systèmes de démonstration STARK. Par conséquence, de nombreuses personnes s'intéressent à soutenir les clients sans état grâce aux arbres de Merkle binaires et STARKsau lieu de - soit en sautant complètement Verkle, soit en effectuant une mise à niveau quelques années après la transition vers Verkle une fois que les STARKs seront plus matures. Les preuves STARK des branches d'arbre de hachage binaire ont de nombreux avantages, mais elles ont le point faible clé que les preuves prennent beaucoup de temps à générer: tandis que arbres Verklepeut prouverplus de cent mille valeurs par seconde, les STARK basés sur le hash peuvent généralement prouver seulement quelques milliers de hachages par seconde, et prouver chaque valeur nécessite une “branche” contenant de nombreux hachages. Étant donné les chiffres qui sont projetés aujourd'hui à partir de systèmes de preuve hyper-optimisés tels que BiniusetPlonky3et des hachages spécialisés commeVision-Mark-32, il semble probable que nous serons pendant un certain temps dans un régime où il est pratique de prouver 1 000 valeurs en moins d'une seconde, mais pas 14 285 valeurs. Les blocs moyens seraient acceptables, mais les blocs du pire des cas, potentiellement publiés par un attaquant, pourraient rompre le réseau. La façon "par défaut" dont nous avons géré un tel scénario est la revalorisation : rendre la lecture du stockage plus coûteuse pour réduire le maximum par bloc à quelque chose de plus sûr. Cependant, nous avonsdéjàfaitceci beaucoup fois, et cela rendrait trop d'applications trop coûteuses pour refaire cela. Une meilleure approche serait le gaz multidimensionnel : limiter et facturer l'accès au stockage séparément, en maintenant l'utilisation moyenne à 1 000 accès au stockage par bloc, mais en fixant une limite par bloc de par exemple 2 000. Une autre ressource qui vaut la peine d'être prise en compte est la croissance de la taille de l'état : les opérations qui augmentent la taille de l'état d'Ethereum, que les nœuds complets devront conserver à partir de ce moment-là. La propriété unique de la croissance de la taille de l'état est que la justification de sa limitation provient entièrement d'une utilisation soutenue à long terme, et non de pics. Par conséquent, il peut être utile d'ajouter une dimension de gaz distincte pour les opérations augmentant la taille de l'état (par exemple, SSTORE de zéro à non nul, création de contrat), mais avec un objectif différent : nous pourrions fixer un prix flottant pour cibler une utilisation moyenne spécifique, mais ne fixer aucune limite par bloc du tout. Cela montre l'une des propriétés puissantes du gaz multidimensionnel : il nous permet de poser séparément les questions de (i) quel est l'usage moyen idéal, et (ii) quel est l'usage maximal par bloc sûr, pour chaque ressource. Au lieu de fixer les prix du gaz en fonction des maximums par bloc, et de laisser l'usage moyen suivre, nous avons 2𝑛 degrés de liberté à définir 2𝑛 paramètres, ajustant chacun en fonction de ce qui est sûr pour le réseau. Des situations plus complexes, comme celles où deux ressources présentent des considérations de sécurité partiellement additives, pourraient être gérées en faisant en sorte qu'un opcode ou un coût de ressource nécessite une certaine quantité de plusieurs types de gaz (par exemple, un SSTORE de zéro à non nul pourrait coûter 5000 gaz de preuve de client sans état et 20000 gaz d'expansion de stockage). Laissez 𝑥1 être le coût en gaz des données et 𝑥2 être le coût en gaz de la computation, donc dans un système de gaz unidimensionnel, nous pouvons écrire le coût en gaz d'une transaction: 𝑔𝑎𝑠=𝑥1∗𝑑𝑎𝑡𝑎+𝑥2∗𝑐𝑜𝑚𝑝𝑢𝑡𝑎𝑡𝑖𝑜𝑛 Dans ce schéma, nous définissons plutôt le coût en gaz d'une transaction comme suit : 𝑔𝑎𝑠=𝑚𝑎𝑥(𝑥1∗𝑑𝑎𝑡𝑎,𝑥2∗𝑐𝑜𝑚𝑝𝑢𝑡𝑎𝑡𝑖𝑜𝑛) C'est-à-dire, au lieu qu'une transaction soit facturée pour les données plus la computation, la transaction est facturée en fonction de la ressource des deux qu'elle consomme le plus. Cela peut facilement être étendu pour couvrir plus de dimensions (par ex. max(…,x3*stockage_acces) ). Il devrait être facile de voir comment cela améliore le débit tout en préservant la sécurité. La quantité maximale théorique de données dans un bloc est toujours 𝐺𝐴𝑆𝐿𝐼𝑀𝐼𝑇𝑥1 , exactement la même que dans le schéma de gaz unidimensionnel. De même, la quantité maximale théorique de calcul est 𝐺𝐴𝑆𝐿𝐼𝑀𝐼𝑇𝑥2 , à nouveau exactement la même que dans le schéma de gaz unidimensionnel. Cependant, le coût en gaz de toute transaction qui consomme à la fois des données et des calculs diminue. C'est approximativement le schéma utilisé dans la propositionEIP-7623, pour réduire la taille maximale du bloc tout en augmentant davantage le nombre de blocs. Le mécanisme précis dans l'EIP-7623 est légèrement plus compliqué : il conserve le prix actuel des données d'appel à 16 gaz par octet, mais il ajoute un « prix plancher » de 48 gaz par octet ; une transaction paie le montant le plus élevé entre (16 bytes + execution_gas) et (48 bytes). En conséquence, l'EIP-7623 réduit la charge utile théorique maximale des transactions dans un bloc de ~1,9 Mo à ~0,6 Mo, tout en laissant les coûts de la plupart des applications inchangés. L'avantage de cette approche est qu'il s'agit d'un changement très mineur par rapport au schéma de gaz unidimensionnel actuel, il est donc très facile à mettre en œuvre. Il y a deux inconvénients: Je soutiendrais qu'une règle de style EIP-7623, à la fois pour les données d'appel de transaction et pour d'autres ressources, peut apporter des avantages suffisamment importants pour en valoir la peine malgré ces inconvénients. Cependant, si et quand nous sommes prêts à fournir l'effort de développement (nettement plus élevé), il existe une approche plus idéale. Commençons par rappeler comment fonctionne le EIP-1559 “classique”. Nous nous concentrerons sur la version introduite dans le EIP-4844 pour les blobs, car elle est mathématiquement plus élégante. Nous suivons un paramètre, excess_blobs. Pendant chaque bloc, nous définissons : excès_blobs <— max(excès_blobs + len(block.blobs) - TARGET, 0) Où TARGET = 3. C'est-à-dire, si un bloc a plus de blobs que la cible, excess_blobs augmente, et si un bloc a moins que la cible, il diminue. Nous définissons ensuite blob_basefee = exp(excess_blobs / 25.47), où exp est une approximation de la fonction exponentielle. 𝑒𝑥𝑝(𝑥)=2.71828𝑥 . C'est-à-dire que chaque fois que excess_blobs augmente d'environ 25, le basefee des blobs augmente d'un facteur d'environ 2,7. Si les blobs deviennent trop chers, l'utilisation moyenne diminue et excess_blobs commence à diminuer, faisant automatiquement baisser le prix à nouveau. Le prix d'un blob s'ajuste constamment pour s'assurer qu'en moyenne, les blocs sont à moitié pleins - c'est-à-dire qu'ils contiennent en moyenne 3 blobs chacun. S'il y a une augmentation à court terme de l'utilisation, alors la limite entre en jeu : chaque bloc ne peut contenir qu'un maximum de 6 blobs, et dans de telles circonstances, les transactions peuvent rivaliser entre elles en surenchérissant sur leurs frais de priorité. Dans le cas normal, cependant, chaque blob doit seulement payer le blob_basefee plus des frais de priorité supplémentaires minimes comme incitation pour être inclus. Ce type de tarification existait dans Ethereum pour le gaz depuis des années : un mécanisme très similaire a été introduit avec@vbuterin/eip-1559-faq">EIP-1559 de retour en 2020. Avec l'EIP-4844, nous avons maintenant deux prix flottants séparés pour le gas et pour les blobs. Frais de base de gaz sur une heure le 08-05-2024, en gwei. Source : ultrasound.money. En principe, nous pourrions ajouter des frais supplémentaires de stockage en lecture, et d'autres types d'opérations indépendantes, bien que avec une réserve que je développerai dans la section suivante. Pour les utilisateurs, l’expérience est remarquablement similaire à celle d’aujourd’hui : au lieu de payer un seul frais de base, vous en payez deux, mais votre portefeuille peut vous en faire abstraction et vous montrer simplement les frais attendus et les frais maximums que vous pouvez vous attendre à payer. Pour les constructeurs de blocs, la plupart du temps, la stratégie optimale est la même qu'aujourd'hui : inclure tout ce qui est valide. La plupart des blocs ne sont pas pleins - nidans le gaznidans les blobsLe cas difficile est lorsque le gaz ou les blobs sont suffisants pour dépasser la limite de bloc, et que le constructeur doit potentiellement résoudre unProblème de sac à dos multidimensionnelpour maximiser son profit. Cependant, même s'il existe de très bons algorithmes d'approximation, les gains de la création d'algorithmes propriétaires pour optimiser les profits dans ce cas sont bien inférieurs aux gains obtenus en faisant de même avec MEV. Pour les développeurs, le principal défi est la nécessité de repenser les fonctionnalités de l'EVM et de son infrastructure environnante, conçues autour d'un prix et d'une limite uniques aujourd'hui, en une conception qui prend en compte plusieurs prix et plusieurs limites. Un problème pour les développeurs d'applications est que l'optimisation devient légèrement plus difficile : dans certains cas, vous ne pouvez plus dire de manière non équivoque que A est plus efficace que B, car si A utilise plus de calldata mais que B utilise plus d'exécution, alors A pourrait être moins cher lorsque calldata est bon marché et plus cher lorsque calldata est cher. Cependant, les développeurs pourraient tout de même obtenir des résultats raisonnablement bons en optimisant en fonction des prix moyens historiques à long terme. Il y a un problème qui n'est pas apparu avec les blobs, et n'apparaîtra pas avec EIP-7623 ou même une implémentation de tarification multidimensionnelle "complète" pour calldata, mais apparaîtra si nous essayons de tarifer séparément les accès à l'état, ou toute autre ressource: les limites de gaz dans les sous-appels. Les limites de gaz dans l'EVM existent en deux endroits. Premièrement, chaque transaction définit une limite de gaz, qui limite le montant total de gaz pouvant être utilisé dans cette transaction. Deuxièmement, lorsqu'un contrat appelle un autre contrat, l'appel peut définir sa propre limite de gaz. Cela permet aux contrats d'appeler d'autres contrats en lesquels ils n'ont pas confiance, tout en garantissant qu'ils auront encore du gaz pour effectuer d'autres calculs après cet appel. Une trace d'une transaction d'abstraction de compte, où un compte appelle un autre compte et ne donne au destinataire qu'une quantité limitée de gaz, pour s'assurer que l'appel externe puisse continuer à s'exécuter même si le destinataire consomme tout le gaz qui lui a été attribué. Le défi est le suivant : rendre le gaz multidimensionnel entre différents types d'exécution semble nécessiter des sous-appels pour fournir plusieurs limites pour chaque type de gaz, ce qui nécessiterait un changement vraiment profond de l'EVM et ne serait pas compatible avec les applications existantes. C'est une des raisons pour lesquelles les propositions de gaz multidimensionnel s'arrêtent souvent à deux dimensions : les données et l'exécution. Les données (qu'il s'agisse de l'appel de transaction ou des blocs) ne sont attribuées qu'en dehors de l'EVM, de sorte que rien à l'intérieur de l'EVM n'a besoin de changer pour que l'appel de transaction ou les blocs soient tarifés séparément. Nous pouvons envisager une solution de style “EIP-7623” à ce problème. Voici une mise en œuvre simple : pendant l'exécution, facturer 4 fois plus pour les opérations de stockage ; pour simplifier l'analyse, disons 10000 gas par opération de stockage. À la fin de la transaction, rembourser min(7500 * opérations_de_stockage, gas_d_execution). Le résultat serait qu'après déduction du remboursement, un utilisateur est facturé : execution_gas + 10000 opérations de stockage - min(7500 opérations de stockage, gas d'exécution) Ce qui équivaut à : max(execution_gas + 2500 opérations de stockage, 10000storage_operations) Cela reflète la structure de l'EIP-7623. Une autre façon de le faire est de suivre les opérations de stockage et le gaz d'exécution en temps réel, et de facturer soit 2500, soit 10000 en fonction de la quantité maximale (gaz d'exécution + 2500)opérations de stockage, 10000Le coût en gaz des opérations de stockage) augmente au moment où l'opcode est appelé. Cela évite le besoin pour les transactions de sur-allouer du gaz qu'elles récupéreront principalement via des remboursements. Nous n'obtenons pas d'autorisation détaillée pour les sous-appels : un sous-appel pourrait consommer toute l'"allocation" d'une transaction pour des opérations de stockage bon marché. Mais nous obtenons quelque chose de suffisamment bon, où un contrat effectuant un sous-appel peut définir une limite et s'assurer qu'une fois l'exécution du sous-appel terminée, l'appel principal a toujours suffisamment de gaz pour effectuer tout post-traitement nécessaire. La solution de tarification la plus simple et complète que je puisse imaginer est la suivante : nous considérons les limites de gaz des sous-appels comme étant proportionnelles. C'est-à-dire, supposons qu'il y en ait 𝑘 différents types d'exécution, et chaque transaction définit une limite multidimensionnelle 𝐿1…𝐿𝑘 . Suppose that, at the current point in execution, the remaining gas is 𝑔1…𝑔𝑘 Supposons qu'un opcode CALL soit appelé, avec une limite de gas de sous-appel 𝑆 . Laissez 𝑠1=𝑆 , et ensuite 𝑠2=𝑠1𝑔1∗𝑔2 , 𝑠3=𝑠1𝑔1∗𝑔3 , et ainsi de suite. C’est-à-dire que nous traitons le premier type de gaz (de manière réaliste, l’exécution de la machine virtuelle) comme étant une sorte d'« unité de compte » privilégiée, puis nous affectons les autres types de gaz afin que le sous-appel obtienne le même pourcentage de gaz disponible pour chaque type. C’est un peu moche, mais cela maximise la rétrocompatibilité. Si nous voulons rendre le schéma plus « neutre » entre les différents types de gaz, au prix de sacrifier la rétrocompatibilité, nous pourrions simplement faire en sorte que le paramètre limite de gaz sous-call représente une fraction (par exemple. [1… 63] / 64) du gaz restant dans le contexte actuel). Dans l'un ou l'autre cas, il convient cependant de souligner que dès que vous commencez à introduire un gaz d'exécution multidimensionnel, le niveau inhérent de la laideur augmente, et il semble difficile d'éviter cela. Ainsi, notre tâche est de faire un compromis compliqué : acceptons-nous une certaine laideur au niveau de l'EVM, afin de débloquer en toute sécurité des gains significatifs de scalabilité L1, et si c'est le cas, quelle proposition spécifique fonctionne le mieux pour l'économie du protocole et les développeurs d'applications ? Il est fort probable que ce ne soit ni l'un ni l'autre des propositions que j'ai mentionnées ci-dessus, et il reste encore de la place pour trouver quelque chose de plus élégant et de meilleur.Blobs: gaz multidimensionnel dans Dencun
Clients multi-dimensionnels de gaz et sans état
Gaz multidimensionnel plus généralement
Par transaction max : le moyen plus faible mais plus simple d'obtenir du gaz multidimensionnel
Multidimensionnel EIP-1559: la stratégie plus difficile mais idéale
Tarification multidimensionnelle, l'EVM et les sous-appels
Avertissement: