cargo +nightly fmt (#3540)

* cargo +nightly fmt

* add cargo-fmt check to ci

* update ci

* fmt

* fmt

* skip macro

* ignore bridges
This commit is contained in:
Shawn Tabrizi
2021-08-02 12:47:33 +02:00
committed by GitHub
parent 30e3012270
commit ff5d56fb76
350 changed files with 20617 additions and 21266 deletions
+153 -101
View File
@@ -14,9 +14,13 @@
// You should have received a copy of the GNU General Public License
// along with Polkadot. If not, see <http://www.gnu.org/licenses/>.
use sp_std::{prelude::*, mem, collections::{btree_map::BTreeMap, btree_set::BTreeSet}};
use xcm::v0::{MultiAsset, MultiLocation, AssetInstance};
use sp_runtime::RuntimeDebug;
use sp_std::{
collections::{btree_map::BTreeMap, btree_set::BTreeSet},
mem,
prelude::*,
};
use xcm::v0::{AssetInstance, MultiAsset, MultiLocation};
/// Classification of an asset being concrete or abstract.
#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, RuntimeDebug)]
@@ -91,43 +95,43 @@ impl From<MultiAsset> for Assets {
impl Assets {
/// New value, containing no assets.
pub fn new() -> Self { Self::default() }
pub fn new() -> Self {
Self::default()
}
/// An iterator over the fungible assets.
pub fn fungible_assets_iter<'a>(&'a self) -> impl Iterator<Item=MultiAsset> + 'a {
self.fungible.iter()
.map(|(id, &amount)| match id.clone() {
AssetId::Concrete(id) => MultiAsset::ConcreteFungible { id, amount },
AssetId::Abstract(id) => MultiAsset::AbstractFungible { id, amount },
})
pub fn fungible_assets_iter<'a>(&'a self) -> impl Iterator<Item = MultiAsset> + 'a {
self.fungible.iter().map(|(id, &amount)| match id.clone() {
AssetId::Concrete(id) => MultiAsset::ConcreteFungible { id, amount },
AssetId::Abstract(id) => MultiAsset::AbstractFungible { id, amount },
})
}
/// An iterator over the non-fungible assets.
pub fn non_fungible_assets_iter<'a>(&'a self) -> impl Iterator<Item=MultiAsset> + 'a {
self.non_fungible.iter()
.map(|&(ref class, ref instance)| match class.clone() {
AssetId::Concrete(class) => MultiAsset::ConcreteNonFungible { class, instance: instance.clone() },
AssetId::Abstract(class) => MultiAsset::AbstractNonFungible { class, instance: instance.clone() },
})
pub fn non_fungible_assets_iter<'a>(&'a self) -> impl Iterator<Item = MultiAsset> + 'a {
self.non_fungible.iter().map(|&(ref class, ref instance)| match class.clone() {
AssetId::Concrete(class) =>
MultiAsset::ConcreteNonFungible { class, instance: instance.clone() },
AssetId::Abstract(class) =>
MultiAsset::AbstractNonFungible { class, instance: instance.clone() },
})
}
/// An iterator over all assets.
pub fn into_assets_iter(self) -> impl Iterator<Item=MultiAsset> {
let fungible = self.fungible.into_iter()
.map(|(id, amount)| match id {
AssetId::Concrete(id) => MultiAsset::ConcreteFungible { id, amount },
AssetId::Abstract(id) => MultiAsset::AbstractFungible { id, amount },
});
let non_fungible = self.non_fungible.into_iter()
.map(|(id, instance)| match id {
AssetId::Concrete(class) => MultiAsset::ConcreteNonFungible { class, instance },
AssetId::Abstract(class) => MultiAsset::AbstractNonFungible { class, instance },
});
pub fn into_assets_iter(self) -> impl Iterator<Item = MultiAsset> {
let fungible = self.fungible.into_iter().map(|(id, amount)| match id {
AssetId::Concrete(id) => MultiAsset::ConcreteFungible { id, amount },
AssetId::Abstract(id) => MultiAsset::AbstractFungible { id, amount },
});
let non_fungible = self.non_fungible.into_iter().map(|(id, instance)| match id {
AssetId::Concrete(class) => MultiAsset::ConcreteNonFungible { class, instance },
AssetId::Abstract(class) => MultiAsset::AbstractNonFungible { class, instance },
});
fungible.chain(non_fungible)
}
/// An iterator over all assets.
pub fn assets_iter<'a>(&'a self) -> impl Iterator<Item=MultiAsset> + 'a {
pub fn assets_iter<'a>(&'a self) -> impl Iterator<Item = MultiAsset> + 'a {
let fungible = self.fungible_assets_iter();
let non_fungible = self.non_fungible_assets_iter();
fungible.chain(non_fungible)
@@ -151,16 +155,16 @@ impl Assets {
match asset {
MultiAsset::ConcreteFungible { id, amount } => {
self.saturating_subsume_fungible(AssetId::Concrete(id), amount);
}
},
MultiAsset::AbstractFungible { id, amount } => {
self.saturating_subsume_fungible(AssetId::Abstract(id), amount);
}
MultiAsset::ConcreteNonFungible { class, instance} => {
},
MultiAsset::ConcreteNonFungible { class, instance } => {
self.saturating_subsume_non_fungible(AssetId::Concrete(class), instance);
}
MultiAsset::AbstractNonFungible { class, instance} => {
},
MultiAsset::AbstractNonFungible { class, instance } => {
self.saturating_subsume_non_fungible(AssetId::Abstract(class), instance);
}
},
_ => (),
}
}
@@ -191,14 +195,22 @@ impl Assets {
pub fn try_take(&mut self, asset: MultiAsset) -> Result<Assets, ()> {
match asset {
MultiAsset::None => Ok(Assets::new()),
MultiAsset::ConcreteFungible { id, amount } => self.try_take_fungible(AssetId::Concrete(id), amount),
MultiAsset::AbstractFungible { id, amount } => self.try_take_fungible(AssetId::Abstract(id), amount),
MultiAsset::ConcreteNonFungible { class, instance} => self.try_take_non_fungible(AssetId::Concrete(class), instance),
MultiAsset::AbstractNonFungible { class, instance} => self.try_take_non_fungible(AssetId::Abstract(class), instance),
MultiAsset::AllAbstractFungible { id } => Ok(self.take_fungible(&AssetId::Abstract(id))),
MultiAsset::AllConcreteFungible { id } => Ok(self.take_fungible(&AssetId::Concrete(id))),
MultiAsset::AllAbstractNonFungible { class } => Ok(self.take_non_fungible(&AssetId::Abstract(class))),
MultiAsset::AllConcreteNonFungible { class } => Ok(self.take_non_fungible(&AssetId::Concrete(class))),
MultiAsset::ConcreteFungible { id, amount } =>
self.try_take_fungible(AssetId::Concrete(id), amount),
MultiAsset::AbstractFungible { id, amount } =>
self.try_take_fungible(AssetId::Abstract(id), amount),
MultiAsset::ConcreteNonFungible { class, instance } =>
self.try_take_non_fungible(AssetId::Concrete(class), instance),
MultiAsset::AbstractNonFungible { class, instance } =>
self.try_take_non_fungible(AssetId::Abstract(class), instance),
MultiAsset::AllAbstractFungible { id } =>
Ok(self.take_fungible(&AssetId::Abstract(id))),
MultiAsset::AllConcreteFungible { id } =>
Ok(self.take_fungible(&AssetId::Concrete(id))),
MultiAsset::AllAbstractNonFungible { class } =>
Ok(self.take_non_fungible(&AssetId::Abstract(class))),
MultiAsset::AllConcreteNonFungible { class } =>
Ok(self.take_non_fungible(&AssetId::Concrete(class))),
MultiAsset::AllFungible => {
let mut taken = Assets::new();
mem::swap(&mut self.fungible, &mut taken.fungible);
@@ -218,7 +230,11 @@ impl Assets {
Ok(id.into_fungible_multiasset(amount).into())
}
pub fn try_take_non_fungible(&mut self, id: AssetId, instance: AssetInstance) -> Result<Assets, ()> {
pub fn try_take_non_fungible(
&mut self,
id: AssetId,
instance: AssetInstance,
) -> Result<Assets, ()> {
let asset_id_instance = (id, instance);
self.try_remove_non_fungible(&asset_id_instance)?;
let (asset_id, instance) = asset_id_instance;
@@ -252,7 +268,10 @@ impl Assets {
Ok(())
}
pub fn try_remove_non_fungible(&mut self, class_instance: &(AssetId, AssetInstance)) -> Result<(), ()> {
pub fn try_remove_non_fungible(
&mut self,
class_instance: &(AssetId, AssetInstance),
) -> Result<(), ()> {
match self.non_fungible.remove(class_instance) {
true => Ok(()),
false => Err(()),
@@ -280,13 +299,21 @@ impl Assets {
pub fn prepend_location(&mut self, prepend: &MultiLocation) {
let mut fungible = Default::default();
mem::swap(&mut self.fungible, &mut fungible);
self.fungible = fungible.into_iter()
.map(|(mut id, amount)| { let _ = id.prepend_location(prepend); (id, amount) })
self.fungible = fungible
.into_iter()
.map(|(mut id, amount)| {
let _ = id.prepend_location(prepend);
(id, amount)
})
.collect();
let mut non_fungible = Default::default();
mem::swap(&mut self.non_fungible, &mut non_fungible);
self.non_fungible = non_fungible.into_iter()
.map(|(mut class, inst)| { let _ = class.prepend_location(prepend); (class, inst) })
self.non_fungible = non_fungible
.into_iter()
.map(|(mut class, inst)| {
let _ = class.prepend_location(prepend);
(class, inst)
})
.collect();
}
@@ -340,67 +367,77 @@ impl Assets {
non_fungible: self.non_fungible.clone(),
}
},
MultiAsset::AllAbstractFungible { id } => {
MultiAsset::AllAbstractFungible { id } =>
for asset in self.fungible_assets_iter() {
match &asset {
MultiAsset::AbstractFungible { id: identifier, .. } => {
if id == identifier { result.saturating_subsume(asset) }
if id == identifier {
result.saturating_subsume(asset)
}
},
_ => (),
}
}
},
},
MultiAsset::AllAbstractNonFungible { class } => {
for asset in self.non_fungible_assets_iter() {
match &asset {
MultiAsset::AbstractNonFungible { class: c, .. } => {
if class == c { result.saturating_subsume(asset) }
},
_ => (),
}
}
}
MultiAsset::AllConcreteFungible { id } => {
for asset in self.fungible_assets_iter() {
match &asset {
MultiAsset::ConcreteFungible { id: identifier, .. } => {
if id == identifier { result.saturating_subsume(asset) }
},
MultiAsset::AbstractNonFungible { class: c, .. } =>
if class == c {
result.saturating_subsume(asset)
},
_ => (),
}
}
},
MultiAsset::AllConcreteNonFungible { class } => {
for asset in self.non_fungible_assets_iter() {
MultiAsset::AllConcreteFungible { id } =>
for asset in self.fungible_assets_iter() {
match &asset {
MultiAsset::ConcreteNonFungible { class: c, .. } => {
if class == c { result.saturating_subsume(asset) }
MultiAsset::ConcreteFungible { id: identifier, .. } => {
if id == identifier {
result.saturating_subsume(asset)
}
},
_ => (),
}
},
MultiAsset::AllConcreteNonFungible { class } => {
for asset in self.non_fungible_assets_iter() {
match &asset {
MultiAsset::ConcreteNonFungible { class: c, .. } =>
if class == c {
result.saturating_subsume(asset)
},
_ => (),
}
}
}
x @ MultiAsset::ConcreteFungible { .. } | x @ MultiAsset::AbstractFungible { .. } => {
},
x @ MultiAsset::ConcreteFungible { .. } |
x @ MultiAsset::AbstractFungible { .. } => {
let (id, amount) = match x {
MultiAsset::ConcreteFungible { id, amount } => (AssetId::Concrete(id.clone()), *amount),
MultiAsset::AbstractFungible { id, amount } => (AssetId::Abstract(id.clone()), *amount),
MultiAsset::ConcreteFungible { id, amount } =>
(AssetId::Concrete(id.clone()), *amount),
MultiAsset::AbstractFungible { id, amount } =>
(AssetId::Abstract(id.clone()), *amount),
_ => unreachable!(),
};
if let Some(v) = self.fungible.get(&id) {
result.saturating_subsume_fungible(id, amount.min(*v));
}
},
x @ MultiAsset::ConcreteNonFungible { .. } | x @ MultiAsset::AbstractNonFungible { .. } => {
x @ MultiAsset::ConcreteNonFungible { .. } |
x @ MultiAsset::AbstractNonFungible { .. } => {
let (class, instance) = match x {
MultiAsset::ConcreteNonFungible { class, instance } => (AssetId::Concrete(class.clone()), instance.clone()),
MultiAsset::AbstractNonFungible { class, instance } => (AssetId::Abstract(class.clone()), instance.clone()),
MultiAsset::ConcreteNonFungible { class, instance } =>
(AssetId::Concrete(class.clone()), instance.clone()),
MultiAsset::AbstractNonFungible { class, instance } =>
(AssetId::Abstract(class.clone()), instance.clone()),
_ => unreachable!(),
};
let item = (class, instance);
if self.non_fungible.contains(&item) {
result.non_fungible.insert(item);
}
}
},
}
}
result
@@ -455,7 +492,8 @@ impl Assets {
result.saturating_subsume_non_fungible(class, instance);
});
},
x @ MultiAsset::AllAbstractFungible { .. } | x @ MultiAsset::AllConcreteFungible { .. } => {
x @ MultiAsset::AllAbstractFungible { .. } |
x @ MultiAsset::AllConcreteFungible { .. } => {
let id = match x {
MultiAsset::AllConcreteFungible { id } => AssetId::Concrete(id),
MultiAsset::AllAbstractFungible { id } => AssetId::Abstract(id),
@@ -465,36 +503,41 @@ impl Assets {
let mut non_matching_fungibles = BTreeMap::<AssetId, u128>::new();
let fungible = mem::replace(&mut self.fungible, Default::default());
fungible.into_iter().for_each(|(iden, amount)| {
if iden == id {
result.saturating_subsume_fungible(iden, amount);
} else {
non_matching_fungibles.insert(iden, amount);
}
});
if iden == id {
result.saturating_subsume_fungible(iden, amount);
} else {
non_matching_fungibles.insert(iden, amount);
}
});
self.fungible = non_matching_fungibles;
},
x @ MultiAsset::AllAbstractNonFungible { .. } | x @ MultiAsset::AllConcreteNonFungible { .. } => {
x @ MultiAsset::AllAbstractNonFungible { .. } |
x @ MultiAsset::AllConcreteNonFungible { .. } => {
let class = match x {
MultiAsset::AllConcreteNonFungible { class } => AssetId::Concrete(class),
MultiAsset::AllAbstractNonFungible { class } => AssetId::Abstract(class),
_ => unreachable!(),
};
// At the end of this block, we will be left with only the non-matching non-fungibles.
let mut non_matching_non_fungibles = BTreeSet::<(AssetId, AssetInstance)>::new();
let mut non_matching_non_fungibles =
BTreeSet::<(AssetId, AssetInstance)>::new();
let non_fungible = mem::replace(&mut self.non_fungible, Default::default());
non_fungible.into_iter().for_each(|(c, instance)| {
if class == c {
result.saturating_subsume_non_fungible(c, instance);
} else {
non_matching_non_fungibles.insert((c, instance));
}
});
if class == c {
result.saturating_subsume_non_fungible(c, instance);
} else {
non_matching_non_fungibles.insert((c, instance));
}
});
self.non_fungible = non_matching_non_fungibles;
},
x @ MultiAsset::ConcreteFungible {..} | x @ MultiAsset::AbstractFungible {..} => {
x @ MultiAsset::ConcreteFungible { .. } |
x @ MultiAsset::AbstractFungible { .. } => {
let (id, amount) = match x {
MultiAsset::ConcreteFungible { id, amount } => (AssetId::Concrete(id), amount),
MultiAsset::AbstractFungible { id, amount } => (AssetId::Abstract(id), amount),
MultiAsset::ConcreteFungible { id, amount } =>
(AssetId::Concrete(id), amount),
MultiAsset::AbstractFungible { id, amount } =>
(AssetId::Abstract(id), amount),
_ => unreachable!(),
};
// remove the maxmimum possible up to id/amount from self, add the removed onto
@@ -509,11 +552,14 @@ impl Assets {
result.saturating_subsume_fungible(id, e.clone());
}
}
}
x @ MultiAsset::ConcreteNonFungible {..} | x @ MultiAsset::AbstractNonFungible {..} => {
},
x @ MultiAsset::ConcreteNonFungible { .. } |
x @ MultiAsset::AbstractNonFungible { .. } => {
let (class, instance) = match x {
MultiAsset::ConcreteNonFungible { class, instance } => (AssetId::Concrete(class), instance),
MultiAsset::AbstractNonFungible { class, instance } => (AssetId::Abstract(class), instance),
MultiAsset::ConcreteNonFungible { class, instance } =>
(AssetId::Concrete(class), instance),
MultiAsset::AbstractNonFungible { class, instance } =>
(AssetId::Abstract(class), instance),
_ => unreachable!(),
};
// remove the maxmimum possible up to id/amount from self, add the removed onto
@@ -521,7 +567,7 @@ impl Assets {
if let Some(entry) = self.non_fungible.take(&(class, instance)) {
result.non_fungible.insert(entry);
}
}
},
}
}
result
@@ -543,7 +589,10 @@ mod tests {
}
#[allow(non_snake_case)]
fn ANF(class: u8, instance_id: u128) -> MultiAsset {
MultiAsset::AbstractNonFungible { class: vec![class], instance: AssetInstance::Index { id: instance_id } }
MultiAsset::AbstractNonFungible {
class: vec![class],
instance: AssetInstance::Index { id: instance_id },
}
}
#[allow(non_snake_case)]
fn CF(amount: u128) -> MultiAsset {
@@ -551,7 +600,10 @@ mod tests {
}
#[allow(non_snake_case)]
fn CNF(instance_id: u128) -> MultiAsset {
MultiAsset::ConcreteNonFungible { class: MultiLocation::Null, instance: AssetInstance::Index { id: instance_id } }
MultiAsset::ConcreteNonFungible {
class: MultiLocation::Null,
instance: AssetInstance::Index { id: instance_id },
}
}
fn test_assets() -> Assets {
+8 -6
View File
@@ -14,18 +14,20 @@
// You should have received a copy of the GNU General Public License
// along with Polkadot. If not, see <http://www.gnu.org/licenses/>.
use xcm::v0::SendXcm;
use frame_support::dispatch::{Dispatchable, Parameter};
use frame_support::weights::{PostDispatchInfo, GetDispatchInfo};
use crate::traits::{
TransactAsset, ConvertOrigin, FilterAssetLocation, InvertLocation, ShouldExecute, WeightTrader, WeightBounds,
OnResponse,
ConvertOrigin, FilterAssetLocation, InvertLocation, OnResponse, ShouldExecute, TransactAsset,
WeightBounds, WeightTrader,
};
use frame_support::{
dispatch::{Dispatchable, Parameter},
weights::{GetDispatchInfo, PostDispatchInfo},
};
use xcm::v0::SendXcm;
/// The trait to parameterize the `XcmExecutor`.
pub trait Config {
/// The outer call dispatch type.
type Call: Parameter + Dispatchable<PostInfo=PostDispatchInfo> + GetDispatchInfo;
type Call: Parameter + Dispatchable<PostInfo = PostDispatchInfo> + GetDispatchInfo;
/// How to send an onward XCM message.
type XcmSender: SendXcm;
+74 -41
View File
@@ -16,24 +16,25 @@
#![cfg_attr(not(feature = "std"), no_std)]
use sp_std::{prelude::*, marker::PhantomData};
use frame_support::{
ensure, weights::GetDispatchInfo,
dispatch::{Weight, Dispatchable}
dispatch::{Dispatchable, Weight},
ensure,
weights::GetDispatchInfo,
};
use sp_std::{marker::PhantomData, prelude::*};
use xcm::v0::{
ExecuteXcm, SendXcm, Error as XcmError, Outcome,
MultiLocation, MultiAsset, Xcm, Order, Response,
Error as XcmError, ExecuteXcm, MultiAsset, MultiLocation, Order, Outcome, Response, SendXcm,
Xcm,
};
pub mod traits;
use traits::{
TransactAsset, ConvertOrigin, FilterAssetLocation, InvertLocation, WeightBounds, WeightTrader,
ShouldExecute, OnResponse
ConvertOrigin, FilterAssetLocation, InvertLocation, OnResponse, ShouldExecute, TransactAsset,
WeightBounds, WeightTrader,
};
mod assets;
pub use assets::{Assets, AssetId};
pub use assets::{AssetId, Assets};
mod config;
pub use config::Config;
@@ -70,10 +71,17 @@ impl<Config: config::Config> ExecuteXcm<Config::Call> for XcmExecutor<Config> {
None => return Outcome::Error(XcmError::Overflow),
};
if maximum_weight > weight_limit {
return Outcome::Error(XcmError::WeightLimitReached(maximum_weight));
return Outcome::Error(XcmError::WeightLimitReached(maximum_weight))
}
let mut trader = Config::Trader::new();
let result = Self::do_execute_xcm(origin, true, message, &mut weight_credit, Some(shallow_weight), &mut trader);
let result = Self::do_execute_xcm(
origin,
true,
message,
&mut weight_credit,
Some(shallow_weight),
&mut trader,
);
drop(trader);
log::trace!(target: "xcm::execute_xcm", "result: {:?}", &result);
match result {
@@ -106,10 +114,10 @@ impl<Config: config::Config> XcmExecutor<Config> {
log::trace!(
target: "xcm::do_execute_xcm",
"origin: {:?}, top_level: {:?}, message: {:?}, weight_credit: {:?}, maybe_shallow_weight: {:?}",
origin,
top_level,
message,
weight_credit,
origin,
top_level,
message,
weight_credit,
maybe_shallow_weight,
);
// This is the weight of everything that cannot be paid for. This basically means all computation
@@ -118,8 +126,14 @@ impl<Config: config::Config> XcmExecutor<Config> {
.or_else(|| Config::Weigher::shallow(&mut message).ok())
.ok_or(XcmError::WeightNotComputable)?;
Config::Barrier::should_execute(&origin, top_level, &message, shallow_weight, weight_credit)
.map_err(|()| XcmError::Barrier)?;
Config::Barrier::should_execute(
&origin,
top_level,
&message,
shallow_weight,
weight_credit,
)
.map_err(|()| XcmError::Barrier)?;
// The surplus weight, defined as the amount by which `shallow_weight` plus all nested
// `shallow_weight` values (ensuring no double-counting and also known as `deep_weight`) is an
@@ -136,17 +150,20 @@ impl<Config: config::Config> XcmExecutor<Config> {
holding.saturating_subsume_all(withdrawn);
}
Some((holding, effects))
}
},
(origin, Xcm::ReserveAssetDeposit { assets, effects }) => {
// check whether we trust origin to be our reserve location for this asset.
for asset in assets.iter() {
ensure!(!asset.is_wildcard(), XcmError::Wildcard);
// We only trust the origin to send us assets that they identify as their
// sovereign assets.
ensure!(Config::IsReserve::filter_asset_location(asset, &origin), XcmError::UntrustedReserveLocation);
ensure!(
Config::IsReserve::filter_asset_location(asset, &origin),
XcmError::UntrustedReserveLocation
);
}
Some((Assets::from(assets), effects))
}
},
(origin, Xcm::TransferAsset { assets, dest }) => {
// Take `assets` from the origin account (on-chain) and place into dest account.
for asset in assets {
@@ -154,7 +171,7 @@ impl<Config: config::Config> XcmExecutor<Config> {
Config::AssetTransactor::teleport_asset(&asset, &origin, &dest)?;
}
None
}
},
(origin, Xcm::TransferReserveAsset { mut assets, dest, effects }) => {
// Take `assets` from the origin account (on-chain) and place into dest account.
let inv_dest = Config::LocationInverter::invert_location(&dest);
@@ -165,14 +182,17 @@ impl<Config: config::Config> XcmExecutor<Config> {
}
Config::XcmSender::send_xcm(dest, Xcm::ReserveAssetDeposit { assets, effects })?;
None
}
},
(origin, Xcm::TeleportAsset { assets, effects }) => {
// check whether we trust origin to teleport this asset to us via config trait.
for asset in assets.iter() {
ensure!(!asset.is_wildcard(), XcmError::Wildcard);
// We only trust the origin to send us assets that they identify as their
// sovereign assets.
ensure!(Config::IsTeleporter::filter_asset_location(asset, &origin), XcmError::UntrustedTeleportLocation);
ensure!(
Config::IsTeleporter::filter_asset_location(asset, &origin),
XcmError::UntrustedTeleportLocation
);
// We should check that the asset can actually be teleported in (for this to be in error, there
// would need to be an accounting violation by one of the trusted chains, so it's unlikely, but we
// don't want to punish a possibly innocent chain/user).
@@ -182,7 +202,7 @@ impl<Config: config::Config> XcmExecutor<Config> {
Config::AssetTransactor::check_in(&origin, asset);
}
Some((Assets::from(assets), effects))
}
},
(origin, Xcm::Transact { origin_type, require_weight_at_most, mut call }) => {
// We assume that the Relay-chain is allowed to use transact on this parachain.
@@ -198,8 +218,9 @@ impl<Config: config::Config> XcmExecutor<Config> {
// Not much to do with the result as it is. It's up to the parachain to ensure that the
// message makes sense.
error_and_info.post_info.actual_weight
}
}.unwrap_or(weight);
},
}
.unwrap_or(weight);
let surplus = weight.saturating_sub(actual_weight);
// Credit any surplus weight that we bought. This should be safe since it's work we
// didn't realise that we didn't have to do.
@@ -212,20 +233,21 @@ impl<Config: config::Config> XcmExecutor<Config> {
// Return the overestimated amount so we can adjust our expectations on how much this entire
// execution has taken.
None
}
},
(origin, Xcm::QueryResponse { query_id, response }) => {
Config::ResponseHandler::on_response(origin, query_id, response);
None
}
},
(origin, Xcm::RelayedFrom { who, message }) => {
ensure!(who.is_interior(), XcmError::EscalationOfPrivilege);
let mut origin = origin;
origin.append_with(who).map_err(|_| XcmError::MultiLocationFull)?;
let surplus = Self::do_execute_xcm(origin, top_level, *message, weight_credit, None, trader)?;
let surplus =
Self::do_execute_xcm(origin, top_level, *message, weight_credit, None, trader)?;
total_surplus = total_surplus.saturating_add(surplus);
None
}
_ => Err(XcmError::UnhandledXcmMessage)?, // Unhandled XCM message.
},
_ => Err(XcmError::UnhandledXcmMessage)?, // Unhandled XCM message.
};
if let Some((mut holding, effects)) = maybe_holding_effects {
@@ -266,11 +288,11 @@ impl<Config: config::Config> XcmExecutor<Config> {
let assets = Self::reanchored(deposited, &dest);
Config::XcmSender::send_xcm(dest, Xcm::ReserveAssetDeposit { assets, effects })?;
},
Order::InitiateReserveWithdraw { assets, reserve, effects} => {
Order::InitiateReserveWithdraw { assets, reserve, effects } => {
let assets = Self::reanchored(holding.saturating_take(assets), &reserve);
Config::XcmSender::send_xcm(reserve, Xcm::WithdrawAsset { assets, effects })?;
}
Order::InitiateTeleport { assets, dest, effects} => {
},
Order::InitiateTeleport { assets, dest, effects } => {
// We must do this first in order to resolve wildcards.
let assets = holding.saturating_take(assets);
for asset in assets.assets_iter() {
@@ -278,28 +300,39 @@ impl<Config: config::Config> XcmExecutor<Config> {
}
let assets = Self::reanchored(assets, &dest);
Config::XcmSender::send_xcm(dest, Xcm::TeleportAsset { assets, effects })?;
}
},
Order::QueryHolding { query_id, dest, assets } => {
let assets = Self::reanchored(holding.min(assets.iter()), &dest);
Config::XcmSender::send_xcm(dest, Xcm::QueryResponse { query_id, response: Response::Assets(assets) })?;
}
Config::XcmSender::send_xcm(
dest,
Xcm::QueryResponse { query_id, response: Response::Assets(assets) },
)?;
},
Order::BuyExecution { fees, weight, debt, halt_on_error, xcm } => {
// pay for `weight` using up to `fees` of the holding account.
let purchasing_weight = Weight::from(weight.checked_add(debt).ok_or(XcmError::Overflow)?);
let purchasing_weight =
Weight::from(weight.checked_add(debt).ok_or(XcmError::Overflow)?);
let max_fee = holding.try_take(fees).map_err(|()| XcmError::NotHoldingFees)?;
let unspent = trader.buy_weight(purchasing_weight, max_fee)?;
holding.saturating_subsume_all(unspent);
let mut remaining_weight = weight;
for message in xcm.into_iter() {
match Self::do_execute_xcm(origin.clone(), false, message, &mut remaining_weight, None, trader) {
match Self::do_execute_xcm(
origin.clone(),
false,
message,
&mut remaining_weight,
None,
trader,
) {
Err(e) if halt_on_error => return Err(e),
Err(_) => {}
Ok(surplus) => { total_surplus += surplus }
Err(_) => {},
Ok(surplus) => total_surplus += surplus,
}
}
holding.saturating_subsume(trader.refund_weight(remaining_weight));
}
},
_ => return Err(XcmError::UnhandledEffect)?,
}
Ok(total_surplus)
@@ -14,8 +14,8 @@
// You should have received a copy of the GNU General Public License
// along with Polkadot. If not, see <http://www.gnu.org/licenses/>.
use sp_std::{prelude::*, result::Result, borrow::Borrow, convert::TryFrom};
use parity_scale_codec::{Encode, Decode};
use parity_scale_codec::{Decode, Encode};
use sp_std::{borrow::Borrow, convert::TryFrom, prelude::*, result::Result};
use xcm::v0::{MultiLocation, OriginKind};
/// Generic third-party conversion trait. Use this when you don't want to force the user to use default
@@ -29,12 +29,16 @@ use xcm::v0::{MultiLocation, OriginKind};
/// the `Err(_)` of the last failing conversion (or `Err(())` for ref conversions).
pub trait Convert<A: Clone, B: Clone> {
/// Convert from `value` (of type `A`) into an equivalent value of type `B`, `Err` if not possible.
fn convert(value: A) -> Result<B, A> { Self::convert_ref(&value).map_err(|_| value) }
fn convert(value: A) -> Result<B, A> {
Self::convert_ref(&value).map_err(|_| value)
}
fn convert_ref(value: impl Borrow<A>) -> Result<B, ()> {
Self::convert(value.borrow().clone()).map_err(|_| ())
}
/// Convert from `value` (of type `B`) into an equivalent value of type `A`, `Err` if not possible.
fn reverse(value: B) -> Result<A, B> { Self::reverse_ref(&value).map_err(|_| value) }
fn reverse(value: B) -> Result<A, B> {
Self::reverse_ref(&value).map_err(|_| value)
}
fn reverse_ref(value: impl Borrow<B>) -> Result<A, ()> {
Self::reverse(value.borrow().clone()).map_err(|_| ())
}
@@ -85,13 +89,19 @@ impl<A: Clone, B: Clone> Convert<A, B> for Tuple {
/// Simple pass-through which implements `BytesConversion` while not doing any conversion.
pub struct Identity;
impl<T: Clone> Convert<T, T> for Identity {
fn convert(value: T) -> Result<T, T> { Ok(value) }
fn reverse(value: T) -> Result<T, T> { Ok(value) }
fn convert(value: T) -> Result<T, T> {
Ok(value)
}
fn reverse(value: T) -> Result<T, T> {
Ok(value)
}
}
/// Implementation of `Convert` trait using `TryFrom`.
pub struct JustTry;
impl<Source: TryFrom<Dest> + Clone, Dest: TryFrom<Source> + Clone> Convert<Source, Dest> for JustTry {
impl<Source: TryFrom<Dest> + Clone, Dest: TryFrom<Source> + Clone> Convert<Source, Dest>
for JustTry
{
fn convert(value: Source) -> Result<Dest, Source> {
Dest::try_from(value.clone()).map_err(|_| value)
}
@@ -103,7 +113,9 @@ impl<Source: TryFrom<Dest> + Clone, Dest: TryFrom<Source> + Clone> Convert<Sourc
/// Implementation of `Convert<_, Vec<u8>>` using the parity scale codec.
pub struct Encoded;
impl<T: Clone + Encode + Decode> Convert<T, Vec<u8>> for Encoded {
fn convert_ref(value: impl Borrow<T>) -> Result<Vec<u8>, ()> { Ok(value.borrow().encode()) }
fn convert_ref(value: impl Borrow<T>) -> Result<Vec<u8>, ()> {
Ok(value.borrow().encode())
}
fn reverse_ref(bytes: impl Borrow<Vec<u8>>) -> Result<T, ()> {
T::decode(&mut &bytes.borrow()[..]).map_err(|_| ())
}
@@ -115,7 +127,9 @@ impl<T: Clone + Encode + Decode> Convert<Vec<u8>, T> for Decoded {
fn convert_ref(bytes: impl Borrow<Vec<u8>>) -> Result<T, ()> {
T::decode(&mut &bytes.borrow()[..]).map_err(|_| ())
}
fn reverse_ref(value: impl Borrow<T>) -> Result<Vec<u8>, ()> { Ok(value.borrow().encode()) }
fn reverse_ref(value: impl Borrow<T>) -> Result<Vec<u8>, ()> {
Ok(value.borrow().encode())
}
}
/// A converter `trait` for origin types.
@@ -14,8 +14,8 @@
// You should have received a copy of the GNU General Public License
// along with Polkadot. If not, see <http://www.gnu.org/licenses/>.
use xcm::v0::{MultiAsset, Error as XcmError};
use sp_std::result;
use xcm::v0::{Error as XcmError, MultiAsset};
/// Errors associated with [`MatchesFungibles`] operation.
pub enum Error {
@@ -35,7 +35,8 @@ impl From<Error> for XcmError {
match e {
Error::AssetNotFound => XcmError::AssetNotFound,
Error::AccountIdConversionFailed => FailedToTransactAsset("AccountIdConversionFailed"),
Error::AmountToBalanceConversionFailed => FailedToTransactAsset("AmountToBalanceConversionFailed"),
Error::AmountToBalanceConversionFailed =>
FailedToTransactAsset("AmountToBalanceConversionFailed"),
Error::AssetIdConversionFailed => FailedToTransactAsset("AssetIdConversionFailed"),
}
}
@@ -46,10 +47,7 @@ pub trait MatchesFungibles<AssetId, Balance> {
}
#[impl_trait_for_tuples::impl_for_tuples(30)]
impl<
AssetId: Clone,
Balance: Clone,
> MatchesFungibles<AssetId, Balance> for Tuple {
impl<AssetId: Clone, Balance: Clone> MatchesFungibles<AssetId, Balance> for Tuple {
fn matches_fungibles(a: &MultiAsset) -> result::Result<(AssetId, Balance), Error> {
for_tuples!( #(
match Tuple::matches_fungibles(a) { o @ Ok(_) => return o, _ => () }
+4 -4
View File
@@ -17,13 +17,13 @@
//! Various traits used in configuring the executor.
mod conversion;
pub use conversion::{InvertLocation, ConvertOrigin, Convert, JustTry, Identity, Encoded, Decoded};
pub use conversion::{Convert, ConvertOrigin, Decoded, Encoded, Identity, InvertLocation, JustTry};
mod filter_asset_location;
pub use filter_asset_location::{FilterAssetLocation};
pub use filter_asset_location::FilterAssetLocation;
mod matches_fungible;
pub use matches_fungible::{MatchesFungible};
pub use matches_fungible::MatchesFungible;
mod matches_fungibles;
pub use matches_fungibles::{MatchesFungibles, Error};
pub use matches_fungibles::{Error, MatchesFungibles};
mod on_response;
pub use on_response::OnResponse;
mod should_execute;
@@ -14,8 +14,8 @@
// You should have received a copy of the GNU General Public License
// along with Polkadot. If not, see <http://www.gnu.org/licenses/>.
use xcm::v0::{Response, MultiLocation};
use frame_support::weights::Weight;
use xcm::v0::{MultiLocation, Response};
/// Define what needs to be done upon receiving a query response.
pub trait OnResponse {
@@ -25,6 +25,10 @@ pub trait OnResponse {
fn on_response(origin: MultiLocation, query_id: u64, response: Response) -> Weight;
}
impl OnResponse for () {
fn expecting_response(_origin: &MultiLocation, _query_id: u64) -> bool { false }
fn on_response(_origin: MultiLocation, _query_id: u64, _response: Response) -> Weight { 0 }
fn expecting_response(_origin: &MultiLocation, _query_id: u64) -> bool {
false
}
fn on_response(_origin: MultiLocation, _query_id: u64, _response: Response) -> Weight {
0
}
}
@@ -14,9 +14,9 @@
// You should have received a copy of the GNU General Public License
// along with Polkadot. If not, see <http://www.gnu.org/licenses/>.
use sp_std::result::Result;
use xcm::v0::{Xcm, MultiLocation};
use frame_support::weights::Weight;
use sp_std::result::Result;
use xcm::v0::{MultiLocation, Xcm};
/// Trait to determine whether the execution engine should actually execute a given XCM.
///
@@ -14,9 +14,9 @@
// You should have received a copy of the GNU General Public License
// along with Polkadot. If not, see <http://www.gnu.org/licenses/>.
use sp_std::result::Result;
use xcm::v0::{Error as XcmError, Result as XcmResult, MultiAsset, MultiLocation};
use crate::Assets;
use sp_std::result::Result;
use xcm::v0::{Error as XcmError, MultiAsset, MultiLocation, Result as XcmResult};
/// Facility for asset transacting.
///
@@ -78,22 +78,30 @@ pub trait TransactAsset {
/// Move an `asset` `from` one location in `to` another location.
///
/// Returns `XcmError::FailedToTransactAsset` if transfer failed.
fn transfer_asset(_asset: &MultiAsset, _from: &MultiLocation, _to: &MultiLocation) -> Result<Assets, XcmError> {
fn transfer_asset(
_asset: &MultiAsset,
_from: &MultiLocation,
_to: &MultiLocation,
) -> Result<Assets, XcmError> {
Err(XcmError::Unimplemented)
}
/// Move an `asset` `from` one location in `to` another location.
///
/// Attempts to use `transfer_asset` and if not available then falls back to using a two-part withdraw/deposit.
fn teleport_asset(asset: &MultiAsset, from: &MultiLocation, to: &MultiLocation) -> Result<Assets, XcmError> {
fn teleport_asset(
asset: &MultiAsset,
from: &MultiLocation,
to: &MultiLocation,
) -> Result<Assets, XcmError> {
match Self::transfer_asset(asset, from, to) {
Err(XcmError::Unimplemented) => {
let assets = Self::withdraw_asset(asset, from)?;
// Not a very forgiving attitude; once we implement roll-backs then it'll be nicer.
Self::deposit_asset(asset, to)?;
Ok(assets)
}
result => result
},
result => result,
}
}
}
@@ -160,7 +168,11 @@ impl TransactAsset for Tuple {
Err(XcmError::AssetNotFound)
}
fn transfer_asset(what: &MultiAsset, from: &MultiLocation, to: &MultiLocation) -> Result<Assets, XcmError> {
fn transfer_asset(
what: &MultiAsset,
from: &MultiLocation,
to: &MultiLocation,
) -> Result<Assets, XcmError> {
for_tuples!( #(
match Tuple::transfer_asset(what, from, to) {
Err(XcmError::AssetNotFound | XcmError::Unimplemented) => (),
@@ -199,7 +211,11 @@ mod tests {
Err(XcmError::AssetNotFound)
}
fn transfer_asset(_what: &MultiAsset, _from: &MultiLocation, _to: &MultiLocation) -> Result<Assets, XcmError> {
fn transfer_asset(
_what: &MultiAsset,
_from: &MultiLocation,
_to: &MultiLocation,
) -> Result<Assets, XcmError> {
Err(XcmError::AssetNotFound)
}
}
@@ -218,7 +234,11 @@ mod tests {
Err(XcmError::Overflow)
}
fn transfer_asset(_what: &MultiAsset, _from: &MultiLocation, _to: &MultiLocation) -> Result<Assets, XcmError> {
fn transfer_asset(
_what: &MultiAsset,
_from: &MultiLocation,
_to: &MultiLocation,
) -> Result<Assets, XcmError> {
Err(XcmError::Overflow)
}
}
@@ -237,16 +257,24 @@ mod tests {
Ok(Assets::default())
}
fn transfer_asset(_what: &MultiAsset, _from: &MultiLocation, _to: &MultiLocation) -> Result<Assets, XcmError> {
fn transfer_asset(
_what: &MultiAsset,
_from: &MultiLocation,
_to: &MultiLocation,
) -> Result<Assets, XcmError> {
Ok(Assets::default())
}
}
#[test]
fn defaults_to_asset_not_found() {
type MultiTransactor = (UnimplementedTransactor, NotFoundTransactor, UnimplementedTransactor);
type MultiTransactor =
(UnimplementedTransactor, NotFoundTransactor, UnimplementedTransactor);
assert_eq!(MultiTransactor::deposit_asset(&MultiAsset::All, &MultiLocation::Null), Err(XcmError::AssetNotFound));
assert_eq!(
MultiTransactor::deposit_asset(&MultiAsset::All, &MultiLocation::Null),
Err(XcmError::AssetNotFound)
);
}
#[test]
@@ -260,7 +288,10 @@ mod tests {
fn unexpected_error_stops_iteration() {
type MultiTransactor = (OverflowTransactor, SuccessfulTransactor);
assert_eq!(MultiTransactor::deposit_asset(&MultiAsset::All, &MultiLocation::Null), Err(XcmError::Overflow));
assert_eq!(
MultiTransactor::deposit_asset(&MultiAsset::All, &MultiLocation::Null),
Err(XcmError::Overflow)
);
}
#[test]
@@ -14,10 +14,10 @@
// You should have received a copy of the GNU General Public License
// along with Polkadot. If not, see <http://www.gnu.org/licenses/>.
use sp_std::result::Result;
use xcm::v0::{Xcm, MultiAsset, MultiLocation, Error};
use frame_support::weights::Weight;
use crate::Assets;
use frame_support::weights::Weight;
use sp_std::result::Result;
use xcm::v0::{Error, MultiAsset, MultiLocation, Xcm};
/// Determine the weight of an XCM message.
pub trait WeightBounds<Call> {
@@ -71,11 +71,15 @@ pub trait WeightTrader: Sized {
/// purchased using `buy_weight`.
///
/// Default implementation refunds nothing.
fn refund_weight(&mut self, _weight: Weight) -> MultiAsset { MultiAsset::None }
fn refund_weight(&mut self, _weight: Weight) -> MultiAsset {
MultiAsset::None
}
}
impl WeightTrader for () {
fn new() -> Self { () }
fn new() -> Self {
()
}
fn buy_weight(&mut self, _: Weight, _: Assets) -> Result<Assets, Error> {
Err(Error::Unimplemented)
}