Skip to content

Commit

Permalink
when messages pallet is halted, relay shall not submit messages deliv…
Browse files Browse the repository at this point in the history
…ery/confirmation transactions (paritytech#1289)
  • Loading branch information
svyatonik authored and serban300 committed Apr 10, 2024
1 parent 09eb029 commit 2fb4249
Show file tree
Hide file tree
Showing 4 changed files with 72 additions and 4 deletions.
11 changes: 10 additions & 1 deletion bridges/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 bridges/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 bridges/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 bridges/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

0 comments on commit 2fb4249

Please sign in to comment.