はじめに

こんにちは。ブロックチェーン推進室の鈴木です。

私の所属するブロックチェーン推進室では、企業間取引に特化したエンタープライズブロックチェーンプラットフォーム:Cordaに関して機能調査を行っております。
Cordaは世界で350社を超える金融機関、規制当局、中央銀行、業界団体、システム・インテグレーターやソフトウェアベンダーにより構成されるR3エコシステムから、エンドユーザー目線で設計・開発されています。
また、4半期に1度のバージョンアップにより機能追加がされていますが、その機能がお客様に活用できるものなのか、ドキュメントだけではわからないことも多く、ブロックチェーン推進室独自で調査を進めています。

このブログでは、そういったCordaの機能調査をした結果を機能の使い方含めて紹介していきます。

Cordaの導入方法についてはこちらのドキュメントをご参照ください。

今後以下の内容で紹介しようと思います。

  1. Corda JMeterの使い方(9/1公開済み)
  2. Corda Enterprise Performance検証 ノードスペックを変化することによる性能変化(9/15公開済み)
  3. Corda Tokens SDK and Accounts(9/29公開済み)
  4. Corda Enterprise Collaborative Recovery(10/15公開済み)
  5. Corda Enterprise Archive Service(10/27公開済み)
  6. Corda Firewallの設定方法(11/9公開済み)
  7. Corda re-issuance Tokens SDK and Accountsを利用した一括「re-issuance」(11/24公開済み)
  8. Corda Time-windows(12/8公開済み)
  9. Corda Oracle(12/22公開済み)
  10. Corda attachment(←今回はこちらの記事)
  11. Corda Webアプリケーション開発について

(以降、バージョンアップの都度、新機能を紹介予定)

第10回目は「Corda attachment」について紹介します。

概要

今回の記事はCordaの「attachment」についてです。attachmentはTransactionに添付できる任意のデータファイルです。
ファイルをやり取りするのは他のブロックチェーンプラットフォームではあまり見られないCordaならではの機能ではないかと思います。
本記事ではattachmentがどのようなものか、また実際の使用方法について解説します。

attachmentは、zipファイル、もしくはjarファイルである必要があります。
よって、写真やドキュメントファイルは事前にzipまたはjarに圧縮しておく必要があります。
実際にファイルそのものはTransactionに含まれず、このattachmentのハッシュ値がTransactionに含まれます。
このハッシュ値はTransactionの有効性を確かめるために利用、もしくは送信先のノードで利用します。

ユースケース

attachmentはトレーサビリティなどのユースケースにおいて、製造工程や製造者の写真などをPDFにいれておいて、エンドユーザに確認してもらうために利用をします。
また、カレンダーや通貨のコード表などを添付し、Transactionを検証するために利用することもできます。
Contract.jarを利用するユースケースにおいては、特定のContractを使って検証したい場合に利用します。
Contract.jarをattachmentとして添付することでそのContractを使って、検証を行うことができます。

attachmentの種類

Contract.jarファイルと一般ファイルの2つに分類できます。

  1. Contract.jarファイル Contract.jarファイルをattachmentに追加することでそのContractによる検証を行う
  2. 一般ファイル ネットワーク参加者によって共有および再利用される任意のデータ

zipとjarの使い分け

使い分けの想定として以下の通りです。

  • jar:Contract.jar
  • zip:PDFなどの一般的なファイル

jarファイルにはzipファイルと同様にPDFや他の種類のファイルを含めることも可能なため、Contract.jar以外のファイルを含んだjar形式のattachmentとして添付しているケースも存在します。
また、jarファイルにはjarsignerにて署名を付与させることができるため、ファイルの署名者を検証させたいような要件で利用することもあります。

実装方法

attachmentを用いたやり取りを行う流れは以下のようになります。

  1. attachmentをノードへアップロード
  2. 図1:attachmentのアップロード

  3. Transactionにattachmentを添付
  4. 図2:Transactionに添付

  5. attachmentをダウンロード

図3:attachmentのダウンロード

この流れをひとつずつ見ていきます。

1. attachmentをノードへアップロード

パスを指定して、zipファイルもしくはjarファイルをノードへアップロードします。アップロードを行うとノードのDBへ登録されます。
アップロード方法はノードシェルからコマンドを入力する方法とFlowを利用する方法の二種類あります。

  • ノードシェルからコマンドを入力する方法

以下のコマンドを入力することでアップロードできます。

run uploadAttachment jar: アップロードするファイルのパス
  • Flowを利用する方法

以下のようにServiceHubを利用することでアップロードできます。

serviceHub.attachments.importAttachment(File(”ファイルのパス”).inputStream(),”アップローダー名”, ”ファイル名”)

アップロードが完了するとNODE_ATTACHMENTSテーブルにattachmentが登録されます。
ファイルはBLOBとしてDBの中に入りますので、実際の運用では格納するファイルサイズを見積り、最適な容量をもつDBを準備する必要があります。

2. Transactionにattachmentを添付

ノードのDBに登録してあるATTID(Hash値)を指定し、Transactionに追加します。
Transactionにinput stateやoutput stateを追加するようにattachmentも以下のように追加できます。

transactionBuilder.addAttachment(attachmentHash)

パラメータにはattachmentのHash値を指定します。
Hash値はFlowのパラメータとして受け取るか、AttachmentQueryCriteriaを使って検索条件を指定してノードのDBに登録されているattachmentのHash値を検索できます。
Transactionにはファイルそのものは入らず、Hash値のみTransactionに入ります。
Transactionの受け入れ、拒否にかかわらず、検証するためにTransactionを相手に送信したタイミングで送信先のノードのDBにattachmentが自動的に登録されます。

3. attachmentをダウンロード

ノードのDBに登録してあるattachmentをノードのサーバ上にダウンロードします。

  • ノードシェルからコマンドを入力する方法

以下のコマンドを入力することでダウンロードできます。

run openAttachment id: Hash値

この時、保存するファイル名を求められるので、名前を入力する必要があります。

  • Flowを利用する方法

以下のようにServiceHubを利用することでダウンロードできます。
後者のInputStream.toFile()はユーザ自身で定義する必要があります。

serviceHub.attachments.openAttachment(Hash値)!!.open().toFile(path)
fun InputStream.toFile(path: String) {
  File(path).outputStream().use { this.copyTo(it) }
 }

Contract.jarとattachment

Contract.jarをattachmentとしてアップロードするとNODE_ATTACHMENTS_CONTRACTSテーブルにもレコードが登録されます。
jarファイルに署名がされている場合、NODE_ATTACHMENTS_SIGNERSテーブルにもレコードが登録されます。
Transactionを生成してやり取りする際に、対応するStateのContractを含むjarがattachmentとして自動的に追加されます。
やり取りする相手がいる場合、Stateを検証する際、Transactionの生成者のContractが使用されます。
Transaction生成者のノードに登録されているContract.jarであれば、使用するContract.jarを別の実装のContract.jarに変更できます。
その際は使用するContract.jarをAttachmentQueryCriteriaで検索条件を指定して、検索したattachmentをTransactionにaddAttachment()をします。
すると、この追加したContract.jarによって検証が行われます。
別のノードから送信されたContract.jarをTransactionに追加し使用する場合、うまくいかない場合があります。うまくいかない場合の例を以下で解説します。
NodeAがNodeBとやり取りする際に、NodeBが所持していないContract.jarを使用します。このContract.jarは取引中にNodeBのDBに登録されます。

図4:NodeBのContract.jarの登録

①の後、NodeBはNodeCとやり取りする際にそのContract.jarを使用します。

図5:Contract.jarの使用

このままの場合、UntrustedAttachmentsExceptionがスローされる可能性があります。
対処法として、このContract.jarをNodeBが一度ダウンロードし、NodeBが再度アップロードすることで解決できます。
相手から受け取ったContract.jarは信頼できないものとして認識されており、自身でアップロードしたものは信頼できるものとして認識されます。そのため、受け取ったContract.jarを自身で再アップロードする必要があります。

attachmentによる検証

attachmentのzipファイルの中にあるテキストファイルの内容などをContractの中で検証できます。
例として、テキストファイルに複数の組織の名前が書いてあり、StateのParticipantsの中にその名前が含まれていたら例外を発生させるなどの検証を行うことができます。
このようにattachmentを添付しないといけませんが、Contractのコードに組織の名前などをハードコーディングしなくて済むメリットもあります。

まとめ

attachmentに関しての注意点と考察を以下に示します。

注意点

▼アップロード時の注意点

  • ファイル名や拡張子が異なっていても中身が同じなら生成されるハッシュ値は変わりません。
    つまり、一度アップロードしたファイルをコピーして、ファイルの名前や拡張子だけ変えても、そのファイルはハッシュ値が競合するためアップロードできません。
    これはファイルのHash値がキーとなっているためです。一方で、名前や拡張子が同じでも中身が異なっていればアップロードできます。

▼Transactionに添付時の注意点

  • Transactionをやり取りする相手のDBにすでに登録されている場合、再登録や更新することはしません。
  • attachmentを添付する際にレコードの一部が改ざん及び削除されている場合、Hash値が合わなくなるためTransactionは失敗します。

▼添付ファイルをダウンロードする際の注意点

  • ダウンロードされたファイルはCordaNode直下のディレクトリに保存されます。
  • 保存する際のファイル名は拡張子まで含める必要があります。この時、アップロードした時と同じファイル名や拡張子でなくてもダウンロードできます。

考察

attachmentはカレンダーや通貨のコード表のような何度も再利用するようなデータを意図していますがもちろん再利用しないようなものにも使用できます。
検証するためであったり、ファイルの共有であったり様々な用途で活用できる機能であると思います。
Transactionが失敗したとしても、検証するために相手にTransactionを送信した時点で相手にattachmentが登録される以上、個人情報などを含むようなファイルは適していないように思います。
これは前提として、attachmentは共有されるものとなっているからです。
共有するファイルサイズが巨大である場合、サイズによっては相手ノードのDB容量を逼迫させることにもなりかねないため、attachmentとしてやり取りを行うファイルのサイズについては事前に設計しておくことが重要となります。

おわりに

attachmentを調査し、使い方や実装方法などはとても簡単だと感じました。
しかし、実際のファイルがどのような流れで動いているのか登録されるのはどのタイミングかなど苦戦しました。
また、Contract.jarに関するところの理解は少し難しいように感じました。この記事を通して、attachmentの基本的な使い方や概要理解の参考になったら幸いです。

今回は以上になります。