Author: StJohn Piano
Published: 2020-09-16
Datafeed Article 179
This article has been digitally signed by Edgecase Datafeed.
2077 words - 600 lines - 15 pages


This recipe describes a method for storing bitcoin on an online Windows 10 laptop.


- Description
- Contents
- Brief Summary
- Notes
- Equipment
- Services
- Recipe


Using an online Windows 10 laptop, complete the following tasks:
- generate a Bitcoin private key
- generate a Bitcoin address from the private key
- test the address by transferring some bitcoin into and out of it
- transfer some bitcoin into the address for long-term storage

Note: Storing bitcoin on an online laptop is more secure than storing it in a web application (e.g. a cryptocurrency exchange). However, it is less secure than storing it offline. Suggestion: Take a look at Recipe for storing bitcoin on paper using an offline Raspberry Pi #2.


Bitcoin is stored in a Bitcoin address.

An address holds "unspent outputs", which have been created by previous Bitcoin transactions. The sum of the values in the unspent outputs is the amount of bitcoin that is held in the address.

To transfer bitcoin, a transaction must be created, which will use one or more unspent outputs as inputs (i.e. spend them). The transaction's outputs will be new unspent outputs, which are now stored in the destination addresses.

The original address can be used as a destination address. This means that an input's value can be split, so that only some of it goes to an external destination address, and most returns to the original storage address.

This recipe uses Edgecase Bitcoin Storage Toolset version 2 (EBSTv2).


Required equipment for this recipe:
- An online Windows 10 laptop.
- A set of 5 dice and a tray with raised edges in which to roll them. Add a dust cloth on top of the tray to muffle the sound of the dice rolls.


You will need access to services that allow you to:

1) Send and receive bitcoin.

This will probably be an online exchange service.

Other possibilities: An online wallet service, someone you know who is willing to sell bitcoin to you, another Bitcoin storage system that you already own.

2) Look up the list of unspent outputs that are stored in a Bitcoin address.

You will need the following details for each unspent output:
- "txid": The txid of the original transaction that sent the unspent output to its current address. It is a 64-hex-character string.
- "previous_output_index": The index of the unspent output in the list of outputs in the original transaction. It is an integer.
- "satoshi_value": The value of the unspent output in satoshi. It is an integer. Alternatively, look up the Bitcoin value of the unspent output, which will be a decimal value with 8 decimal places.

Suggestion: Use this recipe:
Recipe for looking up the unspent outputs in a Bitcoin address #2

The linked recipe relies on a particular feature of a specific block explorer. If that feature is discontinued at some point in the future, you can use the previous version of that recipe, which requires more manual work, but can be used with any block explorer. Link:
Recipe for looking up the unspent outputs in a Bitcoin address

3) Look up current Bitcoin network transaction fee rates in satoshi / byte.

Suggestion: Consult the Other services page. It should list an active service that supplies this information.

4) Decode a signed transaction.

If a transaction can be successfully decoded, this shows that it is formatted correctly.

The Other services page should list an active transaction decoder service.

5) Broadcast a transaction to the Bitcoin network.

The Other services page should list an active transaction broadcast service.

6) Check the status of a transaction: Has it been mined? If so, how many confirmations has it received?

Use a block explorer. The Other services page should list an active block explorer.


Initial setup:
- Windows Subsystem for Linux (WSL) enabled
- A Linux distro installed on WSL
- Python 2.7.x installed on the Linux distro
- An account on an online cryptocurrency exchange

The Linux commands in this recipe can be run in a WSL Linux terminal.

Creating this initial setup is not covered in this recipe.

1) Check Python version

In a terminal, run the following command to check the version of Python.

python --version

The result must be Python 2.7.x. The code assets may not work as expected on e.g. Python 2.6.1.

2) Create a project directory.

Choose a location and create a new project directory named "storageProject".

Within it, create a subdirectory named "work".

3) Download assets.

Browse to the following article, go to the Downloadable Assets section, and download all the linked assets. The list of assets is shown below the link.

Edgecase Bitcoin Storage Toolset version 2:

- bitcoin_functions_2.py
- bjorn_edstrom_ripemd160.py
- convert_dice_rolls_to_hex_bytes_3.py
- create_nonstandard_transaction_3.py
- create_transaction_3.py
- ecdsa-0.10.tar.gz
- generate_bitcoin_address_4.py
- nonstandard_bitcoin_functions_2.py
- nonstandard_transaction_3.py
- pypy_sha256.py
- transaction_3.py

Move the assets into the work directory.

These assets will be required by various sub-recipes linked within this recipe.

4) Unpack the zipped tape archive file ecdsa-0.10.tar.gz.

This can be done by opening a terminal, changing directory to the work directory, and running the following command:
tar -zxvf ecdsa-0.10.tar.gz

This unpacking will produce a new directory named "ecdsa-0.10" in the work directory. The directory "ecdsa-0.10" will contain a directory named "ecdsa". Copy the "ecdsa" directory into the work directory. The copy operation can be performed using the following command:
cp -r ecdsa-0.10/ecdsa .

5) Generate a new Bitcoin private key.

A Bitcoin private key is 32 bytes. Using Recipe for generating entropy bytes using dice #2, generate 32 bytes of random entropy. This is a new private key.

Example Bitcoin private key:

Save the private key in the storageProject directory in a new text file named "privateKey.txt". For protection against typos, store several copies of the private key on consecutive lines.

The contents of the private key file should look like this:


Note: Some text editors, when you select a string and highlight it, highlight other identical strings in the document. This can be used as a quick test to confirm that all copies of the key are identical (i.e. that no copy has a typo).

You should make multiple copies of this key file. If it is lost, you will not be able to retrieve the bitcoin stored in it.

Do not share this private key with anyone else. Anyone who knows the private key can spend (i.e. take) the bitcoin stored in it.

Suggestion: Save a copy of the key file in another directory. Also, back up the key file to a memory stick.

6) Derive the corresponding Bitcoin address from the private key.

Use Recipe for generating a Bitcoin address #2.

Example Bitcoin address:

Save the address in the storageProject directory in a new text file named "address.txt". For protection against typos, store several copies of the address on consecutive lines.

Store the address file with the key file, so that you can easily match the key and the address to each other. Make backup copies of the address file, in the same way that you did for the key file.

7) Estimate the bitcoin required for testing the address.

To test the address, send some bitcoin to it, and then transfer it out again to a second address. This will confirm that you can successfully move bitcoin back out of the address.

Use the deposit address of your online exchange account as the second address. [0]

Look up the current Bitcoin network transaction fee rates in satoshi / byte. Choose a fee rate based on how much you're willing to pay and how long you're willing to wait for a transaction to be mined. Example: A transaction with a fee rate of 100 satoshi / byte might be estimated to be mined in 2-8 blocks. Later, when creating the test transaction, set its fee rate to be this value.

A standard 1-input 1-output Bitcoin transaction will be ~225 bytes. Multiply the fee rate by 225 to get the estimated transaction fee.

Check if your online exchange service charges a deposit fee. If it does, then add this fee to the estimated transaction fee.

Multiply this final amount by some factor, e.g. 2, so that you can tolerate a degree of change in the Bitcoin network's transaction fee rates.

Multiply by 0.00000001 to convert this satoshi amount to bitcoin (1 bitcoin == 10^8 satoshi).

8) Transfer the calculated amount of bitcoin to the address.

You can copy the address from the address.txt file in the project directory.

Use the online exchange service to make the transfer.

Wait for the transfer transaction to receive 6 confirmations.

9) Create and sign a Bitcoin transaction that will transfer the bitcoin in the address back to the deposit address of your online exchange account.

Look up the required information:
- The deposit address.
- The details of the unspent output in the test address:
-- the txid.
-- the previous output index.
-- the satoshi value (or bitcoin value).

Save the deposit address and the details in the project directory in a new text file named "details.txt".

Double-check the current fee rates.

If the deposit address is standard, use this recipe:
Recipe for creating and signing a standard Bitcoin transaction #2

Standard addresses start with the character '1'.

Example standard address:

Working definition of a standard address: An uncompressed single-signature Pay-To-Public-Key-Hash (P2PKH) address.

If the deposit address is nonstandard, use this recipe:
Recipe for creating and signing a nonstandard Bitcoin transaction #2

Example of a nonstandard address:
- A Pay-To-Script-Hash (P2SH) address.

Pay-To-Script-Hash (P2SH) addresses begin with the character '3'.

Example nonstandard P2SH address:

Now, using one of the linked sub-recipes for creating a transaction:
- Generate 32 bytes of new entropy for signing the transaction.
- Set the fee rate.
- Assign all the bitcoin value to the deposit address. Note: If there is some mistake, and some value is left over, this value will be assigned to the change address.
- Set the deposit address as the change address.
- Create and sign the transaction.

Example signed Bitcoin transaction:

Copy the signed transaction and save it in the project directory in a new text file named "signedTransaction.txt".

10) Broadcast the Bitcoin transaction.

Use a transaction decoder service to decode the transaction, which will confirm that its format is valid.

Use a transaction broadcast service to broadcast the transaction to the Bitcoin network.

Wait for the transaction to receive 6 confirmations.

If the transaction is not mined, follow this recipe:
Recipe for managing the fee and broadcast of a Bitcoin transaction #2

Once the transaction is mined with 6 confirmations, the test is complete. You can now move a large amount of bitcoin into this address and be certain that you can retrieve it.

The test has shown that the address is correctly derived from the private key. If you later construct a new transaction that turns out to be invalid, and discover that the cause was an error in the code stack used to create and sign a transaction, you know that eventually this error can be fixed and a valid transaction can be created. You risk only a temporary lack of access to the bitcoin stored in this address, not its permanent loss.

11) Use the tested Bitcoin address for long-term storage.

You can now transfer more bitcoin into this address for long-term storage.

Suggestion: If you would like to make paper backup copies of your private key and address, take a look at:
- How to write a Bitcoin private key on paper
- How to write a Bitcoin address on paper

Suggestion: If you would like to store bitcoin with a greater degree of security, take a look at:
- Effective offline storage of Bitcoin
- Recipe for storing bitcoin on paper using an offline Raspberry Pi #2

[start of footnotes]

Alternatively, you could create a second Bitcoin address yourself. By later transferring bitcoin from this second address back to the first address, you would have successfully tested both addresses.

[return to main text]

[end of footnotes]