Перейти к основному содержимому

Доказательства Меркла

Каждое разрешение имени, возвращаемое API, сопровождается доказательством Меркла. Оно позволяет сверить ответ с корнем состояния, а не доверять приславшему его серверу.

Дерево

PiNS хранит все имена в компактном разрежённом дереве Меркла над 128-битным пространством ключей. Ключ имени — это первые 16 байт SHA-256(domain_name), поэтому имена распределяются равномерно и никто не может выбрать, куда попадёт его имя.

«Компактное» означает, что лист располагается на минимальной глубине, где префикс его ключа уникален, а не на фиксированной глубине 128. В дереве с несколькими тысячами имён большинство доказательств состоит всего из десятка с небольшим хешей — достаточно мало, чтобы проверить их на телефоне, в расширении браузера или внутри кошелька.

Два следствия, о которых стоит знать, прежде чем писать верификатор:

  • Длина доказательства непостоянна. Читайте proof_depth из ответа и никогда не рассчитывайте на фиксированный размер.
  • Пустое поддерево — это 32 нулевых байта на любой высоте. Поэтому корень пустого дерева состоит из одних нулей: только что инициализированный индексатор, сообщающий 0000…0000, работает правильно, а не сломан.

Что содержит доказательство

ПолеЗначение
merkle_proofсоседние хеши, [0] — самый глубокий (ближайший к листу)
proof_depthколичество соседей — должно совпадать с merkle_proof.length
proof_terminalчто находится в конце пути: Occupied, Vacant или Blocked
smt_rootкорень, который восстанавливают эти соседи

Наличие и отсутствие

Именно терминал позволяет доказательству утверждать «это имя не зарегистрировано» так же убедительно, как и «зарегистрировано»:

  • Occupied — в конце пути стоит собственный лист этого ключа. Имя существует, и выданная вам запись — та самая, что лежит в дереве.
  • Vacant — там пустое поддерево. Имя не зарегистрировано.
  • Blocked — эту позицию занимает лист другого имени. Имя не зарегистрировано; ответ несёт блокирующую запись, так что вы можете убедиться, что она хешируется в найденный там лист и что её ключ действительно разделяет тот же префикс.

Без Blocked индексатор мог бы скрыть регистрацию, заявив, что слот пуст. Поскольку блокирующая запись включена целиком, это заявление можно проверить, а не принять на веру.

Проверка

Захешируйте запись в лист, затем сверните соседей обратно к корню, определяя на каждом шаге по битам ключа, идти влево или вправо. Если вы пришли к smt_root, запись — ровно то, что фиксирует дерево.

Остаётся один вопрос: а smt_root — это настоящий корень? Ответ даёт якорный контракт в BNB Smart Chain. Оба шага, с проверенным кодом на Python, PHP и JavaScript, описаны в разделе Проверка доказательств.