Доказательства Меркла
Каждое разрешение имени, возвращаемое 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, описаны в разделе
Проверка доказательств.