mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-05-30 23:21:02 +00:00
Proof of concept: Add a new runtime that uses pallet_contracts (#186)
* seal: Copy over a legacy version of pallet_contracts from substrate * seal: Fix substrate dependency pathes and add as dependency to runtime * seal: Adapt pallet to current substrate version * seal: Add contracts pallet to runtime * seal: Implement rpc runtime api * seal: Update to latest rpc output format * seal: Replace child trie by prefix trie * seal: Add contracts endpoint to the client * seal: fixup rpc test * Fix whitespace issue Co-authored-by: Sergei Shulepov <sergei@parity.io> * seal: Move pallet out of the runtime directory * seal: Create a seperate runtime for contracts * Move parachains to top level directory * seal: Disable rent for easier testing Co-authored-by: Sergei Shulepov <sergei@parity.io>
This commit is contained in:
committed by
GitHub
parent
10533db948
commit
8a6e29eef9
@@ -0,0 +1,147 @@
|
||||
// Copyright 2019 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Cumulus.
|
||||
|
||||
// Cumulus is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
|
||||
// Cumulus is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Cumulus. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
use cumulus_primitives::ParaId;
|
||||
use parachain_runtime::{
|
||||
AccountId, BalancesConfig, GenesisConfig, Signature, SudoConfig, SystemConfig,
|
||||
TokenDealerConfig, WASM_BINARY,
|
||||
};
|
||||
use sc_chain_spec::{ChainSpecExtension, ChainSpecGroup};
|
||||
use sc_service::ChainType;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use sp_core::{sr25519, Pair, Public};
|
||||
use sp_runtime::traits::{IdentifyAccount, Verify};
|
||||
use hex_literal::hex;
|
||||
|
||||
/// Specialized `ChainSpec`. This is a specialization of the general Substrate ChainSpec type.
|
||||
pub type ChainSpec = sc_service::GenericChainSpec<GenesisConfig, Extensions>;
|
||||
|
||||
/// Helper function to 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()
|
||||
}
|
||||
|
||||
/// The extensions for the [`ChainSpec`].
|
||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, ChainSpecGroup, ChainSpecExtension)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct Extensions {
|
||||
/// The relay chain of the Parachain.
|
||||
pub relay_chain: String,
|
||||
/// The id of the Parachain.
|
||||
pub para_id: u32,
|
||||
}
|
||||
|
||||
impl Extensions {
|
||||
/// Try to get the extension from the given `ChainSpec`.
|
||||
pub fn try_get(chain_spec: &Box<dyn sc_service::ChainSpec>) -> Option<&Self> {
|
||||
sc_chain_spec::get_extension(chain_spec.extensions())
|
||||
}
|
||||
}
|
||||
|
||||
type AccountPublic = <Signature as Verify>::Signer;
|
||||
|
||||
/// Helper function to generate an account ID 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()
|
||||
}
|
||||
|
||||
pub fn get_chain_spec(id: ParaId) -> ChainSpec {
|
||||
ChainSpec::from_genesis(
|
||||
"Local Testnet",
|
||||
"local_testnet",
|
||||
ChainType::Local,
|
||||
move || {
|
||||
testnet_genesis(
|
||||
get_account_id_from_seed::<sr25519::Public>("Alice"),
|
||||
vec![
|
||||
get_account_id_from_seed::<sr25519::Public>("Alice"),
|
||||
get_account_id_from_seed::<sr25519::Public>("Bob"),
|
||||
get_account_id_from_seed::<sr25519::Public>("Charlie"),
|
||||
get_account_id_from_seed::<sr25519::Public>("Dave"),
|
||||
get_account_id_from_seed::<sr25519::Public>("Eve"),
|
||||
get_account_id_from_seed::<sr25519::Public>("Ferdie"),
|
||||
get_account_id_from_seed::<sr25519::Public>("Alice//stash"),
|
||||
get_account_id_from_seed::<sr25519::Public>("Bob//stash"),
|
||||
get_account_id_from_seed::<sr25519::Public>("Charlie//stash"),
|
||||
get_account_id_from_seed::<sr25519::Public>("Dave//stash"),
|
||||
get_account_id_from_seed::<sr25519::Public>("Eve//stash"),
|
||||
get_account_id_from_seed::<sr25519::Public>("Ferdie//stash"),
|
||||
],
|
||||
id,
|
||||
)
|
||||
},
|
||||
vec![],
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
Extensions {
|
||||
relay_chain: "westend-dev".into(),
|
||||
para_id: id.into(),
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
pub fn staging_test_net(id: ParaId) -> ChainSpec {
|
||||
ChainSpec::from_genesis(
|
||||
"Staging Testnet",
|
||||
"staging_testnet",
|
||||
ChainType::Live,
|
||||
move || {
|
||||
testnet_genesis(
|
||||
hex!["9ed7705e3c7da027ba0583a22a3212042f7e715d3c168ba14f1424e2bc111d00"].into(),
|
||||
vec![hex!["9ed7705e3c7da027ba0583a22a3212042f7e715d3c168ba14f1424e2bc111d00"].into()],
|
||||
id,
|
||||
)
|
||||
},
|
||||
Vec::new(),
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
Extensions {
|
||||
relay_chain: "westend-dev".into(),
|
||||
para_id: id.into(),
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
fn testnet_genesis(
|
||||
root_key: AccountId,
|
||||
endowed_accounts: Vec<AccountId>,
|
||||
id: ParaId,
|
||||
) -> GenesisConfig {
|
||||
GenesisConfig {
|
||||
frame_system: Some(SystemConfig {
|
||||
code: WASM_BINARY.expect("WASM binary was not build, please build it!").to_vec(),
|
||||
changes_trie_config: Default::default(),
|
||||
}),
|
||||
pallet_balances: Some(BalancesConfig {
|
||||
balances: endowed_accounts
|
||||
.iter()
|
||||
.cloned()
|
||||
.map(|k| (k, 1 << 60))
|
||||
.collect(),
|
||||
}),
|
||||
pallet_sudo: Some(SudoConfig { key: root_key }),
|
||||
message_example: Some(TokenDealerConfig { parachain_id: id }),
|
||||
// TODO: add contracts genesis for the contracts runtime
|
||||
// pallet_contracts: Some(parachain_runtime::ContractsConfig { current_schedule: Default::default() }),
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,126 @@
|
||||
// Copyright 2019 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Cumulus.
|
||||
|
||||
// Cumulus is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
|
||||
// Cumulus is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Cumulus. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
use std::path::PathBuf;
|
||||
|
||||
use sc_cli;
|
||||
use structopt::StructOpt;
|
||||
|
||||
/// Sub-commands supported by the collator.
|
||||
#[derive(Debug, StructOpt)]
|
||||
pub enum Subcommand {
|
||||
#[structopt(flatten)]
|
||||
Base(sc_cli::Subcommand),
|
||||
|
||||
/// Export the genesis state of the parachain.
|
||||
#[structopt(name = "export-genesis-state")]
|
||||
ExportGenesisState(ExportGenesisStateCommand),
|
||||
|
||||
/// Export the genesis wasm of the parachain.
|
||||
#[structopt(name = "export-genesis-wasm")]
|
||||
ExportGenesisWasm(ExportGenesisWasmCommand),
|
||||
}
|
||||
|
||||
/// Command for exporting the genesis state of the parachain
|
||||
#[derive(Debug, StructOpt)]
|
||||
pub struct ExportGenesisStateCommand {
|
||||
/// Output file name or stdout if unspecified.
|
||||
#[structopt(parse(from_os_str))]
|
||||
pub output: Option<PathBuf>,
|
||||
|
||||
/// Id of the parachain this state is for.
|
||||
#[structopt(long, default_value = "100")]
|
||||
pub parachain_id: u32,
|
||||
|
||||
/// The name of the chain for that the genesis state should be exported.
|
||||
#[structopt(long)]
|
||||
pub chain: Option<String>,
|
||||
}
|
||||
|
||||
/// Command for exporting the genesis wasm file.
|
||||
#[derive(Debug, StructOpt)]
|
||||
pub struct ExportGenesisWasmCommand {
|
||||
/// Output file name or stdout if unspecified.
|
||||
#[structopt(parse(from_os_str))]
|
||||
pub output: Option<PathBuf>,
|
||||
|
||||
/// The name of the chain for that the genesis wasm file should be exported.
|
||||
#[structopt(long)]
|
||||
pub chain: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Debug, StructOpt)]
|
||||
pub struct RunCmd {
|
||||
#[structopt(flatten)]
|
||||
pub base: sc_cli::RunCmd,
|
||||
|
||||
/// Id of the parachain this collator collates for.
|
||||
#[structopt(long)]
|
||||
pub parachain_id: Option<u32>,
|
||||
}
|
||||
|
||||
impl std::ops::Deref for RunCmd {
|
||||
type Target = sc_cli::RunCmd;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.base
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, StructOpt)]
|
||||
#[structopt(settings = &[
|
||||
structopt::clap::AppSettings::GlobalVersion,
|
||||
structopt::clap::AppSettings::ArgsNegateSubcommands,
|
||||
structopt::clap::AppSettings::SubcommandsNegateReqs,
|
||||
])]
|
||||
pub struct Cli {
|
||||
#[structopt(subcommand)]
|
||||
pub subcommand: Option<Subcommand>,
|
||||
|
||||
#[structopt(flatten)]
|
||||
pub run: RunCmd,
|
||||
|
||||
/// Relaychain arguments
|
||||
#[structopt(raw = true)]
|
||||
pub relaychain_args: Vec<String>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct RelayChainCli {
|
||||
/// The actual relay chain cli object.
|
||||
pub base: polkadot_cli::RunCmd,
|
||||
|
||||
/// Optional chain id that should be passed to the relay chain.
|
||||
pub chain_id: Option<String>,
|
||||
|
||||
/// The base path that should be used by the relay chain.
|
||||
pub base_path: Option<PathBuf>,
|
||||
}
|
||||
|
||||
impl RelayChainCli {
|
||||
/// Create a new instance of `Self`.
|
||||
pub fn new<'a>(
|
||||
base_path: Option<PathBuf>,
|
||||
chain_id: Option<String>,
|
||||
relay_chain_args: impl Iterator<Item = &'a String>,
|
||||
) -> Self {
|
||||
Self {
|
||||
base_path,
|
||||
chain_id,
|
||||
base: polkadot_cli::RunCmd::from_iter(relay_chain_args),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,451 @@
|
||||
// Copyright 2019 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Cumulus.
|
||||
|
||||
// Cumulus is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
|
||||
// Cumulus is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Cumulus. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
use crate::{
|
||||
chain_spec,
|
||||
cli::{Cli, RelayChainCli, Subcommand},
|
||||
};
|
||||
use codec::Encode;
|
||||
use cumulus_primitives::ParaId;
|
||||
use log::info;
|
||||
use parachain_runtime::Block;
|
||||
use polkadot_parachain::primitives::AccountIdConversion;
|
||||
use sc_cli::{
|
||||
ChainSpec, CliConfiguration, Error, ImportParams, KeystoreParams, NetworkParams, Result,
|
||||
RuntimeVersion, SharedParams, SubstrateCli,
|
||||
};
|
||||
use sc_service::config::{BasePath, PrometheusConfig};
|
||||
use sp_core::hexdisplay::HexDisplay;
|
||||
use sp_runtime::traits::{Block as BlockT, Hash as HashT, Header as HeaderT, Zero};
|
||||
use std::{io::Write, net::SocketAddr, sync::Arc};
|
||||
|
||||
impl SubstrateCli for Cli {
|
||||
fn impl_name() -> String {
|
||||
"Cumulus Test Parachain Collator".into()
|
||||
}
|
||||
|
||||
fn impl_version() -> String {
|
||||
env!("SUBSTRATE_CLI_IMPL_VERSION").into()
|
||||
}
|
||||
|
||||
fn description() -> String {
|
||||
format!(
|
||||
"Cumulus test parachain collator\n\nThe command-line arguments provided first will be \
|
||||
passed to the parachain node, while the arguments provided after -- will be passed \
|
||||
to the relaychain node.\n\n\
|
||||
{} [parachain-args] -- [relaychain-args]",
|
||||
Self::executable_name()
|
||||
)
|
||||
}
|
||||
|
||||
fn author() -> String {
|
||||
env!("CARGO_PKG_AUTHORS").into()
|
||||
}
|
||||
|
||||
fn support_url() -> String {
|
||||
"https://github.com/paritytech/cumulus/issues/new".into()
|
||||
}
|
||||
|
||||
fn copyright_start_year() -> i32 {
|
||||
2017
|
||||
}
|
||||
|
||||
fn load_spec(&self, id: &str) -> std::result::Result<Box<dyn sc_service::ChainSpec>, String> {
|
||||
match id {
|
||||
"staging" => Ok(Box::new(chain_spec::staging_test_net(
|
||||
self.run.parachain_id.unwrap_or(100).into(),
|
||||
))),
|
||||
"tick" => Ok(Box::new(chain_spec::ChainSpec::from_json_bytes(
|
||||
&include_bytes!("../res/tick.json")[..],
|
||||
)?)),
|
||||
"trick" => Ok(Box::new(chain_spec::ChainSpec::from_json_bytes(
|
||||
&include_bytes!("../res/trick.json")[..],
|
||||
)?)),
|
||||
"track" => Ok(Box::new(chain_spec::ChainSpec::from_json_bytes(
|
||||
&include_bytes!("../res/track.json")[..],
|
||||
)?)),
|
||||
"" => Ok(Box::new(chain_spec::get_chain_spec(
|
||||
self.run.parachain_id.unwrap_or(100).into(),
|
||||
))),
|
||||
path => Ok(Box::new(chain_spec::ChainSpec::from_json_file(
|
||||
path.into(),
|
||||
)?)),
|
||||
}
|
||||
}
|
||||
|
||||
fn native_runtime_version(_: &Box<dyn ChainSpec>) -> &'static RuntimeVersion {
|
||||
¶chain_runtime::VERSION
|
||||
}
|
||||
}
|
||||
|
||||
impl SubstrateCli for RelayChainCli {
|
||||
fn impl_name() -> String {
|
||||
"Cumulus Test Parachain Collator".into()
|
||||
}
|
||||
|
||||
fn impl_version() -> String {
|
||||
env!("SUBSTRATE_CLI_IMPL_VERSION").into()
|
||||
}
|
||||
|
||||
fn description() -> String {
|
||||
"Cumulus test parachain collator\n\nThe command-line arguments provided first will be \
|
||||
passed to the parachain node, while the arguments provided after -- will be passed \
|
||||
to the relaychain node.\n\n\
|
||||
rococo-collator [parachain-args] -- [relaychain-args]"
|
||||
.into()
|
||||
}
|
||||
|
||||
fn author() -> String {
|
||||
env!("CARGO_PKG_AUTHORS").into()
|
||||
}
|
||||
|
||||
fn support_url() -> String {
|
||||
"https://github.com/paritytech/cumulus/issues/new".into()
|
||||
}
|
||||
|
||||
fn copyright_start_year() -> i32 {
|
||||
2017
|
||||
}
|
||||
|
||||
fn load_spec(&self, id: &str) -> std::result::Result<Box<dyn sc_service::ChainSpec>, String> {
|
||||
polkadot_cli::Cli::from_iter([RelayChainCli::executable_name().to_string()].iter())
|
||||
.load_spec(id)
|
||||
}
|
||||
|
||||
fn native_runtime_version(chain_spec: &Box<dyn ChainSpec>) -> &'static RuntimeVersion {
|
||||
polkadot_cli::Cli::native_runtime_version(chain_spec)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn generate_genesis_state(chain_spec: &Box<dyn sc_service::ChainSpec>) -> Result<Block> {
|
||||
let storage = chain_spec.build_storage()?;
|
||||
|
||||
let child_roots = storage.children_default.iter().map(|(sk, child_content)| {
|
||||
let state_root = <<<Block as BlockT>::Header as HeaderT>::Hashing as HashT>::trie_root(
|
||||
child_content.data.clone().into_iter().collect(),
|
||||
);
|
||||
(sk.clone(), state_root.encode())
|
||||
});
|
||||
let state_root = <<<Block as BlockT>::Header as HeaderT>::Hashing as HashT>::trie_root(
|
||||
storage.top.clone().into_iter().chain(child_roots).collect(),
|
||||
);
|
||||
|
||||
let extrinsics_root =
|
||||
<<<Block as BlockT>::Header as HeaderT>::Hashing as HashT>::trie_root(Vec::new());
|
||||
|
||||
Ok(Block::new(
|
||||
<<Block as BlockT>::Header as HeaderT>::new(
|
||||
Zero::zero(),
|
||||
extrinsics_root,
|
||||
state_root,
|
||||
Default::default(),
|
||||
Default::default(),
|
||||
),
|
||||
Default::default(),
|
||||
))
|
||||
}
|
||||
|
||||
fn extract_genesis_wasm(chain_spec: &Box<dyn sc_service::ChainSpec>) -> Result<Vec<u8>> {
|
||||
let mut storage = chain_spec.build_storage()?;
|
||||
|
||||
storage
|
||||
.top
|
||||
.remove(sp_core::storage::well_known_keys::CODE)
|
||||
.ok_or_else(|| "Could not find wasm file in genesis state!".into())
|
||||
}
|
||||
|
||||
/// Parse command line arguments into service configuration.
|
||||
pub fn run() -> Result<()> {
|
||||
let cli = Cli::from_args();
|
||||
|
||||
match &cli.subcommand {
|
||||
Some(Subcommand::Base(subcommand)) => {
|
||||
let runner = cli.create_runner(subcommand)?;
|
||||
|
||||
runner.run_subcommand(subcommand, |mut config| {
|
||||
let params = crate::service::new_partial(&mut config)?;
|
||||
|
||||
Ok((
|
||||
params.client,
|
||||
params.backend,
|
||||
params.import_queue,
|
||||
params.task_manager,
|
||||
))
|
||||
})
|
||||
}
|
||||
Some(Subcommand::ExportGenesisState(params)) => {
|
||||
sc_cli::init_logger("");
|
||||
|
||||
let block =
|
||||
generate_genesis_state(&cli.load_spec(¶ms.chain.clone().unwrap_or_default())?)?;
|
||||
let header_hex = format!("0x{:?}", HexDisplay::from(&block.header().encode()));
|
||||
|
||||
if let Some(output) = ¶ms.output {
|
||||
std::fs::write(output, header_hex)?;
|
||||
} else {
|
||||
println!("{}", header_hex);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
Some(Subcommand::ExportGenesisWasm(params)) => {
|
||||
sc_cli::init_logger("");
|
||||
|
||||
let wasm_file =
|
||||
extract_genesis_wasm(&cli.load_spec(¶ms.chain.clone().unwrap_or_default())?)?;
|
||||
|
||||
if let Some(output) = ¶ms.output {
|
||||
std::fs::write(output, wasm_file)?;
|
||||
} else {
|
||||
std::io::stdout().write_all(&wasm_file)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
None => {
|
||||
let runner = cli.create_runner(&*cli.run)?;
|
||||
|
||||
runner.run_node_until_exit(|config| {
|
||||
// TODO
|
||||
let key = Arc::new(sp_core::Pair::generate().0);
|
||||
|
||||
let extension = chain_spec::Extensions::try_get(&config.chain_spec);
|
||||
let relay_chain_id = extension.map(|e| e.relay_chain.clone());
|
||||
let para_id = extension.map(|e| e.para_id);
|
||||
|
||||
let polkadot_cli = RelayChainCli::new(
|
||||
config.base_path.as_ref().map(|x| x.path().join("polkadot")),
|
||||
relay_chain_id,
|
||||
[RelayChainCli::executable_name().to_string()]
|
||||
.iter()
|
||||
.chain(cli.relaychain_args.iter()),
|
||||
);
|
||||
|
||||
let id = ParaId::from(cli.run.parachain_id.or(para_id).unwrap_or(100));
|
||||
|
||||
let parachain_account =
|
||||
AccountIdConversion::<polkadot_primitives::v0::AccountId>::into_account(&id);
|
||||
|
||||
let block =
|
||||
generate_genesis_state(&config.chain_spec).map_err(|e| format!("{:?}", e))?;
|
||||
let genesis_state = format!("0x{:?}", HexDisplay::from(&block.header().encode()));
|
||||
|
||||
let task_executor = config.task_executor.clone();
|
||||
let polkadot_config =
|
||||
SubstrateCli::create_configuration(&polkadot_cli, &polkadot_cli, task_executor)
|
||||
.map_err(|err| format!("Relay chain argument error: {}", err))?;
|
||||
|
||||
info!("Parachain id: {:?}", id);
|
||||
info!("Parachain Account: {}", parachain_account);
|
||||
info!("Parachain genesis state: {}", genesis_state);
|
||||
info!(
|
||||
"Is collating: {}",
|
||||
if cli.run.base.validator { "yes" } else { "no" }
|
||||
);
|
||||
|
||||
crate::service::run_collator(
|
||||
config,
|
||||
key,
|
||||
polkadot_config,
|
||||
id,
|
||||
cli.run.base.validator,
|
||||
)
|
||||
.map(|(x, _)| x)
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl CliConfiguration for RelayChainCli {
|
||||
fn shared_params(&self) -> &SharedParams {
|
||||
self.base.base.shared_params()
|
||||
}
|
||||
|
||||
fn import_params(&self) -> Option<&ImportParams> {
|
||||
self.base.base.import_params()
|
||||
}
|
||||
|
||||
fn network_params(&self) -> Option<&NetworkParams> {
|
||||
self.base.base.network_params()
|
||||
}
|
||||
|
||||
fn keystore_params(&self) -> Option<&KeystoreParams> {
|
||||
self.base.base.keystore_params()
|
||||
}
|
||||
|
||||
fn base_path(&self) -> Result<Option<BasePath>> {
|
||||
Ok(self
|
||||
.shared_params()
|
||||
.base_path()
|
||||
.or_else(|| self.base_path.clone().map(Into::into)))
|
||||
}
|
||||
|
||||
fn rpc_http(&self) -> Result<Option<SocketAddr>> {
|
||||
let rpc_external = self.base.base.rpc_external;
|
||||
let unsafe_rpc_external = self.base.base.unsafe_rpc_external;
|
||||
let validator = self.base.base.validator;
|
||||
let rpc_port = self.base.base.rpc_port;
|
||||
// copied directly from substrate
|
||||
let rpc_interface: &str = interface_str(rpc_external, unsafe_rpc_external, validator)?;
|
||||
|
||||
Ok(Some(parse_address(
|
||||
&format!("{}:{}", rpc_interface, 9934),
|
||||
rpc_port,
|
||||
)?))
|
||||
}
|
||||
|
||||
fn rpc_ipc(&self) -> Result<Option<String>> {
|
||||
self.base.base.rpc_ipc()
|
||||
}
|
||||
|
||||
fn rpc_ws(&self) -> Result<Option<SocketAddr>> {
|
||||
let ws_external = self.base.base.ws_external;
|
||||
let unsafe_ws_external = self.base.base.unsafe_ws_external;
|
||||
let validator = self.base.base.validator;
|
||||
let ws_port = self.base.base.ws_port;
|
||||
// copied directly from substrate
|
||||
let ws_interface: &str = interface_str(ws_external, unsafe_ws_external, validator)?;
|
||||
|
||||
Ok(Some(parse_address(
|
||||
&format!("{}:{}", ws_interface, 9945),
|
||||
ws_port,
|
||||
)?))
|
||||
}
|
||||
|
||||
fn prometheus_config(&self) -> Result<Option<PrometheusConfig>> {
|
||||
let no_prometheus = self.base.base.no_prometheus;
|
||||
let prometheus_external = self.base.base.prometheus_external;
|
||||
let prometheus_port = self.base.base.prometheus_port;
|
||||
|
||||
if no_prometheus {
|
||||
Ok(None)
|
||||
} else {
|
||||
let prometheus_interface: &str = if prometheus_external {
|
||||
"0.0.0.0"
|
||||
} else {
|
||||
"127.0.0.1"
|
||||
};
|
||||
|
||||
Ok(Some(PrometheusConfig::new_with_default_registry(
|
||||
parse_address(
|
||||
&format!("{}:{}", prometheus_interface, 9616),
|
||||
prometheus_port,
|
||||
)?,
|
||||
)))
|
||||
}
|
||||
}
|
||||
|
||||
fn init<C: SubstrateCli>(&self) -> Result<()> {
|
||||
unreachable!("PolkadotCli is never initialized; qed");
|
||||
}
|
||||
|
||||
fn chain_id(&self, is_dev: bool) -> Result<String> {
|
||||
let chain_id = self.base.base.chain_id(is_dev)?;
|
||||
|
||||
Ok(if chain_id.is_empty() {
|
||||
self.chain_id.clone().unwrap_or_default()
|
||||
} else {
|
||||
chain_id
|
||||
})
|
||||
}
|
||||
|
||||
fn role(&self, is_dev: bool) -> Result<sc_service::Role> {
|
||||
self.base.base.role(is_dev)
|
||||
}
|
||||
|
||||
fn transaction_pool(&self) -> Result<sc_service::config::TransactionPoolOptions> {
|
||||
self.base.base.transaction_pool()
|
||||
}
|
||||
|
||||
fn state_cache_child_ratio(&self) -> Result<Option<usize>> {
|
||||
self.base.base.state_cache_child_ratio()
|
||||
}
|
||||
|
||||
fn rpc_methods(&self) -> Result<sc_service::config::RpcMethods> {
|
||||
self.base.base.rpc_methods()
|
||||
}
|
||||
|
||||
fn rpc_ws_max_connections(&self) -> Result<Option<usize>> {
|
||||
self.base.base.rpc_ws_max_connections()
|
||||
}
|
||||
|
||||
fn rpc_cors(&self, is_dev: bool) -> Result<Option<Vec<String>>> {
|
||||
self.base.base.rpc_cors(is_dev)
|
||||
}
|
||||
|
||||
fn telemetry_external_transport(&self) -> Result<Option<sc_service::config::ExtTransport>> {
|
||||
self.base.base.telemetry_external_transport()
|
||||
}
|
||||
|
||||
fn default_heap_pages(&self) -> Result<Option<u64>> {
|
||||
self.base.base.default_heap_pages()
|
||||
}
|
||||
|
||||
fn force_authoring(&self) -> Result<bool> {
|
||||
self.base.base.force_authoring()
|
||||
}
|
||||
|
||||
fn disable_grandpa(&self) -> Result<bool> {
|
||||
self.base.base.disable_grandpa()
|
||||
}
|
||||
|
||||
fn max_runtime_instances(&self) -> Result<Option<usize>> {
|
||||
self.base.base.max_runtime_instances()
|
||||
}
|
||||
|
||||
fn announce_block(&self) -> Result<bool> {
|
||||
self.base.base.announce_block()
|
||||
}
|
||||
}
|
||||
|
||||
// copied directly from substrate
|
||||
fn parse_address(address: &str, port: Option<u16>) -> std::result::Result<SocketAddr, String> {
|
||||
let mut address: SocketAddr = address
|
||||
.parse()
|
||||
.map_err(|_| format!("Invalid address: {}", address))?;
|
||||
if let Some(port) = port {
|
||||
address.set_port(port);
|
||||
}
|
||||
|
||||
Ok(address)
|
||||
}
|
||||
|
||||
// copied directly from substrate
|
||||
fn interface_str(
|
||||
is_external: bool,
|
||||
is_unsafe_external: bool,
|
||||
is_validator: bool,
|
||||
) -> Result<&'static str> {
|
||||
if is_external && is_validator {
|
||||
return Err(Error::Input(
|
||||
"--rpc-external and --ws-external options shouldn't be \
|
||||
used if the node is running as a validator. Use `--unsafe-rpc-external` if you understand \
|
||||
the risks. See the options description for more information."
|
||||
.to_owned(),
|
||||
));
|
||||
}
|
||||
|
||||
if is_external || is_unsafe_external {
|
||||
log::warn!(
|
||||
"It isn't safe to expose RPC publicly without a proxy server that filters \
|
||||
available set of RPC methods."
|
||||
);
|
||||
|
||||
Ok("0.0.0.0")
|
||||
} else {
|
||||
Ok("127.0.0.1")
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,212 @@
|
||||
// Copyright 2020 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Substrate.
|
||||
|
||||
// Substrate is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
|
||||
// Substrate is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Substrate. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
use codec::Encode;
|
||||
use futures::{
|
||||
future::{self, FutureExt},
|
||||
pin_mut, select,
|
||||
};
|
||||
use polkadot_primitives::v0::{Id as ParaId, Info, Scheduling};
|
||||
use polkadot_runtime_common::registrar;
|
||||
use polkadot_test_runtime_client::Sr25519Keyring;
|
||||
use sc_client_api::execution_extensions::ExecutionStrategies;
|
||||
use sc_informant::OutputFormat;
|
||||
use sc_network::{config::TransportConfig, multiaddr};
|
||||
use sc_service::{
|
||||
config::{
|
||||
DatabaseConfig, KeystoreConfig, MultiaddrWithPeerId, NetworkConfiguration,
|
||||
WasmExecutionMethod,
|
||||
},
|
||||
BasePath, Configuration, Error as ServiceError, Role, TaskExecutor,
|
||||
};
|
||||
use std::{sync::Arc, time::Duration};
|
||||
use substrate_test_client::BlockchainEventsExt;
|
||||
use substrate_test_runtime_client::AccountKeyring::*;
|
||||
use tokio::{spawn, time::delay_for as sleep};
|
||||
|
||||
static INTEGRATION_TEST_ALLOWED_TIME: Option<&str> = option_env!("INTEGRATION_TEST_ALLOWED_TIME");
|
||||
|
||||
#[tokio::test]
|
||||
#[ignore]
|
||||
async fn integration_test() {
|
||||
let task_executor: TaskExecutor = (|fut, _| spawn(fut).map(|_| ())).into();
|
||||
|
||||
// start alice
|
||||
let mut alice =
|
||||
polkadot_test_service::run_test_node(task_executor.clone(), Alice, || {}, vec![]);
|
||||
|
||||
// start bob
|
||||
let mut bob = polkadot_test_service::run_test_node(
|
||||
task_executor.clone(),
|
||||
Bob,
|
||||
|| {},
|
||||
vec![alice.addr.clone()],
|
||||
);
|
||||
|
||||
let t1 = sleep(Duration::from_secs(
|
||||
INTEGRATION_TEST_ALLOWED_TIME
|
||||
.and_then(|x| x.parse().ok())
|
||||
.unwrap_or(600),
|
||||
)).fuse();
|
||||
|
||||
let t2 = async {
|
||||
let para_id = ParaId::from(100);
|
||||
|
||||
future::join(alice.wait_for_blocks(2), bob.wait_for_blocks(2)).await;
|
||||
|
||||
// export genesis state
|
||||
let spec = crate::chain_spec::get_chain_spec(para_id);
|
||||
let genesis_state = crate::command::generate_genesis_state(&(Box::new(spec) as Box<_>))
|
||||
.unwrap()
|
||||
.encode();
|
||||
|
||||
// create and sign transaction
|
||||
let function = polkadot_test_runtime::Call::Sudo(pallet_sudo::Call::sudo(Box::new(
|
||||
polkadot_test_runtime::Call::Registrar(registrar::Call::register_para(
|
||||
para_id,
|
||||
Info {
|
||||
scheduling: Scheduling::Always,
|
||||
},
|
||||
parachain_runtime::WASM_BINARY
|
||||
.expect("You need to build the WASM binary to run this test!")
|
||||
.to_vec()
|
||||
.into(),
|
||||
genesis_state.into(),
|
||||
)),
|
||||
)));
|
||||
|
||||
// register parachain
|
||||
let _ = alice.call_function(function, Alice).await.unwrap();
|
||||
|
||||
// run cumulus charlie
|
||||
let key = Arc::new(sp_core::Pair::from_seed(&[10; 32]));
|
||||
let mut polkadot_config = polkadot_test_service::node_config(
|
||||
|| {},
|
||||
task_executor.clone(),
|
||||
Charlie,
|
||||
vec![alice.addr.clone(), bob.addr.clone()],
|
||||
);
|
||||
use std::net::{Ipv4Addr, SocketAddr};
|
||||
polkadot_config.rpc_http = Some(SocketAddr::new(Ipv4Addr::LOCALHOST.into(), 27016));
|
||||
polkadot_config.rpc_methods = sc_service::config::RpcMethods::Unsafe;
|
||||
let parachain_config =
|
||||
parachain_config(task_executor.clone(), Charlie, vec![], para_id).unwrap();
|
||||
let (_service, charlie_client) =
|
||||
crate::service::run_collator(parachain_config, key, polkadot_config, para_id, true)
|
||||
.unwrap();
|
||||
sleep(Duration::from_secs(3)).await;
|
||||
charlie_client.wait_for_blocks(4).await;
|
||||
|
||||
alice.task_manager.terminate();
|
||||
bob.task_manager.terminate();
|
||||
}
|
||||
.fuse();
|
||||
|
||||
pin_mut!(t1, t2);
|
||||
|
||||
select! {
|
||||
_ = t1 => {
|
||||
panic!("the test took too long, maybe no parachain blocks have been produced");
|
||||
},
|
||||
_ = t2 => {},
|
||||
}
|
||||
}
|
||||
|
||||
pub fn parachain_config(
|
||||
task_executor: TaskExecutor,
|
||||
key: Sr25519Keyring,
|
||||
boot_nodes: Vec<MultiaddrWithPeerId>,
|
||||
para_id: ParaId,
|
||||
) -> Result<Configuration, ServiceError> {
|
||||
let base_path = BasePath::new_temp_dir()?;
|
||||
let root = base_path.path().to_path_buf();
|
||||
let role = Role::Authority {
|
||||
sentry_nodes: Vec::new(),
|
||||
};
|
||||
let key_seed = key.to_seed();
|
||||
let spec = crate::chain_spec::get_chain_spec(para_id);
|
||||
|
||||
let mut network_config = NetworkConfiguration::new(
|
||||
format!("Cumulus Test Node for: {}", key_seed),
|
||||
"network/test/0.1",
|
||||
Default::default(),
|
||||
None,
|
||||
);
|
||||
let informant_output_format = OutputFormat {
|
||||
enable_color: false,
|
||||
prefix: format!("[{}] ", key_seed),
|
||||
};
|
||||
|
||||
network_config.boot_nodes = boot_nodes;
|
||||
|
||||
network_config.allow_non_globals_in_dht = true;
|
||||
|
||||
network_config
|
||||
.listen_addresses
|
||||
.push(multiaddr::Protocol::Memory(rand::random()).into());
|
||||
|
||||
network_config.transport = TransportConfig::MemoryOnly;
|
||||
|
||||
Ok(Configuration {
|
||||
impl_name: "cumulus-test-node".to_string(),
|
||||
impl_version: "0.1".to_string(),
|
||||
role,
|
||||
task_executor,
|
||||
transaction_pool: Default::default(),
|
||||
network: network_config,
|
||||
keystore: KeystoreConfig::Path {
|
||||
path: root.join("key"),
|
||||
password: None,
|
||||
},
|
||||
database: DatabaseConfig::RocksDb {
|
||||
path: root.join("db"),
|
||||
cache_size: 128,
|
||||
},
|
||||
state_cache_size: 16777216,
|
||||
state_cache_child_ratio: None,
|
||||
pruning: Default::default(),
|
||||
chain_spec: Box::new(spec),
|
||||
wasm_method: WasmExecutionMethod::Interpreted,
|
||||
// NOTE: we enforce the use of the native runtime to make the errors more debuggable
|
||||
execution_strategies: ExecutionStrategies {
|
||||
syncing: sc_client_api::ExecutionStrategy::NativeWhenPossible,
|
||||
importing: sc_client_api::ExecutionStrategy::NativeWhenPossible,
|
||||
block_construction: sc_client_api::ExecutionStrategy::NativeWhenPossible,
|
||||
offchain_worker: sc_client_api::ExecutionStrategy::NativeWhenPossible,
|
||||
other: sc_client_api::ExecutionStrategy::NativeWhenPossible,
|
||||
},
|
||||
rpc_http: None,
|
||||
rpc_ws: None,
|
||||
rpc_ipc: None,
|
||||
rpc_ws_max_connections: None,
|
||||
rpc_cors: None,
|
||||
rpc_methods: Default::default(),
|
||||
prometheus_config: None,
|
||||
telemetry_endpoints: None,
|
||||
telemetry_external_transport: None,
|
||||
default_heap_pages: None,
|
||||
offchain_worker: Default::default(),
|
||||
force_authoring: false,
|
||||
disable_grandpa: false,
|
||||
dev_key_seed: Some(key_seed),
|
||||
tracing_targets: None,
|
||||
tracing_receiver: Default::default(),
|
||||
max_runtime_instances: 8,
|
||||
announce_block: true,
|
||||
base_path: Some(base_path),
|
||||
informant_output_format,
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
// Copyright 2019 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Cumulus.
|
||||
|
||||
// Cumulus is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
|
||||
// Cumulus is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Cumulus. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//! Cumulus test parachain collator
|
||||
|
||||
#![warn(missing_docs)]
|
||||
#![warn(unused_extern_crates)]
|
||||
|
||||
mod chain_spec;
|
||||
#[macro_use]
|
||||
mod service;
|
||||
mod cli;
|
||||
mod command;
|
||||
#[cfg(test)]
|
||||
mod integration_test;
|
||||
|
||||
fn main() -> sc_cli::Result<()> {
|
||||
command::run()
|
||||
}
|
||||
@@ -0,0 +1,269 @@
|
||||
// Copyright 2019 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Cumulus.
|
||||
|
||||
// Cumulus is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
|
||||
// Cumulus is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Cumulus. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
use ansi_term::Color;
|
||||
use cumulus_collator::{prepare_collator_config, CollatorBuilder};
|
||||
use cumulus_network::{DelayedBlockAnnounceValidator, JustifiedBlockAnnounceValidator};
|
||||
use polkadot_primitives::v0::{CollatorPair, Block as PBlock, Id as ParaId};
|
||||
use sc_executor::native_executor_instance;
|
||||
pub use sc_executor::NativeExecutor;
|
||||
use sc_informant::OutputFormat;
|
||||
use sc_service::{Configuration, PartialComponents, TaskManager, TFullBackend, TFullClient, Role};
|
||||
use std::sync::Arc;
|
||||
use sp_core::crypto::Pair;
|
||||
use sp_trie::PrefixedMemoryDB;
|
||||
use sp_runtime::traits::{BlakeTwo256, Block as BlockT};
|
||||
use polkadot_service::{AbstractClient, RuntimeApiCollection};
|
||||
use sp_consensus::SyncOracle;
|
||||
|
||||
// Our native executor instance.
|
||||
native_executor_instance!(
|
||||
pub Executor,
|
||||
parachain_runtime::api::dispatch,
|
||||
parachain_runtime::native_version,
|
||||
);
|
||||
|
||||
/// Starts a `ServiceBuilder` for a full service.
|
||||
///
|
||||
/// Use this macro if you don't actually need the full service, but just the builder in order to
|
||||
/// be able to perform chain operations.
|
||||
pub fn new_partial(config: &mut Configuration) -> Result<
|
||||
PartialComponents<
|
||||
TFullClient<parachain_runtime::opaque::Block, parachain_runtime::RuntimeApi, crate::service::Executor>,
|
||||
TFullBackend<parachain_runtime::opaque::Block>,
|
||||
(),
|
||||
sp_consensus::import_queue::BasicQueue<parachain_runtime::opaque::Block, PrefixedMemoryDB<BlakeTwo256>>,
|
||||
sc_transaction_pool::FullPool<parachain_runtime::opaque::Block, TFullClient<parachain_runtime::opaque::Block, parachain_runtime::RuntimeApi, crate::service::Executor>>,
|
||||
(),
|
||||
>,
|
||||
sc_service::Error,
|
||||
>
|
||||
{
|
||||
let inherent_data_providers = sp_inherents::InherentDataProviders::new();
|
||||
|
||||
let (client, backend, keystore, task_manager) =
|
||||
sc_service::new_full_parts::<
|
||||
parachain_runtime::opaque::Block,
|
||||
parachain_runtime::RuntimeApi,
|
||||
crate::service::Executor,
|
||||
>(&config)?;
|
||||
let client = Arc::new(client);
|
||||
//let select_chain = sc_consensus::LongestChain::new(backend.clone());
|
||||
|
||||
let registry = config.prometheus_registry();
|
||||
|
||||
let transaction_pool = sc_transaction_pool::BasicPool::new_full(
|
||||
config.transaction_pool.clone(),
|
||||
//std::sync::Arc::new(pool_api),
|
||||
config.prometheus_registry(),
|
||||
task_manager.spawn_handle(),
|
||||
client.clone(),
|
||||
);
|
||||
|
||||
let import_queue = cumulus_consensus::import_queue::import_queue(
|
||||
client.clone(),
|
||||
client.clone(),
|
||||
inherent_data_providers.clone(),
|
||||
&task_manager.spawn_handle(),
|
||||
registry.clone(),
|
||||
)?;
|
||||
|
||||
let params = PartialComponents {
|
||||
backend,
|
||||
client,
|
||||
import_queue,
|
||||
keystore,
|
||||
task_manager,
|
||||
transaction_pool,
|
||||
inherent_data_providers,
|
||||
select_chain: (),
|
||||
other: (),
|
||||
};
|
||||
|
||||
Ok(params)
|
||||
}
|
||||
|
||||
/// Run a collator node with the given parachain `Configuration` and relaychain `Configuration`
|
||||
///
|
||||
/// This function blocks until done.
|
||||
pub fn run_collator(
|
||||
parachain_config: Configuration,
|
||||
key: Arc<CollatorPair>,
|
||||
mut polkadot_config: polkadot_collator::Configuration,
|
||||
id: polkadot_primitives::v0::Id,
|
||||
validator: bool,
|
||||
) -> sc_service::error::Result<(
|
||||
TaskManager,
|
||||
Arc<TFullClient<parachain_runtime::opaque::Block, parachain_runtime::RuntimeApi, crate::service::Executor>>,
|
||||
)> {
|
||||
if matches!(parachain_config.role, Role::Light) {
|
||||
return Err("Light client not supported!".into());
|
||||
}
|
||||
|
||||
let mut parachain_config = prepare_collator_config(parachain_config);
|
||||
|
||||
parachain_config.informant_output_format = OutputFormat {
|
||||
enable_color: true,
|
||||
prefix: format!("[{}] ", Color::Yellow.bold().paint("Parachain")),
|
||||
};
|
||||
polkadot_config.informant_output_format = OutputFormat {
|
||||
enable_color: true,
|
||||
prefix: format!("[{}] ", Color::Blue.bold().paint("Relaychain")),
|
||||
};
|
||||
|
||||
let params = new_partial(&mut parachain_config)?;
|
||||
params.inherent_data_providers
|
||||
.register_provider(sp_timestamp::InherentDataProvider)
|
||||
.unwrap();
|
||||
|
||||
let client = params.client.clone();
|
||||
let backend = params.backend.clone();
|
||||
let block_announce_validator = DelayedBlockAnnounceValidator::new();
|
||||
let block_announce_validator_builder = {
|
||||
let block_announce_validator = block_announce_validator.clone();
|
||||
move |_| Box::new(block_announce_validator) as Box<_>
|
||||
};
|
||||
|
||||
let prometheus_registry = parachain_config.prometheus_registry().cloned();
|
||||
let transaction_pool = params.transaction_pool.clone();
|
||||
let mut task_manager = params.task_manager;
|
||||
let import_queue = params.import_queue;
|
||||
let (network, network_status_sinks, system_rpc_tx, start_network) =
|
||||
sc_service::build_network(sc_service::BuildNetworkParams {
|
||||
config: ¶chain_config,
|
||||
client: client.clone(),
|
||||
transaction_pool: transaction_pool.clone(),
|
||||
spawn_handle: task_manager.spawn_handle(),
|
||||
import_queue,
|
||||
on_demand: None,
|
||||
block_announce_validator_builder: Some(Box::new(block_announce_validator_builder)),
|
||||
finality_proof_request_builder: None,
|
||||
finality_proof_provider: None,
|
||||
})?;
|
||||
|
||||
let rpc_extensions_builder = {
|
||||
let _client = client.clone();
|
||||
|
||||
Box::new(move |_deny_unsafe| {
|
||||
let io = jsonrpc_core::IoHandler::default();
|
||||
|
||||
// TODO: add this rpc when running the contracts runtime
|
||||
/*
|
||||
use pallet_contracts_rpc::{Contracts, ContractsApi};
|
||||
io.extend_with(
|
||||
ContractsApi::to_delegate(Contracts::new(client.clone()))
|
||||
);
|
||||
*/
|
||||
io
|
||||
})
|
||||
};
|
||||
|
||||
let _rpc_handlers = sc_service::spawn_tasks(sc_service::SpawnTasksParams {
|
||||
on_demand: None,
|
||||
remote_blockchain: None,
|
||||
rpc_extensions_builder,
|
||||
client: client.clone(),
|
||||
transaction_pool: transaction_pool.clone(),
|
||||
task_manager: &mut task_manager,
|
||||
telemetry_connection_sinks: Default::default(),
|
||||
config: parachain_config,
|
||||
keystore: params.keystore,
|
||||
backend,
|
||||
network: network.clone(),
|
||||
network_status_sinks,
|
||||
system_rpc_tx,
|
||||
})?;
|
||||
|
||||
if validator {
|
||||
let proposer_factory = sc_basic_authorship::ProposerFactory::new(
|
||||
client.clone(),
|
||||
transaction_pool,
|
||||
prometheus_registry.as_ref(),
|
||||
);
|
||||
|
||||
let block_import = client.clone();
|
||||
let announce_block = Arc::new(move |hash, data| network.announce_block(hash, data));
|
||||
let builder = CollatorBuilder::new(
|
||||
proposer_factory,
|
||||
params.inherent_data_providers,
|
||||
block_import,
|
||||
client.clone(),
|
||||
id,
|
||||
client.clone(),
|
||||
announce_block,
|
||||
block_announce_validator,
|
||||
);
|
||||
|
||||
let (polkadot_future, polkadot_task_manager) =
|
||||
polkadot_collator::start_collator(builder, id, key, polkadot_config)?;
|
||||
|
||||
task_manager
|
||||
.spawn_essential_handle()
|
||||
.spawn("polkadot", polkadot_future);
|
||||
|
||||
task_manager.add_child(polkadot_task_manager);
|
||||
} else {
|
||||
let is_light = matches!(polkadot_config.role, Role::Light);
|
||||
let (polkadot_task_manager, client, handles) = if is_light {
|
||||
Err("Light client not supported.".into())
|
||||
} else {
|
||||
polkadot_service::build_full(
|
||||
polkadot_config,
|
||||
Some((key.public(), id)),
|
||||
None,
|
||||
false,
|
||||
6000,
|
||||
None,
|
||||
)
|
||||
}?;
|
||||
let polkadot_network = handles.polkadot_network.expect("polkadot service is started; qed");
|
||||
client.execute_with(SetDelayedBlockAnnounceValidator {
|
||||
block_announce_validator,
|
||||
para_id: id,
|
||||
polkadot_sync_oracle: Box::new(polkadot_network),
|
||||
});
|
||||
|
||||
task_manager.add_child(polkadot_task_manager);
|
||||
}
|
||||
|
||||
start_network.start_network();
|
||||
|
||||
Ok((task_manager, client))
|
||||
}
|
||||
|
||||
struct SetDelayedBlockAnnounceValidator<B: BlockT> {
|
||||
block_announce_validator: DelayedBlockAnnounceValidator<B>,
|
||||
para_id: ParaId,
|
||||
polkadot_sync_oracle: Box<dyn SyncOracle + Send>,
|
||||
}
|
||||
|
||||
impl<B: BlockT> polkadot_service::ExecuteWithClient for SetDelayedBlockAnnounceValidator<B> {
|
||||
type Output = ();
|
||||
|
||||
fn execute_with_client<Client, Api, Backend>(self, client: Arc<Client>) -> Self::Output
|
||||
where<Api as sp_api::ApiExt<PBlock>>::StateBackend: sp_api::StateBackend<BlakeTwo256>,
|
||||
Backend: sc_client_api::Backend<PBlock>,
|
||||
Backend::State: sp_api::StateBackend<BlakeTwo256>,
|
||||
Api: RuntimeApiCollection<StateBackend = Backend::State>,
|
||||
Client: AbstractClient<PBlock, Backend, Api = Api> + 'static
|
||||
{
|
||||
self.block_announce_validator.set(Box::new(JustifiedBlockAnnounceValidator::new(
|
||||
client,
|
||||
self.para_id,
|
||||
self.polkadot_sync_oracle,
|
||||
)));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user