Unified Address (ZIP-316) Валідація
Це навчальний посібник, а не готовий декодер чи бібліотека платежів для копіювання й вставлення. У ньому пояснено, як структуровано Unified Address, щоб ви могли зрозуміти, що підтримувані бібліотеки роблять внутрішньо. Для всього, що працює з реальними коштами, покладайтеся на специфікацію ZIP-316 та офіційні реалізації, наведені нижче.
Загальна картина
Unified Address (UA) — це єдиний рядок адреси, який містить кілька типів отримувачів: Прозорий, Sapling, Orchard або їхню комбінацію. Гаманець платника автоматично вибирає найкращий пул отримувачів, який він підтримує.
Уявіть UA як запечатаний конверт із кількома підписаними картками. Кожна картка представляє інший спосіб зв’язатися з вами. Щоб перевірити адресу, застосунок має:
- Відкрити конверт: декодувати текстовий рядок.
- Упорядкувати вміст: скасувати захисне перемішування (F4Jumble).
- Прочитати кожну картку: витягти окремих отримувачів.
- Застосувати правила протоколу: ігнорувати або відхиляти записи відповідно до діапазону їхніх кодів типів.
Чому недостатньо «просто декодувати Bech32m»
UA використовує текстове кодування Bech32m, але саме декодування Bech32m не виявляє придатних для використання отримувачів.
ZIP-316 навмисно перемішує корисне навантаження за допомогою F4Jumble перед кодуванням. F4Jumble гарантує, що зміна навіть одного символу в адресі повністю змінює декодований результат. Це запобігає атакам на модифікованість адреси, коли зловмисник замінює байти в середині адреси, водночас залишаючи префікс і суфікс такими, що виглядають дійсними.
Ключове правило: захист від модифікованості працює лише тоді, коли ваш застосунок виконує повний конвеєр декодування та валідації. Часткове декодування прибирає безпеку, зберігаючи весь ризик.
Конвеєр декодування, крок за кроком
Крок 1: Декодуйте Bech32m і перевірте мережу
- Частина, придатна для читання людиною (HRP):
u позначає основну мережу; utest позначає тестову мережу. (UA основної мережі починаються з u1, де 1 є роздільником Bech32.)
- Обмеження довжини: стандартний Bech32m встановлює обмеження у 90 символів. UA зазвичай перевищують це обмеження, тому стандартні перевірки довжини потрібно вимкнути в декодері.
- Перетворіть 5-бітові слова Bech32m назад на стандартні 8-бітові байти.
Крок 2: Інвертуйте F4Jumble
F4Jumble — це 4-раундова мережа Фейстеля, побудована на BLAKE2b:
- Довжина лівої половини:
min(64, floor(length / 2)) байтів. Обмеження в 64 байти відповідає максимальному розміру виводу BLAKE2b. Права половина містить решту корисного навантаження.
- Хеш-функції: чергує G та H, використовуючи фіксовані мітки персоналізації (
UA_F4Jumble_G і UA_F4Jumble_H).
- Порядок раундів: пряме кодування виконує G(0) → H(0) → G(1) → H(1). Зворотне перетворення (скасування перемішування) виконує H(1) → G(1) → H(0) → G(0).
- Перевірка діапазону: відхиляйте вхідні дані поза межами обмежень розміру корисного навантаження ZIP-316.
Крок 3: Видаліть доповнення та перевірте HRP
Перед перемішуванням кодер додає 16 байтів із HRP, доповнених нулями.
- Видаліть останні 16 байтів після скасування перемішування.
- Підтвердьте, що вбудований HRP відповідає очікуваній мережі (
u або utest). Це запобігає випадковому прийняттю адрес тестової мережі в основній мережі.
Крок 4: Витягніть отримувачів
Решта корисного навантаження складається із записів (typecode, length, content), де код типу та довжина зберігаються як цілі числа компактного розміру (один байт для малих значень). Відомі коди типів отримувачів:
| Код типу | Тип отримувача | Довжина вмісту |
|---|
0x00 | Прозорий (P2PKH) | 20 байтів |
0x01 | Прозорий (P2SH) | 20 байтів |
0x02 | Sapling | 43 байти |
0x03 | Orchard | 43 байти |
Крім них, ZIP-316 резервує ще два діапазони для сумісності з майбутніми версіями:
0xC0–0xDF (метадані, які НЕ ОБОВ’ЯЗКОВО розуміти): споживачі мають ігнорувати нерозпізнані елементи метаданих у цьому діапазоні.
0xE0 і 0xE1 (призначені метадані завершення строку дії, які ОБОВ’ЯЗКОВО розуміти): поточний реєстр ZIP-316 призначає їх висоті та часу завершення строку дії адреси. Споживачі мають розуміти ці елементи або відхиляти адресу.
0xE2–0xFC (непризначені метадані, які ОБОВ’ЯЗКОВО розуміти): споживачі мають відхиляти адресу, якщо натрапляють на нерозпізнаний елемент у цьому діапазоні.
Для відомих типів отримувачів перевірте, що закодована довжина відповідає визначеній довжині вмісту цього типу. Для елементів метаданих використовуйте їхню закодовану довжину компактного розміру, щоб визначити довжину вмісту. Відхиляйте усічені записи або будь-які кінцеві байти.
Бажаний порядок отримувачів. Після успішного аналізу адреси гаманець або платіжний інструмент повинен вибрати найкращого отримувача в такому порядку: Orchard, потім Sapling, потім прозорий.
Обов’язкові правила відхилення ZIP-316
Успішне декодування не робить адресу дійсною. Офіційні гаманці Zcash суворо відхиляють адреси, що порушують наведені нижче правила. Вебінструменти також мають їх відхиляти, щоб запобігти помилкам платежів:
- Відсутні захищені отримувачі: адреса має містити щонайменше одного отримувача Sapling або Orchard. UA лише з прозорими отримувачами є недійсним відповідно до ZIP-316.
- Дублікати кодів типів: кожен тип отримувача може з’являтися щонайбільше один раз.
- Невідсортовані коди типів: отримувачі мають розташовуватися в суворо висхідному порядку кодів типів.
- Конфліктні прозорі отримувачі: UA може містити або P2PKH, або P2SH, але ніколи обидва.
- Некоректні записи або доповнення: невідповідні мережеві префікси, усічені корисні навантаження чи невідповідності довжини мають спричиняти негайне відхилення.
- Нерозпізнані коди типів: споживачі мають ігнорувати нерозпізнані елементи, за винятком елементів у діапазоні метаданих, які ОБОВ’ЯЗКОВО розуміти (
0xE0–0xFC), які вони мають відхиляти, якщо не розпізнають. У поточному реєстрі 0xE0 і 0xE1 є призначеними типами завершення строку дії, тоді як 0xE2–0xFC не призначені. Незалежно від цього, відхиляйте будь-яку адресу, яка не відповідає наведеним вище обов’язковим правилам дійсності, включно з вимогою отримувача Sapling або Orchard.
Найкращі практики для розробників
- Порівнюйте проаналізованих отримувачів, а не необроблені рядки. Спершу декодуйте адреси, перш ніж перевіряти рівність.
- Використовуйте підтримувані бібліотеки для всього, що працює з коштами. Компілюйте офіційні Rust-крейти (такі як
zcash_address) у WebAssembly, а не розгортайте власні декодери JavaScript.
- Будьте обережні з вручну написаними парсерами. Якщо ви пишете такий для навчання, розглядайте його як навчальний проєкт і перевіряйте за офіційними векторами нижче, перш ніж довіряти йому будь-що.
Офіційні специфікації та еталонні реалізації
Глосарій
| Термін | Значення |
|---|
| Unified Address (UA) | Єдиний рядок адреси, що об’єднує кілька пулів отримувачів. |
| Receiver | Конкретний тип призначення платежу (прозорий, Sapling або Orchard). |
| Bech32m | Схема текстового кодування, що використовується для рядків UA. |
| HRP | Частина, придатна для читання людиною, або мережевий префікс (u або utest). |
| F4Jumble | Оборотний алгоритм обфускації, що забезпечує цілісність адреси. |
| Typecode | Число в кожному записі, яке визначає тип отримувача в корисному навантаженні. |
| Malleability | Несанкціонована зміна байтів адреси без виявлення. |
Див. також: Ключі перегляду