Un "top trace" es el frame de llamada más externo en el trazado de ejecución de una transacción: el punto de entrada del que descienden cada llamada interna, reversión y registro. Leer primero el top trace le indica si un fallo ocurrió en la lógica de la propia transacción, en una llamada anidada a un contrato o antes de que comenzara la ejecución. Este artículo explica el modelo mental detrás de los métodos RPC trace y debug, ofrece un procedimiento ejecutable para capturar y comparar trazas entre proveedores y muestra cómo convertir una traza sin procesar en un diagnóstico. Separa el comportamiento documentado del nodo de las mediciones que usted debe ejecutar contra su propio endpoint RPC.
Qué representa realmente un top trace
Cuando una transacción se ejecuta en una cadena EVM, el nodo registra un árbol de frames de llamada: la llamada de entrada de la transacción, cada llamada a contrato que realiza, cada delegatecall, staticcall y create, además del estado de retorno o reversión de cada uno. El top trace es la raíz de ese árbol: el frame correspondiente a la transacción misma, con la dirección to, los datos de entrada, el gas suministrado y el estado final de toda la ejecución.
Esto importa porque la mayoría de los fallos de transacción se le presentan como una única cadena opaca. Una billetera o dapp ve execution reverted sin motivo, o una transacción que nunca se mina, y el error de nivel superior no le dice nada sobre qué llamada anidada falló. La traza es la única forma fiable de recorrer desde ese síntoma hasta el frame que realmente revirtió.
El término también se usa de forma laxa para la primera traza devuelta por una API de trazado cuando se consulta una dirección o un bloque. En este artículo significa el frame raíz de la ejecución de una sola transacción, que es la interpretación que hace reproducible el procedimiento de diagnóstico.
- Top trace = frame de llamada raíz de la ejecución de una transacción.
- Frames hijos = llamadas internas, delegatecalls, creates y sus resultados.
- El motivo de la reversión, si existe, suele estar en el frame fallido más profundo, no en la raíz.
Supuestos y requisitos previos
Necesita un endpoint RPC que exponga los espacios de nombres trace o debug. No todos los proveedores los habilitan: los métodos debug_* y trace_* son costosos, pueden estar deshabilitados por defecto y a menudo tienen límites de velocidad o están restringidos a nodos de archivo. Antes de crear un flujo de trabajo basado en el trazado, confirme qué métodos sirve realmente su endpoint.
También necesita el hash de una transacción que ya pueda ver en la cadena, o una transacción pendiente que esté intentando diagnosticar. Para las transacciones pendientes, el trazado depende de la visibilidad del mempool del nodo, que varía según el proveedor y no está garantizada.
Por último, trate el trazado como un diagnóstico de solo lectura. No reenvía ni modifica nada, pero puede ser lento y pesado, así que evite ejecutarlo en bucles ajustados contra un endpoint compartido. Si necesita acceso sostenido al trazado, un nodo dedicado es el lugar adecuado para ejecutarlo; consulte opciones de nodo dedicado para saber cómo se aprovisiona.
En qué se diferencian los métodos trace y debug
Hay dos familias de métodos RPC de trazado y no son intercambiables. La familia debug_* es al estilo Geth: debug_traceTransaction devuelve un árbol de llamadas anidado (o un registro plano de opcodes, según la configuración del tracer). La familia trace_* es al estilo Parity/OpenEthereum: trace_transaction devuelve una lista plana de trazas con rutas traceAddress que usted reensambla en un árbol.
Ambas describen la misma ejecución, pero las formas difieren. Una respuesta de debug_traceTransaction con el tracer de llamadas predeterminado anida los hijos dentro de calls. Una respuesta de trace_transaction le da un array donde cada entrada tiene un traceAddress como [0, 1], que significa "segundo hijo del primer hijo de la raíz". La raíz misma tiene un traceAddress vacío.
Cuál obtenga depende del cliente detrás del endpoint. Geth y Erigon exponen debug_*; Erigon y Nethermind pueden exponer trace_*; algunos proveedores exponen ambos, otros ninguno. Verifique la lista de métodos de su endpoint antes de escribir código contra él.
curl -s -X POST RPC_URL \
-H 'Content-Type: application/json' \
-d '{"jsonrpc":"2.0","id":1,"method":"debug_traceTransaction","params":["0xYOUR_TX_HASH",{"tracer":"callTracer"}]}'Captura del top trace con debug_traceTransaction
La variante callTracer es el punto de partida más legible porque devuelve una estructura anidada que puede inspeccionar directamente. El objeto raíz es su top trace: tiene type, from, to, value, gas, gasUsed, input, output y un campo calls o error.
Si el objeto raíz tiene un error y no tiene calls, el fallo ocurrió en el propio frame superior, por ejemplo, una reversión en la función de entrada antes de cualquier llamada externa. Si la raíz tiene calls y una de ellas lleva el error, el fallo está anidado y debe descender.
El siguiente fragmento de Python obtiene la traza e imprime el frame raíz más el primer hijo fallido, lo que suele ser suficiente para identificar al culpable:
import json, urllib.request
RPC_URL = "RPC_URL"
TX_HASH = "0xYOUR_TX_HASH"
payload = json.dumps({
"jsonrpc": "2.0", "id": 1,
"method": "debug_traceTransaction",
"params": [TX_HASH, {"tracer": "callTracer"}],
}).encode()
req = urllib.request.Request(RPC_URL, data=payload,
headers={"Content-Type": "application/json"})
root = json.load(urllib.request.urlopen(req))["result"]
print("root:", root.get("type"), root.get("to"), root.get("error"))
def walk(frame, depth=0):
for child in frame.get("calls", []):
if child.get("error"):
print(" " * depth, "fail:", child.get("type"),
child.get("to"), child.get("error"))
walk(child, depth + 1)
walk(root)Reensamblaje de un top trace a partir de trace_transaction
Si su endpoint expone trace_transaction en su lugar, obtiene un array plano. El top trace es la entrada cuyo traceAddress es []. Cada otra entrada es un descendiente, y el array traceAddress es la ruta desde la raíz.
Para reconstruir el árbol, ordene por longitud de traceAddress y adjunte cada entrada a la ruta de su padre. Esto es mecánico pero vale la pena hacerlo una vez en un helper, porque leer una lista plana a simple vista es propenso a errores cuando una transacción realiza docenas de llamadas.
Se aplica la misma regla de diagnóstico: encuentre la entrada más profunda con un campo error y luego lea su revertReason si está presente. El error de la entrada raíz a menudo solo dice Reverted, mientras que el hijo lleva la cadena de motivo real.
curl -s -X POST RPC_URL \
-H 'Content-Type: application/json' \
-d '{"jsonrpc":"2.0","id":1,"method":"trace_transaction","params":["0xYOUR_TX_HASH"]}'Un procedimiento de comparación reproducible
Dado que la compatibilidad y la fidelidad del trazado varían según el endpoint, la forma honesta de elegir uno es medirlo contra su propia carga de trabajo. Ejecute el mismo conjunto de hashes de transacción en cada endpoint candidato y registre el resultado en una tabla como la siguiente. No complete los números de este artículo: las celdas son para sus mediciones.
| Etiqueta del endpoint | Método probado | Frame raíz devuelto | Frame fallido más profundo encontrado | Latencia (ms) | Error / notas |
|---|---|---|---|---|---|
| RPC_URL_A | debug_traceTransaction | ||||
| RPC_URL_B | debug_traceTransaction | ||||
| RPC_URL_C | trace_transaction |
Elija una muestra fija de transacciones: algunas que se completaron con éxito, algunas que revirtieron en el frame superior, algunas que revirtieron en una llamada anidada y algunas que aún están pendientes. Ejecute cada endpoint contra la misma muestra, aproximadamente al mismo tiempo, y registre si se devolvió la traza, si el frame fallido estaba presente y cuánto tardó la llamada. Repita la ejecución varias veces para que una única respuesta lenta no domine su conclusión.
La comparación solo es significativa si los endpoints sirven la misma cadena y la misma altura de bloque. Si un endpoint está retrasado, su traza para una transacción reciente puede faltar o ser inconsistente, lo que es un hallazgo en sí mismo.
Lectura del resultado: cómo se ve una traza saludable
Una traza exitosa tiene un frame raíz sin error, un gasUsed menor o igual a gas y un árbol de frames hijos que todos retornan sin error. La output de la raíz son los datos de retorno de la llamada de entrada de la transacción.
Una traza revertida tiene exactamente un frame fallido en el caso común, y los frames por encima de él se marcan como revertidos porque el fallo se propagó hacia arriba. Si ve varios hermanos fallidos, es probable que la transacción haya usado un patrón try/catch o un multicall que toleró fallos individuales; lea la lógica del frame padre antes de concluir que la transacción falló.
Una traza que devuelve un resultado vacío o malformado generalmente significa que el endpoint no admite el método, que la transacción es demasiado antigua para un nodo que no es de archivo o que el nodo podó el estado necesario para reejecutarla. Esos son problemas del endpoint, no del contrato.
Solución de problemas comunes de trazado
El fallo más común es method not found o method not supported. Es un problema de configuración del proveedor, no un error en su código. Confirme la lista de métodos de su endpoint y, si el trazado no está disponible, cambie de endpoint o mueva la carga de trabajo a un nodo que usted controle.
El segundo más común es missing trie node o un error de poda de estado. El trazado reejecuta la transacción contra el estado histórico, por lo que necesita un nodo de archivo para cualquier cosa anterior a la ventana de poda. Si está trazando transacciones recientes y aún ve esto, el endpoint puede estar balanceado entre nodos con diferente retención.
El tercero es el tiempo de espera agotado. Las llamadas de trazado son más pesadas que eth_call y pueden superar los tiempos de espera HTTP predeterminados en transacciones grandes. Aumente el tiempo de espera de su cliente y evite paralelizar solicitudes de trazado contra un endpoint compartido. Para trazado de alto volumen, un nodo dedicado elimina por completo el límite de velocidad compartido; consulte precios de RPC para saber cómo se mide la capacidad.
- Método no encontrado → el endpoint no expone el espacio de nombres trace/debug.
- Missing trie node → nodo que no es de archivo o estado podado.
- Tiempo de espera agotado → transacción grande o límite de velocidad compartido; reintente con retroceso exponencial o capacidad dedicada.
- Resultado vacío → transacción aún no indexada o nodo retrasado respecto a la cabeza.
Limitaciones y compensaciones
El trazado no sustituye la lectura del código fuente del contrato. Una traza le dice qué frame revirtió y con qué motivo, pero no por qué la lógica del contrato eligió esa ruta. Combine la traza con el código fuente verificado y los datos de entrada de la llamada.
La salida del trazado también depende del cliente. El callTracer de Geth y el trace_transaction de Erigon describen la misma ejecución pero difieren en nombres de campos, anidamiento y cómo representan delegatecalls y creates. Cualquier herramienta que construya debe normalizar la forma en lugar de asumir el formato de un cliente.
Por último, el trazado de transacciones pendientes es de mejor esfuerzo. La visibilidad del mempool difiere según el proveedor, y una transacción que puede ver en el mempool de un nodo puede ser invisible para otro. No construya un flujo de trabajo de producción que dependa del trazado de transacciones no confirmadas a menos que controle el nodo.
Próximos pasos
Comience por confirmar qué métodos de trazado sirve su endpoint actual y luego ejecute el procedimiento de comparación anterior contra una pequeña muestra fija. Si el trazado no está disponible o no es fiable, mueva esa carga de trabajo a un nodo dedicado y mantenga el endpoint compartido para lecturas ordinarias.
Para obtener una visión más amplia de cómo se estructuran los endpoints RPC y cuánto cuesta cada espacio de nombres, consulte la guía de endpoints RPC y la guía de endpoints RPC multicadena. Para comparar redes antes de comprometerse, explore las redes compatibles. Y si prefiere que la elección del endpoint se haga por usted, el Asistente RPC puede recomendar un proveedor concreto y una configuración de red para su carga de trabajo de trazado.