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] [package]
name = "state-res" name = "ruma-state-res"
version = "0.1.0"
authors = ["Devin R <devin.ragotzy@gmail.com>"] authors = ["Devin R <devin.ragotzy@gmail.com>"]
edition = "2018"
categories = ["api-bindings", "web-programming"] categories = ["api-bindings", "web-programming"]
keywords = ["matrix", "chat", "state resolution", "ruma"]
description = "An abstraction for Matrix state resolution." description = "An abstraction for Matrix state resolution."
homepage = "https://www.ruma.io/" homepage = "https://www.ruma.io/"
keywords = ["matrix", "chat", "state resolution", "ruma"] repository = "https://github.com/ruma/ruma"
license = "MIT"
readme = "README.md" 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] [dependencies]
itertools = "0.10.0" itertools = "0.10.0"
ruma = { version = "0.0.3", path = "../ruma", features = ["events", "signatures"] }
serde = { version = "1.0.118", features = ["derive"] } serde = { version = "1.0.118", features = ["derive"] }
serde_json = "1.0.60" serde_json = "1.0.60"
maplit = "1.0.2" maplit = "1.0.2"
thiserror = "1.0.22" thiserror = "1.0.22"
log = "0.4.11" 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] [dev-dependencies]
criterion = "0.3.3" criterion = "0.3.3"
rand = "0.7.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, EventId, RoomId, RoomVersionId, UserId,
}; };
use ruma_state_res::{Error, Event, EventMap, Result, StateMap, StateResolution};
use serde_json::{json, Value as JsonValue}; use serde_json::{json, Value as JsonValue};
use state_res::{Error, Event, Result, StateMap, StateResolution};
static mut SERVER_TIMESTAMP: u64 = 0; 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(); let (state_at_bob, state_at_charlie, _) = store.set_up();
b.iter(|| { 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 state_sets = vec![state_at_bob.clone(), state_at_charlie.clone()];
let _ = match StateResolution::resolve::<StateEvent>( let _ = match StateResolution::resolve::<StateEvent>(
&room_id(), &room_id(),
@ -202,10 +202,7 @@ impl<E: Event> TestStore<E> {
for ids in event_ids { for ids in event_ids {
// TODO state store `auth_event_ids` returns self in the event ids list // TODO state store `auth_event_ids` returns self in the event ids list
// when an event returns `auth_event_ids` self is not contained // when an event returns `auth_event_ids` self is not contained
let chain = self let chain = self.auth_event_ids(room_id, &ids)?.into_iter().collect::<BTreeSet<_>>();
.auth_event_ids(room_id, &ids)?
.into_iter()
.collect::<BTreeSet<_>>();
chains.push(chain); chains.push(chain);
} }
@ -250,8 +247,7 @@ impl TestStore<StateEvent> {
&[cre.clone()], &[cre.clone()],
&[cre.clone()], &[cre.clone()],
); );
self.0 self.0.insert(alice_mem.event_id().clone(), Arc::clone(&alice_mem));
.insert(alice_mem.event_id().clone(), Arc::clone(&alice_mem));
let join_rules = to_pdu_event( let join_rules = to_pdu_event(
"IJR", "IJR",
@ -262,8 +258,7 @@ impl TestStore<StateEvent> {
&[cre.clone(), alice_mem.event_id().clone()], &[cre.clone(), alice_mem.event_id().clone()],
&[alice_mem.event_id().clone()], &[alice_mem.event_id().clone()],
); );
self.0 self.0.insert(join_rules.event_id().clone(), join_rules.clone());
.insert(join_rules.event_id().clone(), join_rules.clone());
// Bob and Charlie join at the same time, so there is a fork // Bob and Charlie join at the same time, so there is a fork
// this will be represented in the state_sets when we resolve // this will be represented in the state_sets when we resolve
@ -287,8 +282,7 @@ impl TestStore<StateEvent> {
&[cre, join_rules.event_id().clone()], &[cre, join_rules.event_id().clone()],
&[join_rules.event_id().clone()], &[join_rules.event_id().clone()],
); );
self.0 self.0.insert(charlie_mem.event_id().clone(), charlie_mem.clone());
.insert(charlie_mem.event_id().clone(), charlie_mem.clone());
let state_at_bob = [&create_event, &alice_mem, &join_rules, &bob_mem] let state_at_bob = [&create_event, &alice_mem, &join_rules, &bob_mem]
.iter() .iter()
@ -300,13 +294,7 @@ impl TestStore<StateEvent> {
.map(|e| ((e.kind(), e.state_key().unwrap()), e.event_id().clone())) .map(|e| ((e.kind(), e.state_key().unwrap()), e.event_id().clone()))
.collect::<StateMap<_>>(); .collect::<StateMap<_>>();
let expected = [ let expected = [&create_event, &alice_mem, &join_rules, &bob_mem, &charlie_mem]
&create_event,
&alice_mem,
&join_rules,
&bob_mem,
&charlie_mem,
]
.iter() .iter()
.map(|e| ((e.kind(), e.state_key().unwrap()), e.event_id().clone())) .map(|e| ((e.kind(), e.state_key().unwrap()), e.event_id().clone()))
.collect::<StateMap<_>>(); .collect::<StateMap<_>>();
@ -379,21 +367,9 @@ where
SERVER_TIMESTAMP += 1; SERVER_TIMESTAMP += 1;
ts ts
}; };
let id = if id.contains('$') { let id = if id.contains('$') { id.to_string() } else { format!("${}:foo", id) };
id.to_string() let auth_events = auth_events.iter().map(AsRef::as_ref).map(event_id).collect::<Vec<_>>();
} else { let prev_events = prev_events.iter().map(AsRef::as_ref).map(event_id).collect::<Vec<_>>();
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); let state_key = state_key.map(ToString::to_string);
Arc::new(StateEvent { Arc::new(StateEvent {
@ -557,11 +533,10 @@ pub mod event {
}, },
EventId, RoomId, RoomVersionId, ServerName, ServerSigningKeyId, UInt, UserId, EventId, RoomId, RoomVersionId, ServerName, ServerSigningKeyId, UInt, UserId,
}; };
use ruma_state_res::Event;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use serde_json::Value as JsonValue; use serde_json::Value as JsonValue;
use state_res::Event;
impl Event for StateEvent { impl Event for StateEvent {
fn event_id(&self) -> &EventId { fn event_id(&self) -> &EventId {
self.event_id() self.event_id()
@ -632,10 +607,7 @@ pub mod event {
id: EventId, id: EventId,
json: serde_json::Value, json: serde_json::Value,
) -> Result<Self, serde_json::Error> { ) -> Result<Self, serde_json::Error> {
Ok(Self { Ok(Self { event_id: id, rest: Pdu::RoomV3Pdu(serde_json::from_value(json)?) })
event_id: id,
rest: Pdu::RoomV3Pdu(serde_json::from_value(json)?),
})
} }
pub fn from_id_canon_obj( 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 // 3. If event does not have m.room.create in auth_events reject
if auth_events if auth_events.get(&(EventType::RoomCreate, "".to_string())).is_none() {
.get(&(EventType::RoomCreate, "".to_string()))
.is_none()
{
log::warn!("no m.room.create event in auth chain"); log::warn!("no m.room.create event in auth chain");
return Ok(false); return Ok(false);
@ -275,11 +272,12 @@ pub fn auth_check<E: Event>(
log::info!("power levels event allowed"); log::info!("power levels event allowed");
} }
// Room version 3: Redaction events are always accepted (provided the event is allowed by `events` and // Room version 3: Redaction events are always accepted (provided the event is allowed by
// `events_default` in the power levels). However, servers should not apply or send redaction's // `events` and `events_default` in the power levels). However, servers should not apply or
// to clients until both the redaction event and original event have been seen, and are valid. // send redaction's to clients until both the redaction event and original event have been
// Servers should only apply redaction's to events where the sender's domains match, // seen, and are valid. Servers should only apply redaction's to events where the sender's
// or the sender of the redaction has the appropriate permissions per the power levels. // domains match, or the sender of the redaction has the appropriate permissions per the
// power levels.
if room_version.extra_redaction_checks if room_version.extra_redaction_checks
&& incoming_event.kind() == EventType::RoomRedaction && incoming_event.kind() == EventType::RoomRedaction
@ -310,10 +308,7 @@ pub fn valid_membership_change<E: Event>(
auth_events: &StateMap<Arc<E>>, auth_events: &StateMap<Arc<E>>,
) -> Result<bool> { ) -> Result<bool> {
let target_membership = serde_json::from_value::<MembershipState>( let target_membership = serde_json::from_value::<MembershipState>(
content content.get("membership").expect("we should test before that this field exists").clone(),
.get("membership")
.expect("we should test before that this field exists")
.clone(),
)?; )?;
let third_party_invite = content let third_party_invite = content
@ -327,10 +322,7 @@ pub fn valid_membership_change<E: Event>(
let sender = auth_events.get(&key); let sender = auth_events.get(&key);
let sender_membership = sender.map_or(Ok::<_, Error>(MembershipState::Leave), |pdu| { let sender_membership = sender.map_or(Ok::<_, Error>(MembershipState::Leave), |pdu| {
Ok(serde_json::from_value::<MembershipState>( Ok(serde_json::from_value::<MembershipState>(
pdu.content() pdu.content().get("membership").expect("we assume existing events are valid").clone(),
.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| { let current_membership = current.map_or(Ok::<_, Error>(MembershipState::Leave), |pdu| {
Ok(serde_json::from_value::<MembershipState>( Ok(serde_json::from_value::<MembershipState>(
pdu.content() pdu.content().get("membership").expect("we assume existing events are valid").clone(),
.get("membership")
.expect("we assume existing events are valid")
.clone(),
)?) )?)
})?; })?;
@ -436,9 +425,7 @@ pub fn valid_membership_change<E: Event>(
); );
false false
} else { } else {
let allow = sender_power let allow = sender_power.filter(|&p| p >= &power_levels.invite).is_some();
.filter(|&p| p >= &power_levels.invite)
.is_some();
if !allow { if !allow {
warn!("User does not have enough power to invite"); 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; return false;
} }
if event if event.state_key().as_ref().map_or(false, |k| k.starts_with('@'))
.state_key()
.as_ref()
.map_or(false, |k| k.starts_with('@'))
&& event.state_key().as_deref() != Some(event.sender().as_str()) && event.state_key().as_deref() != Some(event.sender().as_str())
{ {
return false; // permission required to post in this room return false; // permission required to post in this room
@ -539,9 +523,7 @@ pub fn check_power_levels<E: Event>(
power_event: &Arc<E>, power_event: &Arc<E>,
auth_events: &StateMap<Arc<E>>, auth_events: &StateMap<Arc<E>>,
) -> Option<bool> { ) -> Option<bool> {
let power_event_state_key = power_event let power_event_state_key = power_event.state_key().expect("power events have state keys");
.state_key()
.expect("power events have state keys");
let key = (power_event.kind(), power_event_state_key); let key = (power_event.kind(), power_event_state_key);
let current_state = if let Some(current_state) = auth_events.get(&key) { let current_state = if let Some(current_state) = auth_events.get(&key) {
current_state current_state
@ -647,15 +629,8 @@ pub fn check_power_levels<E: Event>(
} }
} }
let levels = [ let levels =
"users_default", ["users_default", "events_default", "state_default", "ban", "redact", "kick", "invite"];
"events_default",
"state_default",
"ban",
"redact",
"kick",
"invite",
];
let old_state = serde_json::to_value(old_state).unwrap(); let old_state = serde_json::to_value(old_state).unwrap();
let new_state = serde_json::to_value(new_state).unwrap(); let new_state = serde_json::to_value(new_state).unwrap();
for lvl_name in &levels { 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 // 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 // domain of the event_id of the m.room.redaction, allow
if redaction_event.event_id().server_name() if redaction_event.event_id().server_name()
== redaction_event == redaction_event.redacts().as_ref().and_then(|id| id.server_name())
.redacts()
.as_ref()
.and_then(|id| id.server_name())
{ {
log::info!("redaction event allowed via room version 1 rules"); log::info!("redaction event allowed via room version 1 rules");
return Ok(true); return Ok(true);
@ -863,7 +835,8 @@ pub fn verify_third_party_invite<E: Event>(
return false; 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::< if let Ok(tpid_ev) = serde_json::from_value::<
ruma::events::room::third_party_invite::ThirdPartyInviteEventContent, ruma::events::room::third_party_invite::ThirdPartyInviteEventContent,
>(current_tpid.content()) >(current_tpid.content())

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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