2014-09-28 15:52:50 +00:00
|
|
|
#include <bitcoin/bitcoin.hpp>
|
|
|
|
|
2015-01-18 20:19:57 +00:00
|
|
|
bc::hash_digest create_merkle(bc::hash_list& merkle)
|
2014-09-28 15:52:50 +00:00
|
|
|
{
|
|
|
|
// 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.
|
2015-01-18 20:19:57 +00:00
|
|
|
bc::hash_list new_merkle;
|
2014-09-28 15:52:50 +00:00
|
|
|
// 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);
|
2017-07-18 04:07:31 +00:00
|
|
|
auto concat = bc::serializer<
|
|
|
|
decltype(concat_data.begin())>(concat_data.begin());
|
2014-09-28 15:52:50 +00:00
|
|
|
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)
|
2017-07-18 04:07:31 +00:00
|
|
|
std::cout << " " << bc::encode_base16(hash) << std::endl;
|
2014-09-28 15:52:50 +00:00
|
|
|
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.
|
2015-01-18 20:19:57 +00:00
|
|
|
bc::hash_list tx_hashes{{
|
2015-01-21 21:29:43 +00:00
|
|
|
bc::hash_literal("0000000000000000000000000000000000000000000000000000000000000000"),
|
|
|
|
bc::hash_literal("0000000000000000000000000000000000000000000000000000000000000011"),
|
|
|
|
bc::hash_literal("0000000000000000000000000000000000000000000000000000000000000022"),
|
2014-09-28 15:52:50 +00:00
|
|
|
}};
|
|
|
|
const bc::hash_digest merkle_root = create_merkle(tx_hashes);
|
2017-07-18 04:07:31 +00:00
|
|
|
std::cout << "Result: " << bc::encode_base16(merkle_root) << std::endl;
|
2014-09-28 15:52:50 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|