Una transacción blob de EIP-4844 es una envoltura de tipo 0x03 que transporta uno o más blobs, pero los datos del blob en sí no forman parte del payload de ejecución; la transacción se compromete a ellos mediante hashes versionados (compromisos KZG) y el recibo registra blobGasUsed y blobGasPrice. Los blobs se tarifan con una blob base fee independiente que se actualiza mediante un mecanismo de exceso de blob gas, por lo que el gas de ejecución y el blob gas pueden ser baratos o caros de forma independiente. Leer una transacción blob vía JSON-RPC requiere eth_getTransactionByHash para blobVersionedHashes y el recibo para blobGasUsed y blobGasPrice; el sidecar (blobs, compromisos, pruebas) viaja con la transacción en bruto pero no se almacena en la cadena y se poda tras una ventana de retención. Este artículo muestra cómo enviar y verificar una transacción tipo 3 contra un único endpoint, calcular explícitamente la comisión total de blob y distinguir la disponibilidad del sidecar específica del proveedor de la retención a nivel de protocolo. También cubre la solución de problemas para sidecars eliminados, recibos incompletos, nodos pre-Dencun y estimadores de comisiones que omiten la dimensión blob.
Envoltura de transacción tipo 3 y mecánica del compromiso blob
Una transacción blob de EIP-4844 es una envoltura de transacción normal con un nuevo identificador de tipo, 0x03, que transporta uno o más blobs. Los datos del blob en sí no forman parte del payload de ejecución; en su lugar, la transacción se compromete al blob mediante un hash versionado, que es un compromiso KZG al polinomio del blob. Esto significa que un llamador RPC que solo lee campos de ejecución no puede saber si se publicó un blob ni cuánto costó. La especificación autoritativa es EIP-4844: Shard Blob Transactions, y la semántica de los métodos JSON-RPC se define en la especificación de execution-apis de Ethereum.
Los campos tipo 3 que un lector debe reconocer son maxFeePerBlobGas, blobVersionedHashes y el sidecar (blobs, compromisos, pruebas) que viaja con la transacción en bruto pero no se almacena en la cadena. El sidecar es propagado y retenido por la capa de consenso y se poda tras una ventana acotada en lugar de conservarse como parte del estado de Ethereum. En consecuencia, una lectura JSON-RPC del contenido de un blob es una consulta de disponibilidad que puede fallar legítimamente para un bloque antiguo mientras que el bloque en sí es perfectamente consultable. Debes distinguir 'este endpoint no sirve sidecars de blob' de 'este blob ha caducado'.
Como los datos del blob no están en el payload de ejecución, el bloque se compromete a datos que no almacena. Por eso lo que sobrevive en el bloque son los blobVersionedHashes y no los bytes del blob. Para una visión más amplia de cómo OnFinality expone las redes Ethereum, consulta /en/networks/eth.
- Envoltura tipo 0x03: campos de ejecución más campos específicos de blob.
- blobVersionedHashes: uno por blob, derivado de los compromisos KZG.
- Sidecar: blobs, compromisos, pruebas — no se almacena en la cadena.
- Recibo: blobGasUsed y blobGasPrice registran la comisión de blob realmente pagada.
Mercado de comisiones bidimensional: gas de ejecución vs blob gas
El gas de ejecución se tarifa con baseFee más una propina de prioridad, mientras que los blobs se tarifan con una blob base fee independiente que se actualiza mediante su propio mecanismo de exceso de blob gas. Esto significa que una transacción puede ser barata en gas de ejecución y cara en blob gas al mismo tiempo. Un estimador de comisiones que solo lee baseFeePerGas de eth_feeHistory subestimará o eliminará por completo la comisión de blob. Para la estimación de comisiones de ejecución, consulta Historial de comisiones de Ethereum y estimación de comisiones.
El cálculo de la comisión de blob es explícito: la comisión total de blob es igual a blobGasUsed multiplicado por blobGasPrice, y blobGasUsed es igual al número de blobs multiplicado por la constante de protocolo GAS_PER_BLOB (131072). Debes verificarlo con tu propio recibo en lugar de codificarlo de forma fija. La blob base fee no es devuelta por eth_feeHistory en todas las implementaciones; algunos proveedores la exponen mediante eth_blobBaseFee o la incluyen en las cabeceras de bloque como blobBaseFee. Este comportamiento está documentado / varía según el proveedor.
Al enviar una transacción tipo 3, debes establecer maxFeePerBlobGas además de maxFeePerGas y maxPriorityFeePerGas. Si maxFeePerBlobGas es demasiado bajo, la transacción será rechazada o quedará atascada. El mercado de comisiones de blob es independiente, por lo que un pico en la demanda de blobs no afecta necesariamente a los precios del gas de ejecución.
- Gas de ejecución: baseFee + propina de prioridad.
- Blob gas: blob base fee independiente a partir del exceso de blob gas.
- GAS_PER_BLOB = 131072 (constante de protocolo).
- maxFeePerBlobGas es obligatorio para transacciones tipo 3.
Enviar una transacción blob tipo 3 vía JSON-RPC
Para enviar una transacción blob, construyes una transacción tipo 3 con el sidecar del blob y la envías mediante eth_sendRawTransaction. La transacción en bruto debe incluir los blobs, los compromisos y las pruebas. El nodo validará los compromisos KZG y propagará el sidecar a la capa de consenso. La especificación de execution-apis define eth_sendRawTransaction como la aceptación de una transacción en bruto firmada y la devolución del hash de la transacción. Para un endpoint de producción, consulta /en/networks/eth.
A continuación se muestra un script de Node.js ejecutable que envía una transacción tipo 3 usando ethers.js. Asume que tienes una URL de proveedor y un firmante con fondos. Construye una transacción blob con un blob, establece maxFeePerBlobGas y la envía. El script imprime el hash de la transacción y luego sondea el recibo para mostrar blobGasUsed y blobGasPrice.
Ten en cuenta que el sidecar no se almacena en la cadena; el script solo lo envía. Después de enviar, puedes verificar la transacción por hash usando eth_getTransactionByHash y eth_getTransactionReceipt. El recibo contendrá blobGasUsed y blobGasPrice, que puedes usar para calcular la comisión total de blob.
const { ethers } = require('ethers');
async function main() {
const provider = new ethers.JsonRpcProvider(process.env.RPC_URL);
const wallet = new ethers.Wallet(process.env.PRIVATE_KEY, provider);
// Example blob data (32 bytes)
const blobData = '0x' + '00'.repeat(32);
const tx = {
to: wallet.address,
value: 0,
maxFeePerGas: ethers.parseUnits('10', 'gwei'),
maxPriorityFeePerGas: ethers.parseUnits('1', 'gwei'),
maxFeePerBlobGas: ethers.parseUnits('10', 'gwei'),
blobs: [{ data: blobData }],
kzg: undefined // ethers v6 handles KZG via provider
};
const sent = await wallet.sendTransaction(tx);
console.log('Transaction hash:', sent.hash);
const receipt = await sent.wait();
console.log('blobGasUsed:', receipt.blobGasUsed.toString());
console.log('blobGasPrice:', receipt.blobGasPrice.toString());
const totalBlobFee = receipt.blobGasUsed * receipt.blobGasPrice;
console.log('Total blob fee (wei):', totalBlobFee.toString());
}
main().catch(console.error);Leer y conciliar una transacción tipo 3 por hash
La ruta de lectura que realmente funciona es: recuperar la transacción por hash con eth_getTransactionByHash para obtener blobVersionedHashes y blobGasUsed/blobGasPrice, luego recuperar el recibo y leer blobGasUsed y blobGasPrice para calcular la comisión de blob realmente pagada. También debes comprobar si el endpoint expone algún método de sidecar de blob; esto está documentado / varía según el proveedor. Algunos proveedores ofrecen eth_getBlobSidecar o eth_getBlobs, pero no forman parte de la especificación central de execution-apis.
A continuación se muestra un script de Node.js ejecutable que toma un hash de transacción tipo 3 conocido, obtiene la transacción y el recibo, clasifica el tipo de transacción, extrae los hashes versionados e imprime una tabla de hashes versionados, número de blobs, blobGasUsed, blobGasPrice, comisión total de blob derivada y comisión de ejecución en paralelo. Utiliza únicamente métodos JSON-RPC estándar.
El script usa eth_getTransactionByHash y eth_getTransactionReceipt. Calcula la comisión de ejecución como gasUsed multiplicado por effectiveGasPrice. También comprueba la presencia de blobVersionedHashes y blobGasUsed para confirmar que la transacción es tipo 3. Si el proveedor elimina los campos del sidecar, el script seguirá funcionando porque solo lee campos en la cadena.
const { ethers } = require('ethers');
async function inspectBlobTx(txHash) {
const provider = new ethers.JsonRpcProvider(process.env.RPC_URL);
const tx = await provider.getTransaction(txHash);
if (!tx) throw new Error('Transaction not found');
const receipt = await provider.getTransactionReceipt(txHash);
if (!receipt) throw new Error('Receipt not found');
const type = tx.type;
console.log('Transaction type:', type);
const versionedHashes = tx.blobVersionedHashes || [];
const blobCount = versionedHashes.length;
const blobGasUsed = receipt.blobGasUsed ? receipt.blobGasUsed.toString() : 'N/A';
const blobGasPrice = receipt.blobGasPrice ? receipt.blobGasPrice.toString() : 'N/A';
let totalBlobFee = 'N/A';
if (receipt.blobGasUsed && receipt.blobGasPrice) {
totalBlobFee = (receipt.blobGasUsed * receipt.blobGasPrice).toString();
}
const executionFee = (receipt.gasUsed * receipt.effectiveGasPrice).toString();
console.log('\n--- Blob Transaction Report ---');
console.log('Versioned Hashes:');
versionedHashes.forEach((h, i) => console.log(` ${i}: ${h}`));
console.log('Blob Count:', blobCount);
console.log('blobGasUsed:', blobGasUsed);
console.log('blobGasPrice:', blobGasPrice);
console.log('Total Blob Fee (wei):', totalBlobFee);
console.log('Execution Fee (wei):', executionFee);
}
inspectBlobTx(process.argv[2]).catch(console.error);Cálculo de la comisión de blob y verificación con tu recibo
La comisión total de blob se calcula como blobGasUsed multiplicado por blobGasPrice. blobGasUsed es el número de blobs multiplicado por GAS_PER_BLOB (131072). Debes verificarlo con tu propio recibo en lugar de codificarlo de forma fija. Por ejemplo, si tu recibo muestra blobGasUsed = 131072 y blobGasPrice = 1000000000 wei, la comisión total de blob es 131072 * 1000000000 = 131072000000000 wei. Esto es independiente de la comisión de ejecución, que es gasUsed multiplicado por effectiveGasPrice.
Para verificar, obtén el recibo y comprueba que blobGasUsed sea igual al número de hashes versionados multiplicado por 131072. Si no lo es, el proveedor puede estar devolviendo datos incompletos. Comprueba también que blobGasPrice no sea null. Algunos proveedores devuelven blobGasUsed pero omiten blobGasPrice, lo que indica una indexación incompleta. Esto es un problema específico del proveedor, no del protocolo.
La blob base fee se actualiza en función del exceso de blob gas, que es una función del blob gas total usado en bloques anteriores en relación con un objetivo. La fórmula exacta está en EIP-4844. Puedes leer la blob base fee actual desde la cabecera del último bloque si el proveedor la expone, o usar eth_blobBaseFee si está disponible. De nuevo, esto varía según el proveedor.
- Comisión total de blob = blobGasUsed * blobGasPrice.
- blobGasUsed = blobCount * 131072.
- Verifica blobGasUsed con el número de hashes versionados.
- Comprueba que blobGasPrice no sea null; si es null, la indexación del proveedor está incompleta.
Compromisos KZG y verificación de evaluación de punto
Un compromiso KZG es un compromiso polinómico que permite a un verificador comprobar que los datos de un blob coinciden con un compromiso pequeño sin tener el blob. Por eso el bloque puede comprometerse a datos que no almacena. El compromiso es un punto en una curva elíptica, y el hash versionado se deriva de él. El hash versionado es lo que aparece en la transacción y en el bloque.
La verificación de evaluación de punto es una operación criptográfica que el lector realiza sobre datos obtenidos fuera de banda, no un método JSON-RPC. Para verificar un blob, necesitas los datos del blob, el compromiso y una prueba. Puedes obtenerlos del sidecar si está disponible, o de un nodo de la capa de consenso. La verificación en sí usa la biblioteca KZG, no JSON-RPC. La especificación de execution-apis no define un método para la evaluación de punto.
Si necesitas verificar datos de blob, debes obtener el sidecar de una fuente que lo retenga. El sidecar se poda tras una ventana de retención, por lo que para blobs antiguos puede que necesites depender de datos de archivo de la capa de consenso. Esto es una cuestión de ventana de retención, no una garantía permanente.
- Compromiso KZG: compromiso pequeño al polinomio del blob.
- Hash versionado: derivado del compromiso, almacenado en la transacción.
- Evaluación de punto: verificación criptográfica, no JSON-RPC.
- Retención del sidecar: ventana acotada, no permanente.
Tabla de resultados: comportamiento del endpoint para campos tipo 3 y métodos de sidecar
Usa la siguiente tabla para registrar el comportamiento de tu propio endpoint. Rellena los valores ejecutando el script de inspección contra un hash de transacción tipo 3 conocido. Esto te ayudará a distinguir las limitaciones específicas del proveedor del comportamiento a nivel de protocolo.
Para cada fila, anota si el campo está presente, es null o está ausente. Para los métodos de sidecar, comprueba si el endpoint admite eth_getBlobSidecar, eth_getBlobs o similares. Documenta los resultados para tu proveedor.
- Tipo de transacción: ¿0x03 presente?
- blobVersionedHashes: ¿presente? ¿cuántos?
- blobGasUsed en el recibo: ¿presente? ¿valor?
- blobGasPrice en el recibo: ¿presente? ¿valor?
- Método de sidecar (eth_getBlobSidecar): ¿admitido?
- Método de blob base fee (eth_blobBaseFee): ¿admitido?
Solución de problemas comunes de RPC tipo 3
Es común que un proveedor devuelva transacciones tipo 3 con los campos del sidecar eliminados. La transacción seguirá teniendo blobVersionedHashes, pero faltarán los blobs, los compromisos y las pruebas. Esto es esperado porque el sidecar no se almacena en la cadena. Si necesitas el sidecar, debes consultar un nodo de la capa de consenso o un proveedor que sirva explícitamente sidecars de blob. Esto está documentado / varía según el proveedor.
Un recibo cuyo blobGasUsed está presente pero cuyo blobGasPrice es null indica que la indexación del proveedor está incompleta. Esto puede ocurrir si el proveedor no ha implementado completamente los campos de recibo de EIP-4844. En este caso, no puedes calcular la comisión de blob solo a partir del recibo. Puede que necesites derivarla de blobBaseFee de la cabecera del bloque y de maxFeePerBlobGas de la transacción, pero el blobGasPrice real lo determina el protocolo.
Un eth_sendRawTransaction que rechaza un payload tipo 3 porque el nodo no es post-Dencun devolverá un error como 'transaction type not supported'. Asegúrate de que tu nodo ejecuta una versión de cliente post-Dencun. De forma similar, un estimador de comisiones que omite silenciosamente la dimensión blob subestimará la transacción. Establece siempre maxFeePerBlobGas explícitamente. Para más información sobre el comportamiento del pool de transacciones, consulta Pool de transacciones de Ethereum y el espacio de nombres txpool.
- Sidecar eliminado: esperado; el sidecar no está en la cadena.
- blobGasPrice null: indexación del proveedor incompleta.
- Tipo 3 rechazado: nodo no post-Dencun.
- El estimador de comisiones omite la comisión de blob: establece maxFeePerBlobGas manualmente.
Limitaciones, compensaciones y variabilidad entre proveedores
Lo que es comportamiento de protocolo documentado: las transacciones tipo 3, el blob gas, GAS_PER_BLOB, los hashes versionados y los campos de recibo blobGasUsed y blobGasPrice están definidos en EIP-4844 y en la especificación de execution-apis. Lo que varía según el proveedor: el soporte de métodos de sidecar de blob, la disponibilidad de la blob base fee en eth_feeHistory y la completitud de la indexación del recibo. Debes verificar con tu propio endpoint.
La disponibilidad de blobs es una cuestión de ventana de retención, no una garantía permanente. El sidecar se poda tras una ventana acotada, por lo que una lectura JSON-RPC del contenido de un blob puede fallar para un bloque antiguo mientras que el bloque en sí es perfectamente consultable. EIP-7594 (PeerDAS) cambia cómo se propagan los sidecars, por lo que debes volver a verificar tras las actualizaciones de red. Consulta siempre las últimas especificaciones y la documentación de tu proveedor.
Para la recuperación masiva de recibos, consulta eth_getBlockReceipts: recibos masivos en una sola llamada. Para el trazado, consulta Trazado de transacciones de Ethereum: trace vs debug. Para la selección de endpoints, consulta Guía de endpoints RPC (RPC Assistant).
- Definido por el protocolo: campos tipo 3, blob gas, campos de recibo.
- Específico del proveedor: métodos de sidecar, disponibilidad de blob base fee.
- Ventana de retención: sidecar podado, no permanente.
- EIP-7594 cambia la propagación; vuelve a verificar tras las actualizaciones.
Próximos pasos: integrar transacciones blob en tu flujo de trabajo
Para integrar transacciones blob en tu flujo de trabajo, empieza por asegurarte de que tu nodo o proveedor es post-Dencun y admite transacciones tipo 3. Usa el script de inspección para verificar que tu endpoint devuelve blobVersionedHashes y los campos de blob del recibo. Si necesitas enviar blobs, usa una biblioteca como ethers.js que gestione los compromisos KZG y la construcción del sidecar.
Para producción, considera usar un proveedor que ofrezca disponibilidad fiable de sidecars de blob si necesitas leer datos de blobs. OnFinality proporciona endpoints RPC de Ethereum; consulta /en/networks/eth y Precios de RPC para más detalles. También puedes explorar el centro de aprendizaje de OnFinality para más guías, y el servicio de API para acceso gestionado.
Por último, calcula siempre la comisión total de blob a partir del recibo y compárala con tus expectativas. Supervisa las tendencias de la blob base fee para elegir el momento de publicar tus blobs. Recuerda que el blob gas y el gas de ejecución son independientes, así que optimiza cada uno por separado.
- Verifica que el endpoint admite tipo 3 y campos de blob en el recibo.
- Usa ethers.js o similar para enviar blobs.
- Elige un proveedor con disponibilidad de sidecar si es necesario.
- Supervisa la blob base fee para optimizar costes.