先までは、"愛記"についての記載で、どのようにブロックチェーンSNSに組み込んで実装していけばよいのか、概念的なところからアプローチ方法を記載していった。大まかな概念としてはひとまず終えた。次は、ブロックチェーンの概念設計といえるところまで、基本設計書に着手できるようなところまで、概念を具体化していきたい。
愛記システムのシステム評価について
システム評価とは、つまりは、このシステムを導入して成功だったか失敗だったかという効果検証という意味だ。概念設計をする上で必ず抑えておくべきポイントということだ。それには各項目があり、それぞれの項目を見ていくことで、その結果が得られる。そのシステム評価項目を1つずつ見ていきたい。
システム構築の品質評価のポイント1:理解可能性(Understandability)
システム構築の品質評価のポイント2:完全性(Completeness)
システム構築の品質評価のポイント3:簡潔性(Conciseness)
システム構築の品質評価のポイント4:移植性(Portability)
システム構築の品質評価のポイント5:一貫性(Consistency)と構造化の度合い
システム構築の品質評価のポイント6:保守性(Maintainability)
システム構築の品質評価のポイント7:試験性(Testability)
システム構築の品質評価のポイント8:ユーザビリティ(Usability)
システム構築の品質評価のポイント9:効率性(Efficiency)
システム構築の品質評価のポイント10:セキュリティ(Security)
システム構築の品質評価のポイント7:試験性③(Testability)
システム構築の品質評価ポイントとなっている試験性とは、不具合があるかどうかを確認するための各種テスト項目が簡単に実施できるかどうかである。不具合があった際にその不具合が階層まで調査する必要があり、見つけるまで非常に時間がかかるのは問題である。この試験性は先ほど記載した保守性と非常に関連性があり、試験性の高さは保守性の高さに繋がる。逆に低いと保守性の品質評価も下がる。
さて、試験性の定義として、7つの特性があるのでそれぞれについて見ていこう。
- 実行円滑性(Operability)
- 観測容易性(Observability)
- 制御容易性(Controllability)
- 分解容易性(Decomposability)
- 単純性(Simplicity)
- 安定性(Stability)
- 理解容易性(Understandability)
これらの特性はJames Bach著『ソフトウェアテスト293の法則』やRoger S. Pressman著『実践ソフトウェアエンジニアリング』 で挙げられている。
5. 単純性(Simplicity)
テスト対象となるシステムやコンポーネントがどれだけ簡単に理解し、分析し、そしてテストできるかを表す特性である。例えば次のような状況は、単純性が低い。
・過度に複雑な機能や仕様
・複数の責務を持つ
如何にシンプルな構造にできるかどうか、設計の問題であろう。Solanaのようなブロックチェーンは、すべてがL1レベルで設計できる仕様のため、シンプルな構造である。ブロックチェーンの分野では、複雑なコンセンサスアルゴリズムやスマートコントラクトの実装はセキュリティ上の要件が高くなるため、シンプルで予測可能な設計が重要である。単純性を向上させるための一般的なアプローチは、以下の点に焦点を当てることである:
▪ネットワークアーキテクチャのドキュメント:
▪スマートコントラクトの仕様書:
▪トランザクションのフォーマットと意味論のドキュメンテーション:
▪ノードの役割と構成ガイド:
▪デプロイメントガイド:
▪モジュールやコンポーネントのAPIドキュメンテーション:
▪セキュリティガイド:
-
シンプルなデザインの採用: 不必要な複雑さを避け、明確なデザイン原則に従うこと。フェデレーションモデルにおいてシンプルなデザインを採用する例として、以下は、NetworkManager クラスがノードの追加、削除、ネットワークサイズの取得などの基本的な操作を提供し、デザインがシンプルであり、必要最小限の機能を持つようにしている。
class NetworkManager:
def __init__(self):
self.nodes = set()
def add_node(self, node):
# ネットワークにノードを追加
self.nodes.add(node)
print(f"Node {node} added to the network")
def remove_node(self, node):
# ネットワークからノードを削除
self.nodes.remove(node)
print(f"Node {node} removed from the network")
def get_network_size(self):
# ネットワークのサイズを取得
return len(self.nodes)
# フェデレーションモデルのネットワーク管理クラスの使用例
network_manager = NetworkManager()
# ノードの追加
network_manager.add_node("Node1")
network_manager.add_node("Node2")
# ネットワークサイズの取得
network_size = network_manager.get_network_size()
print(f"Current network size: {network_size}")
# ノードの削除
network_manager.remove_node("Node1")
# 更新後のネットワークサイズの取得
updated_network_size = network_manager.get_network_size()
print(f"Updated network size: {updated_network_size}")
-
責務の分離: 各コンポーネントやモジュールが特定の責務を持つようにし、役割を明確に分離する。フェデレーションモデルにおいて、責務の分離は各市町村のブロックチェーンが特定の役割を持ち、それぞれが明確に区別されることを指す。以下の例では、MainBlockchainがメインブロックチェーンの責務を担当し、各市町村のブロックチェーンはMunicipalityBlockchainで独自のロジックを持つ。Federationはこれらのブロックチェーンを統合し、フェデレーションでのトランザクション処理を担当する。
# メインブロックチェーンのコード
class MainBlockchain:
def __init__(self):
# メインブロックチェーンの初期化ロジック
def process_transaction(self, transaction):
# メインブロックチェーンでのトランザクション処理ロジック
pass
def validate_transaction(self, transaction):
# メインブロックチェーンでのトランザクション検証ロジック
pass
# 各市町村のブロックチェーンのコード
class MunicipalityBlockchain:
def __init__(self, municipality_name):
self.municipality_name = municipality_name
# 各市町村のブロックチェーンの初期化ロジック
def process_local_transaction(self, transaction):
# 各市町村でのローカルなトランザクション処理ロジック
pass
def validate_local_transaction(self, transaction):
# 各市町村でのローカルなトランザクション検証ロジック
pass
# フェデレーションのコード
class Federation:
def __init__(self, main_blockchain, municipality_blockchains):
self.main_blockchain = main_blockchain
self.municipality_blockchains = municipality_blockchains
def process_federated_transaction(self, transaction):
# フェデレーションでのトランザクション処理ロジック
# ここで必要に応じてメインブロックチェーンと各市町村のブロックチェーンとの連携を行う
pass
def validate_federated_transaction(self, transaction):
# フェデレーションでのトランザクション検証ロジック
# ここで必要に応じてメインブロックチェーンと各市町村のブロックチェーンとの連携を行う
pass
# 利用例
# メインブロックチェーンのインスタンス化
main_chain = MainBlockchain()
# 各市町村のブロックチェーンのインスタンス化
municipality_chain_A = MunicipalityBlockchain("Municipality A")
municipality_chain_B = MunicipalityBlockchain("Municipality B")
# フェデレーションのインスタンス化
federation = Federation(main_chain, [municipality_chain_A, municipality_chain_B])
# トランザクション処理の例
transaction_data = {...} # トランザクションデータの例
federation.process_federated_transaction(transaction_data)
-
クリーンなインターフェース: インターフェースをシンプルかつ理解しやすくすることで、モジュール間の相互作用を最小限に抑える。この例では、Transaction クラスを導入してトランザクションのデータをより構造化し、各ブロックチェーンが直接トランザクションを操作する形にしている。それぞれのクラスが独立しており、外部の変更に対しても柔軟に対応できるようになっている。
class Transaction:
def __init__(self, sender, receiver, amount):
self.sender = sender
self.receiver = receiver
self.amount = amount
class MunicipalityBlockchain:
def __init__(self, name):
self.name = name
self.pending_transactions = []
def propose_transaction(self, transaction):
# 各市町村のブロックチェーンがトランザクションを提案する
self.pending_transactions.append(transaction)
print(f"{self.name} proposed a transaction: {transaction}")
def approve_transaction(self, main_blockchain, transaction):
# メインブロックチェーンがトランザクションを承認する
if transaction in self.pending_transactions:
main_blockchain.add_transaction(transaction)
self.pending_transactions.remove(transaction)
print(f"{self.name} approved the transaction: {transaction}")
else:
print(f"{self.name} did not approve the transaction (not in pending).")
class MainBlockchain:
def __init__(self):
self.transactions = []
def add_transaction(self, transaction):
# メインブロックチェーンにトランザクションを追加する
self.transactions.append(transaction)
print(f"Main blockchain added a transaction: {transaction}")
# 各市町村のブロックチェーンを作成
municipality1 = MunicipalityBlockchain("Municipality 1")
municipality2 = MunicipalityBlockchain("Municipality 2")
# メインブロックチェーンを作成
main_blockchain = MainBlockchain()
# 各市町村がトランザクションを提案し、メインブロックチェーンが承認する
transaction1 = Transaction("Sender1", "Receiver1", 100)
transaction2 = Transaction("Sender2", "Receiver2", 150)
municipality1.propose_transaction(transaction1)
municipality2.propose_transaction(transaction2)
municipality1.approve_transaction(main_blockchain, transaction1)
municipality2.approve_transaction(main_blockchain, transaction2)
-
ドキュメンテーション: システムやコンポーネントの理解を助けるために十分なドキュメンテーションを提供する。フェデレーションモデルにおいて、十分なドキュメンテーションを提供することは非常に重要である。以下は、その一例である:
- メインブロックチェーンと各市町村のブロックチェーンのアーキテクチャを説明する。以下は、フェデレーションモデルの一部としてのシンプルなアーキテクチャの概要である。
-
メインブロックチェーンのアーキテクチャ:
-
Delegated Proof of Stake (DPoS):
- 各市町村の代表者がDPoSによって選ばれる。これにより、ブロック生成のためのバリデーターが定期的に選ばれ、分散的な意思決定が行われる。
-
ランダムな承認者の選定:
- メインブロックチェーン上で、完全なランダム性を持つ乱数を発生させる。
- 生成されたランダムな値に基づいて、1人の承認者が選ばれる。
-
スマートコントラクト:
- メインブロックチェーン上には、フェデレーション全体で共有されるスマートコントラクトが配置されている。
- このスマートコントラクトは、フェデレーションメンバーが相互にやり取りする際のルールや条件を定義している。
-
ブロックチェーンノード:
- メインブロックチェーンは、各市町村のノードと連携し、ネットワーク全体を維持する。
- バリデーターとなるノードは、新しいブロックの生成やトランザクションの承認に参加する。
-
各市町村のブロックチェーンのアーキテクチャ:
-
独自のブロックチェーン:
- 各市町村は独自のブロックチェーンを有しており、自治体ごとに分散台帳が独立して構築されている。
- 各ブロックチェーンはメインブロックチェーンとは独立して動作する。
-
自治体データ:
- 各自治体のブロックチェーンには、その自治体に関連するデータやトランザクションが格納される。
- 例えば、マイナンバーカード情報などが含まれる。
-
自治体ノード:
- 各市町村は自身のノードを運用し、自治体ブロックチェーンに参加する。
- バリデーターとしての権限を持つ自治体のノードが新しいブロックを生成し、トランザクションを検証する。
-
フェデレーションへの連携:
- 各自治体のブロックチェーンは、メインブロックチェーンと連携している。
- データの相互運用性やブロックチェーン間のトランザクションが可能なように、相互に連携が行われる。
-
これらのアーキテクチャは、各自治体が自身のデータを独立して管理しながら、メインブロックチェーンと連携して全体の信頼性やセキュリティを確保するように設計されている。なお、実際のシステムにおいては、様々な詳細が考慮されるべきであろう。
- 各スマートコントラクトの機能、パラメータ、トランザクションのフォーマットなどを明確に定義する。
- 各関数やメソッドの役割や期待される挙動を説明する。以下は、フェデレーションモデルにおいて各スマートコントラクトの機能、パラメータ、およびトランザクションのフォーマットを定義した例である。具体的な実装に先立っての例であり、必要に応じて変更が必要である。
-
MunicipalityRegistry スマートコントラクト:
- 機能:
- 各市町村の登録と管理を担当する。
- 新しい市町村が参加する際の手続きを管理する。
- メソッド/関数:
- registerMunicipality(address municipalityAddress, string municipalityName): 新しい市町村の登録を行う。
- getMunicipality(address municipalityAddress) returns (string): 指定された市町村の情報を取得する。
- 機能:
-
TransactionProposal スマートコントラクト:
- 機能:
- ネットワーク上での提案されたトランザクションを管理する。
- メソッド/関数:
- submitProposal(address municipality, uint256 amount, string description): トランザクションの提案を行う。
- approveProposal(uint256 proposalId): 提案されたトランザクションを承認する。
- executeProposal(uint256 proposalId): 承認されたトランザクションを実行する。
- 機能:
-
ValidatorRegistry スマートコントラクト:
- 機能:
- バリデーターの登録と管理を担当する。
- メソッド/関数:
- registerValidator(address validatorAddress, string validatorName): 新しいバリデーターの登録を行う。
- getValidator(address validatorAddress) returns (string): 指定されたバリデーターの情報を取得する。
- 機能:
-
FederationConfiguration スマートコントラクト:
- 機能:
- フェデレーション全体の設定を管理する。
- メソッド/関数:
- setThreshold(uint256 newThreshold): 承認のための閾値を設定する。
- setReward(uint256 newReward): 承認者に与えられる報酬を設定する。
- 機能:
-
これらのスマートコントラクトは、各機能の要件に基づいて設計され、相互に連携してフェデレーションモデル全体を構築する。なお、実際の実装においては、セキュリティや効率性を考慮した適切な実装が必要である。
- トランザクションがどのようなデータを含むか、それがどのように処理されるかについてのドキュメントを提供する。以下は、フェデレーションモデルにおいて、初期ドキュメンテーションの一部であり、実際の要件に応じて変更が必要である。
-
トランザクションデータの構造:
- トランザクションID(Transaction ID): トランザクションを一意に識別するためのユニークなID。
- ユーザーアカウント(User Account): トランザクションを送信したユーザーのアカウント情報。
- タイムスタンプ(Timestamp): トランザクションが作成された時間情報。
- 署名(Signature): トランザクションが有効であることを確認するためのデジタル署名。
- トランザクションの前提条件(Preconditions): トランザクションが実行される前に満たされている必要がある条件。
- 位置(GIS):トランザクションが作成されたときの位置情報。
- 愛の行動レベル(Love Action Level): トランザクションの愛に関する行動のレベルを示す数値と科目。
- 次元(Dimension): 生命体の次元を表す識別子やカテゴリ。
- 愛貨額(Amount): 提案されたトランザクションの愛貨額。
- 行動内容(Action Content): 実際の行動や提案された行動の詳細な説明。
- 承認相手(Approval Target): 行動の承認を得る対象のアドレスやID。
- ゆらぎ(Fluctuation): 新たな生命体の発起活動。
-
追加の要素:
- ハッシュ(Hash): トランザクションデータ全体のハッシュ値。データの整合性を確保するための重要な要素。
- メタデータ(Metadata): トランザクションに関する追加情報やコンテキストを含む任意のメタデータ。
- ガス代(Fee): トランザクションの実行にかかるガス代。
- イベント通知(Event Notifications): トランザクションが実行されたことを他のコンポーネントに通知するためのイベント情報。
-
トークン管理:Wallet 構造体を使用して実装される。この構造体は、トークンを保持するためのウォレットを表す。ウォレットは、アドレスとバランスを持つ。
struct Wallet { address: String, balance: f64, } -
トークンの追加と減算: Wallet 構造体には、トークンの追加と減算を行うメソッドが実装される。(注:rustで表記)
impl Wallet {
fn add_balance(&mut self, amount: f64) {
self.balance += amount;
}
fn subtract_balance(&mut self, amount: f64) -> Result<(), &'static str> {
if self.balance >= amount {
self.balance -= amount;
Ok(())
} else {
Err("Insufficient balance")
}
}
} -
トークンの処理: トークンを含むトランザクションが承認されると、トランザクションの送信者から承認者に報酬が支払われる。(注:rustで表記)
これらの要素によって、ウォレットを使用してトークンの管理が行われる。ウォレットは、トランザクションの送信者や承認者など、ユーザーごとに管理される。なお、プログラム内では、トークンの種類を識別するために TOKEN_TYPES というハッシュマップが使用される。このハッシュマップを介して、各トランザクションがどの種類のトークンを扱っているかを判断し、それに基づいてトークンの転送が行われる。このアプローチにより、プライベートトークンやNFTなど、さまざまな種類のトークンを管理することができる。
fn pay_reward_to_approver(&self, reward_amount: f64, wallets: &mut HashMap<String, Wallet>) {
if let Some(approver_wallet) = wallets.get_mut(&self.approval_target) {
approver_wallet.add_balance(reward_amount);
}
}
-
トランザクションの処理:
- 提案されたトランザクションは、ValidatorRegistry スマートコントラクトによって承認される前提とする。
- 承認が得られたトランザクションは TransactionProposal スマートコントラクトに送信され、実行のために保留される。
- 各バリデーターがトランザクションを承認すると、承認の数が閾値を超えると TransactionProposal スマートコントラクトによって実際に実行される。
-
トランザクションのステータスやエラーメッセージの意味を説明する。
- 各市町村のノードがどのような役割を果たし、どのように構成されるかに関するドキュメントを提供する。
- バリデーターとしての期待される機能や責務を明示する。
- フェデレーションモデルを実際にデプロイする手順や要件に関するガイドを提供する。
- 必要な依存関係、設定、および最適な構成に関する情報を提供する。
- メインブロックチェーンや各市町村のブロックチェーンで提供されるAPIやインターフェースに関するドキュメントを提供する。
- 開発者がこれらのAPIを使用する際の期待される入力と出力を示す。以下は、メインブロックチェーンと各市町村のブロックチェーンが提供するAPIの簡単なドキュメンテーションの例である。具体的な仕様やエンドポイントは実際のシステムによって異なるため、この例は一般的なガイドとして理解してもらいたい。
メインブロックチェーン API
1. トランザクション発行エンドポイント -
エンドポイント: /api/transactions/issue
-
メソッド: POST
-
リクエスト:
- Body パラメータ:
- sender_address: 送信者のウォレットアドレス
- recipient_address: 受信者のウォレットアドレス
- amount: 送金額
- data: トランザクションに関連するデータ
- Body パラメータ:
-
レスポンス:
- transaction_id: トランザクションの一意の識別子
- status: トランザクションのステータス
- 2. ブロック情報取得エンドポイント
-
エンドポイント: /api/blocks/{block_number}
-
メソッド: GET
-
パラメータ:
- block_number: 取得したいブロックの番号
-
レスポンス:
- block_hash: ブロックのハッシュ
- transactions: ブロック内のトランザクションリスト
- 他のブロック情報...
-
各市町村のブロックチェーン API
1. ノード情報取得エンドポイント -
エンドポイント: /api/node/info
-
メソッド: GET
-
レスポンス:
- node_id: ノードの識別子
- peer_nodes: 接続している他のノードのリスト
- current_block: ノードが保持する最新のブロック情報
- 他のノード情報...
- 2. トランザクション検証エンドポイント
-
エンドポイント: /api/transactions/verify
-
メソッド: POST
-
リクエスト:
- Body パラメータ:
- transaction_data: 検証するトランザクションデータ
- Body パラメータ:
-
レスポンス:
- valid: トランザクションの検証結果 (true/false)
- error_message: 検証エラーがある場合のエラーメッセージ
- システム全体のセキュリティ設計やベストプラクティスに関するガイドラインを提供する。
- ユーザーがセキュリティのリスクを理解し、適切な対策を講じるのに役立つ情報を提供する。
単純性は、システム全体の理解可能性を向上させ、保守性やテストの容易性を高める重要な特性である。
いかがであろうか、今回は単純性について記載した。単純にしようとするほど、いろんなことを考慮しながらシンプルに設計する必要がある。なかなか難しいところであろう。