Logo
Nuevos usuarios de RPC: 35% de descuento el primer mesVer oferta
OnFinality Learn
Guías de Red y Protocolo12 min de lectura

Transacciones Versionadas de Solana y Análisis de getBlock/getTransaction: v0, Tablas de Búsqueda de Direcciones y Decodificación

Aprende a analizar transacciones versionadas de Solana (v0) devueltas por getBlock y getTransaction, incluyendo tablas de búsqueda de direcciones, indicadores de versión y pasos de decodificación con un script ejecutable.

TL;DR

Una inmersión profunda en las transacciones versionadas de Solana (v0) y cómo analizarlas correctamente desde las respuestas RPC de getBlock/getTransaction, cubriendo tablas de búsqueda de direcciones, indicadores de versión y un script de decodificación ejecutable.

Respuesta Directa: Análisis de Transacciones Versionadas de Solana desde getBlock/getTransaction

Cuando llamas a getBlock o getTransaction en un endpoint RPC de Solana, el objeto de transacción que recibes puede ser una transacción heredada o una transacción versionada (v0). La clave para analizarlas correctamente es inspeccionar el primer byte del mensaje de transacción: si el bit alto (0x80) está establecido, es una transacción v0 que utiliza tablas de búsqueda de direcciones (ALT). Para transacciones v0, la lista de cuentas no está completamente en línea; parte de ella se referencia a través de tablas de búsqueda, por lo que un analizador ingenuo que asume que todas las cuentas están en línea producirá resultados incorrectos. Este artículo explica el mecanismo y proporciona un script reproducible para decodificar ambos tipos.

La documentación de Solana sobre Transacciones Versionadas y Tablas de Búsqueda de Direcciones son las fuentes primarias del protocolo. Los documentos de los métodos RPC getBlock y getTransaction también describen los formatos de respuesta en detalle.

Cómo Funcionan las Transacciones Versionadas

Las transacciones de Solana tienen un formato de cable que está codificado en base58 (o base64 cuando se usa JSON-RPC con encoding: 'base64'). El mensaje de transacción comienza con un encabezado que incluye un indicador de versión. Los mensajes heredados comienzan con un número corto-u16 de firmas requeridas, seguido del número de cuentas firmadas de solo lectura, etc. En contraste, los mensajes v0 establecen el bit alto del primer byte (0x80) para indicar que son versionados, y luego codifican el número de versión (actualmente 0) en los bits bajos.

La principal diferencia es que los mensajes v0 pueden incluir una sección addressTableLookups. Esta sección lista una o más direcciones de tabla de búsqueda, cada una con una lista de índices en esa tabla. Las claves públicas de cuentas reales no se almacenan en línea en el mensaje; se resuelven obteniendo los datos de la cuenta de la tabla desde la blockchain. Esto permite que las transacciones referencien más del límite estático de 32 cuentas heredado, porque la tabla puede contener hasta 256 cuentas, y cada búsqueda agrega solo unos pocos bytes al mensaje.

Para una explicación detallada, consulta los documentos de Solana sobre Transacciones Versionadas - v0: Tablas de Búsqueda de Direcciones.

Análisis de Respuestas de getBlock y getTransaction

Cuando solicitas una transacción con getTransaction o getBlock, puedes especificar una codificación. El valor predeterminado es json, que devuelve una representación analizada si usas getParsedTransaction o getParsedBlock. En el formato analizado, el objeto de transacción incluye un message con accountKeys (una matriz de objetos con pubkey y banderas signer/writable), instructions y addressTableLookups (si los hay). El campo version indica si es 'legacy' o '0'.

Si solicitas encoding: 'jsonParsed', el RPC devuelve una transacción completamente analizada con datos de instrucción legibles por humanos. Sin embargo, si solicitas encoding: 'base58' o encoding: 'base64', obtienes el blob de transacción sin procesar, que debes decodificar tú mismo. El blob sin procesar es lo que necesitas analizar si quieres entender el formato de cable o si estás construyendo una herramienta de bajo nivel.

Los documentos RPC de Solana para getTransaction y getBlock describen los formatos de respuesta. Para una perspectiva comunitaria, consulta la guía de transacciones versionadas de Solana.

Decodificación Paso a Paso con un Script Ejecutable

A continuación se muestra un script de Node.js que obtiene una transacción reciente (proporcionas la firma), inspecciona el indicador de versión, expande las búsquedas de tablas de direcciones y decodifica las instrucciones. Utiliza la biblioteca @solana/web3.js, que maneja el análisis de bajo nivel por ti. El script imprime un resumen de la transacción, incluida la versión, las claves de cuenta y los detalles de las instrucciones.

Para ejecutarlo, necesitarás instalar las dependencias y proporcionar tu propia URL RPC y una firma de transacción reciente. El script es autónomo y utiliza solo bibliotecas públicas.

// decode-solana-tx.js
// Uso: node decode-solana-tx.js <RPC_URL> <TX_SIGNATURE>
// Ejemplo: node decode-solana-tx.js https://api.mainnet-beta.solana.com <signature>

const web3 = require('@solana/web3.js');

async function main() {
  const rpcUrl = process.argv[2];
  const signature = process.argv[3];
  if (!rpcUrl || !signature) {
    console.error('Por favor, proporciona la URL RPC y la firma de la transacción.');
    process.exit(1);
  }

  const connection = new web3.Connection(rpcUrl, 'confirmed');
  const tx = await connection.getParsedTransaction(signature, {
    maxSupportedTransactionVersion: 0, // permitir v0
  });

  if (!tx) {
    console.error('Transacción no encontrada.');
    process.exit(1);
  }

  console.log('Versión de la transacción:', tx.version);
  console.log('Slot:', tx.slot);
  console.log('Tiempo de bloque:', tx.blockTime);

  const meta = tx.meta;
  if (meta) {
    console.log('Tarifa:', meta.fee);
    console.log('Registros:', meta.logMessages);
  }

  const message = tx.transaction.message;
  console.log('Claves de cuenta:');
  message.accountKeys.forEach((key, i) => {
    console.log(`  [${i}] ${key.pubkey.toString()} (firmante: ${key.signer}, escribible: ${key.writable})`);
  });

  if (message.addressTableLookups && message.addressTableLookups.length > 0) {
    console.log('Búsquedas de tabla de direcciones:');
    for (const lookup of message.addressTableLookups) {
      console.log(`  Tabla: ${lookup.accountKey.toString()}`);
      console.log(`    Índices escribibles: ${lookup.writableIndexes.join(', ')}`);
      console.log(`    Índices de solo lectura: ${lookup.readonlyIndexes.join(', ')}`);
    }
  }

  console.log('Instrucciones:');
  for (const ix of message.instructions) {
    console.log(`  Programa: ${ix.programId.toString()}`);
    console.log(`    Cuentas: ${ix.accounts.map(a => a.toString()).join(', ')}`);
    console.log(`    Datos: ${ix.data}`);
  }
}

main().catch(err => {
  console.error(err);
  process.exit(1);
});

Salida Esperada y Verificación

Cuando ejecutes el script con una firma de transacción v0 válida, verás una salida similar a la siguiente (los valores reales variarán):

El script imprime la versión de la transacción, slot, tarifa, claves de cuenta, búsquedas de tabla de direcciones (si las hay) e instrucciones decodificadas. Para verificar la corrección, puedes contrastar las claves de cuenta y los datos de instrucción con un explorador de bloques como Solscan o Solana Explorer.

Si la transacción es heredada, el campo version será 'legacy' y no habrá addressTableLookups. El script maneja ambos casos.

Versión de la transacción: 0
Slot: 123456789
Tiempo de bloque: 1699999999
Tarifa: 5000
Registros: [...]
Claves de cuenta:
  [0] 11111111111111111111111111111111 (firmante: true, escribible: true)
  [1] ...
Búsquedas de tabla de direcciones:
  Tabla: 8mU... (firmante: false, escribible: false)
    Índices escribibles: 1, 2
    Índices de solo lectura: 0
Instrucciones:
  Programa: 11111111111111111111111111111111
    Cuentas: 11111111111111111111111111111111, ...
    Datos: 3Bxs...

Fallos Comunes y Soluciones

Al analizar transacciones de Solana, puedes encontrarte con varios problemas comunes. La tabla a continuación mapea los síntomas a las causas y soluciones.

  • La transacción no se analiza: Si estás usando una biblioteca que no admite v0 (por ejemplo, una versión anterior de @solana/web3.js), obtendrás un error. Solución: actualiza a una versión que admita maxSupportedTransactionVersion: 0.
  • La lista de cuentas parece incorrecta: Si analizas una transacción v0 como heredada, la lista de cuentas estará incompleta o será incorrecta porque no incluye las cuentas de la tabla de búsqueda. Solución: verifica siempre el indicador de versión y expande las búsquedas de tablas de direcciones.
  • ALT deshabilitado: Algunos endpoints RPC o bibliotecas pueden deshabilitar las tablas de búsqueda de direcciones por defecto. Solución: establece explícitamente maxSupportedTransactionVersion: 0 en tu solicitud.
  • base58 vs base64: Si solicitas encoding: 'base58', obtienes una cadena base58; si solicitas encoding: 'base64', obtienes una cadena base64. Asegúrate de que tu decodificador coincida con la codificación.
  • Datos de tabla de búsqueda faltantes: Para expandir las búsquedas de tablas de direcciones, necesitas obtener los datos de la cuenta de la tabla. Si la tabla se ha cerrado o no está disponible, la decodificación falla. Solución: asegúrate de que la tabla aún exista en la cadena.

Compensaciones y Limitaciones

Las transacciones versionadas con tablas de búsqueda de direcciones ofrecen beneficios significativos: permiten más cuentas por transacción, reducen el tamaño de la transacción y habilitan instrucciones más complejas. Sin embargo, introducen una dependencia de la existencia de la tabla de búsqueda y requieren una llamada RPC adicional para obtener los datos de la tabla si estás decodificando manualmente.

El formato heredado es más simple y autónomo, pero está limitado a 32 cuentas. Para la mayoría de las aplicaciones modernas de Solana, v0 es el estándar, y debes diseñar tus herramientas para manejar ambos.

Cuando usas un endpoint RPC público, puedes encontrarte con límites de velocidad o problemas de latencia. Para producción, considera un endpoint dedicado de un proveedor como OnFinality. Consulta nuestras páginas de precios RPC y servicio API para opciones.

Próximos Pasos y Lecturas Adicionales

Ahora que entiendes cómo analizar transacciones versionadas, puedes aplicar este conocimiento para construir aplicaciones de Solana más robustas. Para más temas de RPC de Solana, consulta nuestras guías sobre consulta de datos históricos, suscripciones WebSocket y tiempos de espera y reintentos.

Si trabajas con múltiples llamadas RPC, consulta nuestras mejores prácticas de agrupación JSON-RPC. Para una lista completa de métodos RPC de Solana, consulta los métodos JSON-RPC de Solana (Asistente RPC).

Explora el centro de aprendizaje de OnFinality para más tutoriales, y no olvides consultar nuestra página de red de Solana para detalles de endpoints.

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