En Ethereum, los recursos eran hasta hace poco limitados y con precio, utilizando un único recurso llamado "gas". El gas es una medida de la cantidad de "esfuerzo computacional" necesario para procesar una transacción o bloque dado. El gas fusiona varios tipos de "esfuerzo", en particular:
Por ejemplo, esta transacciónque envié costó un total de 47,085 gas. Esto se divide entre (i) un “costo base” de 21000 gas, (ii) 1556 gas por los bytes en los calldata incluidos como parte de la transacción, (iii) 16500 gas por lectura y escritura en el almacenamiento, (iv) gas 2149 por hacer unregistro, y el resto para la ejecución de EVM. La tarifa de transacción que un usuario debe pagar es proporcional al gas que consume la transacción. Un bloque puede contener hasta un máximo de 30 millones de gas, y los precios del gas se ajustan constantemente a través de la @vbuterinMecanismo de focalización de EIP-1559, asegurando que en promedio, los bloques contengan 15 millones de gas.
Este enfoque tiene una eficiencia principal: porque todo se fusiona en un recurso virtual, conduce a un diseño de mercado muy simple. Optimizar una transacción para minimizar costos es fácil, optimizar un bloque para recolectar las tarifas más altas posibles es relativamente fácil (sin incluirMEV) y no hay incentivos extraños que animen a algunas transacciones a agruparse con otras transacciones para ahorrar en comisiones.
Pero este enfoque también tiene una gran ineficiencia: trata diferentes recursos como si fueran mutuamente convertibles, cuando los límites subyacentes reales de lo que la red puede manejar no lo son. Una forma de entender este problema es mirar este diagrama:
El límite de gas impone una restricción de
𝑥1∗𝑑𝑎𝑡𝑎+𝑥2∗𝑐𝑜𝑚𝑝𝑢𝑡𝑎𝑡𝑖𝑜𝑛<𝑁
. La restricción de seguridad subyacente real a menudo está más cerca de
max(x1*data,x2*computación) Esta discrepancia lleva a que el límite de gas excluya innecesariamente bloques realmente seguros, o acepte bloques realmente inseguros, o alguna mezcla de ambos. Si hay 𝑛 recursos que tienen límites de seguridad distintos, entonces el gas unidimensional reduce plausiblemente el rendimiento hasta un factor de 𝑛 Por esta razón, ha habido durante mucho tiempo interés en el concepto de gas multi-dimensional, y con EIP-4844en realidad tenemos gas multidimensional funcionando en Ethereum hoy. Esta publicación explora los beneficios de este enfoque y las perspectivas para aumentarlo aún más. Al comienzo de este año, el bloque promedio era150 kB de tamaño. Una gran fracción de ese tamaño es datos de rollup: protocolos de capa 2almacenar datos en la cadena para seguridad. Estos datos eran costosos: aunque las transacciones en rollups costarían ~5-10 veces menos que las transacciones correspondientes en la capa Ethereum L1, incluso ese costo era demasiado alto para muchos casos de uso. ¿Por qué no disminuir el costo de gas de los datos de llamada (actualmente 16 gas por byte distinto de cero y 4 gas por byte de cero), para abaratar los rollups? Nosotros hizo esto antes, podríamos hacerlo de nuevo. La respuesta aquí es: el tamaño del peor caso de un bloque era 30,000,00016=1,875,000 bytes no nulos, y la red ya apenas puede manejar bloques de ese tamaño. Reducir los costos en otro 4x elevaría el máximo a 7.5 MB, lo cual sería un gran riesgo para la seguridad. Este problema terminó siendo manejado mediante la introducción de un espacio separado de datos amigables para rollup, conocidos como "blobs", en cada bloque. Los dos recursos tienen precios y límites separados: después de la bifurcación dencun, un bloque de Ethereum puede contener como máximo (i) 30 millones de gas y (ii) 6 blobs, que pueden contener ~125 kB de calldata cada uno. Ambos recursos tienen precios separados, ajustados por mecanismos de fijación de precios similares a EIP-1559 separados, apuntando a un uso promedio de 15 millones de gas y 3 blobs por bloque. Como resultado, los rollups se han vuelto 100 veces más baratos, el volumen de transacciones en los rollups aumentó en más de 3 veces y el tamaño máximo teórico del bloque solo se incrementó ligeramente: de ~1.9 MB a ~2.6 MB. Tarifas de transacción en rollups, cortesía de growthepie.xyz. La bifurcación Dencun, que introdujo blobs con precios multidimensionales, ocurrió el 13 de marzo de 2024. En un futuro cercano, surgirá un problema similar con respecto a las pruebas de almacenamiento para clientes sin estado. Los clientes sin estado son un nuevo tipo de cliente que podrá verificar la cadena sin almacenar muchos o ningún dato localmente. Estos clientes lo hacen al aceptar pruebas de las partes específicas del estado de Ethereum que las transacciones en ese bloque necesitan tocar. Un cliente sin estado recibe un bloque, junto con pruebas que demuestran los valores actuales en las partes específicas del estado (por ejemplo, saldos de cuentas, código, almacenamiento) que la ejecución del bloque toca. Esto permite a un nodo verificar un bloque sin tener ningún almacenamiento en sí mismo. Un costo de lectura de almacenamiento de 2100-2600 gas dependiendo del tipo de lectura, y las escrituras de almacenamiento cuestan más. En promedio, un bloque realiza alrededor de 1000 lecturas y escrituras de almacenamiento (incluyendo verificaciones de saldo de ETH, llamadas SSTORE y SLOAD, lectura de código de contrato y otras operaciones). El máximo teórico, sin embargo, es 30,000,0002,100=14,285 Lee. La carga de ancho de banda de un cliente sin estado es directamente proporcional a este número. Hoy, el plan es apoyar a los clientes sin estado al mover el diseño del árbol de estado de Ethereum desde Árboles de Merkle PatriciaaÁrboles VerkleSin embargo, los árboles Verkle no son resistentes a la computación cuántica y no son óptimos para las nuevas oleadas de sistemas de prueba STARK. Como resultado, muchas personas están interesadas en apoyar a los clientes sin estado a través de árboles Merkle binarios y STARKsen lugar - ya sea omitiendo Verkle por completo, o actualizando un par de años después de la transición de Verkle una vez que los STARKs se vuelvan más maduros. Las pruebas STARK de las ramas del árbol de hash binario tienen muchas ventajas, pero tienen la debilidad clave de que las pruebas tardan mucho tiempo en generarse: mientras Árboles Verklepuede demostrarmás de cien mil valores por segundo, los STARKs basados en hash suelen poder demostrar solo un par de miles de hashes por segundo, y probar cada valor requiere una “rama” que contiene muchos hashes. Dado los números que se están proyectando hoy de sistemas de prueba hiper-optimizados como Binius y Plonky3 y hashes especializados como Vision-Mark-32, parece probable que durante algún tiempo estemos en un régimen en el que sea práctico probar 1,000 valores en menos de un segundo, pero no 14,285 valores. Los bloques promedio estarían bien, pero los bloques de peor caso, potencialmente publicados por un atacante, romperían la red. La forma "predeterminada" en la que hemos manejado tal escenario es volver a fijar el precio: hacer que la lectura de almacenamiento sea más cara para reducir el máximo por bloque a algo más seguro. Sin embargo, tenemosyahechoesto mucho veces, y haría que demasiadas aplicaciones fueran demasiado caras para volver a hacer esto. Un mejor enfoque sería el gas multidimensional: limitar y cobrar por el acceso al almacenamiento por separado, manteniendo el uso promedio en 1.000 accesos al almacenamiento por bloque, pero estableciendo un límite por bloque de, por ejemplo. 2,000. Otro recurso que vale la pena considerar es el crecimiento del tamaño del estado: operaciones que aumentan el tamaño del estado de Ethereum, que los nodos completos necesitarán mantener a partir de entonces. La propiedad única del crecimiento del tamaño del estado es que la justificación para limitarlo proviene enteramente del uso sostenido a largo plazo, y no de picos. Por lo tanto, puede haber valor en agregar una dimensión de gas separada para operaciones que aumenten el tamaño del estado (por ejemplo, SSTORE de cero a distinto de cero, creación de contratos), pero con un objetivo diferente: podríamos establecer un precio flotante para apuntar a un uso promedio específico, pero no establecer ningún límite por bloque en absoluto. Esto muestra una de las propiedades poderosas de gas multidimensional: nos permite hacer las preguntas por separado de (i) cuál es el uso promedio ideal, y (ii) cuál es el uso máximo por bloque seguro, para cada recurso. En lugar de establecer precios de gas basados en máximos por bloque, y dejar que el uso promedio siga, 2𝑛 grados de libertad para establecer 2𝑛 parámetros, ajustando cada uno basado en lo que es seguro para la red. Situaciones más complicadas, como cuando dos recursos tienen consideraciones de seguridad que son parcialmente aditivas, podrían ser manejadas haciendo que un opcode o costo de recurso requiera cierta cantidad de múltiples tipos de gas (por ejemplo, un SSTORE de cero a no cero podría costar 5000 gas de prueba de cliente sin estado y 20000 gas de expansión de almacenamiento). Deja 𝑥1 ser el costo de gas de datos y 𝑥2 ser el costo de gas de la computación, por lo que en un sistema de gas unidimensional podemos escribir el costo de gas de una transacción: gas=x1∗data+x2∗computación En este esquema, en cambio, definimos el costo de gas de una transacción como: gas=mx(x1*data,x2*computación) Es decir, en lugar de cobrar una transacción por datos más computación, la transacción se cobra en función de cuál de los dos recursos consume más. Esto se puede ampliar fácilmente para abarcar más dimensiones (por ejemplo, 𝑚𝑎𝑥(…,𝑥3∗𝑠𝑡𝑜𝑟𝑎𝑔𝑒_𝑎𝑐𝑐𝑒𝑠𝑠) ). Debería ser fácil ver cómo esto mejora el rendimiento mientras se preserva la seguridad. La cantidad máxima teórica de datos en un bloque sigue siendo 𝐺𝐴𝑆𝐿𝐼𝑀𝐼𝑇𝑥1 , exactamente igual que en el esquema de gas unidimensional. Del mismo modo, la cantidad máxima teórica de cálculo es 𝐺𝐴𝑆𝐿𝐼𝑀𝐼𝑇𝑥2 , nuevamente exactamente igual que en el esquema de gas unidimensional. Sin embargo, el costo de gas de cualquier transacción que consuma tanto datos como computación disminuye. Este es aproximadamente el esquema empleado en el propuesto EIP-7623, para reducir el tamaño máximo del bloque mientras se aumenta aún más el recuento de blobs. El mecanismo preciso en EIP-7623 es ligeramente más complicado: mantiene el precio actual de calldata de 16 gas por byte, pero agrega un "precio mínimo" de 48 gas por byte; una transacción paga el mayor de (16 bytes + execution_gas) y (48 bytes). Como resultado, EIP-7623 reduce el tamaño máximo teórico de los datos de llamada de transacción en un bloque de ~1.9 MB a ~0.6 MB, dejando los costos de la mayoría de las aplicaciones sin cambios. El beneficio de este enfoque es que es un cambio muy pequeño en comparación con el esquema de gas unidimensional actual, por lo que es muy fácil de implementar. Hay dos inconvenientes: Yo argumentaría que una regla al estilo EIP-7623, tanto para los datos de llamada de transacción como para otros recursos, puede aportar beneficios lo suficientemente grandes como para que valga la pena, incluso a pesar de estos inconvenientes. Sin embargo, si y cuando estemos dispuestos a invertir en el esfuerzo de desarrollo (significativamente mayor), hay un enfoque más ideal. Primero recordemos cómo funciona el EIP-1559 "regular". Nos enfocaremos en la versión que fue introducida en el EIP-4844 para blobs, porque matemáticamente es más elegante. Seguimos un parámetro, exceso_blobs. Durante cada bloque, establecemos: exceso_blobs <— max(exceso_blobs + len(block.blobs) - TARGET, 0) Donde TARGET = 3. Es decir, si un bloque tiene más blobs que el objetivo, excess_blobs aumenta, y si un bloque tiene menos que el objetivo, disminuye. Luego establecemos blob_basefee = exp(excess_blobs / 25.47), donde exp es una aproximación de la función exponencial exp(x)=2.71828x . Es decir, cada vez que excess_blobs aumenta en ~25, el basefee del blob aumenta en un factor de ~2.7. Si los blobs se vuelven demasiado caros, la utilización promedio disminuye y excess_blobs comienza a disminuir, lo que hace que el precio vuelva a bajar automáticamente. El precio de un blob se ajusta constantemente para asegurarse de que, en promedio, los bloques estén medio llenos, es decir, que contengan un promedio de 3 blobs cada uno. Si hay un pico a corto plazo en el uso, entonces el límite entra en acción: cada bloque solo puede contener un máximo de 6 bloques, y en tales circunstancias las transacciones pueden competir entre sí al ofertar sus tarifas de prioridad. En el caso normal, sin embargo, cada bloque solo necesita pagar la tarifa_base de blob más una pequeña tarifa de prioridad adicional como incentivo para ser incluido en absoluto. Este tipo de precios existió en Ethereum para gas durante años: un mecanismo muy similar fue introducido con @vbuterin/eip-1559-faq">EIP-1559 de regreso en 2020. Con EIP-4844, ahora tenemos dos precios flotantes separados para gas y para blobs. Tarifa base de gas durante el transcurso de una hora el 08-05-2024, en gwei. Fuente: ultrasound.money. En principio, podríamos agregar más tarifas flotantes por separado para la lectura de almacenamiento y otros tipos de operaciones, aunque con una advertencia que ampliaré en la siguiente sección. Para los usuarios, la experiencia es notablemente similar a la de hoy: en lugar de pagar una tarifa base, pagas dos tarifas base, pero tu billetera puede abstraer eso de ti y simplemente mostrarte la tarifa esperada y la tarifa máxima que puedes esperar pagar. Para los constructores de bloques, la mayoría de las veces la estrategia óptima es la misma que hoy: incluir todo lo que sea válido. La mayoría de los bloques no están llenos - tampocoen gasnien blobsEl caso desafiante es cuando hay suficiente gas o suficientes blobs para exceder el límite de bloque, y el constructor necesita potencialmente resolver un Problema de mochila multidimensionalpara maximizar sus ganancias. Sin embargo, incluso existen algoritmos de aproximación bastante buenos, y las ganancias por elaborar algoritmos propietarios para optimizar ganancias en este caso son mucho menores que las ganancias por hacer lo mismo con MEV. Para los desarrolladores, el principal desafío es la necesidad de rediseñar las características del EVM, y su infraestructura circundante, que está diseñada en torno a un precio y un límite hoy en día, en un diseño que pueda acomodar múltiples precios y múltiples límites. Un problema para los desarrolladores de aplicaciones es que la optimización se vuelve ligeramente más difícil: en algunos casos, ya no puedes decir inequívocamente que A es más eficiente que B, porque si A utiliza más calldata pero B utiliza más ejecución, entonces A podría ser más barato cuando calldata es barato, y más caro cuando calldata es caro. Sin embargo, los desarrolladores aún podrían obtener resultados razonablemente buenos optimizando en función de los precios promedio históricos a largo plazo. Hay un problema que no apareció con los blobs, y no aparecerá con EIP-7623 o incluso con una implementación de precios multidimensionales “completa” para calldata, pero aparecerá si intentamos fijar precios por separado para los accesos al estado, u otro recurso: límites de gas en subllamadas. Los límites de gas en el EVM existen en dos lugares. En primer lugar, cada transacción establece un límite de gas, que limita la cantidad total de gas que se puede utilizar en esa transacción. En segundo lugar, cuando un contrato llama a otro contrato, la llamada puede establecer su propio límite de gas. Esto permite que los contratos llamen a otros contratos en los que no confían, y aún así garantizan que les quedará gas para realizar otras computaciones después de esa llamada. Una traza de una transacción de abstracción de cuenta, donde una cuenta llama a otra cuenta y solo le da al destinatario una cantidad limitada de gas, para asegurar que la llamada externa pueda seguir ejecutándose incluso si el destinatario consume todo el gas asignado a él. El desafío es: hacer que el gas sea multidimensional entre diferentes tipos de ejecución parece que requeriría subllamadas para proporcionar múltiples límites para cada tipo de gas, lo que requeriría un cambio realmente profundo en el EVM, y no sería compatible con las aplicaciones existentes. Esta es una razón por la cual las propuestas de gas multidimensionales a menudo se detienen en dos dimensiones: datos y ejecución. Los datos (ya sea datos de llamada de transacción o blobs) solo se asignan fuera del EVM, por lo que nada dentro del EVM necesita cambiar para que los datos de llamada o blobs se pricen por separado. Podemos pensar en una solución de estilo EIP-7623 para este problema. Aquí hay una implementación simple: durante la ejecución, cobrar 4 veces más por las operaciones de almacenamiento; para simplificar el análisis, digamos 10000 gas por operación de almacenamiento. Al final de la transacción, reembolsar min(7500 * operaciones_de_almacenamiento, gas_de_ejecución). El resultado sería que, después de restar el reembolso, a un usuario se le cobra: execution_gas + 10000operaciones de almacenamiento - min(7500operaciones de almacenamiento, gas de ejecución) Lo cual equivale: máximo (execution_gas + 2500operaciones de almacenamiento, 10000 storage_operations) Esto refleja la estructura de EIP-7623. Otra forma de hacerlo es rastrear las operaciones de almacenamiento y el gas de ejecución en tiempo real, y cobrar ya sea 2500 o 10000 dependiendo de cuánto sea el máximo (gas de ejecución + 2500)operaciones de almacenamiento, 10000El consumo de gas (operaciones de almacenamiento) aumenta en el momento en que se llama el opcode. Esto evita la necesidad de que las transacciones asignen en exceso gas que en su mayoría recuperarán a través de reembolsos. No obtenemos permisos detallados para subllamadas: una subllamada podría consumir toda la “asignación” de una transacción para operaciones de almacenamiento baratas. Pero obtenemos algo lo suficientemente bueno, donde un contrato que realiza una subllamada puede establecer un límite y asegurarse de que una vez que la subllamada termine de ejecutarse, la llamada principal todavía tenga suficiente gas para hacer cualquier postprocesamiento que necesite hacer. La solución de precios multidimensionales más fácil que se me ocurre es: tratamos los límites de gas de las subllamadas como proporcionales. Es decir, supongamos que hay k diferentes tipos de ejecución, y cada transacción establece un límite multidimensional 𝐿1…𝐿𝑘 . Supongamos que, en el punto actual de la ejecución, el gas restante es 𝑔1…𝑔𝑘 Supongamos que se llama a un código de operación CALL, con límite de gas de subllamada 𝑆 . Dejar 𝑠1=𝑆 , y luego 𝑠2=𝑠1𝑔1∗gas2 , 𝑠3=𝑠1𝑔1∗gas3 , y así sucesivamente. Es decir, tratamos el primer tipo de gas (realísticamente, la ejecución de VM) como una especie de "unidad de cuenta" privilegiada, y luego asignamos los otros tipos de gas de manera que la subllamada reciba el mismo porcentaje de gas disponible en cada tipo. Esto es un poco feo, pero maximiza la compatibilidad con versiones anteriores. Si queremos hacer el esquema más "neutral" entre diferentes tipos de gas, a costa de sacrificar la compatibilidad con versiones anteriores, simplemente podríamos hacer que el parámetro de límite de gas de la subllamada represente una fracción (por ejemplo, [1…63] / 64) del gas restante en el contexto actual). En cualquier caso, sin embargo, vale la pena destacar que una vez que comiences a introducir gas de ejecución multidimensional, el nivel inherente de fealdad aumenta, y parece difícil de evitar. Por lo tanto, nuestra tarea es hacer un intercambio complicado: ¿aceptamos algo más de fealdad a nivel de EVM, para desbloquear de manera segura ganancias significativas de escalabilidad L1, y si es así, cuál propuesta específica funciona mejor para la economía del protocolo y los desarrolladores de aplicaciones? Muy probablemente, no sea ninguno de los que mencioné anteriormente, y aún hay margen para idear algo más elegante y mejor.Blobs: gas multidimensional en Dencun
Clientes sin estado y de gas multidimensional
Gas multidimensional más generalmente
Máximo por transacción: la forma más débil pero más fácil de obtener gas multidimensional
EIP-1559 multidimensional: la estrategia más difícil pero ideal
Precios multidimensionales, el EVM y subllamadas
Descargo de responsabilidad:
Mời người khác bỏ phiếu
Nội dung
En Ethereum, los recursos eran hasta hace poco limitados y con precio, utilizando un único recurso llamado "gas". El gas es una medida de la cantidad de "esfuerzo computacional" necesario para procesar una transacción o bloque dado. El gas fusiona varios tipos de "esfuerzo", en particular:
Por ejemplo, esta transacciónque envié costó un total de 47,085 gas. Esto se divide entre (i) un “costo base” de 21000 gas, (ii) 1556 gas por los bytes en los calldata incluidos como parte de la transacción, (iii) 16500 gas por lectura y escritura en el almacenamiento, (iv) gas 2149 por hacer unregistro, y el resto para la ejecución de EVM. La tarifa de transacción que un usuario debe pagar es proporcional al gas que consume la transacción. Un bloque puede contener hasta un máximo de 30 millones de gas, y los precios del gas se ajustan constantemente a través de la @vbuterinMecanismo de focalización de EIP-1559, asegurando que en promedio, los bloques contengan 15 millones de gas.
Este enfoque tiene una eficiencia principal: porque todo se fusiona en un recurso virtual, conduce a un diseño de mercado muy simple. Optimizar una transacción para minimizar costos es fácil, optimizar un bloque para recolectar las tarifas más altas posibles es relativamente fácil (sin incluirMEV) y no hay incentivos extraños que animen a algunas transacciones a agruparse con otras transacciones para ahorrar en comisiones.
Pero este enfoque también tiene una gran ineficiencia: trata diferentes recursos como si fueran mutuamente convertibles, cuando los límites subyacentes reales de lo que la red puede manejar no lo son. Una forma de entender este problema es mirar este diagrama:
El límite de gas impone una restricción de
𝑥1∗𝑑𝑎𝑡𝑎+𝑥2∗𝑐𝑜𝑚𝑝𝑢𝑡𝑎𝑡𝑖𝑜𝑛<𝑁
. La restricción de seguridad subyacente real a menudo está más cerca de
max(x1*data,x2*computación) Esta discrepancia lleva a que el límite de gas excluya innecesariamente bloques realmente seguros, o acepte bloques realmente inseguros, o alguna mezcla de ambos. Si hay 𝑛 recursos que tienen límites de seguridad distintos, entonces el gas unidimensional reduce plausiblemente el rendimiento hasta un factor de 𝑛 Por esta razón, ha habido durante mucho tiempo interés en el concepto de gas multi-dimensional, y con EIP-4844en realidad tenemos gas multidimensional funcionando en Ethereum hoy. Esta publicación explora los beneficios de este enfoque y las perspectivas para aumentarlo aún más. Al comienzo de este año, el bloque promedio era150 kB de tamaño. Una gran fracción de ese tamaño es datos de rollup: protocolos de capa 2almacenar datos en la cadena para seguridad. Estos datos eran costosos: aunque las transacciones en rollups costarían ~5-10 veces menos que las transacciones correspondientes en la capa Ethereum L1, incluso ese costo era demasiado alto para muchos casos de uso. ¿Por qué no disminuir el costo de gas de los datos de llamada (actualmente 16 gas por byte distinto de cero y 4 gas por byte de cero), para abaratar los rollups? Nosotros hizo esto antes, podríamos hacerlo de nuevo. La respuesta aquí es: el tamaño del peor caso de un bloque era 30,000,00016=1,875,000 bytes no nulos, y la red ya apenas puede manejar bloques de ese tamaño. Reducir los costos en otro 4x elevaría el máximo a 7.5 MB, lo cual sería un gran riesgo para la seguridad. Este problema terminó siendo manejado mediante la introducción de un espacio separado de datos amigables para rollup, conocidos como "blobs", en cada bloque. Los dos recursos tienen precios y límites separados: después de la bifurcación dencun, un bloque de Ethereum puede contener como máximo (i) 30 millones de gas y (ii) 6 blobs, que pueden contener ~125 kB de calldata cada uno. Ambos recursos tienen precios separados, ajustados por mecanismos de fijación de precios similares a EIP-1559 separados, apuntando a un uso promedio de 15 millones de gas y 3 blobs por bloque. Como resultado, los rollups se han vuelto 100 veces más baratos, el volumen de transacciones en los rollups aumentó en más de 3 veces y el tamaño máximo teórico del bloque solo se incrementó ligeramente: de ~1.9 MB a ~2.6 MB. Tarifas de transacción en rollups, cortesía de growthepie.xyz. La bifurcación Dencun, que introdujo blobs con precios multidimensionales, ocurrió el 13 de marzo de 2024. En un futuro cercano, surgirá un problema similar con respecto a las pruebas de almacenamiento para clientes sin estado. Los clientes sin estado son un nuevo tipo de cliente que podrá verificar la cadena sin almacenar muchos o ningún dato localmente. Estos clientes lo hacen al aceptar pruebas de las partes específicas del estado de Ethereum que las transacciones en ese bloque necesitan tocar. Un cliente sin estado recibe un bloque, junto con pruebas que demuestran los valores actuales en las partes específicas del estado (por ejemplo, saldos de cuentas, código, almacenamiento) que la ejecución del bloque toca. Esto permite a un nodo verificar un bloque sin tener ningún almacenamiento en sí mismo. Un costo de lectura de almacenamiento de 2100-2600 gas dependiendo del tipo de lectura, y las escrituras de almacenamiento cuestan más. En promedio, un bloque realiza alrededor de 1000 lecturas y escrituras de almacenamiento (incluyendo verificaciones de saldo de ETH, llamadas SSTORE y SLOAD, lectura de código de contrato y otras operaciones). El máximo teórico, sin embargo, es 30,000,0002,100=14,285 Lee. La carga de ancho de banda de un cliente sin estado es directamente proporcional a este número. Hoy, el plan es apoyar a los clientes sin estado al mover el diseño del árbol de estado de Ethereum desde Árboles de Merkle PatriciaaÁrboles VerkleSin embargo, los árboles Verkle no son resistentes a la computación cuántica y no son óptimos para las nuevas oleadas de sistemas de prueba STARK. Como resultado, muchas personas están interesadas en apoyar a los clientes sin estado a través de árboles Merkle binarios y STARKsen lugar - ya sea omitiendo Verkle por completo, o actualizando un par de años después de la transición de Verkle una vez que los STARKs se vuelvan más maduros. Las pruebas STARK de las ramas del árbol de hash binario tienen muchas ventajas, pero tienen la debilidad clave de que las pruebas tardan mucho tiempo en generarse: mientras Árboles Verklepuede demostrarmás de cien mil valores por segundo, los STARKs basados en hash suelen poder demostrar solo un par de miles de hashes por segundo, y probar cada valor requiere una “rama” que contiene muchos hashes. Dado los números que se están proyectando hoy de sistemas de prueba hiper-optimizados como Binius y Plonky3 y hashes especializados como Vision-Mark-32, parece probable que durante algún tiempo estemos en un régimen en el que sea práctico probar 1,000 valores en menos de un segundo, pero no 14,285 valores. Los bloques promedio estarían bien, pero los bloques de peor caso, potencialmente publicados por un atacante, romperían la red. La forma "predeterminada" en la que hemos manejado tal escenario es volver a fijar el precio: hacer que la lectura de almacenamiento sea más cara para reducir el máximo por bloque a algo más seguro. Sin embargo, tenemosyahechoesto mucho veces, y haría que demasiadas aplicaciones fueran demasiado caras para volver a hacer esto. Un mejor enfoque sería el gas multidimensional: limitar y cobrar por el acceso al almacenamiento por separado, manteniendo el uso promedio en 1.000 accesos al almacenamiento por bloque, pero estableciendo un límite por bloque de, por ejemplo. 2,000. Otro recurso que vale la pena considerar es el crecimiento del tamaño del estado: operaciones que aumentan el tamaño del estado de Ethereum, que los nodos completos necesitarán mantener a partir de entonces. La propiedad única del crecimiento del tamaño del estado es que la justificación para limitarlo proviene enteramente del uso sostenido a largo plazo, y no de picos. Por lo tanto, puede haber valor en agregar una dimensión de gas separada para operaciones que aumenten el tamaño del estado (por ejemplo, SSTORE de cero a distinto de cero, creación de contratos), pero con un objetivo diferente: podríamos establecer un precio flotante para apuntar a un uso promedio específico, pero no establecer ningún límite por bloque en absoluto. Esto muestra una de las propiedades poderosas de gas multidimensional: nos permite hacer las preguntas por separado de (i) cuál es el uso promedio ideal, y (ii) cuál es el uso máximo por bloque seguro, para cada recurso. En lugar de establecer precios de gas basados en máximos por bloque, y dejar que el uso promedio siga, 2𝑛 grados de libertad para establecer 2𝑛 parámetros, ajustando cada uno basado en lo que es seguro para la red. Situaciones más complicadas, como cuando dos recursos tienen consideraciones de seguridad que son parcialmente aditivas, podrían ser manejadas haciendo que un opcode o costo de recurso requiera cierta cantidad de múltiples tipos de gas (por ejemplo, un SSTORE de cero a no cero podría costar 5000 gas de prueba de cliente sin estado y 20000 gas de expansión de almacenamiento). Deja 𝑥1 ser el costo de gas de datos y 𝑥2 ser el costo de gas de la computación, por lo que en un sistema de gas unidimensional podemos escribir el costo de gas de una transacción: gas=x1∗data+x2∗computación En este esquema, en cambio, definimos el costo de gas de una transacción como: gas=mx(x1*data,x2*computación) Es decir, en lugar de cobrar una transacción por datos más computación, la transacción se cobra en función de cuál de los dos recursos consume más. Esto se puede ampliar fácilmente para abarcar más dimensiones (por ejemplo, 𝑚𝑎𝑥(…,𝑥3∗𝑠𝑡𝑜𝑟𝑎𝑔𝑒_𝑎𝑐𝑐𝑒𝑠𝑠) ). Debería ser fácil ver cómo esto mejora el rendimiento mientras se preserva la seguridad. La cantidad máxima teórica de datos en un bloque sigue siendo 𝐺𝐴𝑆𝐿𝐼𝑀𝐼𝑇𝑥1 , exactamente igual que en el esquema de gas unidimensional. Del mismo modo, la cantidad máxima teórica de cálculo es 𝐺𝐴𝑆𝐿𝐼𝑀𝐼𝑇𝑥2 , nuevamente exactamente igual que en el esquema de gas unidimensional. Sin embargo, el costo de gas de cualquier transacción que consuma tanto datos como computación disminuye. Este es aproximadamente el esquema empleado en el propuesto EIP-7623, para reducir el tamaño máximo del bloque mientras se aumenta aún más el recuento de blobs. El mecanismo preciso en EIP-7623 es ligeramente más complicado: mantiene el precio actual de calldata de 16 gas por byte, pero agrega un "precio mínimo" de 48 gas por byte; una transacción paga el mayor de (16 bytes + execution_gas) y (48 bytes). Como resultado, EIP-7623 reduce el tamaño máximo teórico de los datos de llamada de transacción en un bloque de ~1.9 MB a ~0.6 MB, dejando los costos de la mayoría de las aplicaciones sin cambios. El beneficio de este enfoque es que es un cambio muy pequeño en comparación con el esquema de gas unidimensional actual, por lo que es muy fácil de implementar. Hay dos inconvenientes: Yo argumentaría que una regla al estilo EIP-7623, tanto para los datos de llamada de transacción como para otros recursos, puede aportar beneficios lo suficientemente grandes como para que valga la pena, incluso a pesar de estos inconvenientes. Sin embargo, si y cuando estemos dispuestos a invertir en el esfuerzo de desarrollo (significativamente mayor), hay un enfoque más ideal. Primero recordemos cómo funciona el EIP-1559 "regular". Nos enfocaremos en la versión que fue introducida en el EIP-4844 para blobs, porque matemáticamente es más elegante. Seguimos un parámetro, exceso_blobs. Durante cada bloque, establecemos: exceso_blobs <— max(exceso_blobs + len(block.blobs) - TARGET, 0) Donde TARGET = 3. Es decir, si un bloque tiene más blobs que el objetivo, excess_blobs aumenta, y si un bloque tiene menos que el objetivo, disminuye. Luego establecemos blob_basefee = exp(excess_blobs / 25.47), donde exp es una aproximación de la función exponencial exp(x)=2.71828x . Es decir, cada vez que excess_blobs aumenta en ~25, el basefee del blob aumenta en un factor de ~2.7. Si los blobs se vuelven demasiado caros, la utilización promedio disminuye y excess_blobs comienza a disminuir, lo que hace que el precio vuelva a bajar automáticamente. El precio de un blob se ajusta constantemente para asegurarse de que, en promedio, los bloques estén medio llenos, es decir, que contengan un promedio de 3 blobs cada uno. Si hay un pico a corto plazo en el uso, entonces el límite entra en acción: cada bloque solo puede contener un máximo de 6 bloques, y en tales circunstancias las transacciones pueden competir entre sí al ofertar sus tarifas de prioridad. En el caso normal, sin embargo, cada bloque solo necesita pagar la tarifa_base de blob más una pequeña tarifa de prioridad adicional como incentivo para ser incluido en absoluto. Este tipo de precios existió en Ethereum para gas durante años: un mecanismo muy similar fue introducido con @vbuterin/eip-1559-faq">EIP-1559 de regreso en 2020. Con EIP-4844, ahora tenemos dos precios flotantes separados para gas y para blobs. Tarifa base de gas durante el transcurso de una hora el 08-05-2024, en gwei. Fuente: ultrasound.money. En principio, podríamos agregar más tarifas flotantes por separado para la lectura de almacenamiento y otros tipos de operaciones, aunque con una advertencia que ampliaré en la siguiente sección. Para los usuarios, la experiencia es notablemente similar a la de hoy: en lugar de pagar una tarifa base, pagas dos tarifas base, pero tu billetera puede abstraer eso de ti y simplemente mostrarte la tarifa esperada y la tarifa máxima que puedes esperar pagar. Para los constructores de bloques, la mayoría de las veces la estrategia óptima es la misma que hoy: incluir todo lo que sea válido. La mayoría de los bloques no están llenos - tampocoen gasnien blobsEl caso desafiante es cuando hay suficiente gas o suficientes blobs para exceder el límite de bloque, y el constructor necesita potencialmente resolver un Problema de mochila multidimensionalpara maximizar sus ganancias. Sin embargo, incluso existen algoritmos de aproximación bastante buenos, y las ganancias por elaborar algoritmos propietarios para optimizar ganancias en este caso son mucho menores que las ganancias por hacer lo mismo con MEV. Para los desarrolladores, el principal desafío es la necesidad de rediseñar las características del EVM, y su infraestructura circundante, que está diseñada en torno a un precio y un límite hoy en día, en un diseño que pueda acomodar múltiples precios y múltiples límites. Un problema para los desarrolladores de aplicaciones es que la optimización se vuelve ligeramente más difícil: en algunos casos, ya no puedes decir inequívocamente que A es más eficiente que B, porque si A utiliza más calldata pero B utiliza más ejecución, entonces A podría ser más barato cuando calldata es barato, y más caro cuando calldata es caro. Sin embargo, los desarrolladores aún podrían obtener resultados razonablemente buenos optimizando en función de los precios promedio históricos a largo plazo. Hay un problema que no apareció con los blobs, y no aparecerá con EIP-7623 o incluso con una implementación de precios multidimensionales “completa” para calldata, pero aparecerá si intentamos fijar precios por separado para los accesos al estado, u otro recurso: límites de gas en subllamadas. Los límites de gas en el EVM existen en dos lugares. En primer lugar, cada transacción establece un límite de gas, que limita la cantidad total de gas que se puede utilizar en esa transacción. En segundo lugar, cuando un contrato llama a otro contrato, la llamada puede establecer su propio límite de gas. Esto permite que los contratos llamen a otros contratos en los que no confían, y aún así garantizan que les quedará gas para realizar otras computaciones después de esa llamada. Una traza de una transacción de abstracción de cuenta, donde una cuenta llama a otra cuenta y solo le da al destinatario una cantidad limitada de gas, para asegurar que la llamada externa pueda seguir ejecutándose incluso si el destinatario consume todo el gas asignado a él. El desafío es: hacer que el gas sea multidimensional entre diferentes tipos de ejecución parece que requeriría subllamadas para proporcionar múltiples límites para cada tipo de gas, lo que requeriría un cambio realmente profundo en el EVM, y no sería compatible con las aplicaciones existentes. Esta es una razón por la cual las propuestas de gas multidimensionales a menudo se detienen en dos dimensiones: datos y ejecución. Los datos (ya sea datos de llamada de transacción o blobs) solo se asignan fuera del EVM, por lo que nada dentro del EVM necesita cambiar para que los datos de llamada o blobs se pricen por separado. Podemos pensar en una solución de estilo EIP-7623 para este problema. Aquí hay una implementación simple: durante la ejecución, cobrar 4 veces más por las operaciones de almacenamiento; para simplificar el análisis, digamos 10000 gas por operación de almacenamiento. Al final de la transacción, reembolsar min(7500 * operaciones_de_almacenamiento, gas_de_ejecución). El resultado sería que, después de restar el reembolso, a un usuario se le cobra: execution_gas + 10000operaciones de almacenamiento - min(7500operaciones de almacenamiento, gas de ejecución) Lo cual equivale: máximo (execution_gas + 2500operaciones de almacenamiento, 10000 storage_operations) Esto refleja la estructura de EIP-7623. Otra forma de hacerlo es rastrear las operaciones de almacenamiento y el gas de ejecución en tiempo real, y cobrar ya sea 2500 o 10000 dependiendo de cuánto sea el máximo (gas de ejecución + 2500)operaciones de almacenamiento, 10000El consumo de gas (operaciones de almacenamiento) aumenta en el momento en que se llama el opcode. Esto evita la necesidad de que las transacciones asignen en exceso gas que en su mayoría recuperarán a través de reembolsos. No obtenemos permisos detallados para subllamadas: una subllamada podría consumir toda la “asignación” de una transacción para operaciones de almacenamiento baratas. Pero obtenemos algo lo suficientemente bueno, donde un contrato que realiza una subllamada puede establecer un límite y asegurarse de que una vez que la subllamada termine de ejecutarse, la llamada principal todavía tenga suficiente gas para hacer cualquier postprocesamiento que necesite hacer. La solución de precios multidimensionales más fácil que se me ocurre es: tratamos los límites de gas de las subllamadas como proporcionales. Es decir, supongamos que hay k diferentes tipos de ejecución, y cada transacción establece un límite multidimensional 𝐿1…𝐿𝑘 . Supongamos que, en el punto actual de la ejecución, el gas restante es 𝑔1…𝑔𝑘 Supongamos que se llama a un código de operación CALL, con límite de gas de subllamada 𝑆 . Dejar 𝑠1=𝑆 , y luego 𝑠2=𝑠1𝑔1∗gas2 , 𝑠3=𝑠1𝑔1∗gas3 , y así sucesivamente. Es decir, tratamos el primer tipo de gas (realísticamente, la ejecución de VM) como una especie de "unidad de cuenta" privilegiada, y luego asignamos los otros tipos de gas de manera que la subllamada reciba el mismo porcentaje de gas disponible en cada tipo. Esto es un poco feo, pero maximiza la compatibilidad con versiones anteriores. Si queremos hacer el esquema más "neutral" entre diferentes tipos de gas, a costa de sacrificar la compatibilidad con versiones anteriores, simplemente podríamos hacer que el parámetro de límite de gas de la subllamada represente una fracción (por ejemplo, [1…63] / 64) del gas restante en el contexto actual). En cualquier caso, sin embargo, vale la pena destacar que una vez que comiences a introducir gas de ejecución multidimensional, el nivel inherente de fealdad aumenta, y parece difícil de evitar. Por lo tanto, nuestra tarea es hacer un intercambio complicado: ¿aceptamos algo más de fealdad a nivel de EVM, para desbloquear de manera segura ganancias significativas de escalabilidad L1, y si es así, cuál propuesta específica funciona mejor para la economía del protocolo y los desarrolladores de aplicaciones? Muy probablemente, no sea ninguno de los que mencioné anteriormente, y aún hay margen para idear algo más elegante y mejor.Blobs: gas multidimensional en Dencun
Clientes sin estado y de gas multidimensional
Gas multidimensional más generalmente
Máximo por transacción: la forma más débil pero más fácil de obtener gas multidimensional
EIP-1559 multidimensional: la estrategia más difícil pero ideal
Precios multidimensionales, el EVM y subllamadas
Descargo de responsabilidad: