Дерево Меркла: проверка без скачивания всего

Дерево Меркла — это способ доказать «моя транзакция точно в блоке», не скачивая весь блок целиком.

«Зачем перечитывать всю книгу, чтобы убедиться, что одна страница на месте? Дерево Меркла позволяет проверить страницу по короткой подписи.»

В блоке могут быть тысячи транзакций. Хранить и пересылать их все ради одной проверки — расточительно. Здесь на помощь приходит элегантная структура — дерево Меркла (Merkle tree). Она сворачивает все транзакции блока в один-единственный хеш, который называют корнем Меркла (Merkle root).

Как строится дерево

Идея пошаговая. Сначала хешируем каждую транзакцию — получаем «листья». Затем берём листья парами и хешируем каждую пару — получаем уровень выше. Повторяем, пока не останется один хеш — это и есть корень. Корень записывается в заголовок блока.

Как работает под капотом

        Дерево Меркла (4 транзакции)

                 [ Корень ]
                /          \
          [ H_AB ]        [ H_CD ]
          /     \          /     \
      [H_A]   [H_B]    [H_C]   [H_D]
        |       |        |       |
       tx_A    tx_B     tx_C    tx_D

   Каждый узел = хеш( левый_ребёнок + правый_ребёнок )

Построим настоящее дерево Меркла из четырёх транзакций и получим корень.

Попробуй сам ▶ Запусти код прямо здесь — он работает в браузере:

import hashlib

def h(x):
    return hashlib.sha256(x.encode()).hexdigest()

txs = ['Аня->Боря 5', 'Боря->Вася 2', 'Вася->Гена 1', 'Гена->Аня 3']

def merkle_root(items):
    level = [h(t) for t in items]          # листья
    while len(level) > 1:
        if len(level) % 2 == 1:            # нечётное число -> дублируем последний
            level.append(level[-1])
        level = [h(level[i] + level[i + 1]) for i in range(0, len(level), 2)]
    return level[0]

root = merkle_root(txs)
print('Корень Меркла:', root[:20], '...')

# Подменим одну транзакцию -> корень изменится
txs[1] = 'Боря->Вася 200'
print('После подмены:  ', merkle_root(txs)[:20], '...')

Подмена даже одной транзакции меняет корень — а корень лежит в заголовке блока и защищён хеш-цепочкой. Так дерево Меркла «запечатывает» все транзакции блока одним числом.

Зачем это нужно на практике

Дерево Меркла даёт доказательство включения (Merkle proof). Чтобы убедить кого-то, что транзакция tx_A в блоке, не нужно отдавать все транзакции — достаточно отдать tx_A и пару «соседних» хешей по пути к корню. Получатель сам пересчитает корень и сравнит с тем, что в заголовке. Именно так работают лёгкие кошельки на телефонах.

Частые заблуждения

  • «Дерево Меркла исполняет транзакции». Нет, оно лишь подтверждает, что транзакция включена и не изменена.
  • «Нужно скачать весь блок для проверки». Наоборот, доказательство Меркла позволяет проверить включение по нескольким хешам.
  • «Порядок транзакций не важен». Важен: дерево строится по фиксированному порядку, и его изменение даёт другой корень.

Важно понимать (риски)

Дерево Меркла доказывает включение и целостность, но не правильность бизнес-логики. Оно подтвердит, что транзакция в блоке, но не скажет, была ли она честной. Лёгкие кошельки экономят память за счёт доверия полным узлам в части проверки правил — это компромисс. Всегда понимай, что именно гарантирует та или иная проверка, а что — нет.

Разбор: зачем телефону не качать весь блокчейн

Представь приложение-кошелёк на твоём телефоне. Полная история блокчейна — это сотни гигабайт, которые ни один телефон не потянет. Но кошельку и не нужна вся история: ему важно лишь убедиться, что конкретные транзакции — твои поступления и списания — реально вошли в блоки. Вот тут дерево Меркла раскрывается во всей красе.

Лёгкий кошелёк хранит только заголовки блоков (а в них — корни Меркла). Когда нужно проверить транзакцию, он запрашивает у полного узла короткое доказательство: саму транзакцию и несколько «соседних» хешей по пути от листа к корню. Кошелёк пересчитывает корень из этих данных и сравнивает с корнем в заголовке. Сходится — транзакция точно в блоке. Так проверка, которая наивно потребовала бы весь блок, укладывается в десяток хешей. Это пример того, как удачная структура данных превращает невозможное в практичное.

Итоги

  • Дерево Меркла сворачивает все транзакции блока в один корневой хеш.
  • Корень лежит в заголовке и защищён хеш-цепочкой.
  • Доказательство Меркла позволяет проверить включение транзакции без всего блока.
  • Оно гарантирует включение и целостность, но не правильность логики.
Проверьте себя
1. Что такое корень Меркла?
AХеш предыдущего блока
BЕдинственный хеш, в который свёрнуты все транзакции блока
CАдрес кошелька
DСписок всех узлов сети
2. Какое преимущество даёт дерево Меркла?
AУскоряет майнинг
BПозволяет доказать включение транзакции, не скачивая весь блок
CДелает транзакции анонимными
DСнижает комиссии