Files
pezkuwi-sdk/pezcumulus/test/service/benches/validate_block.rs
T
pezkuwichain 4666047395 chore: add Dijital Kurdistan Tech Institute to copyright headers
Updated 4763 files with dual copyright:
- Parity Technologies (UK) Ltd.
- Dijital Kurdistan Tech Institute
2025-12-27 21:28:36 +03:00

181 lines
6.1 KiB
Rust

// This file is part of Pezcumulus.
// Copyright (C) Parity Technologies (UK) Ltd. and Dijital Kurdistan Tech Institute
// 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, Throughput};
use pezcumulus_primitives_core::{
relay_chain::AccountId, ParaId, PersistedValidationData, ValidationParams,
};
use pezcumulus_test_client::{
generate_extrinsic_with_pair, BuildTeyrchainBlockData, InitBlockBuilder, TestClientBuilder,
ValidationResult,
};
use pezcumulus_test_relay_sproof_builder::RelayStateSproofBuilder;
use pezcumulus_test_runtime::{BalancesCall, Block, Header, UncheckedExtrinsic};
use pezcumulus_test_service::bench_utils as utils;
use pezkuwi_primitives::HeadData;
use pezsc_block_builder::BlockBuilderBuilder;
use pezsc_client_api::UsageProvider;
use pezsc_executor_common::wasm_runtime::WasmModule;
use pezsp_blockchain::{ApplyExtrinsicFailed::Validity, Error::ApplyExtrinsicFailed};
use pezsp_core::{sr25519, Pair};
use pezsp_runtime::{
traits::Header as HeaderT,
transaction_validity::{InvalidTransaction, TransactionValidityError},
};
fn create_extrinsics(
client: &pezcumulus_test_client::Client,
src_accounts: &[sr25519::Pair],
dst_accounts: &[sr25519::Pair],
) -> (usize, Vec<UncheckedExtrinsic>) {
// Add as many transfer extrinsics as possible into a single block.
let mut block_builder = BlockBuilderBuilder::new(client)
.on_parent_block(client.chain_info().best_hash)
.with_parent_block_number(client.chain_info().best_number)
.build()
.unwrap();
let mut max_transfer_count = 0;
let mut extrinsics = Vec::new();
for (src, dst) in src_accounts.iter().zip(dst_accounts.iter()) {
let extrinsic: UncheckedExtrinsic = generate_extrinsic_with_pair(
client,
src.clone(),
BalancesCall::transfer_keep_alive {
dest: AccountId::from(dst.public()).into(),
value: 10000,
},
None,
);
match block_builder.push(extrinsic.clone()) {
Ok(_) => {},
Err(ApplyExtrinsicFailed(Validity(TransactionValidityError::Invalid(
InvalidTransaction::ExhaustsResources,
)))) => break,
Err(error) => panic!("{}", error),
}
extrinsics.push(extrinsic);
max_transfer_count += 1;
}
(max_transfer_count, extrinsics)
}
fn benchmark_block_validation(c: &mut Criterion) {
pezsp_tracing::try_init_simple();
// Create enough accounts to fill the block with transactions.
// Each account should only be included in one transfer.
let (src_accounts, dst_accounts, account_ids) = utils::create_benchmark_accounts();
let para_id = ParaId::from(pezcumulus_test_runtime::TEYRCHAIN_ID);
let mut test_client_builder = TestClientBuilder::with_default_backend();
let genesis_init = test_client_builder.genesis_init_mut();
*genesis_init =
pezcumulus_test_client::GenesisParameters { endowed_accounts: account_ids, wasm: None };
let client = test_client_builder.build_with_native_executor(None).0;
let (max_transfer_count, extrinsics) = create_extrinsics(&client, &src_accounts, &dst_accounts);
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 sproof_builder = RelayStateSproofBuilder {
included_para_head: Some(parent_header.clone().encode().into()),
para_id,
..Default::default()
};
let pezcumulus_test_client::BlockBuilderAndSupportData { mut block_builder, .. } =
client.init_block_builder(Some(validation_data), sproof_builder.clone());
for extrinsic in extrinsics {
block_builder.push(extrinsic).unwrap();
}
let teyrchain_block = block_builder.build_teyrchain_block(*parent_header.state_root());
let proof_size_in_kb = teyrchain_block.proof().encoded_size() as f64 / 1024f64;
let runtime = utils::get_wasm_module();
let (relay_parent_storage_root, _) = sproof_builder.into_state_root_and_proof();
let encoded_params = ValidationParams {
block_data: pezcumulus_test_client::BlockData(teyrchain_block.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, teyrchain_block.blocks()[0].clone());
let mut group = c.benchmark_group("Block validation");
group.sample_size(20);
group.measurement_time(Duration::from_secs(120));
group.throughput(Throughput::Elements(max_transfer_count as u64));
group.bench_function(
format!(
"(transfers = {}, proof_size = {}kb) block validation",
max_transfer_count, 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],
teyrchain_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!(teyrchain_block.header, header);
}
criterion_group!(benches, benchmark_block_validation);
criterion_main!(benches);