¿Alguna vez has querido saber más sobre cómo funciona Rollup? La teoría es buena, pero siempre es preferible la experiencia práctica. Desafortunadamente, los proyectos existentes no siempre hacen que sea fácil ver lo que está pasando. Es por eso que creamos BYOR (Build Your Own Rollup). Es un rollup soberano con una funcionalidad mínima, con un enfoque en hacer que el código sea fácil de leer y entender.
Nuestra motivación para este proyecto es que las personas, tanto de afuera como de adentro, entiendan mejor lo que realmente están haciendo los rollups que nos rodean. Puedes jugar con el BYOR desplegado de Holesky o leer el código fuente en GitHub.
¿Qué es BYOR?
El proyecto BYOR es una versión simplificada del resumen soberano. A diferencia de las pruebas optimistas y de conocimiento cero de los rollups, los rollups soberanos no validan las raíces estatales en Ethereum y se basan únicamente en la disponibilidad de datos y el consenso en Ethereum. Esto evita los puentes de minimización de confianza entre L1 y BYOR, pero simplifica enormemente el código y es ideal para fines educativos.
El código base consta de tres programas: contratos inteligentes, nodos y billeteras. Cuando se implementan juntos, permiten a los usuarios finales interactuar con la red. Curiosamente, el estado de la red está determinado completamente por los datos en cadena, lo que significa que varios nodos pueden ejecutarse. Cada nodo también puede publicar datos de forma independiente como secuenciador.
Aquí está la lista completa de características implementadas en BYOR:
Clasificación de tarifas
Publicar el estado en L1 y obtener el estado de L1
Descartar transacciones no válidas
Consultar el saldo de la cuenta
Enviar transacciones
Comprobar el estado de la transacción
Usa la billetera
En una aplicación de billetera, actúa como el front-end de la red, donde los usuarios pueden enviar transacciones y verificar el estado de sus cuentas o el estado de las transacciones. En la página de destino, verá una descripción general que proporciona algunas estadísticas sobre el estado actual del paquete acumulativo, seguido del estado de su cuenta. Lo más probable es que solo haya un botón para conectarse a la billetera de su elección y haya noticias sobre el grifo de tokens. A continuación, hay una barra de búsqueda donde puede pegar la dirección de alguien o el hash de la transacción para explorar el estado actual de L2. Por último, hay dos listas de transacciones: la primera es la lista de transacciones en el mempool L2 y la segunda es la lista de transacciones publicadas en L1.
Para comenzar, use el botón WalletConnect para conectar su billetera. Una vez conectado, es posible que reciba una notificación de que su billetera está conectada a la red incorrecta. Si su aplicación admite la conmutación de red, haga clic en el botón Cambiar red para cambiar a la red de prueba de Holesky. De lo contrario, cambie manualmente.
Ahora puede enviar tokens a alguien proporcionando la dirección del destinatario, la cantidad de tokens a enviar y las tarifas requeridas. Una vez enviado, la aplicación de billetera le pedirá que firme el mensaje. Si se firma correctamente, el mensaje se envía al grupo de memoria del nodo L2, a la espera de que se publique en L1. El tiempo que tarda una transacción en agruparse en una versión por lotes puede variar. Cada 10 segundos, el nodo L2 comprueba si se va a publicar contenido. Las transacciones con tarifas más altas se envían primero, por lo que si especifica tarifas más bajas y tiene mucho tráfico de transacciones, es posible que experimente largos tiempos de espera.
Cómo funciona
Diagrama de arquitectura acumulativa ## pila de tecnología
Construimos cada componente utilizando las siguientes técnicas:
El código BYOR está diseñado para ser fácilmente entendido mirando la base de código. ¡Siéntete libre de explorar nuestra base de código! Primero lea README.md, para comprender la estructura del proyecto, lea el archivo ARCHITECTURE.md.
Estos son algunos aspectos interesantes del código:
Contratos inteligentes
Identificador de licencia SPDX: MIT
solidez del pragma ^0.8.0;
contrato Insumos {
evento BatchAppended(remitente de la dirección);
function appendBatch(bytes calldata) external {
require(msg.sender == tx.origin);
emit BatchAppended(msg.sender);
}
}
Este es el único contrato inteligente necesario. Su nombre deriva del hecho de que las entradas se almacenan en funciones de transición de estado. El único propósito de este contrato es almacenar convenientemente todas las transacciones. El lote serializado se publica en este contrato inteligente como calldata y emite un evento BatchAppended con la dirección del publicador del lote. Si bien podemos diseñar el sistema para que publique transacciones directamente en EOA en lugar de contratos, los datos se pueden obtener fácilmente a través de JSON-RPC mediante la emisión de eventos. El único requisito para este contrato inteligente es que no debe ser llamado desde otro contrato inteligente, sino directamente desde EOA.
Esquema de base de datos
CREAR cuentas TABLE (
texto de la dirección CLAVE PRINCIPAL NO NULA,
balance entero DEFAULT 0 NOT NULL,
nonce entero DEFAULT 0 NOT NULL
);
Transacciones CREATE TABLE (
id entero,
del texto NOT NULL,
al texto NOT NULL,
valor entero NOT NULL,
nonce entero NO NULO,
El entero de la tarifa NO NULO,
feeReceipent text NOT NULL,
l1SubmittedDate entero NOT NULL,
hash text NOT NULL
CLAVE PRIMARIA (desde, nonce)
);
-- Esta tabla tiene una sola fila
CREATE TABLE fetcherStates (
chainId integer PRIMARY KEY NOT NULL,
lastFetchedBlock entero DEFAULT 0 NOT NULL
);
Este es el esquema completo de la base de datos que se usa para almacenar información sobre el paquete acumulativo. Quizás se pregunte por qué necesitamos una base de datos cuando todos los datos necesarios se almacenan en L1. Si bien esto es cierto, almacenar datos localmente puede ahorrar tiempo y recursos al evitar adquisiciones duplicadas. Trate todos los datos almacenados en este esquema como notas de estado, hashes de transacción y otra información calculada.
La tabla fetcherStates se usa para realizar un seguimiento del último bloque que obtuvimos al buscar el evento BatchAppended. Esto es útil cuando el nodo se apaga y se reinicia; Sabe dónde reanudar la búsqueda.
Las funciones que se muestran arriba están en el corazón del mecanismo de transición de estado en BYOR. Asume que la transacción se puede ejecutar de forma segura, con el nonce correcto y el saldo suficiente para realizar el pago definido. Debido a esta suposición, no hay pasos de validación o control de errores dentro de esta función. En su lugar, estos pasos se realizan antes de llamar a la función. Cada estado de la cuenta se almacena en un mapa. Si una cuenta aún no existe en esta asignación, se establecerá en el valor predeterminado visible en la parte superior de la lista de código. De las tres cuentas utilizadas, se actualiza el nonce y se asigna el saldo.
Firma de transacciones
Firma de transacción: Utilizamos el estándar EIP-712 para firmar datos escritos. Esto nos permite mostrar claramente a los usuarios lo que están firmando. Como se muestra arriba, al enviar una transacción, podemos mostrar el destinatario, el monto y la tarifa de una manera fácil de usar.
Obtención del evento L1
función getNewStates() {
const lastBatchBlock = getLastBatchBlock()
const events = getLogs(lastBatchBlock)
const calldata = getCalldata(eventos)
const timestamps = getTimestamps(eventos)
const posters = getTransactionPosters(eventos)
updateLastFetchedBlock(lastBatchBlock)
Zip de retorno (carteles, marcas de tiempo, datos de llamadas)
}
Para obtener el nuevo evento, recuperamos todos los eventos BatchAppended del último bloque recuperado del contrato de entradas. El número máximo de eventos que recuperamos es el fragmento más reciente o el último fragmento recuperado más el límite de tamaño del lote. Después de recuperar todos los eventos, extraemos los datos de llamada, la marca de tiempo y la dirección del editor de cada transacción. Actualice el último bloque que obtenemos al último bloque que estamos obteniendo. A continuación, los datos de llamada, la marca de tiempo y el publicador extraídos se empaquetan juntos y se devuelven desde la función para su posterior procesamiento.
Grupos de memoria y su clasificación de costos
function popNHighestFee(txPool, n) {
txPool.sort((a, b) => b.fee - a.fee))
return txPool.splice(0, n)
}
Un mempool es un objeto que administra una matriz de transacciones firmadas. El aspecto más interesante es cómo determina el orden en el que se registran las transacciones en L1. Como se muestra en el código anterior, las transacciones se ordenan según sus tarifas. Esto permite que el precio medio de la tarifa en el sistema fluctúe en función de la actividad en la cadena.
Incluso si especifica tarifas altas, las transacciones aún deben producir un estado válido si es necesario anexarlas al estado actual. Por lo tanto, no puede enviar transacciones no válidas solo por las altas tarifas.
¿BYOR realmente escala Ethereum?
Optimism y ZK rollup han creado sistemas para demostrar que las raíces estatales publicadas son consistentes con las funciones de transición de estado y los datos que comprometen, pero las acumulaciones soberanas no lo hacen. Por lo tanto, la incapacidad de este tipo de rollup para escalar Ethereum puede parecer contradictoria al principio. Sin embargo, esto se vuelve razonable cuando nos damos cuenta de que otros tipos de resúmenes solo pueden usar L1 para demostrar que la raíz de estado publicada es correcta. Para distinguir si los datos del rollup soberano son correctos o no, necesitamos ejecutar un nodo L1 junto con software adicional para formalizar el nodo L2 para realizar funciones de transición de estado, aumentando así la carga computacional.
Perspectivas de futuro
La construcción de este proyecto fue una gran experiencia de aprendizaje para nosotros, y esperamos que nuestros esfuerzos también sean valiosos. Esperamos volver a BYOR en el futuro y añadirle un sistema a prueba de fraudes. Esto lo convertirá en un resumen verdaderamente optimista y, una vez más, en una lección sobre el funcionamiento interno de los sistemas que usamos todos los días.
Ver originales
Esta página puede contener contenido de terceros, que se proporciona únicamente con fines informativos (sin garantías ni declaraciones) y no debe considerarse como un respaldo por parte de Gate a las opiniones expresadas ni como asesoramiento financiero o profesional. Consulte el Descargo de responsabilidad para obtener más detalles.
Construya su propio Rollup: una lista de proyectos BYOR
Compilación: Plan de traducción de Denlink
¿Alguna vez has querido saber más sobre cómo funciona Rollup? La teoría es buena, pero siempre es preferible la experiencia práctica. Desafortunadamente, los proyectos existentes no siempre hacen que sea fácil ver lo que está pasando. Es por eso que creamos BYOR (Build Your Own Rollup). Es un rollup soberano con una funcionalidad mínima, con un enfoque en hacer que el código sea fácil de leer y entender.
Nuestra motivación para este proyecto es que las personas, tanto de afuera como de adentro, entiendan mejor lo que realmente están haciendo los rollups que nos rodean. Puedes jugar con el BYOR desplegado de Holesky o leer el código fuente en GitHub.
¿Qué es BYOR?
El proyecto BYOR es una versión simplificada del resumen soberano. A diferencia de las pruebas optimistas y de conocimiento cero de los rollups, los rollups soberanos no validan las raíces estatales en Ethereum y se basan únicamente en la disponibilidad de datos y el consenso en Ethereum. Esto evita los puentes de minimización de confianza entre L1 y BYOR, pero simplifica enormemente el código y es ideal para fines educativos.
El código base consta de tres programas: contratos inteligentes, nodos y billeteras. Cuando se implementan juntos, permiten a los usuarios finales interactuar con la red. Curiosamente, el estado de la red está determinado completamente por los datos en cadena, lo que significa que varios nodos pueden ejecutarse. Cada nodo también puede publicar datos de forma independiente como secuenciador.
Aquí está la lista completa de características implementadas en BYOR:
Usa la billetera
En una aplicación de billetera, actúa como el front-end de la red, donde los usuarios pueden enviar transacciones y verificar el estado de sus cuentas o el estado de las transacciones. En la página de destino, verá una descripción general que proporciona algunas estadísticas sobre el estado actual del paquete acumulativo, seguido del estado de su cuenta. Lo más probable es que solo haya un botón para conectarse a la billetera de su elección y haya noticias sobre el grifo de tokens. A continuación, hay una barra de búsqueda donde puede pegar la dirección de alguien o el hash de la transacción para explorar el estado actual de L2. Por último, hay dos listas de transacciones: la primera es la lista de transacciones en el mempool L2 y la segunda es la lista de transacciones publicadas en L1.
Para comenzar, use el botón WalletConnect para conectar su billetera. Una vez conectado, es posible que reciba una notificación de que su billetera está conectada a la red incorrecta. Si su aplicación admite la conmutación de red, haga clic en el botón Cambiar red para cambiar a la red de prueba de Holesky. De lo contrario, cambie manualmente.
Ahora puede enviar tokens a alguien proporcionando la dirección del destinatario, la cantidad de tokens a enviar y las tarifas requeridas. Una vez enviado, la aplicación de billetera le pedirá que firme el mensaje. Si se firma correctamente, el mensaje se envía al grupo de memoria del nodo L2, a la espera de que se publique en L1. El tiempo que tarda una transacción en agruparse en una versión por lotes puede variar. Cada 10 segundos, el nodo L2 comprueba si se va a publicar contenido. Las transacciones con tarifas más altas se envían primero, por lo que si especifica tarifas más bajas y tiene mucho tráfico de transacciones, es posible que experimente largos tiempos de espera.
Cómo funciona
Construimos cada componente utilizando las siguientes técnicas:
Desglose del código
El código BYOR está diseñado para ser fácilmente entendido mirando la base de código. ¡Siéntete libre de explorar nuestra base de código! Primero lea README.md, para comprender la estructura del proyecto, lea el archivo ARCHITECTURE.md.
Estos son algunos aspectos interesantes del código:
Contratos inteligentes
Identificador de licencia SPDX: MIT
solidez del pragma ^0.8.0;
contrato Insumos {
evento BatchAppended(remitente de la dirección);
function appendBatch(bytes calldata) external {
require(msg.sender == tx.origin);
emit BatchAppended(msg.sender);
}
}
Este es el único contrato inteligente necesario. Su nombre deriva del hecho de que las entradas se almacenan en funciones de transición de estado. El único propósito de este contrato es almacenar convenientemente todas las transacciones. El lote serializado se publica en este contrato inteligente como calldata y emite un evento BatchAppended con la dirección del publicador del lote. Si bien podemos diseñar el sistema para que publique transacciones directamente en EOA en lugar de contratos, los datos se pueden obtener fácilmente a través de JSON-RPC mediante la emisión de eventos. El único requisito para este contrato inteligente es que no debe ser llamado desde otro contrato inteligente, sino directamente desde EOA.
Esquema de base de datos
CREAR cuentas TABLE (
texto de la dirección CLAVE PRINCIPAL NO NULA,
balance entero DEFAULT 0 NOT NULL,
nonce entero DEFAULT 0 NOT NULL
);
Transacciones CREATE TABLE (
id entero,
del texto NOT NULL,
al texto NOT NULL,
valor entero NOT NULL,
nonce entero NO NULO,
El entero de la tarifa NO NULO,
feeReceipent text NOT NULL,
l1SubmittedDate entero NOT NULL,
hash text NOT NULL
CLAVE PRIMARIA (desde, nonce)
);
-- Esta tabla tiene una sola fila
CREATE TABLE fetcherStates (
chainId integer PRIMARY KEY NOT NULL,
lastFetchedBlock entero DEFAULT 0 NOT NULL
);
Este es el esquema completo de la base de datos que se usa para almacenar información sobre el paquete acumulativo. Quizás se pregunte por qué necesitamos una base de datos cuando todos los datos necesarios se almacenan en L1. Si bien esto es cierto, almacenar datos localmente puede ahorrar tiempo y recursos al evitar adquisiciones duplicadas. Trate todos los datos almacenados en este esquema como notas de estado, hashes de transacción y otra información calculada.
La tabla fetcherStates se usa para realizar un seguimiento del último bloque que obtuvimos al buscar el evento BatchAppended. Esto es útil cuando el nodo se apaga y se reinicia; Sabe dónde reanudar la búsqueda.
Funciones de transición de estado
const DEFAULT_ACCOUNT = { balance: 0, nonce: 0 }
function uteTransaction(state, tx, feeRecipient) {
const fromAccount = getAccount(state, tx.from, DEFAULT_ACCOUNT)
const toAccount = getAccount(state, tx.to, DEFAULT_ACCOUNT)
Paso 1 Actualizar nonce
fromAccount.nonce = tx.nonce
Paso 2: Transferir valor
fromAccount.balance -= tx.value
toAccount.balance += tx.value
Paso 3 Pagar la tarifa
fromAccount.balance -= tx.fee
feeRecipientAccount.balance += tx.fee
}
Las funciones que se muestran arriba están en el corazón del mecanismo de transición de estado en BYOR. Asume que la transacción se puede ejecutar de forma segura, con el nonce correcto y el saldo suficiente para realizar el pago definido. Debido a esta suposición, no hay pasos de validación o control de errores dentro de esta función. En su lugar, estos pasos se realizan antes de llamar a la función. Cada estado de la cuenta se almacena en un mapa. Si una cuenta aún no existe en esta asignación, se establecerá en el valor predeterminado visible en la parte superior de la lista de código. De las tres cuentas utilizadas, se actualiza el nonce y se asigna el saldo.
Firma de transacciones
Obtención del evento L1
función getNewStates() {
const lastBatchBlock = getLastBatchBlock()
const events = getLogs(lastBatchBlock)
const calldata = getCalldata(eventos)
const timestamps = getTimestamps(eventos)
const posters = getTransactionPosters(eventos)
updateLastFetchedBlock(lastBatchBlock)
Zip de retorno (carteles, marcas de tiempo, datos de llamadas)
}
Para obtener el nuevo evento, recuperamos todos los eventos BatchAppended del último bloque recuperado del contrato de entradas. El número máximo de eventos que recuperamos es el fragmento más reciente o el último fragmento recuperado más el límite de tamaño del lote. Después de recuperar todos los eventos, extraemos los datos de llamada, la marca de tiempo y la dirección del editor de cada transacción. Actualice el último bloque que obtenemos al último bloque que estamos obteniendo. A continuación, los datos de llamada, la marca de tiempo y el publicador extraídos se empaquetan juntos y se devuelven desde la función para su posterior procesamiento.
Grupos de memoria y su clasificación de costos
function popNHighestFee(txPool, n) {
txPool.sort((a, b) => b.fee - a.fee))
return txPool.splice(0, n)
}
Un mempool es un objeto que administra una matriz de transacciones firmadas. El aspecto más interesante es cómo determina el orden en el que se registran las transacciones en L1. Como se muestra en el código anterior, las transacciones se ordenan según sus tarifas. Esto permite que el precio medio de la tarifa en el sistema fluctúe en función de la actividad en la cadena.
Incluso si especifica tarifas altas, las transacciones aún deben producir un estado válido si es necesario anexarlas al estado actual. Por lo tanto, no puede enviar transacciones no válidas solo por las altas tarifas.
¿BYOR realmente escala Ethereum?
Optimism y ZK rollup han creado sistemas para demostrar que las raíces estatales publicadas son consistentes con las funciones de transición de estado y los datos que comprometen, pero las acumulaciones soberanas no lo hacen. Por lo tanto, la incapacidad de este tipo de rollup para escalar Ethereum puede parecer contradictoria al principio. Sin embargo, esto se vuelve razonable cuando nos damos cuenta de que otros tipos de resúmenes solo pueden usar L1 para demostrar que la raíz de estado publicada es correcta. Para distinguir si los datos del rollup soberano son correctos o no, necesitamos ejecutar un nodo L1 junto con software adicional para formalizar el nodo L2 para realizar funciones de transición de estado, aumentando así la carga computacional.
Perspectivas de futuro
La construcción de este proyecto fue una gran experiencia de aprendizaje para nosotros, y esperamos que nuestros esfuerzos también sean valiosos. Esperamos volver a BYOR en el futuro y añadirle un sistema a prueba de fraudes. Esto lo convertirá en un resumen verdaderamente optimista y, una vez más, en una lección sobre el funcionamiento interno de los sistemas que usamos todos los días.