Ayer mismo, ocurrió un evento impactante: Linea, la solución Ethereum Capa 2 desarrollada por Consensys, la empresa matriz de Metamask, fue cerrada de manera proactiva. La razón oficial dada fue mitigar el impacto del incidente de piratería de Velocore. Este incidente inevitablemente trae a la mente un caso anterior en el que la cadena BSC (BNB Chain) también se cerró bajo coordinación oficial para minimizar las pérdidas por piratería. Estos acontecimientos suelen llevar a la gente a cuestionar los valores descentralizados que defiende la Web3.
La razón principal detrás de los eventos mencionados radica en la imperfección de la infraestructura, específicamente en su falta de descentralización. Si una cadena de bloques estuviera lo suficientemente descentralizada, no debería poder cerrarse tan fácilmente. Debido a la estructura única de Ethereum Capa 2, la mayoría de las soluciones Capa 2 se basan en secuenciadores centralizados. A pesar del creciente discurso sobre los secuenciadores descentralizados en los últimos años, dado el propósito y la estructura de la Capa 2, podemos suponer que es poco probable que los secuenciadores de la Capa 2 alcancen altos niveles de descentralización. De hecho, pueden terminar siendo menos descentralizados que la cadena BSC. Si este es el caso, ¿qué se puede hacer? Para la capa 2, los riesgos más inmediatos de los secuenciadores no descentralizados son la falta de resistencia a la censura y la vida. Si solo hay unas pocas entidades que procesan transacciones (secuenciadores), tienen poder absoluto sobre si servirle o no: pueden rechazar sus transacciones a voluntad, dejándolo sin recurso. Abordar el problema de la resistencia a la censura en la Capa 2 es claramente un tema importante. En los últimos años, varias soluciones Ethereum Capa 2 han propuesto diferentes enfoques para abordar este problema. Por ejemplo, Loopring, Degate y StarkEx han introducido funciones de retirada forzada y escotilla de escape, mientras que Arbitrum y otros Optimistic Rollups han implementado funciones de inclusión forzada. Estos mecanismos pueden imponer controles a los secuenciadores para evitar el rechazo arbitrario de las transacciones de los usuarios. En el artículo de hoy, NIC Lin de la Asociación Ethereum de Taipei comparte su experiencia de primera mano, experimentando con las características de transacción resistentes a la censura de cuatro Rollups principales y proporcionando un análisis en profundidad del mecanismo de inclusión de fuerza, centrándose en el flujo de trabajo y los métodos operativos. Este análisis es especialmente valioso para la comunidad de Ethereum y los grandes tenedores de activos.
La censura resistencia en las transacciones es crucial para cualquier cadena de bloques. Si una cadena de bloques puede censurar y rechazar arbitrariamente las transacciones de los usuarios, no es diferente de un servidor Web2. La resistencia a la censura de las transacciones de Ethereum está actualmente garantizada por sus numerosos validadores. Si alguien quiere censurar la transacción de Bob y evitar que se incluya en la cadena de bloques, tendría que sobornar a la mayoría de los validadores de la red o enviar spam a la red con transacciones basura que tienen tarifas más altas que las de Bob, ocupando así espacio en bloque. Ambos métodos son extremadamente costosos.
Nota: En la arquitectura actual de separación entre proponentes y constructores (PBS) de Ethereum, el costo de censurar las transacciones se reduce significativamente. Por ejemplo, puedes ver la proporción de bloques que cumplen con la censura de la OFAC de las transacciones de Tornado Cash. La resistencia a la censura actual se basa en validadores y relés independientes que están fuera de la jurisdicción de la OFAC y otras entidades gubernamentales.
Pero, ¿qué pasa con los Rollups? Los rollups no requieren un gran número de validadores para garantizar la seguridad. Incluso si un Rollup tiene solo una entidad centralizada (secuenciador) que produce bloques, sigue siendo tan seguro como la capa 1 (L1). Sin embargo, la seguridad y la resistencia a la censura son dos asuntos diferentes. Un Rollup, aunque es tan seguro como Ethereum, aún puede censurar la transacción de cualquier usuario si solo tiene un secuenciador centralizado.
Sequencer puede negarse a procesar la transacción de un usuario, lo que hace que los fondos del usuario se bloqueen y no puedan salir del Rollup.
En lugar de requerir que los Rollups tengan una gran cantidad de secuenciadores descentralizados, es más efectivo aprovechar directamente el resistencia a la censura de la Capa 1 (L1):
Dado que el secuenciador necesita empaquetar los datos de la transacción y enviarlos al contrato Rollup en L1, podemos agregar una característica en el contrato que permita a los usuarios insertar sus transacciones en el contrato Rollup ellos mismos. Este mecanismo se conoce como "Inclusión de la Fuerza". Tan largo como el secuenciador no puede censurar a los usuarios en el nivel L1, no puede evitar que los usuarios inserten transacciones por la fuerza en L1. De esta manera, el Rollup puede heredar la resistencia a la censura de L1.
Sequencer no puede revisar las transacciones L1 del usuario sin pagar un alto costo
Si se permite que las transacciones se escriban directamente en el contrato Rollup a través de la inclusión forzada (lo que significa que entran en vigor inmediatamente), el estado del Rollup cambiará al instante. Por ejemplo, si Bob usa el mecanismo de inclusión forzada para insertar una transacción que transfiere 1000 DAI a Carol y la transacción surte efecto inmediatamente, el saldo de Bob disminuiría en 1000 DAI, mientras que el saldo de Carol aumentaría en 1000 DAI en el estado actualizado.
Si la inclusión forzada permite que las transacciones se escriban directamente en el contrato consolidado y surtan efecto inmediatamente, el estado del resumen cambiaría instantáneamente. Si el secuenciador está recopilando simultáneamente transacciones off-chain y preparándose para enviar el siguiente lote al contrato Rollup, podría verse interrumpido por la transacción insertada a la fuerza de Bob que tiene efecto inmediato. Para evitar este problema, los resúmenes generalmente no permiten que las transacciones de inclusión forzada surtan efecto inmediatamente. En su lugar, los usuarios insertan inicialmente sus transacciones en una cola de espera en L1, donde entran en un estado de "preparación". Cuando el secuenciador empaqueta transacciones off-chain para enviarlas al contrato Rollup, puede elegir si desea incluir estas transacciones en cola. Si el secuenciador ignora continuamente las transacciones en el estado de "preparación", una vez que finaliza el período de ventana, los usuarios pueden forzar la inserción de estas transacciones en el contrato consolidado. El secuenciador puede decidir cuándo incluir "incidentalmente" las transacciones de la cola de espera, pero aún puede negarse a procesarlas. Si el secuenciador se niega sistemáticamente, después de un cierto período, cualquiera puede usar la función Forzar inclusión para forzar la inserción de las transacciones en el contrato Rollup. A continuación, presentaremos la implementación del mecanismo Force Inclusion en cuatro Rollups destacados: Optimism, Arbitrum, StarkNet y zkSync.
El secuenciador puede elegir cuándo obtener transacciones de la cola de espera.
Los secuenciadores aún pueden negarse a procesar transacciones en la cola de espera.
Si el secuenciador se niega sistemáticamente a procesar transacciones, después de un período determinado, cualquiera puede usar la función Forzar inclusión para insertar transacciones a la fuerza en el contrato Rollup. A continuación, presentaremos cómo se implementa el mecanismo Force Inclusion en cuatro Rollups destacados: Optimism, Arbitrum, StarkNet y zkSync.
En primer lugar, analicemos el proceso de depósito de Optimism. Este proceso de depósito implica no solo transferir fondos a Optimism, sino también enviar "mensajes de usuario a L2". Cuando un nodo L2 recibe un mensaje recién depositado, convierte el mensaje en una transacción L2 y la ejecuta, entregándola al destinatario especificado.
Mensajes de usuario depositados de L1 a L2
Contrato L1CrossDomainMessenger
Cuando un usuario quiere depositar ETH o ERC-20 tokens en Optimism, interactúa con el contrato L1StandardBridge en L1 a través de una página web de frontend, especificando la cantidad a depositar y la dirección L2 que recibirá estos activos. A continuación, el contrato L1StandardBridge reenvía el mensaje al contrato L1CrossDomainMessenger, que actúa como puente de comunicación principal entre L1 y L2. L1StandardBridge utiliza este componente de comunicación para interactuar con L2StandardBridge en L2, determinando quién puede acuñar tokens en L2 o desbloquear tokens de L1. Los desarrolladores que necesiten crear contratos que interoperen y sincronicen estados entre L1 y L2 pueden crearlos sobre el contrato L1CrossDomainMessenger.
Mensajes de usuario transmitidos de L1 a L2 a través del contrato CrossDomainMessenger
Nota: En algunas imágenes de este artículo, CrossDomainMessenger se escribe como CrossChainMessenger.
Contrato de OptimismPortal
A continuación, el contrato L1CrossDomainMessenger reenvía el mensaje a la capa inferior, el contrato OptimismPortal. Después de procesar el mensaje, el contrato de OptimismPortal emite un evento llamado TransactionDeposited, que incluye parámetros como el "remitente", el "receptor" y otros detalles de ejecución relevantes. Los nodos de Optimism en L2 escuchan este evento TransactionDeposited desde el contrato de OptimismPortal y convierten los parámetros del evento en una transacción L2. El iniciador de esta transacción será el "remitente" especificado en el evento, el receptor será el "receptor" mencionado en el evento, y otros detalles de la transacción también se derivarán de los parámetros del evento.
Los nodos L2 convierten los parámetros del evento Transaction Deposited emitido por OptimismPortal en una transacción L2.
Por ejemplo, cuando un usuario deposita 0,01 ETH a través del contrato L1StandardBridge, el mensaje y la ETH se transmiten al contrato OptimismPortal (dirección 0xbEb5... 06Ed). Unos minutos más tarde, esto se convierte en una transacción L2: el remitente del mensaje es el contrato L1CrossDomainMessenger, el receptor es el contrato L2CrossDomainMessenger en L2 y el contenido del mensaje indica que L1StandardBridge recibió una ETH depositar 0.01 de Bob. Esto desencadena procesos adicionales, como acuñar 0.01 ETH para L2StandardBridge, que posteriormente lo transfiere a Bob.
Cómo activarlo
Si desea incluir a la fuerza una transacción en el contrato Rollup de Optimism, su objetivo es asegurarse de que una transacción "iniciada y ejecutada desde su dirección L2 en L2" pueda ejecutarse con éxito. Para lograr esto, debe enviar el mensaje directamente al contrato de OptimismPortal utilizando su dirección L2 (tenga en cuenta que el contrato de OptimismPortal está realmente en L1, pero el formato de dirección OP coincide con el formato de dirección L1, por lo que puede llamar a este contrato usando una cuenta L1 con la misma dirección que su cuenta L2). El "remitente" de la transacción L2 derivada del evento Transacción depositada emitida por este contrato será su cuenta L2, y el formato de transacción será coherente con una transacción L2 estándar.
En la transacción L2 derivada del evento Transaction Deposited, el propio Bob será el iniciador; el receptor será el contrato Uniswap; e incluirá el ETH especificado, como si Bob estuviera iniciando la transacción L2 él mismo.
Para utilizar la función Force Inclusion de Optimism, debe llamar directamente a la función depositTransaction del contrato de OptimismPortal e introducir los parámetros de la transacción que desea ejecutar en L2. Llevé a cabo un simple experimento de Inclusión de la Fuerza. El objetivo de esta transacción era realizar una autotransferencia en L2 utilizando mi dirección (0xeDc1... 6909) e incluir un mensaje que diga "forzar la inclusión". Esta es la transacción L1 que ejecuté llamando a la función depositTransaction a través del contrato OptimismPortal. Como puede ver en el evento de transacción depositada que emitió, tanto el remitente como el receptor soy yo.
Los valores restantes de la columna Data opaca codifican información como "cuánto ETH adjunta la persona que llama a la función depositTransaction", "cuánto ETH quiere enviar el iniciador de la transacción L2 al receptor", "GasLimit de la transacción L2" y "Datos para el receptor L2". Después de decodificar esta información, obtendrá los siguientes detalles: "cuánto ETH adjunta la persona que llama a depositTransaction": 0, porque no estoy depositando ETH de L1 a L2; "cuánto ETH quiere enviar el iniciador de la transacción L2 al receptor": 5566 (Wei); "GasLimit de la transacción L2": 50000; "Datos para el receptor L2": 0x666f72636520696e636c7573696f6e, que es la codificación hexadecimal de la cadena "forzar inclusión". Poco después, apareció la transacción L2 convertida: una transacción L2 donde me transfiero 5566 wei a mí mismo, con el campo Data que contiene la cadena "forzar inclusión". Además, en la penúltima línea de la sección Otros atributos, el TxnType (tipo de transacción) se muestra como transacción del sistema 126 (Sistema), lo que indica que esta transacción no fue iniciada por mí en L2, sino que se convirtió a partir del evento Depositado de la transacción L1.
Transacción L2 convertida
Si desea llamar a un contrato L2 a través de Force Inclusion y enviar datos diferentes, simplemente necesita completar los parámetros en la función depositTransaction. Solo recuerde usar la misma dirección L1 que su cuenta L2 cuando llame a la función depositTransaction. De esta manera, cuando el evento depositado se convierta en una transacción L2, el iniciador será su cuenta L2. Ventana del secuenciador El nodo L2 de Optimism que convierte el evento Transacción depositada en una transacción L2 es en realidad el secuenciador. Dado que esto implica el orden de las transacciones, solo el secuenciador puede decidir cuándo convertir el evento en una transacción L2. Cuando el secuenciador escucha el evento TransactionDeposited, no necesariamente convierte el evento en una transacción L2 inmediatamente; Puede haber un retraso. La duración máxima de este retardo se denomina ventana del secuenciador. Actualmente, la ventana del secuenciador en la red principal de Optimism es de 24 horas. Esto significa que cuando un usuario deposita dinero de L1 o utiliza Force Inclusion para una transacción, en el peor de los casos, se incluirá en el historial de transacciones de L2 después de 24 horas.
En Optimism, la operación L1 depositar desencadena un evento Transaction Deposited y, a continuación, solo es cuestión de esperar a que el secuenciador incluya la operación. Sin embargo, en Arbitrum, las operaciones en L1 (como depositar fondos o enviar mensajes a L2) se almacenan en una cola en L1, en lugar de simplemente emitir un evento. El secuenciador tiene un período específico para incluir estas transacciones en cola en el historial de transacciones de L2. Si el secuenciador no lo hace dentro de este período de tiempo, cualquiera puede intervenir para completar la inclusión en nombre del secuenciador.
Arbitrum mantiene una cola en un contrato L1. Si el secuenciador no puede procesar las transacciones en la cola dentro de un período determinado, cualquiera puede incluir estas transacciones a la fuerza en el historial de transacciones de L2. En el diseño de Arbitrum, las operaciones en L1, como los depósitos, deben pasar por el contrato de bandeja de entrada retrasada, donde, como su nombre indica, estas operaciones se retrasarán antes de entrar en vigor. Otro contrato, la bandeja de entrada del secuenciador, es donde el secuenciador carga directamente las transacciones L2 a L1. Cada vez que el secuenciador carga transacciones L2, también puede tomar algunas transacciones pendientes de la bandeja de entrada retrasada e incluirlas en el historial de transacciones.
Cuando
el secuenciador escribe nuevas transacciones, también puede incluir transacciones de la bandeja de entrada retrasada.
Diseño complejo y falta de materiales de referencia
Si consulta la documentación oficial de Arbitrum sobre el secuenciador y la inclusión forzada, encontrará una explicación general de cómo funciona la inclusión forzada, junto con algunos nombres de parámetros y funciones: Los usuarios llaman primero a la función sendUnsignedTransaction en el contrato DelayedInbox. Si el secuenciador no lo incluye en un plazo aproximado de 24 horas, los usuarios pueden llamar a la función forceInclusion en el contrato SequencerInbox. Sin embargo, la documentación oficial no proporciona enlaces a estas funciones, por lo que debe buscarlas usted mismo en el código del contrato. Cuando encuentre la función sendUnsignedTransaction, se dará cuenta de que tiene que rellenar el valor nonce y el valor maxFeePerGas usted mismo. ¿De quién es el nonce? ¿Qué red es maxFeePerGas? ¿Cómo debes rellenarlo correctamente? No hay documentos de referencia, ni siquiera NatSpec. También encontrará muchas funciones similares en el contrato de Arbitrum: sendL1FundedUnsignedTransaction, sendUnsignedTransactionToFork, sendContractTransaction, sendL1FundedContractTransaction. No hay documentos que expliquen las diferencias entre estas funciones, cómo usarlas o cómo completar los parámetros, ni siquiera NatSpec.
Intenta completar los parámetros y enviar la transacción con un enfoque de prueba y error, con la esperanza de encontrar el uso correcto. Sin embargo, descubre que todas estas funciones aplican alias de dirección a su dirección L1, lo que hace que el remitente de la transacción en L2 sea una dirección completamente diferente, dejando su dirección L2 inactiva. Más tarde, accidentalmente te topaste con un resultado de búsqueda de Google que revelaba que Arbitrum tiene una biblioteca de tutoriales con scripts que demuestran cómo enviar transacciones L2 desde L1 (esencialmente Force Inclusion). En el tutorial se enumera una función que no se ha mencionado anteriormente: sendL2Message. Sorprendentemente, el parámetro de mensaje requerido es en realidad una transacción L2 firmada que utiliza una cuenta L2. ¿Quién hubiera sabido que el "mensaje enviado a L2 a través de Force Inclusion" es en realidad una "transacción L2 firmada"? Además, no hay documentos ni NatSpec que expliquen cuándo y cómo utilizar esta función.
Conclusión: Generar manualmente una transacción forzada en Arbitrum es bastante complicado. Se recomienda seguir el tutorial oficial y utilizar el SDK de Arbitrum. A diferencia de otros Rollups, Arbitrum carece de documentación clara para desarrolladores y anotaciones de código. Muchas funciones carecen de explicaciones sobre sus propósitos y parámetros, lo que hace que los desarrolladores dediquen mucho más tiempo del esperado a integrarlas y usarlas. También pedí ayuda en el Discord de Arbitrum, pero no recibí respuestas satisfactorias. Al preguntar en Discord, solo me indicaron que mirara sendL2Message y no me explicaron las funciones de otros métodos (incluidos los mencionados en la documentación de inclusión forzada como sendUnsignedTransaction), sus propósitos, cómo usarlos o cuándo usarlos.
Desafortunadamente, StarkNet actualmente no tiene un mecanismo de inclusión de fuerza. Solo hay dos artículos en el foro oficial que discuten la censura y la inclusión forzada. La razón de la imposibilidad de probar transacciones fallidas es que el sistema de prueba de conocimiento cero de StarkNet no puede probar una transacción fallida, por lo que no se puede permitir la inclusión forzada. Si alguien maliciosamente (o no) forzó la inclusión de una transacción fallida e indemostrable, StarkNet se quedaría atascado: porque una vez que la transacción se incluye a la fuerza, el probador debe probar la transacción fallida, pero no puede. Se espera que StarkNet introduzca la capacidad de probar transacciones fallidas en la versión v0.15.0, después de lo cual el mecanismo de inclusión forzada debería implementarse aún más.
El mecanismo de zkSync para la transmisión de mensajes L1->L2 y la inclusión forzada se controla a través de la función requestL2Transaction del contrato MailBox. Los usuarios especifican la dirección L2, los datos de llamada, la cantidad de ETH que se va a adjuntar, el valor L2GasLimit y otros detalles. La función requestL2Transaction combina estos parámetros en una transacción L2 y la coloca en PriorityQueue. Cuando el secuenciador empaqueta las transacciones y las carga en L1 (a través de la función commitBatches), indica cuántas transacciones se deben tomar de PriorityQueue para incluirlas en los registros de transacciones de L2. En términos de inclusión forzada, zkSync es similar a Optimism, donde la dirección L2 del iniciador (la misma que la dirección L1) se usa para llamar a las funciones relevantes y completar los detalles necesarios (destinatario, datos de llamada, etc.), en lugar de Arbitrum, que requiere una transacción L2 firmada. Sin embargo, en el diseño, es similar a Arbitrum, ya que ambos mantienen una cola en L1, y el secuenciador toma las transacciones pendientes enviadas directamente por los usuarios desde la cola y las escribe en el historial de transacciones.
Si depositar ETH a través de la puente oficial de zkSync, como esta transacción, llama a la función requestL2Transaction del contrato MailBox. Esta función coloca la transacción Deposit ETH L2 en PriorityQueue y emite un evento NewPriorityRequest. Dado que el contrato codifica los datos de la transacción L2 en una cadena de bytes, no es fácil de leer. Sin embargo, si observa los parámetros de esta transacción L1, verá que el destinatario L2 también es el iniciador de la transacción (ya que es un depositario para uno mismo). Después de un tiempo, cuando el secuenciador saque esta transacción L2 de PriorityQueue y la incluya en el historial de transacciones, se convertirá en una transacción L2 a la que se transferirá a sí mismo. El monto de la transferencia será el monto ETH adjunto por el iniciador en la transacción ETH de depósito L1. En la transacción de depósito L1, tanto el iniciador como el destinatario son 0xeDc1... 6909, la cantidad es 0.03 ETH y no hay datos de llamada. En L2, habrá una transacción en la que 0xeDc1... 6909 se transfiere a sí mismo. El tipo de transacción (TxnType) es 255, lo que indica una transacción del sistema. Luego, al igual que experimenté con la función de transacción forzada en Optimism antes, llamé a la función requestL2Transaction de zkSync e inicié una transacción de autotransferencia: no se adjuntaba ETH y los datos de llamada contenían la codificación HEX de la cadena "forzar inclusión". Esto se convirtió en una transacción L2 en la que me transfiero a mí mismo, con los datos de llamada que contienen la cadena hexadecimal para "forzar la inclusión": 0x666f72636520696e636c7573696f6e. Cuando el secuenciador toma transacciones de PriorityQueue y las escribe en el historial de transacciones, se convierten en las transacciones L2 correspondientes. Con la función requestL2Transaction, los usuarios pueden enviar datos en L1 con la misma cuenta L1 que su dirección L2, especificando el destinatario L2, la cantidad de ETH que se adjuntará y los datos de llamada. Si los usuarios desean llamar a otros contratos o incluir datos diferentes, simplemente deben completar los parámetros en la función requestL2Transaction. Todavía no hay función de inclusión forzada para los usuarios Aunque una transacción L2 colocada en PriorityQueue tendrá un período de espera calculado para su inclusión por parte del secuenciador, el diseño actual de zkSync no tiene una función Force Inclusion que permita a los usuarios aplicarla. Esto significa que es solo una solución parcial. A pesar de que hay un "período de espera para la inclusión", en última instancia depende de si el secuenciador decide incluirlo: el secuenciador puede incluirlo después de que expire el período o nunca incluir ninguna transacción de PriorityQueue. En el futuro, zkSync debería agregar funciones que permitan a los usuarios incluir a la fuerza transacciones en el historial de transacciones L2 si no han sido incluidas por el secuenciador después del período de espera. Este sería un mecanismo de Inclusión de la Fuerza verdaderamente efectivo. Resumir
L1 se basa en un gran número de validadores para garantizar la "seguridad" y la "resistencia a la censura" de la red. Los rollups, sin embargo, tienen una resistencia a la censura más débil porque las transacciones son escritas por unos pocos o incluso un solo secuenciador. Por lo tanto, los Rollups necesitan un mecanismo de inclusión forzada que permita a los usuarios omitir el secuenciador y escribir transacciones en el historial, evitando que la censura por parte del secuenciador haga que el Rollup sea inutilizable y que los usuarios retiren fondos. La inclusión forzada permite a los usuarios escribir transacciones a la fuerza en el historial, pero el diseño debe elegir si "las transacciones se pueden insertar inmediatamente en el historial y surtir efecto de inmediato". Si se permite el efecto inmediato, afectaría negativamente al secuenciador porque las transacciones pendientes en L2 podrían verse afectadas por transacciones incluidas a la fuerza desde L1. Por lo tanto, los mecanismos actuales de inclusión forzada en los paquetes acumulativos colocan primero las transacciones insertadas desde L1 en un estado de espera y dan al secuenciador una ventana de tiempo para reaccionar y decidir si incluir estas transacciones pendientes. zkSync y Arbitrum mantienen una cola en L1 para administrar transacciones L2 o mensajes enviados de L1 a L2. Arbitrum lo llama DelayedInbox; zkSync lo llama PriorityQueue. Sin embargo, el método de zkSync para enviar transacciones L2 es más similar a Optimism, donde los mensajes se envían desde L1 utilizando la dirección L2, de modo que cuando se convierten en una transacción L2, el iniciador es la dirección L2. La función para enviar transacciones L2 en Optimism se llama depositTransaction; en zkSync, se llama requestL2Transaction. Por el contrario, Arbitrum genera una transacción L2 completa y la firma, luego la envía a través de la función sendL2Message. En L2, Arbitrum utiliza la firma para restaurar al firmante como iniciador de la transacción L2. StarkNet actualmente no tiene un mecanismo de inclusión de fuerza; zkSync tiene un mecanismo de inclusión forzada a medio implementar: tiene una cola de prioridad y cada transacción L2 en la cola tiene un período de validez de inclusión, pero este período de validez es actualmente solo para mostrar. En la práctica, el secuenciador puede optar por no incluir ninguna transacción L2 de PriorityQueue.
Este artículo se reenvía desde: [Geek Web3], el título original es "Teoría y práctica: ¿Cómo desencadenar transacciones resistentes a la censura en Ethereum Rollup?", atribución de derechos de autor al autor original [NIC Lin, Jefe de Taipei Ethereum Meetup], si tiene alguna objeción a la reimpresión, comuníquese con Gate Learn Team, el equipo lo manejará lo antes posible de acuerdo con los procedimientos pertinentes.
Descargo de responsabilidad: Los puntos de vista y opiniones expresados en este artículo representan solo los puntos de vista personales del autor y no constituyen ningún consejo de inversión.
Las versiones en otros idiomas del artículo son traducidas por el equipo de Gate Learn. Sin hacer referencia a Gate.io, está prohibido copiar, distribuir o plagiar los artículos traducidos.
Ayer mismo, ocurrió un evento impactante: Linea, la solución Ethereum Capa 2 desarrollada por Consensys, la empresa matriz de Metamask, fue cerrada de manera proactiva. La razón oficial dada fue mitigar el impacto del incidente de piratería de Velocore. Este incidente inevitablemente trae a la mente un caso anterior en el que la cadena BSC (BNB Chain) también se cerró bajo coordinación oficial para minimizar las pérdidas por piratería. Estos acontecimientos suelen llevar a la gente a cuestionar los valores descentralizados que defiende la Web3.
La razón principal detrás de los eventos mencionados radica en la imperfección de la infraestructura, específicamente en su falta de descentralización. Si una cadena de bloques estuviera lo suficientemente descentralizada, no debería poder cerrarse tan fácilmente. Debido a la estructura única de Ethereum Capa 2, la mayoría de las soluciones Capa 2 se basan en secuenciadores centralizados. A pesar del creciente discurso sobre los secuenciadores descentralizados en los últimos años, dado el propósito y la estructura de la Capa 2, podemos suponer que es poco probable que los secuenciadores de la Capa 2 alcancen altos niveles de descentralización. De hecho, pueden terminar siendo menos descentralizados que la cadena BSC. Si este es el caso, ¿qué se puede hacer? Para la capa 2, los riesgos más inmediatos de los secuenciadores no descentralizados son la falta de resistencia a la censura y la vida. Si solo hay unas pocas entidades que procesan transacciones (secuenciadores), tienen poder absoluto sobre si servirle o no: pueden rechazar sus transacciones a voluntad, dejándolo sin recurso. Abordar el problema de la resistencia a la censura en la Capa 2 es claramente un tema importante. En los últimos años, varias soluciones Ethereum Capa 2 han propuesto diferentes enfoques para abordar este problema. Por ejemplo, Loopring, Degate y StarkEx han introducido funciones de retirada forzada y escotilla de escape, mientras que Arbitrum y otros Optimistic Rollups han implementado funciones de inclusión forzada. Estos mecanismos pueden imponer controles a los secuenciadores para evitar el rechazo arbitrario de las transacciones de los usuarios. En el artículo de hoy, NIC Lin de la Asociación Ethereum de Taipei comparte su experiencia de primera mano, experimentando con las características de transacción resistentes a la censura de cuatro Rollups principales y proporcionando un análisis en profundidad del mecanismo de inclusión de fuerza, centrándose en el flujo de trabajo y los métodos operativos. Este análisis es especialmente valioso para la comunidad de Ethereum y los grandes tenedores de activos.
La censura resistencia en las transacciones es crucial para cualquier cadena de bloques. Si una cadena de bloques puede censurar y rechazar arbitrariamente las transacciones de los usuarios, no es diferente de un servidor Web2. La resistencia a la censura de las transacciones de Ethereum está actualmente garantizada por sus numerosos validadores. Si alguien quiere censurar la transacción de Bob y evitar que se incluya en la cadena de bloques, tendría que sobornar a la mayoría de los validadores de la red o enviar spam a la red con transacciones basura que tienen tarifas más altas que las de Bob, ocupando así espacio en bloque. Ambos métodos son extremadamente costosos.
Nota: En la arquitectura actual de separación entre proponentes y constructores (PBS) de Ethereum, el costo de censurar las transacciones se reduce significativamente. Por ejemplo, puedes ver la proporción de bloques que cumplen con la censura de la OFAC de las transacciones de Tornado Cash. La resistencia a la censura actual se basa en validadores y relés independientes que están fuera de la jurisdicción de la OFAC y otras entidades gubernamentales.
Pero, ¿qué pasa con los Rollups? Los rollups no requieren un gran número de validadores para garantizar la seguridad. Incluso si un Rollup tiene solo una entidad centralizada (secuenciador) que produce bloques, sigue siendo tan seguro como la capa 1 (L1). Sin embargo, la seguridad y la resistencia a la censura son dos asuntos diferentes. Un Rollup, aunque es tan seguro como Ethereum, aún puede censurar la transacción de cualquier usuario si solo tiene un secuenciador centralizado.
Sequencer puede negarse a procesar la transacción de un usuario, lo que hace que los fondos del usuario se bloqueen y no puedan salir del Rollup.
En lugar de requerir que los Rollups tengan una gran cantidad de secuenciadores descentralizados, es más efectivo aprovechar directamente el resistencia a la censura de la Capa 1 (L1):
Dado que el secuenciador necesita empaquetar los datos de la transacción y enviarlos al contrato Rollup en L1, podemos agregar una característica en el contrato que permita a los usuarios insertar sus transacciones en el contrato Rollup ellos mismos. Este mecanismo se conoce como "Inclusión de la Fuerza". Tan largo como el secuenciador no puede censurar a los usuarios en el nivel L1, no puede evitar que los usuarios inserten transacciones por la fuerza en L1. De esta manera, el Rollup puede heredar la resistencia a la censura de L1.
Sequencer no puede revisar las transacciones L1 del usuario sin pagar un alto costo
Si se permite que las transacciones se escriban directamente en el contrato Rollup a través de la inclusión forzada (lo que significa que entran en vigor inmediatamente), el estado del Rollup cambiará al instante. Por ejemplo, si Bob usa el mecanismo de inclusión forzada para insertar una transacción que transfiere 1000 DAI a Carol y la transacción surte efecto inmediatamente, el saldo de Bob disminuiría en 1000 DAI, mientras que el saldo de Carol aumentaría en 1000 DAI en el estado actualizado.
Si la inclusión forzada permite que las transacciones se escriban directamente en el contrato consolidado y surtan efecto inmediatamente, el estado del resumen cambiaría instantáneamente. Si el secuenciador está recopilando simultáneamente transacciones off-chain y preparándose para enviar el siguiente lote al contrato Rollup, podría verse interrumpido por la transacción insertada a la fuerza de Bob que tiene efecto inmediato. Para evitar este problema, los resúmenes generalmente no permiten que las transacciones de inclusión forzada surtan efecto inmediatamente. En su lugar, los usuarios insertan inicialmente sus transacciones en una cola de espera en L1, donde entran en un estado de "preparación". Cuando el secuenciador empaqueta transacciones off-chain para enviarlas al contrato Rollup, puede elegir si desea incluir estas transacciones en cola. Si el secuenciador ignora continuamente las transacciones en el estado de "preparación", una vez que finaliza el período de ventana, los usuarios pueden forzar la inserción de estas transacciones en el contrato consolidado. El secuenciador puede decidir cuándo incluir "incidentalmente" las transacciones de la cola de espera, pero aún puede negarse a procesarlas. Si el secuenciador se niega sistemáticamente, después de un cierto período, cualquiera puede usar la función Forzar inclusión para forzar la inserción de las transacciones en el contrato Rollup. A continuación, presentaremos la implementación del mecanismo Force Inclusion en cuatro Rollups destacados: Optimism, Arbitrum, StarkNet y zkSync.
El secuenciador puede elegir cuándo obtener transacciones de la cola de espera.
Los secuenciadores aún pueden negarse a procesar transacciones en la cola de espera.
Si el secuenciador se niega sistemáticamente a procesar transacciones, después de un período determinado, cualquiera puede usar la función Forzar inclusión para insertar transacciones a la fuerza en el contrato Rollup. A continuación, presentaremos cómo se implementa el mecanismo Force Inclusion en cuatro Rollups destacados: Optimism, Arbitrum, StarkNet y zkSync.
En primer lugar, analicemos el proceso de depósito de Optimism. Este proceso de depósito implica no solo transferir fondos a Optimism, sino también enviar "mensajes de usuario a L2". Cuando un nodo L2 recibe un mensaje recién depositado, convierte el mensaje en una transacción L2 y la ejecuta, entregándola al destinatario especificado.
Mensajes de usuario depositados de L1 a L2
Contrato L1CrossDomainMessenger
Cuando un usuario quiere depositar ETH o ERC-20 tokens en Optimism, interactúa con el contrato L1StandardBridge en L1 a través de una página web de frontend, especificando la cantidad a depositar y la dirección L2 que recibirá estos activos. A continuación, el contrato L1StandardBridge reenvía el mensaje al contrato L1CrossDomainMessenger, que actúa como puente de comunicación principal entre L1 y L2. L1StandardBridge utiliza este componente de comunicación para interactuar con L2StandardBridge en L2, determinando quién puede acuñar tokens en L2 o desbloquear tokens de L1. Los desarrolladores que necesiten crear contratos que interoperen y sincronicen estados entre L1 y L2 pueden crearlos sobre el contrato L1CrossDomainMessenger.
Mensajes de usuario transmitidos de L1 a L2 a través del contrato CrossDomainMessenger
Nota: En algunas imágenes de este artículo, CrossDomainMessenger se escribe como CrossChainMessenger.
Contrato de OptimismPortal
A continuación, el contrato L1CrossDomainMessenger reenvía el mensaje a la capa inferior, el contrato OptimismPortal. Después de procesar el mensaje, el contrato de OptimismPortal emite un evento llamado TransactionDeposited, que incluye parámetros como el "remitente", el "receptor" y otros detalles de ejecución relevantes. Los nodos de Optimism en L2 escuchan este evento TransactionDeposited desde el contrato de OptimismPortal y convierten los parámetros del evento en una transacción L2. El iniciador de esta transacción será el "remitente" especificado en el evento, el receptor será el "receptor" mencionado en el evento, y otros detalles de la transacción también se derivarán de los parámetros del evento.
Los nodos L2 convierten los parámetros del evento Transaction Deposited emitido por OptimismPortal en una transacción L2.
Por ejemplo, cuando un usuario deposita 0,01 ETH a través del contrato L1StandardBridge, el mensaje y la ETH se transmiten al contrato OptimismPortal (dirección 0xbEb5... 06Ed). Unos minutos más tarde, esto se convierte en una transacción L2: el remitente del mensaje es el contrato L1CrossDomainMessenger, el receptor es el contrato L2CrossDomainMessenger en L2 y el contenido del mensaje indica que L1StandardBridge recibió una ETH depositar 0.01 de Bob. Esto desencadena procesos adicionales, como acuñar 0.01 ETH para L2StandardBridge, que posteriormente lo transfiere a Bob.
Cómo activarlo
Si desea incluir a la fuerza una transacción en el contrato Rollup de Optimism, su objetivo es asegurarse de que una transacción "iniciada y ejecutada desde su dirección L2 en L2" pueda ejecutarse con éxito. Para lograr esto, debe enviar el mensaje directamente al contrato de OptimismPortal utilizando su dirección L2 (tenga en cuenta que el contrato de OptimismPortal está realmente en L1, pero el formato de dirección OP coincide con el formato de dirección L1, por lo que puede llamar a este contrato usando una cuenta L1 con la misma dirección que su cuenta L2). El "remitente" de la transacción L2 derivada del evento Transacción depositada emitida por este contrato será su cuenta L2, y el formato de transacción será coherente con una transacción L2 estándar.
En la transacción L2 derivada del evento Transaction Deposited, el propio Bob será el iniciador; el receptor será el contrato Uniswap; e incluirá el ETH especificado, como si Bob estuviera iniciando la transacción L2 él mismo.
Para utilizar la función Force Inclusion de Optimism, debe llamar directamente a la función depositTransaction del contrato de OptimismPortal e introducir los parámetros de la transacción que desea ejecutar en L2. Llevé a cabo un simple experimento de Inclusión de la Fuerza. El objetivo de esta transacción era realizar una autotransferencia en L2 utilizando mi dirección (0xeDc1... 6909) e incluir un mensaje que diga "forzar la inclusión". Esta es la transacción L1 que ejecuté llamando a la función depositTransaction a través del contrato OptimismPortal. Como puede ver en el evento de transacción depositada que emitió, tanto el remitente como el receptor soy yo.
Los valores restantes de la columna Data opaca codifican información como "cuánto ETH adjunta la persona que llama a la función depositTransaction", "cuánto ETH quiere enviar el iniciador de la transacción L2 al receptor", "GasLimit de la transacción L2" y "Datos para el receptor L2". Después de decodificar esta información, obtendrá los siguientes detalles: "cuánto ETH adjunta la persona que llama a depositTransaction": 0, porque no estoy depositando ETH de L1 a L2; "cuánto ETH quiere enviar el iniciador de la transacción L2 al receptor": 5566 (Wei); "GasLimit de la transacción L2": 50000; "Datos para el receptor L2": 0x666f72636520696e636c7573696f6e, que es la codificación hexadecimal de la cadena "forzar inclusión". Poco después, apareció la transacción L2 convertida: una transacción L2 donde me transfiero 5566 wei a mí mismo, con el campo Data que contiene la cadena "forzar inclusión". Además, en la penúltima línea de la sección Otros atributos, el TxnType (tipo de transacción) se muestra como transacción del sistema 126 (Sistema), lo que indica que esta transacción no fue iniciada por mí en L2, sino que se convirtió a partir del evento Depositado de la transacción L1.
Transacción L2 convertida
Si desea llamar a un contrato L2 a través de Force Inclusion y enviar datos diferentes, simplemente necesita completar los parámetros en la función depositTransaction. Solo recuerde usar la misma dirección L1 que su cuenta L2 cuando llame a la función depositTransaction. De esta manera, cuando el evento depositado se convierta en una transacción L2, el iniciador será su cuenta L2. Ventana del secuenciador El nodo L2 de Optimism que convierte el evento Transacción depositada en una transacción L2 es en realidad el secuenciador. Dado que esto implica el orden de las transacciones, solo el secuenciador puede decidir cuándo convertir el evento en una transacción L2. Cuando el secuenciador escucha el evento TransactionDeposited, no necesariamente convierte el evento en una transacción L2 inmediatamente; Puede haber un retraso. La duración máxima de este retardo se denomina ventana del secuenciador. Actualmente, la ventana del secuenciador en la red principal de Optimism es de 24 horas. Esto significa que cuando un usuario deposita dinero de L1 o utiliza Force Inclusion para una transacción, en el peor de los casos, se incluirá en el historial de transacciones de L2 después de 24 horas.
En Optimism, la operación L1 depositar desencadena un evento Transaction Deposited y, a continuación, solo es cuestión de esperar a que el secuenciador incluya la operación. Sin embargo, en Arbitrum, las operaciones en L1 (como depositar fondos o enviar mensajes a L2) se almacenan en una cola en L1, en lugar de simplemente emitir un evento. El secuenciador tiene un período específico para incluir estas transacciones en cola en el historial de transacciones de L2. Si el secuenciador no lo hace dentro de este período de tiempo, cualquiera puede intervenir para completar la inclusión en nombre del secuenciador.
Arbitrum mantiene una cola en un contrato L1. Si el secuenciador no puede procesar las transacciones en la cola dentro de un período determinado, cualquiera puede incluir estas transacciones a la fuerza en el historial de transacciones de L2. En el diseño de Arbitrum, las operaciones en L1, como los depósitos, deben pasar por el contrato de bandeja de entrada retrasada, donde, como su nombre indica, estas operaciones se retrasarán antes de entrar en vigor. Otro contrato, la bandeja de entrada del secuenciador, es donde el secuenciador carga directamente las transacciones L2 a L1. Cada vez que el secuenciador carga transacciones L2, también puede tomar algunas transacciones pendientes de la bandeja de entrada retrasada e incluirlas en el historial de transacciones.
Cuando
el secuenciador escribe nuevas transacciones, también puede incluir transacciones de la bandeja de entrada retrasada.
Diseño complejo y falta de materiales de referencia
Si consulta la documentación oficial de Arbitrum sobre el secuenciador y la inclusión forzada, encontrará una explicación general de cómo funciona la inclusión forzada, junto con algunos nombres de parámetros y funciones: Los usuarios llaman primero a la función sendUnsignedTransaction en el contrato DelayedInbox. Si el secuenciador no lo incluye en un plazo aproximado de 24 horas, los usuarios pueden llamar a la función forceInclusion en el contrato SequencerInbox. Sin embargo, la documentación oficial no proporciona enlaces a estas funciones, por lo que debe buscarlas usted mismo en el código del contrato. Cuando encuentre la función sendUnsignedTransaction, se dará cuenta de que tiene que rellenar el valor nonce y el valor maxFeePerGas usted mismo. ¿De quién es el nonce? ¿Qué red es maxFeePerGas? ¿Cómo debes rellenarlo correctamente? No hay documentos de referencia, ni siquiera NatSpec. También encontrará muchas funciones similares en el contrato de Arbitrum: sendL1FundedUnsignedTransaction, sendUnsignedTransactionToFork, sendContractTransaction, sendL1FundedContractTransaction. No hay documentos que expliquen las diferencias entre estas funciones, cómo usarlas o cómo completar los parámetros, ni siquiera NatSpec.
Intenta completar los parámetros y enviar la transacción con un enfoque de prueba y error, con la esperanza de encontrar el uso correcto. Sin embargo, descubre que todas estas funciones aplican alias de dirección a su dirección L1, lo que hace que el remitente de la transacción en L2 sea una dirección completamente diferente, dejando su dirección L2 inactiva. Más tarde, accidentalmente te topaste con un resultado de búsqueda de Google que revelaba que Arbitrum tiene una biblioteca de tutoriales con scripts que demuestran cómo enviar transacciones L2 desde L1 (esencialmente Force Inclusion). En el tutorial se enumera una función que no se ha mencionado anteriormente: sendL2Message. Sorprendentemente, el parámetro de mensaje requerido es en realidad una transacción L2 firmada que utiliza una cuenta L2. ¿Quién hubiera sabido que el "mensaje enviado a L2 a través de Force Inclusion" es en realidad una "transacción L2 firmada"? Además, no hay documentos ni NatSpec que expliquen cuándo y cómo utilizar esta función.
Conclusión: Generar manualmente una transacción forzada en Arbitrum es bastante complicado. Se recomienda seguir el tutorial oficial y utilizar el SDK de Arbitrum. A diferencia de otros Rollups, Arbitrum carece de documentación clara para desarrolladores y anotaciones de código. Muchas funciones carecen de explicaciones sobre sus propósitos y parámetros, lo que hace que los desarrolladores dediquen mucho más tiempo del esperado a integrarlas y usarlas. También pedí ayuda en el Discord de Arbitrum, pero no recibí respuestas satisfactorias. Al preguntar en Discord, solo me indicaron que mirara sendL2Message y no me explicaron las funciones de otros métodos (incluidos los mencionados en la documentación de inclusión forzada como sendUnsignedTransaction), sus propósitos, cómo usarlos o cuándo usarlos.
Desafortunadamente, StarkNet actualmente no tiene un mecanismo de inclusión de fuerza. Solo hay dos artículos en el foro oficial que discuten la censura y la inclusión forzada. La razón de la imposibilidad de probar transacciones fallidas es que el sistema de prueba de conocimiento cero de StarkNet no puede probar una transacción fallida, por lo que no se puede permitir la inclusión forzada. Si alguien maliciosamente (o no) forzó la inclusión de una transacción fallida e indemostrable, StarkNet se quedaría atascado: porque una vez que la transacción se incluye a la fuerza, el probador debe probar la transacción fallida, pero no puede. Se espera que StarkNet introduzca la capacidad de probar transacciones fallidas en la versión v0.15.0, después de lo cual el mecanismo de inclusión forzada debería implementarse aún más.
El mecanismo de zkSync para la transmisión de mensajes L1->L2 y la inclusión forzada se controla a través de la función requestL2Transaction del contrato MailBox. Los usuarios especifican la dirección L2, los datos de llamada, la cantidad de ETH que se va a adjuntar, el valor L2GasLimit y otros detalles. La función requestL2Transaction combina estos parámetros en una transacción L2 y la coloca en PriorityQueue. Cuando el secuenciador empaqueta las transacciones y las carga en L1 (a través de la función commitBatches), indica cuántas transacciones se deben tomar de PriorityQueue para incluirlas en los registros de transacciones de L2. En términos de inclusión forzada, zkSync es similar a Optimism, donde la dirección L2 del iniciador (la misma que la dirección L1) se usa para llamar a las funciones relevantes y completar los detalles necesarios (destinatario, datos de llamada, etc.), en lugar de Arbitrum, que requiere una transacción L2 firmada. Sin embargo, en el diseño, es similar a Arbitrum, ya que ambos mantienen una cola en L1, y el secuenciador toma las transacciones pendientes enviadas directamente por los usuarios desde la cola y las escribe en el historial de transacciones.
Si depositar ETH a través de la puente oficial de zkSync, como esta transacción, llama a la función requestL2Transaction del contrato MailBox. Esta función coloca la transacción Deposit ETH L2 en PriorityQueue y emite un evento NewPriorityRequest. Dado que el contrato codifica los datos de la transacción L2 en una cadena de bytes, no es fácil de leer. Sin embargo, si observa los parámetros de esta transacción L1, verá que el destinatario L2 también es el iniciador de la transacción (ya que es un depositario para uno mismo). Después de un tiempo, cuando el secuenciador saque esta transacción L2 de PriorityQueue y la incluya en el historial de transacciones, se convertirá en una transacción L2 a la que se transferirá a sí mismo. El monto de la transferencia será el monto ETH adjunto por el iniciador en la transacción ETH de depósito L1. En la transacción de depósito L1, tanto el iniciador como el destinatario son 0xeDc1... 6909, la cantidad es 0.03 ETH y no hay datos de llamada. En L2, habrá una transacción en la que 0xeDc1... 6909 se transfiere a sí mismo. El tipo de transacción (TxnType) es 255, lo que indica una transacción del sistema. Luego, al igual que experimenté con la función de transacción forzada en Optimism antes, llamé a la función requestL2Transaction de zkSync e inicié una transacción de autotransferencia: no se adjuntaba ETH y los datos de llamada contenían la codificación HEX de la cadena "forzar inclusión". Esto se convirtió en una transacción L2 en la que me transfiero a mí mismo, con los datos de llamada que contienen la cadena hexadecimal para "forzar la inclusión": 0x666f72636520696e636c7573696f6e. Cuando el secuenciador toma transacciones de PriorityQueue y las escribe en el historial de transacciones, se convierten en las transacciones L2 correspondientes. Con la función requestL2Transaction, los usuarios pueden enviar datos en L1 con la misma cuenta L1 que su dirección L2, especificando el destinatario L2, la cantidad de ETH que se adjuntará y los datos de llamada. Si los usuarios desean llamar a otros contratos o incluir datos diferentes, simplemente deben completar los parámetros en la función requestL2Transaction. Todavía no hay función de inclusión forzada para los usuarios Aunque una transacción L2 colocada en PriorityQueue tendrá un período de espera calculado para su inclusión por parte del secuenciador, el diseño actual de zkSync no tiene una función Force Inclusion que permita a los usuarios aplicarla. Esto significa que es solo una solución parcial. A pesar de que hay un "período de espera para la inclusión", en última instancia depende de si el secuenciador decide incluirlo: el secuenciador puede incluirlo después de que expire el período o nunca incluir ninguna transacción de PriorityQueue. En el futuro, zkSync debería agregar funciones que permitan a los usuarios incluir a la fuerza transacciones en el historial de transacciones L2 si no han sido incluidas por el secuenciador después del período de espera. Este sería un mecanismo de Inclusión de la Fuerza verdaderamente efectivo. Resumir
L1 se basa en un gran número de validadores para garantizar la "seguridad" y la "resistencia a la censura" de la red. Los rollups, sin embargo, tienen una resistencia a la censura más débil porque las transacciones son escritas por unos pocos o incluso un solo secuenciador. Por lo tanto, los Rollups necesitan un mecanismo de inclusión forzada que permita a los usuarios omitir el secuenciador y escribir transacciones en el historial, evitando que la censura por parte del secuenciador haga que el Rollup sea inutilizable y que los usuarios retiren fondos. La inclusión forzada permite a los usuarios escribir transacciones a la fuerza en el historial, pero el diseño debe elegir si "las transacciones se pueden insertar inmediatamente en el historial y surtir efecto de inmediato". Si se permite el efecto inmediato, afectaría negativamente al secuenciador porque las transacciones pendientes en L2 podrían verse afectadas por transacciones incluidas a la fuerza desde L1. Por lo tanto, los mecanismos actuales de inclusión forzada en los paquetes acumulativos colocan primero las transacciones insertadas desde L1 en un estado de espera y dan al secuenciador una ventana de tiempo para reaccionar y decidir si incluir estas transacciones pendientes. zkSync y Arbitrum mantienen una cola en L1 para administrar transacciones L2 o mensajes enviados de L1 a L2. Arbitrum lo llama DelayedInbox; zkSync lo llama PriorityQueue. Sin embargo, el método de zkSync para enviar transacciones L2 es más similar a Optimism, donde los mensajes se envían desde L1 utilizando la dirección L2, de modo que cuando se convierten en una transacción L2, el iniciador es la dirección L2. La función para enviar transacciones L2 en Optimism se llama depositTransaction; en zkSync, se llama requestL2Transaction. Por el contrario, Arbitrum genera una transacción L2 completa y la firma, luego la envía a través de la función sendL2Message. En L2, Arbitrum utiliza la firma para restaurar al firmante como iniciador de la transacción L2. StarkNet actualmente no tiene un mecanismo de inclusión de fuerza; zkSync tiene un mecanismo de inclusión forzada a medio implementar: tiene una cola de prioridad y cada transacción L2 en la cola tiene un período de validez de inclusión, pero este período de validez es actualmente solo para mostrar. En la práctica, el secuenciador puede optar por no incluir ninguna transacción L2 de PriorityQueue.
Este artículo se reenvía desde: [Geek Web3], el título original es "Teoría y práctica: ¿Cómo desencadenar transacciones resistentes a la censura en Ethereum Rollup?", atribución de derechos de autor al autor original [NIC Lin, Jefe de Taipei Ethereum Meetup], si tiene alguna objeción a la reimpresión, comuníquese con Gate Learn Team, el equipo lo manejará lo antes posible de acuerdo con los procedimientos pertinentes.
Descargo de responsabilidad: Los puntos de vista y opiniones expresados en este artículo representan solo los puntos de vista personales del autor y no constituyen ningún consejo de inversión.
Las versiones en otros idiomas del artículo son traducidas por el equipo de Gate Learn. Sin hacer referencia a Gate.io, está prohibido copiar, distribuir o plagiar los artículos traducidos.