Долговечные nonce: подпись двумя устройствами в Solana

·7 мин. чтения·Автор: SSP Editorial Team
Обложка SSP для статьи рубрики «Мультиподпись понятным языком» о долговечных nonce в Solana и подписи двумя устройствами

Долговечные nonce: подпись двумя устройствами в Solana

SSP — это кошелёк 2 из 2. Каждая транзакция требует двух подписей: одной от Wallet, браузерного расширения на вашем компьютере, и одной от SSP Key на вашем телефоне. В этом и весь смысл такой схемы: вор, укравший одно устройство, всё равно не сможет перевести ваши средства. Но она порождает очень человеческую проблему. Компьютер строит и подписывает транзакцию за доли секунды. Телефон может подписать её совместно лишь через две-три минуты, потому что человеку нужно взять телефон, посмотреть запрос и нажать «одобрить».

В Solana этот промежуток — проблема. Эта статья объясняет почему и как SSP решает её, ничего хрупкого не сохраняя.

Blockhash, который истекает

Каждая обычная транзакция Solana несёт в себе данные, называемые недавним blockhash. Это отпечаток недавнего блока цепочки, и он выполняет сразу две задачи. Он доказывает, что транзакция создана недавно, и не даёт одной и той же подписанной транзакции воспроизводиться вечно.

Хитрость кроется в слове недавний. Blockhash действителен лишь около 150 блоков. В Solana блоки появляются быстро, поэтому 150 блоков — это всего около 60–90 секунд. После этого окна сеть просто отклоняет транзакцию — не потому, что с подписями что-то не так, а потому, что blockhash устарел.

Теперь сопоставьте процесс подписания SSP с этими часами. Wallet строит транзакцию, фиксирует свежий blockhash и подписывает. Затем пользователь получает уведомление на телефон. Если он ответит в течение 90 секунд — хорошо. Если он на совещании, телефон в другой комнате или он просто хочет внимательно прочитать транзакцию, blockhash тихо умирает. Подпись Wallet по-прежнему криптографически верна, но транзакция, к которой она была прикреплена, теперь ничего не стоит. Всё нужно собирать и переподписывать с нуля.

Для кошелька с одной подписью, который подписывает и рассылает на одном дыхании, окно в 90 секунд щедрое. Для кошелька 2 из 2, где между двумя подписями стоит человек, это гонка, которую пользователь раз за разом проигрывает.

Что такое долговечный nonce

У Solana есть встроенный ответ на это, и он появился раньше SSP: долговечный nonce. Идея в том, чтобы заменить истекающий blockhash значением, которое не истекает.

Долговечный nonce живёт в собственном небольшом аккаунте в цепочке — nonce-аккаунте. Этот аккаунт принадлежит системе, хранит всего 80 байт данных, и одна из этих частей — само значение nonce: долгоживущая замена blockhash. Транзакцию можно построить так, чтобы она использовала значение nonce-аккаунта вместо недавнего blockhash. Поскольку это значение не стареет, транзакция остаётся действительной столько, сколько нужно — минуты, часы, дни.

Но бесплатного ничего не бывает, и nonce нуждается в защите от повтора. Эта защита — правило: любая транзакция, использующая долговечный nonce, должна нести определённую инструкцию nonceAdvance в качестве самой первой инструкции. Когда транзакция наконец подтверждается, nonceAdvance потребляет текущее значение nonce и поворачивает аккаунт к новому. Nonce одноразовый. Транзакция, которую вы подписали в понедельник, может ждать до среды, но как только она исполнится, именно этот nonce уже никогда не сможет авторизовать другую транзакцию. Если вы хотите прочитать собственное описание механизма от Solana, документация о долговечных nonce транзакций — первоисточник.

Так долговечный nonce покупает время, не покупая риск повтора. Это именно то свойство, которое нужно кошельку из двух устройств.

Изюминка SSP: nonce-аккаунт, который вам никогда не надо хранить

Долговечный nonce-аккаунт всё равно остаётся аккаунтом, а в Solana у каждого аккаунта есть адрес. Наивный подход — создать nonce-аккаунт по какому-то случайному адресу, а затем бережно помнить этот адрес вечно: записать его в локальное хранилище кошелька, сделать резервную копию, надеяться, что он переживёт сброс устройства. Это ещё одна хрупкая вещь, которую можно потерять.

SSP отказывается её хранить. Вместо этого мультиподписная программа SSP для Solana содержит инструкцию provision_nonce, и она создаёт nonce-аккаунт по выводимому адресу. Адрес берётся из детерминированного рецепта: он вычисляется из самого мультиподписного аккаунта, фиксированной текстовой метки "nonce" и системной программы Solana. Один и тот же мультисиг на входе — один и тот же адрес nonce на выходе, каждый раз.

Это важно из-за того, что уже установлено в остальной части серии. Мультисиг SSP для Solana выводит адрес мультисига из набора участников и выводит адрес хранилища из мультисига. (Если эти выводы вам в новинку, статья самоинициирующийся мультисиг Solana разбирает их.) Теперь nonce-аккаунт присоединяется к той же семье: он тоже чистый вывод. Любое устройство SSP — ваш компьютер, ваш телефон, заново установленный кошелёк — может пересчитать адрес nonce-аккаунта с нуля. Нет секретного адреса, который можно потерять, потому что нет вообще никакого сохранённого адреса.

Из этого замысла следует несколько практических замечаний. provision_nonce бесправный (permissionless): любой может оплатить небольшую ренту (около 0,00144 SOL), чтобы nonce-аккаунт появился, и тот, кто платит, становится его начальным распорядителем — на практике это paymaster relay-сервиса SSP. Этого распорядителя можно позже переназначить, и адрес аккаунта при этом никогда не меняется, так что выведенный вами сегодня адрес остаётся верным, даже если стоящий за ним рабочий ключ сменится. Расположение nonce-аккаунта привязано к вашему мультисигу, а не к тому, кто его профинансировал.

Спокойный процесс подписания

Соберите детали вместе — и гонка исчезает. Wallet строит транзакцию, которая использует выводимый nonce-аккаунт вместо недавнего blockhash, ставит nonceAdvance первой инструкцией и подписывает. На телефон уходит push-уведомление. Пользователь одобряет, когда будет готов — никаких тикающих против него часов. SSP Key добавляет вторую подпись, и полностью подписанная транзакция рассылается. Поскольку она построена на долговечном nonce, она по-прежнему действительна, а nonceAdvance поворачивает nonce, чтобы транзакцию нельзя было воспроизвести.

Есть ещё одно ограничение, которое стоит назвать. Solana ограничивает одну транзакцию 1232 байтами. Мультиподписная транзакция должна уместить список участников и инструкции расхода в этот предел, поэтому SSP использует компактный формат версионированной транзакции Solana и передаёт данные как можно плотнее. Долговечный nonce не меняет бюджет размера; он меняет только бюджет времени.

Выводить всё, не хранить ничего

Это нить, проходящая через всю серию «Мультисиг в Solana, по-сэспэшному». Адрес мультисига, хранилище с вашими средствами и теперь nonce-аккаунт, дающий двум устройствам время договориться, — ни одно из них не является значением, которое SSP надо сохранять и оберегать. Каждое пересчитывается по требованию из входных данных, которые кошелёк и так знает. Меньше нужно резервировать, меньше может утечь и меньше может пойти не так при сбросе устройства. Мультиподписные схемы, опирающиеся на эту идею, например подход SSP мультисиг с одним подписантом, как правило, имеют меньше всего подвижных частей, которые могут сломаться.

Заключительное замечание в том же духе честности, что и остальная серия: мультиподписная программа SSP для Solana сейчас развёрнута только в devnet и ожидает внешнего аудита безопасности перед любым выпуском в mainnet. Описанный здесь замысел — включая provision_nonce и его выводимый nonce-аккаунт — реален и читаем в открытой программе, но это пока не продакшен-инфраструктура. Если сама двухустройственная модель SSP для вас нова, вводная статья что такое мультисиг 2 из 2 — место для старта.

Долговечный nonce — небольшой и старый элемент инженерной обвязки Solana. Вклад SSP в том, чтобы его адрес стал ещё одной вещью, которую вам никогда не нужно запоминать.

Поделиться статьёй

Похожие статьи