bitcoindからのメッセージをZeroMQ経由(+SpringBoot)で購読する
やること
bitcoindにはJSON-RPC以外にZeroMQを介したメッセージ購読ができるようになっていますが、これをSpringBootアプリケーション上にサンプル実装します。
ZeroMQの実装ライブラリとしてjeromqを使用します。
GitHub - zeromq/jeromq: Pure Java ZeroMQ
公式ドキュメント
bitcoin/zmq.md at master · bitcoin/bitcoin · GitHub
開発環境
- Windows10
- Java8
bitcoindのインストールと起動
公式サイトからインストーラをダウンロードしてインストールします。
ダウンロード - ビットコイン設定ファイル作成して適当なディレクトリに配置します。
bitcoin.confregtest=1 server=1 rpcuser=username rpcpassword=password zmqpubrawblock=tcp://127.0.0.1:28332 zmqpubhashblock=tcp://127.0.0.1:28332 zmqpubrawtx=tcp://127.0.0.1:28332 zmqpubhashtx=tcp://127.0.0.1:28332
実装の確認をするだけなので regtest 環境で起動させます。
bitcoindを起動します。
$ cd ${bitcoin intall dir}/daemon $ ./bitcoind.exe -conf=/path/to/bitcoin.conf
SpringBootアプリケーションの作成
Spirng Initializr等で作成したテンプレートプロジェクトにjeromqライブラリを追加します。
build.gradle
dependencies { compile('org.springframework.boot:spring-boot-starter-web') compile group: 'org.zeromq', name: 'jeromq', version: '0.4.2' }
zmqクライアント部分は公式のpython実装を参考に作成します。
https://github.com/bitcoin/bitcoin/tree/master/contrib/zmq
購読対象のメッセージを設定しないと受信できないので、追加する場合はsubscribeメソッドを呼んでください(コメントアウトの部分)。
bitcoindは以下4種類のメッセージをサポートしています。
socket.subscribe("hashtx"); // transactionのハッシュ値 socket.subscribe("hashblock"); // blockのハッシュ値 socket.subscribe("rawblock"); // blockの生データ socket.subscribe("rawtx"); // transactionの生データ
BitcondZmqClient.java
@Slf4j @Component public class BitcondZmqClient { private static final String url = "tcp://127.0.0.1:28332"; @PostConstruct private void init() { ExecutorService executor = Executors.newFixedThreadPool(1); Runnable runner = this::connectZmqServer; executor.execute(runner); } private void connectZmqServer() { ZMQ.Context context = ZMQ.context(1); ZMQ.Socket socket = context.socket(ZMQ.SUB); socket.connect(url); socket.subscribe("rawblock"); // socket.subscribe("hashblock"); // socket.subscribe("rawtx"); // socket.subscribe("hashtx"); log.info("connect to " + url); while (!Thread.currentThread().isInterrupted()) { String topic = socket.recvStr(); log.info("client - topic:" + topic); if (socket.hasReceiveMore()) { // byte[] body = socket.recv(); String body = socket.recvStr(); switch (topic) { case "rawblock": log.info("client - body:" + body); break; default: break; } } if (socket.hasReceiveMore()) { String sequence = socket.recvStr(); log.info("client - sequence:" + sequence); } } socket.close(); context.term(); } }
ComponentScan対象になるように@SpringBootApplication配下のディレクトリに配置してください。
メインの業務処理とは分けられるように別スレッドでZmqClientを起動しています。
ZeroMQ経由のメッセージ購読確認
SpringBootアプリケーションを起動します。
regtest環境とbitcoin-cliコマンドを使ってブロックをマイニングします。
$ cd ${bitcoin intall dir}/daemon $ ./bitcoin-cli.exe -conf=/path/to/bitcoin.conf generate 1
ログにブロックの情報が表示されれば成功です。
memo
トランザクション情報もメッセージを変えることで購読できるので試してみてください。
regtest環境を初期構築した後はマイニング報酬を得るのに100ブロック掘る必要があるので sendtoaddress コマンド実行時にお金が足りないと表示される場合には generate 100 で100ブロックを掘ってみてください。