substrate-test-runtime migrated to "pure" frame runtime (#13737)

* substrate-test-runtime migrated to pure-frame based

* test block builder: helpers added

* simple renaming

* basic_authorship test adjusted

* block_building storage_proof test adjusted

* babe: tests: should_panic expected added

* babe: tests adjusted

ConsensusLog::NextEpochData is now added by pallet_babe as
pallet_babe::SameAuthoritiesForever trigger is used in runtime config.

* beefy: tests adjusted

test-substrate-runtime is now using frame::executive to finalize the
block. during finalization the digests stored during block execution are
checked against header digests:
https://github.com/paritytech/substrate/blob/91bb2d29ca905599098a5b35eaf24867c4fbd60a/frame/executive/src/lib.rs#L585-L591

It makes impossible to directly manipulate header's digets, w/o
depositing logs into system pallet storage `Digest<T: Config>`.

Instead of this dedicated extrinsic allowing to store logs items
(MmrRoot / AuthoritiesChange) is used.

* grandpa: tests adjusted

test-substrate-runtime is now using frame::executive to finalize the
block. during finalization the digest logs stored during block execution are
checked against header digest logs:
https://github.com/paritytech/substrate/blob/91bb2d29ca905599098a5b35eaf24867c4fbd60a/frame/executive/src/lib.rs#L585-L591

It makes impossible to directly manipulate header's digets, w/o
depositing logs into system pallet storage `Digest<T: Config>`.

Instead of this dedicated extrinsic allowing to store logs items
(ScheduledChange / ForcedChange and DigestItem::Other) is used.

* network:bitswap: test adjusted

The size of unchecked extrinsic was increased. The pattern used in test will
be placed at the end of scale-encoded buffer.

* runtime apis versions adjusted

* storage keys used in runtime adjusted

* wasm vs native tests removed

* rpc tests: adjusted

Transfer transaction processing was slightly improved, test was
adjusted.

* tests: sizes adjusted

Runtime extrinsic size was increased. Size of data read during block
execution was also increased due to usage of new pallets in runtime.

Sizes were adjusted in tests.

* cargo.lock update

cargo update -p substrate-test-runtime -p substrate-test-runtime-client

* warnings fixed

* builders cleanup: includes / std

* extrinsic validation cleanup

* txpool: benches performance fixed

* fmt

* spelling

* Apply suggestions from code review

Co-authored-by: Davide Galassi <davxy@datawok.net>

* Apply code review suggestions

* Apply code review suggestions

* get rid of 1063 const

* renaming: UncheckedExtrinsic -> Extrinsic

* test-utils-runtime: further step to pure-frame

* basic-authorship: tests OK

* CheckSubstrateCall added + tests fixes

* test::Transfer call removed

* priority / propagate / no sudo+root-testing

* fixing warnings + format

* cleanup: build2/nonce + format

* final tests fixes

all tests are passing

* logs/comments removal

* should_not_accept_old_signatures test removed

* make txpool benches work again

* Cargo.lock reset

* format

* sudo hack removed

* txpool benches fix+cleanup

* .gitignore reverted

* rebase fixing + unsigned cleanup

* Cargo.toml/Cargo.lock cleanup

* force-debug feature removed

* mmr tests fixed

* make cargo-clippy happy

* network sync test uses unsigned extrinsic

* cleanup

* ".git/.scripts/commands/fmt/fmt.sh"

* push_storage_change signed call remove

* GenesisConfig cleanup

* fix

* fix

* GenesisConfig simplified

* storage_keys_works: reworked

* storage_keys_works: expected keys in vec

* storage keys list moved to substrate-test-runtime

* substrate-test: some sanity tests + GenesisConfigBuilder rework

* Apply suggestions from code review

Co-authored-by: Bastian Köcher <git@kchr.de>

* Apply suggestions from code review

* Review suggestions

* fix

* fix

* beefy: generate_blocks_and_sync block_num sync with actaul value

* Apply suggestions from code review

Co-authored-by: Davide Galassi <davxy@datawok.net>

* Update test-utils/runtime/src/genesismap.rs

Co-authored-by: Davide Galassi <davxy@datawok.net>

* cargo update -p sc-rpc -p sc-transaction-pool

* Review suggestions

* fix

* doc added

* slot_duration adjusted for Babe::slot_duration

* small doc fixes

* array_bytes::hex used instead of hex

* tiny -> medium name fix

* Apply suggestions from code review

Co-authored-by: Sebastian Kunert <skunert49@gmail.com>

* TransferData::try_from_unchecked_extrinsic -> try_from

* Update Cargo.lock

---------

Co-authored-by: parity-processbot <>
Co-authored-by: Davide Galassi <davxy@datawok.net>
Co-authored-by: Bastian Köcher <git@kchr.de>
Co-authored-by: Sebastian Kunert <skunert49@gmail.com>
This commit is contained in:
Michal Kucharczyk
2023-05-04 18:20:22 +02:00
committed by GitHub
parent 3a90728de0
commit 6a295e7c28
34 changed files with 1943 additions and 2356 deletions
@@ -0,0 +1,244 @@
// This file is part of Substrate.
// 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.
//! # substrate-test pallet
//!
//! Provides functionality used in unit-tests of numerous modules across substrate that require
//! functioning runtime. Some calls are allowed to be submitted as unsigned extrinsics, however most
//! of them requires signing. Refer to `pallet::Call` for further details.
use crate::AuthorityId;
use frame_support::{pallet_prelude::*, storage};
use sp_runtime::transaction_validity::{
InvalidTransaction, TransactionSource, TransactionValidity, ValidTransaction,
};
use sp_std::prelude::*;
pub use self::pallet::*;
const LOG_TARGET: &str = "substrate_test_pallet";
#[frame_support::pallet(dev_mode)]
pub mod pallet {
use super::*;
use crate::TransferData;
use frame_system::pallet_prelude::*;
use sp_core::storage::well_known_keys;
use sp_runtime::{transaction_validity::TransactionPriority, Perbill};
#[pallet::pallet]
#[pallet::without_storage_info]
pub struct Pallet<T>(PhantomData<T>);
#[pallet::config]
pub trait Config: frame_system::Config {}
#[pallet::storage]
#[pallet::getter(fn authorities)]
pub type Authorities<T> = StorageValue<_, Vec<AuthorityId>, ValueQuery>;
#[pallet::genesis_config]
#[cfg_attr(feature = "std", derive(Default))]
pub struct GenesisConfig {
pub authorities: Vec<AuthorityId>,
}
#[pallet::genesis_build]
impl<T: Config> GenesisBuild<T> for GenesisConfig {
fn build(&self) {
<Authorities<T>>::put(self.authorities.clone());
}
}
#[pallet::call]
impl<T: Config> Pallet<T> {
/// Legacy call used in transaction pool benchmarks.
#[pallet::call_index(0)]
#[pallet::weight(100)]
pub fn bench_call(_origin: OriginFor<T>, _transfer: TransferData) -> DispatchResult {
Ok(())
}
/// Implicitly fill a block body with some data.
#[pallet::call_index(1)]
#[pallet::weight(100)]
pub fn include_data(origin: OriginFor<T>, _data: Vec<u8>) -> DispatchResult {
frame_system::ensure_signed(origin)?;
Ok(())
}
/// Put/delete some data from storage. Intended to use as an unsigned extrinsic.
#[pallet::call_index(2)]
#[pallet::weight(100)]
pub fn storage_change(
_origin: OriginFor<T>,
key: Vec<u8>,
value: Option<Vec<u8>>,
) -> DispatchResult {
match value {
Some(value) => storage::unhashed::put_raw(&key, &value),
None => storage::unhashed::kill(&key),
}
Ok(())
}
/// Write a key value pair to the offchain database.
#[pallet::call_index(3)]
#[pallet::weight(100)]
pub fn offchain_index_set(
origin: OriginFor<T>,
key: Vec<u8>,
value: Vec<u8>,
) -> DispatchResult {
frame_system::ensure_signed(origin)?;
sp_io::offchain_index::set(&key, &value);
Ok(())
}
/// Remove a key and an associated value from the offchain database.
#[pallet::call_index(4)]
#[pallet::weight(100)]
pub fn offchain_index_clear(origin: OriginFor<T>, key: Vec<u8>) -> DispatchResult {
frame_system::ensure_signed(origin)?;
sp_io::offchain_index::clear(&key);
Ok(())
}
/// Create an index for this call.
#[pallet::call_index(5)]
#[pallet::weight(100)]
pub fn indexed_call(origin: OriginFor<T>, data: Vec<u8>) -> DispatchResult {
frame_system::ensure_signed(origin)?;
let content_hash = sp_io::hashing::blake2_256(&data);
let extrinsic_index: u32 =
storage::unhashed::get(well_known_keys::EXTRINSIC_INDEX).unwrap();
sp_io::transaction_index::index(extrinsic_index, data.len() as u32, content_hash);
Ok(())
}
/// Deposit given digest items into the system storage. They will be included in a header
/// during finalization.
#[pallet::call_index(6)]
#[pallet::weight(100)]
pub fn deposit_log_digest_item(
_origin: OriginFor<T>,
log: sp_runtime::generic::DigestItem,
) -> DispatchResult {
<frame_system::Pallet<T>>::deposit_log(log);
Ok(())
}
/// This call is validated as `ValidTransaction` with given priority.
#[pallet::call_index(7)]
#[pallet::weight(100)]
pub fn call_with_priority(
_origin: OriginFor<T>,
_priority: TransactionPriority,
) -> DispatchResult {
Ok(())
}
/// This call is validated as non-propagable `ValidTransaction`.
#[pallet::call_index(8)]
#[pallet::weight(100)]
pub fn call_do_not_propagate(_origin: OriginFor<T>) -> DispatchResult {
Ok(())
}
/// Fill the block weight up to the given ratio.
#[pallet::call_index(9)]
#[pallet::weight(*_ratio * T::BlockWeights::get().max_block)]
pub fn fill_block(origin: OriginFor<T>, _ratio: Perbill) -> DispatchResult {
ensure_signed(origin)?;
Ok(())
}
/// Read X times from the state some data.
///
/// Panics if it can not read `X` times.
#[pallet::call_index(10)]
#[pallet::weight(100)]
pub fn read(_origin: OriginFor<T>, count: u32) -> DispatchResult {
Self::execute_read(count, false)
}
/// Read X times from the state some data and then panic!
///
/// Returns `Ok` if it didn't read anything.
#[pallet::call_index(11)]
#[pallet::weight(100)]
pub fn read_and_panic(_origin: OriginFor<T>, count: u32) -> DispatchResult {
Self::execute_read(count, true)
}
}
impl<T: Config> Pallet<T> {
fn execute_read(read: u32, panic_at_end: bool) -> DispatchResult {
let mut next_key = vec![];
for _ in 0..(read as usize) {
if let Some(next) = sp_io::storage::next_key(&next_key) {
// Read the value
sp_io::storage::get(&next);
next_key = next;
} else {
if panic_at_end {
return Ok(())
} else {
panic!("Could not read {read} times from the state");
}
}
}
if panic_at_end {
panic!("BYE")
} else {
Ok(())
}
}
}
#[pallet::validate_unsigned]
impl<T: Config> ValidateUnsigned for Pallet<T> {
type Call = Call<T>;
fn validate_unsigned(_source: TransactionSource, call: &Self::Call) -> TransactionValidity {
log::trace!(target: LOG_TARGET, "validate_unsigned {call:?}");
match call {
// Some tests do not need to be complicated with signer and nonce, some need
// reproducible block hash (call signature can't be there).
// Offchain testing requires storage_change.
Call::deposit_log_digest_item { .. } |
Call::storage_change { .. } |
Call::read { .. } |
Call::read_and_panic { .. } => Ok(Default::default()),
_ => Err(TransactionValidityError::Invalid(InvalidTransaction::Call)),
}
}
}
}
pub fn validate_runtime_call<T: pallet::Config>(call: &pallet::Call<T>) -> TransactionValidity {
log::trace!(target: LOG_TARGET, "validate_runtime_call {call:?}");
match call {
Call::call_do_not_propagate {} =>
Ok(ValidTransaction { propagate: false, ..Default::default() }),
Call::call_with_priority { priority } =>
Ok(ValidTransaction { priority: *priority, ..Default::default() }),
_ => Ok(Default::default()),
}
}