Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

When messages pallet is halted, relay shall not submit messages delivery/confirmation transactions #1289

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
11 changes: 10 additions & 1 deletion modules/messages/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1113,7 +1113,11 @@ mod tests {
REGULAR_PAYLOAD, TEST_LANE_ID, TEST_RELAYER_A, TEST_RELAYER_B,
};
use bp_messages::{UnrewardedRelayer, UnrewardedRelayersState};
use frame_support::{assert_noop, assert_ok, storage::generator::StorageMap, weights::Weight};
use frame_support::{
assert_noop, assert_ok,
storage::generator::{StorageMap, StorageValue},
weights::Weight,
};
use frame_system::{EventRecord, Pallet as System, Phase};
use sp_runtime::DispatchError;

Expand Down Expand Up @@ -2276,6 +2280,11 @@ mod tests {

#[test]
fn storage_keys_computed_properly() {
assert_eq!(
PalletOperatingMode::<TestRuntime>::storage_value_final_key().to_vec(),
bp_messages::storage_keys::operating_mode_key("Messages").0,
);

assert_eq!(
OutboundMessages::<TestRuntime>::storage_map_final_key(MessageKey {
lane_id: TEST_LANE_ID,
Expand Down
26 changes: 26 additions & 0 deletions primitives/messages/src/storage_keys.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@

//! Storage keys of bridge messages pallet.

/// Name of the `OPERATING_MODE_VALUE_NAME` storage value.
pub const OPERATING_MODE_VALUE_NAME: &str = "PalletOperatingMode";
/// Name of the `OutboundMessages` storage map.
pub const OUTBOUND_MESSAGES_MAP_NAME: &str = "OutboundMessages";
/// Name of the `OutboundLanes` storage map.
Expand All @@ -29,6 +31,17 @@ use codec::Encode;
use frame_support::Blake2_128Concat;
use sp_core::storage::StorageKey;

/// Storage key of the `PalletOperatingMode` value in the runtime storage.
pub fn operating_mode_key(pallet_prefix: &str) -> StorageKey {
StorageKey(
bp_runtime::storage_value_final_key(
pallet_prefix.as_bytes(),
OPERATING_MODE_VALUE_NAME.as_bytes(),
)
.to_vec(),
)
}

/// Storage key of the outbound message in the runtime storage.
pub fn message_key(pallet_prefix: &str, lane: &LaneId, nonce: MessageNonce) -> StorageKey {
bp_runtime::storage_map_final_key::<Blake2_128Concat>(
Expand Down Expand Up @@ -61,6 +74,19 @@ mod tests {
use super::*;
use hex_literal::hex;

#[test]
fn operating_mode_key_computed_properly() {
// If this test fails, then something has been changed in module storage that is possibly
// breaking all existing message relays.
let storage_key = operating_mode_key("BridgeMessages").0;
assert_eq!(
storage_key,
hex!("dd16c784ebd3390a9bc0357c7511ed010f4cf0917788d791142ff6c1f216e7b3").to_vec(),
"Unexpected storage key: {}",
hex::encode(&storage_key),
);
}

#[test]
fn storage_message_key_computed_properly() {
// If this test fails, then something has been changed in module storage that is breaking
Expand Down
30 changes: 28 additions & 2 deletions relays/lib-substrate-relay/src/messages_source.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@ use crate::{

use async_trait::async_trait;
use bp_messages::{
storage_keys::outbound_lane_data_key, LaneId, MessageNonce, OutboundLaneData,
UnrewardedRelayersState,
storage_keys::{operating_mode_key, outbound_lane_data_key},
LaneId, MessageNonce, OperatingMode, OutboundLaneData, UnrewardedRelayersState,
};
use bridge_runtime_common::messages::{
source::FromBridgedChainMessagesDeliveryProof, target::FromBridgedChainMessagesProof,
Expand Down Expand Up @@ -99,6 +99,11 @@ impl<P: SubstrateMessageLane> SubstrateMessagesSource<P> {
)
.await
}

/// Ensure that the messages pallet at source chain is active.
async fn ensure_pallet_active(&self) -> Result<(), SubstrateError> {
ensure_messages_pallet_active::<P::SourceChain, P::TargetChain>(&self.client).await
}
}

impl<P: SubstrateMessageLane> Clone for SubstrateMessagesSource<P> {
Expand Down Expand Up @@ -132,6 +137,8 @@ where
// we can't continue to deliver confirmations if source node is out of sync, because
// it may have already received confirmations that we're going to deliver
self.client.ensure_synced().await?;
// we can't relay confirmations if messages pallet at source chain is halted
self.ensure_pallet_active().await?;

read_client_state::<
_,
Expand Down Expand Up @@ -292,6 +299,25 @@ where
}
}

/// Ensure that the messages pallet at source chain is active.
pub(crate) async fn ensure_messages_pallet_active<AtChain, WithChain>(
client: &Client<AtChain>,
) -> Result<(), SubstrateError>
where
AtChain: ChainWithMessages,
WithChain: ChainWithMessages,
{
let operating_mode = client
.storage_value(operating_mode_key(WithChain::WITH_CHAIN_MESSAGES_PALLET_NAME), None)
.await?;
let is_halted = operating_mode == Some(OperatingMode::Halted);
if is_halted {
Err(SubstrateError::BridgePalletIsHalted)
} else {
Ok(())
}
}

/// Make messages delivery proof transaction from given proof.
fn make_messages_delivery_proof_transaction<P: SubstrateMessageLane>(
spec_version: u32,
Expand Down
9 changes: 8 additions & 1 deletion relays/lib-substrate-relay/src/messages_target.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
use crate::{
messages_lane::{MessageLaneAdapter, ReceiveMessagesProofCallBuilder, SubstrateMessageLane},
messages_metrics::StandaloneMessagesMetrics,
messages_source::{read_client_state, SubstrateMessagesProof},
messages_source::{ensure_messages_pallet_active, read_client_state, SubstrateMessagesProof},
on_demand_headers::OnDemandHeadersRelay,
TransactionParams,
};
Expand Down Expand Up @@ -100,6 +100,11 @@ impl<P: SubstrateMessageLane> SubstrateMessagesTarget<P> {
)
.await
}

/// Ensure that the messages pallet at target chain is active.
async fn ensure_pallet_active(&self) -> Result<(), SubstrateError> {
ensure_messages_pallet_active::<P::TargetChain, P::SourceChain>(&self.client).await
}
}

impl<P: SubstrateMessageLane> Clone for SubstrateMessagesTarget<P> {
Expand Down Expand Up @@ -136,6 +141,8 @@ where
// we can't continue to deliver messages if target node is out of sync, because
// it may have already received (some of) messages that we're going to deliver
self.client.ensure_synced().await?;
// we can't relay messages if messages pallet at target chain is halted
self.ensure_pallet_active().await?;

read_client_state::<
_,
Expand Down