空谷に吼える

ブロックチェーン/DLTまわりのなにかしらを書いていく所存

Oracle Blockchain Cloud ServiceのリッチヒストリーDB使ってみた

もういくつ寝るとお正月です、やっていきましょう

解説したこと&やったこと

  • Oracle Blockchain Cloud Service(OBCS)のリッチヒストリーDB機能を解説
  • OBCSでリッチヒストリーDBへの連携を構成して利用してみる

内容

このエントリはOracle Cloud Advent Calendar 2018の16日目として書かれています。Oracle Blockchain Cloud Service(OBCS)の便利機能であるリッチヒストリーDB機能を紹介するよ

書いていたら長くなりすぎて読みにくくなってきたのでOBCSのインスタンス作ってサンプルChaincode動かしとくところとOCI Databaseのインスタンス作るとことは事前準備編として分けて公開しておきました、親切ですね

事前準備編その①:Oracle Blockchain Cloud Serviceのインスタンスを作成してサンプルChaincode動かしてみた - 空谷に吼える

事前準備編その②:Oracle CloudでOBCSのリッチヒストリーDB連携用のOCI Database作成してみた - 空谷に吼える

リッチヒストリーDB機能とは

Oracle Blockchain Cloud Service(OBCS)のリッチヒストリーDB機能とは、HLFのPeerノードが抱えている台帳の内容を、オフチェーンのRDBOracle DB)に複製するという機能です。RDB側にはステート履歴のテーブルと、現在のStateのテーブル、また、複製済のブロック/トランザクション地点(Block Height)を表すテーブルが作成されます。

なお、これらのテーブルはいずれも、複製元の台帳のうち、ブロックチェーン(上に格納されているトランザクション履歴)をソースとして生成されています。RDB側に作成される現在のStateのテーブルは、State DBから複製してきているわけではないということです。「トランザクション履歴を最新まで処理していった結果できあがるState」と、State DBの内容は通常一致するはずなので特に気にしていなくてもどうということはないですが、まあ知っておくに越したことはない

HLFでHistory DBと呼ばれているオブジェクトは実のところ所謂データベースではなく、単にあるKeyに係る過去バージョンのステートのブロックチェーン上でのIndexを保持しているに過ぎません。この素のHistory DBをいちいちChaincodeから呼び出してステート履歴をクエリし、分析する…というのは処理コストがかなり高くなってしまってあまり効率的ではないと思います。

リッチヒストリーDB機能を使うことで、データの構造化および分析をもともと得意とするRDB側でこれらの操作を行うことができるようになります。BIツール、可視化ツールなどもRDBのほうが圧倒的に充実しているため、効率的かつ効果的な分析ができるようになるはずです。

また、前述の通り、台帳のState DBと同じ情報を持っている(はずの)現在のStateをテーブルも複製されています。リッチヒストリーDB機能を使用している場合も、Peerが保持する台帳をSSoT(Single Source of Truth)として扱うべきであることは変わらないことには注意が必要です。しかしユースケースによっては、台帳のState DBをChaincode経由でクエリするのではなくRDB側の現在Stateをクエリするので十分な場合もあるでしょう。

どういうカラムが作られるのかなどの詳しい情報は↓の公式ドキュメントを参照ください。

Create the Rich History Database

リッチヒストリーDB連携機能を使ってみる

百聞は一見にしかず、OBCSでリッチヒストリーDB連携機能を使ってみましょう。

前提事項

ここでは事前にOBCSのインスタンスの作成と、リッチヒストリーDB機能の連携先であるOCI Databaseの作成は済ませてある前提です。それぞれの作成方法は前述の事前準備編その①とその②のエントリに書いておいたので参照ください。

また、OBCSのインスタンスを作成しただけの状態だとリッチヒストリーDBで複製するべき台帳が存在していないので、上記のエントリに含まれているチャネルの作成とサンプルChaincodeの動作のところまで済ませている必要があります。

連携先のDBへの接続を構成する

OBCSのコンソール画面の上のほうになんか常に出てる青いエリア、その右端にこっそりあるハンバーガーメニューをクリックしましょう。するとConfigure Rich Historyというメニューがヌルッと出てくるのでこれをくりっく

f:id:gakumura:20181216170013p:plain

以下の接続情報構成フォームが出てくるので、作成しておいたOCIベースのDatabaseへの接続に必要な情報を入力していきましょう。なお、Connection Stringは
<publicIP>:<portNumber>/<database unique name>.<host domain name>の形式です。
例:123.213.85.123:1521/CustDB_iad1vm.sub05031027070.customervcnwith.oraclevcn.com

なお、接続先にAutonomous Databaseを使っている場合はWallet Fileのアップロードが必要です。また、Connection Stringは{データベース名}_{lowやmiddle、highなどのプロファイル}の形式です。例: adb4obp_low

f:id:gakumura:20181216170822p:plain

適切に情報を入力してSaveボタンを押すと、接続のテストが行われます。正常に接続できれば↓のように成功メッセージが表示されたのちフォームが自動的に閉じます。

f:id:gakumura:20181216171442p:plain

チャネルのリッチヒストリーDB機能を有効にする

そしたら今度はチャネルでリッチヒストリーDB機能を有効にします。Channelsタブを開き、事前にChaincodeを動かしておいたチャネルの右端のハンバーガーメニューをクリック、そんで出てくるメニューからConfigure Rich Historyをくりっくくりっく

f:id:gakumura:20181216191145p:plain

シンプルな画面が出るのでシンプルにEnable Rich Historyにチェック、からのSave

f:id:gakumura:20181216191350p:plain

ちゃんとSaveした?したら今度はNodesタブを開いて、一覧に表示されているPeerノードのうち、さっきEnable Rich Historyしたチャネルに所属してるやつをひとつ以上再起動しましょう。右端のハンバーガーメニューからRestartを選ぶと再起動するという寸法

f:id:gakumura:20181216191919p:plain

ここでPeerを再起動してるのは、起動時にチャネルのリッチヒストリーDB機能が有効になってるかどうかチェックするからです。複数Peerを再起動しといてもいいですよ

複製されたRDB側のテーブルを確認

Peerが再起動したのを確認(ステータスがUPに戻る)したら、リッチヒストリーDB機能が有効になり、複製先のRDB(OCI Database)にテーブルが作られているはずです。SQLDeveloperで確認してみましょう

↓のようにテーブルがかっt、もとい自動的に作られていました。なお、charlie_から始まっているテーブルは他のOBCSインスタンスのリッチヒストリーDB機能で作られたやつです。このように複数のOBCSインスタンスからひとつのDBにリッチヒストリーDBを構成することもできるよというやつです。テーブル名は<インスタンス名(Orgnization名>_<チャネル名>_<hist|last|state>の形式ですね。

f:id:gakumura:20181216192610p:plain

stateテーブル

ではstateのテーブルを見てみましょう。これは最新のStateを保持するテーブルで、通常State DBの内容と一致するはずだと前述しておいた

f:id:gakumura:20181216193123p:plain

そのKey-Valueの持ち主のChaincodeのID、Key、Valueを見ることができます。動かしておいたサンプルChaincodeのBalance TransferはふたつのアカウントA,Bの残高をどうこうするシンプルなやつなので、Stateもシンプルです。バージョン情報として扱われるBlock No.とTransaction No.も書いてますね、親切

Value列とValueJSON列があるのが気になりますか?ValueJSON型の場合はValueJSON列に格納され、そうでない場合はValue列に格納されます。ValueJSON列に対してはOracle DB上でJSONクエリが効くようになっており、利便性のためこうなってます

historyテーブル

次にhistoryのテーブルを見てみます。そうですこれがステート履歴を保持するテーブルです。このテーブルが保持するのは、あるステート(Key-Valueセット)の過去~現在バージョンと、そのステートに更新を行ったトランザクション(Write-Setが存在するトランザクション)の情報です。

f:id:gakumura:20181216193855p:plain

いろいろ見えています。stateテーブルと同様に、ChaincodeのID、Key、Value/ValueJSON、Block No.とTransaction No.が見える。他にTransactionが有効だったか(isValid)、Transaction IDとタイムスタンプも見えますね。TxIsDelete列は、そのトランザクションが台帳のStateから、Keyを取り除くようなものだったかどうかを表しています。

lastテーブル

では最後にlastテーブルを見てみましょう。Lastなだけに最後にな、ガハハ。これはリッチヒストリーDB機能が台帳(のブロックチェーン部分)のどこまでを複製してきているかを管理するテーブルです。

f:id:gakumura:20181216194501p:plain

これだけです、ちょっと拍子抜けしましたか?でも人生ってそういうものですよね、アデュー