Parts
- Description
- Assets
- Notes
- Recipe
- Example
Description
This recipe describes a method of creating and signing a standard Bitcoin transaction with at least one input and at least one output.
This recipe was written for Edgecase Bitcoin Storage Toolset version 2. It includes links to the specific assets that it uses.
Each input is an "unspent output" that is stored at a particular address. When the transaction is mined, this unspent output is "spent". Each output of the transaction is a new "unspent output".
Various combinations of inputs and outputs are possible. For example, a transaction can have 3 inputs and 2 outputs.
Assets
Asset: A library of functions for handling standard Bitcoin data types.
bitcoin_functions_2.py [paywalled]
Asset: An implementation of RIPEMD-160, written by Björn Edström.
bjorn_edstrom_ripemd160.py [paywalled]
Asset: A script that creates and signs a standard Bitcoin transaction with at least one input and at least one output.
create_transaction_3.py [paywalled]
Asset: A Python implementation of ECDSA cryptography, written by Peter Pearson.
ecdsa-0.10.tar.gz [paywalled]
Asset: A Python implementation of SHA256.
pypy_sha256.py [paywalled]
Asset: A library of classes for standard Bitcoin transactions.
transaction_3.py [paywalled]
Notes
Working definition of a standard transaction:
- It has at least one input and at least one output.
- All input and output addresses are Pay-To-Public-Key-Hash (P2PKH).
- All input scriptSigs contain uncompressed public keys.
Working definition of a standard address:
- An uncompressed single-signature Pay-To-Public-Key-Hash (P2PKH) address.
Standard addresses start with the character '1'.
The code used in this recipe only supports transactions with standard inputs and standard outputs. A standard input spends bitcoin from a standard address. A standard output sends bitcoin to a standard address.
Previous version of this recipe:
Recipe for creating and signing a standard Bitcoin transaction
Several points concerning Bitcoin transactions:
- New transactions spend unspent-outputs-of-previous-transactions.
- The bitcoin balance of an address is the sum of the unspent outputs sent by previous transactions to this address.
- To spend bitcoin from an address, the bitcoin amount must be constructed from complete unspent outputs. Any change can be sent in a new unspent output back to the original address or another that you control. Unspent outputs cannot be broken into smaller unspent outputs prior to spending - new unspent outputs (larger or smaller) must be created by a new transaction.
- A transaction fee is not a strict requirement, but in practice your transaction is unlikely to be mined without one.
- The transaction will be signed with the private key of each source address. Each signature will be stored with the relevant input in the transaction.
Recipe
Definitions:
- Source address: The address that currently contains some bitcoin that you want to transfer in this transaction.
- Destination address: The address to which some bitcoin will be transferred by this transaction.
- Previous output hash: Big-endian 32-byte double-SHA256 hash of a previous transaction.
- Txid: "transaction id". The little-endian form of the previous output hash.
- Previous output index: The index of an unspent output in the onchain transaction that created it. This index is implicit and starts at zero, and can be found by examining the list of outputs in the transaction, and finding the position of the specific unspent output in question.
Initial conditions:
- You must have Python 2.7.x installed on your computer. The code used in this recipe has been run in Python 2.7.5 on CentOS 7.6 and in Python 2.7.13 on Mac OS X 10.6.8. It should run successfully in Python 2.7.x.
- For each input, you will need to generate 32 bytes of entropy. The transaction will be signed once using each input and each signature requires 32 bytes of entropy. The following article describes one way to generate this entropy: Recipe for generating entropy bytes using dice #2. Every ECDSA signature you ever make should use a different random 32-byte value.
Notes on hex values:
- All byte sequences are written in hex when supplied as input or printed as output.
- 1 byte is written as 2 hex characters. A 32-byte sequence is therefore 64 characters in hex.
- Hex characters consist of the ten digit characters "0123456789" and the lower-case alphabetical characters "abcdef".
1) Source details.
For each input, gather the following pieces of information:
- Txid: The txid of the previous transaction that transferred the unspent output to the source address.
- Previous output index: The index of this unspent output in the previous transaction.
- Private key: The 32-byte private key of the source address.
- Input amount: The amount contained within the unspent output. This can be a bitcoin value or a satoshi value.
- Random value: A 32-byte random value.
2) Destination details.
Choose the following pieces of information:
- Destination addresses, and the amount to be sent to each one.
- Change address. If there is a difference between the total input value and the total output value, this difference will be sent to the change address. The transaction fee will be subtracted from the amount assigned to the change address.
- Fee or fee rate. A fee value is in satoshi and a fee_rate value is in satoshi / byte. Look up the range of fee rates for transactions that are currently being mined.
3) Create a work directory.
4) Browse to the Assets part of this article and download all the linked assets. List of assets:
- bitcoin_functions_2.py
- bjorn_edstrom_ripemd160.py
- create_transaction_3.py
- ecdsa-0.10.tar.gz
- pypy_sha256.py
- transaction_3.py
5) Move these assets into the work directory.
6) Unpack the zipped tape archive file ecdsa-0.10.tar.gz. This can be done by opening a terminal, changing directory to the work directory, and running the following command:
tar -zxvf ecdsa-0.10.tar.gz
This unpacking should produce a new directory named "ecdsa-0.10" in the work directory. The directory "ecdsa-0.10" should contain a directory named "ecdsa". Copy the "ecdsa" directory into the work directory.
7) Open the file create_transaction_3.py in a text editor. Scroll to lines 44-86, which should be the section of text that lies between
##### START CONTROLS
and
##### END CONTROLS
Note: In create_transaction_3.py, all control values are strings (i.e. are contained within quotation marks).
8) Set the list variable
random_values
to contain the 32-byte random values, one for each input. The first random value will be used to make the first input's signature, the second will be used to make second's signature, and so on.9) Set the variable
random_value_type
to
"hex_bytes"
. 10) The variable
input_data
is a list that contains dictionaries. Each dictionary contains the data for one input. For each input dictionary:
- Set the value of the
"txid"
key to be the txid. - Set the value of the
"previous_output_index"
key to be the previous output index. - Set the value of the
"private_key_hex"
key to be the private key. - If the input amount is in satoshi, set the value of the
"satoshi_amount"
key to be the input amount. - If the input amount is in bitcoin, set the value of the
"bitcoin_amount"
key to be the input amount. Note: If both of the
"satoshi_amount"
and
"bitcoin_amount"
keys are supplied, then
"bitcoin_amount"
will take precedence. You can comment out the unused variable of the pair by placing a number sign ('#') at the start of the relevant line.11) The variable
output_data
is a list that contains dictionaries. Each dictionary contains the data for one output. For each output:
- Set the value of the
"address"
key to be the output address.- If the output amount is in satoshi, set the value of the
"satoshi_amount"
key to be the output amount.- If the output amount is in bitcoin, set the value of the
"bitcoin_amount"
key to be the output amount.Note: If both of the
"satoshi_amount"
and
"bitcoin_amount"
keys are set, then
"bitcoin_amount"
will take precedence. You can comment out the unused variable of the pair by placing a number sign ('#') at the start of the relevant line. 12) Set the variable
change_address
to be the change address.13) Set the fee or fee rate.
If you have chosen to set the fee as an absolute number of satoshi, set the variable
fee
to be the fee amount and set the variable
fee_type
to be
"fee"
. The fee must be an integer e.g.
"225"
. Otherwise, if you have chosen to set the fee as a fee rate (in satoshi / byte), set the variable
fee_rate
to be the fee rate and set the variable
fee_type
to be
"fee_rate"
. The fee_rate must be an integer e.g.
"1"
or a float e.g.
"1.2"
. 14) Open a terminal and change directory to the work directory.
15) Run the following command:
python create_transaction_3.py
At the end, the output will contain the signed transaction as a hex byte sequence without spaces.
Examples
I'm going to replicate Transactions 4 and 5 from Bitcoin transaction test set. Transaction 4 has 1 input and 2 outputs. Transaction 5 has 2 inputs and 1 output.
Machine details:
- Windows 10
- Windows Subsystem for Linux (WSL): Ubuntu 16.04
- I'm working in the WSL Ubuntu terminal.
I've created a work directory (named "work"), downloaded the assets, and installed them in the work directory.
Transaction 4:
I'll deliberately leave some value unallocated. This value will be sent to the change address. As long as the correct amount is assigned to the non-change address, the result will be as expected.
Source details:
- Input 1:
-- Txid:
1b1ad779f50b07aac0048471844c0637100561b179457ddd433f1c05adf24a19
-- Previous output index:
3
-- Private key:
7a0d11f6015f941ea486922e45310535c5b71c59d8489447648eebdb6a39e2a8
-- Input amount:
0.004 bitcoin
-- Random value:
84425ee562f20d7493420c97eea153d37891eb63ce51fa24f51bfc7646353d32
Destination details:
- Addresses and amounts:
-- 1PFw45xp5JUcLZfDQnMpto6yJpcjRLqrJ8: 0.002 bitcoin
-- 19u4WSjpp19yoAK9kdRyY9HJ7ad2S8s1E4: 0.001 bitcoin
- Change address:
19u4WSjpp19yoAK9kdRyY9HJ7ad2S8s1E4
- Fee:
386 satoshi
Expected result: Signed version of Transaction 4:
0100000001194af2ad051c3f43dd7d4579b161051037064c84718404c0aa070bf579d71a1b030000008a47304402204f38e1194a0f71f4cb03b1a8644dae69c543cab339d19f0412511bed0868904a02201a9356663d0ad3527b5633ced4cbc469f98bccb0940f2583c7c6c0c0868973a3014104c0128d7e4cbfef4e1bae30788b7bd7a4b974027eea5d83c07ac041f194707e8bba70a162c557cdbcb89682a5a310a2d5a722b2d58d18920a00b6b4c7024ce966ffffffff02400d0300000000001976a914f425b648af85989c1387d532393938fcb7d7bcbb88acbe0b0300000000001976a91461999077782b7298b813d83459a9c944da6460bd88ac00000000
Note: The actual amount sent to the output 2 address in the transaction is 199614 satoshi.
Plug these values into the controls in create_transaction_3.py, as shown below:
##### START CONTROLS | |
# Note: Hex characters in input variable values must be lowercase. | |
random_values = [ | |
"84425ee562f20d7493420c97eea153d37891eb63ce51fa24f51bfc7646353d32", | |
] | |
# random_value must be between 1 and 32 bytes. If random_value_type is "raw_bytes", then random_value must be between 1 and 32 ASCII characters. If random_value_type is "hex_bytes", then random_value must be an even number of hex characters and between 2 and 64 hex characters (1 byte is represented by 2 hex characters). | |
# Note: Every ECDSA signature (one for each input in a transaction) requires new random entropy. | |
# random_value_type options: ["raw_bytes", "hex_bytes"] | |
random_value_type = "hex_bytes" | |
input_data = [ | |
{ | |
"txid": "1b1ad779f50b07aac0048471844c0637100561b179457ddd433f1c05adf24a19", | |
"previous_output_index": "3", | |
"private_key_hex": "7a0d11f6015f941ea486922e45310535c5b71c59d8489447648eebdb6a39e2a8", | |
#"satoshi_amount": "", | |
"bitcoin_amount": "0.004", | |
}, | |
] | |
output_data = [ | |
{ | |
"address": "1PFw45xp5JUcLZfDQnMpto6yJpcjRLqrJ8", | |
#"satoshi_amount": "", | |
"bitcoin_amount": "0.002", | |
}, | |
{ | |
"address": "19u4WSjpp19yoAK9kdRyY9HJ7ad2S8s1E4", | |
#"satoshi_amount": "", | |
"bitcoin_amount": "0.001", | |
}, | |
] | |
# note: all inputs and outputs are assumed to be Pay-To-Public-Key-Hash (P2PKH). | |
change_address = "19u4WSjpp19yoAK9kdRyY9HJ7ad2S8s1E4" | |
# note: the fee will be subtracted from the amount that is being sent to the change address. | |
fee = "386" # satoshi | |
fee_rate = "" # satoshi / byte | |
# fee_type options: ["fee", "fee_rate"] | |
fee_type = "fee" | |
##### END CONTROLS |
Run the script.
stjohn@judgement:work$ python create_transaction_3.py
### START CREATION OF BITCOIN TRANSACTION
- Fee type: fee
- Fee: 386 (satoshi)
- Number of inputs (i.e. as-yet-unspent outputs): 1
- Number of outputs: 2
- Change address: 19u4WSjpp19yoAK9kdRyY9HJ7ad2S8s1E4
- Amount to be sent to the change address: 0.001
- Input addresses, with total-value-to-be-sent:
-- 17pNyD9ur28aBgPhHtAFi6fAyrvgshp5yn: 0.00400000
- Output addresses, with total-value-to-be-received:
-- 19u4WSjpp19yoAK9kdRyY9HJ7ad2S8s1E4: 0.00100000
-- 1PFw45xp5JUcLZfDQnMpto6yJpcjRLqrJ8: 0.00200000
- Total value of all inputs: 0.00400000
- Total value of all outputs: 0.00300000
- Total value of all inputs is greater than total value of all outputs.
-- Some input value has not been assigned to an output.
-- Extra value: 0.00100000
-- This extra value will be sent to the change address.
-- Change address: 19u4WSjpp19yoAK9kdRyY9HJ7ad2S8s1E4
-- New amount to be sent to change address: 0.00200000
- Estimated transaction size: 257 bytes
- Final fee: 386 (satoshi)
- Final fee rate (using estimated transaction size): 1.5019 (satoshi per byte)
- Fee subtracted from amount-to-be-sent-to-change-address.
- New amount to be sent to change address: 199614 (satoshi)
- Size of signed transaction: 257 bytes
- (signed_tx_size - estimated_tx_size): 0 bytes
- Fee rate in signed transaction: 1.502 (satoshi / byte)
Input 0:
Input: {40 bytes unsigned, 66 bytes signable, 179 bytes signed}
- [data] previous_output_hash: 194af2ad051c3f43dd7d4579b161051037064c84718404c0aa070bf579d71a1b (32 bytes)
- [data] previous_output_index: 03000000 (4 bytes)
- [signed form] script_length: 8a (1 bytes)
- [signed form] scriptSig: 47304402204f38e1194a0f71f4cb03b1a8644dae69c543cab339d19f0412511bed0868904a02201a9356663d0ad3527b5633ced4cbc469f98bccb0940f2583c7c6c0c0868973a3014104c0128d7e4cbfef4e1bae30788b7bd7a4b974027eea5d83c07ac041f194707e8bba70a162c557cdbcb89682a5a310a2d5a722b2d58d18920a00b6b4c7024ce966 (138 bytes)
- [data] sequence: ffffffff (4 bytes)
- [used for signing] private_key_hex: 7a0d11f6015f941ea486922e45310535c5b71c59d8489447648eebdb6a39e2a8 (32 bytes)
- [source, goes into scriptSig] public_key_hex: 04c0128d7e4cbfef4e1bae30788b7bd7a4b974027eea5d83c07ac041f194707e8bba70a162c557cdbcb89682a5a310a2d5a722b2d58d18920a00b6b4c7024ce966 (65 bytes)
- [signable form] script_length_scriptPubKey: 19 (1 bytes)
- [signable form] scriptPubKey: 76a9144ac6a4d0ee2aa064974bf6e571f6f700b7f67ce688ac (25 bytes)
- [more info] address: 17pNyD9ur28aBgPhHtAFi6fAyrvgshp5yn
- [more info] previous_output_index_int: 3
- [more info] txid: 1b1ad779f50b07aac0048471844c0637100561b179457ddd433f1c05adf24a19
Output 0:
Output: {34 bytes}
- [data] value: 400d030000000000 (8 bytes)
- [data] script_length: 19 (1 bytes)
- [data] scriptPubKey: 76a914f425b648af85989c1387d532393938fcb7d7bcbb88ac (25 bytes)
- [more info] address: 1PFw45xp5JUcLZfDQnMpto6yJpcjRLqrJ8
- [more info] bitcoin_amount: 0.002
- [more info] satoshi_amount: 200000
- [more info] public_key_hash_hex: f425b648af85989c1387d532393938fcb7d7bcbb
Output 1:
Output: {34 bytes}
- [data] value: be0b030000000000 (8 bytes)
- [data] script_length: 19 (1 bytes)
- [data] scriptPubKey: 76a91461999077782b7298b813d83459a9c944da6460bd88ac (25 bytes)
- [more info] address: 19u4WSjpp19yoAK9kdRyY9HJ7ad2S8s1E4
- [more info] bitcoin_amount: 0.00199614
- [more info] satoshi_amount: 199614
- [more info] public_key_hash_hex: 61999077782b7298b813d83459a9c944da6460bd
Transaction (unsigned form): {118 bytes}
- version: 01000000 (4 bytes)
- input_count: 01 (1 bytes)
- Input 0: {40 bytes}
-- previous_output_hash: 194af2ad051c3f43dd7d4579b161051037064c84718404c0aa070bf579d71a1b (32 bytes)
-- previous_output_index: 03000000 (4 bytes)
-- script_length: [none] (0 bytes)
-- scriptSig: [none] (0 bytes)
-- sequence: ffffffff (4 bytes)
- output_count: 02 (1 bytes)
- Output 0: {34 bytes}
-- value: 400d030000000000 (8 bytes)
-- script_length: 19 (1 bytes)
-- scriptPubKey: 76a914f425b648af85989c1387d532393938fcb7d7bcbb88ac (25 bytes)
- Output 1: {34 bytes}
-- value: be0b030000000000 (8 bytes)
-- script_length: 19 (1 bytes)
-- scriptPubKey: 76a91461999077782b7298b813d83459a9c944da6460bd88ac (25 bytes)
- block_lock_time: 00000000 (4 bytes)
Transaction (signable form 0): {148 bytes}
- version: 01000000 (4 bytes)
- input_count: 01 (1 bytes)
- Input 0 [to be used to sign this signable form]: {66 bytes}
-- previous_output_hash: 194af2ad051c3f43dd7d4579b161051037064c84718404c0aa070bf579d71a1b (32 bytes)
-- previous_output_index: 03000000 (4 bytes)
-- script_length_scriptPubKey: 19 (1 bytes)
-- scriptPubKey: 76a9144ac6a4d0ee2aa064974bf6e571f6f700b7f67ce688ac (25 bytes)
-- sequence: ffffffff (4 bytes)
- output_count: 02 (1 bytes)
- Output 0: {34 bytes}
-- value: 400d030000000000 (8 bytes)
-- script_length: 19 (1 bytes)
-- scriptPubKey: 76a914f425b648af85989c1387d532393938fcb7d7bcbb88ac (25 bytes)
- Output 1: {34 bytes}
-- value: be0b030000000000 (8 bytes)
-- script_length: 19 (1 bytes)
-- scriptPubKey: 76a91461999077782b7298b813d83459a9c944da6460bd88ac (25 bytes)
- block_lock_time: 00000000 (4 bytes)
- hash_type_4_byte: 01000000 (4 bytes)
Transaction (signed form): {257 bytes}
- version: 01000000 (4 bytes)
- input_count: 01 (1 bytes)
- Input 0: {179 bytes}
-- previous_output_hash: 194af2ad051c3f43dd7d4579b161051037064c84718404c0aa070bf579d71a1b (32 bytes)
-- previous_output_index: 03000000 (4 bytes)
-- script_length: 8a (1 bytes)
-- scriptSig: 47304402204f38e1194a0f71f4cb03b1a8644dae69c543cab339d19f0412511bed0868904a02201a9356663d0ad3527b5633ced4cbc469f98bccb0940f2583c7c6c0c0868973a3014104c0128d7e4cbfef4e1bae30788b7bd7a4b974027eea5d83c07ac041f194707e8bba70a162c557cdbcb89682a5a310a2d5a722b2d58d18920a00b6b4c7024ce966 (138 bytes)
-- sequence: ffffffff (4 bytes)
- output_count: 02 (1 bytes)
- Output 0: {34 bytes}
-- value: 400d030000000000 (8 bytes)
-- script_length: 19 (1 bytes)
-- scriptPubKey: 76a914f425b648af85989c1387d532393938fcb7d7bcbb88ac (25 bytes)
- Output 1: {34 bytes}
-- value: be0b030000000000 (8 bytes)
-- script_length: 19 (1 bytes)
-- scriptPubKey: 76a91461999077782b7298b813d83459a9c944da6460bd88ac (25 bytes)
- block_lock_time: 00000000 (4 bytes)
Signed transaction:
0100000001194af2ad051c3f43dd7d4579b161051037064c84718404c0aa070bf579d71a1b030000008a47304402204f38e1194a0f71f4cb03b1a8644dae69c543cab339d19f0412511bed0868904a02201a9356663d0ad3527b5633ced4cbc469f98bccb0940f2583c7c6c0c0868973a3014104c0128d7e4cbfef4e1bae30788b7bd7a4b974027eea5d83c07ac041f194707e8bba70a162c557cdbcb89682a5a310a2d5a722b2d58d18920a00b6b4c7024ce966ffffffff02400d0300000000001976a914f425b648af85989c1387d532393938fcb7d7bcbb88acbe0b0300000000001976a91461999077782b7298b813d83459a9c944da6460bd88ac00000000
### END CREATION OF BITCOIN TRANSACTION
Compare the result with the expected result.
stjohn@judgement:work$ expected=0100000001194af2ad051c3f43dd7d4579b161051037064c84718404c0aa070bf579d71a1b030000008a47304402204f38e1194a0f71f4cb03b1a8644dae69c543cab339d19f0412511bed0868904a02201a9356663d0ad3527b5633ced4cbc469f98bccb0940f2583c7c6c0c0868973a3014104c0128d7e4cbfef4e1bae30788b7bd7a4b974027eea5d83c07ac041f194707e8bba70a162c557cdbcb89682a5a310a2d5a722b2d58d18920a00b6b4c7024ce966ffffffff02400d0300000000001976a914f425b648af85989c1387d532393938fcb7d7bcbb88acbe0b0300000000001976a91461999077782b7298b813d83459a9c944da6460bd88ac00000000
stjohn@judgement:work$ result=0100000001194af2ad051c3f43dd7d4579b161051037064c84718404c0aa070bf579d71a1b030000008a47304402204f38e1194a0f71f4cb03b1a8644dae69c543cab339d19f0412511bed0868904a02201a9356663d0ad3527b5633ced4cbc469f98bccb0940f2583c7c6c0c0868973a3014104c0128d7e4cbfef4e1bae30788b7bd7a4b974027eea5d83c07ac041f194707e8bba70a162c557cdbcb89682a5a310a2d5a722b2d58d18920a00b6b4c7024ce966ffffffff02400d0300000000001976a914f425b648af85989c1387d532393938fcb7d7bcbb88acbe0b0300000000001976a91461999077782b7298b813d83459a9c944da6460bd88ac00000000
stjohn@judgement:work$ [[ "$expected" = "$result" ]] && echo equal || echo not-equal
equal
Good. The new transaction matches the original one.
Transaction 5:
This time, I assign exactly the total available amount to the single output address (which is also the change address). The specified fee amount will be subtracted from this total amount.
Source details:
- Input 1:
-- Txid:
8f6318124bdd66f4643ccbfcbcb0a802924833505c015929dc7b1cab2ca02826
-- Previous output index:
0
-- Private key:
cbac84458fcfbb39f87fca7ab9a9ef2f76812a6f999a75dfa25dbcbb0ee3eb6f
-- Input amount:
0.002 bitcoin
-- Random value:
5ab5bbe6fdc861a461a6721b2953d32be23c233e5ad5dc08d7c13daa95adbc17
- Input 2:
-- Txid:
8f6318124bdd66f4643ccbfcbcb0a802924833505c015929dc7b1cab2ca02826
-- Previous output index:
1
-- Private key:
7d37c1a74d3b87d3994ac6db65b4f298f64a8ed6144edfdb2cacea70cf3070af
-- Input amount:
0.00199614 bitcoin
-- Random value:
75fc65686a47326556735be91491a06f380a9db682fe9d50f82ad8d8d8849c2f
Destination details:
- Addresses and amounts:
-- 17PZ6uyL59vPirNqqpMnB1kjEXkU7ske7s: 0.00399614 bitcoin
- Change address:
17PZ6uyL59vPirNqqpMnB1kjEXkU7ske7s
- Fee:
443 satoshi
Expected result: Signed version of Transaction 5:
01000000022628a02cab1c7bdc2959015c5033489202a8b0bcfccb3c64f466dd4b1218638f000000008b4830450221008d4ecab2a74461cabcd3e5398ca6752594fbd758c3d10ff3a50c5bf45e460a4502206e7607d2f9ff8fa40489c041fdbbcaecfe723caabf28de9451a2be67d8705d1901410426f2ad4968ef7c5412a2cfac85c902f613b7406962477c931d25ddfb2957c494e70f832ac8dd50740c64297038c722542005b0c5191061e444c793b62d9b2aceffffffff2628a02cab1c7bdc2959015c5033489202a8b0bcfccb3c64f466dd4b1218638f010000008a4730440220184f1d7e9cfe7539cd40cae04e71dc21ce05de958620294cb2d490d45356bfc102203f4ae4afe33b93d1cc96c356735d7a4d3b90cfe62cab0d0cf71fd2f7718e99df0141043c8564e9fa9e9530699ffe7c5dd75077698ff96f3786e96bdbb210a109147cedacfdaa784eb4ba538556e8dd70455ba3627fe902f152940d70ffdd55acdb82a9ffffffff0143170600000000001976a9144614b4066faf3ef831a20186f76381c25dd6ea8288ac00000000
Plug these values into the controls in create_transaction_3.py, as shown below:
##### START CONTROLS | |
# Note: Hex characters in input variable values must be lowercase. | |
random_values = [ | |
"5ab5bbe6fdc861a461a6721b2953d32be23c233e5ad5dc08d7c13daa95adbc17", | |
"75fc65686a47326556735be91491a06f380a9db682fe9d50f82ad8d8d8849c2f", | |
] | |
# random_value must be between 1 and 32 bytes. If random_value_type is "raw_bytes", then random_value must be between 1 and 32 ASCII characters. If random_value_type is "hex_bytes", then random_value must be an even number of hex characters and between 2 and 64 hex characters (1 byte is represented by 2 hex characters). | |
# Note: Every ECDSA signature (one for each input in a transaction) requires new random entropy. | |
# random_value_type options: ["raw_bytes", "hex_bytes"] | |
random_value_type = "hex_bytes" | |
input_data = [ | |
{ | |
"txid": "8f6318124bdd66f4643ccbfcbcb0a802924833505c015929dc7b1cab2ca02826", | |
"previous_output_index": "0", | |
"private_key_hex": "cbac84458fcfbb39f87fca7ab9a9ef2f76812a6f999a75dfa25dbcbb0ee3eb6f", | |
#"satoshi_amount": "", | |
"bitcoin_amount": "0.002", | |
}, | |
{ | |
"txid": "8f6318124bdd66f4643ccbfcbcb0a802924833505c015929dc7b1cab2ca02826", | |
"previous_output_index": "1", | |
"private_key_hex": "7d37c1a74d3b87d3994ac6db65b4f298f64a8ed6144edfdb2cacea70cf3070af", | |
#"satoshi_amount": "", | |
"bitcoin_amount": "0.00199614", | |
}, | |
] | |
output_data = [ | |
{ | |
"address": "17PZ6uyL59vPirNqqpMnB1kjEXkU7ske7s", | |
#"satoshi_amount": "", | |
"bitcoin_amount": "0.00399614", | |
}, | |
] | |
# note: all inputs and outputs are assumed to be Pay-To-Public-Key-Hash (P2PKH). | |
change_address = "17PZ6uyL59vPirNqqpMnB1kjEXkU7ske7s" | |
# note: the fee will be subtracted from the amount that is being sent to the change address. | |
fee = "443" # satoshi | |
fee_rate = "" # satoshi / byte | |
# fee_type options: ["fee", "fee_rate"] | |
fee_type = "fee" | |
##### END CONTROLS |
Run the script.
stjohn@judgement:work$ python create_transaction_3.py
### START CREATION OF BITCOIN TRANSACTION
- Fee type: fee
- Fee: 443 (satoshi)
- Number of inputs (i.e. as-yet-unspent outputs): 2
- Number of outputs: 1
- Change address: 17PZ6uyL59vPirNqqpMnB1kjEXkU7ske7s
- Amount to be sent to the change address: 0.00399614
- Input addresses, with total-value-to-be-sent:
-- 19u4WSjpp19yoAK9kdRyY9HJ7ad2S8s1E4: 0.00199614
-- 1PFw45xp5JUcLZfDQnMpto6yJpcjRLqrJ8: 0.00200000
- Output addresses, with total-value-to-be-received:
-- 17PZ6uyL59vPirNqqpMnB1kjEXkU7ske7s: 0.00399614
- Total value of all inputs: 0.00399614
- Total value of all outputs: 0.00399614
- Total value of all inputs exactly matches total value of all outputs.
- Estimated transaction size: 402 bytes
- Final fee: 443 (satoshi)
- Final fee rate (using estimated transaction size): 1.1020 (satoshi per byte)
- Fee subtracted from amount-to-be-sent-to-change-address.
- New amount to be sent to change address: 399171 (satoshi)
- Size of signed transaction: 403 bytes
- (signed_tx_size - estimated_tx_size): 1 bytes
- Fee rate in signed transaction: 1.099 (satoshi / byte)
Input 0:
Input: {40 bytes unsigned, 66 bytes signable, 180 bytes signed}
- [data] previous_output_hash: 2628a02cab1c7bdc2959015c5033489202a8b0bcfccb3c64f466dd4b1218638f (32 bytes)
- [data] previous_output_index: 00000000 (4 bytes)
- [signed form] script_length: 8b (1 bytes)
- [signed form] scriptSig: 4830450221008d4ecab2a74461cabcd3e5398ca6752594fbd758c3d10ff3a50c5bf45e460a4502206e7607d2f9ff8fa40489c041fdbbcaecfe723caabf28de9451a2be67d8705d1901410426f2ad4968ef7c5412a2cfac85c902f613b7406962477c931d25ddfb2957c494e70f832ac8dd50740c64297038c722542005b0c5191061e444c793b62d9b2ace (139 bytes)
- [data] sequence: ffffffff (4 bytes)
- [used for signing] private_key_hex: cbac84458fcfbb39f87fca7ab9a9ef2f76812a6f999a75dfa25dbcbb0ee3eb6f (32 bytes)
- [source, goes into scriptSig] public_key_hex: 0426f2ad4968ef7c5412a2cfac85c902f613b7406962477c931d25ddfb2957c494e70f832ac8dd50740c64297038c722542005b0c5191061e444c793b62d9b2ace (65 bytes)
- [signable form] script_length_scriptPubKey: 19 (1 bytes)
- [signable form] scriptPubKey: 76a914f425b648af85989c1387d532393938fcb7d7bcbb88ac (25 bytes)
- [more info] address: 1PFw45xp5JUcLZfDQnMpto6yJpcjRLqrJ8
- [more info] previous_output_index_int: 0
- [more info] txid: 8f6318124bdd66f4643ccbfcbcb0a802924833505c015929dc7b1cab2ca02826
Input 1:
Input: {40 bytes unsigned, 66 bytes signable, 179 bytes signed}
- [data] previous_output_hash: 2628a02cab1c7bdc2959015c5033489202a8b0bcfccb3c64f466dd4b1218638f (32 bytes)
- [data] previous_output_index: 01000000 (4 bytes)
- [signed form] script_length: 8a (1 bytes)
- [signed form] scriptSig: 4730440220184f1d7e9cfe7539cd40cae04e71dc21ce05de958620294cb2d490d45356bfc102203f4ae4afe33b93d1cc96c356735d7a4d3b90cfe62cab0d0cf71fd2f7718e99df0141043c8564e9fa9e9530699ffe7c5dd75077698ff96f3786e96bdbb210a109147cedacfdaa784eb4ba538556e8dd70455ba3627fe902f152940d70ffdd55acdb82a9 (138 bytes)
- [data] sequence: ffffffff (4 bytes)
- [used for signing] private_key_hex: 7d37c1a74d3b87d3994ac6db65b4f298f64a8ed6144edfdb2cacea70cf3070af (32 bytes)
- [source, goes into scriptSig] public_key_hex: 043c8564e9fa9e9530699ffe7c5dd75077698ff96f3786e96bdbb210a109147cedacfdaa784eb4ba538556e8dd70455ba3627fe902f152940d70ffdd55acdb82a9 (65 bytes)
- [signable form] script_length_scriptPubKey: 19 (1 bytes)
- [signable form] scriptPubKey: 76a91461999077782b7298b813d83459a9c944da6460bd88ac (25 bytes)
- [more info] address: 19u4WSjpp19yoAK9kdRyY9HJ7ad2S8s1E4
- [more info] previous_output_index_int: 1
- [more info] txid: 8f6318124bdd66f4643ccbfcbcb0a802924833505c015929dc7b1cab2ca02826
Output 0:
Output: {34 bytes}
- [data] value: 4317060000000000 (8 bytes)
- [data] script_length: 19 (1 bytes)
- [data] scriptPubKey: 76a9144614b4066faf3ef831a20186f76381c25dd6ea8288ac (25 bytes)
- [more info] address: 17PZ6uyL59vPirNqqpMnB1kjEXkU7ske7s
- [more info] bitcoin_amount: 0.00399171
- [more info] satoshi_amount: 399171
- [more info] public_key_hash_hex: 4614b4066faf3ef831a20186f76381c25dd6ea82
Transaction (unsigned form): {124 bytes}
- version: 01000000 (4 bytes)
- input_count: 02 (1 bytes)
- Input 0: {40 bytes}
-- previous_output_hash: 2628a02cab1c7bdc2959015c5033489202a8b0bcfccb3c64f466dd4b1218638f (32 bytes)
-- previous_output_index: 00000000 (4 bytes)
-- script_length: [none] (0 bytes)
-- scriptSig: [none] (0 bytes)
-- sequence: ffffffff (4 bytes)
- Input 1: {40 bytes}
-- previous_output_hash: 2628a02cab1c7bdc2959015c5033489202a8b0bcfccb3c64f466dd4b1218638f (32 bytes)
-- previous_output_index: 01000000 (4 bytes)
-- script_length: [none] (0 bytes)
-- scriptSig: [none] (0 bytes)
-- sequence: ffffffff (4 bytes)
- output_count: 01 (1 bytes)
- Output 0: {34 bytes}
-- value: 4317060000000000 (8 bytes)
-- script_length: 19 (1 bytes)
-- scriptPubKey: 76a9144614b4066faf3ef831a20186f76381c25dd6ea8288ac (25 bytes)
- block_lock_time: 00000000 (4 bytes)
Transaction (signable form 0): {155 bytes}
- version: 01000000 (4 bytes)
- input_count: 02 (1 bytes)
- Input 0 [to be used to sign this signable form]: {66 bytes}
-- previous_output_hash: 2628a02cab1c7bdc2959015c5033489202a8b0bcfccb3c64f466dd4b1218638f (32 bytes)
-- previous_output_index: 00000000 (4 bytes)
-- script_length_scriptPubKey: 19 (1 bytes)
-- scriptPubKey: 76a914f425b648af85989c1387d532393938fcb7d7bcbb88ac (25 bytes)
-- sequence: ffffffff (4 bytes)
- Input 1: {41 bytes}
-- previous_output_hash: 2628a02cab1c7bdc2959015c5033489202a8b0bcfccb3c64f466dd4b1218638f (32 bytes)
-- previous_output_index: 01000000 (4 bytes)
-- script_length: 00 (1 bytes)
-- sequence: ffffffff (4 bytes)
- output_count: 01 (1 bytes)
- Output 0: {34 bytes}
-- value: 4317060000000000 (8 bytes)
-- script_length: 19 (1 bytes)
-- scriptPubKey: 76a9144614b4066faf3ef831a20186f76381c25dd6ea8288ac (25 bytes)
- block_lock_time: 00000000 (4 bytes)
- hash_type_4_byte: 01000000 (4 bytes)
Transaction (signable form 1): {155 bytes}
- version: 01000000 (4 bytes)
- input_count: 02 (1 bytes)
- Input 0: {41 bytes}
-- previous_output_hash: 2628a02cab1c7bdc2959015c5033489202a8b0bcfccb3c64f466dd4b1218638f (32 bytes)
-- previous_output_index: 00000000 (4 bytes)
-- script_length: 00 (1 bytes)
-- sequence: ffffffff (4 bytes)
- Input 1 [to be used to sign this signable form]: {66 bytes}
-- previous_output_hash: 2628a02cab1c7bdc2959015c5033489202a8b0bcfccb3c64f466dd4b1218638f (32 bytes)
-- previous_output_index: 01000000 (4 bytes)
-- script_length_scriptPubKey: 19 (1 bytes)
-- scriptPubKey: 76a91461999077782b7298b813d83459a9c944da6460bd88ac (25 bytes)
-- sequence: ffffffff (4 bytes)
- output_count: 01 (1 bytes)
- Output 0: {34 bytes}
-- value: 4317060000000000 (8 bytes)
-- script_length: 19 (1 bytes)
-- scriptPubKey: 76a9144614b4066faf3ef831a20186f76381c25dd6ea8288ac (25 bytes)
- block_lock_time: 00000000 (4 bytes)
- hash_type_4_byte: 01000000 (4 bytes)
Transaction (signed form): {403 bytes}
- version: 01000000 (4 bytes)
- input_count: 02 (1 bytes)
- Input 0: {180 bytes}
-- previous_output_hash: 2628a02cab1c7bdc2959015c5033489202a8b0bcfccb3c64f466dd4b1218638f (32 bytes)
-- previous_output_index: 00000000 (4 bytes)
-- script_length: 8b (1 bytes)
-- scriptSig: 4830450221008d4ecab2a74461cabcd3e5398ca6752594fbd758c3d10ff3a50c5bf45e460a4502206e7607d2f9ff8fa40489c041fdbbcaecfe723caabf28de9451a2be67d8705d1901410426f2ad4968ef7c5412a2cfac85c902f613b7406962477c931d25ddfb2957c494e70f832ac8dd50740c64297038c722542005b0c5191061e444c793b62d9b2ace (139 bytes)
-- sequence: ffffffff (4 bytes)
- Input 1: {179 bytes}
-- previous_output_hash: 2628a02cab1c7bdc2959015c5033489202a8b0bcfccb3c64f466dd4b1218638f (32 bytes)
-- previous_output_index: 01000000 (4 bytes)
-- script_length: 8a (1 bytes)
-- scriptSig: 4730440220184f1d7e9cfe7539cd40cae04e71dc21ce05de958620294cb2d490d45356bfc102203f4ae4afe33b93d1cc96c356735d7a4d3b90cfe62cab0d0cf71fd2f7718e99df0141043c8564e9fa9e9530699ffe7c5dd75077698ff96f3786e96bdbb210a109147cedacfdaa784eb4ba538556e8dd70455ba3627fe902f152940d70ffdd55acdb82a9 (138 bytes)
-- sequence: ffffffff (4 bytes)
- output_count: 01 (1 bytes)
- Output 0: {34 bytes}
-- value: 4317060000000000 (8 bytes)
-- script_length: 19 (1 bytes)
-- scriptPubKey: 76a9144614b4066faf3ef831a20186f76381c25dd6ea8288ac (25 bytes)
- block_lock_time: 00000000 (4 bytes)
Signed transaction:
01000000022628a02cab1c7bdc2959015c5033489202a8b0bcfccb3c64f466dd4b1218638f000000008b4830450221008d4ecab2a74461cabcd3e5398ca6752594fbd758c3d10ff3a50c5bf45e460a4502206e7607d2f9ff8fa40489c041fdbbcaecfe723caabf28de9451a2be67d8705d1901410426f2ad4968ef7c5412a2cfac85c902f613b7406962477c931d25ddfb2957c494e70f832ac8dd50740c64297038c722542005b0c5191061e444c793b62d9b2aceffffffff2628a02cab1c7bdc2959015c5033489202a8b0bcfccb3c64f466dd4b1218638f010000008a4730440220184f1d7e9cfe7539cd40cae04e71dc21ce05de958620294cb2d490d45356bfc102203f4ae4afe33b93d1cc96c356735d7a4d3b90cfe62cab0d0cf71fd2f7718e99df0141043c8564e9fa9e9530699ffe7c5dd75077698ff96f3786e96bdbb210a109147cedacfdaa784eb4ba538556e8dd70455ba3627fe902f152940d70ffdd55acdb82a9ffffffff0143170600000000001976a9144614b4066faf3ef831a20186f76381c25dd6ea8288ac00000000
### END CREATION OF BITCOIN TRANSACTION
Compare the result with the expected result.
stjohn@judgement:work$ expected=01000000022628a02cab1c7bdc2959015c5033489202a8b0bcfccb3c64f466dd4b1218638f000000008b4830450221008d4ecab2a74461cabcd3e5398ca6752594fbd758c3d10ff3a50c5bf45e460a4502206e7607d2f9ff8fa40489c041fdbbcaecfe723caabf28de9451a2be67d8705d1901410426f2ad4968ef7c5412a2cfac85c902f613b7406962477c931d25ddfb2957c494e70f832ac8dd50740c64297038c722542005b0c5191061e444c793b62d9b2aceffffffff2628a02cab1c7bdc2959015c5033489202a8b0bcfccb3c64f466dd4b1218638f010000008a4730440220184f1d7e9cfe7539cd40cae04e71dc21ce05de958620294cb2d490d45356bfc102203f4ae4afe33b93d1cc96c356735d7a4d3b90cfe62cab0d0cf71fd2f7718e99df0141043c8564e9fa9e9530699ffe7c5dd75077698ff96f3786e96bdbb210a109147cedacfdaa784eb4ba538556e8dd70455ba3627fe902f152940d70ffdd55acdb82a9ffffffff0143170600000000001976a9144614b4066faf3ef831a20186f76381c25dd6ea8288ac00000000
stjohn@judgement:work$ result=01000000022628a02cab1c7bdc2959015c5033489202a8b0bcfccb3c64f466dd4b1218638f000000008b4830450221008d4ecab2a74461cabcd3e5398ca6752594fbd758c3d10ff3a50c5bf45e460a4502206e7607d2f9ff8fa40489c041fdbbcaecfe723caabf28de9451a2be67d8705d1901410426f2ad4968ef7c5412a2cfac85c902f613b7406962477c931d25ddfb2957c494e70f832ac8dd50740c64297038c722542005b0c5191061e444c793b62d9b2aceffffffff2628a02cab1c7bdc2959015c5033489202a8b0bcfccb3c64f466dd4b1218638f010000008a4730440220184f1d7e9cfe7539cd40cae04e71dc21ce05de958620294cb2d490d45356bfc102203f4ae4afe33b93d1cc96c356735d7a4d3b90cfe62cab0d0cf71fd2f7718e99df0141043c8564e9fa9e9530699ffe7c5dd75077698ff96f3786e96bdbb210a109147cedacfdaa784eb4ba538556e8dd70455ba3627fe902f152940d70ffdd55acdb82a9ffffffff0143170600000000001976a9144614b4066faf3ef831a20186f76381c25dd6ea8288ac00000000
stjohn@judgement:work$ [[ "$expected" = "$result" ]] && echo equal || echo not-equal
equal
Good. The new transaction matches the original one.
Excellent. That's the end of the project.