edgecase_datafeed 201 2021-01-07 This is the date at the time of creation of this datafeed article. A checkpoint article containing a hash of this datafeed article may be created on this date or at a later date. 144 9 2020-05-28 bitcoin b27618deae05910f529240cc6960aeb87f017b12d302327253ee893825ce2bd4 632100 1HtwyqFWNVDoSEVqZwjBRRAV2oEsi8aQXr 13MfGs39pR5aEK4iKdoLjVYXKwi6Y3uyPq
Creating_a_Bitcoin_transaction stjohn_piano 2021-01-07 yes GOAL Develop a tool for creating a Bitcoin transaction. This tool should have a good command-line interface and a test suite. CONTENTS - Goal - Contents - Brief Summary - Summary - Notes - Downloadable Assets - How To Use The Tools - Future Work - Project Log BRIEF SUMMARY I've written a tool for creating and signing a Bitcoin transaction. It has robust input validation and optional logging. SUMMARY I've written a tool for creating a Bitcoin transaction, and an accompanying test suite: - create_transaction_4.py - test_create_transaction_4.py I used the existing tool create_transaction_3.py as my starting point. The new tool has various improvements: - Load all input data from outside the code via command-line arguments. - More levels of input validation. - A proper logging system, rather than print statements. - Restructure into a tree of functions. (This is cleaner and makes it possible to write tests for the individual functions.) - Write a test suite using onchain Bitcoin transactions. - Remove "raw byte" option for random K value. (It's best to only use hex bytes internally so that debugging is easier and the data flow is simpler.) - Include the random K value in the debug log output. - Generate the txid and include it in the info log output. - Validate the output addresses and the change address. - Require private key and K values to be exactly 32 bytes long. - Handle an input domain bug: Too many decimal places in a Bitcoin amount (details are in comment 2 (item 1) on article Edgecase_Bitcoin_Storage_Toolset_version_2 edgecase 148 Edgecase Bitcoin Storage Toolset version 2 ). Tool inputs: - Change address, Bitcoin inputs, Bitcoin outputs, private keys, random values, various control settings. Tool outputs: - (optional) Logging output, including the calculated txid. - A signed transaction in hex bytes. NOTES Important: - Bitcoin inputs are actually unspent Bitcoin outputs from previous transactions. - Each input in a standard Bitcoin transaction requires one ECDSA signature. A new random value must be used for every public ECDSA signature. If the transaction is signed and broadcast, and you create a new variant (e.g. if the first variant was not mined), you must supply a new random value for each input in the transaction. Two signatures made with the same private key and the same random value allows a third party to easily derive the private key. - The input value that may be spent is limited to a default maximum percentage. All remaining value (minus the fee) will be sent to the change address. If you wish to send more than this percentage to other addresses, you must explicitly provide a new maxSpendPercentage value. - The fee will be subtracted from the amount sent to the change address. If the fee is greater than the default maximum fee, you will need to explicitly provide a new maximum fee value. 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. For test data, I used article Bitcoin_transaction_test_set_#2 edgecase 199 Bitcoin transaction test set #2 as my source. - The addresses that correspond to the private keys in the test transactions are available in article Bitcoin_address_test_set_#2 edgecase 200 Bitcoin address test set #2 . - Some transaction creation tests use fee rates instead of fees. These fee rates are available in comment 2 on the source article. Logging: - Logging at "info" level provides useful information: A bird's-eye view of the process. - Logging at "debug" level provides a large amount of detailed information, including secret values (private keys and random values). - At log level "info", the txid is printed just before the signed transaction. - The txid is calculated by applying the SHA256 hash algorithm twice to the signed transaction binary data, and then converting the result to little-endian. - Due to Transaction Malleability (transaction signatures can be slightly altered in-flight by third parties without compromising their validity), for some mined transactions the final txid may differ from the calculated version. DOWNLOADABLE ASSETS Assets of this article: List: - create_transaction_4.py - test_create_transaction_4.py Asset: A tool that creates and signs a standard Bitcoin transaction. Python 2.7.12. asset create_transaction_4.py create_transaction_4.py 614d5e71f7cec1a41d5e908837936eff60d611e8b83082fced1562ff2de6fb78 Asset: A test suite for the transaction creation tool. Python 2.7.12, Pytest 4.6.11. asset test_create_transaction_4.py test_create_transaction_4.py 74db16efbc5f219acb52670d10f98877755e3263f08732930e91aeffbbaabfb8 Assets of other articles: List: - bitcoin_functions_2.py - bjorn_edstrom_ripemd160.py - ecdsa-0.10.tar.gz - pypy_sha256.py - transaction_3.py Asset: A library of functions for handling standard Bitcoin data types. Python 2.7. asset_of_another_article Creating_a_Bitcoin_transaction_with_two_outputs edgecase 85 bitcoin_functions_2.py bitcoin_functions_2.py 653f38ebab7f7c176ce7925364b5916c32b8e97ab5d4c00a66b990a0b6e0074c Asset: An implementation of RIPEMD-160, written by B_j_o:r_n_ E_d_s_t_r_o:m_. Python 2.7. asset_of_another_article Reading_and_verifying_a_standard_raw_bitcoin_transaction edgecase 51 bjorn_edstrom_ripemd160.py bjorn_edstrom_ripemd160.py a5ca6eb289989861e30806ff7e39165622bd366a1c6cd5edd2dbd7dfc4877666 Asset: A Python implementation of ECDSA cryptography, written by Peter Pearson. Python 2.7. asset_of_another_article Reading_and_verifying_a_standard_raw_bitcoin_transaction edgecase 51 ecdsa-0.10.tar.gz ecdsa-0.10.tar.gz 67dae9e1af2b0fd71bc9a378654f7dc89211c1c5aee71e160f8cfce1fa6d6980 Asset: A Python implementation of SHA256. Author unknown. Python 2.7. asset_of_another_article Reading_and_verifying_a_standard_raw_bitcoin_transaction edgecase 51 pypy_sha256.py pypy_sha256.py 2bbd4a83b69625e2f7ece5201475af2803f0ea11f3815c83d8afab3773d8f47b Asset: A library of classes for standard Bitcoin transactions. Python 2.7. asset_of_another_article Edgecase_Bitcoin_Storage_Toolset_version_2 edgecase 148 transaction_3.py transaction_3.py 140a3e7c0501f7598806cf55b4648adc0ae36ed2dbbd260cf994092185a0f520 Dependency tree: - create_transaction_4.py -- bitcoin_functions_2.py --- bjorn_edstrom_ripemd160.py --- ecdsa-0.10.tar.gz --- pypy_sha256.py -- transaction_3.py --- bitcoin_functions_2.py --- ecdsa-0.10.tar.gz The ecdsa-0.10.tar.gz package must be unpacked so that it can be imported and used. Steps: - Unpack the zipped tape archive file ecdsa-0.10.tar.gz, by opening a terminal, changing directory to the work directory, and running the following 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, using the following command: cp -r ecdsa-0.10/ecdsa . - (optional) Delete ecdsa-0.10 and ecdsa-0.10.tar.gz. HOW TO USE THE TOOLS Notes: - "spend" means to send bitcoin to any address that is not the change address. - Be very careful when setting the changeAddress file path. The protection offered by the maxSpendPercentage setting only works if the changeAddress is correct. - The maxSpendPercentage setting is a safeguard against accidentally choosing to send too much to a destination address. - The maximum spend amount is checked prior to the subtraction of the fee from the change amount. - The maxFee setting is a safeguard against accidentally choosing an excessive fee. Example of creating a transaction: python create_transaction_4.py \\ \> --changeAddressFilePath data/tx1_change_address.txt \\ \> --inputsFilePath data/tx1_inputs.json \\ \> --outputsFilePath data/tx1_outputs.json \\ \> --privateKeyFilePaths data/tx1_private_key_1.txt \\ \> --randomValuesFilePath data/tx1_random_values.txt \\ \> --maxSpendPercentage 5 \\ \> --maxFee 1000 \\ \> --feeType fee \\ \> --fee 225 0100000001ceb493941bf44671994f853fe8585f330070956640bd30fe885d429183e48284090000008a47304402206a2eea0c908efbd780a34c48b48d80946a6e740c272468427bada3ba9773d39a022076017028c4386020b19b7d1f1640558cd902aeffbfbd85f4637a8be0e92ee1de014104e8ade66f2cc0e43073f4ccea47db279bbab1a5e30a6e8ba49f12538b215c5b9e0d28bd080d35fde878081e8f05dbc23eeba02b544fa83e6d13b5f2145681e76dffffffff015f0c0300000000001976a9140f9ee78522f6cc8a88784ae02b0408e452d8025988ac00000000 This example uses the data for Transaction 1 in article Bitcoin_transaction_test_set_#2 edgecase 199 Bitcoin transaction test set #2 . Here is the data in the input files: data/tx1_change_address.txt 12RbVkKwHcwHbMZmnSVAyR4g88ZChpQD6f data/tx1_inputs.json [ { "txid": "8482e48391425d88fe30bd4066957000335f58e83f854f997146f41b9493b4ce", "previous_output_index": "9", "address": "1CTumCMjzBfccCJBTkHoPQmAwEqU9Uj2sQ", "bitcoin_amount": "0.00200000" } ] data/tx1_outputs.json [ { "address": "12RbVkKwHcwHbMZmnSVAyR4g88ZChpQD6f", "bitcoin_amount": "0.00199775" } ] data/tx1_private_key_1.txt 0000000000000000000000007468655f6c6962726172795f6f665f626162656c data/tx1_random_values.txt 0072616e646f6d5f627974655f737472696e675f61786178617861735f6d6c6f Example of running the tests: stjohn@judgement:work$ pytest -q test_create_transaction_4.py ........................................................................ [ 90%] ........ [100%] 80 passed in 18.81 seconds The Project Log section includes examples of: - running the creation tool with debug & info level logging. - creating a transaction with multiple inputs and outputs. - running a single test with logging. FUTURE WORK Here are some possible future approaches: 1) Split the creation and signing operations into separate tools. - The creation tool should produce a JSON file containing the transaction information. -- This approach would make it somewhat easier to (if desired) manually transfer the transaction information to an offline signing machine. - The primary utility of the creation tool would be the design of the transaction (choice of inputs, fee, various checks, etc). It can be run online i.e. it can connect directly to a node or blockchain explorer, so it can get up-to-date information for use during creation. - The function of the signing tool would be to create the input signatures. -- It should validate the unsigned transaction before signing it. -- It should produce JSON-formatted output that can be read and checked by a human, and later reformatted into hex for broadcast. -- Optionally, the signatures could be stored in files and later displayed in an easier-to-read format, so that they could be manual transferred out of an offline signing machine. 2) A transaction validation tool that can verify a signed transaction in both hex form and in a JSON format. 3) Options for the user to supply inputs & outputs with satoshi values instead of bitcoin values. Convert these to bitcoin values, then proceed as normal. 4) Options for the user to supply a fee value in bitcoin or a fee rate value in bitcoin/byte. Convert these to satoshi or satoshi/byte values, then proceed as normal. PROJECT LOG I have an existing tool: create_transaction_3.py This will be my starting point. It's a component of article Edgecase_Bitcoin_Storage_Toolset_version_2 edgecase 148 Edgecase Bitcoin Storage Toolset version 2 , and there is a recipe for its use: article Recipe_for_creating_and_signing_a_standard_Bitcoin_transaction_#2 edgecase 168 Recipe for creating and signing a standard Bitcoin transaction #2 . I would like to make various improvements: - Load all input data from outside the code via command-line arguments. - A proper logging system, rather than print statements. - Remove "raw byte" option for random K value. Best to stick with hex bytes as the default. - Write a test suite using onchain Bitcoin transactions. - Include the random K value in the debug log output. - Generate the txid and include it in the info log output. - Validate the output addresses and the change address. - Require private key and K values to be exactly 32 bytes long. Work machine: - Name: Judgement - Windows 10 - Windows Subsystem for Linux (WSL): Ubuntu 16.04 - I'm working in the WSL Ubuntu terminal. My Python version: stjohn@judgement:work$ python --version Python 2.7.12 My Pytest version: stjohn@judgement:work$ pytest --version This is pytest version 4.6.11, imported from /home/stjohn/.local/lib/python2.7/site-packages/pytest.pyc Create a project directory, called: "creating_a_standard_bitcoin_transaction" Browse to article Edgecase_Bitcoin_Storage_Toolset_version_2 edgecase 148 Edgecase Bitcoin Storage Toolset version 2 and download the following assets: - create_transaction_3.py - transaction_3.py - bitcoin_functions_2.py - bjorn_edstrom_ripemd160.py - ecdsa-0.10.tar.gz - pypy_sha256.py Create a new directory named "work" in the project directory. Move the downloaded assets into the work directory. Unpack the zipped tape archive file ecdsa-0.10.tar.gz, by opening a terminal, changing directory to the work directory, and running the following command: tar -zxvf ecdsa-0.10.tar.gz This unpacking produced 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, using the following command: cp -r ecdsa-0.10/ecdsa . Delete ecdsa-0.10 and ecdsa-0.10.tar.gz. For test data, I'll use article Bitcoin_transaction_test_set_#2 edgecase 199 Bitcoin transaction test set #2 as my source. Notes: - The addresses that correspond to the private keys in the transactions are available in article Bitcoin_address_test_set_#2 edgecase 200 Bitcoin address test set #2 . - Some transaction creation tests use fee rates instead of fees. These fee rates are available in comment 2 on the source article. [development occurs here.] I've written a tool for creating a Bitcoin transaction, and an accompanying test suite: - create_transaction_4.py - test_create_transaction_4.py I drew on previous work published in these articles: - article Validating_a_standard_Bitcoin_address edgecase 192 Validating a standard Bitcoin address - article Generating_a_standard_Bitcoin_address_#2 edgecase 189 Generating a standard Bitcoin address #2 - article Generating_entropy_from_dice_#2 edgecase 188 Generating entropy from dice #2 Notes: - "spend" means to send bitcoin to any address that is not the change address. - Be very careful when setting the changeAddress file path. The protection offered by the maxSpendPercentage setting only works if the changeAddress is correct. - The maxSpendPercentage setting is a safeguard against accidentally choosing to send too much to a destination address. - The maximum spend amount is checked prior to the subtraction of the fee from the change amount. - The maxFee setting is a safeguard against accidentally choosing an excessive fee. Tool inputs: - change address, inputs, outputs, private keys, random values, various control settings. (Note: inputs = as-yet-unspent outputs) Tool outputs: - A signed transaction in hex bytes. Dependency tree: - create_transaction_4.py -- bitcoin_functions_2.py --- bjorn_edstrom_ripemd160.py --- ecdsa-0.10.tar.gz --- pypy_sha256.py -- transaction_3.py --- bitcoin_functions_2.py [...] --- ecdsa-0.10.tar.gz 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. Important: - Each input in a standard Bitcoin transaction requires one ECDSA signature. A new random value must be used for every public ECDSA signature. If the transaction is signed and broadcast, and you create a new variant (e.g. if the first variant was not mined), you must supply a new random value for each input in the transaction. Two signatures made with the same private key and the same random value allows a third party to easily derive the private key. - The input value that may be spent is limited to a default maximum percentage. All remaining value (minus the fee) will be sent to the change address. If you wish to send more than this percentage to other addresses, you must explicitly provide a new maxSpendPercentage value. - The fee will be subtracted from the amount sent to the change address. If the fee is greater than the default maximum fee, you will need to explicitly provide a new maximum fee value. Let's record some examples of using create_transaction_4.py stjohn@judgement:work$ python create_transaction_4.py \\ \> -c data/tx1_change_address.txt \\ \> -i data/tx1_inputs.json \\ \> -o data/tx1_outputs.json \\ \> -p data/tx1_private_key_1.txt \\ \> -r data/tx1_random_values.txt \\ \> -m 5 \\ \> -x 1000 \\ \> -t fee \\ \> -e 225 0100000001ceb493941bf44671994f853fe8585f330070956640bd30fe885d429183e48284090000008a47304402206a2eea0c908efbd780a34c48b48d80946a6e740c272468427bada3ba9773d39a022076017028c4386020b19b7d1f1640558cd902aeffbfbd85f4637a8be0e92ee1de014104e8ade66f2cc0e43073f4ccea47db279bbab1a5e30a6e8ba49f12538b215c5b9e0d28bd080d35fde878081e8f05dbc23eeba02b544fa83e6d13b5f2145681e76dffffffff015f0c0300000000001976a9140f9ee78522f6cc8a88784ae02b0408e452d8025988ac00000000 [same, but as a one-line command] stjohn@judgement:work$ python create_transaction_4.py -c data/tx1_change_address.txt -i data/tx1_inputs.json -o data/tx1_outputs.json -p data/tx1_private_key_1.txt -r data/tx1_random_values.txt -m 5 -x 1000 -t fee -e 225 0100000001ceb493941bf44671994f853fe8585f330070956640bd30fe885d429183e48284090000008a47304402206a2eea0c908efbd780a34c48b48d80946a6e740c272468427bada3ba9773d39a022076017028c4386020b19b7d1f1640558cd902aeffbfbd85f4637a8be0e92ee1de014104e8ade66f2cc0e43073f4ccea47db279bbab1a5e30a6e8ba49f12538b215c5b9e0d28bd080d35fde878081e8f05dbc23eeba02b544fa83e6d13b5f2145681e76dffffffff015f0c0300000000001976a9140f9ee78522f6cc8a88784ae02b0408e452d8025988ac00000000 [same, but using long option names] python create_transaction_4.py \\ \> --changeAddressFilePath data/tx1_change_address.txt \\ \> --inputsFilePath data/tx1_inputs.json \\ \> --outputsFilePath data/tx1_outputs.json \\ \> --privateKeyFilePaths data/tx1_private_key_1.txt \\ \> --randomValuesFilePath data/tx1_random_values.txt \\ \> --maxSpendPercentage 5 \\ \> --maxFee 1000 \\ \> --feeType fee \\ \> --fee 225 0100000001ceb493941bf44671994f853fe8585f330070956640bd30fe885d429183e48284090000008a47304402206a2eea0c908efbd780a34c48b48d80946a6e740c272468427bada3ba9773d39a022076017028c4386020b19b7d1f1640558cd902aeffbfbd85f4637a8be0e92ee1de014104e8ade66f2cc0e43073f4ccea47db279bbab1a5e30a6e8ba49f12538b215c5b9e0d28bd080d35fde878081e8f05dbc23eeba02b544fa83e6d13b5f2145681e76dffffffff015f0c0300000000001976a9140f9ee78522f6cc8a88784ae02b0408e452d8025988ac00000000 These examples use the data for Transaction 1 in article Bitcoin_transaction_test_set_#2 edgecase 199 Bitcoin transaction test set #2 . Here's the data in the input files: stjohn@judgement:work$ tail -n +1 data/tx1_* ==\> data/tx1_change_address.txt \<== 12RbVkKwHcwHbMZmnSVAyR4g88ZChpQD6f ==\> data/tx1_inputs.json \<== [ { "txid": "8482e48391425d88fe30bd4066957000335f58e83f854f997146f41b9493b4ce", "previous_output_index": "9", "address": "1CTumCMjzBfccCJBTkHoPQmAwEqU9Uj2sQ", "bitcoin_amount": "0.00200000" } ] ==\> data/tx1_outputs.json \<== [ { "address": "12RbVkKwHcwHbMZmnSVAyR4g88ZChpQD6f", "bitcoin_amount": "0.00199775" } ] ==\> data/tx1_private_key_1.txt \<== 0000000000000000000000007468655f6c6962726172795f6f665f626162656c ==\> data/tx1_random_values.txt \<== 0072616e646f6d5f627974655f737472696e675f61786178617861735f6d6c6f Here's the help output. stjohn@judgement:work$ python create_transaction_4.py -h usage: create_transaction_4.py [-h] [-c CHANGEADDRESSFILEPATH] [-i INPUTSFILEPATH] [-o OUTPUTSFILEPATH] [-p [PRIVATEKEYFILEPATHS [PRIVATEKEYFILEPATHS ...]]] [-r RANDOMVALUESFILEPATH] [-m MAXSPENDPERCENTAGE] [-x MAXFEE] [-t {fee,fee_rate}] [-e FEE | -f FEERATE] [-l {debug,info,warning,error}] [-d] Create and sign a Bitcoin transaction. optional arguments: -h, --help show this help message and exit -c CHANGEADDRESSFILEPATH, --changeAddressFilePath CHANGEADDRESSFILEPATH Path to file containing the change address (default: 'changeAddress.txt'). -i INPUTSFILEPATH, --inputsFilePath INPUTSFILEPATH Path to file containing the transaction inputs (default: 'inputs.json'). -o OUTPUTSFILEPATH, --outputsFilePath OUTPUTSFILEPATH Path to file containing the transaction outputs (default: 'outputs.json'). -p [PRIVATEKEYFILEPATHS [PRIVATEKEYFILEPATHS ...]], --privateKeyFilePaths [PRIVATEKEYFILEPATHS [PRIVATEKEYFILEPATHS ...]] Paths to file containing the transaction outputs (default: '['privateKey.txt']'). -r RANDOMVALUESFILEPATH, --randomValuesFilePath RANDOMVALUESFILEPATH Path to file containing the random values (default: 'randomValues.txt'). -m MAXSPENDPERCENTAGE, --maxSpendPercentage MAXSPENDPERCENTAGE Set maximum percentage of total input value that may be spent (default: '1'). All remaining value (minus the fee) will be sent to the change address. -x MAXFEE, --maxFee MAXFEE Choose maximum fee in satoshi that is permitted (default: '225'). -t {fee,fee_rate}, --feeType {fee,fee_rate} Choose format of output (default: 'fee_rate'). -e FEE, --fee FEE Set transaction fee in satoshi (default: '225'). -f FEERATE, --feeRate FEERATE Set transaction fee rate in satoshi/byte (default: '1'). -l {debug,info,warning,error}, --logLevel {debug,info,warning,error} Choose logging level (default: 'error'). -d, --debug Sets logLevel to 'debug'. This overrides --logLevel. This tool creates and signs a standard Bitcoin transaction. 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. Important: - Each input in a standard Bitcoin transaction requires one ECDSA signature. A new random value must be used for every public ECDSA signature. If the transaction is signed and broadcast, and you create a new variant (e.g. if the first variant was not mined), you must supply a new random value for each input in the transaction. Two signatures made with the same private key and the same random value allows a third party to easily derive the private key. - The input value that may be spent is limited to a default maximum percentage. All remaining value (minus the fee) will be sent to the change address. If you wish to send more than this percentage to other addresses, you must explicitly provide a new maxSpendPercentage value. - The fee will be subtracted from the amount sent to the change address. If the fee is greater than the default maximum fee, you will need to explicitly provide a new maximum fee value. Notes: - There are default values for the input file paths. These can be altered within the code if desired. - There are default values for the maxSpendPercentage, maxFee, feeType, fee, and feeRate. In order to exceed these limits, larger values will have to be explicitly supplied. These can be altered within the code if desired. Here's an example of relying on the default values for maxFee and fee. feeType is by default "fee_rate" so we set it manually to "fee". maxSpendPercentage is not relevant for Transaction 1 because all the value will be sent to the change address. stjohn@judgement:work$ python create_transaction_4.py \\ \> --changeAddressFilePath data/tx1_change_address.txt \\ \> --inputsFilePath data/tx1_inputs.json \\ \> --outputsFilePath data/tx1_outputs.json \\ \> --privateKeyFilePaths data/tx1_private_key_1.txt \\ \> --randomValuesFilePath data/tx1_random_values.txt \\ \> --feeType fee 0100000001ceb493941bf44671994f853fe8585f330070956640bd30fe885d429183e48284090000008a47304402206a2eea0c908efbd780a34c48b48d80946a6e740c272468427bada3ba9773d39a022076017028c4386020b19b7d1f1640558cd902aeffbfbd85f4637a8be0e92ee1de014104e8ade66f2cc0e43073f4ccea47db279bbab1a5e30a6e8ba49f12538b215c5b9e0d28bd080d35fde878081e8f05dbc23eeba02b544fa83e6d13b5f2145681e76dffffffff015f0c0300000000001976a9140f9ee78522f6cc8a88784ae02b0408e452d8025988ac00000000 An example of supplying a fee rate instead of a fee: stjohn@judgement:work$ python create_transaction_4.py \\ \> --changeAddressFilePath data/tx8_change_address.txt \\ \> --inputsFilePath data/tx8_inputs.json \\ \> --outputsFilePath data/tx8_outputs.json \\ \> --privateKeyFilePaths data/tx8_private_key_1.txt data/tx8_private_key_2.txt \\ \> --randomValuesFilePath data/tx8_random_values.txt \\ \> --maxSpendPercentage 52 \\ \> --maxFee 50000 \\ \> --feeType fee_rate \\ \> --feeRate 100 0100000002ea1b9db39c6fd5df377e381a896ddb47da4c3c23faf80fe2da9b13014c055f58000000008b483045022100d75efc99b640bcc09f569b1b53cb33d407720f9931a719d0ae3212182927cbb802205ea59d7e86f3bdcf7ec5b483a181704909e401cdeb3f8c60172d72aa842ec142014104e5f0aa4e9ee32cc982db529c981f18171cd9d1ccf224a94e4b3c09b51fd3752c6ebf66f0861dc435fee962f995ab9c5346d32332a409c598eb575cec74115180ffffffffea1b9db39c6fd5df377e381a896ddb47da4c3c23faf80fe2da9b13014c055f58010000008b483045022100c70dbea33b9a7d51a9f952a63d65f0572194af68774c09e03d347f65cddd38c3022072e8341e85f5cb6c49be050c862837d451f46a6f5d0f51fa80993a45983cf9d6014104cca91b1ad65fc428789b469f0e030fb2de58132c61f3240f416e3a6eb1963009a359770805e71e9b7c7982da51c2a3209ec908efe71cf5ec8b65f5b9eb05115bffffffff026c920600000000001976a91417091ffac2b6bb51d9fd1d979fac6ec6bf3a2f1e88ac20a10700000000001976a9140f3a634504545b37a97b10214b2f640fb16085e588ac00000000 Notes: - This example uses the data for Transaction 8 in article Bitcoin_transaction_test_set_#2 edgecase 199 Bitcoin transaction test set #2 . - In this transaction, two private key filepaths are supplied. Here's the data in the input files: stjohn@judgement:work$ tail -n +1 data/tx8_* ==\> data/tx8_change_address.txt \<== 136oURWq1zjkdQHKcanE7TyA3o36ibARNM ==\> data/tx8_inputs.json \<== [ { "txid": "585f054c01139bdae20ff8fa233c4cda47db6d891a387e37dfd56f9cb39d1bea", "previous_output_index": "0", "address": "12YCFdpsRDvEHNcj5rsmvJ5G2XXkW1icJP", "bitcoin_amount": "0.00474300" }, { "txid": "585f054c01139bdae20ff8fa233c4cda47db6d891a387e37dfd56f9cb39d1bea", "previous_output_index": "1", "address": "1H5SUR7Fv7x252WuJPqBjewwpeHuJ218Ky", "bitcoin_amount": "0.00500000" } ] ==\> data/tx8_outputs.json \<== [ { "address": "136oURWq1zjkdQHKcanE7TyA3o36ibARNM", "bitcoin_amount": "0.00430700" }, { "address": "12PX5jPyQYejyrU79nZUDmKXvB3ttMfDqZ", "bitcoin_amount": "0.00500000" } ] ==\> data/tx8_private_key_1.txt \<== ecfb8057d4e053dda6849f6a361ca2d6797368651bbb2b52ce4691515a7909e1 ==\> data/tx8_private_key_2.txt \<== fc8c7e92b44fe66f8f20d98a648f659da69461661673e22292a67dc20742ef17 ==\> data/tx8_random_values.txt \<== 0a5a9cc087cf3337bfb0fa12f6fa036d17d6b6dc0e93dfa657c8caca47ad8155 2493ac84058e4f4b79f1bd267c45f52bc7545ef01dd66b8bf077cae86460e954 An example of the error produced when the transaction will spend more than the maximum spend percentage: stjohn@judgement:work$ python create_transaction_4.py \\ \> --changeAddressFilePath data/tx8_change_address.txt \\ \> --inputsFilePath data/tx8_inputs.json \\ \> --outputsFilePath data/tx8_outputs.json \\ \> --privateKeyFilePaths data/tx8_private_key_1.txt data/tx8_private_key_2.txt \\ \> --randomValuesFilePath data/tx8_random_values.txt \\ \> --maxSpendPercentage 5 \\ \> --maxFee 50000 \\ \> --feeType fee_rate \\ \> --feeRate 100 Traceback (most recent call last): File "create_transaction_4.py", line 724, in \ main() File "create_transaction_4.py", line 213, in main signedTransaction = createAndSignTransaction(b) File "create_transaction_4.py", line 460, in createAndSignTransaction raise ValueError(msg) ValueError: Spend amount (0.00500000 bitcoin) is greater than the maximum permitted spend amount (0.00048715 bitcoin). To spend this amount, you will need to increase the maxSpendPercentage from 5 to 52. An example of the error produced when the transaction will spend more than the maximum fee: stjohn@judgement:work$ python create_transaction_4.py \\ \> --changeAddressFilePath data/tx8_change_address.txt \\ \> --inputsFilePath data/tx8_inputs.json \\ \> --outputsFilePath data/tx8_outputs.json \\ \> --privateKeyFilePaths data/tx8_private_key_1.txt data/tx8_private_key_2.txt \\ \> --randomValuesFilePath data/tx8_random_values.txt \\ \> --maxSpendPercentage 5 \\ \> --maxFee 555 \\ \> --feeType fee_rate \\ \> --feeRate 100 Traceback (most recent call last): File "create_transaction_4.py", line 724, in \ main() File "create_transaction_4.py", line 213, in main signedTransaction = createAndSignTransaction(b) File "create_transaction_4.py", line 489, in createAndSignTransaction raise ValueError(msg) ValueError: The fee (43600 satoshi) is greater than the specified maximum fee (555 satoshi). Let's run the tests. stjohn@judgement:work$ pytest test_create_transaction_4.py ============================= test session starts ============================== platform linux2 -- Python 2.7.12, pytest-4.6.11, py-1.9.0, pluggy-0.13.1 rootdir: /mnt/c/Users/User/Desktop/stuff/articles/creating_a_standard_bitcoin_transaction/work, inifile: pytest.ini collected 80 items test_create_transaction_4.py ........................................... [ 53%] ..................................... [100%] ========================== 80 passed in 19.32 seconds ========================== Example: Run a specific test. stjohn@judgement:work$ pytest test_create_transaction_4.py::test_arg_none ============================= test session starts ============================== platform linux2 -- Python 2.7.12, pytest-4.6.11, py-1.9.0, pluggy-0.13.1 rootdir: /mnt/c/Users/User/Desktop/stuff/articles/creating_a_standard_bitcoin_transaction/work, inifile: pytest.ini collected 1 item test_create_transaction_4.py . [100%] =========================== 1 passed in 0.07 seconds =========================== Example: Run a specific test quietly. stjohn@judgement:work$ pytest -q test_create_transaction_4.py::test_arg_none . [100%] 1 passed in 0.05 seconds Examples: Print log data when running a test. stjohn@judgement:work$ pytest -o log_cli=true --log-cli-level=DEBUG --log-format="%(levelname)s [%(lineno)s: %(funcName)s] %(message)s" test_create_transaction_4.py::test_output_item_invalid_amount ============================= test session starts ============================== platform linux2 -- Python 2.7.12, pytest-4.6.11, py-1.9.0, pluggy-0.13.1 rootdir: /mnt/c/Users/User/Desktop/stuff/articles/creating_a_standard_bitcoin_transaction/work, inifile: pytest.ini collected 1 item test_create_transaction_4.py::test_output_item_invalid_amount -------------------------------- live log call --------------------------------- DEBUG [633: validateBitcoinAddress] Address: 12RbVkKwHcwHbMZmnSVAyR4g88ZChpQD6f DEBUG [641: validateBitcoinAddress] Number of leading '1' characters: 1 DEBUG [644: validateBitcoinAddress] base10 value inside address: 383018945214016431340896370610606860961941348280797832512 DEBUG [647: validateBitcoinAddress] Address value in hex: 0f9ee78522f6cc8a88784ae02b0408e452d80259ccc52540 DEBUG [652: validateBitcoinAddress] Checksum: ccc52540 DEBUG [654: validateBitcoinAddress] Address value in hex without checksum: 0f9ee78522f6cc8a88784ae02b0408e452d80259 DEBUG [657: validateBitcoinAddress] Address value with leading zero bytes added back on: 000f9ee78522f6cc8a88784ae02b0408e452d80259 DEBUG [660: validateBitcoinAddress] Recalculated checksum: ccc52540 DEBUG [667: validateBitcoinAddress] versionByte: 00 DEBUG [672: validateBitcoinAddress] publicKeyHash: 0f9ee78522f6cc8a88784ae02b0408e452d80259 DEBUG [676: validateBitcoinAddress] Address 12RbVkKwHcwHbMZmnSVAyR4g88ZChpQD6f validated. No problems found. PASSED [100%] =========================== 1 passed in 0.08 seconds =========================== stjohn@judgement:work$ pytest -o log_cli=true --log-cli-level=INFO --log-format= "%(levelname)s [%(lineno)s: %(funcName)s] %(message)s" test_create_transaction_4 .py::test_total_input_too_small ============================= test session starts ============================== platform linux2 -- Python 2.7.12, pytest-4.6.11, py-1.9.0, pluggy-0.13.1 rootdir: /mnt/c/Users/User/Desktop/stuff/articles/creating_a_standard_bitcoin_transaction/work, inifile: pytest.ini collected 1 item test_create_transaction_4.py::test_total_input_too_small -------------------------------- live log call --------------------------------- INFO [292: createAndSignTransaction] All arguments validated. No problems found. INFO [333: createAndSignTransaction] Number of inputs: 2 INFO [341: createAndSignTransaction] Number of outputs: 2 INFO [353: createAndSignTransaction] Input addresses, with total value to be spent from each: -- 12YCFdpsRDvEHNcj5rsmvJ5G2XXkW1icJP: 0.00474300 (bitcoin) -- 1H5SUR7Fv7x252WuJPqBjewwpeHuJ218Ky: 0.00100000 (bitcoin) INFO [372: createAndSignTransaction] Output addresses, with total value to be sent to each: -- 12PX5jPyQYejyrU79nZUDmKXvB3ttMfDqZ: 0.00500000 (bitcoin) -- 136oURWq1zjkdQHKcanE7TyA3o36ibARNM: 0.00430700 (bitcoin) INFO [398: createAndSignTransaction] Change address, with total value to be sent to it: -- 136oURWq1zjkdQHKcanE7TyA3o36ibARNM: 0.00430700 (bitcoin) INFO [405: createAndSignTransaction] Total input value: 0.00574300 (bitcoin) INFO [406: createAndSignTransaction] Total output value: 0.00930700 (bitcoin) PASSED [100%] =========================== 1 passed in 0.51 seconds =========================== This is my pytest.ini: stjohn@judgement:work$ cat pytest.ini [pytest] # Commands: # - pytest # - pytest --help # - pytest --quiet # - pytest --override-ini log_cli=true # note: -o == --override-ini # - pytest -o log_cli=true # - pytest -o log_cli=true -o log_level=info # - pytest -o log_cli=true -o log_level=debug addopts = -ra log_cli = false log_level = CRITICAL log_format = [%(name)s] %(levelname)s [%(lineno)s: %(funcName)s] %(message)s log_date_format = %Y-%m-%d %H:%M:%S Let's look at using logging when creating a transaction. Notes: - Logging at "info" level provides useful information: A bird's-eye view of the process. - Logging at "debug" level provides a large amount of detailed information, including secret values (private keys and random values). Here's the creation of Transaction 8, with logging at "info" level. stjohn@judgement:work$ python create_transaction_4.py \\ \> --changeAddressFilePath data/tx8_change_address.txt \\ \> --inputsFilePath data/tx8_inputs.json \\ \> --outputsFilePath data/tx8_outputs.json \\ \> --privateKeyFilePaths data/tx8_private_key_1.txt data/tx8_private_key_2.txt \\ \> --randomValuesFilePath data/tx8_random_values.txt \\ \> --maxSpendPercentage 52 \\ \> --maxFee 50000 \\ \> --feeType fee_rate \\ \> --feeRate 100 \\ \> --logLevel info - Data has been loaded from files. - Addresses have been derived from private keys. - Each input address has been matched to a private key. - All arguments validated. No problems found. - Number of inputs: 2 - Number of outputs: 2 - Input addresses, with total value to be spent from each: -- 12YCFdpsRDvEHNcj5rsmvJ5G2XXkW1icJP: 0.00474300 (bitcoin) -- 1H5SUR7Fv7x252WuJPqBjewwpeHuJ218Ky: 0.00500000 (bitcoin) - Output addresses, with total value to be sent to each: -- 12PX5jPyQYejyrU79nZUDmKXvB3ttMfDqZ: 0.00500000 (bitcoin) -- 136oURWq1zjkdQHKcanE7TyA3o36ibARNM: 0.00430700 (bitcoin) - Change address, with total value to be sent to it: -- 136oURWq1zjkdQHKcanE7TyA3o36ibARNM: 0.00430700 (bitcoin) - Total input value: 0.00974300 (bitcoin) - Total output value: 0.00930700 (bitcoin) - Total input value is greater than total output value. -- Some input value has not been assigned to an output. -- Extra value: 0.00043600 (bitcoin) -- This extra value will be sent to the change address. -- Change address: 136oURWq1zjkdQHKcanE7TyA3o36ibARNM -- Old change amount: 0.00430700 (bitcoin) -- New change amount: 0.00474300 (bitcoin) - New total output value: 0.00974300 (bitcoin) - Maximum percentage of input value (prior to fee subtraction) that can be spent: 52% - Note: "spend" means to send bitcoin to any address that is not the change address. - Maximum spend amount: 0.00506636 (bitcoin) - Spend amount: 0.00500000 (bitcoin) - The spend amount is 51.32% of the input value. - Estimated transaction size: 436 bytes - Fee type: fee_rate - Fee rate: 100.0 (satoshi/byte) - Note: Calculate final fee by multiplying {estimated transaction size} by {fee rate} and rounding up to the nearest satoshi. - Final fee: 43600 (satoshi) - Final fee rate (using estimated transaction size): 100.0000 (satoshi/byte) - Maximum fee: 50000 (satoshi) - Fee subtracted from change amount. - New change amount: 430700 (satoshi), 0.00430700 (bitcoin) - Transaction created. - Note: The first random value will be used to sign the first input. The second will be used to sign the second, and so on. - Transaction signed. - Signed transaction size: 438 bytes - signedTxSize - estimatedTxSize = 2 bytes - Signed transaction fee rate: 99.5434 (satoshi/byte) - Txid (little-endian double SHA256 hash of signed transaction): 2b0cef7b0abfefeb6c7c6b228930e6218e86e9d8c33f5525d10f34f91cc7bad4 - Signed transaction: 0100000002ea1b9db39c6fd5df377e381a896ddb47da4c3c23faf80fe2da9b13014c055f58000000008b483045022100d75efc99b640bcc09f569b1b53cb33d407720f9931a719d0ae3212182927cbb802205ea59d7e86f3bdcf7ec5b483a181704909e401cdeb3f8c60172d72aa842ec142014104e5f0aa4e9ee32cc982db529c981f18171cd9d1ccf224a94e4b3c09b51fd3752c6ebf66f0861dc435fee962f995ab9c5346d32332a409c598eb575cec74115180ffffffffea1b9db39c6fd5df377e381a896ddb47da4c3c23faf80fe2da9b13014c055f58010000008b483045022100c70dbea33b9a7d51a9f952a63d65f0572194af68774c09e03d347f65cddd38c3022072e8341e85f5cb6c49be050c862837d451f46a6f5d0f51fa80993a45983cf9d6014104cca91b1ad65fc428789b469f0e030fb2de58132c61f3240f416e3a6eb1963009a359770805e71e9b7c7982da51c2a3209ec908efe71cf5ec8b65f5b9eb05115bffffffff026c920600000000001976a91417091ffac2b6bb51d9fd1d979fac6ec6bf3a2f1e88ac20a10700000000001976a9140f3a634504545b37a97b10214b2f640fb16085e588ac00000000 Notes: - At log level "info", the txid is printed just before the signed transaction. - The txid is calculated by applying the SHA256 hash algorithm twice to the signed transaction binary data, and then converting the result to little-endian. - Due to Transaction Malleability (transaction signatures can be slightly altered in-flight by third parties without compromising their validity), for some mined transactions the final txid may differ from the calculated version. Here's the creation of Transaction 1, with logging at "debug" level. stjohn@judgement:work$ python create_transaction_4.py \\ \> --changeAddressFilePath data/tx1_change_address.txt \\ \> --inputsFilePath data/tx1_inputs.json \\ \> --outputsFilePath data/tx1_outputs.json \\ \> --privateKeyFilePaths data/tx1_private_key_1.txt \\ \> --randomValuesFilePath data/tx1_random_values.txt \\ \> --maxSpendPercentage 5 \\ \> --maxFee 1000 \\ \> --feeType fee \\ \> --fee 225 \\ \> --logLevel debug INFO [165: main] Data has been loaded from files. INFO [175: main] Addresses have been derived from private keys. DEBUG [176: main] List of private keys and their corresponding addresses: - 0000000000000000000000007468655f6c6962726172795f6f665f626162656c -- 1CTumCMjzBfccCJBTkHoPQmAwEqU9Uj2sQ INFO [187: main] Each input address has been matched to a private key. DEBUG [633: validateBitcoinAddress] Address: 12RbVkKwHcwHbMZmnSVAyR4g88ZChpQD6f DEBUG [641: validateBitcoinAddress] Number of leading '1' characters: 1 DEBUG [644: validateBitcoinAddress] base10 value inside address: 383018945214016431340896370610606860961941348280797832512 DEBUG [647: validateBitcoinAddress] Address value in hex: 0f9ee78522f6cc8a88784ae02b0408e452d80259ccc52540 DEBUG [652: validateBitcoinAddress] Checksum: ccc52540 DEBUG [654: validateBitcoinAddress] Address value in hex without checksum: 0f9ee78522f6cc8a88784ae02b0408e452d80259 DEBUG [657: validateBitcoinAddress] Address value with leading zero bytes added back on: 000f9ee78522f6cc8a88784ae02b0408e452d80259 DEBUG [660: validateBitcoinAddress] Recalculated checksum: ccc52540 DEBUG [667: validateBitcoinAddress] versionByte: 00 DEBUG [672: validateBitcoinAddress] publicKeyHash: 0f9ee78522f6cc8a88784ae02b0408e452d80259 DEBUG [676: validateBitcoinAddress] Address 12RbVkKwHcwHbMZmnSVAyR4g88ZChpQD6f validated. No problems found. DEBUG [274: createAndSignTransaction] Validate change address: 12RbVkKwHcwHbMZmnSVAyR4g88ZChpQD6f DEBUG [633: validateBitcoinAddress] Address: 12RbVkKwHcwHbMZmnSVAyR4g88ZChpQD6f DEBUG [641: validateBitcoinAddress] Number of leading '1' characters: 1 DEBUG [644: validateBitcoinAddress] base10 value inside address: 383018945214016431340896370610606860961941348280797832512 DEBUG [647: validateBitcoinAddress] Address value in hex: 0f9ee78522f6cc8a88784ae02b0408e452d80259ccc52540 DEBUG [652: validateBitcoinAddress] Checksum: ccc52540 DEBUG [654: validateBitcoinAddress] Address value in hex without checksum: 0f9ee78522f6cc8a88784ae02b0408e452d80259 DEBUG [657: validateBitcoinAddress] Address value with leading zero bytes added back on: 000f9ee78522f6cc8a88784ae02b0408e452d80259 DEBUG [660: validateBitcoinAddress] Recalculated checksum: ccc52540 DEBUG [667: validateBitcoinAddress] versionByte: 00 DEBUG [672: validateBitcoinAddress] publicKeyHash: 0f9ee78522f6cc8a88784ae02b0408e452d80259 DEBUG [676: validateBitcoinAddress] Address 12RbVkKwHcwHbMZmnSVAyR4g88ZChpQD6f validated. No problems found. INFO [292: createAndSignTransaction] All arguments validated. No problems found. DEBUG [317: createAndSignTransaction] Input data 0: -- txid: 8482e48391425d88fe30bd4066957000335f58e83f854f997146f41b9493b4ce -- previous_output_index: 9 -- private_key_hex: 0000000000000000000000007468655f6c6962726172795f6f665f626162656c -- (address): 1CTumCMjzBfccCJBTkHoPQmAwEqU9Uj2sQ -- bitcoin_amount: 0.00200000 DEBUG [322: createAndSignTransaction] Output data 0: -- address: 12RbVkKwHcwHbMZmnSVAyR4g88ZChpQD6f -- bitcoin_amount: 0.00199775 INFO [333: createAndSignTransaction] Number of inputs: 1 INFO [341: createAndSignTransaction] Number of outputs: 1 INFO [353: createAndSignTransaction] Input addresses, with total value to be spent from each: -- 1CTumCMjzBfccCJBTkHoPQmAwEqU9Uj2sQ: 0.00200000 (bitcoin) INFO [372: createAndSignTransaction] Output addresses, with total value to be sent to each: -- 12RbVkKwHcwHbMZmnSVAyR4g88ZChpQD6f: 0.00199775 (bitcoin) DEBUG [394: createAndSignTransaction] Change address found in output addresses. INFO [398: createAndSignTransaction] Change address, with total value to be sent to it: -- 12RbVkKwHcwHbMZmnSVAyR4g88ZChpQD6f: 0.00199775 (bitcoin) INFO [405: createAndSignTransaction] Total input value: 0.00200000 (bitcoin) INFO [406: createAndSignTransaction] Total output value: 0.00199775 (bitcoin) INFO [425: createAndSignTransaction] Total input value is greater than total output value. -- Some input value has not been assigned to an output. -- Extra value: 0.00000225 (bitcoin) -- This extra value will be sent to the change address. -- Change address: 12RbVkKwHcwHbMZmnSVAyR4g88ZChpQD6f -- Old change amount: 0.00199775 (bitcoin) -- New change amount: 0.00200000 (bitcoin) INFO [429: createAndSignTransaction] New total output value: 0.00200000 (bitcoin) INFO [439: createAndSignTransaction] Maximum percentage of input value (prior to fee subtraction) that can be spent: 5% INFO [440: createAndSignTransaction] Note: "spend" means to send bitcoin to any address that is not the change address. INFO [445: createAndSignTransaction] Maximum spend amount: 0.00010000 (bitcoin) INFO [453: createAndSignTransaction] Spend amount: 0.00000000 (bitcoin) INFO [456: createAndSignTransaction] The spend amount is 0.00% of the input value. INFO [465: createAndSignTransaction] Estimated transaction size: 223 bytes INFO [467: createAndSignTransaction] Fee type: fee INFO [469: createAndSignTransaction] Fee: 225 (satoshi) INFO [481: createAndSignTransaction] Final fee: 225 (satoshi) INFO [483: createAndSignTransaction] Final fee rate (using estimated transaction size): 1.0090 (satoshi/byte) INFO [486: createAndSignTransaction] Maximum fee: 1000 (satoshi) INFO [501: createAndSignTransaction] Fee subtracted from change amount. INFO [504: createAndSignTransaction] New change amount: 199775 (satoshi), 0.00199775 (bitcoin) INFO [508: createAndSignTransaction] Transaction created. DEBUG [513: createAndSignTransaction] Random values: -- 0072616e646f6d5f627974655f737472696e675f61786178617861735f6d6c6f INFO [514: createAndSignTransaction] Note: The first random value will be used to sign the first input. The second will be used to sign the second, and so on. INFO [516: createAndSignTransaction] Transaction signed. INFO [519: createAndSignTransaction] Signed transaction size: 223 bytes INFO [520: createAndSignTransaction] signedTxSize - estimatedTxSize = 0 bytes INFO [522: createAndSignTransaction] Signed transaction fee rate: 1.0090 (satoshi/byte) DEBUG [527: createAndSignTransaction] Input 0: Input: {40 bytes unsigned, 66 bytes signable, 179 bytes signed} - [data] previous_output_hash: ceb493941bf44671994f853fe8585f330070956640bd30fe885d429183e48284 (32 bytes) - [data] previous_output_index: 09000000 (4 bytes) - [signed form] script_length: 8a (1 bytes) - [signed form] scriptSig: 47304402206a2eea0c908efbd780a34c48b48d80946a6e740c272468427bada3ba9773d39a022076017028c4386020b19b7d1f1640558cd902aeffbfbd85f4637a8be0e92ee1de014104e8ade66f2cc0e43073f4ccea47db279bbab1a5e30a6e8ba49f12538b215c5b9e0d28bd080d35fde878081e8f05dbc23eeba02b544fa83e6d13b5f2145681e76d (138 bytes) - [data] sequence: ffffffff (4 bytes) - [used for signing] private_key_hex: 0000000000000000000000007468655f6c6962726172795f6f665f626162656c (32 bytes) - [source, goes into scriptSig] public_key_hex: 04e8ade66f2cc0e43073f4ccea47db279bbab1a5e30a6e8ba49f12538b215c5b9e0d28bd080d35fde878081e8f05dbc23eeba02b544fa83e6d13b5f2145681e76d (65 bytes) - [signable form] script_length_scriptPubKey: 19 (1 bytes) - [signable form] scriptPubKey: 76a9147dc03dfbe8c62821bcd1ab95446b88ed7008a76e88ac (25 bytes) - [more info] address: 1CTumCMjzBfccCJBTkHoPQmAwEqU9Uj2sQ - [more info] previous_output_index_int: 9 - [more info] txid: 8482e48391425d88fe30bd4066957000335f58e83f854f997146f41b9493b4ce DEBUG [531: createAndSignTransaction] Output 0: Output: {34 bytes} - [data] value: 5f0c030000000000 (8 bytes) - [data] script_length: 19 (1 bytes) - [data] scriptPubKey: 76a9140f9ee78522f6cc8a88784ae02b0408e452d8025988ac (25 bytes) - [more info] address: 12RbVkKwHcwHbMZmnSVAyR4g88ZChpQD6f - [more info] bitcoin_amount: 0.00199775 - [more info] satoshi_amount: 199775 - [more info] public_key_hash_hex: 0f9ee78522f6cc8a88784ae02b0408e452d80259 DEBUG [532: createAndSignTransaction] Transaction (unsigned form): {84 bytes} - version: 01000000 (4 bytes) - input_count: 01 (1 bytes) - Input 0: {40 bytes} -- previous_output_hash: ceb493941bf44671994f853fe8585f330070956640bd30fe885d429183e48284 (32 bytes) -- previous_output_index: 09000000 (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: 5f0c030000000000 (8 bytes) -- script_length: 19 (1 bytes) -- scriptPubKey: 76a9140f9ee78522f6cc8a88784ae02b0408e452d8025988ac (25 bytes) - block_lock_time: 00000000 (4 bytes) DEBUG [534: createAndSignTransaction] Transaction (signable form 0): {114 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: ceb493941bf44671994f853fe8585f330070956640bd30fe885d429183e48284 (32 bytes) -- previous_output_index: 09000000 (4 bytes) -- script_length_scriptPubKey: 19 (1 bytes) -- scriptPubKey: 76a9147dc03dfbe8c62821bcd1ab95446b88ed7008a76e88ac (25 bytes) -- sequence: ffffffff (4 bytes) - output_count: 01 (1 bytes) - Output 0: {34 bytes} -- value: 5f0c030000000000 (8 bytes) -- script_length: 19 (1 bytes) -- scriptPubKey: 76a9140f9ee78522f6cc8a88784ae02b0408e452d8025988ac (25 bytes) - block_lock_time: 00000000 (4 bytes) - hash_type_4_byte: 01000000 (4 bytes) DEBUG [535: createAndSignTransaction] Transaction (signed form): {223 bytes} - version: 01000000 (4 bytes) - input_count: 01 (1 bytes) - Input 0: {179 bytes} -- previous_output_hash: ceb493941bf44671994f853fe8585f330070956640bd30fe885d429183e48284 (32 bytes) -- previous_output_index: 09000000 (4 bytes) -- script_length: 8a (1 bytes) -- scriptSig: 47304402206a2eea0c908efbd780a34c48b48d80946a6e740c272468427bada3ba9773d39a022076017028c4386020b19b7d1f1640558cd902aeffbfbd85f4637a8be0e92ee1de014104e8ade66f2cc0e43073f4ccea47db279bbab1a5e30a6e8ba49f12538b215c5b9e0d28bd080d35fde878081e8f05dbc23eeba02b544fa83e6d13b5f2145681e76d (138 bytes) -- sequence: ffffffff (4 bytes) - output_count: 01 (1 bytes) - Output 0: {34 bytes} -- value: 5f0c030000000000 (8 bytes) -- script_length: 19 (1 bytes) -- scriptPubKey: 76a9140f9ee78522f6cc8a88784ae02b0408e452d8025988ac (25 bytes) - block_lock_time: 00000000 (4 bytes) INFO [540: createAndSignTransaction] Txid (little-endian double SHA256 hash of signed transaction): 4bdd5f653d0100ea4735953e8e22e92321af9074926b3bd33c279c289f2d975a INFO [214: main] Signed transaction: 0100000001ceb493941bf44671994f853fe8585f330070956640bd30fe885d429183e48284090000008a47304402206a2eea0c908efbd780a34c48b48d80946a6e740c272468427bada3ba9773d39a022076017028c4386020b19b7d1f1640558cd902aeffbfbd85f4637a8be0e92ee1de014104e8ade66f2cc0e43073f4ccea47db279bbab1a5e30a6e8ba49f12538b215c5b9e0d28bd080d35fde878081e8f05dbc23eeba02b544fa83e6d13b5f2145681e76dffffffff015f0c0300000000001976a9140f9ee78522f6cc8a88784ae02b0408e452d8025988ac00000000 Good. That's the end of this project.
iQIcBAABCgAGBQJf92bUAAoJEC8RP+HmG9MXqdIQAKSybLKD8bV6P/C6UvxA3AqE fF7WU8etrORyBK8jKnXYRygJjWjQyQQA8lrFjjY6iz956a2oNe3Tuip0ZXJk5psW jX0QMqFRWlLIcSlxacXUc/Si4hq+cOD0FfBFhqJlJyM7pbhatFi4IWax/H0lqRFF 0g/eFLJ0AKQvzE3SLCPNWowlDhqUJr0cPWF0c8A9Fi3CHsX35fw50hO/9CVIAdiL EZWJ0qjzqAKdLC8utI4lgEuHrIkoyfk//yvxIYm6xLllmGuZZnKd6gdLaXkHZLow w+puPv+UyQoiHTVncUtue73niaqgHd8pOSoOZcxqrwz5xx+k5SWZ8fmlfrod60+s nhqDVR/NQQShfuvUIXQW4J47q0keMBRi6M/B5aexKTBeLw/vRzmVGgKKxPI567pL Y+BoKb1U7YF1VrCWDQBNL1KjukXnnMDb+nY7N7kw32Du8cVVLuu7lYEkKHYa2Vzi 29GJN6F5ts1AQ0X44EeNUCYpiq5br7XY7LGeS/xPTKiPhmgcrq8oEyX3B/z9j115 8d0j6zQs/f1AUrJP528PBUWyWFJxwaW/ZJSpj9VPzQqgZNiYEV7MzT7QUHlOF4ki Ctwha2fWrTk0ylRNwYYcLKsCQr4JA44rD9s3KwqalUcFf97UVu428l+PN3t47dgJ //XmEpWJWVdLjAmNdef4 =Aym1
iQIcBAABCgAGBQJf92czAAoJECL1OzZgiBhwRmoQAI/OUeuEeLAJvrTkjMNvjdX0 wdfo88/aClcp7Ubdreo3SnD7NFJtQruWcaSHQkRThtgr35/1dc7CGovFnfVKdBLj WgbIppLZCQ2jKPImGiYiT2LQpTlHQX3cs+70L9y9yqDnavxMyPfZnF4eF4W8IsEK 0il6Eiz7XyjXFGf9NMqNNJ1ZQI8ctUE+LWGQOCvHF5AblionOB6r0N2KsF5weBss XqvDZf7/hqih7PVf169mJ5u+6RN7O79qVVgeQ2vaptRnhTm9pRHOYJpciUjYsYjR qZjS0lQnR/V5rRDzM/PnjxbN4ur5CSRRpjF8LJ2sEzrLUO9bKm5aBRKrkxgIVmoJ FBSHgcvgvopLI47P8f91HtirjzU+ltdJVg8mlEVUT4f4fHpiKcptGFjWLs4aobGa eDnonlRyzKhpEEmic0aiwO2NDdjvVPDgqtHF5HPQuvXxsR8t3I21bs5N3b9eeZsP DydIcmanowIK0osU9cUixlz7VuzPmBUzUJyH2S3ZAS6ldBxKZYcSzDHn7c7Um96S z2HQSvkKSy1h48BowU/77COluwf9gmCmUgHs898lvxPDyJZewiriCui48o4VWkLk doGw/TmOzJySBC7YoZBnNnt5dc6D3pFMsvTOpok2iHPRIb1glptT4iBixWjFL1yV MYlYkF4w/tOYzVyLGonA =GZwi