Skip to content
This repository has been archived by the owner on Nov 15, 2023. It is now read-only.

Ensure inherent are first #8173

Merged
26 commits merged into from
Apr 13, 2021
Merged
Show file tree
Hide file tree
Changes from 22 commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
4f44f62
impl
gui1117 Feb 18, 2021
6836b61
fix tests
gui1117 Feb 22, 2021
a03ea8b
impl in execute_block
gui1117 Feb 22, 2021
8ad86df
Merge remote-tracking branch 'origin/master' into gui-inherent-forced…
gui1117 Feb 23, 2021
12eeac3
fix tests
gui1117 Feb 23, 2021
2baee86
add a test in frame-executive
gui1117 Feb 23, 2021
b3eb416
fix some panic warning
gui1117 Feb 23, 2021
8934a1c
use trait to get call from extrinsic
gui1117 Feb 23, 2021
fc16e58
remove unused
gui1117 Feb 23, 2021
2d11ef0
Merge remote-tracking branch 'origin/master' into gui-inherent-forced…
gui1117 Mar 4, 2021
bf3cb1d
fix test
gui1117 Mar 4, 2021
7d271c4
fix testing
gui1117 Mar 4, 2021
1dc15e2
fix tests
gui1117 Mar 4, 2021
e8a2e08
return index of extrinsic on error
gui1117 Mar 9, 2021
c33fcf3
Merge remote-tracking branch 'origin/master' into gui-inherent-forced…
gui1117 Mar 9, 2021
1aa24b9
fix test
gui1117 Mar 10, 2021
5b9561d
Merge remote-tracking branch 'origin/master' into gui-inherent-forced…
gui1117 Mar 10, 2021
325d50c
Update primitives/inherents/src/lib.rs
gui1117 Mar 15, 2021
7f9c9a9
address comments
gui1117 Mar 15, 2021
bcb5188
Merge remote-tracking branch 'origin/master' into gui-inherent-forced…
gui1117 Mar 15, 2021
9680c42
Merge remote-tracking branch 'origin/master' into gui-inherent-forced…
gui1117 Mar 16, 2021
3f6fefb
refactor + doc improvment
gui1117 Mar 16, 2021
d204996
Merge remote-tracking branch 'origin/master' into gui-inherent-forced…
gui1117 Mar 18, 2021
35f1b5c
fix tests
gui1117 Mar 18, 2021
cb6f7aa
Merge remote-tracking branch 'origin/master' into gui-inherent-forced…
gui1117 Mar 23, 2021
d1fa0f7
Merge remote-tracking branch 'origin/master' into gui-inherent-forced…
gui1117 Apr 12, 2021
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions frame/authorship/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -392,6 +392,10 @@ impl<T: Config> ProvideInherent for Module<T> {
},
}
}

fn is_inherent(call: &Self::Call) -> bool {
matches!(call, Call::set_uncles(_))
}
}

#[cfg(test)]
Expand Down
1 change: 1 addition & 0 deletions frame/executive/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ pallet-indices = { version = "3.0.0", path = "../indices" }
pallet-balances = { version = "3.0.0", path = "../balances" }
pallet-transaction-payment = { version = "3.0.0", path = "../transaction-payment" }
sp-version = { version = "3.0.0", path = "../../primitives/version" }
sp-inherents = { version = "3.0.0", path = "../../primitives/inherents" }

[features]
default = ["std"]
Expand Down
107 changes: 96 additions & 11 deletions frame/executive/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,10 @@
use sp_std::{prelude::*, marker::PhantomData};
use frame_support::{
weights::{GetDispatchInfo, DispatchInfo, DispatchClass},
traits::{OnInitialize, OnIdle, OnFinalize, OnRuntimeUpgrade, OffchainWorker, ExecuteBlock},
traits::{
OnInitialize, OnIdle, OnFinalize, OnRuntimeUpgrade, OffchainWorker, ExecuteBlock,
EnsureInherentsAreFirst,
},
dispatch::PostDispatchInfo,
};
use sp_runtime::{
Expand Down Expand Up @@ -153,7 +156,7 @@ pub struct Executive<System, Block, Context, UnsignedValidator, AllModules, OnRu
);

impl<
System: frame_system::Config,
System: frame_system::Config + EnsureInherentsAreFirst<Block>,
Block: traits::Block<Header=System::Header, Hash=System::Hash>,
Context: Default,
UnsignedValidator,
Expand Down Expand Up @@ -181,7 +184,7 @@ where
}

impl<
System: frame_system::Config,
System: frame_system::Config + EnsureInherentsAreFirst<Block>,
Block: traits::Block<Header = System::Header, Hash = System::Hash>,
Context: Default,
UnsignedValidator,
Expand Down Expand Up @@ -311,6 +314,10 @@ where
&& <frame_system::Module<System>>::block_hash(n - System::BlockNumber::one()) == *header.parent_hash(),
"Parent hash should be valid.",
);

if let Err(i) = System::ensure_inherents_are_first(block) {
panic!("Invalid inherent position for extrinsic at index {}", i);
}
}

/// Actually execute all transitions for `block`.
Expand Down Expand Up @@ -543,7 +550,7 @@ mod tests {
mod custom {
use frame_support::weights::{Weight, DispatchClass};
use sp_runtime::transaction_validity::{
UnknownTransaction, TransactionSource, TransactionValidity
UnknownTransaction, TransactionSource, TransactionValidity, TransactionValidityError,
};

pub trait Config: frame_system::Config {}
Expand Down Expand Up @@ -574,6 +581,11 @@ mod tests {
let _ = frame_system::ensure_root(origin)?;
}

#[weight = 0]
fn inherent_call(origin) {
let _ = frame_system::ensure_none(origin)?;
}

// module hooks.
// one with block number arg and one without
fn on_initialize(n: T::BlockNumber) -> Weight {
Expand Down Expand Up @@ -607,9 +619,22 @@ mod tests {
}
}

impl<T: Config> sp_inherents::ProvideInherent for Module<T> {
type Call = Call<T>;
type Error = sp_inherents::MakeFatalError<()>;
const INHERENT_IDENTIFIER: [u8; 8] = *b"test1234";
fn create_inherent(_data: &sp_inherents::InherentData) -> Option<Self::Call> {
None
}
fn is_inherent(call: &Self::Call) -> bool {
*call == Call::<T>::inherent_call()
}
}

impl<T: Config> sp_runtime::traits::ValidateUnsigned for Module<T> {
type Call = Call<T>;

// Inherent call is not validated as unsigned
fn validate_unsigned(
_source: TransactionSource,
call: &Self::Call,
Expand All @@ -618,6 +643,18 @@ mod tests {
Call::allowed_unsigned(..) => Ok(Default::default()),
_ => UnknownTransaction::NoUnsignedValidator.into(),
}

}

// Inherent call is accepted for being dispatched
fn pre_dispatch(
call: &Self::Call,
) -> Result<(), TransactionValidityError> {
match call {
Call::allowed_unsigned(..) => Ok(()),
Call::inherent_call(..) => Ok(()),
gui1117 marked this conversation as resolved.
Show resolved Hide resolved
_ => Err(UnknownTransaction::NoUnsignedValidator.into()),
}
}
}
}
Expand All @@ -630,7 +667,7 @@ mod tests {
{
System: frame_system::{Module, Call, Config, Storage, Event<T>},
Balances: pallet_balances::{Module, Call, Storage, Config<T>, Event<T>},
Custom: custom::{Module, Call, ValidateUnsigned},
Custom: custom::{Module, Call, ValidateUnsigned, Inherent},
}
);

Expand Down Expand Up @@ -717,12 +754,7 @@ mod tests {
);
type TestXt = sp_runtime::testing::TestXt<Call, SignedExtra>;
type TestBlock = Block<TestXt>;
type TestUncheckedExtrinsic = sp_runtime::generic::UncheckedExtrinsic<
<Runtime as frame_system::Config>::AccountId,
<Runtime as frame_system::Config>::Call,
(),
SignedExtra,
>;
type TestUncheckedExtrinsic = TestXt;

// Will contain `true` when the custom runtime logic was called.
const CUSTOM_ON_RUNTIME_KEY: &[u8] = &*b":custom:on_runtime";
Expand Down Expand Up @@ -1226,4 +1258,57 @@ mod tests {
Executive::execute_block(Block::new(header, vec![xt]));
});
}

#[test]
#[should_panic(expected = "Invalid inherent position for extrinsic at index 1")]
fn invalid_inherent_position_fail() {
let xt1 = TestXt::new(Call::Balances(BalancesCall::transfer(33, 0)), sign_extra(1, 0, 0));
let xt2 = TestXt::new(Call::Custom(custom::Call::inherent_call()), None);

let header = new_test_ext(1).execute_with(|| {
// Let's build some fake block.
Executive::initialize_block(&Header::new(
1,
H256::default(),
H256::default(),
[69u8; 32].into(),
Digest::default(),
));

Executive::apply_extrinsic(xt1.clone()).unwrap().unwrap();
Executive::apply_extrinsic(xt2.clone()).unwrap().unwrap();

Executive::finalize_block()
});

new_test_ext(1).execute_with(|| {
Executive::execute_block(Block::new(header, vec![xt1, xt2]));
});
}

#[test]
fn valid_inherents_position_works() {
let xt1 = TestXt::new(Call::Custom(custom::Call::inherent_call()), None);
let xt2 = TestXt::new(Call::Balances(BalancesCall::transfer(33, 0)), sign_extra(1, 0, 0));

let header = new_test_ext(1).execute_with(|| {
// Let's build some fake block.
Executive::initialize_block(&Header::new(
1,
H256::default(),
H256::default(),
[69u8; 32].into(),
Digest::default(),
));

Executive::apply_extrinsic(xt1.clone()).unwrap().unwrap();
Executive::apply_extrinsic(xt2.clone()).unwrap().unwrap();

Executive::finalize_block()
});

new_test_ext(1).execute_with(|| {
Executive::execute_block(Block::new(header, vec![xt1, xt2]));
});
}
}
5 changes: 4 additions & 1 deletion frame/support/procedural/src/construct_runtime/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,7 @@ fn construct_runtime_parsed(definition: RuntimeDefinition) -> Result<TokenStream
let metadata = decl_runtime_metadata(&name, modules.iter(), &scrate, &unchecked_extrinsic);
let outer_config = decl_outer_config(&name, modules.iter(), &scrate);
let inherent = decl_outer_inherent(
&name,
&block,
&unchecked_extrinsic,
modules.iter(),
Expand Down Expand Up @@ -235,6 +236,7 @@ fn decl_validate_unsigned<'a>(
}

fn decl_outer_inherent<'a>(
runtime: &'a Ident,
block: &'a syn::TypePath,
unchecked_extrinsic: &'a syn::TypePath,
module_declarations: impl Iterator<Item = &'a Module>,
Expand All @@ -251,7 +253,8 @@ fn decl_outer_inherent<'a>(
#scrate::impl_outer_inherent!(
impl Inherents where
Block = #block,
UncheckedExtrinsic = #unchecked_extrinsic
UncheckedExtrinsic = #unchecked_extrinsic,
Runtime = #runtime,
{
#(#modules_tokens)*
}
Expand Down
Loading