mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-12 05:21:08 +00:00
c312f0b9a6
* Import Clippy config from Polkadot Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Auto clippy fix Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * No tabs in comments Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Prefer matches Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Dont drop references Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Trivial Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Refactor Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * fmt Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * add clippy to ci * Clippy reborrow Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Update client/pov-recovery/src/lib.rs Co-authored-by: Bastian Köcher <git@kchr.de> * Update client/pov-recovery/src/lib.rs Co-authored-by: Bastian Köcher <git@kchr.de> * Partially revert 'Prefer matches' Using matches! instead of match does give less compiler checks as per review from @chevdor. Partially reverts 8c0609677f3ea040f77fffd5be6facf7c3fec95c Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Update .cargo/config.toml Co-authored-by: Chevdor <chevdor@users.noreply.github.com> * Revert revert 💩 Should be fine to use matches! macro since it is an explicit whitelist, not wildcard matching. --------- Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> Co-authored-by: alvicsam <alvicsam@gmail.com> Co-authored-by: Bastian Köcher <git@kchr.de> Co-authored-by: Chevdor <chevdor@users.noreply.github.com> Co-authored-by: parity-processbot <>
322 lines
10 KiB
Rust
322 lines
10 KiB
Rust
// Copyright 2019-2021 Parity Technologies (UK) Ltd.
|
|
// This file is part of Substrate.
|
|
|
|
// Substrate 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.
|
|
|
|
// Substrate 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 Cumulus. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
use codec::{Decode, DecodeAll, Encode};
|
|
use cumulus_primitives_core::{ParachainBlockData, PersistedValidationData};
|
|
use cumulus_test_client::{
|
|
generate_extrinsic,
|
|
runtime::{Block, Hash, Header, TestPalletCall, UncheckedExtrinsic, WASM_BINARY},
|
|
transfer, BlockData, BuildParachainBlockData, Client, DefaultTestClientBuilderExt, HeadData,
|
|
InitBlockBuilder, TestClientBuilder, TestClientBuilderExt, ValidationParams,
|
|
};
|
|
use cumulus_test_relay_sproof_builder::RelayStateSproofBuilder;
|
|
use sp_keyring::AccountKeyring::*;
|
|
use sp_runtime::traits::Header as HeaderT;
|
|
use std::{env, process::Command};
|
|
|
|
use crate::validate_block::MemoryOptimizedValidationParams;
|
|
|
|
fn call_validate_block_encoded_header(
|
|
parent_head: Header,
|
|
block_data: ParachainBlockData<Block>,
|
|
relay_parent_storage_root: Hash,
|
|
) -> cumulus_test_client::ExecutorResult<Vec<u8>> {
|
|
cumulus_test_client::validate_block(
|
|
ValidationParams {
|
|
block_data: BlockData(block_data.encode()),
|
|
parent_head: HeadData(parent_head.encode()),
|
|
relay_parent_number: 1,
|
|
relay_parent_storage_root,
|
|
},
|
|
WASM_BINARY.expect("You need to build the WASM binaries to run the tests!"),
|
|
)
|
|
.map(|v| v.head_data.0)
|
|
}
|
|
|
|
fn call_validate_block(
|
|
parent_head: Header,
|
|
block_data: ParachainBlockData<Block>,
|
|
relay_parent_storage_root: Hash,
|
|
) -> cumulus_test_client::ExecutorResult<Header> {
|
|
call_validate_block_encoded_header(parent_head, block_data, relay_parent_storage_root)
|
|
.map(|v| Header::decode(&mut &v[..]).expect("Decodes `Header`."))
|
|
}
|
|
|
|
fn create_test_client() -> (Client, Header) {
|
|
let client = TestClientBuilder::new()
|
|
// NOTE: this allows easier debugging
|
|
.set_execution_strategy(sc_client_api::ExecutionStrategy::NativeWhenPossible)
|
|
.build();
|
|
|
|
let genesis_header = client
|
|
.header(client.chain_info().genesis_hash)
|
|
.ok()
|
|
.flatten()
|
|
.expect("Genesis header exists; qed");
|
|
|
|
(client, genesis_header)
|
|
}
|
|
|
|
struct TestBlockData {
|
|
block: ParachainBlockData<Block>,
|
|
validation_data: PersistedValidationData,
|
|
}
|
|
|
|
fn build_block_with_witness(
|
|
client: &Client,
|
|
extra_extrinsics: Vec<UncheckedExtrinsic>,
|
|
parent_head: Header,
|
|
sproof_builder: RelayStateSproofBuilder,
|
|
) -> TestBlockData {
|
|
let (relay_parent_storage_root, _) = sproof_builder.clone().into_state_root_and_proof();
|
|
let mut validation_data = PersistedValidationData {
|
|
relay_parent_number: 1,
|
|
parent_head: parent_head.encode().into(),
|
|
..Default::default()
|
|
};
|
|
let mut builder = client.init_block_builder(Some(validation_data.clone()), sproof_builder);
|
|
|
|
validation_data.relay_parent_storage_root = relay_parent_storage_root;
|
|
|
|
extra_extrinsics.into_iter().for_each(|e| builder.push(e).unwrap());
|
|
|
|
let block = builder.build_parachain_block(*parent_head.state_root());
|
|
|
|
TestBlockData { block, validation_data }
|
|
}
|
|
|
|
#[test]
|
|
fn validate_block_no_extra_extrinsics() {
|
|
sp_tracing::try_init_simple();
|
|
|
|
let (client, parent_head) = create_test_client();
|
|
let TestBlockData { block, validation_data } =
|
|
build_block_with_witness(&client, Vec::new(), parent_head.clone(), Default::default());
|
|
let header = block.header().clone();
|
|
|
|
let res_header =
|
|
call_validate_block(parent_head, block, validation_data.relay_parent_storage_root)
|
|
.expect("Calls `validate_block`");
|
|
assert_eq!(header, res_header);
|
|
}
|
|
|
|
#[test]
|
|
fn validate_block_with_extra_extrinsics() {
|
|
sp_tracing::try_init_simple();
|
|
|
|
let (client, parent_head) = create_test_client();
|
|
let extra_extrinsics = vec![
|
|
transfer(&client, Alice, Bob, 69),
|
|
transfer(&client, Bob, Charlie, 100),
|
|
transfer(&client, Charlie, Alice, 500),
|
|
];
|
|
|
|
let TestBlockData { block, validation_data } = build_block_with_witness(
|
|
&client,
|
|
extra_extrinsics,
|
|
parent_head.clone(),
|
|
Default::default(),
|
|
);
|
|
let header = block.header().clone();
|
|
|
|
let res_header =
|
|
call_validate_block(parent_head, block, validation_data.relay_parent_storage_root)
|
|
.expect("Calls `validate_block`");
|
|
assert_eq!(header, res_header);
|
|
}
|
|
|
|
#[test]
|
|
fn validate_block_returns_custom_head_data() {
|
|
sp_tracing::try_init_simple();
|
|
|
|
let expected_header = vec![1, 3, 3, 7, 4, 5, 6];
|
|
|
|
let (client, parent_head) = create_test_client();
|
|
let extra_extrinsics = vec![
|
|
transfer(&client, Alice, Bob, 69),
|
|
generate_extrinsic(
|
|
&client,
|
|
Charlie,
|
|
TestPalletCall::set_custom_validation_head_data {
|
|
custom_header: expected_header.clone(),
|
|
},
|
|
),
|
|
transfer(&client, Bob, Charlie, 100),
|
|
];
|
|
|
|
let TestBlockData { block, validation_data } = build_block_with_witness(
|
|
&client,
|
|
extra_extrinsics,
|
|
parent_head.clone(),
|
|
Default::default(),
|
|
);
|
|
let header = block.header().clone();
|
|
assert_ne!(expected_header, header.encode());
|
|
|
|
let res_header = call_validate_block_encoded_header(
|
|
parent_head,
|
|
block,
|
|
validation_data.relay_parent_storage_root,
|
|
)
|
|
.expect("Calls `validate_block`");
|
|
assert_eq!(expected_header, res_header);
|
|
}
|
|
|
|
#[test]
|
|
fn validate_block_invalid_parent_hash() {
|
|
sp_tracing::try_init_simple();
|
|
|
|
if env::var("RUN_TEST").is_ok() {
|
|
let (client, parent_head) = create_test_client();
|
|
let TestBlockData { block, validation_data } =
|
|
build_block_with_witness(&client, Vec::new(), parent_head.clone(), Default::default());
|
|
let (mut header, extrinsics, witness) = block.deconstruct();
|
|
header.set_parent_hash(Hash::from_low_u64_be(1));
|
|
|
|
let block_data = ParachainBlockData::new(header, extrinsics, witness);
|
|
call_validate_block(parent_head, block_data, validation_data.relay_parent_storage_root)
|
|
.unwrap_err();
|
|
} else {
|
|
let output = Command::new(env::current_exe().unwrap())
|
|
.args(["validate_block_invalid_parent_hash", "--", "--nocapture"])
|
|
.env("RUN_TEST", "1")
|
|
.output()
|
|
.expect("Runs the test");
|
|
assert!(output.status.success());
|
|
|
|
assert!(dbg!(String::from_utf8(output.stderr).unwrap()).contains("Invalid parent hash"));
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn validate_block_fails_on_invalid_validation_data() {
|
|
sp_tracing::try_init_simple();
|
|
|
|
if env::var("RUN_TEST").is_ok() {
|
|
let (client, parent_head) = create_test_client();
|
|
let TestBlockData { block, .. } =
|
|
build_block_with_witness(&client, Vec::new(), parent_head.clone(), Default::default());
|
|
|
|
call_validate_block(parent_head, block, Hash::random()).unwrap_err();
|
|
} else {
|
|
let output = Command::new(env::current_exe().unwrap())
|
|
.args(["validate_block_fails_on_invalid_validation_data", "--", "--nocapture"])
|
|
.env("RUN_TEST", "1")
|
|
.output()
|
|
.expect("Runs the test");
|
|
assert!(output.status.success());
|
|
|
|
assert!(dbg!(String::from_utf8(output.stderr).unwrap())
|
|
.contains("Relay parent storage root doesn't match"));
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn check_inherent_fails_on_validate_block_as_expected() {
|
|
sp_tracing::try_init_simple();
|
|
|
|
if env::var("RUN_TEST").is_ok() {
|
|
let (client, parent_head) = create_test_client();
|
|
|
|
let TestBlockData { block, validation_data } = build_block_with_witness(
|
|
&client,
|
|
Vec::new(),
|
|
parent_head.clone(),
|
|
RelayStateSproofBuilder { current_slot: 1337.into(), ..Default::default() },
|
|
);
|
|
|
|
call_validate_block(parent_head, block, validation_data.relay_parent_storage_root)
|
|
.unwrap_err();
|
|
} else {
|
|
let output = Command::new(env::current_exe().unwrap())
|
|
.args(["check_inherent_fails_on_validate_block_as_expected", "--", "--nocapture"])
|
|
.env("RUN_TEST", "1")
|
|
.output()
|
|
.expect("Runs the test");
|
|
assert!(output.status.success());
|
|
|
|
assert!(
|
|
dbg!(String::from_utf8(output.stderr).unwrap()).contains("Checking inherents failed")
|
|
);
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn check_inherents_are_unsigned_and_before_all_other_extrinsics() {
|
|
sp_tracing::try_init_simple();
|
|
|
|
if env::var("RUN_TEST").is_ok() {
|
|
let (client, parent_head) = create_test_client();
|
|
|
|
let TestBlockData { block, validation_data } =
|
|
build_block_with_witness(&client, Vec::new(), parent_head.clone(), Default::default());
|
|
|
|
let (header, mut extrinsics, proof) = block.deconstruct();
|
|
|
|
extrinsics.insert(0, transfer(&client, Alice, Bob, 69));
|
|
|
|
call_validate_block(
|
|
parent_head,
|
|
ParachainBlockData::new(header, extrinsics, proof),
|
|
validation_data.relay_parent_storage_root,
|
|
)
|
|
.unwrap_err();
|
|
} else {
|
|
let output = Command::new(env::current_exe().unwrap())
|
|
.args([
|
|
"check_inherents_are_unsigned_and_before_all_other_extrinsics",
|
|
"--",
|
|
"--nocapture",
|
|
])
|
|
.env("RUN_TEST", "1")
|
|
.output()
|
|
.expect("Runs the test");
|
|
assert!(output.status.success());
|
|
|
|
assert!(String::from_utf8(output.stderr)
|
|
.unwrap()
|
|
.contains("Could not find `set_validation_data` inherent"));
|
|
}
|
|
}
|
|
|
|
/// Test that ensures that `ValidationParams` and `MemoryOptimizedValidationParams`
|
|
/// are encoding/decoding.
|
|
#[test]
|
|
fn validation_params_and_memory_optimized_validation_params_encode_and_decode() {
|
|
const BLOCK_DATA: &[u8] = &[1, 2, 3, 4, 5];
|
|
const PARENT_HEAD: &[u8] = &[1, 3, 4, 5, 6, 7, 9];
|
|
|
|
let validation_params = ValidationParams {
|
|
block_data: BlockData(BLOCK_DATA.encode()),
|
|
parent_head: HeadData(PARENT_HEAD.encode()),
|
|
relay_parent_number: 1,
|
|
relay_parent_storage_root: Hash::random(),
|
|
};
|
|
|
|
let encoded = validation_params.encode();
|
|
|
|
let decoded = MemoryOptimizedValidationParams::decode_all(&mut &encoded[..]).unwrap();
|
|
assert_eq!(decoded.relay_parent_number, validation_params.relay_parent_number);
|
|
assert_eq!(decoded.relay_parent_storage_root, validation_params.relay_parent_storage_root);
|
|
assert_eq!(decoded.block_data, validation_params.block_data.0);
|
|
assert_eq!(decoded.parent_head, validation_params.parent_head.0);
|
|
|
|
let encoded = decoded.encode();
|
|
|
|
let decoded = ValidationParams::decode_all(&mut &encoded[..]).unwrap();
|
|
assert_eq!(decoded, validation_params);
|
|
}
|