Make a test crate to make the runtime-test usable (#1258)

Fixes #833
This commit is contained in:
Cecile Tonglet
2020-07-09 15:12:52 +02:00
committed by GitHub
parent 8696788747
commit a4fa71ed17
16 changed files with 1161 additions and 357 deletions
+205 -137
View File
File diff suppressed because it is too large Load Diff
+1
View File
@@ -52,6 +52,7 @@ members = [
"node/service",
"node/subsystem",
"node/test-helpers/subsystem",
"node/test-service",
"parachain/test-parachains",
"parachain/test-parachains/adder",
+1 -1
View File
@@ -29,7 +29,7 @@ fn prepare_good_block() -> (TestClient, Hash, u64, PeerId, IncomingBlock<Block>)
let mut client = polkadot_test_runtime_client::new();
let mut builder = client.new_block(Default::default()).unwrap();
let extrinsics = polkadot_test_runtime_client::needed_extrinsics(vec![]);
let extrinsics = polkadot_test_runtime_client::needed_extrinsics(vec![], 0);
for extrinsic in &extrinsics {
builder.push(extrinsic.clone()).unwrap();
+6 -2
View File
@@ -250,17 +250,21 @@ mod tests {
let mut push_blocks = {
let mut client = client.clone();
let mut base = 0;
move |n| {
for _ in 0..n {
for i in 0..n {
let mut builder = client.new_block(Default::default()).unwrap();
for extrinsic in polkadot_test_runtime_client::needed_extrinsics(vec![]) {
for extrinsic in polkadot_test_runtime_client::needed_extrinsics(vec![], base + i) {
builder.push(extrinsic).unwrap()
}
let block = builder.build().unwrap().block;
client.import(BlockOrigin::Own, block).unwrap();
}
base += n;
}
};
+56
View File
@@ -0,0 +1,56 @@
[package]
name = "polkadot-test-service"
version = "0.8.2"
authors = ["Parity Technologies <admin@parity.io>"]
edition = "2018"
[dependencies]
futures = "0.3.4"
futures01 = { package = "futures", version = "0.1.29" }
hex = "0.4"
log = "0.4.8"
rand = "0.7.3"
tempfile = "3.1.0"
# Polkadot dependencies
av_store = { package = "polkadot-availability-store", path = "../../availability-store" }
consensus = { package = "polkadot-validation", path = "../../validation" }
polkadot-network = { path = "../../network" }
polkadot-primitives = { path = "../../primitives" }
polkadot-rpc = { path = "../../rpc" }
polkadot-runtime-common = { path = "../../runtime/common" }
polkadot-service = { path = "../../service" }
polkadot-test-runtime = { path = "../../runtime/test-runtime" }
# Substrate dependencies
authority-discovery = { package = "sc-authority-discovery", git = "https://github.com/paritytech/substrate", branch = "master" }
babe = { package = "sc-consensus-babe", git = "https://github.com/paritytech/substrate", branch = "master" }
babe-primitives = { package = "sp-consensus-babe", git = "https://github.com/paritytech/substrate", branch = "master" }
consensus_common = { package = "sp-consensus", git = "https://github.com/paritytech/substrate", branch = "master" }
frame-benchmarking = { git = "https://github.com/paritytech/substrate", branch = "master" }
frame-system = { git = "https://github.com/paritytech/substrate", branch = "master" }
grandpa = { package = "sc-finality-grandpa", git = "https://github.com/paritytech/substrate", branch = "master" }
grandpa_primitives = { package = "sp-finality-grandpa", git = "https://github.com/paritytech/substrate", branch = "master" }
inherents = { package = "sp-inherents", git = "https://github.com/paritytech/substrate", branch = "master" }
pallet-staking = { git = "https://github.com/paritytech/substrate", branch = "master" }
pallet-transaction-payment = { git = "https://github.com/paritytech/substrate", branch = "master" }
sc-chain-spec = { git = "https://github.com/paritytech/substrate", branch = "master" }
sc-client-api = { git = "https://github.com/paritytech/substrate", branch = "master" }
sc-consensus = { git = "https://github.com/paritytech/substrate", branch = "master" }
sc-executor = { git = "https://github.com/paritytech/substrate", branch = "master" }
sc-informant = { git = "https://github.com/paritytech/substrate", branch = "master" }
sc-network = { git = "https://github.com/paritytech/substrate", branch = "master" }
sc-transaction-pool = { git = "https://github.com/paritytech/substrate", branch = "master" }
service = { package = "sc-service", git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
sp-arithmetic = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-blockchain = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-keyring = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-state-machine = { git = "https://github.com/paritytech/substrate", branch = "master" }
substrate-test-client = { git = "https://github.com/paritytech/substrate", branch = "master" }
[dev-dependencies]
pallet-balances = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
serde_json = "1.0"
tokio = { version = "0.2", features = ["macros"] }
@@ -0,0 +1,184 @@
// Copyright 2020 Parity Technologies (UK) Ltd.
// This file is part of Polkadot.
// Polkadot 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.
// Polkadot 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 Polkadot. If not, see <http://www.gnu.org/licenses/>.
use babe_primitives::AuthorityId as BabeId;
use grandpa::AuthorityId as GrandpaId;
use pallet_staking::Forcing;
use polkadot_primitives::{parachain::ValidatorId, AccountId};
use polkadot_service::chain_spec::{get_account_id_from_seed, get_from_seed, Extensions};
use polkadot_test_runtime::constants::currency::DOTS;
use sc_chain_spec::{ChainSpec, ChainType};
use sp_core::{sr25519, ChangesTrieConfiguration};
use sp_runtime::Perbill;
const DEFAULT_PROTOCOL_ID: &str = "dot";
/// The `ChainSpec parametrised for polkadot runtime`.
pub type PolkadotChainSpec =
service::GenericChainSpec<polkadot_test_runtime::GenesisConfig, Extensions>;
/// Polkadot local testnet config (multivalidator Alice + Bob)
pub fn polkadot_local_testnet_config() -> PolkadotChainSpec {
PolkadotChainSpec::from_genesis(
"Local Testnet",
"local_testnet",
ChainType::Local,
|| polkadot_local_testnet_genesis(None),
vec![],
None,
Some(DEFAULT_PROTOCOL_ID),
None,
Default::default(),
)
}
/// Polkadot local testnet genesis config (multivalidator Alice + Bob)
pub fn polkadot_local_testnet_genesis(
changes_trie_config: Option<ChangesTrieConfiguration>,
) -> polkadot_test_runtime::GenesisConfig {
polkadot_testnet_genesis(
vec![
get_authority_keys_from_seed("Alice"),
get_authority_keys_from_seed("Bob"),
get_authority_keys_from_seed("Charlie"),
],
get_account_id_from_seed::<sr25519::Public>("Alice"),
None,
changes_trie_config,
)
}
/// Helper function to generate stash, controller and session key from seed
fn get_authority_keys_from_seed(
seed: &str,
) -> (AccountId, AccountId, BabeId, GrandpaId, ValidatorId) {
(
get_account_id_from_seed::<sr25519::Public>(&format!("{}//stash", seed)),
get_account_id_from_seed::<sr25519::Public>(seed),
get_from_seed::<BabeId>(seed),
get_from_seed::<GrandpaId>(seed),
get_from_seed::<ValidatorId>(seed),
)
}
fn testnet_accounts() -> Vec<AccountId> {
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"),
]
}
/// Helper function to create polkadot GenesisConfig for testing
fn polkadot_testnet_genesis(
initial_authorities: Vec<(AccountId, AccountId, BabeId, GrandpaId, ValidatorId)>,
root_key: AccountId,
endowed_accounts: Option<Vec<AccountId>>,
changes_trie_config: Option<ChangesTrieConfiguration>,
) -> polkadot_test_runtime::GenesisConfig {
use polkadot_test_runtime as polkadot;
let endowed_accounts: Vec<AccountId> = endowed_accounts.unwrap_or_else(testnet_accounts);
const ENDOWMENT: u128 = 1_000_000 * DOTS;
const STASH: u128 = 100 * DOTS;
polkadot::GenesisConfig {
system: Some(polkadot::SystemConfig {
code: polkadot::WASM_BINARY.to_vec(),
changes_trie_config,
}),
indices: Some(polkadot::IndicesConfig { indices: vec![] }),
balances: Some(polkadot::BalancesConfig {
balances: endowed_accounts
.iter()
.map(|k| (k.clone(), ENDOWMENT))
.collect(),
}),
session: Some(polkadot::SessionConfig {
keys: initial_authorities
.iter()
.map(|x| {
(
x.0.clone(),
x.0.clone(),
polkadot_test_runtime::SessionKeys {
babe: x.2.clone(),
grandpa: x.3.clone(),
parachain_validator: x.4.clone(),
},
)
})
.collect::<Vec<_>>(),
}),
staking: Some(polkadot::StakingConfig {
minimum_validator_count: 1,
validator_count: 2,
stakers: initial_authorities
.iter()
.map(|x| {
(
x.0.clone(),
x.1.clone(),
STASH,
polkadot::StakerStatus::Validator,
)
})
.collect(),
invulnerables: initial_authorities.iter().map(|x| x.0.clone()).collect(),
force_era: Forcing::NotForcing,
slash_reward_fraction: Perbill::from_percent(10),
..Default::default()
}),
babe: Some(Default::default()),
grandpa: Some(Default::default()),
authority_discovery: Some(polkadot::AuthorityDiscoveryConfig { keys: vec![] }),
parachains: Some(polkadot::ParachainsConfig {
authorities: vec![],
}),
registrar: Some(polkadot::RegistrarConfig {
parachains: vec![],
_phdata: Default::default(),
}),
claims: Some(polkadot::ClaimsConfig {
claims: vec![],
vesting: vec![],
}),
vesting: Some(polkadot::VestingConfig { vesting: vec![] }),
sudo: Some(polkadot::SudoConfig { key: root_key }),
}
}
/// Can be called for a `Configuration` to check if it is a configuration for the `Test` network.
pub trait IdentifyVariant {
/// Returns if this is a configuration for the `Test` network.
fn is_test(&self) -> bool;
}
impl IdentifyVariant for Box<dyn ChainSpec> {
fn is_test(&self) -> bool {
self.id().starts_with("test")
}
}
+307
View File
@@ -0,0 +1,307 @@
// Copyright 2020 Parity Technologies (UK) Ltd.
// This file is part of Polkadot.
// Polkadot 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.
// Polkadot 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 Polkadot. If not, see <http://www.gnu.org/licenses/>.
//! Polkadot test service only.
#![warn(missing_docs)]
mod chain_spec;
pub use chain_spec::*;
use consensus_common::{block_validation::Chain, SelectChain};
use futures::future::Future;
use grandpa::FinalityProofProvider as GrandpaFinalityProofProvider;
use log::info;
use polkadot_network::{legacy::gossip::Known, protocol as network_protocol};
use polkadot_primitives::{
parachain::{self, CollatorId},
Block, BlockId, Hash,
};
use polkadot_runtime_common::{parachains, registrar, BlockHashCount};
use polkadot_service::{
new_full, new_full_start, FullNodeHandles, PolkadotClient, ServiceComponents,
};
use polkadot_test_runtime::{RestrictFunctionality, Runtime, SignedExtra, SignedPayload, VERSION};
use sc_chain_spec::ChainSpec;
use sc_client_api::{execution_extensions::ExecutionStrategies, BlockchainEvents};
use sc_executor::native_executor_instance;
use sc_informant::OutputFormat;
use sc_network::{
config::{NetworkConfiguration, TransportConfig},
multiaddr, NetworkService,
};
use service::{
config::{DatabaseConfig, KeystoreConfig, MultiaddrWithPeerId, WasmExecutionMethod},
error::Error as ServiceError,
RpcHandlers, TaskExecutor, TaskManager,
};
use service::{BasePath, Configuration, Role, TFullBackend};
use sp_arithmetic::traits::SaturatedConversion;
use sp_blockchain::HeaderBackend;
use sp_keyring::Sr25519Keyring;
use sp_runtime::{codec::Encode, generic};
use sp_state_machine::BasicExternalities;
use std::sync::Arc;
use std::time::Duration;
use substrate_test_client::{BlockchainEventsExt, RpcHandlersExt, RpcTransactionOutput, RpcTransactionError};
native_executor_instance!(
pub PolkadotTestExecutor,
polkadot_test_runtime::api::dispatch,
polkadot_test_runtime::native_version,
frame_benchmarking::benchmarking::HostFunctions,
);
/// Create a new Polkadot test service for a full node.
pub fn polkadot_test_new_full(
config: Configuration,
collating_for: Option<(CollatorId, parachain::Id)>,
max_block_data_size: Option<u64>,
authority_discovery_enabled: bool,
slot_duration: u64,
) -> Result<
(
TaskManager,
Arc<impl PolkadotClient<Block, TFullBackend<Block>, polkadot_test_runtime::RuntimeApi>>,
FullNodeHandles,
Arc<NetworkService<Block, Hash>>,
Arc<RpcHandlers>,
),
ServiceError,
> {
let (task_manager, client, handles, network, rpc_handlers) = new_full!(test
config,
collating_for,
max_block_data_size,
authority_discovery_enabled,
slot_duration,
polkadot_test_runtime::RuntimeApi,
PolkadotTestExecutor,
);
Ok((task_manager, client, handles, network, rpc_handlers))
}
/// Create a Polkadot `Configuration`. By default an in-memory socket will be used, therefore you need to provide boot
/// nodes if you want the future node to be connected to other nodes. The `storage_update_func` can be used to make
/// adjustements to the runtime before the node starts.
pub fn node_config(
storage_update_func: impl Fn(),
task_executor: TaskExecutor,
key: Sr25519Keyring,
boot_nodes: Vec<MultiaddrWithPeerId>,
) -> Configuration {
let base_path = BasePath::new_temp_dir().expect("could not create temporary directory");
let root = base_path.path();
let role = Role::Authority {
sentry_nodes: Vec::new(),
};
let key_seed = key.to_seed();
let mut spec = polkadot_local_testnet_config();
let mut storage = spec
.as_storage_builder()
.build_storage()
.expect("could not build storage");
BasicExternalities::execute_with_storage(&mut storage, storage_update_func);
spec.set_storage(storage);
let mut network_config = NetworkConfiguration::new(
format!("Polkadot 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;
Configuration {
impl_name: "polkadot-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,
}
}
/// Run a Polkadot test node using the Polkadot test runtime. The node will be using an in-memory socket, therefore you
/// need to provide boot nodes if you want it to be connected to other nodes. The `storage_update_func` can be used to
/// make adjustements to the runtime before the node starts.
pub fn run_test_node(
task_executor: TaskExecutor,
key: Sr25519Keyring,
storage_update_func: impl Fn(),
boot_nodes: Vec<MultiaddrWithPeerId>,
) -> PolkadotTestNode<
TaskManager,
impl PolkadotClient<Block, TFullBackend<Block>, polkadot_test_runtime::RuntimeApi>,
> {
let config = node_config(storage_update_func, task_executor, key, boot_nodes);
let multiaddr = config.network.listen_addresses[0].clone();
let authority_discovery_enabled = false;
let (task_manager, client, handles, network, rpc_handlers) =
polkadot_test_new_full(config, None, None, authority_discovery_enabled, 6000)
.expect("could not create Polkadot test service");
let peer_id = network.local_peer_id().clone();
let addr = MultiaddrWithPeerId { multiaddr, peer_id };
PolkadotTestNode {
task_manager,
client,
handles,
addr,
rpc_handlers,
}
}
/// A Polkadot test node instance used for testing.
pub struct PolkadotTestNode<S, C> {
/// TaskManager's instance.
pub task_manager: S,
/// Client's instance.
pub client: Arc<C>,
/// Node's handles.
pub handles: FullNodeHandles,
/// The `MultiaddrWithPeerId` to this node. This is useful if you want to pass it as "boot node" to other nodes.
pub addr: MultiaddrWithPeerId,
/// RPCHandlers to make RPC queries.
pub rpc_handlers: Arc<RpcHandlers>,
}
impl<S, C> PolkadotTestNode<S, C>
where
C: HeaderBackend<Block>,
{
/// Send a transaction through RPCHandlers to call a function.
pub async fn call_function(
&self,
function: polkadot_test_runtime::Call,
caller: Sr25519Keyring,
) -> Result<RpcTransactionOutput, RpcTransactionError> {
let current_block_hash = self.client.info().best_hash;
let current_block = self.client.info().best_number.saturated_into();
let genesis_block = self.client.hash(0).unwrap().unwrap();
let nonce = 0;
let period = BlockHashCount::get()
.checked_next_power_of_two()
.map(|c| c / 2)
.unwrap_or(2) as u64;
let tip = 0;
let extra: SignedExtra = (
RestrictFunctionality,
frame_system::CheckSpecVersion::<Runtime>::new(),
frame_system::CheckTxVersion::<Runtime>::new(),
frame_system::CheckGenesis::<Runtime>::new(),
frame_system::CheckEra::<Runtime>::from(generic::Era::mortal(period, current_block)),
frame_system::CheckNonce::<Runtime>::from(nonce),
frame_system::CheckWeight::<Runtime>::new(),
pallet_transaction_payment::ChargeTransactionPayment::<Runtime>::from(tip),
registrar::LimitParathreadCommits::<Runtime>::new(),
parachains::ValidateDoubleVoteReports::<Runtime>::new(),
);
let raw_payload = SignedPayload::from_raw(
function.clone(),
extra.clone(),
(
(),
VERSION.spec_version,
VERSION.transaction_version,
genesis_block,
current_block_hash,
(),
(),
(),
(),
(),
),
);
let signature = raw_payload.using_encoded(|e| caller.sign(e));
let extrinsic = polkadot_test_runtime::UncheckedExtrinsic::new_signed(
function.clone(),
polkadot_test_runtime::Address::Id(caller.public().into()),
polkadot_primitives::Signature::Sr25519(signature.clone()),
extra.clone(),
);
self.rpc_handlers.send_transaction(extrinsic.into()).await
}
}
impl<S, C> PolkadotTestNode<S, C>
where
C: BlockchainEvents<Block>,
{
/// Wait for `count` blocks to be imported in the node and then exit. This function will not return if no blocks
/// are ever created, thus you should restrict the maximum amount of time of the test execution.
pub fn wait_for_blocks(&self, count: usize) -> impl Future<Output = ()> {
self.client.wait_for_blocks(count)
}
}
@@ -0,0 +1,78 @@
// Copyright 2020 Parity Technologies (UK) Ltd.
// This file is part of Polkadot.
// Polkadot 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.
// Polkadot 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 Polkadot. If not, see <http://www.gnu.org/licenses/>.
use tokio::{time::delay_for as sleep, task::spawn};
use futures::{future, pin_mut, select, FutureExt as _};
use polkadot_test_service::*;
use service::TaskExecutor;
use sp_keyring::Sr25519Keyring;
use std::time::Duration;
static INTEGRATION_TEST_ALLOWED_TIME: Option<&str> = option_env!("INTEGRATION_TEST_ALLOWED_TIME");
#[tokio::test]
async fn ensure_test_service_build_blocks() {
let task_executor: TaskExecutor = (move |fut, _| {
spawn(fut);
})
.into();
let mut alice = run_test_node(
task_executor.clone(),
Sr25519Keyring::Alice,
|| {},
Vec::new(),
);
let mut bob = run_test_node(
task_executor.clone(),
Sr25519Keyring::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 t1 = future::join(alice.wait_for_blocks(3), bob.wait_for_blocks(3)).fuse();
let t2 = alice.task_manager.future().fuse();
let t3 = bob.task_manager.future().fuse();
pin_mut!(t1, t2, t3);
select! {
_ = t1 => {},
_ = t2 => panic!("service Alice failed"),
_ = t3 => panic!("service Bob failed"),
}
}
alice.task_manager.terminate();
bob.task_manager.terminate();
}
.fuse();
pin_mut!(t1, t2);
select! {
_ = t1 => {
panic!("the test took too long, maybe no blocks have been produced");
},
_ = t2 => {},
}
}
@@ -0,0 +1,73 @@
// Copyright 2020 Parity Technologies (UK) Ltd.
// This file is part of Polkadot.
// Polkadot 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.
// Polkadot 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 Polkadot. If not, see <http://www.gnu.org/licenses/>.
use tokio::{time::delay_for as sleep, task::spawn};
use futures::{pin_mut, select, FutureExt as _};
use polkadot_test_service::*;
use sp_keyring::Sr25519Keyring::{Alice, Bob};
use std::time::Duration;
static INTEGRATION_TEST_ALLOWED_TIME: Option<&str> = option_env!("INTEGRATION_TEST_ALLOWED_TIME");
#[tokio::test]
async fn call_function_actually_work() {
let mut alice = run_test_node(
(move |fut, _| {
spawn(fut);
})
.into(),
Alice,
|| {},
Vec::new(),
);
let t1 = sleep(Duration::from_secs(
INTEGRATION_TEST_ALLOWED_TIME
.and_then(|x| x.parse().ok())
.unwrap_or(600),
))
.fuse();
let t2 = async {
let function = polkadot_test_runtime::Call::Balances(pallet_balances::Call::transfer(
Default::default(),
1,
));
let output = alice.call_function(function, Bob).await.unwrap();
let res = output.result.expect("return value expected");
let json = serde_json::from_str::<serde_json::Value>(res.as_str()).expect("valid JSON");
let object = json.as_object().expect("JSON is an object");
assert!(object.contains_key("jsonrpc"), "key jsonrpc exists");
let result = object.get("result");
let result = result.expect("key result exists");
assert_eq!(
result.as_str().map(|x| x.starts_with("0x")),
Some(true),
"result starts with 0x"
);
alice.task_manager.terminate();
}
.fuse();
pin_mut!(t1, t2);
select! {
_ = t1 => {
panic!("the test took too long, maybe no blocks have been produced");
},
_ = t2 => {},
}
}
+7
View File
@@ -14,9 +14,11 @@ serde = { version = "1.0.102", default-features = false }
serde_derive = { version = "1.0.102", optional = true }
smallvec = "1.4.1"
authority-discovery-primitives = { package = "sp-authority-discovery", git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
babe-primitives = { package = "sp-consensus-babe", git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
sp-api = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
inherents = { package = "sp-inherents", git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
offchain-primitives = { package = "sp-offchain", git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
rstd = { package = "sp-std", git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
sp-io = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
@@ -27,6 +29,7 @@ version = { package = "sp-version", git = "https://github.com/paritytech/substra
tx-pool-api = { package = "sp-transaction-pool", git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
block-builder-api = { package = "sp-block-builder", git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
authority-discovery = { package = "pallet-authority-discovery", git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
authorship = { package = "pallet-authorship", git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
babe = { package = "pallet-babe", git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
balances = { package = "pallet-balances", git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
@@ -46,6 +49,7 @@ pallet-staking-reward-curve = { git = "https://github.com/paritytech/substrate",
system = { package = "frame-system", git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
system_rpc_runtime_api = { package = "frame-system-rpc-runtime-api", git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
timestamp = { package = "pallet-timestamp", git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
sudo = { package = "pallet-sudo", git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
vesting = { package = "pallet-vesting", git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
runtime-common = { package = "polkadot-runtime-common", path = "../common", default-features = false }
@@ -68,6 +72,8 @@ default = ["std"]
no_std = []
only-staking = []
std = [
"authority-discovery-primitives/std",
"authority-discovery/std",
"bitvec/std",
"primitives/std",
"rustc-hex/std",
@@ -78,6 +84,7 @@ std = [
"sp-api/std",
"tx-pool-api/std",
"block-builder-api/std",
"offchain-primitives/std",
"rstd/std",
"sp-io/std",
"frame-support/std",
+15 -10
View File
@@ -6,19 +6,24 @@ edition = "2018"
license = "GPL-3.0"
[dependencies]
futures = "0.3.1"
codec = { package = "parity-scale-codec", version = "1.0.0" }
# Polkadot dependencies
polkadot-primitives = { path = "../../../primitives" }
polkadot-runtime-common = { path = "../../common" }
polkadot-test-runtime = { path = ".." }
polkadot-test-service = { path = "../../../node/test-service" }
# Substrate dependencies
pallet-timestamp = { git = "https://github.com/paritytech/substrate", branch = "master" }
sc-block-builder = { git = "https://github.com/paritytech/substrate", branch = "master" }
sc-client-api = { git = "https://github.com/paritytech/substrate", branch = "master" }
sc-consensus = { git = "https://github.com/paritytech/substrate", branch = "master" }
sc-light = { git = "https://github.com/paritytech/substrate", branch = "master" }
sc-service = { git = "https://github.com/paritytech/substrate", branch = "master", features = ["test-helpers"], default-features = false }
substrate-test-client = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" }
polkadot-test-runtime = { path = ".." }
polkadot-runtime-common = { path = "../../common" }
polkadot-primitives = { path = "../../../primitives" }
sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-api = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-blockchain = { git = "https://github.com/paritytech/substrate", branch = "master" }
codec = { package = "parity-scale-codec", version = "1.0.0" }
sc-client-api = { git = "https://github.com/paritytech/substrate", branch = "master" }
pallet-timestamp = { git = "https://github.com/paritytech/substrate", branch = "master" }
futures = "0.3.1"
sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" }
sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" }
substrate-test-client = { git = "https://github.com/paritytech/substrate", branch = "master" }
+27 -20
View File
@@ -20,13 +20,18 @@
use std::sync::Arc;
use std::collections::BTreeMap;
use std::convert::TryFrom;
pub use substrate_test_client::*;
pub use polkadot_test_runtime as runtime;
use sp_core::{sr25519, ChangesTrieConfiguration, map, twox_128};
use sp_core::{ChangesTrieConfiguration, map, twox_128};
use sp_core::storage::{ChildInfo, Storage, StorageChild};
use polkadot_test_runtime::genesismap::GenesisConfig;
use sp_runtime::traits::{Block as BlockT, Header as HeaderT, Hash as HashT, HashFor};
use polkadot_test_runtime::GenesisConfig;
use polkadot_test_service::polkadot_local_testnet_genesis;
use sp_runtime::{
traits::{Block as BlockT, Header as HeaderT, Hash as HashT, HashFor},
BuildStorage,
};
use sc_consensus::LongestChain;
use sc_client_api::light::{RemoteCallRequest, RemoteBodyRequest};
use sc_service::client::{
@@ -89,16 +94,10 @@ pub struct GenesisParameters {
impl GenesisParameters {
fn genesis_config(&self) -> GenesisConfig {
GenesisConfig::new(
self.changes_trie_config.clone(),
vec![
sr25519::Public::from(Sr25519Keyring::Alice).into(),
sr25519::Public::from(Sr25519Keyring::Bob).into(),
sr25519::Public::from(Sr25519Keyring::Charlie).into(),
],
1000,
self.extra_storage.clone(),
)
let config = polkadot_local_testnet_genesis(self.changes_trie_config.clone());
config.assimilate_storage(&mut self.extra_storage.clone()).expect("Adding `system::GensisConfig` to the genesis");
config
}
}
@@ -112,7 +111,7 @@ impl substrate_test_client::GenesisInit for GenesisParameters {
fn genesis_storage(&self) -> Storage {
use codec::Encode;
let mut storage = self.genesis_config().genesis_map();
let mut storage = self.genesis_config().build_storage().unwrap();
let child_roots = storage.children_default.iter().map(|(sk, child_content)| {
let state_root = <<<runtime::Block as BlockT>::Header as HeaderT>::Hashing as HashT>::trie_root(
@@ -323,20 +322,28 @@ pub fn new_native_executor() -> sc_executor::NativeExecutor<LocalExecutor> {
}
/// Extrinsics that must be included in each block.
pub fn needed_extrinsics(heads: Vec<polkadot_primitives::parachain::AttestedCandidate>) -> Vec<polkadot_test_runtime::UncheckedExtrinsic> {
///
/// The index of the block must be provided to calculate a valid timestamp for the block. The value starts at 0 and
/// should be incremented by one for every block produced.
pub fn needed_extrinsics(
heads: Vec<polkadot_primitives::parachain::AttestedCandidate>,
i: u64,
) -> Vec<polkadot_test_runtime::UncheckedExtrinsic> {
use polkadot_runtime_common::parachains;
let timestamp = std::time::SystemTime::now().duration_since(std::time::UNIX_EPOCH)
.expect("now always later than unix epoch; qed")
.as_millis() + (i * polkadot_test_runtime::constants::time::SLOT_DURATION / 2) as u128;
vec![
polkadot_test_runtime::UncheckedExtrinsic {
function: polkadot_test_runtime::Call::Parachains(parachains::Call::set_heads(heads)),
signature: None,
},
polkadot_test_runtime::UncheckedExtrinsic {
function: polkadot_test_runtime::Call::Timestamp(pallet_timestamp::Call::set({
std::time::SystemTime::now().duration_since(std::time::UNIX_EPOCH)
.expect("now always later than unix epoch; qed")
.as_millis() as u64
})),
function: polkadot_test_runtime::Call::Timestamp(pallet_timestamp::Call::set(
u64::try_from(timestamp).expect("unexpected big timestamp"),
)),
signature: None,
}
]
@@ -1,75 +0,0 @@
// 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/>.
//! Tool for creating the genesis block.
use std::collections::BTreeMap;
use super::{AccountId, WASM_BINARY, constants::currency};
use sp_core::ChangesTrieConfiguration;
use sp_core::storage::Storage;
use sp_runtime::BuildStorage;
/// Configuration of a general Substrate test genesis block.
pub struct GenesisConfig {
changes_trie_config: Option<ChangesTrieConfiguration>,
balances: Vec<(AccountId, u128)>,
/// Additional storage key pairs that will be added to the genesis map.
extra_storage: Storage,
}
impl GenesisConfig {
pub fn new(
changes_trie_config: Option<ChangesTrieConfiguration>,
endowed_accounts: Vec<AccountId>,
balance: u128,
extra_storage: Storage,
) -> Self {
GenesisConfig {
changes_trie_config,
balances: endowed_accounts.into_iter().map(|a| (a, balance * currency::DOLLARS)).collect(),
extra_storage,
}
}
pub fn genesis_map(&self) -> Storage {
// Assimilate the system genesis config.
let mut storage = Storage {
top: BTreeMap::new(),
children_default: self.extra_storage.children_default.clone(),
};
let config = crate::GenesisConfig {
system: Some(system::GenesisConfig {
changes_trie_config: self.changes_trie_config.clone(),
code: WASM_BINARY.to_vec(),
}),
babe: None,
indices: None,
balances: Some(balances::GenesisConfig {
balances: self.balances.clone()
}),
staking: None,
session: None,
grandpa: None,
claims: None,
parachains: None,
registrar: None,
vesting: None,
};
config.assimilate_storage(&mut storage).expect("Adding `system::GensisConfig` to the genesis");
storage
}
}
+53 -30
View File
@@ -55,6 +55,7 @@ use frame_support::{
traits::{KeyOwnerProofSystem, Randomness},
weights::Weight,
};
use authority_discovery_primitives::AuthorityId as AuthorityDiscoveryId;
use pallet_transaction_payment_rpc_runtime_api::RuntimeDispatchInfo;
use session::historical as session_historical;
@@ -69,8 +70,6 @@ pub use parachains::Call as ParachainsCall;
/// Constant values used within the runtime.
pub mod constants;
#[cfg(feature = "std")]
pub mod genesismap;
use constants::{time::*, currency::*, fee::*};
// Make the WASM binary available.
@@ -166,8 +165,8 @@ impl<C> system::offchain::SendTransactionTypes<C> for Runtime where
}
parameter_types! {
pub const EpochDuration: u64 = EPOCH_DURATION_IN_BLOCKS as u64;
pub const ExpectedBlockTime: Moment = MILLISECS_PER_BLOCK;
pub storage EpochDuration: u64 = EPOCH_DURATION_IN_BLOCKS as u64;
pub storage ExpectedBlockTime: Moment = MILLISECS_PER_BLOCK;
}
impl babe::Trait for Runtime {
@@ -193,7 +192,7 @@ impl babe::Trait for Runtime {
}
parameter_types! {
pub const IndexDeposit: Balance = 1 * DOLLARS;
pub storage IndexDeposit: Balance = 1 * DOLLARS;
}
impl indices::Trait for Runtime {
@@ -205,7 +204,7 @@ impl indices::Trait for Runtime {
}
parameter_types! {
pub const ExistentialDeposit: Balance = 1 * CENTS;
pub storage ExistentialDeposit: Balance = 1 * CENTS;
}
impl balances::Trait for Runtime {
@@ -218,7 +217,7 @@ impl balances::Trait for Runtime {
}
parameter_types! {
pub const TransactionByteFee: Balance = 10 * MILLICENTS;
pub storage TransactionByteFee: Balance = 10 * MILLICENTS;
}
impl transaction_payment::Trait for Runtime {
@@ -230,7 +229,8 @@ impl transaction_payment::Trait for Runtime {
}
parameter_types! {
pub const MinimumPeriod: u64 = 0;
pub storage SlotDuration: u64 = SLOT_DURATION;
pub storage MinimumPeriod: u64 = SlotDuration::get() / 2;
}
impl timestamp::Trait for Runtime {
type Moment = u64;
@@ -240,7 +240,7 @@ impl timestamp::Trait for Runtime {
}
parameter_types! {
pub const UncleGenerations: u32 = 0;
pub storage UncleGenerations: u32 = 0;
}
// TODO: substrate#2986 implement this properly
@@ -252,8 +252,8 @@ impl authorship::Trait for Runtime {
}
parameter_types! {
pub const Period: BlockNumber = 10 * MINUTES;
pub const Offset: BlockNumber = 0;
pub storage Period: BlockNumber = 10 * MINUTES;
pub storage Offset: BlockNumber = 0;
}
impl_opaque_keys! {
@@ -265,7 +265,7 @@ impl_opaque_keys! {
}
parameter_types! {
pub const DisabledValidatorsThreshold: Perbill = Perbill::from_percent(17);
pub storage DisabledValidatorsThreshold: Perbill = Perbill::from_percent(17);
}
impl session::Trait for Runtime {
@@ -299,16 +299,16 @@ pallet_staking_reward_curve::build! {
parameter_types! {
// Six sessions in an era (6 hours).
pub const SessionsPerEra: SessionIndex = 6;
pub storage SessionsPerEra: SessionIndex = 6;
// 28 eras for unbonding (7 days).
pub const BondingDuration: staking::EraIndex = 28;
pub storage BondingDuration: staking::EraIndex = 28;
// 28 eras in which slashes can be cancelled (7 days).
pub const SlashDeferDuration: staking::EraIndex = 28;
pub storage SlashDeferDuration: staking::EraIndex = 28;
pub const RewardCurve: &'static PiecewiseLinear<'static> = &REWARD_CURVE;
pub const MaxNominatorRewardedPerValidator: u32 = 64;
pub const ElectionLookahead: BlockNumber = 0;
pub const StakingUnsignedPriority: TransactionPriority = TransactionPriority::max_value() / 2;
pub const MaxIterations: u32 = 10;
pub storage MaxNominatorRewardedPerValidator: u32 = 64;
pub storage ElectionLookahead: BlockNumber = 0;
pub storage StakingUnsignedPriority: TransactionPriority = TransactionPriority::max_value() / 2;
pub storage MaxIterations: u32 = 10;
pub MinSolutionScoreBump: Perbill = Perbill::from_rational_approximation(5u32, 10_000);
}
@@ -366,12 +366,12 @@ impl attestations::Trait for Runtime {
}
parameter_types! {
pub const MaxCodeSize: u32 = 10 * 1024 * 1024; // 10 MB
pub const MaxHeadDataSize: u32 = 20 * 1024; // 20 KB
pub storage MaxCodeSize: u32 = 10 * 1024 * 1024; // 10 MB
pub storage MaxHeadDataSize: u32 = 20 * 1024; // 20 KB
pub const ValidationUpgradeFrequency: BlockNumber = 2;
pub const ValidationUpgradeDelay: BlockNumber = 1;
pub const SlashPeriod: BlockNumber = 1 * MINUTES;
pub storage ValidationUpgradeFrequency: BlockNumber = 2;
pub storage ValidationUpgradeDelay: BlockNumber = 1;
pub storage SlashPeriod: BlockNumber = 1 * MINUTES;
}
impl parachains::Trait for Runtime {
@@ -447,7 +447,7 @@ impl system::offchain::SigningTypes for Runtime {
}
parameter_types! {
pub OffencesWeightSoftLimit: Weight = Perbill::from_percent(60) * MaximumBlockWeight::get();
pub storage OffencesWeightSoftLimit: Weight = Perbill::from_percent(60) * MaximumBlockWeight::get();
}
impl offences::Trait for Runtime {
@@ -458,10 +458,12 @@ impl offences::Trait for Runtime {
type WeightInfo = ();
}
impl authority_discovery::Trait for Runtime {}
parameter_types! {
pub const ParathreadDeposit: Balance = 5 * DOLLARS;
pub storage ParathreadDeposit: Balance = 5 * DOLLARS;
pub const QueueSize: usize = 2;
pub const MaxRetries: u32 = 3;
pub storage MaxRetries: u32 = 3;
}
impl registrar::Trait for Runtime {
@@ -475,8 +477,8 @@ impl registrar::Trait for Runtime {
}
parameter_types! {
pub const LeasePeriod: BlockNumber = 100_000;
pub const EndingPeriod: BlockNumber = 1000;
pub storage LeasePeriod: BlockNumber = 100_000;
pub storage EndingPeriod: BlockNumber = 1000;
}
impl slots::Trait for Runtime {
@@ -500,7 +502,7 @@ impl claims::Trait for Runtime {
}
parameter_types! {
pub const MinVestedTransfer: Balance = 100 * DOLLARS;
pub storage MinVestedTransfer: Balance = 100 * DOLLARS;
}
impl vesting::Trait for Runtime {
@@ -511,6 +513,11 @@ impl vesting::Trait for Runtime {
type WeightInfo = ();
}
impl sudo::Trait for Runtime {
type Event = Event;
type Call = Call;
}
construct_runtime! {
pub enum Runtime where
Block = Block,
@@ -536,6 +543,7 @@ construct_runtime! {
Historical: session_historical::{Module},
Session: session::{Module, Call, Storage, Event, Config<T>},
Grandpa: grandpa::{Module, Call, Storage, Config, Event},
AuthorityDiscovery: authority_discovery::{Module, Call, Config},
// Claims. Usable initially.
Claims: claims::{Module, Call, Storage, Event<T>, Config<T>, ValidateUnsigned},
@@ -549,6 +557,9 @@ construct_runtime! {
// Vesting. Usable initially, but removed once all vesting is finished.
Vesting: vesting::{Module, Call, Storage, Event<T>, Config<T>},
// Sudo. Last module.
Sudo: sudo::{Module, Call, Storage, Config<T>, Event<T>},
}
}
@@ -642,6 +653,18 @@ sp_api::impl_runtime_apis! {
}
}
impl offchain_primitives::OffchainWorkerApi<Block> for Runtime {
fn offchain_worker(header: &<Block as BlockT>::Header) {
Executive::offchain_worker(header)
}
}
impl authority_discovery_primitives::AuthorityDiscoveryApi<Block> for Runtime {
fn authorities() -> Vec<AuthorityDiscoveryId> {
Vec::new()
}
}
impl parachain::ParachainHost<Block> for Runtime {
fn validators() -> Vec<parachain::ValidatorId> {
Parachains::authorities()
+7 -3
View File
@@ -23,7 +23,7 @@ use sp_runtime::traits::{Block as BlockT, NumberFor};
/// same last finalized block) after a given block at height `N` has been
/// finalized and for a delay of `M` blocks, i.e. until the best block reaches
/// `N` + `M`, the voter will keep voting for block `N`.
pub(crate) struct PauseAfterBlockFor<N>(pub(crate) N, pub(crate) N);
pub struct PauseAfterBlockFor<N>(pub N, pub N);
impl<Block, B> grandpa::VotingRule<Block, B> for PauseAfterBlockFor<NumberFor<Block>> where
Block: BlockT,
@@ -250,17 +250,21 @@ mod tests {
let mut push_blocks = {
let mut client = client.clone();
let mut base = 0;
move |n| {
for _ in 0..n {
for i in 0..n {
let mut builder = client.new_block(Default::default()).unwrap();
for extrinsic in polkadot_test_runtime_client::needed_extrinsics(vec![]) {
for extrinsic in polkadot_test_runtime_client::needed_extrinsics(vec![], base + i) {
builder.push(extrinsic).unwrap()
}
let block = builder.build().unwrap().block;
client.import(BlockOrigin::Own, block).unwrap();
}
base += n;
}
};
+141 -79
View File
@@ -17,7 +17,7 @@
//! Polkadot service. Specialized wrapper over substrate service.
pub mod chain_spec;
mod grandpa_support;
pub mod grandpa_support;
mod client;
use std::sync::Arc;
@@ -136,27 +136,20 @@ impl IdentifyVariant for Box<dyn ChainSpec> {
}
}
// If we're using prometheus, use a registry with a prefix of `polkadot`.
fn set_prometheus_registry(config: &mut Configuration) -> Result<(), ServiceError> {
if let Some(PrometheusConfig { registry, .. }) = config.prometheus_config.as_mut() {
*registry = Registry::new_custom(Some("polkadot".into()), None)?;
}
Ok(())
}
/// 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.
#[macro_export]
macro_rules! new_full_start {
($config:expr, $runtime:ty, $executor:ty) => {{
set_prometheus_registry(&mut $config)?;
let mut import_setup = None;
let mut rpc_setup = None;
let inherent_data_providers = inherents::InherentDataProviders::new();
let builder = service::ServiceBuilder::new_full::<
(prometheus_setup $config:expr) => {{
// If we're using prometheus, use a registry with a prefix of `polkadot`.
if let Some(PrometheusConfig { registry, .. }) = $config.prometheus_config.as_mut() {
*registry = Registry::new_custom(Some("polkadot".into()), None)?;
}
}};
(start_builder $config:expr, $runtime:ty, $executor:ty $(,)?) => {{
service::ServiceBuilder::new_full::<
Block, $runtime, $executor
>($config)?
.with_select_chain(|_, backend| {
@@ -174,56 +167,58 @@ macro_rules! new_full_start {
);
Ok(pool)
})?
.with_import_queue(|
config,
}};
(import_queue_setup
$builder:expr, $inherent_data_providers:expr, $import_setup:expr, $grandpa_hard_forks:expr, $(,)?
) => {{
$builder.with_import_queue(|
_config,
client,
mut select_chain,
_,
spawn_task_handle,
registry,
| {
let select_chain = select_chain.take()
.ok_or_else(|| service::Error::SelectChainRequired)?;
let (grandpa_block_import, grandpa_link) =
grandpa::block_import_with_authority_set_hard_forks(
client.clone(),
&(client.clone() as Arc<_>),
select_chain.clone(),
$grandpa_hard_forks,
)?;
let justification_import = grandpa_block_import.clone();
let (block_import, babe_link) = babe::block_import(
babe::Config::get_or_compute(&*client)?,
grandpa_block_import,
client.clone(),
)?;
let import_queue = babe::import_queue(
babe_link.clone(),
block_import.clone(),
Some(Box::new(justification_import)),
None,
client,
mut select_chain,
_,
select_chain,
$inherent_data_providers.clone(),
spawn_task_handle,
registry,
| {
let select_chain = select_chain.take()
.ok_or_else(|| service::Error::SelectChainRequired)?;
)?;
let grandpa_hard_forks = if config.chain_spec.is_kusama() {
grandpa_support::kusama_hard_forks()
} else {
Vec::new()
};
$import_setup = Some((block_import, grandpa_link, babe_link));
Ok(import_queue)
})?
}};
(finish_builder_setup $builder:expr, $inherent_data_providers:expr, $import_setup:expr) => {{
let mut rpc_setup = None;
let (grandpa_block_import, grandpa_link) =
grandpa::block_import_with_authority_set_hard_forks(
client.clone(),
&(client.clone() as Arc<_>),
select_chain.clone(),
grandpa_hard_forks,
)?;
let justification_import = grandpa_block_import.clone();
let (block_import, babe_link) = babe::block_import(
babe::Config::get_or_compute(&*client)?,
grandpa_block_import,
client.clone(),
)?;
let import_queue = babe::import_queue(
babe_link.clone(),
block_import.clone(),
Some(Box::new(justification_import)),
None,
client,
select_chain,
inherent_data_providers.clone(),
spawn_task_handle,
registry,
)?;
import_setup = Some((block_import, grandpa_link, babe_link));
Ok(import_queue)
})?
.with_rpc_extensions_builder(|builder| {
let grandpa_link = import_setup.as_ref().map(|s| &s.1)
let builder = $builder.with_rpc_extensions_builder(|builder| {
let grandpa_link = $import_setup.as_ref().map(|s| &s.1)
.expect("GRANDPA LinkHalf is present for full services or set up failed; qed.");
let shared_authority_set = grandpa_link.shared_authority_set().clone();
@@ -231,7 +226,7 @@ macro_rules! new_full_start {
rpc_setup = Some((shared_voter_state.clone()));
let babe_link = import_setup.as_ref().map(|s| &s.2)
let babe_link = $import_setup.as_ref().map(|s| &s.2)
.expect("BabeLink is present for full services or set up faile; qed.");
let babe_config = babe_link.config().clone();
@@ -264,22 +259,47 @@ macro_rules! new_full_start {
})
})?;
(builder, import_setup, inherent_data_providers, rpc_setup)
}}
(builder, $import_setup, $inherent_data_providers, rpc_setup)
}};
($config:expr, $runtime:ty, $executor:ty $(,)?) => {{
let inherent_data_providers = inherents::InherentDataProviders::new();
let mut import_setup = None;
new_full_start!(prometheus_setup $config);
let grandpa_hard_forks = if $config.chain_spec.is_kusama() {
$crate::grandpa_support::kusama_hard_forks()
} else {
Vec::new()
};
let builder = new_full_start!(start_builder $config, $runtime, $executor);
let builder = new_full_start!(import_queue_setup
builder, inherent_data_providers, import_setup, grandpa_hard_forks,
);
new_full_start!(finish_builder_setup builder, inherent_data_providers, import_setup)
}};
(test $config:expr, $runtime:ty, $executor:ty $(,)?) => {{
let inherent_data_providers = inherents::InherentDataProviders::new();
let mut import_setup = None;
let grandpa_hard_forks = Vec::new();
let builder = new_full_start!(start_builder $config, $runtime, $executor);
let builder = new_full_start!(import_queue_setup
builder, inherent_data_providers, import_setup, grandpa_hard_forks,
);
new_full_start!(finish_builder_setup builder, inherent_data_providers, import_setup)
}};
}
/// Builds a new service for a full client.
#[macro_export]
macro_rules! new_full {
(
with_full_start
$config:expr,
$collating_for:expr,
$max_block_data_size:expr,
$authority_discovery_enabled:expr,
$slot_duration:expr,
$grandpa_pause:expr,
$runtime:ty,
$dispatch:ty,
$new_full_start:expr $(,)?
) => {{
use sc_network::Event;
use sc_client_api::ExecutorProvider;
@@ -290,22 +310,21 @@ macro_rules! new_full {
let role = $config.role.clone();
let is_authority = role.is_authority() && !is_collator;
let force_authoring = $config.force_authoring;
let max_block_data_size = $max_block_data_size;
let db_path = match $config.database.path() {
Some(path) => std::path::PathBuf::from(path),
None => return Err("Starting a Polkadot service with a custom database isn't supported".to_string().into()),
};
let max_block_data_size = $max_block_data_size;
let disable_grandpa = $config.disable_grandpa;
let name = $config.network.node_name.clone();
let authority_discovery_enabled = $authority_discovery_enabled;
let slot_duration = $slot_duration;
let (builder, mut import_setup, inherent_data_providers, mut rpc_setup) =
new_full_start!($config, $runtime, $dispatch);
let (builder, mut import_setup, inherent_data_providers, mut rpc_setup) = $new_full_start;
let ServiceComponents {
client, network, select_chain, keystore, transaction_pool, prometheus_registry,
task_manager, telemetry_on_connect_sinks, ..
task_manager, telemetry_on_connect_sinks, rpc_handlers, ..
} = builder
.with_finality_proof_provider(|client, backend| {
let provider = client as Arc<dyn grandpa::StorageAndProofProvider<_, _>>;
@@ -510,7 +529,7 @@ macro_rules! new_full {
);
grandpa::VotingRulesBuilder::default()
.add(grandpa_support::PauseAfterBlockFor(block, delay))
.add($crate::grandpa_support::PauseAfterBlockFor(block, delay))
.build()
},
None =>
@@ -542,15 +561,58 @@ macro_rules! new_full {
}
handles.polkadot_network = Some(polkadot_network_service);
(task_manager, client, handles)
}}
(task_manager, client, handles, network, rpc_handlers)
}};
(
$config:expr,
$collating_for:expr,
$max_block_data_size:expr,
$authority_discovery_enabled:expr,
$slot_duration:expr,
$grandpa_pause:expr,
$runtime:ty,
$dispatch:ty,
) => {{
new_full!(with_full_start
$config,
$collating_for,
$max_block_data_size,
$authority_discovery_enabled,
$slot_duration,
$grandpa_pause,
new_full_start!($config, $runtime, $dispatch),
)
}};
(
test
$config:expr,
$collating_for:expr,
$max_block_data_size:expr,
$authority_discovery_enabled:expr,
$slot_duration:expr,
$runtime:ty,
$dispatch:ty,
) => {{
new_full!(with_full_start
$config,
$collating_for,
$max_block_data_size,
$authority_discovery_enabled,
$slot_duration,
None,
new_full_start!(test $config, $runtime, $dispatch),
)
}};
}
/// Builds a new service for a light client.
#[macro_export]
macro_rules! new_light {
($config:expr, $runtime:ty, $dispatch:ty) => {{
crate::set_prometheus_registry(&mut $config)?;
// If we're using prometheus, use a registry with a prefix of `polkadot`.
if let Some(PrometheusConfig { registry, .. }) = $config.prometheus_config.as_mut() {
*registry = Registry::new_custom(Some("polkadot".into()), None)?;
}
let inherent_data_providers = inherents::InherentDataProviders::new();
ServiceBuilder::new_light::<Block, $runtime, $dispatch>($config)?
@@ -646,7 +708,7 @@ macro_rules! new_light {
/// Builds a new object suitable for chain operations.
pub fn new_chain_ops<Runtime, Dispatch, Extrinsic>(mut config: Configuration) -> Result<
(
Arc<service::TFullClient<Block, Runtime, Dispatch>>,
Arc<service::TFullClient<Block, Runtime, Dispatch>>,
Arc<TFullBackend<Block>>,
consensus_common::import_queue::BasicQueue<Block, PrefixedMemoryDB<BlakeTwo256>>,
TaskManager,
@@ -685,7 +747,7 @@ pub fn polkadot_new_full(
FullNodeHandles,
), ServiceError>
{
let (service, client, handles) = new_full!(
let (service, client, handles, _, _) = new_full!(
config,
collating_for,
max_block_data_size,
@@ -719,7 +781,7 @@ pub fn kusama_new_full(
FullNodeHandles
), ServiceError>
{
let (service, client, handles) = new_full!(
let (service, client, handles, _, _) = new_full!(
config,
collating_for,
max_block_data_size,
@@ -753,7 +815,7 @@ pub fn westend_new_full(
FullNodeHandles,
), ServiceError>
{
let (service, client, handles) = new_full!(
let (service, client, handles, _, _) = new_full!(
config,
collating_for,
max_block_data_size,