Skip to content
mod.rs 38.5 KiB
Newer Older
// Copyright (C) Parity Technologies (UK) Ltd.
// This file is part of Polkadot.

// Polkadot is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// Polkadot is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with Polkadot.  If not, see <http://www.gnu.org/licenses/>.

use crate::{
	mock::*, pallet::SupportedVersion, AssetTraps, Config, CurrentMigration, Error,
	ExecuteControllerWeightInfo, LatestVersionedLocation, Pallet, Queries, QueryStatus,
	VersionDiscoveryQueue, VersionMigrationStage, VersionNotifiers, VersionNotifyTargets,
	WeightInfo,
};
use frame_support::{
	assert_err_ignore_postinfo, assert_noop, assert_ok,
	traits::{Currency, Hooks},
	weights::Weight,
use polkadot_parachain_primitives::primitives::Id as ParaId;
use sp_runtime::traits::{AccountIdConversion, BlakeTwo256, Hash};
Gavin Wood's avatar
Gavin Wood committed
use xcm::{latest::QueryResponseInfo, prelude::*};
use xcm_builder::AllowKnownQueryResponses;
use xcm_executor::{
	traits::{Properties, QueryHandler, QueryResponseStatus, ShouldExecute},

const ALICE: AccountId = AccountId::new([0u8; 32]);
const BOB: AccountId = AccountId::new([1u8; 32]);
const INITIAL_BALANCE: u128 = 100;
const SEND_AMOUNT: u128 = 10;
#[test]
fn report_outcome_notify_works() {
	let balances = vec![
		(ALICE, INITIAL_BALANCE),
		(ParaId::from(OTHER_PARA_ID).into_account_truncating(), INITIAL_BALANCE),
Francisco Aguirre's avatar
Francisco Aguirre committed
	let sender: Location = AccountId32 { network: None, id: ALICE.into() }.into();
	let mut message = Xcm(vec![TransferAsset {
		assets: (Here, SEND_AMOUNT).into(),
		beneficiary: sender.clone(),
	}]);
	let call = pallet_test_notifier::Call::notification_received {
		query_id: 0,
		response: Default::default(),
	};
	let notify = RuntimeCall::TestNotifier(call);
	new_test_ext_with_balances(balances).execute_with(|| {
Gavin Wood's avatar
Gavin Wood committed
		XcmPallet::report_outcome_notify(
			&mut message,
			Parachain(OTHER_PARA_ID).into_location(),
Gavin Wood's avatar
Gavin Wood committed
			notify,
			100,
		)
		.unwrap();
Gavin Wood's avatar
Gavin Wood committed
				SetAppendix(Xcm(vec![ReportError(QueryResponseInfo {
					destination: Parent.into(),
Gavin Wood's avatar
Gavin Wood committed
					max_weight: Weight::from_parts(1_000_000, 1_000_000),
				})])),
				TransferAsset { assets: (Here, SEND_AMOUNT).into(), beneficiary: sender },
Francisco Aguirre's avatar
Francisco Aguirre committed
		let querier: Location = Here.into();
Francisco Aguirre's avatar
Francisco Aguirre committed
			responder: Location::from(Parachain(OTHER_PARA_ID)).into(),
Francisco Aguirre's avatar
Francisco Aguirre committed
			maybe_match_querier: Some(querier.clone().into()),
		};
		assert_eq!(crate::Queries::<Test>::iter().collect::<Vec<_>>(), vec![(0, status)]);

Gavin Wood's avatar
Gavin Wood committed
		let message = Xcm(vec![QueryResponse {
			query_id: 0,
			response: Response::ExecutionResult(None),
			max_weight: Weight::from_parts(1_000_000, 1_000_000),
			querier: Some(querier),
		}]);
Francisco Aguirre's avatar
Francisco Aguirre committed
		let mut hash = fake_message_hash(&message);
		let r = XcmExecutor::<XcmConfig>::prepare_and_execute(
Gavin Wood's avatar
Gavin Wood committed
			message,
Francisco Aguirre's avatar
Francisco Aguirre committed
			&mut hash,
Gavin Wood's avatar
Gavin Wood committed
			Weight::from_parts(1_000_000_000, 1_000_000_000),
Francisco Aguirre's avatar
Francisco Aguirre committed
			Weight::zero(),
Francisco Aguirre's avatar
Francisco Aguirre committed
		assert_eq!(r, Outcome::Complete { used: Weight::from_parts(1_000, 1_000) });
				RuntimeEvent::TestNotifier(pallet_test_notifier::Event::ResponseReceived(
					Response::ExecutionResult(None),
				RuntimeEvent::XcmPallet(crate::Event::Notified {
					query_id: 0,
			]
		);
		assert_eq!(crate::Queries::<Test>::iter().collect::<Vec<_>>(), vec![]);
	});
}

#[test]
fn report_outcome_works() {
	let balances = vec![
		(ALICE, INITIAL_BALANCE),
		(ParaId::from(OTHER_PARA_ID).into_account_truncating(), INITIAL_BALANCE),
Francisco Aguirre's avatar
Francisco Aguirre committed
	let sender: Location = AccountId32 { network: None, id: ALICE.into() }.into();
	let mut message = Xcm(vec![TransferAsset {
		assets: (Here, SEND_AMOUNT).into(),
		beneficiary: sender.clone(),
	}]);
	new_test_ext_with_balances(balances).execute_with(|| {
		XcmPallet::report_outcome(&mut message, Parachain(OTHER_PARA_ID).into_location(), 100)
			.unwrap();
Gavin Wood's avatar
Gavin Wood committed
				SetAppendix(Xcm(vec![ReportError(QueryResponseInfo {
					destination: Parent.into(),
Gavin Wood's avatar
Gavin Wood committed
					max_weight: Weight::zero(),
				})])),
				TransferAsset { assets: (Here, SEND_AMOUNT).into(), beneficiary: sender },
Francisco Aguirre's avatar
Francisco Aguirre committed
		let querier: Location = Here.into();
Francisco Aguirre's avatar
Francisco Aguirre committed
			responder: Location::from(Parachain(OTHER_PARA_ID)).into(),
Francisco Aguirre's avatar
Francisco Aguirre committed
			maybe_match_querier: Some(querier.clone().into()),
		};
		assert_eq!(crate::Queries::<Test>::iter().collect::<Vec<_>>(), vec![(0, status)]);

Gavin Wood's avatar
Gavin Wood committed
		let message = Xcm(vec![QueryResponse {
			query_id: 0,
			response: Response::ExecutionResult(None),
			max_weight: Weight::zero(),
			querier: Some(querier),
		}]);
Francisco Aguirre's avatar
Francisco Aguirre committed
		let mut hash = fake_message_hash(&message);
		let r = XcmExecutor::<XcmConfig>::prepare_and_execute(
Gavin Wood's avatar
Gavin Wood committed
			message,
Francisco Aguirre's avatar
Francisco Aguirre committed
			&mut hash,
Gavin Wood's avatar
Gavin Wood committed
			Weight::from_parts(1_000_000_000, 1_000_000_000),
Francisco Aguirre's avatar
Francisco Aguirre committed
			Weight::zero(),
Francisco Aguirre's avatar
Francisco Aguirre committed
		assert_eq!(r, Outcome::Complete { used: Weight::from_parts(1_000, 1_000) });
Gavin Wood's avatar
Gavin Wood committed
		assert_eq!(
			last_event(),
			RuntimeEvent::XcmPallet(crate::Event::ResponseReady {
				query_id: 0,
				response: Response::ExecutionResult(None),
			})
Gavin Wood's avatar
Gavin Wood committed
		);

		let response =
			QueryResponseStatus::Ready { response: Response::ExecutionResult(None), at: 1 };
Gavin Wood's avatar
Gavin Wood committed
		assert_eq!(XcmPallet::take_response(0), response);
	});
}

#[test]
fn custom_querier_works() {
	let balances = vec![
		(ALICE, INITIAL_BALANCE),
		(ParaId::from(OTHER_PARA_ID).into_account_truncating(), INITIAL_BALANCE),
Gavin Wood's avatar
Gavin Wood committed
	];
	new_test_ext_with_balances(balances).execute_with(|| {
Francisco Aguirre's avatar
Francisco Aguirre committed
		let querier: Location = (Parent, AccountId32 { network: None, id: ALICE.into() }).into();
Gavin Wood's avatar
Gavin Wood committed

Francisco Aguirre's avatar
Francisco Aguirre committed
		let r = TestNotifier::prepare_new_query(RuntimeOrigin::signed(ALICE), querier.clone());
Gavin Wood's avatar
Gavin Wood committed
		assert_eq!(r, Ok(()));
		let status = QueryStatus::Pending {
Francisco Aguirre's avatar
Francisco Aguirre committed
			responder: Location::from(AccountId32 { network: None, id: ALICE.into() }).into(),
Loading full blame...