Goal
Create and sign a Bitcoin transaction with two inputs and one output.
Contents
- Goal
- Contents
- Brief Summary
- Summary
- Changing transaction_2.py And nonstandard_transaction_2.py To Correctly Describe A Non-Signing Input
- Notes
- Financial Information For This Project
- Completion Of Further Work Outlined In Previous Projects
- Project Log
Brief Summary
I have created and signed a standard Bitcoin transaction with two inputs and one output. I uploaded it to an online service for broadcast. A little while later, it was added to the Bitcoin blockchain ("mined"). Its acceptance into the Bitcoin blockchain proves its validity.
Summary
I have created and signed a standard Bitcoin transaction with two inputs and one output. I uploaded it to an online service for broadcast. A little while later, it was added to the Bitcoin blockchain ("mined"). Its acceptance into the Bitcoin blockchain proves its validity.
My 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.
The successful mining of a one-input two-output transaction confirmed that, in a given transaction-in-signable-form prepared for signing by a particular input, all other input scriptSigs are removed and a single 0x00 byte is substituted for each of their length var_ints (indicating that these scriptSigs contain no data).
Original plan of action:
- Generate 32 bytes of entropy and create a "source" address.
- Look up current Bitcoin transaction fee rates. Choose a higher-end fee rate for use in financial calculations (in order to have slack).
- Look up current LocalBitcoins sending fee (this is deducted from the wallet total, not from the amount sent, but will be included in the financial information for this project).
- Look up current LocalBitcoins deposit fee.
- Perform a rough calculation of the maximum fee I should expect to pay for transactions. Choose an amount X to transfer to the source address that covers a) the maximum Bitcoin transaction fee total and b) the deposit fee for LocalBitcoins.
-- Update: Looking at this completed plan, I see that this will consist of: 3 transaction fees + 1 deposit fee for LocalBitcoins. Use a high upper bound of 500 bytes per transaction when estimating.
- Using LocalBitcoins, transfer X bitcoin to the source address. LocalBitcoins will construct a larger transaction that will include this transfer. This will be transaction tx_0.
- Wait for 6-block confirmation of the transaction.
- Generate 2 sets of 32 bytes of entropy and create two "test" addresses.
- Look up current Bitcoin transaction fee rates. Choose a lower-end fee rate (in order to save money).
- Assemble information for creating a 1-input 2-output transaction that transfers X/2 bitcoin from the source address into each test address. This will be transaction tx_1.
- Generate 32 bytes of entropy for signing tx_1.
- Create and sign tx_1.
- Upload tx_1 for broadcast.
- Wait for 6-block confirmation of the transaction.
- Generate 32 bytes of entropy and create a "destination" address.
- Look up current Bitcoin transaction fee rates. Choose a lower-end fee rate (in order to save money).
- Assemble information for creating a 2-input 1-output transaction that transfers the bitcoin in the test addresses into the destination address. This will be transaction tx_2.
- Generate 2 sets of 32 bytes of entropy for signing tx_2.
- Create and sign tx_2. Development may occur here. This will be transaction tx_2. The ability to construct transactions of this type is the goal of this project.
- Upload tx_2 for broadcast.
- Wait for 6-block confirmation of the transaction.
- Look up current LocalBitcoins receiving address. This will be the "final" address. This will be a nonstandard P2SH address.
- Look up current Bitcoin transaction fee rates. Choose a lower-end fee rate (in order to save money).
- Assemble information for creating a 1-input 1-nonstandard-output transaction that transfers the bitcoin in the destination address to the final address. This will be transaction tx_3.
- Generate 32 bytes of entropy for signing tx_3.
- Create and sign tx_3.
- Upload tx_3 for broadcast.
- Wait for 6-block confirmation of the transaction.
- Log in to LocalBitcoins and confirm receipt of the deposit.
- If development work has been done, then add new or changed files as assets to this article. Test the final versions to make sure that they still produce the expected results.
Additional steps performed during the project:
- Look up transaction data after the successful confirmation of a transaction.
- Get the output index of relevant transaction outputs.
- Attempt the decoding of a transaction prior to uploading for broadcast.
I was able to follow the original plan without changing course.
Exception: The last step. I did a little development work. The changes were not very extensive - they involve the printing of a description of a transaction-in-signable-form. I won't add the new versions of transaction_2.py and nonstandard_transaction_2.py as assets to this article. The changes are recorded in the section Changing transaction_2.py And nonstandard_transaction_2.py To Correctly Describe A Non-Signing Input.
The assets used during this project are listed in the Downloadable Assets section of this previous project:
Creating a Bitcoin transaction with two outputs
Notes section:
The Notes section contains the following parts:
- Terms and acryonyms
- Services used during this project
- Equipment used during this project
- Addresses generated
- Transactions created
- Transaction creation data
Changing Transaction_2.Py And Nonstandard_Transaction_2.Py To Correctly Describe A Non-Signing Input
In transaction_2.py, in the class Transaction, in the method get_description_of_signable_form(), in the
for
loop that describes the inputs, all inputs are described as being "used to sign this signable form", whereas in fact only one input will be used to sign each particular signable form of a transaction.The code that generates the hex-byte signable form and that signs the transaction works correctly. Only the code that generates the description is incorrect, and then only when the transaction contains multiple inputs.
The following changes will fix this problem. Line numbers refer to lines in the original version of the file.
In transaction_2.py:
- Replace line 211
s += "\n- Input %d [to be used to sign this signable form]: {%d bytes}" % (i, bf.hex_len(input.get_signable_form()))
with
if i == input_index:
s += "\n- Input %d [to be used to sign this signable form]: {%d bytes}" % (i, bf.hex_len(input.get_signable_form()))
else:
s += "\n- Input %d: {%d bytes}" % (i, bf.hex_len(input.get_signable_empty_form()))
- After line 449, insert
def get_signable_empty_form(self):
# this is the form used when another input is being used to sign the transaction.
s = self.previous_output_hash
s += self.previous_output_index
s += bf.int_to_var_int(0) # 0x00 script_length for scriptSig
# no scriptSig
s += self.sequence
return s
The same problem exists in nonstandard_transaction_2.py and can be fixed in the same way. Nonstandard_transaction_2.py uses the Input class from transaction_2.py (it is imported by the create_nonstandard_transaction.py script and its instances are passed to nonstandard_transaction_2.py), so this change is simpler.
In nonstandard_transaction_2.py:
- Replace line 149
s += "\n- Input %d [to be used to sign this signable form]: {%d bytes}" % (i, bf.hex_len(input.get_signable_form()))
with
if i == input_index:
s += "\n- Input %d [to be used to sign this signable form]: {%d bytes}" % (i, bf.hex_len(input.get_signable_form()))
else:
s += "\n- Input %d: {%d bytes}" % (i, bf.hex_len(input.get_signable_empty_form()))
Notes
Parts
- Terms and acryonyms
- Services used during this project
- Equipment used during this project
- Addresses generated
- Transactions created
- Transaction creation data
Terms and acryonyms
- tx = transaction
- txid = transaction id
Services used during this project
I used
localbitcoins.com
to:
- store some bitcoin
- transfer some bitcoin to the source address
- receive bitcoin back from the destination address
I used
bitcoinfees.earn.com
to choose fee rates for my transactions. It displays estimated delays (in blocks and in minutes) for ranges of fee rates (in satoshi / byte).
I used the search field at
live.blockcypher.com
to search for transactions by txid.
On the resulting transaction pages e.g. for tx_0:
live.blockcypher.com/btc/tx/1b1ad779f50b07aac0048471844c0637100561b179457ddd433f1c05adf24a19
I was able to click Advanced Details / API Call, which produced a raw text dump of the transaction, e.g.
api.blockcypher.com/v1/btc/main/txs/1b1ad779f50b07aac0048471844c0637100561b179457ddd433f1c05adf24a19?limit=50&includeHex=true
Note: I had to read through the transaction raw text dump in order to find the index of a particular unspent output. A service that allowed someone to look up the index of an unspent output would be useful.
Procedure for finding the output index of a particular unspent output in the JSON-formatted raw transaction information (this is used when making a transaction that spends this output):
1) Copy the transaction data into a text editor. Delete everything apart from the output list. Find all '{'. Result is an integer e.g. 35.
2) Find the unspent output by searching for the source address. Select the text of all outputs that appear after it. Delete this text.
3) Find all '{'. Result is an integer e.g. 13.
4) The result of step (3) gives you the position of the unspent output in the output list e.g. it's the 13th output. Taking the initial index to be 0, the output's index would then be 12.
I used
live.blockcypher.com/btc/decodetx
to decode a signed transaction. If the service can successfully decode a transaction, this indicates that the transaction is formatted correctly.
I used
live.blockcypher.com/btc/pushtx
to upload a signed transaction for broadcast to the Bitcoin network. After the upload, the relevant transaction page (based on the txid) would then be loaded.
Example transaction page:
live.blockcypher.com/btc/tx/8f6318124bdd66f4643ccbfcbcb0a802924833505c015929dc7b1cab2ca02826
Equipment used during this project
My work computer: Aineko, a 2008 Macbook running Mac OS X 10.6.8 Snow Leopard, with Python 2.7.13 installed.
Addresses generated
Source address:
- Bitcoin private key:
7a0d11f6015f941ea486922e45310535c5b71c59d8489447648eebdb6a39e2a8
- Bitcoin address:
17pNyD9ur28aBgPhHtAFi6fAyrvgshp5yn
Test address 1:
- Bitcoin private key:
cbac84458fcfbb39f87fca7ab9a9ef2f76812a6f999a75dfa25dbcbb0ee3eb6f
- Bitcoin address:
1PFw45xp5JUcLZfDQnMpto6yJpcjRLqrJ8
Test address 2:
- Bitcoin private key:
7d37c1a74d3b87d3994ac6db65b4f298f64a8ed6144edfdb2cacea70cf3070af
- Bitcoin address:
19u4WSjpp19yoAK9kdRyY9HJ7ad2S8s1E4
Destination address:
- Bitcoin private key:
419292d169b515be1aec881018157f0a41883ea54da2b2405e10fd8a6abb76ec
- Bitcoin address:
17PZ6uyL59vPirNqqpMnB1kjEXkU7ske7s
Final address (generated by LocalBitcoins):
36aPuLiBnXwcx4L3rDc74E9aMvXYsE9dEC
Transactions created
Transaction details:
- tx_0: Transferred bitcoin from my LocalBitcoins account to the source address.
- tx_1: Transferred bitcoin from the source address to the two test addresses.
- tx_2: Transferred bitcoin from the two test addresses to the destination address.
- tx_3: Transferred bitcoin from the destination address to the final address.
===== Transaction tx_0 =====
txid_0:
1b1ad779f50b07aac0048471844c0637100561b179457ddd433f1c05adf24a19
===== Transaction tx_1 =====
txid_1:
8f6318124bdd66f4643ccbfcbcb0a802924833505c015929dc7b1cab2ca02826
Signed transaction tx_1:
0100000001194af2ad051c3f43dd7d4579b161051037064c84718404c0aa070bf579d71a1b030000008a47304402204f38e1194a0f71f4cb03b1a8644dae69c543cab339d19f0412511bed0868904a02201a9356663d0ad3527b5633ced4cbc469f98bccb0940f2583c7c6c0c0868973a3014104c0128d7e4cbfef4e1bae30788b7bd7a4b974027eea5d83c07ac041f194707e8bba70a162c557cdbcb89682a5a310a2d5a722b2d58d18920a00b6b4c7024ce966ffffffff02400d0300000000001976a914f425b648af85989c1387d532393938fcb7d7bcbb88acbe0b0300000000001976a91461999077782b7298b813d83459a9c944da6460bd88ac00000000
Final fee: 386 (satoshi)
Size: 257 bytes
Fee rate: 1.502 (satoshi / byte)
Time taken from broadcast to confirmation:
1 hour 52 minutes
===== Transaction tx_2 =====
txid_2:
92616e432f7807bf6d93252fcdca7efb139e56f7aa34835b50670ebc6a4b5649
Signed transaction tx_2:
01000000022628a02cab1c7bdc2959015c5033489202a8b0bcfccb3c64f466dd4b1218638f000000008b4830450221008d4ecab2a74461cabcd3e5398ca6752594fbd758c3d10ff3a50c5bf45e460a4502206e7607d2f9ff8fa40489c041fdbbcaecfe723caabf28de9451a2be67d8705d1901410426f2ad4968ef7c5412a2cfac85c902f613b7406962477c931d25ddfb2957c494e70f832ac8dd50740c64297038c722542005b0c5191061e444c793b62d9b2aceffffffff2628a02cab1c7bdc2959015c5033489202a8b0bcfccb3c64f466dd4b1218638f010000008a4730440220184f1d7e9cfe7539cd40cae04e71dc21ce05de958620294cb2d490d45356bfc102203f4ae4afe33b93d1cc96c356735d7a4d3b90cfe62cab0d0cf71fd2f7718e99df0141043c8564e9fa9e9530699ffe7c5dd75077698ff96f3786e96bdbb210a109147cedacfdaa784eb4ba538556e8dd70455ba3627fe902f152940d70ffdd55acdb82a9ffffffff0143170600000000001976a9144614b4066faf3ef831a20186f76381c25dd6ea8288ac00000000
Final fee: 443 (satoshi)
Size: 403 bytes
Fee rate: 1.099 (satoshi / byte)
Time taken from broadcast to confirmation:
3 minutes
===== Transaction tx_3 =====
txid_3:
833ebb5434d5ce55e1d0637b5deaf4881a76226d85701e4adb7b9fb8f2a8cf9c
Signed transaction tx_3:
010000000149564b6abc0e67505b8334aaf7569e13fb7ecacd2f25936dbf07782f436e6192000000008b483045022100b94b19c0c6bc845a335004dc6f52a80100fcca3309ffc0fd22d6c95ee207340a0220158c4576cdca1644a1c37b2ec38da1b85babc2caee151cc49fde0a619170a065014104e7652b2b4a2080825bff6ac17eceb52487254e296577da6e0e2183632922ba46c6008d416eac91da3203ec0c728c06272bbb246ddc95c65daceb1636d9dd5a0cffffffff014f1606000000000017a914359810861535b9a53303f78169c0bfc5beab0b188700000000
Final fee: 244 (satoshi)
Size: 222 bytes
Fee rate: 1.099 (satoshi / byte)
Time taken from broadcast to confirmation:
1 minute
Transaction creation data
===== Transaction tx_0 =====
On LocalBitcoins, send 0.004 bitcoin to the source address:
17pNyD9ur28aBgPhHtAFi6fAyrvgshp5yn
===== Transaction tx_1 =====
Fee rate: 1.5 satoshi / byte
The information for the single input (input_1):
- txid (of the previous transaction that transferred the unspent output to the input address):
1b1ad779f50b07aac0048471844c0637100561b179457ddd433f1c05adf24a19
- previous_output_index (the index of this unspent output in the previous transaction):
3
- private key (of the input address):
7a0d11f6015f941ea486922e45310535c5b71c59d8489447648eebdb6a39e2a8
-- Note: This is the private key for the source address.
- input amount (amount contained in the unspent output):
0.004 bitcoin (400000 satoshi).
- 32-byte random value (in this case, entropy_1):
84425ee562f20d7493420c97eea153d37891eb63ce51fa24f51bfc7646353d32
The information for the two outputs:
Output 1 (to test address 1):
- Bitcoin address:
1PFw45xp5JUcLZfDQnMpto6yJpcjRLqrJ8
- amount: 0.002 bitcoin (200000 satoshi)
Output 2 (to test address 2):
- Bitcoin address:
19u4WSjpp19yoAK9kdRyY9HJ7ad2S8s1E4
- amount: 0.002 bitcoin (200000 satoshi)
Change address: test address 2
19u4WSjpp19yoAK9kdRyY9HJ7ad2S8s1E4
===== Transaction tx_2 =====
Fee rate: 1.1 satoshi / byte
Input data:
Input_2:
- txid (of the previous transaction tx_1 that transferred the unspent output to the input address):
8f6318124bdd66f4643ccbfcbcb0a802924833505c015929dc7b1cab2ca02826
- previous_output_index (the index of this unspent output in the previous transaction):
0
-- Note: Reading the output from making tx_1, or looking at the data about it above, shows that the output sent to test address 1 appears first in the output list.
- private key (of the input address):
cbac84458fcfbb39f87fca7ab9a9ef2f76812a6f999a75dfa25dbcbb0ee3eb6f
-- Note: This is the private key for test address 1.
- input amount (amount contained in the unspent output):
0.002 bitcoin (200000 satoshi)
- 32-byte random value (in this case, entropy_2):
5ab5bbe6fdc861a461a6721b2953d32be23c233e5ad5dc08d7c13daa95adbc17
Input_3:
- txid (of the previous transaction tx_1 that transferred the unspent output to the input address):
8f6318124bdd66f4643ccbfcbcb0a802924833505c015929dc7b1cab2ca02826
- previous_output_index (the index of this unspent output in the previous transaction):
1
-- Note: Reading the output from making tx_1, or looking at the data about it above, shows that the output sent to test address 2 appears second in the output list.
- private key (of the input address):
7d37c1a74d3b87d3994ac6db65b4f298f64a8ed6144edfdb2cacea70cf3070af
-- Note: This is the private key for test address 2.
- input amount (amount contained in the unspent output):
0.00199614 bitcoin (199614 satoshi)
- 32-byte random value (in this case, entropy_3):
75fc65686a47326556735be91491a06f380a9db682fe9d50f82ad8d8d8849c2f
Output data:
- Bitcoin address:
17PZ6uyL59vPirNqqpMnB1kjEXkU7ske7s
- amount: 0.00399614 bitcoin (399614 satoshi)
Change address: destination address
17PZ6uyL59vPirNqqpMnB1kjEXkU7ske7s
===== Transaction tx_3 =====
Fee rate: 1.1 satoshi / byte
Input data (for input_4):
- txid (of the previous transaction tx_2 that transferred the unspent output to the input address):
92616e432f7807bf6d93252fcdca7efb139e56f7aa34835b50670ebc6a4b5649
- previous_output_index (the index of this unspent output in the previous transaction):
0
-- Note: Reading the output from making tx_2, or looking at the data about it above, shows that the output sent to the destination address appears first in the output list.
- private key (of the input address):
419292d169b515be1aec881018157f0a41883ea54da2b2405e10fd8a6abb76ec
-- Note: This is the private key for the destination address.
- input amount (amount contained in the unspent output):
0.00399171 bitcoin (399171 satoshi)
- 32-byte random value (in this case, entropy_4):
c35da685f448d8aca9aed2169e73ef4bde69d51ff574f4980b0b3c71469c88a7
Output data:
- Bitcoin address:
36aPuLiBnXwcx4L3rDc74E9aMvXYsE9dEC
- amount: 0.00399171 bitcoin (399171 satoshi)
Change address: final address
36aPuLiBnXwcx4L3rDc74E9aMvXYsE9dEC
Financial Information For This Project
I planned to make 3 transactions.
- The first would have 1 input and 2 outputs.
- The second would have 2 inputs and 1 output. The 2 inputs would be the outputs from the first transaction.
- The third would have 1 input and 1 output. It would transfer the remaining bitcoin to my LocalBitcoins receiving address (the "final address").
I looked up current Bitcoin transaction fee rates. I chose a higher-end fee rate for calculations in order to have slack (financial room to manoeuvre). This was 50 satoshi / byte.
LocalBitcoins would charge a transaction fee for sending bitcoin and a deposit fee for receiving bitcoin. I looked these up.
- LocalBitcoins transaction fee (for sending bitcoin) was 0.00005 BTC. This was deducted from the available wallet balance and was not involved in the transactions that I created.
- LocalBitcoins deposit fee (for receiving bitcoin) was 0.00015 BTC.
I used a high upper bound of 500 bytes per transaction when estimating transaction sizes.
Total bytes (estimated, high bound):
3 transactions * 500 bytes / transaction
= 1500 bytes
Total Bitcoin transaction fees (estimated, high bound):
1500 bytes * 50 satoshi / byte = 1500 * 50
= 75000 satoshi
Total project costs (estimated, high bound):
LocalBitcoins transaction fee + Total Bitcoin transaction fees + LocalBitcoins deposit fee
= 0.00005 BTC + 75000 satoshi + 0.00015 BTC
= 0.00005 BTC + 0.00075 BTC + 0.00015 BTC
= 0.00005 + 0.00075 + 0.00015
= 0.00095 bitcoin
USD / Bitcoin exchange rate: $3,863.14 / btc
Total project costs (estimated, high bound) in dollars:
0.00095 bitcoin * $3,863.14 / btc
= 0.00095 * 3863.14
~= $3.67
I chose a high initial amount to transfer to the source address. It had to be sufficiently high enough (higher than 0.00095 bitcoin) to provide financial slack.
Initial amount: 0.004 bitcoin.
Initial amount in dollars:
0.004 btc * $3,863.14 / btc
= 0.004 * 3863.14
~= $15.45
Actual costs:
- tx_0: LocalBitcoins transaction fee
0.00005 bitcoin
- tx_1: Bitcoin transaction fee
386 satoshi
= 0.00000386 bitcoin
- tx_2: Bitcoin transaction fee
443 satoshi
= 0.00000443 bitcoin
- tx_3: Bitcoin transaction fee + LocalBitcoins deposit fee
244 satoshi + 0.00015 bitcoin
= 0.00000244 bitcoin + 0.00015 bitcoin
= (0.00000244 + 0.00015) bitcoin
= 0.00015244 bitcoin
Total costs:
0.00005 bitcoin + 0.00000386 bitcoin + 0.00000443 bitcoin + 0.00015244 bitcoin
= (0.00005 + 0.00000386 + 0.00000443 + 0.00015244) bitcoin
= 0.00021073 bitcoin
Total costs in dollars:
0.00021073 bitcoin * $3,863.14 / btc
= 0.00021073 * 3863.14
~= $0.81
Double-check: Amount received back into LocalBitcoins account:
- tx_3:
- Received BTC: 0.00383927 btc
Final amount: 0.00383927 bitcoin
Initial amount: 0.004 bitcoin
Total costs: (initial amount) - (final amount)
= 0.004 bitcoin - 0.00383927 bitcoin
= (0.004 - 0.00383927) bitcoin
= 0.00016073 bitcoin
This total costs calculation doesn't take account of the LocalBitcoins transaction fee for making tx_0 (0.00005 bitcoin), so add this in.
Total costs 2: 0.00016073 bitcoin + 0.00005 bitcoin
= (0.00016073 + 0.00005) bitcoin
= 0.00021073 bitcoin
This result is equal to the earlier calculated result for total costs.
Completion Of Further Work Outlined In Previous Projects
Previous project:
Reading and verifying a standard raw bitcoin transaction
Excerpt from the Project Log section:
Some reading indicates that the other scriptSigs are in fact replaced with a zero byte (0x00) within the transaction-to-be-signed.
Future: Test this by verifying a multiple-input transaction.
Excerpt from the Notes / Discoveries section:
The input signatures in a transaction are created by this process:
- For each input:
-- Acquire the relevant scriptPubKey of the previous transaction (that supplies the unspent output used as an input in the new transaction).
-- Substitute this scriptPubKey for the scriptSig of this input. Also substitute the scriptPubKey's length var_int for the scriptSig's length var_int.
-- Remove the scriptSigs of other inputs. I haven't tested this myself. Some reading indicates that a single 0x00 byte is substituted for each length var_int of other scriptSigs (thus indicating that the scriptSig contains no data).
-- Append a four-byte form of the hash_type. For hash type 1, SIGHASH_ALL, this is 0x01 00 00 00 (The value "1" in little-endian form).
-- The transaction is currently the transaction-in-signable-form.
-- Sign this form of the transaction with the private key corresponding to the public key to which the unspent output was originally sent.
-- Remove the four-byte hash_type from the end of the transaction.
-- Append a one-byte version of the hash_type (e.g. SIGHASH_ALL == 0x01) to the scriptSig signature data.
-- Save the scriptSig for this input.
Note: The transaction-in-signable-form differs for each input.
To construct the final transaction:
- After all signatures have been constructed, place all the final scriptSigs in the appropriate locations within the transaction.
During this project, the successful mining of a one-input two-output transaction confirmed that, in a given transaction-in-signable-form prepared for signing by a particular input, all other input scriptSigs are removed and a single 0x00 byte is substituted for each of their length var_ints (indicating that these scriptSigs contain no data).
I'll also note other mentions of this issue in other projects.
Creating and signing a standard raw Bitcoin transaction
Excerpt:
4) Remove the scriptSigs of other inputs. I haven't tested this myself yet. Some reading indicates that a single 0x00 byte is substituted for each length var_int of other scriptSigs (thus indicating that the scriptSig contains no data).
Creating and signing a standard raw Bitcoin transaction: Iteration #2
Excerpt:
Construct and broadcast a standard transaction with two inputs and one output.
- test whether, within the transaction-in-signable-form, the input-not-being-used-to-sign is removed and its script_length var_int set to 0x00.
Project Log
Plan of action:
- Generate 32 bytes of entropy and create a "source" address.
- Look up current Bitcoin transaction fee rates. Choose a higher-end fee rate for use in financial calculations (in order to have slack).
- Look up current LocalBitcoins sending fee (this is deducted from the wallet total, not from the amount sent, but will be included in the financial information for this project).
- Look up current LocalBitcoins deposit fee.
- Perform a rough calculation of the maximum fee I should expect to pay for transactions. Choose an amount X to transfer to the source address that covers a) the maximum Bitcoin transaction fee total and b) the deposit fee for LocalBitcoins.
-- Update: Looking at this completed plan, I see that this will consist of: 3 transaction fees + 1 deposit fee for LocalBitcoins. Use a high upper bound of 500 bytes per transaction when estimating.
- Using LocalBitcoins, transfer X bitcoin to the source address. LocalBitcoins will construct a larger transaction that will include this transfer. This will be transaction tx_0.
- Wait for 6-block confirmation of the transaction.
- Generate 2 sets of 32 bytes of entropy and create two "test" addresses.
- Look up current Bitcoin transaction fee rates. Choose a lower-end fee rate (in order to save money).
- Assemble information for creating a 1-input 2-output transaction that transfers X/2 bitcoin from the source address into each test address. This will be transaction tx_1.
- Generate 32 bytes of entropy for signing tx_1.
- Create and sign tx_1.
- Upload tx_1 for broadcast.
- Wait for 6-block confirmation of the transaction.
- Generate 32 bytes of entropy and create a "destination" address.
- Look up current Bitcoin transaction fee rates. Choose a lower-end fee rate (in order to save money).
- Assemble information for creating a 2-input 1-output transaction that transfers the bitcoin in the test addresses into the destination address. This will be transaction tx_2.
- Generate 2 sets of 32 bytes of entropy for signing tx_2.
- Create and sign tx_2. Development may occur here. This will be transaction tx_2. The ability to construct transactions of this type is the goal of this project.
- Upload tx_2 for broadcast.
- Wait for 6-block confirmation of the transaction.
- Look up current LocalBitcoins receiving address. This will be the "final" address. This will be a nonstandard P2SH address.
- Look up current Bitcoin transaction fee rates. Choose a lower-end fee rate (in order to save money).
- Assemble information for creating a 1-input 1-nonstandard-output transaction that transfers the bitcoin in the destination address to the final address. This will be transaction tx_3.
- Generate 32 bytes of entropy for signing tx_3.
- Create and sign tx_3.
- Upload tx_3 for broadcast.
- Wait for 6-block confirmation of the transaction.
- Log in to LocalBitcoins and confirm receipt of the deposit.
- If development work has been done, then add new or changed files as assets to this article. Test the final versions to make sure that they still produce the expected results.
My work computer during this project: Aineko, a 2008 Macbook running Mac OS X 10.6.8 Snow Leopard, with Python 2.7.13 installed.
Create a project directory.
In the project directory, create a new directory named "work".
====== STEP:
- Generate 32 bytes of entropy and create a "source" address.
In the project directory, create a new directory named "generate_addresses", in which to work.
Use the following recipe to generate 32 bytes of entropy (i.e. a new Bitcoin private key):
Recipe for generating entropy bytes using dice
Bitcoin private key:
7a0d11f6015f941ea486922e45310535c5b71c59d8489447648eebdb6a39e2a8
Use the following recipe to derive the corresponding Bitcoin address from the private key:
Recipe for generating a Bitcoin address
Bitcoin address:
17pNyD9ur28aBgPhHtAFi6fAyrvgshp5yn
^ This is the source address.
====== STEP:
- Look up current Bitcoin transaction fee rates. Choose a higher-end fee rate for use in financial calculations (in order to have slack).
Browse to
bitcoinfees.earn.com
Looking at the data displayed, I see that (currently) the estimated delay for a fee of 27-28 satoshi / byte is 0 blocks (0-30 minutes).
I choose a maximum fee rate of 50 satoshi / byte.
====== STEP:
- Look up current LocalBitcoins sending fee (this is deducted from the wallet total, not from the amount sent, but will be included in the financial information for this project).
- Look up current LocalBitcoins deposit fee.
Log in to LocalBitcoins.
LocalBitcoins transaction fee (for sending bitcoin) is currently 0.00005 BTC. This is deducted from the available wallet balance and is not involved in the transactions that I will create.
LocalBitcoins deposit fee (for receiving bitcoin) is currently 0.00015 BTC.
====== STEP:
- Perform a rough calculation of the maximum fee I should expect to pay for transactions. Choose an amount X to transfer to the source address that covers a) the maximum Bitcoin transaction fee total and b) the deposit fee for LocalBitcoins.
-- Update: Looking at this completed plan, I see that this will consist of: 3 transaction fees + 1 deposit fee for LocalBitcoins. Use a high upper bound of 500 bytes per transaction when estimating.
chosen maximum transaction fee rate: 50 satoshi / byte
number of transactions: 3
size of transactions (high upper bound): 500 bytes
total bytes: 3 * 500 = 1500
total transaction fees: 1500 bytes * 50 satoshi / byte = 1500 * 50 = 75000 satoshi
total cost: (total transaction fees) + (1 deposit fee for LocalBitcoins) = 75000 satoshi + 0.00015 BTC = 0.00075000 + 0.00015 = 0.0009 bitcoin
There will also be a LocalBitcoins transaction fee (for sending bitcoin) of 0.00005 BTC.
total cost 2: 0.0009 + 0.00005 = 0.00095 bitcoin
I will choose the amount X to be 0.004 bitcoin.
Current USD / Bitcoin = $3,863.14 / btc
0.004 btc * $3,863.14 / btc = 0.004 * 3863.14 ~= $15.45
====== STEP:
- Using LocalBitcoins, transfer X bitcoin to the source address. LocalBitcoins will construct a larger transaction that will include this transfer. This will be transaction tx_0.
- Wait for 6-block confirmation of the transaction.
source address:
17pNyD9ur28aBgPhHtAFi6fAyrvgshp5yn
Log in to LocalBitcoins.
Send 0.004 bitcoin to the source address.
LocalBitcoin says that this is equal to $15.46.
Wait a few minutes. Browse to Wallet / Transactions.
Most recent transaction listed:
- 0.004 btc sent to 17pNyD9ur28aBgPhHtAFi6fAyrvgshp5yn
- txid:
1b1ad779f50b07aac0048471844c0637100561b179457ddd433f1c05adf24a19
Below it, there is a fee payment of 0.00005, made at same datetime.
Log out of LocalBitcoins.
Time: 10:55 am
Time: 12:47
Browse to:
live.blockcypher.com
Search for the txid.
The home page reloads.
Search again:
Result:
live.blockcypher.com/btc/tx/1b1ad779f50b07aac0048471844c0637100561b179457ddd433f1c05adf24a19
Confirmations: 6+
Click Advanced Details / API Call.
Result: tx_0
api.blockcypher.com/v1/btc/main/txs/1b1ad779f50b07aac0048471844c0637100561b179457ddd433f1c05adf24a19?limit=50&includeHex=true
Search for the source address in the output.
Excerpts from the raw data returned by the API call:
{
"block_hash": "00000000000000000019ff0e0e5eacf5f7815b58044b600e78c5096dab7d6853",
"block_height": 567173,
"block_index": 1511,
"hash": "1b1ad779f50b07aac0048471844c0637100561b179457ddd433f1c05adf24a19",
[...]
"confirmed": "2019-03-15T11:09:27Z",
"received": "2019-03-15T10:53:20.51Z",
"ver": 2,
"lock_time": 567172,
"double_spend": false,
"vin_sz": 1,
"vout_sz": 35,
"confirmations": 10,
[...]
"outputs": [
{
[...]
{
"value": 400000,
"script": "76a9144ac6a4d0ee2aa064974bf6e571f6f700b7f67ce688ac",
"addresses": [
"17pNyD9ur28aBgPhHtAFi6fAyrvgshp5yn"
],
"script_type": "pay-to-pubkey-hash"
},
The output shown is the one that made the transfer to the source address:
17pNyD9ur28aBgPhHtAFi6fAyrvgshp5yn
Let's call this "output_1".
Need to find the output index of output_1 (this is used when making a transaction that spends this output).
Procedure for finding the output index of a particular unspent output in the JSON-formatted raw transaction information:
1) Copy the transaction data into a text editor. Delete everything apart from the output list. Count all '{'. Result is an integer e.g. 35.
2) Find the unspent output by searching for the source address. Select the text of all outputs that appear after it. Delete this text.
3) Count all '{'. Result is an integer e.g. 13.
4) The result of step (3) gives you the position of the unspent output in the output list e.g. it's the 13th output. Taking the initial index to be 0, the output's index would then be 12.
step 1: 35 found.
step 2: done
step 3: 4 found
step 4: output_1's output index is "3".
====== STEP:
- Generate 2 sets of 32 bytes of entropy and create two "test" addresses.
Do the work in the generate_addresses directory.
Use the following recipe to generate 32 bytes of entropy (i.e. a new Bitcoin private key):
Recipe for generating entropy bytes using dice
Do this twice:
Bitcoin private key (test address 1):
cbac84458fcfbb39f87fca7ab9a9ef2f76812a6f999a75dfa25dbcbb0ee3eb6f
Bitcoin private key (test address 2):
7d37c1a74d3b87d3994ac6db65b4f298f64a8ed6144edfdb2cacea70cf3070af
Use the following recipe to derive the corresponding Bitcoin address from each private key:
Recipe for generating a Bitcoin address
Bitcoin address (test address 1):
1PFw45xp5JUcLZfDQnMpto6yJpcjRLqrJ8
Bitcoin address (test address 2):
19u4WSjpp19yoAK9kdRyY9HJ7ad2S8s1E4
====== STEP:
- Look up current Bitcoin transaction fee rates. Choose a lower-end fee rate (in order to save money).
Browse to
bitcoinfees.earn.com
Looking at the data displayed, I see that (currently) the estimated delay for a fee of 1-2 satoshi / byte is 1-14 blocks (0-180 minutes).
I'll choose an initial fee rate of 1.5 satoshi / byte.
====== STEP:
- Assemble information for creating a 1-input 2-output transaction that transfers X/2 bitcoin from the source address into each test address. This will be transaction tx_1.
The addresses for the input and outputs are all standard. Tx_1 will be a standard transaction.
Browse to Creating a Bitcoin transaction with two outputs
Go to the Downloadable Assets section.
Excerpt:
Transaction creation toolset (standard transactions):
- bitcoin_functions_2.py
- bjorn_edstrom_ripemd160.py
- create_transaction_2.py
- ecdsa-0.10.tar.gz
- pypy_sha256.py
- transaction_2.py
These assets are all linked in the Downloadable Assets section. Download them.
Place the downloaded assets into the work directory.
I'll follow the recipe in this article:
Recipe for creating and signing a standard Bitcoin transaction
but I'll use the set of assets downloaded from
Creating a Bitcoin transaction with two outputs.
Information-to-be-gathered:
- The txid of the previous transaction that transferred the unspent output to the input address.
This is the txid of tx_0:
1b1ad779f50b07aac0048471844c0637100561b179457ddd433f1c05adf24a19
- The index of this unspent output in the previous transaction (the "previous_output_index").
The output index of output_1 is "3".
- The private key (in hex bytes) of the input address.
This is the private key of the source address:
7a0d11f6015f941ea486922e45310535c5b71c59d8489447648eebdb6a39e2a8
- The bitcoin amount (or satoshi amount) contained within the unspent output. Let's call this the "input amount".
I transferred 0.004 bitcoin to the source address.
- A 32-byte random value (1 per input)
[leave this for now]
Information-to-be-chosen:
- The output addresses:
The two test addresses:
Test address 1:
1PFw45xp5JUcLZfDQnMpto6yJpcjRLqrJ8
Test address 2:
19u4WSjpp19yoAK9kdRyY9HJ7ad2S8s1E4
- The bitcoin amounts (or satoshi amounts) that you wish to transfer to the output addresses. Let's call these the "output amounts".
Well, X/2 = 0.004/2 = 0.002 bitcoin to go to each test address.
- The change address.
I'll set test address 2 to be the change address. The transaction fee will be deducted from its output amount.
- The fee (in satoshi) or fee_rate (in satoshi / byte).
A fee rate of 1.5 satoshi / byte.
====== STEP:
- Generate 32 bytes of entropy for signing tx_1.
Do the work in the generate_addresses directory.
Use the following recipe to generate 32 bytes of entropy (this is the same process as generating a new Bitcoin private key):
Recipe for generating entropy bytes using dice
entropy_1:
84425ee562f20d7493420c97eea153d37891eb63ce51fa24f51bfc7646353d32
====== STEP:
- Create and sign tx_1.
I'll follow the recipe in this article:
Recipe for creating and signing a standard Bitcoin transaction
using the set of assets downloaded from
Creating a Bitcoin transaction with two outputs.
Open a terminal. Change directory to the work directory.
Unpack the zipped tape archive file ecdsa-0.10.tar.gz, using the command
tar -zxvf ecdsa-0.10.tar.gz
This unpacking produces a new directory named "ecdsa-0.10" in the work directory. The directory "ecdsa-0.10" contains a directory named "ecdsa". Copy the "ecdsa" directory into the work directory.
Open the file create_transaction_2.py in a text editor.
Scroll to lines 44-79, which should be the section of text that lies between
##### START CONTROLS
and
##### END CONTROLS
Note: In create_transaction_2.py, all control values are strings (i.e. are contained within quotation marks).
Set the variable
random_value
to the 32-byte random value entropy_1. Set the variable
random_value_type
to
"hex_bytes"
. The variable
input_data
is a list that contains one or more inputs. Inputs are represented as dictionaries (key-value stores).For each input dictionary (everything between and including a pair of braces {}):
- Set the value of the key
"txid"
to be the txid. 1b1ad779f50b07aac0048471844c0637100561b179457ddd433f1c05adf24a19
- Set the value of the key
"previous_output_index"
to be the index of the unspent output. 3
- Set the value of the key
"private_key_hex"
to be the private key. 7a0d11f6015f941ea486922e45310535c5b71c59d8489447648eebdb6a39e2a8
- If the input amount is in satoshi, set the value of the key
"satoshi_amount"
to be the input amount. - If the input amount is in bitcoin, set the value of the key
"bitcoin_amount"
to be the input amount. 0.004
Note: Currently, if both of the keys
"satoshi_amount"
and
"bitcoin_amount"
are set, then
"bitcoin_amount"
will take precedence. You can comment out the unused key of the pair by placing a number sign ('#') at the start of the relevant line. The variable
output_data
is a list that contains one or more outputs. Outputs are represented as dictionaries (key-value stores).For each output dictionary (everything between and including a pair of braces {}):
- Set the value of the key
"address"
to be the output address.1PFw45xp5JUcLZfDQnMpto6yJpcjRLqrJ8
19u4WSjpp19yoAK9kdRyY9HJ7ad2S8s1E4
- If the output amount is in satoshi, set the value of the key
"satoshi_amount"
to be the output amount.- If the output amount is in bitcoin, set the value of the key
"bitcoin_amount"
to be the output amount.0.002
0.002
Note: Currently, if both of the keys
"satoshi_amount"
and
"bitcoin_amount"
are set,
"bitcoin_amount"
will take precedence. You can comment out the unused key of the pair by placing a number sign ('#') at the start of the relevant line. Note: You must include an output that is directed to the change address.
Set the variable
change_address
to be the change address.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"
. Here is how the controls look:
create_transaction_2.py
##### 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": "242000", | |
"bitcoin_amount": "0.004", | |
}, | |
] | |
output_data = [ | |
{ | |
"address": "1PFw45xp5JUcLZfDQnMpto6yJpcjRLqrJ8", | |
#"satoshi_amount": "200000", | |
"bitcoin_amount": "0.002", | |
}, | |
{ | |
"address": "19u4WSjpp19yoAK9kdRyY9HJ7ad2S8s1E4", | |
#"satoshi_amount": "200000", | |
"bitcoin_amount": "0.002", | |
}, | |
] | |
# 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 = "774" # satoshi | |
fee_rate = "1.5" # satoshi / byte | |
# fee_type options: ["fee", "fee_rate"] | |
fee_type = "fee_rate" | |
##### END CONTROLS |
In the terminal, in the work directory, run the following command:
python create_transaction_2.py
At the end, the output should contain the signed transaction as a hex byte sequence without spaces.
aineko:work stjohnpiano$ python create_transaction_2.py
### START CREATION OF BITCOIN TRANSACTION
- Fee type: fee_rate
- Fee rate: 1.5 (satoshi / byte)
- 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.002
- Input addresses, with total-value-to-be-sent:
-- 17pNyD9ur28aBgPhHtAFi6fAyrvgshp5yn: 0.00400000
- Output addresses, with total-value-to-be-received:
-- 19u4WSjpp19yoAK9kdRyY9HJ7ad2S8s1E4: 0.00200000
-- 1PFw45xp5JUcLZfDQnMpto6yJpcjRLqrJ8: 0.00200000
- Total value of all inputs: 0.00400000
- Total value of all outputs: 0.00400000
- Total value of all inputs exactly matches total value of all outputs.
- Estimated transaction size: 257 bytes
- Fee rate: 1.5 (satoshi / byte)
- Calculate 257 * 1.5 and round up to nearest satoshi.
- 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)
- [destination, 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
Signed transaction tx_1:
0100000001194af2ad051c3f43dd7d4579b161051037064c84718404c0aa070bf579d71a1b030000008a47304402204f38e1194a0f71f4cb03b1a8644dae69c543cab339d19f0412511bed0868904a02201a9356663d0ad3527b5633ced4cbc469f98bccb0940f2583c7c6c0c0868973a3014104c0128d7e4cbfef4e1bae30788b7bd7a4b974027eea5d83c07ac041f194707e8bba70a162c557cdbcb89682a5a310a2d5a722b2d58d18920a00b6b4c7024ce966ffffffff02400d0300000000001976a914f425b648af85989c1387d532393938fcb7d7bcbb88acbe0b0300000000001976a91461999077782b7298b813d83459a9c944da6460bd88ac00000000
====== STEP:
- Upload tx_1 for broadcast.
- Wait for 6-block confirmation of the transaction.
Browse to:
live.blockcypher.com/btc/decodetx
If this service can successfully decode a transaction, this indicates that the transaction is formatted correctly.
Paste the signed transaction into the text box named "Transaction Hex". Network is set to "Bitcoin".
Click "Decode Transaction".
Result:
{
"addresses": [
"1PFw45xp5JUcLZfDQnMpto6yJpcjRLqrJ8",
"19u4WSjpp19yoAK9kdRyY9HJ7ad2S8s1E4",
"17pNyD9ur28aBgPhHtAFi6fAyrvgshp5yn"
],
"block_height": -1,
"block_index": -1,
"confirmations": 0,
"double_spend": false,
"fees": 386,
"hash": "8f6318124bdd66f4643ccbfcbcb0a802924833505c015929dc7b1cab2ca02826",
"inputs": [
{
"addresses": [
"17pNyD9ur28aBgPhHtAFi6fAyrvgshp5yn"
],
"age": 567173,
"output_index": 3,
"output_value": 400000,
"prev_hash": "1b1ad779f50b07aac0048471844c0637100561b179457ddd433f1c05adf24a19",
"script": "47304402204f38e1194a0f71f4cb03b1a8644dae69c543cab339d19f0412511bed0868904a02201a9356663d0ad3527b5633ced4cbc469f98bccb0940f2583c7c6c0c0868973a3014104c0128d7e4cbfef4e1bae30788b7bd7a4b974027eea5d83c07ac041f194707e8bba70a162c557cdbcb89682a5a310a2d5a722b2d58d18920a00b6b4c7024ce966",
"script_type": "pay-to-pubkey-hash",
"sequence": 4294967295
}
],
"outputs": [
{
"addresses": [
"1PFw45xp5JUcLZfDQnMpto6yJpcjRLqrJ8"
],
"script": "76a914f425b648af85989c1387d532393938fcb7d7bcbb88ac",
"script_type": "pay-to-pubkey-hash",
"value": 200000
},
{
"addresses": [
"19u4WSjpp19yoAK9kdRyY9HJ7ad2S8s1E4"
],
"script": "76a91461999077782b7298b813d83459a9c944da6460bd88ac",
"script_type": "pay-to-pubkey-hash",
"value": 199614
}
],
"preference": "low",
"received": "2019-03-15T18:36:55.963849901Z",
"relayed_by": "3.86.180.216",
"size": 257,
"total": 399614,
"ver": 1,
"vin_sz": 1,
"vout_sz": 2
}
Looks good. No immediate error reported.
It reports the transaction size to be 257 bytes, as calculated during its generation.
Let's broadcast the signed transaction.
Browse to:
live.blockcypher.com/btc/pushtx
Paste the signed transaction into the text box named "Transaction Hex". Network is set to "Bitcoin".
Click "Broadcast Transaction".
Result:
Transaction page loads:
live.blockcypher.com/btc/tx/8f6318124bdd66f4643ccbfcbcb0a802924833505c015929dc7b1cab2ca02826
Details:
- Transaction Successfully Broadcst
- AMOUNT TRANSACTED: 0.00399614 BTC
- FEES: 0.00000386 BTC
- Confirmations: 0/6
- Miner Preference: LOW
- Size: 257 bytes
- Version: 1
- Relayed By: 100.26.145.81
Approximate datetime: 2019-03-15 18:39
[time passes]
Datetime: 2019-03-18 11:29
Browse to transaction page on blockcypher.com.
Confirmations: 6+
Good.
Click Advanced Details / API Call.
Result: tx_1
api.blockcypher.com/v1/btc/main/txs/8f6318124bdd66f4643ccbfcbcb0a802924833505c015929dc7b1cab2ca02826?limit=50&includeHex=true
The raw data returned by the API call:
{
"block_hash": "0000000000000000001036aca10fb6186829d8dc1af01de4b442289f55f11fd2",
"block_height": 567234,
"block_index": 796,
"hash": "8f6318124bdd66f4643ccbfcbcb0a802924833505c015929dc7b1cab2ca02826",
"hex": "0100000001194af2ad051c3f43dd7d4579b161051037064c84718404c0aa070bf579d71a1b030000008a47304402204f38e1194a0f71f4cb03b1a8644dae69c543cab339d19f0412511bed0868904a02201a9356663d0ad3527b5633ced4cbc469f98bccb0940f2583c7c6c0c0868973a3014104c0128d7e4cbfef4e1bae30788b7bd7a4b974027eea5d83c07ac041f194707e8bba70a162c557cdbcb89682a5a310a2d5a722b2d58d18920a00b6b4c7024ce966ffffffff02400d0300000000001976a914f425b648af85989c1387d532393938fcb7d7bcbb88acbe0b0300000000001976a91461999077782b7298b813d83459a9c944da6460bd88ac00000000",
"addresses": [
"17pNyD9ur28aBgPhHtAFi6fAyrvgshp5yn",
"19u4WSjpp19yoAK9kdRyY9HJ7ad2S8s1E4",
"1PFw45xp5JUcLZfDQnMpto6yJpcjRLqrJ8"
],
"total": 399614,
"fees": 386,
"size": 257,
"preference": "low",
"relayed_by": "100.26.145.81",
"confirmed": "2019-03-15T20:30:21Z",
"received": "2019-03-15T18:38:31.704Z",
"ver": 1,
"double_spend": false,
"vin_sz": 1,
"vout_sz": 2,
"confirmations": 392,
"confidence": 1,
"inputs": [
{
"prev_hash": "1b1ad779f50b07aac0048471844c0637100561b179457ddd433f1c05adf24a19",
"output_index": 3,
"script": "47304402204f38e1194a0f71f4cb03b1a8644dae69c543cab339d19f0412511bed0868904a02201a9356663d0ad3527b5633ced4cbc469f98bccb0940f2583c7c6c0c0868973a3014104c0128d7e4cbfef4e1bae30788b7bd7a4b974027eea5d83c07ac041f194707e8bba70a162c557cdbcb89682a5a310a2d5a722b2d58d18920a00b6b4c7024ce966",
"output_value": 400000,
"sequence": 4294967295,
"addresses": [
"17pNyD9ur28aBgPhHtAFi6fAyrvgshp5yn"
],
"script_type": "pay-to-pubkey-hash",
"age": 567173
}
],
"outputs": [
{
"value": 200000,
"script": "76a914f425b648af85989c1387d532393938fcb7d7bcbb88ac",
"addresses": [
"1PFw45xp5JUcLZfDQnMpto6yJpcjRLqrJ8"
],
"script_type": "pay-to-pubkey-hash"
},
{
"value": 199614,
"script": "76a91461999077782b7298b813d83459a9c944da6460bd88ac",
"addresses": [
"19u4WSjpp19yoAK9kdRyY9HJ7ad2S8s1E4"
],
"script_type": "pay-to-pubkey-hash"
}
]
}
Key details:
- block_hash:
0000000000000000001036aca10fb6186829d8dc1af01de4b442289f55f11fd2
- block_height: 567234
- confirmed: 2019-03-15T20:30:21Z
- received: 2019-03-15T18:38:31.704Z
- txid ("hash"):
8f6318124bdd66f4643ccbfcbcb0a802924833505c015929dc7b1cab2ca02826
- vout_sz (number of outputs): 2
Time taken between reception and confirmation:
~= 20:30 - 18:38 = 2 hrs - 8 mins = 1 hr 52 mins
I'll call the outputs in tx_1: "output_2" and "output_3"
- output_2: sent 200000 satoshi to
1PFw45xp5JUcLZfDQnMpto6yJpcjRLqrJ8
- output_3: sent 199614 satoshi to
19u4WSjpp19yoAK9kdRyY9HJ7ad2S8s1E4
In the output list of tx_1,
- output_2 has the output index "0"
- output_3 has the output index "1"
====== STEP:
- Generate 32 bytes of entropy and create a "destination" address.
Do the work in the generate_addresses directory.
Use the following recipe to generate 32 bytes of entropy (i.e. a new Bitcoin private key):
Recipe for generating entropy bytes using dice
Bitcoin private key (destination address):
419292d169b515be1aec881018157f0a41883ea54da2b2405e10fd8a6abb76ec
Use the following recipe to derive the corresponding Bitcoin address from each private key:
Recipe for generating a Bitcoin address
Bitcoin address (destination address):
17PZ6uyL59vPirNqqpMnB1kjEXkU7ske7s
====== STEP:
- Look up current Bitcoin transaction fee rates. Choose a lower-end fee rate (in order to save money).
Browse to
bitcoinfees.earn.com
Looking at the data displayed, I see that (currently) the estimated delay for a fee of 1-2 satoshi / byte is 0-7 blocks (0-110 minutes).
I'll choose an initial fee rate of 1.1 satoshi / byte.
====== STEP:
- Assemble information for creating a 2-input 1-output transaction that transfers the bitcoin in the test addresses into the destination address. This will be transaction tx_2.
I'll use the recipe in this article:
Recipe for creating and signing a standard Bitcoin transaction
as guidance. I'll modify the guidance to be applicable to a two-input transaction.
Information-to-be-gathered:
- The txid of the previous transaction that transferred the unspent outputs to the input addresses.
This is the txid of tx_1:
8f6318124bdd66f4643ccbfcbcb0a802924833505c015929dc7b1cab2ca02826
- The index of each unspent output in the previous transaction (the "previous_output_index").
The output index of output_2 is "0".
The output index of output_3 is "1".
- The private keys (in hex bytes) of the input addresses.
These are the private keys of the test addresses:
- test address 1:
cbac84458fcfbb39f87fca7ab9a9ef2f76812a6f999a75dfa25dbcbb0ee3eb6f
- test address 2:
7d37c1a74d3b87d3994ac6db65b4f298f64a8ed6144edfdb2cacea70cf3070af
- The bitcoin amounts (or satoshi amounts) contained within the unspent outputs. Let's call these the "input amounts".
- "input_2" (unspent output_2):
200000 satoshi sent to test address 1
- "input_3" (unspent output_3):
199614 satoshi sent to test address 2
- 2 x 32-byte random value (1 per input)
[leave these for now]
I'll retroactively use the name "input_1" for the input for tx_1 (i.e. unspent output_1).
Information-to-be-chosen:
- The output address:
The destination address:
17PZ6uyL59vPirNqqpMnB1kjEXkU7ske7s
- The bitcoin amount (or satoshi amount) that you wish to transfer to the output address. Let's call this the "output amount".
Hm. 200000 + 199614 = 399614 satoshi. So that's the output amount to be transferred to the destination address.
- The change address.
I'll set the single output address (the destination address) to be the change address. The transaction fee will be deducted from its output amount.
- The fee (in satoshi) or fee_rate (in satoshi / byte).
A fee rate of 1.1 satoshi / byte.
====== STEP:
- Generate 2 sets of 32 bytes of entropy for signing tx_2.
Do the work in the generate_addresses directory.
Use the following recipe to generate 2 sets of 32 bytes of entropy (this is the same process as generating a new Bitcoin private key):
Recipe for generating entropy bytes using dice
entropy_2:
5ab5bbe6fdc861a461a6721b2953d32be23c233e5ad5dc08d7c13daa95adbc17
entropy_3:
75fc65686a47326556735be91491a06f380a9db682fe9d50f82ad8d8d8849c2f
====== STEP:
- Create and sign tx_2. Development may occur here. This will be transaction tx_2. The ability to construct transactions of this type is the goal of this project.
I'll use the set of assets downloaded earlier from
Creating a Bitcoin transaction with two outputs.
Open a terminal and change directory to the work directory.
aineko:work stjohnpiano$ ls -1
bitcoin_functions_2.py
bitcoin_functions_2.pyc
bjorn_edstrom_ripemd160.py
bjorn_edstrom_ripemd160.pyc
create_transaction_2.py
ecdsa
ecdsa-0.10
ecdsa-0.10.tar.gz
pypy_sha256.py
pypy_sha256.pyc
transaction_2.py
transaction_2.pyc
Make a copy of the work directory. Name it "work2".
Here is what I think will work for signing a multi-input standard transaction:
- Set all input scriptSigs to be empty (no data, 0 bytes)
- Set all the script_length var_ints (that describe the length of the input scriptSigs) to be 0 (1 byte, 0x00).
- The transaction must be signed by every input. One signature will be made using each input, and then formatted into a scriptSig. When an input is used to sign a transaction-in-signable-form, its scriptSig is set to be the previous scriptPubKey (of the address that contains the unspent output that the input is spending in this new transaction), and the corresponding script_length var_int is set to the length of this scriptPubKey.
This is based on reading that I did during a previous project:
Reading and verifying a standard raw bitcoin transaction
Excerpt from the Project Log section:
Some reading indicates that the other scriptSigs are in fact replaced with a zero byte (0x00) within the transaction-to-be-signed.
Future: Test this by verifying a multiple-input transaction.
Excerpt from the Notes / Discoveries section:
The input signatures in a transaction are created by this process:
- For each input:
-- Acquire the relevant scriptPubKey of the previous transaction (that supplies the unspent output used as an input in the new transaction).
-- Substitute this scriptPubKey for the scriptSig of this input. Also substitute the scriptPubKey's length var_int for the scriptSig's length var_int.
-- Remove the scriptSigs of other inputs. I haven't tested this myself. Some reading indicates that a single 0x00 byte is substituted for each length var_int of other scriptSigs (thus indicating that the scriptSig contains no data).
-- Append a four-byte form of the hash_type. For hash type 1, SIGHASH_ALL, this is 0x01 00 00 00 (The value "1" in little-endian form).
-- The transaction is currently the transaction-in-signable-form.
-- Sign this form of the transaction with the private key corresponding to the public key to which the unspent output was originally sent.
-- Remove the four-byte hash_type from the end of the transaction.
-- Append a one-byte version of the hash_type (e.g. SIGHASH_ALL == 0x01) to the scriptSig signature data.
-- Save the scriptSig for this input.
Note: The transaction-in-signable-form differs for each input.
To construct the final transaction:
- After all signatures have been constructed, place all the final scriptSigs in the appropriate locations within the transaction.
I implemented this approach in transaction_2.py, but I have never tried to test it until now.
Use the information assembled earlier for tx_2 to set the controls in create_transaction_2.py.
Here is how the controls look now:
create_transaction_2.py
##### 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": "200000", | |
#"bitcoin_amount": "0.004", | |
}, | |
{ | |
"txid": "8f6318124bdd66f4643ccbfcbcb0a802924833505c015929dc7b1cab2ca02826", | |
"previous_output_index": "1", | |
"private_key_hex": "7d37c1a74d3b87d3994ac6db65b4f298f64a8ed6144edfdb2cacea70cf3070af", | |
"satoshi_amount": "199614", | |
#"bitcoin_amount": "0.004", | |
}, | |
] | |
output_data = [ | |
{ | |
"address": "17PZ6uyL59vPirNqqpMnB1kjEXkU7ske7s", | |
"satoshi_amount": "399614", | |
#"bitcoin_amount": "0.002", | |
}, | |
] | |
# 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 = "774" # satoshi | |
fee_rate = "1.1" # satoshi / byte | |
# fee_type options: ["fee", "fee_rate"] | |
fee_type = "fee_rate" | |
##### END CONTROLS |
In the terminal, in the work2 directory, run the following command:
python create_transaction_2.py
At the end, the output should contain the signed transaction as a hex byte sequence without spaces.
[A small amount of development occurs here. There was a mistake in the code that constructs a printable description of the signable form of a transaction, when the transaction has more than one input. I couldn't see any problems in the actual signable forms or the signing process.]
aineko:work2 stjohnpiano$ python create_transaction_2.py
### START CREATION OF BITCOIN TRANSACTION
- Fee type: fee_rate
- Fee rate: 1.1 (satoshi / byte)
- 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
- Fee rate: 1.1 (satoshi / byte)
- Calculate 402 * 1.1 and round up to nearest satoshi.
- 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)
- [destination, 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)
- [destination, 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
Ok.
Signed transaction tx_2:
01000000022628a02cab1c7bdc2959015c5033489202a8b0bcfccb3c64f466dd4b1218638f000000008b4830450221008d4ecab2a74461cabcd3e5398ca6752594fbd758c3d10ff3a50c5bf45e460a4502206e7607d2f9ff8fa40489c041fdbbcaecfe723caabf28de9451a2be67d8705d1901410426f2ad4968ef7c5412a2cfac85c902f613b7406962477c931d25ddfb2957c494e70f832ac8dd50740c64297038c722542005b0c5191061e444c793b62d9b2aceffffffff2628a02cab1c7bdc2959015c5033489202a8b0bcfccb3c64f466dd4b1218638f010000008a4730440220184f1d7e9cfe7539cd40cae04e71dc21ce05de958620294cb2d490d45356bfc102203f4ae4afe33b93d1cc96c356735d7a4d3b90cfe62cab0d0cf71fd2f7718e99df0141043c8564e9fa9e9530699ffe7c5dd75077698ff96f3786e96bdbb210a109147cedacfdaa784eb4ba538556e8dd70455ba3627fe902f152940d70ffdd55acdb82a9ffffffff0143170600000000001976a9144614b4066faf3ef831a20186f76381c25dd6ea8288ac00000000
Output concerning the fee calculations:
- Estimated transaction size: 402 bytes
- Fee rate: 1.1 (satoshi / byte)
- Calculate 402 * 1.1 and round up to nearest satoshi.
- 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)
- Fee rate: 1.1 (satoshi / byte)
- Calculate 402 * 1.1 and round up to nearest satoshi.
- 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)
I note that the size is reported to be 403 bytes.
====== STEP:
- Upload tx_2 for broadcast.
- Wait for 6-block confirmation of the transaction.
Browse to:
live.blockcypher.com/btc/decodetx
If this service can successfully decode a transaction, this indicates that the transaction is formatted correctly.
Paste the signed transaction into the text box named "Transaction Hex". Network is set to "Bitcoin".
Click "Decode Transaction".
Result:
{
"addresses": [
"1PFw45xp5JUcLZfDQnMpto6yJpcjRLqrJ8",
"19u4WSjpp19yoAK9kdRyY9HJ7ad2S8s1E4",
"17PZ6uyL59vPirNqqpMnB1kjEXkU7ske7s"
],
"block_height": -1,
"block_index": -1,
"confirmations": 0,
"double_spend": false,
"fees": 443,
"hash": "92616e432f7807bf6d93252fcdca7efb139e56f7aa34835b50670ebc6a4b5649",
"inputs": [
{
"addresses": [
"1PFw45xp5JUcLZfDQnMpto6yJpcjRLqrJ8"
],
"age": 567234,
"output_index": 0,
"output_value": 200000,
"prev_hash": "8f6318124bdd66f4643ccbfcbcb0a802924833505c015929dc7b1cab2ca02826",
"script": "4830450221008d4ecab2a74461cabcd3e5398ca6752594fbd758c3d10ff3a50c5bf45e460a4502206e7607d2f9ff8fa40489c041fdbbcaecfe723caabf28de9451a2be67d8705d1901410426f2ad4968ef7c5412a2cfac85c902f613b7406962477c931d25ddfb2957c494e70f832ac8dd50740c64297038c722542005b0c5191061e444c793b62d9b2ace",
"script_type": "pay-to-pubkey-hash",
"sequence": 4294967295
},
{
"addresses": [
"19u4WSjpp19yoAK9kdRyY9HJ7ad2S8s1E4"
],
"age": 567234,
"output_index": 1,
"output_value": 199614,
"prev_hash": "8f6318124bdd66f4643ccbfcbcb0a802924833505c015929dc7b1cab2ca02826",
"script": "4730440220184f1d7e9cfe7539cd40cae04e71dc21ce05de958620294cb2d490d45356bfc102203f4ae4afe33b93d1cc96c356735d7a4d3b90cfe62cab0d0cf71fd2f7718e99df0141043c8564e9fa9e9530699ffe7c5dd75077698ff96f3786e96bdbb210a109147cedacfdaa784eb4ba538556e8dd70455ba3627fe902f152940d70ffdd55acdb82a9",
"script_type": "pay-to-pubkey-hash",
"sequence": 4294967295
}
],
"outputs": [
{
"addresses": [
"17PZ6uyL59vPirNqqpMnB1kjEXkU7ske7s"
],
"script": "76a9144614b4066faf3ef831a20186f76381c25dd6ea8288ac",
"script_type": "pay-to-pubkey-hash",
"value": 399171
}
],
"preference": "low",
"received": "2019-03-18T14:31:12.589093715Z",
"relayed_by": "3.92.255.115",
"size": 403,
"total": 399171,
"ver": 1,
"vin_sz": 2,
"vout_sz": 1
}
Looks good. No immediate error reported.
The service reports that the transaction size is 403 bytes, the same result as calculated during its generation.
Let's broadcast the signed transaction.
Browse to:
live.blockcypher.com/btc/pushtx
Paste the signed transaction into the text box named "Transaction Hex". Network is set to "Bitcoin".
Click "Broadcast Transaction".
Result:
Transaction page loads:
live.blockcypher.com/btc/tx/8f6318124bdd66f4643ccbfcbcb0a802924833505c015929dc7b1cab2ca02826
Details:
- Transaction Successfully Broadcst
- AMOUNT TRANSACTED: 0.00399171 BTC
- FEES: 0.00000443 BTC
- Confirmations: 0/6
- Miner Preference: LOW
- Size: 403 bytes
- Version: 1
- Relayed By: 3.91.6.127
Approximate datetime: 2019-03-18 14:53
[some time passes]
Datetime: 2019-03-18 16:03
Browse to transaction page on blockcypher.com.
Confirmations: 6+
Excellent.
Click Advanced Details / API Call.
Result: tx_2
api.blockcypher.com/v1/btc/main/txs/92616e432f7807bf6d93252fcdca7efb139e56f7aa34835b50670ebc6a4b5649?limit=50&includeHex=true
The raw data returned by the API call:
{
"block_hash": "0000000000000000002c2376b60eb82079852a7baaa82582b17536f1277827ed",
"block_height": 567658,
"block_index": 1411,
"hash": "92616e432f7807bf6d93252fcdca7efb139e56f7aa34835b50670ebc6a4b5649",
"hex": "01000000022628a02cab1c7bdc2959015c5033489202a8b0bcfccb3c64f466dd4b1218638f000000008b4830450221008d4ecab2a74461cabcd3e5398ca6752594fbd758c3d10ff3a50c5bf45e460a4502206e7607d2f9ff8fa40489c041fdbbcaecfe723caabf28de9451a2be67d8705d1901410426f2ad4968ef7c5412a2cfac85c902f613b7406962477c931d25ddfb2957c494e70f832ac8dd50740c64297038c722542005b0c5191061e444c793b62d9b2aceffffffff2628a02cab1c7bdc2959015c5033489202a8b0bcfccb3c64f466dd4b1218638f010000008a4730440220184f1d7e9cfe7539cd40cae04e71dc21ce05de958620294cb2d490d45356bfc102203f4ae4afe33b93d1cc96c356735d7a4d3b90cfe62cab0d0cf71fd2f7718e99df0141043c8564e9fa9e9530699ffe7c5dd75077698ff96f3786e96bdbb210a109147cedacfdaa784eb4ba538556e8dd70455ba3627fe902f152940d70ffdd55acdb82a9ffffffff0143170600000000001976a9144614b4066faf3ef831a20186f76381c25dd6ea8288ac00000000",
"addresses": [
"17PZ6uyL59vPirNqqpMnB1kjEXkU7ske7s",
"19u4WSjpp19yoAK9kdRyY9HJ7ad2S8s1E4",
"1PFw45xp5JUcLZfDQnMpto6yJpcjRLqrJ8"
],
"total": 399171,
"fees": 443,
"size": 403,
"preference": "low",
"relayed_by": "3.91.6.127",
"confirmed": "2019-03-18T14:46:17Z",
"received": "2019-03-18T14:43:07.572Z",
"ver": 1,
"double_spend": false,
"vin_sz": 2,
"vout_sz": 1,
"confirmations": 8,
"confidence": 1,
"inputs": [
{
"prev_hash": "8f6318124bdd66f4643ccbfcbcb0a802924833505c015929dc7b1cab2ca02826",
"output_index": 0,
"script": "4830450221008d4ecab2a74461cabcd3e5398ca6752594fbd758c3d10ff3a50c5bf45e460a4502206e7607d2f9ff8fa40489c041fdbbcaecfe723caabf28de9451a2be67d8705d1901410426f2ad4968ef7c5412a2cfac85c902f613b7406962477c931d25ddfb2957c494e70f832ac8dd50740c64297038c722542005b0c5191061e444c793b62d9b2ace",
"output_value": 200000,
"sequence": 4294967295,
"addresses": [
"1PFw45xp5JUcLZfDQnMpto6yJpcjRLqrJ8"
],
"script_type": "pay-to-pubkey-hash",
"age": 567234
},
{
"prev_hash": "8f6318124bdd66f4643ccbfcbcb0a802924833505c015929dc7b1cab2ca02826",
"output_index": 1,
"script": "4730440220184f1d7e9cfe7539cd40cae04e71dc21ce05de958620294cb2d490d45356bfc102203f4ae4afe33b93d1cc96c356735d7a4d3b90cfe62cab0d0cf71fd2f7718e99df0141043c8564e9fa9e9530699ffe7c5dd75077698ff96f3786e96bdbb210a109147cedacfdaa784eb4ba538556e8dd70455ba3627fe902f152940d70ffdd55acdb82a9",
"output_value": 199614,
"sequence": 4294967295,
"addresses": [
"19u4WSjpp19yoAK9kdRyY9HJ7ad2S8s1E4"
],
"script_type": "pay-to-pubkey-hash",
"age": 567234
}
],
"outputs": [
{
"value": 399171,
"script": "76a9144614b4066faf3ef831a20186f76381c25dd6ea8288ac",
"addresses": [
"17PZ6uyL59vPirNqqpMnB1kjEXkU7ske7s"
],
"script_type": "pay-to-pubkey-hash"
}
]
}
Key details:
- block_hash:
0000000000000000002c2376b60eb82079852a7baaa82582b17536f1277827ed
- block_height: 567658
- confirmed: 2019-03-18T14:46:17Z
- received: 2019-03-18T14:43:07.572Z
- txid ("hash"):
92616e432f7807bf6d93252fcdca7efb139e56f7aa34835b50670ebc6a4b5649
- vout_sz (number of outputs): 1
Time taken between reception and confirmation:
~= 14:46 - 14:43 = 3 mins
I'll call the output in tx_2: "output_4"
- output_4: sent 399171 satoshi to
17PZ6uyL59vPirNqqpMnB1kjEXkU7ske7s
In the output list of tx_2,
- output_4 has the output index "0"
I'll use the name "input_4" for the input for tx_3 (i.e. unspent output_4).
====== STEP:
- Look up current LocalBitcoins receiving address. This will be the "final" address. This will be a nonstandard P2SH address.
Log in to LocalBitcoins.
Browse to Wallet / Receive bitcoins
Current receiving address (final address):
36aPuLiBnXwcx4L3rDc74E9aMvXYsE9dEC
====== STEP:
- Look up current Bitcoin transaction fee rates. Choose a lower-end fee rate (in order to save money).
Browse to
bitcoinfees.earn.com
Looking at the data displayed, I see that (currently) the estimated delay for a fee of 1-2 satoshi / byte is 1-5 blocks (0-80 minutes).
I'll choose an initial fee rate of 1.1 satoshi / byte.
====== STEP:
- Assemble information for creating a 1-input 1-nonstandard-output transaction that transfers the bitcoin in the destination address to the final address. This will be transaction tx_3.
I'll follow the recipe in this article:
Recipe for creating and signing a nonstandard Bitcoin transaction
to assemble the necessary information.
Information-to-be-gathered:
- The txid of the previous transaction that transferred the unspent output to the input address.
This is the txid of tx_2:
92616e432f7807bf6d93252fcdca7efb139e56f7aa34835b50670ebc6a4b5649
- The index of the unspent output in the previous transaction (the "previous_output_index").
The output index of output_4 is "0".
- The private key (in hex bytes) of the input address.
This is the private key of the destination address:
419292d169b515be1aec881018157f0a41883ea54da2b2405e10fd8a6abb76ec
- The bitcoin amount (or satoshi amount) contained within the unspent output. Let's call this the "input amount".
- "input_4" (unspent output_4):
399171 satoshi sent to destination address:
17PZ6uyL59vPirNqqpMnB1kjEXkU7ske7s
- 32-byte random value (1 per input)
[leave this for now]
Information-to-be-chosen:
- The output address:
The final address:
36aPuLiBnXwcx4L3rDc74E9aMvXYsE9dEC
- The bitcoin amount (or satoshi amount) that you wish to transfer to the output address. Let's call this the "output amount".
399171 satoshi available in destination address. So that's the output amount to be transferred to the final address.
- The change address.
I'll set the single output address (the final address) to be the change address. The transaction fee will be deducted from its output amount.
- The fee (in satoshi) or fee_rate (in satoshi / byte).
A fee rate of 1.1 satoshi / byte.
====== STEP:
- Generate 32 bytes of entropy for signing tx_3.
Do the work in the generate_addresses directory.
Use the following recipe to generate 32 bytes of entropy (this is the same process as generating a new Bitcoin private key):
Recipe for generating entropy bytes using dice
entropy_4:
c35da685f448d8aca9aed2169e73ef4bde69d51ff574f4980b0b3c71469c88a7
====== STEP:
- Create and sign tx_3.
In the project directory, create a new work directory named "work3".
I'll follow the recipe in this article:
Recipe for creating and signing a nonstandard Bitcoin transaction
But I'll use the set of assets from this article:
Creating a Bitcoin transaction with two outputs
Browse to this second article and go to the Downloadable Assets section.
Excerpt:
Transaction creation toolset (nonstandard transactions):
- bitcoin_functions.py.
-- Note: nonstandard_bitcoin_functions.py still imports bitcoin_functions.py.
- bitcoin_functions_2.py
- bjorn_edstrom_ripemd160.py
- create_nonstandard_transaction_2.py
- ecdsa-0.10.tar.gz
- nonstandard_bitcoin_functions.py
- nonstandard_transaction_2.py
- pypy_sha256.py
- transaction_2.py
These assets are all linked in the Downloadable Assets section. Download them.
Place the downloaded assets into the work directory "work3".
Reading nonstandard_transaction_2.py
I see that the method
get_description_of_signable_form()
has the same problem as the method of the same name
in
transaction_2.py: An incorrect description of an input that won't be used for signing (in that particular signable form).
Delete the asset
transaction_2.py
Copy the (slightly changed) asset
transaction_2.py
from work2 into work3.
Edit the method
get_description_of_signable_form()
in
nonstandard_transaction_2.py,
in the same way that I earlier corrected it in
transaction_2.py.
Open a terminal. Change directory to the work3 directory.
Unpack the zipped tape archive file ecdsa-0.10.tar.gz, using the command
tar -zxvf ecdsa-0.10.tar.gz
This unpacking produces a new directory named "ecdsa-0.10" in the work directory. The directory "ecdsa-0.10" contains a directory named "ecdsa". Copy the "ecdsa" directory into the work directory.
Use the information assembled earlier for tx_3 to set the controls in create_nonstandard_transaction_2.py.
Here is how the controls look now:
create_nonstandard_transaction_2.py
##### START CONTROLS | |
random_values = [ | |
"c35da685f448d8aca9aed2169e73ef4bde69d51ff574f4980b0b3c71469c88a7", | |
] | |
# 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. | |
# 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": "92616e432f7807bf6d93252fcdca7efb139e56f7aa34835b50670ebc6a4b5649", | |
"previous_output_index": "0", | |
"private_key_hex": "419292d169b515be1aec881018157f0a41883ea54da2b2405e10fd8a6abb76ec", | |
"satoshi_amount": "399171", | |
#"bitcoin_amount": "0.00241777", | |
"input_type": "p2pkh", | |
}, | |
] | |
output_data = [ | |
{ | |
"address": "36aPuLiBnXwcx4L3rDc74E9aMvXYsE9dEC", | |
"satoshi_amount": "399171", | |
#"bitcoin_amount": "0.00241", | |
"output_type": "p2sh", | |
}, | |
] | |
change_address = "36aPuLiBnXwcx4L3rDc74E9aMvXYsE9dEC" | |
# note: the fee will be subtracted from the amount that is being sent to the change address. | |
fee = "225" # satoshi | |
fee_rate = "1.1" # satoshi / byte | |
# fee_type options: ["fee", "fee_rate"] | |
fee_type = "fee_rate" | |
##### END CONTROLS |
In the terminal, in the work3 directory, run the following command:
python create_nonstandard_transaction_2.py
At the end, the output should contain the signed transaction as a hex byte sequence without spaces.
aineko:work3 stjohnpiano$ python create_nonstandard_transaction_2.py
### START CREATION OF NONSTANDARD BITCOIN TRANSACTION
- Fee type: fee_rate
- Fee rate: 1.1 (satoshi / byte)
- Number of inputs (i.e. as-yet-unspent outputs): 1
- Number of outputs: 1
- Change address: 36aPuLiBnXwcx4L3rDc74E9aMvXYsE9dEC
- Amount to be sent to the change address: 0.00399171
- Input addresses, with total-value-to-be-sent:
-- 17PZ6uyL59vPirNqqpMnB1kjEXkU7ske7s: 0.00399171
- Output addresses, with total-value-to-be-received:
-- 36aPuLiBnXwcx4L3rDc74E9aMvXYsE9dEC: 0.00399171
- Total value of all inputs: 0.00399171
- Total value of all outputs: 0.00399171
- Total value of all inputs exactly matches total value of all outputs.
- Estimated transaction size: 221 bytes
- Fee rate: 1.1 (satoshi / byte)
- Calculate 221 * 1.1 and round up to nearest satoshi.
- Final fee: 244 (satoshi)
- Final fee rate (using estimated transaction size): 1.1041 (satoshi per byte)
- Fee subtracted from amount to be sent to change address.
- New amount to be sent to change address: 398927 (satoshi)
- Size of signed transaction: 222 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: 49564b6abc0e67505b8334aaf7569e13fb7ecacd2f25936dbf07782f436e6192 (32 bytes)
- [data] previous_output_index: 00000000 (4 bytes)
- [signed form] script_length: 8b (1 bytes)
- [signed form] scriptSig: 483045022100b94b19c0c6bc845a335004dc6f52a80100fcca3309ffc0fd22d6c95ee207340a0220158c4576cdca1644a1c37b2ec38da1b85babc2caee151cc49fde0a619170a065014104e7652b2b4a2080825bff6ac17eceb52487254e296577da6e0e2183632922ba46c6008d416eac91da3203ec0c728c06272bbb246ddc95c65daceb1636d9dd5a0c (139 bytes)
- [data] sequence: ffffffff (4 bytes)
- [used for signing] private_key_hex: 419292d169b515be1aec881018157f0a41883ea54da2b2405e10fd8a6abb76ec (32 bytes)
- [destination, goes into scriptSig] public_key_hex: 04e7652b2b4a2080825bff6ac17eceb52487254e296577da6e0e2183632922ba46c6008d416eac91da3203ec0c728c06272bbb246ddc95c65daceb1636d9dd5a0c (65 bytes)
- [signable form] script_length_scriptPubKey: 19 (1 bytes)
- [signable form] scriptPubKey: 76a9144614b4066faf3ef831a20186f76381c25dd6ea8288ac (25 bytes)
- [more info] address: 17PZ6uyL59vPirNqqpMnB1kjEXkU7ske7s
- [more info] previous_output_index_int: 0
- [more info] txid: 92616e432f7807bf6d93252fcdca7efb139e56f7aa34835b50670ebc6a4b5649
Output 0 (P2SH):
P2SH Output: {32 bytes}
- [data] value: 4f16060000000000 (8 bytes)
- [data] script_length: 17 (1 bytes)
- [data] script: a914359810861535b9a53303f78169c0bfc5beab0b1887 (23 bytes)
- [more info] address: 36aPuLiBnXwcx4L3rDc74E9aMvXYsE9dEC
- [more info] bitcoin_amount: 0.00398927
- [more info] satoshi_amount: 398927
- [more info] redeem_script_hash_hex: 359810861535b9a53303f78169c0bfc5beab0b18
Nonstandard Transaction (unsigned form): {82 bytes}
- version: 01000000 (4 bytes)
- input_count: 01 (1 bytes)
- Input 0: {40 bytes}
-- previous_output_hash: 49564b6abc0e67505b8334aaf7569e13fb7ecacd2f25936dbf07782f436e6192 (32 bytes)
-- previous_output_index: 00000000 (4 bytes)
-- script_length: [none] (0 bytes)
-- scriptSig: [none] (0 bytes)
-- sequence: ffffffff (4 bytes)
- output_count: 01 (1 bytes)
- Output 0 (P2SH): {32 bytes}
-- value: 4f16060000000000 (8 bytes)
-- script_length: 17 (1 bytes)
-- script: a914359810861535b9a53303f78169c0bfc5beab0b1887 (23 bytes)
- block_lock_time: 00000000 (4 bytes)
Nonstandard Transaction (signable form 0): {112 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: 49564b6abc0e67505b8334aaf7569e13fb7ecacd2f25936dbf07782f436e6192 (32 bytes)
-- previous_output_index: 00000000 (4 bytes)
-- script_length_scriptPubKey: 19 (1 bytes)
-- scriptPubKey: 76a9144614b4066faf3ef831a20186f76381c25dd6ea8288ac (25 bytes)
-- sequence: ffffffff (4 bytes)
- output_count: 01 (1 bytes)
- Output 0 (P2SH): {32 bytes}
-- value: 4f16060000000000 (8 bytes)
-- script_length: 17 (1 bytes)
-- script: a914359810861535b9a53303f78169c0bfc5beab0b1887 (23 bytes)
- block_lock_time: 00000000 (4 bytes)
- hash_type_4_byte: 01000000 (4 bytes)
Nonstandard Transaction (signed form): {222 bytes}
- version: 01000000 (4 bytes)
- input_count: 01 (1 bytes)
- Input 0: {180 bytes}
-- previous_output_hash: 49564b6abc0e67505b8334aaf7569e13fb7ecacd2f25936dbf07782f436e6192 (32 bytes)
-- previous_output_index: 00000000 (4 bytes)
-- script_length: 8b (1 bytes)
-- scriptSig: 483045022100b94b19c0c6bc845a335004dc6f52a80100fcca3309ffc0fd22d6c95ee207340a0220158c4576cdca1644a1c37b2ec38da1b85babc2caee151cc49fde0a619170a065014104e7652b2b4a2080825bff6ac17eceb52487254e296577da6e0e2183632922ba46c6008d416eac91da3203ec0c728c06272bbb246ddc95c65daceb1636d9dd5a0c (139 bytes)
-- sequence: ffffffff (4 bytes)
- output_count: 01 (1 bytes)
- Output 0 (P2SH): {32 bytes}
-- value: 4f16060000000000 (8 bytes)
-- script_length: 17 (1 bytes)
-- script: a914359810861535b9a53303f78169c0bfc5beab0b1887 (23 bytes)
- block_lock_time: 00000000 (4 bytes)
Signed transaction:
010000000149564b6abc0e67505b8334aaf7569e13fb7ecacd2f25936dbf07782f436e6192000000008b483045022100b94b19c0c6bc845a335004dc6f52a80100fcca3309ffc0fd22d6c95ee207340a0220158c4576cdca1644a1c37b2ec38da1b85babc2caee151cc49fde0a619170a065014104e7652b2b4a2080825bff6ac17eceb52487254e296577da6e0e2183632922ba46c6008d416eac91da3203ec0c728c06272bbb246ddc95c65daceb1636d9dd5a0cffffffff014f1606000000000017a914359810861535b9a53303f78169c0bfc5beab0b188700000000
### END CREATION OF BITCOIN TRANSACTION
Signed transaction tx_3:
010000000149564b6abc0e67505b8334aaf7569e13fb7ecacd2f25936dbf07782f436e6192000000008b483045022100b94b19c0c6bc845a335004dc6f52a80100fcca3309ffc0fd22d6c95ee207340a0220158c4576cdca1644a1c37b2ec38da1b85babc2caee151cc49fde0a619170a065014104e7652b2b4a2080825bff6ac17eceb52487254e296577da6e0e2183632922ba46c6008d416eac91da3203ec0c728c06272bbb246ddc95c65daceb1636d9dd5a0cffffffff014f1606000000000017a914359810861535b9a53303f78169c0bfc5beab0b188700000000
I note that the size is reported to be 222 bytes.
====== STEP:
- Upload tx_3 for broadcast.
- Wait for 6-block confirmation of the transaction.
Browse to:
live.blockcypher.com/btc/decodetx
If this service can successfully decode a transaction, this indicates that the transaction is formatted correctly.
Paste the signed transaction into the text box named "Transaction Hex". Network is set to "Bitcoin".
Click "Decode Transaction".
Result:
{
"addresses": [
"17PZ6uyL59vPirNqqpMnB1kjEXkU7ske7s",
"36aPuLiBnXwcx4L3rDc74E9aMvXYsE9dEC"
],
"block_height": -1,
"block_index": -1,
"confirmations": 0,
"double_spend": false,
"fees": 244,
"hash": "833ebb5434d5ce55e1d0637b5deaf4881a76226d85701e4adb7b9fb8f2a8cf9c",
"inputs": [
{
"addresses": [
"17PZ6uyL59vPirNqqpMnB1kjEXkU7ske7s"
],
"age": 567658,
"output_index": 0,
"output_value": 399171,
"prev_hash": "92616e432f7807bf6d93252fcdca7efb139e56f7aa34835b50670ebc6a4b5649",
"script": "483045022100b94b19c0c6bc845a335004dc6f52a80100fcca3309ffc0fd22d6c95ee207340a0220158c4576cdca1644a1c37b2ec38da1b85babc2caee151cc49fde0a619170a065014104e7652b2b4a2080825bff6ac17eceb52487254e296577da6e0e2183632922ba46c6008d416eac91da3203ec0c728c06272bbb246ddc95c65daceb1636d9dd5a0c",
"script_type": "pay-to-pubkey-hash",
"sequence": 4294967295
}
],
"outputs": [
{
"addresses": [
"36aPuLiBnXwcx4L3rDc74E9aMvXYsE9dEC"
],
"script": "a914359810861535b9a53303f78169c0bfc5beab0b1887",
"script_type": "pay-to-script-hash",
"value": 398927
}
],
"preference": "low",
"received": "2019-03-19T10:04:52.367757167Z",
"relayed_by": "3.93.58.81",
"size": 222,
"total": 398927,
"ver": 1,
"vin_sz": 1,
"vout_sz": 1
}
Looks good. No immediate error reported.
The service reports that the transaction size is 222 bytes, the same result as calculated during its generation.
Let's broadcast the signed transaction.
Browse to:
live.blockcypher.com/btc/pushtx
Paste the signed transaction into the text box named "Transaction Hex". Network is set to "Bitcoin".
Click "Broadcast Transaction".
Result:
Transaction page loads:
live.blockcypher.com/btc/tx/833ebb5434d5ce55e1d0637b5deaf4881a76226d85701e4adb7b9fb8f2a8cf9c
Details:
- Transaction Successfully Broadcst
- AMOUNT TRANSACTED: 0.00398927 BTC
- FEES: 0.00000244 BTC
- Confirmations: 0/6
- Miner Preference: LOW
- Size: 222 bytes
- Version: 1
- Relayed By: 3.93.58.81
Approximate datetime: 2019-03-19 10:06
[some time passes]
Datetime: 2019-03-19 12:12
Browse to transaction page on blockcypher.com.
Confirmations: 6+
Excellent.
Click Advanced Details / API Call.
Result: tx_3
api.blockcypher.com/v1/btc/main/txs/833ebb5434d5ce55e1d0637b5deaf4881a76226d85701e4adb7b9fb8f2a8cf9c?limit=50&includeHex=true
The raw data returned by the API call:
{
"block_hash": "0000000000000000001ba2bb4be7b08573a4a189837612a00b34a8d3976fc0cf",
"block_height": 567799,
"block_index": 423,
"hash": "833ebb5434d5ce55e1d0637b5deaf4881a76226d85701e4adb7b9fb8f2a8cf9c",
"hex": "010000000149564b6abc0e67505b8334aaf7569e13fb7ecacd2f25936dbf07782f436e6192000000008b483045022100b94b19c0c6bc845a335004dc6f52a80100fcca3309ffc0fd22d6c95ee207340a0220158c4576cdca1644a1c37b2ec38da1b85babc2caee151cc49fde0a619170a065014104e7652b2b4a2080825bff6ac17eceb52487254e296577da6e0e2183632922ba46c6008d416eac91da3203ec0c728c06272bbb246ddc95c65daceb1636d9dd5a0cffffffff014f1606000000000017a914359810861535b9a53303f78169c0bfc5beab0b188700000000",
"addresses": [
"17PZ6uyL59vPirNqqpMnB1kjEXkU7ske7s",
"36aPuLiBnXwcx4L3rDc74E9aMvXYsE9dEC"
],
"total": 398927,
"fees": 244,
"size": 222,
"preference": "low",
"relayed_by": "3.93.58.81",
"confirmed": "2019-03-19T10:06:44Z",
"received": "2019-03-19T10:05:36.644Z",
"ver": 1,
"double_spend": false,
"vin_sz": 1,
"vout_sz": 1,
"confirmations": 10,
"confidence": 1,
"inputs": [
{
"prev_hash": "92616e432f7807bf6d93252fcdca7efb139e56f7aa34835b50670ebc6a4b5649",
"output_index": 0,
"script": "483045022100b94b19c0c6bc845a335004dc6f52a80100fcca3309ffc0fd22d6c95ee207340a0220158c4576cdca1644a1c37b2ec38da1b85babc2caee151cc49fde0a619170a065014104e7652b2b4a2080825bff6ac17eceb52487254e296577da6e0e2183632922ba46c6008d416eac91da3203ec0c728c06272bbb246ddc95c65daceb1636d9dd5a0c",
"output_value": 399171,
"sequence": 4294967295,
"addresses": [
"17PZ6uyL59vPirNqqpMnB1kjEXkU7ske7s"
],
"script_type": "pay-to-pubkey-hash",
"age": 567658
}
],
"outputs": [
{
"value": 398927,
"script": "a914359810861535b9a53303f78169c0bfc5beab0b1887",
"addresses": [
"36aPuLiBnXwcx4L3rDc74E9aMvXYsE9dEC"
],
"script_type": "pay-to-script-hash"
}
]
}
Key details:
- block_hash:
0000000000000000001ba2bb4be7b08573a4a189837612a00b34a8d3976fc0cf
- block_height: 567799
- confirmed: 2019-03-19T10:06:44Z
- received: 2019-03-19T10:05:36.644Z
- txid ("hash"):
833ebb5434d5ce55e1d0637b5deaf4881a76226d85701e4adb7b9fb8f2a8cf9c
- vout_sz (number of outputs): 1
Time taken between reception and confirmation:
~= 10:05 - 10:06 = 1 min
====== STEP:
- Log in to LocalBitcoins and confirm receipt of the deposit.
Log in to LocalBitcoins.
Browse to Wallet / Transactions.
Most recent transaction listed:
- Date: 03/19/2019 10:18
- Received BTC: 0.00383927 btc
- Description: deposit to 36aPuL......
- Deposit Fee BTC = 0.00015000
====== STEP:
- If development work has been done, then add new or changed files as assets to this article. Test the final versions to make sure that they still produce the expected results.
Hm. The changes were not very extensive. They are also not errors. The original files still work for their intended purpose: Constructing and signing a Bitcoin transaction with a single standard input. I won't add new files as assets to this article.
Let's record the changes.
transaction_2.py:
- Replace line 211
s += "\n- Input %d [to be used to sign this signable form]: {%d bytes}" % (i, bf.hex_len(input.get_signable_form()))
with
if i == input_index:
s += "\n- Input %d [to be used to sign this signable form]: {%d bytes}" % (i, bf.hex_len(input.get_signable_form()))
else:
s += "\n- Input %d: {%d bytes}" % (i, bf.hex_len(input.get_signable_empty_form()))
- After line 449, insert
def get_signable_empty_form(self):
# this is the form used when another input is being used to sign the transaction.
s = self.previous_output_hash
s += self.previous_output_index
s += bf.int_to_var_int(0) # 0x00 script_length for scriptSig
# no scriptSig
s += self.sequence
return s
Line numbers refer to lines in the original version of the file.
I downloaded the original versions of the relevant files:
- transaction_2.py
- create_transaction_2.py
- create_nonstandard_transaction_2.py
and used the
diff
tool to compare them against the versions in the work directories. Update:
- I forgot that a similar change needed to be made to nonstandard_transaction_2.py
Ok. Next: Cleanup.
aineko:5000_creating_a_bitcoin_transaction_with_two_inputs stjohnpiano$ ls -1
2019-03-21_stjohn_piano_creating_a_bitcoin_transaction_with_two_inputs.txt
analysis.txt
end.txt
generate_addresses
items
notes.txt
to_do.txt
work
work2
work3
aineko:5000_creating_a_bitcoin_transaction_with_two_inputs stjohnpiano$ rm -rf generate_addresses
aineko:5000_creating_a_bitcoin_transaction_with_two_inputs stjohnpiano$ rm -rf work
aineko:5000_creating_a_bitcoin_transaction_with_two_inputs stjohnpiano$ rm -rf work2
aineko:5000_creating_a_bitcoin_transaction_with_two_inputs stjohnpiano$ rm -rf work3
aineko:5000_creating_a_bitcoin_transaction_with_two_inputs stjohnpiano$ ls -1
2019-03-21_stjohn_piano_creating_a_bitcoin_transaction_with_two_inputs.txt
analysis.txt
end.txt
items
notes.txt
to_do.txt
After some more cleanup and writing:
aineko:5000_creating_a_bitcoin_transaction_with_two_inputs stjohnpiano$ ls -1
2019-03-21_stjohn_piano_creating_a_bitcoin_transaction_with_two_inputs.txt
tmp
to_do.txt
That's the end of this project.
[start of notes]
Changes from the original text:
- I have not always preserved the format of any excerpts from webpages on other sites (e.g. not preserving the original bold/italic styles, changing the list structures, not preserving hyperlinks).
- I have not always preserved the format of any computer output (e.g. from running bash commands). Examples: Setting input lines in bold text, adding/removing newlines in order to make a sequence of commands easier to read, using hyphens for lists and sublists instead of indentation, breaking wide tables into consecutive sections.
[end of notes]