Skip to content

Commit cfef5ca

Browse files
boundless-foresticodezjb
authored andcommitted
Add CheckWeight for evm txs, copy from
(1) Add extrinsic weight and lenght check (polkadot-evm#637) (2) fix(frame): CheckWeight controls should be applied on pre_dispatch (polkadot-evm#749)
1 parent b36e8b9 commit cfef5ca

File tree

10 files changed

+255
-150
lines changed

10 files changed

+255
-150
lines changed

Cargo.lock

+108-108
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

frame/ethereum/src/lib.rs

+22-5
Original file line numberDiff line numberDiff line change
@@ -40,14 +40,14 @@ use frame_support::{
4040
dispatch::DispatchResultWithPostInfo,
4141
scale_info::TypeInfo,
4242
traits::{EnsureOrigin, Get, PalletInfoAccess},
43-
weights::{Pays, PostDispatchInfo, Weight},
43+
weights::{DispatchInfo, Pays, PostDispatchInfo, Weight},
4444
};
45-
use frame_system::{pallet_prelude::OriginFor, WeightInfo};
45+
use frame_system::{pallet_prelude::OriginFor, CheckWeight, WeightInfo};
4646
use pallet_evm::{BlockHashMapping, FeeCalculator, GasWeightMapping, Runner};
4747
use sha3::{Digest, Keccak256};
4848
use sp_runtime::{
4949
generic::DigestItem,
50-
traits::{One, Saturating, UniqueSaturatedInto, Zero},
50+
traits::{DispatchInfoOf, Dispatchable, One, Saturating, UniqueSaturatedInto, Zero},
5151
transaction_validity::{
5252
InvalidTransaction, TransactionValidity, TransactionValidityError, ValidTransactionBuilder,
5353
},
@@ -110,6 +110,8 @@ impl<O: Into<Result<RawOrigin, O>> + From<RawOrigin>> EnsureOrigin<O>
110110
impl<T: Config> Call<T>
111111
where
112112
OriginFor<T>: Into<Result<RawOrigin, OriginFor<T>>>,
113+
T: Send + Sync + Config,
114+
T::Call: Dispatchable<Info = DispatchInfo, PostInfo = PostDispatchInfo>,
113115
{
114116
pub fn is_self_contained(&self) -> bool {
115117
match self {
@@ -137,19 +139,34 @@ where
137139
pub fn pre_dispatch_self_contained(
138140
&self,
139141
origin: &H160,
142+
dispatch_info: &DispatchInfoOf<T::Call>,
143+
len: usize,
140144
) -> Option<Result<(), TransactionValidityError>> {
141145
if let Call::transact { transaction } = self {
146+
if let Err(e) = CheckWeight::<T>::do_pre_dispatch(dispatch_info, len) {
147+
return Some(Err(e));
148+
}
149+
142150
Some(Pallet::<T>::validate_transaction_in_block(
143151
*origin,
144-
&transaction,
152+
transaction,
145153
))
146154
} else {
147155
None
148156
}
149157
}
150158

151-
pub fn validate_self_contained(&self, origin: &H160) -> Option<TransactionValidity> {
159+
pub fn validate_self_contained(
160+
&self,
161+
origin: &H160,
162+
dispatch_info: &DispatchInfoOf<T::Call>,
163+
len: usize,
164+
) -> Option<TransactionValidity> {
152165
if let Call::transact { transaction } = self {
166+
if let Err(e) = CheckWeight::<T>::do_validate(dispatch_info, len) {
167+
return Some(Err(e));
168+
}
169+
153170
Some(Pallet::<T>::validate_transaction_in_pool(
154171
*origin,
155172
transaction,

frame/ethereum/src/mock.rs

+10-3
Original file line numberDiff line numberDiff line change
@@ -193,19 +193,26 @@ impl fp_self_contained::SelfContainedCall for Call {
193193
}
194194
}
195195

196-
fn validate_self_contained(&self, info: &Self::SignedInfo) -> Option<TransactionValidity> {
196+
fn validate_self_contained(
197+
&self,
198+
info: &Self::SignedInfo,
199+
dispatch_info: &DispatchInfoOf<Call>,
200+
len: usize,
201+
) -> Option<TransactionValidity> {
197202
match self {
198-
Call::Ethereum(call) => call.validate_self_contained(info),
203+
Call::Ethereum(call) => call.validate_self_contained(info, dispatch_info, len),
199204
_ => None,
200205
}
201206
}
202207

203208
fn pre_dispatch_self_contained(
204209
&self,
205210
info: &Self::SignedInfo,
211+
dispatch_info: &DispatchInfoOf<Call>,
212+
len: usize,
206213
) -> Option<Result<(), TransactionValidityError>> {
207214
match self {
208-
Call::Ethereum(call) => call.pre_dispatch_self_contained(info),
215+
Call::Ethereum(call) => call.pre_dispatch_self_contained(info, dispatch_info, len),
209216
_ => None,
210217
}
211218
}

frame/ethereum/src/tests/eip1559.rs

+22-7
Original file line numberDiff line numberDiff line change
@@ -61,9 +61,14 @@ fn transaction_without_enough_gas_should_not_work() {
6161

6262
let call = crate::Call::<Test>::transact { transaction };
6363
let source = call.check_self_contained().unwrap().unwrap();
64-
64+
let extrinsic = fp_self_contained::CheckedExtrinsic::<u64, crate::mock::Call, SignedExtra, _> {
65+
signed: fp_self_contained::CheckedSignature::SelfContained(source),
66+
function: Call::Ethereum(call.clone()),
67+
};
68+
let dispatch_info = extrinsic.get_dispatch_info();
6569
assert_err!(
66-
call.validate_self_contained(&source).unwrap(),
70+
call.validate_self_contained(&source, &dispatch_info, 0)
71+
.unwrap(),
6772
InvalidTransaction::Payment
6873
);
6974
});
@@ -83,9 +88,15 @@ fn transaction_with_to_low_nonce_should_not_work() {
8388
transaction: signed,
8489
};
8590
let source = call.check_self_contained().unwrap().unwrap();
91+
let extrinsic = fp_self_contained::CheckedExtrinsic::<u64, crate::mock::Call, SignedExtra, H160> {
92+
signed: fp_self_contained::CheckedSignature::SelfContained(source),
93+
function: Call::Ethereum(call.clone()),
94+
};
95+
let dispatch_info = extrinsic.get_dispatch_info();
8696

8797
assert_eq!(
88-
call.validate_self_contained(&source).unwrap(),
98+
call.validate_self_contained(&source, &dispatch_info, 0)
99+
.unwrap(),
89100
ValidTransactionBuilder::default()
90101
.and_provides((alice.address, U256::from(1)))
91102
.priority(0u64)
@@ -105,9 +116,15 @@ fn transaction_with_to_low_nonce_should_not_work() {
105116
transaction: signed2,
106117
};
107118
let source2 = call2.check_self_contained().unwrap().unwrap();
119+
let extrinsic2 = fp_self_contained::CheckedExtrinsic::<u64, crate::mock::Call, SignedExtra, _> {
120+
signed: fp_self_contained::CheckedSignature::SelfContained(source),
121+
function: Call::Ethereum(call2.clone()),
122+
};
108123

109124
assert_err!(
110-
call2.validate_self_contained(&source2).unwrap(),
125+
call2
126+
.validate_self_contained(&source2, &extrinsic2.get_dispatch_info(), 0)
127+
.unwrap(),
111128
InvalidTransaction::Stale
112129
);
113130
});
@@ -131,7 +148,6 @@ fn transaction_with_to_hight_nonce_should_fail_in_block() {
131148
signed: fp_self_contained::CheckedSignature::SelfContained(source),
132149
function: Call::Ethereum(call),
133150
};
134-
use frame_support::weights::GetDispatchInfo as _;
135151
let dispatch_info = extrinsic.get_dispatch_info();
136152
assert_err!(
137153
extrinsic.apply::<Test>(&dispatch_info, 0),
@@ -155,7 +171,6 @@ fn transaction_with_invalid_chain_id_should_fail_in_block() {
155171
signed: fp_self_contained::CheckedSignature::SelfContained(source),
156172
function: Call::Ethereum(call),
157173
};
158-
use frame_support::weights::GetDispatchInfo as _;
159174
let dispatch_info = extrinsic.get_dispatch_info();
160175
assert_err!(
161176
extrinsic.apply::<Test>(&dispatch_info, 0),
@@ -337,7 +352,7 @@ fn self_contained_transaction_with_extra_gas_should_adjust_weight_with_post_disp
337352
transaction: signed,
338353
};
339354
let source = call.check_self_contained().unwrap().unwrap();
340-
let extrinsic = CheckedExtrinsic::<_, _, frame_system::CheckWeight<Test>, _> {
355+
let extrinsic = fp_self_contained::CheckedExtrinsic::<_, _, frame_system::CheckWeight<Test>, _> {
341356
signed: fp_self_contained::CheckedSignature::SelfContained(source),
342357
function: Call::Ethereum(call),
343358
};

frame/ethereum/src/tests/eip2930.rs

+22-4
Original file line numberDiff line numberDiff line change
@@ -60,9 +60,15 @@ fn transaction_without_enough_gas_should_not_work() {
6060

6161
let call = crate::Call::<Test>::transact { transaction };
6262
let source = call.check_self_contained().unwrap().unwrap();
63+
let extrinsic = fp_self_contained::CheckedExtrinsic::<u64, crate::mock::Call, SignedExtra, _> {
64+
signed: fp_self_contained::CheckedSignature::SelfContained(source),
65+
function: Call::Ethereum(call.clone()),
66+
};
67+
let dispatch_info = extrinsic.get_dispatch_info();
6368

6469
assert_err!(
65-
call.validate_self_contained(&source).unwrap(),
70+
call.validate_self_contained(&source, &dispatch_info, 0)
71+
.unwrap(),
6672
InvalidTransaction::Payment
6773
);
6874
});
@@ -83,9 +89,15 @@ fn transaction_with_to_low_nonce_should_not_work() {
8389
transaction: signed,
8490
};
8591
let source = call.check_self_contained().unwrap().unwrap();
92+
let extrinsic = fp_self_contained::CheckedExtrinsic::<u64, crate::mock::Call, SignedExtra, H160> {
93+
signed: fp_self_contained::CheckedSignature::SelfContained(source),
94+
function: Call::Ethereum(call.clone()),
95+
};
96+
let dispatch_info = extrinsic.get_dispatch_info();
8697

8798
assert_eq!(
88-
call.validate_self_contained(&source).unwrap(),
99+
call.validate_self_contained(&source, &dispatch_info, 0)
100+
.unwrap(),
89101
ValidTransactionBuilder::default()
90102
.and_provides((alice.address, U256::from(1)))
91103
.priority(0u64)
@@ -105,9 +117,15 @@ fn transaction_with_to_low_nonce_should_not_work() {
105117
transaction: signed2,
106118
};
107119
let source2 = call2.check_self_contained().unwrap().unwrap();
120+
let extrinsic2 = fp_self_contained::CheckedExtrinsic::<u64, crate::mock::Call, SignedExtra, _> {
121+
signed: fp_self_contained::CheckedSignature::SelfContained(source),
122+
function: Call::Ethereum(call2.clone()),
123+
};
108124

109125
assert_err!(
110-
call2.validate_self_contained(&source2).unwrap(),
126+
call2
127+
.validate_self_contained(&source2, &extrinsic2.get_dispatch_info(), 0)
128+
.unwrap(),
111129
InvalidTransaction::Stale
112130
);
113131
});
@@ -334,7 +352,7 @@ fn self_contained_transaction_with_extra_gas_should_adjust_weight_with_post_disp
334352
transaction: signed,
335353
};
336354
let source = call.check_self_contained().unwrap().unwrap();
337-
let extrinsic = CheckedExtrinsic::<_, _, frame_system::CheckWeight<Test>, _> {
355+
let extrinsic = fp_self_contained::CheckedExtrinsic::<_, _, frame_system::CheckWeight<Test>, _> {
338356
signed: fp_self_contained::CheckedSignature::SelfContained(source),
339357
function: Call::Ethereum(call),
340358
};

frame/ethereum/src/tests/legacy.rs

+22-4
Original file line numberDiff line numberDiff line change
@@ -60,9 +60,15 @@ fn transaction_without_enough_gas_should_not_work() {
6060

6161
let call = crate::Call::<Test>::transact { transaction };
6262
let source = call.check_self_contained().unwrap().unwrap();
63+
let extrinsic = fp_self_contained::CheckedExtrinsic::<u64, crate::mock::Call, SignedExtra, _> {
64+
signed: fp_self_contained::CheckedSignature::SelfContained(source),
65+
function: Call::Ethereum(call.clone()),
66+
};
67+
let dispatch_info = extrinsic.get_dispatch_info();
6368

6469
assert_err!(
65-
call.validate_self_contained(&source).unwrap(),
70+
call.validate_self_contained(&source, &dispatch_info, 0)
71+
.unwrap(),
6672
InvalidTransaction::Payment
6773
);
6874
});
@@ -83,9 +89,15 @@ fn transaction_with_to_low_nonce_should_not_work() {
8389
transaction: signed,
8490
};
8591
let source = call.check_self_contained().unwrap().unwrap();
92+
let extrinsic = fp_self_contained::CheckedExtrinsic::<u64, crate::mock::Call, SignedExtra, H160> {
93+
signed: fp_self_contained::CheckedSignature::SelfContained(source),
94+
function: Call::Ethereum(call.clone()),
95+
};
96+
let dispatch_info = extrinsic.get_dispatch_info();
8697

8798
assert_eq!(
88-
call.validate_self_contained(&source).unwrap(),
99+
call.validate_self_contained(&source, &dispatch_info, 0)
100+
.unwrap(),
89101
ValidTransactionBuilder::default()
90102
.and_provides((alice.address, U256::from(1)))
91103
.priority(0u64)
@@ -105,9 +117,15 @@ fn transaction_with_to_low_nonce_should_not_work() {
105117
transaction: signed2,
106118
};
107119
let source2 = call2.check_self_contained().unwrap().unwrap();
120+
let extrinsic2 = fp_self_contained::CheckedExtrinsic::<u64, crate::mock::Call, SignedExtra, _> {
121+
signed: fp_self_contained::CheckedSignature::SelfContained(source),
122+
function: Call::Ethereum(call2.clone()),
123+
};
108124

109125
assert_err!(
110-
call2.validate_self_contained(&source2).unwrap(),
126+
call2
127+
.validate_self_contained(&source2, &extrinsic2.get_dispatch_info(), 0)
128+
.unwrap(),
111129
InvalidTransaction::Stale
112130
);
113131
});
@@ -334,7 +352,7 @@ fn self_contained_transaction_with_extra_gas_should_adjust_weight_with_post_disp
334352
transaction: signed,
335353
};
336354
let source = call.check_self_contained().unwrap().unwrap();
337-
let extrinsic = CheckedExtrinsic::<_, _, frame_system::CheckWeight<Test>, _> {
355+
let extrinsic = fp_self_contained::CheckedExtrinsic::<_, _, frame_system::CheckWeight<Test>, _> {
338356
signed: fp_self_contained::CheckedSignature::SelfContained(source),
339357
function: Call::Ethereum(call),
340358
};

frame/ethereum/src/tests/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use frame_support::{assert_err, assert_ok, unsigned::TransactionValidityError};
1+
use frame_support::{assert_err, assert_ok, unsigned::TransactionValidityError, weights::GetDispatchInfo};
22
use rustc_hex::{FromHex, ToHex};
33
use sp_runtime::{
44
traits::Applyable,

primitives/self-contained/src/checked_extrinsic.rs

+7-6
Original file line numberDiff line numberDiff line change
@@ -87,11 +87,12 @@ where
8787
let unsigned_validation = U::validate_unsigned(source, &self.function)?;
8888
Ok(valid.combine_with(unsigned_validation))
8989
}
90-
CheckedSignature::SelfContained(signed_info) => {
91-
self.function.validate_self_contained(&signed_info).ok_or(
92-
TransactionValidityError::Invalid(InvalidTransaction::BadProof),
93-
)?
94-
}
90+
CheckedSignature::SelfContained(signed_info) => self
91+
.function
92+
.validate_self_contained(signed_info, info, len)
93+
.ok_or(TransactionValidityError::Invalid(
94+
InvalidTransaction::BadProof,
95+
))?
9596
}
9697
}
9798

@@ -139,7 +140,7 @@ where
139140
CheckedSignature::SelfContained(signed_info) => {
140141
// If pre-dispatch fail, the block must be considered invalid
141142
self.function
142-
.pre_dispatch_self_contained(&signed_info)
143+
.pre_dispatch_self_contained(&signed_info, info, len)
143144
.ok_or(TransactionValidityError::Invalid(
144145
InvalidTransaction::BadProof,
145146
))??;

primitives/self-contained/src/lib.rs

+13-3
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ pub use crate::{
2626
};
2727

2828
use sp_runtime::{
29-
traits::{Dispatchable, PostDispatchInfoOf},
29+
traits::{DispatchInfoOf, Dispatchable, PostDispatchInfoOf},
3030
transaction_validity::{TransactionValidity, TransactionValidityError},
3131
};
3232

@@ -43,7 +43,12 @@ pub trait SelfContainedCall: Dispatchable {
4343
fn check_self_contained(&self) -> Option<Result<Self::SignedInfo, TransactionValidityError>>;
4444
/// Validate a self-contained function. Returns `None` if the
4545
/// function is not a self-contained.
46-
fn validate_self_contained(&self, info: &Self::SignedInfo) -> Option<TransactionValidity>;
46+
fn validate_self_contained(
47+
&self,
48+
info: &Self::SignedInfo,
49+
dispatch_info: &DispatchInfoOf<Self>,
50+
len: usize,
51+
) -> Option<TransactionValidity>;
4752
/// Do any pre-flight stuff for a self-contained call.
4853
///
4954
/// Note this function by default delegates to `validate_self_contained`, so that
@@ -57,7 +62,12 @@ pub trait SelfContainedCall: Dispatchable {
5762
fn pre_dispatch_self_contained(
5863
&self,
5964
info: &Self::SignedInfo,
60-
) -> Option<Result<(), TransactionValidityError>>;
65+
dispatch_info: &DispatchInfoOf<Self>,
66+
len: usize,
67+
) -> Option<Result<(), TransactionValidityError>> {
68+
self.validate_self_contained(info, dispatch_info, len)
69+
.map(|res| res.map(|_| ()))
70+
}
6171
/// Apply a self-contained function. Returns `None` if the
6272
/// function is not a self-contained.
6373
fn apply_self_contained(

0 commit comments

Comments
 (0)