edgecase_datafeed1892020-11-05
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.14492020-05-28bitcoinb27618deae05910f529240cc6960aeb87f017b12d302327253ee893825ce2bd46321001HtwyqFWNVDoSEVqZwjBRRAV2oEsi8aQXr13MfGs39pR5aEK4iKdoLjVYXKwi6Y3uyPqGenerating_a_standard_Bitcoin_address_#2stjohn_piano2020-11-03yes
GOAL
Develop a tool for generating a Bitcoin address from a private key. This tool should have a good command-line interface and a test suite.
CONTENTS
- Goal
- Contents
- Summary
- Downloadable Assets
- How To Use The Tools
- Project Log
SUMMARY
I developed:
- a tool for deriving a Bitcoin address from a private key.
- an accompanying test suite.
The tool has a useful command-line interface.
Please see the Downloadable Assets section for the tool and the test suite, and the How To Use The Tools section for instructions and examples.
DOWNLOADABLE ASSETS
Assets of this article:
List:
- private_key_to_address.py
- test_private_key_to_address.py
Asset: A tool that derives a Bitcoin address from a private key. Python 2.7.12.
assetprivate_key_to_address.pyprivate_key_to_address.pydc6da10180110faf728902eecc6c39da86312a7e82c2966b950cdf54a6a1ecaa
Asset: A test suite for the derivation tool. Python 2.7.12, Pytest 4.6.11.
assettest_private_key_to_address.pytest_private_key_to_address.py83b6d3501d7b8c7bee6101741b9317076f460a22feda76c0e3196f884c12678d
Assets of other articles:
List:
- bitcoin_functions_2.py
- bjorn_edstrom_ripemd160.py
- ecdsa-0.10.tar.gz
- pypy_sha256.py
Asset: A library of functions for handling standard Bitcoin data types. Python 2.7.
asset_of_another_articleCreating_a_Bitcoin_transaction_with_two_outputsedgecase85bitcoin_functions_2.pybitcoin_functions_2.py653f38ebab7f7c176ce7925364b5916c32b8e97ab5d4c00a66b990a0b6e0074c
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_articleReading_and_verifying_a_standard_raw_bitcoin_transactionedgecase51bjorn_edstrom_ripemd160.pybjorn_edstrom_ripemd160.pya5ca6eb289989861e30806ff7e39165622bd366a1c6cd5edd2dbd7dfc4877666
Asset: A Python implementation of ECDSA cryptography, written by Peter Pearson. Python 2.7.
asset_of_another_articleReading_and_verifying_a_standard_raw_bitcoin_transactionedgecase51ecdsa-0.10.tar.gzecdsa-0.10.tar.gz67dae9e1af2b0fd71bc9a378654f7dc89211c1c5aee71e160f8cfce1fa6d6980
Asset: A Python implementation of SHA256. Author unknown. Python 2.7.
asset_of_another_articleReading_and_verifying_a_standard_raw_bitcoin_transactionedgecase51pypy_sha256.pypypy_sha256.py2bbd4a83b69625e2f7ece5201475af2803f0ea11f3815c83d8afab3773d8f47b
Dependency tree:
- test_private_key_to_address.py
-- private_key_to_address.py
--- bitcoin_functions_2.py
---- bjorn_edstrom_ripemd160.py
---- ecdsa-0.10.tar.gz
---- pypy_sha256.py
HOW TO USE THE TOOLS
Help:
python private_key_to_address.py --help
Main:
python private_key_to_address.py -f privateKey.txt
Note: By default, the tool looks for a file named 'privateKey.txt' in its local directory, so in the above command the filepath argument is optional.
python private_key_to_address.py
Test:
pytest -q test_private_key_to_address.py
Note: The test suite file needs to be in the same directory as the tool file.
Examples:
stjohn@judgement:work$ python private_key_to_address.py --privateKeyFilePath privateKey.txt
1QAZz5b4MzqG64Loq3qsvAQiwHqweY7mbT
[same as above, but in shorthand]
stjohn@judgement:work$ python private_key_to_address.py -f privateKey.txt
1QAZz5b4MzqG64Loq3qsvAQiwHqweY7mbT
stjohn@judgement:work$ cat privateKey.txt
089f7ffa2076aeb36d09a0d095296116cf6e3a93a1fcce0ca31e7628c43001d8
[default privateKey filepath is 'privateKey.txt'.]
stjohn@judgement:work$ python private_key_to_address.py
1QAZz5b4MzqG64Loq3qsvAQiwHqweY7mbT
stjohn@judgement:work$ python private_key_to_address.py --privateKeyString 089f7ffa2076aeb36d09a0d095296116cf6e3a93a1fcce0ca31e7628c43001d8
1QAZz5b4MzqG64Loq3qsvAQiwHqweY7mbT
stjohn@judgement:work$ python private_key_to_address.py -f privateKey.txt --debug
INFO [92: deriveBitcoinAddress] Private key: 089f7ffa2076aeb36d09a0d095296116cf6e3a93a1fcce0ca31e7628c43001d8
INFO [94: deriveBitcoinAddress] Private key (WIF): 5Ht5r13wvzsUJKPoqCasYH1hpBCjKMgQkXE4e538CcQLHum2Uyz
INFO [96: deriveBitcoinAddress] Bitcoin address: 1QAZz5b4MzqG64Loq3qsvAQiwHqweY7mbT
1QAZz5b4MzqG64Loq3qsvAQiwHqweY7mbT
stjohn@judgement:work$ pytest -q test_private_key_to_address.py
........................ [100%]
24 passed in 2.94 seconds
PROJECT LOG
The
articleEdgecase_Bitcoin_Storage_Toolset_version_2edgecase148Edgecase Bitcoin Storage Toolset version 2
already contains a tool for generating a bitcoin address from a private key, called:
generate_bitcoin_address_4.py
I'll reuse the underlying code from it and its dependencies.
The previous project
articleGenerating_entropy_from_dice_#2edgecase188Generating entropy from dice #2
contains an good command-line tool and test suite. I'll use the same approach.
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:
"generating_a_standard_bitcoin_address_2"
Browse to the linked EBSTv2 article and download the various assets for the address generation tool.
Dependency tree:
- generate_bitcoin_address_4.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.
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.
I'll use the data from the previous project
articleBitcoin_address_test_setedgecase146Bitcoin address test set
when writing tests.
[development work occurs here.]
I've written a tool for generating a bitcoin address from a private key, and an accompanying test suite:
- private_key_to_address.py
- test_private_key_to_address.py
Let's record some examples of using
private_key_to_address.py
stjohn@judgement:work$ python private_key_to_address.py --help
usage: private_key_to_address.py [-h] [-f PRIVATEKEYFILEPATH]
[-p PRIVATEKEYSTRING]
[-l {debug,info,warning,error}] [-d]
Derive a Bitcoin address from a Bitcoin private key.
optional arguments:
-h, --help show this help message and exit
-f PRIVATEKEYFILEPATH, --privateKeyFilePath PRIVATEKEYFILEPATH
path to file containing the private key (default:
'privateKey.txt').
-p PRIVATEKEYSTRING, --privateKeyString PRIVATEKEYSTRING
private key passed as a direct argument. This
overrides --privateKeyFilePath.
-l {debug,info,warning,error}, --logLevel {debug,info,warning,error}
Choose logging level (default: 'error').
-d, --debug Sets logLevel to 'debug'. This overrides --logLevel.
Supplementary Notes:
- A standard Bitcoin address is an uncompressed single-signature Pay-To-Public-Key-Hash (P2PKH) address.
- A Bitcoin private key is a sequence of 32 bytes. In hex, 1 byte is written as two characters. So, a private key written in hex is 64 characters.
-- Example:
089f7ffa2076aeb36d09a0d095296116cf6e3a93a1fcce0ca31e7628c43001d8
stjohn@judgement:work$ cat privateKey.txt
089f7ffa2076aeb36d09a0d095296116cf6e3a93a1fcce0ca31e7628c43001d8
stjohn@judgement:work$ python private_key_to_address.py --privateKeyFilePath privateKey.txt
1QAZz5b4MzqG64Loq3qsvAQiwHqweY7mbT
[same, but in shorthand]
stjohn@judgement:work$ python private_key_to_address.py -f privateKey.txt
1QAZz5b4MzqG64Loq3qsvAQiwHqweY7mbT
[Note: By default, the tool looks for a file named 'privateKey.txt' in its local directory, so the filepath argument is optional.]
stjohn@judgement:work$ python private_key_to_address.py
1QAZz5b4MzqG64Loq3qsvAQiwHqweY7mbT
stjohn@judgement:work$ python private_key_to_address.py --privateKeyString 089f7ffa2076aeb36d09a0d095296116cf6e3a93a1fcce0ca31e7628c43001d8
1QAZz5b4MzqG64Loq3qsvAQiwHqweY7mbT
[same, but in shorthand]
stjohn@judgement:work$ python private_key_to_address.py -p 089f7ffa2076aeb36d09a
0d095296116cf6e3a93a1fcce0ca31e7628c43001d8
1QAZz5b4MzqG64Loq3qsvAQiwHqweY7mbT
stjohn@judgement:work$ python private_key_to_address.py -f privateKey.txt --debug
INFO [92: deriveBitcoinAddress] Private key: 089f7ffa2076aeb36d09a0d095296116cf6e3a93a1fcce0ca31e7628c43001d8
INFO [94: deriveBitcoinAddress] Private key (WIF): 5Ht5r13wvzsUJKPoqCasYH1hpBCjKMgQkXE4e538CcQLHum2Uyz
INFO [96: deriveBitcoinAddress] Bitcoin address: 1QAZz5b4MzqG64Loq3qsvAQiwHqweY7mbT
1QAZz5b4MzqG64Loq3qsvAQiwHqweY7mbT
stjohn@judgement:work$ python private_key_to_address.py -f privateKey.txt --logLevel=info
- Private key: 089f7ffa2076aeb36d09a0d095296116cf6e3a93a1fcce0ca31e7628c43001d8
- Private key (WIF): 5Ht5r13wvzsUJKPoqCasYH1hpBCjKMgQkXE4e538CcQLHum2Uyz
- Bitcoin address: 1QAZz5b4MzqG64Loq3qsvAQiwHqweY7mbT
1QAZz5b4MzqG64Loq3qsvAQiwHqweY7mbT
And some examples of testing the tool.
stjohn@judgement:work$ pytest test_private_key_to_address.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/generating_a_standard_bitcoin_address_2/work
collected 24 items
test_private_key_to_address.py ........................ [100%]
========================== 24 passed in 1.52 seconds ===========================
stjohn@judgement:work$ pytest test_private_key_to_address.py --quiet
........................ [100%]
24 passed in 1.44 seconds
stjohn@judgement:work$ pytest test_private_key_to_address.py::test_one --quiet
. [100%]
1 passed in 0.03 seconds
stjohn@judgement:work$ pytest -o log_cli=true --log-cli-level=DEBUG --log-format="%(levelname)s [%(lineno)s: %(funcName)s] %(message)s" test_private_key_to_address.py::test_one
============================= 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/generating_a_standard_bitcoin_address_2/work
collected 1 item
test_private_key_to_address.py::test_one
-------------------------------- live log call ---------------------------------
INFO [92: deriveBitcoinAddress] Private key: 0000000000000000000000000000000000000000000000000000000000000001
INFO [94: deriveBitcoinAddress] Private key (WIF): 5HpHagT65TZzG1PH3CSu63k8DbpvD8s5ip4nEB3kEsreAnchuDf
INFO [96: deriveBitcoinAddress] Bitcoin address: 1EHNa6Q4Jz2uvNExL497mE43ikXhwF6kZm
PASSED [100%]
=========================== 1 passed in 0.05 seconds ===========================
stjohn@judgement:work$ pytest -o log_cli=true --log-cli-level=DEBUG --log-format="%(levelname)s [%(lineno)s: %(funcName)s] %(message)s" test_private_key_to_address.py::test_pair_1
============================= 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/generating_a_standard_bitcoin_address_2/work
collected 1 item
test_private_key_to_address.py::test_pair_1
-------------------------------- live log call ---------------------------------
INFO [92: deriveBitcoinAddress] Private key: 0000000000000000000000007468655f6c6962726172795f6f665f626162656c
INFO [94: deriveBitcoinAddress] Private key (WIF): 5HpHagT65TZzG1PH3CdWbVZG75U59A8FphH7EtKwbFCZf3p6bjg
INFO [96: deriveBitcoinAddress] Bitcoin address: 1CTumCMjzBfccCJBTkHoPQmAwEqU9Uj2sQ
PASSED [100%]
=========================== 1 passed in 0.11 seconds ===========================
Good. That's the end of this project.
List of previous tools for deriving Bitcoin addresses from private keys, together with the projects in which they were published:
Tool 1:
asset_of_another_articleGenerating_a_standard_Bitcoin_addressedgecase54generate_bitcoin_address.pygenerate_bitcoin_address.py70f1288a5957ffc02dd43625446043b27c4132c02a609ea959a574f7ff6af563
Project:
articleGenerating_a_standard_Bitcoin_addressedgecase54Generating a standard Bitcoin address
Tool 2:
asset_of_another_articleVerifying_a_signed_deed_of_the_GPG_1.4.10_source_codeedgecase60generate_bitcoin_address_2.pygenerate_bitcoin_address_2.py18be6cc5c66f9f672bf2247184b416340a9309de789f9737714d17efffb67a4e
Project:
articleVerifying_a_signed_deed_of_the_GPG_1.4.10_source_codeedgecase60Verifying a signed deed of the GPG 1.4.10 source code
Tool 3:
asset_of_another_articleCreating_and_signing_a_standard_raw_Bitcoin_transaction:_Iteration_#2edgecase63generate_bitcoin_address_3.pygenerate_bitcoin_address_3.pyb18c438fe479095eff17702c52968309351b6e5f9d147758ce5924b116f5a8ef
Project:
articleCreating_and_signing_a_standard_raw_Bitcoin_transaction:_Iteration_#2edgecase63Creating and signing a standard raw Bitcoin transaction: Iteration #2
Tool 4:
asset_of_another_articleEdgecase_Bitcoin_Storage_Toolset_version_2edgecase148generate_bitcoin_address_4.pygenerate_bitcoin_address_4.pyf8fad8e3c31555b9ff309d52fca360a9e22ea0f8b3689bfa9fc8e6370339f456
Project:
articleEdgecase_Bitcoin_Storage_Toolset_version_2edgecase148Edgecase Bitcoin Storage Toolset version 2
iQIcBAABCgAGBQJfo92nAAoJEC8RP+HmG9MX6OgP/0Z0aqufmfR2i6RWAzKoWlXy
NwI02O2p7AtybNSKAkrkwD+nI67aUdH94zqTvFzjBXdDFM78rxefORtTwZL2jcAl
Qk6eRiyDDkiWijCGImcwBvSnF3ULdjm0+ooBIuzBEOCI508KClnSNfHFGPXT+Mlo
Ge3uM+fgo3aY2autNijtrnmlsLVbz9LBwLx8HOtD8e7EIXv/jRM/RPEfd/P5C7VE
UvXId7M4jpNJaVA9Spy+PE3fjzCE6TKNtYv/M6fsG0zai4wlO4Z/mpnDGOCSk1A2
mm9BO9E9xo7glTo7D6SizwZzGxWDOXrJnC+QqTp7Y/6uZJspBr+1Ksl+VHCF3etJ
DG7gYuZfLIsrloK2M5MuMXFELsrMlumhySemHtWqNkW1Hwg0cmp4K7/addt+roxE
bAmecyapNyWDdoaAGjqq5vpGzLRImkmCUKqmIhNePf+5RD5VeQBO5NDwKDD0/uXF
cUleaONiFqyA5EbaYEGYsR5f646vOXXWdDNjJmQTNSz4wCqDhU7sHQDPVSX7lrF4
20oxROYzT8C43rpnlL4W/Vp47QV4L3Ruo/Cb1spAWTnoJDcftCZYrWDSRfsQGz+I
aySgENzf6v+1oWfZ3ukdffSfP17mPPs3vk/2gPjtGZLq2f5lafz/jKQ/EPf6VId6
Ezohq9RIuLXuln5jEbN1
=wTeG
iQIcBAABCgAGBQJfo935AAoJECL1OzZgiBhw5zEP/AxZuMIPBt3DLtoGcmcTFF2G
iyBgVNm2OAcFBxPD7yy43nWABtvEqAQpvKPDpBjThtlaOAf8uUZ+Dsbd63wU78LY
aOgwQLImZWXm+HbU8PEpeSXUe1+ti1/eX+xt8A3BYtazTcv6wFlo9oWhQZvgrucF
tOLF3fI+7KXSsXRUMwtPvUTAmZCRtgqEhjTKg8ymvn3vsETDTP/WDQnLGRXeJ4Aw
iWAQ53NF4/+smKN8v6qQbUEgretFqTKacISMxQcD3TgvtWS/Zo2RQkhZwIXmLfQv
5+8+8YPKPHz30b0kiqkjrD4I0DMySl5vhl4bBh7sALcz74gajp8yyeJ5CaCSj0yT
6jnjjTRB38RL21pA7rLDi+vosJHHgVP71EUsBtjIShfoziT6WuXBhRRcHgpBREAS
+qq8j7uyYWAirn6TuDbIDIbRgvvdo4vK+HO3zsM020sC6zCEQHqNO/w4oanLNgvR
sKl4zLF5ujCzwyc2/qGH19aEjBQSTOBASXOglD1SZTxpq/fd1cE+nHq2rNf0ZyMu
3t+JW5/SFjRAo7Xmy2aRFvkZqMYiayQU6g8L1hGxbZquEVindKAR2jwhSwIAH5zg
wYBJfQ8iMEE0+c3zZKA6rZPnReDzGQQkCRZvsTsRJGNeG+DI7SwqTfP1F1hPVd9C
hkn+a6zlRwLjEEByovKh
=NMNU