Глоссарий / Адреса и ключи
Точка NUMS
- Что такое точка NUMS?
- Точка NUMS представляет собой публичный ключ, приватный ключ от которого ни у кого нет; ее используют как внутренний ключ taproot, когда кооперативный путь расходования должен быть невозможен.
Определено в BIP-341.
Nothing Up My Sleeve (ничего в рукаве) и есть это свойство: точка получается по публичному воспроизводимому рецепту, поэтому никто не может заявить, что владеет секретным ключом от нее. BIP-341 публикует одну такую точку, координату x 0x50929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0, полученную хешированием стандартного несжатого представления базовой точки G кривой secp256k1. Для кошелька это способ сделать выход taproot доступным только через скрипт: он расходуется через свое дерево условий и никак иначе.
Как это работает
Точка NUMS начинается как хеш, а не как ключ.
Обычный публичный ключ представляет собой генератор G, умноженный на секретное число, и тот, кто выбрал это число, может подписывать. Точка NUMS строится в обратном порядке: берется фиксированная публичная строка, вычисляется ее хеш, и дайджест длиной 32 байта читается как координата x. Пример в BIP-341 хеширует стандартное несжатое представление самой G, что не оставляет автору свободы подтасовать входные данные. Подъем этого значения до точки кривой дает публичный ключ, действительный во всех отношениях, кроме одного: подписать за него означало бы решить задачу дискретного логарифмирования, и BIP-341 называет 1 к 2 в степени 128 пределом стойкости этой схемы.
Остальное дает Taproot. Ключ выхода taproot представляет собой внутренний ключ P, сдвинутый вдоль кривой на поправку, фиксирующую корень Меркла дерева скриптов: BIP-341 задает t = hash_TapTweak(p || merkle_root), затем Q = P + int(t)G. Подпись для Q по ключевому пути требует приватного ключа, стоящего за P, поэтому, когда P является точкой NUMS, этот путь закрыт и единственным входом остается путь скрипта. Такое расходование раскрывает один лист плюс блок управления размером 33 + 32m байт, где m является числом хешей-братьев, ограниченным в BIP-341 значением 128.
Об одной утечке стоит знать. Общеизвестная точка NUMS узнается с первого взгляда, поэтому ее публикация в чистом виде в блоке управления сообщает, что ключевой путь был мертв с самого начала. BIP-341 не рекомендует так поступать: выберите новый целый r равномерно случайно от 0 до n минус 1 и используйте вместо нее H + rG, что неотличимо от обычного внутреннего ключа. Сохраните r, и вы по-прежнему сможете доказать другому подписанту, что точка была NUMS, передав его для пересчета.
Где это встречается
Точка NUMS никогда не появляется в адресе, только в свидетельстве расходования по пути скрипта.
В блокчейне выход занимает 34 байта, OP_1, за которым следует вставка длиной 32 байта, ничем не отличаясь от любого другого выхода taproot. Внутренний ключ представляет собой 32 байта, идущие после первого байта блока управления, поэтому он всплывает при первом расходовании через дерево. Выход, который пополнен и никогда не расходуется через скрипт, его не раскрывает.
Дескрипторы делают выбор явным. BIP-386 требует, чтобы каждое выражение ключа внутри tr() было x-only, и ставит внутренний ключ первым в tr(KEY, TREE), поэтому точка NUMS там является способом дескриптора указать, что ключевого пути не существует. Зеркальный случай представляет собой tr(KEY) без дерева, где BIP-386 цитирует совет BIP-341 о том, что выход без пути скрипта все равно должен фиксировать нерасходуемый путь.
Внутренний ключ NUMS делает восстановление зависимым от строки дескриптора, а не только от сид-фраз: сид-фразы воспроизводят ключи листьев, и ничто в них не записывает дерево или точку над ним. Процедура мультиподписи в Sparrow велит вам сохранить дескриптор, и эта инструкция весит здесь больше, чем для обычного кошелька с ключевым путем.
Точка NUMS vs транзакция с нулевыми данными
Точка NUMS закрывает один путь расходования, тогда как транзакция с нулевыми данными делает выход нерасходуемым вообще. Выход OP_RETURN доказуемо мертв по своему устройству: узлы удаляют его из набора UTXO, и любая назначенная ему стоимость сжигается. Средства за внутренним ключом NUMS не сжигаются: каждое условие в дереве скриптов по-прежнему расходуется обычным образом. Общее у них слово «нерасходуемый», которое в одном случае охватывает весь выход, а в другом единственную ветвь.