......@@ -399,6 +399,41 @@ impl<T: Contains<Location>> ShouldExecute for AllowSubscriptionsFrom<T> {
}
}
/// Allows execution for the Relay Chain origin (represented as `Location::parent()`) if it is just
/// a straight `HrmpNewChannelOpenRequest`, `HrmpChannelAccepted`, or `HrmpChannelClosing`
/// instruction.
///
/// Note: This barrier fulfills safety recommendations for the mentioned instructions - see their
/// documentation.
pub struct AllowHrmpNotificationsFromRelayChain;
impl ShouldExecute for AllowHrmpNotificationsFromRelayChain {
fn should_execute<RuntimeCall>(
origin: &Location,
instructions: &mut [Instruction<RuntimeCall>],
_max_weight: Weight,
_properties: &mut Properties,
) -> Result<(), ProcessMessageError> {
log::trace!(
target: "xcm::barriers",
"AllowHrmpNotificationsFromRelayChain origin: {:?}, instructions: {:?}, max_weight: {:?}, properties: {:?}",
origin, instructions, _max_weight, _properties,
);
// accept only the Relay Chain
ensure!(matches!(origin.unpack(), (1, [])), ProcessMessageError::Unsupported);
// accept only HRMP notifications and nothing else
instructions
.matcher()
.assert_remaining_insts(1)?
.match_next_inst(|inst| match inst {
HrmpNewChannelOpenRequest { .. } |
HrmpChannelAccepted { .. } |
HrmpChannelClosing { .. } => Ok(()),
_ => Err(ProcessMessageError::BadFormat),
})?;
Ok(())
}
}
/// Deny executing the XCM if it matches any of the Deny filter regardless of anything else.
/// If it passes the Deny, and matches one of the Allow cases then it is let through.
pub struct DenyThenTry<Deny, Allow>(PhantomData<Deny>, PhantomData<Allow>)
......
......@@ -21,7 +21,6 @@
use frame_support::{
dispatch::{DispatchErrorWithPostInfo, WithPostDispatchInfo},
pallet_prelude::DispatchError,
parameter_types, BoundedVec,
};
use sp_std::boxed::Box;
use xcm::prelude::*;
......@@ -42,12 +41,8 @@ impl<T, Origin, RuntimeCall, Timeout> Controller<Origin, RuntimeCall, Timeout> f
/// Weight functions needed for [`ExecuteController`].
pub trait ExecuteControllerWeightInfo {
/// Weight for [`ExecuteController::execute_blob`]
fn execute_blob() -> Weight;
}
parameter_types! {
pub const MaxXcmEncodedSize: u32 = xcm::MAX_XCM_ENCODED_SIZE;
/// Weight for [`ExecuteController::execute`]
fn execute() -> Weight;
}
/// Execute an XCM locally, for a given origin.
......@@ -66,19 +61,19 @@ pub trait ExecuteController<Origin, RuntimeCall> {
/// # Parameters
///
/// - `origin`: the origin of the call.
/// - `msg`: the encoded XCM to be executed, should be decodable as a [`VersionedXcm`]
/// - `message`: the XCM program to be executed.
/// - `max_weight`: the maximum weight that can be consumed by the execution.
fn execute_blob(
fn execute(
origin: Origin,
message: BoundedVec<u8, MaxXcmEncodedSize>,
message: Box<VersionedXcm<RuntimeCall>>,
max_weight: Weight,
) -> Result<Weight, DispatchErrorWithPostInfo>;
}
/// Weight functions needed for [`SendController`].
pub trait SendControllerWeightInfo {
/// Weight for [`SendController::send_blob`]
fn send_blob() -> Weight;
/// Weight for [`SendController::send`]
fn send() -> Weight;
}
/// Send an XCM from a given origin.
......@@ -98,11 +93,11 @@ pub trait SendController<Origin> {
///
/// - `origin`: the origin of the call.
/// - `dest`: the destination of the message.
/// - `msg`: the encoded XCM to be sent, should be decodable as a [`VersionedXcm`]
fn send_blob(
/// - `msg`: the XCM to be sent.
fn send(
origin: Origin,
dest: Box<VersionedLocation>,
message: BoundedVec<u8, MaxXcmEncodedSize>,
message: Box<VersionedXcm<()>>,
) -> Result<XcmHash, DispatchError>;
}
......@@ -142,35 +137,35 @@ pub trait QueryController<Origin, Timeout>: QueryHandler {
impl<Origin, RuntimeCall> ExecuteController<Origin, RuntimeCall> for () {
type WeightInfo = ();
fn execute_blob(
fn execute(
_origin: Origin,
_message: BoundedVec<u8, MaxXcmEncodedSize>,
_message: Box<VersionedXcm<RuntimeCall>>,
_max_weight: Weight,
) -> Result<Weight, DispatchErrorWithPostInfo> {
Err(DispatchError::Other("ExecuteController::execute_blob not implemented")
Err(DispatchError::Other("ExecuteController::execute not implemented")
.with_weight(Weight::zero()))
}
}
impl ExecuteControllerWeightInfo for () {
fn execute_blob() -> Weight {
fn execute() -> Weight {
Weight::zero()
}
}
impl<Origin> SendController<Origin> for () {
type WeightInfo = ();
fn send_blob(
fn send(
_origin: Origin,
_dest: Box<VersionedLocation>,
_message: BoundedVec<u8, MaxXcmEncodedSize>,
_message: Box<VersionedXcm<()>>,
) -> Result<XcmHash, DispatchError> {
Ok(Default::default())
}
}
impl SendControllerWeightInfo for () {
fn send_blob() -> Weight {
fn send() -> Weight {
Weight::zero()
}
}
......
......@@ -35,15 +35,16 @@ pub use asset_conversion::{
mod barriers;
pub use barriers::{
AllowExplicitUnpaidExecutionFrom, AllowKnownQueryResponses, AllowSubscriptionsFrom,
AllowTopLevelPaidExecutionFrom, AllowUnpaidExecutionFrom, DenyReserveTransferToRelayChain,
DenyThenTry, IsChildSystemParachain, IsParentsOnly, IsSiblingSystemParachain,
RespectSuspension, TakeWeightCredit, TrailingSetTopicAsId, WithComputedOrigin,
AllowExplicitUnpaidExecutionFrom, AllowHrmpNotificationsFromRelayChain,
AllowKnownQueryResponses, AllowSubscriptionsFrom, AllowTopLevelPaidExecutionFrom,
AllowUnpaidExecutionFrom, DenyReserveTransferToRelayChain, DenyThenTry, IsChildSystemParachain,
IsParentsOnly, IsSiblingSystemParachain, RespectSuspension, TakeWeightCredit,
TrailingSetTopicAsId, WithComputedOrigin,
};
mod controller;
pub use controller::{
Controller, ExecuteController, ExecuteControllerWeightInfo, MaxXcmEncodedSize, QueryController,
Controller, ExecuteController, ExecuteControllerWeightInfo, QueryController,
QueryControllerWeightInfo, QueryHandler, SendController, SendControllerWeightInfo,
};
......@@ -119,7 +120,7 @@ mod process_xcm_message;
pub use process_xcm_message::ProcessXcmMessage;
mod routing;
pub use routing::{EnsureDelivery, WithTopicSource, WithUniqueTopic};
pub use routing::{EnsureDecodableXcm, EnsureDelivery, WithTopicSource, WithUniqueTopic};
mod transactional;
pub use transactional::FrameTransactionalProcessor;
......
......@@ -102,7 +102,12 @@ impl<
target: LOG_TARGET,
"XCM message execution error: {error:?}",
);
(required, Err(ProcessMessageError::Unsupported))
let error = match error {
xcm::latest::Error::ExceedsStackLimit => ProcessMessageError::StackLimitReached,
_ => ProcessMessageError::Unsupported,
};
(required, Err(error))
},
};
meter.consume(consumed);
......@@ -148,6 +153,45 @@ mod tests {
}
}
#[test]
fn process_message_exceeds_limits_fails() {
struct MockedExecutor;
impl ExecuteXcm<()> for MockedExecutor {
type Prepared = xcm_executor::WeighedMessage<()>;
fn prepare(
message: xcm::latest::Xcm<()>,
) -> core::result::Result<Self::Prepared, xcm::latest::Xcm<()>> {
Ok(xcm_executor::WeighedMessage::new(Weight::zero(), message))
}
fn execute(
_: impl Into<Location>,
_: Self::Prepared,
_: &mut XcmHash,
_: Weight,
) -> Outcome {
Outcome::Error { error: xcm::latest::Error::ExceedsStackLimit }
}
fn charge_fees(_location: impl Into<Location>, _fees: Assets) -> xcm::latest::Result {
unreachable!()
}
}
type Processor = ProcessXcmMessage<Junction, MockedExecutor, ()>;
let xcm = VersionedXcm::V4(xcm::latest::Xcm::<()>(vec![
xcm::latest::Instruction::<()>::ClearOrigin,
]));
assert_err!(
Processor::process_message(
&xcm.encode(),
ORIGIN,
&mut WeightMeter::new(),
&mut [0; 32]
),
ProcessMessageError::StackLimitReached,
);
}
#[test]
fn process_message_overweight_fails() {
for msg in [v3_xcm(true), v3_xcm(false), v3_xcm(false), v2_xcm(false)] {
......
......@@ -139,3 +139,37 @@ impl EnsureDelivery for Tuple {
(None, None)
}
}
/// A wrapper router that attempts to *encode* and *decode* passed XCM `message` to ensure that the
/// receiving side will be able to decode, at least with the same XCM version.
///
/// This is designed to be at the top-level of any routers which do the real delivery. While other
/// routers can manipulate the `message`, we cannot access the final XCM due to the generic
/// `Inner::Ticket`. Therefore, this router aims to validate at least the passed `message`.
///
/// NOTE: For use in mock runtimes which don't have the DMP/UMP/HRMP XCM validations.
pub struct EnsureDecodableXcm<Inner>(sp_std::marker::PhantomData<Inner>);
impl<Inner: SendXcm> SendXcm for EnsureDecodableXcm<Inner> {
type Ticket = Inner::Ticket;
fn validate(
destination: &mut Option<Location>,
message: &mut Option<Xcm<()>>,
) -> SendResult<Self::Ticket> {
if let Some(msg) = message {
let versioned_xcm = VersionedXcm::<()>::from(msg.clone());
if versioned_xcm.validate_xcm_nesting().is_err() {
log::error!(
target: "xcm::validate_xcm_nesting",
"EnsureDecodableXcm validate_xcm_nesting error for \nversioned_xcm: {versioned_xcm:?}\nbased on xcm: {msg:?}"
);
return Err(SendError::Transport("EnsureDecodableXcm validate_xcm_nesting error"))
}
}
Inner::validate(destination, message)
}
fn deliver(ticket: Self::Ticket) -> Result<XcmHash, SendError> {
Inner::deliver(ticket)
}
}
......@@ -315,56 +315,150 @@ fn allow_subscriptions_from_should_work() {
// allow only parent
AllowSubsFrom::set(vec![Location::parent()]);
let valid_xcm_1 = Xcm::<TestCall>(vec![SubscribeVersion {
query_id: 42,
max_response_weight: Weight::from_parts(5000, 5000),
}]);
let valid_xcm_2 = Xcm::<TestCall>(vec![UnsubscribeVersion]);
let invalid_xcm_1 = Xcm::<TestCall>(vec![
SetAppendix(Xcm(vec![])),
SubscribeVersion { query_id: 42, max_response_weight: Weight::from_parts(5000, 5000) },
]);
let invalid_xcm_2 = Xcm::<TestCall>(vec![
SubscribeVersion { query_id: 42, max_response_weight: Weight::from_parts(5000, 5000) },
SetTopic([0; 32]),
]);
let test_data = vec![
(
valid_xcm_1.clone(),
// closure for (xcm, origin) testing with `AllowSubscriptionsFrom`
let assert_should_execute = |mut xcm: Vec<Instruction<()>>, origin, expected_result| {
assert_eq!(
AllowSubscriptionsFrom::<IsInVec<AllowSubsFrom>>::should_execute(
&origin,
&mut xcm,
Weight::from_parts(10, 10),
&mut props(Weight::zero()),
),
expected_result
);
};
// invalid origin
assert_should_execute(
vec![SubscribeVersion {
query_id: Default::default(),
max_response_weight: Default::default(),
}],
Parachain(1).into_location(),
// not allowed origin
Err(ProcessMessageError::Unsupported),
),
(valid_xcm_1, Location::parent(), Ok(())),
(
valid_xcm_2.clone(),
);
assert_should_execute(
vec![UnsubscribeVersion],
Parachain(1).into_location(),
// not allowed origin
Err(ProcessMessageError::Unsupported),
),
(valid_xcm_2, Location::parent(), Ok(())),
(
invalid_xcm_1,
);
// invalid XCM (unexpected instruction before)
assert_should_execute(
vec![
SetAppendix(Xcm(vec![])),
SubscribeVersion {
query_id: Default::default(),
max_response_weight: Default::default(),
},
],
Location::parent(),
// invalid XCM
Err(ProcessMessageError::BadFormat),
),
(
invalid_xcm_2,
);
assert_should_execute(
vec![SetAppendix(Xcm(vec![])), UnsubscribeVersion],
Location::parent(),
// invalid XCM
Err(ProcessMessageError::BadFormat),
),
];
);
// invalid XCM (unexpected instruction after)
assert_should_execute(
vec![
SubscribeVersion {
query_id: Default::default(),
max_response_weight: Default::default(),
},
SetTopic([0; 32]),
],
Location::parent(),
Err(ProcessMessageError::BadFormat),
);
assert_should_execute(
vec![UnsubscribeVersion, SetTopic([0; 32])],
Location::parent(),
Err(ProcessMessageError::BadFormat),
);
// invalid XCM (unexpected instruction)
assert_should_execute(
vec![SetAppendix(Xcm(vec![]))],
Location::parent(),
Err(ProcessMessageError::BadFormat),
);
// ok
assert_should_execute(
vec![SubscribeVersion {
query_id: Default::default(),
max_response_weight: Default::default(),
}],
Location::parent(),
Ok(()),
);
assert_should_execute(vec![UnsubscribeVersion], Location::parent(), Ok(()));
}
for (mut message, origin, expected_result) in test_data {
let r = AllowSubscriptionsFrom::<IsInVec<AllowSubsFrom>>::should_execute(
#[test]
fn allow_hrmp_notifications_from_relay_chain_should_work() {
// closure for (xcm, origin) testing with `AllowHrmpNotificationsFromRelayChain`
let assert_should_execute = |mut xcm: Vec<Instruction<()>>, origin, expected_result| {
assert_eq!(
AllowHrmpNotificationsFromRelayChain::should_execute(
&origin,
message.inner_mut(),
&mut xcm,
Weight::from_parts(10, 10),
&mut props(Weight::zero()),
),
expected_result
);
};
// invalid origin
assert_should_execute(
vec![HrmpChannelAccepted { recipient: Default::default() }],
Location::new(1, [Parachain(1)]),
Err(ProcessMessageError::Unsupported),
);
// invalid XCM (unexpected instruction before)
assert_should_execute(
vec![SetAppendix(Xcm(vec![])), HrmpChannelAccepted { recipient: Default::default() }],
Location::parent(),
Err(ProcessMessageError::BadFormat),
);
// invalid XCM (unexpected instruction after)
assert_should_execute(
vec![HrmpChannelAccepted { recipient: Default::default() }, SetTopic([0; 32])],
Location::parent(),
Err(ProcessMessageError::BadFormat),
);
// invalid XCM (unexpected instruction)
assert_should_execute(
vec![SetAppendix(Xcm(vec![]))],
Location::parent(),
Err(ProcessMessageError::BadFormat),
);
// ok
assert_should_execute(
vec![HrmpChannelAccepted { recipient: Default::default() }],
Location::parent(),
Ok(()),
);
assert_should_execute(
vec![HrmpNewChannelOpenRequest {
max_capacity: Default::default(),
sender: Default::default(),
max_message_size: Default::default(),
}],
Location::parent(),
Ok(()),
);
assert_should_execute(
vec![HrmpChannelClosing {
recipient: Default::default(),
sender: Default::default(),
initiator: Default::default(),
}],
Location::parent(),
Ok(()),
);
assert_eq!(r, expected_result, "Failed for origin: {origin:?} and message: {message:?}");
}
}
......@@ -19,6 +19,7 @@
use crate::{
barriers::{AllowSubscriptionsFrom, RespectSuspension, TrailingSetTopicAsId},
test_utils::*,
EnsureDecodableXcm,
};
pub use crate::{
AliasForeignAccountId32, AllowExplicitUnpaidExecutionFrom, AllowKnownQueryResponses,
......@@ -165,8 +166,8 @@ pub fn set_exporter_override(
pub fn clear_exporter_override() {
EXPORTER_OVERRIDE.with(|x| x.replace(None));
}
pub struct TestMessageSender;
impl SendXcm for TestMessageSender {
pub struct TestMessageSenderImpl;
impl SendXcm for TestMessageSenderImpl {
type Ticket = (Location, Xcm<()>, XcmHash);
fn validate(
dest: &mut Option<Location>,
......@@ -183,6 +184,8 @@ impl SendXcm for TestMessageSender {
Ok(hash)
}
}
pub type TestMessageSender = EnsureDecodableXcm<TestMessageSenderImpl>;
pub struct TestMessageExporter;
impl ExportXcm for TestMessageExporter {
type Ticket = (NetworkId, u32, InteriorLocation, InteriorLocation, Xcm<()>, XcmHash);
......
......@@ -187,7 +187,7 @@ pub fn forward_id_for(original_id: &XcmHash) -> XcmHash {
/// end with the `SetTopic` instruction.
///
/// In the case that the message ends with a `SetTopic(T)` (as should be the case if the top-level
/// router is `EnsureUniqueTopic`), then the forwarding message (i.e. the one carrying the
/// router is `WithUniqueTopic`), then the forwarding message (i.e. the one carrying the
/// export instruction *to* the bridge in local consensus) will also end with a `SetTopic` whose
/// inner is `forward_id_for(T)`. If this is not the case then the onward message will not be given
/// the `SetTopic` afterword.
......@@ -254,7 +254,7 @@ impl<Bridges: ExporterFor, Router: SendXcm, UniversalLocation: Get<InteriorLocat
/// end with the `SetTopic` instruction.
///
/// In the case that the message ends with a `SetTopic(T)` (as should be the case if the top-level
/// router is `EnsureUniqueTopic`), then the forwarding message (i.e. the one carrying the
/// router is `WithUniqueTopic`), then the forwarding message (i.e. the one carrying the
/// export instruction *to* the bridge in local consensus) will also end with a `SetTopic` whose
/// inner is `forward_id_for(T)`. If this is not the case then the onward message will not be given
/// the `SetTopic` afterword.
......
......@@ -35,9 +35,9 @@ use staging_xcm_builder as xcm_builder;
use xcm_builder::{
AccountId32Aliases, AllowTopLevelPaidExecutionFrom, AllowUnpaidExecutionFrom,
ChildParachainAsNative, ChildParachainConvertsVia, ChildSystemParachainAsSuperuser,
FixedRateOfFungible, FixedWeightBounds, FungibleAdapter, IsChildSystemParachain, IsConcrete,
MintLocation, RespectSuspension, SignedAccountId32AsNative, SignedToAccountId32,
SovereignSignedViaLocation, TakeWeightCredit,
EnsureDecodableXcm, FixedRateOfFungible, FixedWeightBounds, FungibleAdapter,
IsChildSystemParachain, IsConcrete, MintLocation, RespectSuspension, SignedAccountId32AsNative,
SignedToAccountId32, SovereignSignedViaLocation, TakeWeightCredit,
};
pub type AccountId = AccountId32;
......@@ -68,6 +68,8 @@ impl SendXcm for TestSendXcm {
}
}
pub type TestXcmRouter = EnsureDecodableXcm<TestSendXcm>;
// copied from kusama constants
pub const UNITS: Balance = 1_000_000_000_000;
pub const CENTS: Balance = UNITS / 30_000;
......@@ -137,7 +139,7 @@ impl configuration::Config for Runtime {
parameter_types! {
pub const KsmLocation: Location = Location::here();
pub const KusamaNetwork: NetworkId = NetworkId::Kusama;
pub UniversalLocation: InteriorLocation = Here;
pub UniversalLocation: InteriorLocation = KusamaNetwork::get().into();
pub CheckAccount: (AccountId, MintLocation) = (XcmPallet::check_account(), MintLocation::Local);
}
......@@ -180,7 +182,7 @@ pub type TrustedTeleporters = (xcm_builder::Case<KusamaForAssetHub>,);
pub struct XcmConfig;
impl xcm_executor::Config for XcmConfig {
type RuntimeCall = RuntimeCall;
type XcmSender = TestSendXcm;
type XcmSender = TestXcmRouter;
type AssetTransactor = LocalAssetTransactor;
type OriginConverter = LocalOriginConverter;
type IsReserve = ();
......@@ -215,7 +217,7 @@ impl pallet_xcm::Config for Runtime {
type RuntimeEvent = RuntimeEvent;
type UniversalLocation = UniversalLocation;
type SendXcmOrigin = xcm_builder::EnsureXcmOrigin<RuntimeOrigin, LocalOriginToLocation>;
type XcmRouter = TestSendXcm;
type XcmRouter = TestXcmRouter;
// Anyone can execute XCM messages locally...
type ExecuteXcmOrigin = xcm_builder::EnsureXcmOrigin<RuntimeOrigin, LocalOriginToLocation>;
type XcmExecuteFilter = Nothing;
......
......@@ -182,6 +182,13 @@ impl<C> PreparedMessage for WeighedMessage<C> {
}
}
#[cfg(any(test, feature = "std"))]
impl<C> WeighedMessage<C> {
pub fn new(weight: Weight, message: Xcm<C>) -> Self {
Self(weight, message)
}
}
impl<Config: config::Config> ExecuteXcm<Config::RuntimeCall> for XcmExecutor<Config> {
type Prepared = WeighedMessage<Config::RuntimeCall>;
fn prepare(
......
......@@ -40,10 +40,10 @@ use polkadot_parachain_primitives::primitives::{
use xcm::{latest::prelude::*, VersionedXcm};
use xcm_builder::{
Account32Hash, AccountId32Aliases, AllowUnpaidExecutionFrom, ConvertedConcreteId,
EnsureXcmOrigin, FixedRateOfFungible, FixedWeightBounds, FrameTransactionalProcessor,
FungibleAdapter, IsConcrete, NativeAsset, NoChecking, NonFungiblesAdapter, ParentIsPreset,
SiblingParachainConvertsVia, SignedAccountId32AsNative, SignedToAccountId32,
SovereignSignedViaLocation,
EnsureDecodableXcm, EnsureXcmOrigin, FixedRateOfFungible, FixedWeightBounds,
FrameTransactionalProcessor, FungibleAdapter, IsConcrete, NativeAsset, NoChecking,
NonFungiblesAdapter, ParentIsPreset, SiblingParachainConvertsVia, SignedAccountId32AsNative,
SignedToAccountId32, SovereignSignedViaLocation,
};
use xcm_executor::{
traits::{ConvertLocation, JustTry},
......@@ -176,7 +176,7 @@ parameter_types! {
parameter_types! {
pub const KsmLocation: Location = Location::parent();
pub const RelayNetwork: NetworkId = NetworkId::Kusama;
pub UniversalLocation: InteriorLocation = Parachain(MsgQueue::parachain_id().into()).into();
pub UniversalLocation: InteriorLocation = [GlobalConsensus(RelayNetwork::get()), Parachain(MsgQueue::parachain_id().into())].into();
}
pub type LocationToAccountId = (
......@@ -212,7 +212,7 @@ pub type LocalAssetTransactor = (
>,
);
pub type XcmRouter = super::ParachainXcmRouter<MsgQueue>;
pub type XcmRouter = EnsureDecodableXcm<super::ParachainXcmRouter<MsgQueue>>;
pub type Barrier = AllowUnpaidExecutionFrom<Everything>;
parameter_types! {
......
......@@ -36,9 +36,9 @@ use xcm::latest::prelude::*;
use xcm_builder::{
Account32Hash, AccountId32Aliases, AllowUnpaidExecutionFrom, AsPrefixedGeneralIndex,
ChildParachainAsNative, ChildParachainConvertsVia, ChildSystemParachainAsSuperuser,
ConvertedConcreteId, FixedRateOfFungible, FixedWeightBounds, FrameTransactionalProcessor,
FungibleAdapter, IsConcrete, NoChecking, NonFungiblesAdapter, SignedAccountId32AsNative,
SignedToAccountId32, SovereignSignedViaLocation,
ConvertedConcreteId, EnsureDecodableXcm, FixedRateOfFungible, FixedWeightBounds,
FrameTransactionalProcessor, FungibleAdapter, IsConcrete, NoChecking, NonFungiblesAdapter,
SignedAccountId32AsNative, SignedToAccountId32, SovereignSignedViaLocation,
};
use xcm_executor::{traits::JustTry, Config, XcmExecutor};
......@@ -131,7 +131,7 @@ parameter_types! {
pub const TokenLocation: Location = Here.into_location();
pub RelayNetwork: NetworkId = ByGenesis([0; 32]);
pub const AnyNetwork: Option<NetworkId> = None;
pub UniversalLocation: InteriorLocation = Here;
pub UniversalLocation: InteriorLocation = RelayNetwork::get().into();
pub UnitWeightCost: u64 = 1_000;
}
......@@ -168,7 +168,7 @@ parameter_types! {
pub const MaxAssetsIntoHolding: u32 = 64;
}
pub type XcmRouter = super::RelayChainXcmRouter;
pub type XcmRouter = EnsureDecodableXcm<super::RelayChainXcmRouter>;
pub type Barrier = AllowUnpaidExecutionFrom<Everything>;
pub struct XcmConfig;
......
......@@ -101,7 +101,7 @@ parameter_types! {
parameter_types! {
pub const KsmLocation: Location = Location::parent();
pub const RelayNetwork: NetworkId = NetworkId::Kusama;
pub UniversalLocation: InteriorLocation = Parachain(MsgQueue::parachain_id().into()).into();
pub UniversalLocation: InteriorLocation = [GlobalConsensus(RelayNetwork::get()), Parachain(MsgQueue::parachain_id().into())].into();
}
pub type LocationToAccountId = (
......
......@@ -104,7 +104,7 @@ parameter_types! {
pub const TokenLocation: Location = Here.into_location();
pub const ThisNetwork: NetworkId = NetworkId::ByGenesis([0; 32]);
pub const AnyNetwork: Option<NetworkId> = None;
pub const UniversalLocation: InteriorLocation = Here;
pub UniversalLocation: InteriorLocation = ThisNetwork::get().into();
}
pub type SovereignAccountOf =
......
......@@ -21,7 +21,7 @@ requests = { memory = "2G", cpu = "1" }
[[relaychain.node_groups]]
name = "honest-validator"
count = 3
args = ["-lparachain=debug"]
args = ["-lparachain=debug,runtime::staking=debug"]
[[relaychain.node_groups]]
image = "{{MALUS_IMAGE}}"
......
title: Validator disabling strategy in runtime
doc:
- audience: Node Operator
description: |
On each committed offence (no matter slashable or not) the offending validator will be
disabled for a whole era.
- audience: Runtime Dev
description: |
The disabling strategy in staking pallet is no longer hardcoded but abstracted away via
`DisablingStrategy` trait. The trait contains a single function (make_disabling_decision) which
is called for each offence. The function makes a decision if (and which) validators should be
disabled. A default implementation is provided - `UpToLimitDisablingStrategy`. It
will be used on Kusama and Polkadot. In nutshell `UpToLimitDisablingStrategy`
disables offenders up to the configured threshold. Offending validators are not disabled for
offences in previous eras. The threshold is controlled via `DISABLING_LIMIT_FACTOR` (a generic
parameter of `UpToLimitDisablingStrategy`).
migrations:
db: []
runtime:
- reference: pallet-staking
description: |
Renames `OffendingValidators` storage item to `DisabledValidators` and changes its type from
`Vec<(u32, bool)>` to `Vec<u32>`.
crates:
- name: pallet-staking
\ No newline at end of file
......@@ -6,7 +6,7 @@ title: "pallet-xcm: add new extrinsic for asset transfers using explicit reserve
doc:
- audience: Runtime User
description: |
pallet-xcm has a new extrinsic `transfer_assets_using_type` for transferring
pallet-xcm has a new extrinsic `transfer_assets_using_type_and_then` for transferring
assets from local chain to destination chain using an explicit XCM transfer
types for transferring the assets and the fees:
- `TransferType::LocalReserve`: transfer assets to sovereign account of destination
......@@ -33,6 +33,13 @@ doc:
Same when transferring bridged assets back across the bridge, the local bridging
parachain must be used as the explicit reserve location.
The new method takes a `custom_xcm_on_dest` parameter allowing the caller to specify
what should happen to the transferred assets once they reach
the `dest` chain. The `custom_xcm_on_dest` parameter should contains the instructions
to execute on `dest` as a final step. Usually as simple as:
`Xcm(vec![DepositAsset { assets: Wild(AllCounted(assets.len())), beneficiary }])`,
but could be something more exotic like sending the `assets` even further.
crates:
- name: pallet-xcm
bump: minor
title: "Balances: add failsafe for consumer ref underflow"
doc:
- audience: Runtime Dev
description: |
Pallet balances now handles the case that historic accounts violate a invariant that they should have a consumer ref on `reserved > 0` balance.
This disallows such accounts from reaping and should prevent TI from getting messed up even more.
crates:
- name: pallet-balances
bump: patch
title: Adds ability to trigger tasks via unsigned transactions
doc:
- audience: Runtime Dev
description: |
This PR updates the `validate_unsigned` hook for `frame_system` to allow valid tasks
to be submitted as unsigned transactions. It also updates the task example to be able to
submit such transactions via an off-chain worker.
Note that `is_valid` call on a task MUST be cheap with minimal to no storage reads.
Else, it can make the blockchain vulnerable to DoS attacks.
Further, these tasks will be executed in a random order.
crates:
- name: frame-system
bump: patch
- name: pallet-example-tasks
bump: minor
title: "Bridge: make some headers submissions free"
doc:
- audience: Runtime Dev
description: |
Adds `FreeHeadersInterval` configuration constant to the `pallet_bridge_grandpa`.
Transactions that improve best known header by at least `FreeHeadersInterval` headers
are now free for the submitter. Additionally, we allow single free parachain header
update per every free relay chain header. Bridge signed extensions are adjusted
to support that new scheme. Bridge runtime APIs are extended to support that new
scheme. Bridge fees are decreased by ~98% because now they do not include cost of
finality submissions - we assume relayers will be submitting finality transactions
for free.
crates:
- name: bridge-runtime-common
bump: major
- name: bp-bridge-hub-cumulus
bump: patch
- name: bp-bridge-hub-kusama
bump: major
- name: bp-bridge-hub-polkadot
bump: major
- name: bp-bridge-hub-rococo
bump: major
- name: bp-bridge-hub-westend
bump: major
- name: pallet-bridge-grandpa
bump: major
- name: pallet-bridge-parachains
bump: major
- name: bp-parachains
bump: major
- name: bp-runtime
bump: major
- name: relay-substrate-client
bump: major
- name: bridge-hub-rococo-runtime
bump: major
- name: bridge-hub-westend-runtime
bump: major
- name: bridge-hub-test-utils
bump: minor