愛記システムの基本設計:フェデレーションモデルのブロックチェーン 合意形成フロー | 続・ティール組織 研究会のブログ

続・ティール組織 研究会のブログ

ティール組織が話題になっているが、具現化するにはどうしたらよいか?
その研究を続けるにあたり、さらに次の形態である、続・ティール組織なるものまで視野に入れ、具体的な施策・行動内容を研究・支援する会。

先までは、"愛記"についての記載で、どのようにブロックチェーンSNSに組み込んで実装していけばよいのか、概念的なところからアプローチ方法を記載していった。概念設計としてはひとまず終えた。次は、フェデレーションモデル全体の基本設計といえるところまで、基本設計書に着手できるようなところまで、概念を具体化していきたい。

 

フェデレーションモデルのブロックチェーンの基本設計を進めるには、以下の手順に従って詳細に設計していくことが重要である。これにはシステムの機能、アーキテクチャ、データフロー、技術スタック、および具体的な実装方法の設計が含まれる。

基本設計のステップ

  1. 要求分析

  2. システムアーキテクチャの設計

  3. データフローの設計

  4. 技術スタックの選定

  5. データモデルの設計

  6. API設計

  7. セキュリティ設計

  8. エラーハンドリングとログ設計

基本設計の各ステップを順番に進めることで、フェデレーションモデルのブロックチェーンの詳細な設計が可能になる。各ステップでは、関係者との協議やレビューを通じて設計内容を確定していくことが重要である。

1.要求分析

まず、基本設計の最初のステップである要求分析をしていきたい。どのような機能が必要か、どのような問題を解決するのかを洗い出したい。要求分析はシステム設計の最初の重要なステップであり、システムが解決するべき問題と、必要な機能を明確に定義するプロセスである。以下に、メインチェーンとフェデレーションモデルでつながる市町村のブロックチェーンのプログラムに必要な機能と解決すべき問題を列挙してみよう。

解決すべき問題

  1. データの一貫性と整合性

  2. スケーラビリティとパフォーマンス

  3. ガバナンスとコンセンサス

  4. システムの拡張性

  5. トランザクションの信頼性とセキュリティ

  6. トランザクションのトレーサビリティ

必要な機能

  1. トランザクション生成

  2. トランザクションの検証

  3. トランザクション承認と統合

  4. ブロック生成

  5. 自治体の登録と管理

  6. 履歴証明(Proof of History)

  7. APIゲートウェイ

  8. ガバナンス機能

  9. セキュリティ機能

  10. スケーラビリティとパフォーマンス最適化

コンセンサスの設計項目

  1. コンセンサスアルゴリズムの選定

    • DPoS (Delegated Proof of Stake): 市町村代表がトランザクションを承認するためのアルゴリズム。
    • PoP(Proof of Place): 位置証明。各ノードや承認の位置を証明することで、地域間の利益を演出するためのアルゴリズム。
    • PoH (Proof of History): 履歴証明。トランザクションの順序を保証するためのアルゴリズム。
  2. 代表選出のメカニズム

    • 選出プロセス: 代表ノードを選ぶためのプロセス(例: 投票、ランダム選出)。
    • 任期と再選ルール: 代表ノードの任期や再選ルールを設定。
  3. コンセンサスの合意形成

    • 合意形成のフロー: トランザクションがどのように承認されるか(例: 提案→検証→承認)。
    • コンフリクト解決メカニズム: コンフリクトが発生した場合の解決方法(例: 再投票、仲裁)。
  4. コンセンサスの拡張性と効率化

    • スケーラブルな合意形成: ノード数が増えてもコンセンサスを効率的に行うための手法。
    • APIゲートウェイ: 効率的でセキュリティも強化されたAPIが必要。
    • 最適化戦略: コンセンサスプロセスを最適化するための技術的手法(例: 先行承認、PoP活用)。
       

合意形成のフロー

これまでの内容をもとに、Municipal_ChainとContinental_Main_Chainの設計を行う。今回は各フェーズごとに具体的なデータフローとロジックを丁寧に解説したい。

1. Municipal Chainの設計

Municipal Chainは、各市町村ごとに存在し、住民が提案するトランザクションを受け付け、それを承認する役割を持つ。トランザクションが承認されると、Continental_Main_Chainに送信される。

1.1 トランザクション提案フェーズ

誰が: トランザクションの送信者(市町村内の住民)

何を: トランザクションを提案し、Municipal Chainに送信

いつ: トランザクションが生成されたとき

どのように:

  1. DAppsでのトランザクション生成: 住民がDApps(デジタルアプリケーション)を使用してトランザクションを作成する。このトランザクションには、送信者、受信者、金額、トランザクションの詳細情報(例: PoP証明、アクションレベル、ディメンションなど)が含まれる。
  2. Municipal_Chainへのトランザクション送信: DAppsは生成されたトランザクションをMunicipal_Chainに送信する。

1.2 トランザクション検証フェーズ

誰が: Municipal_Chainの代表者(DPoSにより選出)

何を: トランザクションの内容と送信者のPoP証明を検証

いつ: トランザクションがMunicipal_Chainに送信された後

どのように:

  1. DPoSによる代表者の選出: Municipal_Chainは、DPoS(Delegated Proof of Stake)を使用して代表者を選出する。選ばれた3人の代表者のうち1人がランダムに選ばれてトランザクションを検証する。
  2. PoP(Proof of Place)の検証: 選ばれた代表者がトランザクションのPoP証明を検証する。これにより、送信者が指定された場所にいることが確認される。
  3. トランザクションの承認: トランザクションの内容とPoP証明が正しいと確認された場合、代表者がトランザクションを承認する。

1.3 トランザクション承認フェーズ

誰が: Municipal_Chainの代表者

何を: トランザクションを承認し、Continental_Main_Chainに送信

いつ: 検証フェーズが完了した後

どのように:

  1. トランザクションのContinental_Main_Chainへの送信: Municipal_Chainで代表者がトランザクションを承認すると、そのトランザクションはContinental_Main_Chainに送信される。
  2. PoH(Proof of History)の生成: 承認されたトランザクションは、PoHによってタイムスタンプが記録され、履歴が保証される。

2. Continental Main Chainの設計

Continental_Main_Chainは、大陸ごとに存在し、Municipal_Chainから送信されたトランザクションを一時的に保留し、受信者がそのトランザクションを受信する際に処理を完了する。

2.1 トランザクション保留フェーズ

誰が: Continental_Main_Chain

何を: Municipal_Chainから送信されたトランザクションを一時的に保留

どのように:

  1. トランザクションの受信: Continental_Main_Chainは、Municipal_Chainから送信されたトランザクションを受信し、それを保留リストに追加する。
  2. MongoDBへの保存: 保留されたトランザクションは、MongoDBに保存される。これにより、受信者がトランザクションを受信するまでデータが保護される。

2.2 トランザクション受信フェーズ

誰が: トランザクションの受信者

何を: トランザクションの受信を確認し、Continental Main Chainに通知

どのように:

  1. 受信信号の送信: 受信者がトランザクションを受け取りたい場合、DAppsを介して受信信号を送信する。この信号がContinental_Main_Chainに届くと、該当するトランザクションがMunicipal_Chainに返される。
  2. Municipal_Chainへの送信: Continental_Main_Chainは、該当するMunicipal_Chainにトランザクションデータを送信する。

2.3 トランザクション完了フェーズ

誰が: Municipal Chainの代表者とContinental Main Chain

何を: トランザクションの完了を確定し、愛貨を交換

どのように:

  1. Municipal Chainでの承認: 受信者のMunicipal Chainで、再度代表者が選出され、トランザクションが承認される。
  2. 愛貨の交換: トランザクションが承認されると、愛貨が送信者から受信者に移動する。これでトランザクションは完了し、データがMongoDBから削除される。

3. Rustコード設計

3.1 Municipal Chainの実装

Municipal Chainは、トランザクションの提案、検証、承認を行う。

use std::collections::HashMap;
use rand::seq::SliceRandom;
use tokio::sync::Mutex;
use rocket::State;
use rocket::serde::json::Json;
use rocket::http::Status;
use std::sync::Arc;

#[derive(Clone, Debug)]
struct Transaction {
    transaction_id: String,
    sender: String,
    receiver: String,
    amount: f64,
    pop_proof: String,
    timestamp: String,
    municipality: String,
    // その他のフィールド...
}

struct Representative {
    id: u32,
    name: String,
    verified: bool,
}

struct MunicipalChain {
    representatives: Vec<Representative>,
    transactions: HashMap<String, Transaction>,
    approvals: HashMap<String, u32>,
}

impl MunicipalChain {
    fn new(representatives: Vec<Representative>) -> Self {
        Self {
            representatives,
            transactions: HashMap::new(),
            approvals: HashMap::new(),
        }
    }

    fn propose_transaction(&mut self, transaction: Transaction) {
        self.transactions.insert(transaction.transaction_id.clone(), transaction.clone());
        self.approvals.insert(transaction.transaction_id.clone(), 0);
        self.verify_transaction(transaction.transaction_id.clone());
    }

    fn verify_transaction(&mut self, transaction_id: String) {
        if let Some(transaction) = self.transactions.get(&transaction_id) {
            let mut rng = rand::thread_rng();
            let selected_representative = self.representatives.choose_mut(&mut rng).unwrap();
            println!("Representative {} selected for verification", selected_representative.name);

            if self.validate_pop(transaction) {
                selected_representative.verified = true;
                *self.approvals.get_mut(&transaction_id).unwrap() += 1;
            } else {
                println!("Transaction {} verification failed", transaction_id);
            }

            self.check_approval_status(transaction_id);
        }
    }

    fn validate_pop(&self, transaction: &Transaction) -> bool {
        !transaction.pop_proof.is_empty()
    }

    fn check_approval_status(&self, transaction_id: String) {
        let required_approvals = self.representatives.len() / 2 + 1;
        if let Some(&approval_count) = self.approvals.get(&transaction_id) {
            if approval_count >= required_approvals as u32 {
                println!("Transaction {} is fully approved", transaction_id);
                // Continental Main Chainに送信
            } else {
                println!("Transaction {} requires more approvals", transaction_id);
            }
        }
    }
}
 

3.2 Continental_Main_Chainの実装

Continental_Main_Chainは、Municipal_Chainから送信されたトランザクションを受信し、受信者からの信号を待つ。

use rocket::serde::json::Json;
use rocket::State;
use rocket::http::Status;
use tokio::sync::Mutex;
use std::sync::Arc;
use mongodb::{bson::doc, Client as MongoClient, Collection};
use mongodb::bson::Document;
use std::collections::HashMap;

#[derive(Clone, Debug)]
struct Transaction {
    transaction_id: String,
    sender: String,
    receiver: String,
    amount: f64,
    municipality: String,
    // その他のフィールド...
}

#[derive(Clone)]
struct AppState {
    pending_transactions: Arc<Mutex<HashMap<String, Transaction>>>,
    mongo_collection: Collection<Document>,
}

async fn save_transaction_to_mongo(transaction: &Transaction, collection: &Collection<Document>) -> Result<(), mongodb::error::Error> {
    let doc = doc! {
        "transaction_id": &transaction.transaction_id,
        "sender": &transaction.sender,
        "receiver": &transaction.receiver,
        "amount": &transaction.amount,
        "municipality": &transaction.municipality,
        // その他のフィールド...
    };

    collection.insert_one(doc, None).await?;
    Ok(())
}

#[post("/receive_transaction", format = "json", data = "<transaction>")]
async fn receive_transaction(
    transaction: Json<Transaction>, 
    state: &State<Arc<Mutex<AppState>>>
) -> Status {
    let transaction = transaction.into_inner();

    let mut state = state.lock().await;

    if let Err(e) = save_transaction_to_mongo(&transaction, &state.mongo_collection).await {
        println!("Failed to save transaction: {:?}", e);
        return Status::InternalServerError;
    }

    state.pending_transactions.insert(transaction.transaction_id.clone(), transaction.clone());

    Status::Accepted
}

#[post("/query_transaction", format = "json", data = "<query>")]
async fn query_transaction(
    query: Json<Transaction>, 
    state: &State<Arc<Mutex<AppState>>>
) -> Status {
    let mut state = state.lock().await;

    if let Some(transaction) = state.pending_transactions.remove(&query.transaction_id) {
        let municipal_chain_url = format!("http://{}/receive_transaction", transaction.receiver);
        let client = Client::new();
        let res = client.post(&municipal_chain_url).json(&transaction).send().await;

        if res.is_ok() {
            Status::Accepted
        } else {
            Status::InternalServerError
        }
    } else {
        Status::NotFound
    }
}

4. まとめ

この設計では、Municipal_ChainとContinental_Main_Chainが連携して、トランザクションが安全かつ効率的に処理されることを目指す。Municipal_Chainはトランザクションの提案から承認までを行い、Continental_Main_Chainはトランザクションを一時的に保留し、受信者がそのトランザクションを受け取るときに処理を完了する。

 

 

いかがであろうか、合意形成フローはシンプルだが、ここにセキュリティやら署名やらDBの認証やら、いろんなものが入ってくる。まずは、このシンプルな合意形成フローが基本設計となる。