Tres hashes de un mismo mensaje
Un mensaje TON viaja como un bag of cells — un BoC — y tres hashes distintos reciben el nombre de "el hash del mensaje" según quién hable. El stream de mempool de TONNode entrega los tres para cada mensaje pendiente, con estos nombres:
cell_hash— el hash de representación de la celda raíz. Es lo que los exploradores llaman el hash del mensaje y, una vez el mensaje se incluye en un bloque, coincide con el hashin_msgde esa transacción. Depende solo de las celdas, no de cómo se serializaron en bytes.norm_hash— el hash normalizado de TEP-467: el hash del mismo mensaje externo entrante reescrito en una forma fija —ext_in_msg_info$10 src:addr_none dest:<unchanged> import_fee:0 init:nothing body:right$1 ^body. Se mantiene estable cuando el mensaje se reserializa o cuando cambian sus campossrc,import_feeoinit. Si el mensaje ya tiene esa forma,norm_hashes igual acell_hash.sha256— SHA-256 de los bytes del BoC exactamente como se entregaron. Las mismas celdas pueden serializarse de varias formas válidas (con o sin índice, con o sin CRC32C), y cada serialización tiene un SHA-256 distinto mientras los dos hashes de celda no se mueven.
La herramienta imprime cada uno en hex y en base64, porque las API no se ponen de acuerdo: los exploradores y el protocolo de liteserver usan hex, varias API HTTP devuelven base64.
Por qué existe el hash normalizado
Un mensaje externo lo firma un monedero y lo entrega a la red quien lo retransmite. Por el camino puede recodificarse, y un relayer puede añadir o quitar la dirección src, el import_fee o un init adjunto — nada de lo cual firmó el monedero. Cada cambio da una nueva celda raíz y un nuevo cell_hash, así que un nodo que deduplicara por hash de celda aceptaría varias veces la misma carga firmada. TEP-467 fija la forma que se hashea para que todas esas variantes colapsen en una sola identidad, y la propia función del nodo get_ext_in_msg_hash_norm (en validator/impl/external-message.cpp) lo calcula así.
La construcción es pequeña: toma los bits del destino tal cual, pon a cero el origen, pon a cero la comisión, descarta el init y mete el cuerpo en una referencia estuviera o no en una. Solo un mensaje externo entrante tiene hash normalizado; para un mensaje interno o externo saliente, la herramienta muestra los otros dos y lo dice.
Qué lleva el stream de mempool
Cada frame msg del stream de mempool de TONNode lleva el propio boc, su size, y cell_hash, norm_hash y sha256 tal como se definen arriba. Deduplica tu propio procesamiento por cell_hash: el mismo mensaje puede llegar dos veces, primero como early (sin verificar) y luego como checked, y de nuevo tras una reconexión. sha256 es la clave que el nodo usa para deduplicar los bytes que recibió, y por eso se hashea sobre los bytes entregados y no sobre una recodificación.
Probado con mensajes reales
La implementación de aquí construye la celda normalizada exactamente como lo hace el propio parser del stream, y la suite de pruebas del repositorio pasa por ella 72 mensajes externos reales de mainnet — el conjunto de fixtures del stream, cada uno con el cell_hash, el norm_hash y el sha256 que el stream entregó — y comprueba que los tres coinciden. El mensaje de ejemplo de la documentación del mempool es uno de ellos; pégalo para ver los tres valores lado a lado.
