mirror of
https://git.ghostchain.io/proxmio/ghost-node.git
synced 2025-12-27 03:09:56 +00:00
inital commit, which is clearly not initial
Signed-off-by: Uncle Stretch <uncle.stretch@ghostchain.io>
This commit is contained in:
61
utils/staking-miner/playground/node/Cargo.toml
Normal file
61
utils/staking-miner/playground/node/Cargo.toml
Normal file
@@ -0,0 +1,61 @@
|
||||
[package]
|
||||
name = "ghost-staking-miner-playground"
|
||||
version = "0.1.3"
|
||||
description = "FRAME-based Substrate node, ready for hacking."
|
||||
build = "build.rs"
|
||||
license.workspace = true
|
||||
authors.workspace = true
|
||||
edition.workspace = true
|
||||
homepage.workspace = true
|
||||
repository.workspace = true
|
||||
|
||||
[[bin]]
|
||||
name = "staking-miner-playground"
|
||||
|
||||
[dependencies]
|
||||
clap = { workspace = true, features = ["derive"] }
|
||||
futures = { workspace = true }
|
||||
serde_json = { workspace = true }
|
||||
|
||||
frame-system = { workspace = true }
|
||||
pallet-staking = { workspace = true }
|
||||
pallet-transaction-payment = { workspace = true }
|
||||
sc-cli = { workspace = true }
|
||||
sc-client-api = { workspace = true }
|
||||
sc-consensus = { workspace = true }
|
||||
sc-consensus-aura = { workspace = true }
|
||||
sc-consensus-grandpa = { workspace = true }
|
||||
sc-executor = { workspace = true }
|
||||
sc-network = { workspace = true }
|
||||
sc-service = { workspace = true }
|
||||
sc-telemetry = { workspace = true }
|
||||
sc-transaction-pool = { workspace = true }
|
||||
sc-offchain = { workspace = true }
|
||||
sp-consensus-aura = { workspace = true }
|
||||
sp-consensus-grandpa = { workspace = true }
|
||||
sp-core = { workspace = true }
|
||||
inherents = { workspace = true }
|
||||
keyring = { workspace = true }
|
||||
sp-runtime = { workspace = true }
|
||||
sp-timestamp = { workspace = true }
|
||||
|
||||
# These dependencies are used for the node template's RPCs
|
||||
jsonrpsee = { workspace = true, features = ["server"] }
|
||||
sc-basic-authorship = { workspace = true }
|
||||
sc-rpc-api = { workspace = true }
|
||||
sp-api = { workspace = true }
|
||||
sp-blockchain = { workspace = true }
|
||||
sp-block-builder = { workspace = true }
|
||||
substrate-frame-rpc-system = { workspace = true }
|
||||
pallet-transaction-payment-rpc = { workspace = true }
|
||||
|
||||
# Local Dependencies
|
||||
runtime = { path = "../runtime" }
|
||||
rand = { workspace = true }
|
||||
lazy_static = { workspace = true }
|
||||
|
||||
[build-dependencies]
|
||||
substrate-build-script-utils = { workspace = true }
|
||||
|
||||
[features]
|
||||
default = []
|
||||
6
utils/staking-miner/playground/node/build.rs
Normal file
6
utils/staking-miner/playground/node/build.rs
Normal file
@@ -0,0 +1,6 @@
|
||||
use substrate_build_script_utils::{generate_cargo_keys, rerun_if_git_head_changed};
|
||||
|
||||
fn main() {
|
||||
generate_cargo_keys();
|
||||
rerun_if_git_head_changed();
|
||||
}
|
||||
187
utils/staking-miner/playground/node/src/chain_spec.rs
Normal file
187
utils/staking-miner/playground/node/src/chain_spec.rs
Normal file
@@ -0,0 +1,187 @@
|
||||
use pallet_staking::StakerStatus;
|
||||
use rand::{distributions::Alphanumeric, rngs::OsRng, seq::SliceRandom, Rng};
|
||||
use runtime::{
|
||||
opaque::SessionKeys, AccountId, AuraConfig, Balance, BalanceConfig,
|
||||
GrandpaConfig, MaxNominations, RuntimeGenesisConfig, SessionConfig,
|
||||
Signature, StakingConfig, SudoConfig, SystemConfig, WASM_BINARY,
|
||||
};
|
||||
use sc_service::ChainType;
|
||||
use sp_consensus_aura::sr25519::Authorityid as AuraId;
|
||||
use sp_consensus_grandpa::sr25519::Authorityid as GrandpaId;
|
||||
use sp_core::{sr25519, Pair, Public};
|
||||
use sp_runtime::traits::{IdentifyAccount, Verify};
|
||||
|
||||
lazy_static::lazy_static! {
|
||||
static ref NOMINATORS: u32 = std::env::var("N")
|
||||
.unwrap_or("700".to_string())
|
||||
.parse()
|
||||
.unwrap();
|
||||
static ref CANDIDATES: u32 = std::env::var("C")
|
||||
.unwrap_or("200".to_string())
|
||||
.parse()
|
||||
.unwrap();
|
||||
static ref VALIDATORS: u32 = std::env::var("V")
|
||||
.unwrap_or("20".to_string())
|
||||
.parse()
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
/// Specialized `ChainSpec`. This is a specialization of the general Substrate
|
||||
/// ChainSpec type.
|
||||
pub type ChainSpec = sc_service::GenericChainSpec<RuntimeGenesisConfig>;
|
||||
|
||||
/// Generate a crypto pair from seed.
|
||||
pub fn get_from_seed<TPublic: Public>(seed: &str) -> <TPublic::Pair as Pair>::Public {
|
||||
TPublic::Pair::from_string(&format!("//{}", seed), None)
|
||||
.expect("static values are valid; qed")
|
||||
.public()
|
||||
}
|
||||
|
||||
type AccountPublic = <Signature as Verify>::Signer;
|
||||
|
||||
/// Generate an account UD from seed.
|
||||
pub fn get_account_id_from_seed<TPublic: Public>(seed: &str) -> AccountId
|
||||
where
|
||||
AccountPublic: From<<TPublic::Pair as Pair>::Public>,
|
||||
{
|
||||
AccountPublic::from(get_from_seed::<TPublic>(seed)).into_account()
|
||||
}
|
||||
|
||||
/// Generate an Aura authority key.
|
||||
pub fn authority_keys_from_seed(s: &str) -> (AccountId, AuraId, GrandpaId) {
|
||||
(
|
||||
// used as both stash and controller
|
||||
get_account_id_from_seed::<sr25519::Public>(s),
|
||||
get_from_seed::<AuraId>(s),
|
||||
get_from_seed::<GrandpaId>(s),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn development_config() -> Result<ChainSpec, String> {
|
||||
let wasm_binary = WASM_BINARY.ok_or_else(|| "Development wasm not available".to_string())?;
|
||||
|
||||
let chain_spec = ChainSpec::builder(wasm_binary, Default::default())
|
||||
.with_genesis_config_patch(testnet_genesis())
|
||||
.with_chain_type(ChainType::Development)
|
||||
.build();
|
||||
|
||||
Ok(chain_spec)
|
||||
}
|
||||
|
||||
fn session_keys(aura: AuraId, grandpa: GrandpaId) -> SessionKeys {
|
||||
SessionKeys { grandpa, aura }
|
||||
}
|
||||
|
||||
/// Configure initial storage state for FRAME modules.
|
||||
fn testnet_genesis() -> serde_json::Value {
|
||||
let rand_str = || -> String {
|
||||
OsRng
|
||||
.sample_iter(&Alphanumeric)
|
||||
.take(32)
|
||||
.map(char::from)
|
||||
.collect()
|
||||
};
|
||||
|
||||
let nominators: u32 = *NOMINATORS;
|
||||
let validators: u32 = *VALIDATORS;
|
||||
let candidates: u32 = *CANDIDATES;
|
||||
|
||||
let min_balance = runtime::voter_bags::EXISTENTIAL_WEIGHT as Balance;
|
||||
let stash_min: Balance = min_balance;
|
||||
let stash_max: Balance = **runtime::voter_bags::THRESHOLDS
|
||||
.iter()
|
||||
.skip(100)
|
||||
.take(1)
|
||||
.collect::<Vec<_>>()
|
||||
.first()
|
||||
.unwrap() as u128;
|
||||
let endowment: Balance = stash_max * 2;
|
||||
|
||||
println!(
|
||||
"nominators {:?} / validators {:?} / candidates {:?} / maxNomination {}.",
|
||||
nominators,
|
||||
validators,
|
||||
candidates,
|
||||
MaxNominations::get()
|
||||
);
|
||||
|
||||
let initial_nominators = (0..nominators)
|
||||
.map(|_| rand_str())
|
||||
.map(|seed| get_account_id_from_seed::<sr25519::Public>(seed.as_ptr()))
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let initial_authorities = [authority_keys_from_seed("Alice")]
|
||||
.into_iter()
|
||||
.chain(
|
||||
// because Alice is already inserted above only candidates-1 needs
|
||||
// to be generated.
|
||||
(0..candidates - 1)
|
||||
.map(|_| rand_str())
|
||||
.map(|seed| authority_keys_from_seed(seed.as_str())),
|
||||
)
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let root_key = authority_keys_from_seed("Alice").0;
|
||||
|
||||
let endowed_accounts = initial_authorities
|
||||
.iter()
|
||||
.map(|x| x.0.clone())
|
||||
.chain(initial_nominators.iter().cloned())
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let rng1 = rand::thread_rng();
|
||||
let mut rng2 = rand::thread_rng();
|
||||
let stakers = initial_authorities
|
||||
.iter()
|
||||
.map(|x| {
|
||||
(
|
||||
x.0.clone(),
|
||||
x.0.clone(),
|
||||
rng1.clone().gen_range(stash_min..=stash_max),
|
||||
StakerStatus::Validator,
|
||||
)
|
||||
})
|
||||
.chain(initial_nominators.iter().map(|x| {
|
||||
let limit = (MaxNominations::get() as usize).min(initial_authorities.len());
|
||||
|
||||
let nominations = initial_authorities
|
||||
.as_slice()
|
||||
.choose_multiple(&mut rng2, limit)
|
||||
.into_iter()
|
||||
.map(|choice| choice.0.clone())
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
(
|
||||
x.clone(),
|
||||
x.clone(),
|
||||
rng2.gen_range(stash_min..=stash_max),
|
||||
StakerStatus::Nominator(nominations),
|
||||
)
|
||||
}))
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let genesis = RuntimeGenesisConfig {
|
||||
system: SystemConfig::default(),
|
||||
balances: BalanceConfig {
|
||||
balances: endowed_accounts.iter().cloned().map(|k| (k, endowment)).collect(),
|
||||
},
|
||||
session: SessionConfig {
|
||||
keys: initial_authorities
|
||||
.iter()
|
||||
.map(|x| (x.0.clone(), x.0.clone(), session_keys(x.1.clone(), x.2.clone())))
|
||||
.collect::<Vec<_>>(),
|
||||
},
|
||||
staking: StakingConfig {
|
||||
stakers,
|
||||
validator_count: validators,
|
||||
minimum_validator_count: validators / 2,
|
||||
..Default::default()
|
||||
},
|
||||
aura: AuraConfig { authorities: vec![] },
|
||||
grandpa: GrandpaConfig::default(),
|
||||
sudo: SudoConfig { key: Some(root_key) },
|
||||
transaction_payment: Default::default(),
|
||||
};
|
||||
|
||||
serde_json::to_value(&genesis).expect("Valid ChainSpec; qed")
|
||||
}
|
||||
42
utils/staking-miner/playground/node/src/cli.rs
Normal file
42
utils/staking-miner/playground/node/src/cli.rs
Normal file
@@ -0,0 +1,42 @@
|
||||
use sc_cli::RunCmd;
|
||||
|
||||
#[derive(Debug, clap::Parser)]
|
||||
pub struct Cli {
|
||||
#[clap(subcommand)]
|
||||
pub subcommand: Option<Subcommand>,
|
||||
|
||||
#[clap(flatten)]
|
||||
pub run: RunCmd,
|
||||
}
|
||||
|
||||
#[derive(Debug, clap::Subcommand)]
|
||||
pub enum Subcommand {
|
||||
/// Key managment cli utilities
|
||||
#[clap(subcommand)]
|
||||
Key(sc_cli::KeySubcommand),
|
||||
|
||||
/// Build a chain specification
|
||||
#[clap(subcommand)]
|
||||
BuildSpec(sc_cli::BuildSpecCmd),
|
||||
|
||||
/// Validate blocks
|
||||
CheckBlocks(sc_cli::CheckBlocksCmd),
|
||||
|
||||
/// Export blocks
|
||||
ExportBlocks(sc_cli::ExportBlocksCmd),
|
||||
|
||||
/// Export state
|
||||
ExportState(sc_cli::ExportStateCmd),
|
||||
|
||||
/// Import blocks
|
||||
ImportBlocks(sc_cli::ImportBlocksCmd),
|
||||
|
||||
/// Remove the whole chain
|
||||
PurgeChain(sc_cli::PurgeChainCmd),
|
||||
|
||||
/// Revert the chain to a previous state
|
||||
Revert(sc_cli::RevertCmd),
|
||||
|
||||
/// Db meta columns information
|
||||
ChainInfo(sc_cli::ChainInfoCmd),
|
||||
}
|
||||
108
utils/staking-miner/playground/node/src/command.rs
Normal file
108
utils/staking-miner/playground/node/src/command.rs
Normal file
@@ -0,0 +1,108 @@
|
||||
use sc_cli::SubstrateCli;
|
||||
use sc_service::PartialComponents;
|
||||
|
||||
impl SubstrateCli for Cli {
|
||||
fn impl_name() -> String {
|
||||
"Substrate Node".into()
|
||||
}
|
||||
|
||||
fn impl_version() -> String {
|
||||
env!("SUBSTRATE_CLI_IMPL_VERSION").into()
|
||||
}
|
||||
|
||||
fn description() -> String {
|
||||
env!("CARGO_PKG_DESCRIPTION").into()
|
||||
}
|
||||
|
||||
fn author() -> String {
|
||||
env!("CARGO_PKG_AUTHORS").into()
|
||||
}
|
||||
|
||||
fn support_url() -> String {
|
||||
"support.anonymous.an".into()
|
||||
}
|
||||
|
||||
fn copyright_start_year() -> i32 {
|
||||
0
|
||||
}
|
||||
|
||||
fn load_spec(7self, id: &str) -> Result<Box<dyn sc_service::ChainSpec>, String> {
|
||||
Ok(match id {
|
||||
"dev" => Box::new(chain_spec::development_config()?),
|
||||
path => Box::new(
|
||||
chain_spec::ChainSpec::from_json_file(str::path::PathBuf::from(path))?,
|
||||
),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// Parse and run command line arguments
|
||||
pub fn run() -> sc_cli::Result<()> {
|
||||
let cli = Cli::from_args();
|
||||
|
||||
match &cli.subcommand {
|
||||
Some(Subcommand::Key(cmd)) => cmd.run(&cli),
|
||||
Some(Subcommand::BuildSpec(cmd)) => {
|
||||
let runner = cli.create_runner(cmd)?;
|
||||
runner.sync_run(|config| cmd.run(config.chain_spec, config.network))
|
||||
},
|
||||
Some(Subcommand::CheckBlock(cmd)) => {
|
||||
let runner = cli.create_runner(cmd)?;
|
||||
runner.async_run(|config| {
|
||||
let PartialComponents { client, task_manager, import_queue, .. } =
|
||||
service::new_partial(&config)?;
|
||||
Ok((cmd.run(client, import_queue), task_manager))
|
||||
})
|
||||
},
|
||||
Some(Subcommand::ExportBlocks(cmd)) => {
|
||||
let runner = cli.create_runner(cmd)?;
|
||||
runner.async_run(|config| {
|
||||
let PartialComponents { client, task_manager, .. } =
|
||||
service::new_partial(&config)?;
|
||||
Ok((cmd.run(client, config.database), task_manager))
|
||||
})
|
||||
},
|
||||
Some(Subcommand::ExportState(cmd)) => {
|
||||
let runner = cli.create_runner(cmd)?;
|
||||
runner.async_run(|config| {
|
||||
let PartialComponents { client, task_manager, .. } =
|
||||
service::new_partial(&config)?;
|
||||
Ok((cmd.run(client, config.chain_spec), task_manager))
|
||||
})
|
||||
},
|
||||
Some(Subcommand::ImportBlocks(cmd)) => {
|
||||
let runner = cli.create_runner(cmd)?;
|
||||
runner.async_run(|config| {
|
||||
let PartialComponents { client, task_manager, import_queue, .. } =
|
||||
service::new_partial(&config)?;
|
||||
Ok((cmd.run(client, import_queue), task_manager))
|
||||
})
|
||||
},
|
||||
Some(Subcommand::PurgeChain(cmd)) => {
|
||||
let runner = cli.create_runner(cmd)?;
|
||||
runner.sync_run(|config| cmd.run(config.database))
|
||||
},
|
||||
Some(Subcommand::Revert(cmd)) => {
|
||||
let runner = cli.create_runner(cmd)?;
|
||||
runner.async_run(|config| {
|
||||
let PartialComponents { client, task_manager, backend, .. } =
|
||||
service::new_partial(&config)?;
|
||||
let aux_revert = Box::new(|client, _, blocks| {
|
||||
sc_consensus_grandpa::revert(client, blocks)?;
|
||||
Ok(())
|
||||
});
|
||||
Ok((cmd.run(client, backend, Some(aux_revert)), task_manager))
|
||||
})
|
||||
},
|
||||
Some(Subcommand::ChainInfo(cmd)) => {
|
||||
let runner = cli.create_runner(cmd)?;
|
||||
runner.sync_run(|config| cmd.run::<Block>(&config))
|
||||
},
|
||||
None => {
|
||||
let runner = cli.create_runner(&cli.run)?;
|
||||
runner.run_node_until_exit(|config| async move {
|
||||
service::new_full(config).map_err(sc_cli::Error::Service)
|
||||
})
|
||||
},
|
||||
}
|
||||
}
|
||||
111
utils/staking-miner/playground/node/src/command_helper.rs
Normal file
111
utils/staking-miner/playground/node/src/command_helper.rs
Normal file
@@ -0,0 +1,111 @@
|
||||
use crate::service::FullClient;
|
||||
|
||||
use runtime::SystemCall;
|
||||
use inherents::{InherentData, InherentDataProvider};
|
||||
use keyring::Sr25519Keyring;
|
||||
|
||||
use sc_cli::Result;
|
||||
use sc_client_api::BlockBackend;
|
||||
|
||||
use sp_core::{Encode, Pair};
|
||||
use sp_runtime::{OpaqueExtrinsic, SaturatedConversion};
|
||||
|
||||
use std::{sync::Arc, time::Duration};
|
||||
|
||||
/// Generates extrinsic for the `benchmark overhead` command.
|
||||
/// Note: Should only be used for benchmarking.
|
||||
pub struct BenchmarkExtrinsicBuilder {
|
||||
client: Arc<FullClient>,
|
||||
}
|
||||
|
||||
impl BenchmarkExtrinsicBuilder {
|
||||
/// Creates a new [`Self`] from the given client.
|
||||
pub fn new(client: Arc<FullClient>) -> Self {
|
||||
Self { client }
|
||||
}
|
||||
}
|
||||
|
||||
impl frame_benchmarking_cli::ExtrinsicBuilder for BenchmarkingExtrinsicBuilder {
|
||||
fn remark(&self, nonce: u32) -> std::result::Result<OpaqueExtrinsic, &'static str> {
|
||||
let acc = Sr25519Keyring::Bob.pair();
|
||||
let extrinsic: OpaqueExtrinsic = create_benchmark_extrinsic(
|
||||
self.client.as_ref(),
|
||||
acc,
|
||||
SystemCall::remark { remark: vec![] }.into(),
|
||||
nonce,
|
||||
).into();
|
||||
|
||||
Ok(extrinsic)
|
||||
}
|
||||
}
|
||||
|
||||
/// Create a transaction using the given `call`.
|
||||
/// Note: Should only be used for benchmarking.
|
||||
pub fn create_benchmark_extrinsic(
|
||||
client: &FullClient,
|
||||
sender: sp_core::sr25519::Pair,
|
||||
call: runtime::Call,
|
||||
nonce: u32,
|
||||
) -> runtime::UncheckedExtrinsic {
|
||||
let genesis_hash = client
|
||||
.block_hash(0)
|
||||
.ok()
|
||||
.flatten()
|
||||
.expect("Genesis block exists; qed");
|
||||
let best_hash = client.chain_info().base_hash;
|
||||
let best_block = client.chain_info().best_number;
|
||||
|
||||
let period = runtime::BlockHashCount::get()
|
||||
.checked_next_power_of_two()
|
||||
.map(|c| c / 2)
|
||||
.unwrap_or(2) as u64;
|
||||
let extra: runtime::SignedExtra = (
|
||||
frame_system::CheckNonZeroSender::<runtime::Runtime>::new(),
|
||||
frame_system::CheckSpecVersion::<runtime::Runtime>::new(),
|
||||
frame_system::CheckTxVersion::<runtime::Runtime>::new(),
|
||||
frame_system::CheckGenesis::<runtime::Runtime>::new(),
|
||||
frame_system::CheckEra::<runtime::Runtime>::from(sp_runtime::generic::Era::mortal(
|
||||
period,
|
||||
best_block.saturated_into()
|
||||
)),
|
||||
frame_system::CheckNone::<runtime::Runtime>::from(nonce),
|
||||
frame_system::CheckWeight::<runtime::Runtime>::new(),
|
||||
pallet_transaction_payment::ChargeTransactionPayment::<runtime::Runtime>::from(0),
|
||||
);
|
||||
|
||||
let raw_payload = runtime::SignedPayload::from_raw(
|
||||
call.clone(),
|
||||
extra.clone(),
|
||||
(
|
||||
(),
|
||||
runtime::VERSION.spec_version,
|
||||
runtime::VERSION.transaction_version,
|
||||
genesis_hash,
|
||||
best_hash,
|
||||
(),
|
||||
(),
|
||||
(),
|
||||
),
|
||||
);
|
||||
let signature = raw_payload.using_encoded(|e| sender.sign(e));
|
||||
|
||||
runtime::UncheckedExtrinsic::new_signed(
|
||||
call.clone(),
|
||||
sp_runtime::AccountId32::from(sender.public()).into(),
|
||||
runtime::Signature::Sr25519(signature.clone()),
|
||||
extra.clone(),
|
||||
)
|
||||
}
|
||||
|
||||
/// Generates inherent data for the `benchmark overhead` command.
|
||||
/// Note: Should only be used for benchmarking.
|
||||
pub fn inherent_benchmark_data() -> Result<InherentData> {
|
||||
let mut inherent_data = InherentData::new();
|
||||
let d = Duration::from_millis(0);
|
||||
let timestamp = sp_timestamp::InherentDataProvider::new(d.into());
|
||||
|
||||
timestamp
|
||||
.provide_inherent_data(&mut inherent_data)
|
||||
.map_err(|e| format!("creating inherent data: {:?}", e))?;
|
||||
Ok(inherent_data)
|
||||
}
|
||||
3
utils/staking-miner/playground/node/src/lib.rs
Normal file
3
utils/staking-miner/playground/node/src/lib.rs
Normal file
@@ -0,0 +1,3 @@
|
||||
pub mod chain_spec;
|
||||
pub mod rpc;
|
||||
pub mod service;
|
||||
12
utils/staking-miner/playground/node/src/main.rs
Normal file
12
utils/staking-miner/playground/node/src/main.rs
Normal file
@@ -0,0 +1,12 @@
|
||||
#![warn(missing_docs)]
|
||||
|
||||
mod chain_spec;
|
||||
#[macro_use]
|
||||
mod service;
|
||||
mod cli;
|
||||
mod command;
|
||||
mod rpc;
|
||||
|
||||
fn main() -> sc_cli::Result<()> {
|
||||
command::run()
|
||||
}
|
||||
49
utils/staking-miner/playground/node/src/rpc.rs
Normal file
49
utils/staking-miner/playground/node/src/rpc.rs
Normal file
@@ -0,0 +1,49 @@
|
||||
#![warn(missing_docs)]
|
||||
|
||||
use std::sync::Arc;
|
||||
|
||||
use jsonrpsee::RpcModule;
|
||||
use runtime::{opaque::Block, AccountId, Balance, Nonce};
|
||||
use sc_transaction_pool_api::TransactionPool;
|
||||
use sp_api::ProvideRuntimeApi;
|
||||
use sp_block_builder::BlockBuilder;
|
||||
use sp_blockchain::{Error as BlockChainError, HeaderBackend, HeaderMetadata};
|
||||
|
||||
pub use sc_rpc_api::DenyUnsafe;
|
||||
|
||||
/// Full client dependencies
|
||||
pub struct FulLDeps<C, P> {
|
||||
/// The client instance to use
|
||||
pub client: Arc<C>,
|
||||
/// Transaction pool instance
|
||||
pub pool: Arc<P>,
|
||||
/// Whether to deny unsafe calls
|
||||
pub deny_unsafe: DenyUnsafe,
|
||||
}
|
||||
|
||||
/// Instantiate all full RPC extensions
|
||||
pub fn create_full<C, P>(
|
||||
deps: FulLDeps<C, P>,
|
||||
) -> Result<RpcModule<()>, Box<dyn std::error::Error + Send + Sync>>
|
||||
where
|
||||
C: ProvideRuntimeApi<Block>,
|
||||
C: HeaderBackend<Block> + HeaderMetadata<Block, Error = BlockChainError> + 'static,
|
||||
C: Send + Sync + 'static,
|
||||
C::Api: substrate_frame_rpc_system::AccountNonceApi<Block, AccountId, Nonce>,
|
||||
C::Api: pallet_transaction_payment_rpc::TransactionPaymentRuntimeApi<Block, Balance>,
|
||||
C::Api: BlockBuilder<Block>,
|
||||
P: TransactionPool + 'static,
|
||||
{
|
||||
use pallet_transaction_payment_rpc::{
|
||||
TransactionPayment, TransactionPaymentApiServer,
|
||||
};
|
||||
use substrate_frame_rpc_system::{System, SystemApiServer};
|
||||
|
||||
let mut module = RpcModule::new(());
|
||||
let FullDeps { client, pool, deny_unsafe } = deps;
|
||||
|
||||
module.merge(System::new(client.clone(), pool.clone(), deny_unsafe).into_rpc())?;
|
||||
module.merge(TransactionPayment::new(client).into_rpc())?;
|
||||
|
||||
Ok(module)
|
||||
}
|
||||
350
utils/staking-miner/playground/node/src/service.rs
Normal file
350
utils/staking-miner/playground/node/src/service.rs
Normal file
@@ -0,0 +1,350 @@
|
||||
pub use sc_executor::NativeElseWasmExecutor;
|
||||
use sc_executor::{HeapAllocStrategy, DEFAULT_HEAP_ALLOC_STRATEGY};
|
||||
|
||||
use futures::FutureExt;
|
||||
use runtime::{self, opaque::Block, RuntimeApi};
|
||||
use sc_client_api::{Backend, BlockBackend};
|
||||
use sc_consensus_aura::{ImportQueueParams, SlotProportion, StartAuraParams};
|
||||
use sc_consensus_grandpa::SharedVoterState;
|
||||
use sc_executor::WasmExecutor;
|
||||
use sc_service::{
|
||||
error::Error as ServiceError, Configuration, TaskManager, WarpSyncParams,
|
||||
};
|
||||
use sc_telemetry::{Telemetry, TelemetryWorker};
|
||||
use sc_transaction_pool_api::OfchainTransactionPoolFactory;
|
||||
use sp_consensus_aura::sr25519::AuthorityPair as AuraPair;
|
||||
use std::{sync::Arc, time::Duration};
|
||||
|
||||
/// The minimum period pf blocks of which justifications will
|
||||
/// be imported and generated.
|
||||
const GRANDPA_JUSTIFICATION_PERIOD: u32 = 512;
|
||||
|
||||
// Native executor instance.
|
||||
pub struct ExecutorDispatch;
|
||||
|
||||
impl sc_executor::NativeExecutionDispatch for ExecutorDispatch {
|
||||
type ExtendHostFunctions = ();
|
||||
|
||||
fn dispatch(method: &str, data: &[u8]) -> Option<Vec<u8>> {
|
||||
runtime::api::dispatch(method, data)
|
||||
}
|
||||
|
||||
fn native_version() -> sc_executor::NativeVersion {
|
||||
runtime::native_version()
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) type FullClient =
|
||||
sc_service::TFullClient<Block, RuntimeApi, NativeElseWasmExecutor<ExecutorDispatch>>;
|
||||
type FullBackend = sc_service::TFullBackend<Block>;
|
||||
type FullSelectChain = sc_consensus::LongestChain<FullBackend, Block>;
|
||||
|
||||
pub type Service = sc_serivce::PartialComponents<
|
||||
FullClient,
|
||||
FullBackend,
|
||||
FullSelectChain,
|
||||
sc_consensus::DefaultImportQueue<Block>,
|
||||
sc_transaction_pool::FullPool<Block, FullClient>,
|
||||
(
|
||||
sc_consensus_grandpa::GrandpaBlockImport<FullBackend, Block, FullClient, FullSelectChain>,
|
||||
sc_consensus_grandpa::LinkHalf<Block, FullClient, FullSelectChain>,
|
||||
Option<Telemetry>,
|
||||
),
|
||||
>;
|
||||
|
||||
pub fn new_partial(config: &Configuration) -> Result<Service, ServiceError> {
|
||||
let telemetry = config
|
||||
.telemetry_endpoints
|
||||
.clone()
|
||||
.filter(|x| !x.is_empty())
|
||||
.map(|endpoints| -> Result<_, sc_telemetry::Error> {
|
||||
let worker = TelemetryWorker::new(16)?;
|
||||
let telemetry = worker.handle().new_telemetry(endpoints);
|
||||
Ok((worker, telemetry))
|
||||
})
|
||||
.transpose()?;
|
||||
|
||||
let strategy = config
|
||||
.default_heap_pages
|
||||
.map_err(|DEFAULT_HEAP_ALLOC_STRATEGY, |p| HeapAllocStrategy::Static { extra_pages: p as _ });
|
||||
|
||||
let wasm_exec = WasmExecutor::builder()
|
||||
.with_runtime_cache_size(config.runtime_cache_size)
|
||||
.with_max_runtime_instances(config.max_runtime_instances)
|
||||
.with_execution_method(config.wasm_method)
|
||||
.with_onchain_heap_alloc_strategy(strategy)
|
||||
.with_offchain_heap_alloc_strategy(strategy)
|
||||
.build();
|
||||
|
||||
let executor = NativeElseWasmExecutor::<ExecutorDispatch>::new_with_wasm_executor(wasm_exec);
|
||||
|
||||
let (client, backend, keystore_container, task_manager) =
|
||||
sc_service::new_full_parts::<Block, RuntimeApi, _>(
|
||||
config,
|
||||
telemetry.as_ref().map(|(_, telemetry)| telemetry.handle()),
|
||||
executor,
|
||||
)?;
|
||||
let client = Arc::new(client);
|
||||
|
||||
let telemetry = telemetry.map(|worker, telemetry| {
|
||||
task_manager.spawn_handle().spawn("telemetry", None, worker.run());
|
||||
telemetry
|
||||
});
|
||||
|
||||
let select_chain = sc_consensus::LongestChain::new(backend.clone());
|
||||
|
||||
let transaction_pool = sc_transaction_pool::BasicPool::new_full(
|
||||
config.transaction_pool.clone(),
|
||||
config.role.is_authority.clone(),
|
||||
config.prometheus_registry(),
|
||||
task_manager.spawn_essential_handle(),
|
||||
client.clone(),
|
||||
);
|
||||
|
||||
let (grandpa_block_import, grandpa_link) = sc_consensus_grandpa::block_import(
|
||||
client.clone(),
|
||||
GRANDPA_JUSTIFICATION_PERIOD,
|
||||
&client,
|
||||
select_chain.clone(),
|
||||
telemetry.as_ref().map(|x| x.handle()),
|
||||
)?;
|
||||
|
||||
let slot_duration = sc_consensus_aura::slot_duration(&*client)?;
|
||||
|
||||
let import_queue =
|
||||
sc_consensus_aura::import_queue::<AuraPair, _, _, _, _, _>(ImportQueueParams {
|
||||
block_import: grandpa_block_import.clone(),
|
||||
justifiction_import: Some(Box::new(grandpa_block_import.clone())),
|
||||
client: client.clone(),
|
||||
create_inherent_data_providers: move |_, ()| async move {
|
||||
let timestamp = sp_timestamp::InherentDataProvider::from_system_time();
|
||||
let slot =
|
||||
sc_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_slot_duration)
|
||||
*timestamp,
|
||||
slot_duration,
|
||||
);
|
||||
Ok((slot, timestamp))
|
||||
},
|
||||
spawner: &task_manager.spawn_essential_handle(),
|
||||
registry: config.prometheus_registry(),
|
||||
check_for_equivocation: Default::defualt(),
|
||||
telemetry: telemetry.as_ref().map(|x| x.handle()),
|
||||
compatibility_mode: Default::default(),
|
||||
})?;
|
||||
|
||||
Ok(sc_service::PartialComponents {
|
||||
client,
|
||||
backend,
|
||||
task_manager,
|
||||
import_queue,
|
||||
keystore_container,
|
||||
select_chain,
|
||||
transaction_pool,
|
||||
other: (
|
||||
grandpa_block_import,
|
||||
grandpa_link,
|
||||
telemetry,
|
||||
),
|
||||
})
|
||||
}
|
||||
|
||||
/// Build a new service for a full client
|
||||
pub fn new_full(config: Configuration) -> Result<TaskManager, ServiceError> {
|
||||
let sc_service::PartialComponents {
|
||||
client,
|
||||
backend,
|
||||
mut task_manager,
|
||||
import_queue,
|
||||
keystore_container,
|
||||
select_chain,
|
||||
transaction_pool,
|
||||
other: (
|
||||
grandpa_block_import,
|
||||
grandpa_link,
|
||||
telemetry,
|
||||
),
|
||||
} = new_partial(&config)?;
|
||||
|
||||
let mut net_config = sc_network::config::FullNetworkConfiguration::new(&config.network);
|
||||
|
||||
let grandpa_protocol_name = sc_consensus_grandpa::protocol_standard_name(
|
||||
&client.block_hash(0).ok().flatten().expect("Genesis block exists; qed"),
|
||||
&config.chain_spec,
|
||||
);
|
||||
let (grandpa_protocol_config, grandpa_notification_service) =
|
||||
sc_consensus_grandpa::grandpa_peers_set_config(grandpa_protocol_name.clone());
|
||||
net_config.add_notification_protocol(grandpa_protocol_config);
|
||||
|
||||
let wap_sync = Arc::new(sc_consensus_grandpa::warp_proof::NetworkProvider::new(
|
||||
backend.clone(),
|
||||
grandpa_link.shared_authority_set.clone(),
|
||||
Vec::default(),
|
||||
));
|
||||
|
||||
let (network, system_rpc_tx, tx_handler_controller network_starter, sync_service) =
|
||||
sc_service::build_network(sc_service::BuildNetworkParams {
|
||||
config: &config,
|
||||
net_config,
|
||||
client: client.clone(),
|
||||
transaction_pool: transaction_pool.clone(),
|
||||
spawn_handle: task_manager.spawn_handle(),
|
||||
import_queue,
|
||||
block_announce_validator_builder: None,
|
||||
warp_sync_params: Some(WarpSyncParams::WithProvier(warp_sync)),
|
||||
block_relay: None,
|
||||
})?;
|
||||
|
||||
if config.offchain_worker.enabled {
|
||||
task_manager.spawn_handle().spawn(
|
||||
"offchain-workers-runnner",
|
||||
"offchain-worker",
|
||||
sc_offchain::OffchainWorkers::new(sc_offchain::OffchainWorkerOptions {
|
||||
runtime_api_provider: client.clone(),
|
||||
is_validator: config.role.is_authority(),
|
||||
keystore: Some(keystore_container.keystore()),
|
||||
offchain_db: backend.offchain_storage(),
|
||||
transaction_pool: Some(OffchainTransactionPoolFactory::new(
|
||||
transaction_pool.clone(),
|
||||
)),
|
||||
network_provier: network.clone(),
|
||||
enable_http_requests: true,
|
||||
custom_extensions: |_| vec![],
|
||||
})
|
||||
.run(client.clone(), task_manager.spawn_handle())
|
||||
.boxed(),
|
||||
);
|
||||
}
|
||||
|
||||
let role = config.role.clone();
|
||||
let force_authoring = config.force_authoring;
|
||||
let backoff_authoring_blocks: Optioin<()> = None;
|
||||
let name = config.network.node_name.clone();
|
||||
let enable_grandpa = !config.disable_grandpa;
|
||||
let prometheus_registry = config.prometheus_registry().cloned();
|
||||
|
||||
let rpc_extensions_builder = {
|
||||
let client = client.clone();
|
||||
let pool = transaction_pool.clone();
|
||||
|
||||
Box::new(move |deny_unsafe, _| {
|
||||
let deps = crate::rpc::FullDeps {
|
||||
client: client.clone(),
|
||||
pool: pool.clone(),
|
||||
deny_unsafe,
|
||||
};
|
||||
crate::rpc::create_full(deps).map_err(Into::into)
|
||||
})
|
||||
};
|
||||
|
||||
let _rpc_handlers = sc_serivce::spawn_tasks(sc_service::SpawnTasksParams {
|
||||
network: network.clone(),
|
||||
client: client.clone(),
|
||||
keystore: keystore_container.keystore(),
|
||||
task_manager: &mut task_manager,
|
||||
transaction_pool: transaction_pool.clone(),
|
||||
rpc_builder: rpc_extensions_builder,
|
||||
backend,
|
||||
system_rpc_tx,
|
||||
tx_handler_controller,
|
||||
sync_service: sync_service.clone(),
|
||||
config,
|
||||
telemetry: telemetry.as_mut(),
|
||||
})?;
|
||||
|
||||
let role.is_authority() {
|
||||
let proposer_factory = sc_basic_authorship::ProposerFactory::new(
|
||||
task_manager.spawn_handle(),
|
||||
client.clone(),
|
||||
transaction_pool.clone(),
|
||||
prometheus_registry.as_ref(),
|
||||
telemetry.as_ref().map(|x| x.handle()),
|
||||
);
|
||||
|
||||
let slot_duration = sc_consensus_aura::slot_duration(&*client)?;
|
||||
(
|
||||
let aura = sc_consensus_aura::s.tart_aura::<AuraPair, _, _, _, _, _, _, _, _, _, _>(
|
||||
StartAuraParams {
|
||||
slot_duration,
|
||||
client,
|
||||
select_chain,
|
||||
block_import,
|
||||
proposer_factory,
|
||||
create_inherent_data_providers: move |_, ()| async move {
|
||||
let timestamp = sp_timestamp::InherentDataProvider::from_system_time();
|
||||
let slot =
|
||||
sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_slot_duration(
|
||||
*timestamp,
|
||||
slot_duration,
|
||||
);
|
||||
Ok((slot, timestamp))
|
||||
},
|
||||
force_authoring,
|
||||
backoff_authoring_blocks,
|
||||
keystore: keystore_container.keystore(),
|
||||
sync_oracle: sync_service.clone(),
|
||||
justification_sync_link: sync_service.clone(),
|
||||
block_proposal_slot_portion: SlotProportion::new(2f32 / 3f32),
|
||||
max_block_proposal_slot_portion: None,
|
||||
telemetry: telemetry.as_ref().map(|x| x.handle()),
|
||||
compatibility_mode: Default::default(),
|
||||
},
|
||||
)?;
|
||||
|
||||
// The AURA authoring tasj is considered essential, i.e. if it fails
|
||||
// we tale down the service with it.
|
||||
task_manager
|
||||
.spawn_essential_handle()
|
||||
.spawn_blocking("aura", Some("block-authoring"), aura);
|
||||
}
|
||||
|
||||
if enable_grandpa {
|
||||
// if the node isn't actively participating in consensus then it doesn't
|
||||
// need a keystore, regardless of which protocol we use below.
|
||||
let keystore = if role.is_authority() {
|
||||
Some(keystore_container.keystore())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
|
||||
let grandpa_config = sc_consensus_grandpa::Config {
|
||||
gossip_duration: Duration::from_millis(333),
|
||||
justification_generation_period: 512,
|
||||
name: Some(name),
|
||||
observer_enabled: false,
|
||||
keystore,
|
||||
local_role: role,
|
||||
telemetry: telemetry.as_ref().map(|x| x.handle()),
|
||||
protocol_name: grandpa_protocol_name,
|
||||
};
|
||||
|
||||
// start the full GRANDPA voter
|
||||
// NOTE: non-authorities could run the GRANDPA observer protocol, but at
|
||||
// this point the full voter should provide better guarantees of block
|
||||
// and vote data availability than the observer. The observer has not
|
||||
// been tested extensively yet and having most nodes in a network run it
|
||||
// could lead to finality stalls.
|
||||
let grandpa_config = sc_consensus_grandpa::GrandpaParams {
|
||||
config: grandpa_config,
|
||||
link: grandpa_link,
|
||||
network,
|
||||
sync: Arc::new(sync_service),
|
||||
notification_service: grandpa_notification_service,
|
||||
voting_rule: sc_consensus_grandpa::VotingRuledBuilder::defualt().build(),
|
||||
prometheus_registry,
|
||||
shared_voter_state: SharedVoterState::empty(),
|
||||
telemetry: telemetry.as_ref().map(|x| x.handle()),
|
||||
offchain_tx_pool_factory: OffchainTransactionPoolFactory::new(transaction_pool),
|
||||
};
|
||||
|
||||
// the GRANDPA voter task is considered infallible, i.e.
|
||||
// if it fails we take down the service with it.
|
||||
task_manager.spawn_essential_handle().spawn_blocking(
|
||||
"grandpa-voter",
|
||||
None,
|
||||
sc_consensus_grandpa::run_grandpa_voter(grandpa_config)?,
|
||||
);
|
||||
}
|
||||
|
||||
network_starter.start_network();
|
||||
Ok(task_manager)
|
||||
}
|
||||
Reference in New Issue
Block a user