Зачем нужен BIP-147 (работа с податливостью фиктивных элементов стека, часть segwit)?

Учитывая BIP-11 (стандартные транзакции M-of-N), неясно, почему необходим BIP-147 (работа с податливостью фиктивных элементов стека).

БИП-11 гласит:

Транзакции OP_CHECKMULTISIG погашаются с помощью стандартного скрипта Sig:

OP_0 ...signatures...

(OP_0 требуется из-за ошибки в OP_CHECKMULTISIG; он выталкивает слишком много элементов из стека выполнения, поэтому в стек необходимо поместить фиктивное значение).

Тем не менее, BIP-147 утверждает:

Недостаток конструкции в OP_CHECKMULTISIG и OP_CHECKMULTISIGVERIFY приводит к тому, что они используют дополнительный элемент стека («фиктивный элемент») после проверки подписи. Пустой элемент никак не проверяется и может быть заменен любым значением без нарушения скрипта. ... [выделено мной]

Это утверждение противоречит BIP-11, который явно требует OP_0 в качестве первого элемента сценария проверки.

Я могу придумать две причины для BIP-147:

  1. BIP-11 явно не требует проверки стека, а просто требует, чтобы сценарий проверки мультиподписи начинался с OP_0;
  2. BIP-11 вообще не применяется к OP_CHECKMULTISIGVERIFY.

Действительно ли это мотивы для BIP-147, и есть ли другие?

Ответы (1)

BIP 11 — это не правило консенсуса, а рекомендация по использованию мультиподписи в сети.

BIP 147 правильно описывает существующие правила консенсуса в сети: OP_CHECKMULTISIG и OP_CHECKMULTISIGVERIFY извлекают из стека на один элемент больше, чем необходимо, и игнорируют этот элемент. BIP 147 изменяет правило, чтобы эти коды операций не игнорировали элемент, а требовали, чтобы он был равен 0. Чтобы соответствовать BIP 11, транзакции уже должны были помещать туда ноль 0, и на практике все всегда так делают. Но не было требования, чтобы транзакции следовали BIP11 — это была просто рекомендация для лучшей совместимости. С BIP147 становится необходимым иметь 0 для того, чтобы каждая транзакция была действительной.

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

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

Исправлена ​​ли ошибка с дополнительным элементом в транзакциях SegWit по-другому? Я смотрю на ввод мультиподписи погашения SegWit и думаю, что вижу «пустой» элемент стека, за которым следуют 2 подписи, а затем сценарий погашения P2SH. Является ли этот первый пустой элемент стека ""фиктивным элементом для CHECKMULTISIG?
@pinhead Да и нет. 0 кодируется как "" в стеке выполнения скрипта, поэтому OP_0 на самом деле просто помещает пустой элемент стека, а BIP147 на самом деле не требует OP_0 - ему просто требуется пустой элемент стека. В SegWit входной стек кодируется напрямую, а не как последовательность кодов операций (как в случае scriptSig). В результате фиктивный аргумент CMS в стеке-свидетеле действительно просто "".