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:
Alexander Theißen
2020-08-07 17:41:15 +02:00
committed by GitHub
parent 9e28ea67b6
commit bda46b0b07
63 changed files with 13517 additions and 148 deletions
-82
View File
@@ -1,82 +0,0 @@
[package]
name = 'rococo-collator'
version = '0.1.0'
authors = ["Parity Technologies <admin@parity.io>"]
build = 'build.rs'
edition = '2018'
[[bin]]
name = 'rococo-collator'
path = 'src/main.rs'
[dependencies]
derive_more = '0.15.0'
exit-future = '0.1.4'
futures = { version = "0.3.1", features = ["compat"] }
log = '0.4.8'
parking_lot = '0.9.0'
trie-root = '0.15.2'
codec = { package = 'parity-scale-codec', version = '1.0.0' }
structopt = "0.3.3"
ansi_term = "0.12.1"
serde = { version = "1.0.101", features = ["derive"] }
hex-literal = "0.2.1"
# Parachain dependencies
parachain-runtime = { package = "cumulus-test-parachain-runtime", path = "runtime" }
# Substrate dependencies
sp-runtime = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "rococo-branch" }
sp-io = { git = "https://github.com/paritytech/substrate", branch = "rococo-branch" }
sp-core = { git = "https://github.com/paritytech/substrate", branch = "rococo-branch" }
sp-inherents = { git = "https://github.com/paritytech/substrate", branch = "rococo-branch" }
sp-consensus = { git = "https://github.com/paritytech/substrate", branch = "rococo-branch" }
sc-consensus = { git = "https://github.com/paritytech/substrate", branch = "rococo-branch" }
sc-cli = { git = "https://github.com/paritytech/substrate", branch = "rococo-branch" }
sc-client-api = { git = "https://github.com/paritytech/substrate", branch = "rococo-branch" }
sc-executor = { git = "https://github.com/paritytech/substrate", branch = "rococo-branch" }
sc-service = { git = "https://github.com/paritytech/substrate", branch = "rococo-branch" }
sc-transaction-pool = { git = "https://github.com/paritytech/substrate", branch = "rococo-branch" }
sp-transaction-pool = { git = "https://github.com/paritytech/substrate", branch = "rococo-branch" }
sc-network = { git = "https://github.com/paritytech/substrate", branch = "rococo-branch" }
sc-basic-authorship = { git = "https://github.com/paritytech/substrate", branch = "rococo-branch", version = "0.8.0-rc5" }
sp-timestamp = { git = "https://github.com/paritytech/substrate", branch = "rococo-branch" }
sp-trie = { git = "https://github.com/paritytech/substrate", branch = "rococo-branch" }
sp-api = { git = "https://github.com/paritytech/substrate", branch = "rococo-branch" }
sc-finality-grandpa = { git = "https://github.com/paritytech/substrate", branch = "rococo-branch" }
sc-informant = { git = "https://github.com/paritytech/substrate", branch = "rococo-branch" }
sc-chain-spec = { git = "https://github.com/paritytech/substrate", branch = "rococo-branch" }
# Cumulus dependencies
cumulus-consensus = { path = "../../consensus" }
cumulus-collator = { path = "../../collator" }
cumulus-network = { path = "../../network" }
cumulus-primitives = { path = "../../primitives" }
# Polkadot dependencies
polkadot-primitives = { git = "https://github.com/paritytech/polkadot", branch = "rococo-branch" }
polkadot-collator = { git = "https://github.com/paritytech/polkadot", branch = "rococo-branch" }
polkadot-service = { git = "https://github.com/paritytech/polkadot", branch = "rococo-branch" }
polkadot-cli = { git = "https://github.com/paritytech/polkadot", branch = "rococo-branch" }
polkadot-test-service = { git = "https://github.com/paritytech/polkadot", branch = "rococo-branch" }
polkadot-parachain = { git = "https://github.com/paritytech/polkadot", branch = "rococo-branch" }
[build-dependencies]
substrate-build-script-utils = { git = "https://github.com/paritytech/substrate", branch = "rococo-branch" }
[dev-dependencies]
assert_cmd = "0.12"
nix = "0.17"
rand = "0.7.3"
tokio = { version = "0.2.13", features = ["macros"] }
# Polkadot dependencies
polkadot-runtime-common = { git = "https://github.com/paritytech/polkadot", branch = "rococo-branch" }
polkadot-test-runtime = { git = "https://github.com/paritytech/polkadot", branch = "rococo-branch" }
polkadot-test-runtime-client = { git = "https://github.com/paritytech/polkadot", branch = "rococo-branch" }
polkadot-test-service = { git = "https://github.com/paritytech/polkadot", branch = "rococo-branch" }
# Substrate dependencies
pallet-sudo = { git = "https://github.com/paritytech/substrate", branch = "rococo-branch" }
substrate-test-client = { git = "https://github.com/paritytech/substrate", branch = "rococo-branch" }
substrate-test-runtime-client = { git = "https://github.com/paritytech/substrate", branch = "rococo-branch" }
-22
View File
@@ -1,22 +0,0 @@
// Copyright 2019 Parity Technologies (UK) Ltd.
// This file is part of Cumulus.
// 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 Cumulus. If not, see <http://www.gnu.org/licenses/>.
use substrate_build_script_utils::{generate_cargo_keys, rerun_if_git_head_changed};
fn main() {
generate_cargo_keys();
rerun_if_git_head_changed();
}
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
-80
View File
@@ -1,80 +0,0 @@
[package]
name = 'cumulus-test-parachain-runtime'
version = '0.1.0'
authors = ["Parity Technologies <admin@parity.io>"]
edition = '2018'
[dependencies]
serde = { version = "1.0.101", optional = true, features = ["derive"] }
codec = { package = "parity-scale-codec", version = "1.3.0", default-features = false, features = ["derive"] }
# Substrate dependencies
sp-std = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "rococo-branch" }
sp-api = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "rococo-branch" }
sp-io = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "rococo-branch" }
sp-version = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "rococo-branch" }
sp-runtime = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "rococo-branch" }
sp-core = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "rococo-branch" }
sp-session = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "rococo-branch" }
sp-offchain = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "rococo-branch" }
sp-block-builder = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "rococo-branch" }
sp-transaction-pool = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "rococo-branch" }
sp-inherents = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "rococo-branch" }
frame-support = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "rococo-branch" }
frame-executive = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "rococo-branch" }
frame-system = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "rococo-branch" }
pallet-balances = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "rococo-branch" }
pallet-randomness-collective-flip = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "rococo-branch" }
pallet-timestamp = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "rococo-branch" }
pallet-sudo = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "rococo-branch" }
pallet-transaction-payment = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "rococo-branch" }
# Cumulus dependencies
cumulus-runtime = { path = "../../../runtime", default-features = false }
cumulus-parachain-upgrade = { path = "../../../parachain-upgrade", default-features = false }
cumulus-message-broker = { path = "../../../message-broker", default-features = false }
cumulus-upward-message = { path = "../../../upward-message", default-features = false }
cumulus-primitives = { path = "../../../primitives", default-features = false }
# Polkadot dependencies
polkadot-parachain = { git = "https://github.com/paritytech/polkadot", branch = "rococo-branch", default-features = false }
[build-dependencies]
wasm-builder-runner = { package = "substrate-wasm-builder-runner", version = "1.0.6" }
[features]
default = [ "std" ]
std = [
"codec/std",
"serde",
"sp-api/std",
"sp-std/std",
"sp-io/std",
"sp-core/std",
"sp-runtime/std",
"sp-version/std",
"sp-offchain/std",
"sp-session/std",
"sp-block-builder/std",
"sp-transaction-pool/std",
"sp-inherents/std",
"frame-support/std",
"frame-executive/std",
"frame-system/std",
"pallet-balances/std",
"pallet-randomness-collective-flip/std",
"pallet-timestamp/std",
"pallet-sudo/std",
"pallet-transaction-payment/std",
"cumulus-runtime/std",
"cumulus-parachain-upgrade/std",
"cumulus-message-broker/std",
"cumulus-upward-message/std",
"cumulus-primitives/std",
"polkadot-parachain/std",
]
# Will be enabled by the `wasm-builder` when building the runtime for WASM.
runtime-wasm = [
"cumulus-upward-message/runtime-wasm",
]
-26
View File
@@ -1,26 +0,0 @@
// Copyright 2019 Parity Technologies (UK) Ltd.
// This file is part of Cumulus.
// 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 Cumulus. If not, see <http://www.gnu.org/licenses/>.
use wasm_builder_runner::WasmBuilder;
fn main() {
WasmBuilder::new()
.with_current_project()
.with_wasm_builder_from_crates("2.0.0")
.export_heap_base()
.import_memory()
.build()
}
-390
View File
@@ -1,390 +0,0 @@
// 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/>.
#![cfg_attr(not(feature = "std"), no_std)]
// `construct_runtime!` does a lot of recursion and requires us to increase the limit to 256.
#![recursion_limit = "256"]
// Make the WASM binary available.
#[cfg(feature = "std")]
include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs"));
use sp_api::impl_runtime_apis;
use sp_core::OpaqueMetadata;
use sp_runtime::{
create_runtime_str, generic, impl_opaque_keys,
traits::{BlakeTwo256, Block as BlockT, IdentifyAccount, IdentityLookup, Saturating, Verify},
transaction_validity::{TransactionSource, TransactionValidity},
ApplyExtrinsicResult, MultiSignature,
};
use sp_std::prelude::*;
#[cfg(feature = "std")]
use sp_version::NativeVersion;
use sp_version::RuntimeVersion;
mod message_example;
// A few exports that help ease life for downstream crates.
pub use frame_support::{
construct_runtime, parameter_types,
traits::Randomness,
weights::{constants::WEIGHT_PER_SECOND, IdentityFee, Weight},
StorageValue,
};
pub use pallet_balances::Call as BalancesCall;
pub use pallet_timestamp::Call as TimestampCall;
#[cfg(any(feature = "std", test))]
pub use sp_runtime::BuildStorage;
pub use sp_runtime::{Perbill, Permill};
/// An index to a block.
pub type BlockNumber = u32;
/// Alias to 512-bit hash when used in the context of a transaction signature on the chain.
pub type Signature = MultiSignature;
/// Some way of identifying an account on the chain. We intentionally make it equivalent
/// to the public key of our transaction signing scheme.
pub type AccountId = <<Signature as Verify>::Signer as IdentifyAccount>::AccountId;
/// The type for looking up accounts. We don't expect more than 4 billion of them, but you
/// never know...
pub type AccountIndex = u32;
/// Balance of an account.
pub type Balance = u128;
/// Index of a transaction in the chain.
pub type Index = u32;
/// A hash of some data used by the chain.
pub type Hash = sp_core::H256;
/// Digest item type.
pub type DigestItem = generic::DigestItem<Hash>;
/// Opaque types. These are used by the CLI to instantiate machinery that don't need to know
/// the specifics of the runtime. They can then be made to be agnostic over specific formats
/// of data like extrinsics, allowing for them to continue syncing the network through upgrades
/// to even the core datastructures.
pub mod opaque {
use super::*;
pub use sp_runtime::OpaqueExtrinsic as UncheckedExtrinsic;
/// Opaque block header type.
pub type Header = generic::Header<BlockNumber, BlakeTwo256>;
/// Opaque block type.
pub type Block = generic::Block<Header, UncheckedExtrinsic>;
/// Opaque block identifier type.
pub type BlockId = generic::BlockId<Block>;
pub type SessionHandlers = ();
impl_opaque_keys! {
pub struct SessionKeys {}
}
}
/// This runtime version.
pub const VERSION: RuntimeVersion = RuntimeVersion {
spec_name: create_runtime_str!("cumulus-test-parachain"),
impl_name: create_runtime_str!("cumulus-test-parachain"),
authoring_version: 1,
spec_version: 1,
impl_version: 1,
apis: RUNTIME_API_VERSIONS,
transaction_version: 1,
};
pub const MILLISECS_PER_BLOCK: u64 = 6000;
pub const SLOT_DURATION: u64 = MILLISECS_PER_BLOCK;
pub const EPOCH_DURATION_IN_BLOCKS: u32 = 10 * MINUTES;
// These time units are defined in number of blocks.
pub const MINUTES: BlockNumber = 60_000 / (MILLISECS_PER_BLOCK as BlockNumber);
pub const HOURS: BlockNumber = MINUTES * 60;
pub const DAYS: BlockNumber = HOURS * 24;
// 1 in 4 blocks (on average, not counting collisions) will be primary babe blocks.
pub const PRIMARY_PROBABILITY: (u64, u64) = (1, 4);
#[derive(codec::Encode, codec::Decode)]
pub enum XCMPMessage<XAccountId, XBalance> {
/// Transfer tokens to the given account from the Parachain account.
TransferToken(XAccountId, XBalance),
}
/// The version infromation used to identify this runtime when compiled natively.
#[cfg(feature = "std")]
pub fn native_version() -> NativeVersion {
NativeVersion {
runtime_version: VERSION,
can_author_with: Default::default(),
}
}
parameter_types! {
pub const BlockHashCount: BlockNumber = 250;
pub const MaximumBlockWeight: Weight = 2 * WEIGHT_PER_SECOND;
/// Assume 10% of weight for average on_initialize calls.
pub MaximumExtrinsicWeight: Weight = AvailableBlockRatio::get()
.saturating_sub(Perbill::from_percent(10)) * MaximumBlockWeight::get();
pub const AvailableBlockRatio: Perbill = Perbill::from_percent(75);
pub const MaximumBlockLength: u32 = 5 * 1024 * 1024;
pub const Version: RuntimeVersion = VERSION;
pub const ExtrinsicBaseWeight: Weight = 10_000_000;
}
impl frame_system::Trait for Runtime {
/// The identifier used to distinguish between accounts.
type AccountId = AccountId;
/// The aggregated dispatch type that is available for extrinsics.
type Call = Call;
/// The lookup mechanism to get account ID from whatever is passed in dispatchers.
type Lookup = IdentityLookup<AccountId>;
/// The index type for storing how many extrinsics an account has signed.
type Index = Index;
/// The index type for blocks.
type BlockNumber = BlockNumber;
/// The type for hashing blocks and tries.
type Hash = Hash;
/// The hashing algorithm used.
type Hashing = BlakeTwo256;
/// The header type.
type Header = generic::Header<BlockNumber, BlakeTwo256>;
/// The ubiquitous event type.
type Event = Event;
/// The ubiquitous origin type.
type Origin = Origin;
/// Maximum number of block number to block hash mappings to keep (oldest pruned first).
type BlockHashCount = BlockHashCount;
/// Maximum weight of each block. With a default weight system of 1byte == 1weight, 4mb is ok.
type MaximumBlockWeight = MaximumBlockWeight;
/// Maximum size of all encoded transactions (in bytes) that are allowed in one block.
type MaximumBlockLength = MaximumBlockLength;
/// Portion of the block weight that is available to all normal transactions.
type AvailableBlockRatio = AvailableBlockRatio;
/// Runtime version.
type Version = Version;
/// Converts a module to an index of this module in the runtime.
type ModuleToIndex = ModuleToIndex;
type AccountData = pallet_balances::AccountData<Balance>;
type OnNewAccount = ();
type OnKilledAccount = ();
type DbWeight = ();
type ExtrinsicBaseWeight = ExtrinsicBaseWeight;
type BlockExecutionWeight = ();
type MaximumExtrinsicWeight = MaximumExtrinsicWeight;
type BaseCallFilter = ();
type SystemWeightInfo = ();
}
parameter_types! {
pub const MinimumPeriod: u64 = SLOT_DURATION / 2;
}
impl pallet_timestamp::Trait for Runtime {
/// A timestamp: milliseconds since the unix epoch.
type Moment = u64;
type OnTimestampSet = ();
type MinimumPeriod = MinimumPeriod;
type WeightInfo = ();
}
parameter_types! {
pub const ExistentialDeposit: u128 = 500;
pub const TransferFee: u128 = 0;
pub const CreationFee: u128 = 0;
pub const TransactionByteFee: u128 = 1;
}
impl pallet_balances::Trait for Runtime {
/// The type for recording an account's balance.
type Balance = Balance;
/// The ubiquitous event type.
type Event = Event;
type DustRemoval = ();
type ExistentialDeposit = ExistentialDeposit;
type AccountStore = System;
type WeightInfo = ();
}
impl pallet_transaction_payment::Trait for Runtime {
type Currency = Balances;
type OnTransactionPayment = ();
type TransactionByteFee = TransactionByteFee;
type WeightToFee = IdentityFee<Balance>;
type FeeMultiplierUpdate = ();
}
impl pallet_sudo::Trait for Runtime {
type Call = Call;
type Event = Event;
}
impl cumulus_parachain_upgrade::Trait for Runtime {
type Event = Event;
type OnValidationFunctionParams = ();
}
parameter_types! {
pub storage ParachainId: cumulus_primitives::ParaId = 100.into();
}
impl cumulus_message_broker::Trait for Runtime {
type Event = Event;
type DownwardMessageHandlers = TokenDealer;
type UpwardMessage = cumulus_upward_message::RococoUpwardMessage;
type ParachainId = ParachainId;
type XCMPMessage = XCMPMessage<AccountId, Balance>;
type XCMPMessageHandlers = TokenDealer;
}
impl message_example::Trait for Runtime {
type Event = Event;
type UpwardMessageSender = MessageBroker;
type UpwardMessage = cumulus_upward_message::RococoUpwardMessage;
type Currency = Balances;
type XCMPMessageSender = MessageBroker;
}
construct_runtime! {
pub enum Runtime where
Block = Block,
NodeBlock = opaque::Block,
UncheckedExtrinsic = UncheckedExtrinsic
{
System: frame_system::{Module, Call, Storage, Config, Event<T>},
Timestamp: pallet_timestamp::{Module, Call, Storage, Inherent},
Balances: pallet_balances::{Module, Call, Storage, Config<T>, Event<T>},
Sudo: pallet_sudo::{Module, Call, Storage, Config<T>, Event<T>},
RandomnessCollectiveFlip: pallet_randomness_collective_flip::{Module, Call, Storage},
ParachainUpgrade: cumulus_parachain_upgrade::{Module, Call, Storage, Inherent, Event},
MessageBroker: cumulus_message_broker::{Module, Call, Inherent, Event<T>},
TokenDealer: message_example::{Module, Call, Event<T>, Config},
TransactionPayment: pallet_transaction_payment::{Module, Storage},
}
}
/// The address format for describing accounts.
pub type Address = AccountId;
/// Block header type as expected by this runtime.
pub type Header = generic::Header<BlockNumber, BlakeTwo256>;
/// Block type as expected by this runtime.
pub type Block = generic::Block<Header, UncheckedExtrinsic>;
/// A Block signed with a Justification
pub type SignedBlock = generic::SignedBlock<Block>;
/// BlockId type as expected by this runtime.
pub type BlockId = generic::BlockId<Block>;
/// The SignedExtension to the basic transaction logic.
pub type SignedExtra = (
frame_system::CheckSpecVersion<Runtime>,
frame_system::CheckGenesis<Runtime>,
frame_system::CheckEra<Runtime>,
frame_system::CheckNonce<Runtime>,
frame_system::CheckWeight<Runtime>,
pallet_transaction_payment::ChargeTransactionPayment<Runtime>,
);
/// Unchecked extrinsic type as expected by this runtime.
pub type UncheckedExtrinsic = generic::UncheckedExtrinsic<Address, Call, Signature, SignedExtra>;
/// Extrinsic type that has already been checked.
pub type CheckedExtrinsic = generic::CheckedExtrinsic<AccountId, Call, SignedExtra>;
/// Executive: handles dispatch to the various modules.
pub type Executive = frame_executive::Executive<
Runtime,
Block,
frame_system::ChainContext<Runtime>,
Runtime,
AllModules,
>;
impl_runtime_apis! {
impl sp_api::Core<Block> for Runtime {
fn version() -> RuntimeVersion {
VERSION
}
fn execute_block(block: Block) {
Executive::execute_block(block)
}
fn initialize_block(header: &<Block as BlockT>::Header) {
Executive::initialize_block(header)
}
}
impl sp_api::Metadata<Block> for Runtime {
fn metadata() -> OpaqueMetadata {
Runtime::metadata().into()
}
}
impl sp_block_builder::BlockBuilder<Block> for Runtime {
fn apply_extrinsic(
extrinsic: <Block as BlockT>::Extrinsic,
) -> ApplyExtrinsicResult {
Executive::apply_extrinsic(extrinsic)
}
fn finalize_block() -> <Block as BlockT>::Header {
Executive::finalize_block()
}
fn inherent_extrinsics(data: sp_inherents::InherentData) -> Vec<<Block as BlockT>::Extrinsic> {
data.create_extrinsics()
}
fn check_inherents(block: Block, data: sp_inherents::InherentData) -> sp_inherents::CheckInherentsResult {
data.check_extrinsics(&block)
}
fn random_seed() -> <Block as BlockT>::Hash {
RandomnessCollectiveFlip::random_seed()
}
}
impl sp_transaction_pool::runtime_api::TaggedTransactionQueue<Block> for Runtime {
fn validate_transaction(
source: TransactionSource,
tx: <Block as BlockT>::Extrinsic,
) -> TransactionValidity {
Executive::validate_transaction(source, tx)
}
}
impl sp_offchain::OffchainWorkerApi<Block> for Runtime {
fn offchain_worker(header: &<Block as BlockT>::Header) {
Executive::offchain_worker(header)
}
}
impl sp_session::SessionKeys<Block> for Runtime {
fn decode_session_keys(
encoded: Vec<u8>,
) -> Option<Vec<(Vec<u8>, sp_core::crypto::KeyTypeId)>> {
opaque::SessionKeys::decode_into_raw_public_keys(&encoded)
}
fn generate_session_keys(seed: Option<Vec<u8>>) -> Vec<u8> {
opaque::SessionKeys::generate(seed)
}
}
}
cumulus_runtime::register_validate_block!(Block, Executive);
@@ -1,179 +0,0 @@
// Copyright 2020 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/>.
//! Example Pallet that shows how to send upward messages and how to receive
//! downward messages.
use frame_support::{
decl_event, decl_module, decl_storage,
traits::{Currency, ExistenceRequirement, WithdrawReason},
};
use frame_system::ensure_signed;
use crate::XCMPMessage;
use codec::{Decode, Encode};
use cumulus_primitives::{
relay_chain::DownwardMessage,
xcmp::{XCMPMessageHandler, XCMPMessageSender},
DownwardMessageHandler, ParaId, UpwardMessageOrigin, UpwardMessageSender,
};
use cumulus_upward_message::BalancesMessage;
use polkadot_parachain::primitives::AccountIdConversion;
use sp_runtime::DispatchResult;
type BalanceOf<T> =
<<T as Trait>::Currency as Currency<<T as frame_system::Trait>::AccountId>>::Balance;
/// Configuration trait of this pallet.
pub trait Trait: frame_system::Trait {
/// Event type used by the runtime.
type Event: From<Event<Self>> + Into<<Self as frame_system::Trait>::Event>;
/// The sender of upward messages.
type UpwardMessageSender: UpwardMessageSender<Self::UpwardMessage>;
/// The upward message type used by the Parachain runtime.
type UpwardMessage: codec::Codec + BalancesMessage<Self::AccountId, BalanceOf<Self>>;
/// Currency of the runtime.
type Currency: Currency<Self::AccountId>;
/// The sender of XCMP messages.
type XCMPMessageSender: XCMPMessageSender<XCMPMessage<Self::AccountId, BalanceOf<Self>>>;
}
// This pallet's storage items.
decl_storage! {
trait Store for Module<T: Trait> as ParachainUpgrade {}
add_extra_genesis {
config(parachain_id): ParaId;
build(|config: &Self| {
// This is basically a hack to make the parachain id easily configurable.
// Could also be done differently, but yeah..
crate::ParachainId::set(&config.parachain_id);
});
}
}
decl_event! {
pub enum Event<T> where
AccountId = <T as frame_system::Trait>::AccountId,
Balance = BalanceOf<T>
{
/// Transferred tokens to the account on the relay chain.
TransferredTokensToRelayChain(AccountId, Balance),
/// Transferred tokens to the account on request from the relay chain.
TransferredTokensFromRelayChain(AccountId, Balance),
/// Transferred tokens to the account from the given parachain account.
TransferredTokensViaXCMP(ParaId, AccountId, Balance, DispatchResult),
}
}
decl_module! {
pub struct Module<T: Trait> for enum Call where origin: T::Origin, system = frame_system {
/// Transfer `amount` of tokens on the relay chain from the Parachain account to
/// the given `dest` account.
#[weight = 10]
fn transfer_tokens_to_relay_chain(origin, dest: T::AccountId, amount: BalanceOf<T>) {
let who = ensure_signed(origin)?;
let _ = T::Currency::withdraw(
&who,
amount,
WithdrawReason::Transfer.into(),
ExistenceRequirement::AllowDeath,
)?;
let msg = <T as Trait>::UpwardMessage::transfer(dest.clone(), amount.clone());
<T as Trait>::UpwardMessageSender::send_upward_message(&msg, UpwardMessageOrigin::Signed)
.expect("Should not fail; qed");
Self::deposit_event(Event::<T>::TransferredTokensToRelayChain(dest, amount));
}
/// Transfer `amount` of tokens to another parachain.
#[weight = 10]
fn transfer_tokens_to_parachain_chain(
origin,
para_id: u32,
dest: T::AccountId,
amount: BalanceOf<T>,
) {
//TODO we don't make sure that the parachain has some tokens on the other parachain.
let who = ensure_signed(origin)?;
let _ = T::Currency::withdraw(
&who,
amount,
WithdrawReason::Transfer.into(),
ExistenceRequirement::AllowDeath,
)?;
T::XCMPMessageSender::send_xcmp_message(
para_id.into(),
&XCMPMessage::TransferToken(dest, amount),
).expect("Should not fail; qed");
}
fn deposit_event() = default;
}
}
/// This is a hack to convert from one generic type to another where we are sure that both are the
/// same type/use the same encoding.
fn convert_hack<O: Decode>(input: &impl Encode) -> O {
input.using_encoded(|e| Decode::decode(&mut &e[..]).expect("Must be compatible; qed"))
}
impl<T: Trait> DownwardMessageHandler for Module<T> {
fn handle_downward_message(msg: &DownwardMessage) {
match msg {
DownwardMessage::TransferInto(dest, amount, _) => {
let dest = convert_hack(&dest);
let amount: BalanceOf<T> = convert_hack(amount);
let _ = T::Currency::deposit_creating(&dest, amount.clone());
Self::deposit_event(Event::<T>::TransferredTokensFromRelayChain(dest, amount));
}
_ => {}
}
}
}
impl<T: Trait> XCMPMessageHandler<XCMPMessage<T::AccountId, BalanceOf<T>>> for Module<T> {
fn handle_xcmp_message(src: ParaId, msg: &XCMPMessage<T::AccountId, BalanceOf<T>>) {
match msg {
XCMPMessage::TransferToken(dest, amount) => {
let para_account = src.clone().into_account();
let res = T::Currency::transfer(
&para_account,
dest,
amount.clone(),
ExistenceRequirement::AllowDeath,
);
Self::deposit_event(Event::<T>::TransferredTokensViaXCMP(
src,
dest.clone(),
amount.clone(),
res,
));
}
}
}
}
-145
View File
@@ -1,145 +0,0 @@
// 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 }),
}
}
-126
View File
@@ -1,126 +0,0 @@
// 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),
}
}
}
-451
View File
@@ -1,451 +0,0 @@
// 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 {
&parachain_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(&params.chain.clone().unwrap_or_default())?)?;
let header_hex = format!("0x{:?}", HexDisplay::from(&block.header().encode()));
if let Some(output) = &params.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(&params.chain.clone().unwrap_or_default())?)?;
if let Some(output) = &params.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")
}
}
-212
View File
@@ -1,212 +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/>.
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,
})
}
-32
View File
@@ -1,32 +0,0 @@
// 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()
}
-252
View File
@@ -1,252 +0,0 @@
// 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: &parachain_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_handlers = sc_service::spawn_tasks(sc_service::SpawnTasksParams {
on_demand: None,
remote_blockchain: None,
rpc_extensions_builder: Box::new(|_| ()),
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,
)));
}
}
-38
View File
@@ -1,38 +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/>.
use std::{
process::{Child, ExitStatus},
thread,
time::Duration,
};
/// Wait for the given `child` the given ammount of `secs`.
///
/// Returns the `Some(exit status)` or `None` if the process did not finish in the given time.
pub fn wait_for(child: &mut Child, secs: usize) -> Option<ExitStatus> {
for _ in 0..secs {
match child.try_wait().unwrap() {
Some(status) => return Some(status),
None => thread::sleep(Duration::from_secs(1)),
}
}
eprintln!("Took to long to exit. Killing...");
let _ = child.kill();
child.wait().unwrap();
None
}
@@ -1,65 +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/>.
use assert_cmd::cargo::cargo_bin;
use std::{convert::TryInto, fs, process::Command, thread, time::Duration};
mod common;
#[test]
#[cfg(unix)]
fn polkadot_argument_parsing() {
use nix::{
sys::signal::{
kill,
Signal::{self, SIGINT, SIGTERM},
},
unistd::Pid,
};
fn run_command_and_kill(signal: Signal) {
let _ = fs::remove_dir_all("polkadot_argument_parsing");
let mut cmd = Command::new(cargo_bin("rococo-collator"))
.args(&[
"-d",
"polkadot_argument_parsing",
"--",
"--dev",
"--bootnodes",
"/ip4/127.0.0.1/tcp/30333/p2p/Qmbx43psh7LVkrYTRXisUpzCubbgYojkejzAgj5mteDnxy",
"--bootnodes",
"/ip4/127.0.0.1/tcp/50500/p2p/Qma6SpS7tzfCrhtgEVKR9Uhjmuv55ovC3kY6y6rPBxpWde",
])
.spawn()
.unwrap();
thread::sleep(Duration::from_secs(20));
assert!(
cmd.try_wait().unwrap().is_none(),
"the process should still be running"
);
kill(Pid::from_raw(cmd.id().try_into().unwrap()), signal).unwrap();
assert_eq!(
common::wait_for(&mut cmd, 30).map(|x| x.success()),
Some(true),
"the process must exit gracefully after signal {}",
signal,
);
}
run_command_and_kill(SIGINT);
run_command_and_kill(SIGTERM);
}
@@ -1,56 +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/>.
use assert_cmd::cargo::cargo_bin;
use std::{convert::TryInto, fs, process::Command, thread, time::Duration};
mod common;
#[test]
#[cfg(unix)]
fn interrupt_polkadot_mdns_issue_test() {
use nix::{
sys::signal::{
kill,
Signal::{self, SIGINT, SIGTERM},
},
unistd::Pid,
};
fn run_command_and_kill(signal: Signal) {
let _ = fs::remove_dir_all("interrupt_polkadot_mdns_issue_test");
let mut cmd = Command::new(cargo_bin("rococo-collator"))
.args(&["-d", "interrupt_polkadot_mdns_issue_test", "--", "--dev"])
.spawn()
.unwrap();
thread::sleep(Duration::from_secs(20));
assert!(
cmd.try_wait().unwrap().is_none(),
"the process should still be running"
);
kill(Pid::from_raw(cmd.id().try_into().unwrap()), signal).unwrap();
assert_eq!(
common::wait_for(&mut cmd, 30).map(|x| x.success()),
Some(true),
"the process must exit gracefully after signal {}",
signal,
);
}
run_command_and_kill(SIGINT);
run_command_and_kill(SIGTERM);
}
-64
View File
@@ -1,64 +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/>.
use assert_cmd::cargo::cargo_bin;
use std::{convert::TryInto, fs, path::PathBuf, process::Command, thread, time::Duration};
mod common;
#[test]
#[cfg(unix)]
fn purge_chain_works() {
use nix::{
sys::signal::{kill, Signal::SIGINT},
unistd::Pid,
};
let base_path = "purge_chain_test";
let _ = fs::remove_dir_all(base_path);
let mut cmd = Command::new(cargo_bin("rococo-collator"))
.args(&["-d", base_path, "--", "--dev"])
.spawn()
.unwrap();
// Let it produce some blocks.
thread::sleep(Duration::from_secs(30));
assert!(
cmd.try_wait().unwrap().is_none(),
"the process should still be running"
);
// Stop the process
kill(Pid::from_raw(cmd.id().try_into().unwrap()), SIGINT).unwrap();
assert!(common::wait_for(&mut cmd, 30)
.map(|x| x.success())
.unwrap_or_default());
let status = Command::new(cargo_bin("rococo-collator"))
.args(&["purge-chain", "-d", base_path, "-y"])
.status()
.unwrap();
assert!(status.success());
// Make sure that the `parachain_local_testnet` chain folder exists, but the `db` is deleted.
assert!(PathBuf::from(base_path)
.join("chains/local_testnet/")
.exists());
assert!(!PathBuf::from(base_path)
.join("chains/local_testnet/db")
.exists());
}
@@ -1,56 +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/>.
use assert_cmd::cargo::cargo_bin;
use std::{convert::TryInto, fs, process::Command, thread, time::Duration};
mod common;
#[test]
#[cfg(unix)]
fn running_the_node_works_and_can_be_interrupted() {
use nix::{
sys::signal::{
kill,
Signal::{self, SIGINT, SIGTERM},
},
unistd::Pid,
};
fn run_command_and_kill(signal: Signal) {
let _ = fs::remove_dir_all("interrupt_test");
let mut cmd = Command::new(cargo_bin("rococo-collator"))
.args(&["-d", "interrupt_test", "--", "--dev"])
.spawn()
.unwrap();
thread::sleep(Duration::from_secs(30));
assert!(
cmd.try_wait().unwrap().is_none(),
"the process should still be running"
);
kill(Pid::from_raw(cmd.id().try_into().unwrap()), signal).unwrap();
assert_eq!(
common::wait_for(&mut cmd, 30).map(|x| x.success()),
Some(true),
"the process must exit gracefully after signal {}",
signal,
);
}
run_command_and_kill(SIGINT);
run_command_and_kill(SIGTERM);
}