BUG: follows synapse until get_mainline_depth then it loops forever

This commit is contained in:
Devin R 2020-07-21 08:55:51 -04:00
parent d69e712dba
commit 2f443cf41a
3 changed files with 104 additions and 31 deletions

View File

@ -34,19 +34,29 @@ pub fn auth_types_for_event(event: &StateEvent) -> Vec<(EventType, String)> {
if event.kind() == EventType::RoomMember { if event.kind() == EventType::RoomMember {
if let Ok(content) = event.deserialize_content::<room::member::MemberEventContent>() { if let Ok(content) = event.deserialize_content::<room::member::MemberEventContent>() {
if [MembershipState::Join, MembershipState::Invite].contains(&content.membership) { if [MembershipState::Join, MembershipState::Invite].contains(&content.membership) {
auth_types.push((EventType::RoomJoinRules, "".into())) let key = (EventType::RoomJoinRules, "".into());
if !auth_types.contains(&key) {
auth_types.push(key)
}
} }
// TODO is None the same as "" for state_key, probably NOT // TODO what when we don't find a state_key
auth_types.push((EventType::RoomMember, event.state_key().unwrap_or_default())); let key = (EventType::RoomMember, event.state_key().unwrap());
if !auth_types.contains(&key) {
auth_types.push(key)
}
if content.membership == MembershipState::Invite { if content.membership == MembershipState::Invite {
if let Some(t_id) = content.third_party_invite { if let Some(t_id) = content.third_party_invite {
auth_types.push((EventType::RoomThirdPartyInvite, t_id.signed.token)) let key = (EventType::RoomThirdPartyInvite, t_id.signed.token);
if !auth_types.contains(&key) {
auth_types.push(key)
}
} }
} }
} }
} }
auth_types auth_types
} }

View File

@ -62,12 +62,18 @@ impl StateResolution {
room_id: &RoomId, room_id: &RoomId,
room_version: &RoomVersionId, room_version: &RoomVersionId,
state_sets: &[StateMap<EventId>], state_sets: &[StateMap<EventId>],
// TODO remove or make this mut so we aren't cloning the whole thing
event_map: Option<EventMap<StateEvent>>,
store: &dyn StateStore, store: &dyn StateStore,
// TODO actual error handling (`thiserror`??) // TODO actual error handling (`thiserror`??)
) -> Result<ResolutionResult, String> { ) -> Result<ResolutionResult, String> {
tracing::debug!("State resolution starting"); tracing::debug!("State resolution starting");
let mut event_map = EventMap::new(); let mut event_map = if let Some(ev_map) = event_map {
ev_map
} else {
EventMap::new()
};
// split non-conflicting and conflicting state // split non-conflicting and conflicting state
let (clean, conflicting) = self.separate(&state_sets); let (clean, conflicting) = self.separate(&state_sets);
@ -78,21 +84,24 @@ impl StateResolution {
tracing::debug!("computing {} conflicting events", conflicting.len()); tracing::debug!("computing {} conflicting events", conflicting.len());
// the set of auth events that are not common across server forks // the set of auth events that are not common across server forks
let mut auth_diff = let mut auth_diff = self.get_auth_chain_diff(room_id, &state_sets, &event_map, store)?;
self.get_auth_chain_diff(room_id, &state_sets, &mut event_map, store)?;
// add the auth_diff to conflicting now we have a full set of conflicting events
auth_diff.extend(conflicting.values().cloned().flatten());
let mut all_conflicted = auth_diff
.into_iter()
.collect::<BTreeSet<_>>()
.into_iter()
.collect::<Vec<_>>();
println!( println!(
"AUTH DIFF {:?}", "FULL CONF {:?}",
auth_diff all_conflicted
.iter() .iter()
.map(ToString::to_string) .map(ToString::to_string)
.collect::<Vec<_>>() .collect::<Vec<_>>()
); );
// add the auth_diff to conflicting now we have a full set of conflicting events
auth_diff.extend(conflicting.values().cloned().flatten());
let mut all_conflicted = auth_diff;
tracing::debug!("full conflicted set is {} events", all_conflicted.len()); tracing::debug!("full conflicted set is {} events", all_conflicted.len());
// gather missing events for the event_map // gather missing events for the event_map
@ -106,6 +115,7 @@ impl StateResolution {
.collect::<Vec<_>>(), .collect::<Vec<_>>(),
) )
.unwrap(); .unwrap();
// update event_map to include the fetched events // update event_map to include the fetched events
event_map.extend( event_map.extend(
events events
@ -137,6 +147,13 @@ impl StateResolution {
.filter(|id| is_power_event(id, store)) .filter(|id| is_power_event(id, store))
.cloned() .cloned()
.collect::<Vec<_>>(); .collect::<Vec<_>>();
println!(
"POWER {:?}",
power_events
.iter()
.map(ToString::to_string)
.collect::<Vec<_>>()
);
// sort the power events based on power_level/clock/event_id and outgoing/incoming edges // sort the power events based on power_level/clock/event_id and outgoing/incoming edges
let mut sorted_power_levels = self.reverse_topological_power_sort( let mut sorted_power_levels = self.reverse_topological_power_sort(
@ -147,6 +164,14 @@ impl StateResolution {
&all_conflicted, &all_conflicted,
); );
println!(
"SRTD {:?}",
sorted_power_levels
.iter()
.map(ToString::to_string)
.collect::<Vec<_>>()
);
// sequentially auth check each event. // sequentially auth check each event.
let resolved = self.iterative_auth_check( let resolved = self.iterative_auth_check(
room_id, room_id,
@ -157,6 +182,8 @@ impl StateResolution {
store, store,
)?; )?;
println!("AUTHED {:?}", resolved.iter().collect::<Vec<_>>());
// At this point the power_events have been resolved we now have to // At this point the power_events have been resolved we now have to
// sort the remaining events using the mainline of the resolved power level. // sort the remaining events using the mainline of the resolved power level.
sorted_power_levels.dedup(); sorted_power_levels.dedup();
@ -165,15 +192,33 @@ impl StateResolution {
// we have resolved the power events so remove them, I'm sure theres other reasons to do so // we have resolved the power events so remove them, I'm sure theres other reasons to do so
let events_to_resolve = all_conflicted let events_to_resolve = all_conflicted
.iter() .iter()
.filter(|id| deduped_power_ev.contains(id)) .filter(|id| !deduped_power_ev.contains(id))
.cloned() .cloned()
.collect::<Vec<_>>(); .collect::<Vec<_>>();
println!(
"LEFT {:?}",
events_to_resolve
.iter()
.map(ToString::to_string)
.collect::<Vec<_>>()
);
let power_event = resolved.get(&(EventType::RoomPowerLevels, "".into())); let power_event = resolved.get(&(EventType::RoomPowerLevels, "".into()));
println!("PL {:?}", power_event);
let sorted_left_events = let sorted_left_events =
self.mainline_sort(room_id, &events_to_resolve, power_event, &event_map, store); self.mainline_sort(room_id, &events_to_resolve, power_event, &event_map, store);
println!(
"SORTED LEFT {:?}",
events_to_resolve
.iter()
.map(ToString::to_string)
.collect::<Vec<_>>()
);
let mut resolved_state = self.iterative_auth_check( let mut resolved_state = self.iterative_auth_check(
room_id, room_id,
room_version, room_version,
@ -276,6 +321,7 @@ impl StateResolution {
let mut event_to_pl = BTreeMap::new(); let mut event_to_pl = BTreeMap::new();
for (idx, event_id) in graph.keys().enumerate() { for (idx, event_id) in graph.keys().enumerate() {
let pl = self.get_power_level_for_sender(room_id, &event_id, event_map, store); let pl = self.get_power_level_for_sender(room_id, &event_id, event_map, store);
println!("{}", pl);
event_to_pl.insert(event_id.clone(), pl); event_to_pl.insert(event_id.clone(), pl);
@ -287,6 +333,7 @@ impl StateResolution {
} }
self.lexicographical_topological_sort(&mut graph, |event_id| { self.lexicographical_topological_sort(&mut graph, |event_id| {
println!("{:?}", event_map.get(event_id).unwrap().origin_server_ts());
let ev = event_map.get(event_id).unwrap(); let ev = event_map.get(event_id).unwrap();
let pl = event_to_pl.get(event_id).unwrap(); let pl = event_to_pl.get(event_id).unwrap();
// This return value is the key used for sorting events, // This return value is the key used for sorting events,
@ -510,6 +557,7 @@ impl StateResolution {
let mainline_map = mainline let mainline_map = mainline
.iter() .iter()
.rev()
.enumerate() .enumerate()
.map(|(idx, eid)| ((*eid).clone(), idx)) .map(|(idx, eid)| ((*eid).clone(), idx))
.collect::<BTreeMap<_, _>>(); .collect::<BTreeMap<_, _>>();
@ -553,6 +601,7 @@ impl StateResolution {
mainline_map: &EventMap<usize>, mainline_map: &EventMap<usize>,
store: &dyn StateStore, store: &dyn StateStore,
) -> usize { ) -> usize {
let mut count = 0;
while let Some(sort_ev) = event { while let Some(sort_ev) = event {
if let Some(id) = sort_ev.event_id() { if let Some(id) = sort_ev.event_id() {
if let Some(depth) = mainline_map.get(id) { if let Some(depth) = mainline_map.get(id) {
@ -565,6 +614,18 @@ impl StateResolution {
} else { } else {
vec![] vec![]
}; };
if count < 15 {
println!(
"{:?}",
auth_events
.iter()
.map(ToString::to_string)
.collect::<Vec<_>>()
);
} else {
panic!("{}", sort_ev.event_id().unwrap().to_string())
}
count += 1;
event = None; event = None;
for aid in auth_events { for aid in auth_events {
@ -591,8 +652,9 @@ impl StateResolution {
while !state.is_empty() { while !state.is_empty() {
// we just checked if it was empty so unwrap is fine // we just checked if it was empty so unwrap is fine
let eid = state.pop().unwrap(); let eid = state.pop().unwrap();
graph.insert(eid.clone(), vec![]); graph.entry(eid.clone()).or_insert(vec![]);
// prefer the store to event as the store filters dedups the events
// otherwise it seems we can loop forever
for aid in store.auth_event_ids(room_id, &[eid.clone()]).unwrap() { for aid in store.auth_event_ids(room_id, &[eid.clone()]).unwrap() {
if auth_diff.contains(&aid) { if auth_diff.contains(&aid) {
if !graph.contains_key(&aid) { if !graph.contains_key(&aid) {

View File

@ -249,13 +249,14 @@ fn INITIAL_EDGES() -> Vec<EventId> {
.unwrap() .unwrap()
} }
pub struct TestStore(BTreeMap<EventId, StateEvent>); pub struct TestStore(RefCell<BTreeMap<EventId, StateEvent>>);
#[allow(unused)] #[allow(unused)]
impl StateStore for TestStore { impl StateStore for TestStore {
fn get_events(&self, events: &[EventId]) -> Result<Vec<StateEvent>, String> { fn get_events(&self, events: &[EventId]) -> Result<Vec<StateEvent>, String> {
Ok(self Ok(self
.0 .0
.borrow()
.iter() .iter()
.filter(|e| events.contains(e.0)) .filter(|e| events.contains(e.0))
.map(|(_, s)| s) .map(|(_, s)| s)
@ -265,6 +266,7 @@ impl StateStore for TestStore {
fn get_event(&self, event_id: &EventId) -> Result<StateEvent, String> { fn get_event(&self, event_id: &EventId) -> Result<StateEvent, String> {
self.0 self.0
.borrow()
.get(event_id) .get(event_id)
.cloned() .cloned()
.ok_or(format!("{} not found", event_id.to_string())) .ok_or(format!("{} not found", event_id.to_string()))
@ -345,13 +347,13 @@ fn do_check(events: &[StateEvent], edges: Vec<Vec<EventId>>, expected_state_ids:
let mut resolver = StateResolution::default(); let mut resolver = StateResolution::default();
// TODO what do we fill this with, everything ?? // TODO what do we fill this with, everything ??
let store = TestStore( let store = TestStore(RefCell::new(
INITIAL_EVENTS() INITIAL_EVENTS()
.values() .values()
.chain(events) .chain(events)
.map(|ev| (ev.event_id().unwrap().clone(), ev.clone())) .map(|ev| (ev.event_id().unwrap().clone(), ev.clone()))
.collect(), .collect(),
); ));
// This will be lexi_topo_sorted for resolution // This will be lexi_topo_sorted for resolution
let mut graph = BTreeMap::new(); let mut graph = BTreeMap::new();
@ -361,6 +363,7 @@ fn do_check(events: &[StateEvent], edges: Vec<Vec<EventId>>, expected_state_ids:
// create the DB of events that led up to this point // create the DB of events that led up to this point
// TODO maybe clean up some of these clones it is just tests but... // TODO maybe clean up some of these clones it is just tests but...
for ev in INITIAL_EVENTS().values().chain(events) { for ev in INITIAL_EVENTS().values().chain(events) {
println!("{:?}", ev.event_id().unwrap().to_string());
graph.insert(ev.event_id().unwrap().clone(), vec![]); graph.insert(ev.event_id().unwrap().clone(), vec![]);
fake_event_map.insert(ev.event_id().unwrap().clone(), ev.clone()); fake_event_map.insert(ev.event_id().unwrap().clone(), ev.clone());
} }
@ -390,6 +393,7 @@ fn do_check(events: &[StateEvent], edges: Vec<Vec<EventId>>, expected_state_ids:
// TODO is this `key_fn` return correct ?? // TODO is this `key_fn` return correct ??
.lexicographical_topological_sort(&graph, |id| (0, UNIX_EPOCH, Some(id.clone()))) .lexicographical_topological_sort(&graph, |id| (0, UNIX_EPOCH, Some(id.clone())))
{ {
println!("{}", node.to_string());
let fake_event = fake_event_map.get(&node).unwrap(); let fake_event = fake_event_map.get(&node).unwrap();
let event_id = fake_event.event_id().unwrap(); let event_id = fake_event.event_id().unwrap();
@ -421,7 +425,8 @@ fn do_check(events: &[StateEvent], edges: Vec<Vec<EventId>>, expected_state_ids:
&room_id(), &room_id(),
&RoomVersionId::version_1(), &RoomVersionId::version_1(),
&state_sets, &state_sets,
&TestStore(event_map.clone()), Some(event_map.clone()),
&store,
); );
match resolved { match resolved {
Ok(ResolutionResult::Resolved(state)) => state, Ok(ResolutionResult::Resolved(state)) => state,
@ -432,20 +437,16 @@ fn do_check(events: &[StateEvent], edges: Vec<Vec<EventId>>, expected_state_ids:
let mut state_after = state_before.clone(); let mut state_after = state_before.clone();
if fake_event.state_key().is_some() { if fake_event.state_key().is_some() {
let ty = fake_event.kind().clone(); let ty = fake_event.kind().clone();
// we know there is a state_key unwrap OK
let key = fake_event.state_key().unwrap().clone(); let key = fake_event.state_key().unwrap().clone();
state_after.insert((ty, key), event_id.clone()); state_after.insert((ty, key), event_id.clone());
} }
let auth_types = state_res::auth_types_for_event(fake_event) let auth_types = state_res::auth_types_for_event(fake_event);
.into_iter() println!(
.collect::<BTreeSet<_>>(); "AUTH TYPES {:?}",
// println!( auth_types.iter().map(|(t, id)| (t, id)).collect::<Vec<_>>()
// "{:?}", );
// auth_types
// .iter()
// .map(|(t, id)| (t, id.to_string()))
// .collect::<Vec<_>>()
// );
let mut auth_events = vec![]; let mut auth_events = vec![];
for key in auth_types { for key in auth_types {
@ -469,7 +470,7 @@ fn do_check(events: &[StateEvent], edges: Vec<Vec<EventId>>, expected_state_ids:
); );
// we have to update our store, an actual user of this lib would do this // we have to update our store, an actual user of this lib would do this
// with the result of the resolution> // with the result of the resolution>
// *store.0.borrow_mut().get_mut(ev_id).unwrap() = event.clone(); *store.0.borrow_mut().get_mut(ev_id).unwrap() = event.clone();
state_at_event.insert(node, state_after); state_at_event.insert(node, state_after);
event_map.insert(event_id.clone(), event); event_map.insert(event_id.clone(), event);