paritytech / polkadot-sdk

The Parity Polkadot Blockchain SDK
https://polkadot.com/
1.91k stars 704 forks source link

[xcm] Transact v4 vs v5 compatibility #6585

Open bkontur opened 22 hours ago

bkontur commented 22 hours ago

E.g. Westend is sending Transact to the child: https://polkadot.js.org/apps/?rpc=wss%3A%2F%2Fwestend-rpc.polkadot.io#/explorer/query/0x01cd07a4ede58f34d76422febdf1adc28669c1a2ed5fa5ccaa7d15a7d1bfb0a5

take_decoded()?.get_dispatch_info is a problem for Transact, because on the sending chain we don't know what is RuntimeCall so decoding fails here for ():

For the real usage, we use e.g. xcm router which expects Xcm<()>:

fn validate(
        dest: &mut Option<Location>,
        msg: &mut Option<Xcm<()>>,
    ) -> SendResult<(HostConfiguration<BlockNumberFor<T>>, ParaId, Vec<u8>)> {
        let d = dest.take().ok_or(MissingArgument)?;
        let id = if let (0, [Parachain(id)]) = d.unpack() {
            *id
        } else {
            *dest = Some(d);
            return Err(NotApplicable)
        };

        // Downward message passing.
        let xcm = msg.take().ok_or(MissingArgument)?;
        let config = configuration::ActiveConfig::<T>::get();
        let para = id.into();
        let price = P::price_for_delivery(para, &xcm);
        let versioned_xcm = W::wrap_version(&d, xcm).map_err(|()| DestinationUnsupported)?;

and the wrap_version ends here, because it tries to decode with RuntimeCall = ()"

                       Transact { origin_kind, mut call } => {
                let require_weight_at_most = call.take_decoded()?.get_dispatch_info().call_weight;
                Self::Transact { origin_kind, require_weight_at_most, call: call.into() }
            },
bkontur commented 4 hours ago

Description contains problem on the sending side, when workaround with force_xcm_version(location, 5) is used then it bubbles to the problem on the receiving side Corrupt error, where ProcessXcmMessage cannot decode the received XCM:

let versioned_message = VersionedXcm::<Call>::decode(&mut &message[..]).map_err(|e| {
            log::trace!(
                target: LOG_TARGET,
                "`VersionedXcm` failed to decode: {e:?}",
            );

            ProcessMessageError::Corrupt
        })?;

e.g.: https://polkadot.js.org/apps/?rpc=wss%3A%2F%2Fwestend-coretime-rpc.polkadot.io#/explorer/query/0x21f8e21c63aa8f0554c8f955d093193ef465a9fe3b86ec228b3fbcd5df692e89


cc: @georgepisaltu This is exactly what you reported to me before cc: @franciscoaguirre so now we have both parts of the one problem :)

bkontur commented 4 hours ago

sorry, force_xcm_version(location, 5) is not a workaround and Corrupt is ok, because that is the point, we want to update new blob with xcmv4->xcmv5, but the actual runtime has 4 :) so ignore my comment above