Skip to content
Snippets Groups Projects
cesium.rs 4.66 KiB
Newer Older
use crate::data::Data;
use crate::keys;
use crate::keys::KeyPair;
use crate::runtime_config::AccountId;
use crate::utils::GcliError;
use bs58;
use sp_core::{ed25519, Pair};
use std::str::FromStr;

/// define cesium subcommands
#[derive(Clone, Default, Debug, clap::Parser)]
pub enum Subcommand {
	// Nothing
	#[default]
	#[clap(hide = true)]
	Nothing,
	/// Analyse a base58 pubkey and gives it in all its form
	Pubkey { pubkey: String },
	/// Prompt for cesium input
	Prompt,
}

/// handle blockchain commands
pub async fn handle_command(_data: Data, command: Subcommand) -> Result<(), GcliError> {
	match command {
		Subcommand::Nothing => {}
		Subcommand::Pubkey { pubkey } => {
			let raw_pubkey = bs58::decode(pubkey).into_vec().unwrap();
			let raw_pubkey: [u8; 32] = if raw_pubkey.len() > 32 {
				return Err(GcliError::Input("invalid pubkey size".to_string()));
			} else {
				[vec![0; 32 - raw_pubkey.len()], raw_pubkey]
					.concat()
					.try_into()
					.unwrap()
			};
			println!("Pubkey (hex): 0x{}", hex::encode(raw_pubkey));
			let address: AccountId = sp_core::ed25519::Public::from_raw(raw_pubkey).into();
			println!("Address (SS58): {}", address);
		}
		Subcommand::Prompt => {
			let pair = keys::prompt_secret_cesium();
				compute_g1v1_public_key_from_ed25519_pair(&pair)
			);
			let address: AccountId = pair.public().into();
			println!("Address: {}", address);

/// Computes G1v1 public key from a KeyPair of type sp_core::ed25519::Pair - fails otherwise
pub fn compute_g1v1_public_key(key_pair: &KeyPair) -> Result<String, GcliError> {
	match key_pair {
		KeyPair::Sr25519(_) => Err(GcliError::Logic(
			"key pair is not of type ed25519".to_string(),
		)),
		KeyPair::Ed25519(key_pair) => Ok(compute_g1v1_public_key_from_ed25519_pair(key_pair)),
pub fn compute_g1v1_public_key_from_ed25519_pair(ed25519_key_pair: &ed25519::Pair) -> String {
	compute_g1v1_public_key_from_ed25519_public(&ed25519_key_pair.public())
}

/// Computes G1v1 public key from an ed25519 Public
pub fn compute_g1v1_public_key_from_ed25519_public(ed25519_public: &ed25519::Public) -> String {
	bs58::encode(ed25519_public).into_string()
}

/// Computes G1v1 public key from an ed25519 AccountId
pub fn compute_g1v1_public_key_from_ed25519_account_id(ed25519_account_id: &AccountId) -> String {
	let ed25519_public: ed25519::Public = ed25519::Public::from(ed25519_account_id.0);
	bs58::encode(ed25519_public).into_string()
}

/// Computes G1v1 public key from an ed25519 SS58 Address
#[allow(unused)]
pub fn compute_g1v1_public_key_from_ed25519_ss58_address(
	ed25519_ss58_address: &str,
	Ok(compute_g1v1_public_key_from_ed25519_account_id(
		&AccountId::from_str(ed25519_ss58_address).map_err(|e| GcliError::Input(e.to_string()))?,
	))
}

// Unit tests
#[cfg(test)]
mod tests {
	use super::*;

	///	Test data:
	/// cesium_id = "test_cesium_id"
	/// cesium_pwd = "test_cesium_pwd"
	///
	/// G1v1 base58 public key: 86pW1doyJPVH3jeDPZNQa1UZFBo5zcdvHERcaeE758W7
	///
	/// ```
	/// subkey inspect --scheme ed25519
	/// URI:
	/// Secret Key URI `0x2101d2bc68de9ad149c06293bfe489c8608de576c88927aa5439a81be17aae84` is account:
	///   Network ID:        substrate
	///   Secret seed:       0x2101d2bc68de9ad149c06293bfe489c8608de576c88927aa5439a81be17aae84
	///   Public key (hex):  0x697f6bd16ddebf142384e503fd3f3efc39fe5c7be7c693bd98d982403bb6eb74
	///   Account ID:        0x697f6bd16ddebf142384e503fd3f3efc39fe5c7be7c693bd98d982403bb6eb74
	///   Public key (SS58): 5ET2jhgJFoNQUpgfdSkdwftK8DKWdqZ1FKm5GKWdPfMWhPr4
	///   SS58 Address:      5ET2jhgJFoNQUpgfdSkdwftK8DKWdqZ1FKm5GKWdPfMWhPr4
	/// ```
	#[test]
	fn test_compute_g1v1_public_key() {
		let expected_base58_public_key = "86pW1doyJPVH3jeDPZNQa1UZFBo5zcdvHERcaeE758W7";
		let ss58_address = "5ET2jhgJFoNQUpgfdSkdwftK8DKWdqZ1FKm5GKWdPfMWhPr4";

		assert_eq!(
			expected_base58_public_key,
			compute_g1v1_public_key_from_ed25519_ss58_address(ss58_address).unwrap()
		);

		let account_id = AccountId::from_str(ss58_address).unwrap();

		assert_eq!(
			expected_base58_public_key,
			compute_g1v1_public_key_from_ed25519_account_id(&account_id)
		);

		let ed25519_public = ed25519::Public::from(account_id.0);

		assert_eq!(
			expected_base58_public_key,
			compute_g1v1_public_key_from_ed25519_public(&ed25519_public)
		);

		let cesium_id = "test_cesium_id".to_string();
		let cesium_pwd = "test_cesium_pwd".to_string();

		let seed = keys::seed_from_cesium(&cesium_id, &cesium_pwd);
		let ed25519_pair_from_seed = ed25519::Pair::from_seed(&seed);

		assert_eq!(
			expected_base58_public_key,
			compute_g1v1_public_key_from_ed25519_pair(&ed25519_pair_from_seed)
		);
	}