mirror of
https://github.com/bitcoinbook/bitcoinbook
synced 2024-11-01 13:10:04 +00:00
63 lines
2.3 KiB
C++
63 lines
2.3 KiB
C++
#include <bitcoin/bitcoin.hpp>
|
|
|
|
bc::hash_digest create_merkle(bc::hash_digest_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_digest_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::make_serializer(concat_data.begin());
|
|
concat.write_hash(*it);
|
|
concat.write_hash(*(it + 1));
|
|
assert(concat.iterator() == concat_data.end());
|
|
// 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_hex(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_digest_list tx_hashes{{
|
|
bc::decode_hash("0000000000000000000000000000000000000000000000000000000000000000"),
|
|
bc::decode_hash("0000000000000000000000000000000000000000000000000000000000000011"),
|
|
bc::decode_hash("0000000000000000000000000000000000000000000000000000000000000022"),
|
|
}};
|
|
const bc::hash_digest merkle_root = create_merkle(tx_hashes);
|
|
std::cout << "Result: " << bc::encode_hex(merkle_root) << std::endl;
|
|
return 0;
|
|
}
|
|
|