Skip to content
Snippets Groups Projects
Forked from clients / Rust / Ğcli-v2s
126 commits behind the upstream repository.
expire.rs 6.10 KiB
use crate::{cache, gdev, indexer::*, Args, Client};

use anyhow::Result;
use futures::join;
use std::collections::BTreeMap;

pub async fn monitor_expirations(
    client: Client,
    blocks: u32,
    sessions: u32,
    args: &Args,
) -> Result<()> {
    let gql_client = reqwest::Client::builder()
        .user_agent("gcli/0.1.0")
        .build()?;

    let parent_hash = client
        .storage()
        .fetch(&gdev::storage().system().parent_hash(), None)
        .await?
        .unwrap();
    let addr_current_block = gdev::storage().system().number();
    let addr_current_session = gdev::storage().session().current_index();
    let (current_block, current_session) = join!(
        client
            .storage()
            .fetch(&addr_current_block, Some(parent_hash)),
        client
            .storage()
            .fetch(&addr_current_session, Some(parent_hash),)
    );
    let current_block = current_block?.unwrap();
    let current_session = current_session?.unwrap();

    let end_block = current_block + blocks;
    let end_session = current_session + sessions;

    let mut identity_cache = cache::IdentityCache::new(
        &client,
        if args.no_indexer {
            None
        } else {
            Some(Indexer {
                gql_client,
                gql_url: &args.indexer,
            })
        },
    );

    // Rotate keys
    let mut must_rotate_keys_before_iter = client
        .storage()
        .iter(
            gdev::storage()
                .authority_members()
                .must_rotate_keys_before(0),
            10,
            Some(parent_hash),
        )
        .await?;
    let mut must_rotate_keys_before = BTreeMap::new();
    while let Some((k, v)) = must_rotate_keys_before_iter.next().await? {
        let session_index = u32::from_le_bytes(k.as_ref()[40..44].try_into().unwrap());
        if session_index < end_session {
            must_rotate_keys_before.insert(session_index - current_session, v);
        }
    }

    println!("\nAuthority members:");
    for (sessions_left, identity_ids) in must_rotate_keys_before {
        println!("Must rotate keys before {sessions_left} sessions:");
        for identity_id in identity_ids {
            println!(
                "  {} ({})",
                identity_cache
                    .fetch_identity(identity_id, parent_hash)
                    .await
                    .unwrap_or_else(|_| "?".into()),
                identity_id
            );
        }
    }

    // Certifications
    let mut basic_certs_iter = client
        .storage()
        .iter(
            gdev::storage().cert().storage_certs_removable_on(0),
            10,
            Some(parent_hash),
        )
        .await?;
    let mut basic_certs = BTreeMap::new();
    while let Some((k, v)) = basic_certs_iter.next().await? {
        let block_number = u32::from_le_bytes(k.as_ref()[40..44].try_into().unwrap());
        if block_number < end_block {
            basic_certs.insert(block_number - current_block, v);
        }
    }

    let mut smith_certs_iter = client
        .storage()
        .iter(
            gdev::storage().smiths_cert().storage_certs_removable_on(0),
            10,
            Some(parent_hash),
        )
        .await?;
    let mut smith_certs = BTreeMap::new();
    while let Some((k, v)) = smith_certs_iter.next().await? {
        let block_number = u32::from_le_bytes(k.as_ref()[40..44].try_into().unwrap());
        if block_number < end_block {
            smith_certs.insert(block_number - current_block, v);
        }
    }

    for (title, certs) in [
        ("Certifications", basic_certs),
        ("Smith certifications", smith_certs),
    ] {
        println!("\n{title}:");
        for (blocks_left, certs) in certs {
            println!("{blocks_left} blocks before expiration:");
            for (issuer_id, receiver_id) in certs {
                println!(
                    "  {} ({}) -> {} ({})",
                    identity_cache
                        .fetch_identity(issuer_id, parent_hash)
                        .await
                        .unwrap_or_else(|_| "?".into()),
                    issuer_id,
                    identity_cache
                        .fetch_identity(receiver_id, parent_hash)
                        .await
                        .unwrap_or_else(|_| "?".into()),
                    receiver_id,
                );
            }
        }
    }

    // Memberships
    let mut basic_membership_iter = client
        .storage()
        .iter(
            gdev::storage().membership().memberships_expire_on(0),
            10,
            Some(parent_hash),
        )
        .await?;
    let mut basic_memberships = BTreeMap::new();
    while let Some((k, v)) = basic_membership_iter.next().await? {
        let block_number = u32::from_le_bytes(k.as_ref()[40..44].try_into().unwrap());
        if block_number < end_block {
            basic_memberships.insert(block_number - current_block, v);
        }
    }

    let mut smith_membership_iter = client
        .storage()
        .iter(
            gdev::storage().smiths_membership().memberships_expire_on(0),
            10,
            Some(parent_hash),
        )
        .await?;
    let mut smith_memberships = BTreeMap::new();
    while let Some((k, v)) = smith_membership_iter.next().await? {
        let block_number = u32::from_le_bytes(k.as_ref()[40..44].try_into().unwrap());
        if block_number < end_block {
            smith_memberships.insert(block_number - current_block, v);
        }
    }

    for (title, memberships) in [
        ("Memberships", basic_memberships),
        ("Smith memberships", smith_memberships),
    ] {
        println!("\n{title}:");
        for (blocks_left, membership) in memberships {
            println!("{blocks_left} blocks before expiration:");
            for identity_id in membership {
                println!(
                    "  {} ({})",
                    identity_cache
                        .fetch_identity(identity_id, parent_hash)
                        .await
                        .unwrap_or_else(|_| "?".into()),
                    identity_id,
                );
            }
        }
    }

    Ok(())
}