Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

check-weight: Disable total pov size check for mandatory extrinsics #4571

Merged
merged 6 commits into from
May 27, 2024
Merged
Changes from 1 commit
Commits
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
126 changes: 108 additions & 18 deletions substrate/frame/system/src/extensions/check_weight.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.

use crate::{limits::BlockWeights, Config, Pallet, LOG_TARGET};
use crate::{limits::BlockWeights, Config, DispatchClass, Pallet, LOG_TARGET};
use codec::{Decode, Encode};
use frame_support::{
dispatch::{DispatchInfo, PostDispatchInfo},
Expand Down Expand Up @@ -107,7 +107,7 @@ where
let maximum_weight = T::BlockWeights::get();
let next_weight =
calculate_consumed_weight::<T::RuntimeCall>(&maximum_weight, all_weight, info)?;
check_combined_proof_size(&maximum_weight, next_len, &next_weight)?;
check_combined_proof_size::<T::RuntimeCall>(info, &maximum_weight, next_len, &next_weight)?;
Self::check_extrinsic_weight(info)?;

crate::AllExtrinsicsLen::<T>::put(next_len);
Expand All @@ -131,11 +131,20 @@ where
}

/// Check that the combined extrinsic length and proof size together do not exceed the PoV limit.
pub fn check_combined_proof_size(
pub fn check_combined_proof_size<Call>(
info: &DispatchInfoOf<Call>,
maximum_weight: &BlockWeights,
next_len: u32,
next_weight: &crate::ConsumedWeight,
) -> Result<(), TransactionValidityError> {
) -> Result<(), TransactionValidityError>
where
Call: Dispatchable<Info = DispatchInfo, PostInfo = PostDispatchInfo>,
{
if matches!(info.class, DispatchClass::Mandatory) {
// Allow mandatory extrinsics
return Ok(());
}
skunert marked this conversation as resolved.
Show resolved Hide resolved

// 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);
Expand All @@ -146,7 +155,7 @@ pub fn check_combined_proof_size(
total_pov_size as f64/1024.0,
maximum_weight.max_block.proof_size() as f64/1024.0
);
return Err(InvalidTransaction::ExhaustsResources.into())
return Err(InvalidTransaction::ExhaustsResources.into());
}
Ok(())
}
Expand Down Expand Up @@ -190,7 +199,7 @@ where
"Exceeded the per-class allowance.",
);

return Err(InvalidTransaction::ExhaustsResources.into())
return Err(InvalidTransaction::ExhaustsResources.into());
},
// There is no `max_total` limit (`None`),
// or we are below the limit.
Expand All @@ -208,7 +217,7 @@ where
"Total block weight is exceeded.",
);

return Err(InvalidTransaction::ExhaustsResources.into())
return Err(InvalidTransaction::ExhaustsResources.into());
},
// There is either no limit in reserved pool (`None`),
// or we are below the limit.
Expand Down Expand Up @@ -791,6 +800,8 @@ mod tests {

assert_eq!(maximum_weight.max_block, Weight::from_parts(20, 10));

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),
Expand All @@ -799,24 +810,61 @@ mod tests {
});

// Simple checks for the length
assert_ok!(check_combined_proof_size(&maximum_weight, 0, &next_weight));
assert_ok!(check_combined_proof_size(&maximum_weight, 5, &next_weight));
assert_ok!(check_combined_proof_size::<<Test as Config>::RuntimeCall>(
&info,
&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(&maximum_weight, 6, &next_weight),
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>(
&mandatory,
&maximum_weight,
6,
&next_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(&maximum_weight, 0, &next_weight));
assert_ok!(check_combined_proof_size::<<Test as Config>::RuntimeCall>(
&info,
&maximum_weight,
0,
&next_weight
));
assert_err!(
check_combined_proof_size(&maximum_weight, 1, &next_weight),
check_combined_proof_size::<<Test as Config>::RuntimeCall>(
&info,
&maximum_weight,
1,
&next_weight
),
InvalidTransaction::ExhaustsResources
);
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.
Expand All @@ -825,12 +873,33 @@ mod tests {
DispatchClass::Operational => Weight::from_parts(0, 3),
DispatchClass::Mandatory => Weight::zero(),
});
assert_ok!(check_combined_proof_size(&maximum_weight, 0, &next_weight));
assert_ok!(check_combined_proof_size(&maximum_weight, 2, &next_weight));
assert_ok!(check_combined_proof_size::<<Test as Config>::RuntimeCall>(
&info,
&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(&maximum_weight, 3, &next_weight),
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>(
&mandatory,
&maximum_weight,
3,
&next_weight
));

// Ref time is over the limit. Should not happen, but we should make sure that it is
// ignored.
Expand All @@ -839,11 +908,32 @@ mod tests {
DispatchClass::Operational => Weight::from_parts(0, 0),
DispatchClass::Mandatory => Weight::zero(),
});
assert_ok!(check_combined_proof_size(&maximum_weight, 0, &next_weight));
assert_ok!(check_combined_proof_size(&maximum_weight, 5, &next_weight));
assert_ok!(check_combined_proof_size::<<Test as Config>::RuntimeCall>(
&info,
&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(&maximum_weight, 6, &next_weight),
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>(
&mandatory,
&maximum_weight,
6,
&next_weight
));
}
}
Loading