Pass transaction source to validate_transaction (#5366)

* WiP

* Support source in the runtime API.

* Finish implementation in txpool.

* Fix warning.

* Fix tests.

* Apply suggestions from code review

Co-Authored-By: Kian Paimani <5588131+kianenigma@users.noreply.github.com>
Co-Authored-By: Nikolay Volf <nikvolf@gmail.com>

* Extra changes.

* Fix test and benches.

* fix test

* Fix test & benches again.

* Fix tests.

* Update bumpalo

* Fix doc test.

* Fix doctest.

* Fix doctest.

Co-authored-by: Kian Paimani <5588131+kianenigma@users.noreply.github.com>
Co-authored-by: Nikolay Volf <nikvolf@gmail.com>
This commit is contained in:
Tomasz Drwięga
2020-03-25 14:09:23 +01:00
committed by GitHub
parent 601ac11e52
commit 04ccb179e9
37 changed files with 414 additions and 163 deletions
@@ -51,7 +51,9 @@ use sp_core::crypto::KeyTypeId;
use sp_runtime::{
offchain::{http, Duration, storage::StorageValueRef},
traits::Zero,
transaction_validity::{InvalidTransaction, ValidTransaction, TransactionValidity},
transaction_validity::{
InvalidTransaction, ValidTransaction, TransactionValidity, TransactionSource,
},
};
use sp_std::{vec, vec::Vec};
use lite_json::json::JsonValue;
@@ -509,7 +511,10 @@ impl<T: Trait> frame_support::unsigned::ValidateUnsigned for Module<T> {
/// By default unsigned transactions are disallowed, but implementing the validator
/// here we make sure that some particular calls (the ones produced by offchain worker)
/// are being whitelisted and marked as valid.
fn validate_unsigned(call: &Self::Call) -> TransactionValidity {
fn validate_unsigned(
_source: TransactionSource,
call: &Self::Call,
) -> TransactionValidity {
// Firstly let's check that we call the right function.
if let Call::submit_price_unsigned(block_number, new_price) = call {
// Now let's check if the transaction has any chance to succeed.
+18 -7
View File
@@ -59,12 +59,14 @@
//! # pub type Balances = u64;
//! # pub type AllModules = u64;
//! # pub enum Runtime {};
//! # use sp_runtime::transaction_validity::{TransactionValidity, UnknownTransaction};
//! # use sp_runtime::transaction_validity::{
//! TransactionValidity, UnknownTransaction, TransactionSource,
//! # };
//! # use sp_runtime::traits::ValidateUnsigned;
//! # impl ValidateUnsigned for Runtime {
//! # type Call = ();
//! #
//! # fn validate_unsigned(_call: &Self::Call) -> TransactionValidity {
//! # fn validate_unsigned(_source: TransactionSource, _call: &Self::Call) -> TransactionValidity {
//! # UnknownTransaction::NoUnsignedValidator.into()
//! # }
//! # }
@@ -85,7 +87,7 @@ use sp_runtime::{
self, Header, Zero, One, Checkable, Applyable, CheckEqual, ValidateUnsigned, NumberFor,
Block as BlockT, Dispatchable, Saturating,
},
transaction_validity::TransactionValidity,
transaction_validity::{TransactionValidity, TransactionSource},
};
use codec::{Codec, Encode};
use frame_system::{extrinsics_root, DigestOf};
@@ -338,12 +340,15 @@ where
/// side-effects; it merely checks whether the transaction would panic if it were included or not.
///
/// Changes made to storage should be discarded.
pub fn validate_transaction(uxt: Block::Extrinsic) -> TransactionValidity {
pub fn validate_transaction(
source: TransactionSource,
uxt: Block::Extrinsic,
) -> TransactionValidity {
let encoded_len = uxt.using_encoded(|d| d.len());
let xt = uxt.check(&Default::default())?;
let dispatch_info = xt.get_dispatch_info();
xt.validate::<UnsignedValidator>(dispatch_info, encoded_len)
xt.validate::<UnsignedValidator>(source, dispatch_info, encoded_len)
}
/// Start an offchain worker and generate extrinsics.
@@ -511,7 +516,10 @@ mod tests {
Ok(())
}
fn validate_unsigned(call: &Self::Call) -> TransactionValidity {
fn validate_unsigned(
_source: TransactionSource,
call: &Self::Call,
) -> TransactionValidity {
match call {
Call::Balances(BalancesCall::set_balance(_, _, _)) => Ok(Default::default()),
_ => UnknownTransaction::NoUnsignedValidator.into(),
@@ -725,7 +733,10 @@ mod tests {
let mut t = new_test_ext(1);
t.execute_with(|| {
assert_eq!(Executive::validate_transaction(xt.clone()), Ok(Default::default()));
assert_eq!(
Executive::validate_transaction(TransactionSource::InBlock, xt.clone()),
Ok(Default::default()),
);
assert_eq!(Executive::apply_extrinsic(xt), Ok(Err(DispatchError::BadOrigin)));
});
}
@@ -24,6 +24,7 @@ use frame_system::RawOrigin;
use frame_benchmarking::benchmarks;
use sp_core::offchain::{OpaquePeerId, OpaqueMultiaddr};
use sp_runtime::traits::{ValidateUnsigned, Zero};
use sp_runtime::transaction_validity::TransactionSource;
use crate::Module as ImOnline;
@@ -72,7 +73,7 @@ benchmarks! {
let (input_heartbeat, signature) = create_heartbeat::<T>(k, e)?;
let call = Call::heartbeat(input_heartbeat, signature);
}: {
ImOnline::<T>::validate_unsigned(&call)?;
ImOnline::<T>::validate_unsigned(TransactionSource::InBlock, &call)?;
}
}
+5 -2
View File
@@ -82,7 +82,7 @@ use sp_runtime::{
RuntimeDebug,
traits::{Convert, Member, Saturating, AtLeast32Bit}, Perbill, PerThing,
transaction_validity::{
TransactionValidity, ValidTransaction, InvalidTransaction,
TransactionValidity, ValidTransaction, InvalidTransaction, TransactionSource,
TransactionPriority,
},
};
@@ -624,7 +624,10 @@ impl<T: Trait> pallet_session::OneSessionHandler<T::AccountId> for Module<T> {
impl<T: Trait> frame_support::unsigned::ValidateUnsigned for Module<T> {
type Call = Call<T>;
fn validate_unsigned(call: &Self::Call) -> TransactionValidity {
fn validate_unsigned(
_source: TransactionSource,
call: &Self::Call,
) -> TransactionValidity {
if let Call::heartbeat(heartbeat, signature) = call {
if <Module<T>>::is_online(heartbeat.authority_index) {
// we already received a heartbeat for this authority
@@ -89,7 +89,7 @@ fn construct_runtime_parsed(definition: RuntimeDefinition) -> Result<TokenStream
let inherent = decl_outer_inherent(&block, &unchecked_extrinsic, modules.iter(), &scrate);
let validate_unsigned = decl_validate_unsigned(&name, modules.iter(), &scrate);
Ok(quote!(
let res = quote!(
#scrate_decl
#[derive(Clone, Copy, PartialEq, Eq)]
@@ -119,8 +119,9 @@ fn construct_runtime_parsed(definition: RuntimeDefinition) -> Result<TokenStream
#inherent
#validate_unsigned
)
.into())
);
Ok(res.into())
}
fn decl_validate_unsigned<'a>(
+13 -5
View File
@@ -18,7 +18,7 @@
pub use crate::sp_runtime::traits::ValidateUnsigned;
#[doc(hidden)]
pub use crate::sp_runtime::transaction_validity::{
TransactionValidity, UnknownTransaction, TransactionValidityError,
TransactionValidity, UnknownTransaction, TransactionValidityError, TransactionSource,
};
@@ -34,7 +34,8 @@ pub use crate::sp_runtime::transaction_validity::{
/// # impl frame_support::unsigned::ValidateUnsigned for Module {
/// # type Call = Call;
/// #
/// # fn validate_unsigned(call: &Self::Call) -> frame_support::unsigned::TransactionValidity {
/// # fn validate_unsigned(_source: frame_support::unsigned::TransactionSource, _call: &Self::Call)
/// -> frame_support::unsigned::TransactionValidity {
/// # unimplemented!();
/// # }
/// # }
@@ -78,10 +79,14 @@ macro_rules! impl_outer_validate_unsigned {
}
}
fn validate_unsigned(call: &Self::Call) -> $crate::unsigned::TransactionValidity {
fn validate_unsigned(
#[allow(unused_variables)]
source: $crate::unsigned::TransactionSource,
call: &Self::Call,
) -> $crate::unsigned::TransactionValidity {
#[allow(unreachable_patterns)]
match call {
$( Call::$module(inner_call) => $module::validate_unsigned(inner_call), )*
$( Call::$module(inner_call) => $module::validate_unsigned(source, inner_call), )*
_ => $crate::unsigned::UnknownTransaction::NoUnsignedValidator.into(),
}
}
@@ -110,7 +115,10 @@ mod test_partial_and_full_call {
impl super::super::ValidateUnsigned for Module {
type Call = Call;
fn validate_unsigned(_call: &Self::Call) -> super::super::TransactionValidity {
fn validate_unsigned(
_source: super::super::TransactionSource,
_call: &Self::Call
) -> super::super::TransactionValidity {
unimplemented!();
}
}