Eliminate redundant duplicate auth and matching room check.

Signed-off-by: Jason Volk <jason@zemos.net>
This commit is contained in:
Jason Volk
2025-08-28 01:41:13 +00:00
parent 9db3e35f41
commit 4b66911886
2 changed files with 43 additions and 55 deletions

View File

@@ -60,9 +60,12 @@ pub(super) async fn fetch_state(
v.insert(pdu.event_id().to_owned());
},
| hash_map::Entry::Occupied(_) => {
return Err!(Database(
"State event's type and state_key combination exists multiple times.",
));
return Err!(Request(InvalidParam(
"State event's type and state_key ({:?},{:?}) exists multiple times.",
pdu.event_type(),
pdu.state_key()
.expect("all state events have state_key"),
)));
},
}
}

View File

@@ -1,13 +1,14 @@
use std::collections::{HashMap, hash_map};
use futures::{StreamExt, TryFutureExt};
use ruma::{
CanonicalJsonObject, CanonicalJsonValue, EventId, RoomId, RoomVersionId, ServerName,
events::{StateEventType, TimelineEventType},
events::TimelineEventType,
};
use tuwunel_core::{
Err, Result, debug, debug_info, err, implement,
matrix::{Event, PduEvent, event::TypeExt, room_version},
state_res, trace, warn,
ref_at, state_res, trace,
utils::{future::TryExtExt, stream::IterStream},
warn,
};
use super::check_room_id;
@@ -89,67 +90,51 @@ pub(super) async fn handle_outlier_pdu(
debug!("Checking based on auth events");
let room_rules = room_version::rules(room_version)?;
let is_create = *event.kind() == TimelineEventType::RoomCreate;
let is_hydra = room_rules
.authorization
.room_create_event_id_as_room_id;
let is_hydra = !room_rules
.event_format
.allow_room_create_in_auth_events;
let hydra_create_id = (is_hydra && !is_create).then_some(event.room_id().as_event_id()?);
let auth_event_ids = event
let not_create = *event.kind() != TimelineEventType::RoomCreate;
let hydra_create_id = (not_create && is_hydra)
.then(|| event.room_id().as_event_id().ok())
.flatten();
let auth_events: Vec<_> = event
.auth_events()
.map(ToOwned::to_owned)
.chain(hydra_create_id.into_iter());
.chain(hydra_create_id.as_deref().into_iter())
.stream()
.filter_map(|auth_event_id| {
self.event_fetch(auth_event_id)
.inspect_err(move |e| warn!("Missing auth_event {auth_event_id}: {e}"))
.ok()
})
.map(|auth_event| {
let event_type = auth_event.event_type();
let state_key = auth_event
.state_key()
.expect("all auth events have state_key");
// Build map of auth events
let mut auth_events = HashMap::with_capacity(event.auth_events().count().saturating_add(1));
for id in auth_event_ids {
let Ok(auth_event) = self.services.timeline.get_pdu(&id).await else {
warn!("Could not find auth event {id}");
continue;
};
check_room_id(room_id, &auth_event)?;
match auth_events.entry((
auth_event.kind.to_string().into(),
auth_event
.state_key
.clone()
.expect("all auth events have state keys"),
)) {
| hash_map::Entry::Vacant(v) => {
v.insert(auth_event);
},
| hash_map::Entry::Occupied(_) => {
return Err!(Request(InvalidParam(
"Auth event's type and state_key combination exists multiple times.",
)));
},
}
}
// The original create event must be in the auth events
if !matches!(
auth_events.get(&(StateEventType::RoomCreate, String::new().into())),
Some(_) | None
) {
return Err!(Request(InvalidParam("Incoming event refers to wrong create event.")));
}
(event_type.with_state_key(state_key), auth_event)
})
.collect()
.await;
state_res::auth_check(
&room_rules,
&event,
&async |event_id| self.event_fetch(&event_id).await,
&async |event_type, state_key| {
let target = event_type.with_state_key(state_key);
auth_events
.get(&event_type.with_state_key(state_key.as_str()))
.map(ToOwned::to_owned)
.iter()
.find(|(type_state_key, _)| *type_state_key == target)
.map(ref_at!(1))
.cloned()
.ok_or_else(|| err!(Request(NotFound("state not found"))))
},
)
.await
.map_err(|e| err!(Request(Forbidden("Auth check failed: {e:?}"))))?;
trace!("Validation successful.");
.inspect_ok(|()| trace!("Validation successful."))
.await?;
// 7. Persist the event as an outlier.
self.services