Перейти к содержимому
buybitcoinsmart

Глоссарий / Справочник разработчика

OP_EQUALVERIFY

Что такое OP_EQUALVERIFY?
OP_EQUALVERIFY сравнивает два верхних элемента стека и мгновенно прерывает скрипт, если они различаются; именно так расходование по старому шаблону доказывает, что предъявлен правильный публичный ключ.

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

Как это работает

OP_EQUALVERIFY снимает со стека два элемента, сравнивает их побайтно и либо молча продолжает выполнение, либо завершает скрипт.

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

Успех ничего не возвращает в стек. В этом вся причина существования слитой формы, и поэтому скрипт pay-to-public-key-hash длиной 25 байт может завершаться проверкой подписи, а не оставшимся логическим значением, которое никому не нужно. Интерпретатор Bitcoin Core реализует слияние буквально: он выполняет ветку сравнения, а затем переходит в общую ветку утверждения, так что это один путь в коде, а не два похожих.

Эта схема повторяется по всему языку. Каждый слитый опкод verify находится ровно на один байт выше своего простого аналога: 0x87 и 0x88 для равенства, 0xac и 0xad для проверки подписи, 0xae и 0xaf для старого опкода мультиподписи. Там, где условие должно выполняться прежде, чем может произойти что-либо еще, авторы скриптов берут более высокий байт.

Где это встречается

Яснее всего OP_EQUALVERIFY встречается не в обозревателе блоков, а в сообщении об отказе.

Если транзакция подписана ключом, который не соответствует адресу, Bitcoin Core отвечает ошибкой mandatory-script-verify-flag-failed, называя неудачную операцию OP_EQUALVERIFY в следующей за ней скобке. На практике эта ошибка почти всегда означает одно: устройство подписи вывело свой ключ по другому пути или из другой сид-фразы, чем та, которой принадлежат средства. Восстановление кошелька по неверному пути деривации с последующей попыткой расходования дает ровно это.

Декодированные скрипты тоже показывают это наглядно. Любой выход, оплачивающий адрес, который начинается с 1, отображается как скрипт из пяти элементов, где этот опкод стоит четвертым, а bitcoin-cli decodescript выводит ту же сборку для скрипта погашения, который вы вставите.

OP_EQUALVERIFY vs OP_VERIFY

OP_EQUALVERIFY представляет собой конкретную проверку с приваренным к ней утверждением, а OP_VERIFY является утверждением само по себе. Общая форма, байт 0x69, ничего не знает о том, что породило проверяемое значение; она снимает один элемент и требует, чтобы он был истинным. OP_EQUALVERIFY выполняет сравнение и требование вместе в одном байте, поэтому их редко пишут отдельно. Прибегайте к общей форме, когда условие происходит из арифметики, проверки блокировки по времени или проверки прообраза, которая не является простым равенством. Прибегайте к слитой форме всякий раз, когда вопрос действительно в том, совпадают ли две строки байт, а при расходовании одним ключом это всегда так.

Не путать с

Часто задаваемые вопросы

Что означает ошибка OP_EQUALVERIFY при трансляции транзакции?

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

Почему бы просто не написать OP_EQUAL, а затем OP_VERIFY?

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

Связанные термины

Еще в разделе «Справочник разработчика»

Читать эту страницу на английском