Skip to content
Snippets Groups Projects
Select Git revision
  • 91541c96ceb7026f05a87c181cd92bd141ef0411
  • master default protected
  • dev
  • appimage
  • fix_gitlab
  • fixappveyor
  • gitlab
  • fix_ci
  • fix_dbus_error
  • fix_ci_osx
  • sakia020
  • fix_travis#1105
  • feature/backend
  • check_uniq_node_by_endpoints
  • qt5.7
  • feature/agent_architecture
  • translations
  • pyqt5.6
  • qtwebengine
  • pyinstaller
  • landscape
  • 0.53.2
  • 0.53.1
  • 0.53.0
  • 0.52.0
  • 0.51.1
  • 0.51.0
  • 0.50.5
  • 0.50.4
  • 0.50.3
  • 0.50.2
  • 0.50.1
  • 0.50.0
  • 0.33.0rc7
  • 0.33.0rc6
  • 0.33.0rc5
  • 0.33.0rc4
  • 0.33.0rc3
  • 0.33.0rc2
  • 0.33.0rc1
  • 0.32.10post1
41 results

run_tests.py

Blame
  • identity.rs 6.04 KiB
    use crate::*;
    
    use crate::{
    	commands::revocation::generate_revoc_doc,
    	runtime::runtime_types::{
    		common_runtime::entities::IdtyData, pallet_identity::types::*, sp_core::sr25519::Signature,
    		sp_runtime::MultiSignature,
    	},
    };
    use std::str::FromStr;
    
    /// define identity subcommands
    #[derive(Clone, Default, Debug, clap::Parser)]
    pub enum Subcommand {
    	/// show identity
    	#[default]
    	Show,
    	/// Fetch identity
    	Get {
    		#[clap(short = 'a', long = "address")]
    		account_id: Option<AccountId>,
    		#[clap(short = 'i', long = "identity")]
    		identity_id: Option<u32>,
    		#[clap(short = 'u', long = "username")]
    		username: Option<String>,
    	},
    	/// Create and certify an identity
    	///
    	/// Caller must be member, and the target account must exist.
    	Create { target: AccountId },
    	/// Confirm an identity
    	///
    	/// To be called by the certified not-yet-member account, to become member.
    	Confirm { name: String },
    	/// Revoke an identity immediately
    	Revoke,
    	/// Generate a revocation document for the provided account
    	GenRevocDoc,
    }
    
    /// handle identity commands
    pub async fn handle_command(data: Data, command: Subcommand) -> anyhow::Result<()> {
    	let mut data = data.build_client().await?;
    	match command {
    		Subcommand::Show => {}
    		Subcommand::Get {
    			account_id,
    			identity_id,
    			username,
    		} => {
    			data = data.build_indexer().await?;
    			commands::identity::get_identity(&data, account_id, identity_id, username).await?
    		}
    		Subcommand::Create { target } => {
    			commands::identity::create_identity(data.keypair(), data.client(), target).await?;
    		}
    		Subcommand::Confirm { name } => {
    			commands::identity::confirm_identity(data.keypair(), data.client(), name).await?;
    		}
    		Subcommand::Revoke => {
    			data = data.fetch_idty_index().await?;
    			commands::identity::revoke_identity(data).await?;
    		}
    		Subcommand::GenRevocDoc => {
    			data = data.fetch_idty_index().await?;
    			commands::revocation::print_revoc_sig(&data)
    		}
    	};
    
    	Ok(())
    }
    
    // ======================
    
    /// get identity
    pub async fn get_identity(
    	data: &Data,
    	mut account_id: Option<AccountId>,
    	mut identity_id: Option<u32>,
    	mut username: Option<String>,
    ) -> Result<(), anyhow::Error> {
    	let client = data.client();
    	let indexer = data.indexer.clone();
    
    	// fetch missing information
    	match (&account_id, identity_id, &username) {
    		(None, Some(identity_id), None) => {
    			account_id = get_identity_by_index(client, identity_id)
    				.await?
    				.map(|idty| idty.owner_key);
    		}
    		(Some(account_id), None, None) => {
    			identity_id = get_idty_index_by_account_id(client, account_id).await?;
    		}
    		(None, None, Some(username)) => {
    			let indexer = indexer.as_ref().ok_or(anyhow!(
    				"Cannot fetch identity from username without indexer."
    			))?;
    			if let Some(pubkey) = indexer.pubkey_by_username(username).await? {
    				// convert string to accountid
    				let fetched_account_id = AccountId::from_str(&pubkey).map_err(|e| anyhow!(e))?;
    				// in the future, also ask indexer the identity index
    				identity_id = get_idty_index_by_account_id(client, &fetched_account_id).await?;
    				account_id = Some(fetched_account_id);
    			} else {
    				return Err(anyhow!("no identity found for this username"));
    			}
    		}
    		_ => {
    			return Err(anyhow!(
    				"One and only one argument is needed to fetch the identity."
    			));
    		}
    	};
    
    	// print result
    	println!(
    		"Account id:  {}",
    		account_id
    			.as_ref()
    			.map_or(String::new(), AccountId::to_string)
    	);
    	println!(
    		"Identity id: {}",
    		identity_id.map_or(String::new(), |identity_id| format!("{identity_id}"))
    	);
    
    	if let (Some(indexer), Some(account_id), None) = (&indexer, &account_id, &username) {
    		username = indexer.username_by_pubkey(&account_id.to_string()).await?;
    	}
    	println!(
    		"Username:    {}",
    		username.unwrap_or("<no indexer>".to_string())
    	);
    
    	Ok(())
    }
    
    /// get identity index by account id
    pub async fn get_idty_index_by_account_id(
    	client: &Client,
    	account_id: &AccountId,
    ) -> Result<Option<u32>, anyhow::Error> {
    	Ok(client
    		.storage()
    		.fetch(
    			&runtime::storage().identity().identity_index_of(account_id),
    			None,
    		)
    		.await?)
    }
    
    /// get identityt value by index
    pub async fn get_identity_by_index(
    	client: &Client,
    	idty_index: u32,
    ) -> Result<Option<IdtyValue<u32, AccountId, IdtyData>>, anyhow::Error> {
    	Ok(client
    		.storage()
    		.fetch(&runtime::storage().identity().identities(idty_index), None)
    		.await?)
    }
    
    /// created identity
    pub async fn create_identity(
    	pair: Pair,
    	client: &Client,
    	target: AccountId,
    ) -> Result<(), subxt::Error> {
    	let progress = client
    		.tx()
    		.sign_and_submit_then_watch(
    			&runtime::tx().identity().create_identity(target),
    			&PairSigner::new(pair),
    			BaseExtrinsicParamsBuilder::new(),
    		)
    		.await?;
    
    	let events = track_progress(progress).await?;
    	if let Some(e) = events.find_first::<runtime::identity::events::IdtyCreated>()? {
    		println!("{e:?}");
    	}
    	Ok(())
    }
    
    /// confirm identity
    pub async fn confirm_identity(
    	pair: Pair,
    	client: &Client,
    	name: String,
    ) -> Result<(), subxt::Error> {
    	let progress = client
    		.tx()
    		.sign_and_submit_then_watch(
    			&runtime::tx().identity().confirm_identity(name),
    			&PairSigner::new(pair),
    			BaseExtrinsicParamsBuilder::new(),
    		)
    		.await?;
    
    	let events = track_progress(progress).await?;
    	if let Some(e) = events.find_first::<runtime::identity::events::IdtyConfirmed>()? {
    		println!("{e:?}");
    	}
    	Ok(())
    }
    
    /// generate revokation document and submit it immediately
    pub async fn revoke_identity(data: Data) -> Result<(), subxt::Error> {
    	let (_payload, signature) = generate_revoc_doc(&data);
    
    	// Transform signature to MultiSignature
    	// TODO: this is a hack, we should be able to use the signature directly
    	let signature = Signature(signature.0);
    	let multisign = MultiSignature::Sr25519(signature);
    
    	let progress = data
    		.client()
    		.tx()
    		.sign_and_submit_then_watch(
    			&runtime::tx()
    				.identity()
    				.revoke_identity(data.idty_index(), data.address(), multisign),
    			&PairSigner::new(data.keypair()),
    			BaseExtrinsicParamsBuilder::new(),
    		)
    		.await?;
    
    	let events = track_progress(progress).await?;
    	if let Some(e) = events.find_first::<runtime::identity::events::IdtyRemoved>()? {
    		println!("{e:?}");
    	}
    	Ok(())
    }