Reference Stateの活用に関する手法や制約を、デモンストレーションを踏まえて理解することができます。
- まえがき
- 自己紹介
- 調査内容(再掲)
- 調査結果について(再掲)
- サンプルプログラムについて(再掲)
- デモンストレーション手順
- 要望1(Node Terminal Window: ParticipantAで実行)
- 要望2(Node Terminal Window: ParticipantBとParticipantCで実行)
- 要望3(Node Terminal Window: ParticipantAで実行)
- 調査結果
- 調査1: Ref.Stateをトランザクションに含め、コントラクトで検証可能か
- 調査2: あるノードで発行したRef.Stateのバックチェーンを別のノードで確認できるか
- 調査3: 消費済みのRef.Stateをトランザクションに含められるか
- 調査3のエラーについて
- サンプルプログラムのURL
- 終わりに
まえがき
今回、Reference State(以下Ref.State)に関する細かな動作確認を行うため調査を行いました。
調査にあたりましてサンプルプログラムを作成しました。コード解説編とデモンストレーション編の2部編成でお届けしたいと思います。
本記事はRef.Stateについて詳しく知りたいCordaに精通していらっしゃるエンジニアの方やセールスの方を対象としております。
Cordaについて詳しく知りたい方はR3公式ドキュメントや株式会社digglueさんの記事をご覧ください。また、Cordaの概念であるUTXOモデルについて知りたい方は、こちらの解説記事をご覧ください。
自己紹介
SBI R3 Japan株式会社にインターンでお邪魔している井本翔太と申します。現在、都内の大学に通いながらエンジニアとして働かせていただいています。2021年頃からブロックチェーンに興味を持ち始め、その仕組みや活用方法を学ぶ過程でCordaと出会いました。私にとってCordaは社会にブロックチェーンという存在を浸透させる上で大きな役割を果たすと考えております。
調査内容(再掲)
改めて調査内容の確認です。
調査1:Ref.Stateをトランザクションに含め、コントラクトで検証可能か
調査2:あるノードで発行したRef.Stateのバックチェーンを別のノードで確認できるか
調査3:消費済みのRef.Stateをトランザクションに含められるか
調査結果について(再掲)
調査1,2については要望を満たすことができましたが、
調査3はエラーが出力されました。
調査3で出力されたエラーについては後ほど説明したいと思います。
※調査1,2と調査3では実装が異なるため、サンプルプログラムは2つ作成しました。
サンプルプログラムについて(再掲)
サンプルプログラムはSBI R3 Japan株式会社が提供しております Corda trainingのコードにAddressState(住所録)をRef.Stateとして加えました。Corda trainingで扱うプログラムはIOU(借用証書)の発行(Issue)、譲渡(Transfer)、返済(Settle)に関するプログラムになります。今回は必要最低限の機能を実装するためにRef.Stateの実装対象をIssueのみに絞りました。
デモンストレーション手順
要望1(Node Terminal Window: ParticipantAで実行)
1. PublishFlow.javaを実行して、AddressStateを発行する。
2. MoveFlowを実行して、AddressStateを更新する。
3. IOUIssueFlowを実行して、IOUを発行。この時、SignedTransactionIDを記録
4. トランザクションの詳細を調べるため、run internalFindVerifiedTransaction txnId: Transaction-ID or Hash
というコマンドを実行。引数に手順3で記録したSignedTransactionIDを指定する。
5. referencesという項目に記載されているtxhashがMoveFlow実行後に表示されるハッシュ値と一致するか確認
要望2(Node Terminal Window: ParticipantBとParticipantCで実行)
1. IOUTransferFlow.javaでIOUのトランザクションをParticipantBからParticipantCに渡す。
2. ParticipantCのNode Terminal Windowsにてrun internalFindVerifiedTransaction txnId: ~
を実行し、付随されているAddressStateのハッシュ値を確認する。
3. 再びrun internalFindVerifiedTransaction txnId: ~
を実行し、手順2で確認したハッシュ値を引数に指定する。InputStateに関する項目でハッシュ値を確認する。
4. 再びrun internalFindVerifiedTransaction txnId: ~
を実行し、手順3で確認したハッシュ値を引数に指定する。InputStateに関する項目が空白になっていれば、別ノードでAddressStateのバックチェーンが確認できた事になります。
要望3(Node Terminal Window: ParticipantAで実行)
1.PulishFlowを実行し、AddressStateを発行
2.MoveFlowを実行し、AddressStateを更新
3.IOUIssueFlowを実行。この時、SignedTransactionIDを記録。
4.run internalFindVerifiedTransaction txnId: ~
を実行。引数には手順3で記録したSignedTransactionIDを指定
5.referencesという項目に記載されているtxhashがPublishしたAddressStateと一致するか確認
調査結果
調査1: Ref.Stateをトランザクションに含め、コントラクトで検証可能か
- PublishFlow PublishFlowの実行結果です。issuerがParticipantA、addressがshinjuku(新宿) というAddressStateを発行しました。以下に実行結果を示します。
- MoveFlow MoveFlowの実行結果になります。新しいaddressをroppongi(六本木) としAddressStateを更新しました。以下に実行結果を示します。
- IOUIssueFlow IOUIssueFlowの実行結果になります。 ※SignedTransactionID=081209B~は次の手順で使用するため必ず記録します。
ref=8C7EF4~が発行したAddressStateのハッシュ値
ref=8169C4~が更新したAddressStateのハッシュ値
- コマンド
続いて、AddressStateがIOUIssueのトランザクションに含まれている事を確認します。確認には
run internalFindVerifiedTransaction txnId: ~
というコマンドを使用します。この時、LinearIdを調査2で使用するため記録します。 以下に実行結果を示します。※添付図は一部カットしています。
コマンドの引数は先ほど記録したIOUIssueのSignedTransactionID=081209B~です。「references:」という項目に注目するとMoveしたAddressStateのハッシュ値(8169C4~)と一致 することが分かります。したがって、Ref.State(AddressState)はトランザクションに含めることができると判明しました。
調査2: あるノードで発行したRef.Stateのバックチェーンを別のノードで確認できるか
- IOUTransferFlow IOUTransferFlowの実行結果になります。引数にはLinearIdが必要になるため、調査1でトランザクションの詳細を調べた時にLinearIdを記録する必要があります。ここでは、IOUIssueのトランザクションをParticipantBからParticipantCへ渡します。
- コマンド
続いて、ParticipantCでAddressStateのバックチェーンをトレースします。先ほど記録したSignedTransactionIdを引数に指定し、
run internalFindVerifiedTransaction txnId: ~
を実行します。以下に結果を示します。※添付図は一部カットしています。
SignedTransactionId=870F57~は必ず記録します。
「referencese:」という項目からAddressState(addressはroppongi)のハッシュ値を確認します。そして、run internalFindVerifiedTransaction txnId:
を実行します。以下に結果を示します。※添付図は一部カットしています。
赤枠からaddressがroppongiのAddressStateはtxhash=8C7EF4~というAddressState(addressはshinjuku)をinputStateとして使用している事が分かります。再び同様に、run internalFindVerifiedTransaction txnId: ~
を実行します。※添付図は一部カットしています。
赤枠からinputの項目が空であることが分かります。したがって、PublishしたAddressStateまでトレースできたことを意味します。
調査3: 消費済みのRef.Stateをトランザクションに含められるか
基本的な手順は調査1と同様です。
- PublishFlow
- MoveFlow
- IOUIssueFlow
- ParticipantAのログ
最初にsuginami(杉並区)のAddressStateを発行しました。赤色の下線部がハッシュ値です。
次にAddressStateをsuginamiからnakano(中野区)に更新しました。赤色の下線部がハッシュ値です。
コード解説編 にて、このIOUIssueFlowは1つ前のAddressStateを含める処理が記述されています事を確認しました。実行結果を以下に示します。
previousHashという項目と先ほどのPublishFlowの実行結果からvaultQueryを用いた処理で1つ前のAddressStateが発見できている事が分かります。しかし、赤色の下線部からNotaryの処理で止まっている事が確認できます。
先ほどNotaryの処理で止まっていたためParticipantAのログを確認します。すると以下のエラーメッセージが出力されていました。
事項でエラーの発生原因について解説したいと思います。
調査3のエラーについて
先ほどエラーメッセージを直訳すると「一つもしくは複数のStateまたはReference Stateは他のトランザクションの中で既にインプットとして使われた」という意味です。このエラーの原因として、Moveする段階で最初にPublishしたAddressState(=1つ前のRef.State)がInputStateとして使われた事をNotaryが記録する事 が考えられます。詳しい説明のためにCDLを再掲します。
上記のCDLからMoveFlowを実行する際には、PublishしたAddressStateがInputStateとして使われていることが分かります。調査3ならsuginamiのAddressStateを消費して、nakanoのAddressStateを作成しています。
suginamiのAddressStateが消費済みという事実はNotaryに記録されます。したがって、IOUIssueのトランザクションにsuginamiのAddressState(1つ前のAddressState)を含めようとするとNotaryはNGを出します。
調査3が実現不可能な理由についてご理解いただけましたでしょうか?
サンプルプログラムのURL
調査1,2のサンプルプログラムです。
https://github.com/ShotaIMO/investigation-of-ReferenceState
調査3のサンプルプログラムです。
https://github.com/ShotaIMO/investigation-of-Previous-ReferenceState
サンプルプログラム作成にあたって、ご協力いただいたSBI R3 Japan株式会社のエンジニアチームの皆様ありがとうございました。
終わりに
以上が調査結果の報告になります。皆様のRef.Stateに対する理解が深まれば幸いです。Cordaにご興味のある方はSBI R3 Japan株式会社へ直接ご連絡いただければ幸いです。Ref.StateRに関する新たな調査も始動しておりますので、また記事にしたいと思います。ご一読ありがとうございました。
<ご質問・ご要望の例>
- Corda Portalの記事について質問したい
- ブロックチェーンを活用した新規事業を相談したい
- 企業でのブロックチェーン活用方法を教えて欲しい 等々
SBI R3 Japanインターン エンジニアリング部所属
Corda 5の技術検証や記事翻訳など多岐に渡ります
趣味:英語学習(まだまだですが…)・テニス・映画鑑賞