コンテンツにスキップ

第3章 リファレンスアーキテクチャと要件定義#

本章では、手を動かす前に全体設計と要件を確定します。本書が題材とするのは、私募債(プライベート・ボンド)をトークン化するプロジェクトです。以降の章(実装・テスト)は、すべて本章で定義する要件に対応づけて進めます。

本章の要件は、各要件に R-* 形式の ID を付けて定義します。この ID は第9章のテストケース表がトレーサビリティのために参照するもので、ID の定義元は本章です。

前提の確認(第2章より再掲): オンチェーンの残高が、法的な権利の唯一の根拠になるとは限りません。トークンが表章する権利の帰属は、採用する法的ストラクチャに依存します。証券該当性を含む法的判断は、専門家に確認してください。本書は技術設計を扱うものであり、法的助言ではありません。

3.1 要件定義#

3.1.1 ロールとユースケース#

本プロジェクトの登場者(ロール)は3種類です。

ロール 役割
発行体 トークンを発行する主体。凍結・強制回収などの統制権限を持つ
投資家 トークンを保有・移転する主体。KYC を経て許可された者に限る
管理者 許可リスト(レジストリ)を運用する主体。投資家の状態を登録・変更する

主なユースケースは、発行・移転・償還の3つです。

  • 発行: 発行体が、KYC 済みの投資家へトークンを配布する。
  • 移転: 投資家間でトークンを移転する。ただし許可済み投資家間に限る。
  • 償還: 満期・利払い時に、オンチェーン記録とオフチェーン送金を対応づけて処理する(オフチェーン連携は第8章)。

以降、これらを満たすための要件を、区分ごとに ID 付きで定義します。

3.1.2 移転制限の要件#

金融資産のトークン化で中核となるのが、移転を許可済み投資家間に限定する制御です。

要件ID 要件内容
R-TRANSFER-01 送信者・受信者の双方が Approved のときのみ、移転が成立する
R-TRANSFER-02 送信者または受信者が未許可(Suspended / 未登録)なら、移転は失敗する
R-HOOK-01 移転時に、送信者・受信者双方の許可状態を検証する仕組みを持つ

この検証は、Token-2022 の Transfer Hook 拡張と、許可リストを保持するレジストリの組み合わせで実現します(選定理由は 3.3、実装は第7章)。

3.1.3 凍結・凍結解除の要件#

発行体は、口座単位で移転を止められる必要があります。KYC 未完了の口座に、いきなりトークンが渡ることも防ぎます。

要件ID 要件内容
R-FREEZE-01 新規トークンアカウントは既定で Frozen とし、凍結解除(thaw)前は受領・移転できない
R-FREEZE-02 発行体は既存の口座を再度 freeze でき、freeze 中はその口座からの移転を止められる
R-THAW-01 KYC 完了(= レジストリ登録)後に thaw して、初めて配布・移転が可能になる

R-FREEZE-01 は、Token-2022 の Default Account State 拡張を Frozen に設定することで実現します(3.3)。「既定で凍結し、KYC を経てから解除する」という運用順序を、技術的に強制する設計です。

3.1.4 強制回収の要件#

規制対応(裁判所命令・当局の指示など)のため、発行体が投資家の同意なしにトークンを回収できる必要があります。これは最も強い権限であり、要件の書き方も厳密にします。

要件ID 要件内容
R-FORCE-01 発行体(Permanent Delegate 権限者)は、投資家の同意なしに強制移転・回収できる
R-FORCE-02 Permanent Delegate 以外の主体は、強制移転できない(権限の限定)

強制回収は Token-2022 の Permanent Delegate 拡張で実現します。ここで、本書の実装が採用した設計判断を要件レベルで明示します。

  • 送信者側の許可検証の免除は、Permanent Delegate 経路に限定する。 強制回収の対象は Suspended にした投資家であるのが典型のため、送信者に Approved を要求すると強制回収が機能しません。そこで、移転の authority がミントの Permanent Delegate 拡張が保持する値と一致する場合に限り、送信者側の Approved 検証を免除します。
  • 回収先(受信者)は Approved を必須とする。 免除は送信者側だけです。回収先は発行体の回収用トレジャリーアカウントとし、これをレジストリに Approved 登録します。
  • Hook を迂回する例外経路は作らない。 強制回収も Token-2022 の転送経路であり、Transfer Hook は同様に呼ばれます。コンプライアンス保証を崩さないためです。

この判断の根拠と検証は、第7章 7.5(実装)および第9章のテスト(T-20〜T-23)に対応します。

3.1.5 権限・セキュリティ要件#

レジストリの運用権限と、攻撃に対する頑健性の要件です。

要件ID 要件内容
R-AUTH-01 レジストリの状態変更は、管理者(has_one = admin)のみが行える
R-SEC-01 偽の許可レコード(所有者・シード不一致)は拒否される(account confusion 対策)
R-SEC-02 転送コンテキスト外からの Hook 直接呼び出しは拒否される
R-SEC-03 追加アカウントを差し替え・省略して Hook の検証を迂回できない

R-AUTH-01 の権限保持のあり方(マルチシグ前提)は 3.5 で、R-SEC-* の対策実装は第7章・第10章で扱います。

3.1.6 要件ID一覧(トレーサビリティの起点)#

本章で定義した要件を一覧にします。この表が、第9章テストケース表のトレース元です。第9章は各テストをこの ID に対応づけ、未カバーの要件がないことを機械的に確認します。

要件ID 区分 要件内容 主に対応するコンポーネント
R-TRANSFER-01 移転 双方 Approved のときのみ移転成立 Transfer Hook + レジストリ
R-TRANSFER-02 移転 未許可(Suspended/未登録)なら移転失敗 Transfer Hook + レジストリ
R-HOOK-01 移転 移転時に双方の許可状態を検証 Transfer Hook
R-FREEZE-01 凍結 新規口座は既定 Frozen、thaw 前は受領・移転不可 Default Account State
R-FREEZE-02 凍結 既存口座を再 freeze でき、freeze 中は移転停止 Token-2022 freeze authority
R-THAW-01 凍結 KYC 完了後に thaw して配布・移転が可能 freeze authority + レジストリ
R-FORCE-01 強制回収 Permanent Delegate は同意なしに強制回収できる Permanent Delegate
R-FORCE-02 強制回収 Permanent Delegate 以外は強制移転できない Permanent Delegate + Hook
R-AUTH-01 権限 状態変更は管理者のみ レジストリ(Config)
R-SEC-01 セキュリティ 偽の許可レコードを拒否 Transfer Hook(PDA 検証)
R-SEC-02 セキュリティ 転送外からの Hook 直接呼び出しを拒否 Transfer Hook(transferring 検証)
R-SEC-03 セキュリティ 追加アカウントの差し替え・省略を拒否 Transfer Hook(追加アカウント検証)

上表の要件は全12件です(R-TRANSFER-01/02、R-HOOK-01、R-FREEZE-01/02、R-THAW-01、R-FORCE-01/02、R-AUTH-01、R-SEC-01/02/03)。第9章のカバレッジ表と件数・ID が一致します。

3.2 全体アーキテクチャ#

システムはオンチェーンとオフチェーンに分かれます。オンチェーンは移転制限を技術的に強制する部分、オフチェーンは KYC 審査・アテステーション発行・資産データ管理など、チェーン外で行う部分です。

flowchart TB
    subgraph OFF["オフチェーン"]
        KYC["KYC プロバイダ<br/>(本人確認・適格性審査)"]
        SASI["アテステーション発行者<br/>(SAS 等・任意)"]
        API["発行体の管理用 API<br/>(登録・状態変更の実行)"]
        DATA["資産データ<br/>(償還・利払いの原簿)"]
    end

    subgraph ON["オンチェーン"]
        MINT["Token-2022 ミント<br/>(5 拡張付き)"]
        HOOK["Transfer Hook<br/>プログラム"]
        REG["レジストリ<br/>(許可リスト)"]
    end

    KYC -->|審査結果| API
    API -->|register / set_status| REG
    MINT -->|転送時に CPI| HOOK
    HOOK -->|InvestorStatus を参照| REG
    SASI -.->|将来: アテステーション参照| HOOK
    DATA -.->|償還・利払いの突合| API

要点は次のとおりです。

  • 移転可否を決めるのはオンチェーンです。Token-2022 ミントが移転のたびに Transfer Hook を呼び、Hook がレジストリの許可状態を参照して可否を判定します。
  • 審査そのものはオフチェーンです。KYC 審査の結果を、管理者が API 経由でレジストリに反映します。チェーンは「審査済みか」の結果だけを保持します。
  • 点線は将来・任意の拡張です。アテステーション参照(SAS)は本書のリファレンス実装では未実装で、設計方針のみを示します(3.4、第7章 7.4)。

3.3 Token Extensions の選定#

3.3.1 なぜ標準 SPL Token ではなく Token-2022 か#

標準の SPL Token には、移転時に外部プログラムを呼ぶ仕組みがありません。したがって「移転を許可済み投資家間に限る」制御を、トークン自体の機能として組み込めません。Token-2022(Token Extensions)は Transfer Hook をはじめとする拡張を持ち、移転制限・凍結・強制回収を標準機能として実現できます。このため本書では Token-2022 を採用します。

3.3.2 採用する拡張と要件の対応#

本書のミント(scripts/create-mint.ts)が実際に付与する拡張は、次の5つです。各拡張は 3.1 の要件に対応します。

拡張 対応要件 採用理由
Transfer Hook R-TRANSFER-01/02, R-HOOK-01 移転時に外部プログラム(Hook)を呼び、許可状態を検証するため
Permanent Delegate R-FORCE-01/02 発行体による強制回収を可能にするため
Default Account State R-FREEZE-01 新規口座を既定 Frozen にし、KYC 前の受領を防ぐため
Metadata Pointer (メタデータ設計) メタデータの所在をミント自身に指すため(第6章)
Token Metadata (メタデータ設計) 名称・シンボル等のメタデータをミントに格納するため(第6章)

3.3.3 非採用の拡張と、その理由#

Token-2022 には他にも多くの拡張がありますが、本プロジェクトの要件には不要、または方針に合わないため採用しません。代表例を挙げます。

  • Transfer Fee(送金手数料): 私募債の移転制限が目的であり、手数料徴収は要件外です。
  • Confidential Transfer(秘匿送金): 発行体・管理者が移転を監査できる必要があるため、残高・移転額を秘匿する方針とは相容れません。
  • Interest-Bearing(利子付き): 利払いはオフチェーンの原簿と対応づけて処理する方針(第8章)であり、トークン残高を自動増加させる拡張は使いません。

3.3.4 設計上の最重要制約:ミント側拡張は後から追加できない#

ミント側の拡張は、ミント作成時に確定し、後から追加できません。 一方、トークンアカウント側の一部拡張は、口座の作成後に有効化できるものがあります。この2つを混同しないでください。

本章の選定を「実装より前に」確定させる理由は、まさにこの制約にあります。ミントを作ってしまうと拡張構成は変えられないため、要件から必要な拡張を洗い出し、作成前に確定しておく必要があります。拡張の初期化順序(拡張初期化 → ミント初期化)を含む実装の詳細は、第6章で扱います。

3.4 コンプライアンス設計パターンの比較#

移転制限を実現する設計には複数のパターンがあります。本節では3つを比較し、本書がどれを選ぶかを判断します。各パターンの実装は本節では扱わず、選定判断に集中します(実装は第7章。とくにパターン b の SAS は 7.4)。

パターン 概要 信頼モデル 限界
a. Transfer Hook + オンチェーン許可リスト Hook が発行体運用のレジストリを参照して可否判定 発行体(レジストリ管理者)を信頼する 許可状態の更新は管理者の運用に依存する
b. アテステーション参照(SAS 等) KYC プロバイダ等が発行したアテステーションを Hook が検証 アテステーション発行者を信頼する 発行者の管理・失効の扱いが設計の要点になる
c. 標準 SPL + オフチェーン統制のみ オンチェーンでは制限せず、オフチェーンの規約・監視で統制 オフチェーン運用を信頼する オンチェーンでは移転を技術的に止められない

本書はパターン a を選定します。 理由は次のとおりです。

  • 発行体が統制主体である私募債では、「発行体が運用するレジストリを信頼する」モデルが自然で、権限の所在が明確です。
  • 移転可否をオンチェーンで技術的に強制できます(パターン c はこれができません)。
  • パターン b のアテステーション参照は有力な選択肢ですが、発行者の管理・失効の設計が追加で必要になり、SAS の仕様確認も要します。本書はまず a を実装し、b は将来の拡張・併用の候補として位置づけます。

なお a と b は排他ではなく、レジストリで発行体の統制を効かせつつ、アテステーションで外部審査結果を取り込む併用も考えられます。この設計方針の詳細と、SAS の最新仕様確認の必要性は、第7章 7.4 で扱います。

3.5 鍵管理・権限設計#

本システムには、強い権限が複数あります。それぞれを誰が保持するかを設計で確定します。

権限 対象 保持者(実運用の想定)
mint authority 新規発行 発行体(マルチシグ)
freeze authority 口座の freeze / thaw 発行体(マルチシグ)
permanent delegate 強制回収 発行体(マルチシグ)
upgrade authority プログラムの更新 発行体(マルチシグ)
レジストリ admin 投資家状態の変更 管理者(マルチシグ)

実運用では、これらの権限をマルチシグで保持することを前提とします。 単一の鍵にこれだけの権限が集中すると、その鍵の漏洩が全体の危殆化に直結するためです。権限のマルチシグ化・ローテーションの手順は第10章で扱います。

テストとの書き分け: 本書の統合テスト(第9章)では、簡略化のため単一の payer が上記の権限を兼務します。これはテストを読みやすくするための構成であり、実運用の推奨ではありません。実運用では権限を分離し、マルチシグ化してください。

3.6 アカウント(PDA)設計#

レジストリの状態は、2種類の PDA(Program Derived Address)に格納します。実装(programs/registry/src/state.rs / constants.rs)の定義に対応します。

  • Config PDA — レジストリ全体の設定。シード ["config"] から導出される単一の PDA。
  • InvestorStatus PDA — 投資家1名分の許可状態。シード ["investor", investor_pubkey] から導出。

加えて、Transfer Hook は追加アカウントの定義を格納する ExtraAccountMetaList PDA(ミントごと)を持ちます(第7章)。

各 PDA のフィールドは次のとおりです。

classDiagram
    class Config {
        +Pubkey admin
        +u8 bump
        seeds = ["config"]
    }
    class InvestorStatus {
        +Pubkey investor
        +InvestorState state
        +u8 bump
        seeds = ["investor", investor_pubkey]
    }
    class InvestorState {
        <<enumeration>>
        Approved
        Suspended
    }
    InvestorStatus --> InvestorState : state

設計上の要点は次のとおりです。

  • Config は単一インスタンスです。シードに可変要素がないため、ワークスペースに1つだけ存在します。admin が状態変更の唯一の権限者です(R-AUTH-01)。
  • InvestorStatus は投資家ごとに1つです。シードに投資家のアドレスを含むため、投資家1名につき1つの PDA が決まります。state が Approved / Suspended を保持します。
  • 許可状態は Approved / Suspended の2値です。KYC 失効・凍結などで移転を認めない状態を Suspended で表します。

Hook が許可レコードを検証する際は、この PDA の所有者がレジストリであることと、シードが正しいことを確認します。これにより、偽のレコードや他人のレコードの流用を拒否します(R-SEC-01。実装は第7章 7.3)。

3.7 KYC からの全体フロー(概要)#

投資家がトークンを保有できるようになるまでの流れを、全体像として示します。登場者と大まかな順序を確認することが目的です。プロバイダ連携・API・thaw 操作を含む実装レベルの詳細シーケンスは、第8章 8.2(オフチェーン連携)で扱います。

大まかな流れは次のとおりです。

  1. KYC 審査(オフチェーン): KYC プロバイダが投資家の本人確認・適格性を審査する。
  2. レジストリ登録: 審査を通過した投資家を、管理者が Approved でレジストリに登録する(R-THAW-01 の前提)。
  3. 口座の凍結解除(thaw): 発行体が投資家のトークンアカウントを thaw する。新規口座は既定 Frozen のため、この操作で初めて受領可能になる(R-FREEZE-01 / R-THAW-01)。
  4. 配布・移転: 発行体が発行し、以降は許可済み投資家間で移転できる(R-TRANSFER-01)。
  5. 状態変更・強制回収(必要時): 適格性を失った投資家を Suspended にし、必要に応じて強制回収する(R-FREEZE-02 / R-FORCE-01)。

各ステップの具体的な API 呼び出し・プロバイダ連携・詳細なシーケンス図は、第8章 8.2.2 を参照してください。 本章は要件とアーキテクチャの確定に留めます。

3.8 本章の自己チェック表#

観点 結果
スタイル規則違反 なし(です・ます調、一文概ね80字以内、相互参照は番号、図は Mermaid、価格・投資リターン・マーケティング語彙・法的判断示唆なし。冒頭に法的権利に関する注意を明記)
[要検証] の残数 0件(要件・設計は実装済みリポジトリと本章内で定義。SAS は「未実装・選定のみ」と明記し断定を避けたためタグ不要)
バージョン表との不一致 なし(本章はバージョン依存の具体コマンドを含まない。拡張・仕様の帰属は一次情報で確認。本文中に「latest」「最新版」の記載なし)
R-* 整合(対 第9章) 一致。本章 3.1.6 で全12件(R-TRANSFER-01/02, R-HOOK-01, R-FREEZE-01/02, R-THAW-01, R-FORCE-01/02, R-AUTH-01, R-SEC-01/02/03)を定義。ID・内容が docs/test-cases-ch9.md のトレース元と一致
実装との一致 PDA 設計(3.6)は state.rs/constants.rs、拡張選定(3.3)は create-mint.ts の5拡張、強制回収要件(3.1.4)は transfer_hook/src/lib.rs の免除ロジックと一致(構想でなく実装の記述)
章間の役割分担 パターン比較(3.4)は選定判断のみ・実装は第7章 7.4 へ誘導。KYC フロー(3.7)は全体像のみ・詳細シーケンスは第8章 8.2 へ誘導(シーケンス図本体は第8章 8.2.2)