Почему хэш-свидетель вместо сценария публичного ключа в подписи?

Когда ввод 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, поскольку есть более простые способы избежать повторного использования подписи:

  • Наследие: мы могли просто добавить фиктивный байт где-нибудь в текущем вводе.
  • Segwit: недостаток текущего ввода уже решает проблему.

Ответы (1)

Я просто предполагаю, но, фиксируя транзакцию в scriptCode, мы гарантируем, что подписывающая сторона знает, для какого сценария они подписываются. Аппаратный кошелек, например, может быть уверен, что outpoint 1234...cdef:0 оплачивает конкретный скрипт, только если мы передаем ему транзакцию, которая создала этот outpoint (чтобы он мог хешировать эту транзакцию, проверять txid, извлекать scriptPubKey и сравните это с предоставленным свидетелем). Поскольку транзакция (без свидетельских данных) может иметь размер почти до мегабайта, а расходная транзакция может относиться к тысячам предыдущих транзакций, мы создаем ситуацию, когда устройствам с низким уровнем ресурсов, таким как аппаратные кошельки, трудно проверить, что они повторное подписание.

Напротив, с BIP143 нам нужно только сообщить кошельку каждый из scriptCodes, который он должен подписывать. BIP141 позволяет использовать их до 10 000 байт, что составляет всего 1/100 от максимального размера транзакции. Кошелек может проверить эти коды сценариев, убедиться, что они соответствуют ожиданиям кошелька, и зафиксировать их в своей подписи, зная, что если человек, отправляющий им код сценария, солгал о фактическом коде сценария, подпись будет недействительной.

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

«... зная, что если человек, отправивший им scriptCode, солгал о фактическом scriptCode, подпись будет недействительной». Я здесь в глубоком затруднительном положении, но я думаю, что подпись будет недействительной, даже если она не связана напрямую с scriptCode, потому что подпись уже косвенно связана с scriptCode через путь outpoint->WSH->scriptCode. Так что это не совсем ответ на вопрос, я боюсь.
Вы правы в том, что фиксация точки аута фиксирует предыдущий scriptPubKey, а предыдущий scriptPubKey фиксирует скрипт, но суть ответа заключается в том, что для подтверждения кошельку того, что конкретная точка аута соответствует конкретному свидетельскому сценарию, требуется до ~ 1 МБ. данные плюс свидетельский скрипт. При фиксации непосредственно в scriptCode теперь единственными данными, необходимыми для доказательства, является scriptCode (который совпадает со свидетелемScript при обычном использовании).
Рассмотрим транзакцию с одним входом p2wsh. Аппаратный кошелек получает неподписанную транзакцию (Tx), предполагаемый ввод UTXO (U) и предполагаемый сценарий-свидетель (WS). Он также, вероятно, получает путь вывода ключа, но это не имеет отношения к данному обсуждению. Эта информация, [Tx, U, WS], сама по себе не доказывает, что точка выхода фиксирует WS . Кроме того, если ввод подписан на основе [Tx, U, WS] и если U и WS являются ложными, подпись будет недействительной независимо от того, фиксируется ли подпись в scriptCode или нет. Я ошибаюсь здесь? Спасибо за ваше терпение.
Да, я ошибаюсь здесь. Частная беседа с @David заставила меня понять, что подпись не будет недействительной, если BIP143 опустит scriptCode. Промах ума. Так что да, мы должны зафиксировать scriptCode.