villagerHの日記

勉強したことや苦労した事などを書き綴ります

マークルツリー構築サンプル表示のコードで詰まった話

ビットコインとブロックチェーン

ビットコインとブロックチェーン

こちらのサンプルコードで再び詰まったので解決のお話。

サンプルコードをそのまま打ち込んでmakeしたら以下のエラーが出ました。

merkle.cpp:27:22: error: no member named 'make_serializer' in namespace 'libbitcoin'
                        auto concat = bc::make_serializer(concat_data.begin());
                                      ~~~~^
merkle.cpp:42:28: error: no member named 'encode_hex' in namespace 'libbitcoin'; did you mean 'encode_hash'?
                        std::cout << " " << bc::encode_hex(hash) << std::endl;
                                            ~~~~^~~~~~~~~~
                                                encode_hash
/usr/local/Cellar/libbitcoin/3.5.0_4/include/bitcoin/bitcoin/formats/base_16.hpp:65:20: note: 'encode_hash' declared here
BC_API std::string encode_hash(hash_digest hash);
                   ^
merkle.cpp:60:33: error: no member named 'encode_hex' in namespace 'libbitcoin'; did you mean 'encode_hash'?
        std::cout << "Result: " << bc::encode_hex(merkle_root) << std::endl;
                                   ~~~~^~~~~~~~~~
                                       encode_hash
/usr/local/Cellar/libbitcoin/3.5.0_4/include/bitcoin/bitcoin/formats/base_16.hpp:65:20: note: 'encode_hash' declared here
BC_API std::string encode_hash(hash_digest hash);

どれも定義がないよと仰ってるご様子。

encode_hexは前のサンプルでも詰まっていた箇所なのでサクッと直しましょう。
villagerh.hatenablog.com

std::cout << " " << bc::encode_hex(hash) << std::endl;
以下に変更
std::cout << " " << bc::encode_base16(hash) << std::endl;

std::cout << "Result: " << bc::encode_hex(merkle_root) << std::endl;
以下に変更
std::cout << "Result: " << bc::encode_base16(merkle_root) << std::endl;

さて問題はmake_serializerです。
単純にエラー文でぐぐってもどう変化したのかが見当たらなかったので解決法を見つけるのに苦労しました…

参考コードを見つけたので以下の形に置き換えたら通りました!

auto concat = bc::make_serializer(concat_data.begin());
変更後
auto concat = bc::serializer<decltype(concat_data.begin())>(concat_data.begin());

serializerがクラス形式に変更になったようです。
さてこのままmakeを行ってもまだエラーが出ました。

merkle.cpp:30:18: error: no member named 'iterator' in 'libbitcoin::serializer<std::__1::__wrap_iter<unsigned char *> >'
                        assert(concat.iterator() == concat_data.end());

concatの持ち方が変わったことでiteratorがなくなったようです。

解決方法はと言うと…



どう変わったのか調べる時間がなかったのでassertなのでコメントアウトして誤魔化しました^^;;

該当箇所のassertをとりあえずコメントアウトするとついにmakeが通ります。やったー!

動かしてみます。

Current merkle hash list:
 0670d2c428dc9c49b87071394d42658b5d638817f80adb80438e41a049006532
 c44075eebca1af653e1b4e4a26c34ab8d55bcda18c39998bdcc80569b91d8630

あれー?表示されたハッシュ値が本の結果と全く違う???

今回はencodeをbase16でなくhashで行うのが正解のようです。

std::cout << " " << bc::encode_base16(hash) << std::endl;
以下に変更
std::cout << " " << bc::encode_hash(hash) << std::endl;

std::cout << "Result: " << bc::encode_base16(merkle_root) << std::endl;
以下に変更
std::cout << "Result: " << bc::encode_hash(merkle_root) << std::endl;

実行結果
Current merkle hash list:
 32650049a0418e4380db0af81788635d8b65424d397170b8499cdc28c4d27006
 30861db96905c8dc8b99398ca1cd5bd5b84ac3264a4e1b3e65afa1bcee7540c4

無事に望んでいた結果が表示されました!


というか…

merkle.cpp:42:28: error: no member named 'encode_hex' in namespace 'libbitcoin'; did you mean 'encode_hash'?
                        std::cout << " " << bc::encode_hex(hash) << std::endl;

encode_hexのエラー時にencode_hashじゃないの?ってエラーで教えてくれてるのに全く無視してました;;;;