愛記システム概念設計:承認者の選定・報酬支払い③ | 続・ティール組織 研究会のブログ

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

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

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

承認者の選出について③

ブロックチェーンの世界では、承認者はコンピューターであり、特定のアルゴリズムに基づいて選択されたり、ランダムに選ばれたりする。承認者は自動的にトランザクションを承認し、新しいブロックを追加する。承認者の選定には、コンピューターが自動的に行う部分もあるが、その選定方法やルールは人間が設計する。適切な承認者を選定することで、ブロックチェーンのセキュリティや効率が向上し、ネットワーク全体の信頼性が高まるという意味である。つまり、コンピューターが承認を行うとしても、その選定には人間の設計や意図が反映されている。

 

各市町村のブロックチェーンのプログラムが独自で運用されており、メインチェーンで繋がっている。世界中の100万以上もの市町村のブロックチェーンがメインチェーンに接続されているとすると、各市町村のトランザクションやデータの処理がメインチェーンに反映されるため、膨大な量のトランザクションとデータがメインチェーン上で処理されることになる。このような負荷を処理するためには、非常に高いスケーラビリティと処理能力を持つブロックチェーンプラットフォームが必要となる。また、適切なコンセンサスアルゴリズムやネットワーク構成も重要である。このような状況を考慮して、分散型台帳技術(DLT)の設計と運用は慎重に行われる必要がある。このような負荷を処理するためには、いくつかの方法が考えられる。

■並列処理による負荷分散:

ソラナ(Solana)は、高いスループットと低いトランザクション手数料を実現するために、並列処理を活用している。ソラナの設計では、Proof of History(PoH)と呼ばれる仕組みを使用して、ネットワーク全体の時刻を同期させ、各ノードがトランザクションを独立して処理できるようにしている。これにより、ソラナは1秒間に数万から数十万のトランザクションを処理できる高いスループットを実現している。そのプログラムでは、主にブロックの追加が並列に処理されている。具体的には以下の点が並列処理されている。

  1. ブロックの生成と追加: add_block メソッドでは、新しいブロックを生成してからブロックチェーンに追加している。この処理はブロックごとに独立しており、新しいブロックを生成する際には前のブロックのハッシュ値を計算する必要があるため、各ブロックの生成と追加は独立して並列に行うことができる。

  2. ハッシュ値の計算: ブロックのハッシュ値は、そのブロックのインデックス、直前のブロックのハッシュ値、タイムスタンプ、データ、および Proof of History の値を組み合わせて計算される。この計算は各ブロックごとに独立して行われるため、ブロックの追加と同様に並列化することができる。

このように、ブロックの生成と追加、およびハッシュ値の計算は各ブロックごとに独立して行われるため、並列に処理することができる。

 

■メインチェーンのプログラム:

use std::collections::HashMap;
use std::sync::{Arc, Mutex};
use std::thread;
use std::time::Duration;
use sha2::{Digest, Sha256};
use chrono::{DateTime, Utc};

#[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,
    municipality: String, // 所属する市町村を追加
}

#[derive(Debug)]
struct MainChain {
    municipalities: HashMap<String, Vec<Transaction>>,
    approvers: HashMap<String, Approver>,
}

impl MainChain {
    fn new() -> Self {
        MainChain {
            municipalities: HashMap::new(),
            approvers: HashMap::new(),
        }
    }

    fn add_municipality(&mut self, name: &str, transactions: Vec<Transaction>) {
        self.municipalities.insert(name.to_string(), transactions);
    }

    fn select_approver(&mut self, municipality_name: &str) -> Option<String> {
        if let Some(approver) = self.approvers.values_mut().find(|a| a.municipality == municipality_name && !a.is_selected) {
            approver.is_selected = true;
            Some(approver.name.clone())
        } else {
            None
        }
    }

    fn calculate_and_pay_reward(&mut self, transaction: &Transaction) {
        let reward_amount = transaction.amount * 0.03; // 3%の報酬を計算
        println!("Reward amount: {}", reward_amount);

        // 愛貨を承認者が所属する市町村に送金する処理
        if let Some(approver) = self.approvers.get(&transaction.approval_target.clone().unwrap()) {
            if let Some(transactions) = self.municipalities.get_mut(&approver.municipality) {
                transactions.push(Transaction {
                    transaction_id: "報酬用のトランザクションID".to_string(),
                    municipality: approver.municipality.clone(),
                    timestamp: Utc::now(),
                    location: "送金先の市町村の位置情報".to_string(),
                    love_action_level: 1, // レベルは1でOK?
                    amount: reward_amount,
                    action_content: "承認者への報酬".to_string(),
                    is_local: true, // 地域内取引
                    close_flag: true, // 完了フラグ
                    approval_target: None,
                    signature: None,
                    location_hash: Vec::new(),
                    received_timestamp: None,
                });
            }
        }

        // 受信者に通知する処理
        if let Some(transactions) = self.municipalities.get_mut(&transaction.municipality) {
            let recipient_transaction = transactions.iter_mut().find(|t| t.transaction_id == transaction.transaction_id);
            if let Some(recipient_transaction) = recipient_transaction {
                // ここで受信者に通知を送信する処理を実装する
                println!("Notification sent to recipient: {:?}", recipient_transaction);
            }
        }
    }

    fn process_transactions(&mut self) {
        for (municipality, transactions) in self.municipalities.iter_mut() {
            for transaction in transactions.iter_mut() {
                transaction.calculate_location_hash();
                transaction.generate_signature();
                transaction.receive_love_currency();
                if let Some(approver_name) = self.select_approver(municipality) {
                    transaction.approval_target = Some(approver_name.clone());
                    println!("Transaction {} approved by {}", transaction.transaction_id, approver_name);
                    self.calculate_and_pay_reward(transaction);
                }
            }
        }
    }
}

fn main() {
    let main_chain = Arc::new(Mutex::new(MainChain::new()));

    let kaga_transactions = vec![
        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,
        },
        // Add more transactions as needed
    ];

    let main_chain_clone = main_chain.clone();
    thread::spawn(move || {
        let mut main_chain = main_chain_clone.lock().unwrap();
        main_chain.add_municipality("Kaga", kaga_transactions);
    });

    let kanazawa_transactions = vec![
        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,
        },
        // Add more transactions as needed
    ];

    let main_chain_clone = main_chain.clone();
    thread::spawn(move || {
        let mut main_chain = main_chain_clone.lock().unwrap();
        main_chain.add_municipality("Kanazawa", kanazawa_transactions);
    });

    // Process transactions
    thread::sleep(Duration::from_secs(2)); // Sleep to allow transactions to be added
    let mut main_chain = main_chain.lock().unwrap();
    main_chain.process_transactions();

    // Print main chain status
    println!("Main chain status: {:?}", main_chain);
}

Approver 構造体に municipality フィールドを追加し、承認者が所属する市町村を保持するようにした。select_approver メソッドで、承認者が所属する市町村を特定しており、calculate_and_pay_reward メソッドで、承認者が所属する市町村に愛貨を送金する処理をしている。これにより、正しい市町村に報酬を送金できるようになった。なお、Rustでデータ競合を回避し、適切な並列処理を行うための修正を加えたコードを示した。std::sync::Mutexを使用して、複数のスレッドから安全にアクセスできるようにしている。

なお、このメインチェーンのプログラムは、フェデレーションモデルを使用しており、送信者と受信者の間での愛貨のやり取りを確実に処理している。送信者がトランザクションを送信すると、市町村の承認者によって承認され、その後メインチェーンに保存される。同時に、受信者の市町村のブロックチェーンにもトランザクションが送信され、受信者に通知される。受信者が受信ボタンを押すと、受信者の市町村のブロックチェーンでトランザクションが承認され、その後メインチェーンの承認者が承認し、愛貨のやり取りが完了する。このプロセスで、送信者と受信者の間での愛貨の透明なやり取りを実現しており、ブロックチェーンの安全性と信頼性を活用しているといえよう。

 

 

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

上記のメインチェーンのプログラムに繋がるように市町村のブロックチェーンのプログラムを修正してみた。修正点は主に Transaction クラスと Blockchain クラスの一部である。
・Transaction クラスの generate_proof_of_place メソッドと generate_proof_of_history メソッドは削除した。
・Transaction クラスの validators フィールドを追加し、トランザクションを検証する際に使用する。
・Blockchain クラスの select_validators メソッドを修正し、トランザクションの送信者と受信者が異なる場合のみ、適切なバリデータを選択するようにした。

 

from collections import defaultdict
from datetime import datetime, timedelta
import random
import hashlib

TOKEN_TYPES = {
    1: "AIR(Root)",
    2: "AIS(Sacral)",
    3: "AIP(Solar Plexus)",
    4: "AIH(Heart)",
    5: "AIT(Throat)",
    6: "AII(Third Eye)",
    7: "AIC(Crown)",
    8: "AIU(Universal)",
    9: "AIE(Earth Star)",
    10: "AIM(Solar Matrix)"
}

class Wallet:
    def __init__(self, address):
        self.address = address
        self.balance = 0.0

    def add_balance(self, amount):
        self.balance += amount

    def subtract_balance(self, amount):
        if self.balance >= amount:
            self.balance -= amount
        else:
            raise ValueError("Insufficient balance")

class Transaction:
    def __init__(self, sender, receiver, location, love_action_level, action_content, sender_dimension, receiver_dimension, approver, approver_dimension):
        self.transaction_id = hashlib.sha256(str(random.getrandbits(256)).encode()).hexdigest()
        self.sender = sender
        self.receiver = receiver
        self.timestamp = str(datetime.now())
        self.location = location
        self.love_action_level = love_action_level
        self.amount = 0.0  # Amount will be set later when processing the transaction
        self.action_content = action_content
        self.approval_target = approver
        self.zero_knowledge_proof = None
        self.sender_dimension = sender_dimension
        self.receiver_dimension = receiver_dimension
        self.validators = []

    def generate_proof_of_place(self):
        return f"Transaction {self.transaction_id}'s proof of place has been generated: {self.location}"

    def generate_proof_of_history(self):
        return f"Transaction {self.transaction_id}'s proof of history has been generated: {self.timestamp}"

    def generate_zero_knowledge_proof(self):
        n, g, lam = generate_key()
        m = random.randint(1, n - 1)
        c = encrypt(m, n, g)
        proof = generate_zero_knowledge_proof(n, g, lam, m, c)
        self.zero_knowledge_proof = proof

    def transfer_token(self, love_currency):
        # Perform token transfer on the blockchain side
        print(f"Token transfer: {love_currency} token transferred from {self.sender} to {self.receiver} in dimension {self.receiver_dimension}.")

    def decrypt_data(self, private_key):
        decrypted_data = decrypt(self.encrypted_data, private_key)
        return decrypted_data

    def pay_reward_to_approver(self, reward_amount):
        # Pay reward to the approver
        approver_wallet = wallets[self.approval_target]
        approver_wallet.add_balance(reward_amount)

class Block:
    def __init__(self, index, previous_hash, timestamp, data, proof_of_place, proof_of_history, zero_knowledge_proof):
        self.index = index
        self.previous_hash = previous_hash
        self.timestamp = timestamp
        self.data = data
        self.proof_of_place = proof_of_place
        self.proof_of_history = proof_of_history
        self.zero_knowledge_proof = zero_knowledge_proof
        self.hash = self.calculate_hash()

    def calculate_hash(self):
        hash_data = (
            str(self.index) +
            str(self.previous_hash) +
            str(self.timestamp) +
            str(self.data) +
            str(self.proof_of_place) +
            str(self.proof_of_history) +
            str(self.zero_knowledge_proof)
        )
        return hashlib.sha256(hash_data.encode()).hexdigest()

class Blockchain:
    def __init__(self):
        self.chain = [self.create_genesis_block()]
        self.validators = set()
        self.current_validators = set()

    def create_genesis_block(self):
        return Block(0, "0", datetime.now(), "Genesis Block", "Proof of Place", "Proof of History", "Zero Knowledge Proof")

    def get_latest_block(self):
        return self.chain[-1]

    def add_validator(self, validator):
        self.validators.add(validator)

    def select_validators(self):
        self.current_validators = set(random.sample(self.validators, k=3))  # Select 3 random validators from the set of validators
        return self.current_validators

    def add_block(self, transaction):
        index = len(self.chain)
        previous_block = self.get_latest_block()
        new_block = Block(index, previous_block.hash, datetime.now(), transaction, transaction.generate_proof_of_place(), transaction.generate_proof_of_history(), transaction.zero_knowledge_proof)
        self.chain.append(new_block)

        # Validate the block by current validators
        if all(validator in self.current_validators for validator in transaction.validators):
            self.chain.append(new_block)
            transaction.pay_reward_to_approver(transaction.love_action_level * 0.03)  # Pay 3% reward to approver
        else:
            print("Block validation failed. Block not added to the chain.")

def generate_key():
    p = 499
    q = 547
    n = p * q
    lam = (p-1)*(q-1)
    g = 2
    return (n, g, lam)

def encrypt(m, n, g):
    r = random.randint(1, n-1)
    c = (pow(g, m, n**2) * pow(r, n, n**2)) % (n**2)
    return c

def decrypt(c, private_key):
    n, g, _ = private_key
    phi_n = (n - 1) // 2
    m = ((pow(c, phi_n, n**2) - 1) // n) * g % n
    return m

class Human:
    def __init__(self, name, roles):
        self.name = name
        self.roles = roles

class LifeForm:
    def __init__(self, name, dimension, human):
        self.name = name
        self.dimension = dimension
        self.human = human

    def evaluate_lifeform(self):
        total_love_actions = sum([self.human.roles[role] for role in self.human.roles])
        print(f"Lifeform {self.name} in dimension {self.dimension} has total love actions: {total_love_actions}")
        # Perform further evaluation based on total_love_actions and lifeform attributes
        ...

blockchain = Blockchain()
wallets = {}

# Create wallets for municipalities
for municipality in ["Municipality1", "Municipality2", "Municipality3"]:
    wallets[municipality] = Wallet(municipality)

users = {
    "A": {"location": "Location1", "love_action_level": 8, "action_content": "Action Content A", "sender_dimension": 2, "receiver_dimension": 4},
    "B": {"location": "Location2", "love_action_level": 6, "action_content": "Action Content B", "sender_dimension": 2, "receiver_dimension": 3},
    "C": {"location": "Location3", "love_action_level": 3, "action_content": "Action Content C", "sender_dimension": 3, "receiver_dimension": 4},
    "D": {"location": "Location4", "love_action_level": 10, "action_content": "Action Content D", "sender_dimension": 3, "receiver_dimension": 2}
}

humans = {
    "Alice": {"roles": {1: 10, 2: 8, 3: 7, 4: 6, 5: 9, 6: 8, 7: 7, 8: 8, 9: 7, 10: 6}},
    "Bob": {"roles": {1: 6, 2: 8, 3: 7, 4: 6, 5: 9, 6: 8, 7: 7, 8: 8, 9: 7, 10: 6}},
    "Charlie": {"roles": {1: 8, 2: 8, 3: 7, 4: 6, 5: 9, 6: 8, 7: 7, 8: 8, 9: 7, 10: 6}},
    "David": {"roles": {1: 7, 2: 8, 3: 7, 4: 6, 5: 9, 6: 8, 7: 7, 8: 8, 9: 7, 10: 6}}
}

lifeforms = [
    LifeForm("A", 2, Human("Alice", humans["Alice"]["roles"])),
    LifeForm("B", 3, Human("Bob", humans["Bob"]["roles"])),
    LifeForm("C", 4, Human("Charlie", humans["Charlie"]["roles"])),
    LifeForm("D", 3, Human("David", humans["David"]["roles"]))
]

for sender_name, sender_data in users.items():
    for receiver_name, receiver_data in users.items():
        if sender_name != receiver_name:
            approver_name = random.choice(list(users.keys()))  # Choose a random user as the approver
            approver_data = users[approver_name]
            transaction = Transaction(sender_name, receiver_name, sender_data["location"], sender_data["love_action_level"], sender_data["action_content"], sender_data["sender_dimension"], receiver_data["receiver_dimension"], approver_name, approver_data["sender_dimension"])
            transaction.validators = blockchain.select_validators()  # Select validators for the transaction
            transaction.transfer_token(TOKEN_TYPES[transaction.love_action_level])
            blockchain.add_block(transaction)
            lifeforms[transaction.sender_dimension - 1].evaluate_lifeform()

latest_block = blockchain.get_latest_block()
print(f"Latest Block #{latest_block.index} - Hash: {latest_block.hash}")
 

 

■前回のシャーディングと並列処理のプログラムを比較すると、以下の点が異なる。

  1. セキュリティの強固さ:

    • 並列処理のプログラムでは、トランザクションが一つのメインチェーンに集約され、マルチスレッドでの競合を避けるためにMutexを使用して排他制御している。これにより、トランザクションの処理が安全に行われる。
    • 一方、シャーディングのプログラムでは、トランザクションが複数のシャードに分散され、各シャードごとに処理される。これにより、トランザクション処理の負荷が分散され、スケーラビリティが向上するが、セキュリティの面では、シャードごとにデータが分散されるため、全体としてのセキュリティが弱くなる可能性がある。
  2. 負荷の分散:

    • 並列処理のプログラムでは、マルチスレッドでの処理が行われるため、トランザクションの処理が負荷分散される。複数のスレッドが同時に異なるトランザクションを処理できるため、全体としての処理速度が向上する。
    • シャーディングのプログラムでは、トランザクションがシャードごとに分散されるため、各シャードごとに独立して処理が行われる。これにより、トランザクション処理の負荷が分散され、スケーラビリティが向上するが、全体としての処理速度は、シャードごとの処理速度に依存することになる。

総合的に見ると、並列処理のプログラムはセキュリティの面で強固であり、負荷分散も行われている。一方、2つ目のプログラムは負荷分散がより効果的に行われているが、セキュリティの面では弱くなる可能性がある。どちらのプログラムを選択するかは、セキュリティとスケーラビリティのバランスを考慮して決定する必要がある。

 

 

いかがであろうか、メインチェーンに100万以上もの市町村のブロックチェーンが繋がっているような場合、ものすごい負荷がメインチェーンにはかかる。これを分散させるためにも、並列処理やシャーディングのような技術を用いて分散させるのだ。これによって、負荷を少しでも分散させたいのだ。実現させるには、まだまだ、さまざまな課題をクリアせねばならないのだが。