Integrate state-res and rename to ruma-state-res

This commit is contained in:
Jonas Platte 2021-05-08 00:32:27 +02:00
parent 6609829735
commit addc67051e
No known key found for this signature in database
GPG Key ID: 7D261D771D915378
15 changed files with 127 additions and 414 deletions

View File

@ -1,30 +0,0 @@
name: Rust Nightly
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
check:
name: Check
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions-rs/toolchain@v1
with:
toolchain: nightly
profile: minimal
override: true
components: rustfmt, clippy
- name: Check formatting
uses: actions-rs/cargo@v1
with:
command: fmt
args: -- --check
- name: Catch common mistakes
uses: actions-rs/cargo@v1
with:
command: clippy
args: --all-features --all-targets -- -D warnings

View File

@ -1,28 +0,0 @@
name: Rust Stable
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
check:
name: Check
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions-rs/toolchain@v1
with:
toolchain: stable
profile: minimal
override: true
- name: Run tests
uses: actions-rs/cargo@v1
with:
command: test
- name: Run tests (unstable-pre-spec)
uses: actions-rs/cargo@v1
with:
command: test
args: --features unstable-pre-spec

View File

@ -1,2 +0,0 @@
/target
Cargo.lock

View File

@ -1,32 +1,28 @@
[package]
name = "state-res"
version = "0.1.0"
name = "ruma-state-res"
authors = ["Devin R <devin.ragotzy@gmail.com>"]
edition = "2018"
categories = ["api-bindings", "web-programming"]
keywords = ["matrix", "chat", "state resolution", "ruma"]
description = "An abstraction for Matrix state resolution."
homepage = "https://www.ruma.io/"
keywords = ["matrix", "chat", "state resolution", "ruma"]
license = "MIT"
repository = "https://github.com/ruma/ruma"
readme = "README.md"
repository = "https://github.com/ruma/state-res"
license = "MIT"
version = "0.1.0"
edition = "2018"
[features]
unstable-pre-spec = ["ruma/unstable-pre-spec"]
[dependencies]
itertools = "0.10.0"
ruma = { version = "0.0.3", path = "../ruma", features = ["events", "signatures"] }
serde = { version = "1.0.118", features = ["derive"] }
serde_json = "1.0.60"
maplit = "1.0.2"
thiserror = "1.0.22"
log = "0.4.11"
[features]
unstable-pre-spec = ["ruma/unstable-pre-spec"]
[dependencies.ruma]
git = "https://github.com/ruma/ruma"
rev = "8c286e78d41770fe431e7304cc2fe23e383793df"
features = ["events", "signatures"]
[dev-dependencies]
criterion = "0.3.3"
rand = "0.7.3"

View File

@ -1,19 +0,0 @@
Copyright (c) 2020 Devin Ragotzy
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

View File

@ -25,8 +25,8 @@ use ruma::{
},
EventId, RoomId, RoomVersionId, UserId,
};
use ruma_state_res::{Error, Event, EventMap, Result, StateMap, StateResolution};
use serde_json::{json, Value as JsonValue};
use state_res::{Error, Event, Result, StateMap, StateResolution};
static mut SERVER_TIMESTAMP: u64 = 0;
@ -55,7 +55,7 @@ fn resolution_shallow_auth_chain(c: &mut Criterion) {
let (state_at_bob, state_at_charlie, _) = store.set_up();
b.iter(|| {
let mut ev_map: state_res::EventMap<Arc<StateEvent>> = store.0.clone();
let mut ev_map: EventMap<Arc<StateEvent>> = store.0.clone();
let state_sets = vec![state_at_bob.clone(), state_at_charlie.clone()];
let _ = match StateResolution::resolve::<StateEvent>(
&room_id(),
@ -202,10 +202,7 @@ impl<E: Event> TestStore<E> {
for ids in event_ids {
// TODO state store `auth_event_ids` returns self in the event ids list
// when an event returns `auth_event_ids` self is not contained
let chain = self
.auth_event_ids(room_id, &ids)?
.into_iter()
.collect::<BTreeSet<_>>();
let chain = self.auth_event_ids(room_id, &ids)?.into_iter().collect::<BTreeSet<_>>();
chains.push(chain);
}
@ -250,8 +247,7 @@ impl TestStore<StateEvent> {
&[cre.clone()],
&[cre.clone()],
);
self.0
.insert(alice_mem.event_id().clone(), Arc::clone(&alice_mem));
self.0.insert(alice_mem.event_id().clone(), Arc::clone(&alice_mem));
let join_rules = to_pdu_event(
"IJR",
@ -262,8 +258,7 @@ impl TestStore<StateEvent> {
&[cre.clone(), alice_mem.event_id().clone()],
&[alice_mem.event_id().clone()],
);
self.0
.insert(join_rules.event_id().clone(), join_rules.clone());
self.0.insert(join_rules.event_id().clone(), join_rules.clone());
// Bob and Charlie join at the same time, so there is a fork
// this will be represented in the state_sets when we resolve
@ -287,8 +282,7 @@ impl TestStore<StateEvent> {
&[cre, join_rules.event_id().clone()],
&[join_rules.event_id().clone()],
);
self.0
.insert(charlie_mem.event_id().clone(), charlie_mem.clone());
self.0.insert(charlie_mem.event_id().clone(), charlie_mem.clone());
let state_at_bob = [&create_event, &alice_mem, &join_rules, &bob_mem]
.iter()
@ -300,13 +294,7 @@ impl TestStore<StateEvent> {
.map(|e| ((e.kind(), e.state_key().unwrap()), e.event_id().clone()))
.collect::<StateMap<_>>();
let expected = [
&create_event,
&alice_mem,
&join_rules,
&bob_mem,
&charlie_mem,
]
let expected = [&create_event, &alice_mem, &join_rules, &bob_mem, &charlie_mem]
.iter()
.map(|e| ((e.kind(), e.state_key().unwrap()), e.event_id().clone()))
.collect::<StateMap<_>>();
@ -379,21 +367,9 @@ where
SERVER_TIMESTAMP += 1;
ts
};
let id = if id.contains('$') {
id.to_string()
} else {
format!("${}:foo", id)
};
let auth_events = auth_events
.iter()
.map(AsRef::as_ref)
.map(event_id)
.collect::<Vec<_>>();
let prev_events = prev_events
.iter()
.map(AsRef::as_ref)
.map(event_id)
.collect::<Vec<_>>();
let id = if id.contains('$') { id.to_string() } else { format!("${}:foo", id) };
let auth_events = auth_events.iter().map(AsRef::as_ref).map(event_id).collect::<Vec<_>>();
let prev_events = prev_events.iter().map(AsRef::as_ref).map(event_id).collect::<Vec<_>>();
let state_key = state_key.map(ToString::to_string);
Arc::new(StateEvent {
@ -557,11 +533,10 @@ pub mod event {
},
EventId, RoomId, RoomVersionId, ServerName, ServerSigningKeyId, UInt, UserId,
};
use ruma_state_res::Event;
use serde::{Deserialize, Serialize};
use serde_json::Value as JsonValue;
use state_res::Event;
impl Event for StateEvent {
fn event_id(&self) -> &EventId {
self.event_id()
@ -632,10 +607,7 @@ pub mod event {
id: EventId,
json: serde_json::Value,
) -> Result<Self, serde_json::Error> {
Ok(Self {
event_id: id,
rest: Pdu::RoomV3Pdu(serde_json::from_value(json)?),
})
Ok(Self { event_id: id, rest: Pdu::RoomV3Pdu(serde_json::from_value(json)?) })
}
pub fn from_id_canon_obj(

View File

@ -1 +0,0 @@
imports_granularity="Crate"

View File

@ -169,10 +169,7 @@ pub fn auth_check<E: Event>(
*/
// 3. If event does not have m.room.create in auth_events reject
if auth_events
.get(&(EventType::RoomCreate, "".to_string()))
.is_none()
{
if auth_events.get(&(EventType::RoomCreate, "".to_string())).is_none() {
log::warn!("no m.room.create event in auth chain");
return Ok(false);
@ -275,11 +272,12 @@ pub fn auth_check<E: Event>(
log::info!("power levels event allowed");
}
// Room version 3: Redaction events are always accepted (provided the event is allowed by `events` and
// `events_default` in the power levels). However, servers should not apply or send redaction's
// to clients until both the redaction event and original event have been seen, and are valid.
// Servers should only apply redaction's to events where the sender's domains match,
// or the sender of the redaction has the appropriate permissions per the power levels.
// Room version 3: Redaction events are always accepted (provided the event is allowed by
// `events` and `events_default` in the power levels). However, servers should not apply or
// send redaction's to clients until both the redaction event and original event have been
// seen, and are valid. Servers should only apply redaction's to events where the sender's
// domains match, or the sender of the redaction has the appropriate permissions per the
// power levels.
if room_version.extra_redaction_checks
&& incoming_event.kind() == EventType::RoomRedaction
@ -310,10 +308,7 @@ pub fn valid_membership_change<E: Event>(
auth_events: &StateMap<Arc<E>>,
) -> Result<bool> {
let target_membership = serde_json::from_value::<MembershipState>(
content
.get("membership")
.expect("we should test before that this field exists")
.clone(),
content.get("membership").expect("we should test before that this field exists").clone(),
)?;
let third_party_invite = content
@ -327,10 +322,7 @@ pub fn valid_membership_change<E: Event>(
let sender = auth_events.get(&key);
let sender_membership = sender.map_or(Ok::<_, Error>(MembershipState::Leave), |pdu| {
Ok(serde_json::from_value::<MembershipState>(
pdu.content()
.get("membership")
.expect("we assume existing events are valid")
.clone(),
pdu.content().get("membership").expect("we assume existing events are valid").clone(),
)?)
})?;
@ -339,10 +331,7 @@ pub fn valid_membership_change<E: Event>(
let current_membership = current.map_or(Ok::<_, Error>(MembershipState::Leave), |pdu| {
Ok(serde_json::from_value::<MembershipState>(
pdu.content()
.get("membership")
.expect("we assume existing events are valid")
.clone(),
pdu.content().get("membership").expect("we assume existing events are valid").clone(),
)?)
})?;
@ -436,9 +425,7 @@ pub fn valid_membership_change<E: Event>(
);
false
} else {
let allow = sender_power
.filter(|&p| p >= &power_levels.invite)
.is_some();
let allow = sender_power.filter(|&p| p >= &power_levels.invite).is_some();
if !allow {
warn!("User does not have enough power to invite");
}
@ -521,10 +508,7 @@ pub fn can_send_event<E: Event>(event: &Arc<E>, auth_events: &StateMap<Arc<E>>)
return false;
}
if event
.state_key()
.as_ref()
.map_or(false, |k| k.starts_with('@'))
if event.state_key().as_ref().map_or(false, |k| k.starts_with('@'))
&& event.state_key().as_deref() != Some(event.sender().as_str())
{
return false; // permission required to post in this room
@ -539,9 +523,7 @@ pub fn check_power_levels<E: Event>(
power_event: &Arc<E>,
auth_events: &StateMap<Arc<E>>,
) -> Option<bool> {
let power_event_state_key = power_event
.state_key()
.expect("power events have state keys");
let power_event_state_key = power_event.state_key().expect("power events have state keys");
let key = (power_event.kind(), power_event_state_key);
let current_state = if let Some(current_state) = auth_events.get(&key) {
current_state
@ -647,15 +629,8 @@ pub fn check_power_levels<E: Event>(
}
}
let levels = [
"users_default",
"events_default",
"state_default",
"ban",
"redact",
"kick",
"invite",
];
let levels =
["users_default", "events_default", "state_default", "ban", "redact", "kick", "invite"];
let old_state = serde_json::to_value(old_state).unwrap();
let new_state = serde_json::to_value(new_state).unwrap();
for lvl_name in &levels {
@ -701,10 +676,7 @@ pub fn check_redaction<E: Event>(
// If the domain of the event_id of the event being redacted is the same as the
// domain of the event_id of the m.room.redaction, allow
if redaction_event.event_id().server_name()
== redaction_event
.redacts()
.as_ref()
.and_then(|id| id.server_name())
== redaction_event.redacts().as_ref().and_then(|id| id.server_name())
{
log::info!("redaction event allowed via room version 1 rules");
return Ok(true);
@ -863,7 +835,8 @@ pub fn verify_third_party_invite<E: Event>(
return false;
}
// If any signature in signed matches any public key in the m.room.third_party_invite event, allow
// If any signature in signed matches any public key in the m.room.third_party_invite event,
// allow
if let Ok(tpid_ev) = serde_json::from_value::<
ruma::events::room::third_party_invite::ThirdPartyInviteEventContent,
>(current_tpid.content())

View File

@ -45,7 +45,8 @@ impl StateResolution {
/// * `state_sets` - The incoming state to resolve. Each `StateMap` represents a possible fork
/// in the state of a room.
///
/// * `auth_events` - The full recursive set of `auth_events` for each event in the `state_sets`.
/// * `auth_events` - The full recursive set of `auth_events` for each event in the
/// `state_sets`.
///
/// * `event_map` - The `EventMap` acts as a local cache of state, any event that is not found
/// in the `event_map` will cause an unrecoverable `Error` in `resolve`.
@ -77,11 +78,8 @@ impl StateResolution {
// 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<_>>();
let mut all_conflicted =
auth_diff.into_iter().collect::<BTreeSet<_>>().into_iter().collect::<Vec<_>>();
log::info!("full conflicted set is {} events", all_conflicted.len());
@ -122,10 +120,7 @@ impl StateResolution {
log::debug!(
"AUTHED {:?}",
resolved_control
.iter()
.map(|(key, id)| (key, id.to_string()))
.collect::<Vec<_>>()
resolved_control.iter().map(|(key, id)| (key, id.to_string())).collect::<Vec<_>>()
);
// At this point the control_events have been resolved we now have to
@ -133,7 +128,8 @@ impl StateResolution {
sorted_control_levels.dedup();
let deduped_power_ev = sorted_control_levels;
// This removes the control events that passed auth and more importantly those that failed auth
// This removes the control events that passed auth and more importantly those that failed
// auth
let events_to_resolve = all_conflicted
.iter()
.filter(|id| !deduped_power_ev.contains(id))
@ -142,10 +138,7 @@ impl StateResolution {
log::debug!(
"LEFT {:?}",
events_to_resolve
.iter()
.map(ToString::to_string)
.collect::<Vec<_>>()
events_to_resolve.iter().map(ToString::to_string).collect::<Vec<_>>()
);
// This "epochs" power level event
@ -158,10 +151,7 @@ impl StateResolution {
log::debug!(
"SORTED LEFT {:?}",
sorted_left_events
.iter()
.map(ToString::to_string)
.collect::<Vec<_>>()
sorted_left_events.iter().map(ToString::to_string).collect::<Vec<_>>()
);
let mut resolved_state = StateResolution::iterative_auth_check(
@ -189,20 +179,14 @@ impl StateResolution {
) -> (StateMap<EventId>, StateMap<Vec<EventId>>) {
use itertools::Itertools;
log::info!(
"seperating {} sets of events into conflicted/unconflicted",
state_sets.len()
);
log::info!("seperating {} sets of events into conflicted/unconflicted", state_sets.len());
let mut unconflicted_state = StateMap::new();
let mut conflicted_state = StateMap::new();
for key in state_sets.iter().flat_map(|map| map.keys()).dedup() {
let mut event_ids = state_sets
.iter()
.map(|state_set| state_set.get(key))
.dedup()
.collect::<Vec<_>>();
let mut event_ids =
state_sets.iter().map(|state_set| state_set.get(key)).dedup().collect::<Vec<_>>();
if event_ids.len() == 1 {
if let Some(Some(id)) = event_ids.pop() {
@ -241,12 +225,7 @@ impl StateResolution {
let rest = chains.iter().skip(1).flatten().cloned().collect();
let common = chain.intersection(&rest).collect::<Vec<_>>();
Ok(chains
.into_iter()
.flatten()
.filter(|id| !common.contains(&id))
.dedup()
.collect())
Ok(chains.into_iter().flatten().filter(|id| !common.contains(&id)).dedup().collect())
} else {
Ok(vec![])
}
@ -326,10 +305,8 @@ impl StateResolution {
// TODO make the BTreeSet conversion cleaner ??
// outdegree_map is an event referring to the events before it, the
// more outdegree's the more recent the event.
let mut outdegree_map: BTreeMap<EventId, BTreeSet<EventId>> = graph
.iter()
.map(|(k, v)| (k.clone(), v.iter().cloned().collect()))
.collect();
let mut outdegree_map: BTreeMap<EventId, BTreeSet<EventId>> =
graph.iter().map(|(k, v)| (k.clone(), v.iter().cloned().collect())).collect();
// The number of events that depend on the given event (the eventId key)
let mut reverse_graph = BTreeMap::new();
@ -346,10 +323,7 @@ impl StateResolution {
reverse_graph.entry(node).or_insert(btreeset![]);
for edge in edges {
reverse_graph
.entry(edge)
.or_insert(btreeset![])
.insert(node);
reverse_graph.entry(edge).or_insert(btreeset![]).insert(node);
}
}
@ -391,11 +365,7 @@ impl StateResolution {
// TODO store.auth_event_ids returns "self" with the event ids is this ok
// event.auth_event_ids does not include its own event id ?
for aid in event
.as_ref()
.map(|pdu| pdu.auth_events())
.unwrap_or_default()
{
for aid in event.as_ref().map(|pdu| pdu.auth_events()).unwrap_or_default() {
if let Ok(aev) = StateResolution::get_or_load_event(room_id, &aid, event_map) {
if is_type_and_key(&aev, EventType::RoomPowerLevels, "") {
pl = Some(aev);
@ -444,10 +414,7 @@ impl StateResolution {
log::debug!(
"performing auth checks on {:?}",
events_to_check
.iter()
.map(ToString::to_string)
.collect::<Vec<_>>()
events_to_check.iter().map(ToString::to_string).collect::<Vec<_>>()
);
let mut resolved_state = unconflicted_state.clone();
@ -461,7 +428,8 @@ impl StateResolution {
let mut auth_events = BTreeMap::new();
for aid in &event.auth_events() {
if let Ok(ev) = StateResolution::get_or_load_event(room_id, aid, event_map) {
// TODO synapse check "rejected_reason", I'm guessing this is redacted_because in ruma ??
// TODO synapse check "rejected_reason", I'm guessing this is redacted_because
// in ruma ??
auth_events.insert(
(
ev.kind(),
@ -499,8 +467,8 @@ impl StateResolution {
.filter_map(|id| StateResolution::get_or_load_event(room_id, id, event_map).ok())
.next_back();
// The key for this is (eventType + a state_key of the signed token not sender) so search
// for it
// The key for this is (eventType + a state_key of the signed token not sender) so
// search for it
let current_third_party = auth_events.iter().find_map(|(_, pdu)| {
if pdu.kind() == EventType::RoomThirdPartyInvite {
Some(pdu.clone()) // TODO no clone, auth_events is borrowed while moved
@ -520,10 +488,7 @@ impl StateResolution {
resolved_state.insert((event.kind(), state_key), event_id.clone());
} else {
// synapse passes here on AuthError. We do not add this event to resolved_state.
log::warn!(
"event {} failed the authentication check",
event_id.to_string()
);
log::warn!("event {} failed the authentication check", event_id.to_string());
}
// TODO: if these functions are ever made async here
@ -658,9 +623,8 @@ impl StateResolution {
graph.entry(eid.clone()).or_insert_with(Vec::new);
// prefer the store to event as the store filters dedups the events
// otherwise it seems we can loop forever
for aid in &StateResolution::get_or_load_event(room_id, &eid, event_map)
.unwrap()
.auth_events()
for aid in
&StateResolution::get_or_load_event(room_id, &eid, event_map).unwrap().auth_events()
{
if auth_diff.contains(aid) {
if !graph.contains_key(aid) {

View File

@ -65,12 +65,7 @@ impl RoomVersion {
RoomVersionId::Version4 => Self::version_4(),
RoomVersionId::Version5 => Self::version_5(),
RoomVersionId::Version6 => Self::version_6(),
ver => {
return Err(Error::Unsupported(format!(
"found version `{}`",
ver.as_str()
)))
}
ver => return Err(Error::Unsupported(format!("found version `{}`", ver.as_str()))),
})
}

View File

@ -1,7 +1,7 @@
use std::sync::Arc;
use state_res::{event_auth::valid_membership_change, StateMap};
// use state_res::event_auth:::{
use ruma_state_res::{event_auth::valid_membership_change, StateMap};
// use ruma_state_res::event_auth:::{
// auth_check, auth_types_for_event, can_federate, check_power_levels, check_redaction,
// };
@ -12,10 +12,7 @@ use utils::{alice, charlie, event_id, member_content_ban, to_pdu_event, INITIAL_
fn test_ban_pass() {
let events = INITIAL_EVENTS();
let prev = events
.values()
.find(|ev| ev.event_id().as_str().contains("IMC"))
.map(Arc::clone);
let prev = events.values().find(|ev| ev.event_id().as_str().contains("IMC")).map(Arc::clone);
let auth_events = events
.values()
@ -47,10 +44,7 @@ fn test_ban_pass() {
fn test_ban_fail() {
let events = INITIAL_EVENTS();
let prev = events
.values()
.find(|ev| ev.event_id().as_str().contains("IMC"))
.map(Arc::clone);
let prev = events.values().find(|ev| ev.event_id().as_str().contains("IMC")).map(Arc::clone);
let auth_events = events
.values()

View File

@ -1,7 +1,7 @@
use std::collections::BTreeMap;
use ruma::{events::EventType, EventId};
use state_res::{is_power_event, room_version::RoomVersion, StateMap};
use ruma_state_res::{is_power_event, room_version::RoomVersion, StateMap, StateResolution};
mod utils;
use utils::{room_id, INITIAL_EVENTS};
@ -35,7 +35,7 @@ fn test_event_sort() {
// This is a TODO in conduit
// TODO these events are not guaranteed to be sorted but they are resolved, do
// we need the auth_chain
let sorted_power_events = state_res::StateResolution::reverse_topological_power_sort(
let sorted_power_events = StateResolution::reverse_topological_power_sort(
&room_id(),
&power_events,
&mut events,
@ -44,7 +44,7 @@ fn test_event_sort() {
// This is a TODO in conduit
// TODO we may be able to skip this since they are resolved according to spec
let resolved_power = state_res::StateResolution::iterative_auth_check(
let resolved_power = StateResolution::iterative_auth_check(
&room_id(),
&RoomVersion::version_6(),
&sorted_power_events,
@ -60,12 +60,8 @@ fn test_event_sort() {
let power_level = resolved_power.get(&(EventType::RoomPowerLevels, "".to_string()));
let sorted_event_ids = state_res::StateResolution::mainline_sort(
&room_id(),
&events_to_sort,
power_level,
&mut events,
);
let sorted_event_ids =
StateResolution::mainline_sort(&room_id(), &events_to_sort, power_level, &mut events);
assert_eq!(
vec![
@ -78,10 +74,7 @@ fn test_event_sort() {
"$START:foo",
"$END:foo"
],
sorted_event_ids
.iter()
.map(|id| id.to_string())
.collect::<Vec<_>>()
sorted_event_ids.iter().map(|id| id.to_string()).collect::<Vec<_>>()
)
}

View File

@ -3,8 +3,8 @@
use std::{collections::BTreeMap, sync::Arc};
use ruma::{events::EventType, EventId, RoomVersionId};
use ruma_state_res::{EventMap, StateMap, StateResolution};
use serde_json::json;
use state_res::{EventMap, StateMap, StateResolution};
mod utils;
use utils::{
@ -21,16 +21,9 @@ fn ban_with_auth_chains() {
.map(|list| list.into_iter().map(event_id).collect::<Vec<_>>())
.collect::<Vec<_>>();
let expected_state_ids = vec!["PA", "MB"]
.into_iter()
.map(event_id)
.collect::<Vec<_>>();
let expected_state_ids = vec!["PA", "MB"].into_iter().map(event_id).collect::<Vec<_>>();
do_check(
&ban.values().cloned().collect::<Vec<_>>(),
edges,
expected_state_ids,
);
do_check(&ban.values().cloned().collect::<Vec<_>>(), edges, expected_state_ids);
}
#[test]
@ -96,23 +89,12 @@ fn ban_with_auth_chains2() {
.collect::<Vec<_>>()
);
let expected = vec![
"$CREATE:foo",
"$IJR:foo",
"$PA:foo",
"$IMA:foo",
"$IMB:foo",
"$IMC:foo",
"$MB:foo",
];
let expected =
vec!["$CREATE:foo", "$IJR:foo", "$PA:foo", "$IMA:foo", "$IMB:foo", "$IMC:foo", "$MB:foo"];
for id in expected.iter().map(|i| event_id(i)) {
// make sure our resolved events are equal to the expected list
assert!(
resolved.values().any(|eid| eid == &id) || init.contains_key(&id),
"{}",
id
)
assert!(resolved.values().any(|eid| eid == &id) || init.contains_key(&id), "{}", id)
}
assert_eq!(expected.len(), resolved.len())
}
@ -128,11 +110,7 @@ fn join_rule_with_auth_chain() {
let expected_state_ids = vec!["JR"].into_iter().map(event_id).collect::<Vec<_>>();
do_check(
&join_rule.values().cloned().collect::<Vec<_>>(),
edges,
expected_state_ids,
);
do_check(&join_rule.values().cloned().collect::<Vec<_>>(), edges, expected_state_ids);
}
#[allow(non_snake_case)]

View File

@ -5,8 +5,8 @@ use ruma::{
events::{room::join_rules::JoinRule, EventType},
EventId, RoomVersionId,
};
use ruma_state_res::{EventMap, StateMap, StateResolution};
use serde_json::json;
use state_res::{StateMap, StateResolution};
use tracing_subscriber as tracer;
mod utils;
@ -48,18 +48,12 @@ fn ban_vs_power_level() {
),
];
let edges = vec![
vec!["END", "MB", "MA", "PA", "START"],
vec!["END", "PA", "PB"],
]
let edges = vec![vec!["END", "MB", "MA", "PA", "START"], vec!["END", "PA", "PB"]]
.into_iter()
.map(|list| list.into_iter().map(event_id).collect::<Vec<_>>())
.collect::<Vec<_>>();
let expected_state_ids = vec!["PA", "MA", "MB"]
.into_iter()
.map(event_id)
.collect::<Vec<_>>();
let expected_state_ids = vec!["PA", "MA", "MB"].into_iter().map(event_id).collect::<Vec<_>>();
do_check(events, edges, expected_state_ids)
}
@ -93,18 +87,13 @@ fn topic_basic() {
to_init_pdu_event("T3", bob(), EventType::RoomTopic, Some(""), json!({})),
];
let edges = vec![
vec!["END", "PA2", "T2", "PA1", "T1", "START"],
vec!["END", "T3", "PB", "PA1"],
]
let edges =
vec![vec!["END", "PA2", "T2", "PA1", "T1", "START"], vec!["END", "T3", "PB", "PA1"]]
.into_iter()
.map(|list| list.into_iter().map(event_id).collect::<Vec<_>>())
.collect::<Vec<_>>();
let expected_state_ids = vec!["PA2", "T2"]
.into_iter()
.map(event_id)
.collect::<Vec<_>>();
let expected_state_ids = vec!["PA2", "T2"].into_iter().map(event_id).collect::<Vec<_>>();
do_check(events, edges, expected_state_ids)
}
@ -130,18 +119,12 @@ fn topic_reset() {
),
];
let edges = vec![
vec!["END", "MB", "T2", "PA", "T1", "START"],
vec!["END", "T1"],
]
let edges = vec![vec!["END", "MB", "T2", "PA", "T1", "START"], vec!["END", "T1"]]
.into_iter()
.map(|list| list.into_iter().map(event_id).collect::<Vec<_>>())
.collect::<Vec<_>>();
let expected_state_ids = vec!["T1", "MB", "PA"]
.into_iter()
.map(event_id)
.collect::<Vec<_>>();
let expected_state_ids = vec!["T1", "MB", "PA"].into_iter().map(event_id).collect::<Vec<_>>();
do_check(events, edges, expected_state_ids)
}
@ -250,10 +233,7 @@ fn topic_setting() {
.map(|list| list.into_iter().map(event_id).collect::<Vec<_>>())
.collect::<Vec<_>>();
let expected_state_ids = vec!["T4", "PA2"]
.into_iter()
.map(event_id)
.collect::<Vec<_>>();
let expected_state_ids = vec!["T4", "PA2"].into_iter().map(event_id).collect::<Vec<_>>();
do_check(events, edges, expected_state_ids)
}
@ -265,7 +245,7 @@ fn test_event_map_none() {
// build up the DAG
let (state_at_bob, state_at_charlie, expected) = store.set_up();
let mut ev_map: state_res::EventMap<Arc<StateEvent>> = store.0.clone();
let mut ev_map: EventMap<Arc<StateEvent>> = store.0.clone();
let state_sets = vec![state_at_bob, state_at_charlie];
let resolved = match StateResolution::resolve::<StateEvent>(
&room_id(),
@ -317,9 +297,7 @@ impl TestStore<StateEvent> {
pub fn set_up(&mut self) -> (StateMap<EventId>, StateMap<EventId>, StateMap<EventId>) {
// to activate logging use `RUST_LOG=debug cargo t one_test_only`
let _ = LOGGER.call_once(|| {
tracer::fmt()
.with_env_filter(tracer::EnvFilter::from_default_env())
.init()
tracer::fmt().with_env_filter(tracer::EnvFilter::from_default_env()).init()
});
let create_event = to_pdu_event::<EventId>(
"CREATE",
@ -342,8 +320,7 @@ impl TestStore<StateEvent> {
&[cre.clone()],
&[cre.clone()],
);
self.0
.insert(alice_mem.event_id().clone(), Arc::clone(&alice_mem));
self.0.insert(alice_mem.event_id().clone(), Arc::clone(&alice_mem));
let join_rules = to_pdu_event(
"IJR",
@ -354,8 +331,7 @@ impl TestStore<StateEvent> {
&[cre.clone(), alice_mem.event_id().clone()],
&[alice_mem.event_id().clone()],
);
self.0
.insert(join_rules.event_id().clone(), join_rules.clone());
self.0.insert(join_rules.event_id().clone(), join_rules.clone());
// Bob and Charlie join at the same time, so there is a fork
// this will be represented in the state_sets when we resolve
@ -379,8 +355,7 @@ impl TestStore<StateEvent> {
&[cre, join_rules.event_id().clone()],
&[join_rules.event_id().clone()],
);
self.0
.insert(charlie_mem.event_id().clone(), charlie_mem.clone());
self.0.insert(charlie_mem.event_id().clone(), charlie_mem.clone());
let state_at_bob = [&create_event, &alice_mem, &join_rules, &bob_mem]
.iter()
@ -392,13 +367,7 @@ impl TestStore<StateEvent> {
.map(|e| ((e.kind(), e.state_key()), e.event_id().clone()))
.collect::<StateMap<_>>();
let expected = [
&create_event,
&alice_mem,
&join_rules,
&bob_mem,
&charlie_mem,
]
let expected = [&create_event, &alice_mem, &join_rules, &bob_mem, &charlie_mem]
.iter()
.map(|e| ((e.kind(), e.state_key()), e.event_id().clone()))
.collect::<StateMap<_>>();

View File

@ -19,8 +19,8 @@ use ruma::{
},
EventId, RoomId, RoomVersionId, UserId,
};
use ruma_state_res::{auth_types_for_event, Error, Event, Result, StateMap, StateResolution};
use serde_json::{json, Value as JsonValue};
use state_res::{Error, Event, Result, StateMap, StateResolution};
use tracing_subscriber as tracer;
pub use event::StateEvent;
@ -35,20 +35,13 @@ pub fn do_check(
expected_state_ids: Vec<EventId>,
) {
// to activate logging use `RUST_LOG=debug cargo t`
let _ = LOGGER.call_once(|| {
tracer::fmt()
.with_env_filter(tracer::EnvFilter::from_default_env())
.init()
});
let _ = LOGGER
.call_once(|| tracer::fmt().with_env_filter(tracer::EnvFilter::from_default_env()).init());
let init_events = INITIAL_EVENTS();
let mut store = TestStore(
init_events
.values()
.chain(events)
.map(|ev| (ev.event_id().clone(), ev.clone()))
.collect(),
init_events.values().chain(events).map(|ev| (ev.event_id().clone(), ev.clone())).collect(),
);
// This will be lexi_topo_sorted for resolution
@ -140,7 +133,7 @@ pub fn do_check(
let key = fake_event.state_key();
state_after.insert((ty, key), event_id.clone());
let auth_types = state_res::auth_types_for_event(
let auth_types = auth_types_for_event(
&fake_event.kind(),
fake_event.sender(),
Some(fake_event.state_key()),
@ -181,10 +174,7 @@ pub fn do_check(
let ev = event_map.get(&node).expect(&format!(
"{} not found in {:?}",
node.to_string(),
event_map
.keys()
.map(ToString::to_string)
.collect::<Vec<_>>(),
event_map.keys().map(ToString::to_string).collect::<Vec<_>>(),
));
let key = (ev.kind(), ev.state_key());
@ -265,10 +255,7 @@ impl<E: Event> TestStore<E> {
for ids in event_ids {
// TODO state store `auth_event_ids` returns self in the event ids list
// when an event returns `auth_event_ids` self is not contained
let chain = self
.auth_event_ids(room_id, &ids)?
.into_iter()
.collect::<BTreeSet<_>>();
let chain = self.auth_event_ids(room_id, &ids)?.into_iter().collect::<BTreeSet<_>>();
chains.push(chain);
}
@ -276,12 +263,7 @@ impl<E: Event> TestStore<E> {
let rest = chains.iter().skip(1).flatten().cloned().collect();
let common = chain.intersection(&rest).collect::<Vec<_>>();
Ok(chains
.into_iter()
.flatten()
.filter(|id| !common.contains(&id))
.dedup()
.collect())
Ok(chains.into_iter().flatten().filter(|id| !common.contains(&id)).dedup().collect())
} else {
Ok(vec![])
}
@ -350,11 +332,7 @@ pub fn to_init_pdu_event(
SERVER_TIMESTAMP += 1;
ts
};
let id = if id.contains('$') {
id.to_string()
} else {
format!("${}:foo", id)
};
let id = if id.contains('$') { id.to_string() } else { format!("${}:foo", id) };
let state_key = state_key.map(ToString::to_string);
Arc::new(StateEvent {
@ -397,21 +375,9 @@ where
SERVER_TIMESTAMP += 1;
ts
};
let id = if id.contains('$') {
id.to_string()
} else {
format!("${}:foo", id)
};
let auth_events = auth_events
.iter()
.map(AsRef::as_ref)
.map(event_id)
.collect::<Vec<_>>();
let prev_events = prev_events
.iter()
.map(AsRef::as_ref)
.map(event_id)
.collect::<Vec<_>>();
let id = if id.contains('$') { id.to_string() } else { format!("${}:foo", id) };
let auth_events = auth_events.iter().map(AsRef::as_ref).map(event_id).collect::<Vec<_>>();
let prev_events = prev_events.iter().map(AsRef::as_ref).map(event_id).collect::<Vec<_>>();
let state_key = state_key.map(ToString::to_string);
Arc::new(StateEvent {
@ -440,11 +406,8 @@ where
#[allow(non_snake_case)]
pub fn INITIAL_EVENTS() -> BTreeMap<EventId, Arc<StateEvent>> {
// this is always called so we can init the logger here
let _ = LOGGER.call_once(|| {
tracer::fmt()
.with_env_filter(tracer::EnvFilter::from_default_env())
.init()
});
let _ = LOGGER
.call_once(|| tracer::fmt().with_env_filter(tracer::EnvFilter::from_default_env()).init());
vec![
to_pdu_event::<EventId>(
@ -544,11 +507,10 @@ pub mod event {
},
EventId, RoomId, RoomVersionId, ServerName, UInt, UserId,
};
use ruma_state_res::Event;
use serde::{Deserialize, Serialize};
use serde_json::Value as JsonValue;
use state_res::Event;
impl Event for StateEvent {
fn event_id(&self) -> &EventId {
self.event_id()
@ -612,10 +574,7 @@ pub mod event {
id: EventId,
json: serde_json::Value,
) -> Result<Self, serde_json::Error> {
Ok(Self {
event_id: id,
rest: Pdu::RoomV3Pdu(serde_json::from_value(json)?),
})
Ok(Self { event_id: id, rest: Pdu::RoomV3Pdu(serde_json::from_value(json)?) })
}
pub fn from_id_canon_obj(