Авторы: Питер Уилле и Эндрю Поэлстра

Вступление

Биткойн-скрипт

У Биткойна всегда был механизм, позволяющий тратить монеты с помощью более сложных политик, чем просто один ключ: система скриптов. Хотя скрипт в основном используется для платежей с одним ключом, он также является основой для множества кошельков с несколькими подписями, конструкций атомарного свопа и сети Lightning.

Однако это еще не все, на что он способен. Сценарий может использоваться для представления сложных условий, необходимых для выпуска транзакции, например (два из A, B, C) и (D или (E и F)), где A-F каждый представляет уникальный ключ, а также проверки прообраза хэша, временные блокировки и еще несколько экзотических конструкций.

Трудно проверить

Одна из причин, по которой мы еще не приблизились к использованию всего потенциала Script, заключается в том, что на самом деле создание сценариев для нетривиальных задач является обременительным: трудно проверить их правильность и безопасность, и еще сложнее найти наиболее экономичный способ написания вещей.

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

Что, если бы вместо этого приложения Биткойн могли работать с любым сценарием, а не только с несколькими сценариями, для которых они были разработаны? Мы не были бы ограничены использованием разовых проектов и могли бы начать разрабатывать приложения, которые создают и используют сценарии, сгенерированные на лету, в соответствии с требованиями, указанными пользователем. Разработчики кошельков также могут ввести больше вариантов на основе сценариев, сохранив при этом возможность взаимодействия с другими кошельками.

Минискрипт

Введите Miniscript, язык для структурированного представления биткойн-скриптов, обеспечивающий эффективный анализ, составление, общее подписывание и многое другое.

Например биткойн-скрипт

<A> OP_CHECKSIG OP_IFDUP OP_NOTIF OP_DUP OP_HASH160 <hash160(B)> OP_EQUALVERIFY OP_CHECKSIGVERIFY <144> OP_CSV OP_ENDIF

где A и B - открытые ключи, могут быть преобразованы в нотацию Miniscript как

or_d(c:pk(A),and_v(vc:pk_h(B),older(144)))

Эта нотация дает понять, что семантика сценария разрешает расходы, когда либо знак A, либо знак B после 144 блоков. Таким образом можно написать большую часть значимых сценариев.

Сделать скрипты удобочитаемыми для человека (или инженера…) - лишь одна из возможностей Miniscript. Его основная цель - обеспечить автоматическое рассуждение по сценарию, как показано в приведенных ниже сценариях использования.

Случаи применения

Сегодня использовать биткойн-скрипт для создания сложных условий расходов намного сложнее, чем нужно, поскольку для каждого нового варианта использования требуется разработка, тестирование и развертывание специального программного обеспечения. Miniscript может охватить эти случаи способом, который обобщает произвольные наборы условий расходов, и часто намного проще и надежнее, чем решение специального назначения.

Оптимизированный скрипт

Один из таких случаев - поиск оптимального сценария, который реализует заданный набор условий расходов. В биткойн-скрипте есть много разных способов потребовать подпись, описать конъюнкцию или дизъюнкцию или реализовать порог. Даже для опытного разработчика биткойн-скриптов правильный выбор может зависеть от относительной вероятности выполнения различных условий и быть трудным для расчета. Наш онлайн-компилятор, также доступный как исходный код C ++ или реализованный как часть библиотеки rust-miniscript, может мгновенно найти оптимальный Miniscript, соответствующий данной политике расходов.

Пример во введении можно получить, составив политику

or(99@pk(A),1@and(pk(B),older(144)))

это способ записать, что левая сторона или (знаки A) имеет 99% вероятность быть взята, а правая сторона (знаки B после 144 блоков) имеет 1% шанс быть взятой.

Общие расходы

Как только эффективный сценарий был найден, общим препятствием для многих его применений является отсутствие взаимодействия между различными механизмами расходования средств. Пользователи, желающие реализовать долгосрочные временные рамки или сложные требования множественной подписи, могут быть заблокированы из-за опасений, что их контрагенты не имеют (или не будут) программного обеспечения для распознавания и использования монет, контролируемых политикой.

Минискрипт, в силу прямого представления условий расходов, позволяет выражать произвольную политику таким образом, чтобы каждый мог:

  1. вычислить связанный адрес (а) скрипта;
  2. определить, какие подписывающие лица необходимы или достаточны для подписания в данный момент;
  3. произвести действительную транзакцию при наличии достаточного набора подписей.

Пользователям не нужно беспокоиться о том, что все участники используют совместимое программное обеспечение или что такое программное обеспечение будет продолжать существовать к тому времени, когда потребуются такие временные рамки.

Им также не нужно беспокоиться о том, что их потребности могут измениться в несовместимом с их программным обеспечением для подписи образом, гарантируя им, что их использование сценария Биткойн не будет ограничивать их.

Доказательство резервов

С проблемой подписания связана проблема доказательства резервов - процесса, с помощью которого компания доказывает, что она может потратить набор биткойнов, фактически не тратя их. Хотя для этого существуют инструменты, такие как Blockstream’s Proof of Reservations Tool, пока нет единого стандарта, используемого в отрасли. В отсутствие Miniscript, вероятно, не было возможности достичь стандарта, который мог бы охватить все разнообразие используемых сегодня решений по хранению.

Состав политики расходов

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

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

Используя Miniscript, эти директора могут просто составлять свои политики в программном обеспечении своего собственного кошелька, создавая единую политику, описывающую пороговое требование, а затем компилировать ее в Miniscript. Они могут напрямую проверить, что выходные данные компилятора соответствуют исходной политике и что исходная политика соответствует всем требованиям. Затем они могут использовать любое программное обеспечение, совместимое с Miniscript, для вычисления адресов для получения монет, сбора подписей во время трат и объединения этих подписей в действительную транзакцию.

В качестве простого гипотетического примера: компания настраивает индивидуальное хранилище с несколькими подписями с двумя директорами. Один директор уже использует Blockstream Green (настроенный как 2 из 2, который после некоторой задержки становится 1 из 2), а другой использует Electrum (стандартный 1 из 1). Без инструментов, позволяющих составлять безопасные, взаимодействующие политики сценариев, директор, использующий Грина, не смог бы добавить свою политику в качестве «участника» в мультиподписи компании. Если Грин и программное обеспечение, использованное для создания мультиподписи компании, поддерживали Miniscript, оба директора могли бы продолжать использовать свои предпочтительные кошельки напрямую, и никому даже не нужно было знать, что под капотом есть скрипты.

Динамические федерации

Конкретный пример мощи Miniscript можно найти в сайдчейне Liquid от Blockstream. Разрабатываемая в настоящее время функция, известная внутри компании как динамические федерации, позволяет существующим участникам Liquid управлять добавлением новых участников или обновлять скрипт, который контролирует расходуемость биткойнов, находящихся на хранении у федерации. Miniscript предоставляет участникам инструменты для быстрого и эффективного создания таких сценариев - действительно, компилятор Miniscript нашел более короткую на 22 байта версию существующего сценария Liquid, что на 5% меньше нашего исходного, тщательно оптимизированного вручную сценария. Но что более важно, это позволяет участникам автоматически проверять важные свойства предлагаемых сценариев, уменьшая необходимость для участников координировать друг друга или выполнять дорогостоящие ручные проверки безопасности предлагаемых сценариев.

В частности, участники могут автоматически проверять, что любое предложение сценария включает:

  1. собственный ключ;
  2. условие срочного расходования средств на случай чрезвычайной ситуации, которое является правильным и находится в достаточно отдаленном будущем.

Это также позволяет им убедиться, что участники новой федерации могут тратить монеты, контролируемые старой федерацией. Эта проверка необходима, чтобы гарантировать, что переходы не приводят к потере монет даже для пользователей, которые перемещали монеты в систему во время перехода, и была бы практически невозможна без Miniscript.

История

Идея Miniscript возникла летом 2018 года как кульминация нескольких идей, которые тогда находились в разработке. В середине июля Питер Вилле представил дескрипторы вывода в Bitcoin Core, универсальный способ описания множества различных типов адресов, поддерживаемых Core. Между тем, частично подписанная биткойн-транзакция (PSBT, описанная в BIP 174), протокол взаимодействия кошельков, разработанный Энди Чоу, когда он проходил стажировку в Blockstream тем летом, набирала обороты в сфере кошельков.

Важным компонентом PSBT является финализатор, участник, который собирает фактическую биткойн-транзакцию из набора данных подписантов, содержащихся в PSBT. Эта сборка требует понимания выполняемых сценариев, а это означает, что кошельки с поддержкой PSBT, выполняющие нетривиальные задачи, должны реализовывать свои собственные специализированные финализаторы, требующие избыточной разработки и ограничивающие возможность взаимодействия.

Эндрю Поэлстра из Blockstream изо всех сил пытался принять реализацию PSBT для rust-bitcoin, универсальной библиотеки Bitcoin для языка программирования Rust. Такая реализация была предложена Карлом Донгом, но не включала финализатор, достаточно общий для поддержки всех пользователей библиотеки. Поэльстра заметил на IRC, что если у вас есть хорошо структурированные шаблоны сценариев, вы можете избежать проблем, если не понимаете сценарий, - идея, которая стала ядром Miniscript.

Вне связи, Поэльстра и Вуилле работали над проектом, связанным с хранением, и были разочарованы отсутствием стандартных инструментов, доступных для сложных сценариев с несколькими участниками. Эти двое встретились, чтобы обсудить это в августе 2018 года. Уилле предложил реализовать эти «сильно структурированные шаблоны сценариев» как расширение выходных дескрипторов Bitcoin Core.

По мере того, как расширение обрело форму, оно было разделено на структурированное подмножество Биткойн-скрипта, которое стало Miniscript, а также более простой язык политики для прямого представления условий расходов, который можно было скомпилировать в Miniscript. В январе 2019 года Уилле представил предварительные результаты на Стэнфордской конференции по блокчейну.

В мае следующего года Санкет Канжалкар присоединился к Blockstream на трехмесячную стажировку, посвященную внедрению инструментов для Miniscript и помощи в его интеграции с Bitcoin Core. С его помощью Miniscript был полностью и многократно переработан, чтобы он стал меньше, более эффективным, более легко анализируемым и лучше защищенным от податливости. Последний набор изменений был внесен для проверки большого набора случайных Miniscript-совместимых скриптов на соответствие правилам консенсуса и стандартизации Биткойн. Результатом этих итераций стал сегодняшний Минискрипт.

Связанных с работой

Miniscript основан на многих других проектах экосистемы Биткойн и интегрируется с ними. В частности, как описано выше, Miniscript расширяет дескрипторы вывода кошелька Bitcoin Core и дополняет PSBT, обеспечивая полностью общие средства обновления и финализаторы.

Минискрипт можно сравнить с Ivy, другим языком, разработанным для того, чтобы сделать расширенные функции Биткойн-скрипта доступными. Однако, в то время как Ivy компилируется в Script, Miniscript является прямым представлением (подмножества) Script, что означает, что правильность и надежность минискриптов можно эффективно проверять с помощью вычислений. Miniscript также поддается многим другим формам статического анализа, которых нет ни в Script, ни в Ivy.

Язык политики Miniscript похож на Ivy в том, что оба являются абстракциями, которые должны быть скомпилированы в (Mini) Script для использования в блокчейне. Однако язык политик Miniscript настолько структурно похож на сам Miniscript, что выходные данные компилятора можно легко проверить на соответствие входным данным компилятора - фактически, это можно даже проверить вручную - и легко проверить, чтобы они соответствовали ожиданиям пользователя.

Еще один язык блокчейнов, связанный с Miniscript, - Simplicity от Blockstream. Как и Miniscript, Simplicity - это низкоуровневый язык, предназначенный для непосредственного встраивания в транзакции блокчейна. Также, как и Miniscript, Simplicity поддерживает множество форм статического анализа, которые имеют решающее значение при развертывании контрактов на блокчейн, но которые, тем не менее, очень сложны или невозможны по дизайну в альтернативах, таких как EVM Ethereum.

В отличие от Simplicity, которая достаточно мощна для выражения любой вычислимой функции, Miniscript очень ограничен по объему: он может выражать требования подписи, временные рамки, прообразы хэшей и их произвольные комбинации. Такое сокращение объема упрощает рассуждение Miniscript для рассматриваемых им вариантов использования и, что немаловажно, позволяет ему работать с существующей цепочкой блоков Биткойн. Простота, напротив, является радикальным отходом от сценария Биткойн и все еще находится на ранних стадиях своего развития.

Будущая работа и выводы

При разработке Miniscript мы стремились сделать Биткойн-скрипт более доступным. Несмотря на то, что большая часть работы сосредоточена на исследовании и предложении будущих изменений в правилах консенсуса Script и Биткойн для добавления дополнительных функций, мы чувствовали, что инфраструктура отсутствовала, чтобы даже использовать функции, которые уже есть, общим, безопасным, компонуемым и совместимым способом. .

Эта работа еще не закончена. У нас есть две функциональные реализации Miniscript (C ++ и Rust) и компилятора политик, но чтобы сделать эту технологию доступной, нам потребуется интеграция в часто используемые части программного обеспечения. Благодаря реализации PSBT, совместимой с Miniscript (средство обновления и финализатор), многие подписывающие стороны PSBT (в том числе аппаратные кошельки) могут стать пригодными для сложных сценариев даже без явной поддержки. Компиляторы также можно улучшить, поскольку в политике есть много оптимизаций для преобразования скриптов, которые еще не рассматриваются.

Попутно мы узнали несколько вещей:

  • Ограничения ресурсов сценария усложняют оптимизацию политики: множество ограничений ресурсов, установленных консенсусом и стандартизацией (максимальное количество кодов операций, максимальный размер сценария, максимальный размер стека и т. д.), значительно затрудняют поиск оптимального сценария для данной политике, как только она приблизится к достижению этих пределов. Это интересное открытие, так как оно может помочь в предложении улучшений скрипта в будущем. В связи с этим мы также были удивлены, узнав, что правила консенсуса Биткойн фактически подсчитывают количество ключей, участвующих в исполняемом OP_CHECKMULTISIG(VERIFY), до 201 кода операции без принудительной отправки на ограничение сценария.
  • Переменные размеры свидетелей усложняют оценку комиссии. Простые платежи и конструкции с несколькими подписями имеют размер свидетеля, который не зависит от точного набора имеющихся ключей. Когда мы переходим к более сложным сценариям, размер свидетеля становится переменным, что может усложнить расчет комиссии. Потенциальным подписывающим сторонам для выходных данных конкретной транзакции, возможно, потребуется оптимистично предположить, что будет выбран дешевый путь, и построить соответствующую транзакцию. Если не все ключи или хэши для этого пути в конечном итоге становятся доступными, может потребоваться изменить саму транзакцию, чтобы учесть возросшие комиссии.
  • Кодирование стека Segwit усложняет оптимизацию: с момента Segwit входной стек больше не кодируется как скрипт, а непосредственно как список элементов стека. Это имело неприятный побочный эффект - изменение кодировки «истина» с 1 байта на 2 байта. Из-за этого Miniscript должен заботиться о том, какие подвыражения с какой стороны входят в структуру IF / ELSE / ENDIF.
  • Гибкость. Начиная с Segwit, гибкость транзакций больше не является препятствием для правильности протоколов, но все же может иметь нежелательные эффекты (например, неуверенность в размере комиссии при распространении транзакции, замедление компактного блока. распространение и вмешательство в использование хеш-блокировок являются глобальным механизмом публикации). По этим причинам мы разработали Miniscript с учетом неподатливости и узнали, как вообще рассуждать о неподатливости свидетелей. Чтобы достичь этого, Miniscript полагается на определенные правила, специфичные для Segwit, поскольку добиться неизменяемости в правилах транзакций, предшествующих Segwit, очень сложно.
  • Устранение общих подвыражений сложно: несмотря на различные попытки, Miniscript не поддерживает оптимизацию повторяющихся подвыражений. Хотя это возможно в определенных конкретных случаях, кажется, что это очень сложно сделать в Script в целом. Добавление определенных кодов операций управления стеком может изменить это.

Начать строить на Miniscript

Разработчики, заинтересованные в работе с Miniscript, могут начать с изучения конструкций Miniscript с помощью нашего онлайн-компилятора и анализатора. Вы также можете ознакомиться с некоторыми из наших примеров использования rust-miniscript.

Участие в репозиториях GitHub C ++ miniscript и rust-miniscript очень приветствуется, и вы часто можете встретить нашу команду в IRC ## miniscript на Freenode для обсуждения, связанного с минискриптом!