Aurora Silo: una descripción general del código

NEAR_ES
8 min readJun 27, 2023

Artículo original publicado en Aurora Developers: Aurora Silo: Code Overview Traducido por Francisco 27/Junio/2023

Por ahora, solo recordemos que Aurora Silo es simplemente el motor de Aurora con algunas nuevas características adicionales: consulte la sección “¿Qué son los Silos?”, en Aurora Cloud: Recorrido por Silo. Echemos un vistazo más de cerca al repositorio del motor de Aurora para encontrar el código de Silo.

El código fuente se encuentra dentro de la solicitud de extracción (PR) #746: feat: agregar la posibilidad de usar un costo de gas fijo (silo). La primera pregunta que surge es por qué se llama así. La pista se encuentra en la descripción de inmediato y nos lleva a la primera característica:

La solicitud de extracción (PR) agrega la posibilidad de establecer un costo de gas fijo por transacción EVM. Esta característica se puede activar llamando a set_fixed_gas_cost.

La segunda característica es el control de acceso, que se logra mediante los cuatro tipos de listas blancas para regular los derechos de implementar código y enviar transacciones.

Ahora, echemos un vistazo más de cerca a la propia solicitud de extracción (PR) y lo que realmente es Silo.

Primero, echamos un vistazo a las carpetas en las que los desarrolladores han realizado cambios en los archivos:

La carpeta “engine-standalone-storage” no debería preocuparte, ya que es más bien una entrada y salida (IO) para el motor, definitivamente no es la parte principal. En cuanto a “engine-tests” y “engine-types”, no son críticos para entender, pero pueden brindarte algunas ideas sobre los detalles, pues, como todos sabemos, las pruebas y los tipos son fundamentales para un código que funciona correctamente. Por lo tanto, la única carpeta restante es “engine”, y esa es la suposición correcta para investigar:

Esta carpeta es el corazón del repositorio y de Aurora en sí mismo. En su interior veremos algunos archivos del Engine modificados, entre los cuales engine.rs y lib.rs son los más importantes. Además, debemos destacar la carpeta src/silo. ¡Eso es exactamente lo que estábamos buscando!

Importaciones de módulos Silo

El motor de Aurora está escrito en Rust, el lenguaje nativo para los contratos NEAR. En nuestro caso, el punto de entrada principal al módulo Silo es el archivo mod.rs, que es la parte central del módulo. A su vez, también depende de dos submódulos: parameters.rs y whitelist.rs:

Comencemos revisando el archivo parameters.rs.

parameters.rs

Este archivo contiene todas las estructuras y enumeraciones de los argumentos de función importantes para Silo. La razón de tenerlos aquí es separar los argumentos de la implementación: será más fácil cambiarlos en un solo lugar más adelante y dejar las implementaciones de las funciones como están. El archivo comienza importando algunos tipos útiles, traits y el enum WhitelistKind:

Tipos de Listas Blancas (Whitelist Kinds) WhitelistKind puede ser uno de los cuatro tipos, puedes encontrar la definición en whitelist.rs:

Podemos incluir usuarios en la lista blanca utilizando una cuenta de NEAR o una dirección de Aurora. La dirección de EVM es propia del usuario, pero la situación es más complicada con la cuenta de NEAR, ya que se trata de la cuenta desde la cual las transacciones del motor se envían al nodo de NEAR (es decir, es la cuenta de un retransmisor). Esta cuenta pagará el gas de NEAR en nombre del usuario.

Para comprender mejor esta parte, echa un vistazo a esta imagen que ilustra cómo funciona Aurora en general:

El RPC en la imagen de arriba es nuestra instancia de Relayer (incluye RPC, relayer y refiner, pero eso es tema para otro artículo). En la base del triángulo tenemos el nodo NEAR y el contrato del motor. Por lo tanto, es la dirección del vértice superior la que filtramos con las listas blancas de cuentas.

Para continuar con los tipos de lista blanca, tenemos otra dimensión para incluir usuarios: permitir el despliegue de nuevos contratos o permitirles realizar transacciones. Podemos hacer esto más claro utilizando esta tabla (con la excepción de que un administrador también puede editar las listas blancas):

Whitelist Args

La parte principal de parameters.rs está relacionada con los argumentos de las listas blancas de diferentes tipos:

También hay una pequeña prueba al final del archivo con la serialización de los argumentos de las listas blancas utilizando Borsh. Omitiré el código por brevedad.

Whitelist (Listas Blancas)

Pasemos al segundo archivo: whitelists.rs. Ya hemos visto una parte de él anteriormente: el enum WhitelistKind.

Importaciones Ahora, echemos un vistazo a las importaciones que se encuentran dentro del archivo:

Aurora Engine SDK es una forma de FFI (interfaz de programación de funciones) para escribir un contrato NEAR en Rust, lo cual merece un artículo separado, por lo que no nos concentraremos en ello. Lo importamos para comunicarnos con el almacenamiento de NEAR, que es simplemente una base de datos clave-valor. Para generar una clave para los datos a almacenar, utilizamos la función bytes_to_key y KeyPrefix. También tenemos el trait AsBytes para ayudarnos a interpretar cosas como una matriz de bytes.

Tipo de lista blanca (Whitelist)

Veamos ahora el tipo Whitelist:

He omitido los cuerpos de las funciones por brevedad, en general, simplemente trabajan con el almacenamiento y obtienen/establecen pares clave-valor. Como puedes ver, podemos separar los métodos de Whitelist en dos grupos principales: Estado (Status) y Entradas (Entries). El primer grupo se utiliza para habilitar o deshabilitar la lista blanca y verificar su estado. El campo de estado nos indica si la lista blanca será utilizada por un silo o no. El prefijo especial, definido por la variable STATUS, se utiliza para generar una clave para almacenar este campo.

El grupo de Entradas se utiliza para agregar, eliminar o verificar la inclusión de un elemento en la lista blanca. Este elemento puede ser cualquier cosa, definida por el tipo A aquí, que implemente el trait AsBytes.

Almacenamiento (Storage) y funciones de clave (Key)

La lista blanca también está parametrizada por un tipo I:IO para permitir diferentes formas de interacciones de IO. Observa que es un tipo especial de trait IO y no std::io. El trait IO es parte de Aurora Engine SDK, creado para escribir contratos NEAR con FFI, por lo que funciona con almacenamientos de clave-valor (como el almacenamiento de NEAR).

Esta es la razón por la cual la función key es el núcleo de la estructura Whitelist: porque depende en gran medida del almacenamiento. Echemos un vistazo más de cerca a ella:

Como puedes ver, se basa en la función bytes_to_key y une el byte de prefijo del tipo a su valor (en bytes), y agrega un KeyPrefix especial para la Whitelist que se utiliza para diferenciar diferentes partes del almacenamiento en Aurora Engine.

La última parte del archivo incluye dos funciones para operar con el estado de la lista blanca, pero utilizando WhitelistStatusArgs, que actualmente incluye el campo active : bool y WhitelistKind:

Estas funciones son útiles para operar en cualquier tipo de Whitelist sin tener una instancia de la misma.

Módulo Silo

Podemos dividir las funciones públicas de este módulo en dos grupos: Whitelists y Fixed Gas. El primero se encarga de editar las listas blancas y verificar los derechos de los usuarios. Y el segundo, de almacenar el precio de gas fijo para las transacciones dentro del silo.

Whitelists

Comencemos con las Whitelists. Este grupo también se puede dividir en 3 subgrupos: Entries, Status y Rights. El subgrupo Entries se trata de agregar/eliminar entradas de las listas blancas:

El segundo subgrupo, Status, se utiliza para obtener/establecer el estado de las listas blancas:

Y el último subgrupo, Rights, es el más interesante:

¿Por qué? Porque es el primer lugar en el código donde vemos que las listas blancas de cuentas NEAR actúan en pareja con las direcciones EVM. Si echamos un vistazo a la función is_allow_deploy:

Tiene comprobaciones tanto para las cuentas como para las direcciones, y la razón de esto es que la dirección EVM firma la transacción EVM y luego el relayer debe envolverla en la transacción NEAR y firmarla con su cuenta NEAR, como hemos discutido anteriormente al hablar sobre el WhitelistKind.

Fixed Gas

Este grupo es bastante simple y simplemente almacena el campo fixed_gas_cost o lo recupera del almacenamiento:

El precio se utiliza dentro de Aurora Engine en la función submit aquí y en la función charge_gas aquí, al enviar la transacción EVM al motor. Discutiremos esta parte del código con más detalle en nuestro próximo artículo sobre los silos.

El fixed_gas_cost podría establecerse por un administrador del silo que interactúa directamente con un contrato de silo en la red NEAR y llama al método set_fixed_gas_cost aquí.

Conclusiones

Hemos revisado una solicitud de extracción que introduce los silos dentro del repositorio de Aurora Engine. Ahora sabemos que en el interior de un Silo tenemos partes de control de acceso y costo de gas fijo ocultas. Discutiremos las conexiones externas del Silo en futuros artículos. También cubriremos cómo los métodos del Silo afectan la mecánica del propio EVM.

¡Gracias por leer!

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 de Aurora Venezuela: @venezuelaaurora

Telegram canal de Noticias Aurora en Español

--

--

NEAR_ES

Espacio informativo y educativo sobre NEAR Protocol, Aurora, web3 y blockchain en Español para toda la comunidad