Вступление

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

Текущий тип адреса по умолчанию в биткойн-ядре - это P2SH-P2WPKH, который представляет собой Pay-to-Witness-Public-Key-Hash, завернутый в Pay-to-Script-Hash. Для получения дополнительной информации см. Эту предыдущую статью: Как сгенерировать биткойн-адрес - шаг за шагом.

Узнай больше и присоединяйся к людям из 22 стран мира в моем курсе Как стать программистом Биткойн + Блокчейн.

Откройте для себя и ознакомьтесь с лучшими продуктами Биткойн

Формат транзакции

Давайте посмотрим на транзакцию из моей частной сети биткойнов:

0200000000010111b6e0460bb810b05744f8d38262f95fbab02b168b070598a6f31fad438fced4000000001716001427c106013c0042da165c082b3870c31fb3ab4683feffffff0200ca9a3b0000000017a914d8b6fcc85a383261df05423ddf068a8987bf0287873067a3fa0100000017a914d5df0b9ca6c0e1ba60a9ff29359d2600d9c6659d870247304402203b85cb05b43cc68df72e2e54c6cb508aa324a5de0c53f1bbfe997cbd7509774d022041e1b1823bdaddcd6581d7cde6e6a4c4dbef483e42e59e04dbacbaf537c3e3e8012103fbbdb3b3fc3abbbd983b20a557445fb041d6f21cc5977d2121971cb1ce5298978c000000

Это очевидно не требует пояснений, понял?

Если вам все еще интересно, давайте разберемся (слева направо):

Version: 02000000
Flag: 0001 (if present, indicates segwit)
Input Count: 01
Input 1 Previous Output Hash: 11b6e0460bb810b05744f8d38262f95fbab02b168b070598a6f31fad438fced4
Input 1 Previous Output Index: 00000000
Input 1 script length: 0x17 (23 bytes)
Input 1 signature script: 16001427c106013c0042da165c082b3870c31fb3ab4683
Input 1 sequence: feffffff
Output Count: 02
Output 1 Value: 00ca9a3b00000000 (1B satoshis / 10 BTC)
Output 1 public key script length: 0x17 (23 bytes)
Output 1 public key script: a914d8b6fcc85a383261df05423ddf068a8987bf028787
Output 2 Value: 3067a3fa01000000 (8499980080 sats / 84.9998008 BTC)
Output 2 public key script length: 0x17 (23 bytes)
Output 2 public key script: a914d5df0b9ca6c0e1ba60a9ff29359d2600d9c6659d87
Witness Count: 02
Witness 1 length: 0x47 (71 bytes)
Witness 1: 304402203b85cb05b43cc68df72e2e54c6cb508aa324a5de0c53f1bbfe997cbd7509774d022041e1b1823bdaddcd6581d7cde6e6a4c4dbef483e42e59e04dbacbaf537c3e3e801
Witness 2 length: 0x21 (33 bytes)
Witness 2: 03fbbdb3b3fc3abbbd983b20a557445fb041d6f21cc5977d2121971cb1ce529897
Locktime: 8c000000 (block 140)

Примечание. все значения с прямым порядком байтов. Вот описание всех полей:

Создать необработанную транзакцию

Создадим транзакцию с нуля! Давайте воспользуемся выходом 1 из транзакции выше:

$ bitcoin-cli -regtest listunspent
[
  {
    "txid": "375e1622b2690e395df21b33192bad06d2706c139692d43ea84d38df3d183313",
    "vout": 0,
    "address": "2ND179ug8wYvtH5GENkcMEUyXnqhNh7BgkB",
    "account": "test",
    "redeemScript": "0014b93f973eb2bf0b614bddc0f47286788c98c535b4",
    "scriptPubKey": "a914d8b6fcc85a383261df05423ddf068a8987bf028787",
    "amount": 10.00000000,
    "confirmations": 1,
    "spendable": true,
    "solvable": true,
    "safe": true
  },
...

ScriptSig

Обратите внимание, что формат scriptPubkey - это P2SH:

OP_HASH160 0x14 <script hash> OP_EQUAL

Чтобы использовать этот вывод, мы должны предоставить скрипт, который хеширует значение в <script hash>, чтобы OP_EQUAL успешно. Наш scriptSig должен иметь вид:

<0 0x14 <20-byte-key-hash>>

Но поскольку это транзакция-свидетель, часть транзакции-свидетеля также включает: <signature> <pubkey>, который будет оцениваться с использованием <signature> <pubkey> CHECKSIG.

Чтобы получить 20-byte-key-hash, нам нужно знать наш открытый ключ. Поскольку мне принадлежит этот адрес, я могу получить открытый ключ для своего адреса:

$ bitcoin-cli -regtest validateaddress 2ND179ug8wYvtH5GENkcMEUyXnqhNh7BgkB
{
  ...
    "pubkey": "0223bec70d670d29a30d9bcee197910e37cf2a10f0dc3c5ac44d865aec0d7052fb",
    ...
"embedded": {
    ...
    "witness_program": "b93f973eb2bf0b614bddc0f47286788c98c535b4"
    ...
}
Or you can calculate it manually using openssl
$ printf "0223bec70d670d29a30d9bcee197910e37cf2a10f0dc3c5ac44d865aec0d7052fb" | xxd -r -p | openssl sha256
(stdin)= cb84d0fe1066b24f7af055867a5e910577511ce03ebe9bf3b42d4810f437da03
$ printf "cb84d0fe1066b24f7af055867a5e910577511ce03ebe9bf3b42d4810f437da03" | xxd -r -p | openssl ripemd160
(stdin)= b93f973eb2bf0b614bddc0f47286788c98c535b4

Примечания:

  1. <ef> и <0> обозначают тестовую сеть и сжатый ключ, поэтому они удаляются.

Обратите внимание, что окончательный хэш ключа соответствует redeemScript в выходных данных выше. Наша подпись сценария становится:

0014b93f973eb2bf0b614bddc0f47286788c98c535b4

Выходы

Отправим 1 BTC на адрес:

2N8bXfrWTzqZoV89dosge2JxvE38VnHurqD

1 BTC = 100,000,000 satoshi поэтому Выходное значение 1: 00e1f50500000000 (помните, с порядком байтов).

Мы можем получить хеш скрипта из адреса, расшифровав его и удалив префикс тестовой сети 0xc4:

$ printf "2N8bXfrWTzqZoV89dosge2JxvE38VnHurqD" | base58 -dc | xxd -p
c4a860f76561c85551594c18eecceffaee8c4822d7

Помните, что это сценарий OP_HASH160 0x14 <script hash> OP_EQUAL, а c4 - это просто префикс адреса, который нам нужно удалить, поэтому наш сценарий открытого ключа вывода 1 становится: a914a860f76561c85551594c18eecceffaee8c4822d787.

Мы сделаем то же самое для вывода 2, который представляет наше 9 BTC изменение (возврат к исходному адресу) за вычетом 0.0001 BTC комиссии за транзакцию. Значение выхода 2: F0C1A43500000000 (899990000 сатоши). Сценарий открытого ключа вывода 2: a914d8b6fcc85a383261df05423ddf068a8987bf028787.

Подписи и свидетели

Теперь наша подпись и открытый ключ. У нас уже есть открытый ключ из прошлого:

0223bec70d670d29a30d9bcee197910e37cf2a10f0dc3c5ac44d865aec0d7052fb

Чтобы подписать это, мы сначала сериализуем его, но без Flag и scriptSig становится 00:

Version: 02000000
Flag:
Input Count: 01
Input 1 Previous Output Hash: 1333183ddf384da83ed49296136c70d206ad2b19331bf25d390e69b222165e37
Input 1 Previous Output Index: 00000000
Input 1 script length: 00 (empty for now)
Input 1 scriptSig: 
Input 1 sequence: feffffff
Output Count: 02
Output 1 Value: 00e1f50500000000 (100M satoshis / 1 BTC)
Output 1 public key script length: 0x17 (23 bytes)
Output 1 public key script: a914a860f76561c85551594c18eecceffaee8c4822d787
Output 2 Value: F0C1A43500000000 (899990000 sats / 8.9999 BTC)
Output 2 public key script length: 0x17 (23 bytes)
Output 2 public key script: a914d8b6fcc85a383261df05423ddf068a8987bf028787
Witness Count:
Witness 1 length:
Witness 1: 
Witness 2 length:
Witness 2: 
Locktime: 8c000000 (block 140)

После сериализации это становится:

02000000011333183ddf384da83ed49296136c70d206ad2b19331bf25d390e69b222165e370000000000feffffff0200e1f5050000000017a914a860f76561c85551594c18eecceffaee8c4822d787f0c1a4350000000017a914d8b6fcc85a383261df05423ddf068a8987bf02878700000000

Для подписи мы будем использовать вызов RPC signrawtransaction ядра биткойна, который создаст scriptSig для нашего ввода, а также Свидетели и заполнит Флаг .

$ bitcoin-cli -regtest signrawtransaction 02000000011333183ddf384da83ed49296136c70d206ad2b19331bf25d390e69b222165e370000000000feffffff0200e1f5050000000017a914a860f76561c85551594c18eecceffaee8c4822d787F0C1A4350000000017a914d8b6fcc85a383261df05423ddf068a8987bf0287878c000000
{
  "hex": "020000000001011333183ddf384da83ed49296136c70d206ad2b19331bf25d390e69b222165e370000000017160014b93f973eb2bf0b614bddc0f47286788c98c535b4feffffff0200e1f5050000000017a914a860f76561c85551594c18eecceffaee8c4822d787f0c1a4350000000017a914d8b6fcc85a383261df05423ddf068a8987bf028787024730440220434caf5bb442cb6a251e8bce0ec493f9a1a9c4423bcfc029e542b0e8a89d1b3f022011090d4e98f79c62b188245a4aa4eb77e912bfd57e0a9b9a1c5e65f2b39f3ab401210223bec70d670d29a30d9bcee197910e37cf2a10f0dc3c5ac44d865aec0d7052fb8c000000",
  "complete": true
}

Наконец, наша подписанная транзакция выглядит так:

Version: 02000000
Flag: 0001 (indicates segwit)
Input Count: 01
Input 1 Previous Output Hash: 1333183ddf384da83ed49296136c70d206ad2b19331bf25d390e69b222165e37
Input 1 Previous Output Index: 00000000
Input 1 script length: 0x17 (23 bytes)
Input 1 scriptSig: 160014b93f973eb2bf0b614bddc0f47286788c98c535b4
Input 1 sequence: feffffff
Output Count: 02
Output 1 Value: 00e1f50500000000 (100M satoshis / 1 BTC)
Output 1 public key script length: 0x17 (23 bytes)
Output 1 public key script: a914a860f76561c85551594c18eecceffaee8c4822d787
Output 2 Value: F0C1A43500000000 (899990000 sats / 8.9999 BTC)
Output 2 public key script length: 0x17 (23 bytes)
Output 2 public key script: a914d8b6fcc85a383261df05423ddf068a8987bf028787
Witness Count: 02
Witness 1 length: 0x47 (71 bytes)
Witness 1: 30440220434caf5bb442cb6a251e8bce0ec493f9a1a9c4423bcfc029e542b0e8a89d1b3f022011090d4e98f79c62b188245a4aa4eb77e912bfd57e0a9b9a1c5e65f2b39f3ab401
Witness 2 length: 0x21 (33 bytes)
Witness 2: 0223bec70d670d29a30d9bcee197910e37cf2a10f0dc3c5ac44d865aec0d7052fb
Locktime: 8c000000 (block 140)

Если вам понравилась статья, ознакомьтесь с моим курсом Как стать программистом Биткойн + Блокчейн.

Также прочтите

Получайте лучшие предложения по программному обеспечению прямо в свой почтовый ящик