Logo
Nuevos usuarios de RPC: 35% de descuento el primer mesVer oferta
OnFinality Learn
Infraestructura y operaciones14 min de lectura

Nodo de archivo Arbitrum Nitro: sincronización por snapshot y RPC

Aprende cómo los nodos de archivo Arbitrum Nitro almacenan el estado histórico, se sincronizan mediante snapshots y sirven consultas RPC históricas.

TL;DR

Un nodo de archivo Arbitrum Nitro conserva todo el estado histórico de la L2 y los datos de lotes derivados de la L1 necesarios para reconstruirlo, lo que permite consultas históricas eth_call, eth_getBalance y eth_getLogs. A diferencia de un nodo completo, que poda los nodos de trie antiguos, un nodo de archivo se ejecuta con el flag archive habilitado y almacena todo el historial de estado. Sincronizar desde el génesis es fiel pero lento; arrancar desde un snapshot publicado es más rápido pero requiere confiar en la fuente del snapshot y verificar la cabeza. Ejecutar un nodo de archivo Nitro requiere un endpoint RPC de Ethereum L1 saludable y un directorio de datos configurado correctamente. Este artículo explica el mecanismo, proporciona ejemplos de verificación ejecutables y describe las ventajas, desventajas y fallos comunes.

Modelo de nodo Arbitrum Nitro y requisitos de archivo

Arbitrum One es un rollup optimista, y su nodo Nitro deriva el estado de la L2 a partir de dos entradas: la bandeja de entrada de la L1 (Ethereum) para los lotes secuenciados y la propia ejecución de la L2. Esto difiere de un nodo genérico de Ethereum L1, que deriva el estado únicamente de su propia cadena. Por lo tanto, un nodo de archivo debe conservar tanto el historial completo del estado de la L2 como los datos de lotes derivados de la L1 para reconstruir cualquier estado histórico.

El panorama de roles de nodo incluye nodos completos, que mantienen el estado reciente, y nodos de archivo, que conservan el estado histórico de toda la cadena. Los nodos de archivo son necesarios para eth_call y eth_getBalance contra bloques antiguos, eth_getLogs históricos y la reproducción estilo trace. Los dos roles difieren en la estrategia de almacenamiento y el tiempo de sincronización, no en la superficie de la API. Para una comparación más amplia, consulta Nodo de archivo vs nodo completo.

  • Nodo completo: poda los nodos de trie antiguos, sincronización más rápida, menor almacenamiento.
  • Nodo de archivo: conserva todos los nodos de trie, sincronización más lenta, mayor almacenamiento.
  • Ambos exponen la misma API JSON-RPC; los nodos de archivo sirven consultas históricas.

Almacenamiento de estado de Nitro y el flag archive

Nitro almacena el estado en un trie con Merkle comprometido mediante la raíz de estado producida por WAVM/AEVM, utilizando una base de datos de estado persistente derivada de go-ethereum. Este almacén de estado puede ejecutarse en modo de retención 'full' o 'archive'. El flag archive decide si se podan los nodos de trie antiguos; cuando está habilitado, el nodo conserva todo el estado histórico.

El flag archive se establece al iniciar el nodo y no se puede cambiar sin resincronizar o migrar la base de datos. Según la documentación de Arbitrum sobre cómo ejecutar un nodo de archivo, el nodo debe configurarse con los flags adecuados para habilitar el modo archivo. Esto garantiza que las consultas de estado histórico no fallen con errores de 'missing trie node'.

  • La raíz de estado la produce el motor de ejecución de Nitro (WAVM/AEVM).
  • La base de datos de estado persistente utiliza un almacén derivado de go-ethereum.
  • El modo archivo deshabilita la poda de nodos de trie antiguos.

Rutas de sincronización: repetición desde génesis, arranque por snapshot y endpoints alojados

Existen tres rutas principales de sincronización para un nodo de archivo Arbitrum Nitro. Primero, sincronizar desde el génesis reproduciendo la bandeja de entrada es fiel pero lento y limitado por E/S, ya que procesa cada lote desde la L1. Segundo, arrancar desde un snapshot publicado copia una base de datos de estado conocida como buena y luego se pone al día con la bandeja de entrada restante, lo cual es mucho más rápido pero requiere confiar en la fuente del snapshot y verificar la cabeza después. Tercero, depender de un endpoint de archivo alojado elimina la carga operativa; para esa opción, consulta Endpoints RPC de Arbitrum (RPC Assistant).

El flujo de snapshot está documentado en la guía de Docker de Arbitrum Nitro. Implica descargar un archivo de snapshot, extraerlo en el directorio de datos e iniciar el nodo con el flag archive. El nodo luego sincronizará los lotes restantes desde la L1. Este método es significativamente más rápido que la sincronización desde génesis, pero introduce una suposición de confianza en el proveedor del snapshot.

  • Sincronización desde génesis: sin confianza, lenta, alta E/S.
  • Arranque por snapshot: rápido, requiere confiar en la fuente del snapshot.
  • Endpoint alojado: sin operaciones, pero dependencia externa.

Ejecutar un nodo de archivo Nitro con Docker

El despliegue en contenedor documentado ejecuta el nodo Nitro contra un endpoint de Ethereum L1. El nodo lee la L1 para los lotes y para la bandeja de entrada retrasada, por lo que debes proporcionar un RPC de Ethereum L1 saludable además del directorio de datos de la L2. El flag archive debe estar establecido para que el estado no se pode. La guía de Docker de Arbitrum Nitro proporciona el comando Docker canónico y la configuración.

Una invocación típica de Docker incluye variables de entorno para el endpoint de L1, el ID de cadena de L2 y el flag archive. El directorio de datos debe montarse en almacenamiento NVMe rápido con alta resistencia, ya que el almacenamiento de archivo crece continuamente. Después de iniciar el contenedor, monitorea los registros para ver el progreso de sincronización y asegúrate de que el nodo esté consumiendo la bandeja de entrada de L1 sin limitación de velocidad.

docker run -d --name nitro-archive \
  -v /path/to/data:/home/user/.arbitrum \
  -p 8547:8547 -p 8548:8548 \
  offchainlabs/nitro-node:v3.0.0 \
  --l1.url=https://eth-mainnet.example.com \
  --l2.chain-id=42161 \
  --node.archive=true \
  --http.addr=0.0.0.0 \
  --http.port=8547 \
  --http.api=eth,net,web3,debug

Verificar el comportamiento de archivo con llamadas RPC históricas

Para verificar que un nodo de archivo está sirviendo estado histórico, llama a eth_getBalance o eth_call con un número de bloque antiguo explícito—un bloque muy anterior a la ventana reciente del nodo—y confirma que devuelve un valor en lugar de un error de estado podado. Luego compara el avance de la cabeza de eth_getBlockByNumber con el secuenciador o la L1 para confirmar que el nodo está activo. La documentación de Arbitrum sobre el feed del secuenciador explica cómo monitorear la progresión de la cabeza.

Usa el siguiente ejemplo curl para consultar un saldo histórico. Reemplaza el endpoint y el número de bloque con los tuyos. El número de bloque debe ser muy anterior a la ventana reciente del nodo (por ejemplo, el bloque 1000000 en Arbitrum One). Si el nodo está en modo archivo, devolverá el saldo; de lo contrario, devolverá un error que indica missing trie node.

curl -X POST https://your-archive-node.example.com \
  -H "Content-Type: application/json" \
  --data '{"jsonrpc":"2.0","method":"eth_getBalance","params":["0x0000000000000000000000000000000000000000","0xF4240"],"id":1}'

Ejemplo ejecutable en Node.js para consultas históricas

El siguiente fragmento de Node.js emite solicitudes históricas eth_call, eth_getBalance y eth_getLogs e imprime el número de bloque utilizado. Utiliza la API fetch integrada (Node.js 18+). Reemplaza el endpoint y el número de bloque con los tuyos. Este ejemplo te ayuda a verificar el comportamiento de archivo de forma programática.

El script primero obtiene el número de bloque actual para establecer una referencia, luego consulta un bloque histórico. Imprime el número de bloque utilizado y el resultado. Si el nodo no está en modo archivo, las consultas históricas fallarán con un error.

const endpoint = 'https://your-archive-node.example.com';
const historicalBlock = 1000000; // Arbitrum One block number

async function rpcCall(method, params) {
  const res = await fetch(endpoint, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ jsonrpc: '2.0', method, params, id: 1 })
  });
  return res.json();
}

(async () => {
  const head = await rpcCall('eth_blockNumber', []);
  console.log('Current head block:', parseInt(head.result, 16));

  const balance = await rpcCall('eth_getBalance', ['0x0000000000000000000000000000000000000000', '0x' + historicalBlock.toString(16)]);
  console.log(`Balance at block ${historicalBlock}:`, balance.result);

  const call = await rpcCall('eth_call', [{ to: '0x0000000000000000000000000000000000000000', data: '0x' }, '0x' + historicalBlock.toString(16)]);
  console.log(`eth_call at block ${historicalBlock}:`, call.result);

  const logs = await rpcCall('eth_getLogs', [{ fromBlock: '0x' + historicalBlock.toString(16), toBlock: '0x' + historicalBlock.toString(16) }]);
  console.log(`Logs at block ${historicalBlock}:`, logs.result.length);
})();

Tabla de resultados para verificación reproducible

Para que tu verificación sea reproducible sin inventar números, completa la siguiente tabla con tus propias mediciones de endpoint. Usa un número de bloque histórico que sea muy anterior a la ventana reciente del nodo. Registra el resultado de la llamada de archivo, el bloque de cabeza actual y el retraso de sincronización (bloque de cabeza menos el último bloque conocido por el secuenciador). Esta tabla te ayuda a comparar diferentes endpoints o a rastrear la salud de tu nodo a lo largo del tiempo.

La tabla debe completarse con tus propios datos. No confíes en números prellenados. Para una inmersión más profunda en el acceso a datos históricos, consulta Acceder a datos históricos de blockchain.

  • URL del endpoint: [tu endpoint]
  • Número de bloque histórico utilizado: [p. ej., 1000000]
  • Resultado de eth_getBalance: [valor o error]
  • Resultado de eth_call: [valor o error]
  • Resultado de eth_getLogs: [recuento o error]
  • Bloque de cabeza actual: [número]
  • Retraso de sincronización (cabeza vs secuenciador): [número]

Fallos comunes y solución de problemas

Los fallos comunes incluyen errores de 'missing trie node' o 'historical state unavailable', que significan que el flag archive está desactivado o que el nodo todavía está rellenando datos. Una discrepancia de snapshot puede producir una raíz de estado con la que la bandeja de entrada no está de acuerdo, lo que hace que el nodo se detenga o rechace bloques. La limitación de velocidad del endpoint de L1 puede detener el consumo de la bandeja de entrada, impidiendo que el nodo avance. Para diagnosticar, revisa los registros del nodo en busca de errores y verifica la salud del endpoint de L1.

Si encuentras 'missing trie node', asegúrate de que el nodo se inició con el flag archive y de que el directorio de datos contiene el historial completo de estado. Si usaste un snapshot, verifica su integridad y que coincida con la raíz de estado esperada. Para la limitación de velocidad de L1, considera usar un proveedor de RPC de L1 dedicado o aumentar los límites de velocidad. Para monitorear el estado de sincronización, consulta Estado de sincronización del nodo OP Stack mediante la Engine API, que cubre conceptos similares para cadenas OP Stack.

  • Missing trie node: flag archive desactivado o rellenando datos.
  • Discrepancia de snapshot: desacuerdo de raíz de estado con la bandeja de entrada.
  • Limitación de velocidad de L1: el consumo de la bandeja de entrada se detiene.

Ventajas y limitaciones de los nodos de archivo autoalojados

El almacenamiento de archivo crece continuamente y necesita NVMe rápido con alta resistencia. La confianza en el snapshot es una decisión de seguridad real: estás confiando en que el proveedor del snapshot no incluya estado malicioso. Un nodo de archivo autoalojado se justifica solo cuando el volumen de consultas, la localidad de los datos o el cumplimiento superan el costo de un endpoint gestionado. Para muchos casos de uso, un endpoint de archivo alojado es más rentable y requiere menos sobrecarga operativa.

Considera el costo total de propiedad: hardware, ancho de banda, monitoreo y actualizaciones. Si tu volumen de consultas es bajo o intermitente, un endpoint gestionado puede ser más barato. Si necesitas localidad de datos garantizada o tienes requisitos de cumplimiento, el autoalojamiento puede ser necesario. Para consideraciones de precios, consulta Precios de RPC.

  • Almacenamiento: crecimiento continuo, NVMe con alta resistencia.
  • Seguridad: suposición de confianza en el snapshot.
  • Costo: compensación entre autoalojamiento y endpoint gestionado.

Próximos pasos: elegir un endpoint y lecturas adicionales

Después de verificar tu nodo de archivo, es posible que quieras explorar endpoints gestionados para uso en producción. La página Endpoints RPC de Arbitrum (RPC Assistant) proporciona una lista de proveedores. Para una comprensión más amplia de los nodos de archivo, consulta Nodo de archivo vs nodo completo y Acceder a datos históricos de blockchain.

Para obtener información sobre el servicio API de OnFinality, visita Servicio API. Para más tutoriales, explora el centro de aprendizaje de OnFinality. Si trabajas con otras redes, consulta Nodo de archivo Base y RPC histórico y Página de la red Arbitrum.

Nunca te preocupes por la infraestructura nuevamente

OnFinality elimina la carga pesada de DevOps para que puedas construir de forma más inteligente y rápida.

Comenzar