mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-05-30 21:01:02 +00:00
bye bye tes-runner (#4680)
This commit is contained in:
Generated
-132
@@ -7158,59 +7158,6 @@ dependencies = [
|
|||||||
"westend-runtime-constants",
|
"westend-runtime-constants",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "polkadot-simnet"
|
|
||||||
version = "0.9.13"
|
|
||||||
dependencies = [
|
|
||||||
"frame-benchmarking",
|
|
||||||
"frame-support",
|
|
||||||
"frame-system",
|
|
||||||
"log",
|
|
||||||
"pallet-collective",
|
|
||||||
"pallet-democracy",
|
|
||||||
"pallet-transaction-payment",
|
|
||||||
"parity-scale-codec",
|
|
||||||
"polkadot-cli",
|
|
||||||
"polkadot-primitives",
|
|
||||||
"polkadot-runtime",
|
|
||||||
"polkadot-runtime-common",
|
|
||||||
"polkadot-service",
|
|
||||||
"sc-cli",
|
|
||||||
"sc-consensus",
|
|
||||||
"sc-consensus-babe",
|
|
||||||
"sc-consensus-manual-seal",
|
|
||||||
"sc-executor",
|
|
||||||
"sc-finality-grandpa",
|
|
||||||
"sc-service",
|
|
||||||
"sc-tracing",
|
|
||||||
"sp-consensus-babe",
|
|
||||||
"sp-keyring",
|
|
||||||
"sp-runtime",
|
|
||||||
"structopt",
|
|
||||||
"test-runner",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "polkadot-simnet-node"
|
|
||||||
version = "0.9.13"
|
|
||||||
dependencies = [
|
|
||||||
"polkadot-simnet",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "polkadot-simnet-test"
|
|
||||||
version = "0.9.13"
|
|
||||||
dependencies = [
|
|
||||||
"frame-system",
|
|
||||||
"pallet-balances",
|
|
||||||
"polkadot-runtime",
|
|
||||||
"polkadot-simnet",
|
|
||||||
"sc-client-api",
|
|
||||||
"sp-blockchain",
|
|
||||||
"sp-core",
|
|
||||||
"sp-runtime",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "polkadot-statement-distribution"
|
name = "polkadot-statement-distribution"
|
||||||
version = "0.9.13"
|
version = "0.9.13"
|
||||||
@@ -8598,40 +8545,6 @@ dependencies = [
|
|||||||
"sp-runtime",
|
"sp-runtime",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "sc-consensus-manual-seal"
|
|
||||||
version = "0.10.0-dev"
|
|
||||||
source = "git+https://github.com/paritytech/substrate?branch=master#b54c21f354fd973e6a35a53c37b317ae293dbfc8"
|
|
||||||
dependencies = [
|
|
||||||
"assert_matches",
|
|
||||||
"async-trait",
|
|
||||||
"derive_more",
|
|
||||||
"futures 0.3.19",
|
|
||||||
"jsonrpc-core",
|
|
||||||
"jsonrpc-core-client",
|
|
||||||
"jsonrpc-derive",
|
|
||||||
"log",
|
|
||||||
"parity-scale-codec",
|
|
||||||
"sc-client-api",
|
|
||||||
"sc-consensus",
|
|
||||||
"sc-consensus-babe",
|
|
||||||
"sc-consensus-epochs",
|
|
||||||
"sc-transaction-pool",
|
|
||||||
"sc-transaction-pool-api",
|
|
||||||
"serde",
|
|
||||||
"sp-api",
|
|
||||||
"sp-blockchain",
|
|
||||||
"sp-consensus",
|
|
||||||
"sp-consensus-babe",
|
|
||||||
"sp-consensus-slots",
|
|
||||||
"sp-core",
|
|
||||||
"sp-inherents",
|
|
||||||
"sp-keystore",
|
|
||||||
"sp-runtime",
|
|
||||||
"sp-timestamp",
|
|
||||||
"substrate-prometheus-endpoint",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "sc-consensus-slots"
|
name = "sc-consensus-slots"
|
||||||
version = "0.10.0-dev"
|
version = "0.10.0-dev"
|
||||||
@@ -10771,51 +10684,6 @@ dependencies = [
|
|||||||
"tiny-keccak",
|
"tiny-keccak",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "test-runner"
|
|
||||||
version = "0.9.0"
|
|
||||||
source = "git+https://github.com/paritytech/substrate?branch=master#b54c21f354fd973e6a35a53c37b317ae293dbfc8"
|
|
||||||
dependencies = [
|
|
||||||
"frame-system",
|
|
||||||
"futures 0.3.19",
|
|
||||||
"jsonrpc-core",
|
|
||||||
"log",
|
|
||||||
"num-traits",
|
|
||||||
"sc-basic-authorship",
|
|
||||||
"sc-cli",
|
|
||||||
"sc-client-api",
|
|
||||||
"sc-consensus",
|
|
||||||
"sc-consensus-babe",
|
|
||||||
"sc-consensus-manual-seal",
|
|
||||||
"sc-executor",
|
|
||||||
"sc-finality-grandpa",
|
|
||||||
"sc-informant",
|
|
||||||
"sc-network",
|
|
||||||
"sc-rpc",
|
|
||||||
"sc-rpc-server",
|
|
||||||
"sc-service",
|
|
||||||
"sc-transaction-pool",
|
|
||||||
"sc-transaction-pool-api",
|
|
||||||
"sp-api",
|
|
||||||
"sp-block-builder",
|
|
||||||
"sp-blockchain",
|
|
||||||
"sp-consensus",
|
|
||||||
"sp-consensus-babe",
|
|
||||||
"sp-core",
|
|
||||||
"sp-externalities",
|
|
||||||
"sp-finality-grandpa",
|
|
||||||
"sp-inherents",
|
|
||||||
"sp-keyring",
|
|
||||||
"sp-offchain",
|
|
||||||
"sp-runtime",
|
|
||||||
"sp-runtime-interface",
|
|
||||||
"sp-session",
|
|
||||||
"sp-state-machine",
|
|
||||||
"sp-transaction-pool",
|
|
||||||
"sp-wasm-interface",
|
|
||||||
"tokio",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "test-runtime-constants"
|
name = "test-runtime-constants"
|
||||||
version = "0.9.13"
|
version = "0.9.13"
|
||||||
|
|||||||
@@ -92,9 +92,6 @@ members = [
|
|||||||
"node/test/client",
|
"node/test/client",
|
||||||
"node/test/performance-test",
|
"node/test/performance-test",
|
||||||
"node/test/service",
|
"node/test/service",
|
||||||
"node/test/polkadot-simnet/common",
|
|
||||||
"node/test/polkadot-simnet/node",
|
|
||||||
"node/test/polkadot-simnet/test",
|
|
||||||
"node/zombienet-backchannel",
|
"node/zombienet-backchannel",
|
||||||
"parachain/test-parachains",
|
"parachain/test-parachains",
|
||||||
"parachain/test-parachains/adder",
|
"parachain/test-parachains/adder",
|
||||||
|
|||||||
@@ -1,39 +0,0 @@
|
|||||||
[package]
|
|
||||||
name = "polkadot-simnet"
|
|
||||||
version = "0.9.13"
|
|
||||||
authors = ["Parity Technologies <admin@parity.io>"]
|
|
||||||
edition = "2018"
|
|
||||||
|
|
||||||
[dependencies]
|
|
||||||
system = { package = "frame-system", git = "https://github.com/paritytech/substrate", branch = "master" }
|
|
||||||
support = { package = "frame-support", git = "https://github.com/paritytech/substrate", branch = "master" }
|
|
||||||
benchmarking = { package = "frame-benchmarking", git = "https://github.com/paritytech/substrate", branch = "master" }
|
|
||||||
transaction-payment = { package = "pallet-transaction-payment", git = "https://github.com/paritytech/substrate", branch = "master" }
|
|
||||||
collective = { package = "pallet-collective", git = "https://github.com/paritytech/substrate", branch = "master" }
|
|
||||||
democracy = { package = "pallet-democracy", git = "https://github.com/paritytech/substrate", branch = "master" }
|
|
||||||
|
|
||||||
test-runner = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
|
||||||
grandpa = { package = "sc-finality-grandpa", git = "https://github.com/paritytech/substrate", branch = "master" }
|
|
||||||
sc-consensus-babe = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
|
||||||
sc-consensus-manual-seal = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
|
||||||
sc-service = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
|
||||||
sc-executor = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
|
||||||
sc-consensus = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
|
||||||
sc-tracing = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
|
||||||
sc-cli = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
|
||||||
|
|
||||||
sp-consensus-babe = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
|
||||||
sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
|
||||||
sp-keyring = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
|
||||||
|
|
||||||
polkadot-primitives = { path = "../../../../primitives" }
|
|
||||||
polkadot-cli = { path = "../../../../cli", features = ["cli"] }
|
|
||||||
polkadot-service = { path = "../../../../node/service" }
|
|
||||||
polkadot-runtime = { path = "../../../../runtime/polkadot" }
|
|
||||||
polkadot-runtime-common = { path = "../../../../runtime/common" }
|
|
||||||
|
|
||||||
codec = { package = "parity-scale-codec", version = "2.0.0" }
|
|
||||||
structopt = "0.3.25"
|
|
||||||
|
|
||||||
[dev-dependencies]
|
|
||||||
log = "0.4.14"
|
|
||||||
@@ -1,449 +0,0 @@
|
|||||||
// 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/>.
|
|
||||||
|
|
||||||
#![deny(unused_extern_crates, missing_docs)]
|
|
||||||
|
|
||||||
//! Utilities for End to end runtime tests
|
|
||||||
|
|
||||||
use codec::Encode;
|
|
||||||
use democracy::{AccountVote, Conviction, Vote};
|
|
||||||
use grandpa::GrandpaBlockImport;
|
|
||||||
use polkadot_runtime::{
|
|
||||||
CouncilCollective, Event, FastTrackVotingPeriod, Runtime, RuntimeApi, TechnicalCollective,
|
|
||||||
};
|
|
||||||
use polkadot_runtime_common::claims;
|
|
||||||
use sc_consensus_babe::BabeBlockImport;
|
|
||||||
use sc_consensus_manual_seal::consensus::babe::SlotTimestampProvider;
|
|
||||||
use sc_executor::NativeElseWasmExecutor;
|
|
||||||
use sc_service::{TFullBackend, TFullClient};
|
|
||||||
use sp_runtime::{app_crypto::sp_core::H256, generic::Era, AccountId32};
|
|
||||||
use std::{error::Error, future::Future, str::FromStr};
|
|
||||||
use support::weights::Weight;
|
|
||||||
use test_runner::{
|
|
||||||
build_runtime, client_parts, ChainInfo, ConfigOrChainSpec, Node, SignatureVerificationOverride,
|
|
||||||
};
|
|
||||||
|
|
||||||
type BlockImport<B, BE, C, SC> = BabeBlockImport<B, C, GrandpaBlockImport<BE, B, C, SC>>;
|
|
||||||
type Block = polkadot_primitives::v1::Block;
|
|
||||||
type SelectChain = sc_consensus::LongestChain<TFullBackend<Block>, Block>;
|
|
||||||
|
|
||||||
/// Declare an instance of the native executor named `ExecutorDispatch`. Include the wasm binary as the
|
|
||||||
/// equivalent wasm code.
|
|
||||||
pub struct ExecutorDispatch;
|
|
||||||
|
|
||||||
impl sc_executor::NativeExecutionDispatch for ExecutorDispatch {
|
|
||||||
type ExtendHostFunctions =
|
|
||||||
(benchmarking::benchmarking::HostFunctions, SignatureVerificationOverride);
|
|
||||||
|
|
||||||
fn dispatch(method: &str, data: &[u8]) -> Option<Vec<u8>> {
|
|
||||||
polkadot_runtime::api::dispatch(method, data)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn native_version() -> sc_executor::NativeVersion {
|
|
||||||
polkadot_runtime::native_version()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// `ChainInfo` implementation.
|
|
||||||
pub struct PolkadotChainInfo;
|
|
||||||
|
|
||||||
impl ChainInfo for PolkadotChainInfo {
|
|
||||||
type Block = Block;
|
|
||||||
type ExecutorDispatch = ExecutorDispatch;
|
|
||||||
type Runtime = Runtime;
|
|
||||||
type RuntimeApi = RuntimeApi;
|
|
||||||
type SelectChain = SelectChain;
|
|
||||||
type BlockImport = BlockImport<
|
|
||||||
Self::Block,
|
|
||||||
TFullBackend<Self::Block>,
|
|
||||||
TFullClient<Self::Block, RuntimeApi, NativeElseWasmExecutor<ExecutorDispatch>>,
|
|
||||||
Self::SelectChain,
|
|
||||||
>;
|
|
||||||
type SignedExtras = polkadot_runtime::SignedExtra;
|
|
||||||
type InherentDataProviders =
|
|
||||||
(SlotTimestampProvider, sp_consensus_babe::inherents::InherentDataProvider);
|
|
||||||
|
|
||||||
fn signed_extras(from: <Runtime as system::Config>::AccountId) -> Self::SignedExtras {
|
|
||||||
(
|
|
||||||
system::CheckNonZeroSender::<Runtime>::new(),
|
|
||||||
system::CheckSpecVersion::<Runtime>::new(),
|
|
||||||
system::CheckTxVersion::<Runtime>::new(),
|
|
||||||
system::CheckGenesis::<Runtime>::new(),
|
|
||||||
system::CheckMortality::<Runtime>::from(Era::Immortal),
|
|
||||||
system::CheckNonce::<Runtime>::from(system::Pallet::<Runtime>::account_nonce(from)),
|
|
||||||
system::CheckWeight::<Runtime>::new(),
|
|
||||||
transaction_payment::ChargeTransactionPayment::<Runtime>::from(0),
|
|
||||||
claims::PrevalidateAttests::<Runtime>::new(),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Dispatch with root origin, via pallet-democracy
|
|
||||||
pub async fn dispatch_with_root<T>(
|
|
||||||
call: impl Into<<T::Runtime as system::Config>::Call>,
|
|
||||||
node: &Node<T>,
|
|
||||||
) -> Result<(), Box<dyn Error>>
|
|
||||||
where
|
|
||||||
T: ChainInfo<
|
|
||||||
Block = Block,
|
|
||||||
ExecutorDispatch = ExecutorDispatch,
|
|
||||||
Runtime = Runtime,
|
|
||||||
RuntimeApi = RuntimeApi,
|
|
||||||
SelectChain = SelectChain,
|
|
||||||
BlockImport = BlockImport<
|
|
||||||
Block,
|
|
||||||
TFullBackend<Block>,
|
|
||||||
TFullClient<Block, RuntimeApi, NativeElseWasmExecutor<ExecutorDispatch>>,
|
|
||||||
SelectChain,
|
|
||||||
>,
|
|
||||||
SignedExtras = polkadot_runtime::SignedExtra,
|
|
||||||
>,
|
|
||||||
{
|
|
||||||
type DemocracyCall = democracy::Call<Runtime>;
|
|
||||||
type CouncilCollectiveEvent = collective::Event<Runtime, CouncilCollective>;
|
|
||||||
type CouncilCollectiveCall = collective::Call<Runtime, CouncilCollective>;
|
|
||||||
type TechnicalCollectiveCall = collective::Call<Runtime, TechnicalCollective>;
|
|
||||||
type TechnicalCollectiveEvent = collective::Event<Runtime, TechnicalCollective>;
|
|
||||||
|
|
||||||
// here lies a black mirror esque copy of on chain whales.
|
|
||||||
let whales = vec![
|
|
||||||
"1rvXMZpAj9nKLQkPFCymyH7Fg3ZyKJhJbrc7UtHbTVhJm1A",
|
|
||||||
"15j4dg5GzsL1bw2U2AWgeyAk6QTxq43V7ZPbXdAmbVLjvDCK",
|
|
||||||
]
|
|
||||||
.into_iter()
|
|
||||||
.map(|account| AccountId32::from_str(account).unwrap())
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
|
|
||||||
// and these
|
|
||||||
let (technical_collective, council_collective) = node.with_state(|| {
|
|
||||||
(
|
|
||||||
collective::Members::<Runtime, TechnicalCollective>::get(),
|
|
||||||
collective::Members::<Runtime, CouncilCollective>::get(),
|
|
||||||
)
|
|
||||||
});
|
|
||||||
|
|
||||||
// hash of the proposal in democracy
|
|
||||||
let proposal_hash = {
|
|
||||||
// note the call (pre-image?) of the call.
|
|
||||||
node.submit_extrinsic(
|
|
||||||
DemocracyCall::note_preimage { encoded_proposal: call.into().encode() },
|
|
||||||
Some(whales[0].clone()),
|
|
||||||
)
|
|
||||||
.await?;
|
|
||||||
node.seal_blocks(1).await;
|
|
||||||
|
|
||||||
// fetch proposal hash from event emitted by the runtime
|
|
||||||
let events = node.events();
|
|
||||||
events
|
|
||||||
.iter()
|
|
||||||
.filter_map(|event| match event.event {
|
|
||||||
Event::Democracy(democracy::Event::PreimageNoted { ref proposal_hash, .. }) =>
|
|
||||||
Some(proposal_hash.clone()),
|
|
||||||
_ => None,
|
|
||||||
})
|
|
||||||
.next()
|
|
||||||
.ok_or_else(|| {
|
|
||||||
format!("democracy::Event::PreimageNoted not found in events: {:#?}", events)
|
|
||||||
})?
|
|
||||||
};
|
|
||||||
|
|
||||||
// submit `external_propose` call through council collective
|
|
||||||
{
|
|
||||||
let external_propose = DemocracyCall::external_propose_majority {
|
|
||||||
proposal_hash: proposal_hash.clone().into(),
|
|
||||||
};
|
|
||||||
let length = external_propose.using_encoded(|x| x.len()) as u32 + 1;
|
|
||||||
let weight = Weight::MAX / 100_000_000;
|
|
||||||
let proposal = CouncilCollectiveCall::propose {
|
|
||||||
threshold: council_collective.len() as u32,
|
|
||||||
proposal: Box::new(external_propose.clone().into()),
|
|
||||||
length_bound: length,
|
|
||||||
};
|
|
||||||
|
|
||||||
node.submit_extrinsic(proposal.clone(), Some(council_collective[0].clone()))
|
|
||||||
.await?;
|
|
||||||
node.seal_blocks(1).await;
|
|
||||||
|
|
||||||
// fetch proposal index from event emitted by the runtime
|
|
||||||
let events = node.events();
|
|
||||||
let (index, hash): (u32, H256) = events
|
|
||||||
.iter()
|
|
||||||
.filter_map(|event| match event.event {
|
|
||||||
Event::Council(CouncilCollectiveEvent::Proposed {
|
|
||||||
account: _,
|
|
||||||
proposal_index,
|
|
||||||
ref proposal_hash,
|
|
||||||
threshold: _,
|
|
||||||
}) => Some((proposal_index, proposal_hash.clone())),
|
|
||||||
_ => None,
|
|
||||||
})
|
|
||||||
.next()
|
|
||||||
.ok_or_else(|| {
|
|
||||||
format!("CouncilCollectiveEvent::Proposed not found in events: {:#?}", events)
|
|
||||||
})?;
|
|
||||||
|
|
||||||
// vote
|
|
||||||
for member in &council_collective[1..] {
|
|
||||||
let call = CouncilCollectiveCall::vote { proposal: hash.clone(), index, approve: true };
|
|
||||||
node.submit_extrinsic(call, Some(member.clone())).await?;
|
|
||||||
}
|
|
||||||
node.seal_blocks(1).await;
|
|
||||||
|
|
||||||
// close vote
|
|
||||||
let call = CouncilCollectiveCall::close {
|
|
||||||
proposal_hash: hash,
|
|
||||||
index,
|
|
||||||
proposal_weight_bound: weight,
|
|
||||||
length_bound: length,
|
|
||||||
};
|
|
||||||
node.submit_extrinsic(call, Some(council_collective[0].clone())).await?;
|
|
||||||
node.seal_blocks(1).await;
|
|
||||||
|
|
||||||
// assert that proposal has been passed on chain
|
|
||||||
let events = node
|
|
||||||
.events()
|
|
||||||
.into_iter()
|
|
||||||
.filter(|event| match event.event {
|
|
||||||
Event::Council(CouncilCollectiveEvent::Closed { proposal_hash, yes: _, no: _ })
|
|
||||||
if hash == proposal_hash =>
|
|
||||||
true,
|
|
||||||
Event::Council(CouncilCollectiveEvent::Approved { proposal_hash })
|
|
||||||
if hash == proposal_hash =>
|
|
||||||
true,
|
|
||||||
Event::Council(CouncilCollectiveEvent::Executed {
|
|
||||||
proposal_hash,
|
|
||||||
result: Ok(()),
|
|
||||||
}) if hash == proposal_hash => true,
|
|
||||||
_ => false,
|
|
||||||
})
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
|
|
||||||
// make sure all 3 events are in state
|
|
||||||
assert_eq!(
|
|
||||||
events.len(),
|
|
||||||
3,
|
|
||||||
"CouncilCollectiveEvent::{{Closed, Approved, Executed}} not found in events: {:#?}",
|
|
||||||
node.events(),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// next technical collective must fast track the proposal.
|
|
||||||
{
|
|
||||||
let fast_track = DemocracyCall::fast_track {
|
|
||||||
proposal_hash: proposal_hash.into(),
|
|
||||||
voting_period: FastTrackVotingPeriod::get(),
|
|
||||||
delay: 0,
|
|
||||||
};
|
|
||||||
let weight = Weight::MAX / 100_000_000;
|
|
||||||
let length = fast_track.using_encoded(|x| x.len()) as u32 + 1;
|
|
||||||
let proposal = TechnicalCollectiveCall::propose {
|
|
||||||
threshold: technical_collective.len() as u32,
|
|
||||||
proposal: Box::new(fast_track.into()),
|
|
||||||
length_bound: length,
|
|
||||||
};
|
|
||||||
|
|
||||||
node.submit_extrinsic(proposal, Some(technical_collective[0].clone())).await?;
|
|
||||||
node.seal_blocks(1).await;
|
|
||||||
|
|
||||||
let events = node.events();
|
|
||||||
let (index, hash) = events
|
|
||||||
.iter()
|
|
||||||
.filter_map(|event| match event.event {
|
|
||||||
Event::TechnicalCommittee(TechnicalCollectiveEvent::Proposed {
|
|
||||||
account: _,
|
|
||||||
proposal_index,
|
|
||||||
ref proposal_hash,
|
|
||||||
threshold: _,
|
|
||||||
}) => Some((proposal_index, proposal_hash.clone())),
|
|
||||||
_ => None,
|
|
||||||
})
|
|
||||||
.next()
|
|
||||||
.ok_or_else(|| {
|
|
||||||
format!("TechnicalCollectiveEvent::Proposed not found in events: {:#?}", events)
|
|
||||||
})?;
|
|
||||||
|
|
||||||
// vote
|
|
||||||
for member in &technical_collective[1..] {
|
|
||||||
let call =
|
|
||||||
TechnicalCollectiveCall::vote { proposal: hash.clone(), index, approve: true };
|
|
||||||
node.submit_extrinsic(call, Some(member.clone())).await?;
|
|
||||||
}
|
|
||||||
node.seal_blocks(1).await;
|
|
||||||
|
|
||||||
// close vote
|
|
||||||
let call = CouncilCollectiveCall::close {
|
|
||||||
proposal_hash: hash,
|
|
||||||
index,
|
|
||||||
proposal_weight_bound: weight,
|
|
||||||
length_bound: length,
|
|
||||||
};
|
|
||||||
node.submit_extrinsic(call, Some(technical_collective[0].clone())).await?;
|
|
||||||
node.seal_blocks(1).await;
|
|
||||||
|
|
||||||
// assert that fast-track proposal has been passed on chain
|
|
||||||
let events = node
|
|
||||||
.events()
|
|
||||||
.into_iter()
|
|
||||||
.filter(|event| match event.event {
|
|
||||||
Event::TechnicalCommittee(TechnicalCollectiveEvent::Closed {
|
|
||||||
proposal_hash: _hash,
|
|
||||||
..
|
|
||||||
}) if hash == _hash => true,
|
|
||||||
Event::TechnicalCommittee(TechnicalCollectiveEvent::Approved {
|
|
||||||
proposal_hash: _hash,
|
|
||||||
}) if hash == _hash => true,
|
|
||||||
Event::TechnicalCommittee(TechnicalCollectiveEvent::Executed {
|
|
||||||
proposal_hash: _hash,
|
|
||||||
result: Ok(()),
|
|
||||||
}) if hash == _hash => true,
|
|
||||||
_ => false,
|
|
||||||
})
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
|
|
||||||
// make sure all 3 events are in state
|
|
||||||
assert_eq!(
|
|
||||||
events.len(),
|
|
||||||
3,
|
|
||||||
"TechnicalCollectiveEvent::{{Closed, Approved, Executed}} not found in events: {:#?}",
|
|
||||||
node.events(),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// now runtime upgrade proposal is a fast-tracked referendum we can vote for.
|
|
||||||
let ref_index = node
|
|
||||||
.events()
|
|
||||||
.into_iter()
|
|
||||||
.filter_map(|event| match event.event {
|
|
||||||
Event::Democracy(democracy::Event::Started { ref_index: index, .. }) => Some(index),
|
|
||||||
_ => None,
|
|
||||||
})
|
|
||||||
.next()
|
|
||||||
.ok_or_else(|| {
|
|
||||||
format!("democracy::Event::Started not found in events: {:#?}", node.events())
|
|
||||||
})?;
|
|
||||||
|
|
||||||
let call = DemocracyCall::vote {
|
|
||||||
ref_index,
|
|
||||||
vote: AccountVote::Standard {
|
|
||||||
vote: Vote { aye: true, conviction: Conviction::Locked1x },
|
|
||||||
// 10 DOTS
|
|
||||||
balance: 10_000_000_000_000,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
for whale in whales {
|
|
||||||
node.submit_extrinsic(call.clone(), Some(whale)).await?;
|
|
||||||
}
|
|
||||||
|
|
||||||
// wait for fast track period.
|
|
||||||
node.seal_blocks(FastTrackVotingPeriod::get() as usize).await;
|
|
||||||
|
|
||||||
// assert that the proposal is passed by looking at events
|
|
||||||
let events = node
|
|
||||||
.events()
|
|
||||||
.into_iter()
|
|
||||||
.filter(|event| match event.event {
|
|
||||||
Event::Democracy(democracy::Event::Passed { ref_index: _index })
|
|
||||||
if _index == ref_index =>
|
|
||||||
true,
|
|
||||||
Event::Democracy(democracy::Event::PreimageUsed { proposal_hash: _hash, .. })
|
|
||||||
if _hash == proposal_hash =>
|
|
||||||
true,
|
|
||||||
Event::Democracy(democracy::Event::Executed { ref_index: _index, result: Ok(()) })
|
|
||||||
if _index == ref_index =>
|
|
||||||
true,
|
|
||||||
_ => false,
|
|
||||||
})
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
|
|
||||||
// make sure all events were emitted
|
|
||||||
assert_eq!(
|
|
||||||
events.len(),
|
|
||||||
3,
|
|
||||||
"democracy::Event::{{Passed, PreimageUsed, Executed}} not found in events: {:#?}",
|
|
||||||
node.events(),
|
|
||||||
);
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Runs the test-runner as a binary.
|
|
||||||
pub fn run<F, Fut>(callback: F) -> Result<(), Box<dyn Error>>
|
|
||||||
where
|
|
||||||
F: FnOnce(Node<PolkadotChainInfo>) -> Fut,
|
|
||||||
Fut: Future<Output = Result<(), Box<dyn Error>>>,
|
|
||||||
{
|
|
||||||
use sc_cli::{CliConfiguration, SubstrateCli};
|
|
||||||
use structopt::StructOpt;
|
|
||||||
|
|
||||||
let tokio_runtime = build_runtime()?;
|
|
||||||
// parse CLI args
|
|
||||||
let cmd = <polkadot_cli::Cli as StructOpt>::from_args();
|
|
||||||
// set up logging
|
|
||||||
let filters = cmd.run.base.log_filters()?;
|
|
||||||
let logger = sc_tracing::logging::LoggerBuilder::new(filters);
|
|
||||||
logger.init()?;
|
|
||||||
|
|
||||||
// set up the test-runner
|
|
||||||
let config = cmd.create_configuration(&cmd.run.base, tokio_runtime.handle().clone())?;
|
|
||||||
sc_cli::print_node_infos::<polkadot_cli::Cli>(&config);
|
|
||||||
let (rpc, task_manager, client, pool, command_sink, backend) =
|
|
||||||
client_parts::<PolkadotChainInfo>(ConfigOrChainSpec::Config(config))?;
|
|
||||||
let node =
|
|
||||||
Node::<PolkadotChainInfo>::new(rpc, task_manager, client, pool, command_sink, backend);
|
|
||||||
|
|
||||||
// hand off node.
|
|
||||||
tokio_runtime.block_on(callback(node))?;
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod tests {
|
|
||||||
use super::*;
|
|
||||||
use polkadot_service::chain_spec::polkadot_development_config;
|
|
||||||
use sp_keyring::sr25519::Keyring::Alice;
|
|
||||||
use sp_runtime::{traits::IdentifyAccount, MultiSigner};
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_runner() {
|
|
||||||
let runtime = build_runtime().unwrap();
|
|
||||||
let (rpc, task_manager, client, pool, command_sink, backend) =
|
|
||||||
client_parts::<PolkadotChainInfo>(ConfigOrChainSpec::ChainSpec(
|
|
||||||
Box::new(polkadot_development_config().unwrap()),
|
|
||||||
runtime.handle().clone(),
|
|
||||||
))
|
|
||||||
.unwrap();
|
|
||||||
let node =
|
|
||||||
Node::<PolkadotChainInfo>::new(rpc, task_manager, client, pool, command_sink, backend);
|
|
||||||
|
|
||||||
runtime.block_on(async {
|
|
||||||
// seals blocks
|
|
||||||
node.seal_blocks(1).await;
|
|
||||||
// submit extrinsics
|
|
||||||
let alice = MultiSigner::from(Alice.public()).into_account();
|
|
||||||
node.submit_extrinsic(
|
|
||||||
system::Call::remark { remark: (b"hello world").to_vec() },
|
|
||||||
Some(alice),
|
|
||||||
)
|
|
||||||
.await
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
// look ma, I can read state.
|
|
||||||
let _events = node.with_state(|| system::Pallet::<Runtime>::events());
|
|
||||||
// get access to the underlying client.
|
|
||||||
let _client = node.client();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
[package]
|
|
||||||
name = "polkadot-simnet-node"
|
|
||||||
version = "0.9.13"
|
|
||||||
authors = ["Parity Technologies <admin@parity.io>"]
|
|
||||||
edition = "2018"
|
|
||||||
|
|
||||||
[dependencies]
|
|
||||||
polkadot-simnet = { path = "../common" }
|
|
||||||
@@ -1,30 +0,0 @@
|
|||||||
// 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/>.
|
|
||||||
|
|
||||||
//! Binary used for Simnet nodes, supports all runtimes, although only polkadot is implemented currently.
|
|
||||||
//! This binary accepts all the CLI args the polkadot binary does, with the only difference that it uses
|
|
||||||
//! manual-seal™ and babe for block authorship, it has a no-op verifier, so all blocks received over the network
|
|
||||||
//! are imported and executed straight away. Block authorship/Finalization maybe done by calling the
|
|
||||||
//! rpc methods `engine_createBlock` and `engine_FinalizeBlock` respectively.
|
|
||||||
|
|
||||||
use std::error::Error;
|
|
||||||
|
|
||||||
fn main() -> Result<(), Box<dyn Error>> {
|
|
||||||
polkadot_simnet::run(|node| async {
|
|
||||||
node.until_shutdown().await;
|
|
||||||
Ok(())
|
|
||||||
})
|
|
||||||
}
|
|
||||||
@@ -1,22 +0,0 @@
|
|||||||
[package]
|
|
||||||
name = "polkadot-simnet-test"
|
|
||||||
version = "0.9.13"
|
|
||||||
authors = ["Parity Technologies <admin@parity.io>"]
|
|
||||||
edition = "2018"
|
|
||||||
|
|
||||||
[dependencies]
|
|
||||||
# substrate primitives
|
|
||||||
sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
|
||||||
sp-blockchain = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
|
||||||
sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
|
||||||
|
|
||||||
# frame pallets
|
|
||||||
system = { package = "frame-system", git = "https://github.com/paritytech/substrate", branch = "master" }
|
|
||||||
balances = { package = "pallet-balances", git = "https://github.com/paritytech/substrate", branch = "master" }
|
|
||||||
|
|
||||||
# substrate client libs
|
|
||||||
sc-client-api = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
|
||||||
|
|
||||||
# polkadot deps
|
|
||||||
polkadot-simnet = { path = "../common" }
|
|
||||||
polkadot-runtime = { path = "../../../../runtime/polkadot" }
|
|
||||||
@@ -1,104 +0,0 @@
|
|||||||
// 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/>.
|
|
||||||
//! Attempts to upgrade the polkadot runtime, in a Simnet environment
|
|
||||||
use std::{error::Error, str::FromStr};
|
|
||||||
|
|
||||||
use polkadot_runtime::Event;
|
|
||||||
use polkadot_simnet::{dispatch_with_root, run};
|
|
||||||
use sc_client_api::{CallExecutor, ExecutorProvider};
|
|
||||||
use sp_blockchain::HeaderBackend;
|
|
||||||
use sp_core::crypto::AccountId32;
|
|
||||||
use sp_runtime::generic::BlockId;
|
|
||||||
|
|
||||||
fn main() -> Result<(), Box<dyn Error>> {
|
|
||||||
run(|node| async {
|
|
||||||
let old_runtime_version = node
|
|
||||||
.client()
|
|
||||||
.executor()
|
|
||||||
.runtime_version(&BlockId::Hash(node.client().info().best_hash))?
|
|
||||||
.spec_version;
|
|
||||||
|
|
||||||
let wasm_binary = polkadot_runtime::WASM_BINARY
|
|
||||||
.ok_or("Polkadot development wasm not available")?
|
|
||||||
.to_vec();
|
|
||||||
// upgrade runtime.
|
|
||||||
dispatch_with_root(system::Call::set_code { code: wasm_binary }, &node).await?;
|
|
||||||
|
|
||||||
// assert that the runtime has been updated by looking at events
|
|
||||||
let events = node
|
|
||||||
.events()
|
|
||||||
.into_iter()
|
|
||||||
.filter(|event| match event.event {
|
|
||||||
Event::System(system::Event::CodeUpdated) => true,
|
|
||||||
_ => false,
|
|
||||||
})
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
|
|
||||||
// make sure event was emitted
|
|
||||||
assert_eq!(
|
|
||||||
events.len(),
|
|
||||||
1,
|
|
||||||
"system::Event::CodeUpdate not found in events: {:#?}",
|
|
||||||
node.events()
|
|
||||||
);
|
|
||||||
let new_runtime_version = node
|
|
||||||
.client()
|
|
||||||
.executor()
|
|
||||||
.runtime_version(&BlockId::Hash(node.client().info().best_hash))?
|
|
||||||
.spec_version;
|
|
||||||
// just confirming
|
|
||||||
assert!(
|
|
||||||
new_runtime_version > old_runtime_version,
|
|
||||||
"Invariant, spec_version of new runtime: {} not greater than spec_version of old runtime: {}",
|
|
||||||
new_runtime_version,
|
|
||||||
old_runtime_version,
|
|
||||||
);
|
|
||||||
|
|
||||||
let (from, dest, balance) = (
|
|
||||||
AccountId32::from_str("15j4dg5GzsL1bw2U2AWgeyAk6QTxq43V7ZPbXdAmbVLjvDCK")?,
|
|
||||||
AccountId32::from_str("1rvXMZpAj9nKLQkPFCymyH7Fg3ZyKJhJbrc7UtHbTVhJm1A")?,
|
|
||||||
10_000_000_000_000, // 10 dots
|
|
||||||
);
|
|
||||||
|
|
||||||
// post upgrade tests, a simple balance transfer
|
|
||||||
node.submit_extrinsic(
|
|
||||||
balances::Call::transfer { dest: dest.into(), value: balance },
|
|
||||||
Some(from),
|
|
||||||
)
|
|
||||||
.await?;
|
|
||||||
node.seal_blocks(1).await;
|
|
||||||
|
|
||||||
let events = node
|
|
||||||
.events()
|
|
||||||
.into_iter()
|
|
||||||
.filter(|event| match event.event {
|
|
||||||
Event::Balances(balances::Event::Transfer { .. }) => true,
|
|
||||||
_ => false,
|
|
||||||
})
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
// make sure transfer went through
|
|
||||||
assert_eq!(
|
|
||||||
events.len(), 1,
|
|
||||||
"balances::Call::transfer failed to execute, balances::Event::Transfer not found in events: {:#?}",
|
|
||||||
node.events()
|
|
||||||
);
|
|
||||||
|
|
||||||
// we're done, drop node.
|
|
||||||
drop(node);
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
})
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user