Corda Flowの分解

 

Cordaの開発では、典型的なコード構造として、CorDappを、contractsとworkflowsの2つのモジュールに分けることができます。contractsは、statesとcontractsを含むモジュールで、workflowsはCorda Flowを含みます。workflows用に単一のモジュールを持つことで、配布ロジックがシンプルになります。すなわち、全てのFlowが単一のjarファイルにパッケージされます。一方で、あるノードにCorDappをインストールすると、必要かどうかに関わらず、すべてのFlowが利用可能になることを意味します。この事象は、ノードがさまざまな役割を果たし、さまざまな機能を必要とするネットワークでより起こりやすくなります。

例えば、自動車登録用のCorDappをイメージしてください。ネットワークの参加者には、Department of Motor Vehicleといった政府機関を表すノード(以下、DMVノード)と、車の所有者を表す複数のノード(以下、所有者ノード)があるとします。DMVノードは所有者ノードに対し、登録証発行トランザクションを開始し、所有者ノードはトランザクションの情報を検証し、問題がなければそれを受け入れることになります。一般的なセットアップでは、 Initiator FlowsとResponder Flowsの両方が同じjarファイルにバンドルされています。つまり、登録証発行用のInitiator Flowsは、所有者ノードが実行することを想定していなくても、所有者ノードにインストールされてしまいます。

 

コードでアクセスを制限

この問題について、一つの解決策は、Flowロジックの中で、現在のノードが特定のトランザクションを開始する資格があるかどうかをチェックすることです。自動車登録のCorDappを例にとると、登録証発行Flowを開始するノードがDMVノードであるかどうかをチェックし、そうでない場合は例外を投げます。しかし、この方法は、より複雑なユースケースでは拡張性が低く、Flowのコードのメンテナンスが無駄に困難になる可能性があります。

 

Flowを分解してアクセスを制限

より理想的なアプローチは、workflowsをより小さなモジュールに分割し、ノードが必要とするFlowのみをインストールすることです。例えば、登録証発行のInitiator Flowsのように、DMVノードでのみ開始できるFlowを1つのjarファイルに束ねることができます。一方、登録証発行のResponder Flowsのように、所有者ノードのみが実行可能なFlowは、別のjarファイルに束ねます。

再び自動車登録用のCorDappを例にとります。このCorDappには、自動車登録と、自動車の所有者から別の所有者への譲渡という2種類のトランザクションがあるとします。モジュール構造は以下のようになります。

carbon__1_.png

 

ご覧の通り、Initiator Flowsはdmv-workflowsモジュールにあります。DMVノードのみがこれらのトランザクションを開始できることを意味しています。一方、Responder Flowsは、owner-workflowsに分類されています。

Cordaでは、@InitiatedByアノテーションを用いて、Responder Flowsの対応するInitiatorを指定する必要があります。例えば、RegisterFlowHandlerでは、RegisterFlowに応答することを指定する必要があります。

carbon__2_.png

 

しかし、所有者ノードには dmv-workflows モジュールがインストールされていないため、Responder Flowsを実行するとエラーが発生します。この問題を解決する一つの方法として、RegisterFlowの抽象的な親クラス(AbstractRegisterFlowとします)を定義し、この親クラスを所有者ノードにもインストールされる共有モジュールで公開します。この共有モジュールは、上の構造ツリーでは common-workflows モジュールです。

そして、AbstractRegisterFlow@InitiatedBy に渡すことで、RegisterFlowAbstractRegisterFlow のサブクラスであることから、オーナーノードが RegisterFlow に応答できるようにします。

carbon__3_.png

 

RegisterFlowの定義は次のようになります。

carbon__4_.png

 

 

BootStrapperを使用してネットワークを展開する場合(本番環境では推奨されません)、特定のノードにインストールするモジュールを指定することができます。例えば、build.gradle 内にある DMV ノードのノード設定では、dmv-workflows モジュールをインストールするように指定します。

carbon__5_.png

 

 

一方で所有者ノードの設定は次のようにします。

carbon__6_.png

 

結論

この記事では、異なるノードに独立してFlowをインストールできるようにInitiator FlowsとResponder Flowsを分離する方法について説明してきました。この方法は、ノードで実行可能なFlowを定義するための、拡張性のある方法としてだけでなく、CorDappにおけるworkflowsのモジュール化を促進し、配布のための高い柔軟性を提供します。注意すべきは、分離はInitiator FlowsとResponder Flowsの間で常に起こるわけではないということです。モジュールをどのように定義するかは、アプリケーションの要件によって異なります。

この記事で使用したサンプルの詳細に興味がある方は、こちらのGithubからソースコードをご覧いただけます。

この記事は役に立ちましたか?
0人中0人がこの記事が役に立ったと言っています