Artículo original publicado en Aurora Developers: EVM gas vs. Near gas on Aurora. Traducido por: Milly Rodriguez.
El smart contract Aurora Engine funciona como la pieza central de la tecnología de Aurora, el cual es una implementación de la máquina virtual de Ethereum (EVM) desplegada como un contrato inteligente en Near. Por lo tanto, Aurora se encuentra en la intersección de los tiempos de ejecución de EVM y Near. Es por ello, que esto nos lleva a pensar en comparaciones entre EVM y Near.
Por ejemplo, el concepto de “gas” existe tanto en el EVM como en el tiempo de ejecución de Near. La razón es el famoso problema de detención, que dice que no podemos saber de antemano si un programa informático arbitrario terminará en un tiempo finito. En el contexto de una plataforma de contratos inteligentes, esto significa que debemos medir (y limitar) el cálculo que el contrato realiza en tiempo de ejecución. Tanto en EVM como en Near, “gas” es la unidad que se utiliza para medir el trabajo computacional realizado por un contrato inteligente.
Aunque el gas EVM y el gas Near miden lo mismo, no son idénticos. Una analogía son las millas y los kilómetros; ambos miden la distancia, pero el valor numérico de la misma distancia física será diferente dependiendo de la unidad que se utilice. El cómputo es un concepto más abstracto que la distancia, pero esta analogía nos lleva a esperar algún tipo de relación aproximadamente lineal entre el gas EVM y el gas Near, de forma similar a cómo 1 milla equivale a 1,61 kilómetros.
En este artículo, se explorará esto y se darán a conocer las implicaciones para los desarrolladores que construyen sobre Aurora.
La relación teórica.
En teoría, deberíamos poder deducir la relación entre el gas EVM y el gas Near, considerando el coste del gas EVM de cada operación en la EVM y calculando cuánto gas Near cuesta esta misma operación, en función de su implementación en Aurora. Por desgracia, en la práctica esto es mucho más difícil de lo que parece. El Aurora Engine está escrito en Rust y compilado a Web Assembly (Wasm). Este proceso de compilación convulsiona el mapeo conceptual entre los opcodes de EVM y las operaciones en el tiempo de ejecución de Near. Hay complejidades adicionales al tratar de hacer este cálculo en que Aurora virtualiza todo el EVM dentro de Wasm, y por lo tanto cuánto gas Near toma un opcode puede depender del estado general de la VM (por ejemplo, porque más memoria Wasm necesita ser asignada).
Es importante tener esta idea de como poder calcular la relación a partir de los primeros principios (y lo retomaremos más adelante en este post), no es una forma práctica de responder a nuestra pregunta. Para ello, utilizaremos en su lugar datos empíricos.
Recopilación de datos
Los datos de gas EVM y Near utilizados para todas las transacciones en Aurora están disponibles a través de una combinación de nuestro RPC y el RPC de Near. Considere la siguiente llamada (realizada a través de la línea de comandos utilizando la herramienta HTTPie):
http post https://mainnet.aurora.dev/ jsonrpc=2.0 id=1 \method=eth_getTransactionReceipt \
params:=’[“0x4c2b8b5d766fe0411d0003bf4c9d2becc9d6dd7120272cf9f1a6cac73e4c3543”]’
El parámetro de esta llamada puede ser cualquier hash de una transacción en Aurora (el dado es sólo un ejemplo). Fíjese en el campo gasUsed de la respuesta, que da la cantidad (codificada en hexadecimal) de gas EVM utilizado en la transacción (46.574 en este ejemplo).
Además de los campos de respuesta estándar definidos por el estándar de Ethereum, el RPC de Aurora devuelve otros dos campos: `nearReceiptHash` y `nearTransactionHash`. Estos dan los hashes de recibo/transacción correspondientes a la transacción subyacente que fue ejecutada en Near (por el contrato Aurora Engine).
Para utilizar estos campos adicionales, hay algo de trabajo adicional porque los hashes Near siempre se presentan en codificación base58, mientras que nuestro RPC los devuelve en codificación hexadecimal (para ser coherentes con la forma en que Ethereum suele presentar los hashes). Puedes leer más sobre esto en un artículo anterior. Para nuestros propósitos aquí, es bastante fácil escribir un script en Python para hacer la conversión por nosotros y encadenar esto junto con la herramienta jq para obtener el hash de la transacción Near en un solo comando:
http post https://mainnet.aurora.dev/ jsonrpc=2.0 id=1 \method=eth_getTransactionReceipt \
params:=’[“0x4c2b8b5d766fe0411d0003bf4c9d2becc9d6dd7120272cf9f1a6cac73e4c3543”]’ \
| jq .result.nearTransactionHash | hex2b58
A partir del hash de la transacción Near, podemos obtener la cantidad de gas Near utilizado en la transacción a partir de la RPC Near:
http post https://archival-rpc.mainnet.near.org jsonrpc=2.0 id=dontcare \method=tx \
params:=’[ “46ACGRcUQadezAWQuZ9WVopSAbeeWpJZ1H8hmVuWPhJu
Donde el primer parámetro es el hash de la transacción Near obtenido del RPC de Aurora por el comando anterior. Hay un montón de datos devueltos de la respuesta, pero para nuestros propósitos, sólo nos importa el gas utilizado en la ejecución del motor de Aurora. Podemos aislar sólo esta parte de la respuesta usando jq:
http post https://archival-rpc.mainnet.near.org jsonrpc=2.0 id=dontcare \method=tx \
params:=’[ “46ACGRcUQadezAWQuZ9WVopSAbeeWpJZ1H8hmVuWPhJu”, “relay.aurora”]’ \
| jq ‘.result.receipts_outcome[0].outcome
Teniendo esto en cuenta, ¡es bastante fácil automatizar la obtención de los datos de EVM y Near gas de cualquier transacción de Aurora que queramos!
Resultados empíricos.
En lo que sigue, consideramos todas las transacciones de Aurora realizadas con éxito (es decir, ignorando fallos obvios como un nonce incorrecto — éstos serían valores atípicos en nuestros datos porque no realizan ninguna ejecución EVM real) desde el 4 de junio de 2023 (altura del bloque 93442283) hasta el 12 de junio de 2023 (altura del bloque 94047083). A continuación se muestra un gráfico del gas EVM frente al gas Near. Los números Near se han escalado por 10¹² ya que Tgas es la unidad común en la que se presentan los valores Near gas, y los 3 EVM se han escalado por 10³ ya que el menor EVM gas posible es 2100.
Como era de esperar, existe una fuerte correlación lineal entre los valores. Aunque, curiosamente, hay (al menos) 3 líneas distintas en lugar de una sola.
La línea con la pendiente menos pronunciada (línea naranja en el gráfico) corresponde a las transacciones con mucho almacenamiento (por ejemplo, despliegues de contratos). Estas transacciones utilizan mucho gas EVM pero no mucho gas Near. La razón es la diferencia entre cómo cobra el almacenamiento EVM y cómo lo cobra Near. En el EVM, el acceso al almacenamiento es bastante caro en términos de gas, pero hay un reembolso de gas cuando se libera el almacenamiento. Por otro lado, Near no cambia mucho gas por el acceso al almacenamiento, pero sí lo cobra a la cuenta en forma de staking de almacenamiento (la cuenta debe mantener un saldo mínimo de Near para que se le permita tener tanto almacenamiento utilizado). Esta diferencia en la forma de cobrar el almacenamiento significa que se utiliza una cantidad desproporcionadamente menor de gas Near para el almacenamiento en comparación con otros costes computacionales (por ejemplo, el acceso a la CPU y a la memoria).
La mayoría de los puntos del gráfico se sitúan en la línea más empinada (línea verde del gráfico), aunque hay mucha varianza a su alrededor. Si hacemos una regresión lineal de estos datos, determinamos que la pendiente media es de 0,122 aproximadamente. Esto nos proporciona una respuesta empírica a nuestra pregunta de cómo están relacionados el EVM y el gas Near en Near. Se gasta aproximadamente 1,22 x10⁸ de gas Near por cada gas EVM. De hecho, esta relación es la que informa del precio fijo del gas EVM establecido por los repetidores de Aurora. La relación entre el gas EVM y el gas Near nos permite convertir el precio del gas Near en un precio del gas EVM para cobrar a nuestros usuarios (por supuesto, la mayoría de los usuarios aprovechan la transacción gratuita disponible en AuroraPass y no se preocupan por los precios del gas de todos modos).
La línea roja del gráfico sigue un conjunto de puntos distintos entre las líneas “de almacenamiento intensivo” y “principal”. No sé qué tienen de especial estas transacciones, que hacen que utilicen menos gas Near que las de la línea de tendencia principal. Es difícil obtener información de alto nivel sobre las transacciones sólo a partir del conjunto de direcciones a las que llaman y la entrada binaria que envían. Una hipótesis podría ser que estas transacciones son literalmente un punto intermedio entre los dos extremos del gas, procedentes principalmente de los costes de la CPU y procedentes principalmente de los costes de almacenamiento. Podría haber algo en el algoritmo que implementan los contratos inteligentes de tal manera que la cantidad de acceso al almacenamiento que necesitan es proporcional a la cantidad de computación ligada a la CPU que realizan. Independientemente de la razón, esto puede ser información útil para que los desarrolladores de esos contratos sepan, ya que son capaces de completar transacciones con valores de gas EVM más altos que las transacciones en la línea principal.
Estos datos tienen consecuencias adicionales para los desarrolladores en Aurora. Por ejemplo, nuestra documentación menciona un caso límite de incompatibilidad entre Aurora y Ethereum mainnet en el que una transacción puede quedarse sin gas Near antes de quedarse sin gas EVM. Esto hace que la transacción falle en Aurora cuando pasaría en Ethereum. El límite de gas de transacción en Near (no existe tal concepto en Ethereum, sólo existe el límite de gas de bloque) es de 300 Tgas, lo que implica que este caso límite descrito en la documentación surge para transacciones EVM que superan aproximadamente 2,5 x 10⁶ de gas EVM. Esto supone que la transacción se encuentra en la línea de tendencia principal, aunque, como hemos comentado, existen otros tipos de transacciones con diferentes ratios de conversión Near/Gas EVM que pueden alcanzar valores de Gas EVM superiores.
Orientaciones futuras.
Para nosotros, en Aurora, este gráfico también nos proporciona una medida clara del rendimiento de nuestro motor. Nuestro objetivo es procesar las transacciones EVM de la forma más eficiente posible (es decir, utilizar la menor cantidad posible de gas Near por gas EVM), lo que corresponde a reducir la pendiente de la línea de tendencia principal en el gráfico de gas EVM frente a gas Near. Desde el lanzamiento de Aurora, hemos avanzado mucho en este sentido: una mejora de más de un factor 2 desde febrero de 2022 (Engine v2.4.0 frente a v2.9.0). Pero aún nos queda trabajo por hacer. Nos gustaría conseguir que la cantidad de gas EVM que cabe en 300 Near Tgas sea igual al límite de gas de bloque de Ethereum (30 x 10⁶ de gas EVM) para que nuestros desarrolladores ya no tengan que preocuparse por el caso límite comentado anteriormente. Porque, en este caso, estaremos seguros de que ninguna transacción EVM que tenga éxito en la red principal de Ethereum puede superar los 300TGas en Near. Volviendo al argumento teórico de antes, sabemos que deberíamos ser capaces de mejorar la eficiencia del motor cambiando los detalles de implementación. En concreto, la sobrecarga de ejecutar un intérprete EVM debe contribuir al coste de gas de Near de forma significativa.
Nuestra próxima innovación hacia este objetivo es desarrollar un compilador de EVM a Wasm. Este compilador permitirá ejecutar directamente contratos EVM en el tiempo de ejecución Near, en lugar de tener que interpretarlos en un EVM virtualizado. Algunos datos de evaluación comparativa sugieren que deberíamos ser capaces de obtener mejoras de rendimiento de órdenes de magnitud utilizando este tipo de enfoque.
Sigue las cuentas de Aurora y la comunidad de Aurora en Español
Twitter oficial de Aurora: @auroraisnear
Twitter oficial de Aurora Venezuela: @venezuelaaurora
Canal YouTube Mundo Aurora: @mundo_aurora
NEAR Social: mundoaurora.near
Telegram oficial AuroraESNear: @venezuelaaurora
Telegram canal de Noticias AuroraESNear