愛記システムの基本設計:DApps側である愛記システム 取引の透明性の確保 データベースの設計 | 続・ティール組織 研究会のブログ

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

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

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

 

愛の行動のPL,BSを決算書として、個人単位、市町村単位、で公表するような愛記システムというものを考えている。愛の行動のデータベースはブロックチェーンのプログラムであり、日々の愛の行動による愛貨の移動を決算書にまとめていきたい。なお、市町村のブロックチェーンのプログラムは以前にも記載している。その市町村のブロックチェーンのプログラムにつながる愛記システムを、DApps側であるPythonプログラムとして設計したい。その場合、基本設計をどのような手順で進めていけばよいか、詳しく見ていこう。

 

愛記システムを設計するための基本手順を以下に示す。このシステムは、Pythonを用いて市町村のブロックチェーンと連携し、個人および市町村単位での愛の行動のデータを収集、記録し、決算書(PL、BS)として公表するものである。

基本設計のステップ

  1. 要件定義
  2. アーキテクチャ設計
  3. データベース設計
  4. API設計
  5. ブロックチェーンインターフェース
  6. 決算書の生成
  7. フロントエンド開発
  8. テストとデプロイ

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

1.要件定義

まず、基本設計の最初のステップである要件定義をしていきたい。どのような機能が必要か、どのような問題を解決するのかを洗い出したい。要件定義はシステム設計の最初の重要なステップであり、システムが解決するべき問題と、必要な機能を明確に定義するプロセスである。以下に、愛記システムのプログラムに必要な機能と解決すべき問題を列挙してみよう。

機能要件

  1. 愛の行動の記録

  2. 愛貨の移動の記録

  3. 決算書の生成

  4. 個人および市町村単位でのデータの集約

  5. データのブロックチェーンへの記録と取得

  6. 愛貨の管理

  7. ユーザー管理

  8. 通知機能

  9. レポート機能

  10. ダッシュボード

非機能要件

  1. セキュリティ

  2. 可用性

  3. パフォーマンス

  4. スケーラビリティ

  5. ユーザビリティ

  6. コンプライアンス

解決すべき問題

  1. 透明性と信頼性の確保

  2. データの一元管理

  3. 愛の行動の促進

  4. 評価制度の確立

  5. データのセキュリティとプライバシーの保護

これらの要件を基に、愛記システムの基本設計を進めていくことが重要である。次のステップでは、これらの要件を具体的なアーキテクチャ設計に反映していくことになる。まずは、要件定義の解決すべき問題を一つずつクリアにしていきたい。

透明性と信頼性の確保

1. データの完全性と一貫性の保証

  • データの完全性: すべての取引と愛の行動記録が正確かつ改ざんされていないことを保証する。

  • データの一貫性: システム全体でデータが統一されていることを確認する。

2. 取引の透明性の確保

  • 公開取引データ取引データを公開し、誰でも確認できるようにする。

  • 監査ログ: 取引や行動のすべての変更履歴を保持し、監査可能にする。

3. データのセキュリティとプライバシー保護

  • 暗号化: データの送受信時および保存時に暗号化を行い、データの安全性を確保。

  • アクセス制御: データへのアクセスを制御し、必要な権限を持つユーザーのみに限定。

4. 取引の正当性の確認

  • 署名の生成と検証: 取引データの署名を生成し、取引の正当性を検証。

  • 取引の検証: 各取引を検証し、不正行為や二重支出を防止。

これらの項目を詳細に決定し、実装することで、愛記システムの透明性と信頼性を確保することができる。各項目については、具体的な技術要件や設計仕様を定義し、システム開発の各フェーズで反映させることが重要である。

公開取引データについて

取引データを公開し、誰でも確認できるようにするというが、公開取引データの基本設計をするにあたり、いつ、何を、どのように設計していけばいいのか、具体的にプログラムも含めて見ていこう。公開取引データの基本設計を行うにあたり、以下のステップで進める。

  1. 公開取引データの定義

    • 公開すべき取引データの項目を定義する。例えば、取引ID、送信者、受信者、金額、タイムスタンプ、取引内容など。
    • プライバシーに配慮し、公開するデータから個人情報を排除する。
  2. データの公開方法

    • 取引データを公開するAPIエンドポイントを設計する。
    • 公開データを格納するデータベースまたはストレージを設計する。
  3. データの整合性と完全性の確保

    • 公開データの整合性チェックを実装する。
    • 公開データが改ざんされていないことを保証するための仕組みを設計する。
  4. 透明性の確保

    • 誰でも取引データを確認できるインターフェースを提供する。
    • 取引データの照会ログを記録し、誰がいつデータを照会したかを追跡できるようにする。

公開データを格納するデータベースまたはストレージの設計

データの公開方法について、公開データを格納するデータベースまたはストレージの設計を以下に示す。この設計は、DApps側のPythonプログラムと市町村のブロックチェーンプログラムの連携を考慮している。

1. データベースの選定

  • データベース種類: 公開データを格納するために、NoSQLデータベース(MongoDBなど)を選定する。
  • 理由: NoSQLデータベースはスケーラビリティが高く、トランザクションデータの高速な読み書きに適している。

2. データベースの設計

  • データベース名: public_transactions_db
  • コレクション名: transactions
  • スキーマ:
    • transaction_id (string): トランザクションID
    • sender (string): 送信者のウォレットアドレス(匿名化)
    • receiver (string): 受信者のウォレットアドレス(匿名化)
    • amount (float): 金額
    • action_content (string): 取引内容(匿名化)
    • location (string): 場所(匿名化)
    • municipality (string): 市町村
    • timestamp (string): タイムスタンプ
    • signature (string): 署名(ハッシュ化)
    • proof_of_place (object): PoP(匿名化)
    • approver_info (object): 承認者情報(匿名化)
    • transaction_status (string): 取引の状態
    • fee (float): 手数料
    • currency_type (string): 愛貨の種類

3. データベースの設置と接続

MongoDBのインストールと設定

  • インストール: MongoDBをインストールする。
  • 設定: public_transactions_dbという名前のデータベースを作成する。

○DApps側のPythonプログラム

from pymongo import MongoClient

# MongoDBのクライアントを設定
client = MongoClient('mongodb://localhost:27017/')
db = client['public_transactions_db']
transactions_collection = db['transactions']

# トランザクションデータを保存する関数
def save_transaction_to_db(transaction):
    transactions_collection.insert_one(transaction.__dict__)
    print("Transaction saved to database")

# トランザクションデータの例
transaction_data = {
    "transaction_id": "unique_transaction_id",
    "sender": "0x1234567890abcdef",
    "receiver": "0xabcdef1234567890",
    "amount": 100.0,
    "action_content": "Sample action content",
    "location": "Sample location",
    "municipality": "Sample municipality",
    "timestamp": "2024-06-23T10:00:00Z",
    "signature": "transaction_signature",
    "latitude": 35.6895,
    "longitude": 139.6917,
    "pop_timestamp": "2024-06-23T10:00:00Z",
    "approver_user_id": "approver_id",
    "approver_public_key": "0x1234567890abcdef",
    "approval_timestamp": "2024-06-23T10:05:00Z",
    "approver_signature": "approver_signature",
    "transaction_status": "pending",
    "fee": 0.01,
    "currency_type": "love_currency"
}

# トランザクションの生成と保存
transaction = create_transaction(transaction_data)
save_transaction_to_db(transaction)
 

○市町村のブロックチェーンプログラム

use actix_web::{post, web, App, HttpResponse, HttpServer, Responder};
use serde::{Deserialize, Serialize};
use mongodb::{Client, options::ClientOptions, Collection};
use std::sync::Mutex;

#[derive(Debug, Clone, Serialize, Deserialize)]
struct Transaction {
    transaction_id: String,
    sender: String,
    receiver: String,
    amount: f64,
    timestamp: String,
    signature: String,
    action_content: String,
    location: String,
    municipality: String,
    proof_of_place: ProofOfPlace,
    approver_info: ApproverInfo,
    transaction_status: String,
    fee: f64,
    currency_type: String,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
struct ProofOfPlace {
    latitude: f64,
    longitude: f64,
    timestamp: String,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
struct ApproverInfo {
    user_id: String,
    public_key: String,
    approval_timestamp: String,
    signature: String,
}

struct AppState {
    transactions: Mutex<Collection<Transaction>>,
}

#[post("/api/transactions")]
async fn add_transaction(data: web::Data<AppState>, req: web::Json<Transaction>) -> impl Responder {
    let collection = data.transactions.lock().unwrap();
    match collection.insert_one(req.into_inner(), None).await {
        Ok(_) => HttpResponse::Created().json("Transaction added"),
        Err(e) => HttpResponse::InternalServerError().json(format!("Error: {}", e)),
    }
}

#[actix_web::main]
async fn main() -> std::io::Result<()> {
    let client_options = ClientOptions::parse("mongodb://localhost:27017").await?;
    let client = Client::with_options(client_options)?;
    let db = client.database("public_transactions_db");
    let transactions_collection = db.collection::<Transaction>("transactions");

    let app_state = web::Data::new(AppState {
        transactions: Mutex::new(transactions_collection),
    });

    HttpServer::new(move || {
        App::new()
            .app_data(app_state.clone())
            .service(add_transaction)
    })
    .bind("0.0.0.0:8080")?
    .run()
    .await
}

・説明:

 ・データベースの選定と設計

  • データベース選定: MongoDBを使用。
  • データベース設計: public_transactions_dbデータベースにtransactionsコレクションを作成し、必要なフィールドを定義。

 ・データの匿名化と保存

  • DApps側のPythonプログラム:
    • トランザクションデータを生成し、必要に応じて匿名化。
    • MongoDBにトランザクションデータを保存する。

 ・市町村のブロックチェーンプログラム

  • データ受信と保存:
    • Actix-webを使用してAPIエンドポイントを作成。
    • MongoDBにトランザクションデータを保存する。

この設計により、公開取引データを安全かつ効率的に格納し、システム全体の透明性と信頼性を確保することができる。


○MongoDBの設計

MongoDBにトランザクションデータを保存するというが、DApps側のPythonプログラムで、MongoDBにトランザクションデータを匿名化して保存する具体的な設計を示す。

・インフラ設計:データベースの設置場所

  • オンプレミス: 企業内のデータセンターや自社サーバーに設置。
  • クラウド: AWS、Azure、Google CloudなどのクラウドサービスプロバイダーにMongoDBをホスト。
     

・インストールと設定:MongoDBのインストール

  • オンプレミスの場合:
    • サーバーにMongoDBをインストール。
    • 必要なポート(デフォルトでは27017)を開けて、ネットワーク経由でアクセス可能にする。
  • クラウドの場合:
    • クラウドプロバイダーのコンソールを使用して、MongoDBのインスタンスを作成。
    • 必要なセキュリティ設定(例:VPC、セキュリティグループ、ファイアウォール)を構成。
    • MongoDB Atlasなどのサービスを使用することも検討。
       

・MongoDBの基本設定:

  • データベース名: public_transactions_db
  • コレクション名: transactions
  • ユーザー認証を有効化し、データベースへのアクセスを制御。
  • バックアップポリシーを設定し、定期的にデータをバックアップ。
     

・Pythonプログラムの詳細設計:必要なライブラリのインストール

pip install pymongo dnspython
 

・データベース接続設定:

from pymongo import MongoClient

# MongoDBに接続するクライアントを作成
client = MongoClient('mongodb+srv://<username>:<password>@cluster0.mongodb.net/public_transactions_db?retryWrites=true&w=majority')
db = client['public_transactions_db']
transactions_collection = db['transactions']
 

・トランザクションデータの匿名化と保存:

import hashlib
import datetime
import re
from pymongo import MongoClient

# MongoDBに接続するクライアントを作成
client = MongoClient('mongodb+srv://<username>:<password>@cluster0.mongodb.net/public_transactions_db?retryWrites=true&w=majority')
db = client['public_transactions_db']
transactions_collection = db['transactions']

# ウォレットアドレスの一部をマスクする関数
def mask_address(address):
    return address[:4] + "****" + address[-2:]

# デジタル署名をハッシュ化する関数
def hash_signature(signature):
    return hashlib.sha256(signature.encode()).hexdigest()

# 取引データを匿名化する関数
def anonymize_transaction(transaction):
    transaction['sender'] = mask_address(transaction['sender'])
    transaction['receiver'] = mask_address(transaction['receiver'])
    transaction['signature'] = hash_signature(transaction['signature'])
    if 'proof_of_place' in transaction:
        transaction['proof_of_place']['latitude'] = round(transaction['proof_of_place']['latitude'], 2)
        transaction['proof_of_place']['longitude'] = round(transaction['proof_of_place']['longitude'], 2)
    if 'approver_info' in transaction:
        transaction['approver_info']['public_key'] = mask_address(transaction['approver_info']['public_key'])
        transaction['approver_info']['signature'] = hash_signature(transaction['approver_info']['signature'])
    return transaction

# トランザクションデータを保存する関数
def save_transaction_to_db(transaction):
    anonymized_transaction = anonymize_transaction(transaction)
    transactions_collection.insert_one(anonymized_transaction)
    print("Transaction saved to database")

# トランザクションデータの例
transaction_data = {
    "transaction_id": "unique_transaction_id",
    "sender": "0x1234567890abcdef",
    "receiver": "0xabcdef1234567890",
    "amount": 100.0,
    "action_content": "Sample action content",
    "location": "Sample location",
    "municipality": "Sample municipality",
    "timestamp": datetime.datetime.now().isoformat(),
    "signature": "transaction_signature",
    "proof_of_place": {
        "latitude": 35.6895,
        "longitude": 139.6917,
        "timestamp": datetime.datetime.now().isoformat()
    },
    "approver_info": {
        "user_id": "approver_id",
        "public_key": "0x1234567890abcdef",
        "approval_timestamp": datetime.datetime.now().isoformat(),
        "signature": "approver_signature"
    },
    "transaction_status": "pending",
    "fee": 0.01,
    "currency_type": "love_currency"
}

# トランザクションの生成と保存
save_transaction_to_db(transaction_data)
 

・データのメンテナンス:定期バックアップ

  • MongoDBの定期バックアップを設定し、自動バックアップをスケジュール。
  • バックアップの保存場所を決定し、データの安全性を確保。

・モニタリングとアラート

  • MongoDBのモニタリングツールを使用して、データベースのパフォーマンスとヘルスを監視。
  • エラーログやパフォーマンスの低下を検知するためのアラート設定。

・データのアーカイブ

  • 古いトランザクションデータを定期的にアーカイブし、アクティブデータベースのパフォーマンスを維持。
     

・セキュリティ対策:

  • アクセス制御: MongoDBのユーザー権限を設定し、アクセスを制限。
  • データ暗号化: MongoDBの暗号化機能を使用して、保存時および通信時のデータを保護。
  • 定期的なセキュリティレビュー: データベースとアプリケーションのセキュリティ設定を定期的にレビューし、必要に応じて更新。

この詳細設計に基づいて、DApps側のPythonプログラムはMongoDBと連携し、安全かつ効率的にデータを保存し、メンテナンスすることができる。
 

 

いかがであろうか、今回は公開取引データを格納するデータベースの設計について記載した。セキュリティ面は考慮していないので、まだまだ基本設計の段階だが、考え方は理解できる。