先までは、"愛記"についての記載で、どのようにブロックチェーンSNSに組み込んで実装していけばよいのか、概念的なところからアプローチ方法を記載していった。大まかな概念としてはひとまず終えた。次は、ブロックチェーンの概念設計といえるところまで、基本設計書に着手できるようなところまで、概念を具体化していきたい。
Proof of Place(PoP)アルゴリズム⑤
前回までをふまえて、さらに今回は、メインチェーンのプログラミングについて記載したい。
各市町村で愛の行動をしたとすると、行動した人が相手に対して愛の行動をした!というメッセージと愛の行動レベルと愛貨を渡すというトランザクションを送信する。それを各市町村の代表者たちが承認すると、メインチェーンにデータが飛んでいき、相手にも通知される。メインチェーンにてしばらくデータは保存されているが、相手が愛の行動を受信します!というボタンを押せば、受信というトランザクションとしてメインチェーンにて承認依頼となっていく。それを最終承認するのがDpoSで完全ランダム選出されたメインチェーンでの最終承認者となる。最終承認者により承認されれば、愛貨が移動するという仕組み。この際、最終承認者は、各市町村にいる必要はなく、他の世界中の市町村に居ても良い。いわゆるマイニングに相当する行為であり、世界中のマイナーが承認を行うのと同じだ。
新たな自治体のメインチェーンへの追加
各自治体が独自のブロックチェーンを持つ分散システムでは、新しい自治体を追加する際には、理想的にはメインチェーンの再プログラミングが必要ないはずである。以下は、新しい自治体の統合を処理するための高レベルなアプローチである:
・動的自治体登録:新しい自治体がメインチェーンに動的に登録できる仕組みを実装する。この登録プロセスには、自治体の基本情報の提供と初期設定が含まれる。
・スマートコントラクトによる相互作用:メインチェーンと自治体のブロックチェーン間の相互作用を管理するためにスマートコントラクトを使用する。これらのコントラクトは、新しい自治体を手動で介入することなく柔軟に対応できるようにする必要がある。
・標準化されたインターフェイス:メインチェーンと自治体のブロックチェーン間の通信のための標準化されたインターフェイスを定義する。これにより、新しい自治体がこれらのインターフェースに準拠することで容易に統合できるようになる。
・コンセンサスメカニズム:DPoSなど、動的参加をサポートするコンセンサスメカニズムを使用する。これにより、新しい自治体が大規模な再構成なしにコンセンサスプロセスに参加できるようになる。
・スケーラブルなアーキテクチャ:新しい自治体を追加してもメインチェーンのパフォーマンスに大きな影響を与えないように、システムをスケーラブルに設計する。
・テストとシミュレーション:新しい自治体を本番システムに追加する前に、互換性を確認し、潜在的な問題を特定するために、十分なテストとシミュレーションを実施する。
・コミュニティガバナンス:既存の自治体が新しい自治体の統合を承認できるようにするガバナンスモデルを確立する。これにより、すべての参加者の利益が考慮されることが保証される。
これらの原則に従うことで、新しい自治体を追加する際にメインチェーンの再プログラミングが不要で、統合がシームレスに行われるシステムを作成できる。
この具体例を実現するために、AさんとBさんがそれぞれの市町村で愛貨を申請し、保有している状態を模擬するために、以下の手順でメインチェーンのプログラムをやってみよう。なお、Aさんは石川県加賀市の住民、Bさんは石川県金沢市の住民であるとする。
- Aさんが横浜市内で愛の行動を行い、PoPで位置と時間の証明を行い、愛貨を送信するトランザクションを生成する。
- 生成したトランザクションはAさん所属の石川県加賀市のブロックチェーンに追加され、代表者に承認される。
- Bさんが時間差で大阪市内で愛の行動を受け取り、PoPで位置と時間の証明を行い、愛貨を受け取るトランザクションを生成する。
- 生成したトランザクションはBさん所属の石川県金沢市のブロックチェーンに追加される。
- Bさんが受け取りボタンを押すことで、愛貨の受け取りがメインチェーンにリクエストされる。
- メインチェーンで受け取りがDPosでランダム選出された最終承認者により承認され、AさんからBさんへと愛貨が移動する。
use chrono::{DateTime, Utc};
use std::collections::HashMap;
use std::time::Duration;
#[derive(Debug)]
struct Transaction {
transaction_id: String,
municipality: String,
timestamp: DateTime<Utc>,
location: String,
love_action_level: u32,
amount: f64,
action_content: String,
is_local: bool,
close_flag: bool,
approval_target: Option<String>,
signature: Option<String>,
location_hash: Vec<u8>,
received_timestamp: Option<DateTime<Utc>>,
}
impl Transaction {
fn calculate_location_hash(&mut self) {
let mut hasher = Sha256::new();
hasher.update(self.location.clone());
self.location_hash = hasher.finalize().to_vec();
}
fn generate_signature(&mut self) {
let message = format!(
"{}{}{}{}{}{}{}{}",
self.transaction_id,
self.municipality,
self.timestamp.to_rfc3339(),
self.location,
self.love_action_level,
self.amount,
self.action_content,
String::from_utf8_lossy(&self.location_hash)
);
self.signature = Some(sha2::Sha256::digest(message.as_bytes()).to_string());
}
fn receive_love_currency(&mut self) -> f64 {
if self.received_timestamp.is_none() {
self.received_timestamp = Some(Utc::now());
}
let time_diff = Utc::now() - self.received_timestamp.unwrap();
let hours_diff = time_diff.num_hours() as f64;
let decreased_amount = self.amount - (hours_diff * 0.05); // 1時間ごとに5%ずつ減少
self.amount = decreased_amount.max(0.0); // 愛貨が0未満にならないようにする
self.amount
}
}
#[derive(Debug)]
struct Approver {
name: String,
is_selected: bool,
}
impl Approver {
fn select_approver(approvers: &mut HashMap<String, Approver>) -> Option<String> {
let mut selected_approver: Option<String> = None;
for (name, approver) in approvers.iter_mut() {
if !approver.is_selected {
approver.is_selected = true;
selected_approver = Some(name.clone());
break;
}
}
selected_approver
}
}
fn main() {
let mut transaction_a = Transaction {
transaction_id: "123456".to_string(),
municipality: "Kaga".to_string(),
timestamp: Utc::now(),
location: "35.4436, 139.6372".to_string(), // 横浜市
love_action_level: 3,
amount: 100.0,
action_content: "Helped someone carry groceries".to_string(),
is_local: false,
close_flag: false,
approval_target: None,
signature: None,
location_hash: Vec::new(),
received_timestamp: None,
};
transaction_a.calculate_location_hash();
transaction_a.generate_signature();
let mut transaction_b = Transaction {
transaction_id: "654321".to_string(),
municipality: "Kanazawa".to_string(),
timestamp: Utc::now() + Duration::hours(1),
location: "34.6937, 135.5023".to_string(), // 大阪市
love_action_level: 3,
amount: 0.0,
action_content: "Received help carrying groceries".to_string(),
is_local: false,
close_flag: false,
approval_target: None,
signature: None,
location_hash: Vec::new(),
received_timestamp: None,
};
transaction_b.calculate_location_hash();
transaction_b.generate_signature();
let mut approvers: HashMap<String, Approver> = HashMap::new();
approvers.insert("Approver1".to_string(), Approver { name: "Approver1".to_string(), is_selected: false });
approvers.insert("Approver2".to_string(), Approver { name: "Approver2".to_string(), is_selected: false });
if let Some(approver_name) = Approver::select_approver(&mut approvers) {
transaction_a.approval_target = Some(approver_name.clone());
println!("Transaction A approved by {}", approver_name);
}
if let Some(approver_name) = Approver::select_approver(&mut approvers) {
transaction_b.approval_target = Some(approver_name.clone());
println!("Transaction B approved by {}", approver_name);
}
transaction_b.amount = transaction_b.receive_love_currency();
println!("Transaction A: {:?}", transaction_a);
println!("Transaction B: {:?}", transaction_b);
}
各ブロックチェーンとメインチェーンをつなぐAPI
-
APIの設計: 独自のプロトコルに基づいたAPIを設計する必要がある。このAPIは、メインチェーンと各自治体のブロックチェーン間の通信を管理し、新しい自治体をシームレスに統合できるようにする必要がある。
-
通信プロトコル: メインチェーンと自治体のブロックチェーン間の通信に使用するプロトコルを決定する必要がある。これには、データの送受信、承認プロセス、エラーハンドリングなどが含まれる。
-
データ形式: APIが使用するデータ形式を定義する必要がある。これには、トランザクションデータ、承認依頼、承認結果などが含まれる。
-
認証とセキュリティ: APIには認証機能を実装し、セキュリティを確保する必要がある。これには、データの暗号化、アクセス制御などが含まれる。
-
テストとシミュレーション: APIを開発する前に、十分なテストとシミュレーションを行うことが重要である。これにより、システムが正常に動作し、新しい自治体の統合がスムーズに行われることが確認される。
これらの仮説をもとに、独自のAPIを開発するためのプロトタイプを作成してみることができる。以下は、トランザクションの作成、承認者の選択、承認プロセスの進行などの機能を持つAPIの設計例である。
use chrono::{DateTime, Utc};
use std::collections::HashMap;
// トランザクションの構造体
#[derive(Debug)]
pub struct Transaction {
pub transaction_id: String,
pub municipality: String,
pub timestamp: DateTime<Utc>,
pub location: String,
pub love_action_level: u32,
pub amount: f64,
pub action_content: String,
pub is_local: bool,
pub close_flag: bool,
pub approval_target: Option<String>,
pub signature: Option<String>,
pub location_hash: Vec<u8>,
pub received_timestamp: Option<DateTime<Utc>>,
}
impl Transaction {
pub fn new(
transaction_id: &str,
municipality: &str,
location: &str,
love_action_level: u32,
amount: f64,
action_content: &str,
) -> Self {
let timestamp = Utc::now();
let mut hasher = Sha256::new();
hasher.update(location);
let location_hash = hasher.finalize().to_vec();
Transaction {
transaction_id: transaction_id.to_string(),
municipality: municipality.to_string(),
timestamp,
location: location.to_string(),
love_action_level,
amount,
action_content: action_content.to_string(),
is_local: false,
close_flag: false,
approval_target: None,
signature: None,
location_hash,
received_timestamp: None,
}
}
pub fn calculate_location_hash(&mut self) {
let mut hasher = Sha256::new();
hasher.update(self.location.clone());
self.location_hash = hasher.finalize().to_vec();
}
pub fn generate_signature(&mut self) {
let message = format!(
"{}{}{}{}{}{}{}{}",
self.transaction_id,
self.municipality,
self.timestamp.to_rfc3339(),
self.location,
self.love_action_level,
self.amount,
self.action_content,
String::from_utf8_lossy(&self.location_hash)
);
self.signature = Some(sha2::Sha256::digest(message.as_bytes()).to_string());
}
pub fn receive_love_currency(&mut self) -> f64 {
if self.received_timestamp.is_none() {
self.received_timestamp = Some(Utc::now());
}
let time_diff = Utc::now() - self.received_timestamp.unwrap();
let hours_diff = time_diff.num_hours() as f64;
let decreased_amount = self.amount - (hours_diff * 0.05); // 1時間ごとに5%ずつ減少
self.amount = decreased_amount.max(0.0); // 愛貨が0未満にならないようにする
self.amount
}
}
// 承認者の構造体
#[derive(Debug)]
pub struct Approver {
pub name: String,
pub is_selected: bool,
}
impl Approver {
pub fn new(name: &str) -> Self {
Approver {
name: name.to_string(),
is_selected: false,
}
}
pub fn select_approver(approvers: &mut HashMap<String, Approver>) -> Option<String> {
let mut selected_approver: Option<String> = None;
for (name, approver) in approvers.iter_mut() {
if !approver.is_selected {
approver.is_selected = true;
selected_approver = Some(name.clone());
break;
}
}
selected_approver
}
}
このAPI設計例はシステム全体の管理や拡張性を考慮した設計を行っており、具体的な機能や操作を行うための実装を提供している。さらなる詳細な機能も実際に合わせて加えていく必要はあるのだろうが。
use chrono::{DateTime, Utc};
use std::collections::HashMap;
use std::time::Duration;
// トランザクションの構造体
#[derive(Debug)]
struct Transaction {
transaction_id: String,
municipality: String,
timestamp: DateTime<Utc>,
location: String,
love_action_level: u32,
amount: f64,
action_content: String,
is_local: bool,
close_flag: bool,
approval_target: Option<String>,
signature: Option<String>,
location_hash: Vec<u8>,
received_timestamp: Option<DateTime<Utc>>,
}
impl Transaction {
fn calculate_location_hash(&mut self) {
let mut hasher = Sha256::new();
hasher.update(self.location.clone());
self.location_hash = hasher.finalize().to_vec();
}
fn generate_signature(&mut self) {
let message = format!(
"{}{}{}{}{}{}{}{}",
self.transaction_id,
self.municipality,
self.timestamp.to_rfc3339(),
self.location,
self.love_action_level,
self.amount,
self.action_content,
String::from_utf8_lossy(&self.location_hash)
);
self.signature = Some(sha2::Sha256::digest(message.as_bytes()).to_string());
}
fn receive_love_currency(&mut self) -> f64 {
if self.received_timestamp.is_none() {
self.received_timestamp = Some(Utc::now());
}
let time_diff = Utc::now() - self.received_timestamp.unwrap();
let hours_diff = time_diff.num_hours() as f64;
let decreased_amount = self.amount - (hours_diff * 0.05); // 1時間ごとに5%ずつ減少
self.amount = decreased_amount.max(0.0); // 愛貨が0未満にならないようにする
self.amount
}
// 新たに追加したメソッド
fn verify_signature(&self) -> bool {
if let Some(signature) = &self.signature {
let message = format!(
"{}{}{}{}{}{}{}{}",
self.transaction_id,
self.municipality,
self.timestamp.to_rfc3339(),
self.location,
self.love_action_level,
self.amount,
self.action_content,
String::from_utf8_lossy(&self.location_hash)
);
let calculated_signature = sha2::Sha256::digest(message.as_bytes()).to_string();
return *signature == calculated_signature;
}
false
}
}
// 承認者の構造体
#[derive(Debug)]
struct Approver {
name: String,
is_selected: bool,
}
impl Approver {
fn select_approver(approvers: &mut HashMap<String, Approver>) -> Option<String> {
let mut selected_approver: Option<String> = None;
for (name, approver) in approvers.iter_mut() {
if !approver.is_selected {
approver.is_selected = true;
selected_approver = Some(name.clone());
break;
}
}
selected_approver
}
}
// APIの実装
struct LoveCurrencyApi;
impl LoveCurrencyApi {
// メインチェーンから自治体のブロックチェーンにデータを送信するメソッド
fn send_data_to_municipality_chain(transaction: &Transaction, municipality: &str) {
if transaction.verify_signature() {
println!("Sending data to municipality chain: {:?}", transaction);
// メインチェーンから自治体のブロックチェーンにデータを送信する処理を実装する
} else {
println!("Failed to send data: Invalid signature");
}
}
// 新しい自治体を登録するメソッド
fn register_new_municipality(municipality_name: &str) {
println!("Registering new municipality: {}", municipality_name);
// 新しい自治体を登録する処理を実装する
}
// APIの初期化処理
fn init() -> Self {
LoveCurrencyApi
}
}
fn main() {
let mut transaction_a = Transaction {
transaction_id: "123456".to_string(),
municipality: "Kaga".to_string(),
timestamp: Utc::now(),
location: "35.4436, 139.6372".to_string(), // 横浜市
love_action_level: 3,
amount: 100.0,
action_content: "Helped someone carry groceries".to_string(),
is_local: false,
close_flag: false,
approval_target: None,
signature: None,
location_hash: Vec::new(),
received_timestamp: None,
};
transaction_a.calculate_location_hash();
transaction_a.generate_signature();
let mut transaction_b = Transaction {
transaction_id: "654321".to_string(),
municipality: "Kanazawa".to_string(),
timestamp: Utc::now() + Duration::hours(1),
location: "34.6937, 135.5023".to_string(), // 大阪市
love_action_level: 3,
amount: 0.0,
action_content: "Received help carrying groceries".to_string(),
is_local: false,
close_flag: false,
approval_target: None,
signature: None,
location_hash: Vec::new(),
received_timestamp: None,
};
transaction_b.calculate_location_hash();
transaction_b.generate_signature();
let mut approvers: HashMap<String, Approver> = HashMap::new();
approvers.insert("Approver1".to_string(), Approver { name: "Approver1".to_string(), is_selected: false });
approvers.insert("Approver2".to_string(), Approver { name: "Approver2".to_string(), is_selected: false });
if let Some(approver_name) = Approver::select_approver(&mut approvers) {
transaction_a.approval_target = Some(approver_name.clone());
println!("Transaction A approved by {}", approver_name);
}
if let Some(approver_name) = Approver::select_approver(&mut approvers) {
transaction_b.approval_target = Some(approver_name.clone());
println!("Transaction B approved by {}", approver_name);
}
transaction_b.amount = transaction_b.receive_love_currency();
println!("Transaction A: {:?}", transaction_a);
println!("Transaction B: {:?}", transaction_b);
// APIを初期化
let api = LoveCurrencyApi::init();
// 新しい自治体を登録する例
api.register_new_municipality("Saitama");
// メインチェーンから自治体のブロックチェーンにデータを送信する例
api.send_data_to_municipality_chain(&transaction_a, "Saitama");
}