愛記システム概念設計:システム構築の品質評価のポイント6 保守性③ | 続・ティール組織 研究会のブログ

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

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

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

愛記システムのシステム評価について

システム評価とは、つまりは、このシステムを導入して成功だったか失敗だったかという効果検証という意味だ。概念設計をする上で必ず抑えておくべきポイントということだ。それには各項目があり、それぞれの項目を見ていくことで、その結果が得られる。そのシステム評価項目を1つずつ見ていきたい。

システム構築の品質評価のポイント1:理解可能性(Understandability)

システム構築の品質評価のポイント2:完全性(Completeness)

システム構築の品質評価のポイント3:簡潔性(Conciseness)

システム構築の品質評価のポイント4:移植性(Portability)

システム構築の品質評価のポイント5:一貫性(Consistency)と構造化の度合い

システム構築の品質評価のポイント6:保守性(Maintainability)

システム構築の品質評価のポイント7:試験性(Testability)

システム構築の品質評価のポイント8:ユーザビリティ(Usability)

システム構築の品質評価のポイント9:効率性(Efficiency)

システム構築の品質評価のポイント10:セキュリティ(Security)

システム構築の品質評価のポイント6:保守性③(Maintainability)

システム構築の評価に繋がる保守性であるが、当方は、ブロックチェーンSNSとDapps側の愛記システムを、”愛貨”というトークンで創っていくということを考えている。そのために、APIによる通信ではなく、フェデレーションモデルを検討したい。

 

最初は一つの市町村における所得税減税や法人税減税サービスにつながるブロックチェーンSNSを考慮しているのだが、ゆくゆくは、他の市町村も同様に”愛貨”をやり取りするブロックチェーンSNSを導入したい!という声があがるだろう。さらには、世界中の各都市が同様に手をあげるかもしれない。そうなると、各市町村のブロックチェーンSNSが群雄割拠することになり、それらブロックチェーン間をブリッジして情報をやりとりすることも出てくるだろう。そうなると、各市町村のブロックチェーンを跨いで承認行為を行うようなフェデレーションモデルが必要になってくるということだ。

 

そして、フェデレーションが承認を行う際に、データやトランザクションにアクセスして必要な合意形成を行うことで、各市町村のブロックチェーンが提供する様々なサービスや機能を統合し、連携させる。このような仕組みを設けておけば、ある市町村のブロックチェーンSNSと、別の市町村のブロックチェーンSNSとを選択しながらユーザーは行動していけるということも可能となる。

”愛貨”をトークンとするブロックチェーンについて

Solanaの仕組みは魅力的であり、”愛貨”をトークンとする当方のブロックチェーンや愛記システムも同様な仕組みとすることを検討したい。Solanaは、トランザクションの処理にシャードやセカンドレイヤーを利用することなく、すべての処理がオンチェーンで行われるため、透明性が担保される。また、開発者やプログラムはSolanaの単一のグローバルな状態にアクセスできるため、プロジェクト間のコンポーザビリティが向上する。極めて保守性が高いといえる。”愛貨”もこのような状態を目指したい。

 

Proof of History (POH) — コンセンサスにおける時間同期。 

Tower BFT — POHに最適化されたビザンチン将軍問題解決 

Turbine — ブロックの伝搬プロトコル 

Gulf Stream — Mempoolレスなトランザクションフォワードプロトコル 

Sealevel — スマートコントラクトを並列で実行 

Pipelining — 認証最適化のためのトランザクション処理ユニット 

Cloudbreak — パラレルスケーリングのアカウントデータベース 

Archivers — 分散型台帳保管

 

これらのアイデアはとても魅力的であり、愛記システムにもできる限り組み込んでいきたい。愛記システムにこれらの技術を組み込み、さらに、PoP(proof of Place)のアルゴリズムも加えたい。というのも、各市町村のブロックチェーンは、各市町村で愛の行動をしたという場所の証明が重要になる。

PoPアルゴリズム

数学的な概念からの設計は別に行うとして、各市町村というエリア内で行われた愛の行動かどうかを証明するアルゴリズムであればよいと考える。以下に、フェデレーションが各市町村の公開鍵を持ち、ユーザーが位置情報を署名してその署名が検証されると、フェデレーションを通じて各市町村に対して位置情報が通知されるフローを示す。

  1. 各市町村の鍵生成:

    • 各市町村は自身の鍵ペア(公開鍵と秘密鍵)を生成する。
  2. ユーザーの鍵生成:

    • ユーザーは自身の鍵ペアを生成する。この鍵ペアには、公開鍵が他者に共有される部分で、秘密鍵はユーザーが秘密に保持する部分が含まれる。
  3. 位置情報の署名:

    • ユーザーは自身の秘密鍵を使用して、位置情報を署名する。これにより、ユーザーがその位置情報に対して正当な所有者であることが示される。
  4. 署名検証:

    • フェデレーションはユーザーの公開鍵を使用して、ユーザーが署名した位置情報を検証する。署名が正当であれば、その位置情報はユーザーによって認証されたものと見なされる。
  5. 位置情報の通知:

    • 署名が検証された位置情報は、フェデレーションを通じて各市町村に通知される。各市町村はそれを受け取り、必要に応じて処理を行う。

このような流れを通じて、フェデレーションを介して位置情報が各市町村に配信され、信頼性のある位置情報が得られることが期待される。

 

また、Proof of Place (PoP) のアルゴリズムをブロックチェーンに組み込む試みは、他でも実際に行われているが、その導入には様々な課題がある。以下にいくつかの理由を挙げてみよう:

  1. セキュリティの懸念:

    • PoPのアルゴリズムがうまく機能するためには、位置情報が正確で信頼性が高いことが求められる。しかし、GPSや他の位置情報取得手段は、スプーフィング(位置情報の偽装)などの攻撃に対して脆弱である可能性がある。このため、セキュリティの懸念が存在する。
  2. プライバシーの問題:

    • ブロックチェーン上で個々のユーザーの位置情報を扱うことは、プライバシーの観点から慎重に考える必要がある。ユーザーの位置情報を不用意に公開すると、プライバシー侵害のリスクが高まる。
  3. 実装の複雑性:

    • ブロックチェーン上で位置情報を扱うことは、実装の複雑性を増す可能性がある。特に、リアルタイムで位置情報を確認し、それをブロックチェーンに反映させることは技術的な課題を伴う。
  4. 合法的な制約:

    • ある地域では位置情報の取り扱いに法的な制約がある場合がある。これらの法的な要件を満たすためには、慎重な設計と実装が必要である。

これらの理由から、PoPをブロックチェーンに組み込むことは難易度が高く、検討すべき多くの側面が存在する。一部のプロジェクトやアプリケーションは、これらの問題に対処し、PoPを導入しているが、一般的には慎重な検討とセキュリティ対策が求められる。

 

そこで当方では、位置をそのまま取ると法的に問題があるなら、市町村に居るか居ないかだけを判別するというアルゴリズムにしているという具合だ。市町村に居るかどうかを判別するアルゴリズムを設計することは、プライバシーに対する配慮があり、法的な問題を軽減する一手段となりえる。

  1. ユーザーが特定の市町村にいる場合、特定のトリガーが発生する(例: 特定のWi-Fiネットワークに接続された、特定のBluetoothデバイスが検出された、GPSの位置情報を取得し市町村内にいるかどうかを判別する、など)。

  2. ユーザーのデバイスは、トリガーの発生を検知し、それをブロックチェーンにトランザクションとして送信する。

  3. ブロックチェーン上でトランザクションが確認されると、ユーザーはその市町村にいると見なされる。

  4. ブロックチェーン上でトランザクションがない場合、ユーザーはその市町村にいないと見なされる。

from ecdsa import SigningKey, VerifyingKey, NIST521p

class LocationAlgorithmECC:
    def __init__(self, municipality_private_key, municipality_boundary):
        self.private_key = SigningKey.generate(curve=NIST521p) if municipality_private_key is None else municipality_private_key
        self.public_key = self.private_key.verifying_key
        self.is_in_municipality = False
        self.municipality_boundary = municipality_boundary

    def detect_location_trigger(self, user_public_key, user_signature, gps_location):
        # ユーザーの公開鍵で署名を検証
        verification_result = self.verify_user_signature(user_public_key, user_signature)

        if verification_result:
            # ユーザーの署名が正当な場合、GPS位置情報を検証
            self.is_in_municipality = self.verify_gps_location(gps_location)
            return self.is_in_municipality
        else:
            # ユーザーの署名が不正な場合、市町村にいないと見なす
            self.is_in_municipality = False
            return False

    def verify_user_signature(self, user_public_key, user_signature):
        try:
            verifying_key = VerifyingKey.from_string(user_public_key, curve=NIST521p)
            verifying_key.verify(user_signature, "User is in the municipality".encode())
            return True
        except Exception as e:
            print(f"Verification failed: {e}")
            return False

    def verify_gps_location(self, gps_location):
        # 市町村の範囲内にいるかどうかを判定
        return self.municipality_boundary[0][0] <= gps_location[0] <= self.municipality_boundary[1][0] and \
               self.municipality_boundary[0][1] <= gps_location[1] <= self.municipality_boundary[1][1]

# メインチェーンのフェデレーション
class Federation:
    def __init__(self, municipality_public_keys, municipality_boundaries):
        self.municipality_public_keys = [VerifyingKey.from_string(key, curve=NIST521p) for key in municipality_public_keys]
        self.municipality_boundaries = municipality_boundaries

    def verify_user_location(self, user_public_key, user_signature, gps_location):
        for i, public_key in enumerate(self.municipality_public_keys):
            try:
                public_key.verify(user_signature, "User is in the municipality".encode())
                # フェデレーションの検証が成功した場合、GPS位置情報を検証
                if self.verify_gps_location(gps_location, i):
                    return True
            except Exception as e:
                pass  # 各市町村の公開鍵で検証を試みる

        return False

    def verify_gps_location(self, gps_location, municipality_index):
        # 市町村の範囲内にいるかどうかを判定
        return self.municipality_boundaries[municipality_index][0][0] <= gps_location[0] <= self.municipality_boundaries[municipality_index][1][0] and \
               self.municipality_boundaries[municipality_index][0][1] <= gps_location[1] <= self.municipality_boundaries[municipality_index][1][1]

# 各市町村の鍵ペア生成
municipality1_private_key = SigningKey.generate(curve=NIST521p)
municipality1_public_key = municipality1_private_key.verifying_key.to_string().hex()

municipality2_private_key = SigningKey.generate(curve=NIST521p)
municipality2_public_key = municipality2_private_key.verifying_key.to_string().hex()

# 各市町村の範囲を設定(仮のダミーデータ)
municipality1_boundary = ((35.0, 138.5), (35.5, 139.0))
municipality2_boundary = ((36.0, 139.0), (36.5, 139.5))

# 各市町村のインスタンス生成
municipality1_algorithm = LocationAlgorithmECC(municipality1_private_key, municipality1_boundary)
municipality2_algorithm = LocationAlgorithmECC(municipality2_private_key, municipality2_boundary)

# 各市町村の公開鍵リストおよび範囲のリスト
municipality_public_keys = [municipality1_public_key, municipality2_public_key]
municipality_boundaries = [municipality1_boundary, municipality2_boundary]

# フェデレーションのインスタンス生成
federation = Federation(municipality_public_keys, municipality_boundaries)

# ユーザーの鍵ペア生成
user_private_key = SigningKey.generate(curve=NIST521p)
user_public_key = user_private_key.verifying_key.to_string().hex()

# ダミーのGPS位置情報 (例: 東京都庁の位置)
gps_location = (35.6895, 139.6917)

# ユーザーが位置情報を署名
user_signature = user_private_key.sign("User is in the municipality".encode())

# トリガーが検出されたかどうかの確認
trigger_detected = check_specific_trigger()

# 各市町村でトリガーが検出された場合、ユーザーの位置情報を検証
for municipality_algorithm in [municipality1_algorithm, municipality2_algorithm]:
    if municipality_algorithm.detect_location_trigger(user_public_key, user_signature, gps_location):
        print("User is in the municipality.")
        break
else:
    print("User is not in the municipality.")
 

この例では、各市町村とフェデレーションが位置情報の検証を行う。各市町村は自身の範囲内にユーザーがいるかどうかを検証し、フェデレーションは各市町村の検証結果を確認して最終的な結果を出力する。GPS位置情報の範囲判定の具体的なアルゴリズムは、地理情報データを利用して正確な範囲を設定する必要があるのだろう。

 

なお、今は直接オープンデータやGISデータベースにアクセスすることはしない。しかし、一般的な手順に基づいて、地理情報データを使用して範囲判定を行うアルゴリズムを作成することができる。実際のデータに基づいた正確なアルゴリズムを作成するには、対象となる地域の具体的なデータを入手する必要がある。

 

def is_in_municipality(gps_location, municipality_polygon):
    """
    緯度経度が市町村のポリゴン内にあるかどうかを判定する関数
    :param gps_location: (latitude, longitude) 形式の緯度経度
    :param municipality_polygon: 市町村のポリゴン座標 [(lat1, lon1), (lat2, lon2), ..., (latn, lonn)]
    :return: 真(True)なら市町村内、偽(False)なら市町村外
    """
    lat, lon = gps_location

    # ポリゴン内外の判定アルゴリズム
    cross_count = 0
    for i in range(len(municipality_polygon)):
        lat1, lon1 = municipality_polygon[i]
        lat2, lon2 = municipality_polygon[(i + 1) % len(municipality_polygon)]

        if ((lat1 <= lat < lat2) or (lat2 <= lat < lat1)) and \
                (lon < (lon2 - lon1) * (lat - lat1) / (lat2 - lat1) + lon1):
            cross_count += 1

    return cross_count % 2 == 1

# 例として市町村のポリゴン座標を設定
municipality_polygon = [(35.0, 138.5), (36.0, 138.5), (36.0, 139.5), (35.0, 139.5)]

# 例としてGPS位置を設定
gps_location = (35.5, 139.0)

# 範囲判定を行う
result = is_in_municipality(gps_location, municipality_polygon)
print(f"The user is in the municipality: {result}")
 

この例では、市町村のポリゴン座標とGPS位置が与えられた場合に、指定された座標が市町村内にあるかどうかを判定できる。ただ、面倒なのが、市町村の数が何千、何万、何十万と増えていった場合、処理が面倒ではある。メインチェーンの場合は、受信者が受信するプロセスになるが、受信者が在籍している市町村と、受信時に居た市町村では異なる可能性があるため、結局は受信時に居た市町村のデータを返さねばならない。そのため何十万という市町村のポリゴンと突き合わせをしていく必要が出てくるので、とても面倒である。

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

では、上記をふまえて、メインチェーンのプログラムをやりなおしてみよう。メインチェーンのプログラムは、フェデレーションモデルで各市町村のブロックチェーンとつながるものである。まず、市町村のブロックチェーンが、送信者の位置情報を確認して、自身の市町村に居ることを確認してから、トランザクションを承認してメインチェーンにデータを送る。メインチェーンでは、送られてきたトランザクションを保留にしておき、受信者が受信ボタンを押すと、その信号がメインチェーンに飛んでくるので、そこから保留にしていたトランザクションを承認しにかかる。その時、受信者がどの市町村にいるか、GPSやその他の手段で読み取りがなされて、世界中のどの市町村にいるのかを特定する。そして、保留にしていたトランザクションを承認するとともに、受信者が受信時に居た市町村の位置データもトランザクションに含めて、トランザクションの承認を行う。それにより、愛貨トークンがやりとりされるという仕組みにしたい。
 

use chrono::{DateTime, Utc};
use sha2::{Digest, Sha256};
use std::collections::{HashMap, HashSet};
use std::time::Duration;

// トランザクション結果
#[derive(Debug)]
enum TransactionResult {
    Success,
    Failure,
}

// Verifiable Credentialの構造体
#[derive(Debug, Clone)]
struct VerifiableCredential {
    user_id: String,
    claim_data: HashMap<String, String>,
    timestamp: DateTime<Utc>,
}

// Blockchainトレイト
trait Blockchain {
    fn store_credential(&self, credential: &VerifiableCredential) -> Option<TransactionResult>;
    fn update_shared_credential(&self, recipient_id: &str, credential: &VerifiableCredential) -> Option<TransactionResult>;
}

// Blockchainのダミー実装
struct DummyBlockchain;

impl Blockchain for DummyBlockchain {
    fn store_credential(&self, _credential: &VerifiableCredential) -> Option<TransactionResult> {
        Some(TransactionResult::Success)
    }

    fn update_shared_credential(&self, _recipient_id: &str, _credential: &VerifiableCredential) -> Option<TransactionResult> {
        Some(TransactionResult::Success)
    }
}

// VerifiableCredentialManagerクラス
struct VerifiableCredentialManager<T: Blockchain> {
    blockchain: T,
    credentials: HashMap<String, VerifiableCredential>,
}

impl<T: Blockchain> VerifiableCredentialManager<T> {
    fn new(blockchain: T) -> Self {
        VerifiableCredentialManager {
            blockchain,
            credentials: HashMap::new(),
        }
    }

    fn create_verifiable_credential(&mut self, user_id: String, claim_data: HashMap<String, String>) {
        let credential = VerifiableCredential {
            user_id: user_id.clone(),
            claim_data: claim_data.clone(),
            timestamp: Utc::now(),
        };

        if let Some(transaction_result) = self.blockchain.store_credential(&credential) {
            self.credentials.insert(user_id, credential.clone());
            println!("Verifiable Credential created and stored for user {}.", user_id);
        } else {
            println!("Failed to store Verifiable Credential.");
        }
    }

    fn share_verifiable_credential(&mut self, user_id: &str, recipient_id: &str) {
        if let Some(credential_to_share) = self.credentials.get(user_id) {
            if let Some(update_result) = self.blockchain.update_shared_credential(recipient_id, credential_to_share) {
                println!("Verifiable Credential shared with user {}.", recipient_id);
            } else {
                println!("Failed to share Verifiable Credential.");
            }
        } else {
            println!("No Verifiable Credential found for user {}.", user_id);
        }
    }
}

// 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);
            // メインチェーンから自治体のブロックチェーンにデータを送信する処理を実装する
            // ここで自治体のブロックチェーンにデータを送信する処理を実装する
            let mut dummy_blockchain = DummyBlockchain;
            dummy_blockchain.store_credential(&VerifiableCredential {
                user_id: "UserA".to_string(),
                claim_data: HashMap::new(),
                timestamp: Utc::now(),
            });
        } 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
    }

    // 新しいエンドポイントを追加して、リクエストを受け取ってからapprove_requestメソッドを呼び出す
    fn approve_request_from_municipality(data: &Transaction) {
        if data.verify_signature() {
            println!("Received approval request from municipality: {:?}", data);
            let mut dummy_blockchain = DummyBlockchain;
            dummy_blockchain.store_credential(&VerifiableCredential {
                user_id: "UserA".to_string(),
                claim_data: HashMap::new(),
                timestamp: Utc::now(),
            });
            // 実際には、リクエストを処理するロジックを実装する
        } else {
            println!("Failed to approve request: Invalid signature");
        }
    }
}

// トランザクションの構造体
#[derive(Debug)]
struct Transaction {
    transaction_id: String,
    municipality: String,
    timestamp: DateTime<Utc>,
    location: (f64, f64), // 緯度と経度を表すタプル
    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>>,

  recipient_location: Option<(f64, f64)>, // 受信時の位置情報を保持するフィールドを追加 
}

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(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);
        // 愛貨トークンを受け取る処理を実装する
        decreased_amount
    }

    fn verify_signature(&self) -> bool {
        // 署名を検証する処理を実装する
        true
    }
 

  // 位置情報が境界内かどうかを判定 

    fn is_within_boundary(&self, boundary: &((f64, f64), (f64, f64))) -> bool {

         // 境界の座標を定義 

         let boundary = ((35.6, 139.6), (35.7, 139.7)); 

         let ((min_lat, min_lon), (max_lat, max_lon)) = boundary; 

   self.location.0 >= *min_lat && self.location.0 <= *max_lat &&
         self.location.1 >= *min_lon && self.location.1 <= *max_lon

    }

 

    // 受信時の位置情報をセットするメソッド 

    fn set_recipient_location(&mut self, location: (f64, f64)) { 

         self.recipient_location = Some(location);

    }
}
 

fn main() {
    // メインチェーンの初期化
    let main_chain = create_main_chain();
}

// メインチェーンの構造体
struct MainChain {
    federated_blockchains: HashMap<String, Federation>,
    pending_transactions: HashMap<String, Transaction>,
    received_transactions: HashSet<String>,
}

impl MainChain {
    // メインチェーンから自治体のブロックチェーンにデータを送信
    fn send_data_to_municipality_chain(&mut self, transaction_id: &str, municipality_name: &str, recipient_location: &(f64, f64)) {
        if self.received_transactions.contains(transaction_id) {
            println!("Transaction already received with ID {}.", transaction_id);
            return;
        }

        if let Some(federation) = self.federated_blockchains.get(municipality_name) {
            federation.process_pending_transaction(transaction_id, recipient_location);
        } else {
            println!("Federation not found for municipality {}.", municipality_name);
        }
    }

    // メインチェーンが自治体から承認シグナルを受信
    fn receive_approval_signal(&mut self, transaction_id: &str, recipient_location: &(f64, f64)) {
        if let Some(federation) = self.federated_blockchains.values_mut().find(|federation| federation.has_pending_transaction(transaction_id)) {
            if let Some(transaction) = self.pending_transactions.get(transaction_id) {
                // 境界内かどうかを判定
                if federation.is_within_boundary(&transaction.location) && federation.is_within_boundary(recipient_location) {
                    println!("Transaction {} approved by federation.", transaction_id);
                    // フェデレーションにトランザクションの承認シグナルを受信させる処理を実装する
                } else {
                    println!("Transaction {} rejected by federation due to location validation failure.", transaction_id);
                }
            } else {
                println!("Pending transaction not found with ID {}.", transaction_id);
            }
        } else {
            println!("Federation not found for pending transaction with ID {}.", transaction_id);
        }
    }
}

// フェデレーションの構造体
struct Federation {
    boundary: ((f64, f64), (f64, f64)),
    pending_transactions: HashMap<String, (Transaction, (f64, f64))>,
}

impl Federation {
    // 新規フェデレーションの作成
    fn new(public_key: String, boundary: ((f64, f64), (f64, f64))) -> Self {
        Federation {
            public_key,
            boundary,
            pending_transactions: HashMap::new(),
        }
    }

    // フェデレーションがペンディングトランザクションを処理
    fn process_pending_transaction(&mut self, transaction_id: &str, recipient_location: &(f64, f64)) {
        if let Some((transaction, sender_location)) = self.pending_transactions.remove(transaction_id) {
            if self.is_within_boundary(recipient_location) && self.is_within_boundary(&sender_location) {
                println!("Transaction {} approved by federation with public key {}.", transaction_id, self.public_key);
            } else {
                println!("Transaction {} rejected by federation with public key {} due to location validation failure.", transaction_id, self.public_key);
            }
        } else {
            println!("Transaction {} not found in pending transactions.", transaction_id);
        }
    }

    // フェデレーションがペンディングトランザクションの承認シグナルを受信
    fn receive_approval_signal(&mut self, transaction_id: &str, recipient_location: &(f64, f64)) {
        if let Some((transaction, sender_location)) = self.pending_transactions.get(transaction_id) {
            if self.is_within_boundary(recipient_location) && self.is_within_boundary(&sender_location) {
                println!("Received approval signal for transaction {} from federation with public key {}.", transaction_id, self.public_key);
            } else {
                println!("Received invalid approval signal for transaction {} from federation with public key {}.", transaction_id, self.public_key);
            }
        } else {
            println!("Pending transaction not found with ID {} in federation with public key {}.", transaction_id, self.public_key);
        }
    }

    // ペンディングトランザクションの存在確認
    fn has_pending_transaction(&self, transaction_id: &str) -> bool {
        self.pending_transactions.contains_key(transaction_id)
    }

    // 位置情報が境界内かどうかを判定
    fn is_within_boundary(&self, location: &(f64, f64)) -> bool {
        let ((min_lat, min_lon), (max_lat, max_lon)) = self.boundary;
        location.0 >= min_lat && location.0 <= max_lat && location.1 >= min_lon && location.1 <= max_lon
    }
}

 

 

いかがであろうか、以上がブロックチェーンの保守性であった。Solanaの仕組みは魅力的であり、”愛貨”も同様な仕組みにPoPというアルゴリズムを加えることを検討したい。Solanaは、トランザクションの処理にシャードやセカンドレイヤーを利用することなく、すべての処理がオンチェーンで行われるため、透明性が担保される。また、開発者やプログラムはSolanaの単一のグローバルな状態にアクセスできるため、プロジェクト間のコンポーザビリティが向上する。極めて保守性が高いといえる。”愛貨”もこのような状態を目指したい。