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

eth_getRawTransactionByHash: bytes de transacción sin procesar

Aprende cómo eth_getRawTransactionByHash devuelve bytes RLP sin procesar o sobres tipados, cómo verificarlos contra el hash de la transacción y cómo retransmitirlos de forma segura.

TL;DR

eth_getRawTransactionByHash devuelve una transacción como bytes sin procesar codificados en hexadecimal: RLP puro para transacciones legacy o un sobre tipado para transacciones EIP-2718. El objeto decodificado de eth_getTransactionByHash es la interpretación que el nodo hace de esos mismos bytes, por lo que ambos deben coincidir. Puedes verificar los bytes sin procesar calculando keccak256 sobre ellos y comparando el resultado con el hash de transacción solicitado y el campo transactionHash del nodo. Retransmitir los mismos bytes sin procesar a través de eth_sendRawTransaction conserva el nonce y la firma, lo cual es útil cuando una transacción fue descartada del mempool. Esta guía cubre el método, la estructura del sobre, la verificación ejecutable en Node.js y las limitaciones que varían según el cliente y el proveedor.

Bytes de transacción sin procesar y el objeto de transacción decodificado

La especificación JSON-RPC de Ethereum define eth_getRawTransactionByHash como un método que devuelve los bytes sin procesar de una transacción dado su hash. El resultado es una cadena hexadecimal que comienza con 0x, no un objeto JSON con campos con nombre. Para una transacción legacy, esos bytes son la codificación RLP de la transacción firmada; para una transacción EIP-2718, son un byte de tipo seguido de una carga útil opaca. La referencia autorizada es la documentación de eth_getRawTransactionByHash de Ethereum JSON-RPC.

Por el contrario, eth_getTransactionByHash devuelve un objeto decodificado con campos como nonce, gasPrice o maxFeePerGas, input, v, r y s. Ese objeto es la interpretación que el nodo hace de los bytes sin procesar. Los bytes sin procesar son el artefacto canónico: son lo que se firmó, lo que se propaga por la red peer-to-peer y lo que se incluye en un bloque. Cuando necesitas retransmitir, auditar o verificar de forma independiente una transacción, el objeto decodificado por sí solo no es suficiente porque puede omitir o normalizar detalles.

Ambas representaciones deben coincidir. Si aplicas hash a los bytes sin procesar con keccak256, deberías obtener el hash de transacción que solicitaste. Si decodificas los bytes sin procesar, deberías recuperar los mismos valores de nonce, tipo y firma que reporta eth_getTransactionByHash. Una discrepancia es una señal de que el endpoint está haciendo proxy, caché o devolviendo datos de una cadena o estado diferente.

  • eth_getRawTransactionByHash devuelve bytes codificados en hexadecimal, no un objeto JSON.
  • eth_getTransactionByHash devuelve la interpretación decodificada de esos bytes.
  • Los bytes sin procesar son el artefacto firmado; el objeto decodificado es una vista.
  • La coincidencia de hash entre ambos es la verificación de consistencia principal.

Estructura del sobre tipado EIP-2718 y trampas del parser

EIP-2718 introdujo un sobre de transacción tipada: un único byte de tipo seguido de una carga útil opaca. La especificación EIP-2718 lo define como TransactionType || TransactionPayload. Las transacciones legacy son el caso especial en el que toda la cadena de bytes es RLP puro sin byte de tipo inicial. Esto significa que un parser que asume que toda transacción sin procesar es RLP malinterpretará las transacciones tipadas, porque el primer byte es un identificador de tipo en lugar de un prefijo de lista RLP.

Los bytes de tipo comunes incluyen 0x01 para transacciones con lista de acceso (EIP-2930), 0x02 para transacciones con tarifa dinámica (EIP-1559) y 0x03 para transacciones blob (EIP-4844). La carga útil después del byte de tipo está codificada en RLP para estos tipos, pero el framing externo no es una única lista RLP. Para una mirada más profunda al sobre de tipo 3 y los campos específicos de blob, consulta Transacciones blob de Ethereum y EIP-4844.

Un decodificador robusto debe inspeccionar el primer byte. Si es 0x01, 0x02 o 0x03, trata el resto como una carga útil tipada y decodifica en consecuencia. Si es un prefijo de lista RLP como 0xf8 o 0xf9, trata toda la cadena de bytes como RLP legacy. Esta ramificación es la diferencia entre un decodificador correcto y uno que produce campos basura silenciosamente.

  • Legacy: RLP puro, sin byte de tipo.
  • Tipo 0x01: lista de acceso (EIP-2930).
  • Tipo 0x02: tarifa dinámica (EIP-1559).
  • Tipo 0x03: blob (EIP-4844).
  • Siempre ramifica según el byte inicial antes de decodificar.

Verificación de bytes sin procesar contra el hash de la transacción

El hash de la transacción se define como keccak256 de los bytes sin procesar de la transacción. Esto es cierto tanto para transacciones legacy como tipadas: el byte de tipo se incluye en la preimagen del hash. Por lo tanto, la verificación más directa es calcular keccak256 sobre los bytes devueltos por eth_getRawTransactionByHash y comparar el resultado con el hash que solicitaste. Si difieren, el endpoint devolvió bytes de una transacción diferente o de una cadena diferente.

Una segunda comprobación es comparar con eth_getTransactionByHash. El objeto decodificado debería reportar el mismo transactionHash, el mismo tipo y el mismo nonce. Si los bytes sin procesar decodifican a una transacción de tipo 0x02 pero el objeto decodificado dice tipo 0x00, algo es inconsistente. Esto puede ocurrir con proxies mal configurados o endpoints que sirven datos obsoletos.

Para una visión más amplia de cómo se organizan los datos de transacción en bloques y recibos, consulta Recibos masivos eth_getBlockReceipts. Los recibos confirman la inclusión, mientras que los bytes sin procesar confirman la carga útil firmada exacta.

  • keccak256(rawBytes) debe ser igual al hash de transacción solicitado.
  • El transactionHash del objeto decodificado debe coincidir con el mismo valor.
  • El tipo y el nonce del objeto decodificado deben coincidir con los bytes sin procesar.
  • Las discrepancias indican un endpoint con proxy, obsoleto o de cadena incorrecta.

Ejemplo ejecutable en Node.js: obtener, detectar tipo y verificar hash

El siguiente script de Node.js utiliza la API fetch integrada y la librería ethers para keccak256 y la decodificación RLP. Obtiene los bytes sin procesar, detecta el tipo de transacción a partir del byte inicial, calcula el hash keccak256 y lo compara con el hash solicitado. También obtiene el objeto decodificado para una comprobación de segunda fuente.

Reemplaza RPC_URL con el endpoint de tu proveedor. La página de la red Ethereum de OnFinality enumera los endpoints compatibles, y la guía del nodo RPC de Ethereum cubre los conceptos básicos de conexión. El script es intencionalmente mínimo para que puedas adaptarlo a tu propio flujo de verificación.

const { keccak256 } = require('ethers/lib/utils');
const RPC_URL = process.env.RPC_URL || 'https://api.onfinality.io/public/eth';
const TX_HASH = process.env.TX_HASH;

async function rpc(method, params) {
  const res = await fetch(RPC_URL, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ jsonrpc: '2.0', id: 1, method, params })
  });
  const json = await res.json();
  if (json.error) throw new Error(JSON.stringify(json.error));
  return json.result;
}

function detectType(rawHex) {
  const first = parseInt(rawHex.slice(2, 4), 16);
  if (first === 0x01) return '0x01 access list (EIP-2930)';
  if (first === 0x02) return '0x02 dynamic fee (EIP-1559)';
  if (first === 0x03) return '0x03 blob (EIP-4844)';
  return 'legacy RLP';
}

(async () => {
  const raw = await rpc('eth_getRawTransactionByHash', [TX_HASH]);
  if (!raw) throw new Error('raw transaction not found');
  const type = detectType(raw);
  const computed = keccak256(raw);
  const decoded = await rpc('eth_getTransactionByHash', [TX_HASH]);
  console.log('requested hash:', TX_HASH);
  console.log('computed hash :', computed);
  console.log('hash match    :', computed.toLowerCase() === TX_HASH.toLowerCase());
  console.log('detected type :', type);
  console.log('decoded type  :', decoded ? decoded.type : 'n/a');
  console.log('decoded nonce :', decoded ? decoded.nonce : 'n/a');
  console.log('decoded hash  :', decoded ? decoded.hash : 'n/a');
})();

Retransmisión de bytes sin procesar sin volver a firmar

Cuando una transacción se descarta del mempool, los bytes sin procesar firmados siguen siendo válidos hasta que se consume el nonce. Puedes retransmitir exactamente los mismos bytes con eth_sendRawTransaction. Como los bytes ya contienen la firma, el nonce y los parámetros de gas, la retransmisión los conserva todos. Esto es más seguro que volver a firmar, lo que podría producir un hash diferente y crear una transacción competidora.

El espacio de nombres del pool de transacciones y mempool de Ethereum explica cómo se rastrean las transacciones pendientes. Una transacción sin procesar pendiente puede estar disponible a través de eth_getRawTransactionByHash antes de que exista un recibo, porque está en el pool en lugar de en un bloque. Una vez minada, los mismos bytes sin procesar forman parte del bloque y el recibo queda disponible.

Para flujos de trabajo relacionados con MEV, los bytes sin procesar también son la entrada para el envío de bundles. Consulta Bundles MEV de Ethereum y eth_sendBundle para saber cómo los bundles transportan transacciones firmadas. Se aplica el mismo principio: los bytes sin procesar son la unidad de propagación.

  • Retransmite los mismos bytes sin procesar para conservar nonce y firma.
  • No vuelvas a firmar a menos que quieras reemplazar la transacción.
  • Los bytes sin procesar pendientes pueden estar disponibles antes de un recibo.
  • Los bytes sin procesar minados forman parte del bloque; los recibos confirman la inclusión.

Ejemplo ejecutable con curl: obtener bytes sin procesar y comparar endpoints

Una comprobación rápida con curl te ayuda a confirmar si un endpoint admite eth_getRawTransactionByHash y si dos endpoints coinciden. El siguiente ejemplo envía la misma solicitud a dos URL RPC e imprime los bytes sin procesar. Si un endpoint devuelve un error o una cadena de bytes diferente, tienes un problema de proveedor o de configuración.

También es una forma útil de probar si un proveedor restringe el método detrás de un espacio de nombres o una bandera. Algunos clientes deshabilitan la recuperación de transacciones sin procesar de forma predeterminada. La página del servicio de API describe cómo OnFinality expone los endpoints JSON-RPC, y Precios de RPC cubre el acceso a nivel de plan.

TX_HASH=0xYOUR_TRANSACTION_HASH

for URL in https://api.onfinality.io/public/eth https://your-other-rpc.example/eth; do
  echo "== $URL =="
  curl -s -X POST "$URL" \
    -H 'Content-Type: application/json' \
    -d '{"jsonrpc":"2.0","id":1,"method":"eth_getRawTransactionByHash","params":["'"$TX_HASH"'"]}' \
    | head -c 400
  echo
done

Tabla de resultados: medir la recuperación de transacciones sin procesar en tu endpoint

Debido a que el comportamiento del proveedor y la compatibilidad del cliente varían, el enfoque más fiable es medir contra tu propio endpoint. Usa la tabla a continuación para registrar lo que observes. No te bases en cifras publicadas de otros entornos; tus resultados dependen de tu cliente, tu proveedor y tus condiciones de red.

Ejecuta el ejemplo de Node.js o curl contra tu endpoint y completa cada fila. El objetivo es documentar si el método está disponible, si el hash se verifica y si el objeto decodificado coincide. Esto convierte un ambiguo "funciona" en una comprobación reproducible.

  • URL del endpoint: la URL RPC exacta que probaste.
  • Método disponible: sí/no, o código de error si está restringido.
  • Bytes sin procesar devueltos: primeros 20 caracteres hexadecimales como referencia.
  • Tipo detectado: legacy, 0x01, 0x02 o 0x03.
  • Coincidencia keccak256: verdadero/falso contra el hash solicitado.
  • Coincidencia del objeto decodificado: tipo, nonce y hash coinciden verdadero/falso.
  • Notas: cualquier bandera específica del proveedor o requisito de espacio de nombres.

Solución de problemas: discrepancias, bytes faltantes y retransmisiones rechazadas

Si eth_getRawTransactionByHash devuelve null, es posible que la transacción no sea conocida por ese nodo. Esto puede ocurrir si el nodo no está completamente sincronizado, si la transacción está en una cadena diferente o si el hash es incorrecto. Verifica primero la longitud y el prefijo del hash, luego confirma el chain ID y el estado de sincronización del nodo.

Si el método devuelve un error como 'method not found' o 'method not enabled', el cliente puede restringir la recuperación de transacciones sin procesar detrás de una bandera o un espacio de nombres. Este es un comportamiento documentado que varía según el cliente. Algunos clientes lo exponen solo cuando la transacción está en el pool o solo para bloques recientes. Consulta la documentación de tu cliente y los métodos compatibles de tu proveedor.

Si keccak256 de los bytes sin procesar no coincide con el hash solicitado, el endpoint puede estar haciendo proxy a una cadena diferente o devolviendo datos en caché. Compara con un segundo endpoint. Si eth_sendRawTransaction rechaza una retransmisión con un error de nonce, ese rechazo es correcto: el nonce ya se consumió, lo que significa que la transacción original fue minada o reemplazada. No lo trates como un error.

  • Resultado null: verifica hash, chain ID y estado de sincronización.
  • Método no encontrado: el cliente puede restringir el método detrás de una bandera.
  • Discrepancia de hash: sospecha de proxy, caché o cadena incorrecta.
  • Rechazo por nonce en retransmisión: el nonce ya está consumido.
  • Los bytes sin procesar incluyen la firma; no son solo el cuerpo del mensaje.

Limitaciones y compensaciones de la recuperación de transacciones sin procesar

No todos los clientes habilitan eth_getRawTransactionByHash de forma predeterminada. Algunos requieren una bandera, otros lo exponen solo bajo un espacio de nombres específico y algunos proveedores no lo enrutan en absoluto. Este es un comportamiento documentado que varía según el cliente y el proveedor, por lo que debes verificar la compatibilidad antes de construir un flujo de trabajo que dependa de él.

Los bytes sin procesar son la transacción firmada completa, incluida la firma. No son el cuerpo del mensaje sin firmar. Si necesitas verificar una firma, debes decodificar los bytes y extraer v, r y s, y luego recuperar el firmante. Los bytes sin procesar por sí solos no te dicen quién firmó sin ese paso.

La retransmisión no garantiza la inclusión. Si el nonce ya se consumió, la red rechazará la transacción. Si los precios del gas se han movido, la transacción puede permanecer pendiente. Los bytes sin procesar conservan los parámetros originales, lo cual es tanto su fortaleza como su limitación: no puedes ajustar las tarifas sin volver a firmar.

  • La compatibilidad del cliente varía; algunos restringen el método detrás de una bandera.
  • Los bytes sin procesar incluyen la firma, no solo el cuerpo del mensaje.
  • La retransmisión conserva nonce y firma, pero no la inclusión.
  • Los cambios de tarifa requieren volver a firmar y producen un nuevo hash.

Próximos pasos: integrar bytes sin procesar en tu flujo de trabajo

Comienza agregando un paso de verificación a tu monitoreo de transacciones. Cada vez que obtengas una transacción, obtén también sus bytes sin procesar y confirma el hash keccak256. Esto detecta inconsistencias de endpoint a tiempo. El centro de aprendizaje de OnFinality tiene guías relacionadas sobre pools de transacciones, recibos y transacciones blob.

Para sistemas en producción, considera almacenar en caché los bytes sin procesar junto con el objeto decodificado. Esto te permite retransmitir sin otra llamada RPC y te da un rastro de auditoría de la carga útil firmada exacta. Si usas varios proveedores, ejecuta la tabla de resultados contra cada uno para documentar compatibilidad y comportamiento.

Finalmente, revisa la compatibilidad de métodos de tu proveedor y los límites del plan. Las páginas de la red Ethereum y Precios de RPC describen los endpoints disponibles y los niveles de acceso. Combina la recuperación de transacciones sin procesar con comprobaciones de recibos y monitoreo del mempool para obtener una visión completa del ciclo de vida de la transacción.

  • Agrega la verificación keccak256 al monitoreo de transacciones.
  • Almacena en caché los bytes sin procesar para retransmisión y auditoría.
  • Prueba cada proveedor con la tabla de resultados.
  • Combina con recibos y monitoreo del mempool.

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