From ae0b3bf6733e7b9e18badb16128a6b25bef1923b Mon Sep 17 00:00:00 2001 From: Andrei Sandu <54316454+sandreim@users.noreply.github.com> Date: Fri, 14 Jun 2024 15:42:46 +0300 Subject: [PATCH] CheckWeight: account for extrinsic len as proof size (#4765) Fix https://github.com/paritytech/polkadot-sdk/issues/4743 which allows us to remove the defensive limit on pov size in Cumulus after relay chain gets upgraded with these changes. Also add unit test to ensure `CheckWeight` - `StorageWeightReclaim` integration works. TODO: - [x] PRDoc - [x] Add a len to all the other tests in storage weight reclaim and call `CheckWeight::pre_dispatch` --------- Signed-off-by: Andrei Sandu <andrei-mihail@parity.io> --- .../storage-weight-reclaim/src/lib.rs | 115 ++++++++- prdoc/pr_4765.prdoc | 18 ++ substrate/frame/executive/src/tests.rs | 7 +- .../system/src/extensions/check_weight.rs | 240 ++++++------------ 4 files changed, 205 insertions(+), 175 deletions(-) create mode 100644 prdoc/pr_4765.prdoc diff --git a/cumulus/primitives/storage-weight-reclaim/src/lib.rs b/cumulus/primitives/storage-weight-reclaim/src/lib.rs index c09c12d7a0a..35fa334f51c 100644 --- a/cumulus/primitives/storage-weight-reclaim/src/lib.rs +++ b/cumulus/primitives/storage-weight-reclaim/src/lib.rs @@ -201,7 +201,7 @@ mod tests { use super::*; use frame_support::{ assert_ok, - dispatch::DispatchClass, + dispatch::{DispatchClass, PerDispatchClass}, weights::{Weight, WeightMeter}, }; use frame_system::{BlockWeight, CheckWeight}; @@ -215,7 +215,7 @@ mod tests { pages: 0u64, }); const ALICE: AccountId32 = AccountId32::new([1u8; 32]); - const LEN: usize = 0; + const LEN: usize = 150; pub fn new_test_ext() -> sp_io::TestExternalities { let ext: sp_io::TestExternalities = cumulus_test_runtime::RuntimeGenesisConfig::default() @@ -256,6 +256,10 @@ mod tests { }); } + fn get_storage_weight() -> PerDispatchClass<Weight> { + BlockWeight::<Test>::get() + } + #[test] fn basic_refund() { // The real cost will be 100 bytes of storage size @@ -268,6 +272,9 @@ mod tests { let info = DispatchInfo { weight: Weight::from_parts(0, 500), ..Default::default() }; let post_info = PostDispatchInfo::default(); + // Should add 500 + 150 (len) to weight. + assert_ok!(CheckWeight::<Test>::do_pre_dispatch(&info, LEN)); + let pre = StorageWeightReclaim::<Test>(PhantomData) .pre_dispatch(&ALICE, CALL, &info, LEN) .unwrap(); @@ -283,7 +290,7 @@ mod tests { &Ok(()) )); - assert_eq!(BlockWeight::<Test>::get().total().proof_size(), 600); + assert_eq!(get_storage_weight().total().proof_size(), 1250); }) } @@ -299,6 +306,9 @@ mod tests { let info = DispatchInfo { weight: Weight::from_parts(0, 500), ..Default::default() }; let post_info = PostDispatchInfo::default(); + // Adds 500 + 150 (len) weight + assert_ok!(CheckWeight::<Test>::do_pre_dispatch(&info, LEN)); + let pre = StorageWeightReclaim::<Test>(PhantomData) .pre_dispatch(&ALICE, CALL, &info, LEN) .unwrap(); @@ -313,7 +323,7 @@ mod tests { &Ok(()) )); - assert_eq!(BlockWeight::<Test>::get().total().proof_size(), 1000); + assert_eq!(get_storage_weight().total().proof_size(), 1650); }) } @@ -327,6 +337,9 @@ mod tests { let info = DispatchInfo { weight: Weight::from_parts(0, 100), ..Default::default() }; let post_info = PostDispatchInfo::default(); + // Weight added should be 100 + 150 (len) + assert_ok!(CheckWeight::<Test>::do_pre_dispatch(&info, LEN)); + let pre = StorageWeightReclaim::<Test>(PhantomData) .pre_dispatch(&ALICE, CALL, &info, LEN) .unwrap(); @@ -342,7 +355,10 @@ mod tests { &Ok(()) )); - assert_eq!(BlockWeight::<Test>::get().total().proof_size(), 1100); + assert_eq!( + get_storage_weight().total().proof_size(), + 1100 + LEN as u64 + info.weight.proof_size() + ); }) } @@ -354,6 +370,8 @@ mod tests { let info = DispatchInfo { weight: Weight::from_parts(0, 500), ..Default::default() }; let post_info = PostDispatchInfo::default(); + assert_ok!(CheckWeight::<Test>::do_pre_dispatch(&info, LEN)); + let pre = StorageWeightReclaim::<Test>(PhantomData) .pre_dispatch(&ALICE, CALL, &info, LEN) .unwrap(); @@ -368,7 +386,8 @@ mod tests { &Ok(()) )); - assert_eq!(BlockWeight::<Test>::get().total().proof_size(), 0); + // Proof size should be exactly equal to extrinsic length + assert_eq!(get_storage_weight().total().proof_size(), LEN as u64); }); } @@ -382,12 +401,17 @@ mod tests { let info = DispatchInfo { weight: Weight::from_parts(0, 500), ..Default::default() }; let post_info = PostDispatchInfo::default(); + // Adds 500 + 150 (len) weight, total weight is 1950 + assert_ok!(CheckWeight::<Test>::do_pre_dispatch(&info, LEN)); + let pre = StorageWeightReclaim::<Test>(PhantomData) .pre_dispatch(&ALICE, CALL, &info, LEN) .unwrap(); assert_eq!(pre, Some(300)); + // Refund 500 unspent weight according to `post_info`, total weight is now 1650 assert_ok!(CheckWeight::<Test>::post_dispatch(None, &info, &post_info, 0, &Ok(()))); + // Recorded proof size is negative -200, total weight is now 1450 assert_ok!(StorageWeightReclaim::<Test>::post_dispatch( Some(pre), &info, @@ -396,7 +420,7 @@ mod tests { &Ok(()) )); - assert_eq!(BlockWeight::<Test>::get().total().proof_size(), 800); + assert_eq!(get_storage_weight().total().proof_size(), 1450); }); } @@ -416,6 +440,9 @@ mod tests { pays_fee: Default::default(), }; + // Should add 300 + 150 (len) of weight + assert_ok!(CheckWeight::<Test>::do_pre_dispatch(&info, LEN)); + let pre = StorageWeightReclaim::<Test>(PhantomData) .pre_dispatch(&ALICE, CALL, &info, LEN) .unwrap(); @@ -432,7 +459,8 @@ mod tests { &Ok(()) )); - assert_eq!(BlockWeight::<Test>::get().total().proof_size(), 900); + // Reclaimed 100 + assert_eq!(get_storage_weight().total().proof_size(), 1350); }) } @@ -451,6 +479,9 @@ mod tests { pays_fee: Default::default(), }; + // Adds 50 + 150 (len) weight, total weight 1200 + assert_ok!(CheckWeight::<Test>::do_pre_dispatch(&info, LEN)); + let pre = StorageWeightReclaim::<Test>(PhantomData) .pre_dispatch(&ALICE, CALL, &info, LEN) .unwrap(); @@ -458,7 +489,56 @@ mod tests { // The `CheckWeight` extension will refund `actual_weight` from `PostDispatchInfo` // we always need to call `post_dispatch` to verify that they interoperate correctly. + + // Refunds unspent 25 weight according to `post_info`, 1175 assert_ok!(CheckWeight::<Test>::post_dispatch(None, &info, &post_info, 0, &Ok(()))); + // Adds 200 - 25 (unspent) == 175 weight, total weight 1350 + assert_ok!(StorageWeightReclaim::<Test>::post_dispatch( + Some(pre), + &info, + &post_info, + LEN, + &Ok(()) + )); + + assert_eq!(get_storage_weight().total().proof_size(), 1350); + }) + } + + #[test] + fn test_nothing_relcaimed() { + let mut test_ext = setup_test_externalities(&[100, 200]); + + test_ext.execute_with(|| { + set_current_storage_weight(0); + // Benchmarked storage weight: 100 + let info = DispatchInfo { weight: Weight::from_parts(100, 100), ..Default::default() }; + + // Actual proof size is 100 + let post_info = PostDispatchInfo { + actual_weight: Some(Weight::from_parts(50, 100)), + pays_fee: Default::default(), + }; + + // Adds benchmarked weight 100 + 150 (len), total weight is now 250 + assert_ok!(CheckWeight::<Test>::do_pre_dispatch(&info, LEN)); + + // Weight should go up by 150 len + 100 proof size weight, total weight 250 + assert_eq!(get_storage_weight().total().proof_size(), 250); + + let pre = StorageWeightReclaim::<Test>(PhantomData) + .pre_dispatch(&ALICE, CALL, &info, LEN) + .unwrap(); + // Should return `setup_test_externalities` proof recorder value: 100. + assert_eq!(pre, Some(100)); + + // The `CheckWeight` extension will refund `actual_weight` from `PostDispatchInfo` + // we always need to call `post_dispatch` to verify that they interoperate correctly. + // Nothing to refund, unspent is 0, total weight 250 + assert_ok!(CheckWeight::<Test>::post_dispatch(None, &info, &post_info, LEN, &Ok(()))); + // `setup_test_externalities` proof recorder value: 200, so this means the extrinsic + // actually used 100 proof size. + // Nothing to refund or add, weight matches proof recorder assert_ok!(StorageWeightReclaim::<Test>::post_dispatch( Some(pre), &info, @@ -467,7 +547,9 @@ mod tests { &Ok(()) )); - assert_eq!(BlockWeight::<Test>::get().total().proof_size(), 1150); + // Check block len weight was not reclaimed: + // 100 weight + 150 extrinsic len == 250 proof size + assert_eq!(get_storage_weight().total().proof_size(), 250); }) } @@ -487,11 +569,15 @@ mod tests { pays_fee: Default::default(), }; + // Adds 300 + 150 (len) weight, total weight 1450 + assert_ok!(CheckWeight::<Test>::do_pre_dispatch(&info, LEN)); + let pre = StorageWeightReclaim::<Test>(PhantomData) .pre_dispatch(&ALICE, CALL, &info, LEN) .unwrap(); assert_eq!(pre, Some(100)); + // This refunds 100 - 50(unspent), total weight is now 1400 assert_ok!(StorageWeightReclaim::<Test>::post_dispatch( Some(pre), &info, @@ -504,7 +590,8 @@ mod tests { // we always need to call `post_dispatch` to verify that they interoperate correctly. assert_ok!(CheckWeight::<Test>::post_dispatch(None, &info, &post_info, 0, &Ok(()))); - assert_eq!(BlockWeight::<Test>::get().total().proof_size(), 900); + // Above call refunds 50 (unspent), total weight is 1350 now + assert_eq!(get_storage_weight().total().proof_size(), 1350); }) } @@ -523,11 +610,15 @@ mod tests { pays_fee: Default::default(), }; + // Adds 50 + 150 (len) weight, total weight is 1200 + assert_ok!(CheckWeight::<Test>::do_pre_dispatch(&info, LEN)); + let pre = StorageWeightReclaim::<Test>(PhantomData) .pre_dispatch(&ALICE, CALL, &info, LEN) .unwrap(); assert_eq!(pre, Some(100)); + // Adds additional 150 weight recorded assert_ok!(StorageWeightReclaim::<Test>::post_dispatch( Some(pre), &info, @@ -540,7 +631,7 @@ mod tests { // we always need to call `post_dispatch` to verify that they interoperate correctly. assert_ok!(CheckWeight::<Test>::post_dispatch(None, &info, &post_info, 0, &Ok(()))); - assert_eq!(BlockWeight::<Test>::get().total().proof_size(), 1150); + assert_eq!(get_storage_weight().total().proof_size(), 1350); }) } @@ -644,7 +735,7 @@ mod tests { // We reclaimed 3 bytes of storage size! assert_eq!(reclaimed, Some(Weight::from_parts(0, 3))); - assert_eq!(BlockWeight::<Test>::get().total().proof_size(), 10); + assert_eq!(get_storage_weight().total().proof_size(), 10); assert_eq!(remaining_weight_meter.remaining(), Weight::from_parts(10, 8)); } } diff --git a/prdoc/pr_4765.prdoc b/prdoc/pr_4765.prdoc new file mode 100644 index 00000000000..f64b2fdc51a --- /dev/null +++ b/prdoc/pr_4765.prdoc @@ -0,0 +1,18 @@ +title: CheckWeight - account for extrinsic len as proof size + +doc: + - audience: Runtime Dev + description: | + This changes how CheckWeight extension works. It will now account for the extrinsic length + as proof size. When `on_idle` is called, the remaining weight parameter reflects this. + +crates: + - name: frame-system + bump: patch + - name: frame-executive + bump: none + - name: cumulus-primitives-storage-weight-reclaim + bump: none + + + diff --git a/substrate/frame/executive/src/tests.rs b/substrate/frame/executive/src/tests.rs index 71cb54d1fab..69a970a89d9 100644 --- a/substrate/frame/executive/src/tests.rs +++ b/substrate/frame/executive/src/tests.rs @@ -649,8 +649,8 @@ fn block_weight_limit_enforced() { assert!(res.is_ok()); assert_eq!( <frame_system::Pallet<Runtime>>::block_weight().total(), - //--------------------- on_initialize + block_execution + extrinsic_base weight - Weight::from_parts((encoded_len + 5) * (nonce + 1), 0) + base_block_weight, + //--------------------- on_initialize + block_execution + extrinsic_base weight + extrinsic len + Weight::from_parts((encoded_len + 5) * (nonce + 1), (nonce + 1)* encoded_len) + base_block_weight, ); assert_eq!( <frame_system::Pallet<Runtime>>::extrinsic_index(), @@ -698,9 +698,10 @@ fn block_weight_and_size_is_stored_per_tx() { <Runtime as frame_system::Config>::BlockWeights::get() .get(DispatchClass::Normal) .base_extrinsic; + // Check we account for all extrinsic weight and their len. assert_eq!( <frame_system::Pallet<Runtime>>::block_weight().total(), - base_block_weight + 3u64 * extrinsic_weight, + base_block_weight + 3u64 * extrinsic_weight + 3u64 * Weight::from_parts(0, len as u64), ); assert_eq!(<frame_system::Pallet<Runtime>>::all_extrinsics_len(), 3 * len); diff --git a/substrate/frame/system/src/extensions/check_weight.rs b/substrate/frame/system/src/extensions/check_weight.rs index 5d6c68989ed..d4705f200ef 100644 --- a/substrate/frame/system/src/extensions/check_weight.rs +++ b/substrate/frame/system/src/extensions/check_weight.rs @@ -15,7 +15,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -use crate::{limits::BlockWeights, Config, DispatchClass, Pallet, LOG_TARGET}; +use crate::{limits::BlockWeights, Config, Pallet, LOG_TARGET}; use codec::{Decode, Encode}; use frame_support::{ dispatch::{DispatchInfo, PostDispatchInfo}, @@ -106,8 +106,7 @@ where let all_weight = Pallet::<T>::block_weight(); let maximum_weight = T::BlockWeights::get(); let next_weight = - calculate_consumed_weight::<T::RuntimeCall>(&maximum_weight, all_weight, info)?; - check_combined_proof_size::<T::RuntimeCall>(info, &maximum_weight, next_len, &next_weight)?; + calculate_consumed_weight::<T::RuntimeCall>(&maximum_weight, all_weight, info, len)?; Self::check_extrinsic_weight(info)?; crate::AllExtrinsicsLen::<T>::put(next_len); @@ -130,36 +129,6 @@ where } } -/// Check that the combined extrinsic length and proof size together do not exceed the PoV limit. -pub fn check_combined_proof_size<Call>( - info: &DispatchInfoOf<Call>, - maximum_weight: &BlockWeights, - next_len: u32, - next_weight: &crate::ConsumedWeight, -) -> Result<(), TransactionValidityError> -where - Call: Dispatchable<Info = DispatchInfo, PostInfo = PostDispatchInfo>, -{ - // This extra check ensures that the extrinsic length does not push the - // PoV over the limit. - let total_pov_size = next_weight.total().proof_size().saturating_add(next_len as u64); - if total_pov_size > maximum_weight.max_block.proof_size() { - log::debug!( - target: LOG_TARGET, - "Extrinsic exceeds total pov size. Still including if mandatory. size: {}kb, limit: {}kb, is_mandatory: {}", - total_pov_size as f64/1024.0, - maximum_weight.max_block.proof_size() as f64/1024.0, - info.class == DispatchClass::Mandatory - ); - return match info.class { - // Allow mandatory extrinsics - DispatchClass::Mandatory => Ok(()), - _ => Err(InvalidTransaction::ExhaustsResources.into()), - }; - } - Ok(()) -} - /// Checks if the current extrinsic can fit into the block with respect to block weight limits. /// /// Upon successes, it returns the new block weight as a `Result`. @@ -167,12 +136,16 @@ pub fn calculate_consumed_weight<Call>( maximum_weight: &BlockWeights, mut all_weight: crate::ConsumedWeight, info: &DispatchInfoOf<Call>, + len: usize, ) -> Result<crate::ConsumedWeight, TransactionValidityError> where Call: Dispatchable<Info = DispatchInfo, PostInfo = PostDispatchInfo>, { - let extrinsic_weight = - info.weight.saturating_add(maximum_weight.get(info.class).base_extrinsic); + // Also Consider extrinsic length as proof weight. + let extrinsic_weight = info + .weight + .saturating_add(maximum_weight.get(info.class).base_extrinsic) + .saturating_add(Weight::from_parts(0, len as u64)); let limit_per_class = maximum_weight.get(info.class); // add the weight. If class is unlimited, use saturating add instead of checked one. @@ -772,168 +745,115 @@ mod tests { &maximum_weight, all_weight.clone(), &mandatory1, + 0 )); assert_err!( calculate_consumed_weight::<<Test as Config>::RuntimeCall>( &maximum_weight, all_weight, &mandatory2, + 0 ), InvalidTransaction::ExhaustsResources ); } #[test] - fn maximum_proof_size_includes_length() { + fn proof_size_includes_length() { let maximum_weight = BlockWeights::builder() .base_block(Weight::zero()) .for_class(DispatchClass::non_mandatory(), |w| { w.base_extrinsic = Weight::zero(); - w.max_total = Some(Weight::from_parts(20, 10)); + w.max_total = Some(Weight::from_parts(20, 1000)); }) .for_class(DispatchClass::Mandatory, |w| { w.base_extrinsic = Weight::zero(); - w.reserved = Some(Weight::from_parts(5, 10)); - w.max_total = None; + w.max_total = Some(Weight::from_parts(20, 1000)); }) .build_or_panic(); + let all_weight = crate::ConsumedWeight::new(|class| match class { + DispatchClass::Normal => Weight::from_parts(5, 0), + DispatchClass::Operational => Weight::from_parts(5, 0), + DispatchClass::Mandatory => Weight::from_parts(0, 0), + }); - assert_eq!(maximum_weight.max_block, Weight::from_parts(20, 10)); + let normal = DispatchInfo { + weight: Weight::from_parts(5, 0), + class: DispatchClass::Normal, + ..Default::default() + }; - let info = DispatchInfo { class: DispatchClass::Normal, ..Default::default() }; - let mandatory = DispatchInfo { class: DispatchClass::Mandatory, ..Default::default() }; - // We have 10 reftime and 5 proof size left over. - let next_weight = crate::ConsumedWeight::new(|class| match class { - DispatchClass::Normal => Weight::from_parts(10, 5), - DispatchClass::Operational => Weight::from_parts(0, 0), - DispatchClass::Mandatory => Weight::zero(), - }); + let mandatory = DispatchInfo { + weight: Weight::from_parts(5, 0), + class: DispatchClass::Mandatory, + ..Default::default() + }; - // Simple checks for the length - assert_ok!(check_combined_proof_size::<<Test as Config>::RuntimeCall>( - &info, + // Using 0 length extrinsics. + let consumed = calculate_consumed_weight::<<Test as Config>::RuntimeCall>( &maximum_weight, + all_weight.clone(), + &normal, 0, - &next_weight - )); - assert_ok!(check_combined_proof_size::<<Test as Config>::RuntimeCall>( - &info, + ) + .unwrap(); + + assert_eq!(consumed.total().saturating_sub(all_weight.total()), normal.weight); + + let consumed = calculate_consumed_weight::<<Test as Config>::RuntimeCall>( &maximum_weight, - 5, - &next_weight - )); - assert_err!( - check_combined_proof_size::<<Test as Config>::RuntimeCall>( - &info, - &maximum_weight, - 6, - &next_weight - ), - InvalidTransaction::ExhaustsResources - ); - assert_ok!(check_combined_proof_size::<<Test as Config>::RuntimeCall>( + all_weight.clone(), &mandatory, - &maximum_weight, - 6, - &next_weight - )); + 0, + ) + .unwrap(); + assert_eq!(consumed.total().saturating_sub(all_weight.total()), mandatory.weight); - // We have 10 reftime and 0 proof size left over. - let next_weight = crate::ConsumedWeight::new(|class| match class { - DispatchClass::Normal => Weight::from_parts(10, 10), - DispatchClass::Operational => Weight::from_parts(0, 0), - DispatchClass::Mandatory => Weight::zero(), - }); - assert_ok!(check_combined_proof_size::<<Test as Config>::RuntimeCall>( - &info, + // Using non zero length extrinsics. + let consumed = calculate_consumed_weight::<<Test as Config>::RuntimeCall>( &maximum_weight, - 0, - &next_weight - )); - assert_err!( - check_combined_proof_size::<<Test as Config>::RuntimeCall>( - &info, - &maximum_weight, - 1, - &next_weight - ), - InvalidTransaction::ExhaustsResources + all_weight.clone(), + &normal, + 100, + ) + .unwrap(); + // Must account for the len in the proof size + assert_eq!( + consumed.total().saturating_sub(all_weight.total()), + normal.weight.add_proof_size(100) ); - assert_ok!(check_combined_proof_size::<<Test as Config>::RuntimeCall>( - &mandatory, - &maximum_weight, - 1, - &next_weight - )); - // We have 10 reftime and 2 proof size left over. - // Used weight is spread across dispatch classes this time. - let next_weight = crate::ConsumedWeight::new(|class| match class { - DispatchClass::Normal => Weight::from_parts(10, 5), - DispatchClass::Operational => Weight::from_parts(0, 3), - DispatchClass::Mandatory => Weight::zero(), - }); - assert_ok!(check_combined_proof_size::<<Test as Config>::RuntimeCall>( - &info, + let consumed = calculate_consumed_weight::<<Test as Config>::RuntimeCall>( &maximum_weight, - 0, - &next_weight - )); - assert_ok!(check_combined_proof_size::<<Test as Config>::RuntimeCall>( - &info, - &maximum_weight, - 2, - &next_weight - )); - assert_err!( - check_combined_proof_size::<<Test as Config>::RuntimeCall>( - &info, - &maximum_weight, - 3, - &next_weight - ), - InvalidTransaction::ExhaustsResources - ); - assert_ok!(check_combined_proof_size::<<Test as Config>::RuntimeCall>( + all_weight.clone(), &mandatory, - &maximum_weight, - 3, - &next_weight - )); + 100, + ) + .unwrap(); + // Must account for the len in the proof size + assert_eq!( + consumed.total().saturating_sub(all_weight.total()), + mandatory.weight.add_proof_size(100) + ); - // Ref time is over the limit. Should not happen, but we should make sure that it is - // ignored. - let next_weight = crate::ConsumedWeight::new(|class| match class { - DispatchClass::Normal => Weight::from_parts(30, 5), - DispatchClass::Operational => Weight::from_parts(0, 0), - DispatchClass::Mandatory => Weight::zero(), - }); - assert_ok!(check_combined_proof_size::<<Test as Config>::RuntimeCall>( - &info, + // Using oversized zero length extrinsics. + let consumed = calculate_consumed_weight::<<Test as Config>::RuntimeCall>( &maximum_weight, - 0, - &next_weight - )); - assert_ok!(check_combined_proof_size::<<Test as Config>::RuntimeCall>( - &info, - &maximum_weight, - 5, - &next_weight - )); - assert_err!( - check_combined_proof_size::<<Test as Config>::RuntimeCall>( - &info, - &maximum_weight, - 6, - &next_weight - ), - InvalidTransaction::ExhaustsResources + all_weight.clone(), + &normal, + 2000, ); - assert_ok!(check_combined_proof_size::<<Test as Config>::RuntimeCall>( - &mandatory, + // errors out + assert_eq!(consumed, Err(InvalidTransaction::ExhaustsResources.into())); + + // Using oversized zero length extrinsics. + let consumed = calculate_consumed_weight::<<Test as Config>::RuntimeCall>( &maximum_weight, - 6, - &next_weight - )); + all_weight.clone(), + &mandatory, + 2000, + ); + // errors out + assert_eq!(consumed, Err(InvalidTransaction::ExhaustsResources.into())); } } -- GitLab