명령 형식
모든 zNS 연산은 레지스트라의 프로토콜 주소로 보내는 차폐 ZCash 트랜잭션이며, 금액이 곧 결제이고 메모가 곧 서명된 명령입니다. 둘은 같은 노트 안에서 함께 이동하므로 의도와 결제가 원자적으로 묶입니다 — 따로 대조해야 할 참조번호나 청구서가 없습니다.
이 페이지는 정확한 전송 형식을 설명합니다. 이에 맞춰 만든 명령은 레지스트라와 영지식 회로 양쪽 모두가 받아들입니다.
구조
모든 명령은 콜론으로 구분된 ASCII이며, 프로토콜 마커와 버전으로 시작합니다:
zNS:1:{OP}:{name}:…:{ed25519_pubkey_hex}:…:{nonce}:{signature_hex}
그 사이의 필드는 연산에 따라 달라집니다:
| 연산 | 메모 구조 | 지불 금액 |
|---|---|---|
REG 등록 | zNS:1:REG:{name}:{address}:{pubkey}:{nonce}:{sig} | 이름 길이에 따른 등록 요금 |
UPD 주소 변경 | zNS:1:UPD:{name}:{address}:{pubkey}:{nonce}:{sig} | 변경 요금 |
CHG 소유자 이전 | zNS:1:CHG:{name}:{new_pubkey}:{nonce}:{sig} | 변경 요금 |
LST 판매 등록 | zNS:1:LST:{name}:{pubkey}:{price}:{nonce}:{sig} | 변경 요금 |
ULT 등록 해제 | zNS:1:ULT:{name}:{pubkey}:{nonce}:{sig} | 변경 요금 |
BUY 구매 | zNS:1:BUY:{name}:{address}:{pubkey}:{nonce}:{sig} | 정확히 등록 가격 |
CHG에서 {new_pubkey}는 받는 쪽 소유자의 키이며, 서명은 넘기는 쪽 소유자가 만듭니다 —
이전을 승인하는 주체는 현재 소유자입니다.
서명 대상 메시지
서명은 끝의 :{signature}를 제외한 명령을 대상으로 합니다. 즉 마커부터 nonce까지(포함) 전부입니다:
zNS:1:REG:richard.zcash:u1…:0101…0101:1780000001
규칙은 엄격하며, 클라이언트가 이 중 하나라도 어기면 회로가 거부하는 서명이 만들어집니다:
pubkey는 소문자 16진수, 64자입니다.price는LST에서만 나타납니다.address는REG,UPD,BUY에서만 나타납니다.price와nonce는 10진수이며, 선행 0·부호·패딩이 없어야 합니다.- 서명은 바로 그 바이트열에 대한 Ed25519 서명이며, 16진수로 인코딩된 128자입니다.
검증은 엄격합니다. 정규형이 아닌 서명과 작은 위수 키는 거부됩니다.
필드 규칙
이름
| 규칙 | 값 |
|---|---|
| 문자 | a-z, 0-9, 하이픈 |
| 길이 | 영역을 포함해 1~64자 |
| 대소문자 | 소문자만 — 이름은 소문자로 저장되고 해시됩니다 |
| 하이픈 | 맨 앞 불가, 맨 뒤 불가, 연속 불가 |
| 영역 | .zcash, .zec, .private, .secure, .safe |
점은 라벨과 영역을 나누는 정확히 하나만 허용됩니다.
대상 주소
이름이 해석되는 주소는 Orchard 수신자를 포함한 메인넷 Unified Address여야 합니다. 해당 수신자가 없는 주소는 거부됩니다.
이유는 임의적인 것이 아니라 실무적입니다. 레지스트라는 Orchard 키 자료를 통해 자금을 받고 지급하는데, 그 자료는 ZIP 229에 따라 Ironwood 풀도 함께 포괄합니다. Orchard 수신자가 없는 주소로는 지급할 수 없으므로, 환불에도 판매 대금에도 쓸 수 없습니다.
Ironwood는 새 수신자를 추가하지 않습니다
Ironwood는 새로운 가치 풀이지 새로운 주소 형식이 아닙니다. 지갑은 노트를 그쪽으로 옮기지만 수신 주소는 여전히 Orchard 주소로 남습니다. 최신 지갑의 Unified Address는 그대로 동작합니다.
Nonce
nonce는 서명하는 시점의 초 단위 Unix 타임스탬프입니다.
- 해당 이름에 현재 기록된 nonce보다 엄격히 커야 합니다. 이것이 예전에 서명된 명령의 재사용을 막아줍니다.
- 자신을 담고 있는 블록보다 300초 넘게 앞설 수 없습니다. 이 여유는 통상적인 시계 오차는 흡수하면서도 nonce를 먼 미래에 세워두지는 못하게 합니다.
첫 등록이라면 현재 시각의 타임스탬프면 무엇이든 괜찮습니다.
가격
가격을 담는 것은 LST뿐입니다. 정수 zatoshi(1 ZEC = 100,000,000 zatoshi)이며 0보다 커야 합니다.
이미 등록된 이름을 새 가격으로 다시 올리는 것은 허용됩니다 — LST를 한 번 더 보내면 됩니다. 가장 최근
것이 적용됩니다.
크기 제한
ZCash 메모는 정확히 512바이트이며, 명령 전체가 그 안에 들어가야 합니다. 고정 부분이 차지하는 양은 예측 가능합니다:
zNS:1:{OP}: … marker, version, operation 11 bytes
{pubkey} 64 hex characters 65 bytes with separator
{nonce} 10 digits today 11 bytes with separator
{signature} 128 hex characters 128 bytes
남는 약 295바이트를 이름과 대상 주소가 나눠 씁니다. 수신자가 여럿인 Unified Address는 길어질 수 있으므로, 이름이 아주 길면 아주 긴 주소는 들어가지 못할 수도 있습니다. 클라이언트는 이 예산을 계산해 사용자가 결제하기 전에 경고해야지, 나중에 트랜잭션이 실패하도록 두어서는 안 됩니다.
결제
유효성은 메모만큼이나 금액이 좌우합니다:
REG는 이름 길이에 해당하는 등록 요금을 정확히 지불해야 합니다.UPD,CHG,LST,ULT는 변경 요금을 정확히 지불해야 합니다.BUY는 등록 가격을 정확히 지불해야 합니다.
길이는 영역을 제외한 라벨 기준으로 셉니다: ab.zcash는 2자짜리 이름입니다.
금액이 모자라거나 넘치는 명령은 처리되지 않습니다. 연산과 공개 키를 읽을 수 있다면 금액은 내부 잔액에 적립되어 출금할 수 있습니다 — 질문과 답변을 참조하세요.
순서
명령은 ZCash가 만들어 낸 순서대로 처리됩니다. 블록 높이, 그다음 블록 내 트랜잭션 인덱스, 그다음 입력 인덱스 순입니다. 레지스트라는 순서를 고르지 않으며, 모든 독립 인덱서가 다른 루트를 계산하게 만들지 않고는 순서를 바꿀 수도 없습니다.
경합하는 연산 — 같은 이름에 대한 두 개의 REG, 또는 같은 등록에 대한 두 개의 BUY — 에서는 그 순서상
가장 앞선 것이 이기고, 나머지 금액은 내부 잔액으로 환불됩니다.
예시로 따라가기
richard.zcash 등록:
1. Generate an Ed25519 keypair. The public key is your identity across all your names.
2. Build the message to sign (note: no trailing signature field):
zNS:1:REG:richard.zcash:u1mvnsq85wane…:3757ee1a…a53:1780000001
3. Sign it with the private key; hex-encode the 64-byte signature.
4. Append it to form the memo:
zNS:1:REG:richard.zcash:u1mvnsq85wane…:3757ee1a…a53:1780000001:cfec7a58…04
5. Send a shielded transaction to the registrar address, with that memo, paying the
registration fee for a 7-character name.
몇 분 안에 명령은 배치로 묶이고, 증명되고, 앵커링됩니다. 그때부터 richard.zcash는 어떤 인덱서를 통해서든
해석되며, 당신이 직접 검증할 수 있는 머클 증명이 함께 따라옵니다.