Skip to content

Commit 8e3d929

Browse files
authored
[Tx ext stage 2: 1/4] Add TransactionSource as argument in TransactionExtension::validate (#6323)
## Meta This PR is part of 4 PR: * #6323 * #6324 * #6325 * #6326 ## Description One goal of transaction extension is to get rid or unsigned transactions. But unsigned transaction validation has access to the `TransactionSource`. The source is used for unsigned transactions that the node trust and don't want to pay upfront. Instead of using transaction source we could do: the transaction is valid if it is signed by the block author, conceptually it should work, but it doesn't look so easy. This PR add `TransactionSource` to the validate function for transaction extensions
1 parent 5aeaa66 commit 8e3d929

27 files changed

Lines changed: 217 additions & 65 deletions

File tree

bridges/bin/runtime-common/src/extensions.rs

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -299,6 +299,7 @@ macro_rules! generate_bridge_reject_obsolete_headers_and_messages {
299299
_len: usize,
300300
_self_implicit: Self::Implicit,
301301
_inherited_implication: &impl codec::Encode,
302+
_source: sp_runtime::transaction_validity::TransactionSource,
302303
) -> Result<
303304
(
304305
sp_runtime::transaction_validity::ValidTransaction,
@@ -390,7 +391,9 @@ mod tests {
390391
parameter_types, AsSystemOriginSigner, AsTransactionAuthorizedOrigin, ConstU64,
391392
DispatchTransaction, Header as _, TransactionExtension,
392393
},
393-
transaction_validity::{InvalidTransaction, TransactionValidity, ValidTransaction},
394+
transaction_validity::{
395+
InvalidTransaction, TransactionSource::External, TransactionValidity, ValidTransaction,
396+
},
394397
DispatchError,
395398
};
396399

@@ -610,7 +613,8 @@ mod tests {
610613
42u64.into(),
611614
&MockCall { data: 1 },
612615
&(),
613-
0
616+
0,
617+
External,
614618
),
615619
InvalidTransaction::Custom(1)
616620
);
@@ -629,7 +633,8 @@ mod tests {
629633
42u64.into(),
630634
&MockCall { data: 2 },
631635
&(),
632-
0
636+
0,
637+
External,
633638
),
634639
InvalidTransaction::Custom(2)
635640
);
@@ -645,7 +650,7 @@ mod tests {
645650

646651
assert_eq!(
647652
BridgeRejectObsoleteHeadersAndMessages
648-
.validate_only(42u64.into(), &MockCall { data: 3 }, &(), 0)
653+
.validate_only(42u64.into(), &MockCall { data: 3 }, &(), 0, External)
649654
.unwrap()
650655
.0,
651656
ValidTransaction { priority: 3, ..Default::default() },

bridges/modules/relayers/src/extension/mod.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ use bp_runtime::{Chain, RangeInclusiveExt, StaticStrProvider};
3333
use codec::{Decode, Encode};
3434
use frame_support::{
3535
dispatch::{DispatchInfo, PostDispatchInfo},
36+
pallet_prelude::TransactionSource,
3637
weights::Weight,
3738
CloneNoBound, DefaultNoBound, EqNoBound, PartialEqNoBound, RuntimeDebugNoBound,
3839
};
@@ -304,6 +305,7 @@ where
304305
_len: usize,
305306
_self_implicit: Self::Implicit,
306307
_inherited_implication: &impl Encode,
308+
_source: TransactionSource,
307309
) -> ValidateResult<Self::Val, R::RuntimeCall> {
308310
// Prepare relevant data for `prepare`
309311
let parsed_call = match C::parse_and_check_for_obsolete_call(call)? {
@@ -463,7 +465,9 @@ mod tests {
463465
use pallet_utility::Call as UtilityCall;
464466
use sp_runtime::{
465467
traits::{ConstU64, DispatchTransaction, Header as HeaderT},
466-
transaction_validity::{InvalidTransaction, TransactionValidity, ValidTransaction},
468+
transaction_validity::{
469+
InvalidTransaction, TransactionSource::External, TransactionValidity, ValidTransaction,
470+
},
467471
DispatchError,
468472
};
469473

@@ -1076,6 +1080,7 @@ mod tests {
10761080
&call,
10771081
&DispatchInfo::default(),
10781082
0,
1083+
External,
10791084
)
10801085
.map(|t| t.0)
10811086
}
@@ -1088,6 +1093,7 @@ mod tests {
10881093
&call,
10891094
&DispatchInfo::default(),
10901095
0,
1096+
External,
10911097
)
10921098
.map(|t| t.0)
10931099
}
@@ -1100,6 +1106,7 @@ mod tests {
11001106
&call,
11011107
&DispatchInfo::default(),
11021108
0,
1109+
External,
11031110
)
11041111
.map(|t| t.0)
11051112
}

polkadot/runtime/common/src/claims.rs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,8 @@ use sp_runtime::{
3939
Dispatchable, TransactionExtension, Zero,
4040
},
4141
transaction_validity::{
42-
InvalidTransaction, TransactionValidity, TransactionValidityError, ValidTransaction,
42+
InvalidTransaction, TransactionSource, TransactionValidity, TransactionValidityError,
43+
ValidTransaction,
4344
},
4445
RuntimeDebug,
4546
};
@@ -663,6 +664,7 @@ where
663664
_len: usize,
664665
_self_implicit: Self::Implicit,
665666
_inherited_implication: &impl Encode,
667+
_source: TransactionSource,
666668
) -> Result<
667669
(ValidTransaction, Self::Val, <T::RuntimeCall as Dispatchable>::RuntimeOrigin),
668670
TransactionValidityError,
@@ -716,6 +718,7 @@ mod tests {
716718
use super::*;
717719
use hex_literal::hex;
718720
use secp_utils::*;
721+
use sp_runtime::transaction_validity::TransactionSource::External;
719722

720723
use codec::Encode;
721724
// The testing primitives are very useful for avoiding having to work with signatures
@@ -1075,7 +1078,7 @@ mod tests {
10751078
});
10761079
let di = c.get_dispatch_info();
10771080
assert_eq!(di.pays_fee, Pays::No);
1078-
let r = p.validate_only(Some(42).into(), &c, &di, 20);
1081+
let r = p.validate_only(Some(42).into(), &c, &di, 20, External);
10791082
assert_eq!(r.unwrap().0, ValidTransaction::default());
10801083
});
10811084
}
@@ -1088,13 +1091,13 @@ mod tests {
10881091
statement: StatementKind::Regular.to_text().to_vec(),
10891092
});
10901093
let di = c.get_dispatch_info();
1091-
let r = p.validate_only(Some(42).into(), &c, &di, 20);
1094+
let r = p.validate_only(Some(42).into(), &c, &di, 20, External);
10921095
assert!(r.is_err());
10931096
let c = RuntimeCall::Claims(ClaimsCall::attest {
10941097
statement: StatementKind::Saft.to_text().to_vec(),
10951098
});
10961099
let di = c.get_dispatch_info();
1097-
let r = p.validate_only(Some(69).into(), &c, &di, 20);
1100+
let r = p.validate_only(Some(69).into(), &c, &di, 20, External);
10981101
assert!(r.is_err());
10991102
});
11001103
}

prdoc/pr_6323.prdoc

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
title: add `TransactionSource` to `TransactionExtension::validate`
2+
doc:
3+
- audience: Runtime Dev
4+
description: |
5+
Add a the source of the extrinsic as an argument in `TransactionExtension::validate`.
6+
The transaction source can be useful for transactions that should only be valid if it comes from the node. For example from offchain worker.
7+
To update the current code. The transaction source can simply be ignored: `_source: TransactionSource`
8+
9+
10+
crates:
11+
- name: sp-runtime
12+
bump: major
13+
- name: bridge-runtime-common
14+
bump: patch
15+
- name: frame-system
16+
bump: patch
17+
- name: pallet-transaction-payment
18+
bump: patch
19+
- name: polkadot-runtime-common
20+
bump: patch
21+
- name: pallet-sudo
22+
bump: patch
23+
- name: pallet-verify-signature
24+
bump: patch
25+
- name: pallet-asset-tx-payment
26+
bump: patch
27+
- name: pallet-bridge-relayers
28+
bump: patch
29+
- name: pallet-asset-conversion-tx-payment
30+
bump: patch
31+
- name: pallet-skip-feeless-payment
32+
bump: patch

substrate/frame/examples/authorization-tx-extension/src/extensions.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
use core::{fmt, marker::PhantomData};
1919

2020
use codec::{Decode, Encode};
21-
use frame_support::{traits::OriginTrait, Parameter};
21+
use frame_support::{pallet_prelude::TransactionSource, traits::OriginTrait, Parameter};
2222
use scale_info::TypeInfo;
2323
use sp_runtime::{
2424
impl_tx_ext_default,
@@ -94,6 +94,7 @@ where
9494
_len: usize,
9595
_self_implicit: Self::Implicit,
9696
inherited_implication: &impl codec::Encode,
97+
_source: TransactionSource,
9798
) -> ValidateResult<Self::Val, T::RuntimeCall> {
9899
// If the extension is inactive, just move on in the pipeline.
99100
let Some(auth) = &self.inner else {

substrate/frame/examples/basic/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ use codec::{Decode, Encode};
6161
use core::marker::PhantomData;
6262
use frame_support::{
6363
dispatch::{ClassifyDispatch, DispatchClass, DispatchResult, Pays, PaysFee, WeighData},
64+
pallet_prelude::TransactionSource,
6465
traits::IsSubType,
6566
weights::Weight,
6667
};
@@ -508,6 +509,7 @@ where
508509
len: usize,
509510
_self_implicit: Self::Implicit,
510511
_inherited_implication: &impl Encode,
512+
_source: TransactionSource,
511513
) -> ValidateResult<Self::Val, <T as frame_system::Config>::RuntimeCall> {
512514
// if the transaction is too big, just drop it.
513515
if len > 200 {

substrate/frame/examples/basic/src/tests.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ use sp_core::H256;
2828
// or public keys. `u64` is used as the `AccountId` and no `Signature`s are required.
2929
use sp_runtime::{
3030
traits::{BlakeTwo256, DispatchTransaction, IdentityLookup},
31+
transaction_validity::TransactionSource::External,
3132
BuildStorage,
3233
};
3334
// Reexport crate as its pallet name for construct_runtime.
@@ -146,15 +147,15 @@ fn signed_ext_watch_dummy_works() {
146147

147148
assert_eq!(
148149
WatchDummy::<Test>(PhantomData)
149-
.validate_only(Some(1).into(), &call, &info, 150)
150+
.validate_only(Some(1).into(), &call, &info, 150, External)
150151
.unwrap()
151152
.0
152153
.priority,
153154
u64::MAX,
154155
);
155156
assert_eq!(
156157
WatchDummy::<Test>(PhantomData)
157-
.validate_only(Some(1).into(), &call, &info, 250)
158+
.validate_only(Some(1).into(), &call, &info, 250, External)
158159
.unwrap_err(),
159160
InvalidTransaction::ExhaustsResources.into(),
160161
);

substrate/frame/sudo/src/extension.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
use crate::{Config, Key};
1919
use codec::{Decode, Encode};
2020
use core::{fmt, marker::PhantomData};
21-
use frame_support::{dispatch::DispatchInfo, ensure};
21+
use frame_support::{dispatch::DispatchInfo, ensure, pallet_prelude::TransactionSource};
2222
use scale_info::TypeInfo;
2323
use sp_runtime::{
2424
impl_tx_ext_default,
@@ -94,6 +94,7 @@ where
9494
_len: usize,
9595
_self_implicit: Self::Implicit,
9696
_inherited_implication: &impl Encode,
97+
_source: TransactionSource,
9798
) -> Result<
9899
(
99100
ValidTransaction,

substrate/frame/system/src/extensions/check_mortality.rs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
use crate::{pallet_prelude::BlockNumberFor, BlockHash, Config, Pallet};
1919
use codec::{Decode, Encode};
20+
use frame_support::pallet_prelude::TransactionSource;
2021
use scale_info::TypeInfo;
2122
use sp_runtime::{
2223
generic::Era,
@@ -91,6 +92,7 @@ impl<T: Config + Send + Sync> TransactionExtension<T::RuntimeCall> for CheckMort
9192
_len: usize,
9293
_self_implicit: Self::Implicit,
9394
_inherited_implication: &impl Encode,
95+
_source: TransactionSource,
9496
) -> ValidateResult<Self::Val, T::RuntimeCall> {
9597
let current_u64 = <Pallet<T>>::block_number().saturated_into::<u64>();
9698
let valid_till = self.0.death(current_u64);
@@ -115,7 +117,9 @@ mod tests {
115117
weights::Weight,
116118
};
117119
use sp_core::H256;
118-
use sp_runtime::traits::DispatchTransaction;
120+
use sp_runtime::{
121+
traits::DispatchTransaction, transaction_validity::TransactionSource::External,
122+
};
119123

120124
#[test]
121125
fn signed_ext_check_era_should_work() {
@@ -151,7 +155,10 @@ mod tests {
151155
<BlockHash<Test>>::insert(16, H256::repeat_byte(1));
152156

153157
assert_eq!(
154-
ext.validate_only(Some(1).into(), CALL, &normal, len).unwrap().0.longevity,
158+
ext.validate_only(Some(1).into(), CALL, &normal, len, External)
159+
.unwrap()
160+
.0
161+
.longevity,
155162
15
156163
);
157164
})

substrate/frame/system/src/extensions/check_non_zero_sender.rs

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
use crate::Config;
1919
use codec::{Decode, Encode};
2020
use core::marker::PhantomData;
21-
use frame_support::{traits::OriginTrait, DefaultNoBound};
21+
use frame_support::{pallet_prelude::TransactionSource, traits::OriginTrait, DefaultNoBound};
2222
use scale_info::TypeInfo;
2323
use sp_runtime::{
2424
impl_tx_ext_default,
@@ -68,6 +68,7 @@ impl<T: Config + Send + Sync> TransactionExtension<T::RuntimeCall> for CheckNonZ
6868
_len: usize,
6969
_self_implicit: Self::Implicit,
7070
_inherited_implication: &impl Encode,
71+
_source: TransactionSource,
7172
) -> sp_runtime::traits::ValidateResult<Self::Val, T::RuntimeCall> {
7273
if let Some(who) = origin.as_signer() {
7374
if who.using_encoded(|d| d.iter().all(|x| *x == 0)) {
@@ -86,7 +87,7 @@ mod tests {
8687
use frame_support::{assert_ok, dispatch::DispatchInfo};
8788
use sp_runtime::{
8889
traits::{AsTransactionAuthorizedOrigin, DispatchTransaction},
89-
transaction_validity::TransactionValidityError,
90+
transaction_validity::{TransactionSource::External, TransactionValidityError},
9091
};
9192

9293
#[test]
@@ -96,15 +97,16 @@ mod tests {
9697
let len = 0_usize;
9798
assert_eq!(
9899
CheckNonZeroSender::<Test>::new()
99-
.validate_only(Some(0).into(), CALL, &info, len)
100+
.validate_only(Some(0).into(), CALL, &info, len, External)
100101
.unwrap_err(),
101102
TransactionValidityError::from(InvalidTransaction::BadSigner)
102103
);
103104
assert_ok!(CheckNonZeroSender::<Test>::new().validate_only(
104105
Some(1).into(),
105106
CALL,
106107
&info,
107-
len
108+
len,
109+
External,
108110
));
109111
})
110112
}
@@ -115,7 +117,7 @@ mod tests {
115117
let info = DispatchInfo::default();
116118
let len = 0_usize;
117119
let (_, _, origin) = CheckNonZeroSender::<Test>::new()
118-
.validate(None.into(), CALL, &info, len, (), CALL)
120+
.validate(None.into(), CALL, &info, len, (), CALL, External)
119121
.unwrap();
120122
assert!(!origin.is_transaction_authorized());
121123
})

0 commit comments

Comments
 (0)