From 4f4524d3fb054bae3c810df370e8717d4e780867 Mon Sep 17 00:00:00 2001
From: Hugo Trentesaux <hugo.trentesaux@lilo.org>
Date: Fri, 2 Jun 2023 11:55:16 +0200
Subject: [PATCH] Add smith certification

---
 Cargo.lock               |  39 +-------------
 Cargo.toml               |   2 +-
 README.md                |  16 ++++++
 res/metadata.scale       | Bin 127211 -> 131872 bytes
 src/commands/expire.rs   |   4 +-
 src/commands/identity.rs | 107 +++++++++++++++++++++------------------
 src/commands/net_test.rs |   6 +--
 src/commands/oneshot.rs  |   2 +-
 src/commands/smith.rs    |  76 ++++++++++++++++++++++++++-
 src/commands/transfer.rs |   2 +-
 src/main.rs              |  11 ++--
 11 files changed, 164 insertions(+), 101 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock
index 03dd29b..52b2ad5 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -855,7 +855,7 @@ dependencies = [
  "futures",
  "graphql_client",
  "hex",
- "logs",
+ "log",
  "parity-scale-codec",
  "reqwest",
  "rpassword",
@@ -1509,16 +1509,6 @@ dependencies = [
  "cfg-if",
 ]
 
-[[package]]
-name = "logs"
-version = "0.7.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "218ee85e6f2ed7e15253cbfcb61bf960ea797b4d8869d36f1a95bbc7fdc3686d"
-dependencies = [
- "log",
- "time",
-]
-
 [[package]]
 name = "lru"
 version = "0.7.8"
@@ -3105,33 +3095,6 @@ dependencies = [
  "once_cell",
 ]
 
-[[package]]
-name = "time"
-version = "0.3.20"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cd0cbfecb4d19b5ea75bb31ad904eb5b9fa13f21079c3b92017ebdf4999a5890"
-dependencies = [
- "itoa",
- "serde",
- "time-core",
- "time-macros",
-]
-
-[[package]]
-name = "time-core"
-version = "0.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2e153e1f1acaef8acc537e68b44906d2db6436e2b35ac2c6b42640fff91f00fd"
-
-[[package]]
-name = "time-macros"
-version = "0.2.8"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fd80a657e71da814b8e5d60d3374fc6d35045062245d80224748ae522dd76f36"
-dependencies = [
- "time-core",
-]
-
 [[package]]
 name = "tiny-bip39"
 version = "0.8.2"
diff --git a/Cargo.toml b/Cargo.toml
index e88715b..fce1a3e 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -14,7 +14,7 @@ env_logger = "0.10"
 futures = "0.3.27"
 graphql_client = { version = "0.12.0", features = ["reqwest"] }
 hex = "0.4.3"
-logs = "0.7"
+log = "0.4.17"
 reqwest = "0.11.14"
 rpassword = "7.2.0"
 serde = { version = "1.0", features = ["derive"] }
diff --git a/README.md b/README.md
index e04dce2..0f97ffb 100644
--- a/README.md
+++ b/README.md
@@ -20,6 +20,22 @@ List certifications and session keys that will expire within one month:
 
 	cargo run -- --url wss://gdev.p2p.legal:443/ws expire --blocks 432000
 
+#### Log level
+
+You can adjust the log level:
+
+```
+export RUST_LOG=gcli=info
+```
+
+#### Runtime metadata
+
+To update runtime metadata:
+
+```
+subxt metadata -f bytes > res/metadata.scale
+```
+
 ### Smith
 
 You want to rotate keys and go online to start forging blocks.
diff --git a/res/metadata.scale b/res/metadata.scale
index d7c41820b07a0a2e6198009041d239e70602a2d9..3af1b14cabe3e2c9b3561e0ef21320d47923125d 100644
GIT binary patch
delta 17827
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

delta 14532
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
YlRx#SaGk#D5d2LTzoa`Nb{!D^2h-g{-~a#s

diff --git a/src/commands/expire.rs b/src/commands/expire.rs
index d051ea8..a23a530 100644
--- a/src/commands/expire.rs
+++ b/src/commands/expire.rs
@@ -101,7 +101,7 @@ pub async fn monitor_expirations(
 	let mut smith_certs_iter = client
 		.storage()
 		.iter(
-			gdev::storage().smiths_cert().storage_certs_removable_on(0),
+			gdev::storage().smith_cert().storage_certs_removable_on(0),
 			10,
 			Some(parent_hash),
 		)
@@ -162,7 +162,7 @@ pub async fn monitor_expirations(
 	let mut smith_membership_iter = client
 		.storage()
 		.iter(
-			gdev::storage().smiths_membership().memberships_expire_on(0),
+			gdev::storage().smith_membership().memberships_expire_on(0),
 			10,
 			Some(parent_hash),
 		)
diff --git a/src/commands/identity.rs b/src/commands/identity.rs
index 6cde145..e5ee3ca 100644
--- a/src/commands/identity.rs
+++ b/src/commands/identity.rs
@@ -1,5 +1,7 @@
 use crate::{gdev, indexer::*, Args, Client};
 
+use crate::gdev::runtime_types::common_runtime::entities::IdtyData;
+use crate::gdev::runtime_types::pallet_identity::types::*;
 use anyhow::{anyhow, Result};
 use sp_core::{crypto::AccountId32, sr25519::Pair};
 use std::str::FromStr;
@@ -12,63 +14,50 @@ pub async fn get_identity(
 	mut username: Option<String>,
 	args: &Args,
 ) -> Result<()> {
-	let parent_hash = client
-		.storage()
-		.fetch(&gdev::storage().system().parent_hash(), None)
-		.await?
-		.unwrap();
-
-	let gql_client = reqwest::Client::builder()
-		.user_agent("gcli/0.1.0")
-		.build()?;
-
+	// build indexer if not disabled
 	let indexer = if args.no_indexer {
 		None
 	} else {
 		Some(Indexer {
-			gql_client,
+			gql_client: reqwest::Client::builder()
+				.user_agent("gcli/0.1.0")
+				.build()?,
 			gql_url: &args.indexer,
 		})
 	};
 
-	if let Some(account_id) = &account_id {
-		identity_id = client
-			.storage()
-			.fetch(
-				&gdev::storage().identity().identity_index_of(account_id),
-				Some(parent_hash),
-			)
-			.await?;
-	} else if let Some(identity_id) = &identity_id {
-		account_id = client
-			.storage()
-			.fetch(
-				&gdev::storage().identity().identities(identity_id),
-				Some(parent_hash),
-			)
-			.await?
-			.map(|idty| idty.owner_key);
-	} else if let Some(username) = &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? {
-			let some_account_id = AccountId32::from_str(&pubkey).map_err(|e| anyhow!(e))?;
-			identity_id = client
-				.storage()
-				.fetch(
-					&gdev::storage()
-						.identity()
-						.identity_index_of(&some_account_id),
-					Some(parent_hash),
-				)
-				.await?;
-			account_id = Some(some_account_id);
+	// 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);
 		}
-	} else {
-		return Err(anyhow!("One argument is needed to fetch the identity."));
-	}
+		(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 = AccountId32::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
@@ -83,12 +72,34 @@ pub async fn get_identity(
 	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_default());
 
 	Ok(())
 }
 
+pub async fn get_idty_index_by_account_id(
+	client: Client,
+	account_id: &AccountId32,
+) -> Result<Option<u32>> {
+	Ok(client
+		.storage()
+		.fetch(
+			&gdev::storage().identity().identity_index_of(account_id),
+			None,
+		)
+		.await?)
+}
+
+pub async fn get_identity_by_index(
+	client: Client,
+	idty_index: u32,
+) -> Result<Option<IdtyValue<u32, AccountId32, IdtyData>>> {
+	Ok(client
+		.storage()
+		.fetch(&gdev::storage().identity().identities(idty_index), None)
+		.await?)
+}
+
 pub async fn create_identity(pair: Pair, client: Client, target: AccountId32) -> Result<()> {
 	client
 		.tx()
diff --git a/src/commands/net_test.rs b/src/commands/net_test.rs
index 335e0d6..ab2dff3 100644
--- a/src/commands/net_test.rs
+++ b/src/commands/net_test.rs
@@ -41,7 +41,7 @@ pub async fn repart(
 			)
 			.await?
 		{
-			logs::info!("account //{} balance: {}", i, pair_i_account.data.free);
+			log::info!("account //{} balance: {}", i, pair_i_account.data.free);
 		}
 	}
 
@@ -76,7 +76,7 @@ pub async fn spam_roll(pair: Pair, client: Client, actual_repart: usize) -> Resu
 				.submit_and_watch()
 				.await?;
 			nonce += 1;
-			logs::info!("send 1 cent from //{} to //{}", i, i + 1);
+			log::info!("send 1 cent from //{} to //{}", i, i + 1);
 			watchers.push(watcher);
 		}
 		let dest: AccountId32 = pairs[0].1.clone();
@@ -89,7 +89,7 @@ pub async fn spam_roll(pair: Pair, client: Client, actual_repart: usize) -> Resu
 			)
 			.await?;
 		nonce += 1;
-		logs::info!("send 1 cent from //{} to //0", actual_repart - 1);
+		log::info!("send 1 cent from //{} to //0", actual_repart - 1);
 		watchers.push(watcher);
 
 		// Wait all transactions
diff --git a/src/commands/oneshot.rs b/src/commands/oneshot.rs
index 640cf9f..9933693 100644
--- a/src/commands/oneshot.rs
+++ b/src/commands/oneshot.rs
@@ -106,7 +106,7 @@ pub async fn consume_oneshot_account_with_remaining(
 }
 
 pub async fn oneshot_account_balance(client: Client, account: AccountId32) -> Result<()> {
-	logs::info!(
+	log::info!(
 		"{}",
 		client
 			.storage()
diff --git a/src/commands/smith.rs b/src/commands/smith.rs
index 463c179..ca8928f 100644
--- a/src/commands/smith.rs
+++ b/src/commands/smith.rs
@@ -1,9 +1,10 @@
-use crate::{cache, gdev, indexer::*, Args, Client};
+use crate::indexer::Indexer;
+use crate::*;
 
 use anyhow::{anyhow, Result};
 use sp_core::{crypto::AccountId32, sr25519::Pair, Pair as _};
 use std::ops::Deref;
-use subxt::tx::{BaseExtrinsicParamsBuilder, PairSigner};
+use subxt::tx::{BaseExtrinsicParamsBuilder, PairSigner, TxStatus};
 
 type SessionKeys = [u8; 128];
 
@@ -162,3 +163,74 @@ pub async fn online(client: Client, args: &Args) -> Result<()> {
 
 	Ok(())
 }
+
+/// emit a new smith cert from signer's identity to target identity
+pub async fn emit_cert(args: Args, receiver: u32) -> Result<()> {
+	// issuer key
+	let pair = get_keys(
+		args.secret_format,
+		&args.address,
+		&args.secret,
+		NeededKeys::Secret,
+	)?
+	.1
+	.unwrap();
+
+	// connect to client
+	let client = Client::from_url(&args.url).await.unwrap();
+
+	// get issuer index
+	let issuer = commands::identity::get_idty_index_by_account_id(
+		client.clone(),
+		&AccountId32::from(pair.public()),
+	)
+	.await?
+	.ok_or(anyhow!("can not certify if not member"))?;
+
+	// submit and track certification
+	cert(client, pair, issuer, receiver).await?;
+
+	Ok(())
+}
+
+/// submit a certification and track progress
+async fn cert(client: Client, pair: Pair, issuer: u32, receiver: u32) -> Result<()> {
+	let mut progress = client
+		.tx()
+		.sign_and_submit_then_watch(
+			&gdev::tx().smith_cert().add_cert(issuer, receiver),
+			&PairSigner::new(pair),
+			BaseExtrinsicParamsBuilder::new(),
+		)
+		.await?;
+
+	let in_block = loop {
+		if let Some(status) = progress.next_item().await {
+			match status? {
+				TxStatus::Ready => {
+					println!("transaction submitted to the network, waiting 6 seconds...");
+				}
+				TxStatus::InBlock(in_block) => break in_block,
+				TxStatus::Invalid => {
+					println!("Invalid");
+				}
+				_ => continue,
+			}
+		}
+	};
+
+	// get the block events and return if ExtrinsicFailed
+	let events = in_block.wait_for_success().await?;
+	// look for the expected event
+	let new_cert_event = events.find_first::<gdev::smith_cert::events::NewCert>()?;
+	let renew_cert_event = events.find_first::<gdev::smith_cert::events::RenewedCert>()?;
+
+	if let Some(event) = new_cert_event {
+		println!("{event:?}");
+	}
+	if let Some(event) = renew_cert_event {
+		println!("{event:?}");
+	}
+
+	Ok(())
+}
diff --git a/src/commands/transfer.rs b/src/commands/transfer.rs
index 4e51cf3..857dbde 100644
--- a/src/commands/transfer.rs
+++ b/src/commands/transfer.rs
@@ -4,7 +4,7 @@ use anyhow::Result;
 use sp_core::{crypto::AccountId32, sr25519::Pair};
 use subxt::tx::{BaseExtrinsicParamsBuilder, PairSigner};
 
-type Call = gdev::runtime_types::gdev_runtime::Call;
+type Call = gdev::runtime_types::gdev_runtime::RuntimeCall;
 type BalancesCall = gdev::runtime_types::pallet_balances::pallet::Call;
 
 pub async fn transfer(
diff --git a/src/main.rs b/src/main.rs
index 7b451af..f251d64 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -56,11 +56,7 @@ pub struct Args {
 	pub subcommand: Subcommand,
 
 	/// Indexer URL
-	#[clap(
-		short,
-		long,
-		default_value = "https://gdev-indexer.p2p.legal/v1/graphql"
-	)]
+	#[clap(short, long, default_value = "http://localhost:8080/v1/graphql")]
 	indexer: String,
 	/// Do not use indexer
 	#[clap(long)]
@@ -154,6 +150,10 @@ pub enum Subcommand {
 	SudoSetKey {
 		new_key: sp_core::crypto::AccountId32,
 	},
+	/// Emit a smith certification
+	SmithCert {
+		to: u32,
+	},
 	/// List members of the technical committee
 	TechMembers,
 	/// List proposals to the technical committee
@@ -419,6 +419,7 @@ async fn main() -> Result<()> {
 			)
 			.await?
 		}
+		Subcommand::SmithCert { to } => commands::smith::emit_cert(args, to).await?,
 		Subcommand::TechMembers => {
 			commands::collective::technical_committee_members(
 				Client::from_url(&args.url).await.unwrap(),
-- 
GitLab