-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Make HRMP advancement rule more restrictive #9086
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
Changes from all commits
408a035
e66c81d
fa4a7cc
ba143f4
48476b3
f082fc1
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -142,6 +142,14 @@ impl<Message: InboundMessage> InboundMessagesCollection<Message> { | |
| } | ||
| } | ||
|
|
||
| /// A struct containing some info about the expected size of the abridged inbound messages. | ||
| pub struct AbridgedInboundMessagesSizeInfo { | ||
| /// The max size of the full messages collection | ||
| pub max_full_messages_size: usize, | ||
| /// The max size of the first hashed message | ||
| pub first_hashed_msg_max_size: usize, | ||
| } | ||
|
|
||
| /// A compressed collection of inbound messages. | ||
| /// | ||
| /// The first messages in the collection (up to a limit) contain the full message data. | ||
|
|
@@ -161,29 +169,51 @@ impl<Message: InboundMessage> AbridgedInboundMessagesCollection<Message> { | |
| (&self.full_messages, &self.hashed_messages) | ||
| } | ||
|
|
||
| /// Check that the current collection contains as many full messages as possible. | ||
| /// Check that the current collection contains at least 1 full message if needed. | ||
| pub fn check_enough_messages_included_basic(&self, collection_name: &str) { | ||
| if self.hashed_messages.is_empty() { | ||
| return; | ||
| } | ||
|
|
||
| // Here we just check that there is at least 1 full message. | ||
| assert!( | ||
| self.full_messages.len() >= 1, | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. So the case that already the first message is too big can never happen, right?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Very good point ! With the current Polkadot and Kusama configs it won't happen. But with a misconfiguration it probably could. Anyway this check is only used for DMP and the problem there is that we don't know the max message size in order to do a proper check. This will be fixed when we migrate DMP to
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yea we can do it separate
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
If this would happen, we could never move forward. I see this not as an issue. Yes, could be a misconfiguration, but then you can not receive messages anymore. |
||
| "[{}] Advancement rule violation: full messages missing", | ||
| collection_name, | ||
| ); | ||
| } | ||
|
|
||
| /// Check that the current collection contains as many full messages as possible, taking into | ||
| /// consideration the collection constraints. | ||
| /// | ||
| /// The `AbridgedInboundMessagesCollection` is provided to the runtime by a collator. | ||
| /// A malicious collator can provide a collection that contains no full messages or fewer | ||
| /// full messages than possible, leading to censorship. | ||
| pub fn check_enough_messages_included(&self, collection_name: &str) { | ||
| if self.hashed_messages.is_empty() { | ||
| return; | ||
| pub fn check_enough_messages_included_advanced( | ||
| &self, | ||
| collection_name: &str, | ||
| size_info: AbridgedInboundMessagesSizeInfo, | ||
| ) { | ||
| // We should check that the collection contains as many full messages as possible | ||
| // without exceeding the max expected size. | ||
| let AbridgedInboundMessagesSizeInfo { max_full_messages_size, first_hashed_msg_max_size } = | ||
| size_info; | ||
|
|
||
| let mut full_messages_size = 0usize; | ||
| for msg in &self.full_messages { | ||
| full_messages_size = full_messages_size.saturating_add(msg.data().len()); | ||
| } | ||
|
|
||
| // Ideally, we should check that the collection contains as many full messages as possible | ||
| // without exceeding the max expected size. The worst case scenario is that were the first | ||
| // message that had to be hashed is a max size message. So in this case, the min expected | ||
| // size would be `max_expected_size - max_msg_size`. However, there are multiple issues: | ||
| // 1. The max message size config can change while we still have to process messages with | ||
| // the old max message size. | ||
| // 2. We can't access the max downward message size from the parachain runtime. | ||
| // | ||
| // So the safest approach is to check that there is at least 1 full message. | ||
| // The worst case scenario is that were the first message that had to be hashed | ||
| // is a max size message. | ||
| assert!( | ||
| self.full_messages.len() >= 1, | ||
| "[{}] Advancement rule violation: mandatory messages missing", | ||
| full_messages_size.saturating_add(first_hashed_msg_max_size) > max_full_messages_size, | ||
| "[{}] Advancement rule violation: full messages size smaller than expected. \ | ||
| full msgs size: {}, first hashed msg max size: {}, max full msgs size: {}", | ||
| collection_name, | ||
| full_messages_size, | ||
| first_hashed_msg_max_size, | ||
| max_full_messages_size | ||
| ); | ||
| } | ||
| } | ||
|
|
@@ -481,7 +511,7 @@ mod tests { | |
| } | ||
|
|
||
| #[test] | ||
| fn check_enough_messages_included_works() { | ||
| fn check_enough_messages_included_basic_works() { | ||
| let mut messages = AbridgedInboundHrmpMessages { | ||
| full_messages: vec![( | ||
| 1000.into(), | ||
|
|
@@ -493,13 +523,45 @@ mod tests { | |
| )], | ||
| }; | ||
|
|
||
| messages.check_enough_messages_included("Test"); | ||
| messages.check_enough_messages_included_basic("Test"); | ||
|
|
||
| messages.full_messages = vec![]; | ||
| let result = std::panic::catch_unwind(|| messages.check_enough_messages_included("Test")); | ||
| let result = | ||
| std::panic::catch_unwind(|| messages.check_enough_messages_included_basic("Test")); | ||
| assert!(result.is_err()); | ||
|
|
||
| messages.hashed_messages = vec![]; | ||
| messages.check_enough_messages_included("Test"); | ||
| messages.check_enough_messages_included_basic("Test"); | ||
| } | ||
|
|
||
| #[test] | ||
| fn check_enough_messages_included_advanced_works() { | ||
| let mixed_messages = AbridgedInboundHrmpMessages { | ||
| full_messages: vec![( | ||
| 1000.into(), | ||
| InboundHrmpMessage { sent_at: 0, data: vec![1; 50] }, | ||
| )], | ||
| hashed_messages: vec![( | ||
| 2000.into(), | ||
| HashedMessage { sent_at: 1, msg_hash: Default::default() }, | ||
| )], | ||
| }; | ||
| let result = std::panic::catch_unwind(|| { | ||
| mixed_messages.check_enough_messages_included_advanced( | ||
| "Test", | ||
| AbridgedInboundMessagesSizeInfo { | ||
| max_full_messages_size: 100, | ||
| first_hashed_msg_max_size: 50, | ||
| }, | ||
| ) | ||
| }); | ||
| assert!(result.is_err()); | ||
| mixed_messages.check_enough_messages_included_advanced( | ||
| "Test", | ||
| AbridgedInboundMessagesSizeInfo { | ||
| max_full_messages_size: 100, | ||
| first_hashed_msg_max_size: 51, | ||
| }, | ||
| ); | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,8 @@ | ||
| title: Make HRMP advancement rule more restrictive | ||
| doc: | ||
| - audience: Runtime Dev | ||
| description: |- | ||
| This PR improves `check_enough_messages_included()` and makes the advancement rule more restrictive for HRMP. | ||
| crates: | ||
| - name: cumulus-pallet-parachain-system | ||
| bump: major |
Uh oh!
There was an error while loading. Please reload this page.