edgecase
[Regarding self-sabotaging behaviour]
There's a lot of responsibility with success, so if you say yes to things and you do a good job and you bear a large burden, then you have to carry it, and a lot of that might be success, but... failure is a lot easier than success, plus you can complain about it and whine about it and be a victim, and garner all sorts of kudos from yourself and others that way, so there's that. It's just failure to adopt responsibility.
But then I would say too: There's also revenge on the Self and God. That's partly why I liked the Cain and Abel story so much, once I figured out what it meant.
People have a hard time not having the kind of contempt that borders on self-hatred for themselves, partly because we are fragile and mortal creatures and prone to error and malevolence, and we know that of ourselves better than anyone else, and because we know that we're prone to punish ourselves and to think ill of ourselves.
~ Jordan Peterson
Author: StJohn Piano
Published: 2018-12-06
Datafeed Article 75
This article has been digitally signed by Edgecase Datafeed.
This article has been digitally signed by its author.
29864 words - 10629 lines - 266 pages





GOAL



Store bitcoin on an offline Raspberry Pi.




CONTENTS



- Goal
- Contents
- Brief Summary
- Summary
- Recipe For Managing The Fee And Broadcast Of A Bitcoin Transaction #2
- Recipe For Manually Mounting A USB Memory Stick
- Representative Sample Of Bash Commands Used
- Downloadable Assets
- Notes
- Financial Information For This Project
- Further Work
- Project Log




BRIEF SUMMARY



I generated an address on an offline Raspberry Pi. I tested this address by successfully transferring a small amount of bitcoin into and out of it, proving that I could always retrieve bitcoin from it.

I then transferred a larger amount of bitcoin into the address, and stored it there for a week.

Note: All transactions were constructed and signed offline, then manually transferred to an online computer for broadcasting.






SUMMARY





Goal


Store bitcoin on an offline Raspberry Pi.




Overall results:


- I generated an address (the "test address") on an offline Raspberry Pi.
- I validated the test address by successfully transferring a small amount of bitcoin into and out of it. This allowed me to be certain that I could retrieve bitcoin from it.
- I stored a larger amount of bitcoin in the test address for a week, before transferring it back to an exchange service.
- All transactions were constructed and signed offline, then manually transferred to an online computer for broadcasting.




Original plan of action for this project:


- Download necessary code from previous articles.

- Create a private key. Store it on the Raspberry Pi. This will require generating entropy.

- Generate a Bitcoin address from the private key.

- Test this address by transferring some bitcoin into and out of it.

- Store a larger amount of bitcoin in the address.

- The private key will of course be revealed in the article describing this project, so this bitcoin won't be stored permanently in this address. Instead, I'll transfer the bitcoin out again. To store some bitcoin, a reader can follow all the steps apart from this one.




What I actually did during the project:


0) My equipment is listed in the "Equipment" part of the Notes section.

1) I chose this set of previous articles:
- Recipe for generating entropy bytes using dice
- Recipe for generating a Bitcoin address
- Recipe for creating and signing a standard Bitcoin transaction
- Recipe for creating and signing a nonstandard Bitcoin transaction
- Displaying hex bytes for manual copying

2) I downloaded all the assets linked from these articles. Note: Some assets are linked from more than one of these articles.

List of downloaded assets:

- bitcoin_functions.py
- bjorn_edstrom_ripemd160.py
- convert_dice_rolls_to_hex_bytes_2.py
- create_nonstandard_transaction.py
- create_transaction.py
- display_hex_bytes.py
- ecdsa-0.10.tar.gz
- generate_bitcoin_address_3.py
- nonstandard_bitcoin_functions.py
- nonstandard_transaction.py
- pypy_sha256.py
- transaction.py

These assets are linked in the Downloadable Assets section.

3) Using a memory stick, I transferred these assets from my work computer Aineko to the Raspberry Pi. To find out how to do this, please see the section Recipe For Manually Mounting A USB Memory Stick.

4) I logged commands and command output on the Raspberry Pi. Please see the "Recording shell output" part of the Notes section for details. Later, I transferred these logs back to Aineko for integration into this article.

5) I checked and recorded some details about the Raspberry Pi (its operating system, the versions of various tools).

6) I generated a private key using dice and stored it on the Raspberry Pi. I then derived the corresponding Bitcoin address, which I called the "test address".

Note: Files containing the various dice roll results are listed in the Downloadable Assets section. The entropy values derived from these files are included in the "Entropy values generated during this project" part of the Notes section.

7) I calculated an amount of bitcoin to use for validating the test address. Details are included in the section Financial Information For This Project. I used LocalBitcoins to transfer some bitcoin to the test address. LocalBitcoins created a transaction that included this transfer. I named this transaction "tx0".

8) I used a service to obtain information about tx0. Some of this information was needed for constructing a transaction that spent from the test address.

Note: I used various services during this project. They are listed in the "Services used during this project" part of the Notes section.

9) I created a transaction on the offline Raspberry Pi that transferred the available bitcoin from the test address to receiving address 1 (on my LocalBitcoins account). I named this transaction "tx1" and later "tx1a". I used a transaction-broadcasting service to broadcast it to the Bitcoin network. This transaction was never mined. LocalBitcoins saw this transaction and generated a new receiving address for my account, "receiving address 2".

Note: All transactions in this project were manually transferred to the online computer (Aineko) from the offline Raspberry Pi. I used the display_hex_bytes.py tool to display the transaction hex bytes in a more easily-read format.

Note: The addresses used in this project are listed in the "Addresses generated and/or used in this project" part of the Notes section.

Note: The transactions that I created in this project are displayed in the "Transactions created during this project" part of the Notes section. Details about the transactions that LocalBitcoins created are also included.

10) I created a transaction on the offline Raspberry Pi that transferred the available bitcoin from the test address to receiving address 2. I called this transaction "tx1b". This transaction was rejected by two transaction-broadcasting services, because it was a double-spend attempt (it tried to spend the same unspent output as tx1a did, but to a different address, while tx1a was still in the memory pools of the services). I was thinking about the fee rate change and had forgotten that the Bitcoin network would perceive it as a double-spend attempt.

Note: Several points concerning Bitcoin transactions:
- New transactions spend unspent-outputs-of-previous-transactions. These can also be called "inputs".
- The bitcoin balance of an address is the sum of the unspent outputs sent by previous transactions to this address.
- To spend bitcoin from an address, the bitcoin amount must be constructed from complete inputs. Any change can be sent in a new unspent output back to the original address or to another address that you control. Inputs cannot be broken into smaller inputs prior to spending - new inputs (larger or smaller) must be created by a new transaction.

11) I created a transaction on the offline Raspberry Pi that transferred the available bitcoin from the test address to receiving address 1, using a higher fee than in tx1a. I called this transaction "tx1c". This was a replace-by-fee transaction (only the fee was different), which is valid on the Bitcoin network (unlike a double-spend transaction), but the two transaction-broadcasting services still rejected it. I waited until tx1a had been cleared from the memory pool of one of the transaction-broadcasting services (this took about 48 hours), and then uploaded tx1c again to that service. This time, the service accepted tx1c, which was later mined.

Note: A recipe for making replace-by-fee transactions is included in the section Recipe For Managing The Fee And Broadcast Of A Bitcoin Transaction #2.

Note: A new entropy value is needed for each transaction signature.

Note: The times taken for confirmation of tx1c and tx3 are shown in the "Transaction confirmation times" part of the Notes section.

12) The successful mining of tx1c validated the test address. It proved that the address was correctly calculated from the private key. I could now move a large amount of bitcoin into this address and be certain that I could retrieve it. Even if I later constructed a new transaction that turned out to be invalid, and discovered that the cause was an error in the code stack used to create and sign a transaction, I knew that eventually this error could be fixed and a valid transaction could be created. I would only risk a temporary lack of access to the bitcoin stored in this address, not its permanent loss.

13) I used LocalBitcoins to transfer a relatively larger amount of bitcoin ($50 worth at the then-current exchange rate) to the test address. LocalBitcoins created a transaction that included this transfer. I named this transaction "tx2".

14) I used a service to obtain information about tx2. Some of this information was needed for constructing a transaction that could spend from the test address (more specifically: could spend the unspent output that tx2 sent to the test address).

15) A week passed, during which $50 worth of bitcoin was stored on the Raspberry Pi.

16) I created a transaction on the offline Raspberry Pi that transferred the available bitcoin from the test address to receiving address 2 (on my LocalBitcoins account). I named this transaction "tx3". I used a transaction-broadcasting service to broadcast it to the Bitcoin network. After a while, tx3 was mined.

17) This project was now completed. I had approximately carried out the original plan of action, with a deviation (tx1b) and a significant amount of extra detail and additional steps.




Notes section:


The Notes section contains the following parts:

- Definitions and acryonyms
- Services used during this project
- Equipment used during this project
- Entropy values generated during this project
- Addresses generated and/or used in this project
- Transactions created during this project
- create_nonstandard_transaction.py settings used to create the transactions
- Time taken to manually transfer transactions by typing
- Transaction confirmation times
- Dice rolling results
- Recording shell output
- Miscellaneous






RECIPE FOR MANAGING THE FEE AND BROADCAST OF A BITCOIN TRANSACTION #2



A previous recipe with this title was published in the article Creating and signing a standard raw Bitcoin transaction, in the section Recipe For Managing The Fee And Broadcast Of A Bitcoin Transaction.


Objectives:
- Fine control of the transaction fee.
- Ability to rebroadcast a new transaction with a higher fee if the previous transaction is not mined within a reasonable time period. This new transaction, if mined, should invalidate the previous transaction.

Several points concerning Bitcoin transactions:
- New transactions spend unspent-outputs-of-previous-transactions. These can also be called "inputs".
- The bitcoin balance of an address is the sum of the unspent outputs sent by previous transactions to this address.
- To spend bitcoin from an address, the bitcoin amount must be constructed from complete inputs. Any change can be sent in a new unspent output back to the original address or to another address that you control. Inputs cannot be broken into smaller inputs prior to spending - new inputs (larger or smaller) must be created by a new transaction.


1) Gather the required data for a new transaction. How to do this is not specified in this recipe. Include at least one "change address" output. Inputs should be added as necessary to achieve the desired output values. The sum of the inputs may be greater than the sum of the desired output values, i.e. some bitcoin may be left over. This left-over bitcoin should be sent to the change address output. Include an additional input that is specifically for paying the as-yet-unknown transaction fee. Set the bitcoin in this input to be sent to the change address output.

2) Look at current Bitcoin network transaction fee rates. How to do this is not specified in this recipe. Choose a fee rate for the transaction.

3) Use a software tool to create and sign a transaction with the specified fee rate. This tool must be able to calculate an estimate of the transaction size in order to derive a fee value from the fee rate. This fee value will be stored implicitly in the transaction as the difference between the input values and the output values. After the tool has created and signed the transaction, it should calculate and report the actual fee rate of the final signed form of the transaction. The process / structure of the software tool is not specified in this recipe.

4) Broadcast the transaction to the Bitcoin network or upload the transaction to a service that can do this for you. How to do this is not specified in this recipe.

5) A node will store unconfirmed transactions in its memory pools for a particular time period. If the transaction is not mined (confirmed) within this period, the node will delete it from its memory pool. This period will vary depending on the node. Some reading indicates that the default period is 72 hours (3 days). I have tried this once during this project - the delay was about 48 hours (2 days). After broadcasting the transaction, wait 3 days + a small delay. If the transaction is mined during this period, stop here (and wait for the transaction to be 6 blocks deep in the Bitcoin blockchain). Otherwise, confirm that it has been deleted from the relevant node's memory pool (by e.g. looking up the transaction's txid) and continue to step (6).

Note: If you run a node that accepts replace-by-fee transactions (or have access to a service that does this), then you can upload a new version of the transaction immediately, without waiting for it to be removed from the node's memory pool. If there exists a path through the Bitcoin network from your node to a miner's node, consisting of nodes that all accept replace-by-fee transactions, then the new version of your transaction will propagate along this path, allowing you to quickly replace an unconfirmed transaction with a new version. The miner's node will probably be set to accept replace-by-fee transactions for mining, as this is necessarily more profitable.

6) Look at current Bitcoin network transaction fee rates. How to do this is not specified in this recipe. Choose a higher fee rate than the one chosen in step (2).

7) Repeat steps (2)-(6) until the transaction is mined.


Note: If a transaction disappears from the network (i.e. the memory pools of all public nodes), this doesn't mean that it has vanished permanently. Anyone who stored it can rebroadcast it later - it will still be valid. In order to make it invalid, create a new transaction that uses at least one of the same inputs.

Note: An input in a transaction is an as-yet-unspent output of a previous transaction. Each unspent output can only ever be spent once. If a transaction is broadcast that uses at least one input that has already been spent, this transaction is invalid and will not be mined.






RECIPE FOR MANUALLY MOUNTING A USB MEMORY STICK



0) Copy data that you wish to transfer to the destination computer into a directory named "work", located at the top level of the filesystem on the memory stick.


1) Insert the memory stick into a USB port on the destination computer.


2) If you are using a command-line interface, skip this step. If you are using a graphical user interface, open a terminal emulator.


3) Use the following command sequence to manually mount the memory stick (i.e. make its filesystem accessible).

[Make a new directory to be the mount point for the memory stick. Making this new directory in the /mnt directory requires root permissions, so "sudo" is used.]
pi@raspberrypi ~/test $ sudo mkdir /mnt/memory_stick_mount_point


[List items in the directory "/mnt"]
pi@raspberrypi ~/test $ ls -1 /mnt

memory_stick_mount_point

[List items in the directory "/dev" that begin with "sda"]
pi@raspberrypi ~/test $ ls -1 /dev/sda*

/dev/sda
/dev/sda1

[Mount the memory stick located (metaphorically) at the device file /dev/sda1 to the directory /mnt/memory_stick_mount_point]
pi@raspberrypi ~/test $ sudo mount -o uid=pi,gid=pi /dev/sda1 /mnt/memory_stick_mount_point


[
Note that:

-o (lowercase letter "o", not the number zero) specifies that an option string follows.

uid=pi,gid=pi specifies that the user ID is "pi" and the group ID is "pi" (note there are no spaces allowed between these two terms).

/dev/sda1 is the first partition on the first USB memory stick that the computer can detect. [Future: Investigate whether this is accurate.]
]

[List the contents of the top directory in the memory stick filesystem]
pi@raspberrypi ~/test $ ls -1 /mnt/memory_stick_mount_point

work



4) Use the following commands to copy data to and from the memory stick.

[List items in the current directory, one line per item]
pi@raspberrypi ~/test $ ls -1

work.log

[Make a new directory to hold a copy of the contents of the memory stick]
pi@raspberrypi ~/test $ mkdir memory_stick_contents


[Copy the contents of the "work" directory on the memory stick to the directory "memory_stick_contents"]
pi@raspberrypi ~/test $ cp -r /mnt/memory_stick_mount_point/work/* memory_stick_contents


[List the contents of the directory "memory_stick_contents"]
pi@raspberrypi ~/test $ ls -1 memory_stick_contents

bitcoin_functions.py
bjorn_edstrom_ripemd160.py
convert_dice_rolls_to_hex_bytes_2.py
create_nonstandard_transaction.py
create_transaction.py
display_hex_bytes.py
ecdsa-0.10.tar.gz
generate_bitcoin_address_3.py
nonstandard_bitcoin_functions.py
nonstandard_transaction.py
pypy_sha256.py
transaction.py

[Copy the file "work.log" to the memory stick]
pi@raspberrypi ~/test $ cp work.log /mnt/memory_stick_mount_point


[List the contents of the top directory in the memory stick filesystem. This allows you to confirm that the file has been copied over.]
pi@raspberrypi ~/test $ ls -1 /mnt/memory_stick_mount_point

work
work.log



5) Use the following command sequence to unmount the memory stick. Once unmounted, it can be physically unplugged without causing any problems.

[Unmount the memory stick]
pi@raspberrypi ~/test $ sudo umount /mnt/memory_stick_mount_point


[confirm that it has been unmounted]
pi@raspberrypi ~/test $ ls -1 /mnt/memory_stick_mount_point

[nothing should be displayed]



6) Unplug the memory stick from the destination computer.








REPRESENTATIVE SAMPLE OF BASH COMMANDS USED



Note: The output is not always included for every command.


[Print the path of the current working directory (pwd = "print working directory")]
pi@raspberrypi ~ $ pwd

/home/pi

[Make a directory named "test"]
pi@raspberrypi ~ $ mkdir test


[Change directory to "test"]
pi@raspberrypi ~ $ cd test


[Create a file named "work.log"]
pi@raspberrypi ~/test $ touch work.log


[List items in the current directory, one line per item]
pi@raspberrypi ~/test $ ls -1

work.log

[List items in the directory "/dev" that begin with "sda"]
pi@raspberrypi ~/test $ ls -1 /dev/sda*

/dev/sda
/dev/sda1

[Make a new directory to be the mount point for the memory stick. Making this new directory in the /mnt directory requires root permissions, so "sudo" is used.]
pi@raspberrypi ~/test $ sudo mkdir /mnt/memory_stick_mount_point


[List items in the directory "/mnt"]
pi@raspberrypi ~/test $ ls -1 /mnt

drive1
memory_stick_mount_point

[Mount a memory stick located at the device file /dev/sda1 to the directory /mnt/memory_stick_mount_point]
pi@raspberrypi ~/test $ sudo mount -o uid=pi,gid=pi /dev/sda1 /mnt/memory_stick_mount_point


[Copy the contents of the "work" directory on the memory stick to the directory "memory_stick_contents"]
pi@raspberrypi ~/test $ cp -r /mnt/memory_stick_mount_point/work/* memory_stick_contents


[Check the kernel version]
pi@raspberrypi ~/test $ uname -r


[Edit a file using the Nano text editor. If the file does not exist, it will be created.]
pi@raspberrypi ~/test $ nano dice_rolls.txt


[Copy last 10 lines of work.log to a new file named "private_key.txt"]
pi@raspberrypi ~/test $ tail -10 work.log > private_key.txt


[Print the contents of a file]
pi@raspberrypi ~/test $ cat private_key.txt

c592e1dad5e9871fdeffb551b4544b0a1cf0378c6371d7a397ff5faf04c934ca

[Get the byte length of the contents of a file. Use
tr
to remove the newline character at the end of the file.]
pi@raspberrypi ~/test $ cat private_key.txt | tr -d '\n' | wc -c

64

[Copy a file from the "memory_stick_contents" directory to the working directory]
pi@raspberrypi ~/test $ cp memory_stick_contents/bjorn_edstrom_ripemd160.py bjorn_edstrom_ripemd160.py


[Unpack the zipped tape archive file ecdsa-0.10.tar.gz]
pi@raspberrypi ~/test $ tar -zxvf ecdsa-0.10.tar.gz


[Copy the "ecdsa" directory (along with its contents) into the work directory.]
pi@raspberrypi ~/test $ cp -r ecdsa-0.10/ecdsa ecdsa


[Copy the file "work.log" to the memory stick (via its mountpoint directory)]
pi@raspberrypi ~/test $ cp work.log /mnt/memory_stick_mount_point


[Unmount the memory stick]
pi@raspberrypi ~/test $ sudo umount /mnt/memory_stick_mount_point


[Print an excerpt from a file. In this case, print lines 40-66 inclusive.]
pi@raspberrypi ~/test $ cat create_nonstandard_transaction.py | sed -n '40,66p'


[Read a file "tx_copied.txt", removing all space and newline characters, and writing the result to a new file "tx.txt"]
aineko:work stjohnpiano$ cat tx_copied.txt | tr -d ' \n' > tx.txt


[Append a newline to a file]
aineko:work stjohnpiano$ echo '' >> tx.txt




Example of logging into a Raspberry Pi using the default credentials (username = "pi", password = "raspberry"). Note that the password is not printed to the screen.

[Insert the power cable into the Raspberry Pi. Wait for it to boot up.]

raspberrypi login: pi


Password:


Last login: Sun Mar 27 18:28:14 UTC 2016 on tty1
Linux raspberrypi 4.1.13+ #826 PREEMPT Fri Nov 13 20:13:22 GMT 2015 armv61

The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.

pi@raspberrypi ~ $




Example of shutting down a Raspberry Pi:

pi@raspberrypi ~/test $ sudo halt

[a variety of output is printed, then the Raspberry Pi shuts down]


[Then unplug the power cable.]








DOWNLOADABLE ASSETS



This article's assets are files containing 5 sets of 212 dice rolls. 32 bytes of entropy were derived from each set.

List of assets:
- dice_rolls_3.txt (known during this project as dice_rolls.txt)
- dice_rolls_4.txt (known during this project as dice_rolls2.txt)
- dice_rolls_5.txt (known during this project as dice_rolls3.txt)
- dice_rolls_6.txt (known during this project as dice_rolls4.txt)
- dice_rolls_7.txt (known during this project as dice_rolls5.txt)

The asset names have been changed because this datafeed already contains some existing assets with the prefix "dice_rolls".

Asset: Set 1 of the dice roll results
dice_rolls_3.txt

Asset: Set 2 of the dice roll results
dice_rolls_4.txt

Asset: Set 3 of the dice roll results
dice_rolls_5.txt

Asset: Set 4 of the dice roll results
dice_rolls_6.txt

Asset: Set 5 of the dice roll results
dice_rolls_7.txt



The following code assets were developed / tested on my work computer during previous projects. During this project, I used them successfully on the offline computer.

List of assets of other articles:
1) bitcoin_functions.py
2) bjorn_edstrom_ripemd160.py
3) convert_dice_rolls_to_hex_bytes_2.py
4) create_nonstandard_transaction.py
5) create_transaction.py
6) display_hex_bytes.py
7) ecdsa-0.10.tar.gz
8) generate_bitcoin_address_3.py
9) nonstandard_bitcoin_functions.py
10) nonstandard_transaction.py
11) pypy_sha256.py
12) transaction.py

Asset 1: A library of functions for handling standard Bitcoin data types.
bitcoin_functions.py [paywalled]

Asset 2: An implementation of RIPEMD-160, written by Björn Edström.
bjorn_edstrom_ripemd160.py [paywalled]

Asset 3: A script that converts dice roll results into bytes.
convert_dice_rolls_to_hex_bytes_2.py [paywalled]

Asset 4: A script that creates and signs a nonstandard Bitcoin transaction with one standard P2PKH input and one nonstandard P2SH output.
create_nonstandard_transaction.py [paywalled]

Asset 5: A script that creates and signs a standard Bitcoin transaction with one input and one output.
create_transaction.py [paywalled]
Note: This asset was not actually used during this project.

Asset 6: A script that prints a hex byte string, inserting spaces and newlines to make it more readable.
display_hex_bytes.py [paywalled]

Asset 7: A Python implementation of ECDSA cryptography, written by Peter Pearson.
ecdsa-0.10.tar.gz [paywalled]

Asset 8: A script that generates a standard Bitcoin address from a private key.
generate_bitcoin_address_3.py [paywalled]

Asset 9: A library of functions for handling nonstandard Bitcoin data types.
nonstandard_bitcoin_functions.py [paywalled]

Asset 10: A library of classes for nonstandard Bitcoin transactions.
nonstandard_transaction.py [paywalled]

Asset 11: A Python implementation of SHA256.
pypy_sha256.py [paywalled]

Asset 12: A library of classes for standard Bitcoin transactions.
transaction.py [paywalled]



List of the articles that I read in order to choose these assets:
- Recipe for generating entropy bytes using dice
- Recipe for generating a Bitcoin address
- Recipe for creating and signing a standard Bitcoin transaction
- Recipe for creating and signing a nonstandard Bitcoin transaction
- Displaying hex bytes for manual copying










NOTES







Parts:


- Definitions and acryonyms
- Services used during this project
- Equipment used during this project
- Entropy values generated during this project
- Addresses generated and/or used in this project
- Transactions created during this project
- create_nonstandard_transaction.py settings used to create the transactions
- Time taken to manually transfer transactions by typing
- Transaction confirmation times
- Dice rolling results
- Recording shell output
- Miscellaneous






Definitions and acryonyms


P2PKH = Pay-To-Public-Key-Hash

P2SH = Pay-To-Script-Hash

previous_output_hash is the big-endian 32-byte double-SHA256 hash of a previous transaction.

tx = transaction

txid = "transaction id". It is the little-endian form of the previous_output_hash.

aka = "also known as". Indicates a secondary name for something. Example: Robert (aka Bob) is a good programmer. Example: Transaction tx1 (aka tx1a) was never mined.


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.


My working definition of a nonstandard transaction:
- It has at least one input and at least one output.
- At least one input or output address is not a standard Pay-To-Public-Key-Hash (P2PKH) address.


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






Services used during this project


I used
localbitcoins.com
to:
- store some bitcoin
- transfer a small amount of bitcoin to the test address
- receive this small amount back again from the test address
- transfer a relatively larger amount of bitcoin to the now-validated test address
- receive this larger amount back again from the test 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 satoshis / byte).

I used the search field at
live.blockcypher.com
to search for transactions by txid.

On the resulting transaction pages e.g. for tx0:
live.blockcypher.com/btc/tx/07cedb340f588dec2fb14472178a92d5803c70d8d90fc0d8593b03f34035e2cd
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/07cedb340f588dec2fb14472178a92d5803c70d8d90fc0d8593b03f34035e2cd?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.

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.

I used
www.blockchain.com/btc/pushtx
to attempt to upload a signed transaction for broadcast to the Bitcoin network. The error message it produced was helpful.

I used the search field at
www.blockchain.com
to search for transactions (by txid) and for addresses.






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.

The offline computer used during this project: A Raspberry Pi, Model B+ V1.2 [circa 2014]. It has various ports, including 4 USB ports (which allows simultaneous use of a mouse, a keyboard, and a memory stick) and an HDMI port. It does not have an onboard WiFi chip. I have various peripherals for the Raspberry Pi. These are: An 8GB micro SD card with an installed operating system, a Raspberry Pi power cable, a screen with a DVI port, a screen power cable, a DVI male-male connector cable, a DVI female to HDMI male converter, a USB keyboard, a USB mouse, and a plastic case customised for the Raspberry Pi Model B+. The installed operating system is Raspbian GNU/Linux 7 (wheezy) and the Linux kernel version is 4.1.13+. Tools: nano 2.2.6, tee 8.13, Python 2.7.3.

USB memory stick: 8 GB, FAT32 format, name = "NO NAME"






Entropy values generated during this project


Using dice, I generated 5 sets of 212 dice rolls. Files containing the dice roll results are listed in the Downloadable Assets section. I extracted 32 bytes of entropy from each set, producing these files, which contain entropy values:

- private_key.txt
- random_value2.txt
- random_value3.txt
- random_value4.txt
- random_value.txt

The values in these files were printed during the logged work on the Raspberry Pi, so I can go over the project log, find them, and copy them here.

Values:

- private_key.txt
c592e1dad5e9871fdeffb551b4544b0a1cf0378c6371d7a397ff5faf04c934ca


- random_value.txt
91fbb8a38082b09e6ed984fda95866dfab95dc66b0cb6b5133dd87d07315364e


- random_value2.txt
644dc86dd0cb4518d9d7f68db2d6e9455e34ceeb32c897df2616418c4c9bb040


- random_value3.txt
644dc86dd0cb4518d9d7f68db2d6e9455e34ceeb32c897df2616418c4c9bb040


- random_value4.txt
f78c5ebf0efac89d60aedb38c30906ad5b22ae522a3e29819248c21d59e8397f


Note that random_value2.txt and random_value3.txt contain the same value. The value in random_value3.txt should have been derived from dice_rolls4.txt, but I accidentally derived it from dice_rolls3.txt instead.

Uses of these entropy values:
- private_key.txt was used as the private key for the test address.
- random_value.txt was used to sign tx1a.
- random_value2.txt was used to sign tx1b.
- random_value3.txt was used to sign tx1c.
- random_value4.txt was used to sign tx3.






Addresses generated and/or used in this project


I generated one address: "test address"

Test address:
- Private key (hex bytes):
c592e1dad5e9871fdeffb551b4544b0a1cf0378c6371d7a397ff5faf04c934ca
- Bitcoin address:
1vkb4YyPMFcxyC83Z5m5zuN45xASoHeNK

The test address was an output address in transactions tx0 and tx2 (both created by the LocalBitcoins service).


I used two receiving addresses on my LocalBitcoins account.

Receiving address 1: "output address"
369Dpo9CrJASneaHLdwWfKym7N84XTUyvH

Receiving address 1 was the output address for tx1 (aka tx1a) and tx1c.

Because LocalBitcoins saw tx1a, which used receiving address 1 as its output address, LocalBitcoins generated a second receiving address (receiving address 2), even though tx1a was never mined.

Receiving address 2: "output address", later "lb_address2" (lb = LocalBitcoins)
36p1w3YrNKd2Q3xaXbe9ASUQkeynjVLfDx

Receiving address 2 was the output address for tx1b and tx3.


Note from LocalBitcoins concerning receiving addresses:

{To protect your privacy, we provide a new bitcoin address for each transfer. This prevents someone from tracking all the payments you receive by looking at the blockchain.

Note that addresses are valid only for 12 months.}


Because of this note, I used receiving address 1 as an output address in tx1c (mined), even though LocalBitcoins had already generated receiving address 2 for me after seeing tx1a (never mined). LocalBitcoins still interpreted tx1c as a deposit to my account.






Transactions created during this project




Transactions:
- tx0
- tx1 / tx1a
- tx1b
- tx1c
- tx2
- tx3




I'll use:
- txid0 to mean the txid (transaction id) of tx0
- txid1 to mean the txid of tx1 (aka tx1a)
- txid1a to mean the txid of tx1a
- txid1b to mean the txid of tx1b
- txid1c to mean the txid of tx1c
- txid2 to mean the txid of tx2
- txid3 to mean the txid of tx3




Transaction sequence:
- tx0: I used LocalBitcoins to transfer some bitcoin to the test address. LocalBitcoins created a transaction that included this transfer.
- tx1 / tx1a: I created a transaction on the offline Raspberry Pi that transferred the available bitcoin from the test address to receiving address 1 (on my LocalBitcoins account). I used a transaction-broadcasting service to broadcast it to the Bitcoin network. This transaction was never mined. LocalBitcoins saw this transaction and generated a new receiving address for my account, "receiving address 2".
- tx1b: I created a transaction on the offline Raspberry Pi that transferred the available bitcoin from the test address to receiving address 2. This transaction was rejected by two transaction-broadcasting services, because it was a double-spend attempt (it tried to spend the same unspent output as tx1a did, but to a different address, while tx1a was still in the memory pools of the services).
- tx1c: I created a transaction on the offline Raspberry Pi that transferred the available bitcoin from the test address to receiving address 1, using a higher fee than in tx1a. This was a replace-by-fee transaction (only the fee was different), which is valid on the Bitcoin network (unlike a double-spend transaction), but the two transaction-broadcasting services still rejected it. I waited until tx1a had been cleared from the memory pool of one of the transaction-broadcasting services, and then uploaded tx1c again to that service. This time, the service accepted tx1c, which was later mined.
- tx2: I used LocalBitcoins to transfer a relatively larger amount of bitcoin to the test address. LocalBitcoins created a transaction that included this transfer.
- tx3: I created a transaction on the offline Raspberry Pi that transferred the available bitcoin from the test address to receiving address 2 (on my LocalBitcoins account). I used a transaction-broadcasting service to broadcast it to the Bitcoin network. After a while, tx3 was mined.




1) tx0: I used LocalBitcoins to transfer some bitcoin to the test address. LocalBitcoins created a transaction that included this transfer.

txid0:
07cedb340f588dec2fb14472178a92d5803c70d8d90fc0d8593b03f34035e2cd


I did not obtain and use the raw byte sequence of transaction tx0. Instead, I used a service to get the information I needed about an output in tx0. To repeat my steps, browse to the link below, click "Advanced Details", and click "API Call". The result will be the service's information concerning tx0, not the raw form of tx0 as stored in the Bitcoin blockchain.
live.blockcypher.com/btc/tx/07cedb340f588dec2fb14472178a92d5803c70d8d90fc0d8593b03f34035e2cd

Key details:
- block_hash:
0000000000000000001b43b8af8973377619def5043634e9cb2d7dd584d973be
- block_height: 550741
- confirmed: 2018-11-19T19:46:37Z
- received: 2018-11-19T19:46:37Z
- txid:
07cedb340f588dec2fb14472178a92d5803c70d8d90fc0d8593b03f34035e2cd
- vout_sz (number of outputs): 32

tx0 sent a new unspent output to the test address.

From tx0, I acquired the following data of this particular unspent output for use as the input in tx1:
- index: 15
- value: 0.002 bitcoin
- The txid of tx0, which contains this unspent output, is:
07cedb340f588dec2fb14472178a92d5803c70d8d90fc0d8593b03f34035e2cd




2) tx1 / tx1a: I created a transaction on the offline Raspberry Pi that transferred the available bitcoin from the test address to receiving address 1 (on my LocalBitcoins account). I used a transaction-broadcasting service to broadcast it to the Bitcoin network. This transaction was never mined. LocalBitcoins saw this transaction and generated a new receiving address for my account, "receiving address 2".

txid1 / txid1a:
add54b899f1aba8b6276e42af86c3c03b0120a864451640b4a8d3fec89a4a72d


tx1 / tx1a (raw byte form):
0100000001cde23540f3033b59d8c00fd9d8703c80d5928a177244b12fec8d580f34dbce070f0000008a473044022005fc767d513f285c38f718f4c9cfb0909d4ba2d80131aed21b3f26aa630a79f0022044c9b3c0fb4a9d1a8b0c269915399112eea5ee4fd7e42fc0a430a47e5ecbb4520141043ab692792d6c8838fd30c2ff45bf3cbd44286a5cac52ba64dc06452810202b3206f5c7799c3b72ff77fd1976f105ced3cd7700b0412e11266f3888b88c3052c3ffffffff01630c03000000000017a91430d540a50d464852194a195529ebfa44af521bbb870000000001000000





3) tx1b: I created a transaction on the offline Raspberry Pi that transferred the available bitcoin from the test address to receiving address 2. This transaction was rejected by two transaction-broadcasting services, because it was a double-spend attempt (it tried to spend the same unspent output as tx1a did, but to a different address, while tx1a was still in the memory pools of the services).

txid1b:
3677f15c9a6e62a02df0a571370ceb0de9fa90efd56441e3dcb7fe9eff188d16


tx1b (raw byte form):
0100000001cde23540f3033b59d8c00fd9d8703c80d5928a177244b12fec8d580f34dbce070f0000008b483045022100af984f21f3096c47b9684d9cccf76988597accbdb55ff0b66992ef4b30061608022063ae31b6465deb451d3f535145e200bf09e4d51d0c640b90d4d9e25b9c97b2c20141043ab692792d6c8838fd30c2ff45bf3cbd44286a5cac52ba64dc06452810202b3206f5c7799c3b72ff77fd1976f105ced3cd7700b0412e11266f3888b88c3052c3ffffffff0146d402000000000017a914382b8c40b25f104e9d0277ed91ddf3c849aa3403870000000001000000





4) tx1c: I created a transaction on the offline Raspberry Pi that transferred the available bitcoin from the test address to receiving address 1, using a higher fee than in tx1a. This was a replace-by-fee transaction (only the fee was different), which is valid on the Bitcoin network (unlike a double-spend transaction), but the two transaction-broadcasting services still rejected it. I waited until tx1a had been cleared from the memory pool of one of the transaction-broadcasting services, and then uploaded tx1c again to that service. This time, the service accepted tx1c, which was later mined.

txid1c:
8b0f7ba372b61b195cd237429c9a5d079aaf9887e72dd094f2fa942a0f7ccfc0


tx1c (raw byte form):
0100000001cde23540f3033b59d8c00fd9d8703c80d5928a177244b12fec8d580f34dbce070f0000008b483045022100af984f21f3096c47b9684d9cccf76988597accbdb55ff0b66992ef4b3006160802205f6bad0dce3fc5c01ac3128f643302d55b952edf656be25ee996049d74a0e41c0141043ab692792d6c8838fd30c2ff45bf3cbd44286a5cac52ba64dc06452810202b3206f5c7799c3b72ff77fd1976f105ced3cd7700b0412e11266f3888b88c3052c3ffffffff0146d402000000000017a91430d540a50d464852194a195529ebfa44af521bbb870000000001000000


Key details:
- block_hash:
000000000000000000091db255f327f3938cb33cd1076d7554b7bbd22b9c1000
- block_height: 551106
- confirmed: 2018-11-22T20:17:05Z
- received: 2018-11-22T17:46:01.324Z
- hash (txid):
8b0f7ba372b61b195cd237429c9a5d079aaf9887e72dd094f2fa942a0f7ccfc0
- vout_sz (number of outputs): 1




5) tx2: I used LocalBitcoins to transfer a relatively larger amount of bitcoin to the test address. LocalBitcoins created a transaction that included this transfer.

txid2:
af3888cc260b6b6bfb8eb256fb70fd1e761a1c7baac0e19cd11b47726f2327d2


I did not obtain and use the raw byte sequence of transaction tx2. Instead, I used a service to get the information I needed about an output in tx2. To repeat my steps, browse to the link below, click "Advanced Details", and click "API Call". The result will be the service's information concerning tx2, not the raw form of tx as stored in the Bitcoin blockchain.
live.blockcypher.com/btc/tx/af3888cc260b6b6bfb8eb256fb70fd1e761a1c7baac0e19cd11b47726f2327d2

Key details:
- block_hash:
0000000000000000001f85686e50bbc4e929b50768669165731e5c73a690f680
- block_height: 551219
- block_index: 502
- hash (txid):
af3888cc260b6b6bfb8eb256fb70fd1e761a1c7baac0e19cd11b47726f2327d2
- total: 4991126340
- fees: 152990
- size: 2822
- preference: high
- relayed_by: 45.79.10.204:8333
- confirmed: 2018-11-23T18:25:35Z
- received: 2018-11-23T18:10:40.724Z
- vout_sz (number of outputs): 85

tx2 sent a new unspent output to the test address.

From tx2, I acquired the following data of this particular unspent output for use as the input in tx3:
- index: 25
- value: 1200000 satoshi (0.012 bitcoin)
- The txid of tx2, which contains this unspent output, is:
af3888cc260b6b6bfb8eb256fb70fd1e761a1c7baac0e19cd11b47726f2327d2




6) tx3: I created a transaction on the offline Raspberry Pi that transferred the available bitcoin from the test address to receiving address 2 (on my LocalBitcoins account). I used a transaction-broadcasting service to broadcast it to the Bitcoin network. After a while, tx3 was mined.

txid3:
00f630f5152f4fce9831933fcd4eb878428308755f9f8e31a3135de6a4754093


tx3 (raw byte form):
0100000001d227236f72471bd19ce1c0aa7b1c1a761efd70fb56b28efb6b6b0b26cc8838af190000008b483045022100f03c62521817e4faf31abd01782c7df2fcef8a2234400068f1a821b29fe129da02201185879e760fac3d9f2dbdc2e2af074c32c70088dd839108971c39905f5b5bbf0141043ab692792d6c8838fd30c2ff45bf3cbd44286a5cac52ba64dc06452810202b3206f5c7799c3b72ff77fd1976f105ced3cd7700b0412e11266f3888b88c3052c3ffffffff01de4612000000000017a914382b8c40b25f104e9d0277ed91ddf3c849aa3403870000000001000000


Key details:
- block_hash:
0000000000000000000ab9373f3ce1c96528c09ffa13fe2005a4d32470b7c98b
- block_height: 552081
- confirmed: 2018-11-30T23:27:35Z
- received: 2018-11-30T18:55:34.661Z
- hash (txid):
00f630f5152f4fce9831933fcd4eb878428308755f9f8e31a3135de6a4754093
- vout_sz (number of outputs): 1






create_nonstandard_transaction.py settings used to create the transactions




tx1 (aka tx1a):

##### START CONTROLS random_value = "91fbb8a38082b09e6ed984fda95866dfab95dc66b0cb6b5133dd87d07315364e" # 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": "07cedb340f588dec2fb14472178a92d5803c70d8d90fc0d8593b03f34035e2cd", "previous_output_index": "15", "private_key_hex": "c592e1dad5e9871fdeffb551b4544b0a1cf0378c6371d7a397ff5faf04c934ca", #"satoshi_amount": "241777", "bitcoin_amount": "0.0020", "input_type": "p2pkh", } output_data = { "address": "369Dpo9CrJASneaHLdwWfKym7N84XTUyvH", #"satoshi_amount": "241000", "bitcoin_amount": "0.0020", "output_type": "p2sh", } change_address = "369Dpo9CrJASneaHLdwWfKym7N84XTUyvH" # note: the fee will be subtracted from the amount that is being sent to the change address. fee = "225" # satoshi fee_rate = "1" # satoshi / byte # fee_type options: ["fee", "fee_rate"] fee_type = "fee_rate" ##### END CONTROLS





tx1b:

##### START CONTROLS random_value = "644dc86dd0cb4518d9d7f68db2d6e9455e34ceeb32c897df2616418c4c9bb040" # 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": "07cedb340f588dec2fb14472178a92d5803c70d8d90fc0d8593b03f34035e2cd", "previous_output_index": "15", "private_key_hex": "c592e1dad5e9871fdeffb551b4544b0a1cf0378c6371d7a397ff5faf04c934ca", #"satoshi_amount": "241777", "bitcoin_amount": "0.0020", "input_type": "p2pkh", } output_data = { "address": "36p1w3YrNKd2Q3xaXbe9ASUQkeynjVLfDx", #"satoshi_amount": "241000", "bitcoin_amount": "0.0020", "output_type": "p2sh", } change_address = "36p1w3YrNKd2Q3xaXbe9ASUQkeynjVLfDx" # note: the fee will be subtracted from the amount that is being sent to the change address. fee = "225" # satoshi fee_rate = "66" # satoshi / byte # fee_type options: ["fee", "fee_rate"] fee_type = "fee_rate" ##### END CONTROLS





tx1c:

##### START CONTROLS random_value = "644dc86dd0cb4518d9d7f68db2d6e9455e34ceeb32c897df2616418c4c9bb040" # 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": "07cedb340f588dec2fb14472178a92d5803c70d8d90fc0d8593b03f34035e2cd", "previous_output_index": "15", "private_key_hex": "c592e1dad5e9871fdeffb551b4544b0a1cf0378c6371d7a397ff5faf04c934ca", #"satoshi_amount": "241777", "bitcoin_amount": "0.0020", "input_type": "p2pkh", } output_data = { "address": "369Dpo9CrJASneaHLdwWfKym7N84XTUyvH", #"satoshi_amount": "241000", "bitcoin_amount": "0.0020", "output_type": "p2sh", } change_address = "369Dpo9CrJASneaHLdwWfKym7N84XTUyvH" # note: the fee will be subtracted from the amount that is being sent to the change address. fee = "225" # satoshi fee_rate = "66" # satoshi / byte # fee_type options: ["fee", "fee_rate"] fee_type = "fee_rate" ##### END CONTROLS





tx3:

##### START CONTROLS random_value = "f78c5ebf0efac89d60aedb38c30906ad5b22ae522a3e29819248c21d59e8397f" # 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": "af3888cc260b6b6bfb8eb256fb70fd1e761a1c7baac0e19cd11b47726f2327d2", "previous_output_index": "25", "private_key_hex": "c592e1dad5e9871fdeffb551b4544b0a1cf0378c6371d7a397ff5faf04c934ca", "satoshi_amount": "1200000", #"bitcoin_amount": "0.0020", "input_type": "p2pkh", } output_data = { "address": "36p1w3YrNKd2Q3xaXbe9ASUQkeynjVLfDx", "satoshi_amount": "1200000", #"bitcoin_amount": "0.0020", "output_type": "p2sh", } change_address = "36p1w3YrNKd2Q3xaXbe9ASUQkeynjVLfDx" # note: the fee will be subtracted from the amount that is being sent to the change address. fee = "225" # satoshi fee_rate = "10" # satoshi / byte # fee_type options: ["fee", "fee_rate"] fee_type = "fee_rate" ##### END CONTROLS







Time taken to manually transfer transactions by typing


In this project, I read the transactions on the screen of the offline computer (Raspberry Pi) and manually typed them into text files on the online computer (Aineko). Each transaction was a nonstandard P2SH transaction that contained one standard P2PKH input and one nonstandard P2SH output.

I used a tool to display the transaction hex bytes in a more readable format by inserting whitespace. I found that listening to music made the typing process quite tolerable.

I used a stopwatch to record the time taken for typing each transaction, with one exception (tx1c) where I forgot to do so. This time includes a final double-check of each hex character group on the online computer against the original group displayed on the offline computer's screen.

Times taken (minutes:seconds):
- tx1 (aka tx1a): 13:18
- tx1b: 12:37
- tx1c: Not recorded
- tx3: 10:04

From the recorded times, I see that manually typing out a single-input single-output transaction should take about 15 minutes at most, and about 10 minutes if done quickly.

Let's calculate the overall data transfer rate in bits / second. Don't include tx1c in this calculation.

Transaction sizes according to my work:
- tx1 / tx1a: 225 bytes
- tx1b: 226 bytes
- tx3: 226 bytes

Total data size:
225 + 226 + 226 = 677 bytes = 677*8 bits = 5416 bits

Total time:
(13*60 + 18) + (12*60 + 37) + (10*60 + 4) = 2159 seconds

Overall data transfer rate (bits / second):
5416 bits / 2159 seconds = 5416 / 2159 ~=
2.51 bits / second

At this data transfer rate, how long would it hypothetically take to transfer the code assets over to the Raspberry Pi manually, typing them in rather than using a memory stick?

Make a new test directory. Copy these assets into it:
- bitcoin_functions.py
- bjorn_edstrom_ripemd160.py
- convert_dice_rolls_to_hex_bytes_2.py
- create_nonstandard_transaction.py
- create_transaction.py
- display_hex_bytes.py
- ecdsa-0.10.tar.gz
- generate_bitcoin_address_3.py
- nonstandard_bitcoin_functions.py
- nonstandard_transaction.py
- pypy_sha256.py
- transaction.py

Unpack the zipped tape archive file ecdsa-0.10.tar.gz. In the resulting directory ecdsa-0.10, find the directory "ecdsa" and copy it to the test directory.

Delete:
- ecdsa-0.10.tar.gz
- ecdsa-0.10

Open a terminal and change directory to the test directory.

Find the byte length of all the files in the test directory tree.

aineko:test stjohnpiano$ find . -type f -exec wc -c {} \;

23341 ./bitcoin_functions.py 14429 ./bjorn_edstrom_ripemd160.py 7034 ./convert_dice_rolls_to_hex_bytes_2.py 13624 ./create_nonstandard_transaction.py 13000 ./create_transaction.py 2323 ./display_hex_bytes.py 644 ./ecdsa/__init__.py 178 ./ecdsa/_version.py 1640 ./ecdsa/curves.py 7023 ./ecdsa/der.py 24328 ./ecdsa/ecdsa.py 8609 ./ecdsa/ellipticcurve.py 12323 ./ecdsa/keys.py 16105 ./ecdsa/numbertheory.py 2794 ./ecdsa/rfc6979.py 11985 ./ecdsa/six.py 28868 ./ecdsa/test_pyecdsa.py 9263 ./ecdsa/util.py 4270 ./generate_bitcoin_address_3.py 2371 ./nonstandard_bitcoin_functions.py 12817 ./nonstandard_transaction.py 11687 ./pypy_sha256.py 19219 ./transaction.py


23341 + 14429 + 7034 + 13624 + 13000 + 2323 + 644 + 178 + 1640 + 7023 + 24328 + 8609 + 12323 + 16105 + 2794 + 11985 + 28868 + 9263 + 4270 + 2371 + 12817 + 11687 + 19219 =
247875 bytes

Total data:
247875 bytes = 247875 * 8 bits =
1983000 bits

Total time at manual transfer data rate:
1983000 bits / (2.51 bits / second) = 1983000 / 2.51 ~=
790039 seconds ~=
13167 hours ~=
1097 12-hour days ~=
3 years (typing for 12 hours / day)

In practice, typing ASCII code would be significantly faster than typing hex bytes, but this result is a good upper-bound estimate.

Delete the test directory.






Transaction confirmation times


The following times are calculated by subtracting the "received" time from the "confirmed" time as reported by the service live.blockcypher.com. To acquire this information from the service, search for a txid. On the resulting transaction page, click "Advanced Details" then "API Call". On the resulting transaction information page, look for the key names "confirmed" and "received" and record their corresponding values.

Transactions tx0 and tx2 were created by LocalBitcoins, with fees chosen by LocalBitcoins. They are not included here.
Transactions tx1 (aka tx1a) and tx1b were never mined. Transactions tx1c and tx3 were mined.

I assume that "received" time means "the time at which the service first saw the transaction" and that "confirmed" time means "the time at which the transaction was first included in a block".

Transaction details according to the service:
- tx1c: size = 222 bytes, fee = 14586 satoshi
- tx3: size = 222 bytes, fee = 2210 satoshi

Transaction details according to my work:
- tx1c: chosen fee rate = 66 satoshi / byte, estimated size = 221 bytes, size = 226 bytes, fee = 14586 satoshi
- tx3: chosen fee rate = 10 satoshi / byte, estimated size = 221 bytes, size = 226 bytes, fee = 2210 satoshi

Received times:
- tx1c: 2018-11-22T17:46:01.324Z
- tx3: 2018-11-30T18:55:34.661Z

Confirmed times:
- tx1c: 2018-11-22T20:17:05Z
- tx3: 2018-11-30T23:27:35Z

For each transaction, subtract received time from confirmed time to find time taken for confirmation:
- tx1c:
2018-11-22T20:17:05Z - 2018-11-22T17:46:01.324Z =
0 days + (20:17 - 17:46) =
2:31 (hours:minutes)
- tx3:
2018-11-30T23:27:35Z - 2018-11-30T18:55:34.661Z =
0 days + (23:27 - 18:55) =
4:32 (hours:minutes)

Times taken for confirmation (hours:minutes):
- tx1c: 2:31
- tx3: 4:32

Estimated delays according to the service bitcoinfees.earn.com:
- tx1c: 0 blocks (0-35 minutes) for the fee rate of 60 satoshi / byte.
- tx3: 0-7 blocks (0-180 minutes) for the fee rate of 10 satoshi / byte.






Dice rolling results


I found that listening to music made the dice rolling quite tolerable.

Using a set of 5 dice, and rolling them in a tray with raised edges, I generated 5 sets of 212 dice roll results. The files containing these results are included in the Downloadable Assets section.

Table matching sets to filenames:
- Set 1: dice_rolls.txt
- Set 2: dice_rolls2.txt
- Set 3: dice_rolls3.txt
- Set 4: dice_rolls4.txt
- Set 5: dice_rolls5.txt

32 bytes of entropy were derived from each set.

The entropy derived from set 1 was used for the private key of the test address.
The entropy derived from set 2 was used to sign the transaction tx1 (aka tx1a).
The entropy derived from set 3 was used to sign the transaction tx1b.
The entropy derived from set 4 was intended to be used for signing the transaction tx1c. However, I made a mistake and re-used the entropy derived from set 3 to do this.
The entropy derived from set 5 was used to sign the transaction tx3.

I used a stopwatch to record the time taken for each set of 212 results.

Times taken (minutes:seconds):
- Set 1: 10:30
- Set 2: 7:32
- Set 3: 6:33
- Set 4: 5:53
- Set 5: 6:59

Extra entropy generated but not used:
- Set 1: 1 byte
- Set 2: 4 bytes
- Set 3: 1 byte
- Set 4: 1 byte
- Set 5: 5 bytes

From the recorded times, I see that using 5 dice to generate 32 bytes of entropy should take about 10 minutes at most, and about 7 minutes if done quickly.

Let's calculate the overall entropy generation rate in bits / second.

Total entropy bytes: 32*5 + (1+4+1+1+5) = 172 bytes = 172*8 bits = 1376 bits
Total time: (10*60 + 30) + (7*60 + 32) + (6*60 + 33) + (5*60 + 53) + (6*60 + 59) = 2247 seconds

Overall entropy generation rate:
1376 bits / 2247 seconds = 1376 / 2247 ~=
0.61 bits / second






Recording shell output


In a previous project, I learned how to execute a command in the bash shell and simultaneously archive its output in a text file.

The project: Offline installation of a C compiler on Centos 6.9 Minimal on Kalkin

Excerpt:

6) RECORDING SHELL OUTPUT

Use the
tee
command.

Example:
program [arguments...] 2>&1 | tee -a outfile


This should display both output and error messages and append these to a storage file.

The -a option means "append".

2>&1
can be used in Bash to redirect errors/warnings (which are normally sent to stderr) to normal output (stdout). In this case both will be piped to the next command (
tee
).

Note:
tee
doesn't record the command itself, only the output. This can be worked around by echoing the command to the log file before running it. Use the
-e
flag for the
echo
command so that it will interpret backslash-escaped newline characters.

[root@kalkin work]# echo -e "\n\nCOMMAND# rpm --version\n" | tee -a work.log


[root@kalkin work]# rpm --version | tee -a work.log


[root@kalkin work]# echo -e "\n\nCOMMAND# rpm --help\n" | tee -a work.log


[root@kalkin work]# rpm --help | tee -a work.log



Example of capturing output sent to standard error:

# rpm --install rpms/cloog-ppl-0.15.7-1.2.el6.x86_64.rpm --test 2>&1 | tee -a work.log



Note: If the command itself includes a newline sequence "\n", the -e flag in the
echo
command will cause it to be recorded as an actual newline byte. You will have to edit the log file manually in order to correct this.

Note: Use a text editor to remove any mistaken commands from the log file (as long as they didn't cause irreversible changes of some kind), so that the command can be run again properly.

You can check that the
tee
is present by running the command
tee --version
.

I don't usually record the logging commands themselves in a project. I also don't log every command that I use for gathering information (e.g.
ls -1
,
cat [filename]
).

While logging an operation, I usually record the commands (although not in complete detail) along with annotations and comments in a separate text file (usually the main project log). When the operation is finished, I copy the resulting log, piece by piece, into the main project log, integrating the annotations and comments as I go.






Miscellaneous




Each new Bitcoin transaction signature requires a new random value. Using the same random value twice in two different ECDSA signatures (that are both broadcast) could compromise the secrecy of the private key.




Keeping the intermediate results e.g. tx_copied.txt during the project meant that if there were an error, I could go back and look for it without having to completely redo each step.




During logging of the commands on the Raspberry Pi, the text "COMMAND#" was generated as a placeholder. Later, I replaced this placeholder with "pi@raspberrypi ~/test $".




On the LocalBitcoins web application, in Wallet / Receive bitcoins / Old addresses, I found this note:

{To protect your privacy, we provide a new bitcoin address for each transfer. This prevents someone from tracking all the payments you receive by looking at the blockchain.

Note that addresses are valid only for 12 months.}

along with a list of old addresses (although only the first 10 characters of each address are shown).




Listening to music made manually copying a transaction a more tolerable experience.




For transferring data to an offline computer, using a memory stick is not the most secure way (various malware items have been able to store themselves on memory sticks). However, for storing bitcoin, using an offline computer and a memory stick is more secure than using an online computer, and security is always relative.

Ideally, the memory stick should only be used once to transfer all the code to the offline computer. Then, the memory stick should be destroyed, and any data produced on the offline computer should be manually copied to an online computer. See this article for an example of how to display data in a more easily-read format: Displaying hex bytes for manual copying
- In the limit case, code should only be moved onto an offline computer by manually typing it all in. This is not always possible within a useful timeframe. In the "Time taken to manually transfer transactions by typing" part of the Notes section, I estimated an upper bound of 3 years to manually copy the code used in this project to the offline computer. Admittedly, manually copying code would be significantly faster than manually copying hex bytes.
- In practice, steadily increasing security, as and when it is reasonable and affordable to do so, is usually the most effective strategy.
- If this project were repeated, without the logging, it would involve only a single data transfer via memory stick (the initial code installation). Input data (txids, output indices, addresses) was copied over to the offline computer or generated on it. All signed transactions were manually copied over to the online computer.




The errors returned by the transaction-broadcasting services when I uploaded a double-spend attempt (tx1b) are shown below. The same errors occurred when I uploaded a replace-by-fee transaction (tx1c). In both situations, the original transaction (tx1a) was still in the memory pools of both services.

live.blockcypher.com/btc/pushtx:
"Server Error (500)"

www.blockchain.com/btc/pushtx:
"Validation Error: BitcoindException(super=com.neemre.btcdcli4j.core.BitcoindException: Error #-26: 18: txn-mempool-conflict, code=-26)"




Transferring values from the online computer to the offline computer:

On the offline computer, edit create_nonstandard_transaction.py using the Nano text editor. Manually enter the gathered / chosen values (reading them from the online computer), except for the variables
random_value
and
input_data["private_key_hex"]
.
- Delete the existing value for the variable
random_value
. Then use the Nano option "Read File" to paste the contents of the file random_value.txt into the position of the value for this variable (i.e. between the quotation marks). Then press the Backspace key to delete the final newline of the file that was also pasted in.
- The variable
input_data
is a dictionary that contains several other variables. Delete the existing value for the variable
input_data["private_key_hex"]
. Then use the Nano option "Read File" to paste the contents of the file private_key.txt into the position of the value for this variable (i.e. between the quotation marks). Then press the Backspace key to delete the final newline of the file that was also pasted in.
- Note: With long strings, e.g. the txid, you can make a copy on the online computer and split it into groups of 4 characters, then manually copy each group over to the offline Raspberry Pi, then do a double-check of the group values, and finally delete the spaces again to form the original txid.










FINANCIAL INFORMATION FOR THIS PROJECT





Parts


- Definitions and prices
- Cost of storing a larger amount of bitcoin in the test address
- Cost of testing the test address
- Total cost of the project




Definitions and prices


1 satoshi = 0.00000001 bitcoin (10^(-8) bitcoin)

USD = United States Dollars ($)

BTC = bitcoin

LocalBitcoins fees:
- Current deposit fee for incoming transactions: 0.00015 BTC
- Current transaction fee (deducted from the LocalBitcoins wallet balance, not from the transaction amount): 0.00005 BTC




Cost of testing the test address


In order to validate the test address, I needed to transfer a small amount of bitcoin in and out of it. I would need this amount to be at least:
(Bitcoin network transaction fee) + (LocalBitcoins deposit fee)

The Bitcoin network transaction fee was needed in order to pay for the second transaction (that will later transfer bitcoin out of the test address).

To calculate the Bitcoin network transaction fee, I used a service to look at current fee rates for Bitcoin transactions, and chose a reasonably high fee rate:
60 satoshi / byte

I estimated that a nonstandard transaction with one P2PKH input and one P2SH output should be approximately 221 bytes. The estimated fee (using the chosen fee rate) would therefore be:
221 bytes * 60 satoshi / byte = 221 * 60 =
13260 satoshi (0.00013260 BTC)

I therefore needed to transfer at least this much to the test address:
(Bitcoin network transaction fee) + (LocalBitcoins deposit fee)
= 0.00013260 + 0.00015
= 0.00028260 BTC

Then-current USD / BTC exchange rate:
$4904.99 / BTC

(4904.99 USD / BTC) * 0.00028260 BTC = 4904.99 * 0.00028260 ~=
$1.39

I decided to transfer approximately $10 worth of bitcoin to the test address, so as to have room to manoeuvre. If the second transaction were not mined, I would need to increase the fee, and upload a new version for broadcasting.

$10 * (1 BTC / 4904.99 USD) = 10 * 1 / 4904.99 ~=
0.00203874 BTC

I transferred 0.0020 bitcoin (~$9.80) from my LocalBitcoins account into the test address. LocalBitcoins created transaction tx0, which included this transfer.
- LocalBitcoins charged a transaction fee of 0.00005 (deducted from my wallet balance, not from the transaction amount).

I created transaction tx1a and tx1b, which were not mined, so no bitcoin was spent on them.

I created transaction tx1c, which transferred 185414 satoshi from the test address to my LocalBitcoins account.
- It included a Bitcoin network transaction fee of 14586 satoshi.
- LocalBitcoins charged a deposit fee of 0.00015 BTC.

Costs of this test:
- LocalBitcoins transaction fee: 0.00005000 bitcoin
- Bitcoin network transaction fee: 14586 satoshi (0.00014586 bitcoin)
- LocalBitcoins deposit fee: 0.00015000 bitcoin

Total cost in bitcoin:
(LocalBitcoins transaction fee) + (Bitcoin network transaction fee) + (LocalBitcoins deposit fee) =
0.00005000 + 0.00014586 + 0.00015000 =
0.00034586 bitcoin

Total cost (USD):
0.00034586 bitcoin * (4904.99 USD / BTC) =
0.00034586 * (4904.99) ~=
$1.70




Cost of storing a larger amount of bitcoin in the test address


I decided to transfer ~$50 worth of bitcoin to the test address.

Then-current USD / BTC exchange rate:
$4212 / BTC

$50 * (1 BTC / 4212 USD) = 50 * 1 / 4212 ~= 0.01187084 ~=
0.0120 bitcoin

I transferred 0.0120 bitcoin (~$50) from my LocalBitcoins account into the test address. LocalBitcoins created transaction tx2, which included this transfer.
- LocalBitcoins charged a transaction fee of 0.00005 (deducted from my wallet balance, not from the transaction amount).

I created transaction tx3, which transferred 0.01182790 bitcoin from the test address to my LocalBitcoins account.
- It included a Bitcoin network transaction fee of 2210 satoshi.
- LocalBitcoins charged a deposit fee of 0.00015 BTC.

Costs:
- LocalBitcoins transaction fee: 0.00005000 bitcoin
- Bitcoin network transaction fee: 2210 satoshi (0.00002210 bitcoin)
- LocalBitcoins deposit fee: 0.00015000 bitcoin

Total cost in bitcoin:
(LocalBitcoins transaction fee) + (Bitcoin network transaction fee) + (LocalBitcoins deposit fee) =
0.00005000 + 0.00002210 + 0.00015000 =
0.00022210 bitcoin

Total cost (USD):
0.00022210 bitcoin * (4212 USD / BTC) =
0.00022210 * (4212) ~=
$0.94




Overall cost of the project


Overall cost in bitcoin:
(Cost of testing the test address) + (Cost of storing a larger amount of bitcoin in the test address) =
0.00034586 bitcoin + 0.00022210 bitcoin = 0.00034586 + 0.00022210 =
0.00056796 bitcoin

Overall cost (USD):
(Cost of testing the test address) + (Cost of storing a larger amount of bitcoin in the test address) =
$1.70 + $0.94 = 1.70 + 0.94 =
$2.64

Note the use of the relevant then-current exchange rates for each subsection of the project.










FURTHER WORK



I would like to be able to transfer only a portion of the bitcoin (rather than an whole unspent output) in an offline address to another address. In order to do this, I need to be able to create transactions with two outputs - I could then set a default change output (whose destination would be the original offline address), and send only a portion of the bitcoin to the other output. This requires expansion of the existing code and careful testing.


During this project, transaction sizes (in bytes) differed slightly depending on the source.
- I estimated that a nonstandard transaction with one P2PKH input and one P2SH output should be approximately 221 bytes. All transactions that I created in this project were of this type (tx1, tx1b, tx1c, tx3).
- According to my tests after creating the transactions, they were:
-- tx1 / tx1a: 225 bytes
-- tx1b: 226 bytes
-- tx1c: 226 bytes
-- tx3: 226 bytes
- Transaction sizes according to the service live.blockcypher.com:
-- tx1 / tx1a: 221 bytes
-- tx1b: 222 bytes
-- tx1c: 222 bytes
-- tx3: 222 bytes
Investigate why these discrepancies exist, giving priority to how the estimated size is calculated. I derived the current estimate by adding up the sizes of the transaction component parts while developing the code for creating transactions.




















PROJECT LOG



My work computer: Aineko, a 2008 Macbook running Mac OS X 10.6.8 Snow Leopard.

aineko:work stjohnpiano$ python --version

Python 2.7.13



I have a Raspberry Pi in my equipment stores. There is some white text on its surface, which states that it is a Model B+ V1.2 and is copyright Raspberry Pi 2014.

I have used this Raspberry Pi in other projects, and it has been connected to the Internet before, so I would not use it to store bitcoin permanently. I can still use it for a test project, though.

It has various ports, including 4 USB ports (which allows simultaneous use of a mouse, a keyboard, and a memory stick) and an HDMI port.

From previous experience, I recall that it does not have an onboard WiFi chip (instead, various suppliers sell add-on USB-connected WiFi chips that can be plugged into it).

I have various peripherals for the Raspberry Pi. These are: An 8GB micro SD card with an installed operating system, a Raspberry Pi power cable, a screen with a DVI port, a screen power cable, a DVI male-male connector cable, a DVI female to HDMI male converter, a USB keyboard, a USB mouse, and a plastic case customised for the Raspberry Pi Model B+.

Future: When I have booted up the Raspberry Pi, check which operating system is installed (I installed it a long time ago and don't recall which OS it was).

I also have a memory stick, which I will use to transfer code to the Raspberry Pi. Using a memory stick is not the most secure way to do this (various malware items have been able to store themselves on memory sticks). However, for storing bitcoin, using an offline computer and a memory stick is more secure than using an online computer, and security is always relative.

Notes:
- Ideally, the memory stick should only be used once to transfer all the code to the offline computer. Then, the memory stick should be destroyed, and any data produced on the offline computer should be manually copied to an online computer. See this article for an example of how to do this: Displaying hex bytes for manual copying
- In the limit case, code should only be moved onto an offline computer by manually typing it all in.
- In practice, steadily increasing security, as and when it is reasonable and affordable to do so, is usually the most effective strategy.


Create a project directory:
storing_bitcoin_on_an_offline_raspberry_pi

In the project directory, create a work directory:
work


Plan of action:
- Download necessary code from previous articles.
- Create a private key. Store it on the Raspberry Pi. This will require generating entropy.
- Generate a Bitcoin address from the private key.
- Test this address by transferring some bitcoin into and out of it.
- Store a larger amount of bitcoin in the address.
- The private key will of course be revealed in the article describing this project, so this bitcoin won't be stored permanently in this address. Instead, I'll transfer the bitcoin out again. To store some bitcoin, a reader can follow all the steps apart from this one.


Hm. The articles that I will need to use are:

- Recipe for generating entropy bytes using dice
- Recipe for generating a Bitcoin address
- Recipe for creating and signing a standard Bitcoin transaction
- Recipe for creating and signing a nonstandard Bitcoin transaction
- Displaying hex bytes for manual copying


Ok. Next, I will download all the assets linked from these articles. Browse to each article and download all linked assets.

Note: Some assets are linked from more than one of these articles.


List of downloaded assets:

- bitcoin_functions.py
- bjorn_edstrom_ripemd160.py
- convert_dice_rolls_to_hex_bytes_2.py
- create_nonstandard_transaction.py
- create_transaction.py
- display_hex_bytes.py
- ecdsa-0.10.tar.gz
- generate_bitcoin_address_3.py
- nonstandard_bitcoin_functions.py
- nonstandard_transaction.py
- pypy_sha256.py
- transaction.py


Move these assets into the work directory.


The work directory contains only these assets. Mac Finder / Get Info reports:
197 KB on disk (169,268 bytes) for 12 items



Future: I remember that Python is installed on the Raspberry Pi. Which version(s) are installed?



I have a USB memory stick (8 GB, FAT32 format, name = "NO NAME"). Insert it into Aineko. It mounts automatically and an icon appears on the Desktop.

Copy work directory to memory stick. Right-click Desktop icon and choose Eject "NO NAME". Unplug the memory stick from Aineko.


Connect the mouse, keyboard, and screen to the Raspberry Pi. The mouse is for opening a terminal emulator program if the Raspberry Pi boots directly into a graphical user interface.

Insert the power cable into the Raspberry Pi. It boots up.


Result:

raspberrypi login:



Enter default credentials:


raspberrypi login: pi


Password:


Last login: Sun Mar 27 17:11:27 UTC 2016 on tty1
Linux raspberrypi 4.1.13+ #826 PREEMPT Fri Nov 13 20:13:22 GMT 2015 armv61

The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.

pi@raspberrypi ~ $



The password was "raspberry" but this was not echoed to the screen.


Ah. Note: The installed OS is Debian GNU/Linux. It's probably Raspbian.


In a previous project, I learned how to execute a command in the bash shell and simultaneously archive its output in a text file.

The project: Offline installation of a C compiler on Centos 6.9 Minimal on Kalkin

Excerpt:

6) RECORDING SHELL OUTPUT

Use the
tee
command.

Example:
program [arguments...] 2>&1 | tee -a outfile


This should display both output and error messages and append these to a storage file.

The -a option means "append".

2>&1
can be used in Bash to redirect errors/warnings (which are normally sent to stderr) to normal output (stdout). In this case both will be piped to the next command (
tee
).

Note:
tee
doesn't record the command itself, only the output. This can be worked around by echoing the command to the log file before running it. Use the
-e
flag for the
echo
command so that it will interpret backslash-escaped newline characters.

[root@kalkin work]# echo -e "\n\nCOMMAND# rpm --version\n" | tee -a work.log


[root@kalkin work]# rpm --version | tee -a work.log


[root@kalkin work]# echo -e "\n\nCOMMAND# rpm --help\n" | tee -a work.log


[root@kalkin work]# rpm --help | tee -a work.log



Example of capturing output sent to standard error:

# rpm --install rpms/cloog-ppl-0.15.7-1.2.el6.x86_64.rpm --test 2>&1 | tee -a work.log




Running the command
tee --version
on the Raspberry Pi shows me that it is present.

I will use the approaches shown in the excerpt to log the work done on the Raspberry Pi. I won't record the logging commands themselves in this project. Some commands for gathering information (e.g.
ls -1
,
cat [filename]
) may not be logged.



Ok. Next: Insert the memory stick into the Raspberry Pi and mount it.


I did this before in the project How I bought and stored some bitcoin.

Excerpt:

Steps for manually mounting a flash drive on a Raspberry Pi:

Insert the USB flash drive into a USB port on the Raspberry Pi.

Note: If the Raspberry Pi automatically started the graphical user interface, then open the program LXTerminal, which is a terminal emulator. It can be accessed from the Desktop via Menu / Accessories / Terminal. On my Raspbian system I have LXTerminal version 0.1.11.

In the terminal, enter the following commands, which are prefixed with a dollar sign and a space ($ ). Do not include this prefix when typing a command into the terminal.

Make a new directory on the graphical desktop to hold the contents of the flash drive:
$ mkdir /home/pi/Desktop/flash_drive_contents

Make a new directory to be the mount point for the flash drive:
$ sudo mkdir /mnt/flash_drive_mount_point

Mount the flash drive:
$ sudo mount -o uid=pi,gid=pi /dev/sda1 /mnt/flash_drive_mount_point

Note that:

-o (lowercase letter "o", not the number zero) specifies that an option string follows.

uid=pi,gid=pi specifies that the user ID is "pi" and the group ID is "pi" (note there are no spaces allowed between these two terms).

/dev/sda1 is the first partition on the first USB drive that the Raspberry Pi can detect.

Copy the contents of the flash drive to the flash_drive_contents directory on the Desktop:
$ cp -r /mnt/flash_drive_mount_point/* /home/pi/Desktop/flash_drive_contents

Unmount the flash drive:
$ sudo umount /mnt/flash_drive_mount_point

The flash drive can now be unplugged.





Ok. Move to the Raspberry Pi. Insert the memory stick.

pi@raspberrypi ~ $ pwd

/home/pi

pi@raspberrypi ~ $ ls -1

Desktop
Documents
Downloads
indiecity
python_game
Scratch

pi@raspberrypi ~ $ mkdir test


pi@raspberrypi ~ $ cd test


pi@raspberrypi ~/test $ ls -1 /dev/sda*

/dev/sda
/dev/sda1

pi@raspberrypi ~/test $ touch work.log


pi@raspberrypi ~/test $ ls -1

work.log




Now log the work and copy it here. Logged commands are run in the
~/test
directory.

While logging, record any annotations or comments here and integrate them into the log when the log has been transferred back from the Raspberry Pi to Aineko (where this article is being written).



pi@raspberrypi ~/test $ tee --version

tee (GNU coreutils) 8.13
Copyright (C) 2011 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Written by Mike Parker, Richard M. Stallman, and David MacKenzie.


[make a new directory to hold a copy of the contents of the memory stick]
pi@raspberrypi ~/test $ mkdir memory_stick_contents


[make a new directory to be the mount point for the memory stick]
pi@raspberrypi ~/test $ sudo mkdir /mnt/memory_stick_mount_point


pi@raspberrypi ~/test $ ls -1 /mnt

drive1
memory_stick_mount_point


[mount the memory stick]
pi@raspberrypi ~/test $ sudo mount -o uid=pi,gid=pi /dev/sda1 /mnt/memory_stick_mount_point


pi@raspberrypi ~/test $ ls -1 /mnt/memory_stick_mount_point

$RECYCLE.BIN
Recycled
System Volume Information
work


pi@raspberrypi ~/test $ ls -1 /mnt/memory_stick_mount_point/work

bitcoin_functions.py
bjorn_edstrom_ripemd160.py
convert_dice_rolls_to_hex_bytes_2.py
create_nonstandard_transaction.py
create_transaction.py
display_hex_bytes.py
ecdsa-0.10.tar.gz
generate_bitcoin_address_3.py
nonstandard_bitcoin_functions.py
nonstandard_transaction.py
pypy_sha256.py
transaction.py


[copy the contents of the memory stick to the memory_stick_contents directory]
pi@raspberrypi ~/test $ cp -r /mnt/memory_stick_mount_point/work/* memory_stick_contents


pi@raspberrypi ~/test $ ls -1 memory_stick_contents

bitcoin_functions.py
bjorn_edstrom_ripemd160.py
convert_dice_rolls_to_hex_bytes_2.py
create_nonstandard_transaction.py
create_transaction.py
display_hex_bytes.py
ecdsa-0.10.tar.gz
generate_bitcoin_address_3.py
nonstandard_bitcoin_functions.py
nonstandard_transaction.py
pypy_sha256.py
transaction.py


[check the OS version details]
pi@raspberrypi ~/test $ cat /etc/os-release

PRETTY_NAME="Raspbian GNU/Linux 7 (wheezy)"
NAME="Raspbian GNU/Linux"
VERSION_ID="7"
VERSION="7 (wheezy)"
ID=raspbian
ID_LIKE=debian
ANSI_COLOR="1;31"
HOME_URL="http://www.raspbian.org/"
SUPPORT_URL="http://www.raspbian.org/RaspbianForums"
BUG_REPORT_URL="http://www.raspbian.org/RaspbianBugs"


[check the kernel version]
pi@raspberrypi ~/test $ uname -r

4.1.13+


pi@raspberrypi ~/test $ nano --version

GNU nano version 2.2.6 (compiled 16:52:03, Mar 30 2012) (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc. Email: nano@nano-editor.org Web: http://www.nano-editor.org/ Compiled options: --disable-wrapping-as-root --enable-color --enable-extra --enable-multibuffer --enable-nanorc --enable-utf8



[Next: Create a Bitcoin private key, which is 32 bytes long.]

[
I'm following the recipe Recipe for generating entropy bytes using dice
to generate 32 bytes of entropy.
32 * 8 = 256
round_up( 256 / 1.3333 * 1.1 ) = 212 dice rolls
]


[how to use the Nano text editor is not specified here]


[
Perform 212 dice rolls, using Nano to record the results in dice_rolls.txt.

Time this using a stopwatch.

Time taken: 10:30.
Approximately 11 minutes.
]

pi@raspberrypi ~/test $ nano dice_rolls.txt



pi@raspberrypi ~/test $ ls -1

dice_rolls.txt
memory_stick_contents
work.log


pi@raspberrypi ~/test $ cat dice_rolls.txt

41223
26165
34316
52546
25334

25225
46332
63516
25465
15244

64526
46346
64443
54222
21236

42122
56626
66121
34113
53616

26466
61546
55451
11642
64351

41236
14241
55242
52546
56336

14322
45444
46556
22443
35464

11626
16466
13562
14265
56141

63666
31416
16


pi@raspberrypi ~/test $ cp memory_stick_contents/convert_dice_rolls_to_hex_bytes_2.py convert_dice_rolls_to_hex_bytes_2.py


pi@raspberrypi ~/test $ ls -1

convert_dice_rolls_to_hex_bytes_2.py
dice_rolls.txt
memory_stick_contents
work.log


[Use the Nano editor to edit the controls in convert_dice_rolls_to_hex_bytes_2.py, according to the recipe.]
pi@raspberrypi ~/test $ nano convert_dice_rolls_to_hex_bytes_2.py


[
Also, in general, use Nano to remove any mistaken commands from work.log (if they didn't cause irreversible changes of some kind), so that the command can be run again properly. In some cases (e.g. where the command involves a newline), some manual editing of the log may be necessary.

Use
cat work.log
after each command to confirm that its output was recorded as expected.
]


[
What are the Python version(s)?
python --version | tee -a work.log
and
python3 --version | tee -a work.log
don't work. no output recorded in work.log.

record them manually here:
]


pi@raspberrypi ~/test $ python --version

Python 2.7.3


pi@raspberrypi ~/test $ python3 --version

Python 3.2.3


pi@raspberrypi ~/test $ python convert_dice_rolls_to_hex_bytes_2.py


### START CONVERSION OF DICE ROLLS TO HEX BYTES

- number of dice rolls: 212
- number of dice rolls in the list [1234]: 132
- number of hex characters after conversion: 66
- number of hex bytes: 33
- desired number of hex bytes: 32
- the hex bytes produced are sufficient.
- hex byte output:
c592e1dad5e9871fdeffb551b4544b0a1cf0378c6371d7a397ff5faf04c934ca30
- hex byte output shortened to the desired length (32 bytes):
c592e1dad5e9871fdeffb551b4544b0a1cf0378c6371d7a397ff5faf04c934ca
- remaining hex bytes:
30

Result: Desired amount of entropy (32 bytes) has been produced.
Entropy (32 bytes):
c592e1dad5e9871fdeffb551b4544b0a1cf0378c6371d7a397ff5faf04c934ca
Recommendation: Perhaps preserve the 1 extra hex bytes in an entropy storage file.
Extra hex bytes: 30

### END CONVERSION OF DICE ROLLS TO HEX BYTES


[Recipe complete.]


[Let's extract the entropy from the log into its own file.]


[copy last 10 lines of work.log to a new file]
pi@raspberrypi ~/test $ tail -10 work.log > private_key.txt


[Use Nano to remove the text around the 32 entropy hex bytes. These 32 bytes will now be treated as the private key.]
pi@raspberrypi ~/test $ nano private_key.txt


pi@raspberrypi ~/test $ cat private_key.txt

c592e1dad5e9871fdeffb551b4544b0a1cf0378c6371d7a397ff5faf04c934ca


[get string length of private_key hex bytes - should be 32*2 = 64. Use
tr
to remove the newline character at the end of the file.]
pi@raspberrypi ~/test $ cat private_key.txt | tr -d '\n' | wc -c

64


[Next, generate a Bitcoin address from this private key.]


[I'm following the recipe Recipe for generating a Bitcoin address
]


pi@raspberrypi ~/test $ ls -1

convert_dice_rolls_to_hex_bytes_2.py
dice_rolls.txt
memory_stick_contents
private_key.txt
work.log


pi@raspberrypi ~/test $ cp memory_stick_contents/bitcoin_functions.py bitcoin_functions.py


pi@raspberrypi ~/test $ cp memory_stick_contents/bjorn_edstrom_ripemd160.py bjorn_edstrom_ripemd160.py


pi@raspberrypi ~/test $ cp memory_stick_contents/ecdsa-0.10.tar.gz ecdsa-0.10.tar.gz


pi@raspberrypi ~/test $ cp memory_stick_contents/pypy_sha256.py pypy_sha256.py


pi@raspberrypi ~/test $ cp memory_stick_contents/generate_bitcoin_address_3.py generate_bitcoin_address_3.py


pi@raspberrypi ~/test $ ls -1

bitcoin_functions.py
bjorn_edstrom_ripemd160.py
convert_dice_rolls_to_hex_bytes_2.py
dice_rolls.txt
ecdsa-0.10.tar.gz
generate_bitcoin_address_3.py
memory_stick_contents
private_key.txt
pypy_sha256.py
work.log


[Unpack the zipped tape archive file ecdsa-0.10.tar.gz.]
pi@raspberrypi ~/test $ tar -zxvf ecdsa-0.10.tar.gz

ecdsa-0.10/
ecdsa-0.10/ecdsa/
ecdsa-0.10/ecdsa/__init__.py
ecdsa-0.10/ecdsa/_version.py
ecdsa-0.10/ecdsa/curves.py
ecdsa-0.10/ecdsa/der.py
ecdsa-0.10/ecdsa/ecdsa.py
ecdsa-0.10/ecdsa/ellipticcurve.py
ecdsa-0.10/ecdsa/keys.py
ecdsa-0.10/ecdsa/numbertheory.py
ecdsa-0.10/ecdsa/rfc6979.py
ecdsa-0.10/ecdsa/six.py
ecdsa-0.10/ecdsa/test_pyecdsa.py
ecdsa-0.10/ecdsa/util.py
ecdsa-0.10/LICENSE
ecdsa-0.10/MANIFEST.in
ecdsa-0.10/NEWS
ecdsa-0.10/PKG-INFO
ecdsa-0.10/README.md
ecdsa-0.10/setup.py


pi@raspberrypi ~/test $ ls -1 ecdsa-0.10

ecdsa
LICENSE
MANIFEST.in
NEWS
PKG-INFO
README.md
setup.py


[Copy the "ecdsa" directory into the work directory.]
pi@raspberrypi ~/test $ cp -r ecdsa-0.10/ecdsa ecdsa


[
Use the Nano editor to edit the controls in generate_bitcoin_address_3.py, according to the recipe.
- Delete the existing value for the variable
private_key_hex_bytes
. Then use the Nano option "Read File" to paste the contents of the file private_key.txt into the position of the value for this variable (i.e. between the quotation marks). Then press the Backspace key to delete the final newline of the file that was also pasted in.
]


pi@raspberrypi ~/test $ nano generate_bitcoin_address.py


pi@raspberrypi ~/test $ python generate_bitcoin_address_3.py


### START GENERATION OF BITCOIN ADDRESS

Private key (hex bytes): c592e1dad5e9871fdeffb551b4544b0a1cf0378c6371d7a397ff5faf04c934ca
Private key (32 hex bytes): c592e1dad5e9871fdeffb551b4544b0a1cf0378c6371d7a397ff5faf04c934ca
Private key (WIF): 5KKJLZJVY7nZpGdSJcE6xwGf6WTD4m5Zjr7mFZh8dvQBaRFyHZf
Bitcoin address: 1vkb4YyPMFcxyC83Z5m5zuN45xASoHeNK

### END GENERATION OF BITCOIN ADDRESS


[The python generate_bitcoin_address_3.py command took a few seconds.]


[Recipe complete.]





Ok. Now copy work.log to the memory stick, then dismount the memory stick.

pi@raspberrypi ~/test $ cp work.log /mnt/memory_stick_mount_point


pi@raspberrypi ~/test $ sudo umount /mnt/memory_stick_mount_point



Unplug the memory stick from the Raspberry Pi.



Insert it into Aineko. It mounts automatically and an icon appears on the Desktop. Open the file work.log and copy its contents into this article (above this point). Merge any annotations and comments into this log, marking them with square brackets.



Done.




So: I have generated this address on an offline computer:
1vkb4YyPMFcxyC83Z5m5zuN45xASoHeNK

I'll call it the "test address".



On Aineko, right-click memory stick's Desktop icon and choose Eject "NO NAME". Unplug the memory stick from Aineko.




Next: Transfer some bitcoin to this address. Later, transfer it out. This will confirm that the address has been correctly derived from the private key.





First: Calculate how much bitcoin to send to the test address.

LocalBitcoins:
- Current deposit fee for incoming transactions: 0.00015 BTC
- Current transaction fee: 0.00005 BTC

Browse to:
bitcoinfees.earn.com

The fee rates are displayed in satoshi per byte of transaction data. A satoshi is 0.00000001 bitcoin.

Choose a high fee in order to have slack available. I'll attempt to use a low fee in the actual transaction.

A nonstandard transaction with one P2PKH input and one P2SH output should be approximately 221 bytes.

The fee rate range 1-2 satoshi / byte includes many transactions waiting for confirmation. Estimated delay = 3-66 blocks (35-840 minutes).

A fee rate of 60 satoshi / byte looks quite high. Estimated delay = 0 blocks (0-35 minutes).

I estimate that a fairly high fee will therefore be 221 bytes * 60 satoshi / byte = 221 * 60 = 13260 satoshi.

13260 satoshi * 1 BTC / 10^8 satoshi = 0.00013260 BTC


So, expected costs:
- LocalBitcoins transaction fee = 0.00005 BTC. This will be deducted from my LocalBitcoins wallet balance, not from the transction amount.
- Bitcoin network transaction fee (high-end) = 0.00013260 BTC.
- LocalBitcoins deposit fee = 0.00015 BTC.

I need to transfer at least this much to the test address:
(Bitcoin network transaction fee) + (LocalBitcoins deposit fee)
= 0.00013260 + 0.00015
= 0.00028260 BTC

This amount will need to cover the transaction costs of the second transaction (that will later transfer bitcoin out of the test address).


Current USD / BTC price:
$4904.99

(4904.99 USD / BTC) * 0.00028260 BTC = 4904.99 * 0.00028260 ~= $1.39



The number of transactions shown waiting for confirmation, especially at the lower fee ranges, is larger than I've usually seen.


I'll transfer $10-worth of bitcoin to the test address, so as to have room to manoeuvre. If the first version of the transaction is not mined, I will need to increase the fee, and upload a new version for broadcasting.


$10 * (1 BTC / 4904.99 USD) = 10 * 1 / 4904.99 ~= 0.00203874 BTC

I'll transfer 0.0020 bitcoin (~$9.8) into the test address.




Ok. Next:
Log in to LocalBitcoins. Transfer 0.0020 bitcoin to the test address:
1vkb4YyPMFcxyC83Z5m5zuN45xASoHeNK


Go to LocalBitcoins / Wallet / Transactions.

The transaction is listed. Message = "Pending send [etc]"


Wait for a while.


I'll call this transction "tx0" in this project.


Refresh the page.

In the latest entry (for the address
1vkb4YyPMFcxyC83Z5m5zuN45xASoHeNK ),
the txid is shown:
07cedb340f588dec2fb14472178a92d5803c70d8d90fc0d8593b03f34035e2cd



Browse to:
live.blockcypher.com

Search for this txid.

Transaction page loads:
live.blockcypher.com/btc/tx/07cedb340f588dec2fb14472178a92d5803c70d8d90fc0d8593b03f34035e2cd

Confirmations: 3/6

Set timer for 40 minutes.

Timer has ended.
Refresh page.
Confirmations: 6+




Click "Advanced Details". Click "API Call".

Result: tx0

{ "block_hash": "0000000000000000001b43b8af8973377619def5043634e9cb2d7dd584d973be", "block_height": 550741, "block_index": 455, "hash": "07cedb340f588dec2fb14472178a92d5803c70d8d90fc0d8593b03f34035e2cd", "hex": "0200000000010184cf2ed9386d5f3edb357e67540063d642a4f1340d77682c6c790d02ccfb4f121f00000017160014ac04ab49d76aeb07d4c49210f60047f640cb196dfeffffff202bcd22000000000017a914aa8f360859518dca87af02cd405c938a5962556f876d8809000000000017a914e3f53dbfc27efc20f5353ed75c5f56a2f4d22f9d87a35705000000000017a91415f9e71c57ae4682c2f69348f46af05e5d92d87087dc2a01000000000017a91452ee98be576a438d87a32f204c229b59d561796887c93a5db70000000017a91463226a9ea0a6d3c1c2722dd676b56356e14ec16887bd3e49000000000017a91463645845356338f13c2a0a1182c1849021e90f5b873a7204000000000017a914fe3859d20324dcad8094ded3867ee0d86e0e12e7870f7706000000000017a914fff7651a1190fd2d860e67c729ba45fa42411c1687618106000000000017a914b7bbaa02f1cf51b05ac667a042e3254f719a34ee87249703000000000017a914f617e48258c4c548665bf9b4de7a3e713db86ee087fb3749000000000017a914e5407a2219ffdb00505afdd828c1ba61ce6b317a875aad04000000000017a914870832203f94963208aead8869cd95e6075446fb878cbe09000000000017a9145504c5f7a8cb1ae9344cfa71646a59e5945e15d187664402000000000017a9144fa6ca9aa833a6219cb6b65b03e84be72042beab876cc90700000000001976a9149269fa94c59aa5054984a6aa36ab906edba3f36088ac400d0300000000001976a9140a2a6e4834efa5c7c31eed1ebeadf94a370a1e9388ac204e00000000000017a91482f1cf8e9cd1101c20feb549cd2848991ddadaf687685100000000000017a914c42cc570f52a69c9a5fcedf0a1856901aa615f3287c62705000000000017a914319d705ae9480eec4227f0d2bd4adae2ee0e43bb870e7706000000000017a9146c5e0be6a3654619893b01c0e180b74767825bff87184309000000000017a9144de4be7f547ee2c726020aefe4944111e78fd8608780b804000000000017a91462d5e9f939dcca60f43f2b797c860641c2b631aa8762a203000000000017a914ea900e3ea458c4d272257274fa47c32d63cdcd4e87aa3606010000000017a9146b7a98620bc938afa332e100ba9d543a07111daa87a14d10000000000017a914a39e1b5b69c62da1f1ea954a02f5ba9386790b59879afa0400000000001976a91410b77b5a69d4071174c2f480e619075217a83f2788ac904708000000000017a914482f1b3bffbc4c83b3e55c67e7f8add341bb5d908790e71400000000001976a91404a3fd24f45eb2a267a61ab7be2b2043c0f2474c88ac900709000000000017a91499288cbb13aa8a0528abf1999a86d04b17c6ddd687438e01000000000017a914bb22d3ad33802d5ff6fd218413dcbb81f78c3ec48770141507000000001976a914df56a67c8f312699b5114d0e1f8ba63aa0dae8ad88ac40390600000000001976a91459e196681a14c880ff4144cc23a45a14cfaaf0d288ac024830450221009c6f18d0bff51e20e52032f5cf13acc6c734b4a560dc483fc37795de8918b255022022e3cdae51e40d99225d05512e48c686444e79b46bf1c4002824148f7e39c8f7012102fc269453f121876200573e5c1a5b1ecd214064dc0c3f2d2967e4df65dde527163f670800", "addresses": [ "3AjC3qLFG1KymcynTX5EcdNntD7cBEwN9b", "3JSWPnAUigZ8uzxoY9FqM3zcEH6mBPPUGj", "39SZ5WEEBeEgf7M3E4G2fXWrhbctpAKsYR", "39nRG4yzSf7hgTN2UiFTETBD8Jwy9imeTb", "3Gc9UGb8d9xiZzx8cWcoFJHidY4yyVTD5L", "12XPccUSreQ9RwGQEAgeKGo7GdyLcNCokd", "3JkW1EDxnuq84Q4us4ryvjJz4uqaFhda8y", "36DMdzKb9WFnQECwPukHotC3z3xBo3FC6W", "3DzzxttCG7M48Mmd6f6vcCaPWVb2VDaYbT", "38nsyjcVsgnbyNkNx2seKxFqqWgP4cF6Ke", "39FXAG2ytLBgtoqCNWWpPwPXevEkffwKBS", "3Ba1Zj4TeS2sRFm7WDd1xrwRxNqYzMXtPK", "3AhcQLznoPapj1LShqrkXtWg4kBt21MNR5", "3BVK68suAqQ52T5UDSytGnEJW5tPMXc13x", "3NbBuRGMinhcCPsoecMwKphT9BMA4yp6BE", "3FeqtLafmwNfWDhcwmvzTwweJPNEVDXSq4", "1MMuVMFnq7dCyxitnHdAFoDcdiwXKgdujx", "38Gh1N6SQzxQ5o59QFuzh56x3tc5aZ4KnD", "3R2Sbm82wwTPXhLY9E64CaVgVsKYLFvGA5", "3Q8EmpdKDtVZmTTrfhBD17K6ZQDLUASCs3", "38xB7ZzDnAFEyz3hs8cDt1vQxKHZsWu26V", "3DdPSngv2ssAZAgA9ePPNef7m9cHX3HfWT", "3KaHzuNmL4QjpzizHExtPtW7TEAZyoCAND", "19CFPAoWLzUi9rcJ4hnSD5mwJ4xPDWnCpQ", "3QsD4bUGFUt4Ty48Ni4JxYshheTdwnhZKB", "3NUM6kHP7ZLzm2fhHnyrWpa1jCAmrZAY1S", "3AkZ2capQd2GZr3KfMG5guszvzHcVXaD8z", "1vkb4YyPMFcxyC83Z5m5zuN45xASoHeNK", "3HErMdjZR9No28jRUiHwBYRLfC4gVqEaaU", "1EMAcYeU5VNJDAzsLVRRWUp595YZczq9PE", "3P5GcbPGfkdwT62NLhmBfmiBtS8HJKfV3f", "1RY9uu5pebzP2BYMBdBjZDJMrXdiQGmYP", "33hDV7zwRhcgdJmyTWbJFLRMEawYweCNLi" ], "total": 3234824252, "fees": 70068, "size": 1110, "preference": "high", "confirmed": "2018-11-19T19:46:37Z", "received": "2018-11-19T19:46:37Z", "ver": 2, "lock_time": 550719, "double_spend": false, "vin_sz": 1, "vout_sz": 32, "confirmations": 7, "confidence": 1, "inputs": [ { "prev_hash": "124ffbcc020d796c2c68770d34f1a442d6630054677e35db3e5f6d38d92ecf84", "output_index": 31, "script": "160014ac04ab49d76aeb07d4c49210f60047f640cb196d", "output_value": 3234894320, "sequence": 4294967294, "addresses": [ "39nRG4yzSf7hgTN2UiFTETBD8Jwy9imeTb" ], "script_type": "pay-to-script-hash", "age": 550741, "witness": [ "30450221009c6f18d0bff51e20e52032f5cf13acc6c734b4a560dc483fc37795de8918b255022022e3cdae51e40d99225d05512e48c686444e79b46bf1c4002824148f7e39c8f701", "02fc269453f121876200573e5c1a5b1ecd214064dc0c3f2d2967e4df65dde52716" ] } ], "outputs": [ { "value": 2280747, "script": "a914aa8f360859518dca87af02cd405c938a5962556f87", "addresses": [ "3HErMdjZR9No28jRUiHwBYRLfC4gVqEaaU" ], "script_type": "pay-to-script-hash" }, { "value": 624749, "script": "a914e3f53dbfc27efc20f5353ed75c5f56a2f4d22f9d87", "spent_by": "b69db5fc5af41b17c4c521e95cefd6f19d095bf1856d4219c071251cec723ce6", "addresses": [ "3NUM6kHP7ZLzm2fhHnyrWpa1jCAmrZAY1S" ], "script_type": "pay-to-script-hash" }, { "value": 350115, "script": "a91415f9e71c57ae4682c2f69348f46af05e5d92d87087", "addresses": [ "33hDV7zwRhcgdJmyTWbJFLRMEawYweCNLi" ], "script_type": "pay-to-script-hash" }, { "value": 76508, "script": "a91452ee98be576a438d87a32f204c229b59d561796887", "spent_by": "8727eed4e1e629261ada96547b9abcef0d09b98919d04b89a52c68082013d860", "addresses": [ "39FXAG2ytLBgtoqCNWWpPwPXevEkffwKBS" ], "script_type": "pay-to-script-hash" }, { "value": 3076340425, "script": "a91463226a9ea0a6d3c1c2722dd676b56356e14ec16887", "spent_by": "97d499163bf5d78eec5c7c6c4014910a198b5f53b190003dc52396d5d9dfd065", "addresses": [ "3AjC3qLFG1KymcynTX5EcdNntD7cBEwN9b" ], "script_type": "pay-to-script-hash" }, { "value": 4800189, "script": "a91463645845356338f13c2a0a1182c1849021e90f5b87", "addresses": [ "3AkZ2capQd2GZr3KfMG5guszvzHcVXaD8z" ], "script_type": "pay-to-script-hash" }, { "value": 291386, "script": "a914fe3859d20324dcad8094ded3867ee0d86e0e12e787", "spent_by": "5e2a287d6ddd2ef615c1481bdfaaf579fd54ddca8b3b022c5fe399c845a2463a", "addresses": [ "3QsD4bUGFUt4Ty48Ni4JxYshheTdwnhZKB" ], "script_type": "pay-to-script-hash" }, { "value": 423695, "script": "a914fff7651a1190fd2d860e67c729ba45fa42411c1687", "addresses": [ "3R2Sbm82wwTPXhLY9E64CaVgVsKYLFvGA5" ], "script_type": "pay-to-script-hash" }, { "value": 426337, "script": "a914b7bbaa02f1cf51b05ac667a042e3254f719a34ee87", "addresses": [ "3JSWPnAUigZ8uzxoY9FqM3zcEH6mBPPUGj" ], "script_type": "pay-to-script-hash" }, { "value": 235300, "script": "a914f617e48258c4c548665bf9b4de7a3e713db86ee087", "addresses": [ "3Q8EmpdKDtVZmTTrfhBD17K6ZQDLUASCs3" ], "script_type": "pay-to-script-hash" }, { "value": 4798459, "script": "a914e5407a2219ffdb00505afdd828c1ba61ce6b317a87", "addresses": [ "3NbBuRGMinhcCPsoecMwKphT9BMA4yp6BE" ], "script_type": "pay-to-script-hash" }, { "value": 306522, "script": "a914870832203f94963208aead8869cd95e6075446fb87", "spent_by": "1c2d2ed3714fa9928686297aba600fddc9197b59a5a24be8c7969ac6c344f854", "addresses": [ "3DzzxttCG7M48Mmd6f6vcCaPWVb2VDaYbT" ], "script_type": "pay-to-script-hash" }, { "value": 638604, "script": "a9145504c5f7a8cb1ae9344cfa71646a59e5945e15d187", "spent_by": "0c9fa5c06526270f7205c217f06a6df7effd00f3b35a369e2cac713854735e04", "addresses": [ "39SZ5WEEBeEgf7M3E4G2fXWrhbctpAKsYR" ], "script_type": "pay-to-script-hash" }, { "value": 148582, "script": "a9144fa6ca9aa833a6219cb6b65b03e84be72042beab87", "spent_by": "fa7f13662269af17f9ae2ee938e718ec44d0d2c8ef037429b3f83a7a87e0bffa", "addresses": [ "38xB7ZzDnAFEyz3hs8cDt1vQxKHZsWu26V" ], "script_type": "pay-to-script-hash" }, { "value": 510316, "script": "76a9149269fa94c59aa5054984a6aa36ab906edba3f36088ac", "spent_by": "05e10942209f7254cbb989e1ce3976d5bc7e0b6259ec0b8726407991a32bdaad", "addresses": [ "1EMAcYeU5VNJDAzsLVRRWUp595YZczq9PE" ], "script_type": "pay-to-pubkey-hash" }, { "value": 200000, "script": "76a9140a2a6e4834efa5c7c31eed1ebeadf94a370a1e9388ac", "addresses": [ "1vkb4YyPMFcxyC83Z5m5zuN45xASoHeNK" ], "script_type": "pay-to-pubkey-hash" }, { "value": 20000, "script": "a91482f1cf8e9cd1101c20feb549cd2848991ddadaf687", "addresses": [ "3DdPSngv2ssAZAgA9ePPNef7m9cHX3HfWT" ], "script_type": "pay-to-script-hash" }, { "value": 20840, "script": "a914c42cc570f52a69c9a5fcedf0a1856901aa615f3287", "addresses": [ "3KaHzuNmL4QjpzizHExtPtW7TEAZyoCAND" ], "script_type": "pay-to-script-hash" }, { "value": 337862, "script": "a914319d705ae9480eec4227f0d2bd4adae2ee0e43bb87", "addresses": [ "36DMdzKb9WFnQECwPukHotC3z3xBo3FC6W" ], "script_type": "pay-to-script-hash" }, { "value": 423694, "script": "a9146c5e0be6a3654619893b01c0e180b74767825bff87", "addresses": [ "3Ba1Zj4TeS2sRFm7WDd1xrwRxNqYzMXtPK" ], "script_type": "pay-to-script-hash" }, { "value": 607000, "script": "a9144de4be7f547ee2c726020aefe4944111e78fd86087", "spent_by": "abfc5481eccc8b04a866530e8e520194270d06237de56513ab87975054dd9f87", "addresses": [ "38nsyjcVsgnbyNkNx2seKxFqqWgP4cF6Ke" ], "script_type": "pay-to-script-hash" }, { "value": 309376, "script": "a91462d5e9f939dcca60f43f2b797c860641c2b631aa87", "addresses": [ "3AhcQLznoPapj1LShqrkXtWg4kBt21MNR5" ], "script_type": "pay-to-script-hash" }, { "value": 238178, "script": "a914ea900e3ea458c4d272257274fa47c32d63cdcd4e87", "addresses": [ "3P5GcbPGfkdwT62NLhmBfmiBtS8HJKfV3f" ], "script_type": "pay-to-script-hash" }, { "value": 17184426, "script": "a9146b7a98620bc938afa332e100ba9d543a07111daa87", "addresses": [ "3BVK68suAqQ52T5UDSytGnEJW5tPMXc13x" ], "script_type": "pay-to-script-hash" }, { "value": 1068449, "script": "a914a39e1b5b69c62da1f1ea954a02f5ba9386790b5987", "spent_by": "07e826035301cc9c3ad07819b0bac9c47b887c2a704ac1cdde137d438d2a8354", "addresses": [ "3Gc9UGb8d9xiZzx8cWcoFJHidY4yyVTD5L" ], "script_type": "pay-to-script-hash" }, { "value": 326298, "script": "76a91410b77b5a69d4071174c2f480e619075217a83f2788ac", "addresses": [ "12XPccUSreQ9RwGQEAgeKGo7GdyLcNCokd" ], "script_type": "pay-to-pubkey-hash" }, { "value": 542608, "script": "a914482f1b3bffbc4c83b3e55c67e7f8add341bb5d9087", "addresses": [ "38Gh1N6SQzxQ5o59QFuzh56x3tc5aZ4KnD" ], "script_type": "pay-to-script-hash" }, { "value": 1370000, "script": "76a91404a3fd24f45eb2a267a61ab7be2b2043c0f2474c88ac", "addresses": [ "1RY9uu5pebzP2BYMBdBjZDJMrXdiQGmYP" ], "script_type": "pay-to-pubkey-hash" }, { "value": 591760, "script": "a91499288cbb13aa8a0528abf1999a86d04b17c6ddd687", "spent_by": "abfc5481eccc8b04a866530e8e520194270d06237de56513ab87975054dd9f87", "addresses": [ "3FeqtLafmwNfWDhcwmvzTwweJPNEVDXSq4" ], "script_type": "pay-to-script-hash" }, { "value": 101955, "script": "a914bb22d3ad33802d5ff6fd218413dcbb81f78c3ec487", "addresses": [ "3JkW1EDxnuq84Q4us4ryvjJz4uqaFhda8y" ], "script_type": "pay-to-script-hash" }, { "value": 118822000, "script": "76a914df56a67c8f312699b5114d0e1f8ba63aa0dae8ad88ac", "spent_by": "7416e66c3d4ad4d67a6c03a3018d28b62a3a915e336e5f9bb10da2255f1a1fba", "addresses": [ "1MMuVMFnq7dCyxitnHdAFoDcdiwXKgdujx" ], "script_type": "pay-to-pubkey-hash" }, { "value": 407872, "script": "76a91459e196681a14c880ff4144cc23a45a14cfaaf0d288ac", "addresses": [ "19CFPAoWLzUi9rcJ4hnSD5mwJ4xPDWnCpQ" ], "script_type": "pay-to-pubkey-hash" } ] }



Key details:
- block_hash:
0000000000000000001b43b8af8973377619def5043634e9cb2d7dd584d973be
- block_height: 550741
- confirmed: 2018-11-19T19:46:37Z
- received: 2018-11-19T19:46:37Z
- txid:
07cedb340f588dec2fb14472178a92d5803c70d8d90fc0d8593b03f34035e2cd
- vout_sz (number of outputs): 32


Shutting down for the day.

On the Raspberry Pi:

pi@raspberrypi ~/test $ sudo halt

[a variety of output is printed, then the Raspberry Pi shuts down]



To boot the Raspberry Pi up again, unplug the power cable and plug it in again.




Start work again.




Next: Create a transaction that moves the available bitcoin out of the test address. I'll call this "tx1".


I'll transfer it back to my LocalBitcoins account, which will have a nonstandard P2SH address. I will therefore follow this article:
Recipe for creating and signing a nonstandard Bitcoin transaction


Note: If I had decided to transfer the bitcoin to a standard P2PKH address, I would have followed this article:
Recipe for creating and signing a standard Bitcoin transaction



Several points concerning Bitcoin transactions:
- New transactions spend unspent-outputs-of-previous-transactions.
- The bitcoin balance of an address is the sum of the unspent outputs sent by previous transactions to this address.
- To spend bitcoin from an address, the bitcoin amount must be constructed from complete unspent outputs. Any change can be sent in a new unspent output back to the original address or another that you control. Unspent outputs cannot be broken into smaller unspent outputs prior to spending - new unspent outputs (larger or smaller) must be created by a new transaction.




The recipe requires me to gather certain pieces of information.

Let's proceed.


- The txid of the previous transaction (tx0, which transferred the unspent output to the test address) is:
07cedb340f588dec2fb14472178a92d5803c70d8d90fc0d8593b03f34035e2cd

- The index of this unspent output in the previous transaction (the "previous_output_index"):
15

[I found the previous_output_index by searching the raw form of tx0 (included earlier in this article) for the test address, temporarily marking the output that contained it, then counting manually (starting from 0) from the first output until I reached the output containing the test address.]

- The private key (in hex bytes) of the test address is:
c592e1dad5e9871fdeffb551b4544b0a1cf0378c6371d7a397ff5faf04c934ca

Note: This is stored on the Raspberry Pi in the file private_key.txt.

- The "input amount" == The bitcoin amount (or satoshi amount) contained within the unspent output:
0.002 bitcoin

- I need a 32-byte random value, to be used when signing the transaction tx1 with the input (each input must sign the transaction).
-- Hm. I'll leave this for now. I will generate 32 bytes of entropy later, when I'm working again on the Raspberry Pi.
-- Note: The random value must also be kept secret, and never exist, however temporarily on an online computer.




The recipe requires me to choose certain pieces of information.


- The output address (which must be a nonstandard P2SH address) is:
369Dpo9CrJASneaHLdwWfKym7N84XTUyvH

[This is the current receiving address on my LocalBitcoins account. It starts with the character '3', so I know it's a P2SH address.]


- The "output amount" == The bitcoin amount (or satoshi amount) that I wish to transfer to the output address:
0.002 bitcoin


[Note: This should be equal to the input amount (the code does not have the ability to send change). Any unassigned value will still be sent to the single output address (which in this recipe is the same as the change address).]


- The change address.
369Dpo9CrJASneaHLdwWfKym7N84XTUyvH

[Note: In this recipe, the change address must be the same as the single output address.]


- The fee (in satoshi) or fee_rate (in satoshi / byte):
fee_rate = 1 satoshi / byte


This is the lowest end of the fee ranges I looked at earlier.

If the transaction is not mined within 3 days, I'll increase the fee, re-sign it, and broadcast the new version (which will invalidate the older version, because it will spend the same unspent output).

Note: Each new signature requires a new random value. Using the same random value twice in two different signatures could compromise the secrecy of the private key.



I'll switch to the Raspberry Pi.


When I need the information gathered / chosen above, I'll copy it manually into the Raspberry Pi, reading it from Aineko's screen.



Insert the power cable into the Raspberry Pi.



Enter default credentials:


raspberrypi login: pi


Password:


Last login: Sun Mar 27 18:28:14 UTC 2016 on tty1
Linux raspberrypi 4.1.13+ #826 PREEMPT Fri Nov 13 20:13:22 GMT 2015 armv61

The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.

pi@raspberrypi ~ $



The password was "raspberry" but this was not echoed to the screen.


pi@raspberrypi ~ $ pwd

/home/pi

pi@raspberrypi ~ $ ls -1

Desktop
Documents
Downloads
indiecity
python_game
Scratch
test

pi@raspberrypi ~ $ cd test


pi@raspberrypi ~/test $ touch work_log2.txt





I'll begin logging in the new file called "work_log2.txt". Eventually, I'll transfer it via memory stick to Aineko.

Logged commands are run in the
~/test
directory on the Raspberry Pi.

While logging, record any annotations or comments here and integrate them into the log when the log has been transferred back from the Raspberry Pi to Aineko (where this article is being written).





[Begin logging on Raspberry Pi.]


pi@raspberrypi ~/test $ ls -1

bitcoin_functions.py
bitcoin_functions.pyc
bjorn_edstrom_ripemd160.py
bjorn_edstrom_ripemd160.pyc
convert_dice_rolls_to_hex_bytes_2.py
dice_rolls.txt
ecdsa
ecdsa-0.10
ecdsa-0.10.tar.gz
generate_bitcoin_address_3.py
memory_stick_contents
private_key.txt
pypy_sha256.py
pypy_sha256.pyc
work.log
work_log2.txt



[first, generate 32 bytes of entropy to use as the random value for making the transaction signature]



[
I'm following the recipe Recipe for generating entropy bytes using dice
to generate 32 bytes of entropy.
32 * 8 = 256
round_up( 256 / 1.3333 * 1.1 ) = 212 dice rolls
]



pi@raspberrypi ~/test $ nano dice_rolls2.txt

[
Perform 212 dice rolls, using Nano to record the results in dice_rolls2.txt.

Time this using a stopwatch.

Time taken: 7:32.
Approximately 8 minutes.
]



[Use the Nano editor to edit the controls in convert_dice_rolls_to_hex_bytes_2.py, according to the recipe.]
pi@raspberrypi ~/test $ nano convert_dice_rolls_to_hex_bytes_2.py



pi@raspberrypi ~/test $ python convert_dice_rolls_to_hex_bytes_2.py


### START CONVERSION OF DICE ROLLS TO HEX BYTES

- number of dice rolls: 212
- number of dice rolls in the list [1234]: 146
- number of hex characters after conversion: 73
- there is one extra hex character that can't be used to form an entire 8-bit byte.
- number of hex bytes: 36
- desired number of hex bytes: 32
- the hex bytes produced are sufficient.
- hex byte output:
91fbb8a38082b09e6ed984fda95866dfab95dc66b0cb6b5133dd87d07315364e279d9258
- hex byte output shortened to the desired length (32 bytes):
91fbb8a38082b09e6ed984fda95866dfab95dc66b0cb6b5133dd87d07315364e
- remaining hex bytes:
279d9258

Result: Desired amount of entropy (32 bytes) has been produced.
Entropy (32 bytes):
91fbb8a38082b09e6ed984fda95866dfab95dc66b0cb6b5133dd87d07315364e
Recommendation: Perhaps preserve the 4 extra hex bytes in an entropy storage file.
Extra hex bytes: 279d9258

### END CONVERSION OF DICE ROLLS TO HEX BYTES



[Recipe complete.]



[Let's extract the entropy from the log into its own file.]



[copy last 15 lines of work_log2.txt to a new file]
pi@raspberrypi ~/test $ tail -15 work_log2.txt > random_value.txt



[Use Nano to remove the text around the 32 entropy hex bytes contained in the output. I will later use these 32 bytes as the random value.]
pi@raspberrypi ~/test $ nano random_value.txt



[get string length of random_value.txt hex bytes - should be 32*2 = 64. Use
tr
to remove the newline character at the end of the file.]
pi@raspberrypi ~/test $ cat random_value.txt | tr -d '\n' | wc -c

64



pi@raspberrypi ~/test $ ls -1

bitcoin_functions.py
bitcoin_functions.pyc
bjorn_edstrom_ripemd160.py
bjorn_edstrom_ripemd160.pyc
convert_dice_rolls_to_hex_bytes_2.py
dice_rolls2.txt
dice_rolls.txt
ecdsa
ecdsa-0.10
ecdsa-0.10.tar.gz
generate_bitcoin_address_3.py
memory_stick_contents
private_key.txt
pypy_sha256.py
pypy_sha256.pyc
random_value.txt
work.log
work_log2.txt




[Now, proceed with the recipe in Recipe for creating and signing a nonstandard Bitcoin transaction ]



[I'll use the existing directory "test" as the work directory.]



[Copy needed files from memory_stick_contents to test directory.]



pi@raspberrypi ~/test $ cp memory_stick_contents/create_nonstandard_transaction.py create_nonstandard_transaction.py



pi@raspberrypi ~/test $ cp memory_stick_contents/nonstandard_bitcoin_functions.py nonstandard_bitcoin_functions.py



pi@raspberrypi ~/test $ cp memory_stick_contents/nonstandard_transaction.py nonstandard_transaction.py



pi@raspberrypi ~/test $ cp memory_stick_contents/transaction.py transaction.py



pi@raspberrypi ~/test $ ls -1

bitcoin_functions.py
bitcoin_functions.pyc
bjorn_edstrom_ripemd160.py
bjorn_edstrom_ripemd160.pyc
convert_dice_rolls_to_hex_bytes_2.py
create_nonstandard_transaction.py
dice_rolls2.txt
dice_rolls.txt
ecdsa
ecdsa-0.10
ecdsa-0.10.tar.gz
generate_bitcoin_address_3.py
memory_stick_contents
nonstandard_bitcoin_functions.py
nonstandard_transaction.py
private_key.txt
pypy_sha256.py
pypy_sha256.pyc
random_value.txt
transaction.py
work.log
work_log2.txt



[ecdsa-0.10.tar.gz is already unpacked.]



[
Use the Nano editor to edit the controls in create_nonstandard_transaction.py, according to the recipe. Manually enter the gathered / chosen values (reading them from this article displayed on Aineko's screen), except for the variables
random_value
and
input_data["private_key_hex"]
.
- Delete the existing value for the variable
random_value
. Then use the Nano option "Read File" to paste the contents of the file random_value.txt into the position of the value for this variable (i.e. between the quotation marks). Then press the Backspace key to delete the final newline of the file that was also pasted in.
- The variable
input_data
is a dictionary that contains several other variables. Delete the existing value for the variable
input_data["private_key_hex"]
. Then use the Nano option "Read File" to paste the contents of the file private_key.txt into the position of the value for this variable (i.e. between the quotation marks). Then press the Backspace key to delete the final newline of the file that was also pasted in.
Note: With long strings, e.g. the txid, you can make a copy on the online computer (Aineko, in this case) and split it into groups of 4 characters, then manually copy each group over to the offline Raspberry Pi, then do a double-check of the group values, and finally delete the spaces again to form the original txid.
]

pi@raspberrypi ~/test $ nano create_nonstandard_transaction.py



[Note: In create_nonstandard_transaction.py, all control values are strings (i.e. are contained within quotation marks).]



[Let's record a copy of the settings. They are on lines 41-65. I'll copy the excerpt lines 40-66 to the log.]



pi@raspberrypi ~/test $ cat create_nonstandard_transaction.py | sed -n '40,66p'

##### START CONTROLS random_value = "91fbb8a38082b09e6ed984fda95866dfab95dc66b0cb6b5133dd87d07315364e" # 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": "07cedb340f588dec2fb14472178a92d5803c70d8d90fc0d8593b03f34035e2cd", "previous_output_index": "15", "private_key_hex": "c592e1dad5e9871fdeffb551b4544b0a1cf0378c6371d7a397ff5faf04c934ca", #"satoshi_amount": "241777", "bitcoin_amount": "0.0020", "input_type": "p2pkh", } output_data = { "address": "369Dpo9CrJASneaHLdwWfKym7N84XTUyvH", #"satoshi_amount": "241000", "bitcoin_amount": "0.0020", "output_type": "p2sh", } change_address = "369Dpo9CrJASneaHLdwWfKym7N84XTUyvH" # note: the fee will be subtracted from the amount that is being sent to the change address. fee = "225" # satoshi fee_rate = "1" # satoshi / byte # fee_type options: ["fee", "fee_rate"] fee_type = "fee_rate" ##### END CONTROLS




pi@raspberrypi ~/test $ python create_nonstandard_transaction.py


### START CREATION OF NONSTANDARD BITCOIN TRANSACTION

- Fee type: fee_rate
- Fee rate: 1.0 (satoshi / byte)
- Number of inputs (i.e. as-yet-unspent outputs): 1
- Number of outputs: 1
- Change address: 369Dpo9CrJASneaHLdwWfKym7N84XTUyvH
- Amount to be sent to the change address: 0.0020
- Input addresses, with total-value-to-be-sent:
-- 1vkb4YyPMFcxyC83Z5m5zuN45xASoHeNK: 0.00200000
- Output addresses, with total-value-to-be-received:
-- 369Dpo9CrJASneaHLdwWfKym7N84XTUyvH: 0.00200000
- Total value of all inputs: 0.00200000
- Total value of all outputs: 0.00200000
- Total value of all inputs exactly matches total value of all outputs.
- Estimated transaction size: 221 bytes
- Fee rate: 1.0 (satoshi / byte)
- Calculate 221 * 1.0 and round up to nearest satoshi.
- Final fee: 221 (satoshi)
- Final fee rate (using estimated transaction size): 1.0000 (satoshi per byte)
- Fee subtracted from amount to be sent to change address.
- New amount to be sent to change address: 199779 (satoshi)

Input 0:
Input (without signature):
- previous_output_hash: cde23540f3033b59d8c00fd9d8703c80d5928a177244b12fec8d580f34dbce07
- previous_output_index: 0f000000
- sequence: ffffffff
- private_key_hex: c592e1dad5e9871fdeffb551b4544b0a1cf0378c6371d7a397ff5faf04c934ca
- public_key_hex: 043ab692792d6c8838fd30c2ff45bf3cbd44286a5cac52ba64dc06452810202b3206f5c7799c3b72ff77fd1976f105ced3cd7700b0412e11266f3888b88c3052c3
- script_length_scriptPubKey: 19
- scriptPubKey: 76a9140a2a6e4834efa5c7c31eed1ebeadf94a370a1e9388ac
- script_length: None
- scriptSig: None
- address: 1vkb4YyPMFcxyC83Z5m5zuN45xASoHeNK
- previous_output_index_int: 15
- txid: 07cedb340f588dec2fb14472178a92d5803c70d8d90fc0d8593b03f34035e2cd

Output 0:
Output:
- value: 630c030000000000
- script_length: 17
- script: a91430d540a50d464852194a195529ebfa44af521bbb87
- address: 369Dpo9CrJASneaHLdwWfKym7N84XTUyvH
- bitcoin_amount: 0.00199779
- satoshi_amount: 199779
- redeem_script_hash_hex: 30d540a50d464852194a195529ebfa44af521bbb

Nonstandard Transaction (unsigned form):
- version: 01000000
- input_count: 01
- Input:
-- previous_output_hash: cde23540f3033b59d8c00fd9d8703c80d5928a177244b12fec8d580f34dbce07
-- previous_output_index: 0f000000
-- script_length: None
-- scriptSig: None
-- sequence: ffffffff
- output_count: 01
- Output [P2SH]:
-- value: 630c030000000000
-- script_length: 17
-- script: a91430d540a50d464852194a195529ebfa44af521bbb87
- block_lock_time: 00000000

Nonstandard Transaction (signable form):
- version: 01000000
- input_count: 01
- Input [to be used to sign this signable form]:
-- previous_output_hash: cde23540f3033b59d8c00fd9d8703c80d5928a177244b12fec8d580f34dbce07
-- previous_output_index: 0f000000
-- script_length_scriptPubKey: 19
-- scriptPubKey: 76a9140a2a6e4834efa5c7c31eed1ebeadf94a370a1e9388ac
-- sequence: ffffffff
- output_count: 01
- Output [P2SH]:
-- value: 630c030000000000
-- script_length: 17
-- script: a91430d540a50d464852194a195529ebfa44af521bbb87
- block_lock_time: 00000000
- hash_type_4_byte: 01000000

Nonstandard Transaction (signed form):
- version: 01000000
- input_count: 01
- Input:
-- previous_output_hash: cde23540f3033b59d8c00fd9d8703c80d5928a177244b12fec8d580f34dbce07
-- previous_output_index: 0f000000
-- script_length: 8a
-- scriptSig: 473044022005fc767d513f285c38f718f4c9cfb0909d4ba2d80131aed21b3f26aa630a79f0022044c9b3c0fb4a9d1a8b0c269915399112eea5ee4fd7e42fc0a430a47e5ecbb4520141043ab692792d6c8838fd30c2ff45bf3cbd44286a5cac52ba64dc06452810202b3206f5c7799c3b72ff77fd1976f105ced3cd7700b0412e11266f3888b88c3052c3
-- sequence: ffffffff
- output_count: 01
- Output [P2SH]:
-- value: 630c030000000000
-- script_length: 17
-- script: a91430d540a50d464852194a195529ebfa44af521bbb87
- block_lock_time: 00000000
- hash_type_4_byte: 01000000

Signed transaction:
0100000001cde23540f3033b59d8c00fd9d8703c80d5928a177244b12fec8d580f34dbce070f0000008a473044022005fc767d513f285c38f718f4c9cfb0909d4ba2d80131aed21b3f26aa630a79f0022044c9b3c0fb4a9d1a8b0c269915399112eea5ee4fd7e42fc0a430a47e5ecbb4520141043ab692792d6c8838fd30c2ff45bf3cbd44286a5cac52ba64dc06452810202b3206f5c7799c3b72ff77fd1976f105ced3cd7700b0412e11266f3888b88c3052c3ffffffff01630c03000000000017a91430d540a50d464852194a195529ebfa44af521bbb870000000001000000

### END CREATION OF BITCOIN TRANSACTION




[The python create_nonstandard_transaction.py command took a few seconds.]


[Recipe complete.]



[Let's extract the signed transaction from the log into its own file.]



[copy last 15 lines of work_log2.txt to a new file]
pi@raspberrypi ~/test $ tail -15 work_log2.txt > signed_transaction.txt



[Use Nano to remove the text around the signed transaction hex string contained in the output.]
pi@raspberrypi ~/test $ nano signed_transaction.txt



pi@raspberrypi ~/test $ cat signed_transaction.txt

0100000001cde23540f3033b59d8c00fd9d8703c80d5928a177244b12fec8d580f34dbce070f0000008a473044022005fc767d513f285c38f718f4c9cfb0909d4ba2d80131aed21b3f26aa630a79f0022044c9b3c0fb4a9d1a8b0c269915399112eea5ee4fd7e42fc0a430a47e5ecbb4520141043ab692792d6c8838fd30c2ff45bf3cbd44286a5cac52ba64dc06452810202b3206f5c7799c3b72ff77fd1976f105ced3cd7700b0412e11266f3888b88c3052c3ffffffff01630c03000000000017a91430d540a50d464852194a195529ebfa44af521bbb870000000001000000



[get string length of signed_transaction.txt hex bytes. Use
tr
to remove the newline character at the end of the file.]
pi@raspberrypi ~/test $ cat signed_transaction.txt | tr -d '\n' | wc -c

450


[450 / 2 = 225 bytes.]


[Hm. Strange. I had expected 221 bytes for a transaction with a single P2PKH input and a single P2SH output. Future: look into this.]



[Finally, follow the recipe in the article Displaying hex bytes for manual copying to make the signed transaction easier to read and manually copy from the offline Raspberry Pi to the online Aineko.]


pi@raspberrypi ~/test $ ls -1

bitcoin_functions.py
bitcoin_functions.pyc
bjorn_edstrom_ripemd160.py
bjorn_edstrom_ripemd160.pyc
convert_dice_rolls_to_hex_bytes_2.py
create_nonstandard_transaction.py
dice_rolls2.txt
dice_rolls.txt
ecdsa
ecdsa-0.10
ecdsa-0.10.tar.gz
generate_bitcoin_address_3.py
memory_stick_contents
nonstandard_bitcoin_functions.py
nonstandard_bitcoin_functions.pyc
nonstandard_transaction.py
nonstandard_transaction.pyc
private_key.txt
pypy_sha256.py
pypy_sha256.pyc
random_value.txt
signed_transaction.txt
transaction.py
transaction.pyc
work.log
work_log2.txt



[Copy needed files from memory_stick_contents to test directory.]

pi@raspberrypi ~/test $ cp memory_stick_contents/display_hex_bytes.py display_hex_bytes.py




pi@raspberrypi ~/test $ ls -1

bitcoin_functions.py
bitcoin_functions.pyc
bjorn_edstrom_ripemd160.py
bjorn_edstrom_ripemd160.pyc
convert_dice_rolls_to_hex_bytes_2.py
create_nonstandard_transaction.py
dice_rolls2.txt
dice_rolls.txt
display_hex_bytes.py
ecdsa
ecdsa-0.10
ecdsa-0.10.tar.gz
generate_bitcoin_address_3.py
memory_stick_contents
nonstandard_bitcoin_functions.py
nonstandard_bitcoin_functions.pyc
nonstandard_transaction.py
nonstandard_transaction.pyc
private_key.txt
pypy_sha256.py
pypy_sha256.pyc
random_value.txt
signed_transaction.txt
transaction.py
transaction.pyc
work.log
work_log2.txt




[
Use the Nano editor to edit the controls in display_hex_bytes.py, according to the recipe.
- Delete the existing value for the variable
hex_bytes
. Then use the Nano option "Read File" to paste the contents of the file signed_transaction.txt into the position of the value for this variable (i.e. between the quotation marks). Then press the Backspace key to delete the final newline of the file that was also pasted in.
]

pi@raspberrypi ~/test $ nano display_hex_bytes.py



pi@raspberrypi ~/test $ python display_hex_bytes.py

0100 0000 01cd e235 40f3 033b 59d8 c00f d9d8 703c 80d5 928a 1772 44b1 2fec 8d58 0f34 dbce 070f 0000 008a 4730 4402 2005 fc76 7d51 3f28 5c38 f718 f4c9 cfb0 909d 4ba2 d801 31ae d21b 3f26 aa63 0a79 f002 2044 c9b3 c0fb 4a9d 1a8b 0c26 9915 3991 12ee a5ee 4fd7 e42f c0a4 30a4 7e5e cbb4 5201 4104 3ab6 9279 2d6c 8838 fd30 c2ff 45bf 3cbd 4428 6a5c ac52 ba64 dc06 4528 1020 2b32 06f5 c779 9c3b 72ff 77fd 1976 f105 ced3 cd77 00b0 412e 1126 6f38 88b8 8c30 52c3 ffff ffff 0163 0c03 0000 0000 0017 a914 30d5 40a5 0d46 4852 194a 1955 29eb fa44 af52 1bbb 8700 0000 0001 0000 00




[Recipe complete.]



[End logging on Raspberry Pi.]



Now, on Aineko, create a text file called "tx_copied.txt" in the work directory for this project. Manually type this signed transaction data into tx_copied.txt. Double-check the data.


Time this using a stopwatch.

Time taken: 13:18
Approximately 13 minutes.

Listening to music made this step more tolerable.



Note: Keeping the intermediate results e.g. tx_copied.txt during the project means that if there is an error, I can go back and look for it without having to completely redo each step.


On Aineko, open a terminal and change directory to the work directory.


aineko:work stjohnpiano$ cat tx_copied.txt | tr -d ' \n' > tx.txt


aineko:work stjohnpiano$ echo '' >> tx.txt


aineko:work stjohnpiano$ cat tx.txt

0100000001cde23540f3033b59d8c00fd9d8703c80d5928a177244b12fec8d580f34dbce070f0000008a473044022005fc767d513f285c38f718f4c9cfb0909d4ba2d80131aed21b3f26aa630a79f0022044c9b3c0fb4a9d1a8b0c269915399112eea5ee4fd7e42fc0a430a47e5ecbb4520141043ab692792d6c8838fd30c2ff45bf3cbd44286a5cac52ba64dc06452810202b3206f5c7799c3b72ff77fd1976f105ced3cd7700b0412e11266f3888b88c3052c3ffffffff01630c03000000000017a91430d540a50d464852194a195529ebfa44af521bbb870000000001000000




So, the signed transaction tx1, now transferred to the online computer, is:

0100000001cde23540f3033b59d8c00fd9d8703c80d5928a177244b12fec8d580f34dbce070f0000008a473044022005fc767d513f285c38f718f4c9cfb0909d4ba2d80131aed21b3f26aa630a79f0022044c9b3c0fb4a9d1a8b0c269915399112eea5ee4fd7e42fc0a430a47e5ecbb4520141043ab692792d6c8838fd30c2ff45bf3cbd44286a5cac52ba64dc06452810202b3206f5c7799c3b72ff77fd1976f105ced3cd7700b0412e11266f3888b88c3052c3ffffffff01630c03000000000017a91430d540a50d464852194a195529ebfa44af521bbb870000000001000000






Let's see if a blockchain information service can decode this transaction.


Browse to:
live.blockcypher.com/btc/decodetx

Paste the signed transaction into the text box named "Transaction Hex". Network is set to "Bitcoin".

Click "Decode Transaction".

Result:

{ "addresses": [ "1vkb4YyPMFcxyC83Z5m5zuN45xASoHeNK", "369Dpo9CrJASneaHLdwWfKym7N84XTUyvH" ], "block_height": -1, "block_index": -1, "confirmations": 0, "double_spend": false, "fees": 221, "hash": "add54b899f1aba8b6276e42af86c3c03b0120a864451640b4a8d3fec89a4a72d", "inputs": [ { "addresses": [ "1vkb4YyPMFcxyC83Z5m5zuN45xASoHeNK" ], "age": 550741, "output_index": 15, "output_value": 200000, "prev_hash": "07cedb340f588dec2fb14472178a92d5803c70d8d90fc0d8593b03f34035e2cd", "script": "473044022005fc767d513f285c38f718f4c9cfb0909d4ba2d80131aed21b3f26aa630a79f0022044c9b3c0fb4a9d1a8b0c269915399112eea5ee4fd7e42fc0a430a47e5ecbb4520141043ab692792d6c8838fd30c2ff45bf3cbd44286a5cac52ba64dc06452810202b3206f5c7799c3b72ff77fd1976f105ced3cd7700b0412e11266f3888b88c3052c3", "script_type": "pay-to-pubkey-hash", "sequence": 4294967295 } ], "outputs": [ { "addresses": [ "369Dpo9CrJASneaHLdwWfKym7N84XTUyvH" ], "script": "a91430d540a50d464852194a195529ebfa44af521bbb87", "script_type": "pay-to-script-hash", "value": 199779 } ], "preference": "low", "received": "2018-11-20T17:00:45.941747651Z", "relayed_by": "54.224.143.214", "size": 221, "total": 199779, "ver": 1, "vin_sz": 1, "vout_sz": 1 }




Looks good. No immediate error reported.


Hm. Its size is reported as 221 bytes.

Earlier, I measured the length of the signed tx hex string as 450. At 2 hex characters per byte, that's 225 bytes. Hm.


Let's check that again.

aineko:work stjohnpiano$ python

Python 2.7.13 (default, Dec 18 2016, 05:35:59)
[GCC 4.2.1 (Apple Inc. build 5666) (dot 3)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> x = "0100000001cde23540f3033b59d8c00fd9d8703c80d5928a177244b12fec8d580f34dbce070f0000008a473044022005fc767d513f285c38f718f4c9cfb0909d4ba2d80131aed21b3f26aa630a79f0022044c9b3c0fb4a9d1a8b0c269915399112eea5ee4fd7e42fc0a430a47e5ecbb4520141043ab692792d6c8838fd30c2ff45bf3cbd44286a5cac52ba64dc06452810202b3206f5c7799c3b72ff77fd1976f105ced3cd7700b0412e11266f3888b88c3052c3ffffffff01630c03000000000017a91430d540a50d464852194a195529ebfa44af521bbb870000000001000000"
>>> len(x) / 2.0
>>> 225.0

>>>


225 again.

I wonder if the blockchain information service is reformatting some part of the transaction, in a way that miners currently accept.



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/add54b899f1aba8b6276e42af86c3c03b0120a864451640b4a8d3fec89a4a72d
Details:
- Transaction Successfully Broadcst
- AMOUNT TRANSACTED: 0.00199779 BTC
- FEES: 0.00000221 BTC
- Confirmations: 0/6
- Miner Preference: LOW
- Size: 221 bytes
- Version: 1
- Relayed By: 54.224.143.214




Current datetime: 2018-11-20 17:20





Browse to:
bitcoinfees.earn.com

Hm.

For the fee range 1-2 satoshi / byte, I see that:
- 7292 unconfirmed transactions with a fee in this range have been seen in the memory pool in the last 336 hours.
- 7753 transactions with a fee in this range were mined in the last 24 hours.
-- Note: I think these were mined, although this is not stated explicitly, rather than "seen in the memory pool but never confirmed", because for some fee ranges this number is greater than the number "transactions with a fee in this range seen in the memory pool in the last 336 hours".


336 hours * (1 day / 24 hours) = 336 / 24 = 14 days = 2 weeks.




Shut down for now.

On the Raspberry Pi:

pi@raspberrypi ~/test $ sudo halt

[a variety of output is printed, then the Raspberry Pi shuts down]


Unplug the power cable from the Raspberry Pi.





Start work again.

Next: Retrieve work_log2.txt from Raspberry Pi and copy it into this article at the appropriate earlier point. Merge various annotations / comments made here into the log.



Insert the power cable into the Raspberry Pi. It boots up.


Enter default credentials.


raspberrypi login: pi


Password:


Last login: Sun Mar 27 22:44:59 UTC 2016 on tty1
Linux raspberrypi 4.1.13+ #826 PREEMPT Fri Nov 13 20:13:22 GMT 2015 armv61

The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.

pi@raspberrypi ~ $



The password was "raspberry" but this was not echoed to the screen.


Insert the memory stick into the Raspberry Pi.



pi@raspberrypi ~ $ cd test


[mount the memory stick]
pi@raspberrypi ~/test $ sudo mount -o uid=pi,gid=pi /dev/sda1 /mnt/memory_stick_mount_point


[copy work_log2.txt to the memory stick]
pi@raspberrypi ~/test $ cp work_log2.txt /mnt/memory_stick_mount_point


[confirm that the file has been copied over]
pi@raspberrypi ~/test $ ls -1 /mnt/memory_stick_mount_point

$RECYCLE.BIN
Recycled
System Volume Information
work
work.log
work_log2.txt

[unmount the memory stick]
pi@raspberrypi ~/test $ sudo umount /mnt/memory_stick_mount_point


[confirm that it has been unmounted]
pi@raspberrypi ~/test $ ls -1 /mnt/memory_stick_mount_point



Unplug the memory stick from the Raspberry Pi.


Insert it into Aineko. It mounts automatically and an icon appears on the Desktop. Open the file work_log2.txt and integrate its contents into this article.


On Aineko, right-click memory stick's Desktop icon and choose Eject "NO NAME". Unplug the memory stick from Aineko.




Current datetime:
2018-11-21 13:00

[nearly 20 hours have gone by]


Reload transaction page.
live.blockcypher.com/btc/tx/add54b899f1aba8b6276e42af86c3c03b0120a864451640b4a8d3fec89a4a72d
Details:
- Transaction Successfully Broadcst
- AMOUNT TRANSACTED: 0.00199779 BTC
- FEES: 0.00000221 BTC
- Confirmations: 0/6
- Miner Preference: LOW
- Size: 221 bytes
- Version: 1
- Relayed By: 85.144.83.16:8333






Hm.

Actually, I won't wait for 3 days. Instead, I'll use this as an opportunity to practise creating a new version of a transaction with a higher fee.



The previous article that contains this recipe is:
Creating and signing a standard raw Bitcoin transaction


Excerpt:

RECIPE FOR MANAGING THE FEE AND BROADCAST OF A BITCOIN TRANSACTION



Objectives:
- Fine control of the transaction fee.
- Ability to rebroadcast a new transaction with a higher fee if the previous transaction is not mined within a reasonable time period. This new transaction, if mined, should invalidate the previous transaction.

Note: This recipe is derived from work in this project but has not been tested.

1) Gather the required data for a new transaction (this process is not specified in this recipe). Include at least one "change address" output. Inputs should be added as necessary to achieve the desired output values. The sum of the inputs may be greater than the sum of the desired output values, i.e. some bitcoin may be left over. Send this left-over bitcoin to the change address output. Include an additional input that is specifically for paying the as-yet-unknown transaction fee. Send the bitcoin from this input to the change address output.

2) Construct the transaction, without including signatures (this process is not specified in this recipe).

3) Calculate the byte length of the result of step (2). Let this result be A.

4) Let the estimated byte length of the final transaction be N. Let the approximate byte length of a single input signature be B. Let the number of inputs be C. Calculate N = A + B x C.

5) Using a fee estimation service, look at fee ranges (in satoshis / byte) and the estimated delays for each range. Choose an acceptable delay. Let the corresponding fee (in satoshis / byte) be D. Let the final transaction fee (in satoshis) be E. Calculate E = D x N.

6) Copy the result of step (2). Subtract E from the value in the change address output. The transaction fee is stored implicitly in the transaction as the difference between the sum of the input values and the sum of the output values.

7) Sign the transaction (this process is not specified in this recipe). Insert the input signatures into the transaction.

8) Let the final byte length of the transaction be M. Calculate M by finding the byte length of the result of step (7).

9) Let the final transaction fee (in satoshis / byte) be F. Calculate F = E / M. Confirm that F is within the original desired fee range.

10) Record the time, date, and blockheight. Broadcast the transaction to the Bitcoin network or upload the transaction to a service that can do this for you.

11) A node will store unconfirmed transactions in its memory pools for a particular time period. If the transaction is not mined (confirmed) within this period, the node will delete it from its memory pool. This period will vary depending on the node. Some reading indicates that the default period is 72 hours (three days). After broadcasting the transaction, wait three days + a small delay. If the transaction is mined during this period, stop here. Otherwise, continue to step (12).

12) Using a fee estimation service, look at fee ranges (in satoshis / byte) and the estimated delays for each range. Choose a higher fee range than was used previously.

13) Repeat steps (5)-(12) until the transaction is mined.


Note: If a transaction disappears from the network (i.e. the memory pools of all public nodes), this doesn't mean that it has vanished permanently. Anyone who stored it can rebroadcast it later - it will still be valid. In order to make it invalid, create a new transaction that uses at least one of the same inputs.

Note: An input in a transaction is an as-yet-unspent output of a previous transaction. Each unspent output can only ever be spent once. If a transaction is broadcast that uses at least one input that has already been spent, this transaction is invalid and will not be mined.





Hm. Many of the steps in this recipe are already handled in the existing code.

Rather than increment the fee slowly in order to get the lowest fee that I can, I'll choose a fee rate that's a bit higher than the cheapest 0-block-delay fee rate shown on the fee estimation service.


Browse to:
bitcoinfees.earn.com


This service estimates that a transaction with a fee rate of 59-60 satoshis per byte should be mined with a delay of 0 block (0-40 minutes).

I'll choose a fee rate of 66 satoshis per byte.

I'll use the name "tx1b" for this second version of transaction tx1.



Switch back to the Raspberry Pi. Most of the necessary information for creating the transaction has already been transferred over and entered into the settings for create_nonstandard_transaction.py.


Double-check that my LocalBitcoins receiving address has not changed.
Log in. It's:
36p1w3YrNKd2Q3xaXbe9ASUQkeynjVLfDx

Hm. It's changed.

Ah. The first version of tx1 (let's call it tx1a) is listed in LocalBitcoins / Receive bitcoins / incoming transactions. Therefore, a new address has been generated for receiving bitcoin at this LocalBitcoins account. I had previously thought that the address would change only when a transaction had settled. Evidently the LocalBitcoins receiving address changes when a transaction to that address is seen in their node memory pool(s).

I'll need to use this new receiving address when making tx1b.


Note: Each new signature requires a new random value. Using the same random value twice in two different signatures (that are both broadcast) could compromise the secrecy of the private key. I'll need to generate another 32 bytes of entropy.


I'll begin logging in a new file called "wlog3.txt".


pi@raspberrypi ~/test $ touch wlog3.txt





Eventually, I'll transfer it via memory stick to Aineko.

Logged commands are run in the
~/test
directory on the Raspberry Pi.

While logging, record any annotations or comments here and integrate them into the log when the log has been transferred back from the Raspberry Pi to Aineko (where this article is being written).



[Begin logging on Raspberry Pi.]


[first, generate 32 bytes of entropy to use as the random value for making the transaction signature]


[
I'm following the recipe Recipe for generating entropy bytes using dice
to generate 32 bytes of entropy.
32 * 8 = 256
round_up( 256 / 1.3333 * 1.1 ) = 212 dice rolls
]



pi@raspberrypi ~/test $ ls -1

bitcoin_functions.py
bitcoin_functions.pyc
bjorn_edstrom_ripemd160.py
bjorn_edstrom_ripemd160.pyc
convert_dice_rolls_to_hex_bytes_2.py
create_nonstandard_transaction.py
dice_rolls2.txt
dice_rolls.txt
display_hex_bytes.py
ecdsa
ecdsa-0.10
ecdsa-0.10.tar.gz
generate_bitcoin_address_3.py
memory_stick_contents
nonstandard_bitcoin_functions.py
nonstandard_bitcoin_functions.pyc
nonstandard_transaction.py
nonstandard_transaction.pyc
private_key.txt
pypy_sha256.py
pypy_sha256.pyc
random_value.txt
signed_transaction.txt
transaction.py
transaction.pyc
wlog3.txt
work.log
work_log2.txt



pi@raspberrypi ~/test $ nano dice_rolls3.txt

[
Perform 212 dice rolls, using Nano to record the results in dice_rolls3.txt.

Time this using a stopwatch.

Time taken: 6:33
Approximately 7 minutes.
]



[Use the Nano editor to edit the controls in convert_dice_rolls_to_hex_bytes_2.py, according to the recipe.]
pi@raspberrypi ~/test $ nano convert_dice_rolls_to_hex_bytes_2.py



pi@raspberrypi ~/test $ python convert_dice_rolls_to_hex_bytes_2.py


### START CONVERSION OF DICE ROLLS TO HEX BYTES

- number of dice rolls: 212
- number of dice rolls in the list [1234]: 132
- number of hex characters after conversion: 66
- number of hex bytes: 33
- desired number of hex bytes: 32
- the hex bytes produced are sufficient.
- hex byte output:
644dc86dd0cb4518d9d7f68db2d6e9455e34ceeb32c897df2616418c4c9bb04006
- hex byte output shortened to the desired length (32 bytes):
644dc86dd0cb4518d9d7f68db2d6e9455e34ceeb32c897df2616418c4c9bb040
- remaining hex bytes:
06

Result: Desired amount of entropy (32 bytes) has been produced.
Entropy (32 bytes):
644dc86dd0cb4518d9d7f68db2d6e9455e34ceeb32c897df2616418c4c9bb040
Recommendation: Perhaps preserve the 1 extra hex bytes in an entropy storage file.
Extra hex bytes: 06

### END CONVERSION OF DICE ROLLS TO HEX BYTES




[Recipe complete.]



[Let's extract the entropy from the log into its own file.]




[copy last 15 lines of wlog3.txt to a new file]
pi@raspberrypi ~/test $ tail -15 wlog3.txt > random_value2.txt



[Use Nano to remove the text around the 32 entropy hex bytes contained in the output. I will later use these 32 bytes as the random value for signing the transaction tx1b.]
pi@raspberrypi ~/test $ nano random_value2.txt



[get string length of random_value2.txt hex bytes - should be 32*2 = 64. Use
tr
to remove the newline character at the end of the file.]
pi@raspberrypi ~/test $ cat random_value2.txt | tr -d '\n' | wc -c

64



pi@raspberrypi ~/test $ ls -1

bitcoin_functions.py
bitcoin_functions.pyc
bjorn_edstrom_ripemd160.py
bjorn_edstrom_ripemd160.pyc
convert_dice_rolls_to_hex_bytes_2.py
create_nonstandard_transaction.py
dice_rolls2.txt
dice_rolls3.txt
dice_rolls.txt
display_hex_bytes.py
ecdsa
ecdsa-0.10
ecdsa-0.10.tar.gz
generate_bitcoin_address_3.py
memory_stick_contents
nonstandard_bitcoin_functions.py
nonstandard_bitcoin_functions.pyc
nonstandard_transaction.py
nonstandard_transaction.pyc
private_key.txt
pypy_sha256.py
pypy_sha256.pyc
random_value2.txt
random_value.txt
signed_transaction.txt
transaction.py
transaction.pyc
wlog3.txt
work.log
work_log2.txt



[Now, proceed with the recipe in Recipe for creating and signing a nonstandard Bitcoin transaction ]



[I'll use the existing directory "test" as the work directory.]


[ecdsa-0.10.tar.gz is already unpacked.]


[
Use the Nano editor to edit the controls in create_nonstandard_transaction.py, according to the recipe. Manually enter the gathered / chosen values (reading them from this article displayed on Aineko's screen), except for the variables
random_value
and
input_data["private_key_hex"]
.
- Most variable values are already entered from when I made tx1a. Exceptions: The output address and the change address (change both of these to:
36p1w3YrNKd2Q3xaXbe9ASUQkeynjVLfDx )
- Note: With long strings, e.g. the output address, you can make a copy on the online computer (Aineko, in this case) and split it into groups of 4 characters, then manually copy each group over to the offline Raspberry Pi, then do a double-check of the group values, and finally delete the spaces again on the offline Raspberry Pi to form the original address.
- Delete the existing value for the variable
random_value
. Then use the Nano option "Read File" to paste the contents of the file random_value2.txt into the position of the value for this variable (i.e. between the quotation marks). Then press the Backspace key to delete the final newline of the file that was also pasted in.
- Change the fee_rate to 66 (satoshi / byte).
]

pi@raspberrypi ~/test $ nano create_nonstandard_transaction.py



[Note: In create_nonstandard_transaction.py, all control values are strings (i.e. are contained within quotation marks).]



[Let's record a copy of the settings. They are on lines 41-65. I'll copy an excerpt (lines 40-66) to the log.]


pi@raspberrypi ~/test $ cat create_nonstandard_transaction.py | sed -n '40,66p'

##### START CONTROLS random_value = "644dc86dd0cb4518d9d7f68db2d6e9455e34ceeb32c897df2616418c4c9bb040" # 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": "07cedb340f588dec2fb14472178a92d5803c70d8d90fc0d8593b03f34035e2cd", "previous_output_index": "15", "private_key_hex": "c592e1dad5e9871fdeffb551b4544b0a1cf0378c6371d7a397ff5faf04c934ca", #"satoshi_amount": "241777", "bitcoin_amount": "0.0020", "input_type": "p2pkh", } output_data = { "address": "36p1w3YrNKd2Q3xaXbe9ASUQkeynjVLfDx", #"satoshi_amount": "241000", "bitcoin_amount": "0.0020", "output_type": "p2sh", } change_address = "36p1w3YrNKd2Q3xaXbe9ASUQkeynjVLfDx" # note: the fee will be subtracted from the amount that is being sent to the change address. fee = "225" # satoshi fee_rate = "66" # satoshi / byte # fee_type options: ["fee", "fee_rate"] fee_type = "fee_rate" ##### END CONTROLS




pi@raspberrypi ~/test $ python create_nonstandard_transaction.py


### START CREATION OF NONSTANDARD BITCOIN TRANSACTION

- Fee type: fee_rate
- Fee rate: 66.0 (satoshi / byte)
- Number of inputs (i.e. as-yet-unspent outputs): 1
- Number of outputs: 1
- Change address: 36p1w3YrNKd2Q3xaXbe9ASUQkeynjVLfDx
- Amount to be sent to the change address: 0.0020
- Input addresses, with total-value-to-be-sent:
-- 1vkb4YyPMFcxyC83Z5m5zuN45xASoHeNK: 0.00200000
- Output addresses, with total-value-to-be-received:
-- 36p1w3YrNKd2Q3xaXbe9ASUQkeynjVLfDx: 0.00200000
- Total value of all inputs: 0.00200000
- Total value of all outputs: 0.00200000
- Total value of all inputs exactly matches total value of all outputs.
- Estimated transaction size: 221 bytes
- Fee rate: 66.0 (satoshi / byte)
- Calculate 221 * 66.0 and round up to nearest satoshi.
- Final fee: 14586 (satoshi)
- Final fee rate (using estimated transaction size): 66.0000 (satoshi per byte)
- Fee subtracted from amount to be sent to change address.
- New amount to be sent to change address: 185414 (satoshi)

Input 0:
Input (without signature):
- previous_output_hash: cde23540f3033b59d8c00fd9d8703c80d5928a177244b12fec8d580f34dbce07
- previous_output_index: 0f000000
- sequence: ffffffff
- private_key_hex: c592e1dad5e9871fdeffb551b4544b0a1cf0378c6371d7a397ff5faf04c934ca
- public_key_hex: 043ab692792d6c8838fd30c2ff45bf3cbd44286a5cac52ba64dc06452810202b3206f5c7799c3b72ff77fd1976f105ced3cd7700b0412e11266f3888b88c3052c3
- script_length_scriptPubKey: 19
- scriptPubKey: 76a9140a2a6e4834efa5c7c31eed1ebeadf94a370a1e9388ac
- script_length: None
- scriptSig: None
- address: 1vkb4YyPMFcxyC83Z5m5zuN45xASoHeNK
- previous_output_index_int: 15
- txid: 07cedb340f588dec2fb14472178a92d5803c70d8d90fc0d8593b03f34035e2cd

Output 0:
Output:
- value: 46d4020000000000
- script_length: 17
- script: a914382b8c40b25f104e9d0277ed91ddf3c849aa340387
- address: 36p1w3YrNKd2Q3xaXbe9ASUQkeynjVLfDx
- bitcoin_amount: 0.00185414
- satoshi_amount: 185414
- redeem_script_hash_hex: 382b8c40b25f104e9d0277ed91ddf3c849aa3403

Nonstandard Transaction (unsigned form):
- version: 01000000
- input_count: 01
- Input:
-- previous_output_hash: cde23540f3033b59d8c00fd9d8703c80d5928a177244b12fec8d580f34dbce07
-- previous_output_index: 0f000000
-- script_length: None
-- scriptSig: None
-- sequence: ffffffff
- output_count: 01
- Output [P2SH]:
-- value: 46d4020000000000
-- script_length: 17
-- script: a914382b8c40b25f104e9d0277ed91ddf3c849aa340387
- block_lock_time: 00000000

Nonstandard Transaction (signable form):
- version: 01000000
- input_count: 01
- Input [to be used to sign this signable form]:
-- previous_output_hash: cde23540f3033b59d8c00fd9d8703c80d5928a177244b12fec8d580f34dbce07
-- previous_output_index: 0f000000
-- script_length_scriptPubKey: 19
-- scriptPubKey: 76a9140a2a6e4834efa5c7c31eed1ebeadf94a370a1e9388ac
-- sequence: ffffffff
- output_count: 01
- Output [P2SH]:
-- value: 46d4020000000000
-- script_length: 17
-- script: a914382b8c40b25f104e9d0277ed91ddf3c849aa340387
- block_lock_time: 00000000
- hash_type_4_byte: 01000000

Nonstandard Transaction (signed form):
- version: 01000000
- input_count: 01
- Input:
-- previous_output_hash: cde23540f3033b59d8c00fd9d8703c80d5928a177244b12fec8d580f34dbce07
-- previous_output_index: 0f000000
-- script_length: 8b
-- scriptSig: 483045022100af984f21f3096c47b9684d9cccf76988597accbdb55ff0b66992ef4b30061608022063ae31b6465deb451d3f535145e200bf09e4d51d0c640b90d4d9e25b9c97b2c20141043ab692792d6c8838fd30c2ff45bf3cbd44286a5cac52ba64dc06452810202b3206f5c7799c3b72ff77fd1976f105ced3cd7700b0412e11266f3888b88c3052c3
-- sequence: ffffffff
- output_count: 01
- Output [P2SH]:
-- value: 46d4020000000000
-- script_length: 17
-- script: a914382b8c40b25f104e9d0277ed91ddf3c849aa340387
- block_lock_time: 00000000
- hash_type_4_byte: 01000000

Signed transaction:
0100000001cde23540f3033b59d8c00fd9d8703c80d5928a177244b12fec8d580f34dbce070f0000008b483045022100af984f21f3096c47b9684d9cccf76988597accbdb55ff0b66992ef4b30061608022063ae31b6465deb451d3f535145e200bf09e4d51d0c640b90d4d9e25b9c97b2c20141043ab692792d6c8838fd30c2ff45bf3cbd44286a5cac52ba64dc06452810202b3206f5c7799c3b72ff77fd1976f105ced3cd7700b0412e11266f3888b88c3052c3ffffffff0146d402000000000017a914382b8c40b25f104e9d0277ed91ddf3c849aa3403870000000001000000

### END CREATION OF BITCOIN TRANSACTION




[The python create_nonstandard_transaction.py command took a few seconds to run.]


[Recipe complete.]



[Let's extract the signed transaction from the log into its own file.]



[copy last 15 lines of wlog3.txt to a new file]
pi@raspberrypi ~/test $ tail -15 wlog3.txt > signed_transaction2.txt



[Use Nano to remove the text around the signed transaction hex string contained in the output.]
pi@raspberrypi ~/test $ nano signed_transaction2.txt



pi@raspberrypi ~/test $ cat signed_transaction2.txt

0100000001cde23540f3033b59d8c00fd9d8703c80d5928a177244b12fec8d580f34dbce070f0000008b483045022100af984f21f3096c47b9684d9cccf76988597accbdb55ff0b66992ef4b30061608022063ae31b6465deb451d3f535145e200bf09e4d51d0c640b90d4d9e25b9c97b2c20141043ab692792d6c8838fd30c2ff45bf3cbd44286a5cac52ba64dc06452810202b3206f5c7799c3b72ff77fd1976f105ced3cd7700b0412e11266f3888b88c3052c3ffffffff0146d402000000000017a914382b8c40b25f104e9d0277ed91ddf3c849aa3403870000000001000000



[get string length of signed_transaction2.txt hex bytes. Use
tr
to remove the newline character at the end of the file.]
pi@raspberrypi ~/test $ cat signed_transaction2.txt | tr -d '\n' | wc -c

452


[452 / 2 = 226 bytes.]


[Interesting.]



[Finally, follow the recipe in the article Displaying hex bytes for manual copying to make the signed transaction easier to read and manually copy from the offline Raspberry Pi to the online Aineko.]



pi@raspberrypi ~/test $ ls -1

bitcoin_functions.py
bitcoin_functions.pyc
bjorn_edstrom_ripemd160.py
bjorn_edstrom_ripemd160.pyc
convert_dice_rolls_to_hex_bytes_2.py
create_nonstandard_transaction.py
dice_rolls2.txt
dice_rolls3.txt
dice_rolls.txt
display_hex_bytes.py
ecdsa
ecdsa-0.10
ecdsa-0.10.tar.gz
generate_bitcoin_address_3.py
memory_stick_contents
nonstandard_bitcoin_functions.py
nonstandard_bitcoin_functions.pyc
nonstandard_transaction.py
nonstandard_transaction.pyc
private_key.txt
pypy_sha256.py
pypy_sha256.pyc
random_value2.txt
random_value.txt
signed_transaction2.txt
signed_transaction.txt
transaction.py
transaction.pyc
wlog3.txt
work.log
work_log2.txt



[
Use the Nano editor to edit the controls in display_hex_bytes.py, according to the recipe.
- Delete the existing value for the variable
hex_bytes
. Then use the Nano option "Read File" to paste the contents of the file signed_transaction2.txt into the position of the value for this variable (i.e. between the quotation marks). Then press the Backspace key to delete the final newline of the file that was also pasted in.
]

pi@raspberrypi ~/test $ nano display_hex_bytes.py



pi@raspberrypi ~/test $ python display_hex_bytes.py

0100 0000 01cd e235 40f3 033b 59d8 c00f d9d8 703c 80d5 928a 1772 44b1 2fec 8d58 0f34 dbce 070f 0000 008b 4830 4502 2100 af98 4f21 f309 6c47 b968 4d9c ccf7 6988 597a ccbd b55f f0b6 6992 ef4b 3006 1608 0220 63ae 31b6 465d eb45 1d3f 5351 45e2 00bf 09e4 d51d 0c64 0b90 d4d9 e25b 9c97 b2c2 0141 043a b692 792d 6c88 38fd 30c2 ff45 bf3c bd44 286a 5cac 52ba 64dc 0645 2810 202b 3206 f5c7 799c 3b72 ff77 fd19 76f1 05ce d3cd 7700 b041 2e11 266f 3888 b88c 3052 c3ff ffff ff01 46d4 0200 0000 0000 17a9 1438 2b8c 40b2 5f10 4e9d 0277 ed91 ddf3 c849 aa34 0387 0000 0000 0100 0000




[Recipe complete.]



[End logging on Raspberry Pi.]




Now, on Aineko, create a text file called "tx1b_copied.txt" in the work directory for this project. Manually type this signed transaction data into tx1b_copied.txt. Double-check the data.


Time this using a stopwatch.

Time taken: 12:37
Approximately 13 minutes.

Listening to music made this step more tolerable.



Note: Keeping the intermediate results e.g. tx1b_copied.txt during the project means that if there is an error, I can go back, find it, and fix it without having to completely redo each step.




On Aineko, open a terminal and change directory to the work directory.


aineko:work stjohnpiano$ cat tx1b_copied.txt | tr -d ' \n' > tx1b.txt


aineko:work stjohnpiano$ echo '' >> tx1b.txt


aineko:work stjohnpiano$ cat tx1b.txt

0100000001cde23540f3033b59d8c00fd9d8703c80d5928a177244b12fec8d580f34dbce070f0000008b483045022100af984f21f3096c47b9684d9cccf76988597accbdb55ff0b66992ef4b30061608022063ae31b6465deb451d3f535145e200bf09e4d51d0c640b90d4d9e25b9c97b2c20141043ab692792d6c8838fd30c2ff45bf3cbd44286a5cac52ba64dc06452810202b3206f5c7799c3b72ff77fd1976f105ced3cd7700b0412e11266f3888b88c3052c3ffffffff0146d402000000000017a914382b8c40b25f104e9d0277ed91ddf3c849aa3403870000000001000000



[Recipe complete.]



So, the signed transaction tx1b, now transferred to the online computer, is:

0100000001cde23540f3033b59d8c00fd9d8703c80d5928a177244b12fec8d580f34dbce070f0000008b483045022100af984f21f3096c47b9684d9cccf76988597accbdb55ff0b66992ef4b30061608022063ae31b6465deb451d3f535145e200bf09e4d51d0c640b90d4d9e25b9c97b2c20141043ab692792d6c8838fd30c2ff45bf3cbd44286a5cac52ba64dc06452810202b3206f5c7799c3b72ff77fd1976f105ced3cd7700b0412e11266f3888b88c3052c3ffffffff0146d402000000000017a914382b8c40b25f104e9d0277ed91ddf3c849aa3403870000000001000000






Let's see if a blockchain information service can decode this transaction.


Browse to:
live.blockcypher.com/btc/decodetx

Paste the signed transaction into the text box named "Transaction Hex". Network is set to "Bitcoin".

Click "Decode Transaction".

Result:

{ "addresses": [ "1vkb4YyPMFcxyC83Z5m5zuN45xASoHeNK", "36p1w3YrNKd2Q3xaXbe9ASUQkeynjVLfDx" ], "block_height": -1, "block_index": -1, "confirmations": 0, "double_spend": false, "fees": 14586, "hash": "3677f15c9a6e62a02df0a571370ceb0de9fa90efd56441e3dcb7fe9eff188d16", "inputs": [ { "addresses": [ "1vkb4YyPMFcxyC83Z5m5zuN45xASoHeNK" ], "age": 550741, "output_index": 15, "output_value": 200000, "prev_hash": "07cedb340f588dec2fb14472178a92d5803c70d8d90fc0d8593b03f34035e2cd", "script": "483045022100af984f21f3096c47b9684d9cccf76988597accbdb55ff0b66992ef4b30061608022063ae31b6465deb451d3f535145e200bf09e4d51d0c640b90d4d9e25b9c97b2c20141043ab692792d6c8838fd30c2ff45bf3cbd44286a5cac52ba64dc06452810202b3206f5c7799c3b72ff77fd1976f105ced3cd7700b0412e11266f3888b88c3052c3", "script_type": "pay-to-pubkey-hash", "sequence": 4294967295 } ], "outputs": [ { "addresses": [ "36p1w3YrNKd2Q3xaXbe9ASUQkeynjVLfDx" ], "script": "a914382b8c40b25f104e9d0277ed91ddf3c849aa340387", "script_type": "pay-to-script-hash", "value": 185414 } ], "preference": "high", "received": "2018-11-21T16:04:32.919394406Z", "relayed_by": "54.226.63.120", "size": 222, "total": 185414, "ver": 1, "vin_sz": 1, "vout_sz": 1 }




Looks good. No immediate error reported.


Hm. Its size is reported as 222 bytes.

Some details:
- fee: 14586 satoshi
- preference: high
- hash (txid):
3677f15c9a6e62a02df0a571370ceb0de9fa90efd56441e3dcb7fe9eff188d16



Let's check the byte length of tx1b using Python.

aineko:work stjohnpiano$ python

Python 2.7.13 (default, Dec 18 2016, 05:35:59)
[GCC 4.2.1 (Apple Inc. build 5666) (dot 3)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> x = "0100000001cde23540f3033b59d8c00fd9d8703c80d5928a177244b12fec8d580f34dbce070f0000008b483045022100af984f21f3096c47b9684d9cccf76988597accbdb55ff0b66992ef4b30061608022063ae31b6465deb451d3f535145e200bf09e4d51d0c640b90d4d9e25b9c97b2c20141043ab692792d6c8838fd30c2ff45bf3cbd44286a5cac52ba64dc06452810202b3206f5c7799c3b72ff77fd1976f105ced3cd7700b0412e11266f3888b88c3052c3ffffffff0146d402000000000017a914382b8c40b25f104e9d0277ed91ddf3c849aa3403870000000001000000"
>>> len(x) / 2.0
>>> 226.0

>>>



Hm. 226 bytes.




Anyway, let's press on and broadcast the signed transaction tx1b.




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:
- "Server Error (500)"


Hm.


Let's look up the txid.


Browse to:
live.blockcypher.com/btc/tx/3677f15c9a6e62a02df0a571370ceb0de9fa90efd56441e3dcb7fe9eff188d16

Result:
"No transaction found with the hash
3677f15c9a6e62a02df0a571370ceb0de9fa90efd56441e3dcb7fe9eff188d16"



Hm.



I'll try another broadcast service.


Browse to:
www.blockchain.com/btc/pushtx

Paste the signed transaction into the text box.

Click "Submit Transaction".


Result:
"Validation Error: BitcoindException(super=com.neemre.btcdcli4j.core.BitcoindException: Error #-26: 18: txn-mempool-conflict, code=-26)"




Ah. Some searching and reading indicates that in order for the second version of the transaction to be mined, the first version must first remain unconfirmed for some time (3 days?) and then be removed from the memory pool.
- Note: My attempting to broadcast tx1b (which spends the same output to a different receiving address) looks exactly like an attempted double-spend.
-- Ah. Should have realised this earlier before I simply changed the output address. I was just thinking about fees, but in retrospect, this is obvious. Bitcoin was designed specifically to reject this second transaction, because it could have been a double-spend attack on a merchant.



Hm. I should try to follow the replace-by-fee approach more exactly (which means: change only the fee, not any of the output addresses).



I can make a new transaction (tx1c) which sends the bitcoin to the first LocalBitcoins receiving address again, but this time with a high fee.

Will LocalBitcoins still credit my account with this bitcoin amount i.e. will it treat this previous receiving address as still belonging to my account (and only my account)?





Log in to LocalBitcoins.

In Wallet / Receive bitcoins / Old addresses, I find:

"To protect your privacy, we provide a new bitcoin address for each transfer. This prevents someone from tracking all the payments you receive by looking at the blockchain.

Note that addresses are valid only for 12 months."

along with a list of old addresses (although only the first 10 characters of each address are shown).



Ok. I can re-use the LocalBitcoins receiving address that I used originally in tx1.



I'll create a new version of the transaction, tx1c, where everything is the same as tx1 except for the fee and the random_value.



Let's try again.


Switch back to the Raspberry Pi.



Original LocalBitcoins receiving address, used in tx1:
369Dpo9CrJASneaHLdwWfKym7N84XTUyvH


Note: Each new signature requires a new random value. Using the same random value twice in two different signatures (that are both broadcast) could compromise the secrecy of the private key. I'll need to generate another 32 bytes of entropy.



I'll begin logging in a new file called "w4.txt".


pi@raspberrypi ~/test $ touch w4.txt




Eventually, I'll transfer w4.txt to Aineko via memory stick.

Logged commands are run in the
~/test
directory on the Raspberry Pi.

While logging, record any annotations or comments here and integrate them into the log when the log has been transferred back from the Raspberry Pi to Aineko (where this article is being written).




[Begin logging on Raspberry Pi.]


[first, generate 32 bytes of entropy to use as the random value for making the transaction signature]



[
I'm following the recipe Recipe for generating entropy bytes using dice
to generate 32 bytes of entropy.
32 * 8 = 256
round_up( 256 / 1.3333 * 1.1 ) = 212 dice rolls
]




pi@raspberrypi ~/test $ nano dice_rolls4.txt

[
Perform 212 dice rolls, using Nano to record the results in dice_rolls4.txt.

Time this using a stopwatch.

Time taken: 5:53
Approximately 6 minutes.
]



[Use the Nano editor to edit the controls in convert_dice_rolls_to_hex_bytes_2.py, according to the recipe.]
pi@raspberrypi ~/test $ nano convert_dice_rolls_to_hex_bytes_2.py



pi@raspberrypi ~/test $ python convert_dice_rolls_to_hex_bytes_2.py


### START CONVERSION OF DICE ROLLS TO HEX BYTES

- number of dice rolls: 212
- number of dice rolls in the list [1234]: 132
- number of hex characters after conversion: 66
- number of hex bytes: 33
- desired number of hex bytes: 32
- the hex bytes produced are sufficient.
- hex byte output:
644dc86dd0cb4518d9d7f68db2d6e9455e34ceeb32c897df2616418c4c9bb04006
- hex byte output shortened to the desired length (32 bytes):
644dc86dd0cb4518d9d7f68db2d6e9455e34ceeb32c897df2616418c4c9bb040
- remaining hex bytes:
06

Result: Desired amount of entropy (32 bytes) has been produced.
Entropy (32 bytes):
644dc86dd0cb4518d9d7f68db2d6e9455e34ceeb32c897df2616418c4c9bb040
Recommendation: Perhaps preserve the 1 extra hex bytes in an entropy storage file.
Extra hex bytes: 06

### END CONVERSION OF DICE ROLLS TO HEX BYTES



[Recipe complete.]



[copy last 15 lines of w4.txt to a new file]
pi@raspberrypi ~/test $ tail -15 w4.txt > random_value3.txt



[Use Nano to remove the text around the 32 entropy hex bytes contained in the output. I will later use these 32 bytes as the random value for signing the transaction tx1c.]
pi@raspberrypi ~/test $ nano random_value3.txt



pi@raspberrypi ~/test $ cat random_value3.txt

644dc86dd0cb4518d9d7f68db2d6e9455e34ceeb32c897df2616418c4c9bb040



[get string length of random_value3.txt hex bytes - should be 32*2 = 64. Use
tr
to remove the newline character at the end of the file.]
pi@raspberrypi ~/test $ cat random_value3.txt | tr -d '\n' | wc -c

64



pi@raspberrypi ~/test $ ls -1

bitcoin_functions.py
bitcoin_functions.pyc
bjorn_edstrom_ripemd160.py
bjorn_edstrom_ripemd160.pyc
convert_dice_rolls_to_hex_bytes_2.py
create_nonstandard_transaction.py
dice_rolls2.txt
dice_rolls3.txt
dice_rolls4.txt
dice_rolls.txt
display_hex_bytes.py
ecdsa
ecdsa-0.10
ecdsa-0.10.tar.gz
generate_bitcoin_address_3.py
memory_stick_contents
nonstandard_bitcoin_functions.py
nonstandard_bitcoin_functions.pyc
nonstandard_transaction.py
nonstandard_transaction.pyc
private_key.txt
pypy_sha256.py
pypy_sha256.pyc
random_value2.txt
random_value3.txt
random_value.txt
signed_transaction2.txt
signed_transaction.txt
transaction.py
transaction.pyc
w4.txt
wlog3.txt
work.log
work_log2.txt



[Now, proceed with the recipe in Recipe for creating and signing a nonstandard Bitcoin transaction ]



[I'll use the existing directory "test" as the work directory.]


[ecdsa-0.10.tar.gz is already unpacked.]


[
Use the Nano editor to edit the controls in create_nonstandard_transaction.py, according to the recipe. Manually enter the gathered / chosen values, except for the variable
random_value
.
- Most variable values are already entered from when I made tx1b. Exceptions: The output address and the change address (change both of these to the original LocalBitcoins receiving address: 369Dpo9CrJASneaHLdwWfKym7N84XTUyvH )
- Note: With long strings, e.g. the output address, you can make a copy on the online computer (Aineko, in this case) and split it into groups of 4 characters, then manually copy each group over to the offline Raspberry Pi, then do a double-check of the group values, and finally delete the spaces again on the offline Raspberry Pi to form the original address.
- Delete the existing value for the variable
random_value
. Then use the Nano option "Read File" to paste the contents of the file random_value3.txt into the position of the value for this variable (i.e. between the quotation marks). Then press the Backspace key to delete the final newline of the file that was also pasted in.
- Confirm that the fee_rate is set to 66 (satoshi / byte).
]

pi@raspberrypi ~/test $ nano create_nonstandard_transaction.py



[Note: In create_nonstandard_transaction.py, all control values are strings (i.e. are contained within quotation marks).]



[Let's record a copy of the settings. They are on lines 41-65. I'll copy an excerpt (lines 40-66) to the log.]


pi@raspberrypi ~/test $ cat create_nonstandard_transaction.py | sed -n '40,66p'

##### START CONTROLS random_value = "644dc86dd0cb4518d9d7f68db2d6e9455e34ceeb32c897df2616418c4c9bb040" # 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": "07cedb340f588dec2fb14472178a92d5803c70d8d90fc0d8593b03f34035e2cd", "previous_output_index": "15", "private_key_hex": "c592e1dad5e9871fdeffb551b4544b0a1cf0378c6371d7a397ff5faf04c934ca", #"satoshi_amount": "241777", "bitcoin_amount": "0.0020", "input_type": "p2pkh", } output_data = { "address": "369Dpo9CrJASneaHLdwWfKym7N84XTUyvH", #"satoshi_amount": "241000", "bitcoin_amount": "0.0020", "output_type": "p2sh", } change_address = "369Dpo9CrJASneaHLdwWfKym7N84XTUyvH" # note: the fee will be subtracted from the amount that is being sent to the change address. fee = "225" # satoshi fee_rate = "66" # satoshi / byte # fee_type options: ["fee", "fee_rate"] fee_type = "fee_rate" ##### END CONTROLS




pi@raspberrypi ~/test $ python create_nonstandard_transaction.py


### START CREATION OF NONSTANDARD BITCOIN TRANSACTION

- Fee type: fee_rate
- Fee rate: 66.0 (satoshi / byte)
- Number of inputs (i.e. as-yet-unspent outputs): 1
- Number of outputs: 1
- Change address: 369Dpo9CrJASneaHLdwWfKym7N84XTUyvH
- Amount to be sent to the change address: 0.0020
- Input addresses, with total-value-to-be-sent:
-- 1vkb4YyPMFcxyC83Z5m5zuN45xASoHeNK: 0.00200000
- Output addresses, with total-value-to-be-received:
-- 369Dpo9CrJASneaHLdwWfKym7N84XTUyvH: 0.00200000
- Total value of all inputs: 0.00200000
- Total value of all outputs: 0.00200000
- Total value of all inputs exactly matches total value of all outputs.
- Estimated transaction size: 221 bytes
- Fee rate: 66.0 (satoshi / byte)
- Calculate 221 * 66.0 and round up to nearest satoshi.
- Final fee: 14586 (satoshi)
- Final fee rate (using estimated transaction size): 66.0000 (satoshi per byte)
- Fee subtracted from amount to be sent to change address.
- New amount to be sent to change address: 185414 (satoshi)

Input 0:
Input (without signature):
- previous_output_hash: cde23540f3033b59d8c00fd9d8703c80d5928a177244b12fec8d580f34dbce07
- previous_output_index: 0f000000
- sequence: ffffffff
- private_key_hex: c592e1dad5e9871fdeffb551b4544b0a1cf0378c6371d7a397ff5faf04c934ca
- public_key_hex: 043ab692792d6c8838fd30c2ff45bf3cbd44286a5cac52ba64dc06452810202b3206f5c7799c3b72ff77fd1976f105ced3cd7700b0412e11266f3888b88c3052c3
- script_length_scriptPubKey: 19
- scriptPubKey: 76a9140a2a6e4834efa5c7c31eed1ebeadf94a370a1e9388ac
- script_length: None
- scriptSig: None
- address: 1vkb4YyPMFcxyC83Z5m5zuN45xASoHeNK
- previous_output_index_int: 15
- txid: 07cedb340f588dec2fb14472178a92d5803c70d8d90fc0d8593b03f34035e2cd

Output 0:
Output:
- value: 46d4020000000000
- script_length: 17
- script: a91430d540a50d464852194a195529ebfa44af521bbb87
- address: 369Dpo9CrJASneaHLdwWfKym7N84XTUyvH
- bitcoin_amount: 0.00185414
- satoshi_amount: 185414
- redeem_script_hash_hex: 30d540a50d464852194a195529ebfa44af521bbb

Nonstandard Transaction (unsigned form):
- version: 01000000
- input_count: 01
- Input:
-- previous_output_hash: cde23540f3033b59d8c00fd9d8703c80d5928a177244b12fec8d580f34dbce07
-- previous_output_index: 0f000000
-- script_length: None
-- scriptSig: None
-- sequence: ffffffff
- output_count: 01
- Output [P2SH]:
-- value: 46d4020000000000
-- script_length: 17
-- script: a91430d540a50d464852194a195529ebfa44af521bbb87
- block_lock_time: 00000000

Nonstandard Transaction (signable form):
- version: 01000000
- input_count: 01
- Input [to be used to sign this signable form]:
-- previous_output_hash: cde23540f3033b59d8c00fd9d8703c80d5928a177244b12fec8d580f34dbce07
-- previous_output_index: 0f000000
-- script_length_scriptPubKey: 19
-- scriptPubKey: 76a9140a2a6e4834efa5c7c31eed1ebeadf94a370a1e9388ac
-- sequence: ffffffff
- output_count: 01
- Output [P2SH]:
-- value: 46d4020000000000
-- script_length: 17
-- script: a91430d540a50d464852194a195529ebfa44af521bbb87
- block_lock_time: 00000000
- hash_type_4_byte: 01000000

Nonstandard Transaction (signed form):
- version: 01000000
- input_count: 01
- Input:
-- previous_output_hash: cde23540f3033b59d8c00fd9d8703c80d5928a177244b12fec8d580f34dbce07
-- previous_output_index: 0f000000
-- script_length: 8b
-- scriptSig: 483045022100af984f21f3096c47b9684d9cccf76988597accbdb55ff0b66992ef4b3006160802205f6bad0dce3fc5c01ac3128f643302d55b952edf656be25ee996049d74a0e41c0141043ab692792d6c8838fd30c2ff45bf3cbd44286a5cac52ba64dc06452810202b3206f5c7799c3b72ff77fd1976f105ced3cd7700b0412e11266f3888b88c3052c3
-- sequence: ffffffff
- output_count: 01
- Output [P2SH]:
-- value: 46d4020000000000
-- script_length: 17
-- script: a91430d540a50d464852194a195529ebfa44af521bbb87
- block_lock_time: 00000000
- hash_type_4_byte: 01000000

Signed transaction:
0100000001cde23540f3033b59d8c00fd9d8703c80d5928a177244b12fec8d580f34dbce070f0000008b483045022100af984f21f3096c47b9684d9cccf76988597accbdb55ff0b66992ef4b3006160802205f6bad0dce3fc5c01ac3128f643302d55b952edf656be25ee996049d74a0e41c0141043ab692792d6c8838fd30c2ff45bf3cbd44286a5cac52ba64dc06452810202b3206f5c7799c3b72ff77fd1976f105ced3cd7700b0412e11266f3888b88c3052c3ffffffff0146d402000000000017a91430d540a50d464852194a195529ebfa44af521bbb870000000001000000

### END CREATION OF BITCOIN TRANSACTION



[The python create_nonstandard_transaction.py command took a few seconds to run.]


[Recipe complete.]



[Let's extract the signed transaction from the log into its own file.]



[copy last 15 lines of w4.txt to a new file]
pi@raspberrypi ~/test $ tail -15 w4.txt > signed_transaction3.txt



[Use Nano to remove the text around the signed transaction hex string contained in the output.]
pi@raspberrypi ~/test $ nano signed_transaction3.txt



pi@raspberrypi ~/test $ cat signed_transaction3.txt

0100000001cde23540f3033b59d8c00fd9d8703c80d5928a177244b12fec8d580f34dbce070f0000008b483045022100af984f21f3096c47b9684d9cccf76988597accbdb55ff0b66992ef4b3006160802205f6bad0dce3fc5c01ac3128f643302d55b952edf656be25ee996049d74a0e41c0141043ab692792d6c8838fd30c2ff45bf3cbd44286a5cac52ba64dc06452810202b3206f5c7799c3b72ff77fd1976f105ced3cd7700b0412e11266f3888b88c3052c3ffffffff0146d402000000000017a91430d540a50d464852194a195529ebfa44af521bbb870000000001000000



[get string length of signed_transaction3.txt hex bytes. Use
tr
to remove the newline character at the end of the file.]
pi@raspberrypi ~/test $ cat signed_transaction3.txt | tr -d '\n' | wc -c

452


[452 / 2 = 226 bytes.]



[Finally, follow the recipe in the article Displaying hex bytes for manual copying to make the signed transaction easier to read and manually copy from the offline Raspberry Pi to the online Aineko.]



pi@raspberrypi ~/test $ ls -1

bitcoin_functions.py
bitcoin_functions.pyc
bjorn_edstrom_ripemd160.py
bjorn_edstrom_ripemd160.pyc
convert_dice_rolls_to_hex_bytes_2.py
create_nonstandard_transaction.py
dice_rolls2.txt
dice_rolls3.txt
dice_rolls4.txt
dice_rolls.txt
display_hex_bytes.py
ecdsa
ecdsa-0.10
ecdsa-0.10.tar.gz
generate_bitcoin_address_3.py
memory_stick_contents
nonstandard_bitcoin_functions.py
nonstandard_bitcoin_functions.pyc
nonstandard_transaction.py
nonstandard_transaction.pyc
private_key.txt
pypy_sha256.py
pypy_sha256.pyc
random_value2.txt
random_value3.txt
random_value.txt
signed_transaction2.txt
signed_transaction3.txt
signed_transaction.txt
transaction.py
transaction.pyc
w4.txt
wlog3.txt
work.log
work_log2.txt



[
Use the Nano editor to edit the controls in display_hex_bytes.py, according to the recipe.
- Delete the existing value for the variable
hex_bytes
. Then use the Nano option "Read File" to paste the contents of the file signed_transaction3.txt into the position of the value for this variable (i.e. between the quotation marks). Then press the Backspace key to delete the final newline of the file that was also pasted in.
]

pi@raspberrypi ~/test $ nano display_hex_bytes.py



pi@raspberrypi ~/test $ python display_hex_bytes.py

0100 0000 01cd e235 40f3 033b 59d8 c00f d9d8 703c 80d5 928a 1772 44b1 2fec 8d58 0f34 dbce 070f 0000 008b 4830 4502 2100 af98 4f21 f309 6c47 b968 4d9c ccf7 6988 597a ccbd b55f f0b6 6992 ef4b 3006 1608 0220 5f6b ad0d ce3f c5c0 1ac3 128f 6433 02d5 5b95 2edf 656b e25e e996 049d 74a0 e41c 0141 043a b692 792d 6c88 38fd 30c2 ff45 bf3c bd44 286a 5cac 52ba 64dc 0645 2810 202b 3206 f5c7 799c 3b72 ff77 fd19 76f1 05ce d3cd 7700 b041 2e11 266f 3888 b88c 3052 c3ff ffff ff01 46d4 0200 0000 0000 17a9 1430 d540 a50d 4648 5219 4a19 5529 ebfa 44af 521b bb87 0000 0000 0100 0000




[Recipe complete.]



[End logging on Raspberry Pi.]



Now, on Aineko, create a text file called "tx1c_copied.txt" in the work directory for this project. Manually type the signed transaction data displayed on the Raspberry Pi's screen into tx1c_copied.txt. Double-check the data.


I forgot to time this using a stopwatch.

Listening to music made this step more tolerable.


Note: Keeping the intermediate results e.g. tx1c_copied.txt during the project means that if there is an error, I can go back, find it, and fix it without having to completely redo each step.




On Aineko, open a terminal and change directory to the work directory.


aineko:work stjohnpiano$ cat tx1c_copied.txt | tr -d ' \n' > tx1c.txt


aineko:work stjohnpiano$ echo '' >> tx1c.txt


aineko:work stjohnpiano$ cat tx1c.txt

0100000001cde23540f3033b59d8c00fd9d8703c80d5928a177244b12fec8d580f34dbce070f0000008b483045022100af984f21f3096c47b9684d9cccf76988597accbdb55ff0b66992ef4b3006160802205f6bad0dce3fc5c01ac3128f643302d55b952edf656be25ee996049d74a0e41c0141043ab692792d6c8838fd30c2ff45bf3cbd44286a5cac52ba64dc06452810202b3206f5c7799c3b72ff77fd1976f105ced3cd7700b0412e11266f3888b88c3052c3ffffffff0146d402000000000017a91430d540a50d464852194a195529ebfa44af521bbb870000000001000000



[Recipe complete.]



So, the signed transaction tx1c, now transferred to the online computer Aineko, is:

0100000001cde23540f3033b59d8c00fd9d8703c80d5928a177244b12fec8d580f34dbce070f0000008b483045022100af984f21f3096c47b9684d9cccf76988597accbdb55ff0b66992ef4b3006160802205f6bad0dce3fc5c01ac3128f643302d55b952edf656be25ee996049d74a0e41c0141043ab692792d6c8838fd30c2ff45bf3cbd44286a5cac52ba64dc06452810202b3206f5c7799c3b72ff77fd1976f105ced3cd7700b0412e11266f3888b88c3052c3ffffffff0146d402000000000017a91430d540a50d464852194a195529ebfa44af521bbb870000000001000000





Let's see if a blockchain information service can decode this transaction.


Browse to:
live.blockcypher.com/btc/decodetx

Paste the signed transaction into the text box named "Transaction Hex". Network is set to "Bitcoin".

Click "Decode Transaction".

Result:

{ "addresses": [ "1vkb4YyPMFcxyC83Z5m5zuN45xASoHeNK", "369Dpo9CrJASneaHLdwWfKym7N84XTUyvH" ], "block_height": -1, "block_index": -1, "confirmations": 0, "double_spend": false, "fees": 14586, "hash": "8b0f7ba372b61b195cd237429c9a5d079aaf9887e72dd094f2fa942a0f7ccfc0", "inputs": [ { "addresses": [ "1vkb4YyPMFcxyC83Z5m5zuN45xASoHeNK" ], "age": 550741, "output_index": 15, "output_value": 200000, "prev_hash": "07cedb340f588dec2fb14472178a92d5803c70d8d90fc0d8593b03f34035e2cd", "script": "483045022100af984f21f3096c47b9684d9cccf76988597accbdb55ff0b66992ef4b3006160802205f6bad0dce3fc5c01ac3128f643302d55b952edf656be25ee996049d74a0e41c0141043ab692792d6c8838fd30c2ff45bf3cbd44286a5cac52ba64dc06452810202b3206f5c7799c3b72ff77fd1976f105ced3cd7700b0412e11266f3888b88c3052c3", "script_type": "pay-to-pubkey-hash", "sequence": 4294967295 } ], "outputs": [ { "addresses": [ "369Dpo9CrJASneaHLdwWfKym7N84XTUyvH" ], "script": "a91430d540a50d464852194a195529ebfa44af521bbb87", "script_type": "pay-to-script-hash", "value": 185414 } ], "preference": "high", "received": "2018-11-21T17:18:53.214885842Z", "relayed_by": "54.226.63.120", "size": 222, "total": 185414, "ver": 1, "vin_sz": 1, "vout_sz": 1 }





Looks good. No immediate error reported.


Some details:
- size: 222 bytes
- fee: 14586 satoshi
- preference: high
- hash (txid):
8b0f7ba372b61b195cd237429c9a5d079aaf9887e72dd094f2fa942a0f7ccfc0




Let's check the byte length of tx1c using Python.

aineko:work stjohnpiano$ python

Python 2.7.13 (default, Dec 18 2016, 05:35:59)
[GCC 4.2.1 (Apple Inc. build 5666) (dot 3)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> x = "0100000001cde23540f3033b59d8c00fd9d8703c80d5928a177244b12fec8d580f34dbce070f0000008b483045022100af984f21f3096c47b9684d9cccf76988597accbdb55ff0b66992ef4b3006160802205f6bad0dce3fc5c01ac3128f643302d55b952edf656be25ee996049d74a0e41c0141043ab692792d6c8838fd30c2ff45bf3cbd44286a5cac52ba64dc06452810202b3206f5c7799c3b72ff77fd1976f105ced3cd7700b0412e11266f3888b88c3052c3ffffffff0146d402000000000017a91430d540a50d464852194a195529ebfa44af521bbb870000000001000000"
>>> len(x) / 2.0
>>> 226.0

>>>



226 bytes.



Let's broadcast the signed transaction tx1c.





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:
- "Server Error (500)"


Hm.



I'll try another broadcast service.


Browse to:
www.blockchain.com/btc/pushtx

Paste the signed transaction into the text box.

Click "Submit Transaction".


Result:
"Validation Error: BitcoindException(super=com.neemre.btcdcli4j.core.BitcoindException: Error #-26: 18: txn-mempool-conflict, code=-26)"





Hm.


Evidently, these two broadcast-transaction services do not support replace-by-fee transactions.



I'll look up the txid.


Browse to:
live.blockcypher.com/btc/tx/8b0f7ba372b61b195cd237429c9a5d079aaf9887e72dd094f2fa942a0f7ccfc0

Result:
"No transaction found with the hash
8b0f7ba372b61b195cd237429c9a5d079aaf9887e72dd094f2fa942a0f7ccfc0"






Next: Retrieve wlog3.txt and w4.txt from the Raspberry Pi and copy them into this article at the appropriate earlier points. Merge various annotations / comments made here into these logs.




Insert the memory stick into the Raspberry Pi.




[mount the memory stick]
pi@raspberrypi ~/test $ sudo mount -o uid=pi,gid=pi /dev/sda1 /mnt/memory_stick_mount_point


[copy wlog3.txt to the memory stick]
pi@raspberrypi ~/test $ cp wlog3.txt /mnt/memory_stick_mount_point


[copy w4.txt to the memory stick]
pi@raspberrypi ~/test $ cp w4.txt /mnt/memory_stick_mount_point


[confirm that the files have been copied over]
pi@raspberrypi ~/test $ ls -1 /mnt/memory_stick_mount_point

$RECYCLE.BIN
Recycled
System Volume Information
w4.txt
wlog3.txt
work
work.log
work_log2.txt

[unmount the memory stick]
pi@raspberrypi ~/test $ sudo umount /mnt/memory_stick_mount_point


[confirm that it has been unmounted]
pi@raspberrypi ~/test $ ls -1 /mnt/memory_stick_mount_point




Unplug the memory stick from the Raspberry Pi.




Shut down for now.

On the Raspberry Pi:

pi@raspberrypi ~/test $ sudo halt

[a variety of output is printed, then the Raspberry Pi shuts down]


Unplug the power cable from the Raspberry Pi.




Insert the memory stick into Aineko. It mounts automatically and an icon appears on the Desktop. Copy the files wlog3.txt and w4.txt to the work directory for this project on Aineko.

On Aineko, right-click memory stick's Desktop icon and choose Eject "NO NAME". Unplug the memory stick from Aineko.


Integrate the contents of the files wlog3.txt and w4.txt into this article.


Done.



Hm.



Let "replace-by-fee transaction" mean "a new version of a transaction in which nothing has changed other than an increased transaction fee (which means: a lower value in one or more of the output addresses)"

I have read that (some?) miners run nodes that will accept a replace-by-fee transaction, because it will be more profitable to mine than the transaction that it replaces.

However, in order to get this replace-by-fee transaction (tx1c) to a miner's node, I have two options (are there more?):
a) Run my own node, and continually broadcast to the Bitcoin network the new replace-by-fee version of the transaction. Hopefully, this will propagate through the section of the Bitcoin network that accepts replace-by-fee transactions, until it reaches a mining node.
a1) Know someone personally who runs their own node and accepts replace-by-fee transactions.
b) Wait until the first version of the transaction (tx1 / tx1a) is cleared out of the memory pools of many (all?) of the Bitcoin nodes or until it is actually mined. If it is cleared, and not mined, I can broadcast the new version tx1c. This could take a long time, as nodes can choose to keep the first version in their memory pools (and relay it) as long as they like.
- Note: If tx1 is cleared without being mined, I could also broadcast tx1b, as this would no longer look like an attempted double-spend.

Another option: Search online for services that accept replace-by-fee transactions. This is a version of option a1.



Let's check if tx1 has been mined or cleared.




Refresh transaction page (tx1):
live.blockcypher.com/btc/tx/add54b899f1aba8b6276e42af86c3c03b0120a864451640b4a8d3fec89a4a72d
Result:
"No transaction found with the hash
add54b899f1aba8b6276e42af86c3c03b0120a864451640b4a8d3fec89a4a72d"



Current datetime: 2018-11-22 17:45

[about 48 hours have gone by since original broadcast of tx1]




Refresh transaction page (tx1b):
live.blockcypher.com/btc/tx/3677f15c9a6e62a02df0a571370ceb0de9fa90efd56441e3dcb7fe9eff188d16

Result:
"No transaction found with the hash
3677f15c9a6e62a02df0a571370ceb0de9fa90efd56441e3dcb7fe9eff188d16"




Hm. Interesting. This service does not appear to have either transaction (tx1 or tx1b) in its memory pool.



What about tx1c?



Refresh transaction page (tx1c):
live.blockcypher.com/btc/tx/8b0f7ba372b61b195cd237429c9a5d079aaf9887e72dd094f2fa942a0f7ccfc0

Result:
"No transaction found with the hash
8b0f7ba372b61b195cd237429c9a5d079aaf9887e72dd094f2fa942a0f7ccfc0"



Ah. I think that:
- this service accepted tx1 for broadcast. tx1 was never mined. eventually it was cleared from the memory pool.
- while tx1 was in the memory pool, this service rejected tx1b (as an attempt double-spend) and tx1c (also as an attempted double-spend, even though it was actually a replace-by-fee).





Log in to LocalBitcoins. It shows a pending transaction (tx1) and no new completed transaction.



Searching for both
LocalBitcoins receiving address 1:
- 369Dpo9CrJASneaHLdwWfKym7N84XTUyvH
and
LocalBitcoins receiving address 2:
- 36p1w3YrNKd2Q3xaXbe9ASUQkeynjVLfDx
on
live.blockcypher.com
produces "No transactions detected" and a balance of 0.0 BTC.



So, I think I can now try to upload tx1c to this service for broadcast. Transaction tx1 is no longer in this service's memory pool, blocking tx1c from being uploaded.



First, check current fees.


Browse to:
bitcoinfees.earn.com

The cheapest 0-block-estimated-delay fee range that I see is 53-54 satoshi / byte.

The fee rate 66 satoshi / byte in transaction tx1c should ensure a relatively quick inclusion into the blockchain.



tx1c:

0100000001cde23540f3033b59d8c00fd9d8703c80d5928a177244b12fec8d580f34dbce070f0000008b483045022100af984f21f3096c47b9684d9cccf76988597accbdb55ff0b66992ef4b3006160802205f6bad0dce3fc5c01ac3128f643302d55b952edf656be25ee996049d74a0e41c0141043ab692792d6c8838fd30c2ff45bf3cbd44286a5cac52ba64dc06452810202b3206f5c7799c3b72ff77fd1976f105ced3cd7700b0412e11266f3888b88c3052c3ffffffff0146d402000000000017a91430d540a50d464852194a195529ebfa44af521bbb870000000001000000





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/8b0f7ba372b61b195cd237429c9a5d079aaf9887e72dd094f2fa942a0f7ccfc0
Details:
- Transaction Successfully Broadcst
- AMOUNT TRANSACTED: 0.00185414 BTC
- FEES: 0.00014586 BTC
- Confirmations: 0/6
- Miner Preference: HIGH
- Size: 222 bytes
- Version: 1
- Relayed By: 54.242.109.171




Current datetime: 2018-11-22 18:00




Hm.



If I search for these txids and addresses on
www.blockchain.com
I find that tx1 is still stored in that service's system (as "unconfirmed"), and tx1b and tx1c are not.


It's possible that the blockcypher service nodes are surrounded in the Bitcoin network by nodes that have stored tx1 and reject replace-by-fee transactions like tx1c. Even though tx1c has been uploaded to a node, I may still have to wait until tx1 has been cleared out of more memory pools. By the time that happens, tx1c may also have been removed from many memory pools, and I may have to upload it for broadcast again.






Current datetime: 2018-11-23 10:40


Refresh transaction page:
live.blockcypher.com/btc/tx/8b0f7ba372b61b195cd237429c9a5d079aaf9887e72dd094f2fa942a0f7ccfc0

Confirmations: 6+


Excellent. Transaction tx1c has been mined.


Click Advanced Details.

- Block Hash:
000000000000000000091db255f327f3938cb33cd1076d7554b7bbd22b9c1000
- Block Height: 551,106
- Transaction Index: 668


Click API Call.

Result: tx1c

{ "block_hash": "000000000000000000091db255f327f3938cb33cd1076d7554b7bbd22b9c1000", "block_height": 551106, "block_index": 668, "hash": "8b0f7ba372b61b195cd237429c9a5d079aaf9887e72dd094f2fa942a0f7ccfc0", "hex": "0100000001cde23540f3033b59d8c00fd9d8703c80d5928a177244b12fec8d580f34dbce070f0000008b483045022100af984f21f3096c47b9684d9cccf76988597accbdb55ff0b66992ef4b3006160802205f6bad0dce3fc5c01ac3128f643302d55b952edf656be25ee996049d74a0e41c0141043ab692792d6c8838fd30c2ff45bf3cbd44286a5cac52ba64dc06452810202b3206f5c7799c3b72ff77fd1976f105ced3cd7700b0412e11266f3888b88c3052c3ffffffff0146d402000000000017a91430d540a50d464852194a195529ebfa44af521bbb8700000000", "addresses": [ "1vkb4YyPMFcxyC83Z5m5zuN45xASoHeNK", "369Dpo9CrJASneaHLdwWfKym7N84XTUyvH" ], "total": 185414, "fees": 14586, "size": 222, "preference": "high", "relayed_by": "54.242.109.171", "confirmed": "2018-11-22T20:17:05Z", "received": "2018-11-22T17:46:01.324Z", "ver": 1, "double_spend": false, "vin_sz": 1, "vout_sz": 1, "confirmations": 67, "confidence": 1, "inputs": [ { "prev_hash": "07cedb340f588dec2fb14472178a92d5803c70d8d90fc0d8593b03f34035e2cd", "output_index": 15, "script": "483045022100af984f21f3096c47b9684d9cccf76988597accbdb55ff0b66992ef4b3006160802205f6bad0dce3fc5c01ac3128f643302d55b952edf656be25ee996049d74a0e41c0141043ab692792d6c8838fd30c2ff45bf3cbd44286a5cac52ba64dc06452810202b3206f5c7799c3b72ff77fd1976f105ced3cd7700b0412e11266f3888b88c3052c3", "output_value": 200000, "sequence": 4294967295, "addresses": [ "1vkb4YyPMFcxyC83Z5m5zuN45xASoHeNK" ], "script_type": "pay-to-pubkey-hash", "age": 550741 } ], "outputs": [ { "value": 185414, "script": "a91430d540a50d464852194a195529ebfa44af521bbb87", "spent_by": "618ceedd53735af8c3024f0fe13184357544d1af73503dd6ad819fd6ef6b7bc6", "addresses": [ "369Dpo9CrJASneaHLdwWfKym7N84XTUyvH" ], "script_type": "pay-to-script-hash" } ] }




Key details:
- block_hash:
000000000000000000091db255f327f3938cb33cd1076d7554b7bbd22b9c1000
- block_height: 551106
- confirmed: 2018-11-22T20:17:05Z
- received: 2018-11-22T17:46:01.324Z
- hash (txid):
8b0f7ba372b61b195cd237429c9a5d079aaf9887e72dd094f2fa942a0f7ccfc0


My record of the broadcast time:
2018-11-22 18:00

blockcypher.com's record of the broadcast time:
2018-11-22T17:46

Fairly close.


Using the times from blockcypher.com:
- Broadcast time: 2018-11-22 17:46
- Confirmation time: 2018-11-22 20:17

Time taken ~= 2.5 hours



Log on to LocalBitcoins.
Go to Wallet / Transactions.
- Latest received transaction:
-- Datetime: 11/22/2018 20:31
-- Received BTC: 0.00170414
-- Description: Deposit to 369Dpo......
-- Deposit Fee BTC: 0.00015000



The test address has now been validated. I have moved some bitcoin into it and then successfully retrieved it. This proves that the address was correctly calculated from the private key.



I can now move a large amount of bitcoin into this address and be certain that I can retrieve it. Even if I 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, I know that eventually this error could be fixed and a valid transaction could be created. I would only risk a temporary lack of access to the bitcoin stored in this address, not its permanent loss.



So, I'll now test this approach. I'll transfer a larger amount of bitcoin into the test address, store it for a while, and then transfer it back out. This is the process that can be used to securely store bitcoin offline until it is needed.







Log in to LocalBitcoins.


Current exchange rate:
$4212 / 1 BTC


Using my LocalBitcoins account, I'll transfer ~$50 worth of bitcoin to the test address.

$50 * (1 BTC / $4212) = 50 * 1 / 4212 = 0.01187084 ~= 0.012



Test address:
1vkb4YyPMFcxyC83Z5m5zuN45xASoHeNK

I've transferred 0.0120 bitcoin to the test address. LocalBitcoins charged a transaction fee of 0.00005 bitcoin.

Current datetime: 2018-11-23 18:22


Wait 5-10 minutes.


Refresh LocalBitcoins / Wallet / Transactions.

Latest transaction:
- 11/23/2018 18:08
- Sent BTC: 0.012
- Sent to:
1vkb4YyPMFcxyC83Z5m5zuN45xASoHeNK
- txid:
af3888cc260b6b6bfb8eb256fb70fd1e761a1c7baac0e19cd11b47726f2327d2



Browse to:
live.blockcypher.com

Search for this txid.

Transaction page loads:
live.blockcypher.com/btc/tx/af3888cc260b6b6bfb8eb256fb70fd1e761a1c7baac0e19cd11b47726f2327d2


Details:
- AMOUNT TRANSACTED: 49.9112634 BTC
- FEES: 0.0015299 BTC
- CONFIRMATIONS: 0/6
- Miner Preference: HIGH
- Size: 2822 bytes
- Version: 2
- Relayed By: 45.79.10.204:8333
- 1 Input Consumed
- 85 Outputs Created


Set timer for 30 minutes.


Timer has finished.


Refresh transaction page.
Confirmation: 1/6


Set timer for 1 hour.


I refreshed the transaction page after 43 minutes.


Confirmations: 6+

Click Advanced Details / API Call.


Result: tx2

{ "block_hash": "0000000000000000001f85686e50bbc4e929b50768669165731e5c73a690f680", "block_height": 551219, "block_index": 502, "hash": "af3888cc260b6b6bfb8eb256fb70fd1e761a1c7baac0e19cd11b47726f2327d2", "hex": "020000000001017abbae8a4b2b7200ae3fe62454c1dd39031a1b94461590420202ca09652f7e4e2900000017160014514082c38bf390edbdcd7ea45a2afd27dd44ac88feffffff5588cf34000000000017a9143b1404353aa25fa35e00d1199023e4dbc4ccbfb387f5730a000000000017a914e0ac955a7ca184724a36b74326e9dd1473f5580e8778a010000000000017a9148736e84b40ae4e75d98e3bf5398cc5f3ae6f011287504d06000000000017a91481aa83966e76c850e87a11a03eddf6fa73e786a387b7cf05000000000017a914a7a798eb8307456405068b4547a29edd5d9d972b874dca06000000000017a9147bd968cd765e600ff784e18cf9280af46dcc017587320408000000000017a914be75e425f70abdec55256f6f985fc711872a89d687b3ba00000000000017a9140c040f8168f8dbcaf0e990103780e41021768d2a876a0a05000000000017a91458af46baa689a19dd3963c45c49b123654a8fbb887b77712000000000017a914d2c8032f1ae2ccfb2430c7ad608716eba301f27387fbbd09000000000017a9148ee013a317f0e083b27d47baf1a646a75519532c8700350c000000000017a9147a9b7668b80d51543d771abdf656c1a9e71dc4c7873f6e06000000000017a9146ee9e13deae04aff06a6fa4739858f21bedfc070876b5505000000000017a91424470831d0e6e045d047ba5a89a6af42b682eff38786a203000000000017a9144e3ce92f09e1313ff7845231ce02ed3eae2324ea8728f018000000000017a914ff57bc4784f8075b95175b8f9d7f3d0663770dda87f49307000000000017a9146f0795b6a9a662de22c9e7b07972d53477dc3cc687aaa90a000000000017a91400a14d1d06a91b95efa29376cd728176caa8b2a5876ed912000000000017a914d925d1065fd834a536e9422878ec948f266cf00987f3fa07000000000017a9140f00d11ef3157d1c4d9cf8f6e2d839fd0f43bf098749d023000000000017a91431ddd15e88a817370d82998825d1c4c4af52d9f587e5c207000000000017a914d0220fdca7bf25bdef88969db44d3a29097f015287b35105000000000017a91467ca4930f8a09c3e013989b93bb780a919fb48cb8710f108000000000017a914b99fb98272a8f2733f291aee7467e86753f2398a877ccc560f0100000017a9146b208ae81f844e45c43f9e17c5530ef02ba49fe787804f1200000000001976a9140a2a6e4834efa5c7c31eed1ebeadf94a370a1e9388acda4507000000000017a91415b7bf3e57a9d4f88ccf474f0a05780f3696559d877ba967120000000017a9143e696fd23509b8b6637fd463dab1725fc49b2ea787a54706000000000017a9145a21e377a91fe0936d1cfdc64d45afef5debed4987100707000000000017a914c5789ae5d6a57151b83ef64701dc170b969270e78725430a000000000017a914d902f426611e443f514a16949986a9cdf11fdbc587af9e65000000000017a91435cf6e0694f45f6b039feb2c734a482129bea10d87c9050c000000000017a914a267c025e8b1bc82170b8f27582bc87a298e3ace87d6a30d000000000017a914ad35985c54ba3b16392ded0d4184ce55eefc0c958773b706000000000017a91477113252766830267d54bf0152ea2b8156d65d15874a6c0e000000000017a914dff6a651bbb23b69de926f1ba121dd50be046e4a8784c909000000000017a914ef91c009a28fabff2eb07526a1365808a0e38a7287fc4914000000000017a91463346b99c3ef401c690425571e999e6ef5544d4f878ead11000000000017a9143fa9e9680697e8c089284feebb06bb577d4a534f8739be14000000000017a91405e19ef872775f9393f6193e3a9f23dd8c51e4e1871b17a900000000001976a9149d526dbf65d7358848f98d2702561474fb80601f88aca24b30000000000017a914bfb57dc2acad1372fb9140c78c0249ff3d20fe4e8793dc06000000000017a914dd5cf71eb6c75a61a97940440773c36e5e5816198701d406000000000017a914c59a73e0d41d083a21126ba420e60456c6c1cb9e878fb40f000000000017a9146707f646bacfc8066b791ef83ea0f1aef1b756d58702e720000000000017a914365971c1d49a417129a5ce34757cc1acfde944f087603305000000000017a9149a7b245b5a86f78b55e03d393ad1716b1f761dc087ece307000000000017a9148a85d9a402749d206270f99ee2da99c87fe81eb587aae98e00000000001976a914976c1c20664b3d76042b01c98c1933c85de2788788acc04504000000000017a914247884269766403c87ac818f6ed5db655d86bb3f878cc404000000000017a914a4eff4f61ed5384adbb5497e7f67147e59e26d3887c5da04000000000017a91442b920a9892c866bf6218ec107d02698a0738b4d87234101000000000017a914f87797bdf2a392c9c66c363dfc9968521c7a85648725941300000000001976a9143ca960973e95ee40468d92388d7421399a5a1aad88ac0f9f0300000000001976a9141bd917d52d595181570ef17e39f2bf4ea7ae0de288acd77b0b000000000017a914ebc33c8912509c1cd8681981b25889bb2d1cfcac87ee5e33000000000017a9144c4f0c5780b5d26d77e87e412f306333ed78e08d8753900300000000001976a914a6b9bf2b77e6ede60bba794082092034e680d58888acb35f15000000000017a914ab3792a73b283541f66a9f82e869a03e53b8338a8774dbff00000000001976a914a2ff1026a9ed716efbe74473a04a7643e7059b7b88aceac90e000000000017a9145099ae0c09a8f6973d24824c5922abb8ee54127987e9ed0a000000000017a914480d6e62f69ba7ad85689b2625e5a3c2794c5ea487966e0500000000001976a91422855356ff846270d18a83696b2293ae26185a8488ace22606000000000017a914b25da5e2acd5f15e3834493eb55a4354c1eecd1c87d7fc08000000000017a91433f974a43d1cc3bc6c212ab8009e2b69546acdb087a4a105000000000017a914d710f90d7f6d66c9e05b5443ad670ad3a503f6e487ee450400000000001976a9144a6f9c2b63256961a35beec88f534cfdcbfcc68388ace0510700000000001976a914f1b6b0f57ac696834257794e544e3f2b3aefd7ff88ac7d4507000000000017a914c2c9edcb25fa41e7f430704fc192a6c5e084946e87200436000000000017a914c2f270a1416ad36157931543b5f7771bbe2e712b8735ed0400000000001976a9145a53953abed389f72b403a5a170305db300d54a488ac84280a000000000017a91407a1e28534524bc92e766e575b982203befcc85a87c86500000000000017a914cf29d7ffaf5171ca9be395a2b9affee644d6a52987777d0300000000001976a9142c9bcc3cb570e5f6903b56031b13cd3e18a1de1588acbba36c00000000001976a9146ded876b1a5beecd895308688b5d948cfae897fe88ac416e06000000000017a914d49820b7f13679af09679814a4a97b9132c6cc28875e9c0e000000000017a91426b3e6491a7c929bfe8d339ab7a5dd98cb9ef3c9872d3e05000000000017a9146e176372192c96d926d36d15332d5cf95d1dd3c787a9370b000000000017a9149b2d27552bf03012f237e664ee4cf37806d62aca875e0b21000000000017a914b83714debe64d20c5b340a719a1ce899872a048187941b0e000000000017a91452b7aa5d6ab1e0c7284078e6f0c83ac05f9c5af6877bd204000000000017a9148ca4f89847852e99f61091825b7cf9e56fa923298766a854000000000017a914d5ca13f7e4d9dd67946b10aa5aca2cbd8a77da2d87eac6a500000000001976a914e1ca1236a1f078fd51c40681a9bf745fcad8246d88aca0c20b000000000017a91433d21539705f0eb3210596751aae09eada7eb47f8702483045022100f95714dc9ae10ccb37cbace8991c217783d673b2a0387726735545ab59452a5a022010de0390eed54ea962c1445f2157c6dc81032c7b4bbf7f77c7de070043936331012103dc484d558d2f7ed34e2131255330552d3a4a8417054a3ab060397872af73f81632690800", "addresses": [ "13YFK5BuzaUHgNHaGWMKLZ7hdRpCkCKYtK", "149Xh9L2vXAUifrndHV4kockC4WbEyup2M", "154sNTmf9vPJB8ewB4jbCYFvm2QZ4Dxw2K", "16XkT3zCwD31Aiacp2qai2pUBsmK2D6Xrr", "17nahzp9omaMcXVavFi3ArdGBe1Dx2X5k7", "19Ebwi5vkWprkwH4bnwSuLRLoQqBd4iXHf", "1B2FCiJyPhqZW12gJa8YFkTZxdvZR7v2ja", "1EoeYaAZ2mKtxfMBf9AD3qkTJzcsdsLP9L", "1FLqqN7RdL7Kf63CExZ6qA9uegVgY2b4yX", "1Frr2AuG8cJGcAahPvfNU2M4G2QRmqDEvs", "1GCZgkn6L1zFqM5NhGL4jEeQsKwvjvS7sK", "1Mas7K3wJXgGjW7MSJXp2bAbfFToQNDdSd", "1P34hqoXi1xTTJPbo7SncLFaeDZvfEDy6D", "1vkb4YyPMFcxyC83Z5m5zuN45xASoHeNK", "31kM9x1evVgyz6TqrikJCouXsedi9EjyGb", "32E7avWJ9gxaVCfP1eNwZYZW8xt5ARJCgk", "32PNaqqQ5LNcVNVkKLABNqo9yPLaGyRomQ", "32nYtyjTsGfyxF8JVfkH5Ptdgiqo5AtEve", "334M3BL9n6u1mMY3SyE9ySoFq2TyCk33Nf", "33frEYKAqNVE8adVroLUx2ZyKDTRC5HsUF", "34zqLqgoofeaJXQBdGXkfN97wEobHApj2G", "351rd4c9C8JLfAK9Ua7nHbbEXq6jPmvp8f", "35Df7UQiU5cA18gp4EopUp1s5xTgobHhjk", "36Egm7nRS85UCDZpkLrXgmro5jmJMzLz6x", "36R249Gks9iHMBdjxuTMeFpxj1gFN6iMAe", "36RqDoq5TvGTvceSDM3qHku2HEPrRKNsNo", "36bYEBgviuYSgtRj3oiXKwRbfTCJ4acYfz", "36ePZc6fbpKwpjEUJNFjDX5ibe9Cgtins9", "375PmdPUd9T6KA95kCoeCbJnid1SrxDYfK", "37P28KCeGUJfXUBwRKJ74Dcb3Gmza4YkJ7", "37Ve3JaqoGFvopiTXXUCLcrK6j4EQ9oJVv", "37mpJ6TAcY4BMr4yV1t4nksKQBmVqg9G3t", "38Fzfa6pHn4z8uznMLsMi1yUzC6qMKsXYZ", "38eVyVJZqTBvgsPcRwbJk5yCErM8NMMLyi", "38phbfiEfKoqk87C1xUjKwadBq3zVtSKtj", "393C5kjWZ96WKLiZHQ6bDc4HpwtkFnyc8k", "39EPMaLong4ZxYp6BmmYPJJVjTFsZsEjBQ", "39mwMqN2YtathQUeXJkh3RupAQjjQTavxY", "39pfs3HRy56gjPHT9FPCsKxVf3gwk9Bi1r", "39ubLRepPE8FdvYa5dr4id1HxHDqXN2m1m", "3AjZcmAeebyT7N2qtMaqsYbQCSpLGtoSmq", "3B5o4WhgQh8MjZr2M7pGV7AX1QkQ9jSJvn", "3B9orNburYLxCu4DnQkjfgm5ei25CBr4RH", "3BTTDAn8HrmS2Lx48EoJy6v35B4jvAUW8p", "3Bj8GhmkAjnofYH55YLrqK3UsK32mc8LfR", "3BoURuGhintHeuhbugaq7ZfYXmaMHxoNfQ", "3Bp61qdr6hNL8YLddSFqfqjZB4ppQFCwov", "3CYawD9Zattwi4XR1v87ia6Bk62MsF4DAr", "3CsJbg1YDxonVSf4HhjDn6P5CTDwr92p42", "3CysV1QUpHyjL1t7bZFXZYsxzuHQzSpJEn", "3DWdMp1QZZyQ8ogzBWP1eieNnKa9WqpaNF", "3E1xvUS2dUemBpVSMchF4BuwCAJWQMaRte", "3EKTX65jDKjPCFcN8c1qE7vZjsMKBUucr8", "3EWg9nqhaHCXNM7eygm6CJRTN5CBhM6AR4", "3EiUJuWs62WPaJDU6YZrghjquZ2A518gS1", "3FmqW9Fgdap6HG3qiKqFSFbZWFwG4QdMP2", "3FqWkcCFrhrJt3oZggGAPMaLQxRL15eEDy", "3GVjgLVR2KKRYmvMbGynHtQc6ZuJrzMvwy", "3Gj8CVyDuA212EryfqitDThmRnsYCJm2GP", "3GyVYSt25fKHr6bYn9Y8jCogo45rad36e9", "3HJL3ck2f4rVFGZW2VcYmpThW27UQ6bmjJ", "3HUs2b24FfbCp8xq3qXgHMSxDeFVMuN4PC", "3Hx8PTyqUFoih4EpEcY7eLna3VBhxRt3VN", "3JV4EyKnfZ3TVNnWqEz5stbbsGFVUDnZCU", "3JcWGttMtrTyWBmfSE4biuriEtmfLmeCxq", "3K45YDUupjgDgFKwsswHCbN6TwZC8CJnKu", "3KAgQR7ioQUQLF8wPnsKQh3iH4AkEeE7iQ", "3KSxv2KEPvyy2H6QKBHFAv9VogbrGr2J8c", "3KToSnM1qPtjuVtmBQZxrCUrkRH6XsaD3B", "3Kh9X7zwC4tyN9vRtvDh5Q33sdq3G4xcNq", "3Khr4tiq1sUMrT6A8ntESCJxPoJcrZZujL", "3LaPvcAKeKADQWSbnasm5TpeU64Woj1tbb", "3LfXH7Pf39uUfEfHiH4ticwUMukERCKkHr", "3LuXRwEjTDTHyDUM1JBgBVFZnWEDUxEBvc", "3M57REhvZzMniiHeUMgCQfDTTGH3DhnLbU", "3MBRw2eryjDC7SN1okjooSjsqPXax8UaJu", "3MJBY5jZfxtfhs52Y2ghST86cAYjJ7WsV6", "3MUU6Q4MoXvgrLC4vx6rYSA9MPtL2BSABA", "3MVBrhzu6GcbEy7W9x6Xeqf2JavzY4MYdM", "3MsUdHGxaM3bxVPf8qvZFKgChzjouRRB4e", "3N7E5qpKE2QvPjBZ6eXZG4weFvmRcGMtVB", "3NAz2pUtoZe544SipVBBhWvjPKhUHXLJbc", "3PBcbtey4J4S91se4jYKjRys73epnSLLS1", "3PXk2HiNDxNDBoo4VoPYzBNjQ7Y9T6X4L5", "3QLnmZqxi2cn7q52MGof8mJk5Rb2FsHwBt", "3Qy9LRkdQoBPWyq2tyZg2giuCV9QnjXQiz" ], "total": 4991126340, "fees": 152990, "size": 2822, "preference": "high", "relayed_by": "45.79.10.204:8333", "confirmed": "2018-11-23T18:25:35Z", "received": "2018-11-23T18:10:40.724Z", "ver": 2, "lock_time": 551218, "double_spend": false, "vin_sz": 1, "vout_sz": 85, "confirmations": 12, "confidence": 1, "inputs": [ { "prev_hash": "4e7e2f6509ca020242901546941b1a0339ddc15424e63fae00722b4b8aaebb7a", "output_index": 41, "script": "160014514082c38bf390edbdcd7ea45a2afd27dd44ac88", "output_value": 4991279330, "sequence": 4294967294, "addresses": [ "39pfs3HRy56gjPHT9FPCsKxVf3gwk9Bi1r" ], "script_type": "pay-to-script-hash", "age": 551213, "witness": [ "3045022100f95714dc9ae10ccb37cbace8991c217783d673b2a0387726735545ab59452a5a022010de0390eed54ea962c1445f2157c6dc81032c7b4bbf7f77c7de07004393633101", "03dc484d558d2f7ed34e2131255330552d3a4a8417054a3ab060397872af73f816" ] } ], "outputs": [ { "value": 3461000, "script": "a9143b1404353aa25fa35e00d1199023e4dbc4ccbfb387", "addresses": [ "375PmdPUd9T6KA95kCoeCbJnid1SrxDYfK" ], "script_type": "pay-to-script-hash" }, { "value": 685045, "script": "a914e0ac955a7ca184724a36b74326e9dd1473f5580e87", "addresses": [ "3NAz2pUtoZe544SipVBBhWvjPKhUHXLJbc" ], "script_type": "pay-to-script-hash" }, { "value": 1089656, "script": "a9148736e84b40ae4e75d98e3bf5398cc5f3ae6f011287", "spent_by": "ecf32728178b6d85031d6726504f39e09fc2efe1479c22d5d54b8df86d86cb0b", "addresses": [ "3E1xvUS2dUemBpVSMchF4BuwCAJWQMaRte" ], "script_type": "pay-to-script-hash" }, { "value": 413008, "script": "a91481aa83966e76c850e87a11a03eddf6fa73e786a387", "addresses": [ "3DWdMp1QZZyQ8ogzBWP1eieNnKa9WqpaNF" ], "script_type": "pay-to-script-hash" }, { "value": 380855, "script": "a914a7a798eb8307456405068b4547a29edd5d9d972b87", "spent_by": "f6989c89f9c774374ff117119c875e8bb86767049cedc63a8eed22f5fd808e23", "addresses": [ "3GyVYSt25fKHr6bYn9Y8jCogo45rad36e9" ], "script_type": "pay-to-script-hash" }, { "value": 445005, "script": "a9147bd968cd765e600ff784e18cf9280af46dcc017587", "addresses": [ "3CysV1QUpHyjL1t7bZFXZYsxzuHQzSpJEn" ], "script_type": "pay-to-script-hash" }, { "value": 525362, "script": "a914be75e425f70abdec55256f6f985fc711872a89d687", "spent_by": "4b8b716d72e966ce8fefa1e439059428d065274a934d59a36d6453ba509833df", "addresses": [ "3K45YDUupjgDgFKwsswHCbN6TwZC8CJnKu" ], "script_type": "pay-to-script-hash" }, { "value": 47795, "script": "a9140c040f8168f8dbcaf0e990103780e41021768d2a87", "addresses": [ "32nYtyjTsGfyxF8JVfkH5Ptdgiqo5AtEve" ], "script_type": "pay-to-script-hash" }, { "value": 330346, "script": "a91458af46baa689a19dd3963c45c49b123654a8fbb887", "spent_by": "0100701dc7e325eeb9105f68a63274a911ff6a11b2ddf28f755cf08720bdd4a1", "addresses": [ "39mwMqN2YtathQUeXJkh3RupAQjjQTavxY" ], "script_type": "pay-to-script-hash" }, { "value": 1210295, "script": "a914d2c8032f1ae2ccfb2430c7ad608716eba301f27387", "addresses": [ "3LuXRwEjTDTHyDUM1JBgBVFZnWEDUxEBvc" ], "script_type": "pay-to-script-hash" }, { "value": 638459, "script": "a9148ee013a317f0e083b27d47baf1a646a75519532c87", "addresses": [ "3EiUJuWs62WPaJDU6YZrghjquZ2A518gS1" ], "script_type": "pay-to-script-hash" }, { "value": 800000, "script": "a9147a9b7668b80d51543d771abdf656c1a9e71dc4c787", "addresses": [ "3CsJbg1YDxonVSf4HhjDn6P5CTDwr92p42" ], "script_type": "pay-to-script-hash" }, { "value": 421439, "script": "a9146ee9e13deae04aff06a6fa4739858f21bedfc07087", "addresses": [ "3BoURuGhintHeuhbugaq7ZfYXmaMHxoNfQ" ], "script_type": "pay-to-script-hash" }, { "value": 349547, "script": "a91424470831d0e6e045d047ba5a89a6af42b682eff387", "addresses": [ "34zqLqgoofeaJXQBdGXkfN97wEobHApj2G" ], "script_type": "pay-to-script-hash" }, { "value": 238214, "script": "a9144e3ce92f09e1313ff7845231ce02ed3eae2324ea87", "addresses": [ "38phbfiEfKoqk87C1xUjKwadBq3zVtSKtj" ], "script_type": "pay-to-script-hash" }, { "value": 1634344, "script": "a914ff57bc4784f8075b95175b8f9d7f3d0663770dda87", "addresses": [ "3Qy9LRkdQoBPWyq2tyZg2giuCV9QnjXQiz" ], "script_type": "pay-to-script-hash" }, { "value": 496628, "script": "a9146f0795b6a9a662de22c9e7b07972d53477dc3cc687", "addresses": [ "3Bp61qdr6hNL8YLddSFqfqjZB4ppQFCwov" ], "script_type": "pay-to-script-hash" }, { "value": 698794, "script": "a91400a14d1d06a91b95efa29376cd728176caa8b2a587", "spent_by": "10a3504ce524d77bc803466396fcae150c1fa1c5fbd2a42df4616be51db67df6", "addresses": [ "31kM9x1evVgyz6TqrikJCouXsedi9EjyGb" ], "script_type": "pay-to-script-hash" }, { "value": 1235310, "script": "a914d925d1065fd834a536e9422878ec948f266cf00987", "addresses": [ "3MVBrhzu6GcbEy7W9x6Xeqf2JavzY4MYdM" ], "script_type": "pay-to-script-hash" }, { "value": 522995, "script": "a9140f00d11ef3157d1c4d9cf8f6e2d839fd0f43bf0987", "spent_by": "571297585d081add53553d095622b2125088718c2ba3166e6e7b8e00821b5214", "addresses": [ "334M3BL9n6u1mMY3SyE9ySoFq2TyCk33Nf" ], "script_type": "pay-to-script-hash" }, { "value": 2347081, "script": "a91431ddd15e88a817370d82998825d1c4c4af52d9f587", "addresses": [ "36Egm7nRS85UCDZpkLrXgmro5jmJMzLz6x" ], "script_type": "pay-to-script-hash" }, { "value": 508645, "script": "a914d0220fdca7bf25bdef88969db44d3a29097f015287", "spent_by": "9ffcbe2a07ce5415b531c2bc93fd6d7a06df1694ad01902f06e557b1868d299d", "addresses": [ "3LfXH7Pf39uUfEfHiH4ticwUMukERCKkHr" ], "script_type": "pay-to-script-hash" }, { "value": 348595, "script": "a91467ca4930f8a09c3e013989b93bb780a919fb48cb87", "addresses": [ "3B9orNburYLxCu4DnQkjfgm5ei25CBr4RH" ], "script_type": "pay-to-script-hash" }, { "value": 586000, "script": "a914b99fb98272a8f2733f291aee7467e86753f2398a87", "addresses": [ "3JcWGttMtrTyWBmfSE4biuriEtmfLmeCxq" ], "script_type": "pay-to-script-hash" }, { "value": 4552313980, "script": "a9146b208ae81f844e45c43f9e17c5530ef02ba49fe787", "addresses": [ "3BTTDAn8HrmS2Lx48EoJy6v35B4jvAUW8p" ], "script_type": "pay-to-script-hash" }, { "value": 1200000, "script": "76a9140a2a6e4834efa5c7c31eed1ebeadf94a370a1e9388ac", "addresses": [ "1vkb4YyPMFcxyC83Z5m5zuN45xASoHeNK" ], "script_type": "pay-to-pubkey-hash" }, { "value": 476634, "script": "a91415b7bf3e57a9d4f88ccf474f0a05780f3696559d87", "addresses": [ "33frEYKAqNVE8adVroLUx2ZyKDTRC5HsUF" ], "script_type": "pay-to-script-hash" }, { "value": 308783483, "script": "a9143e696fd23509b8b6637fd463dab1725fc49b2ea787", "spent_by": "c93bf4c398277bf1f1ef4aa8f3aa64fd5c5df7e1faba0ef6087e46ac96fd89b9", "addresses": [ "37P28KCeGUJfXUBwRKJ74Dcb3Gmza4YkJ7" ], "script_type": "pay-to-script-hash" }, { "value": 411557, "script": "a9145a21e377a91fe0936d1cfdc64d45afef5debed4987", "spent_by": "4e378798f181ebf31e6a5fcee911baa5fb409d3a4834cc1d9a822e287bbf59d7", "addresses": [ "39ubLRepPE8FdvYa5dr4id1HxHDqXN2m1m" ], "script_type": "pay-to-script-hash" }, { "value": 460560, "script": "a914c5789ae5d6a57151b83ef64701dc170b969270e787", "addresses": [ "3Kh9X7zwC4tyN9vRtvDh5Q33sdq3G4xcNq" ], "script_type": "pay-to-script-hash" }, { "value": 672549, "script": "a914d902f426611e443f514a16949986a9cdf11fdbc587", "addresses": [ "3MUU6Q4MoXvgrLC4vx6rYSA9MPtL2BSABA" ], "script_type": "pay-to-script-hash" }, { "value": 6659759, "script": "a91435cf6e0694f45f6b039feb2c734a482129bea10d87", "addresses": [ "36bYEBgviuYSgtRj3oiXKwRbfTCJ4acYfz" ], "script_type": "pay-to-script-hash" }, { "value": 787913, "script": "a914a267c025e8b1bc82170b8f27582bc87a298e3ace87", "addresses": [ "3GVjgLVR2KKRYmvMbGynHtQc6ZuJrzMvwy" ], "script_type": "pay-to-script-hash" }, { "value": 893910, "script": "a914ad35985c54ba3b16392ded0d4184ce55eefc0c9587", "addresses": [ "3HUs2b24FfbCp8xq3qXgHMSxDeFVMuN4PC" ], "script_type": "pay-to-script-hash" }, { "value": 440179, "script": "a91477113252766830267d54bf0152ea2b8156d65d1587", "addresses": [ "3CYawD9Zattwi4XR1v87ia6Bk62MsF4DAr" ], "script_type": "pay-to-script-hash" }, { "value": 945226, "script": "a914dff6a651bbb23b69de926f1ba121dd50be046e4a87", "spent_by": "cee24fc0d864f421bf896dc2a30b631a9a570b94506b66bc44e1cb969da43ee4", "addresses": [ "3N7E5qpKE2QvPjBZ6eXZG4weFvmRcGMtVB" ], "script_type": "pay-to-script-hash" }, { "value": 641412, "script": "a914ef91c009a28fabff2eb07526a1365808a0e38a7287", "spent_by": "cd2fa51e7d2fcb069b2baf768d5dcdc4ae01375b1f56db1accc9dcc20be5098e", "addresses": [ "3PXk2HiNDxNDBoo4VoPYzBNjQ7Y9T6X4L5" ], "script_type": "pay-to-script-hash" }, { "value": 1329660, "script": "a91463346b99c3ef401c690425571e999e6ef5544d4f87", "spent_by": "1ef28779f6da39a919b869ab8ec2a940965f4d22b9121bc3969514c6ef72c155", "addresses": [ "3AjZcmAeebyT7N2qtMaqsYbQCSpLGtoSmq" ], "script_type": "pay-to-script-hash" }, { "value": 1158542, "script": "a9143fa9e9680697e8c089284feebb06bb577d4a534f87", "spent_by": "4b8b716d72e966ce8fefa1e439059428d065274a934d59a36d6453ba509833df", "addresses": [ "37Ve3JaqoGFvopiTXXUCLcrK6j4EQ9oJVv" ], "script_type": "pay-to-script-hash" }, { "value": 1359417, "script": "a91405e19ef872775f9393f6193e3a9f23dd8c51e4e187", "addresses": [ "32E7avWJ9gxaVCfP1eNwZYZW8xt5ARJCgk" ], "script_type": "pay-to-script-hash" }, { "value": 11081499, "script": "76a9149d526dbf65d7358848f98d2702561474fb80601f88ac", "addresses": [ "1FLqqN7RdL7Kf63CExZ6qA9uegVgY2b4yX" ], "script_type": "pay-to-pubkey-hash" }, { "value": 3165090, "script": "a914bfb57dc2acad1372fb9140c78c0249ff3d20fe4e87", "addresses": [ "3KAgQR7ioQUQLF8wPnsKQh3iH4AkEeE7iQ" ], "script_type": "pay-to-script-hash" }, { "value": 449683, "script": "a914dd5cf71eb6c75a61a97940440773c36e5e58161987", "spent_by": "cd2fa51e7d2fcb069b2baf768d5dcdc4ae01375b1f56db1accc9dcc20be5098e", "addresses": [ "3MsUdHGxaM3bxVPf8qvZFKgChzjouRRB4e" ], "script_type": "pay-to-script-hash" }, { "value": 447489, "script": "a914c59a73e0d41d083a21126ba420e60456c6c1cb9e87", "addresses": [ "3Khr4tiq1sUMrT6A8ntESCJxPoJcrZZujL" ], "script_type": "pay-to-script-hash" }, { "value": 1029263, "script": "a9146707f646bacfc8066b791ef83ea0f1aef1b756d587", "spent_by": "ecf32728178b6d85031d6726504f39e09fc2efe1479c22d5d54b8df86d86cb0b", "addresses": [ "3B5o4WhgQh8MjZr2M7pGV7AX1QkQ9jSJvn" ], "script_type": "pay-to-script-hash" }, { "value": 2156290, "script": "a914365971c1d49a417129a5ce34757cc1acfde944f087", "addresses": [ "36ePZc6fbpKwpjEUJNFjDX5ibe9Cgtins9" ], "script_type": "pay-to-script-hash" }, { "value": 340832, "script": "a9149a7b245b5a86f78b55e03d393ad1716b1f761dc087", "addresses": [ "3FmqW9Fgdap6HG3qiKqFSFbZWFwG4QdMP2" ], "script_type": "pay-to-script-hash" }, { "value": 517100, "script": "a9148a85d9a402749d206270f99ee2da99c87fe81eb587", "addresses": [ "3EKTX65jDKjPCFcN8c1qE7vZjsMKBUucr8" ], "script_type": "pay-to-script-hash" }, { "value": 9365930, "script": "76a914976c1c20664b3d76042b01c98c1933c85de2788788ac", "spent_by": "7f731c7ae76998c12516133e701cc2cd5f4b95638821f5ac877e398fb531d5cd", "addresses": [ "1EoeYaAZ2mKtxfMBf9AD3qkTJzcsdsLP9L" ], "script_type": "pay-to-pubkey-hash" }, { "value": 280000, "script": "a914247884269766403c87ac818f6ed5db655d86bb3f87", "spent_by": "d117fb707a3489a2e2bcdd8ddcc348d0e8c81011441be56f23d189ccb373948d", "addresses": [ "351rd4c9C8JLfAK9Ua7nHbbEXq6jPmvp8f" ], "script_type": "pay-to-script-hash" } ], "next_outputs": "https://api.blockcypher.com/v1/btc/main/txs/af3888cc260b6b6bfb8eb256fb70fd1e761a1c7baac0e19cd11b47726f2327d2?instart=0\u0026outstart=50\u0026limit=50" }




Key details:

- block_hash:
0000000000000000001f85686e50bbc4e929b50768669165731e5c73a690f680
- block_height: 551219
- block_index: 502
- hash (txid):
af3888cc260b6b6bfb8eb256fb70fd1e761a1c7baac0e19cd11b47726f2327d2
- total: 4991126340
- fees: 152990
- size: 2822
- preference: high
- relayed_by: 45.79.10.204:8333
- confirmed: 2018-11-23T18:25:35Z
- received: 2018-11-23T18:10:40.724Z


Hm. Note this section at the end:
"next_outputs": "https://api.blockcypher.com/v1/btc/main/txs/af3888cc260b6b6bfb8eb256fb70fd1e761a1c7baac0e19cd11b47726f2327d2?instart=0\u0026outstart=50\u0026limit=50"


There are 85 outputs. I will eventually need to find the previous_output_index within this transaction. I'll search for the test address in the transaction data included above. If it's there, I don't need to browse to the supplied url to get the remaining outputs.

Yes, it's there.

Copy the transaction data to a new text file. Search for the test address. Select all outputs that come after it in the outputs list and delete them. Each output is contained within pairs of curly braces ('{' and '}'). A readthrough shows me that curly braces are not included within output data. Use the "Find All" feature in my text editor (TextWrangler) to discover that there are 26 total occurrences of '{'. There are therefore 26 outputs. They are zero-indexed, so the previous_output_index of the output sent to my test address in transaction tx2 is 25.

Test address:
1vkb4YyPMFcxyC83Z5m5zuN45xASoHeNK

I'll copy the specific output data here:

{ "value": 1200000, "script": "76a9140a2a6e4834efa5c7c31eed1ebeadf94a370a1e9388ac", "addresses": [ "1vkb4YyPMFcxyC83Z5m5zuN45xASoHeNK" ], "script_type": "pay-to-pubkey-hash" },



Let's summarise:

The index of the output that I will use as an input in tx3 is:
25

The value in this unspent output is:
1200000 satoshi (0.012 bitcoin)

The txid of tx2, which contains this unspent output, is:
af3888cc260b6b6bfb8eb256fb70fd1e761a1c7baac0e19cd11b47726f2327d2


These 3 pieces of information, together with the private key of the test address (which is where this output is now stored in the blockchain), allow me to spend this bitcoin in a new transaction.








[nearly a week has passed]


The datetime of confirmation of tx2 was:
2018-11-23T18:25:35Z

Current datetime:
2018-11-30T12:42 UTC




Ok. I've successfully stored the bitcoin on the Raspberry Pi. I'll now demonstrate how to send it back to an exchange (LocalBitcoins).

I'll gather the necessary information for tx3.


My LocalBitcoins account will have a nonstandard P2SH address. I will follow this recipe again:
Recipe for creating and signing a nonstandard Bitcoin transaction



Let's look at fee rates. Browse to:
bitcoinfees.earn.com

I'll choose a fee rate of 10 satoshi / byte. Estimated delay = 0-7 blocks (0-180 minutes).
- This is the lowest fee rate that has an estimated delay starting at 0 blocks. The fee rate of 7-8 satoshi / byte has an estimated delay of 1-8 blocks (0-180 minutes).



Gathered information:

Unspent output:
- index: 25
- value: 1200000 satoshi (0.012 bitcoin)
- The txid of tx2, which contains this unspent output, is:
af3888cc260b6b6bfb8eb256fb70fd1e761a1c7baac0e19cd11b47726f2327d2

- The private key (in hex bytes) of the test address is:
c592e1dad5e9871fdeffb551b4544b0a1cf0378c6371d7a397ff5faf04c934ca
-- Note: This is stored on the Raspberry Pi in the file private_key.txt.



Chosen information:

Log into LocalBitcoins. Current receiving address is:
36p1w3YrNKd2Q3xaXbe9ASUQkeynjVLfDx
- This was the output address in tx1b.
- This will be the output address for tx3. I'll call it "lb_address2" (lb = LocalBitcoins).

- The "output amount" == The bitcoin amount (or satoshi amount) that I wish to transfer to the output address:
1200000 satoshi (0.012 bitcoin)
-- Note: This should be equal to the input amount (the code does not have the ability to send change). Any unassigned value will still be sent to the single output address (which in this recipe is the same as the change address).

- The change address.
36p1w3YrNKd2Q3xaXbe9ASUQkeynjVLfDx
-- Note: In this recipe, the change address must be the same as the single output address.

- The fee (in satoshi) or fee_rate (in satoshi / byte):
fee_rate = 10 satoshi / byte








I'll switch to the Raspberry Pi.


When I need the information gathered / chosen above, I'll copy it manually into the Raspberry Pi, reading it from Aineko's screen.



Insert the power cable into the Raspberry Pi.



Enter default credentials:


raspberrypi login: pi


Password:


Last login: Mon Mar 28 04:20:15 UTC 2016 on tty1
Linux raspberrypi 4.1.13+ #826 PREEMPT Fri Nov 13 20:13:22 GMT 2015 armv61

The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.

pi@raspberrypi ~ $



The password was "raspberry" but this was not echoed to the screen.


pi@raspberrypi ~ $ pwd

/home/pi

pi@raspberrypi ~ $ ls -1

Desktop
Documents
Downloads
indiecity
python_game
Scratch
test
w4.txt
wlog3.txt

pi@raspberrypi ~ $ cd test


pi@raspberrypi ~/test $




I'll begin logging in the new file called "w5.txt".



pi@raspberrypi ~/test $ touch w5.txt




Eventually, I'll transfer w5.txt to Aineko via memory stick.

Logged commands are run in the
~/test
directory on the Raspberry Pi.


While logging, record any annotations or comments here and integrate them into the log when the log has been transferred back from the Raspberry Pi to Aineko (where this article is being written).





[Begin logging on Raspberry Pi.]



pi@raspberrypi ~/test $ ls -1

bitcoin_functions.py
bitcoin_functions.pyc
bjorn_edstrom_ripemd160.py
bjorn_edstrom_ripemd160.pyc
convert_dice_rolls_to_hex_bytes_2.py
create_nonstandard_transaction.py
dice_rolls2.txt
dice_rolls3.txt
dice_rolls4.txt
dice_rolls.txt
display_hex_bytes.py
ecdsa
ecdsa-0.10
ecdsa-0.10.tar.gz
generate_bitcoin_address_3.py
memory_stick_contents
nonstandard_bitcoin_functions.py
nonstandard_bitcoin_functions.pyc
nonstandard_transaction.py
nonstandard_transaction.pyc
private_key.txt
pypy_sha256.py
pypy_sha256.pyc
random_value2.txt
random_value3.txt
random_value.txt
signed_transaction2.txt
signed_transaction3.txt
signed_transaction.txt
transaction.py
transaction.pyc
w4.txt
w5.txt
wlog3.txt
work.log
work_log2.txt



[first, generate 32 bytes of entropy to use as the random value for making the transaction signature]



[
I'm following the recipe Recipe for generating entropy bytes using dice
to generate 32 bytes of entropy.
32 * 8 = 256
round_up( 256 / 1.3333 * 1.1 ) = 212 dice rolls
]



pi@raspberrypi ~/test $ nano dice_rolls5.txt

[
Perform 212 dice rolls, using Nano to record the results in dice_rolls5.txt.

Time this using a stopwatch.

Time taken: 6:59
Approximately 7 minutes.
]



[Use the Nano editor to edit the controls in convert_dice_rolls_to_hex_bytes_2.py, according to the recipe.]
pi@raspberrypi ~/test $ nano convert_dice_rolls_to_hex_bytes_2.py



Hm. Note: I find that
dice_rolls_file_path
is set to be "dice_rolls3.txt", not "dice_rolls4.txt" as expected.
Perhaps, when signing tx1c, I used the entropy derived from dice_rolls3.txt, not dice_rolls4.txt.
Yup, checking the files "random_value.txt", "random_value2.txt", and "random_value3.txt" with
cat
shows me that random_value2.txt and random_value3.txt contain the same value. Ah well.



pi@raspberrypi ~/test $ python convert_dice_rolls_to_hex_bytes_2.py


### START CONVERSION OF DICE ROLLS TO HEX BYTES

- number of dice rolls: 212
- number of dice rolls in the list [1234]: 150
- number of hex characters after conversion: 75
- there is one extra hex character that can't be used to form an entire 8-bit byte.
- number of hex bytes: 37
- desired number of hex bytes: 32
- the hex bytes produced are sufficient.
- hex byte output:
f78c5ebf0efac89d60aedb38c30906ad5b22ae522a3e29819248c21d59e8397f9b315219aa
- hex byte output shortened to the desired length (32 bytes):
f78c5ebf0efac89d60aedb38c30906ad5b22ae522a3e29819248c21d59e8397f
- remaining hex bytes:
9b315219aa

Result: Desired amount of entropy (32 bytes) has been produced.
Entropy (32 bytes):
f78c5ebf0efac89d60aedb38c30906ad5b22ae522a3e29819248c21d59e8397f
Recommendation: Perhaps preserve the 5 extra hex bytes in an entropy storage file.
Extra hex bytes: 9b315219aa

### END CONVERSION OF DICE ROLLS TO HEX BYTES




[Recipe complete.]



[copy last 15 lines of w5.txt to a new file]
pi@raspberrypi ~/test $ tail -15 w5.txt > random_value4.txt



[Use Nano to remove the text around the 32 entropy hex bytes contained in the output. I will later use these 32 bytes as the random value for signing the transaction tx3.]
pi@raspberrypi ~/test $ nano random_value4.txt



pi@raspberrypi ~/test $ cat random_value4.txt

f78c5ebf0efac89d60aedb38c30906ad5b22ae522a3e29819248c21d59e8397f



[get string length of random_value4.txt hex bytes - should be 32*2 = 64. Use
tr
to remove the newline character at the end of the file.]
pi@raspberrypi ~/test $ cat random_value4.txt | tr -d '\n' | wc -c

64

[I had to use
nano
to manually add the two newline characters "\n" in this command in w5.txt. The
-e
flag with
echo
enables interpretation of backslash escapes.]



pi@raspberrypi ~/test $ ls -1

bitcoin_functions.py
bitcoin_functions.pyc
bjorn_edstrom_ripemd160.py
bjorn_edstrom_ripemd160.pyc
convert_dice_rolls_to_hex_bytes_2.py
create_nonstandard_transaction.py
dice_rolls2.txt
dice_rolls3.txt
dice_rolls4.txt
dice_rolls5.txt
dice_rolls.txt
display_hex_bytes.py
ecdsa
ecdsa-0.10
ecdsa-0.10.tar.gz
generate_bitcoin_address_3.py
memory_stick_contents
nonstandard_bitcoin_functions.py
nonstandard_bitcoin_functions.pyc
nonstandard_transaction.py
nonstandard_transaction.pyc
private_key.txt
pypy_sha256.py
pypy_sha256.pyc
random_value2.txt
random_value3.txt
random_value4.txt
random_value.txt
signed_transaction2.txt
signed_transaction3.txt
signed_transaction.txt
transaction.py
transaction.pyc
w4.txt
w5.txt
wlog3.txt
work.log
work_log2.txt



[Now, proceed with the recipe in Recipe for creating and signing a nonstandard Bitcoin transaction ]



[I'll use the existing directory "test" as the work directory.]



[ecdsa-0.10.tar.gz is already unpacked.]



[
Use the Nano editor to edit the controls in create_nonstandard_transaction.py, according to the recipe. Manually enter the gathered / chosen values, except for the variable
random_value
.
- Delete the existing value for the variable
random_value
. Then use the Nano option "Read File" to paste the contents of the file random_value4.txt into the position of the value for this variable (i.e. between the quotation marks). Then press the Backspace key to delete the final newline of the file that was also pasted in.
- The private key stays the same (tx3 is spending from the test address, the same as in tx1).
- Note: With long strings, e.g. the txid, you can make a copy on the online computer (Aineko, in this case) and split it into groups of 4 characters, then manually copy each group over to the offline Raspberry Pi, then do a double-check of the group values, and finally delete the spaces again on the offline Raspberry Pi to form the original txid.
- Double-check that the fee_rate is set to 10 (satoshi / byte).
]

pi@raspberrypi ~/test $ nano create_nonstandard_transaction.py



[Note: In create_nonstandard_transaction.py, all control values are strings (i.e. are contained within quotation marks).]



[Let's record a copy of the settings. They are on lines 41-65. I'll copy an excerpt (lines 40-66) to the log.]


pi@raspberrypi ~/test $ cat create_nonstandard_transaction.py | sed -n '40,66p'

##### START CONTROLS random_value = "f78c5ebf0efac89d60aedb38c30906ad5b22ae522a3e29819248c21d59e8397f" # 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": "af3888cc260b6b6bfb8eb256fb70fd1e761a1c7baac0e19cd11b47726f2327d2", "previous_output_index": "25", "private_key_hex": "c592e1dad5e9871fdeffb551b4544b0a1cf0378c6371d7a397ff5faf04c934ca", "satoshi_amount": "1200000", #"bitcoin_amount": "0.0020", "input_type": "p2pkh", } output_data = { "address": "36p1w3YrNKd2Q3xaXbe9ASUQkeynjVLfDx", "satoshi_amount": "1200000", #"bitcoin_amount": "0.0020", "output_type": "p2sh", } change_address = "36p1w3YrNKd2Q3xaXbe9ASUQkeynjVLfDx" # note: the fee will be subtracted from the amount that is being sent to the change address. fee = "225" # satoshi fee_rate = "10" # satoshi / byte # fee_type options: ["fee", "fee_rate"] fee_type = "fee_rate" ##### END CONTROLS




pi@raspberrypi ~/test $ python create_nonstandard_transaction.py


### START CREATION OF NONSTANDARD BITCOIN TRANSACTION

- Fee type: fee_rate
- Fee rate: 10.0 (satoshi / byte)
- Number of inputs (i.e. as-yet-unspent outputs): 1
- Number of outputs: 1
- Change address: 36p1w3YrNKd2Q3xaXbe9ASUQkeynjVLfDx
- Amount to be sent to the change address: 0.01200000
- Input addresses, with total-value-to-be-sent:
-- 1vkb4YyPMFcxyC83Z5m5zuN45xASoHeNK: 0.01200000
- Output addresses, with total-value-to-be-received:
-- 36p1w3YrNKd2Q3xaXbe9ASUQkeynjVLfDx: 0.01200000
- Total value of all inputs: 0.01200000
- Total value of all outputs: 0.01200000
- Total value of all inputs exactly matches total value of all outputs.
- Estimated transaction size: 221 bytes
- Fee rate: 10.0 (satoshi / byte)
- Calculate 221 * 10.0 and round up to nearest satoshi.
- Final fee: 2210 (satoshi)
- Final fee rate (using estimated transaction size): 10.0000 (satoshi per byte)
- Fee subtracted from amount to be sent to change address.
- New amount to be sent to change address: 1197790 (satoshi)

Input 0:
Input (without signature):
- previous_output_hash: d227236f72471bd19ce1c0aa7b1c1a761efd70fb56b28efb6b6b0b26cc8838af
- previous_output_index: 19000000
- sequence: ffffffff
- private_key_hex: c592e1dad5e9871fdeffb551b4544b0a1cf0378c6371d7a397ff5faf04c934ca
- public_key_hex: 043ab692792d6c8838fd30c2ff45bf3cbd44286a5cac52ba64dc06452810202b3206f5c7799c3b72ff77fd1976f105ced3cd7700b0412e11266f3888b88c3052c3
- script_length_scriptPubKey: 19
- scriptPubKey: 76a9140a2a6e4834efa5c7c31eed1ebeadf94a370a1e9388ac
- script_length: None
- scriptSig: None
- address: 1vkb4YyPMFcxyC83Z5m5zuN45xASoHeNK
- previous_output_index_int: 25
- txid: af3888cc260b6b6bfb8eb256fb70fd1e761a1c7baac0e19cd11b47726f2327d2

Output 0:
Output:
- value: de46120000000000
- script_length: 17
- script: a914382b8c40b25f104e9d0277ed91ddf3c849aa340387
- address: 36p1w3YrNKd2Q3xaXbe9ASUQkeynjVLfDx
- bitcoin_amount: 0.01197790
- satoshi_amount: 1197790
- redeem_script_hash_hex: 382b8c40b25f104e9d0277ed91ddf3c849aa3403

Nonstandard Transaction (unsigned form):
- version: 01000000
- input_count: 01
- Input:
-- previous_output_hash: d227236f72471bd19ce1c0aa7b1c1a761efd70fb56b28efb6b6b0b26cc8838af
-- previous_output_index: 19000000
-- script_length: None
-- scriptSig: None
-- sequence: ffffffff
- output_count: 01
- Output [P2SH]:
-- value: de46120000000000
-- script_length: 17
-- script: a914382b8c40b25f104e9d0277ed91ddf3c849aa340387
- block_lock_time: 00000000

Nonstandard Transaction (signable form):
- version: 01000000
- input_count: 01
- Input [to be used to sign this signable form]:
-- previous_output_hash: d227236f72471bd19ce1c0aa7b1c1a761efd70fb56b28efb6b6b0b26cc8838af
-- previous_output_index: 19000000
-- script_length_scriptPubKey: 19
-- scriptPubKey: 76a9140a2a6e4834efa5c7c31eed1ebeadf94a370a1e9388ac
-- sequence: ffffffff
- output_count: 01
- Output [P2SH]:
-- value: de46120000000000
-- script_length: 17
-- script: a914382b8c40b25f104e9d0277ed91ddf3c849aa340387
- block_lock_time: 00000000
- hash_type_4_byte: 01000000

Nonstandard Transaction (signed form):
- version: 01000000
- input_count: 01
- Input:
-- previous_output_hash: d227236f72471bd19ce1c0aa7b1c1a761efd70fb56b28efb6b6b0b26cc8838af
-- previous_output_index: 19000000
-- script_length: 8b
-- scriptSig: 483045022100f03c62521817e4faf31abd01782c7df2fcef8a2234400068f1a821b29fe129da02201185879e760fac3d9f2dbdc2e2af074c32c70088dd839108971c39905f5b5bbf0141043ab692792d6c8838fd30c2ff45bf3cbd44286a5cac52ba64dc06452810202b3206f5c7799c3b72ff77fd1976f105ced3cd7700b0412e11266f3888b88c3052c3
-- sequence: ffffffff
- output_count: 01
- Output [P2SH]:
-- value: de46120000000000
-- script_length: 17
-- script: a914382b8c40b25f104e9d0277ed91ddf3c849aa340387
- block_lock_time: 00000000
- hash_type_4_byte: 01000000

Signed transaction:
0100000001d227236f72471bd19ce1c0aa7b1c1a761efd70fb56b28efb6b6b0b26cc8838af190000008b483045022100f03c62521817e4faf31abd01782c7df2fcef8a2234400068f1a821b29fe129da02201185879e760fac3d9f2dbdc2e2af074c32c70088dd839108971c39905f5b5bbf0141043ab692792d6c8838fd30c2ff45bf3cbd44286a5cac52ba64dc06452810202b3206f5c7799c3b72ff77fd1976f105ced3cd7700b0412e11266f3888b88c3052c3ffffffff01de4612000000000017a914382b8c40b25f104e9d0277ed91ddf3c849aa3403870000000001000000

### END CREATION OF BITCOIN TRANSACTION



[The python create_nonstandard_transaction.py command took a few seconds to run.]


[Recipe complete.]



[Let's extract the signed transaction from the log into a separate file.]



[copy last 15 lines of w5.txt to a new file]
pi@raspberrypi ~/test $ tail -15 w5.txt > signed_transaction4.txt



[Use Nano to remove the text around the signed transaction hex string contained in the output.]
pi@raspberrypi ~/test $ nano signed_transaction4.txt



pi@raspberrypi ~/test $ cat signed_transaction4.txt

0100000001d227236f72471bd19ce1c0aa7b1c1a761efd70fb56b28efb6b6b0b26cc8838af190000008b483045022100f03c62521817e4faf31abd01782c7df2fcef8a2234400068f1a821b29fe129da02201185879e760fac3d9f2dbdc2e2af074c32c70088dd839108971c39905f5b5bbf0141043ab692792d6c8838fd30c2ff45bf3cbd44286a5cac52ba64dc06452810202b3206f5c7799c3b72ff77fd1976f105ced3cd7700b0412e11266f3888b88c3052c3ffffffff01de4612000000000017a914382b8c40b25f104e9d0277ed91ddf3c849aa3403870000000001000000



[get string length of signed_transaction4.txt hex bytes. Use
tr
to remove the newline character at the end of the file.]
pi@raspberrypi ~/test $ cat signed_transaction4.txt | tr -d '\n' | wc -c

452

[I had to use
nano
to edit w5.txt manually and insert the newline character "\n" in this command.]



[452 / 2 = 226 bytes.]



[Finally, follow the recipe in the article Displaying hex bytes for manual copying to make the signed transaction easier to read and manually copy from the offline Raspberry Pi to the online Aineko.]



[
Use the Nano editor to edit the controls in display_hex_bytes.py, according to the recipe.
- Delete the existing value for the variable
hex_bytes
. Then use the Nano option "Read File" to paste the contents of the file signed_transaction4.txt into the position of the value for this variable (i.e. between the quotation marks). Then press the Backspace key to delete the final newline of the file that was also pasted in.
]

pi@raspberrypi ~/test $ nano display_hex_bytes.py



pi@raspberrypi ~/test $ python display_hex_bytes.py

0100 0000 01d2 2723 6f72 471b d19c e1c0 aa7b 1c1a 761e fd70 fb56 b28e fb6b 6b0b 26cc 8838 af19 0000 008b 4830 4502 2100 f03c 6252 1817 e4fa f31a bd01 782c 7df2 fcef 8a22 3440 0068 f1a8 21b2 9fe1 29da 0220 1185 879e 760f ac3d 9f2d bdc2 e2af 074c 32c7 0088 dd83 9108 971c 3990 5f5b 5bbf 0141 043a b692 792d 6c88 38fd 30c2 ff45 bf3c bd44 286a 5cac 52ba 64dc 0645 2810 202b 3206 f5c7 799c 3b72 ff77 fd19 76f1 05ce d3cd 7700 b041 2e11 266f 3888 b88c 3052 c3ff ffff ff01 de46 1200 0000 0000 17a9 1438 2b8c 40b2 5f10 4e9d 0277 ed91 ddf3 c849 aa34 0387 0000 0000 0100 0000




[Recipe complete.]



[End logging on Raspberry Pi.]



Now, on Aineko, create a text file called "tx3_copied.txt" in the work directory for this project. Manually type the signed transaction data displayed on the Raspberry Pi's screen into tx3_copied.txt. Double-check the data.

Time taken: 10:04
Approximately 10 minutes.


Listening to music made this step more tolerable.


Note: Keeping the intermediate results e.g. tx3_copied.txt during the project means that if there is an error, I can go back, find it, and fix it without having to completely redo each step.




On Aineko, open a terminal and change directory to the work directory.


aineko:work stjohnpiano$ cat tx3_copied.txt | tr -d ' \n' > tx3.txt


aineko:work stjohnpiano$ echo '' >> tx3.txt


aineko:work stjohnpiano$ cat tx3.txt

0100000001d227236f72471bd19ce1c0aa7b1c1a761efd70fb56b28efb6b6b0b26cc8838af190000008b483045022100f03c62521817e4faf31abd01782c7df2fcef8a2234400068f1a821b29fe129da02201185879e760fac3d9f2dbdc2e2af074c32c70088dd839108971c39905f5b5bbf0141043ab692792d6c8838fd30c2ff45bf3cbd44286a5cac52ba64dc06452810202b3206f5c7799c3b72ff77fd1976f105ced3cd7700b0412e11266f3888b88c3052c3ffffffff01de4612000000000017a914382b8c40b25f104e9d0277ed91ddf3c849aa3403870000000001000000



[Recipe complete.]




So, the signed transaction tx3, now transferred to the online computer Aineko, is:

0100000001d227236f72471bd19ce1c0aa7b1c1a761efd70fb56b28efb6b6b0b26cc8838af190000008b483045022100f03c62521817e4faf31abd01782c7df2fcef8a2234400068f1a821b29fe129da02201185879e760fac3d9f2dbdc2e2af074c32c70088dd839108971c39905f5b5bbf0141043ab692792d6c8838fd30c2ff45bf3cbd44286a5cac52ba64dc06452810202b3206f5c7799c3b72ff77fd1976f105ced3cd7700b0412e11266f3888b88c3052c3ffffffff01de4612000000000017a914382b8c40b25f104e9d0277ed91ddf3c849aa3403870000000001000000







Let's check the byte length of tx3 using Python.

aineko:work stjohnpiano$ python

Python 2.7.13 (default, Dec 18 2016, 05:35:59)
[GCC 4.2.1 (Apple Inc. build 5666) (dot 3)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> x = ""
>>> len(x) / 2.0
>>> 226.0

>>>



226 bytes.






Next: Retrieve w5.txt from the Raspberry Pi and copy it into this article at the appropriate earlier point. Merge various annotations / comments made here into this log.





Insert the memory stick into the Raspberry Pi.




[mount the memory stick]
pi@raspberrypi ~/test $ sudo mount -o uid=pi,gid=pi /dev/sda1 /mnt/memory_stick_mount_point


[copy w5.txt to the memory stick]
pi@raspberrypi ~/test $ cp w5.txt /mnt/memory_stick_mount_point


[confirm that the file has been copied over]
pi@raspberrypi ~/test $ ls -1 /mnt/memory_stick_mount_point

$RECYCLE.BIN
Recycled
System Volume Information
w4.txt
w5.txt
wlog3.txt
work
work.log
work_log2.txt

[unmount the memory stick]
pi@raspberrypi ~/test $ sudo umount /mnt/memory_stick_mount_point


[confirm that it has been unmounted]
pi@raspberrypi ~/test $ ls -1 /mnt/memory_stick_mount_point




Unplug the memory stick from the Raspberry Pi.


Insert the memory stick into Aineko. It mounts automatically and an icon appears on the Desktop. Copy the file w5.txt to the work directory for this project on Aineko.

On Aineko, right-click memory stick's Desktop icon and choose Eject "NO NAME". Unplug the memory stick from Aineko.


Integrate the contents of the file w5.txt into the marked section earlier in this article.


Done.




Shut down the Raspberry Pi for now.

On the Raspberry Pi:

pi@raspberrypi ~/test $ sudo halt

[a variety of output is printed, then the Raspberry Pi shuts down]


Unplug the power cable from the Raspberry Pi.






Switch to Aineko.


Let's see if a blockchain information service can decode this transaction.


Browse to:
live.blockcypher.com/btc/decodetx

Paste the signed transaction into the text box named "Transaction Hex". Network is set to "Bitcoin".

Click "Decode Transaction".

Result:

{ "addresses": [ "1vkb4YyPMFcxyC83Z5m5zuN45xASoHeNK", "36p1w3YrNKd2Q3xaXbe9ASUQkeynjVLfDx" ], "block_height": -1, "block_index": -1, "confirmations": 0, "double_spend": false, "fees": 2210, "hash": "00f630f5152f4fce9831933fcd4eb878428308755f9f8e31a3135de6a4754093", "inputs": [ { "addresses": [ "1vkb4YyPMFcxyC83Z5m5zuN45xASoHeNK" ], "age": 551219, "output_index": 25, "output_value": 1200000, "prev_hash": "af3888cc260b6b6bfb8eb256fb70fd1e761a1c7baac0e19cd11b47726f2327d2", "script": "483045022100f03c62521817e4faf31abd01782c7df2fcef8a2234400068f1a821b29fe129da02201185879e760fac3d9f2dbdc2e2af074c32c70088dd839108971c39905f5b5bbf0141043ab692792d6c8838fd30c2ff45bf3cbd44286a5cac52ba64dc06452810202b3206f5c7799c3b72ff77fd1976f105ced3cd7700b0412e11266f3888b88c3052c3", "script_type": "pay-to-pubkey-hash", "sequence": 4294967295 } ], "outputs": [ { "addresses": [ "36p1w3YrNKd2Q3xaXbe9ASUQkeynjVLfDx" ], "script": "a914382b8c40b25f104e9d0277ed91ddf3c849aa340387", "script_type": "pay-to-script-hash", "value": 1197790 } ], "preference": "low", "received": "2018-11-30T18:53:12.967335417Z", "relayed_by": "54.166.113.205", "size": 222, "total": 1197790, "ver": 1, "vin_sz": 1, "vout_sz": 1 }




Looks good. No immediate error reported.


Some details:
- size: 222
- fee: 2210
- preference: low
- hash (txid):
00f630f5152f4fce9831933fcd4eb878428308755f9f8e31a3135de6a4754093






Let's broadcast the signed transaction tx3.


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/00f630f5152f4fce9831933fcd4eb878428308755f9f8e31a3135de6a4754093
Details:
- Transaction Successfully Broadcst
- AMOUNT TRANSACTED: 0.0119779 BTC
- FEES: 0.0000221 BTC
- Confirmations: 0/6
- Miner Preference: LOW
- Size: 222 bytes
- Version: 1
- Relayed By: 54.166.113.205



Current datetime: 2018-11-30 19:10



Set timer for 2 hours.


Timer has finished.



[some additional time passes]



Current datetime: 2018-11-30 21:47



Refresh transaction page.
Confirmations: 0/6



I'll wait until tomorrow to check again.





Current datetime:
2018-12-01 10:56


Refresh transaction page:
live.blockcypher.com/btc/tx/00f630f5152f4fce9831933fcd4eb878428308755f9f8e31a3135de6a4754093

Confirmations: 6+




Excellent. Transaction tx3 has been mined.


Click Advanced Details.

- Block Hash:
0000000000000000000ab9373f3ce1c96528c09ffa13fe2005a4d32470b7c98b
- Block Height: 552,081
- Transaction Index: 1,941


Click API Call.

Result: tx3

{ "block_hash": "0000000000000000000ab9373f3ce1c96528c09ffa13fe2005a4d32470b7c98b", "block_height": 552081, "block_index": 1941, "hash": "00f630f5152f4fce9831933fcd4eb878428308755f9f8e31a3135de6a4754093", "hex": "0100000001d227236f72471bd19ce1c0aa7b1c1a761efd70fb56b28efb6b6b0b26cc8838af190000008b483045022100f03c62521817e4faf31abd01782c7df2fcef8a2234400068f1a821b29fe129da02201185879e760fac3d9f2dbdc2e2af074c32c70088dd839108971c39905f5b5bbf0141043ab692792d6c8838fd30c2ff45bf3cbd44286a5cac52ba64dc06452810202b3206f5c7799c3b72ff77fd1976f105ced3cd7700b0412e11266f3888b88c3052c3ffffffff01de4612000000000017a914382b8c40b25f104e9d0277ed91ddf3c849aa34038700000000", "addresses": [ "1vkb4YyPMFcxyC83Z5m5zuN45xASoHeNK", "36p1w3YrNKd2Q3xaXbe9ASUQkeynjVLfDx" ], "total": 1197790, "fees": 2210, "size": 222, "preference": "low", "relayed_by": "54.166.113.205", "confirmed": "2018-11-30T23:27:35Z", "received": "2018-11-30T18:55:34.661Z", "ver": 1, "double_spend": false, "vin_sz": 1, "vout_sz": 1, "confirmations": 60, "confidence": 1, "inputs": [ { "prev_hash": "af3888cc260b6b6bfb8eb256fb70fd1e761a1c7baac0e19cd11b47726f2327d2", "output_index": 25, "script": "483045022100f03c62521817e4faf31abd01782c7df2fcef8a2234400068f1a821b29fe129da02201185879e760fac3d9f2dbdc2e2af074c32c70088dd839108971c39905f5b5bbf0141043ab692792d6c8838fd30c2ff45bf3cbd44286a5cac52ba64dc06452810202b3206f5c7799c3b72ff77fd1976f105ced3cd7700b0412e11266f3888b88c3052c3", "output_value": 1200000, "sequence": 4294967295, "addresses": [ "1vkb4YyPMFcxyC83Z5m5zuN45xASoHeNK" ], "script_type": "pay-to-pubkey-hash", "age": 551219 } ], "outputs": [ { "value": 1197790, "script": "a914382b8c40b25f104e9d0277ed91ddf3c849aa340387", "spent_by": "c04e603ac81372592857fefbf1ffe8b689c0d723fd007f43fb9862d171864565", "addresses": [ "36p1w3YrNKd2Q3xaXbe9ASUQkeynjVLfDx" ], "script_type": "pay-to-script-hash" } ] }




Key details:
- block_hash:
0000000000000000000ab9373f3ce1c96528c09ffa13fe2005a4d32470b7c98b
- block_height: 552081
- confirmed: 2018-11-30T23:27:35Z
- received: 2018-11-30T18:55:34.661Z
- hash (txid):
00f630f5152f4fce9831933fcd4eb878428308755f9f8e31a3135de6a4754093




Using the times from blockcypher.com:
- Broadcast time: 2018-11-30 18:55
- Confirmation time: 2018-11-30 23:27

Time taken ~= 4.5 hours




Log on to LocalBitcoins.
Go to Wallet / Transactions.
- Latest received transaction:
-- Datetime: 11/30/2018 23:57
-- Received BTC: 0.0118279
-- Description: Deposit to 36p1w3......
-- Deposit Fee BTC: 0.00015000



I have successfully transferred the relatively larger amount of stored bitcoin from the Raspberry Pi to the LocalBitcoins exchange.



Excellent.



That's the end of the project.



Now, begin writing up the analysis. There may be some clean-up / archival work, which I may document here.




I'll preserve the dice rolling results as assets of this article.

Boot up the Raspberry Pi and transfer the files:
- dice_rolls.txt
- dice_rolls2.txt
- dice_rolls3.txt
- dice_rolls4.txt
- dice_rolls5.txt
to Aineko via memory stick.



I've written recipes:
- Recipe For Managing The Fee And Broadcast Of A Bitcoin Transaction
- Recipe For Manually Mounting A USB Memory Stick

Now test them.

Boot up the Raspberry Pi.

In the home directory ("/home/pi"), make a new directory "test2".

Copy the entropy byte files from the "test" directory to the "test2" directory. These are:
- private_key.txt
- random_value2.txt
- random_value3.txt
- random_value4.txt
- random_value.txt

Note that random_value2.txt and random_value3.txt contain the same value. The value in random_value3.txt should have been derived from dice_rolls4.txt, but was accidentally derived from dice_rolls3.txt instead.

random_value.txt was used to sign tx1a.
random_value2.txt was used to sign tx1b.
random_value3.txt was used to sign tx1c.
random_value4.txt was used to sign tx3.

Copy the signed transaction files to the test2 directory as well.



Delete the "test" directory, which contains almost everything on the Raspberry Pi that I used during this project. I used the command
rm -r test
to do this.

In the home directory, also delete:
- w4.txt
- w5.txt
- wlog3.txt
These were temporary backup files.


Change directory to the test2 directory.

Rename:
- signed_transaction.txt to tx1a_original.txt
- signed_transaction2.txt to tx1b_original.txt
- signed_transaction3.txt to tx1c_original.txt
- signed_transaction4.txt to tx3_original.txt


Delete the directory
/mnt/memory_stick_mount_point
. It was created with root permissions, so root permissions are required to delete it. Use the command
sudo rmdir /mnt/memory_stick_mount_point
.



First, I will test:
Recipe For Manually Mounting A USB Memory Stick
because I'll also use it to transfer the code assets to the Raspberry Pi, in preparation for testing the other recipe.


Insert the memory stick into Aineko. It mounts automatically and an icon appears on the Desktop. Delete everything on it.

Make a new directory named "code_assets" on the memory stick. From the work directory in the project directory on Aineko, copy the code assets into the code_assets directory.

On Aineko, right-click memory stick's Desktop icon and choose Eject "NO NAME". Unplug the memory stick from Aineko.

Follow the recipe as closely as possible. Make a new directory named "memory_stick_contents" in the test2 directory on the Raspberry Pi. Copy the contents of the code_assets directory on the memory stick to the memory_stick_contents directory on the Raspberry Pi.

Note: This time, there's no "work.log" file to copy to the memory stick. Test this recipe section by copying private_key.txt to the memory stick, and then delete it from the memory stick.

Recipe completed. Works fine.



Next, I will test:
Recipe For Managing The Fee And Broadcast Of A Bitcoin Transaction

I won't test it completely. At the appropriate points, I'll assume that the events (e.g. transaction confirmation) occur as they did during the project.

Copy the files in the memory_stick_contents directory to the parent test2 directory. The command I used was:
cp memory_stick_contents/* .


Unpack the zipped tape archive file ecdsa-0.10.tar.gz, then copy the "ecdsa" directory into the test2 directory.


At this point, I assume that I have gathered the required data for a new transaction (step 1), and that I have looked at current Bitcoin network transaction fee rates and chosen a fee rate for the transaction (step 2). Actually, I'm re-using the values used for tx1a. The fee rate is 1 satoshi / byte.


Edit create_nonstandard_transaction.py using the Nano text editor so that its settings section (lines 40-66) are the settings originally used to create tx1a. Manually enter the gathered / chosen values (reading them from the main project log (this text file) displayed on Aineko's screen), except for the variables
random_value
and
input_data["private_key_hex"]
.
- Delete the existing value for the variable
random_value
. Then use the Nano option "Read File" to paste the contents of the file random_value.txt into the position of the value for this variable (i.e. between the quotation marks). Then press the Backspace key to delete the final newline of the file that was also pasted in.
- The variable
input_data
is a dictionary that contains several other variables. Delete the existing value for the variable
input_data["private_key_hex"]
. Then use the Nano option "Read File" to paste the contents of the file private_key.txt into the position of the value for this variable (i.e. between the quotation marks). Then press the Backspace key to delete the final newline of the file that was also pasted in.
- Note: With long strings, e.g. the txid, you can make a copy on the online computer (Aineko, in this case) and split it into groups of 4 characters, then manually copy each group over to the offline Raspberry Pi, then do a double-check of the group values, and finally delete the spaces again to form the original txid.


tx1a settings:

##### START CONTROLS random_value = "91fbb8a38082b09e6ed984fda95866dfab95dc66b0cb6b5133dd87d07315364e" # 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": "07cedb340f588dec2fb14472178a92d5803c70d8d90fc0d8593b03f34035e2cd", "previous_output_index": "15", "private_key_hex": "c592e1dad5e9871fdeffb551b4544b0a1cf0378c6371d7a397ff5faf04c934ca", #"satoshi_amount": "241777", "bitcoin_amount": "0.0020", "input_type": "p2pkh", } output_data = { "address": "369Dpo9CrJASneaHLdwWfKym7N84XTUyvH", #"satoshi_amount": "241000", "bitcoin_amount": "0.0020", "output_type": "p2sh", } change_address = "369Dpo9CrJASneaHLdwWfKym7N84XTUyvH" # note: the fee will be subtracted from the amount that is being sent to the change address. fee = "225" # satoshi fee_rate = "1" # satoshi / byte # fee_type options: ["fee", "fee_rate"] fee_type = "fee_rate" ##### END CONTROLS




I used this command to direct the output of the transaction creation into a file:
python create_nonstandard_transaction.py > tx1a.txt


Then I used the Nano text editor to delete most of the contents of tx1a, leaving only the final signed form of the transaction.

This completes step 3 of the recipe.


The command
diff tx1a.txt tx1a_original.txt
produced no output, confirming that the two files are identical.


At this point, I assume that I have broadcast transaction tx1a (step 4), that 2 days have passed, that it has not been mined, and that it has now been removed from the memory pool of the node run by the broadcast service (step 5).

I also assume that I have looked at current Bitcoin network transaction fee rates and chosen a new and higher fee rate for the transaction (step 6). Actually, I'm re-using the values used for tx1c. The fee rate is 66 satoshi / byte.

Note: I'm not re-constructing tx1b, as it was a double-spend attempt (it tried to spend the same unspent output as tx1a did, but to a different address, while tx1a was still in the memory pool), and it is not relevant to testing this recipe.




Edit create_nonstandard_transaction.py using the Nano text editor so that its settings section (lines 40-66) are the settings originally used to create tx1c. Manually enter the gathered / chosen values (reading them from the main project log (this text file) displayed on Aineko's screen), except for the variable
random_value
.
- Delete the existing value for the variable
random_value
. Then use the Nano option "Read File" to paste the contents of the file random_value3.txt (used to sign the original tx1c) into the position of the value for this variable (i.e. between the quotation marks). Then press the Backspace key to delete the final newline of the file that was also pasted in.
- The details of the input that I am trying to spend do not need to be changed. This refers to every subvariable contained in the dictionary variable
input_data
.
- The output address and the change address do not need to be changed. I am trying to send the available bitcoin to the same output address.
- I only need to change the fee_rate and the random_value.



tx1c settings:

##### START CONTROLS random_value = "644dc86dd0cb4518d9d7f68db2d6e9455e34ceeb32c897df2616418c4c9bb040" # 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": "07cedb340f588dec2fb14472178a92d5803c70d8d90fc0d8593b03f34035e2cd", "previous_output_index": "15", "private_key_hex": "c592e1dad5e9871fdeffb551b4544b0a1cf0378c6371d7a397ff5faf04c934ca", #"satoshi_amount": "241777", "bitcoin_amount": "0.0020", "input_type": "p2pkh", } output_data = { "address": "369Dpo9CrJASneaHLdwWfKym7N84XTUyvH", #"satoshi_amount": "241000", "bitcoin_amount": "0.0020", "output_type": "p2sh", } change_address = "369Dpo9CrJASneaHLdwWfKym7N84XTUyvH" # note: the fee will be subtracted from the amount that is being sent to the change address. fee = "225" # satoshi fee_rate = "66" # satoshi / byte # fee_type options: ["fee", "fee_rate"] fee_type = "fee_rate" ##### END CONTROLS





I used this command to direct the output of the transaction creation into a file:
python create_nonstandard_transaction.py > tx1c.txt


Then I used the Nano text editor to delete most of the contents of tx1c, leaving only the final signed form of the transaction.

This completes another iteration of steps 2-3 of the recipe.


The command
diff tx1c.txt tx1c_original.txt
produced no output, confirming that the two files are identical.


At this point, I assume that I have broadcast transaction tx1c, that it has been mined within 5 hours, and that it is now 6 blocks deep in the Bitcoin blockchain, i.e. the same events have happened as those that occurred during this project, and I have had a successful result.


Ok. I'll count that as a successful test of the recipe.


Shut down the Raspberry Pi.


I've finished writing the analysis (various sections, notes, summary). Boot up the Raspberry Pi, delete the test2 directory, and shut it down again. Insert the memory stick into Aineko and delete the work directory on it.















[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]