Блокчейн/Уровень IV · Глубины протокола/4.1 Script/Урок 1
Script: стековый язык
Стек, благодаря которому выполнение остаётся ограниченным, и опкоды, отключённые Сатоши
МатериалыЛист бумаги и ручкаДоступ к обозревателю блоков BitcoinСтраница «Script» в Bitcoin Wiki
Любопытство
- Почему язык без циклов защищает каждую ноду от бесконечных вычислений?
- Какая конкретная ошибка в 2010 году позволяла кому угодно тратить чужие монеты до её исправления?
- Как выход может быть помечен как доказуемо нерасходуемый и при этом содержать данные?
Исследование
- Bitcoin Script — небольшой стековый язык в стиле Forth. В нём нет циклов и рекурсии, поэтому он намеренно не является полным по Тьюрингу. Такая архитектура гарантирует, что стоимость выполнения любого скрипта ограничена и предсказуема. Ни один скрипт не может выполняться бесконечно или потреблять неограниченные ресурсы, что защищает сеть от атак типа «отказ в обслуживании», присущих универсальному коду. Благодаря простоте любая нода может детерминированно проверять транзакции, не рискуя исчерпать ресурсы.
- Каждый выход содержит запирающий скрипт (scriptPubKey), который задаёт условия траты. Тратящий предоставляет данные для разблокировки через scriptSig или, начиная с SegWit, через данные witness. В ходе выполнения данные помещаются в стек, а опкоды применяются слева направо. Трата действительна, если выполнение завершается без ошибок и на вершине стека остаётся значение true. Этот бинарный результат защищает биткоины, никогда не раскрывая приватных ключей и опираясь на криптографическую проверку, а не на проверку личности.
- В 2010 году Сатоши Накамото в качестве меры предосторожности после обнаружения ошибок отключил несколько опкодов, включая OP_CAT и OP_MUL; одна из этих ошибок (в OP_LSHIFT) могла приводить к падению нод. Ещё более серьёзный изъян заключался в том, как scriptSig и scriptPubKey объединялись и выполнялись как единый скрипт: scriptSig, заканчивающийся на OP_RETURN, мог завершить выполнение с результатом 'true' ещё до того, как запирающий скрипт вообще начинал выполняться, что позволяло кому угодно тратить чужие монеты. Первое исправление сделало так, что OP_RETURN стал сразу приводить к ошибке; в более позднем релизе пошли дальше и стали выполнять scriptSig и scriptPubKey как отдельные скрипты. Это изменение укрепило модель безопасности и устранило опасные операции, которые могли быть использованы злоумышленниками или приводить к непредсказуемому поведению.
- OP_RETURN помечает выход как доказуемо нерасходуемый. Он используется для записи небольших объёмов данных в блокчейн без создания действительного способа траты. Поскольку никакая подпись не может удовлетворить OP_RETURN, монеты блокируются навсегда, но связанные с ними данные остаются частью истории блокчейна. Поскольку такие выходы никогда не могут быть потрачены, ноды не включают их в множество монет, доступных для траты.
- Чтобы понять механику, пошагово выполните на бумаге «2 3 OP_ADD 5 OP_EQUAL». Начните с пустого стека. Поместите в стек 2, затем 3. Примените OP_ADD: он извлекает оба значения и помещает в стек их сумму (5). Снова поместите в стек 5. Примените OP_EQUAL, чтобы сравнить два верхних элемента; поскольку они совпадают, в стек помещается true (1). В итоге в стеке остаётся единственное значение true, что удовлетворяет требованию действительности. Эта простая арифметика показывает, как опкоды работают со стеком, вычисляя условия.
- Откройте обозреватель блоков и найдите любую стандартную транзакцию. Найдите scriptPubKey в разделе выходов: он начинается с OP_DUP для устаревшего (legacy) выхода P2PKH, с OP_0 для нативного SegWit или с OP_1 для Taproot. Затем откройте транзакцию, которая тратит такой выход, и найдите подпись и ключ — в scriptSig для устаревших выходов или в witness для SegWit и Taproot, — которые удовлетворяют этому скрипту, оставляя значение true в стеке выполнения для всех проверяющих нод.
Ключевые факты
- Bitcoin Script не является полным по Тьюрингу: в нём нет циклов и рекурсии.
- В 2010 году Сатоши в качестве меры предосторожности после обнаружения ошибок отключил OP_CAT, OP_MUL и другие опкоды.
- С 2010 года scriptSig и scriptPubKey выполняются отдельно, а не объединяются вместе.
- OP_RETURN помечает выход как доказуемо нерасходуемый — для встраивания данных.
- Действительная трата оставляет значение true на вершине стека выполнения.
- Стоимость каждого скрипта ограничена из-за отсутствия произвольных вычислений.
Упражнение девять, шесть, три, один
9СобратьПеречислите 9 опкодов Bitcoin Script. Отметьте, какие из них отключены, какие напрямую изменяют стек, а какие выполняют криптографические проверки.
6СгруппироватьРаспределите эти 9 опкодов по 6 группам по назначению: арифметика, сравнение, работа со стеком, криптографическая проверка, встраивание данных, устаревшие/удалённые.
3Выделить главноеСведите 6 групп к 3 причинам, по которым Script намеренно оставили ограниченным.
1КристаллизоватьНапишите одно предложение о том, как ограниченное выполнение защищает сеть от вредоносных скриптов.
Проверка фактов
Даты, цифры и утверждения были проверены по приведенным ниже опубликованным источникам.