mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-05-30 08:11:03 +00:00
Introduce test runner biolerplate (#2609)
* adds test-runner boilerplate * revert to master * Update node/test/runtime/Cargo.toml Co-authored-by: Andronik Ordian <write@reusable.software> * fix warning * use polkadot_development_config * remove vestigial code * ... * remove unused dependencies * adds simnet binary * adds simnet binary * merged with remote * dummy to check pipeline * add 2 docker files and a build cmd * adds logging * atempt to use binary from build host * fix simnet-binary * fix docker commands * switch branches * ... * update docker file * update the dockerfile 2 * add some message in the cheatsheet * add repo to chaches stage also * update paths * do only 1 stage build * add time when build cmd started * remove debugg commands * polkadot-simnet-substrate-working-version-v1 * reduce size of polkadot-simnet image * update test runner api * update test-runner * ... * revert to master * Merge branch 'master' of github.com:paritytech/polkadot into substrate-test-runner * bump impl version * remove unused imports, fix test * was_binary.to_vec() * Apply suggestions from code review Co-authored-by: Andronik Ordian <write@reusable.software> * ... * remove unused import * remove unused import * adds post upgrade test * dry code * revert spec_version * update Cargo.lock * tested and it works * compare runtime spec version * fix spaces, remove docker files * replace spaces with tabs * Update runtime/polkadot/src/lib.rs Co-authored-by: Andronik Ordian <write@reusable.software> * ... * revert Cargo.lock * bump cargo.lock Co-authored-by: Andronik Ordian <write@reusable.software> Co-authored-by: radupopa2010 <radupopa2010@yahoo.com> Co-authored-by: CI system <>
This commit is contained in:
Generated
+294
-156
File diff suppressed because it is too large
Load Diff
@@ -81,6 +81,9 @@ members = [
|
|||||||
"node/metered-channel",
|
"node/metered-channel",
|
||||||
"node/test/client",
|
"node/test/client",
|
||||||
"node/test/service",
|
"node/test/service",
|
||||||
|
"node/test/polkadot-simnet/common",
|
||||||
|
"node/test/polkadot-simnet/node",
|
||||||
|
"node/test/polkadot-simnet/test",
|
||||||
"parachain/test-parachains",
|
"parachain/test-parachains",
|
||||||
"parachain/test-parachains/adder",
|
"parachain/test-parachains/adder",
|
||||||
"parachain/test-parachains/adder/collator",
|
"parachain/test-parachains/adder/collator",
|
||||||
|
|||||||
@@ -0,0 +1,44 @@
|
|||||||
|
[package]
|
||||||
|
name = "polkadot-simnet"
|
||||||
|
version = "0.9.0"
|
||||||
|
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-transaction-pool = { 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" }
|
||||||
|
sp-api = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||||
|
sp-inherents = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||||
|
sp-keystore = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||||
|
sp-consensus = { 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.22"
|
||||||
|
|
||||||
|
[dev-dependencies]
|
||||||
|
log = "0.4.14"
|
||||||
@@ -0,0 +1,353 @@
|
|||||||
|
// 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 test_runner::{
|
||||||
|
Node, ChainInfo, SignatureVerificationOverride, task_executor,
|
||||||
|
build_runtime, client_parts, ConfigOrChainSpec,
|
||||||
|
};
|
||||||
|
use grandpa::GrandpaBlockImport;
|
||||||
|
use sc_service::{TFullBackend, TFullClient};
|
||||||
|
use sp_runtime::generic::Era;
|
||||||
|
use sc_consensus_babe::BabeBlockImport;
|
||||||
|
use polkadot_runtime_common::claims;
|
||||||
|
use sp_runtime::AccountId32;
|
||||||
|
use support::{weights::Weight, StorageValue};
|
||||||
|
use democracy::{AccountVote, Conviction, Vote};
|
||||||
|
use polkadot_runtime::{FastTrackVotingPeriod, Runtime, RuntimeApi, Event, TechnicalCollective, CouncilCollective};
|
||||||
|
use std::{str::FromStr, future::Future, error::Error};
|
||||||
|
use codec::Encode;
|
||||||
|
use sc_consensus_manual_seal::consensus::babe::SlotTimestampProvider;
|
||||||
|
use sp_runtime::app_crypto::sp_core::H256;
|
||||||
|
|
||||||
|
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>;
|
||||||
|
|
||||||
|
sc_executor::native_executor_instance!(
|
||||||
|
pub Executor,
|
||||||
|
polkadot_runtime::api::dispatch,
|
||||||
|
polkadot_runtime::native_version,
|
||||||
|
(benchmarking::benchmarking::HostFunctions, SignatureVerificationOverride),
|
||||||
|
);
|
||||||
|
|
||||||
|
/// ChainInfo implementation.
|
||||||
|
pub struct PolkadotChainInfo;
|
||||||
|
|
||||||
|
impl ChainInfo for PolkadotChainInfo {
|
||||||
|
type Block = Block;
|
||||||
|
type Executor = Executor;
|
||||||
|
type Runtime = Runtime;
|
||||||
|
type RuntimeApi = RuntimeApi;
|
||||||
|
type SelectChain = SelectChain;
|
||||||
|
type BlockImport = BlockImport<
|
||||||
|
Self::Block,
|
||||||
|
TFullBackend<Self::Block>,
|
||||||
|
TFullClient<Self::Block, RuntimeApi, Self::Executor>,
|
||||||
|
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::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,
|
||||||
|
Executor=Executor,
|
||||||
|
Runtime=Runtime,
|
||||||
|
RuntimeApi=RuntimeApi,
|
||||||
|
SelectChain=SelectChain,
|
||||||
|
BlockImport=BlockImport<
|
||||||
|
Block,
|
||||||
|
TFullBackend<Block>,
|
||||||
|
TFullClient<Block, RuntimeApi, Executor>,
|
||||||
|
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(call.into().encode()), whales[0].clone()).await?;
|
||||||
|
node.seal_blocks(1).await;
|
||||||
|
|
||||||
|
// fetch proposal hash from event emitted by the runtime
|
||||||
|
node.events()
|
||||||
|
.into_iter()
|
||||||
|
.filter_map(|event| match event.event {
|
||||||
|
Event::Democracy(democracy::Event::PreimageNoted(proposal_hash, _, _)) => Some(proposal_hash),
|
||||||
|
_ => None
|
||||||
|
})
|
||||||
|
.next()
|
||||||
|
.ok_or_else(|| "failed to note pre-image")?
|
||||||
|
};
|
||||||
|
|
||||||
|
// submit external_propose call through council collective
|
||||||
|
{
|
||||||
|
let external_propose = DemocracyCall::external_propose_majority(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(
|
||||||
|
council_collective.len() as u32,
|
||||||
|
Box::new(external_propose.clone().into()),
|
||||||
|
length,
|
||||||
|
);
|
||||||
|
|
||||||
|
node.submit_extrinsic(proposal.clone(), council_collective[0].clone()).await?;
|
||||||
|
node.seal_blocks(1).await;
|
||||||
|
|
||||||
|
// fetch proposal index from event emitted by the runtime
|
||||||
|
let (index, hash): (u32, H256) = node.events()
|
||||||
|
.into_iter()
|
||||||
|
.filter_map(|event| {
|
||||||
|
match event.event {
|
||||||
|
Event::Council(CouncilCollectiveEvent::Proposed(_, index, hash, _)) => Some((index, hash)),
|
||||||
|
_ => None
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.next()
|
||||||
|
.ok_or_else(|| "failed to execute council::Call::propose(democracy::Call::external_propose_majority)")?;
|
||||||
|
|
||||||
|
// vote
|
||||||
|
for member in &council_collective[1..] {
|
||||||
|
let call = CouncilCollectiveCall::vote(hash.clone(), index, true);
|
||||||
|
node.submit_extrinsic(call, member.clone()).await?;
|
||||||
|
}
|
||||||
|
node.seal_blocks(1).await;
|
||||||
|
|
||||||
|
// close vote
|
||||||
|
let call = CouncilCollectiveCall::close(hash, index, weight, length);
|
||||||
|
node.submit_extrinsic(call, 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(_, _, _)) |
|
||||||
|
Event::Council(CouncilCollectiveEvent::Approved(_, )) |
|
||||||
|
Event::Council(CouncilCollectiveEvent::Executed(_, Ok(()))) => true,
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
// make sure all 3 events are in state
|
||||||
|
assert_eq!(events.len(), 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
// next technical collective must fast track the proposal.
|
||||||
|
{
|
||||||
|
let fast_track = DemocracyCall::fast_track(proposal_hash.into(), FastTrackVotingPeriod::get(), 0);
|
||||||
|
let weight = Weight::MAX / 100_000_000;
|
||||||
|
let length = fast_track.using_encoded(|x| x.len()) as u32 + 1;
|
||||||
|
let proposal = TechnicalCollectiveCall::propose(
|
||||||
|
technical_collective.len() as u32,
|
||||||
|
Box::new(fast_track.into()),
|
||||||
|
length,
|
||||||
|
);
|
||||||
|
|
||||||
|
node.submit_extrinsic(proposal, technical_collective[0].clone()).await?;
|
||||||
|
node.seal_blocks(1).await;
|
||||||
|
|
||||||
|
let (index, hash) = node.events()
|
||||||
|
.into_iter()
|
||||||
|
.filter_map(|event| {
|
||||||
|
match event.event {
|
||||||
|
Event::TechnicalCommittee(TechnicalCollectiveEvent::Proposed(_, index, hash, _)) => Some((index, hash)),
|
||||||
|
_ => None
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.next()
|
||||||
|
.ok_or_else(|| "failed to execute council::Call::propose(democracy::Call::fast_track))")?;
|
||||||
|
|
||||||
|
// vote
|
||||||
|
for member in &technical_collective[1..] {
|
||||||
|
let call = TechnicalCollectiveCall::vote(hash.clone(), index, true);
|
||||||
|
node.submit_extrinsic(call, member.clone()).await?;
|
||||||
|
}
|
||||||
|
node.seal_blocks(1).await;
|
||||||
|
|
||||||
|
// close vote
|
||||||
|
let call = TechnicalCollectiveCall::close(hash, index, weight, length);
|
||||||
|
node.submit_extrinsic(call, 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(_, _, _)) |
|
||||||
|
Event::TechnicalCommittee(TechnicalCollectiveEvent::Approved(_)) |
|
||||||
|
Event::TechnicalCommittee(TechnicalCollectiveEvent::Executed(_, Ok(()))) => true,
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
// make sure all 3 events are in state
|
||||||
|
assert_eq!(events.len(), 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
// now runtime upgrade proposal is a fast-tracked referendum we can vote for.
|
||||||
|
let referendum_index = node.events()
|
||||||
|
.into_iter()
|
||||||
|
.filter_map(|event| match event.event {
|
||||||
|
Event::Democracy(democracy::Event::<Runtime>::Started(index, _)) => Some(index),
|
||||||
|
_ => None,
|
||||||
|
})
|
||||||
|
.next()
|
||||||
|
.ok_or_else(|| "failed to execute council::Call::close")?;
|
||||||
|
let call = DemocracyCall::vote(
|
||||||
|
referendum_index,
|
||||||
|
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(), 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(_)) |
|
||||||
|
Event::Democracy(democracy::Event::PreimageUsed(_, _, _)) |
|
||||||
|
Event::Democracy(democracy::Event::Executed(_, true)) => true,
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
// make sure all events were emitted
|
||||||
|
assert_eq!(events.len(), 3);
|
||||||
|
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 structopt::StructOpt;
|
||||||
|
use sc_cli::{CliConfiguration, SubstrateCli};
|
||||||
|
|
||||||
|
let mut tokio_runtime = build_runtime()?;
|
||||||
|
let task_executor = task_executor(tokio_runtime.handle().clone());
|
||||||
|
// 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, task_executor)?;
|
||||||
|
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 sp_keyring::sr25519::Keyring::Alice;
|
||||||
|
use sp_runtime::{MultiSigner, traits::IdentifyAccount};
|
||||||
|
use polkadot_service::chain_spec::polkadot_development_config;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_runner() {
|
||||||
|
let mut runtime = build_runtime().unwrap();
|
||||||
|
let task_executor = task_executor(runtime.handle().clone());
|
||||||
|
let (rpc, task_manager, client, pool, command_sink, backend) =
|
||||||
|
client_parts::<PolkadotChainInfo>(
|
||||||
|
ConfigOrChainSpec::ChainSpec(Box::new(polkadot_development_config().unwrap()), task_executor)
|
||||||
|
).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((b"hello world").to_vec()), 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();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
[package]
|
||||||
|
name = "polkadot-simnet-node"
|
||||||
|
version = "0.1.0"
|
||||||
|
authors = ["Parity Technologies <admin@parity.io>"]
|
||||||
|
edition = "2018"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
polkadot-simnet = { path = "../common" }
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
// 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, Only difference is 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
|
||||||
|
//! `engine_createBlock` & `engine_FinalizeBlock` rpc methods respectively.
|
||||||
|
|
||||||
|
use std::error::Error;
|
||||||
|
|
||||||
|
fn main() -> Result<(), Box<dyn Error>> {
|
||||||
|
polkadot_simnet::run(|node| async {
|
||||||
|
node.until_shutdown().await;
|
||||||
|
Ok(())
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
[package]
|
||||||
|
name = "polkadot-simnet-test"
|
||||||
|
version = "0.1.0"
|
||||||
|
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" }
|
||||||
@@ -0,0 +1,86 @@
|
|||||||
|
// 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_simnet::{run, dispatch_with_root};
|
||||||
|
use polkadot_runtime::Event;
|
||||||
|
use sp_runtime::generic::BlockId;
|
||||||
|
use sc_client_api::{ExecutorProvider, CallExecutor};
|
||||||
|
use sp_core::crypto::AccountId32;
|
||||||
|
use sp_blockchain::HeaderBackend;
|
||||||
|
|
||||||
|
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(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);
|
||||||
|
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);
|
||||||
|
|
||||||
|
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.into(), balance), 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);
|
||||||
|
|
||||||
|
// we're done, drop node.
|
||||||
|
drop(node);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -185,10 +185,10 @@ pub fn node_config(
|
|||||||
rpc_http: None,
|
rpc_http: None,
|
||||||
rpc_ws: None,
|
rpc_ws: None,
|
||||||
rpc_ipc: None,
|
rpc_ipc: None,
|
||||||
|
rpc_max_payload: None,
|
||||||
rpc_ws_max_connections: None,
|
rpc_ws_max_connections: None,
|
||||||
rpc_cors: None,
|
rpc_cors: None,
|
||||||
rpc_methods: Default::default(),
|
rpc_methods: Default::default(),
|
||||||
rpc_max_payload: None,
|
|
||||||
prometheus_config: None,
|
prometheus_config: None,
|
||||||
telemetry_endpoints: None,
|
telemetry_endpoints: None,
|
||||||
telemetry_external_transport: None,
|
telemetry_external_transport: None,
|
||||||
|
|||||||
@@ -565,7 +565,7 @@ parameter_types! {
|
|||||||
pub const CouncilMaxMembers: u32 = 100;
|
pub const CouncilMaxMembers: u32 = 100;
|
||||||
}
|
}
|
||||||
|
|
||||||
type CouncilCollective = pallet_collective::Instance1;
|
pub type CouncilCollective = pallet_collective::Instance1;
|
||||||
impl pallet_collective::Config<CouncilCollective> for Runtime {
|
impl pallet_collective::Config<CouncilCollective> for Runtime {
|
||||||
type Origin = Origin;
|
type Origin = Origin;
|
||||||
type Proposal = Call;
|
type Proposal = Call;
|
||||||
@@ -617,7 +617,7 @@ parameter_types! {
|
|||||||
pub const TechnicalMaxMembers: u32 = 100;
|
pub const TechnicalMaxMembers: u32 = 100;
|
||||||
}
|
}
|
||||||
|
|
||||||
type TechnicalCollective = pallet_collective::Instance2;
|
pub type TechnicalCollective = pallet_collective::Instance2;
|
||||||
impl pallet_collective::Config<TechnicalCollective> for Runtime {
|
impl pallet_collective::Config<TechnicalCollective> for Runtime {
|
||||||
type Origin = Origin;
|
type Origin = Origin;
|
||||||
type Proposal = Call;
|
type Proposal = Call;
|
||||||
|
|||||||
Reference in New Issue
Block a user