mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-19 14:41:02 +00:00
Flag for rejecting all outbound messages (#982)
* flag for rejecting all outbound messages * update weights * Revert "update weights" This reverts commit 992b866edc7c9fd97013cee9cd68b9d783f8681e. * Revert "flag for rejecting all outbound messages" This reverts commit d094964bb4f8800ab6978b9d4b12aade2f80d266. * OperatingMode * Update modules/messages/src/lib.rs Co-authored-by: Hernando Castano <HCastano@users.noreply.github.com> * Poke CI * RustFmt Co-authored-by: Hernando Castano <HCastano@users.noreply.github.com> Co-authored-by: Hernando Castano <hernando@hcastano.com>
This commit is contained in:
committed by
Bastian Köcher
parent
0b7f40a371
commit
41b65c28cf
@@ -50,7 +50,7 @@ use bp_messages::{
|
|||||||
source_chain::{LaneMessageVerifier, MessageDeliveryAndDispatchPayment, RelayersRewards, TargetHeaderChain},
|
source_chain::{LaneMessageVerifier, MessageDeliveryAndDispatchPayment, RelayersRewards, TargetHeaderChain},
|
||||||
target_chain::{DispatchMessage, MessageDispatch, ProvedLaneMessages, ProvedMessages, SourceHeaderChain},
|
target_chain::{DispatchMessage, MessageDispatch, ProvedLaneMessages, ProvedMessages, SourceHeaderChain},
|
||||||
total_unrewarded_messages, InboundLaneData, LaneId, MessageData, MessageKey, MessageNonce, MessagePayload,
|
total_unrewarded_messages, InboundLaneData, LaneId, MessageData, MessageKey, MessageNonce, MessagePayload,
|
||||||
OutboundLaneData, Parameter as MessagesParameter, UnrewardedRelayersState,
|
OperatingMode, OutboundLaneData, Parameter as MessagesParameter, UnrewardedRelayersState,
|
||||||
};
|
};
|
||||||
use bp_runtime::Size;
|
use bp_runtime::Size;
|
||||||
use codec::{Decode, Encode};
|
use codec::{Decode, Encode};
|
||||||
@@ -198,8 +198,10 @@ decl_storage! {
|
|||||||
/// runtime methods may still be used to do that (i.e. democracy::referendum to update halt
|
/// runtime methods may still be used to do that (i.e. democracy::referendum to update halt
|
||||||
/// flag directly or call the `halt_operations`).
|
/// flag directly or call the `halt_operations`).
|
||||||
pub PalletOwner get(fn module_owner): Option<T::AccountId>;
|
pub PalletOwner get(fn module_owner): Option<T::AccountId>;
|
||||||
/// If true, all pallet transactions are failed immediately.
|
/// The current operating mode of the pallet.
|
||||||
pub IsHalted get(fn is_halted) config(): bool;
|
///
|
||||||
|
/// Depending on the mode either all, some, or no transactions will be allowed.
|
||||||
|
pub PalletOperatingMode get(fn operating_mode) config(): OperatingMode;
|
||||||
/// Map of lane id => inbound lane data.
|
/// Map of lane id => inbound lane data.
|
||||||
pub InboundLanes: map hasher(blake2_128_concat) LaneId => InboundLaneData<T::InboundRelayer>;
|
pub InboundLanes: map hasher(blake2_128_concat) LaneId => InboundLaneData<T::InboundRelayer>;
|
||||||
/// Map of lane id => outbound lane data.
|
/// Map of lane id => outbound lane data.
|
||||||
@@ -266,19 +268,18 @@ decl_module! {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Halt or resume all pallet operations.
|
/// Halt or resume all/some pallet operations.
|
||||||
///
|
///
|
||||||
/// May only be called either by root, or by `PalletOwner`.
|
/// May only be called either by root, or by `PalletOwner`.
|
||||||
#[weight = (T::DbWeight::get().reads_writes(1, 1), DispatchClass::Operational)]
|
#[weight = (T::DbWeight::get().reads_writes(1, 1), DispatchClass::Operational)]
|
||||||
pub fn set_operational(origin, operational: bool) {
|
pub fn set_operating_mode(origin, operating_mode: OperatingMode) {
|
||||||
ensure_owner_or_root::<T, I>(origin)?;
|
ensure_owner_or_root::<T, I>(origin)?;
|
||||||
<IsHalted<I>>::put(operational);
|
<PalletOperatingMode<I>>::put(operating_mode);
|
||||||
|
log::info!(
|
||||||
if operational {
|
target: "runtime::bridge-messages",
|
||||||
log::info!(target: "runtime::bridge-messages", "Resuming pallet operations.");
|
"Setting messages pallet operating mode to {:?}.",
|
||||||
} else {
|
operating_mode,
|
||||||
log::warn!(target: "runtime::bridge-messages", "Stopping pallet operations.");
|
);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Update pallet parameter.
|
/// Update pallet parameter.
|
||||||
@@ -301,7 +302,7 @@ decl_module! {
|
|||||||
payload: T::OutboundPayload,
|
payload: T::OutboundPayload,
|
||||||
delivery_and_dispatch_fee: T::OutboundMessageFee,
|
delivery_and_dispatch_fee: T::OutboundMessageFee,
|
||||||
) -> DispatchResult {
|
) -> DispatchResult {
|
||||||
ensure_operational::<T, I>()?;
|
ensure_normal_operating_mode::<T, I>()?;
|
||||||
let submitter = origin.into().map_err(|_| BadOrigin)?;
|
let submitter = origin.into().map_err(|_| BadOrigin)?;
|
||||||
|
|
||||||
// let's first check if message can be delivered to target chain
|
// let's first check if message can be delivered to target chain
|
||||||
@@ -384,6 +385,7 @@ decl_module! {
|
|||||||
nonce: MessageNonce,
|
nonce: MessageNonce,
|
||||||
additional_fee: T::OutboundMessageFee,
|
additional_fee: T::OutboundMessageFee,
|
||||||
) -> DispatchResult {
|
) -> DispatchResult {
|
||||||
|
ensure_not_halted::<T, I>()?;
|
||||||
// if someone tries to pay for already-delivered message, we're rejecting this intention
|
// if someone tries to pay for already-delivered message, we're rejecting this intention
|
||||||
// (otherwise this additional fee will be locked forever in relayers fund)
|
// (otherwise this additional fee will be locked forever in relayers fund)
|
||||||
//
|
//
|
||||||
@@ -441,7 +443,7 @@ decl_module! {
|
|||||||
messages_count: u32,
|
messages_count: u32,
|
||||||
dispatch_weight: Weight,
|
dispatch_weight: Weight,
|
||||||
) -> DispatchResult {
|
) -> DispatchResult {
|
||||||
ensure_operational::<T, I>()?;
|
ensure_not_halted::<T, I>()?;
|
||||||
let _ = ensure_signed(origin)?;
|
let _ = ensure_signed(origin)?;
|
||||||
|
|
||||||
// reject transactions that are declaring too many messages
|
// reject transactions that are declaring too many messages
|
||||||
@@ -532,7 +534,7 @@ decl_module! {
|
|||||||
proof: MessagesDeliveryProofOf<T, I>,
|
proof: MessagesDeliveryProofOf<T, I>,
|
||||||
relayers_state: UnrewardedRelayersState,
|
relayers_state: UnrewardedRelayersState,
|
||||||
) -> DispatchResult {
|
) -> DispatchResult {
|
||||||
ensure_operational::<T, I>()?;
|
ensure_not_halted::<T, I>()?;
|
||||||
|
|
||||||
let confirmation_relayer = ensure_signed(origin)?;
|
let confirmation_relayer = ensure_signed(origin)?;
|
||||||
let (lane_id, lane_data) = T::TargetHeaderChain::verify_messages_delivery_proof(proof).map_err(|err| {
|
let (lane_id, lane_data) = T::TargetHeaderChain::verify_messages_delivery_proof(proof).map_err(|err| {
|
||||||
@@ -697,9 +699,18 @@ fn ensure_owner_or_root<T: Config<I>, I: Instance>(origin: T::Origin) -> Result<
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Ensure that the pallet is in operational mode (not halted).
|
/// Ensure that the pallet is in normal operational mode.
|
||||||
fn ensure_operational<T: Config<I>, I: Instance>() -> Result<(), Error<T, I>> {
|
fn ensure_normal_operating_mode<T: Config<I>, I: Instance>() -> Result<(), Error<T, I>> {
|
||||||
if IsHalted::<I>::get() {
|
if PalletOperatingMode::<I>::get() != OperatingMode::Normal {
|
||||||
|
Err(Error::<T, I>::Halted)
|
||||||
|
} else {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Ensure that the pallet is not halted.
|
||||||
|
fn ensure_not_halted<T: Config<I>, I: Instance>() -> Result<(), Error<T, I>> {
|
||||||
|
if PalletOperatingMode::<I>::get() == OperatingMode::Halted {
|
||||||
Err(Error::<T, I>::Halted)
|
Err(Error::<T, I>::Halted)
|
||||||
} else {
|
} else {
|
||||||
Ok(())
|
Ok(())
|
||||||
@@ -922,29 +933,41 @@ mod tests {
|
|||||||
|
|
||||||
assert_ok!(Pallet::<TestRuntime>::set_owner(Origin::root(), Some(1)));
|
assert_ok!(Pallet::<TestRuntime>::set_owner(Origin::root(), Some(1)));
|
||||||
assert_noop!(
|
assert_noop!(
|
||||||
Pallet::<TestRuntime>::set_operational(Origin::signed(2), false),
|
Pallet::<TestRuntime>::set_operating_mode(Origin::signed(2), OperatingMode::Halted),
|
||||||
DispatchError::BadOrigin,
|
DispatchError::BadOrigin,
|
||||||
);
|
);
|
||||||
assert_ok!(Pallet::<TestRuntime>::set_operational(Origin::root(), false));
|
assert_ok!(Pallet::<TestRuntime>::set_operating_mode(
|
||||||
|
Origin::root(),
|
||||||
|
OperatingMode::Halted
|
||||||
|
));
|
||||||
|
|
||||||
assert_ok!(Pallet::<TestRuntime>::set_owner(Origin::signed(1), None));
|
assert_ok!(Pallet::<TestRuntime>::set_owner(Origin::signed(1), None));
|
||||||
assert_noop!(
|
assert_noop!(
|
||||||
Pallet::<TestRuntime>::set_operational(Origin::signed(1), true),
|
Pallet::<TestRuntime>::set_operating_mode(Origin::signed(1), OperatingMode::Normal),
|
||||||
DispatchError::BadOrigin,
|
DispatchError::BadOrigin,
|
||||||
);
|
);
|
||||||
assert_noop!(
|
assert_noop!(
|
||||||
Pallet::<TestRuntime>::set_operational(Origin::signed(2), true),
|
Pallet::<TestRuntime>::set_operating_mode(Origin::signed(2), OperatingMode::Normal),
|
||||||
DispatchError::BadOrigin,
|
DispatchError::BadOrigin,
|
||||||
);
|
);
|
||||||
assert_ok!(Pallet::<TestRuntime>::set_operational(Origin::root(), true));
|
assert_ok!(Pallet::<TestRuntime>::set_operating_mode(
|
||||||
|
Origin::root(),
|
||||||
|
OperatingMode::Normal
|
||||||
|
));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn pallet_may_be_halted_by_root() {
|
fn pallet_may_be_halted_by_root() {
|
||||||
run_test(|| {
|
run_test(|| {
|
||||||
assert_ok!(Pallet::<TestRuntime>::set_operational(Origin::root(), false));
|
assert_ok!(Pallet::<TestRuntime>::set_operating_mode(
|
||||||
assert_ok!(Pallet::<TestRuntime>::set_operational(Origin::root(), true));
|
Origin::root(),
|
||||||
|
OperatingMode::Halted
|
||||||
|
));
|
||||||
|
assert_ok!(Pallet::<TestRuntime>::set_operating_mode(
|
||||||
|
Origin::root(),
|
||||||
|
OperatingMode::Normal
|
||||||
|
));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -953,21 +976,30 @@ mod tests {
|
|||||||
run_test(|| {
|
run_test(|| {
|
||||||
PalletOwner::<TestRuntime>::put(2);
|
PalletOwner::<TestRuntime>::put(2);
|
||||||
|
|
||||||
assert_ok!(Pallet::<TestRuntime>::set_operational(Origin::signed(2), false));
|
assert_ok!(Pallet::<TestRuntime>::set_operating_mode(
|
||||||
assert_ok!(Pallet::<TestRuntime>::set_operational(Origin::signed(2), true));
|
Origin::signed(2),
|
||||||
|
OperatingMode::Halted
|
||||||
|
));
|
||||||
|
assert_ok!(Pallet::<TestRuntime>::set_operating_mode(
|
||||||
|
Origin::signed(2),
|
||||||
|
OperatingMode::Normal
|
||||||
|
));
|
||||||
|
|
||||||
assert_noop!(
|
assert_noop!(
|
||||||
Pallet::<TestRuntime>::set_operational(Origin::signed(1), false),
|
Pallet::<TestRuntime>::set_operating_mode(Origin::signed(1), OperatingMode::Halted),
|
||||||
DispatchError::BadOrigin,
|
DispatchError::BadOrigin,
|
||||||
);
|
);
|
||||||
assert_noop!(
|
assert_noop!(
|
||||||
Pallet::<TestRuntime>::set_operational(Origin::signed(1), true),
|
Pallet::<TestRuntime>::set_operating_mode(Origin::signed(1), OperatingMode::Normal),
|
||||||
DispatchError::BadOrigin,
|
DispatchError::BadOrigin,
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_ok!(Pallet::<TestRuntime>::set_operational(Origin::signed(2), false));
|
assert_ok!(Pallet::<TestRuntime>::set_operating_mode(
|
||||||
|
Origin::signed(2),
|
||||||
|
OperatingMode::Halted
|
||||||
|
));
|
||||||
assert_noop!(
|
assert_noop!(
|
||||||
Pallet::<TestRuntime>::set_operational(Origin::signed(1), true),
|
Pallet::<TestRuntime>::set_operating_mode(Origin::signed(1), OperatingMode::Normal),
|
||||||
DispatchError::BadOrigin,
|
DispatchError::BadOrigin,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
@@ -1074,7 +1106,7 @@ mod tests {
|
|||||||
// send message first to be able to check that delivery_proof fails later
|
// send message first to be able to check that delivery_proof fails later
|
||||||
send_regular_message();
|
send_regular_message();
|
||||||
|
|
||||||
IsHalted::<DefaultInstance>::put(true);
|
PalletOperatingMode::<DefaultInstance>::put(OperatingMode::Halted);
|
||||||
|
|
||||||
assert_noop!(
|
assert_noop!(
|
||||||
Pallet::<TestRuntime>::send_message(
|
Pallet::<TestRuntime>::send_message(
|
||||||
@@ -1086,6 +1118,11 @@ mod tests {
|
|||||||
Error::<TestRuntime, DefaultInstance>::Halted,
|
Error::<TestRuntime, DefaultInstance>::Halted,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
assert_noop!(
|
||||||
|
Pallet::<TestRuntime>::increase_message_fee(Origin::signed(1), TEST_LANE_ID, 1, 1,),
|
||||||
|
Error::<TestRuntime, DefaultInstance>::Halted,
|
||||||
|
);
|
||||||
|
|
||||||
assert_noop!(
|
assert_noop!(
|
||||||
Pallet::<TestRuntime>::receive_messages_proof(
|
Pallet::<TestRuntime>::receive_messages_proof(
|
||||||
Origin::signed(1),
|
Origin::signed(1),
|
||||||
@@ -1114,6 +1151,53 @@ mod tests {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn pallet_rejects_new_messages_in_rejecting_outbound_messages_operating_mode() {
|
||||||
|
run_test(|| {
|
||||||
|
// send message first to be able to check that delivery_proof fails later
|
||||||
|
send_regular_message();
|
||||||
|
|
||||||
|
PalletOperatingMode::<DefaultInstance>::put(OperatingMode::RejectingOutboundMessages);
|
||||||
|
|
||||||
|
assert_noop!(
|
||||||
|
Pallet::<TestRuntime>::send_message(
|
||||||
|
Origin::signed(1),
|
||||||
|
TEST_LANE_ID,
|
||||||
|
REGULAR_PAYLOAD,
|
||||||
|
REGULAR_PAYLOAD.1,
|
||||||
|
),
|
||||||
|
Error::<TestRuntime, DefaultInstance>::Halted,
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_ok!(Pallet::<TestRuntime>::increase_message_fee(
|
||||||
|
Origin::signed(1),
|
||||||
|
TEST_LANE_ID,
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
));
|
||||||
|
|
||||||
|
assert_ok!(Pallet::<TestRuntime>::receive_messages_proof(
|
||||||
|
Origin::signed(1),
|
||||||
|
TEST_RELAYER_A,
|
||||||
|
Ok(vec![message(1, REGULAR_PAYLOAD)]).into(),
|
||||||
|
1,
|
||||||
|
REGULAR_PAYLOAD.1,
|
||||||
|
),);
|
||||||
|
|
||||||
|
assert_ok!(Pallet::<TestRuntime>::receive_messages_delivery_proof(
|
||||||
|
Origin::signed(1),
|
||||||
|
TestMessagesDeliveryProof(Ok((
|
||||||
|
TEST_LANE_ID,
|
||||||
|
InboundLaneData {
|
||||||
|
last_confirmed_nonce: 1,
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
))),
|
||||||
|
Default::default(),
|
||||||
|
));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn send_message_works() {
|
fn send_message_works() {
|
||||||
run_test(|| {
|
run_test(|| {
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ license = "GPL-3.0-or-later WITH Classpath-exception-2.0"
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] }
|
codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"] }
|
||||||
|
serde = { version = "1.0.101", optional = true, features = ["derive"] }
|
||||||
|
|
||||||
# Bridge dependencies
|
# Bridge dependencies
|
||||||
|
|
||||||
@@ -26,5 +27,6 @@ std = [
|
|||||||
"codec/std",
|
"codec/std",
|
||||||
"frame-support/std",
|
"frame-support/std",
|
||||||
"frame-system/std",
|
"frame-system/std",
|
||||||
|
"serde",
|
||||||
"sp-std/std"
|
"sp-std/std"
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -32,6 +32,30 @@ pub mod target_chain;
|
|||||||
// Weight is reexported to avoid additional frame-support dependencies in related crates.
|
// Weight is reexported to avoid additional frame-support dependencies in related crates.
|
||||||
pub use frame_support::weights::Weight;
|
pub use frame_support::weights::Weight;
|
||||||
|
|
||||||
|
/// Messages pallet operating mode.
|
||||||
|
#[derive(Encode, Decode, Clone, Copy, PartialEq, Eq, RuntimeDebug)]
|
||||||
|
#[cfg_attr(feature = "std", derive(serde::Serialize, serde::Deserialize))]
|
||||||
|
pub enum OperatingMode {
|
||||||
|
/// Normal mode, when all operations are allowed.
|
||||||
|
Normal,
|
||||||
|
/// The pallet is not accepting outbound messages. Inbound messages and receival proofs
|
||||||
|
/// are still accepted.
|
||||||
|
///
|
||||||
|
/// This mode may be used e.g. when bridged chain expects upgrade. Then to avoid dispatch
|
||||||
|
/// failures, the pallet owner may stop accepting new messages, while continuing to deliver
|
||||||
|
/// queued messages to the bridged chain. Once upgrade is completed, the mode may be switched
|
||||||
|
/// back to `Normal`.
|
||||||
|
RejectingOutboundMessages,
|
||||||
|
/// The pallet is halted. All operations (except operating mode change) are prohibited.
|
||||||
|
Halted,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for OperatingMode {
|
||||||
|
fn default() -> Self {
|
||||||
|
OperatingMode::Normal
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Messages pallet parameter.
|
/// Messages pallet parameter.
|
||||||
pub trait Parameter: frame_support::Parameter {
|
pub trait Parameter: frame_support::Parameter {
|
||||||
/// Save parameter value in the runtime storage.
|
/// Save parameter value in the runtime storage.
|
||||||
|
|||||||
Reference in New Issue
Block a user