Идентификаторы транзакций и блоков
Типы идентификаторов VIZ унаследовал от Graphene (BitShares, затем Steem). В исходниках они объявлены как fc::ripemd160, и старая документация и библиотеки называют их «ripemd160 id». Это только имя 20-байтового контейнера, в котором они хранятся: ни один из этих id не является ripemd160-хэшем. Нода объявляет их через алиас id160_type, чтобы сказать это прямо.
| Значение | Как вычисляется | Размер |
|---|---|---|
transaction_id | первые 20 байт sha256(сериализованная транзакция), подписи не входят | 20 байт |
block_id | первые 20 байт sha224(сериализованный заголовок блока), затем байты 0–3 заменяются номером блока (big-endian) | 20 байт |
transaction_merkle_root | ripemd160 от корня sha256-дерева по подписанным транзакциям | 20 байт |
Merkle root — единственное значение, которое действительно ripemd160.
Что это значит для клиентов
- Чтобы посчитать id транзакции, сериализуйте её без
signatures, возьмите sha256 и оставьте первые 20 байт. ripemd160 не применять — результат никогда не совпадёт с нодой. - Номер блока читается прямо из block id: это первые 4 байта, big-endian. TaPoS (
ref_block_num/ref_block_prefix) берёт младшие 16 бит этого номера и байты 4–7 block id. - Id имеют длину 20 байт во всех ответах API, в block log и в истории аккаунтов. Смена хэша (на настоящий ripemd160 или на полный 32-байтовый sha256) была бы хардфорком, который делит историю на два формата id, без выигрыша в безопасности: 160 бит для идентификатора достаточно, а подпись ставится на полный sha256-дайджест, а не на id.
Исходники: transaction::id() в libraries/protocol/transaction.cpp, signed_block_header::id() и signed_block::calculate_merkle_root() в libraries/protocol/block.cpp, типы — в libraries/protocol/include/graphene/protocol/types.hpp.