Avoid consuming XCM message for NotApplicable scenario (#1787)

* Avoid consuming message for NotApplicable scenario

* Avoid consuming message for NotApplicable scenario tests
This commit is contained in:
Branislav Kontur
2022-10-25 13:50:19 +02:00
committed by GitHub
parent c446b6321b
commit 7290787bf3
3 changed files with 192 additions and 4 deletions
+3 -2
View File
@@ -1138,19 +1138,20 @@ impl<T: Config> SendXcm for Pallet<T> {
msg: &mut Option<Xcm<()>>,
) -> SendResult<(ParaId, VersionedXcm<()>)> {
let d = dest.take().ok_or(SendError::MissingArgument)?;
let xcm = msg.take().ok_or(SendError::MissingArgument)?;
match &d {
// An HRMP message for a sibling parachain.
MultiLocation { parents: 1, interior: X1(Parachain(id)) } => {
let xcm = msg.take().ok_or(SendError::MissingArgument)?;
let id = ParaId::from(*id);
let price = T::PriceForSiblingDelivery::price_for_sibling_delivery(id, &xcm);
let versioned_xcm = T::VersionWrapper::wrap_version(&d, xcm)
.map_err(|()| SendError::DestinationUnsupported)?;
Ok(((id, versioned_xcm), price))
},
// Anything else is unhandled. This includes a message this is meant for us.
_ => {
// Anything else is unhandled. This includes a message that is not meant for us.
// We need to make sure that dest/msg is not consumed here.
*dest = Some(d);
Err(SendError::NotApplicable)
},
+85
View File
@@ -247,3 +247,88 @@ fn update_xcmp_max_individual_weight() {
assert_eq!(data.xcmp_max_individual_weight, 30u64 * WEIGHT_PER_MILLIS);
});
}
/// Validates [`validate`] for required Some(destination) and Some(message)
struct OkFixedXcmHashWithAssertingRequiredInputsSender;
impl OkFixedXcmHashWithAssertingRequiredInputsSender {
const FIXED_XCM_HASH: [u8; 32] = [9; 32];
fn fixed_delivery_asset() -> MultiAssets {
MultiAssets::new()
}
fn expected_delivery_result() -> Result<(XcmHash, MultiAssets), SendError> {
Ok((Self::FIXED_XCM_HASH, Self::fixed_delivery_asset()))
}
}
impl SendXcm for OkFixedXcmHashWithAssertingRequiredInputsSender {
type Ticket = ();
fn validate(
destination: &mut Option<MultiLocation>,
message: &mut Option<Xcm<()>>,
) -> SendResult<Self::Ticket> {
assert!(destination.is_some());
assert!(message.is_some());
Ok(((), OkFixedXcmHashWithAssertingRequiredInputsSender::fixed_delivery_asset()))
}
fn deliver(_: Self::Ticket) -> Result<XcmHash, SendError> {
Ok(Self::FIXED_XCM_HASH)
}
}
#[test]
fn xcmp_queue_does_not_consume_dest_or_msg_on_not_applicable() {
// dummy message
let message = Xcm(vec![Trap(5)]);
// XcmpQueue - check dest is really not applicable
let dest = (Parent, Parent, Parent);
let mut dest_wrapper = Some(dest.clone().into());
let mut msg_wrapper = Some(message.clone());
assert_eq!(
Err(SendError::NotApplicable),
<XcmpQueue as SendXcm>::validate(&mut dest_wrapper, &mut msg_wrapper)
);
// check wrapper were not consumed
assert_eq!(Some(dest.clone().into()), dest_wrapper.take());
assert_eq!(Some(message.clone()), msg_wrapper.take());
// another try with router chain with asserting sender
assert_eq!(
OkFixedXcmHashWithAssertingRequiredInputsSender::expected_delivery_result(),
send_xcm::<(XcmpQueue, OkFixedXcmHashWithAssertingRequiredInputsSender)>(
dest.into(),
message
)
);
}
#[test]
fn xcmp_queue_consumes_dest_and_msg_on_ok_validate() {
// dummy message
let message = Xcm(vec![Trap(5)]);
// XcmpQueue - check dest/msg is valid
let dest = (Parent, X1(Parachain(5555)));
let mut dest_wrapper = Some(dest.clone().into());
let mut msg_wrapper = Some(message.clone());
assert!(<XcmpQueue as SendXcm>::validate(&mut dest_wrapper, &mut msg_wrapper).is_ok());
// check wrapper were consumed
assert_eq!(None, dest_wrapper.take());
assert_eq!(None, msg_wrapper.take());
new_test_ext().execute_with(|| {
// another try with router chain with asserting sender
assert_eq!(
Err(SendError::Transport("NoChannel")),
send_xcm::<(XcmpQueue, OkFixedXcmHashWithAssertingRequiredInputsSender)>(
dest.into(),
message
)
);
});
}