Глоссарий / Справочник разработчика
OP_DUP
- Что такое OP_DUP?
- OP_DUP копирует верхний элемент стека, чтобы его можно было использовать дважды, и поэтому стандартный скрипт pay-to-public-key-hash может и вычислить хеш вашего публичного ключа, и проверить подпись по нему.
Один байт, 0x76, и одна задача. В Bitcoin Script нет переменных, только стек, поэтому элемент, израсходованный одной инструкцией, исчезает до запуска следующей, и дублирование остается единственным способом использовать его повторно. Это первый из четырех рабочих опкодов в скрипте размером 25 байт, который защищал почти каждый адрес биткоина, начинающийся с 1.
Как это работает
Дублирование необходимо, потому что для проверки нужен один и тот же публичный ключ для двух несовместимых целей. Выход содержал только хеш, поэтому ключ нужно хешировать и сравнить, чтобы доказать, что это правильный ключ. Затем для проверки подписи нужен сам ключ, который сравнение уже израсходовало бы.
Проследите шаг за шагом за расходованием в формате legacy. Данные отправителя попадают в стек как подпись, а над ней находится публичный ключ. OP_DUP создает вторую копию ключа. OP_HASH160 заменяет копию ее дайджестом размером 20 байт. Выход добавляет в стек зафиксированные 20 байт, OP_EQUALVERIFY расходует оба и прерывает весь скрипт при любом несовпадении, а OP_CHECKSIG остается с исходным ключом и подписью, то есть ровно с тем, что ему нужно. Пять шагов, без ветвлений, без циклов и с фиксированной стоимостью каждый раз.
Опкод учитывается в двух пределах, ничего дорогого при этом не делая. Он является одной из 201 рабочих инструкций, которые может содержать скрипт до Taproot, а создаваемая им копия учитывается в лимите 1000 элементов во всех стеках. Ни то, ни другое не важно при расходовании с одним ключом, и оба важны в скрипте, который дублирует элементы внутри цепочки условий без циклов.
Где это встречается
Посмотрите на любую транзакцию, которая расходует адрес, начинающийся с 1, и скрипт выхода начнется с OP_DUP. Обозреватели блоков печатают его как первый токен в представлении ассемблера.
Интереснее то, где он выполняется, не появляясь. Нативный выход SegWit с одним ключом не содержит логики вообще, только байт версии и хеш размером 20 байт, но BIP-141 предписывает узлу построить классический шаблон из этого хеша и все равно его выполнить. Поэтому опкод по-прежнему срабатывает при каждом расходовании P2WPKH в сети и нигде не появляется в блоке. Поведение сохраняется, а четыре весовые единицы, которые раньше стоил этот байт, платить не нужно.
Выходы с хешем скрипта и расходования по ключевому пути Taproot его полностью пропускают. Выход P2SH сравнивает хеш напрямую, а расходование по ключу Taproot проверяет подпись по ключу выхода без участия скрипта. Это наименьшая возможная иллюстрация того, что на самом деле сделали SegWit и Taproot: не столько новые возможности, сколько те же проверки, организованные так, чтобы цепочке приходилось нести меньше байт для их получения.