diff --git a/ch09.asciidoc b/ch09.asciidoc index 3b1c95e4..bebe80c0 100644 --- a/ch09.asciidoc +++ b/ch09.asciidoc @@ -437,44 +437,6 @@ diagram). .A merkle path used to prove inclusion of a data element image::images/mbc2_0905.png["merkle_tree_path"] -The code in <> demonstrates the process of creating a -merkle tree from the leaf-node hashes up to the root, using the -libbitcoin library for some helper functions. - -[[merkle_example]] -[role="pagebreak-before"] -.Building a merkle tree -==== -[source, cpp] ----- -include::code/merkle.cpp[] ----- -==== - -<> shows the result of compiling and running the -merkle code. - -[[merkle_example_run]] -.Compiling and running the merkle example code -==== -[source,bash] ----- -$ # Compile the merkle.cpp code -$ g++ -o merkle merkle.cpp $(pkg-config --cflags --libs libbitcoin) -$ # Run the merkle executable -$ ./merkle -Current merkle hash list: - 32650049a0418e4380db0af81788635d8b65424d397170b8499cdc28c4d27006 - 30861db96905c8dc8b99398ca1cd5bd5b84ac3264a4e1b3e65afa1bcee7540c4 - -Current merkle hash list: - d47780c084bad3830bcdaf6eace035e4c6cbf646d103795d22104fb105014ba3 - -Result: d47780c084bad3830bcdaf6eace035e4c6cbf646d103795d22104fb105014ba3 - ----- -==== - The efficiency of merkle trees becomes obvious as the scale increases. <> shows the amount of data that needs to be exchanged as a merkle path to prove that a transaction is part of a block. diff --git a/ch10.asciidoc b/ch10.asciidoc index 6cbf54b5..42bb8fee 100644 --- a/ch10.asciidoc +++ b/ch10.asciidoc @@ -722,62 +722,6 @@ This every part of the phrase. Adding a single letter, punctuation mark, or any other character will produce a different hash. -Now, if we change the phrase, we should expect to see completely -different hashes. Let's try that by adding a number to the end of our -phrase, using the simple Python scripting in -<>. - -[[sha256_example_generator]] -.SHA256 script for generating many hashes by iterating on a nonce -==== -[role="c_less_space"] -[source, python] ----- -include::code/hash_example.py[] ----- -==== - -Running this will produce the hashes of several phrases, made different -by adding a number at the end of the text. By incrementing the number, -we can get different hashes, as shown in -<>. - -[[sha256_example_generator_output]] -.SHA256 output of a script for generating many hashes by iterating on a nonce -==== -[source,bash] ----- -$ python hash_example.py ----- - ----- -I am Satoshi Nakamoto0 => a80a81401765c8eddee25df36728d732... -I am Satoshi Nakamoto1 => f7bc9a6304a4647bb41241a677b5345f... -I am Satoshi Nakamoto2 => ea758a8134b115298a1583ffb80ae629... -I am Satoshi Nakamoto3 => bfa9779618ff072c903d773de30c99bd... -I am Satoshi Nakamoto4 => bce8564de9a83c18c31944a66bde992f... -I am Satoshi Nakamoto5 => eb362c3cf3479be0a97a20163589038e... -I am Satoshi Nakamoto6 => 4a2fd48e3be420d0d28e202360cfbaba... -I am Satoshi Nakamoto7 => 790b5a1349a5f2b909bf74d0d166b17a... -I am Satoshi Nakamoto8 => 702c45e5b15aa54b625d68dd947f1597... -I am Satoshi Nakamoto9 => 7007cf7dd40f5e933cd89fff5b791ff0... -I am Satoshi Nakamoto10 => c2f38c81992f4614206a21537bd634a... -I am Satoshi Nakamoto11 => 7045da6ed8a914690f087690e1e8d66... -I am Satoshi Nakamoto12 => 60f01db30c1a0d4cbce2b4b22e88b9b... -I am Satoshi Nakamoto13 => 0ebc56d59a34f5082aaef3d66b37a66... -I am Satoshi Nakamoto14 => 27ead1ca85da66981fd9da01a8c6816... -I am Satoshi Nakamoto15 => 394809fb809c5f83ce97ab554a2812c... -I am Satoshi Nakamoto16 => 8fa4992219df33f50834465d3047429... -I am Satoshi Nakamoto17 => dca9b8b4f8d8e1521fa4eaa46f4f0cd... -I am Satoshi Nakamoto18 => 9989a401b2a3a318b01e9ca9a22b0f3... -I am Satoshi Nakamoto19 => cda56022ecb5b67b2bc93a2d764e75f... ----- -==== - -Each phrase produces a completely different hash result. They seem -completely random, but you can reproduce the exact results in this -example on any computer with Python and see the same exact hashes. - The number used as a variable in such a scenario is called a _nonce_. The nonce is used to vary the output of a cryptographic function, in this case to vary the SHA256 fingerprint of the phrase. diff --git a/code/hash_example.py b/code/hash_example.py deleted file mode 100644 index d5e69b2b..00000000 --- a/code/hash_example.py +++ /dev/null @@ -1,18 +0,0 @@ -# example of iterating a nonce in a hashing algorithm's input - -from __future__ import print_function -import hashlib - -text = "I am Satoshi Nakamoto" - -# iterate nonce from 0 to 19 -for nonce in range(20): - - # add the nonce to the end of the text - input_data = text + str(nonce) - - # calculate the SHA-256 hash of the input (text+nonce) - hash_data = hashlib.sha256(input_data).hexdigest() - - # show the input and hash result - print(input_data, '=>', hash_data) diff --git a/code/merkle.cpp b/code/merkle.cpp deleted file mode 100644 index 6b20059a..00000000 --- a/code/merkle.cpp +++ /dev/null @@ -1,62 +0,0 @@ -#include - -bc::hash_digest create_merkle(bc::hash_list& merkle) -{ - // Stop if hash list is empty. - if (merkle.empty()) - return bc::null_hash; - else if (merkle.size() == 1) - return merkle[0]; - - // While there is more than 1 hash in the list, keep looping... - while (merkle.size() > 1) - { - // If number of hashes is odd, duplicate last hash in the list. - if (merkle.size() % 2 != 0) - merkle.push_back(merkle.back()); - // List size is now even. - assert(merkle.size() % 2 == 0); - - // New hash list. - bc::hash_list new_merkle; - // Loop through hashes 2 at a time. - for (auto it = merkle.begin(); it != merkle.end(); it += 2) - { - // Join both current hashes together (concatenate). - bc::data_chunk concat_data(bc::hash_size * 2); - auto concat = bc::serializer< - decltype(concat_data.begin())>(concat_data.begin()); - concat.write_hash(*it); - concat.write_hash(*(it + 1)); - // Hash both of the hashes. - bc::hash_digest new_root = bc::bitcoin_hash(concat_data); - // Add this to the new list. - new_merkle.push_back(new_root); - } - // This is the new list. - merkle = new_merkle; - - // DEBUG output ------------------------------------- - std::cout << "Current merkle hash list:" << std::endl; - for (const auto& hash: merkle) - std::cout << " " << bc::encode_base16(hash) << std::endl; - std::cout << std::endl; - // -------------------------------------------------- - } - // Finally we end up with a single item. - return merkle[0]; -} - -int main() -{ - // Replace these hashes with ones from a block to reproduce the same merkle root. - bc::hash_list tx_hashes{{ - bc::hash_literal("0000000000000000000000000000000000000000000000000000000000000000"), - bc::hash_literal("0000000000000000000000000000000000000000000000000000000000000011"), - bc::hash_literal("0000000000000000000000000000000000000000000000000000000000000022"), - }}; - const bc::hash_digest merkle_root = create_merkle(tx_hashes); - std::cout << "Result: " << bc::encode_base16(merkle_root) << std::endl; - return 0; -} -