mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-20 01:11:08 +00:00
Reanchor should return canonical location (#4470)
* Reanchor should return canonical * Formatting * Formatting * Update xcm/src/v1/multilocation.rs * Formatting * Fixes * Don't discard unreanchorable assets * Formatting * Docs * Fixes * Fixes * tidy
This commit is contained in:
@@ -194,7 +194,7 @@ impl Assets {
|
||||
self.fungible = fungible
|
||||
.into_iter()
|
||||
.map(|(mut id, amount)| {
|
||||
let _ = id.reanchor(prepend);
|
||||
let _ = id.prepend_with(prepend);
|
||||
(id, amount)
|
||||
})
|
||||
.collect();
|
||||
@@ -203,12 +203,48 @@ impl Assets {
|
||||
self.non_fungible = non_fungible
|
||||
.into_iter()
|
||||
.map(|(mut class, inst)| {
|
||||
let _ = class.reanchor(prepend);
|
||||
let _ = class.prepend_with(prepend);
|
||||
(class, inst)
|
||||
})
|
||||
.collect();
|
||||
}
|
||||
|
||||
/// Mutate the assets to be interpreted as the same assets from the perspective of a `target`
|
||||
/// chain. The local chain's `ancestry` is provided.
|
||||
///
|
||||
/// Any assets which were unable to be reanchored are introduced into `failed_bin`.
|
||||
pub fn reanchor(
|
||||
&mut self,
|
||||
target: &MultiLocation,
|
||||
ancestry: &MultiLocation,
|
||||
mut maybe_failed_bin: Option<&mut Self>,
|
||||
) {
|
||||
let mut fungible = Default::default();
|
||||
mem::swap(&mut self.fungible, &mut fungible);
|
||||
self.fungible = fungible
|
||||
.into_iter()
|
||||
.filter_map(|(mut id, amount)| match id.reanchor(target, ancestry) {
|
||||
Ok(()) => Some((id, amount)),
|
||||
Err(()) => {
|
||||
maybe_failed_bin.as_mut().map(|f| f.fungible.insert(id, amount));
|
||||
None
|
||||
},
|
||||
})
|
||||
.collect();
|
||||
let mut non_fungible = Default::default();
|
||||
mem::swap(&mut self.non_fungible, &mut non_fungible);
|
||||
self.non_fungible = non_fungible
|
||||
.into_iter()
|
||||
.filter_map(|(mut class, inst)| match class.reanchor(target, ancestry) {
|
||||
Ok(()) => Some((class, inst)),
|
||||
Err(()) => {
|
||||
maybe_failed_bin.as_mut().map(|f| f.non_fungible.insert((class, inst)));
|
||||
None
|
||||
},
|
||||
})
|
||||
.collect();
|
||||
}
|
||||
|
||||
/// Returns an error unless all `assets` are contained in `self`. In the case of an error, the first asset in
|
||||
/// `assets` which is not wholly in `self` is returned.
|
||||
pub fn ensure_contains(&self, assets: &MultiAssets) -> Result<(), TakeError> {
|
||||
|
||||
@@ -304,12 +304,11 @@ impl<Config: config::Config> XcmExecutor<Config> {
|
||||
TransferReserveAsset { mut assets, dest, xcm } => {
|
||||
let origin = self.origin.as_ref().ok_or(XcmError::BadOrigin)?;
|
||||
// Take `assets` from the origin account (on-chain) and place into dest account.
|
||||
let inv_dest = Config::LocationInverter::invert_location(&dest)
|
||||
.map_err(|()| XcmError::MultiLocationNotInvertible)?;
|
||||
for asset in assets.inner() {
|
||||
Config::AssetTransactor::beam_asset(asset, origin, &dest)?;
|
||||
}
|
||||
assets.reanchor(&inv_dest).map_err(|()| XcmError::MultiLocationFull)?;
|
||||
let ancestry = Config::LocationInverter::ancestry();
|
||||
assets.reanchor(&dest, &ancestry).map_err(|()| XcmError::MultiLocationFull)?;
|
||||
let mut message = vec![ReserveAssetDeposited(assets), ClearOrigin];
|
||||
message.extend(xcm.0.into_iter());
|
||||
Config::XcmSender::send_xcm(dest, Xcm(message)).map_err(Into::into)
|
||||
@@ -401,13 +400,21 @@ impl<Config: config::Config> XcmExecutor<Config> {
|
||||
for asset in deposited.assets_iter() {
|
||||
Config::AssetTransactor::deposit_asset(&asset, &dest)?;
|
||||
}
|
||||
let assets = Self::reanchored(deposited, &dest)?;
|
||||
// Note that we pass `None` as `maybe_failed_bin` and drop any assets which cannot
|
||||
// be reanchored because we have already called `deposit_asset` on all assets.
|
||||
let assets = Self::reanchored(deposited, &dest, None);
|
||||
let mut message = vec![ReserveAssetDeposited(assets), ClearOrigin];
|
||||
message.extend(xcm.0.into_iter());
|
||||
Config::XcmSender::send_xcm(dest, Xcm(message)).map_err(Into::into)
|
||||
},
|
||||
InitiateReserveWithdraw { assets, reserve, xcm } => {
|
||||
let assets = Self::reanchored(self.holding.saturating_take(assets), &reserve)?;
|
||||
// Note that here we are able to place any assets which could not be reanchored
|
||||
// back into Holding.
|
||||
let assets = Self::reanchored(
|
||||
self.holding.saturating_take(assets),
|
||||
&reserve,
|
||||
Some(&mut self.holding),
|
||||
);
|
||||
let mut message = vec![WithdrawAsset(assets), ClearOrigin];
|
||||
message.extend(xcm.0.into_iter());
|
||||
Config::XcmSender::send_xcm(reserve, Xcm(message)).map_err(Into::into)
|
||||
@@ -418,13 +425,17 @@ impl<Config: config::Config> XcmExecutor<Config> {
|
||||
for asset in assets.assets_iter() {
|
||||
Config::AssetTransactor::check_out(&dest, &asset);
|
||||
}
|
||||
let assets = Self::reanchored(assets, &dest)?;
|
||||
// Note that we pass `None` as `maybe_failed_bin` and drop any assets which cannot
|
||||
// be reanchored because we have already checked all assets out.
|
||||
let assets = Self::reanchored(assets, &dest, None);
|
||||
let mut message = vec![ReceiveTeleportedAsset(assets), ClearOrigin];
|
||||
message.extend(xcm.0.into_iter());
|
||||
Config::XcmSender::send_xcm(dest, Xcm(message)).map_err(Into::into)
|
||||
},
|
||||
QueryHolding { query_id, dest, assets, max_response_weight } => {
|
||||
let assets = Self::reanchored(self.holding.min(&assets), &dest)?;
|
||||
// Note that we pass `None` as `maybe_failed_bin` since no assets were ever removed
|
||||
// from Holding.
|
||||
let assets = Self::reanchored(self.holding.min(&assets), &dest, None);
|
||||
let max_weight = max_response_weight;
|
||||
let response = Response::Assets(assets);
|
||||
let instruction = QueryResponse { query_id, response, max_weight };
|
||||
@@ -497,10 +508,13 @@ impl<Config: config::Config> XcmExecutor<Config> {
|
||||
}
|
||||
}
|
||||
|
||||
fn reanchored(mut assets: Assets, dest: &MultiLocation) -> Result<MultiAssets, XcmError> {
|
||||
let inv_dest = Config::LocationInverter::invert_location(&dest)
|
||||
.map_err(|()| XcmError::MultiLocationNotInvertible)?;
|
||||
assets.prepend_location(&inv_dest);
|
||||
Ok(assets.into_assets_iter().collect::<Vec<_>>().into())
|
||||
/// NOTE: Any assets which were unable to be reanchored are introduced into `failed_bin`.
|
||||
fn reanchored(
|
||||
mut assets: Assets,
|
||||
dest: &MultiLocation,
|
||||
maybe_failed_bin: Option<&mut Assets>,
|
||||
) -> MultiAssets {
|
||||
assets.reanchor(dest, &Config::LocationInverter::ancestry(), maybe_failed_bin);
|
||||
assets.into_assets_iter().collect::<Vec<_>>().into()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -207,5 +207,6 @@ impl<O> ConvertOrigin<O> for Tuple {
|
||||
/// Means of inverting a location: given a location which describes a `target` interpreted from the
|
||||
/// `source`, this will provide the corresponding location which describes the `source`.
|
||||
pub trait InvertLocation {
|
||||
fn ancestry() -> MultiLocation;
|
||||
fn invert_location(l: &MultiLocation) -> Result<MultiLocation, ()>;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user