Skip to content
Snippets Groups Projects
expire.rs 4.85 KiB
Newer Older
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(())