mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-04-26 20:27:58 +00:00
df818d2974
Cumulus test-parachain node and test runtime were still using relay chain consensus and 12s blocktimes. With async backing around the corner on the major chains we should switch our tests too. Also needed to nicely test the changes coming to collators in #3168. ### Changes Overview - Followed the [migration guide](https://wiki.polkadot.network/docs/maintain-guides-async-backing) for async backing for the cumulus-test-runtime - Adjusted the cumulus-test-service to use the correct import-queue, lookahead collator etc. - The block validation function now uses the Aura Ext Executor so that the seal of the block is validated - Previous point requires that we seal block before calling into `validate_block`, I introduced a helper function for that - Test client adjusted to provide a slot to the relay chain proof and the aura pre-digest
213 lines
7.2 KiB
Rust
213 lines
7.2 KiB
Rust
// This file is part of Cumulus.
|
|
|
|
// Copyright (C) Parity Technologies (UK) Ltd.
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
use codec::{Decode, Encode};
|
|
use core::time::Duration;
|
|
use criterion::{criterion_group, criterion_main, BatchSize, Criterion};
|
|
use cumulus_primitives_core::{relay_chain::AccountId, PersistedValidationData, ValidationParams};
|
|
use cumulus_test_client::{
|
|
generate_extrinsic_with_pair, BlockBuilderAndSupportData, BuildParachainBlockData, Client,
|
|
InitBlockBuilder, ParachainBlockData, TestClientBuilder, ValidationResult,
|
|
};
|
|
use cumulus_test_relay_sproof_builder::RelayStateSproofBuilder;
|
|
use cumulus_test_runtime::{Block, GluttonCall, Header, SudoCall};
|
|
use polkadot_primitives::HeadData;
|
|
use sc_client_api::UsageProvider;
|
|
use sc_consensus::{BlockImport, BlockImportParams, ForkChoiceStrategy, ImportResult, StateAction};
|
|
use sc_executor_common::wasm_runtime::WasmModule;
|
|
use sp_api::ProvideRuntimeApi;
|
|
|
|
use frame_system_rpc_runtime_api::AccountNonceApi;
|
|
use sp_arithmetic::{
|
|
traits::{One, Zero},
|
|
FixedU64,
|
|
};
|
|
use sp_consensus::BlockOrigin;
|
|
use sp_keyring::Sr25519Keyring::Alice;
|
|
use sp_runtime::traits::Header as HeaderT;
|
|
|
|
use cumulus_test_service::bench_utils as utils;
|
|
|
|
async fn import_block(
|
|
mut client: &cumulus_test_client::Client,
|
|
built: cumulus_test_runtime::Block,
|
|
import_existing: bool,
|
|
) {
|
|
let mut params = BlockImportParams::new(BlockOrigin::File, built.header.clone());
|
|
params.body = Some(built.extrinsics.clone());
|
|
params.state_action = StateAction::Execute;
|
|
params.fork_choice = Some(ForkChoiceStrategy::LongestChain);
|
|
params.import_existing = import_existing;
|
|
let import_result = client.import_block(params).await;
|
|
assert!(matches!(import_result, Ok(ImportResult::Imported(_))));
|
|
}
|
|
|
|
fn benchmark_block_validation(c: &mut Criterion) {
|
|
sp_tracing::try_init_simple();
|
|
let runtime = tokio::runtime::Runtime::new().expect("creating tokio runtime doesn't fail; qed");
|
|
|
|
let endowed_accounts = vec![AccountId::from(Alice.public())];
|
|
let mut test_client_builder = TestClientBuilder::with_default_backend();
|
|
let genesis_init = test_client_builder.genesis_init_mut();
|
|
*genesis_init = cumulus_test_client::GenesisParameters { endowed_accounts };
|
|
|
|
let client = test_client_builder.build_with_native_executor(None).0;
|
|
|
|
let mut group = c.benchmark_group("Block validation");
|
|
group.sample_size(20);
|
|
group.measurement_time(Duration::from_secs(120));
|
|
|
|
// In the first iteration we want to initialize the glutton pallet.
|
|
let mut is_first = true;
|
|
for (compute_ratio, storage_ratio) in &[(One::one(), Zero::zero()), (One::one(), One::one())] {
|
|
let parachain_block =
|
|
set_glutton_parameters(&client, is_first, compute_ratio, storage_ratio);
|
|
is_first = false;
|
|
|
|
runtime.block_on(import_block(&client, parachain_block.clone().into_block(), false));
|
|
|
|
// Build benchmark block
|
|
let parent_hash = client.usage_info().chain.best_hash;
|
|
let parent_header = client.header(parent_hash).expect("Just fetched this hash.").unwrap();
|
|
let validation_data = PersistedValidationData {
|
|
relay_parent_number: 1,
|
|
parent_head: parent_header.encode().into(),
|
|
..Default::default()
|
|
};
|
|
let BlockBuilderAndSupportData { block_builder, .. } =
|
|
client.init_block_builder(Some(validation_data), Default::default());
|
|
let parachain_block = block_builder.build_parachain_block(*parent_header.state_root());
|
|
|
|
let proof_size_in_kb = parachain_block.storage_proof().encode().len() as f64 / 1024f64;
|
|
runtime.block_on(import_block(&client, parachain_block.clone().into_block(), false));
|
|
let runtime = utils::get_wasm_module();
|
|
|
|
let sproof_builder: RelayStateSproofBuilder = Default::default();
|
|
let (relay_parent_storage_root, _) = sproof_builder.clone().into_state_root_and_proof();
|
|
let encoded_params = ValidationParams {
|
|
block_data: cumulus_test_client::BlockData(parachain_block.clone().encode()),
|
|
parent_head: HeadData(parent_header.encode()),
|
|
relay_parent_number: 1,
|
|
relay_parent_storage_root,
|
|
}
|
|
.encode();
|
|
|
|
// This is not strictly necessary for this benchmark, but
|
|
// let us make sure that the result of `validate_block` is what
|
|
// we expect.
|
|
verify_expected_result(&runtime, &encoded_params, parachain_block.into_block());
|
|
|
|
group.bench_function(
|
|
format!(
|
|
"(compute = {:?}, storage = {:?}, proof_size = {}kb) block validation",
|
|
compute_ratio, storage_ratio, proof_size_in_kb
|
|
),
|
|
|b| {
|
|
b.iter_batched(
|
|
|| runtime.new_instance().unwrap(),
|
|
|mut instance| {
|
|
instance.call_export("validate_block", &encoded_params).unwrap();
|
|
},
|
|
BatchSize::SmallInput,
|
|
)
|
|
},
|
|
);
|
|
}
|
|
}
|
|
|
|
fn verify_expected_result(runtime: &Box<dyn WasmModule>, encoded_params: &[u8], block: Block) {
|
|
let res = runtime
|
|
.new_instance()
|
|
.unwrap()
|
|
.call_export("validate_block", encoded_params)
|
|
.expect("Call `validate_block`.");
|
|
let validation_result =
|
|
ValidationResult::decode(&mut &res[..]).expect("Decode `ValidationResult`.");
|
|
let header =
|
|
Header::decode(&mut &validation_result.head_data.0[..]).expect("Decodes `Header`.");
|
|
assert_eq!(block.header, header);
|
|
}
|
|
|
|
fn set_glutton_parameters(
|
|
client: &Client,
|
|
initialize: bool,
|
|
compute_ratio: &FixedU64,
|
|
storage_ratio: &FixedU64,
|
|
) -> ParachainBlockData {
|
|
let parent_hash = client.usage_info().chain.best_hash;
|
|
let parent_header = client.header(parent_hash).expect("Just fetched this hash.").unwrap();
|
|
|
|
let mut last_nonce = client
|
|
.runtime_api()
|
|
.account_nonce(parent_hash, Alice.into())
|
|
.expect("Fetching account nonce works; qed");
|
|
|
|
let validation_data = PersistedValidationData {
|
|
relay_parent_number: 1,
|
|
parent_head: parent_header.encode().into(),
|
|
..Default::default()
|
|
};
|
|
|
|
let mut extrinsics = vec![];
|
|
if initialize {
|
|
extrinsics.push(generate_extrinsic_with_pair(
|
|
client,
|
|
Alice.into(),
|
|
SudoCall::sudo {
|
|
call: Box::new(
|
|
GluttonCall::initialize_pallet { new_count: 5000, witness_count: None }.into(),
|
|
),
|
|
},
|
|
Some(last_nonce),
|
|
));
|
|
last_nonce += 1;
|
|
}
|
|
|
|
let set_compute = generate_extrinsic_with_pair(
|
|
client,
|
|
Alice.into(),
|
|
SudoCall::sudo {
|
|
call: Box::new(GluttonCall::set_compute { compute: *compute_ratio }.into()),
|
|
},
|
|
Some(last_nonce),
|
|
);
|
|
last_nonce += 1;
|
|
extrinsics.push(set_compute);
|
|
|
|
let set_storage = generate_extrinsic_with_pair(
|
|
client,
|
|
Alice.into(),
|
|
SudoCall::sudo {
|
|
call: Box::new(GluttonCall::set_storage { storage: *storage_ratio }.into()),
|
|
},
|
|
Some(last_nonce),
|
|
);
|
|
extrinsics.push(set_storage);
|
|
|
|
let BlockBuilderAndSupportData { mut block_builder, .. } =
|
|
client.init_block_builder(Some(validation_data), Default::default());
|
|
|
|
for extrinsic in extrinsics {
|
|
block_builder.push(extrinsic).unwrap();
|
|
}
|
|
|
|
block_builder.build_parachain_block(*parent_header.state_root())
|
|
}
|
|
|
|
criterion_group!(benches, benchmark_block_validation);
|
|
criterion_main!(benches);
|