-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Make WeightBounds return XcmError to surface failures
#8535
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
Changes from all commits
f5b9a70
e467f10
06afe71
1710c7a
5376e6e
a05f5f9
977fdc4
bd42b82
b286e8d
125da04
6cba861
341778b
c1a89ef
67647c9
0dc29c3
1d5152b
0688bca
79c34aa
8b8d37e
47011f4
f86d355
c9b5af5
2ea36a9
9f2fa2b
1d5589e
5014064
e85d6f1
ff6eafa
3d5e4ff
f88c1dd
5ec9559
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -38,38 +38,61 @@ pub struct FixedWeightBounds<T, C, M>(PhantomData<(T, C, M)>); | |
| impl<T: Get<Weight>, C: Decode + GetDispatchInfo, M: Get<u32>> WeightBounds<C> | ||
| for FixedWeightBounds<T, C, M> | ||
| { | ||
| fn weight(message: &mut Xcm<C>) -> Result<Weight, ()> { | ||
| fn weight(message: &mut Xcm<C>) -> Result<Weight, XcmError> { | ||
| tracing::trace!(target: "xcm::weight", ?message, "FixedWeightBounds"); | ||
| let mut instructions_left = M::get(); | ||
| Self::weight_with_limit(message, &mut instructions_left) | ||
| Self::weight_with_limit(message, &mut instructions_left).inspect_err(|&error| { | ||
| tracing::debug!( | ||
| target: "xcm::weight", | ||
| ?error, | ||
| ?instructions_left, | ||
| message_length = ?message.0.len(), | ||
| "Weight calculation failed for message" | ||
| ); | ||
| }) | ||
| } | ||
| fn instr_weight(instruction: &mut Instruction<C>) -> Result<Weight, ()> { | ||
| Self::instr_weight_with_limit(instruction, &mut u32::max_value()) | ||
| fn instr_weight(instruction: &mut Instruction<C>) -> Result<Weight, XcmError> { | ||
| let mut max_value = u32::MAX; | ||
| Self::instr_weight_with_limit(instruction, &mut max_value).inspect_err(|&error| { | ||
| tracing::debug!( | ||
| target: "xcm::weight", | ||
| ?error, | ||
| ?instruction, | ||
| instrs_limit = ?max_value, | ||
| "Weight calculation failed for instruction" | ||
| ); | ||
| }) | ||
| } | ||
| } | ||
|
|
||
| impl<T: Get<Weight>, C: Decode + GetDispatchInfo, M> FixedWeightBounds<T, C, M> { | ||
| fn weight_with_limit(message: &mut Xcm<C>, instrs_limit: &mut u32) -> Result<Weight, ()> { | ||
| fn weight_with_limit(message: &mut Xcm<C>, instrs_limit: &mut u32) -> Result<Weight, XcmError> { | ||
| let mut r: Weight = Weight::zero(); | ||
| *instrs_limit = instrs_limit.checked_sub(message.0.len() as u32).ok_or(())?; | ||
| *instrs_limit = instrs_limit | ||
| .checked_sub(message.0.len() as u32) | ||
| .ok_or_else(|| XcmError::ExceedsStackLimit)?; | ||
raymondkfcheung marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| for instruction in message.0.iter_mut() { | ||
| r = r | ||
| .checked_add(&Self::instr_weight_with_limit(instruction, instrs_limit)?) | ||
| .ok_or(())?; | ||
| .ok_or_else(|| XcmError::Overflow)?; | ||
raymondkfcheung marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| } | ||
| Ok(r) | ||
| } | ||
| fn instr_weight_with_limit( | ||
| instruction: &mut Instruction<C>, | ||
| instrs_limit: &mut u32, | ||
| ) -> Result<Weight, ()> { | ||
| ) -> Result<Weight, XcmError> { | ||
| let instr_weight = match instruction { | ||
| Transact { ref mut call, .. } => call.ensure_decoded()?.get_dispatch_info().call_weight, | ||
| Transact { ref mut call, .. } => | ||
| call.ensure_decoded() | ||
| .map_err(|_| XcmError::FailedToDecode)? | ||
| .get_dispatch_info() | ||
| .call_weight, | ||
| SetErrorHandler(xcm) | SetAppendix(xcm) | ExecuteWithOrigin { xcm, .. } => | ||
| Self::weight_with_limit(xcm, instrs_limit)?, | ||
| _ => Weight::zero(), | ||
| }; | ||
| T::get().checked_add(&instr_weight).ok_or(()) | ||
| T::get().checked_add(&instr_weight).ok_or_else(|| XcmError::Overflow) | ||
raymondkfcheung marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| } | ||
| } | ||
|
|
||
|
|
@@ -81,13 +104,30 @@ where | |
| M: Get<u32>, | ||
| Instruction<C>: xcm::latest::GetWeight<W>, | ||
| { | ||
| fn weight(message: &mut Xcm<C>) -> Result<Weight, ()> { | ||
| fn weight(message: &mut Xcm<C>) -> Result<Weight, XcmError> { | ||
| tracing::trace!(target: "xcm::weight", ?message, "WeightInfoBounds"); | ||
| let mut instructions_left = M::get(); | ||
| Self::weight_with_limit(message, &mut instructions_left) | ||
| Self::weight_with_limit(message, &mut instructions_left).inspect_err(|&error| { | ||
| tracing::debug!( | ||
| target: "xcm::weight", | ||
| ?error, | ||
| ?instructions_left, | ||
| message_length = ?message.0.len(), | ||
| "Weight calculation failed for message" | ||
| ); | ||
| }) | ||
| } | ||
| fn instr_weight(instruction: &mut Instruction<C>) -> Result<Weight, ()> { | ||
| Self::instr_weight_with_limit(instruction, &mut u32::max_value()) | ||
| fn instr_weight(instruction: &mut Instruction<C>) -> Result<Weight, XcmError> { | ||
| let mut max_value = u32::MAX; | ||
| Self::instr_weight_with_limit(instruction, &mut max_value).inspect_err(|&error| { | ||
| tracing::debug!( | ||
| target: "xcm::weight", | ||
| ?error, | ||
| ?instruction, | ||
| instrs_limit = ?max_value, | ||
| "Weight calculation failed for instruction" | ||
| ); | ||
| }) | ||
| } | ||
| } | ||
|
|
||
|
|
@@ -98,26 +138,35 @@ where | |
| M: Get<u32>, | ||
| Instruction<C>: xcm::latest::GetWeight<W>, | ||
| { | ||
| fn weight_with_limit(message: &mut Xcm<C>, instrs_limit: &mut u32) -> Result<Weight, ()> { | ||
| fn weight_with_limit(message: &mut Xcm<C>, instrs_limit: &mut u32) -> Result<Weight, XcmError> { | ||
| let mut r: Weight = Weight::zero(); | ||
| *instrs_limit = instrs_limit.checked_sub(message.0.len() as u32).ok_or(())?; | ||
| *instrs_limit = instrs_limit | ||
| .checked_sub(message.0.len() as u32) | ||
| .ok_or_else(|| XcmError::ExceedsStackLimit)?; | ||
raymondkfcheung marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| for instruction in message.0.iter_mut() { | ||
| r = r | ||
| .checked_add(&Self::instr_weight_with_limit(instruction, instrs_limit)?) | ||
| .ok_or(())?; | ||
| .ok_or_else(|| XcmError::Overflow)?; | ||
raymondkfcheung marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| } | ||
| Ok(r) | ||
| } | ||
| fn instr_weight_with_limit( | ||
| instruction: &mut Instruction<C>, | ||
| instrs_limit: &mut u32, | ||
| ) -> Result<Weight, ()> { | ||
| ) -> Result<Weight, XcmError> { | ||
| let instr_weight = match instruction { | ||
| Transact { ref mut call, .. } => call.ensure_decoded()?.get_dispatch_info().call_weight, | ||
| Transact { ref mut call, .. } => | ||
| call.ensure_decoded() | ||
| .map_err(|_| XcmError::FailedToDecode)? | ||
| .get_dispatch_info() | ||
| .call_weight, | ||
| SetErrorHandler(xcm) | SetAppendix(xcm) => Self::weight_with_limit(xcm, instrs_limit)?, | ||
| _ => Weight::zero(), | ||
| }; | ||
| instruction.weight().checked_add(&instr_weight).ok_or(()) | ||
| instruction | ||
| .weight() | ||
| .checked_add(&instr_weight) | ||
| .ok_or_else(|| XcmError::Overflow) | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
| } | ||
| } | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -22,11 +22,11 @@ use xcm::latest::{prelude::*, Weight}; | |
| pub trait WeightBounds<RuntimeCall> { | ||
| /// Return the maximum amount of weight that an attempted execution of this message could | ||
| /// consume. | ||
| fn weight(message: &mut Xcm<RuntimeCall>) -> Result<Weight, ()>; | ||
| fn weight(message: &mut Xcm<RuntimeCall>) -> Result<Weight, XcmError>; | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can we make this return the index of the problematic instruction as well? It'd be very useful to bubble it up in #7730 |
||
|
|
||
| /// Return the maximum amount of weight that an attempted execution of this instruction could | ||
| /// consume. | ||
| fn instr_weight(instruction: &mut Instruction<RuntimeCall>) -> Result<Weight, ()>; | ||
| fn instr_weight(instruction: &mut Instruction<RuntimeCall>) -> Result<Weight, XcmError>; | ||
| } | ||
|
|
||
| /// Charge for weight in order to execute XCM. | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,12 @@ | ||
| title: Make `WeightBounds` return `XcmError` to surface failures | ||
| doc: | ||
| - audience: Runtime Dev | ||
| description: |- | ||
| Improved XCM weight calculation error handling and traceability. The `WeightBounds` trait now returns detailed `XcmError` types instead of opaque results, allowing downstream consumers to access specific error context for failures like instruction decoding issues, weight overflows, and instruction limit violations. Added structured debug logging with contextual information to aid in diagnosing weight estimation failures during message preparation and execution. | ||
| crates: | ||
| - name: pallet-xcm | ||
| bump: patch | ||
| - name: staging-xcm-builder | ||
| bump: major | ||
| - name: staging-xcm-executor | ||
| bump: major |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
just curious why you add
sp-tracingas a dev dependency not as a regular one?