Mastering Bitcoin Exercises
by Mikong Galero
Welcome to the Mastering Bitcoin Exercises workbook! This book provides supplementary exercises to the book Mastering Bitcoin 2nd Edition by Andreas M. Antonopoulos.
How This Book is Organized
The exercises in this book are simply grouped by the chapters of the Mastering Bitcoin 2nd Edition.
License
"Mastering Bitcoin - Second Edition" by Andreas M. Antonopoulos LLC is licensed under CC BY-SA 4.0.
"Mastering Bitcoin Exercises" is therefore also licensed under a Creative Commons Attribution-ShareAlike 4.0 International License.
Source
The source files from which this book is generated can be found on GitHub.
1. Introduction
1.1 Digital signature with OpenSSL
Use the openssl
command-line tool to create an RSA key pair and to sign and
verify a text file.
- Prepare an arbitrary text file to be signed.
- Generate an RSA private key with key length of 2048 bits.
- Extract the public key from the private key.
- Sign the text file using SHA256 and your private key, and output a signature file.
- Verify the signature of the text file using the public key.
1.2 A simple QR code
Use a QR code generator to generate a QR code that simply contains the text "hi". Identify the different parts of the QR code such as the positioning markings, the format information, the timing pattern, and so on. If you can, find where the "h" and "i" is located in the grid of black and white.
2. How Bitcoin Works
2.1 Payment request QR code
Construct a QR code for a payment request with the following details:
- Bitcoin address: "mrCDrCybB6J1vRfbwM5hemdJz73FwDBC8r"
- Amount: "0.00001"
- Label: "Blips and Chitz"
- Message: "Purchase tokens at Blips and Chitz"
Scan the QR code with a QR code reader to verify its contents.
Reading: BIP-21 is a short proposal that describes the URI scheme used in payment request QR codes.
2.2 Cryptographic hash puzzle
Repeatedly compute the SHA256 hash of the following simplified header (in JSON), incrementing the nonce in every iteration, until the resulting hash starts with three consecutive zeros.
{
"height": 0,
"version": 1,
"merkleroot": "4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b",
"nonce" : 0
}
3. Bitcoin Core: The Reference Implementation
Chapter 3 of the book Mastering Bitcoin 2nd Edition is a highly technical chapter for setting up a development environment. It walks you through compiling Bitcoin Core and configuring/running your own node. If you follow the steps and explore the help documentation as described in the chapter, there's more than enough exercises to work on.
The last section of that chapter is Alternative Clients, Libraries and Toolkits. It lists some libraries, clients and toolkits grouped by programming language. We can work on exercises that use any of these to expand on this chapter. With your programming language of choice, select the software in the list that you would like to explore and see if you can do any of the exercises below.
3.1 Decode a raw transaction
Using a client library, decode Alice's coffee transaction with the following transaction ID:
0627052b6f28912f2703066a912ea577f2ce4da4caa5a5fbd8a57286c345c2f2
Depending on the library, you may have to initially obtain a serialized transaction that you will then have to decode, or you may directly get a human-readable format of the transaction.
Check that you can see the same transaction inputs and outputs as in the book.
3.2 Find Alice's transaction in the block
In the book, we saw that Alice's transaction was included in block 277316. Using a client library, obtain this block and find Alice's transaction in the list of transactions that the block contains.
3.3 Execute getmempoolinfo
The book mentioned getmempoolinfo
as one of the more important RPC commands.
Using the Bitcoin Core client or an alternative client library with a similar
command, execute this command and get the details of the memory pool such as the
minimum fee rate for a transaction to be accepted.
4. Keys, Addresses
4.1 Generate a private key
Your program should use a cryptographically secure pseudorandom number generator (CSPRNG) to generate random bits with sufficient entropy (at least 256 bits) and compute its SHA256 hash. Repeat this process in a loop until the value is less than the prime p as defined in the secp256k1 standard:
p = FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFE FFFFFC2F
= 2256 - 232 - 29 - 28 - 27 - 26 - 24 - 1
Some programming languages may require a bignum library for dealing with very large numbers.
Reading: You may need to read more about entropy to make sure that your random number has sufficient entropy. Different operating systems have different sources of entropy.
4.2 Confirm point is on the elliptic curve
In the Elliptic Curve Cryptography Explained section of the book, the following example point P with coordinates (x, y) on the secp256k1 curve is given:
P = (55066263022277343669578718895168534326250603453777594175500187360389116729240, 32670510020758816978083085130507043184471273380659243275938904335757337482424)
The book then provides a sample Python code to confirm that the point is on the elliptic curve:
p = 115792089237316195423570985008687907853269984665640564039457584007908834671663
x = 55066263022277343669578718895168534326250603453777594175500187360389116729240
y = 32670510020758816978083085130507043184471273380659243275938904335757337482424
(x ** 3 + 7 - y**2) % p
If you're using a different programming language, write a similar program to do the same. Make sure that your program can handle very large signed integers. The secp256k1 curve is defined by the following function that you should use in your program:
y2 mod p = (x3 + 7) mod p
4.3 Generate a public key with OpenSSL
Use the OpenSSL cryptographic library's EC_POINT_mul()
to generate a public
key. You can use the private key that you have generated in exercise 4.1 or
alternatively, use the example private key from the book:
1E99423A4ED27608A15A2616A2B0E9E52CED330AC530EDCC32C8FFC6A526AEDD
Use the library's elliptic curve point multiplication to multiply the private key with the generator point G in order to produce the public key K.
K = k * G
Remember that Bitcoin uses a specific elliptic curve and set of constants defined in a standard called secp256k1. From the Standards for Efficient Cryptography (SEC), the base point G in compressed form is:
G = 02 79BE667E F9DCBBAC 55A06295 CE870B07 029BFCDB 2DCE28D9 59F2815B 16F81798
and in uncompressed form is:
G = 04 79BE667E F9DCBBAC 55A06295 CE870B07 029BFCDB 2DCE28D9 59F2815B 16F81798
483ADA77 26A3C465 5DA4FBFC 0E1108A8 FD17B448 A6855419 9C47D08F FB10D4B8
4.4 Convert a public key into a bitcoin address
Using the public key generated from the previous exercise, compute its SHA256 hash and then compute the RIPEMD160 hash of the result to produce a 160-bit bitcoin address.
A = RIPEMD160(SHA256(K))
This double-hash function is called HASH160.
5. Wallets
5.1 Generate mnemonic words
Write a program to generate and print mnemonic words from a given random sequence of bits.
- Create a random sequence (entropy) of 128/160/192/224/256 bits.
- Compute the SHA256 hash of the random sequence. Take the first (entropy-length/32) bits of its hash as the checksum.
- Concatenate the random sequence and the checksum.
- Divide the result into sections of 11 bits.
- Map each 11-bit value to a word from the predefined dictionary of 2048 words.
- Print the mnemonic words in the correct order.
Table 5-1: Checksum bits and number of mnemonic words depend on length of entropy.
Entropy (bits) | Checksum (bits) | Mnemonic length (words) |
---|---|---|
128 | 4 | 12 |
160 | 5 | 15 |
192 | 6 | 18 |
224 | 7 | 21 |
256 | 8 | 24 |
Get the dictionary/wordlist from BIP-39. There's a section that describes the characteristics of an ideal wordlist, and a separate section that links to the actual wordlists.
5.2 PBKDF2
Password-Based Key Derivation Function 2 (PBKDF2) is a key derivation function to make brute force attacks more difficult with key stretching.
DK = PBKDF2(PRF, Password, Salt, c, dkLen)
Given the following parameters, use a PBKDF2 library to derive a key:
c
(number of rounds): 4096PRF
(pseudorandom function): HMAC-SHA256dkLen
(derived key length): 256
The PBKDF2 key derivation function takes two more parameters: a password, and a salt. For this exercise, you can choose arbitrary values for these two.