FlowとContractの役割分担(Cordaのスマートコントラクト-その1)

 

read: 9 min

Cordaのスマートコントラクトはプライバシー確保の観点から、他のブロックチェーンとは異なる考え方に基づいています。この記事では、異なる考えに立つCordaのスマートコントラクト、その応用的な使い方について触れます。基礎的な部分については、概念説明コーディングサンプルをご覧ください。

・・・


 

という事で

 ブロックチェーンとスマートコントラクトが当たり前になった世界を想像してください。

 こうしたエコシステムの中では「自分にとっては重要ではない」トランザクションや「自分にとっては無意味な」トランザクションがどんどん送られてくる可能性があります。パブリックブロックチェーンであれば、こうしたトランザクションを受け入れる事も必要でしょう。しかし、プライベート/コンソーシアムブロックチェーンでは必ずしもそうではありません。

Cordaには、トランザクションを取捨選択し、受け付けないようにする機能があります。

 まずは基本的なCordaのトランザクション(以下Tx)のやり取りを考えましょう。

① NodeがInitiating Flowをキックします。Initiating Flowによって、関係者に向かってTxの検証と署名を求めるトランザクションが送信されます。

②受け取った関係者(と指定されたNode)は送信された(Initiating) Flowに対応するResponder Flowを自ノードから探し、Responder Flowが、受信したトランザクションに署名し、①のノードへ返信します。

③Initiating Flowをキックしたノードは必要な署名が集まった事を確認した上でNotaryへ送信し2重支払いが無い事(原本性と価値の移動の実現)を確認します。

Cordaのこのやり取りは、自ノードがトランザクションのコンテンツにあまり関与していなくても、署名して記録することが期待される状況に陥ることを意味します。

 


少しわき道にそれますが

 皆さんのメールボックスには迷惑メールフォルダが無いでしょうか?もしくは、自分には無関係なのに、なぜかCCに入れられたまま、延々と他人のやり取りを横目に見る事は無いでしょうか?

ブロックチェーンの有名なアナロジーがあります。

インターネットメールによって手紙のやり取りが電子化されたのと同じように、ブロックチェーンによって紙幣や契約書のやり取りが電子化される。

 ブロックチェーンが当たり前になった世界では、無関係だったり興味のないトランザクションが手元に届くことを想定せざるを得ないのです。

 世の中に、友人が自分を無視して飲み会に行った後、割り勘の清算メール(そしてその決済データ)が自分に届くことほど苦痛なことがあるでしょうか。

 


という事で

 自ノードにゴミが送られてこないようにする必要があります。それは、自ノード独自のFlowを構築し、そこで自ノードだけの要件を組み込むことで実現できます。エンタープライズ目線でいうと、Cordaを用いれば各社独自のビジネス要件を組み込んだエコシステムを構築する事ができるのです。

え、、、でも、、、、

と思ったあなたはスマートコントラクトに対する深い理解のある方だとおもいます。「これはスマートコントラクトではない」と。

そうですね。スマートコントラクトの定義はいろいろとありますが、例えば以下のようなものです。

スマートコントラクトを一言でいうと、「自分で実行した結果」と「相手が実行した結果」が必ず一致する仕組みである

 各ノードが独自のビジネス要件を組み込んでしまうと「自分で実行した結果」と「相手が実行した結果」が異なってくるのではないか?これは正解のようでいて正解ではないです。もう少しコードレベルで見ていきましょう。

以下のスニペットはResponderFlowの実例です。

 

@InitiatedBy(SendMessageFlow::class)
class SendMessageResponder(private val session: FlowSession) : FlowLogic<SignedTransaction>() {

@Suspendable
override fun call(): SignedTransaction {
val stx = subFlow(object : SignTransactionFlow(session) {
// [LedgerTransaction.verify] is called before [checkTransaction]
override fun checkTransaction(stx: SignedTransaction) {
val message = stx.coreTransaction.outputStates.single() as MessageState
check(message.recipient == ourIdentity) { "I think you got the wrong person" }
check(!message.contents.containsSwearWords()) { "Mind your language" }
check(!message.contents.containsMemes()) { "Only serious messages are accepted" }
check(message.sender.name.organisation != "Nigerian Prince") { "Spam message detected" }
}
})
return subFlow(ReceiveFinalityFlow(otherSideSession = session, expectedTxId = stx.id))
}
}

 このようなResponderFlowを書くことで、自ノード独自の検証を行う事ができます。(コードに興味が無ければ読み飛ばしていただいて大丈夫)

 注目すべきはコメント部分「// [LedgerTransaction.verify] is called before [checkTransaction]」です。

 ResponderFlowは上記のコードに従って独自に検証を行いますが、その前にSignTransactionFlow によって、LedgerTransaciton.verifyが実行されます。LedgerTransaction.verifyは何をしているのか?それはTxが指定した(有効な)Contractコードによる検証を行います。そうです、Cordaが保証するスマートコントラクトは、Contractによって実現します。

 Flowは各ノード独自の仕組みを構築してよいが、スマートコントラクトとして必要なキーとなるロジック(例えば、外国為替取引において、為替レートが正しくOracleにあっているかどうか、株式のDvP決済なら、株式価格と同額のキャッシュの移転が起きているかどうか)は、Contractに入れておく必要があります。スマートコントラクトの本体であるContractは専用のJarファイルとなり、そのJarファイルが正しい(改ざんされていない事)事は、ネットワークパラメータとInput Stateに基づく各種の制約により保証されます。


もう少し検証について話しましょう。

 Flowレベルの検証に何を含めるべきか?(もしくはContractレベルの検証に何を含めない方が良いのか)に関するアイデアです。

  • Identityの確認

 取引は私にとって重要かどうか?このトランザクションに実際に関与していることを確認することはFlowレベルで検証すべき事だと思います。(ただし、すべてのトランザクションを特定のノードが監視している場合もあり得ます)また、同種の話として自身が必ず買い手である事(もしくは逆に売り手であること)を確認するという検証もあります。基本的に自身のアイデンティティはContractからチェックできない(アクセスできない)ため、フロー内で実行する必要があります。

  • 自ノードの既存Stateとの重複確認

 新たに到着したトランザクションが含むデータは、自ノードの台帳データと比較して矛盾が無いでしょうか(既に発行されたはずのトークンが、再度発行されていないでしょうか?)トランザクションを提案しているノードにとっては一意であるかもしれませんが、他のノードにとってはそうではない場合もあるかもしれません。このような状況はプライバシーを確保した場合に必然的に表れるトレードオフです。

 そして、ノードの台帳データには、Contractからアクセスできません。したがって、VaultQueryを含む検証は、Flow上で実行する必要があります。

  • ビジネスロジック

 自ノードに送られてきたTxの取引条件はビジネス目線で許容できるものですか?例えば、一株2000円で買った株が、今一株500円で売るように依頼されたとしてそれを(スマートコントラクトとして)自動的に受け入れるべきでしょうか?Contractはビジネスルールを検証すべきではありません。(そもそも外部に出したくないルールも多数あるはずです。)

おわりに

 CorDapp開発者にとって、Flowにおける検証とContractにおける検証をどのように区別するかを理解する為に、この投稿を書きました。

 Contractによる検証だけで十分なCordappを書くことは(特にブロックチェーンの文脈では)非常に重要な視点かもしれません。しかし、FLowの中での検証は、CorDappに現実的な健全性を持たせる上で重要な役割を果たします。


 この記事はR3エンジニアDan Newtonの個人ブログを元に作成した記事です。但し、内容についての間違いはすべて私の責任です。

 

Created by: YuIku

Last edited by: YuIku

Updated: 2019/01/09

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