Подписание транзакции Bitcoin Segwit - PullRequest
0 голосов
/ 17 февраля 2020

Чтобы узнать больше о Bitcoin транзакциях, я изучаю бинарный файл и не использую никаких инструментов, таких как BitcoinTx или Bitcoin -cli. Во всяком случае, я столкнулся с некоторым затруднением при попытке подписать транзакцию Segwit. Теперь это простая транзакция, один UTXO и один получатель, и это транзакция P2WPKH.

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

02000000010a02214430acee2ed509798187210171bb387075ce2c82ef5a73774d6159387500000000 00 ffffffff
018ca1b404000000001976a914906ec1c4804632c0b067e5a2732c41cdf620c4e688ac0000000001000000

Выше приведена необработанная транзакция, 1 вход, 1 выход. В поле segwit у меня есть 0x00 байт, как указано. Итак, я SHA256 (sha256) выше бинарная, а затем создать свою подписанную сделку segwit, как показано ниже:

1007 * 020000000001010a02214430acee2ed509798187210171bb387075ce2c82ef5a73774d615938750000000017160014d99f1ea19e98d9ed10e5d442be37a44b6b63c477ffffffff 018ca1b404000000001976a914906ec1c4804632c0b067e5a2732c41cdf620c4e688ac 02 4830460221009f5743a2fc62bb9cee292ef79eb3ec3a20a3ed1ec84bdf9e8520592ca1d84f35022100922f887be7283eb0fd73da53efa554e62a589f6e268c0d300ad727791c2f936c 41047d011958b661181242addd300b6d5c51f80d62674555831dd855b34358b57e05fb46477ba167a57b23bf8a492305c0085d8c34aa04d483b7f15a2d551e2ff66200000000 1009 * Таким образом, в выше, я получил мой входной сделки и в SigScript я поместил pu sh из 0, за которым следует 20-байтовый Hash160 из ключа publi c.

Далее, выходная транзакция, которая просто имеет ключ publi c ha sh с OP_DUP, OP_HASH_160 OP_EQUALVERIFY, OP_CHECKSIG.

Наконец идет подпись, которая имеет 02 для 2 частей, 1 является самой подписью (закодированный в дер) и, наконец, ключ publi c.

По какой-то причине он говорит, что подпись неверна, и я понятия не имею, почему. Должен ли SigScript в транзакции фактически быть NULL, прежде чем я подпишу его? Должен ли это быть HASH160 открытого ключа кошелька c, у которого есть средства (например, для транзакции P2PKH), прежде чем я подпишу его?

Любые указатели будут очень благодарны, потому что я думаю, что я близок Мне просто нужно знать, как должна выглядеть транзакция, прежде чем я подпишу ее.

1 Ответ

1 голос
/ 21 марта 2020

Вам необходимо поместить ScriptPubKey в поле SigScript для целей подписи. Будьте очень осторожны с правилами Endianess и Low-High R и S для сигнатуры кривой elipti c.

Объяснение из: https://bitcoin.stackexchange.com/posts/32695/edit

Step- пошаговое описание:

Мы начинаем создавать новую транзакцию, которую мы sh подписываем.

  1. Добавьте четырехбайтовое поле версии: 01000000
  2. Однобайтовая переменная с указанием количества входных данных: 01
  3. 32-байтового га sh транзакции, из которой мы хотим выкупить выход (обратный порядок): be66e10da854e7aea9338c1f91cd489768d1d6d7189f586d7a3613f2a24d5396
  4. Четырехбайтовое поле, обозначающее выходной индекс, который мы хотим выкупить из транзакции с приведенным выше га sh (считая с нуля): 00000000
  5. Теперь идет scriptSig. Для подписания транзакции она временно заполняется значением scriptPubKey вывода, который мы хотим выкупить. Сначала мы пишем однобайтовую переменную, которая обозначает длину scriptSig (0x19 = 25 байт): 19
  6. Затем мы пишем фактический scriptSig (который является scriptPubKey для вывода, который мы хотим выкупить) : 76 a9 14 dd6cce9f255a8cc17bda8ba0373df8e861cb866e 88 ac (посмотрите на строчку нижней строки на https://blockchain.info/tx/96534da2f213367a6d589f18d7d6d1689748cd911f8c33a9aee754a80de166be?show_adv=true)
  7. Затем мы запишем четырехбайтовое поле, обозначающее последовательность. В настоящее время это всегда значение 0xffffffff: ffffffff
  8. Далее идет однобайтовая переменная, содержащая количество выходов в нашей новой транзакции. В этом примере мы установим значение 1: 01
  9. Затем запишем 8-байтовое поле (64-разрядное целое число с прямым порядком байтов), содержащее сумму, которую мы хотим выкупить из указанного вывода. Я установлю это на общую сумму, доступную на выходе, за вычетом комиссии 0,0001 BT C (128307 - 10000): 23ce010000000000
  10. Затем мы начнем записывать вывод нашей транзакции. Мы начинаем с однобайтовой переменной, обозначающей длину выходного сценария (0x19 или 25 байт): 19
  11. Затем фактический выходной сценарий: 76 a9 14 a2fd2e039a86dbcf0e1a664729e09e8007f89510 88 ac (это перевод средств обратно на адрес 1FromKBPAS8MWsk1Yv1Yiu8rJbjfVioBH c)
  12. Затем мы записываем четырехбайтовое поле «время блокировки»: 00000000
  13. И, наконец, пишем четырехбайтовый «код типа ha sh» ( 1 в нашем случае): 01000000

ОК, результат равен

01000000
01
be66e10da854e7aea9338c1f91cd489768d1d6d7189f586d7a3613f2a24d5396
00000000
19 76 a9 14 dd6cce9f255a8cc17bda8ba0373df8e861cb866e 88 ac
ffffffff
01
23ce010000000000
19 76 a9 14 a2fd2e039a86dbcf0e1a664729e09e8007f89510 88 ac
00000000
01000000

Теперь мы удваиваем SHA256 га sh всю эту структуру, что дает га sh 1cde0239b55717cca8003104abc2ec2673d4f6fabea0b74351940e382e88486f

Теперь мы должны создать сигнатуру ECDSA ... 1MBngSqZbMydscpzSoehjP8kznMaHAzh9y - это мозговой кошелек "mrbubbymrbubbymrbubby!" , который просто кодирует адрес, начинающийся с 'MB' (что делает связывание 2 довольно простым; см. @ WizardOfAuss ie комментарий ниже для происхождения фразы). Закрытый ключ в WIF: 5HvofFG7K1e2aeWESm5pbCzRHtCSiZNbfLYXBvxyA57DhKHV4U3

В шестнадцатеричном виде закрытый ключ - 0ecd20654c2e2be708495853e8da35c664247040c00bd10b9b13e5e86e6a808d. В каждой крипто-библиотеке есть метод sign (key, digest). Он вернет массив байтов. Этот массив будет не более 72 байт и начинается с шестнадцатеричного кода 30. Предположим, что подпись 3046022100cf4d7571dd47a4d47f5cb767d54d6702530a3555726b27b6ac56117f5e7808fe0221008cbb42233bb04d7f28a715cf7c938e238afde90207e9d103dd9018e12cb7180e К этой подписи мы добавляем однобайтовый тип кода ha sh: 01. Ключ c publi для 1MBngSqZbMydscpzSoehjP8kznMaHAzh9y: 042daa93315eebbe2cb9b5c3505df4c6fb6caca8b756786098567550d4820c09db988fe9997d049d687292f815ccd6e7fb5c1b1a91137999818d17c73d0f80aef9

Мы создаем финальный скрипт Sig, объединяя: | <Фактическая DER-закодированная подпись плюс однобайтовый тип кода ha sh> | <Однобайтовый сценарий OPCODE, содержащий длину открытого ключа c>> |

scriptSig будет

49 3046022100cf4d7571dd47a4d47f5cb767d54d6702530a3555726b27b6ac56117f5e7808fe0221008cbb42233bb04d7f28a715cf7c938e238afde90207e9d103dd9018e12cb7180e 01
41 042daa93315eebbe2cb9b5c3505df4c6fb6caca8b756786098567550d4820c09db988fe9997d049d687292f815ccd6e7fb5c1b1a91137999818d17c73d0f80aef9

первая строка 'pu sh подпись, объединенная с 01', вторая строка 'pu sh pubkey'. Длина scriptSig составляет 140 байт (0x8 c в шестнадцатеричном формате)

Затем мы заменяем однобайтовое поле длины переменной из шага 5 длиной данных из шага 16. Длина составляет 140 байтов или 0x8 C байтов: 8c

И мы заменяем фактический scriptSig структурой данных, созданной на шаге 16.

Мы заканчиваем sh выключением , удаляя четырехбайтовый тип кода ha sh, который мы добавили на шаге 13, и мы получаем следующий поток байтов, который является Окончательный сделка:

01000000 01 be66e10da854e7aea9338c1f91cd489768d1d6d7189f586d7a3613f2a24d5396 00000000 8 c 49 3046022100cf4d7571dd47a4d47f5cb767d54d6702530a3555726b27b6ac56117f5e7808fe0221008cbb42233bb04d7f28a715cf7c938e238afde90207e9d103dd9018e12cb7180e 01 41 042daa93315eebbe2cb9b5c3505df4c6fb6caca8b756786098567550d4820c09db988fe9997d049d687292f815ccd6e7fb5c1b1a91137999818d17c73d0f80aef9 FFFFFFFF 01 23ce010000000000 19 76 14 а9 a2fd2e039a86dbcf0e1a664729e09e8007f89510 88 переменного тока 00000000

1107 *
...