Merkle tree
# include <cstdlib>
# include <string>
# include <bitcoin/bitcoin.hpp>
BC_USE_LIBBITCOIN_MAIN
using namespace bc;
bc:: hash_digest calculate_merkle_root ( bc:: hash_list & merkle) ;
int bc:: main ( int argc, char * argv[ ] )
{
bc:: cout << "测试 merkle_tree" << std:: endl;
bc:: hash_list tx_hashes{
bc:: hash_literal ( "0000000000000000000000000000000000000000000000000000000000000000" ) ,
bc:: hash_literal ( "0000000000000000000000000000000000000000000000000000000000000011" ) ,
bc:: hash_literal ( "0000000000000000000000000000000000000000000000000000000000000022" ) ,
} ;
bc:: hash_digest merkle_root = calculate_merkle_root ( tx_hashes) ;
bc:: string right_hash = "d47780c084bad3830bcdaf6eace035e4c6cbf646d103795d22104fb105014ba3" ;
assert ( right_hash == bc:: encode_hash ( merkle_root) ) ;
bc:: cout << bc:: encode_hash ( merkle_root) << std:: endl;
return 0 ;
}
bc:: hash_digest calculate_merkle_root ( bc:: hash_list & merkle)
{
if ( merkle. empty ( ) )
{
return bc:: null_hash;
}
if ( merkle. size ( ) == 1 )
{
return merkle[ 0 ] ;
}
if ( 0 != ( merkle. size ( ) & 1 ) )
{
merkle. push_back ( merkle. back ( ) ) ;
}
assert ( 0 == ( merkle. size ( ) & 1 ) ) ;
bc:: hash_list tmp_merkle;
for ( auto it = merkle. begin ( ) ; it != merkle. end ( ) ; it += 2 )
{
bc:: data_chunk concat_data ( bc:: hash_size * 2 ) ;
auto concat = bc:: make_unsafe_serializer ( concat_data. begin ( ) ) ;
concat. write_hash ( * it) ;
concat. write_hash ( * ( it + 1 ) ) ;
bc:: hash_digest new_root = bc:: bitcoin_hash ( concat_data) ;
tmp_merkle. push_back ( new_root) ;
}
merkle = tmp_merkle;
return calculate_merkle_root ( merkle) ;
}