From ce6938ae92b77b54aa367e6d367a4d490dede7c4 Mon Sep 17 00:00:00 2001
From: Alexandru Vasile <60601340+lexnv@users.noreply.github.com>
Date: Fri, 2 Aug 2024 18:09:13 +0300
Subject: [PATCH] rpc: Enable ChainSpec for polkadot-parachain (#5205)

This PR enables the `chainSpec_v1` class for the polkadot-parachian.
The chainSpec is part of the rpc-v2 which is spec-ed at:
https://github.com/paritytech/json-rpc-interface-spec/blob/main/src/api/chainSpec.md.

This also paves the way for enabling a future `chainSpec_unstable_spec`
on all nodes.

Closes: https://github.com/paritytech/polkadot-sdk/issues/5191

cc @paritytech/subxt-team

---------

Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io>
---
 Cargo.lock                              |  1 -
 polkadot/rpc/src/lib.rs                 |  6 ------
 prdoc/pr_5205.prdoc                     | 18 ++++++++++++++++++
 substrate/bin/node/rpc/Cargo.toml       |  1 -
 substrate/bin/node/rpc/src/lib.rs       |  6 ------
 substrate/client/service/src/builder.rs | 13 +++++++++++--
 6 files changed, 29 insertions(+), 16 deletions(-)
 create mode 100644 prdoc/pr_5205.prdoc

diff --git a/Cargo.lock b/Cargo.lock
index 8cca629e379..d37babb5bbc 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -9276,7 +9276,6 @@ dependencies = [
  "sc-mixnet",
  "sc-rpc",
  "sc-rpc-api",
- "sc-rpc-spec-v2",
  "sc-sync-state-rpc",
  "sc-transaction-pool-api",
  "sp-api",
diff --git a/polkadot/rpc/src/lib.rs b/polkadot/rpc/src/lib.rs
index 7d678ada5ff..eb0133b6e8f 100644
--- a/polkadot/rpc/src/lib.rs
+++ b/polkadot/rpc/src/lib.rs
@@ -124,7 +124,6 @@ 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_frame_rpc_system::{System, SystemApiServer};
 	use substrate_state_trie_migration_rpc::{StateMigration, StateMigrationApiServer};
@@ -139,11 +138,6 @@ 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/prdoc/pr_5205.prdoc b/prdoc/pr_5205.prdoc
new file mode 100644
index 00000000000..48abfe50ca2
--- /dev/null
+++ b/prdoc/pr_5205.prdoc
@@ -0,0 +1,18 @@
+title: Enable ChainSpec API for polkadot-parachain
+
+doc:
+  - audience:
+    - Runtime Dev
+    - Node Dev
+    description: |
+      The substrate service-builder now includes the entire rpc v2 API.
+      The chainspec API was previously defined as rpc extension where for instance chains would need to enable it explicitly.
+      At the same time, this paves the way for implementing in the future a `chainSpec_v1_getSpec`
+      method that can extract the chainSpec of any chain (including parachains) for the use with lightclients.
+      For more info about the `chainSpec`, please see the specification: https://github.com/paritytech/json-rpc-interface-spec/blob/main/src/api/chainSpec.md.
+
+crates: 
+  - name: sc-service
+    bump: patch
+  - name: polkadot-rpc
+    bump: patch
diff --git a/substrate/bin/node/rpc/Cargo.toml b/substrate/bin/node/rpc/Cargo.toml
index 2417496cde4..d85998e3c87 100644
--- a/substrate/bin/node/rpc/Cargo.toml
+++ b/substrate/bin/node/rpc/Cargo.toml
@@ -32,7 +32,6 @@ sc-consensus-grandpa-rpc = { workspace = true, default-features = true }
 sc-mixnet = { workspace = true, default-features = true }
 sc-rpc = { workspace = true, default-features = true }
 sc-rpc-api = { workspace = true, default-features = true }
-sc-rpc-spec-v2 = { workspace = true, default-features = true }
 sc-sync-state-rpc = { workspace = true, default-features = true }
 sc-transaction-pool-api = { workspace = true, default-features = true }
 sp-api = { workspace = true, default-features = true }
diff --git a/substrate/bin/node/rpc/src/lib.rs b/substrate/bin/node/rpc/src/lib.rs
index 52cd7f9561d..c55e03ee9d6 100644
--- a/substrate/bin/node/rpc/src/lib.rs
+++ b/substrate/bin/node/rpc/src/lib.rs
@@ -160,7 +160,6 @@ where
 		mixnet::MixnetApiServer,
 		statement::StatementApiServer,
 	};
-	use sc_rpc_spec_v2::chain_spec::{ChainSpec, ChainSpecApiServer};
 	use sc_sync_state_rpc::{SyncState, SyncStateApiServer};
 	use substrate_frame_rpc_system::{System, SystemApiServer};
 	use substrate_state_trie_migration_rpc::{StateMigration, StateMigrationApiServer};
@@ -176,11 +175,6 @@ where
 		finality_provider,
 	} = grandpa;
 
-	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();
-	io.merge(ChainSpec::new(chain_name, genesis_hash, properties).into_rpc())?;
-
 	io.merge(System::new(client.clone(), pool, deny_unsafe).into_rpc())?;
 	// Making synchronous calls in light client freezes the browser currently,
 	// more context: https://github.com/paritytech/substrate/pull/3480
diff --git a/substrate/client/service/src/builder.rs b/substrate/client/service/src/builder.rs
index 638f30fad10..ebe3f553f7c 100644
--- a/substrate/client/service/src/builder.rs
+++ b/substrate/client/service/src/builder.rs
@@ -68,6 +68,7 @@ use sc_rpc::{
 use sc_rpc_spec_v2::{
 	archive::ArchiveApiServer,
 	chain_head::ChainHeadApiServer,
+	chain_spec::ChainSpecApiServer,
 	transaction::{TransactionApiServer, TransactionBroadcastApiServer},
 };
 use sc_telemetry::{telemetry, ConnectionMessage, Telemetry, TelemetryHandle, SUBSTRATE_INFO};
@@ -675,9 +676,8 @@ where
 	// - block pruning in archive mode: The block's body is kept around
 	let is_archive_node = config.state_pruning.as_ref().map(|sp| sp.is_archive()).unwrap_or(false) &&
 		config.blocks_pruning.is_archive();
+	let genesis_hash = client.hash(Zero::zero()).ok().flatten().expect("Genesis block exists; qed");
 	if is_archive_node {
-		let genesis_hash =
-			client.hash(Zero::zero()).ok().flatten().expect("Genesis block exists; qed");
 		let archive_v2 = sc_rpc_spec_v2::archive::Archive::new(
 			client.clone(),
 			backend.clone(),
@@ -689,6 +689,14 @@ where
 		rpc_api.merge(archive_v2).map_err(|e| Error::Application(e.into()))?;
 	}
 
+	// ChainSpec RPC-v2.
+	let chain_spec_v2 = sc_rpc_spec_v2::chain_spec::ChainSpec::new(
+		config.chain_spec.name().into(),
+		genesis_hash,
+		config.chain_spec.properties(),
+	)
+	.into_rpc();
+
 	let author = sc_rpc::author::Author::new(
 		client.clone(),
 		transaction_pool,
@@ -712,6 +720,7 @@ where
 		.merge(transaction_broadcast_rpc_v2)
 		.map_err(|e| Error::Application(e.into()))?;
 	rpc_api.merge(chain_head_v2).map_err(|e| Error::Application(e.into()))?;
+	rpc_api.merge(chain_spec_v2).map_err(|e| Error::Application(e.into()))?;
 
 	// Part of the old RPC spec.
 	rpc_api.merge(chain).map_err(|e| Error::Application(e.into()))?;
-- 
GitLab