본문으로 건너뛰기

머클 증명

API가 반환하는 모든 해석 결과에는 머클 증명이 함께 따라옵니다. 덕분에 응답을 보낸 서버를 신뢰하는 대신, 답을 어떤 상태 루트와 대조해 확인할 수 있습니다.

트리

PiNS는 모든 이름을 128비트 키 공간 위의 압축 희소 머클 트리에 보관합니다. 이름의 키는 SHA-256(domain_name)의 앞 16바이트이므로 이름이 고르게 분포하며, 누구도 자기 이름이 어디에 놓일지 고를 수 없습니다.

「압축」이란 잎이 고정된 128 깊이가 아니라, 키 접두사가 유일해지는 가장 얕은 깊이에 놓인다는 뜻입니다. 수천 개의 이름이 든 트리에서 대부분의 증명은 해시 열댓 개 정도에 불과합니다 — 휴대폰에서, 브라우저 확장에서, 또는 지갑 안에서 검증할 수 있을 만큼 작습니다.

검증기를 작성하기 전에 알아둘 두 가지 결과:

  • 증명 길이는 가변적입니다. 응답에서 proof_depth를 읽으세요. 절대로 고정 크기를 가정하지 마세요.
  • 빈 서브트리는 어느 높이에서든 32개의 0 바이트입니다. 그래서 빈 트리의 루트는 전부 0입니다 — 갓 초기화된 인덱서가 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로 검증된 코드와 함께 두 단계 모두 증명 검증에 있습니다.