# Корневой хеш транзакций
Поле transactionsRoot
в заголовке блока представляет собой корневой хеш дерева Меркла транзакций блока. Корневой хеш является доказательством того, что все транзакции присутствуют в блоке в заданном порядке.
Корневой хеш транзакций в заголовке блоке позволяет:
- Предоставлять доказательство присутствия транзакции в блоке без предъявления всех транзакций.
- Подписывать только заголовок блока, отдельно от транзакций.
Поле
transactionsRoot
появилось в заголовке блока с момента активации фичи № 15 “Ride V4, VRF, Protobuf, Failed transactions”.
# Как вычисляется transactionsRoot
Вычисляется хеш каждой транзакций в блоке, например:
HA = hash(TA)
HB = hash(TB)
и т.д.
Хеши объединяются попарно, вычисляется хеш каждого объединения:
HAB = hash(HA + HB)
Если количество хешей нечетное, последний хеш объединяется с хешем нулевого байта:
HGH = hash(HG + hash(0))
Шаг 2 повторяется, пока не будет получен корневой хеш:
HABCDEFGH
Этот хеш записывается в поле
transactionsRoot
.
Если блок пустой, то
transactionsRoot
= hash(0).
В блокчейне Waves для хеширования используется алгоритм BLAKE2b-256.
# Как доказывается присутствие транзакции в блоке
Допустим, на стороне 1 имеется полная копия блокчейна, а на стороне 2 — только заголовки блоков.
Для доказательства присутствия транзакции в блоке сторона 1 предоставляет стороне 2 следующие данные:
T
— проверяемую транзакцию;merkleProofs
— массив соседних хешей (верхних хешей соседних веток) на каждом уровне, снизу вверх;index
— порядковый номер транзакции в блоке.
Например, для транзакции TD:
merkleProofs
= [ HС, HAB, HEFGH ]index
= 3
Сторона 2 проверяет предоставленные доказательства:
Вычисляет хеш проверяемой транзакции: хешируются все данные транзакции вместе с подписью:
HD = hash(TD)
Объединяет текущий хеш с соответствующим соседним хешем из массива
merkleProofs
, вычисляет хеш объединения.index
позволяет определить, в каком порядке объединять хеши:• Если
n
-й бит числаindex
с конца равен 0, то порядок такой: текущий хеш +n
-й хеш массиваmerkleProofs
(хеш из массива справа). • Еслиn
-й бит равен 1, то порядок такой:n
-й хеш массиваmerkleProofs
+ текущий хеш (хеш из массива слева).Например,
index
= 310 = 112, поэтому:•
merkleProofs
[0] = HС cлева, •merkleProofs
[1] = HAB слева, •merkleProofs
[2] = HEFGH справа.Повторяет шаг 2, пока не будет получен корневой хеш:
HABCDEFGH
Сравнивает полученный корневой хеш с полем
transactionsRoot
в заголовке блока. Если хеши совпали, значит, транзакция присутствует в блоке.
# Инструменты
Следующие методы Node API принимают на вход идентификаторы транзакций и для каждой транзакции предоставляют доказательства присутствия в блоке:
GET /transactions/merkleProof
POST /transactions/merkleProof
Описание методов см. в разделе Транзакции.
Для проверки присутствия транзакции на том же блокчейне нет необходимости использовать корневой хеш транзакций, поскольку нода Waves хранит полную копию блокчейна, включающую все транзакции. Можно использовать функцию Ride:
transactionHeightById(id: ByteVector): Int|Unit
Функция возвращает высоту блока транзакции, если транзакция с таким id
присутствует на блокчейне, и unit
в противном случае. Описание функции см. в разделе Функции блокчейна.
Для проверки присутствия транзакции в блоке на другом блокчейне можно использовать функцию Ride:
createMerkleRoot(merkleProofs: List[ByteVector], valueBytes: ByteVector, index: Int): ByteVector
Эта функция применима при условии, что другой блокчейн использует такой же алгоритм вычисления корневого хеша транзакций; в частности, для всех Waves-based блокчейнов. Функция createMerkleRoot
вычисляет корневой хеш по предоставленным доказательствам и хешу транзакции (шаги 1–3). Чтобы проверить наличие транзакции в блоке, остается сравнить вычисленный хеш с полем transactionsRoot
в заголовке блока. Описание функции см. в разделе Функции верификации.