From a97a6f2095bd35eb9d7e5f11d04f62e065386c78 Mon Sep 17 00:00:00 2001
From: Niklas Adolfsson <niklasadolfsson1@gmail.com>
Date: Mon, 8 Jan 2024 13:35:12 +0100
Subject: [PATCH] rpc: add `rpc v2 chainSpec` to polkadot (#2859)

The [chainSpec RPC API from the v2
spec](https://paritytech.github.io/json-rpc-interface-spec/api/chainSpec.html)
was only added to substrate-node and should be added to polkadot as well

/cc @lexnv
---
 Cargo.lock                                    |  1 +
 .../runtime_vs_smart_contract.rs              | 21 ++++++++++++-------
 .../node/core/candidate-validation/src/lib.rs |  6 +++---
 .../core/candidate-validation/src/tests.rs    |  2 +-
 polkadot/rpc/Cargo.toml                       |  1 +
 polkadot/rpc/src/lib.rs                       |  6 ++++++
 substrate/bin/node-template/node/src/rpc.rs   |  7 +++++++
 .../client/consensus/beefy/src/import.rs      |  2 +-
 substrate/client/consensus/beefy/src/lib.rs   |  2 +-
 .../src/protocol/notifications/behaviour.rs   |  2 +-
 substrate/frame/contracts/fixtures/build.rs   |  6 +++---
 .../src/construct_runtime/expand/task.rs      |  2 +-
 substrate/frame/system/src/tests.rs           |  2 +-
 substrate/primitives/core/src/address_uri.rs  |  2 +-
 substrate/primitives/core/src/crypto.rs       |  4 ++--
 .../utils/wasm-builder/src/wasm_project.rs    |  2 +-
 16 files changed, 45 insertions(+), 23 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock
index 7a718610bd3..5fba3e62037 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -13200,6 +13200,7 @@ dependencies = [
  "sc-consensus-grandpa",
  "sc-consensus-grandpa-rpc",
  "sc-rpc",
+ "sc-rpc-spec-v2",
  "sc-sync-state-rpc",
  "sc-transaction-pool-api",
  "sp-api",
diff --git a/docs/sdk/src/reference_docs/runtime_vs_smart_contract.rs b/docs/sdk/src/reference_docs/runtime_vs_smart_contract.rs
index 16db44d8be4..099512cf4ee 100644
--- a/docs/sdk/src/reference_docs/runtime_vs_smart_contract.rs
+++ b/docs/sdk/src/reference_docs/runtime_vs_smart_contract.rs
@@ -32,14 +32,21 @@
 //!
 //! ## Comparative Table
 //!
-//! | Aspect                | Runtime                                                                 | Smart Contracts                                                      |
+//! | Aspect                | Runtime
+//! | Smart Contracts                                                      |
 //! |-----------------------|-------------------------------------------------------------------------|----------------------------------------------------------------------|
-//! | **Design Philosophy** | Core logic of a blockchain, allowing broad and deep customization.      | Designed for DApps deployed on the blockchain runtime.|
-//! | **Development Complexity** | Requires in-depth knowledge of Rust and Substrate. Suitable for complex blockchain architectures.         | Easier to develop with knowledge of Smart Contract languages like Solidity or [ink!](https://use.ink/). |
-//! | **Upgradeability and Flexibility** | Offers comprehensive upgradeability with migration logic and on-chain governance, allowing modifications to the entire blockchain logic without hard forks. | Less flexible in upgrade migrations but offers more straightforward deployment and iteration. |
-//! | **Performance and Efficiency** | More efficient, optimized for specific needs of the blockchain.        | Can be less efficient due to its generic nature (e.g. the overhead of a virtual machine).     |
-//! | **Security Considerations** | Security flaws can affect the entire blockchain.                        | Security risks usually localized to the individual contract.        |
-//! | **Weighing and Metering** | Operations can be weighed, allowing for precise benchmarking.           | Execution is metered, allowing for measurement of resource consumption. |
+//! | **Design Philosophy** | Core logic of a blockchain, allowing broad and deep customization.
+//! | Designed for DApps deployed on the blockchain runtime.| | **Development Complexity** | Requires in-depth knowledge of Rust and Substrate. Suitable for complex blockchain architectures.         | Easier to develop with knowledge of Smart Contract languages like Solidity or [ink!](https://use.ink/). |
+//! | **Upgradeability and Flexibility** | Offers comprehensive upgradeability with migration logic
+//! and on-chain governance, allowing modifications to the entire blockchain logic without hard
+//! forks. | Less flexible in upgrade migrations but offers more straightforward deployment and
+//! iteration. | | **Performance and Efficiency** | More efficient, optimized for specific needs of
+//! the blockchain.        | Can be less efficient due to its generic nature (e.g. the overhead of a
+//! virtual machine).     | | **Security Considerations** | Security flaws can affect the entire
+//! blockchain.                        | Security risks usually localized to the individual
+//! contract.        | | **Weighing and Metering** | Operations can be weighed, allowing for precise
+//! benchmarking.           | Execution is metered, allowing for measurement of resource
+//! consumption. |
 //!
 //! We will now explore these differences in more detail.
 //!
diff --git a/polkadot/node/core/candidate-validation/src/lib.rs b/polkadot/node/core/candidate-validation/src/lib.rs
index 5c4e449b2c9..18c27968915 100644
--- a/polkadot/node/core/candidate-validation/src/lib.rs
+++ b/polkadot/node/core/candidate-validation/src/lib.rs
@@ -773,21 +773,21 @@ trait ValidationBackend {
 					if num_death_retries_left > 0 {
 						num_death_retries_left -= 1;
 					} else {
-						break;
+						break
 					},
 
 				Err(ValidationError::PossiblyInvalid(PossiblyInvalidError::JobError(_))) =>
 					if num_job_error_retries_left > 0 {
 						num_job_error_retries_left -= 1;
 					} else {
-						break;
+						break
 					},
 
 				Err(ValidationError::Internal(_)) =>
 					if num_internal_retries_left > 0 {
 						num_internal_retries_left -= 1;
 					} else {
-						break;
+						break
 					},
 
 				Ok(_) | Err(ValidationError::Invalid(_) | ValidationError::Preparation(_)) => break,
diff --git a/polkadot/node/core/candidate-validation/src/tests.rs b/polkadot/node/core/candidate-validation/src/tests.rs
index 11078580465..f646f853549 100644
--- a/polkadot/node/core/candidate-validation/src/tests.rs
+++ b/polkadot/node/core/candidate-validation/src/tests.rs
@@ -726,7 +726,7 @@ fn candidate_validation_retry_on_error_helper(
 		ExecutorParams::default(),
 		exec_kind,
 		&Default::default(),
-	));
+	))
 }
 
 #[test]
diff --git a/polkadot/rpc/Cargo.toml b/polkadot/rpc/Cargo.toml
index 8c582c623ba..dcb7a13f6f3 100644
--- a/polkadot/rpc/Cargo.toml
+++ b/polkadot/rpc/Cargo.toml
@@ -21,6 +21,7 @@ sp-consensus = { path = "../../substrate/primitives/consensus/common" }
 sp-consensus-babe = { path = "../../substrate/primitives/consensus/babe" }
 sc-chain-spec = { path = "../../substrate/client/chain-spec" }
 sc-rpc = { path = "../../substrate/client/rpc" }
+sc-rpc-spec-v2 = { path = "../../substrate/client/rpc-spec-v2" }
 sc-consensus-babe = { path = "../../substrate/client/consensus/babe" }
 sc-consensus-babe-rpc = { path = "../../substrate/client/consensus/babe/rpc" }
 sc-consensus-beefy = { path = "../../substrate/client/consensus/beefy" }
diff --git a/polkadot/rpc/src/lib.rs b/polkadot/rpc/src/lib.rs
index bf9daddba50..4455efd3b53 100644
--- a/polkadot/rpc/src/lib.rs
+++ b/polkadot/rpc/src/lib.rs
@@ -121,6 +121,7 @@ where
 	use sc_consensus_babe_rpc::{Babe, BabeApiServer};
 	use sc_consensus_beefy_rpc::{Beefy, BeefyApiServer};
 	use sc_consensus_grandpa_rpc::{Grandpa, GrandpaApiServer};
+	use sc_rpc_spec_v2::chain_spec::{ChainSpec, ChainSpecApiServer};
 	use sc_sync_state_rpc::{SyncState, SyncStateApiServer};
 	use substrate_state_trie_migration_rpc::{StateMigration, StateMigrationApiServer};
 
@@ -134,6 +135,11 @@ where
 		finality_provider,
 	} = grandpa;
 
+	let chain_name = chain_spec.name().to_string();
+	let genesis_hash = client.hash(0).ok().flatten().expect("Genesis block exists; qed");
+	let properties = chain_spec.properties();
+
+	io.merge(ChainSpec::new(chain_name, genesis_hash, properties).into_rpc())?;
 	io.merge(StateMigration::new(client.clone(), backend.clone(), deny_unsafe).into_rpc())?;
 	io.merge(System::new(client.clone(), pool.clone(), deny_unsafe).into_rpc())?;
 	io.merge(TransactionPayment::new(client.clone()).into_rpc())?;
diff --git a/substrate/bin/node-template/node/src/rpc.rs b/substrate/bin/node-template/node/src/rpc.rs
index f4f1540f732..246391adcbb 100644
--- a/substrate/bin/node-template/node/src/rpc.rs
+++ b/substrate/bin/node-template/node/src/rpc.rs
@@ -53,5 +53,12 @@ where
 	// to call into the runtime.
 	// `module.merge(YourRpcTrait::into_rpc(YourRpcStruct::new(ReferenceToClient, ...)))?;`
 
+	// You probably want to enable the `rpc v2 chainSpec` API as well
+	//
+	// let chain_name = chain_spec.name().to_string();
+	// let genesis_hash = client.block_hash(0).ok().flatten().expect("Genesis block exists; qed");
+	// let properties = chain_spec.properties();
+	// module.merge(ChainSpec::new(chain_name, genesis_hash, properties).into_rpc())?;
+
 	Ok(module)
 }
diff --git a/substrate/client/consensus/beefy/src/import.rs b/substrate/client/consensus/beefy/src/import.rs
index 5bbf07fba70..6eced17b58f 100644
--- a/substrate/client/consensus/beefy/src/import.rs
+++ b/substrate/client/consensus/beefy/src/import.rs
@@ -148,7 +148,7 @@ where
 				// The block is imported as part of some chain sync.
 				// The voter doesn't need to process it now.
 				// It will be detected and processed as part of the voter state init.
-				return Ok(inner_import_result);
+				return Ok(inner_import_result)
 			},
 		}
 
diff --git a/substrate/client/consensus/beefy/src/lib.rs b/substrate/client/consensus/beefy/src/lib.rs
index 51e82b6a811..2e2e22288e3 100644
--- a/substrate/client/consensus/beefy/src/lib.rs
+++ b/substrate/client/consensus/beefy/src/lib.rs
@@ -398,7 +398,7 @@ where
 			header =
 				wait_for_parent_header(backend.blockchain(), header, HEADER_SYNC_DELAY).await?;
 		}
-		return Ok(state);
+		return Ok(state)
 	}
 
 	// No valid voter-state persisted, re-initialize from pallet genesis.
diff --git a/substrate/client/network/src/protocol/notifications/behaviour.rs b/substrate/client/network/src/protocol/notifications/behaviour.rs
index cdbf2a71b93..9ad41e376e8 100644
--- a/substrate/client/network/src/protocol/notifications/behaviour.rs
+++ b/substrate/client/network/src/protocol/notifications/behaviour.rs
@@ -1037,7 +1037,7 @@ impl Notifications {
 						peerset_rejected,
 						incoming_index,
 					};
-					return self.report_reject(index).map_or((), |_| ());
+					return self.report_reject(index).map_or((), |_| ())
 				}
 
 				trace!(
diff --git a/substrate/frame/contracts/fixtures/build.rs b/substrate/frame/contracts/fixtures/build.rs
index 84eb4219c25..34e44c5db11 100644
--- a/substrate/frame/contracts/fixtures/build.rs
+++ b/substrate/frame/contracts/fixtures/build.rs
@@ -105,7 +105,7 @@ fn collect_entries(contracts_dir: &Path, out_dir: &Path) -> Vec<Entry> {
 		.filter_map(|file| {
 			let path = file.expect("file exists; qed").path();
 			if path.extension().map_or(true, |ext| ext != "rs") {
-				return None;
+				return None
 			}
 
 			let entry = Entry::new(path);
@@ -307,7 +307,7 @@ fn find_workspace_root(current_dir: &Path) -> Option<PathBuf> {
 			let cargo_toml_contents =
 				std::fs::read_to_string(current_dir.join("Cargo.toml")).ok()?;
 			if cargo_toml_contents.contains("[workspace]") {
-				return Some(current_dir);
+				return Some(current_dir)
 			}
 		}
 
@@ -325,7 +325,7 @@ fn main() -> Result<()> {
 
 	let entries = collect_entries(&contracts_dir, &out_dir);
 	if entries.is_empty() {
-		return Ok(());
+		return Ok(())
 	}
 
 	let tmp_dir = tempfile::tempdir()?;
diff --git a/substrate/frame/support/procedural/src/construct_runtime/expand/task.rs b/substrate/frame/support/procedural/src/construct_runtime/expand/task.rs
index bd952202bbb..6531c0e9e07 100644
--- a/substrate/frame/support/procedural/src/construct_runtime/expand/task.rs
+++ b/substrate/frame/support/procedural/src/construct_runtime/expand/task.rs
@@ -31,7 +31,7 @@ pub fn expand_outer_task(
 	let mut task_paths = Vec::new();
 	for decl in pallet_decls {
 		if decl.find_part("Task").is_none() {
-			continue;
+			continue
 		}
 
 		let variant_name = &decl.name;
diff --git a/substrate/frame/system/src/tests.rs b/substrate/frame/system/src/tests.rs
index 053cec24f89..e437e7f9f39 100644
--- a/substrate/frame/system/src/tests.rs
+++ b/substrate/frame/system/src/tests.rs
@@ -828,7 +828,7 @@ fn last_runtime_upgrade_spec_version_usage() {
 			// a runtime upgrade in the pipeline of being applied, you should use the spec version
 			// of this upgrade.
 			if System::last_runtime_upgrade_spec_version() > 1337 {
-				return Weight::zero();
+				return Weight::zero()
 			}
 
 			// Do the migration.
diff --git a/substrate/primitives/core/src/address_uri.rs b/substrate/primitives/core/src/address_uri.rs
index 862747c9a4b..211d47c0093 100644
--- a/substrate/primitives/core/src/address_uri.rs
+++ b/substrate/primitives/core/src/address_uri.rs
@@ -184,7 +184,7 @@ impl<'a> AddressUri<'a> {
 					Error::in_pass(initial_input, initial_input_len - input.len())
 				} else {
 					Error::in_phrase(initial_input, initial_input_len - input.len())
-				});
+				})
 			}
 		}
 
diff --git a/substrate/primitives/core/src/crypto.rs b/substrate/primitives/core/src/crypto.rs
index 1f3ae744533..2da38d44be4 100644
--- a/substrate/primitives/core/src/crypto.rs
+++ b/substrate/primitives/core/src/crypto.rs
@@ -434,7 +434,7 @@ impl<T: Sized + AsMut<[u8]> + AsRef<[u8]> + Public + Derive> Ss58Codec for T {
 	fn from_string(s: &str) -> Result<Self, PublicError> {
 		let cap = AddressUri::parse(s)?;
 		if cap.pass.is_some() {
-			return Err(PublicError::PasswordNotAllowed);
+			return Err(PublicError::PasswordNotAllowed)
 		}
 		let s = cap.phrase.unwrap_or(DEV_ADDRESS);
 		let addr = if let Some(stripped) = s.strip_prefix("0x") {
@@ -454,7 +454,7 @@ impl<T: Sized + AsMut<[u8]> + AsRef<[u8]> + Public + Derive> Ss58Codec for T {
 	fn from_string_with_version(s: &str) -> Result<(Self, Ss58AddressFormat), PublicError> {
 		let cap = AddressUri::parse(s)?;
 		if cap.pass.is_some() {
-			return Err(PublicError::PasswordNotAllowed);
+			return Err(PublicError::PasswordNotAllowed)
 		}
 		let (addr, v) = Self::from_ss58check_with_version(cap.phrase.unwrap_or(DEV_ADDRESS))?;
 		if cap.paths.is_empty() {
diff --git a/substrate/utils/wasm-builder/src/wasm_project.rs b/substrate/utils/wasm-builder/src/wasm_project.rs
index 5bf44c2c9b2..2126a49bd7f 100644
--- a/substrate/utils/wasm-builder/src/wasm_project.rs
+++ b/substrate/utils/wasm-builder/src/wasm_project.rs
@@ -935,7 +935,7 @@ fn generate_rerun_if_changed_instructions(
 	while let Some(dependency) = dependencies.pop() {
 		// Ignore all dev dependencies
 		if dependency.kind == DependencyKind::Development {
-			continue;
+			continue
 		}
 
 		let path_or_git_dep =
-- 
GitLab