Logo
    Logo

    Search

    R3-Solana連携

    Blockchainトレンド

    Corda活用事例

    Corda技術

    おすすめ記事

    記事を探す

    その他

    お客様サポート

    SBI R3 Japan HP

    お問い合わせ

    Flow拡張(Cordaのスマートコントラクト-その2)

    公開日
    Jan 23, 2020
    カテゴリ
    Corda技術を知る
    タグ
    🧑‍💻CorDapp開発
    筆者
    生永
    image
    icon
    この記事で学べること

    実装に柔軟性を持たせるためのFlowによるカスタム検証について理解する

    ⚠️
    この記事はR3エンジニアDan Newtonの個人ブログを元に作成した記事です。但し、内容についての間違いはすべて筆者の責任です。
    icon
    目次
    • 前置き
    • アプリケーションロジックがれている場合どのように実装しますか?
    • 拡張可能なFlowが(スマートコントラクトの文脈で)意味を持つ理由
    • CorDapp開発者がしなければならないこと
    • 外部開発者がしなければならないこと
    • まとめ
    ⬅️
    前回の記事はこちら FlowとContractの役割分担(Cordaのスマートコントラクト-その1)

    前置き

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

    次のような質問を考えましょう。

    アプリケーションロジックがれている場合どのように実装しますか?

    では早速答えを。でもその前に、少し免責事項があります。この投稿で説明する内容には、Cordaのアプリケーション(以下CorDapp)開発者の協力が必要です。また、このためには開発者は必要な手順にきちんと従う必要があります。そうしない場合、CorDappは難しく、エラーを起こす可能性は非常に高くなります。(もちろん、既にCorDappを開発した事があれば大丈夫です)

    この記事では、CorDapp開発経験がある事を仮定します。その上で外部開発者が独自のコードを作用させる事ができる、拡張可能なCorDappの作成方法を紹介します。具体的には、作成したresponderflowに追加の検証を実装できるようにします。今回は検証の実装について説明し、次回拡張可能なFlowの書き方について説明します。次の記事を待たず、拡張可能なFlowの書き方について知りたい方は、こちらをご覧ください。

    拡張可能なFlowが(スマートコントラクトの文脈で)意味を持つ理由

    Cordaでは、組織は共有されたコードを介して相互にやり取りします。つまり、すべての組織がまったく同じコードを実行する事を前提としています。このモデルが導く(そしてスマートコントラクトの文脈が導いてしまう)誤った仮定は、すべての企業が同一のプロセスを持っている(もしくは持つことができる)という仮定です。現実を見ましょう。全ての企業が同一のプロセスを持つなど不可能です。どこかに、違いがあります。

    CorDaは(そして当然に他のブロックチェーン/分散台帳基盤も)この現実を受け入れる必要があります。Corda(そしてあらゆるブロックチェーン/分散台帳基盤)は、組織間でプロセスを統合するために最善を尽くす事が前提です。しかし、企業が分散アプリケーションに真に切り替える過程で、ローカルのカスタマイズが必要であるという事実に変わりはありません。

    次回説明する予定ですが、Flowを拡張することで、別のCorDappに定義された追加のロジックを適用できます。Flow Extension(Flow拡張)を使用することで、アプリケーションへ独自検証を注入する事ができるようになります。

    CorDapp開発者がしなければならないこと

    以下のような手順を踏むだけで、Extensible Flow(拡張可能なフロー)を作成する事ができます。

    ・Flowはopen(Kotlin)であるか、もしくはfinal(Java)でない必要があります.

    ・overrideできる(継承先のクラスで上書き可能な)関数を用意します

    ・オーバーライド可能な関数は、必要な場所で呼び出す必要があります

    次のResponderFlowには、上記のすべてのポイントが実装されています。

    さて、先ほど示した3つステップのうち、最後の、そして若干あいまいな3つ目のステップについて考えましょう。

    ・オーバーライド可能な関数は、必要な場所で呼び出す必要があります

    SignTransactionFlow.checkTransactionが、オーバーライド関数を呼び出すのに最適な場所です。checkTransactionトランザクションは、トランザクションへ署名する前に必ずトリガーされるため、ここにルールを追加することは理にかなっています。別の場所に配置することもできますが、コードの効率が低下し、追跡が難しくなります。この点については、前回の記事でも説明しました。

    さて、このように定義されたFlowを定義することで、外部開発者は、このFlowの活用法として、以下の二つの方法を選択できます。

    • 通常のフローと同様に、フローを直接使用します。オリジナルの。checkTransactionが実行されることを意味します。
    • フローを拡張し、独自のカスタム検証を含めることにより、フローを活用します。

    先に進む前に、コードに含めた以下のコメントに触れましょう。

    // [call]関数は上書きできないようfinalにします.
    final override fun call(): SignedTransaction {

    これは重要ではないかもしれません。しかし、外部アプリケーションがフローを過度に変更することを防ぐことにより、フローが誤動作する可能性を減らします。sendとreceiveのバランスが崩れFlowが正しく動作しなくなったりします。もちろん、finalを宣言しても、厳密にはこの問題を防ぐことはできません。ただし、実装に明確な宣言を提供することにより、開発者は間違いを犯しにくくなります。

    外部開発者がしなければならないこと

    拡張可能なフローを拡張して活用するには、次のことを行う必要があります。

    • Flowを拡張する
    • 拡張したflowクラスに@InitiatedByアノテーションを含める
    • 実装する

    つまり、KotlinまたはJavaの普通のクラスの継承と同じです。例えば以下の様になります。

    SendMessageResponderクラスは拡張されて、checkTransactionにカスタム検証を含むようになりました。Cordaは、すべてのSendMessageResponderのセッションを、ValidatingSendMessageResponderへ自動的に送付します。

    CorDapp開発者が拡張可能な準備をした場合、外部開発者は非常に簡単なタスクのみを実行すればよい事になります。

    まとめ

    なぜフロー拡張(Flow Extension)機能がカスタム検証を注入するための理想的なソリューションを提供するのか、そしてどう実装するのかについて検討しました。トランザクション検証を拡張可能であるよう最初から実装することで、柔軟性を手に入れる事ができます。

    柔軟性を見せる事で、エコシステムへの参加を検討する企業は、それぞれのニーズを満たすことができると確信する事ができます。

    つまり、柔軟性を持たせる事で、既存のレガシーアプリケーションから移行が進むのです。

    📬
    最後までお読みいただきありがとうございます。当社へのご質問・ご要望がございましたら、📪SBI R3 Japan お問い合わせフォーム📪よりお気軽にお問い合わせください!

    <ご質問・ご要望の例>

    • Corda Portalの記事について質問したい
    • ブロックチェーンを活用した新規事業を相談したい
    • 企業でのブロックチェーン活用方法を教えて欲しい 等々
    📢
    また、厳選されたCordaに関する最新情報をお伝えるするメールマガジンやX、当社主催のイベントコミュニティを運営しております。ぜひご登録ください。
    • Cordaメールマガジンに登録
    • X(旧Twitter)をフォロー
    • 弊社イベントコミュニティ(Connpass)に参加
    ✍️
    Written by 生永 雄輔 (Yusuke Ikunaga)
    image

    SBI R3 Japan エンジニアリング部長

    書籍出してます:https://amzn.asia/d/c0V31Vd 

    趣味:サッカー、ガンプラ、ドライブ、キャンプ

    →筆者の記事一覧

    Logo

    © copyright SBI R3 Japan 2025

    GitHubYouTubeXFacebookLinkedIn
    @InitiatedBy(SendMessageFlow::class)
    // flowはOpenです
    open class SendMessageResponder(private val session: FlowSession) : FlowLogic<SignedTransaction>() {  // 追加検証を提供する為のoverridableな関数を用意します
      open fun checkTransaction(stx: SignedTransaction) {
        // To be implemented by sub type flows - otherwise do nothing
      }  @Suspendable
      // [call]関数は上書きできないようfinalにします.
      final override fun call(): SignedTransaction {
        val stx = subFlow(object : SignTransactionFlow(session) {
          override fun checkTransaction(stx: SignedTransaction) {
            // The validation function is called
            this@SendMessageResponder.checkTransaction(stx)
            // Any other rules the CorDapp developer wants executed
          }
        })
        return subFlow(ReceiveFinalityFlow(otherSideSession = session, expectedTxId = stx.id))
      }
    }
    @InitiatedBy(SendMessageFlow::class)
    class ValidatingSendMessageResponder(session: FlowSession) : SendMessageResponder(session) {  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" }
      }
    }