mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-04-26 21:37:56 +00:00
ChainSpec trait (#5185)
* ChainSpec trait * Apply suggestions from code review Co-Authored-By: Bastian Köcher <bkchr@users.noreply.github.com> * Added docs * Fixed build * Fixed build Co-authored-by: Bastian Köcher <bkchr@users.noreply.github.com>
This commit is contained in:
@@ -26,6 +26,7 @@ use sp_core::storage::{StorageKey, StorageData, ChildInfo, Storage, StorageChild
|
||||
use sp_runtime::BuildStorage;
|
||||
use serde_json as json;
|
||||
use crate::RuntimeGenesis;
|
||||
use crate::extension::GetExtension;
|
||||
use sc_network::Multiaddr;
|
||||
use sc_telemetry::TelemetryEndpoints;
|
||||
|
||||
@@ -269,9 +270,9 @@ impl<G, E: serde::de::DeserializeOwned> ChainSpec<G, E> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<G: RuntimeGenesis, E: serde::Serialize> ChainSpec<G, E> {
|
||||
impl<G: RuntimeGenesis, E: serde::Serialize + Clone> ChainSpec<G, E> {
|
||||
/// Dump to json string.
|
||||
pub fn to_json(self, raw: bool) -> Result<String, String> {
|
||||
pub fn as_json(&self, raw: bool) -> Result<String, String> {
|
||||
#[derive(Serialize, Deserialize)]
|
||||
struct Container<G, E> {
|
||||
#[serde(flatten)]
|
||||
@@ -306,7 +307,7 @@ impl<G: RuntimeGenesis, E: serde::Serialize> ChainSpec<G, E> {
|
||||
(_, genesis) => genesis,
|
||||
};
|
||||
let container = Container {
|
||||
client_spec: self.client_spec,
|
||||
client_spec: self.client_spec.clone(),
|
||||
genesis,
|
||||
};
|
||||
json::to_string_pretty(&container)
|
||||
@@ -314,6 +315,52 @@ impl<G: RuntimeGenesis, E: serde::Serialize> ChainSpec<G, E> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<G, E> crate::ChainSpec for ChainSpec<G, E>
|
||||
where
|
||||
G: RuntimeGenesis,
|
||||
E: GetExtension + serde::Serialize + Clone,
|
||||
{
|
||||
fn boot_nodes(&self) -> &[String] {
|
||||
ChainSpec::boot_nodes(self)
|
||||
}
|
||||
|
||||
fn name(&self) -> &str {
|
||||
ChainSpec::name(self)
|
||||
}
|
||||
|
||||
fn id(&self) -> &str {
|
||||
ChainSpec::id(self)
|
||||
}
|
||||
|
||||
fn telemetry_endpoints(&self) -> &Option<TelemetryEndpoints> {
|
||||
ChainSpec::telemetry_endpoints(self)
|
||||
}
|
||||
|
||||
fn protocol_id(&self) -> Option<&str> {
|
||||
ChainSpec::protocol_id(self)
|
||||
}
|
||||
|
||||
fn properties(&self) -> Properties {
|
||||
ChainSpec::properties(self)
|
||||
}
|
||||
|
||||
fn add_boot_node(&mut self, addr: Multiaddr) {
|
||||
ChainSpec::add_boot_node(self, addr)
|
||||
}
|
||||
|
||||
fn extensions(&self) -> &dyn GetExtension {
|
||||
ChainSpec::extensions(self) as &dyn GetExtension
|
||||
}
|
||||
|
||||
fn as_json(&self, raw: bool) -> Result<String, String> {
|
||||
ChainSpec::as_json(self, raw)
|
||||
}
|
||||
|
||||
fn as_storage_builder(&self) -> &dyn BuildStorage {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
@@ -344,7 +391,7 @@ mod tests {
|
||||
PathBuf::from("./res/chain_spec.json")
|
||||
).unwrap();
|
||||
|
||||
assert_eq!(spec1.to_json(false), spec2.to_json(false));
|
||||
assert_eq!(spec1.as_json(false), spec2.as_json(false));
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
|
||||
@@ -17,6 +17,8 @@
|
||||
//! Chain Spec extensions helpers.
|
||||
|
||||
use std::fmt::Debug;
|
||||
use std::any::{TypeId, Any};
|
||||
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
use serde::{Serialize, Deserialize, de::DeserializeOwned};
|
||||
@@ -120,6 +122,8 @@ pub trait Extension: Serialize + DeserializeOwned + Clone {
|
||||
|
||||
/// Get an extension of specific type.
|
||||
fn get<T: 'static>(&self) -> Option<&T>;
|
||||
/// Get an extension of specific type as refernce to `Any`
|
||||
fn get_any(&self, t: TypeId) -> &dyn Any;
|
||||
|
||||
/// Get forkable extensions of specific type.
|
||||
fn forks<BlockNumber, T>(&self) -> Option<Forks<BlockNumber, T>> where
|
||||
@@ -137,6 +141,7 @@ impl Extension for crate::NoExtension {
|
||||
type Forks = Self;
|
||||
|
||||
fn get<T: 'static>(&self) -> Option<&T> { None }
|
||||
fn get_any(&self, _t: TypeId) -> &dyn Any { self }
|
||||
}
|
||||
|
||||
pub trait IsForks {
|
||||
@@ -225,22 +230,25 @@ impl<B, E> Extension for Forks<B, E> where
|
||||
type Forks = Self;
|
||||
|
||||
fn get<T: 'static>(&self) -> Option<&T> {
|
||||
use std::any::{TypeId, Any};
|
||||
|
||||
match TypeId::of::<T>() {
|
||||
x if x == TypeId::of::<E>() => Any::downcast_ref(&self.base),
|
||||
_ => self.base.get(),
|
||||
}
|
||||
}
|
||||
|
||||
fn get_any(&self, t: TypeId) -> &dyn Any {
|
||||
match t {
|
||||
x if x == TypeId::of::<E>() => &self.base,
|
||||
_ => self.base.get_any(t),
|
||||
}
|
||||
}
|
||||
|
||||
fn forks<BlockNumber, T>(&self) -> Option<Forks<BlockNumber, T>> where
|
||||
BlockNumber: Ord + Clone + 'static,
|
||||
T: Group + 'static,
|
||||
<Self::Forks as IsForks>::Extension: Extension,
|
||||
<<Self::Forks as IsForks>::Extension as Group>::Fork: Extension,
|
||||
{
|
||||
use std::any::{TypeId, Any};
|
||||
|
||||
if TypeId::of::<BlockNumber>() == TypeId::of::<B>() {
|
||||
Any::downcast_ref(&self.for_type::<T>()?).cloned()
|
||||
} else {
|
||||
@@ -250,6 +258,24 @@ impl<B, E> Extension for Forks<B, E> where
|
||||
}
|
||||
}
|
||||
|
||||
/// A subset if the `Extension` trait that only allows for quering extensions.
|
||||
pub trait GetExtension {
|
||||
/// Get an extension of specific type.
|
||||
fn get_any(&self, t: TypeId) -> &dyn Any;
|
||||
}
|
||||
|
||||
impl <E: Extension> GetExtension for E {
|
||||
fn get_any(&self, t: TypeId) -> &dyn Any {
|
||||
Extension::get_any(self, t)
|
||||
}
|
||||
}
|
||||
|
||||
/// Helper function that queries an extension by type from `GetExtension`
|
||||
/// trait object.
|
||||
pub fn get_extension<T: 'static>(e: &dyn GetExtension) -> Option<&T> {
|
||||
Any::downcast_ref(GetExtension::get_any(e, TypeId::of::<T>()))
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
@@ -30,14 +30,14 @@
|
||||
//! ```rust
|
||||
//! use std::collections::HashMap;
|
||||
//! use serde::{Serialize, Deserialize};
|
||||
//! use sc_chain_spec::{ChainSpec, ChainSpecExtension};
|
||||
//! use sc_chain_spec::{GenericChainSpec, ChainSpecExtension};
|
||||
//!
|
||||
//! #[derive(Clone, Debug, Serialize, Deserialize, ChainSpecExtension)]
|
||||
//! pub struct MyExtension {
|
||||
//! pub known_blocks: HashMap<u64, String>,
|
||||
//! }
|
||||
//!
|
||||
//! pub type MyChainSpec<G> = ChainSpec<G, MyExtension>;
|
||||
//! pub type MyChainSpec<G> = GenericChainSpec<G, MyExtension>;
|
||||
//! ```
|
||||
//!
|
||||
//! Some parameters may require different values depending on the
|
||||
@@ -49,7 +49,7 @@
|
||||
//!
|
||||
//! ```rust
|
||||
//! use serde::{Serialize, Deserialize};
|
||||
//! use sc_chain_spec::{Forks, ChainSpec, ChainSpecGroup, ChainSpecExtension};
|
||||
//! use sc_chain_spec::{Forks, ChainSpecGroup, ChainSpecExtension, GenericChainSpec};
|
||||
//!
|
||||
//! #[derive(Clone, Debug, Serialize, Deserialize, ChainSpecGroup)]
|
||||
//! pub struct ClientParams {
|
||||
@@ -71,10 +71,10 @@
|
||||
//! pub type BlockNumber = u64;
|
||||
//!
|
||||
//! /// A chain spec supporting forkable `ClientParams`.
|
||||
//! pub type MyChainSpec1<G> = ChainSpec<G, Forks<BlockNumber, ClientParams>>;
|
||||
//! pub type MyChainSpec1<G> = GenericChainSpec<G, Forks<BlockNumber, ClientParams>>;
|
||||
//!
|
||||
//! /// A chain spec supporting forkable `Extension`.
|
||||
//! pub type MyChainSpec2<G> = ChainSpec<G, Forks<BlockNumber, Extension>>;
|
||||
//! pub type MyChainSpec2<G> = GenericChainSpec<G, Forks<BlockNumber, Extension>>;
|
||||
//! ```
|
||||
//!
|
||||
//! It's also possible to have a set of parameters that is allowed to change
|
||||
@@ -84,7 +84,7 @@
|
||||
//!
|
||||
//! ```rust
|
||||
//! use serde::{Serialize, Deserialize};
|
||||
//! use sc_chain_spec::{Forks, ChainSpec, ChainSpecGroup, ChainSpecExtension};
|
||||
//! use sc_chain_spec::{Forks, GenericChainSpec, ChainSpecGroup, ChainSpecExtension};
|
||||
//!
|
||||
//! #[derive(Clone, Debug, Serialize, Deserialize, ChainSpecGroup)]
|
||||
//! pub struct ClientParams {
|
||||
@@ -104,20 +104,48 @@
|
||||
//! pub pool: Forks<u64, PoolParams>,
|
||||
//! }
|
||||
//!
|
||||
//! pub type MyChainSpec<G> = ChainSpec<G, Extension>;
|
||||
//! pub type MyChainSpec<G> = GenericChainSpec<G, Extension>;
|
||||
//! ```
|
||||
|
||||
|
||||
mod chain_spec;
|
||||
mod extension;
|
||||
|
||||
pub use chain_spec::{ChainSpec, Properties, NoExtension};
|
||||
pub use extension::{Group, Fork, Forks, Extension};
|
||||
pub use chain_spec::{ChainSpec as GenericChainSpec, Properties, NoExtension};
|
||||
pub use extension::{Group, Fork, Forks, Extension, GetExtension, get_extension};
|
||||
pub use sc_chain_spec_derive::{ChainSpecExtension, ChainSpecGroup};
|
||||
|
||||
use serde::{Serialize, de::DeserializeOwned};
|
||||
use sp_runtime::BuildStorage;
|
||||
use sc_network::Multiaddr;
|
||||
use sc_telemetry::TelemetryEndpoints;
|
||||
|
||||
/// A set of traits for the runtime genesis config.
|
||||
pub trait RuntimeGenesis: Serialize + DeserializeOwned + BuildStorage {}
|
||||
impl<T: Serialize + DeserializeOwned + BuildStorage> RuntimeGenesis for T {}
|
||||
|
||||
/// Common interface to `GenericChainSpec`
|
||||
pub trait ChainSpec: BuildStorage {
|
||||
/// Spec name.
|
||||
fn name(&self) -> &str;
|
||||
/// Spec id.
|
||||
fn id(&self) -> &str;
|
||||
/// A list of bootnode addresses.
|
||||
fn boot_nodes(&self) -> &[String];
|
||||
/// Telemetry endpoints (if any)
|
||||
fn telemetry_endpoints(&self) -> &Option<TelemetryEndpoints>;
|
||||
/// Network protocol id.
|
||||
fn protocol_id(&self) -> Option<&str>;
|
||||
/// Additional loosly-typed properties of the chain.
|
||||
///
|
||||
/// Returns an empty JSON object if 'properties' not defined in config
|
||||
fn properties(&self) -> Properties;
|
||||
/// Returns a reference to defined chain spec extensions.
|
||||
fn extensions(&self) -> &dyn GetExtension;
|
||||
/// Add a bootnode to the list.
|
||||
fn add_boot_node(&mut self, addr: Multiaddr);
|
||||
/// Return spec as JSON.
|
||||
fn as_json(&self, raw: bool) -> Result<String, String>;
|
||||
/// Return StorageBuilder for this spec.
|
||||
fn as_storage_builder(&self) -> &dyn BuildStorage;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user