Unified Address (ZIP-316) Валидация
Это учебное руководство, а не готовый декодер или библиотека платежей для копирования и вставки. Оно объясняет, как устроен Unified Address, чтобы вы могли понять, что происходит внутри поддерживаемых библиотек. Для всего, что работает с реальными средствами, полагайтесь на ZIP-316 specification и официальные реализации, ссылки на которые приведены ниже.
Общая картина
Unified Address (UA) — это единая строка адреса, содержащая несколько типов получателей: прозрачный, Sapling, Orchard или их комбинацию. Кошелёк плательщика автоматически выбирает лучший поддерживаемый им пул получателей.
Представьте UA как запечатанный конверт с несколькими подписанными карточками. Каждая карточка представляет отдельный способ связаться с вами. Чтобы проверить адрес, приложение должно:
- Открыть конверт: декодировать текстовую строку.
- Восстановить порядок содержимого: отменить защитное перемешивание (F4Jumble).
- Прочитать каждую карточку: извлечь отдельных получателей.
- Применить правила протокола: игнорировать или отклонять записи в соответствии с диапазоном их кодов типов.
Почему недостаточно «просто декодировать Bech32m»
UA использует текстовое кодирование Bech32m, но одно лишь декодирование Bech32m не раскрывает пригодные для использования данные получателей.
ZIP-316 намеренно перемешивает полезную нагрузку с помощью F4Jumble перед кодированием. F4Jumble гарантирует, что изменение даже одного символа в адресе полностью меняет декодированный результат. Это предотвращает атаки с изменяемостью адреса, при которых злоумышленник заменяет байты в середине адреса, сохраняя внешне корректные префикс и суффикс.
Ключевое правило: защита от изменяемости работает только в том случае, если приложение выполняет полный конвейер декодирования и валидации. Частичное декодирование устраняет безопасность, сохраняя все риски.
Конвейер декодирования, шаг за шагом
Шаг 1: Декодируйте Bech32m и проверьте сеть
- Человекочитаемая часть (HRP):
u обозначает mainnet; utest обозначает testnet. (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). Это предотвращает случайное принятие адресов testnet в mainnet.
Шаг 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 | Несанкционированное изменение байтов адреса без обнаружения. |
См. также: Ключи просмотра