-
Notifications
You must be signed in to change notification settings - Fork 78
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
Fix/gateway message processing #1991
base: main
Are you sure you want to change the base?
Conversation
@@ -202,9 +202,13 @@ pub mod pallet { | |||
fn service_message_queue(max_weight: Weight) -> Weight { | |||
let mut weight_used = Weight::zero(); | |||
|
|||
let mut processed_entries = Vec::new(); | |||
let mut nonces = MessageQueue::<T>::iter_keys().collect::<Vec<_>>(); | |||
nonces.sort(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since we are collecting the keys here, it also made sense to me to sort them, just in case. Please let me know if there are any objections to this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Although this new solution is more simple, I think there is a problem here:
MessageQueue::<T>::iter_keys().collect::<Vec<_>>();
It can collect many keys, making the block impossible to build.
I think we need a complex structure here that allow us to store them already organized
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It can collect many keys, making the block impossible to build.
Can you elaborate on this please?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How about limiting the number of keys that we collect via:
let mut nonces = MessageQueue::<T>::iter_keys().take(MAX_MESSAGES_PER_BLOCK).collect::<Vec<_>>();
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you elaborate on this please?
When you collect, the iterator will make one read per item, and could be a number of items that overpass the limit for the block weight capacity.
The take(MAX_MESSAGES_PER_BLOCK)
still does not work because could be left a message in the queue that ideally should be processed first.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure if exists some order structure available in substrate for this. If not, we should create some complex/annoying structure to organize the way the messages are stored.
But I'm not able to see a super simple way TBH. We can leave that fix for another PR to unlock this if we see it's not easy
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe there's a simpler solution that involves using the latest message nonce. I'll try something on a different branch.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Something similar to - #1992
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for all the fixed!
BTW, not sure if we should move this to the internal repo, to not forking both main
branches too much.
@@ -202,9 +202,13 @@ pub mod pallet { | |||
fn service_message_queue(max_weight: Weight) -> Weight { | |||
let mut weight_used = Weight::zero(); | |||
|
|||
let mut processed_entries = Vec::new(); | |||
let mut nonces = MessageQueue::<T>::iter_keys().collect::<Vec<_>>(); | |||
nonces.sort(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Although this new solution is more simple, I think there is a problem here:
MessageQueue::<T>::iter_keys().collect::<Vec<_>>();
It can collect many keys, making the block impossible to build.
I think we need a complex structure here that allow us to store them already organized
if res.is_ok() { | ||
TransactionOutcome::Commit(Ok::<(DispatchResult, Weight), DispatchError>(( | ||
res, weight, | ||
))) | ||
} else { | ||
TransactionOutcome::Rollback(Ok::<(DispatchResult, Weight), DispatchError>(( | ||
res, weight, | ||
))) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Super NIT. I think adding the returned type in the closure allows to remove the Ok<stuff>
here
with_transaction(|| -> DispatchResult {
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That won't work given:
pub fn with_transaction<T, E, F>(f: F) -> Result<T, E>
where
E: From<DispatchError>,
F: FnOnce() -> TransactionOutcome<Result<T, E>>, // this
{
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But given that we will always return LP_DEFENSIVE_WEIGHT
for both inbound/outbound, we can change this a bit. I'll ping you when done.
@@ -333,7 +334,11 @@ impl<T: Config> Pallet<T> { | |||
// we can return. | |||
None => return Ok(()), | |||
Some(stored_inbound_entry) => match stored_inbound_entry { | |||
InboundEntry::Message(message_entry) => message = Some(message_entry.message), | |||
InboundEntry::Message(message_entry) | |||
if message_entry.session_id == session_id => |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Question: If session_id
is different, should we remove the entry?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Question: If
session_id
is different, should we remove the entry?
We should not because then it's impossible to replay the message and funds are stuck on the EVM side. Keeping entries for an old session id can be made unstuck via execute_message_recovery
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
execute_message_recovery
will only increase the proof count for a specific router ID, we will still hit this logic and be unable to execute a message from an older session. Maybe we should extend execute_message_recovery
and either:
- set the session of a message entry to the current one;
- increase the proof count - current behavior;
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #1991 +/- ##
==========================================
+ Coverage 48.28% 48.36% +0.08%
==========================================
Files 183 183
Lines 13406 13398 -8
==========================================
+ Hits 6473 6480 +7
+ Misses 6933 6918 -15
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. |
Description
Various fixes for LP gateway-related logic.
Changes and Descriptions
LP Gateway
MessageProcessor
implementation transactional to ensure that storage changes are reverted on failure.LP Gateway Queue
MessageQueue
keys, order them, and iterate over them when servicing theMessageQueue
.Checklist: