How to Create a Raw Bitcoin Transaction — Step by Step

Jordan Baczuk
Coinmonks
Published in
5 min readAug 14, 2018

--

bitcoinchaser.com

Introduction

What makes up a bitcoin transaction? Well, there is more than one kind of bitcoin transaction, and consequently, there are multiple types of addresses to which Bitcoin can be sent (to the same person’s key pair).

The current default address type on bitcoin-core is a P2SH-P2WPKH which is a Pay-to-Witness-Public-Key-Hash wrapped in a Pay-to-Script-Hash. For more info, see this previous article: How to Generate a Bitcoin Address — Step by Step.

Learn more and join people in 22 countries around the world in my course on how to Become a Bitcoin + Blockchain Programmer.

Discover and review best Bitcoin products

Transaction Format

Let’s look at a transaction from my private bitcoin network:

0200000000010111b6e0460bb810b05744f8d38262f95fbab02b168b070598a6f31fad438fced4000000001716001427c106013c0042da165c082b3870c31fb3ab4683feffffff0200ca9a3b0000000017a914d8b6fcc85a383261df05423ddf068a8987bf0287873067a3fa0100000017a914d5df0b9ca6c0e1ba60a9ff29359d2600d9c6659d870247304402203b85cb05b43cc68df72e2e54c6cb508aa324a5de0c53f1bbfe997cbd7509774d022041e1b1823bdaddcd6581d7cde6e6a4c4dbef483e42e59e04dbacbaf537c3e3e8012103fbbdb3b3fc3abbbd983b20a557445fb041d6f21cc5977d2121971cb1ce5298978c000000

It’s obviously self-explanatory, got it now?

If you’re still wondering, let’s break it down (from left to right):

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)

Note: all values are little endian. Here is a description of all of the fields:

Transaction Properties

Create a raw transaction

Lets create a transaction from scratch! Let’s use Output 1 from the transaction above:

$ 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

Notice the format of the scriptPubkey is a P2SH :

OP_HASH160 0x14 <script hash> OP_EQUAL

In order to spend this output, we must provide the script that hashes to the value in <script hash> so the OP_EQUAL succeeds. Our scriptSig needs to take the form:

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

But, since this is a witness transaction, the witness part of the transaction also includes:<signature> <pubkey> , which will be evaluated using <signature> <pubkey> CHECKSIG .

To get the 20-byte-key-hash we need to know our public key. Because I own this address, I can get the public key for my address:

$ 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

Notes:

  1. <ef> and <0> indicate testnet and a compressed key, so they are removed.

Notice the final key hash matches the redeemScript in the output above. Our script sig becomes:

0014b93f973eb2bf0b614bddc0f47286788c98c535b4

Outputs

Let’s send 1 BTC to address:

2N8bXfrWTzqZoV89dosge2JxvE38VnHurqD

1 BTC = 100,000,000 satoshi so Output 1 Value: 00e1f50500000000 (remember, little endian).

We can get the script hash from the address by decoding it and removing the testnet prefix 0xc4:

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

Remember the script is OP_HASH160 0x14 <script hash> OP_EQUAL , and c4 is just an address prefix we need to remove, so our Output 1 public key script becomes: a914a860f76561c85551594c18eecceffaee8c4822d787 .

We’ll do the same for output 2, which represents our 9 BTCchange (back to the original address) minus a 0.0001 BTC transaction fee. Output 2 Value: F0C1A43500000000 (899990000 satoshi). The Output 2 public key script is a914d8b6fcc85a383261df05423ddf068a8987bf028787 .

Signatures & Witnesses

Now for our signature and public key. We already have our public key from before:

0223bec70d670d29a30d9bcee197910e37cf2a10f0dc3c5ac44d865aec0d7052fb

To sign this, we serialize it first, but without the Flag and the scriptSig becomes 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)

Serialized, this becomes:

02000000011333183ddf384da83ed49296136c70d206ad2b19331bf25d390e69b222165e370000000000feffffff0200e1f5050000000017a914a860f76561c85551594c18eecceffaee8c4822d787f0c1a4350000000017a914d8b6fcc85a383261df05423ddf068a8987bf02878700000000

To sign, we will use the Bitcoin-core RPC call signrawtransaction , which will create the scriptSig for our input as well as the Witnesses and populate the Flag.

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

Finally, our signed transaction looks like this:

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)

If you liked the article, check out my course on how to Become a Bitcoin + Blockchain Programmer.

Join Coinmonks Telegram Channel and Youtube Channel get daily Crypto News

Also, Read

--

--