Три хеші одного повідомлення
TON-повідомлення передається як bag of cells — BoC, і «хешем повідомлення» називають три різні хеші залежно від того, хто говорить. Мемпул-стрім TONNode доставляє всі три для кожного очікуваного повідомлення під такими іменами:
cell_hash— representation hash кореневої комірки. Саме його оглядачі називають хешем повідомлення, а після включення повідомлення в блок він дорівнює хешуin_msgтієї транзакції. Він залежить лише від комірок, а не від того, як їх серіалізовано в байти.norm_hash— нормалізований хеш за TEP-467: хеш того самого зовнішнього вхідного повідомлення, переписаного у фіксовану форму —ext_in_msg_info$10 src:addr_none dest:<unchanged> import_fee:0 init:nothing body:right$1 ^body. Він не змінюється при пересеріалізації повідомлення та при зміні полівsrc,import_feeабоinit. Якщо повідомлення вже в цій формі,norm_hashдорівнюєcell_hash.sha256— SHA-256 байтів BoC рівно в тому вигляді, в якому їх доставлено. Ті самі комірки можна серіалізувати кількома припустимими способами (з індексом або без, з CRC32C або без), і в кожної серіалізації свій SHA-256, тоді як два хеші комірок не змінюються.
Інструмент виводить кожен із них у hex і в base64, бо API розходяться: оглядачі та протокол liteserver використовують hex, низка HTTP API повертає base64.
Навіщо існує нормалізований хеш
Зовнішнє повідомлення підписує гаманець, а в мережу його передає той, хто ретранслює. Дорогою його можуть перекодувати, а ретранслятор — додати або прибрати адресу src, import_fee чи прикріплений init, нічого з цього гаманець не підписував. Кожна зміна дає нову кореневу комірку і новий cell_hash, тож нода, що відсіює дублікати за хешем комірки, прийняла б той самий підписаний payload кілька разів. TEP-467 фіксує форму, за якою обчислюється хеш, щоб усі ці варіанти зводилися до однієї сутності, і власна функція ноди get_ext_in_msg_hash_norm (у validator/impl/external-message.cpp) обчислює його саме так.
Конструкція проста: взяти біти отримувача як є, обнулити джерело, обнулити комісію, відкинути init і покласти тіло в посилання незалежно від того, чи було воно там. Нормалізований хеш має лише зовнішнє вхідне повідомлення; для внутрішнього або зовнішнього вихідного інструмент показує два інші хеші й прямо про це каже.
Що несе мемпул-стрім
Кожен кадр msg мемпул-стріму TONNode несе сам boc, його size, а також cell_hash, norm_hash і sha256 у визначеному вище сенсі. Відсіюйте дублікати у своїй обробці за cell_hash: те саме повідомлення може прийти двічі — спочатку як early (неперевірене), потім як checked, — і ще раз після перепідключення. sha256 — ключ, за яким нода відсіює дублікати отриманих байтів, тому він обчислюється за доставленими байтами, а не за перекодуванням.
Перевірено на реальних повідомленнях
Реалізація тут будує нормалізовану комірку точно так, як це робить власний парсер стріму, а набір тестів репозиторію пропускає через неї 72 реальні зовнішні повідомлення mainnet — набір фікстур стріму, для кожного з яких відомі cell_hash, norm_hash і sha256, доставлені стрімом, — і перевіряє збіг усіх трьох. Приклад повідомлення з документації мемпулу — одне з них; вставте його, щоб побачити три значення поруч.
