-
Notifications
You must be signed in to change notification settings - Fork 254
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
Reshare Megolm session after the other party unwedges #3604
Conversation
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #3604 +/- ##
=======================================
Coverage 84.17% 84.18%
=======================================
Files 255 255
Lines 26515 26530 +15
=======================================
+ Hits 22319 22334 +15
Misses 4196 4196 ☔ View full report in Codecov by Sentry. |
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.
Quite the clever implementation, nice. I left some smaller nits we should address before we merge.
@@ -69,7 +69,7 @@ const ROTATION_MESSAGES: u64 = 100; | |||
pub(crate) enum ShareState { | |||
NotShared, | |||
SharedButChangedSenderKey, | |||
Shared(u32), | |||
Shared(u32, u32), |
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.
This could take some docs, a single u32 could be figured out relatively easily, two of them double the confusion. It probably makes sense to convert the enum variant from a tuple variant to one with named fields, i.e.:
Shared {
megolm_index: u32,
wedging_foo: u32,
}
// we use the session. If we don't have their device, this | ||
// means that we haven't tried to send them any Megolm sessions | ||
// yet, so we don't need to worry about it. | ||
if let Some(device) = store.get_device_from_curve_key(sender, sender_key).await? { |
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.
This section is clustered together as well, please add some whitespace to make this easier to read.
d.into_iter().filter(|d| match outbound.is_shared_with(d) { | ||
ShareState::NotShared => true, | ||
ShareState::Shared(_msg_index, olm_wedging_index) => { | ||
// If the recipient device's Olm wedging index is |
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.
This seems to be wrapped at a really small width, we wrap at 80 chars, cargo fmt
will do this automatically for you if the lines are too long.
.await?; | ||
let mut changes = | ||
Changes { sessions: vec![result.session.clone()], ..Default::default() }; | ||
// Any new Olm session will bump the Olm wedging index for the |
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.
This seems to be also wrapped manually, though it doesn't look as comical as the other doc comment, wouldn't hurt to let cargo fmt
format this as well.
// yet, so we don't need to worry about it. | ||
if let Some(device) = store.get_device_from_curve_key(sender, sender_key).await? { | ||
let mut read_only_device = device.inner; | ||
read_only_device.olm_wedging_index += 1; |
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.
Technically this can panic, what do you think about using our SequenceNumber
type for this. Not that it's terribly important but since we have such a type, seems like we could just use it for correctness sake:
matrix-rust-sdk/crates/matrix-sdk-crypto/src/store/caches.rs
Lines 191 to 229 in 3be84a5
/// A numeric type that can represent an infinite ordered sequence. | |
/// | |
/// It uses wrapping arithmetic to make sure we never run out of numbers. (2**64 | |
/// should be enough for anyone, but it's easy enough just to make it wrap.) | |
// | |
/// Internally it uses a *signed* counter so that we can compare values via a | |
/// subtraction. For example, suppose we've just overflowed from i64::MAX to | |
/// i64::MIN. (i64::MAX.wrapping_sub(i64::MIN)) is -1, which tells us that | |
/// i64::MAX comes before i64::MIN in the sequence. | |
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)] | |
pub(crate) struct SequenceNumber(i64); | |
impl Display for SequenceNumber { | |
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { | |
self.0.fmt(f) | |
} | |
} | |
impl PartialOrd for SequenceNumber { | |
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> { | |
Some(self.0.wrapping_sub(other.0).cmp(&0)) | |
} | |
} | |
impl Ord for SequenceNumber { | |
fn cmp(&self, other: &Self) -> std::cmp::Ordering { | |
self.0.wrapping_sub(other.0).cmp(&0) | |
} | |
} | |
impl SequenceNumber { | |
fn increment(&mut self) { | |
self.0 = self.0.wrapping_add(1) | |
} | |
fn previous(&self) -> Self { | |
Self(self.0.wrapping_sub(1)) | |
} | |
} |
You would need to derive Serialize
and Deserialize
for it with the transparent
attribute, but that's about it.
I think I've addressed all the review comments |
@@ -70,7 +71,7 @@ const ROTATION_MESSAGES: u64 = 100; | |||
pub(crate) enum ShareState { | |||
NotShared, | |||
SharedButChangedSenderKey, | |||
Shared(u32), | |||
Shared { message_index: u32, olm_wedging_index: SequenceNumber }, |
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.
This still isn't documented.
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.
Sorry, I misunderstood your original comment and thought that switching to named fields would avoid the need for documentation. I've added docs, and while I was there, added docs for the rest of the enum too.
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.
Nice, thanks for adding the docs.
Fixes element-hq/element-meta#2389
For each recipient device, we keep an "Olm wedging index" that indicates (approximately) how many times they tried to unwedge the Olm session. When we share a Megolm session, we store the Olm wedging index. This allows us to tell whether the Olm session was unwedged since we shared the Megolm session, so that we know if we should re-share it.
We detect an attempt to unwedge the Olm session by checking if the Olm message that we decrypted is from a brand new Olm session. This is not entirely accurate, since this could happen, for example, if Alice and Bob create Olm sessions at the same time. This may result in some Megolm sessions being re-shared unnecessarily, but should not make a huge difference.