Skip to content
This repository has been archived by the owner on Nov 15, 2023. It is now read-only.

XCM: PayOverXcm config #6900

Merged
merged 34 commits into from
May 31, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
3ca5292
Move XCM query functionality to trait
franciscoaguirre Mar 16, 2023
d136364
Fix tests
franciscoaguirre Mar 16, 2023
2529aff
Add PayOverXcm implementation
franciscoaguirre Mar 21, 2023
e6102f6
fix the PayOverXcm trait to compile
tonyalaribe Mar 22, 2023
20f9e1f
moved doc comment out of trait implmeentation and to the trait
tonyalaribe Mar 22, 2023
1a31c92
PayOverXCM documentation
tonyalaribe Mar 22, 2023
4030f14
Change documentation a bit
franciscoaguirre Mar 22, 2023
6d2a686
Added empty benchmark methods implementation and changed docs
franciscoaguirre Mar 22, 2023
1331aa5
update PayOverXCM to convert AccountIds to MultiLocations
tonyalaribe Mar 23, 2023
117c169
Implement benchmarking method
franciscoaguirre Mar 24, 2023
94a30c8
Change v3 to latest
franciscoaguirre Mar 24, 2023
6c0dece
Descend origin to an asset sender (#6970)
muharem Mar 29, 2023
ec24eba
Add more variants to the QueryResponseStatus enum
franciscoaguirre Mar 30, 2023
6aa7b20
Change Beneficiary to Into<[u8; 32]>
franciscoaguirre Apr 4, 2023
41fe1d8
update PayOverXcm to return concrete errors and use AccountId as sender
tonyalaribe Apr 20, 2023
13ceb40
use polkadot-primitives for AccountId
tonyalaribe Apr 21, 2023
9df80ea
fix dependency to use polkadot-core-primitives
tonyalaribe Apr 21, 2023
59b884c
force Unpaid instruction to the top of the instructions list
tonyalaribe Apr 25, 2023
31d3e1d
modify report_outcome to accept interior argument
tonyalaribe Apr 26, 2023
918d62e
use new_query directly for building final xcm query, instead of repor…
tonyalaribe Apr 28, 2023
97d05d0
fix usage of new_query to use the XcmQueryHandler
tonyalaribe Apr 28, 2023
2465cc4
fix usage of new_query to use the XcmQueryHandler
tonyalaribe Apr 28, 2023
a524d26
tiny method calling fix
tonyalaribe Apr 28, 2023
feed38e
Merge branch 'master' into cisco-xcm-query-handler
tonyalaribe May 5, 2023
8ae3a99
xcm query handler (#7198)
muharem May 10, 2023
3ee49cd
Update xcm/xcm-builder/src/pay.rs
tonyalaribe May 26, 2023
00cb2d2
Updates
gavofyork May 29, 2023
a309627
Merge remote-tracking branch 'origin/master' into cisco-xcm-query-han…
gavofyork May 29, 2023
a42c9e3
Docs
gavofyork May 29, 2023
3b38fa1
Fix benchmarking stuff
gavofyork May 29, 2023
3bedbab
Destination can be determined based on asset_kind
gavofyork May 30, 2023
9a28a2a
Tweaking API to minimise clones
gavofyork May 30, 2023
548dcc8
Merge remote-tracking branch 'origin/master' into cisco-xcm-query-han…
gavofyork May 30, 2023
27a0499
Some repotting and docs
gavofyork May 31, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion runtime/test-runtime/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -546,6 +546,7 @@ pub mod pallet_test_notifier {
use pallet_xcm::ensure_response;
use sp_runtime::DispatchResult;
use xcm::latest::prelude::*;
use xcm_executor::traits::QueryHandler as XcmQueryHandler;

#[pallet::pallet]
pub struct Pallet<T>(_);
Expand Down Expand Up @@ -581,7 +582,7 @@ pub mod pallet_test_notifier {
let id = who
.using_encoded(|mut d| <[u8; 32]>::decode(&mut d))
.map_err(|_| Error::<T>::BadAccountFormat)?;
let qid = pallet_xcm::Pallet::<T>::new_query(
let qid = <pallet_xcm::Pallet<T> as XcmQueryHandler>::new_query(
Junction::AccountId32 { network: None, id },
100u32.into(),
Here,
Expand Down
117 changes: 62 additions & 55 deletions xcm/pallet-xcm/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,8 @@ use frame_system::pallet_prelude::*;
pub use pallet::*;
use xcm_executor::{
traits::{
CheckSuspension, ClaimAssets, DropAssets, MatchesFungible, OnResponse,
VersionChangeNotifier, WeightBounds,
CheckSuspension, ClaimAssets, DropAssets, MatchesFungible, OnResponse, QueryHandler,
QueryResponseStatus, VersionChangeNotifier, WeightBounds,
},
Assets,
};
Expand Down Expand Up @@ -1126,6 +1126,66 @@ pub mod pallet {
/// The maximum number of distinct assets allowed to be transferred in a single helper extrinsic.
const MAX_ASSETS_FOR_TRANSFER: usize = 2;

impl<T: Config> QueryHandler for Pallet<T> {
type QueryId = u64;
type BlockNumber = T::BlockNumber;
type Error = XcmError;
type UniversalLocation = T::UniversalLocation;

/// Attempt to create a new query ID and register it as a query that is yet to respond.
fn new_query(
responder: impl Into<MultiLocation>,
timeout: T::BlockNumber,
match_querier: impl Into<MultiLocation>,
) -> Self::QueryId {
Self::do_new_query(responder, None, timeout, match_querier).into()
}

/// To check the status of the query, use `fn query()` passing the resultant `QueryId`
/// value.
tonyalaribe marked this conversation as resolved.
Show resolved Hide resolved
fn report_outcome(
message: &mut Xcm<()>,
responder: impl Into<MultiLocation>,
timeout: Self::BlockNumber,
) -> Result<Self::QueryId, Self::Error> {
let responder = responder.into();
let destination = Self::UniversalLocation::get()
.invert_target(&responder)
.map_err(|()| XcmError::LocationNotInvertible)?;
let query_id = Self::new_query(responder, timeout, Here);
let response_info = QueryResponseInfo { destination, query_id, max_weight: Weight::zero() };
let report_error = Xcm(vec![ReportError(response_info)]);
message.0.insert(0, SetAppendix(report_error));
Ok(query_id)
}

/// Removes response when ready and emits [Event::ResponseTaken] event.
fn take_response(query_id: Self::QueryId) -> QueryResponseStatus<Self::BlockNumber> {
match Queries::<T>::get(query_id) {
Some(QueryStatus::Ready { response, at }) => match response.try_into() {
Ok(response) => {
Queries::<T>::remove(query_id);
Self::deposit_event(Event::ResponseTaken { query_id });
QueryResponseStatus::Ready { response, at }
},
Err(_) => QueryResponseStatus::UnexpectedVersion,
},
Some(QueryStatus::Pending { timeout, .. }) => QueryResponseStatus::Pending { timeout },
Some(_) => QueryResponseStatus::UnexpectedVersion,
None => QueryResponseStatus::NotFound,
}
}

#[cfg(feature = "runtime-benchmarks")]
fn expect_response(id: Self::QueryId, response: Response) {
let response = response.into();
Queries::<T>::insert(
id,
QueryStatus::Ready { response, at: frame_system::Pallet::<T>::block_number() },
);
}
}

impl<T: Config> Pallet<T> {
fn do_reserve_transfer_assets(
origin: OriginFor<T>,
Expand Down Expand Up @@ -1497,36 +1557,6 @@ impl<T: Config> Pallet<T> {
})
}

/// Consume `message` and return another which is equivalent to it except that it reports
/// back the outcome.
///
/// - `message`: The message whose outcome should be reported.
/// - `responder`: The origin from which a response should be expected.
/// - `timeout`: The block number after which it is permissible for `notify` not to be
/// called even if a response is received.
///
/// `report_outcome` may return an error if the `responder` is not invertible.
///
/// It is assumed that the querier of the response will be `Here`.
///
/// To check the status of the query, use `fn query()` passing the resultant `QueryId`
/// value.
pub fn report_outcome(
message: &mut Xcm<()>,
responder: impl Into<MultiLocation>,
timeout: T::BlockNumber,
) -> Result<QueryId, XcmError> {
let responder = responder.into();
let destination = T::UniversalLocation::get()
.invert_target(&responder)
.map_err(|()| XcmError::LocationNotInvertible)?;
let query_id = Self::new_query(responder, timeout, Here);
let response_info = QueryResponseInfo { destination, query_id, max_weight: Weight::zero() };
let report_error = Xcm(vec![ReportError(response_info)]);
message.0.insert(0, SetAppendix(report_error));
Ok(query_id)
}

/// Consume `message` and return another which is equivalent to it except that it reports
/// back the outcome and dispatches `notify` on this chain.
///
Expand Down Expand Up @@ -1568,15 +1598,6 @@ impl<T: Config> Pallet<T> {
Ok(())
}

/// Attempt to create a new query ID and register it as a query that is yet to respond.
pub fn new_query(
responder: impl Into<MultiLocation>,
timeout: T::BlockNumber,
match_querier: impl Into<MultiLocation>,
) -> u64 {
Self::do_new_query(responder, None, timeout, match_querier)
}

/// Attempt to create a new query ID and register it as a query that is yet to respond, and
/// which will call a dispatchable when a response happens.
pub fn new_notify_query(
Expand All @@ -1591,20 +1612,6 @@ impl<T: Config> Pallet<T> {
Self::do_new_query(responder, Some(notify), timeout, match_querier)
}

/// Attempt to remove and return the response of query with ID `query_id`.
///
/// Returns `None` if the response is not (yet) available.
pub fn take_response(query_id: QueryId) -> Option<(Response, T::BlockNumber)> {
if let Some(QueryStatus::Ready { response, at }) = Queries::<T>::get(query_id) {
let response = response.try_into().ok()?;
Queries::<T>::remove(query_id);
Self::deposit_event(Event::ResponseTaken { query_id });
Some((response, at))
} else {
None
}
}

/// Note that a particular destination to whom we would like to send a message is unknown
/// and queue it for version discovery.
fn note_unknown_version(dest: &MultiLocation) {
Expand Down
3 changes: 2 additions & 1 deletion xcm/pallet-xcm/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ pub mod pallet_test_notifier {
use frame_system::pallet_prelude::*;
use sp_runtime::DispatchResult;
use xcm::latest::prelude::*;
use xcm_executor::traits::QueryHandler;

#[pallet::pallet]
pub struct Pallet<T>(_);
Expand Down Expand Up @@ -85,7 +86,7 @@ pub mod pallet_test_notifier {
let id = who
.using_encoded(|mut d| <[u8; 32]>::decode(&mut d))
.map_err(|_| Error::<T>::BadAccountFormat)?;
let qid = crate::Pallet::<T>::new_query(
let qid = <crate::Pallet<T> as QueryHandler>::new_query(
Junction::AccountId32 { network: None, id },
100u32.into(),
querier,
Expand Down
8 changes: 5 additions & 3 deletions xcm/pallet-xcm/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ use sp_runtime::traits::{AccountIdConversion, BlakeTwo256, Hash};
use xcm::{latest::QueryResponseInfo, prelude::*};
use xcm_builder::AllowKnownQueryResponses;
use xcm_executor::{
traits::{Properties, ShouldExecute},
traits::{Properties, QueryHandler, QueryResponseStatus, ShouldExecute},
XcmExecutor,
};

Expand Down Expand Up @@ -170,7 +170,8 @@ fn report_outcome_works() {
})
);

let response = Some((Response::ExecutionResult(None), 1));
let response =
QueryResponseStatus::Ready { response: Response::ExecutionResult(None), at: 1 };
assert_eq!(XcmPallet::take_response(0), response);
});
}
Expand Down Expand Up @@ -270,7 +271,8 @@ fn custom_querier_works() {
})
);

let response = Some((Response::ExecutionResult(None), 1));
let response =
QueryResponseStatus::Ready { response: Response::ExecutionResult(None), at: 1 };
assert_eq!(XcmPallet::take_response(0), response);
});
}
Expand Down
3 changes: 2 additions & 1 deletion xcm/xcm-builder/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,8 @@ polkadot-test-runtime = { path = "../../runtime/test-runtime" }
default = ["std"]
runtime-benchmarks = [
"frame-support/runtime-benchmarks",
"frame-system/runtime-benchmarks"
"frame-system/runtime-benchmarks",
"xcm-executor/runtime-benchmarks",
]
std = [
"log/std",
Expand Down
8 changes: 6 additions & 2 deletions xcm/xcm-builder/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,9 @@ pub mod test_utils;

mod location_conversion;
pub use location_conversion::{
Account32Hash, AccountId32Aliases, AccountKey20Aliases, ChildParachainConvertsVia,
GlobalConsensusParachainConvertsFor, ParentIsPreset, SiblingParachainConvertsVia,
Account32Hash, AccountId32Aliases, AccountKey20Aliases, AliasesIntoAccountId32,
ChildParachainConvertsVia, GlobalConsensusParachainConvertsFor, ParentIsPreset,
SiblingParachainConvertsVia,
};

mod origin_conversion;
Expand Down Expand Up @@ -95,3 +96,6 @@ pub use universal_exports::{
ExporterFor, HaulBlob, HaulBlobError, HaulBlobExporter, NetworkExportTable,
SovereignPaidRemoteExporter, UnpaidLocalExporter, UnpaidRemoteExporter,
};

mod pay;
pub use pay::{FixedLocation, LocatableAssetId, PayAccountId32OnChainOverXcm, PayOverXcm};
20 changes: 20 additions & 0 deletions xcm/xcm-builder/src/location_conversion.rs
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,26 @@ impl<Network: Get<Option<NetworkId>>, AccountId: From<[u8; 32]> + Into<[u8; 32]>
}
}

/// Conversion implementation which converts from a `[u8; 32]`-based `AccountId` into a
/// `MultiLocation` consisting solely of a `AccountId32` junction with a fixed value for its
/// network (provided by `Network`) and the `AccountId`'s `[u8; 32]` datum for the `id`.
pub struct AliasesIntoAccountId32<Network, AccountId>(PhantomData<(Network, AccountId)>);
impl<'a, Network: Get<Option<NetworkId>>, AccountId: Clone + Into<[u8; 32]> + Clone>
Convert<&'a AccountId, MultiLocation> for AliasesIntoAccountId32<Network, AccountId>
{
fn convert(who: &AccountId) -> Result<MultiLocation, &'a AccountId> {
Ok(AccountId32 { network: Network::get(), id: who.clone().into() }.into())
}
}

impl<Network: Get<Option<NetworkId>>, AccountId: Into<[u8; 32]> + Clone>
Convert<AccountId, MultiLocation> for AliasesIntoAccountId32<Network, AccountId>
{
fn convert(who: AccountId) -> Result<MultiLocation, AccountId> {
Ok(AccountId32 { network: Network::get(), id: who.into() }.into())
}
}

pub struct AccountKey20Aliases<Network, AccountId>(PhantomData<(Network, AccountId)>);
impl<Network: Get<Option<NetworkId>>, AccountId: From<[u8; 20]> + Into<[u8; 20]> + Clone>
Convert<MultiLocation, AccountId> for AccountKey20Aliases<Network, AccountId>
Expand Down
Loading