Хэширование мультиподписных скриптов (p2sh): разница между legacy и segwit

Некоторое время назад я заметил, что при одних и тех же входных данных методы ядра addmultisigaddressБиткойн createmultisigгенерировали разные p2sh (адреса).

Я поспрашивал, и пользователь из списка разработчиков биткойнов сказал мне, что это произошло потому, что:

«addmultisigaddress использует тип адреса кошелька по умолчанию, то есть p2sh-segwit, а createmultisig использует устаревший тип адреса по умолчанию»

Пример такого поведения:

bitcoin-cli addmultisigaddress 1 '["045897fee25bd7c5692510b2f50fcae9aa20fbc4d49d59814f4c7fdb5c4bc6eb1c0ce382458f9588e922e0d509ed8d34856787380075b00418b02e0bf7c652ef9d","02ac46c6d74d15e60f4f1035ff07ef740aca1d68d55ba0b8d336a73d7a35858831","0224a4dc5620714a9ecf67a09583d1e4c04f5bedb8ecea99028da05bb15a2a7e07"]'
{
  "address": "36ULucjWUTrDvaJzCyhFoVbDoNS6Zum2Du",
  "redeemScript": "5141045897fee25bd7c5692510b2f50fcae9aa20fbc4d49d59814f4c7fdb5c4bc6eb1c0ce382458f9588e922e0d509ed8d34856787380075b00418b02e0bf7c652ef9d2102ac46c6d74d15e60f4f1035ff07ef740aca1d68d55ba0b8d336a73d7a35858831210224a4dc5620714a9ecf67a09583d1e4c04f5bedb8ecea99028da05bb15a2a7e0753ae"
}

bitcoin-cli createmultisig 1 '["045897fee25bd7c5692510b2f50fcae9aa20fbc4d49d59814f4c7fdb5c4bc6eb1c0ce382458f9588e922e0d509ed8d34856787380075b00418b02e0bf7c652ef9d","02ac46c6d74d15e60f4f1035ff07ef740aca1d68d55ba0b8d336a73d7a35858831","0224a4dc5620714a9ecf67a09583d1e4c04f5bedb8ecea99028da05bb15a2a7e07"]'
{
  "address": "3GiimyxF1R5VixfBFAbQZbuy9EesD2r6n1",
  "redeemScript": "5141045897fee25bd7c5692510b2f50fcae9aa20fbc4d49d59814f4c7fdb5c4bc6eb1c0ce382458f9588e922e0d509ed8d34856787380075b00418b02e0bf7c652ef9d2102ac46c6d74d15e60f4f1035ff07ef740aca1d68d55ba0b8d336a73d7a35858831210224a4dc5620714a9ecf67a09583d1e4c04f5bedb8ecea99028da05bb15a2a7e0753ae"
}

Дело в том, что позже я заметил, что с некоторыми открытыми ключами два метода генерируют один и тот же хэш:

bitcoin-cli addmultisigaddress 1 '["03fc5e16d0ece343a94735ca467d5812922fcc30e3ce43ceaf3cff7d7617631146","02ea92a0cd1738cef7502e42fe119a322845f8f1a2dd9b7216635e17dd2fffd101","04633794a75bfbd9fb2bc6bd54836831c0916dc27f9ac528045cc9352bb2cc97a003b3a6ae397101d801f3d95e6a153368b939aaf7b27bd3a5bb8a30ed92aac204"]'
{
  "address": "32AVnYUUSvm4bGgEXoQ2zuFAJBPH4P31Gi",
  "redeemScript": "512103fc5e16d0ece343a94735ca467d5812922fcc30e3ce43ceaf3cff7d76176311462102ea92a0cd1738cef7502e42fe119a322845f8f1a2dd9b7216635e17dd2fffd1014104633794a75bfbd9fb2bc6bd54836831c0916dc27f9ac528045cc9352bb2cc97a003b3a6ae397101d801f3d95e6a153368b939aaf7b27bd3a5bb8a30ed92aac20453ae"
}

bitcoin-cli createmultisig 1 '["03fc5e16d0ece343a94735ca467d5812922fcc30e3ce43ceaf3cff7d7617631146","02ea92a0cd1738cef7502e42fe119a322845f8f1a2dd9b7216635e17dd2fffd101","04633794a75bfbd9fb2bc6bd54836831c0916dc27f9ac528045cc9352bb2cc97a003b3a6ae397101d801f3d95e6a153368b939aaf7b27bd3a5bb8a30ed92aac204"]'
{
  "address": "32AVnYUUSvm4bGgEXoQ2zuFAJBPH4P31Gi",
  "redeemScript": "512103fc5e16d0ece343a94735ca467d5812922fcc30e3ce43ceaf3cff7d76176311462102ea92a0cd1738cef7502e42fe119a322845f8f1a2dd9b7216635e17dd2fffd1014104633794a75bfbd9fb2bc6bd54836831c0916dc27f9ac528045cc9352bb2cc97a003b3a6ae397101d801f3d95e6a153368b939aaf7b27bd3a5bb8a30ed92aac20453ae"
}

Я не понимаю, как это возможно, если входные данные и сценарии выкупа одинаковы.

В чем разница между этими двумя случаями и вообще между устаревшей транзакцией с мультиподписью и транзакцией segwit?

Читая необработанные данные о транзакциях из блокчейна, как можно узнать, нужно ли хешировать скрипт с помощью устаревшего или segwit?

Я не уверен, почему это происходит. Если есть хотя бы один несжатый открытый ключ, оба метода должны давать устаревшие адреса p2sh. Однако я заметил, что в первом случае, если вы проталкиваете несжатый открытый ключ из позиции 1 в позицию 2 или 3 при передаче вызова RPC, мы получаем одинаковые адреса p2sh обоими методами.
Это хороший момент @UgamKamat, спасибо. Я не думал, что если один из публичных ключей не сжат, p2sh должен быть устаревшим, потому что segwit не поддерживает несжатые ключи. Однако этого недостаточно для общего правила, потому что я думаю, что и в случае, когда все публичные ключи сжаты, p2sh все еще может быть устаревшим.
это правильно, но меня озадачивает то, почему два вызова RPC дают разные адреса в вашем первом случае. Можно проверить, если переложить несжатый публичный ключ в первом случае в последнюю позицию и запустить оба RPC-вызова, они будут давать одинаковые P2SH-адреса. Мне трудно понять, почему они разные, если сначала несжатый открытый ключ
В обоих примерах несжатый публичный ключ является частью вашего кошелька? Я думаю, что здесь есть ошибка.

Ответы (1)

Я считаю, что поведение, которое вы видите, на самом деле является ошибкой.

По умолчанию addmultisigaddressиспользует p2sh-segwit, который является типом адреса по умолчанию для кошелька. По умолчанию createmultisigиспользует устаревшие. Это два разных типа адресов, и обычно вы получаете два разных адреса.

Однако segwit не позволяет использовать несжатые открытые ключи. Таким образом, при создании redeemScript, если обнаружен несжатый открытый ключ, оба RPC будут возвращать устаревшие адреса. Вот почему вы видите тот же адрес во втором примере.

Но я считаю, что это ошибка. Ваш первый пример также должен давать те же устаревшие адреса, но это не так. Я думаю, это связано с тем, что несжатый публичный ключ не является частью кошелька, поэтому он неправильно определяет, что это несжатый публичный ключ. Таким образом addmultisigaddress, по умолчанию выдается адрес p2sh-segwit, а createmultisigпо умолчанию — устаревший адрес.

Читая необработанные данные о транзакциях из блокчейна, как можно узнать, нужно ли хешировать скрипт с помощью устаревшего или segwit?

Для p2sh-segwit redeemScript на самом деле не является redeemScript, который вы получаете от RPC. Скорее это сценарий для вывода P2WSH. «RedeemScript» на самом деле является свидетельским скриптом для сценария P2WSH, который является фактическим redeemScript. Тип скрипта (либо в scriptPubKey, либо в redeemScript) определяет, является ли этот вывод SegWit или нет.

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