villagerHの日記

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

ビットコインアドレス表示のサンプルコードで詰まった話

ビットコインとブロックチェーン:暗号通貨を支える技術

ビットコインとブロックチェーン:暗号通貨を支える技術

こちらの本を読み進めていて、サンプルコードを実際に打ってみたら詰まったので解決までのお話。
※記事を書いている時点で使用したlibbitcoinは3.5.0_4です。

とりあえず実行するためにlibbitcoinライブラリが必要なのでインストールしておきます。
villagerh.hatenablog.com

本に書いてあるサンプルコードを入力してコンパイルを実行します。
※コードに関しては実際に本を購入してそちらを参照ください。

$ g++ -o addr main.cpp $(pkg-config --cflags --libs libbitcoin)
Package libsecp256k1 was not found in the pkg-config search path.
Perhaps you should add the directory containing `libsecp256k1.pc'
to the PKG_CONFIG_PATH environment variable
Package 'libsecp256k1', required by 'libbitcoin', not found
(略)


libbitcoin内でlibsecp256k1を使用しているものの見つからないようです。
brewだとインストールされていないみたいなのでlibsecp256k1を直接インストールします。(ソースからlibbitcoinを入れる方法だとどうなんでしょうね?)
https://github.com/libbitcoin/secp256k1

任意の場所にsecp256k1をcloneしてくる。

$ git clone https://github.com/bitcoin-core/secp256k1.git
$ cd secp256k1

あとは公式の手順に沿って実行するだけ。

$ ./autogen.sh
$ ./configure
$ make
$ sudo make install

何事も起こらなければこれでインストールが完了するので再びmakeしてみます!

$ g++ -o addr main.cpp $(pkg-config --cflags --libs libbitcoin)
/usr/local/Cellar/libbitcoin/3.5.0_4/include/bitcoin/bitcoin/utility/data.hpp:36:20: warning: alias declarations are a C++11 extension [-Wc++11-extensions]
using byte_array = std::array<uint8_t, Size>;
/usr/local/Cellar/libbitcoin/3.5.0_4/include/bitcoin/bitcoin/utility/data.hpp:51:14: error: no type named 'initializer_list' in namespace 'std'
typedef std::initializer_list<data_slice> loaf;

んーまだエラーが出ました。
警告とかの内容を見る感じlibbitcoinはC++11を使用いるけどそれがmakeできていない模様。
どうすればいいんだろうと調べたところこちらのサイトさんにたどり着きました。
https://marycore.jp/prog/xcode/warning-cpp-extension/

オプションを追加すればよいようなのでオプションを加えて再度実行。

$ g++ -o addr main.cpp -std=c++0x $(pkg-config --cflags --libs libbitcoin)
main.cpp:11:6: error: no type named 'ec_point' in namespace 'libbitcoin'
        bc::ec_point public_key = bc::secret_to_public_key(success);
main.cpp:11:32: error: no member named 'secret_to_public_key' in namespace 'libbitcoin'
        bc::ec_point public_key = bc::secret_to_public_key(success);

だいぶエラーが減りましたが、まだ残ってます。
ec_pointとかでエラーになっていたので打ち間違いか?と思って本と見比べたものの間違いは見つからず。
とりあえずググってみたところec_pointとかはいつからかのバージョンで使用しなくなったっぽいです。
ご丁寧に変更後のコードを載せてくれてる場所がgitのIssuesにあったのでそのまま載せます。

bc::ec_point public_key = bc::secret_to_public_key(secret);
std::cout << "Public key: " << bc::encode_hex(public_key) << std::endl;

上記の箇所を以下の形式に変更。

bc::ec_compressed public_key;
bc::secret_to_public(public_key, secret);
std::cout << "Public key: " << bc::encode_base16(public_key) << std::endl;

これでmakeしたところようやく通りました!

本が出てから時間が経ってしまっているので仕方がないことですがサンプルのコードが使えなくなってたりすると大変ですね^^;