diff --git a/pallets/parachain-system/src/validate_block/implementation.rs b/pallets/parachain-system/src/validate_block/implementation.rs index 9acb76875d7..10821744dbc 100644 --- a/pallets/parachain-system/src/validate_block/implementation.rs +++ b/pallets/parachain-system/src/validate_block/implementation.rs @@ -118,6 +118,11 @@ where let inherent_data = block .extrinsics() .iter() + // Inherents are at the front of the block and are unsigned. + // + // If `is_signed` is returning `None`, we keep it safe and assume that it is "signed". + // We are searching for unsigned transactions anyway. + .take_while(|e| !e.is_signed().unwrap_or(true)) .filter_map(|e| e.call().is_sub_type()) .find_map(|c| match c { crate::Call::set_validation_data { data: validation_data } => diff --git a/pallets/parachain-system/src/validate_block/tests.rs b/pallets/parachain-system/src/validate_block/tests.rs index 6453b9cd394..e06c2cafdcf 100644 --- a/pallets/parachain-system/src/validate_block/tests.rs +++ b/pallets/parachain-system/src/validate_block/tests.rs @@ -251,3 +251,40 @@ fn check_inherent_fails_on_validate_block_as_expected() { ); } } + +#[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")); + } +}