mirror of
https://github.com/bitcoinbook/bitcoinbook
synced 2024-11-21 23:58:09 +00:00
CH11-12: remove long & not-very-useful example code
Suggested by Jorge Lesmes
This commit is contained in:
parent
825d52823c
commit
e0932e89f7
@ -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 <<merkle_example>> 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[]
|
||||
----
|
||||
====
|
||||
|
||||
<<merkle_example_run>> 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.
|
||||
<<block_structure2>> shows the amount of data that needs to be exchanged
|
||||
as a merkle path to prove that a transaction is part of a block.
|
||||
|
@ -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_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_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.
|
||||
|
@ -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)
|
@ -1,62 +0,0 @@
|
||||
#include <bitcoin/bitcoin.hpp>
|
||||
|
||||
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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user