Skip to content
This repository has been archived by the owner on Nov 15, 2023. It is now read-only.

Clear Existing HRMP Channel Request When Force Opening #7389

Merged
merged 5 commits into from
Jun 21, 2023
Merged
Show file tree
Hide file tree
Changes from 4 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
2 changes: 1 addition & 1 deletion runtime/kusama/src/weights/runtime_parachains_hrmp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -269,7 +269,7 @@ impl<T: frame_system::Config> runtime_parachains::hrmp::WeightInfo for WeightInf
/// Proof Skipped: Hrmp HrmpIngressChannelsIndex (max_values: None, max_size: None, mode: Measured)
/// Storage: Hrmp HrmpAcceptedChannelRequestCount (r:1 w:1)
/// Proof Skipped: Hrmp HrmpAcceptedChannelRequestCount (max_values: None, max_size: None, mode: Measured)
fn force_open_hrmp_channel() -> Weight {
fn force_open_hrmp_channel(_c: bool, ) -> Weight {
// Proof Size summary in bytes:
// Measured: `350`
// Estimated: `6290`
Expand Down
31 changes: 25 additions & 6 deletions runtime/parachains/src/hrmp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ pub trait WeightInfo {
fn force_process_hrmp_close(c: u32) -> Weight;
fn hrmp_cancel_open_request(c: u32) -> Weight;
fn clean_open_channel_requests(c: u32) -> Weight;
fn force_open_hrmp_channel() -> Weight;
fn force_open_hrmp_channel(c: bool) -> Weight;
}

/// A weight info that is only suitable for testing.
Expand Down Expand Up @@ -90,7 +90,7 @@ impl WeightInfo for TestWeightInfo {
fn clean_open_channel_requests(_: u32) -> Weight {
Weight::MAX
}
fn force_open_hrmp_channel() -> Weight {
fn force_open_hrmp_channel(_: bool) -> Weight {
Weight::MAX
}
}
Expand Down Expand Up @@ -591,17 +591,29 @@ pub mod pallet {
/// Chain's configured limits.
///
/// Expected use is when one of the `ParaId`s involved in the channel is governed by the
/// Relay Chain, e.g. a common good parachain.
/// Relay Chain, e.g. a system parachain.
#[pallet::call_index(7)]
#[pallet::weight(<T as Config>::WeightInfo::force_open_hrmp_channel())]
#[pallet::weight(<T as Config>::WeightInfo::force_open_hrmp_channel(true))]
pub fn force_open_hrmp_channel(
origin: OriginFor<T>,
sender: ParaId,
recipient: ParaId,
max_capacity: u32,
max_message_size: u32,
) -> DispatchResult {
) -> DispatchResultWithPostInfo {
ensure_root(origin)?;

// Guard against a common footgun where someone makes a channel request to a system
// parachain and then makes a proposal to open the channel via governance, which fails
// because `init_open_channel` fails if there is an existing request. This check will
// clear an existing request such that `init_open_channel` should otherwise succeed.
let channel_id = HrmpChannelId { sender, recipient };
let cancel_request = HrmpOpenChannelRequests::<T>::get(&channel_id).is_some();
if cancel_request {
Self::cancel_open_request(sender, channel_id)?;
}

// Now we proceed with normal init/accept.
Self::init_open_channel(sender, recipient, max_capacity, max_message_size)?;
Self::accept_open_channel(recipient, sender)?;
Self::deposit_event(Event::HrmpChannelForceOpened(
Expand All @@ -610,7 +622,14 @@ pub mod pallet {
max_capacity,
max_message_size,
));
Ok(())

if cancel_request {
// We've used the default weight.
Ok(().into())
} else {
// This took the easy path and we can return some weight.
Ok(Some(<T as Config>::WeightInfo::force_open_hrmp_channel(false)).into())
joepetrowski marked this conversation as resolved.
Show resolved Hide resolved
}
}
}
}
Expand Down
28 changes: 26 additions & 2 deletions runtime/parachains/src/hrmp/benchmarking.rs
Original file line number Diff line number Diff line change
Expand Up @@ -301,6 +301,7 @@ frame_benchmarking::benchmarks! {

force_open_hrmp_channel {
let sender_id: ParaId = 1u32.into();
let sender_origin: crate::Origin = 1u32.into();
let recipient_id: ParaId = 2u32.into();

// make sure para is registered, and has enough balance.
Expand All @@ -315,9 +316,32 @@ frame_benchmarking::benchmarks! {
let capacity = Configuration::<T>::config().hrmp_channel_max_capacity;
let message_size = Configuration::<T>::config().hrmp_channel_max_message_size;

// make sure this channel doesn't exist
let c = [true, false];
let channel_id = HrmpChannelId { sender: sender_id, recipient: recipient_id };
assert!(HrmpOpenChannelRequests::<T>::get(&channel_id).is_none());
for case in c {
if case {
// this will consume more weight if a channel _request_ already exists, because it
// will need to clear the request.
assert_ok!(Hrmp::<T>::hrmp_init_open_channel(
sender_origin.clone().into(),
recipient_id,
capacity,
message_size
));
assert!(HrmpOpenChannelRequests::<T>::get(&channel_id).is_some());
} else {
if HrmpOpenChannelRequests::<T>::get(&channel_id).is_some() {
assert_ok!(Hrmp::<T>::hrmp_cancel_open_request(
sender_origin.clone().into(),
channel_id.clone(),
MAX_UNIQUE_CHANNELS,
));
}
assert!(HrmpOpenChannelRequests::<T>::get(&channel_id).is_none());
}
}

// but the _channel_ should not exist
assert!(HrmpChannels::<T>::get(&channel_id).is_none());
}: _(frame_system::Origin::<T>::Root, sender_id, recipient_id, capacity, message_size)
verify {
Expand Down
44 changes: 44 additions & 0 deletions runtime/parachains/src/hrmp/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,50 @@ fn force_open_channel_works() {
});
}

#[test]
fn force_open_channel_works_with_existing_request() {
let para_a = 1.into();
let para_a_origin: crate::Origin = 1.into();
let para_b = 3.into();

new_test_ext(GenesisConfigBuilder::default().build()).execute_with(|| {
// We need both A & B to be registered and live parachains.
register_parachain(para_a);
register_parachain(para_b);

// Request a channel from `a` to `b`.
run_to_block(3, Some(vec![2, 3]));
Hrmp::hrmp_init_open_channel(para_a_origin.into(), para_b, 2, 8).unwrap();
Hrmp::assert_storage_consistency_exhaustive();
assert!(System::events().iter().any(|record| record.event ==
MockEvent::Hrmp(Event::OpenChannelRequested(para_a, para_b, 2, 8))));

run_to_block(5, Some(vec![4, 5]));
// the request exists, but no channel.
assert!(HrmpOpenChannelRequests::<Test>::get(&HrmpChannelId {
sender: para_a,
recipient: para_b
})
.is_some());
assert!(!channel_exists(para_a, para_b));
// now force open it.
Hrmp::force_open_hrmp_channel(RuntimeOrigin::root(), para_a, para_b, 2, 8).unwrap();
Hrmp::assert_storage_consistency_exhaustive();
assert!(System::events().iter().any(|record| record.event ==
MockEvent::Hrmp(Event::HrmpChannelForceOpened(para_a, para_b, 2, 8))));

// Advance to a block 6, but without session change. That means that the channel has
// not been created yet.
run_to_block(6, None);
assert!(!channel_exists(para_a, para_b));
Hrmp::assert_storage_consistency_exhaustive();

// Now let the session change happen and thus open the channel.
run_to_block(8, Some(vec![8]));
assert!(channel_exists(para_a, para_b));
});
}

#[test]
fn close_channel_works() {
let para_a = 5.into();
Expand Down
2 changes: 1 addition & 1 deletion runtime/polkadot/src/weights/runtime_parachains_hrmp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -279,7 +279,7 @@ impl<T: frame_system::Config> runtime_parachains::hrmp::WeightInfo for WeightInf
/// Proof Skipped: Hrmp HrmpIngressChannelsIndex (max_values: None, max_size: None, mode: Measured)
/// Storage: Hrmp HrmpAcceptedChannelRequestCount (r:1 w:1)
/// Proof Skipped: Hrmp HrmpAcceptedChannelRequestCount (max_values: None, max_size: None, mode: Measured)
fn force_open_hrmp_channel() -> Weight {
fn force_open_hrmp_channel(_c: bool, ) -> Weight {
// Proof Size summary in bytes:
// Measured: `666`
// Estimated: `6606`
Expand Down
2 changes: 1 addition & 1 deletion runtime/rococo/src/weights/runtime_parachains_hrmp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -279,7 +279,7 @@ impl<T: frame_system::Config> runtime_parachains::hrmp::WeightInfo for WeightInf
/// Proof Skipped: Hrmp HrmpIngressChannelsIndex (max_values: None, max_size: None, mode: Measured)
/// Storage: Hrmp HrmpAcceptedChannelRequestCount (r:1 w:1)
/// Proof Skipped: Hrmp HrmpAcceptedChannelRequestCount (max_values: None, max_size: None, mode: Measured)
fn force_open_hrmp_channel() -> Weight {
fn force_open_hrmp_channel(_c: bool, ) -> Weight {
// Proof Size summary in bytes:
// Measured: `704`
// Estimated: `6644`
Expand Down
2 changes: 1 addition & 1 deletion runtime/westend/src/weights/runtime_parachains_hrmp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -269,7 +269,7 @@ impl<T: frame_system::Config> runtime_parachains::hrmp::WeightInfo for WeightInf
/// Proof Skipped: Hrmp HrmpIngressChannelsIndex (max_values: None, max_size: None, mode: Measured)
/// Storage: Hrmp HrmpAcceptedChannelRequestCount (r:1 w:1)
/// Proof Skipped: Hrmp HrmpAcceptedChannelRequestCount (max_values: None, max_size: None, mode: Measured)
fn force_open_hrmp_channel() -> Weight {
fn force_open_hrmp_channel(_c: bool, ) -> Weight {
// Proof Size summary in bytes:
// Measured: `307`
// Estimated: `6247`
Expand Down