diff --git a/src/event_auth.rs b/src/event_auth.rs index f9c40259..dffc8065 100644 --- a/src/event_auth.rs +++ b/src/event_auth.rs @@ -34,19 +34,29 @@ pub fn auth_types_for_event(event: &StateEvent) -> Vec<(EventType, String)> { if event.kind() == EventType::RoomMember { if let Ok(content) = event.deserialize_content::() { 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 - auth_types.push((EventType::RoomMember, event.state_key().unwrap_or_default())); + // TODO what when we don't find a state_key + let key = (EventType::RoomMember, event.state_key().unwrap()); + if !auth_types.contains(&key) { + auth_types.push(key) + } if content.membership == MembershipState::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 } diff --git a/src/lib.rs b/src/lib.rs index a029c2c1..6e241900 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -62,12 +62,18 @@ impl StateResolution { room_id: &RoomId, room_version: &RoomVersionId, state_sets: &[StateMap], + // TODO remove or make this mut so we aren't cloning the whole thing + event_map: Option>, store: &dyn StateStore, // TODO actual error handling (`thiserror`??) ) -> Result { 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 let (clean, conflicting) = self.separate(&state_sets); @@ -78,21 +84,24 @@ impl StateResolution { tracing::debug!("computing {} conflicting events", conflicting.len()); // the set of auth events that are not common across server forks - let mut auth_diff = - self.get_auth_chain_diff(room_id, &state_sets, &mut event_map, store)?; + let mut auth_diff = self.get_auth_chain_diff(room_id, &state_sets, &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::>() + .into_iter() + .collect::>(); println!( - "AUTH DIFF {:?}", - auth_diff + "FULL CONF {:?}", + all_conflicted .iter() .map(ToString::to_string) .collect::>() ); - // 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()); // gather missing events for the event_map @@ -106,6 +115,7 @@ impl StateResolution { .collect::>(), ) .unwrap(); + // update event_map to include the fetched events event_map.extend( events @@ -137,6 +147,13 @@ impl StateResolution { .filter(|id| is_power_event(id, store)) .cloned() .collect::>(); + println!( + "POWER {:?}", + power_events + .iter() + .map(ToString::to_string) + .collect::>() + ); // 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( @@ -147,6 +164,14 @@ impl StateResolution { &all_conflicted, ); + println!( + "SRTD {:?}", + sorted_power_levels + .iter() + .map(ToString::to_string) + .collect::>() + ); + // sequentially auth check each event. let resolved = self.iterative_auth_check( room_id, @@ -157,6 +182,8 @@ impl StateResolution { store, )?; + println!("AUTHED {:?}", resolved.iter().collect::>()); + // 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. 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 let events_to_resolve = all_conflicted .iter() - .filter(|id| deduped_power_ev.contains(id)) + .filter(|id| !deduped_power_ev.contains(id)) .cloned() .collect::>(); + println!( + "LEFT {:?}", + events_to_resolve + .iter() + .map(ToString::to_string) + .collect::>() + ); + let power_event = resolved.get(&(EventType::RoomPowerLevels, "".into())); + println!("PL {:?}", power_event); + let sorted_left_events = 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::>() + ); + let mut resolved_state = self.iterative_auth_check( room_id, room_version, @@ -276,6 +321,7 @@ impl StateResolution { let mut event_to_pl = BTreeMap::new(); for (idx, event_id) in graph.keys().enumerate() { 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); @@ -287,6 +333,7 @@ impl StateResolution { } 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 pl = event_to_pl.get(event_id).unwrap(); // This return value is the key used for sorting events, @@ -510,6 +557,7 @@ impl StateResolution { let mainline_map = mainline .iter() + .rev() .enumerate() .map(|(idx, eid)| ((*eid).clone(), idx)) .collect::>(); @@ -553,6 +601,7 @@ impl StateResolution { mainline_map: &EventMap, store: &dyn StateStore, ) -> usize { + let mut count = 0; while let Some(sort_ev) = event { if let Some(id) = sort_ev.event_id() { if let Some(depth) = mainline_map.get(id) { @@ -565,6 +614,18 @@ impl StateResolution { } else { vec![] }; + if count < 15 { + println!( + "{:?}", + auth_events + .iter() + .map(ToString::to_string) + .collect::>() + ); + } else { + panic!("{}", sort_ev.event_id().unwrap().to_string()) + } + count += 1; event = None; for aid in auth_events { @@ -591,8 +652,9 @@ impl StateResolution { while !state.is_empty() { // we just checked if it was empty so unwrap is fine 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() { if auth_diff.contains(&aid) { if !graph.contains_key(&aid) { diff --git a/tests/init.rs b/tests/init.rs index 6fc0c57c..07dd77d8 100644 --- a/tests/init.rs +++ b/tests/init.rs @@ -249,13 +249,14 @@ fn INITIAL_EDGES() -> Vec { .unwrap() } -pub struct TestStore(BTreeMap); +pub struct TestStore(RefCell>); #[allow(unused)] impl StateStore for TestStore { fn get_events(&self, events: &[EventId]) -> Result, String> { Ok(self .0 + .borrow() .iter() .filter(|e| events.contains(e.0)) .map(|(_, s)| s) @@ -265,6 +266,7 @@ impl StateStore for TestStore { fn get_event(&self, event_id: &EventId) -> Result { self.0 + .borrow() .get(event_id) .cloned() .ok_or(format!("{} not found", event_id.to_string())) @@ -345,13 +347,13 @@ fn do_check(events: &[StateEvent], edges: Vec>, expected_state_ids: let mut resolver = StateResolution::default(); // TODO what do we fill this with, everything ?? - let store = TestStore( + let store = TestStore(RefCell::new( INITIAL_EVENTS() .values() .chain(events) .map(|ev| (ev.event_id().unwrap().clone(), ev.clone())) .collect(), - ); + )); // This will be lexi_topo_sorted for resolution let mut graph = BTreeMap::new(); @@ -361,6 +363,7 @@ fn do_check(events: &[StateEvent], edges: Vec>, expected_state_ids: // create the DB of events that led up to this point // TODO maybe clean up some of these clones it is just tests but... for ev in INITIAL_EVENTS().values().chain(events) { + println!("{:?}", ev.event_id().unwrap().to_string()); graph.insert(ev.event_id().unwrap().clone(), vec![]); fake_event_map.insert(ev.event_id().unwrap().clone(), ev.clone()); } @@ -390,6 +393,7 @@ fn do_check(events: &[StateEvent], edges: Vec>, expected_state_ids: // TODO is this `key_fn` return correct ?? .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 event_id = fake_event.event_id().unwrap(); @@ -421,7 +425,8 @@ fn do_check(events: &[StateEvent], edges: Vec>, expected_state_ids: &room_id(), &RoomVersionId::version_1(), &state_sets, - &TestStore(event_map.clone()), + Some(event_map.clone()), + &store, ); match resolved { Ok(ResolutionResult::Resolved(state)) => state, @@ -432,20 +437,16 @@ fn do_check(events: &[StateEvent], edges: Vec>, expected_state_ids: let mut state_after = state_before.clone(); if fake_event.state_key().is_some() { let ty = fake_event.kind().clone(); + // we know there is a state_key unwrap OK let key = fake_event.state_key().unwrap().clone(); state_after.insert((ty, key), event_id.clone()); } - let auth_types = state_res::auth_types_for_event(fake_event) - .into_iter() - .collect::>(); - // println!( - // "{:?}", - // auth_types - // .iter() - // .map(|(t, id)| (t, id.to_string())) - // .collect::>() - // ); + let auth_types = state_res::auth_types_for_event(fake_event); + println!( + "AUTH TYPES {:?}", + auth_types.iter().map(|(t, id)| (t, id)).collect::>() + ); let mut auth_events = vec![]; for key in auth_types { @@ -469,7 +470,7 @@ fn do_check(events: &[StateEvent], edges: Vec>, expected_state_ids: ); // we have to update our store, an actual user of this lib would do this // 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); event_map.insert(event_id.clone(), event);