Когда ввод segwit подписан, подпись будет зафиксирована в сценарии-свидетеле (или в сценарии, подобном p2pkh, в случае p2wpkh). Это указано в BIP143 :
- Для
P2WPKH
программы-свидетеляscriptCode
это0x1976a914{20-byte-pubkey-hash}88ac
.- Для
P2WSH
программы свидетелей,
- если
witnessScript
не содержит никакихOP_CODESEPARATOR
, онscriptCode
сериализуетсяwitnessScript
как скрипты внутриCTxOut
.- если он
witnessScript
содержит какой-либоOP_CODESEPARATOR
, то онscriptCode
удаляетwitnessScript
все, включая последний выполненныйOP_CODESEPARATOR
перед выполнением кода операции проверки подписи, сериализованный как скрипты внутриCTxOut
. (Точная семантика продемонстрирована в примерах ниже)
В чем причина этого? Почему хэш не фиксируется в сценарии публичного ключа, как в устаревших платежах (p2pkh и p2sh)? Эта разница немного усложняет код подписи/проверки, поэтому я полагаю, что для этого должна быть какая-то веская причина.
Может быть, мой вопрос должен быть таким: почему хэш вообще фиксируется в каком-либо скрипте для ввода segwit? В устаревших подписях размещение scriptPubkey в scriptSig для текущего ввода — это (сложный, см. ниже) способ избежать повторного использования подписи между входами. Но в segwit это достигается частью outpoint
алгоритма хеширования. Так нельзя ли просто пропустить эту scriptCode
часть?
Мне кажется, есть еще одна причина, по которой мы хешируем scriptPubkey для легаси-подписей и скрипт-свидетель для подписей segwit, поскольку есть более простые способы избежать повторного использования подписи:
Я просто предполагаю, но, фиксируя транзакцию в scriptCode, мы гарантируем, что подписывающая сторона знает, для какого сценария они подписываются. Аппаратный кошелек, например, может быть уверен, что outpoint 1234...cdef:0 оплачивает конкретный скрипт, только если мы передаем ему транзакцию, которая создала этот outpoint (чтобы он мог хешировать эту транзакцию, проверять txid, извлекать scriptPubKey и сравните это с предоставленным свидетелем). Поскольку транзакция (без свидетельских данных) может иметь размер почти до мегабайта, а расходная транзакция может относиться к тысячам предыдущих транзакций, мы создаем ситуацию, когда устройствам с низким уровнем ресурсов, таким как аппаратные кошельки, трудно проверить, что они повторное подписание.
Напротив, с BIP143 нам нужно только сообщить кошельку каждый из scriptCodes, который он должен подписывать. BIP141 позволяет использовать их до 10 000 байт, что составляет всего 1/100 от максимального размера транзакции. Кошелек может проверить эти коды сценариев, убедиться, что они соответствуют ожиданиям кошелька, и зафиксировать их в своей подписи, зная, что если человек, отправляющий им код сценария, солгал о фактическом коде сценария, подпись будет недействительной.
По той же причине формат подписи BIP143 фиксирует значение каждого ввода. Раньше ему приходилось обрабатывать предыдущие транзакции, чтобы получить их выходные суммы; теперь он просто принимает любые полученные данные и подписывает их, зная, что, если кто-то солгал ему о сумме, подпись будет недействительной.
Калле Розенбаум
Дэвид А. Хардинг
Калле Розенбаум
Калле Розенбаум