mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-13 01:11:10 +00:00
@@ -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")
|
||||
}
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user